diff --git a/examples/core-custom-entrypoint/App.zig b/examples/core-custom-entrypoint/App.zig index 7b088a7d..afef225f 100644 --- a/examples/core-custom-entrypoint/App.zig +++ b/examples/core-custom-entrypoint/App.zig @@ -7,6 +7,7 @@ pub const Mod = mach.Mod(@This()); pub const systems = .{ .init = .{ .handler = init }, + .after_init = .{ .handler = afterInit }, .deinit = .{ .handler = deinit }, .tick = .{ .handler = tick }, }; @@ -20,6 +21,11 @@ pub fn deinit(core: *mach.Core.Mod, game: *Mod) void { } fn init(game: *Mod, core: *mach.Core.Mod) !void { + core.schedule(.init); + game.schedule(.after_init); +} + +fn afterInit(game: *Mod, core: *mach.Core.Mod) !void { // Create our shader module const shader_module = core.state().device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); defer shader_module.release(); @@ -62,7 +68,6 @@ fn init(game: *Mod, core: *mach.Core.Mod) !void { core.schedule(.start); } -// TODO(important): remove need for returning an error here fn tick(core: *mach.Core.Mod, game: *Mod) !void { // TODO(important): event polling should occur in mach.Core module and get fired as ECS event. // TODO(Core) diff --git a/examples/custom-renderer/App.zig b/examples/custom-renderer/App.zig index fa4cb209..9cea5b10 100644 --- a/examples/custom-renderer/App.zig +++ b/examples/custom-renderer/App.zig @@ -43,7 +43,6 @@ pub fn deinit(core: *mach.Core.Mod, renderer: *Renderer.Mod) void { core.schedule(.deinit); } -// TODO(important): remove need for returning an error here fn init( // These are injected dependencies - as long as these modules were registered in the top-level // of the program we can have these types injected here, letting us work with other modules in @@ -53,6 +52,7 @@ fn init( renderer: *Renderer.Mod, game: *Mod, ) !void { + core.schedule(.init); renderer.schedule(.init); // Create our player entity. @@ -80,7 +80,6 @@ fn init( core.schedule(.start); } -// TODO(important): remove need for returning an error here fn tick( entities: *mach.Entities.Mod, core: *mach.Core.Mod, diff --git a/examples/glyphs/App.zig b/examples/glyphs/App.zig index 73bc77c5..e2517ac7 100644 --- a/examples/glyphs/App.zig +++ b/examples/glyphs/App.zig @@ -47,6 +47,7 @@ fn deinit(core: *mach.Core.Mod, sprite_pipeline: *gfx.SpritePipeline.Mod, glyphs } fn init(core: *mach.Core.Mod, sprite_pipeline: *gfx.SpritePipeline.Mod, glyphs: *Glyphs.Mod, game: *Mod) !void { + core.schedule(.init); sprite_pipeline.schedule(.init); glyphs.schedule(.init); @@ -55,8 +56,6 @@ fn init(core: *mach.Core.Mod, sprite_pipeline: *gfx.SpritePipeline.Mod, glyphs: // Run our init code after glyphs module is initialized. game.schedule(.after_init); - - core.schedule(.start); } fn afterInit( @@ -65,6 +64,7 @@ fn afterInit( sprite_pipeline: *gfx.SpritePipeline.Mod, glyphs: *Glyphs.Mod, game: *Mod, + core: *mach.Core.Mod, ) !void { // Create a sprite rendering pipeline const texture = glyphs.state().texture; @@ -96,6 +96,8 @@ fn afterInit( .time = 0, .pipeline = pipeline, }); + + core.schedule(.start); } fn tick( diff --git a/examples/hardware-check/App.zig b/examples/hardware-check/App.zig index fd983b72..dbbd874c 100644 --- a/examples/hardware-check/App.zig +++ b/examples/hardware-check/App.zig @@ -66,8 +66,13 @@ fn init( text_pipeline: *gfx.TextPipeline.Mod, text: *gfx.Text.Mod, sprite_pipeline: *gfx.SpritePipeline.Mod, + core: *mach.Core.Mod, game: *Mod, ) !void { + // If you want to try fullscreen: + // try core.set(core.state().main_window, .fullscreen, true); + + core.schedule(.init); audio.schedule(.init); text.schedule(.init); text_pipeline.schedule(.init); diff --git a/examples/piano/App.zig b/examples/piano/App.zig index 50402d41..8a1efee0 100644 --- a/examples/piano/App.zig +++ b/examples/piano/App.zig @@ -38,6 +38,7 @@ pub const components = .{ ghost_key_mode: bool = false, fn init(core: *mach.Core.Mod, audio: *mach.Audio.Mod, app: *Mod) void { + core.schedule(.init); audio.schedule(.init); app.schedule(.after_init); diff --git a/examples/play-opus/App.zig b/examples/play-opus/App.zig index c905ab78..b71009ff 100644 --- a/examples/play-opus/App.zig +++ b/examples/play-opus/App.zig @@ -37,6 +37,7 @@ fn init( audio: *mach.Audio.Mod, app: *Mod, ) !void { + core.schedule(.init); audio.schedule(.init); app.schedule(.after_init); diff --git a/examples/sprite/App.zig b/examples/sprite/App.zig index edb35e0d..8a4953d5 100644 --- a/examples/sprite/App.zig +++ b/examples/sprite/App.zig @@ -39,6 +39,7 @@ pub const Mod = mach.Mod(@This()); pub const systems = .{ .init = .{ .handler = init }, .deinit = .{ .handler = deinit }, + .after_init = .{ .handler = afterInit }, .tick = .{ .handler = tick }, .end_frame = .{ .handler = endFrame }, }; @@ -52,14 +53,22 @@ fn deinit( } fn init( + core: *mach.Core.Mod, + sprite_pipeline: *gfx.SpritePipeline.Mod, + game: *Mod, +) !void { + core.schedule(.init); + sprite_pipeline.schedule(.init); + game.schedule(.after_init); +} + +fn afterInit( entities: *mach.Entities.Mod, core: *mach.Core.Mod, sprite: *gfx.Sprite.Mod, sprite_pipeline: *gfx.SpritePipeline.Mod, game: *Mod, ) !void { - sprite_pipeline.schedule(.init); - // We can create entities, and set components on them. Note that components live in a module // namespace, e.g. the `.mach_gfx_sprite` module could have a 3D `.location` component with a different // type than the `.physics2d` module's `.location` component if you desire. diff --git a/examples/text/App.zig b/examples/text/App.zig index 1dcb5481..cc8c9605 100644 --- a/examples/text/App.zig +++ b/examples/text/App.zig @@ -61,10 +61,12 @@ fn deinit( } fn init( + core: *mach.Core.Mod, text: *gfx.Text.Mod, text_pipeline: *gfx.TextPipeline.Mod, game: *Mod, ) !void { + core.schedule(.init); text.schedule(.init); text_pipeline.schedule(.init); game.schedule(.after_init); diff --git a/src/Core.zig b/src/Core.zig index b3be208c..4b251e5d 100644 --- a/src/Core.zig +++ b/src/Core.zig @@ -11,8 +11,13 @@ pub const name = .mach_core; pub const Mod = mach.Mod(@This()); pub const systems = .{ + .init = .{ .handler = init, .description = + \\ Send this once you've configured any options you want on e.g. the core.state().main_window + }, + .start = .{ .handler = start, .description = - \\ Send this once your app is initialized and ready for .app.tick events. + \\ Send this once your .app.init has been handled, you've sent .mach_core.init, and you are ready + \\ for .app.tick events. }, .update = .{ .handler = update, .description = @@ -38,7 +43,7 @@ pub const systems = .{ // TODO(important): need some way to tie event execution to a specific thread once we have a // multithreaded dispatch implementation - .init = .{ .handler = init }, + .init_module = .{ .handler = initModule }, .main_thread_tick = .{ .handler = mainThreadTick }, .main_thread_tick_done = .{ .handler = fn () void }, }; @@ -74,6 +79,10 @@ pub const components = .{ .height = .{ .type = u32, .description = \\ The height of the window in virtual pixels }, + + .fullscreen = .{ .type = bool, .description = + \\ Whether the window should be fullscreen (only respected at .start time) + }, }; /// Prints into the window title buffer using a format string and arguments. e.g. @@ -113,27 +122,44 @@ fn start(core: *Mod) !void { core.state().run_state = .running; } -fn init(entities: *mach.Entities.Mod, core: *Mod) !void { +fn init(core: *Mod) !void { + try mach.core.init(.{ + .display_mode = if (core.get(core.state().main_window, .fullscreen).?) .fullscreen else .windowed, + .size = .{ + .width = core.get(core.state().main_window, .width).?, + .height = core.get(core.state().main_window, .height).?, + }, + // TODO: expose this option + .power_preference = .high_performance, + }); + + // TODO(important): update this information upon framebuffer resize events + try core.set(core.state().main_window, .framebuffer_format, mach.core.descriptor.format); + try core.set(core.state().main_window, .framebuffer_width, mach.core.descriptor.width); + try core.set(core.state().main_window, .framebuffer_height, mach.core.descriptor.height); + try core.set(core.state().main_window, .width, mach.core.size().width); + try core.set(core.state().main_window, .height, mach.core.size().height); + + core.state().allocator = mach.core.allocator; + core.state().device = mach.core.device; + core.state().queue = mach.core.device.getQueue(); +} + +fn initModule(entities: *mach.Entities.Mod, core: *Mod) !void { mach.core.allocator = gpa.allocator(); // TODO: banish this global allocator // Initialize GPU implementation if (comptime !mach.use_sysgpu) try mach.wgpu.Impl.init(mach.core.allocator, .{}); if (comptime mach.use_sysgpu) try mach.sysgpu.Impl.init(mach.core.allocator, .{}); - try mach.core.init(.{}); - const main_window = try entities.new(); - // TODO(important): update this information upon framebuffer resize events - try core.set(main_window, .framebuffer_format, mach.core.descriptor.format); - try core.set(main_window, .framebuffer_width, mach.core.descriptor.width); - try core.set(main_window, .framebuffer_height, mach.core.descriptor.height); - try core.set(main_window, .width, mach.core.size().width); - try core.set(main_window, .height, mach.core.size().height); - + try core.set(main_window, .fullscreen, false); + try core.set(main_window, .width, 1920 / 2); + try core.set(main_window, .height, 1080 / 2); core.init(.{ - .allocator = mach.core.allocator, - .device = mach.core.device, - .queue = mach.core.device.getQueue(), + .allocator = undefined, + .device = undefined, + .queue = undefined, .main_window = main_window, }); diff --git a/src/core/main.zig b/src/core/main.zig index d09a0cd9..bd3e3511 100644 --- a/src/core/main.zig +++ b/src/core/main.zig @@ -16,7 +16,7 @@ pub fn initModule() !void { // Initialize the global set of Mach modules used in the program. try mods.init(std.heap.c_allocator); - mods.schedule(.mach_core, .init); + mods.schedule(.mach_core, .init_module); } /// Tick runs a single step of the main loop on the main OS thread.