pub const core = @import("core"); pub const platform = @import("platform"); pub const assets = @import("assets"); pub const rend = @import("rend"); pub const audio = @import("audio"); // pub const graphics = @import("graphics"); // pub const vkImgui = @import("vkImgui"); // pub const ui = @import("ui"); pub const papyrus = @import("papyrus"); pub const physics = @import("physics"); pub const imgui = @import("imgui"); const modulelist = @import("modulelist.zig").list; const std = @import("std"); pub const NwArgs = struct { useGPA: bool = false, // slower zig based memory allocator, provides detailed tracking of leaks and memory violations vulkanValidation: bool = true, fastTest: bool = false, dmt: bool = false, // detailed memory tracking, implements a timeline for tracking all memory allocations fatDump: bool = false, // takes a full fat minidump on crash, very large files are produced }; pub fn getArgs() !NwArgs { const a = try core.ParseArgs(NwArgs); return a; } // entry function for a backlog program // when this function is called it will use the settings specified by the program spec // to conditionally start up feature modules within the engine var shutdownList: std.ArrayListUnmanaged(*const fn (std.mem.Allocator) void) = .{}; var shutdownModuleNames: std.ArrayListUnmanaged([]const u8) = .{}; pub fn start_modules(comptime programSpec: anytype, maybeArgs: ?NwArgs, allocator: std.mem.Allocator) !void { const Backlog = @This(); var z = core.tracy.ZoneN(@src(), "Starting all Modules"); defer z.End(); inline for (modulelist) |feature| { if (@hasDecl(Backlog, feature)) { const Struct = @field(Backlog, feature); if (comptime core.isModuleEnabled(Struct.Module, programSpec)) { var z1 = core.tracy.ZoneN(@src(), @ptrCast("Initializing Module")); defer z1.End(); core.tracy.Message(Struct.Module.name); if (maybeArgs) |args| { try Struct.start_module(programSpec, args, allocator); } else { try Struct.start_module(programSpec, NwArgs{}, allocator); } try shutdownList.append(allocator, Struct.shutdown_module); try shutdownModuleNames.append(allocator, feature); core.engine_logs("module started >>>> " ++ feature ++ " <<<<"); } } } } pub fn shutdown_modules(allocator: std.mem.Allocator) void { var i: isize = @intCast(shutdownList.items.len - 1); while (i >= 0) : (i -= 1) { core.engine_log("module shutting down >>>> {s} <<<<", .{shutdownModuleNames.items[@intCast(i)]}); shutdownList.items[@intCast(i)](allocator); } shutdownList.deinit(allocator); shutdownModuleNames.deinit(allocator); } pub fn start_everything(comptime spec: anytype, allocator: std.mem.Allocator, maybeArgs: ?NwArgs) !void { //if (maybeArgs) |args| { // //if (args.vulkanValidation) // // graphics.setStartupSettings("vulkanValidation", true); //} try start_modules(spec, maybeArgs, allocator); } pub fn shutdown_everything(allocator: std.mem.Allocator) void { shutdown_modules(allocator); } pub fn run_everything(comptime GameContext: type) !void { var canTick: bool = false; if (@hasDecl(GameContext, "tick")) { canTick = true; } core.engine_logs("creating Game context"); _ = try core.createObject(GameContext, .{ .can_tick = canTick }); core.engine_logs("calling gEngine.run"); try core.gEngine.run(); while (!core.gEngine.exitFinished()) { const z = core.tracy.ZoneN(@src(), "shutdown poll"); z.End(); } } pub fn initializeAndRunStandardProgram(comptime GameContext: type, comptime spec: anytype) !void { const args = try getArgs(); var backingAllocator: std.mem.Allocator = std.heap.c_allocator; var gpa: std.heap.GeneralPurposeAllocator(.{ .stack_trace_frames = 20, }) = .{}; defer { const cleanupStatus = gpa.deinit(); if (cleanupStatus == .leak) { std.debug.print("gpa cleanup leaked memory\n", .{}); } } if (args.useGPA) { backingAllocator = gpa.allocator(); } const memory = core.MemoryTracker; memory.MTSetup(backingAllocator, .{ .timeline = args.dmt }); defer memory.MTShutdown(); var tracker = memory.MTGet().?; const allocator = tracker.allocator(); if (args.vulkanValidation) { core.engine_logs("Using vulkan validation"); } try start_everything(spec, allocator, args); defer shutdown_everything(allocator); try run_everything(GameContext); }