Refactored OpaquePtr/Scene slightly.

Removed unused allegro.path.
This commit is contained in:
Sander Schobers 2024-05-02 18:39:59 +02:00
parent 93d9fe6c12
commit 5e2ac5f3fe
7 changed files with 106 additions and 63 deletions

View File

View File

@ -65,6 +65,13 @@ pub const Context = struct {
}; };
} }
pub fn enterScene(self: *Context, scene: Scene) void {
self.exitScene();
self.scene = scene;
scene.enter(self);
}
fn exitScene(self: *Context) void { fn exitScene(self: *Context) void {
if (self.scene) |scene| { if (self.scene) |scene| {
scene.exit(self); scene.exit(self);
@ -83,11 +90,8 @@ pub const Context = struct {
self.shouldQuit = true; self.shouldQuit = true;
} }
pub fn switchToScene(self: *Context, comptime SceneType: type, build: ?*const fn (*SceneType) void) !void { pub fn switchToScene(self: *Context, comptime SceneType: type) !void {
self.exitScene(); const scene = try Scene.init(SceneType, self.allocator);
self.enterScene(scene);
const scene = try Scene.init(SceneType, self.allocator, build);
self.scene = scene;
scene.enter(self);
} }
}; };

View File

@ -3,7 +3,7 @@ const Allocator = std.mem.Allocator;
pub const OpaquePtr = struct { pub const OpaquePtr = struct {
allocator: Allocator, allocator: Allocator,
object: usize = undefined, ptr: usize = undefined,
virtualTable: VirtualTable = undefined, virtualTable: VirtualTable = undefined,
const VirtualTable = struct { const VirtualTable = struct {
@ -13,28 +13,37 @@ pub const OpaquePtr = struct {
pub fn Object(comptime Type: type) type { pub fn Object(comptime Type: type) type {
return struct { return struct {
ptr: *Type, ptr: *Type,
opaquePtr: OpaquePtr, opaque_ptr: OpaquePtr,
}; };
} }
pub fn create(comptime Type: type, allocator: Allocator) !Object(Type) { pub fn create(comptime Type: type, allocator: Allocator) !OpaquePtr {
const ptr = try allocator.create(Type); const ptr = try allocator.create(Type);
const opaq = OpaquePtr{ return OpaquePtr.init(Type, allocator, ptr);
}
pub fn createObject(comptime Type: type, allocator: Allocator) !Object(Type) {
const ptr = try allocator.create(Type);
const opaq = OpaquePtr.init(Type, allocator, ptr);
return Object(Type){
.ptr = ptr,
.opaque_ptr = opaq,
};
}
fn init(comptime Type: type, allocator: Allocator, ptr: *Type) OpaquePtr {
return OpaquePtr{
.allocator = allocator, .allocator = allocator,
.object = @intFromPtr(ptr), .ptr = @intFromPtr(ptr),
.virtualTable = .{ .virtualTable = .{
.destroy = struct { .destroy = struct {
fn destroy(self: OpaquePtr) void { fn destroy(self: OpaquePtr) void {
const object = @as(*Type, @ptrFromInt(self.object)); const p = @as(*Type, @ptrFromInt(self.ptr));
self.allocator.destroy(object); self.allocator.destroy(p);
} }
}.destroy, }.destroy,
}, },
}; };
return Object(Type){
.ptr = ptr,
.opaquePtr = opaq,
};
} }
pub fn destroy(self: OpaquePtr) void { pub fn destroy(self: OpaquePtr) void {

View File

@ -5,9 +5,9 @@ pub fn Scene(comptime Context: type, comptime Event: type) type {
return struct { return struct {
const Self = @This(); const Self = @This();
object: usize = undefined, scene_ptr: usize = undefined,
virtualTable: VirtualTable = undefined, virtualTable: VirtualTable = undefined,
opaquePtr: ?OpaquePtr = null, opaque_ptr: ?OpaquePtr = null,
const VirtualTable = struct { const VirtualTable = struct {
enter: *const fn (Self, *Context) void, enter: *const fn (Self, *Context) void,
@ -37,52 +37,81 @@ pub fn Scene(comptime Context: type, comptime Event: type) type {
self.virtualTable.tick(self, ctx, t, dt); self.virtualTable.tick(self, ctx, t, dt);
} }
pub fn makeOpaque(comptime SceneType: type, object: *SceneType) Self { pub fn Builder(comptime SceneType: type) type {
return Self{ .object = @intFromPtr(object), .virtualTable = .{ return struct {
const SelfBuilder = @This();
pub const Object = struct {
ptr: *SceneType,
opaque_ptr: Scene,
};
pub fn init(allocator: std.mem.Allocator) !Self {
const ptr = try OpaquePtr.create(SceneType, allocator);
return SelfBuilder.initOpaque(ptr);
}
pub fn initBuild(allocator: std.mem.Allocator, build: *const fn (*SceneType) void) !Self {
const ptr = try OpaquePtr.createObject(SceneType, allocator);
build(ptr.ptr);
return SelfBuilder.initOpaque(ptr.opaque_ptr);
}
pub fn initObject(allocator: std.mem.Allocator) !Object {
const ptr = try OpaquePtr.createObject(SceneType, allocator);
return Object{
.ptr = ptr.ptr,
.opaque_ptr = SelfBuilder.initOpaque(ptr.opaque_ptr),
};
}
pub fn initOpaque(ptr: OpaquePtr) Self {
return Self{
.scene_ptr = ptr.ptr,
.virtualTable = .{
.enter = struct { .enter = struct {
fn enter(self: Self, ctx: *Context) void { fn enter(self: Self, ctx: *Context) void {
const scene = @as(*SceneType, @ptrFromInt(self.object)); const scene = @as(*SceneType, @ptrFromInt(self.scene_ptr));
scene.enter(ctx); scene.enter(ctx);
} }
}.enter, }.enter,
.exit = struct { .exit = struct {
fn exit(self: Self, ctx: *Context) void { fn exit(self: Self, ctx: *Context) void {
const scene = @as(*SceneType, @ptrFromInt(self.object)); const scene = @as(*SceneType, @ptrFromInt(self.scene_ptr));
scene.exit(ctx); scene.exit(ctx);
} }
}.exit, }.exit,
.handle = struct { .handle = struct {
fn handle(self: Self, ctx: *Context, event: Event) !void { fn handle(self: Self, ctx: *Context, event: Event) !void {
const scene = @as(*SceneType, @ptrFromInt(self.object)); const scene = @as(*SceneType, @ptrFromInt(self.scene_ptr));
try scene.handle(ctx, event); try scene.handle(ctx, event);
} }
}.handle, }.handle,
.tick = struct { .tick = struct {
fn tick(self: Self, ctx: *Context, t: f32, dt: f32) void { fn tick(self: Self, ctx: *Context, t: f32, dt: f32) void {
const scene = @as(*SceneType, @ptrFromInt(self.object)); const scene = @as(*SceneType, @ptrFromInt(self.scene_ptr));
scene.tick(ctx, t, dt); scene.tick(ctx, t, dt);
} }
}.tick, }.tick,
.render = struct { .render = struct {
fn render(self: Self, ctx: *Context) void { fn render(self: Self, ctx: *Context) void {
const scene = @as(*SceneType, @ptrFromInt(self.object)); const scene = @as(*SceneType, @ptrFromInt(self.scene_ptr));
scene.render(ctx); scene.render(ctx);
} }
}.render, }.render,
} }; },
.opaque_ptr = ptr,
};
}
};
} }
pub fn init(comptime SceneType: type, allocator: std.mem.Allocator, build: ?*const fn (*SceneType) void) !Self { pub fn init(comptime SceneType: type, allocator: std.mem.Allocator) !Self {
const object = try OpaquePtr.create(SceneType, allocator); return Builder(SceneType).init(allocator);
const scene = Self.makeOpaque(SceneType, object.ptr);
if (build) |b| {
b(object.ptr);
}
return scene;
} }
pub fn deinit(self: Self) void { pub fn deinit(self: Self) void {
if (self.opaquePtr) |ptr| { if (self.opaque_ptr) |ptr| {
ptr.destroy(); ptr.destroy();
} }
} }

View File

@ -7,6 +7,7 @@ const Context = @import("context.zig").Context;
const GameScene = @import("game_scene.zig").GameScene; const GameScene = @import("game_scene.zig").GameScene;
const Palette = @import("palette.zig").Palette; const Palette = @import("palette.zig").Palette;
const Renderer = @import("renderer.zig").Renderer; const Renderer = @import("renderer.zig").Renderer;
const Scene = @import("scene.zig").Scene;
const TitleScene = @import("title_scene.zig").TitleScene; const TitleScene = @import("title_scene.zig").TitleScene;
fn hexColor(hex: []const u8) allegro.Color { fn hexColor(hex: []const u8) allegro.Color {
@ -63,7 +64,7 @@ pub fn main() !void {
try renderer.registerFonts(); try renderer.registerFonts();
try context.switchToScene(TitleScene, null); context.switchToScene(TitleScene) catch unreachable;
var t = allegro.getTime(); var t = allegro.getTime();
const fpsBuffer = [_]u8{0} ** 32; const fpsBuffer = [_]u8{0} ** 32;

View File

@ -18,7 +18,7 @@ pub const MainMenuScene = struct {
switch (event.type) { switch (event.type) {
allegro.c.ALLEGRO_EVENT_KEY_CHAR => { allegro.c.ALLEGRO_EVENT_KEY_CHAR => {
switch (event.keyboard.keycode) { switch (event.keyboard.keycode) {
allegro.c.ALLEGRO_KEY_SPACE, allegro.c.ALLEGRO_KEY_ENTER => try ctx.switchToScene(GameScene, null), allegro.c.ALLEGRO_KEY_SPACE, allegro.c.ALLEGRO_KEY_ENTER => try ctx.switchToScene(GameScene),
else => {}, else => {},
} }
}, },

View File

@ -19,7 +19,7 @@ pub const TitleScene = struct {
switch (event.type) { switch (event.type) {
allegro.c.ALLEGRO_EVENT_KEY_CHAR => { allegro.c.ALLEGRO_EVENT_KEY_CHAR => {
switch (event.keyboard.keycode) { switch (event.keyboard.keycode) {
allegro.c.ALLEGRO_KEY_SPACE, allegro.c.ALLEGRO_KEY_ENTER => try ctx.switchToScene(MainMenuScene, null), allegro.c.ALLEGRO_KEY_SPACE, allegro.c.ALLEGRO_KEY_ENTER => try ctx.switchToScene(MainMenuScene),
else => {}, else => {},
} }
}, },