From b90b70084edec90729bb5f0f8c7cede51cb276d6 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Tue, 16 Apr 2024 10:40:36 -0700 Subject: [PATCH] examples: glyphs: improve code structure / naming / init logic Signed-off-by: Stephen Gutekanst --- examples/glyphs/Game.zig | 48 ++++++++++++------------ examples/glyphs/{Text.zig => Glyphs.zig} | 20 +++++----- examples/glyphs/main.zig | 7 +--- 3 files changed, 34 insertions(+), 41 deletions(-) rename examples/glyphs/{Text.zig => Glyphs.zig} (91%) diff --git a/examples/glyphs/Game.zig b/examples/glyphs/Game.zig index a8401087..e2527f85 100644 --- a/examples/glyphs/Game.zig +++ b/examples/glyphs/Game.zig @@ -12,7 +12,7 @@ const Vec3 = math.Vec3; const Mat3x3 = math.Mat3x3; const Mat4x4 = math.Mat4x4; -const Text = @import("Text.zig"); +const Glyphs = @import("Glyphs.zig"); timer: mach.Timer, player: mach.EntityID, @@ -47,20 +47,32 @@ pub const global_events = .{ }; pub const local_events = .{ - .after_sprite_init = .{ .handler = afterSpriteInit }, + .after_init = .{ .handler = afterInit }, }; fn init( + glyphs: *Glyphs.Mod, + game: *Mod, +) !void { + // Prepare which glyphs we will render + glyphs.send(.init, .{}); + glyphs.send(.prepare, .{&[_]u21{ '?', '!', 'a', 'b', '#', '@', '%', '$', '&', '^', '*', '+', '=', '<', '>', '/', ':', ';', 'Q', '~' }}); + + // Run our init code after glyphs module is initialized. + game.send(.after_init, .{}); +} + +fn afterInit( sprite_mod: *gfx.Sprite.Mod, sprite_pipeline: *gfx.SpritePipeline.Mod, - text_mod: *Text.Mod, + glyphs: *Glyphs.Mod, game: *Mod, ) !void { // The Mach .core is where we set window options, etc. core.setTitle("gfx.Sprite example"); // Create a sprite rendering pipeline - const texture = text_mod.state().texture; + const texture = glyphs.state().texture; const pipeline = try sprite_pipeline.newEntity(); try sprite_pipeline.set(pipeline, .texture, texture); sprite_pipeline.send(.update, .{}); @@ -69,9 +81,13 @@ fn init( // namespace, e.g. the `Sprite` module could have a 3D `.location` component with a different // type than the `.physics2d` module's `.location` component if you desire. + const r = glyphs.state().regions.get('?').?; const player = try sprite_mod.newEntity(); try sprite_mod.set(player, .transform, Mat4x4.translate(vec3(-0.02, 0, 0))); try sprite_mod.set(player, .pipeline, pipeline); + try sprite_mod.set(player, .size, vec2(@floatFromInt(r.width), @floatFromInt(r.height))); + try sprite_mod.set(player, .uv_transform, Mat3x3.translate(vec2(@floatFromInt(r.x), @floatFromInt(r.y)))); + sprite_mod.send(.update, .{}); game.init(.{ .timer = try mach.Timer.start(), @@ -84,31 +100,13 @@ fn init( .time = 0, .pipeline = pipeline, }); - - // TODO(important): text module should not use global init, so that game can instruct it more clearly and then - // this after_init would be more clear. Also after_sprite_init should be renamed to after_text_init and the comment - // below is wrong: - // - // Run the rest of our init code after sprite_mod's .init_pipeline - game.send(.after_sprite_init, .{}); -} - -fn afterSpriteInit( - sprite_mod: *gfx.Sprite.Mod, - text_mod: *Text.Mod, - game: *Mod, -) !void { - const r = text_mod.state().regions.get('?').?; - try sprite_mod.set(game.state().player, .size, vec2(@floatFromInt(r.width), @floatFromInt(r.height))); - try sprite_mod.set(game.state().player, .uv_transform, Mat3x3.translate(vec2(@floatFromInt(r.x), @floatFromInt(r.y)))); - sprite_mod.send(.update, .{}); } fn tick( engine: *mach.Engine.Mod, sprite_mod: *gfx.Sprite.Mod, sprite_pipeline: *gfx.SpritePipeline.Mod, - text_mod: *Text.Mod, + glyphs: *Glyphs.Mod, game: *Mod, ) !void { // TODO(engine): event polling should occur in mach.Engine module and get fired as ECS events. @@ -154,8 +152,8 @@ fn tick( new_pos.v[0] += game.state().rand.random().floatNorm(f32) * 25; new_pos.v[1] += game.state().rand.random().floatNorm(f32) * 25; - const rand_index = game.state().rand.random().intRangeAtMost(usize, 0, text_mod.state().regions.count() - 1); - const r = text_mod.state().regions.entries.get(rand_index).value; + const rand_index = game.state().rand.random().intRangeAtMost(usize, 0, glyphs.state().regions.count() - 1); + const r = glyphs.state().regions.entries.get(rand_index).value; const new_entity = try engine.newEntity(); try sprite_mod.set(new_entity, .transform, Mat4x4.translate(new_pos).mul(&Mat4x4.scaleScalar(0.3))); diff --git a/examples/glyphs/Text.zig b/examples/glyphs/Glyphs.zig similarity index 91% rename from examples/glyphs/Text.zig rename to examples/glyphs/Glyphs.zig index 61f90f4e..23821d70 100644 --- a/examples/glyphs/Text.zig +++ b/examples/glyphs/Glyphs.zig @@ -5,15 +5,15 @@ const ft = @import("freetype"); const std = @import("std"); const assets = @import("assets"); -pub const name = .game_text; +pub const name = .glyphs; pub const Mod = mach.Mod(@This()); pub const global_events = .{ .deinit = .{ .handler = deinit }, - .init = .{ .handler = init }, }; pub const local_events = .{ + .init = .{ .handler = init }, .prepare = .{ .handler = prepare }, }; @@ -28,9 +28,9 @@ face: ft.Face, regions: RegionMap = .{}, allocator: std.mem.Allocator, -fn deinit(text_mod: *Mod) !void { - const state = text_mod.state(); - state.texture_atlas.deinit(text_mod.state().allocator); +fn deinit(glyphs: *Mod) !void { + const state = glyphs.state(); + state.texture_atlas.deinit(glyphs.state().allocator); state.texture.release(); state.face.deinit(); state.ft.deinit(); @@ -39,7 +39,7 @@ fn deinit(text_mod: *Mod) !void { fn init( engine: *mach.Engine.Mod, - text_mod: *Mod, + glyphs: *Mod, ) !void { const device = engine.state().device; const allocator = gpa.allocator(); @@ -67,25 +67,23 @@ fn init( const ft_lib = try ft.Library.init(); const face = try ft_lib.createFaceMemory(assets.roboto_medium_ttf, 0); - text_mod.init(.{ + glyphs.init(.{ .texture_atlas = texture_atlas, .texture = texture, .ft = ft_lib, .face = face, .allocator = allocator, }); - - text_mod.send(.prepare, .{&[_]u21{ '?', '!', 'a', 'b', '#', '@', '%', '$', '&', '^', '*', '+', '=', '<', '>', '/', ':', ';', 'Q', '~' }}); } fn prepare( engine: *mach.Engine.Mod, - text_mod: *Mod, + glyphs: *Mod, codepoints: []const u21, ) !void { const device = engine.state().device; const queue = device.getQueue(); - var s = text_mod.state(); + var s = glyphs.state(); for (codepoints) |codepoint| { const font_size = 48 * 1; diff --git a/examples/glyphs/main.zig b/examples/glyphs/main.zig index 32f1c6db..93e9e049 100644 --- a/examples/glyphs/main.zig +++ b/examples/glyphs/main.zig @@ -3,17 +3,14 @@ // Experimental ECS app example. Not yet ready for actual use. const mach = @import("mach"); -const Game = @import("Game.zig"); -const Text = @import("Text.zig"); - // The list of modules to be used in our application. Our game itself is implemented in our own // module called Game. pub const modules = .{ mach.Engine, mach.gfx.Sprite, mach.gfx.SpritePipeline, - Text, - Game, + @import("Glyphs.zig"), + @import("Game.zig"), }; pub const App = mach.App;