Core: support configuring window before it opens
Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
122a1ea9a7
commit
205a1f33db
10 changed files with 73 additions and 23 deletions
|
|
@ -7,6 +7,7 @@ pub const Mod = mach.Mod(@This());
|
||||||
|
|
||||||
pub const systems = .{
|
pub const systems = .{
|
||||||
.init = .{ .handler = init },
|
.init = .{ .handler = init },
|
||||||
|
.after_init = .{ .handler = afterInit },
|
||||||
.deinit = .{ .handler = deinit },
|
.deinit = .{ .handler = deinit },
|
||||||
.tick = .{ .handler = tick },
|
.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 {
|
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
|
// Create our shader module
|
||||||
const shader_module = core.state().device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl"));
|
const shader_module = core.state().device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl"));
|
||||||
defer shader_module.release();
|
defer shader_module.release();
|
||||||
|
|
@ -62,7 +68,6 @@ fn init(game: *Mod, core: *mach.Core.Mod) !void {
|
||||||
core.schedule(.start);
|
core.schedule(.start);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(important): remove need for returning an error here
|
|
||||||
fn tick(core: *mach.Core.Mod, game: *Mod) !void {
|
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(important): event polling should occur in mach.Core module and get fired as ECS event.
|
||||||
// TODO(Core)
|
// TODO(Core)
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,6 @@ pub fn deinit(core: *mach.Core.Mod, renderer: *Renderer.Mod) void {
|
||||||
core.schedule(.deinit);
|
core.schedule(.deinit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(important): remove need for returning an error here
|
|
||||||
fn init(
|
fn init(
|
||||||
// These are injected dependencies - as long as these modules were registered in the top-level
|
// 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
|
// 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,
|
renderer: *Renderer.Mod,
|
||||||
game: *Mod,
|
game: *Mod,
|
||||||
) !void {
|
) !void {
|
||||||
|
core.schedule(.init);
|
||||||
renderer.schedule(.init);
|
renderer.schedule(.init);
|
||||||
|
|
||||||
// Create our player entity.
|
// Create our player entity.
|
||||||
|
|
@ -80,7 +80,6 @@ fn init(
|
||||||
core.schedule(.start);
|
core.schedule(.start);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(important): remove need for returning an error here
|
|
||||||
fn tick(
|
fn tick(
|
||||||
entities: *mach.Entities.Mod,
|
entities: *mach.Entities.Mod,
|
||||||
core: *mach.Core.Mod,
|
core: *mach.Core.Mod,
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
fn init(core: *mach.Core.Mod, sprite_pipeline: *gfx.SpritePipeline.Mod, glyphs: *Glyphs.Mod, game: *Mod) !void {
|
||||||
|
core.schedule(.init);
|
||||||
sprite_pipeline.schedule(.init);
|
sprite_pipeline.schedule(.init);
|
||||||
glyphs.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.
|
// Run our init code after glyphs module is initialized.
|
||||||
game.schedule(.after_init);
|
game.schedule(.after_init);
|
||||||
|
|
||||||
core.schedule(.start);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn afterInit(
|
fn afterInit(
|
||||||
|
|
@ -65,6 +64,7 @@ fn afterInit(
|
||||||
sprite_pipeline: *gfx.SpritePipeline.Mod,
|
sprite_pipeline: *gfx.SpritePipeline.Mod,
|
||||||
glyphs: *Glyphs.Mod,
|
glyphs: *Glyphs.Mod,
|
||||||
game: *Mod,
|
game: *Mod,
|
||||||
|
core: *mach.Core.Mod,
|
||||||
) !void {
|
) !void {
|
||||||
// Create a sprite rendering pipeline
|
// Create a sprite rendering pipeline
|
||||||
const texture = glyphs.state().texture;
|
const texture = glyphs.state().texture;
|
||||||
|
|
@ -96,6 +96,8 @@ fn afterInit(
|
||||||
.time = 0,
|
.time = 0,
|
||||||
.pipeline = pipeline,
|
.pipeline = pipeline,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
core.schedule(.start);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tick(
|
fn tick(
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,13 @@ fn init(
|
||||||
text_pipeline: *gfx.TextPipeline.Mod,
|
text_pipeline: *gfx.TextPipeline.Mod,
|
||||||
text: *gfx.Text.Mod,
|
text: *gfx.Text.Mod,
|
||||||
sprite_pipeline: *gfx.SpritePipeline.Mod,
|
sprite_pipeline: *gfx.SpritePipeline.Mod,
|
||||||
|
core: *mach.Core.Mod,
|
||||||
game: *Mod,
|
game: *Mod,
|
||||||
) !void {
|
) !void {
|
||||||
|
// If you want to try fullscreen:
|
||||||
|
// try core.set(core.state().main_window, .fullscreen, true);
|
||||||
|
|
||||||
|
core.schedule(.init);
|
||||||
audio.schedule(.init);
|
audio.schedule(.init);
|
||||||
text.schedule(.init);
|
text.schedule(.init);
|
||||||
text_pipeline.schedule(.init);
|
text_pipeline.schedule(.init);
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ pub const components = .{
|
||||||
ghost_key_mode: bool = false,
|
ghost_key_mode: bool = false,
|
||||||
|
|
||||||
fn init(core: *mach.Core.Mod, audio: *mach.Audio.Mod, app: *Mod) void {
|
fn init(core: *mach.Core.Mod, audio: *mach.Audio.Mod, app: *Mod) void {
|
||||||
|
core.schedule(.init);
|
||||||
audio.schedule(.init);
|
audio.schedule(.init);
|
||||||
app.schedule(.after_init);
|
app.schedule(.after_init);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ fn init(
|
||||||
audio: *mach.Audio.Mod,
|
audio: *mach.Audio.Mod,
|
||||||
app: *Mod,
|
app: *Mod,
|
||||||
) !void {
|
) !void {
|
||||||
|
core.schedule(.init);
|
||||||
audio.schedule(.init);
|
audio.schedule(.init);
|
||||||
app.schedule(.after_init);
|
app.schedule(.after_init);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ pub const Mod = mach.Mod(@This());
|
||||||
pub const systems = .{
|
pub const systems = .{
|
||||||
.init = .{ .handler = init },
|
.init = .{ .handler = init },
|
||||||
.deinit = .{ .handler = deinit },
|
.deinit = .{ .handler = deinit },
|
||||||
|
.after_init = .{ .handler = afterInit },
|
||||||
.tick = .{ .handler = tick },
|
.tick = .{ .handler = tick },
|
||||||
.end_frame = .{ .handler = endFrame },
|
.end_frame = .{ .handler = endFrame },
|
||||||
};
|
};
|
||||||
|
|
@ -52,14 +53,22 @@ fn deinit(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(
|
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,
|
entities: *mach.Entities.Mod,
|
||||||
core: *mach.Core.Mod,
|
core: *mach.Core.Mod,
|
||||||
sprite: *gfx.Sprite.Mod,
|
sprite: *gfx.Sprite.Mod,
|
||||||
sprite_pipeline: *gfx.SpritePipeline.Mod,
|
sprite_pipeline: *gfx.SpritePipeline.Mod,
|
||||||
game: *Mod,
|
game: *Mod,
|
||||||
) !void {
|
) !void {
|
||||||
sprite_pipeline.schedule(.init);
|
|
||||||
|
|
||||||
// We can create entities, and set components on them. Note that components live in a module
|
// 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
|
// 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.
|
// type than the `.physics2d` module's `.location` component if you desire.
|
||||||
|
|
|
||||||
|
|
@ -61,10 +61,12 @@ fn deinit(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(
|
fn init(
|
||||||
|
core: *mach.Core.Mod,
|
||||||
text: *gfx.Text.Mod,
|
text: *gfx.Text.Mod,
|
||||||
text_pipeline: *gfx.TextPipeline.Mod,
|
text_pipeline: *gfx.TextPipeline.Mod,
|
||||||
game: *Mod,
|
game: *Mod,
|
||||||
) !void {
|
) !void {
|
||||||
|
core.schedule(.init);
|
||||||
text.schedule(.init);
|
text.schedule(.init);
|
||||||
text_pipeline.schedule(.init);
|
text_pipeline.schedule(.init);
|
||||||
game.schedule(.after_init);
|
game.schedule(.after_init);
|
||||||
|
|
|
||||||
56
src/Core.zig
56
src/Core.zig
|
|
@ -11,8 +11,13 @@ pub const name = .mach_core;
|
||||||
pub const Mod = mach.Mod(@This());
|
pub const Mod = mach.Mod(@This());
|
||||||
|
|
||||||
pub const systems = .{
|
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 =
|
.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 =
|
.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
|
// TODO(important): need some way to tie event execution to a specific thread once we have a
|
||||||
// multithreaded dispatch implementation
|
// multithreaded dispatch implementation
|
||||||
.init = .{ .handler = init },
|
.init_module = .{ .handler = initModule },
|
||||||
.main_thread_tick = .{ .handler = mainThreadTick },
|
.main_thread_tick = .{ .handler = mainThreadTick },
|
||||||
.main_thread_tick_done = .{ .handler = fn () void },
|
.main_thread_tick_done = .{ .handler = fn () void },
|
||||||
};
|
};
|
||||||
|
|
@ -74,6 +79,10 @@ pub const components = .{
|
||||||
.height = .{ .type = u32, .description =
|
.height = .{ .type = u32, .description =
|
||||||
\\ The height of the window in virtual pixels
|
\\ 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.
|
/// 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;
|
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
|
mach.core.allocator = gpa.allocator(); // TODO: banish this global allocator
|
||||||
|
|
||||||
// Initialize GPU implementation
|
// Initialize GPU implementation
|
||||||
if (comptime !mach.use_sysgpu) try mach.wgpu.Impl.init(mach.core.allocator, .{});
|
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, .{});
|
if (comptime mach.use_sysgpu) try mach.sysgpu.Impl.init(mach.core.allocator, .{});
|
||||||
|
|
||||||
try mach.core.init(.{});
|
|
||||||
|
|
||||||
const main_window = try entities.new();
|
const main_window = try entities.new();
|
||||||
// TODO(important): update this information upon framebuffer resize events
|
try core.set(main_window, .fullscreen, false);
|
||||||
try core.set(main_window, .framebuffer_format, mach.core.descriptor.format);
|
try core.set(main_window, .width, 1920 / 2);
|
||||||
try core.set(main_window, .framebuffer_width, mach.core.descriptor.width);
|
try core.set(main_window, .height, 1080 / 2);
|
||||||
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);
|
|
||||||
|
|
||||||
core.init(.{
|
core.init(.{
|
||||||
.allocator = mach.core.allocator,
|
.allocator = undefined,
|
||||||
.device = mach.core.device,
|
.device = undefined,
|
||||||
.queue = mach.core.device.getQueue(),
|
.queue = undefined,
|
||||||
.main_window = main_window,
|
.main_window = main_window,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ pub fn initModule() !void {
|
||||||
// Initialize the global set of Mach modules used in the program.
|
// Initialize the global set of Mach modules used in the program.
|
||||||
try mods.init(std.heap.c_allocator);
|
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.
|
/// Tick runs a single step of the main loop on the main OS thread.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue