Add support for launch args and "dump_shader_translations" arg #59
							
								
								
									
										10
									
								
								src/main.zig
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								src/main.zig
									
									
									
									
									
								
							| @ -30,12 +30,10 @@ const Player = struct { | ||||
| 	move_y: ona.act.Axis = .{.keys = .{.w, .s}}, | ||||
| }; | ||||
| 
 | ||||
| pub fn main() !void { | ||||
| 	try ona.start_app(setup, .{ | ||||
| 		.tick_rate = 60, | ||||
| 		.execution = .{.thread_share = 0.1}, | ||||
| 	}); | ||||
| } | ||||
| pub const main = ona.start(setup, .{ | ||||
| 	.tick_rate = 60, | ||||
| 	.execution = .{.thread_share = 0.1}, | ||||
| }); | ||||
| 
 | ||||
| fn load(config: ona.Write(ona.gfx.Config), actors: ona.Write(Actors), assets: ona.Write(ona.gfx.Assets)) !void { | ||||
| 	config.res.width, config.res.height = .{1280, 720}; | ||||
|  | ||||
| @ -1,25 +0,0 @@ | ||||
| const coral = @import("coral"); | ||||
| 
 | ||||
| const flow = @import("flow"); | ||||
| 
 | ||||
| events: *const Events, | ||||
| target_frame_time: f64, | ||||
| elapsed_time: f64, | ||||
| is_running: bool, | ||||
| 
 | ||||
| pub const Events = struct { | ||||
| 	load: flow.World.Event, | ||||
| 	pre_update: flow.World.Event, | ||||
| 	update: flow.World.Event, | ||||
| 	post_update: flow.World.Event, | ||||
| 	render: flow.World.Event, | ||||
| 	finish: flow.World.Event, | ||||
| 	exit: flow.World.Event, | ||||
| }; | ||||
| 
 | ||||
| const Self = @This(); | ||||
| 
 | ||||
| pub fn quit(self: *Self) void { | ||||
| 	self.is_running = false; | ||||
| } | ||||
| 
 | ||||
| @ -1,17 +1,13 @@ | ||||
| const App = @import("./App.zig"); | ||||
| 
 | ||||
| const coral = @import("coral"); | ||||
| 
 | ||||
| const flow = @import("flow"); | ||||
| 
 | ||||
| const gfx = @import("./gfx.zig"); | ||||
| 
 | ||||
| const msg = @import("./msg.zig"); | ||||
| const ona = @import("./ona.zig"); | ||||
| 
 | ||||
| const std = @import("std"); | ||||
| 
 | ||||
| pub const Axis = struct { | ||||
| 	keys: ?[2]gfx.Input.Key = null, | ||||
| 	keys: ?[2]ona.gfx.Input.Key = null, | ||||
| }; | ||||
| 
 | ||||
| pub const Mapping = struct { | ||||
| @ -37,7 +33,7 @@ pub const Mapping = struct { | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| pub fn setup(world: *flow.World, events: App.Events) std.mem.Allocator.Error!void { | ||||
| pub fn setup(world: *flow.World, events: ona.App.Events) std.mem.Allocator.Error!void { | ||||
| 	try world.set_state(Mapping{}); | ||||
| 
 | ||||
| 	try world.on_event(events.pre_update, flow.system_fn(update), .{ | ||||
| @ -45,7 +41,7 @@ pub fn setup(world: *flow.World, events: App.Events) std.mem.Allocator.Error!voi | ||||
| 	}); | ||||
| } | ||||
| 
 | ||||
| pub fn update(inputs: msg.Receive(gfx.Input), mapping: flow.Write(Mapping)) void { | ||||
| pub fn update(inputs: ona.msg.Receive(ona.gfx.Input), mapping: flow.Write(Mapping)) void { | ||||
| 	mapping.res.keys_pressed = Mapping.ScancodeSet.initEmpty(); | ||||
| 
 | ||||
| 	for (inputs.messages()) |message| { | ||||
|  | ||||
| @ -1,5 +1,3 @@ | ||||
| const App = @import("./App.zig"); | ||||
| 
 | ||||
| pub const colors = @import("./gfx/colors.zig"); | ||||
| 
 | ||||
| const coral = @import("coral"); | ||||
| @ -8,7 +6,7 @@ const ext = @import("./ext.zig"); | ||||
| 
 | ||||
| const flow = @import("flow"); | ||||
| 
 | ||||
| const msg = @import("./msg.zig"); | ||||
| const ona = @import("./ona.zig"); | ||||
| 
 | ||||
| const rendering = @import("./gfx/rendering.zig"); | ||||
| 
 | ||||
| @ -437,7 +435,7 @@ fn load_bmp_texture(arena: *std.heap.ArenaAllocator, storage: coral.files.Storag | ||||
| 	}; | ||||
| } | ||||
| 
 | ||||
| pub fn poll(app: flow.Write(App), inputs: msg.Send(Input)) !void { | ||||
| pub fn poll(app: flow.Write(ona.App), inputs: ona.msg.Send(Input)) !void { | ||||
| 	var event = @as(ext.SDL_Event, undefined); | ||||
| 
 | ||||
| 	while (ext.SDL_PollEvent(&event) != 0) { | ||||
| @ -450,7 +448,7 @@ pub fn poll(app: flow.Write(App), inputs: msg.Send(Input)) !void { | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| pub fn setup(world: *flow.World, events: App.Events) (error {Unsupported} || std.Thread.SpawnError || std.mem.Allocator.Error)!void { | ||||
| pub fn setup(world: *flow.World, events: ona.App.Events) (error {Unsupported} || std.Thread.SpawnError || std.mem.Allocator.Error)!void { | ||||
| 	if (ext.SDL_Init(ext.SDL_INIT_VIDEO) != 0) { | ||||
| 		return error.Unsupported; | ||||
| 	} | ||||
|  | ||||
| @ -4,6 +4,8 @@ const ext = @cImport({ | ||||
| 	@cInclude("spirv-cross/spirv_cross_c.h"); | ||||
| }); | ||||
| 
 | ||||
| const ona = @import("../ona.zig"); | ||||
| 
 | ||||
| const std = @import("std"); | ||||
| 
 | ||||
| pub const Error = std.mem.Allocator.Error || error { | ||||
| @ -283,7 +285,9 @@ pub fn analyze(arena: *std.heap.ArenaAllocator, options: Options) Error!Program | ||||
| 			try stage.reflect_images_samplers(arena, compiler, resources); | ||||
| 			try stage.reflect_uniform_blocks(arena, compiler, resources); | ||||
| 
 | ||||
| 			std.log.info("{s}", .{stage.source}); | ||||
| 			if (ona.launch_arg(.dump_shader_translations) != null) { | ||||
| 				std.log.info("Vertex translated:\n{s}", .{stage.source}); | ||||
| 			} | ||||
| 
 | ||||
| 			break: vertex_stage stage; | ||||
| 		}, | ||||
| @ -307,7 +311,9 @@ pub fn analyze(arena: *std.heap.ArenaAllocator, options: Options) Error!Program | ||||
| 			try stage.reflect_images_samplers(arena, compiler, resources); | ||||
| 			try stage.reflect_uniform_blocks(arena, compiler, resources); | ||||
| 
 | ||||
| 			std.log.info("{s}", .{stage.source}); | ||||
| 			if (ona.launch_arg(.dump_shader_translations) != null) { | ||||
| 				std.log.info("Fragment translated:\n{s}", .{stage.source}); | ||||
| 			} | ||||
| 
 | ||||
| 			break: fragment_stage stage; | ||||
| 		}, | ||||
|  | ||||
| @ -1,9 +1,9 @@ | ||||
| const App = @import("./App.zig"); | ||||
| 
 | ||||
| const coral = @import("coral"); | ||||
| 
 | ||||
| const flow = @import("flow"); | ||||
| 
 | ||||
| const ona = @import("./ona.zig"); | ||||
| 
 | ||||
| const std = @import("std"); | ||||
| 
 | ||||
| fn Channel(comptime Message: type) type { | ||||
| @ -106,7 +106,7 @@ pub fn Send(comptime Message: type) type { | ||||
| 				.channel = (try context.register_writable_state_access(TypedChannel)) orelse set: { | ||||
| 					try context.world.set_state(TypedChannel.init(coral.heap.allocator)); | ||||
| 
 | ||||
| 					const app = context.world.get_state(App).?; | ||||
| 					const app = context.world.get_state(ona.App).?; | ||||
| 
 | ||||
| 					try context.world.on_event(app.events.post_update, flow.system_fn(TypedChannel.swap), .{ | ||||
| 						.label = "swap channel of " ++ @typeName(Message), | ||||
|  | ||||
							
								
								
									
										179
									
								
								src/ona/ona.zig
									
									
									
									
									
								
							
							
						
						
									
										179
									
								
								src/ona/ona.zig
									
									
									
									
									
								
							| @ -1,5 +1,3 @@ | ||||
| pub const App = @import("./App.zig"); | ||||
| 
 | ||||
| pub const act = @import("./act.zig"); | ||||
| 
 | ||||
| const coral = @import("coral"); | ||||
| @ -14,6 +12,35 @@ pub const msg = @import("./msg.zig"); | ||||
| 
 | ||||
| const std = @import("std"); | ||||
| 
 | ||||
| pub const App = struct { | ||||
| 	events: *const Events, | ||||
| 	target_frame_time: f64, | ||||
| 	elapsed_time: f64, | ||||
| 	is_running: bool, | ||||
| 
 | ||||
| 	pub const Events = struct { | ||||
| 		load: flow.World.Event, | ||||
| 		pre_update: flow.World.Event, | ||||
| 		update: flow.World.Event, | ||||
| 		post_update: flow.World.Event, | ||||
| 		render: flow.World.Event, | ||||
| 		finish: flow.World.Event, | ||||
| 		exit: flow.World.Event, | ||||
| 	}; | ||||
| 
 | ||||
| 	pub fn quit(self: *App) void { | ||||
| 		self.is_running = false; | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| pub const Flag = enum { | ||||
| 	dump_shader_translations, | ||||
| 
 | ||||
| 	var launch_args = [_]?[]const u8{null} ** std.enums.values(Flag).len; | ||||
| 
 | ||||
| 	const values = std.enums.values(Flag); | ||||
| }; | ||||
| 
 | ||||
| pub const Options = struct { | ||||
| 	tick_rate: u64, | ||||
| 	execution: Execution, | ||||
| @ -38,79 +65,111 @@ pub const default_middlewares = &.{ | ||||
| 	act.setup, | ||||
| }; | ||||
| 
 | ||||
| pub fn start_app(setup: Setup, options: Options) anyerror!void { | ||||
| 	defer { | ||||
| 		coral.heap.trace_leaks(); | ||||
| 		ext.SDL_Quit(); | ||||
| 	} | ||||
| pub fn launch_arg(flag: Flag) ?[]const u8 { | ||||
| 	return Flag.launch_args[@intFromEnum(flag)]; | ||||
| } | ||||
| 
 | ||||
| 	var world = try switch (options.execution) { | ||||
| 		.single_threaded => flow.World.init(0), | ||||
| pub fn start(comptime setup: Setup, options: Options) fn () anyerror!void { | ||||
| 	const Start = struct { | ||||
| 		fn main() anyerror!void { | ||||
| 			defer { | ||||
| 				coral.heap.trace_leaks(); | ||||
| 				ext.SDL_Quit(); | ||||
| 			} | ||||
| 
 | ||||
| 		.thread_share => |thread_share| init: { | ||||
| 			const cpu_count = @as(u32, @intCast(std.math.clamp(std.Thread.getCpuCount() catch |cpu_count_error| { | ||||
| 				@panic(switch (cpu_count_error) { | ||||
| 					error.PermissionDenied => "permission denied retrieving CPU count", | ||||
| 					error.SystemResources => "system resources are preventing retrieval of the CPU count", | ||||
|     				error.Unexpected => "unexpected failure retrieving CPU count", | ||||
| 				}); | ||||
| 			}, 0, std.math.maxInt(u32)))); | ||||
| 			parse_args: for (std.os.argv[1 ..]) |arg| { | ||||
| 				const arg_span = std.mem.span(arg); | ||||
| 				const arg_split_index = std.mem.indexOfScalar(u8, arg_span, '=') orelse arg_span.len; | ||||
| 				const arg_name = arg_span[0 .. arg_split_index]; | ||||
| 
 | ||||
| 			break: init flow.World.init(coral.scalars.fractional(cpu_count, thread_share) orelse 0); | ||||
| 		}, | ||||
| 	}; | ||||
| 				for (Flag.values) |value| { | ||||
| 					const name = @tagName(value); | ||||
| 
 | ||||
| 	defer world.deinit(); | ||||
| 					if (!std.mem.eql(u8, arg_name, name)) { | ||||
| 						continue; | ||||
| 					} | ||||
| 
 | ||||
| 	const events = App.Events{ | ||||
| 		.load = try world.create_event("load"), | ||||
| 		.pre_update = try world.create_event("pre-update"), | ||||
| 		.update = try world.create_event("update"), | ||||
| 		.post_update = try world.create_event("post-update"), | ||||
| 		.render = try world.create_event("render"), | ||||
| 		.finish = try world.create_event("finish"), | ||||
| 		.exit = try world.create_event("exit"), | ||||
| 	}; | ||||
| 					Flag.launch_args[@intFromEnum(value)] = | ||||
| 						if (arg_split_index == arg_span.len) | ||||
| 							name | ||||
| 						else | ||||
| 							arg_span[arg_split_index ..]; | ||||
| 
 | ||||
| 	const app = try world.set_get_state(App{ | ||||
| 		.events = &events, | ||||
| 		.target_frame_time = 1.0 / @as(f64, @floatFromInt(options.tick_rate)), | ||||
| 		.elapsed_time = 0, | ||||
| 		.is_running = true, | ||||
| 	}); | ||||
| 					continue: parse_args; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 	for (options.middlewares) |setup_middleware| { | ||||
| 		try setup_middleware(&world, events); | ||||
| 	} | ||||
| 			var world = try switch (options.execution) { | ||||
| 				.single_threaded => flow.World.init(0), | ||||
| 
 | ||||
| 	try setup(&world, events); | ||||
| 	try world.run_event(events.load); | ||||
| 				.thread_share => |thread_share| init: { | ||||
| 					const cpu_count = @as(u32, @intCast(std.math.clamp(std.Thread.getCpuCount() catch |cpu_count_error| { | ||||
| 						@panic(switch (cpu_count_error) { | ||||
| 							error.PermissionDenied => "permission denied retrieving CPU count", | ||||
| 							error.SystemResources => "system resources are preventing retrieval of the CPU count", | ||||
| 							error.Unexpected => "unexpected failure retrieving CPU count", | ||||
| 						}); | ||||
| 					}, 0, std.math.maxInt(u32)))); | ||||
| 
 | ||||
| 	const ticks_initial = std.time.milliTimestamp(); | ||||
| 	var ticks_previous = ticks_initial; | ||||
| 	var accumulated_time = @as(f64, 0); | ||||
| 					break: init flow.World.init(coral.scalars.fractional(cpu_count, thread_share) orelse 0); | ||||
| 				}, | ||||
| 			}; | ||||
| 
 | ||||
| 	while (app.is_running) { | ||||
| 		const ticks_current = std.time.milliTimestamp(); | ||||
| 		const milliseconds_per_second = 1000.0; | ||||
| 		const delta_time = @as(f64, @floatFromInt(ticks_current - ticks_previous)) / milliseconds_per_second; | ||||
| 			defer world.deinit(); | ||||
| 
 | ||||
| 		app.elapsed_time = @as(f64, @floatFromInt(ticks_current - ticks_initial)) / milliseconds_per_second; | ||||
| 		ticks_previous = ticks_current; | ||||
| 		accumulated_time += delta_time; | ||||
| 			const events = App.Events{ | ||||
| 				.load = try world.create_event("load"), | ||||
| 				.pre_update = try world.create_event("pre-update"), | ||||
| 				.update = try world.create_event("update"), | ||||
| 				.post_update = try world.create_event("post-update"), | ||||
| 				.render = try world.create_event("render"), | ||||
| 				.finish = try world.create_event("finish"), | ||||
| 				.exit = try world.create_event("exit"), | ||||
| 			}; | ||||
| 
 | ||||
| 		try world.run_event(events.pre_update); | ||||
| 			const app = try world.set_get_state(App{ | ||||
| 				.events = &events, | ||||
| 				.target_frame_time = 1.0 / @as(f64, @floatFromInt(options.tick_rate)), | ||||
| 				.elapsed_time = 0, | ||||
| 				.is_running = true, | ||||
| 			}); | ||||
| 
 | ||||
| 		while (accumulated_time >= app.target_frame_time) : (accumulated_time -= app.target_frame_time) { | ||||
| 			try world.run_event(events.update); | ||||
| 			for (options.middlewares) |setup_middleware| { | ||||
| 				try setup_middleware(&world, events); | ||||
| 			} | ||||
| 
 | ||||
| 			try setup(&world, events); | ||||
| 			try world.run_event(events.load); | ||||
| 
 | ||||
| 			const ticks_initial = std.time.milliTimestamp(); | ||||
| 			var ticks_previous = ticks_initial; | ||||
| 			var accumulated_time = @as(f64, 0); | ||||
| 
 | ||||
| 			while (app.is_running) { | ||||
| 				const ticks_current = std.time.milliTimestamp(); | ||||
| 				const milliseconds_per_second = 1000.0; | ||||
| 				const delta_time = @as(f64, @floatFromInt(ticks_current - ticks_previous)) / milliseconds_per_second; | ||||
| 
 | ||||
| 				app.elapsed_time = @as(f64, @floatFromInt(ticks_current - ticks_initial)) / milliseconds_per_second; | ||||
| 				ticks_previous = ticks_current; | ||||
| 				accumulated_time += delta_time; | ||||
| 
 | ||||
| 				try world.run_event(events.pre_update); | ||||
| 
 | ||||
| 				while (accumulated_time >= app.target_frame_time) : (accumulated_time -= app.target_frame_time) { | ||||
| 					try world.run_event(events.update); | ||||
| 				} | ||||
| 
 | ||||
| 				try world.run_event(events.post_update); | ||||
| 				try world.run_event(events.render); | ||||
| 				try world.run_event(events.finish); | ||||
| 			} | ||||
| 
 | ||||
| 			try world.run_event(events.exit); | ||||
| 		} | ||||
| 	}; | ||||
| 
 | ||||
| 		try world.run_event(events.post_update); | ||||
| 		try world.run_event(events.render); | ||||
| 		try world.run_event(events.finish); | ||||
| 	} | ||||
| 
 | ||||
| 	try world.run_event(events.exit); | ||||
| 	return Start.main; | ||||
| } | ||||
| 
 | ||||
| pub const system_fn = flow.system_fn; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user