const std = @import("std"); const GeneralPurposeAllocator = std.heap.GeneralPurposeAllocator(.{}); const core = @import("mach").core; const Renderer = @import("./renderer.zig"); pub const App = @This(); gpa: GeneralPurposeAllocator, allocator: std.mem.Allocator, random: std.rand.Random, renderer: *Renderer, app_timer: core.Timer, title_timer: core.Timer, pub fn init(app: *App) !void { try core.init(.{ // Request high performance = prefer dedicated GPU when available. .power_preference = .high_performance, }); // Set up a "general purpose allocator" that will handle allocations for // the lifetime of the application, for which a more specific allocation // strategy is not necessary. // // Here, `gpa` is an instance of this allocator, which handles the // allocation logic, while `allocator` is the interface through which // functions such as `alloc` and `free` are called. app.gpa = GeneralPurposeAllocator{}; app.allocator = app.gpa.allocator(); // Create a pseudo-random number generator, but initialize it with // a constant seed so we always get the same result when launching. var prng = std.rand.DefaultPrng.init(0); app.random = prng.random(); app.renderer = try Renderer.init(app); app.app_timer = try core.Timer.start(); app.title_timer = try core.Timer.start(); } pub fn deinit(app: *App) void { // Using `defer` here, so we can specify them // in the order they were created in `init`. defer core.deinit(); defer _ = app.gpa.deinit(); // TODO: Check for memory leaks? defer app.renderer.deinit(); } pub fn update(app: *App) !bool { // Read events from the OS such as input. var iter = core.pollEvents(); while (iter.next()) |event| { switch (event) { // Allow the renderer to act on the window being resized. // This is required so we can resize necessary buffers. .framebuffer_resize => |_| app.renderer.resize(), // Close the window when requested, such as when // pressing the X button in the window title bar. .close => return true, else => {}, } } app.renderer.update(); // Update the window title to show FPS and input frequency. if (app.title_timer.read() >= 1.0) { app.title_timer.reset(); try core.printTitle("Triangle [ {d}fps ] [ Input {d}hz ]", .{ core.frameRate(), core.inputRate() }); } return false; }