diff --git a/build.zig b/build.zig index 67cd029..5c57bb5 100644 --- a/build.zig +++ b/build.zig @@ -139,65 +139,6 @@ pub fn addProgram(self: *BuildSystem, opts: AddProgramOptions) *std.Build.Module run_exe.dependOn(&cookShadersCommand.step); } - // I want to generate definitions from the spirv-reflect-tool during pre-build. - // - // shaders will now be part of content, not code. However. .zig code definitions will be generated - // from content via the build.zig script. - // - // heres some thoughts: - // - // -Dupdate_shaders=true - // - // -Dupdate_shaders basically adds a run step to the build process 'python', 'tools/scripts/cook-shaders.py' - // - // 1. ensure spirv-reflect is compiled. - // 2. shadercross cooker generates all shader outputs - specifically spv files. they are output to content/_shaders/ - // - search paths for shaders: - // - content/shaders/** - // - engine//shaders/** - // - shaders must have a unique name across the entire project, naming scheme should be .shadername..hlsl - // 3. spirv-cross --reflect is called on each shader, updating the content/_shaders/defs/shader-name.json folder with up to date .json files - // - // final tree - // - // engine/ - // - ui/ - // - shaders/ - // - papyrus.rect.vert.hlsl - // content/ - // - _shaders/ - // - def/ - // papyrus.rect.vert.json - // - msl/ - // papyrus.rect.vert.msl - // - spv/ - // papyrus.rect.vert.spv - // - dxil/ - // papyrus.rect.vert.dxil - // - // - // During build: - // 1. spirv-reflect is called on each json in each folder and .zig shader interfaces added to the executable as a global import. - // 2. if -Dupdate_shaders is not - // - // At any time: - // asset-cooker will cook shaders and place them under content/_shaders//. - - // self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/triangle_mesh.vert"), "triangle_mesh_vert"); - // self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/default_lit.frag"), "default_lit"); - - // self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/debug.vert"), "debug_vert"); - // self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/debug.frag"), "debug_frag"); - - // self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/skybox/skybox.vert"), "skybox_vert"); - // self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/graphics/shaders/skybox/skybox.frag"), "skybox_frag"); - - // self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/ui/shaders/PapyrusRect.vert"), "papyrus_vk_vert"); - // self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/ui/shaders/PapyrusRect.frag"), "papyrus_vk_frag"); - - // self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/ui/shaders/FontSDF.vert"), "FontSDF_vert"); - // self.spirvReflect.addShaderInstallRef(exe, self.nw_builder.path("engine/ui/shaders/FontSDF.frag"), "FontSDF_frag"); - b.getInstallStep().dependOn(self.nw_builder.getInstallStep()); return mod; diff --git a/engine/assets/src/asset_references.zig b/engine/assets/src/asset_references.zig index d7185a7..189c9d4 100644 --- a/engine/assets/src/asset_references.zig +++ b/engine/assets/src/asset_references.zig @@ -157,12 +157,17 @@ pub const AssetReferenceSys = struct { allocator: std.mem.Allocator, outstandingAssetJobs: std.atomic.Value(i32), - pub fn init(allocator: std.mem.Allocator) @This() { - return @This(){ + pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "AssetReference"); + + pub fn init(allocator: std.mem.Allocator) !*@This() { + const self = try allocator.create(@This()); + self.* = @This(){ .loaders = .{}, .allocator = allocator, .outstandingAssetJobs = std.atomic.Value(i32).init(0), }; + + return self; } pub fn registerLoader(self: *@This(), loader: anytype) !void { @@ -205,5 +210,6 @@ pub const AssetReferenceSys = struct { // i.destroy(self.allocator); // } self.loaders.deinit(self.allocator); + self.allocator.destroy(self); } }; diff --git a/engine/assets/src/assets.zig b/engine/assets/src/assets.zig index 9664a5c..6a1b5f6 100644 --- a/engine/assets/src/assets.zig +++ b/engine/assets/src/assets.zig @@ -19,8 +19,6 @@ pub const MakeImportRefOptions = asset_references.MakeImportRefOptions; pub const AsyncAssetJobContext = asset_jobs.AsyncAssetJobContext; -pub var gAssetSys: *AssetReferenceSys = undefined; - pub const Module = core.ModuleDescription{ .name = "assets", .enabledByDefault = true, @@ -28,6 +26,8 @@ pub const Module = core.ModuleDescription{ var cooking: bool = false; +pub const getAssets = core.EngineObject(AssetReferenceSys).get; + pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.mem.Allocator) !void { _ = args; @@ -38,8 +38,9 @@ pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.me try cook.startup(allocator); } - gAssetSys = allocator.create(AssetReferenceSys) catch @panic("unable to initialize asset reference"); - gAssetSys.* = AssetReferenceSys.init(allocator); + //gAssetSys = allocator.create(AssetReferenceSys) catch @panic("unable to initialize asset reference"); + //gAssetSys.* = AssetReferenceSys.init(allocator); + _ = try core.createObject(AssetReferenceSys, .{}); memory.MTPrintStatsDelta(); } @@ -48,9 +49,7 @@ pub fn shutdown_module(allocator: std.mem.Allocator) void { if (cooking) { cook.shutdown(); } - - gAssetSys.deinit(); - allocator.destroy(gAssetSys); + _ = allocator; } pub fn loadList(assetList: anytype) !void { @@ -64,6 +63,6 @@ pub fn load(assetImport: AssetImportReference) !void { var assetRefName = assetImport.assetRef.name; core.tracy.Message(assetRefName.utf8()); core.tracy.Message(assetImport.properties.path); - try gAssetSys.loadRef(assetImport.assetRef, assetImport.properties); + try getAssets().loadRef(assetImport.assetRef, assetImport.properties); z1.End(); } diff --git a/engine/audio/src/audio.zig b/engine/audio/src/audio.zig index 6cd20d0..1a087b2 100644 --- a/engine/audio/src/audio.zig +++ b/engine/audio/src/audio.zig @@ -20,12 +20,12 @@ pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.me return; } - gSoundEngine = core.gEngine.createObject(NeonSoundEngine, .{ .can_tick = true }) catch unreachable; + gSoundEngine = core.createObject(NeonSoundEngine, .{ .can_tick = true }) catch unreachable; gSoundLoader = allocator.create(soundEngine.SoundLoader) catch unreachable; gSoundLoader.* = soundEngine.SoundLoader.init(gSoundEngine); - assets.gAssetSys.registerLoader(gSoundLoader) catch unreachable; + assets.getAssets().registerLoader(gSoundLoader) catch unreachable; var name = core.MakeName("s_test"); gSoundEngine.loadSound(&name, "content/sounds/engineTick.wav", .{}) catch unreachable; diff --git a/engine/audio/src/sound_engine.zig b/engine/audio/src/sound_engine.zig index dc886e2..29c739c 100644 --- a/engine/audio/src/sound_engine.zig +++ b/engine/audio/src/sound_engine.zig @@ -66,7 +66,7 @@ fn ma_res(value: anytype) !void { } // On init, SoundEngine will spawn a pub const NeonSoundEngine = struct { - pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); + pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "audio.SoundEngine"); engine: *ma.ma_engine, sounds: AutoHashMapUnmanaged(u32, *ma.ma_sound), diff --git a/engine/backlog.zig b/engine/backlog.zig index 59eba82..dcad532 100644 --- a/engine/backlog.zig +++ b/engine/backlog.zig @@ -85,7 +85,7 @@ pub fn shutdown_everything(allocator: std.mem.Allocator) void { shutdown_modules(allocator); } -pub fn run_everything_vtable(gameVtable: *const core.EngineObjectVTable) !void { +pub fn run_everything_vtable(gameVtable: *core.EngineObjectVTable) !void { core.engine_logs("creating Game context"); //_ = try core.createObject(GameContext, .{}); @@ -93,9 +93,9 @@ pub fn run_everything_vtable(gameVtable: *const core.EngineObjectVTable) !void { core.engine_logs("calling gEngine.run"); - try core.gEngine.run(); + try core.getEngine().run(); - while (!core.gEngine.exitFinished()) { + while (!core.getEngine().exitFinished()) { const z = core.tracy.ZoneN(@src(), "shutdown poll"); z.End(); } @@ -109,9 +109,9 @@ pub fn run_everything(gameVtable: *const core.EngineObjectVTable) !void { core.engine_logs("calling gEngine.run"); - try core.gEngine.run(); + try core.getEngine().run(); - while (!core.gEngine.exitFinished()) { + while (!core.getEngine().exitFinished()) { const z = core.tracy.ZoneN(@src(), "shutdown poll"); z.End(); } @@ -119,7 +119,7 @@ pub fn run_everything(gameVtable: *const core.EngineObjectVTable) !void { pub const createSpecVariant = core.createSpecVariant; -pub export fn initAndRun(vtable: *const core.EngineObjectVTable, spec: *core.SpecVariantMap) bool { +pub export fn initAndRun(vtable: *core.EngineObjectVTable, spec: *core.SpecVariantMap) bool { const args = getArgs() catch return false; var backingAllocator: std.mem.Allocator = std.heap.c_allocator; diff --git a/engine/core/src/configVars.zig b/engine/core/src/configVars.zig index 8d4fe25..dfc5896 100644 --- a/engine/core/src/configVars.zig +++ b/engine/core/src/configVars.zig @@ -1,5 +1,3 @@ -var gConfigsObject: *ConfigRegistry = undefined; - pub const ConfigRegistry = struct { pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "core.ConfigRegistry"); @@ -52,8 +50,10 @@ pub fn configVar(comptime T: type, configName: []const u8, default: T) T { return getConfigVar(T, configName) orelse default; } +pub const getConfigRegistry = core.EngineObject(ConfigRegistry).get; + pub fn getConfigVar(comptime T: type, configName: []const u8) ?T { - const ctx = gConfigsObject; + const ctx = getConfigRegistry(); if (ctx.configMap) |map| { if (map.mapValues.get(configName)) |v| { @@ -314,8 +314,8 @@ pub const Parser = struct { }; pub fn setupConfigs(configFilePath: []const u8) !void { - gConfigsObject = try core.createObject(ConfigRegistry, .{}); - try gConfigsObject.loadConfigFile(configFilePath); + _ = try core.createObject(ConfigRegistry, .{}); + try getConfigRegistry().loadConfigFile(configFilePath); } pub fn ConfigEntry(comptime T: type) type { diff --git a/engine/core/src/console.zig b/engine/core/src/console.zig index eeda556..a6eb7da 100644 --- a/engine/core/src/console.zig +++ b/engine/core/src/console.zig @@ -6,7 +6,7 @@ pub const ConsoleCommand = struct { }; pub const Console = struct { - pub const NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "core.Console"); + pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "core.Console"); allocator: std.mem.Allocator, arena: std.heap.ArenaAllocator, @@ -63,20 +63,20 @@ pub const Console = struct { } }; -var gConsoleObject: *Console = undefined; +pub const getConsole = core.EngineObject(Console).get; pub fn start() !void { - gConsoleObject = try core.createObject(Console, .{}); + _ = try core.createObject(Console, .{}); } pub fn shutdown() void {} pub fn addCommand(funcName: []const u8, func: ConsoleFunc) !void { - try gConsoleObject.addConsoleCommand(funcName, func); + try getConsole.addConsoleCommand(funcName, func); } pub fn evaluate(cmd: []const u8) void { - gConsoleObject.eval(cmd); + getConsole.eval(cmd); } const core = @import("core.zig"); diff --git a/engine/core/src/core.zig b/engine/core/src/core.zig index c462900..0f4ec09 100644 --- a/engine/core/src/core.zig +++ b/engine/core/src/core.zig @@ -73,15 +73,31 @@ const log = logging.engine_log; pub const packer = @import("packer"); pub const FileSystem = packer.PackerFS; -const PackerFS = packer.PackerFS; +pub const PackerFS = packer.PackerFS; pub const StackCompactor = stacks.StackCompactor; var staticsInitialized = false; var gEngine: *Engine = undefined; var gPackerFS: *PackerFS = undefined; -var gScene: *SceneSystem = undefined; -var gModuleLoader: *ModuleLoader = undefined; + +pub fn EngineObject(comptime T: type) type { + return struct { + pub var gInstance: ?*T = null; + + pub fn get() *T { + if (gInstance == null) { + gInstance = getEngineObject(T); + } + + return gInstance.?; + } + }; +} + +pub fn getModuleLoader() *ModuleLoader { + return EngineObject(ModuleLoader).get(); +} var gIsUtility: bool = false; @@ -89,6 +105,7 @@ pub const Scene = scene.Scene; pub const externModule = @import("extern/externModule.zig"); pub const ModuleLoader = externModule.ModuleLoader; +pub const ModuleLoaderArgs = externModule.ModuleLoaderArgs; pub const ecs = @import("ecs.zig"); pub usingnamespace ecs; @@ -118,6 +135,10 @@ pub fn checkArgBool(args: anytype, comptime field: []const u8) bool { return false; } +pub fn getSessionStamp() i64 { + return gEngine.sessionStamp; +} + pub fn start_module(map: *SpecVariantMap, args: anytype, allocator: std.mem.Allocator) !void { staticsInitialized = true; @@ -150,7 +171,7 @@ pub fn start_module(map: *SpecVariantMap, args: anytype, allocator: std.mem.Allo gEngine = try allocator.create(Engine); gEngine.* = try Engine.init(allocator); - gModuleLoader = try createObject(ModuleLoader, .{}); + _ = try createObject(ModuleLoader, .{}); try console.start(); const engineName = try std.fmt.allocPrint(allocator, "{s}Engine.ini", .{name}); @@ -164,7 +185,7 @@ pub fn start_module(map: *SpecVariantMap, args: anytype, allocator: std.mem.Allo try ecs.setup(allocator); - gScene = try gEngine.createObject(scene.SceneSystem, .{ .can_tick = true }); + _ = try gEngine.createObject(scene.SceneSystem, .{ .can_tick = true }); try algorithm.string_pool.setup(allocator); @@ -175,6 +196,15 @@ pub fn start_module(map: *SpecVariantMap, args: anytype, allocator: std.mem.Allo return; } +pub fn setupFromModule(__args: ModuleLoaderArgs) !void { + gEngine = __args.engine; + gPackerFS = __args.packerFS; + script.setupLuaFromModule(__args.luaState, __args.luaAllocator); + algorithm.names.gRegistry = __args.nameRegistry; + logging.setupLoggingFromModule(); + staticsInitialized = true; +} + pub fn shutdown_module(_: std.mem.Allocator) void { MemoryTracker.MTPrintStatsDelta(); @@ -201,7 +231,7 @@ pub fn createObject(comptime T: type, params: engine.NeonObjectParams) !*T { return gEngine.createObject(T, params); } -pub fn createObjectVTable(vtable: *const engineObject.EngineObjectVTable, params: engine.NeonObjectParams) !*anyopaque { +pub fn createObjectVTable(vtable: *engineObject.EngineObjectVTable, params: engine.NeonObjectParams) !*anyopaque { return gEngine.createObjectVTable(vtable, params); } @@ -298,6 +328,17 @@ pub fn createSpecVariant(comptime spec: anytype, allocator: std.mem.Allocator) ! return variantMap; } +pub const EngineObjectRef = engineObject.EngineObjectRef; + +pub fn getEngineObjectRef(comptime T: type) ?engineObject.EngineObjectRef { + if (T.NeonObjectTable.singletonName) |name| { + if (getEngine().engineObjectsByName.get(name)) |ref| { + return ref; + } + } + return null; +} + pub fn getEngineObject(comptime T: type) ?*T { if (T.NeonObjectTable.singletonName) |name| { if (getEngine().engineObjectsByName.get(name)) |ref| { @@ -310,5 +351,20 @@ pub fn getEngineObject(comptime T: type) ?*T { pub fn loadModule(moduleName: []const u8, watch: bool) !void { if (watch == false) unreachable; // not implemented - try gModuleLoader.addModule(moduleName); + try getModuleLoader().addModule(moduleName); +} + +pub fn startup_getAllocator(p_allocator: *anyopaque) std.mem.Allocator { + return @as(*std.mem.Allocator, @ptrCast(@alignCast(p_allocator))).*; +} + +pub fn startup_getArgs(p_allocator: *anyopaque) ModuleLoaderArgs { + return @as(*ModuleLoaderArgs, @ptrCast(@alignCast(p_allocator))).*; +} + +pub fn modulePreamble(p_allocator: *anyopaque, p_a: ?*anyopaque) !std.mem.Allocator { + const args = startup_getArgs(p_a.?); + const allocator = startup_getAllocator(p_allocator); + try setupFromModule(args); + return allocator; } diff --git a/engine/core/src/ecs.zig b/engine/core/src/ecs.zig index edf2066..545012a 100644 --- a/engine/core/src/ecs.zig +++ b/engine/core/src/ecs.zig @@ -1,5 +1,3 @@ -var gEcsRegistry: *EcsRegistry = undefined; - // wew lad. this is definitely an exploratory implementation I think. // // todo: cruft @@ -112,19 +110,20 @@ var gEcsRegistry: *EcsRegistry = undefined; // SparseMultiSet (AOS version of sparseSet Really specialized, only used for core engine systems) pub fn createEntity() !Entity { - const rv = Entity{ .handle = try gEcsRegistry.baseSet.createObject(.{}) }; + const rv = Entity{ .handle = try getRegistry().baseSet.createObject(.{}) }; core.engine_log("entity created: {d}", .{rv.handle.index}); return rv; } pub fn destroyEntity(e: Entity) void { core.engine_log("entity destroyed: {d}", .{e.handle.index}); - if (gEcsRegistry.baseSet.get(e.handle)) |entityEntry| { + const registry = getRegistry(); + if (registry.baseSet.get(e.handle)) |entityEntry| { for (entityEntry.containers.items) |ref| { ref.vtable.destroyObject(ref.ptr, e.handle); } - entityEntry.containers.deinit(gEcsRegistry.allocator); - gEcsRegistry.baseSet.destroyObject(e.handle); + entityEntry.containers.deinit(registry.allocator); + registry.baseSet.destroyObject(e.handle); } else { core.engine_log("UNABLE TO DESTROY ENTITY {d}", .{e.handle.index}); } @@ -148,19 +147,17 @@ pub fn CreateEntity_Lua(state: lua.LuaState) i32 { pub fn setup(allocator: std.mem.Allocator) !void { try ComponentRef.setupFormatBuffer(allocator); - gEcsRegistry = try core.createObject(EcsRegistry, .{ .can_tick = true }); + _ = try core.createObject(EcsRegistry, .{ .can_tick = true }); } pub fn shutdown() void { ComponentRef.shutdownFormatBuffer(); } -pub fn getRegistry() *EcsRegistry { - return gEcsRegistry; -} +pub const getRegistry = core.EngineObject(EcsRegistry).get; pub fn registerEcsContainer(ref: EcsContainerRef, name: core.Name) !void { - try gEcsRegistry.registerContainer(ref, name); + try getRegistry().registerContainer(ref, name); } pub fn deregisterEcsContainer(ref: EcsContainerRef) void { @@ -173,9 +170,10 @@ pub fn createSystem(comptime System: type, allocator: std.mem.Allocator) !*Syste const ref = p2.refFromPtr(EcsSystemInterface, system); core.engine_log("ptr = {any}", .{ref.vtable.tick}); - try gEcsRegistry.systems.append(gEcsRegistry.allocator, ref); + const registry = getRegistry(); + try registry.systems.append(registry.allocator, ref); if (ref.vtable.tick != null) { - try gEcsRegistry.tickableSystems.append(gEcsRegistry.allocator, ref); + try registry.tickableSystems.append(registry.allocator, ref); } return system; @@ -193,7 +191,7 @@ pub const EcsRegistry = struct { containerNames: std.ArrayListUnmanaged(core.Name) = .{}, containersByName: std.AutoHashMapUnmanaged(u32, u32) = .{}, - pub const NeonObjectTable = core.EngineObjectVTable.from(@This(), "core.EcsRegistry"); + pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "core.EcsRegistry"); pub fn init(allocator: std.mem.Allocator) !*@This() { const self = try allocator.create(@This()); @@ -325,8 +323,8 @@ pub const Entity = struct { core.engine_log("adding component: {d} {s}", .{ self.handle.index, @typeName(Component) }); const rv = Component.BaseContainer.createWithHandleECS(self.handle); - const list = &gEcsRegistry.baseSet.get(self.handle).?.containers; - const allocator = gEcsRegistry.allocator; + const list = &getRegistry().baseSet.get(self.handle).?.containers; + const allocator = getRegistry().allocator; list.append(allocator, getTypeContainer(Component)) catch return null; // if (@hasDecl(Component, "init")) { diff --git a/engine/core/src/engine.zig b/engine/core/src/engine.zig index d9a3be0..90b7fa3 100644 --- a/engine/core/src/engine.zig +++ b/engine/core/src/engine.zig @@ -80,6 +80,7 @@ pub const Engine = struct { rendererSetupFunc: ?PollFuncFn = null, engineStartTime: f64 = 0, + sessionStamp: i64 = 0, nfdRuntime: *nfd.NFDRuntime, @@ -153,7 +154,7 @@ pub const Engine = struct { } // creates an engine object using the engine's allocator. - pub fn createObjectVTable(self: *@This(), vtable: *const core.EngineObjectVTable, params: NeonObjectParams) !*anyopaque { + pub fn createObjectVTable(self: *@This(), vtable: *core.EngineObjectVTable, params: NeonObjectParams) !*anyopaque { if (self.createObjectLock) { core.engine_err("RECURSIVE OBJECT CREATION NOT ALLOWED", .{}); return error.BadInit; @@ -239,6 +240,7 @@ pub const Engine = struct { self.first = false; self.engineStartTime = newTime; self.lastEngineTime = newTime; + self.sessionStamp = std.time.microTimestamp(); } if (newTime < self.lastEngineTime) { @@ -414,7 +416,7 @@ pub fn loopDelay(comptime src: Src, interval: f64, dt: f64, comptime S: type, ca pub var __timeleft: f64 = 0.0; pub var __interval: f64 = 0.0; }; - C.__interval -= dt; + C.__timeleft -= dt; if (C.__timeleft <= 0.0) { S.func(capture); diff --git a/engine/core/src/engineObject.zig b/engine/core/src/engineObject.zig index 5bb8ee2..d666e2e 100644 --- a/engine/core/src/engineObject.zig +++ b/engine/core/src/engineObject.zig @@ -20,6 +20,13 @@ pub fn InterfaceRef(comptime Vtable: type) type { }; } +pub fn InterfaceRef2(comptime Vtable: type) type { + return struct { + ptr: *anyopaque, + vtable: *Vtable, + }; +} + pub fn MakeTypeName(comptime TargetType: type) Name { const hashedName = comptime std.fmt.comptimePrint("{s}_{d}", .{ @typeName(TargetType), @sizeOf(TargetType) }); @@ -211,4 +218,4 @@ pub const EngineObjectVTable = struct { } }; -pub const EngineObjectRef = InterfaceRef(EngineObjectVTable); +pub const EngineObjectRef = InterfaceRef2(EngineObjectVTable); diff --git a/engine/core/src/extern/externModule.zig b/engine/core/src/extern/externModule.zig index ecc011d..c1106b6 100644 --- a/engine/core/src/extern/externModule.zig +++ b/engine/core/src/extern/externModule.zig @@ -6,6 +6,15 @@ const ModuleInterface = struct { shutdown: *const fn () callconv(.C) void = undefined, }; +pub const ModuleLoaderArgs = extern struct { + firstLoad: bool, + engine: *core.Engine, + nameRegistry: *p2.NameRegistry, + packerFS: *core.PackerFS, + luaState: *anyopaque, + luaAllocator: *anyopaque, +}; + pub const LoadedModule = struct { baseModulePath: []const u8, moduleName: []const u8, @@ -18,6 +27,7 @@ pub const LoadedModule = struct { startOnLoad: bool = true, started: bool = false, + initialLoad: bool = true, pub fn getInterface(self: @This()) ?ModuleInterface { return self.loaded.getLastOrNull(); @@ -25,7 +35,8 @@ pub const LoadedModule = struct { pub fn stageModule(self: *@This(), allocator: std.mem.Allocator) !void { //const stagingDirectory = ".modulecache//0/"; - const stagingDirectoryPath = try std.fmt.allocPrint(allocator, ".modulecache/{s}/{d}", .{ + const stagingDirectoryPath = try std.fmt.allocPrint(allocator, ".modulecache/{d}/{s}/{d}", .{ + core.getSessionStamp(), self.moduleName, self.stagedPaths.items.len, }); @@ -53,35 +64,56 @@ pub const LoadedModule = struct { try self.loaded.append(allocator, mod); } + pub fn load(self: *@This(), allocator: std.mem.Allocator) !void { + core.engine_log("[ModuleLoader] loading module: ", .{}); + self.lastLoad = std.time.microTimestamp(); + try self.stageModule(allocator); + try self.loadStagedModule(allocator); + } + // logic for testing if we should stage and load // // 1. modification check time > last load time // 2. current time > modification check time + debounce pub fn maybeStageAndLoad(self: *@This(), allocator: std.mem.Allocator) !bool { - core.engine_log("[tick]:", .{}); + var shouldLoad: bool = false; + if (self.lastModification > self.lastLoad) { const currentTime = std.time.microTimestamp(); // give 100ms for debouncing if (currentTime > self.lastModification + 50_000) { - self.lastLoad = currentTime; - core.engine_log("[ModuleLoader] loading module: ", .{}); - try self.stageModule(allocator); - try self.loadStagedModule(allocator); - return true; + shouldLoad = true; } } + if (self.initialLoad) { + self.initialLoad = false; + shouldLoad = true; + } + + if (shouldLoad) { + try self.load(allocator); + return true; + } + return false; } }; +fn dllChangedCallback(pathChanged: []const u8, ctx: ?*anyopaque) void { + const loaded: *LoadedModule = @ptrCast(@alignCast(ctx.?)); + loaded.lastModification = std.time.microTimestamp(); + + core.engine_log("{s} change detected", .{pathChanged}); +} + pub const ModuleLoader = struct { backingAllocator: std.mem.Allocator, arena: std.heap.ArenaAllocator, - loadedModules: std.ArrayListUnmanaged(LoadedModule) = .{}, + loadedModules: std.ArrayListUnmanaged(*LoadedModule) = .{}, - pub const NeonObjectTable = core.EngineObjectVTable.from(@This(), "core.ModuleLoader"); + pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "core.ModuleLoader"); pub fn create(allocator: std.mem.Allocator) !*@This() { const self = try allocator.create(@This()); @@ -90,6 +122,8 @@ pub const ModuleLoader = struct { .arena = std.heap.ArenaAllocator.init(allocator), }; + core.fs().watchPath("zig-out/modules/"); + return self; } @@ -97,18 +131,22 @@ pub const ModuleLoader = struct { // modules are always looked for under zig-out/modules core.engine_log("[ModuleLoader]: adding module to watch '{s}'", .{moduleName}); const libFileName = try p2.sharedLibNameAlloc(self.arena.allocator(), moduleName); - const loaded = LoadedModule{ + const loaded = try self.arena.allocator().create(LoadedModule); + + loaded.* = LoadedModule{ .baseModulePath = try std.fmt.allocPrint(self.arena.allocator(), "zig-out/modules/{s}", .{libFileName}), .moduleName = moduleName, .lastModification = std.time.microTimestamp(), }; + try core.fs().addFileChangedCallback(libFileName, dllChangedCallback, loaded); + try self.loadedModules.append(self.arena.allocator(), loaded); } pub fn tick(self: *@This(), dt: f64) void { _ = dt; - for (self.loadedModules.items) |*loaded| { + for (self.loadedModules.items) |loaded| { const didLoad = loaded.maybeStageAndLoad(self.arena.allocator()) catch |err| { core.engine_log("unable to load module error: {any}", .{err}); if (@errorReturnTrace()) |trace| { @@ -124,7 +162,15 @@ pub const ModuleLoader = struct { if (loaded.startOnLoad) { if (!loaded.started) { var a = self.backingAllocator; - if (interface.startup(&a, null)) { + var args = ModuleLoaderArgs{ + .firstLoad = loaded.loaded.items.len == 1, + .engine = core.getEngine(), + .nameRegistry = core.names.gRegistry, + .packerFS = core.fs(), + .luaState = @ptrCast(core.script.gLuaState.l), + .luaAllocator = &core.script.gLuaAllocator, + }; + if (interface.startup(&a, &args)) { core.engine_log("[ModuleLoader] module startup done", .{}); } } diff --git a/engine/core/src/inputs/inputStack.zig b/engine/core/src/inputs/inputStack.zig index 59811e0..f9d4078 100644 --- a/engine/core/src/inputs/inputStack.zig +++ b/engine/core/src/inputs/inputStack.zig @@ -71,7 +71,7 @@ pub const ActionBindingKey = struct { }; fn arenaAlloc() std.mem.Allocator { - return gInputStack.arena.allocator(); + return getInputStack().arena.allocator(); } fn BindingData(Listener: type, Func: type) type { @@ -151,11 +151,11 @@ pub const ActionBinding = struct { } // pushes this binding to the active layer pub fn activate(self: *@This()) void { - gInputStack.active.addBindingByName(self.data.name, self) catch unreachable; + getInputStack().active.addBindingByName(self.data.name, self) catch unreachable; } pub fn deactivate(self: *@This()) void { - gInputStack.active.removeBindingByName(self.data.name); + getInputStack().active.removeBindingByName(self.data.name); } pub fn addKey(self: *@This(), key: Key, event: ActionEvent) void { @@ -205,7 +205,7 @@ pub const Axis1dBinding = struct { // pushes this binding to the active layer pub fn activate(self: *@This()) void { - gInputStack.active.addBindingByName(self.data.name, self) catch unreachable; + getInputStack().active.addBindingByName(self.data.name, self) catch unreachable; } pub fn setClamp(self: *@This(), clampValue: ?f32) void { @@ -213,7 +213,7 @@ pub const Axis1dBinding = struct { } pub fn deactivate(self: *@This()) void { - gInputStack.active.removeBindingByName(self.data.name); + getInputStack().active.removeBindingByName(self.data.name); } pub fn addKey(self: *@This(), key: Key, magnitude: f32) void { @@ -275,11 +275,11 @@ pub const Axis2dBinding = struct { // pushes this binding to the active layer pub fn activate(self: *@This()) void { - gInputStack.active.addBindingByName(self.data.name, self) catch unreachable; + getInputStack().active.addBindingByName(self.data.name, self) catch unreachable; } pub fn deactivate(self: *@This()) void { - gInputStack.active.removeBindingByName(self.data.name); + getInputStack().active.removeBindingByName(self.data.name); } pub fn addKey(self: *@This(), key: Key, magnitude: f32, axis: enum { x, y }) void { @@ -576,7 +576,7 @@ pub const InputStack = struct { .active = try BindingLayer.create(allocator), }; - gInputStack = self; + core.EngineObject(@This()).gInstance = self; return self; } @@ -677,14 +677,12 @@ pub const InputStack = struct { } }; -var gInputStack: *InputStack = undefined; - pub fn getInputStack() *InputStack { - return gInputStack; + return core.EngineObject(InputStack).get(); } pub fn initInputStack() !void { - gInputStack = try core.createObject(InputStack, .{}); + _ = try core.createObject(InputStack, .{}); } // creates a binding for a lua type diff --git a/engine/core/src/logging.zig b/engine/core/src/logging.zig index 4d55b86..b90126b 100644 --- a/engine/core/src/logging.zig +++ b/engine/core/src/logging.zig @@ -297,6 +297,10 @@ pub fn forceFlush() void { } } +pub fn setupLoggingFromModule() void { + gLoggerSys = core.getEngineObject(LoggerSys); +} + pub fn setupLogging(engine: *core.Engine) !void { gLoggerSys = try engine.createObject(LoggerSys, .{ .responds_to_events = true, diff --git a/engine/core/src/scene.zig b/engine/core/src/scene.zig index e98463f..b27d504 100644 --- a/engine/core/src/scene.zig +++ b/engine/core/src/scene.zig @@ -216,8 +216,8 @@ pub const Scene = struct { pub fn getAndResolveTransform(self: @This()) core.Transform { const repr: *SceneObjectRepr = SceneObjectContainer.get(self.handle, ._repr).?; - if (repr.lastUpdate != gSceneSystem.tickCount) { - gSceneSystem.updateTransform(repr, SceneObjectContainer.get(self.handle, .posRot).?); + if (repr.lastUpdate != getSceneSystem().tickCount) { + getSceneSystem().updateTransform(repr, SceneObjectContainer.get(self.handle, .posRot).?); } return repr.transform; @@ -268,10 +268,10 @@ pub const SceneObjectInitParams = union(enum) { }, }; -pub var gSceneSystem: *SceneSystem = undefined; +pub const getSceneSystem = core.EngineObject(SceneSystem).get; fn childAllocator() std.mem.Allocator { - return gSceneSystem.childrenArena.allocator(); + return getSceneSystem().childrenArena.allocator(); } pub const SceneSystem = struct { @@ -364,7 +364,7 @@ pub const SceneSystem = struct { .allocator = allocator, .childrenArena = std.heap.ArenaAllocator.init(allocator), }; - gSceneSystem = self; + core.EngineObject(@This()).gInstance = self; try core.defineComponent(Scene, allocator); Scene.SceneObjectContainer = try SceneObjectSet.create(allocator); return self; diff --git a/engine/core/src/script.zig b/engine/core/src/script.zig index a7a540b..ca9d08d 100644 --- a/engine/core/src/script.zig +++ b/engine/core/src/script.zig @@ -13,8 +13,13 @@ pub const script_bindings = @import("script_bindings.zig"); const c = lua.c; -var gLuaState: lua.LuaState = undefined; -var gLuaAllocator: std.mem.Allocator = undefined; +pub var gLuaState: lua.LuaState = undefined; +pub var gLuaAllocator: std.mem.Allocator = undefined; + +pub fn setupLuaFromModule(pstate: *anyopaque, p_lua_allocator: *anyopaque) void { + gLuaAllocator = core.startup_getAllocator(p_lua_allocator); + gLuaState.l = @ptrCast(pstate); +} const luaRegLibs: []const c.luaL_Reg = &.{ .{ .name = "print", .func = printWrapper }, diff --git a/engine/imgui/src/imgui.zig b/engine/imgui/src/imgui.zig index ec0633b..b9d617d 100644 --- a/engine/imgui/src/imgui.zig +++ b/engine/imgui/src/imgui.zig @@ -9,17 +9,18 @@ pub const Module: core.ModuleDescription = .{ .enabledByDefault = false, }; -var gImgui: *Impl = undefined; - pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.mem.Allocator) !void { _ = allocator; _ = args; _ = spec; - // gImgui = try rend.createRendererObject(Impl); - // try gImgui.setup(); - gImgui = try core.createObject(Impl, .{}); - try gImgui.setup(); + const gimgui = try core.createObject(Impl, .{}); + try gimgui.setup(); +} + +pub fn setupFromModule() void { + const impl = core.getEngineObject(Impl).?; + api.setCurrentContext(impl.context); } pub fn shutdown_module(allocator: std.mem.Allocator) void { diff --git a/engine/imgui/src/sgpu/backend_impl.zig b/engine/imgui/src/sgpu/backend_impl.zig index a4b02c3..0c697a3 100644 --- a/engine/imgui/src/sgpu/backend_impl.zig +++ b/engine/imgui/src/sgpu/backend_impl.zig @@ -4,8 +4,9 @@ pub const Impl = struct { drawData: [*c]ig.DrawData = undefined, rendererDebug: bool = true, + context: *ig.Context = undefined, - pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); + pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "imgui.BackendImpl"); pub const Settings = struct { x: u32 = 0, @@ -29,6 +30,8 @@ pub const Impl = struct { c.Imgui_SDL3_Init(@ptrCast(platform.getInstance().window), @ptrCast(self.device)); try platform.getInstance().addSDLProcessFunction(processSDLEvents); + + self.context = ig.getCurrentContext().?; } pub fn processSDLEvents(event: *sdl3.Event) void { diff --git a/engine/physics/src/physics.zig b/engine/physics/src/physics.zig index aa23a9c..927f7c4 100644 --- a/engine/physics/src/physics.zig +++ b/engine/physics/src/physics.zig @@ -38,15 +38,15 @@ pub const PrimitiveType = enum { // low level helpers - old api pub fn addPrimitiveBody(primitive: PrimitiveType, settings: BodyCreationSettings, activationMode: Activation) !BodyId { - const interface = gPhysicsRuntime.system.getBodyInterfaceMut(); + const interface = context().system.getBodyInterfaceMut(); var s = settings; switch (primitive) { .box => { - s.shape = gPhysicsRuntime.primBoxShape; + s.shape = context().primBoxShape; }, .sphere => { - s.shape = gPhysicsRuntime.primSphereShape; + s.shape = context().primSphereShape; }, } @@ -54,24 +54,24 @@ pub fn addPrimitiveBody(primitive: PrimitiveType, settings: BodyCreationSettings } pub fn setBodyPosition(id: BodyId, pos: core.Vectorf) void { - const interface = gPhysicsRuntime.system.getBodyInterfaceMut(); + const interface = context().system.getBodyInterfaceMut(); interface.setPosition(id, pos.toArr3(), .activate); } pub fn setBodyRotation(id: BodyId, rot: core.Rotation) void { - const interface = gPhysicsRuntime.system.getBodyInterfaceMut(); + const interface = context().system.getBodyInterfaceMut(); interface.setRotation(id, rot.quat, .activate); } pub fn optimizeBroadPhase() void { - gPhysicsRuntime.system.optimizeBroadPhase(); + context().system.optimizeBroadPhase(); } -pub var gPhysicsRuntime: *runtime.PhysicsRuntime = undefined; +pub const context = core.EngineObject(runtime.PhysicsRuntime).get; pub fn addShape(name: []const u8, settings: ShapeSettings) !void { var n = core.MakeName(name); - try gPhysicsRuntime.createShape(&n, settings); + try context().createShape(&n, settings); } pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.mem.Allocator) !void { @@ -79,7 +79,7 @@ pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.me _ = spec; try zphysics.init(allocator, .{}); - gPhysicsRuntime = try core.createObject(runtime.PhysicsRuntime, .{ .can_tick = true }); + _ = try core.createObject(runtime.PhysicsRuntime, .{ .can_tick = true }); } pub fn shutdown_module(allocator: std.mem.Allocator) void { @@ -94,7 +94,7 @@ pub const Module: core.ModuleDescription = .{ pub fn releaseShape(name: core.Name) void { var n = name; - gPhysicsRuntime.shapes.get(n.handle()).?.shape.release(); + context().shapes.get(n.handle()).?.shape.release(); } pub const RayCastSettings = struct { @@ -109,7 +109,7 @@ pub const RayCastResult = struct { }; pub fn traceLine(start: core.Vectorf, direction: core.Vectorf, settings: RayCastSettings) ?RayCastResult { - const query = gPhysicsRuntime.system.getNarrowPhaseQuery(); + const query = context().system.getNarrowPhaseQuery(); const result = query.castRay(.{ .origin = start.toZm(), .direction = direction.toZm(), @@ -127,13 +127,13 @@ pub fn traceLine(start: core.Vectorf, direction: core.Vectorf, settings: RayCast }; if (settings.entityLookup) { - rv.entity = gPhysicsRuntime.idToEntity.get(rv.body).?; + rv.entity = context().idToEntity.get(rv.body).?; } return rv; } pub fn applyForce(body: BodyId, impulse: core.Vectorf, position: core.Vectorf) void { - const interface = gPhysicsRuntime.system.getBodyInterfaceMut(); + const interface = context().system.getBodyInterfaceMut(); interface.addImpulseAtPosition(body, impulse.toArr3(), position.toArr3()); } diff --git a/engine/physics/src/physicsSystem.zig b/engine/physics/src/physicsSystem.zig index 33f3d1d..226b335 100644 --- a/engine/physics/src/physicsSystem.zig +++ b/engine/physics/src/physicsSystem.zig @@ -144,7 +144,7 @@ pub const PhysicsRuntime = struct { timeSinceUpdate: f64 = 0.0, idToEntity: std.AutoHashMapUnmanaged(zphysics.BodyId, core.Entity) = .{}, - pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); + pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "physics.Runtime"); pub fn registerBodyEntity(self: *@This(), bodyId: zphysics.BodyId, entity: core.Entity) !void { try self.idToEntity.put(self.allocator, bodyId, entity); diff --git a/engine/rend/src/sgpu/DebugDrawSystem.zig b/engine/rend/src/sgpu/DebugDrawSystem.zig index c2cbe59..80db39e 100644 --- a/engine/rend/src/sgpu/DebugDrawSystem.zig +++ b/engine/rend/src/sgpu/DebugDrawSystem.zig @@ -1,4 +1,4 @@ -pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); +pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "rend.DebugDrawSystem"); allocator: std.mem.Allocator, debugDraws: core.RingQueueU(DebugPrimitive), diff --git a/engine/rend/src/sgpu/MeshAssetLoader.zig b/engine/rend/src/sgpu/MeshAssetLoader.zig index 74c9ea3..9617e79 100644 --- a/engine/rend/src/sgpu/MeshAssetLoader.zig +++ b/engine/rend/src/sgpu/MeshAssetLoader.zig @@ -3,7 +3,7 @@ allocator: std.mem.Allocator, pub var LoaderInterfaceVTable = assets.AssetLoaderInterface.from("Mesh", @This()); -pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); +pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "rend.MeshAssetLoader"); pub fn create(allocator: std.mem.Allocator) !*@This() { const self = try allocator.create(@This()); diff --git a/engine/rend/src/sgpu/SkyboxSystem.zig b/engine/rend/src/sgpu/SkyboxSystem.zig index d126b27..2e3ddfa 100644 --- a/engine/rend/src/sgpu/SkyboxSystem.zig +++ b/engine/rend/src/sgpu/SkyboxSystem.zig @@ -1,4 +1,4 @@ -pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); +pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "rend.Skybox"); allocator: std.mem.Allocator, diff --git a/engine/rend/src/sgpu/TextureList.zig b/engine/rend/src/sgpu/TextureList.zig index 2634ff8..0f29ad7 100644 --- a/engine/rend/src/sgpu/TextureList.zig +++ b/engine/rend/src/sgpu/TextureList.zig @@ -7,7 +7,7 @@ // pub var LoaderInterfaceVTable = assets.AssetLoaderInterface.from("Texture", @This()); -pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); +pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "rend.TextureList"); allocator: std.mem.Allocator, device: *gpu.GPUDevice = undefined, @@ -26,7 +26,7 @@ pub fn create(allocator: std.mem.Allocator) !*@This() { pub fn setup(self: *@This(), device: *gpu.GPUDevice) !void { core.engine_log("Texture List Added", .{}); - try assets.gAssetSys.registerLoader(self); + try assets.getAssets().registerLoader(self); self.device = device; } diff --git a/engine/rend/src/sgpu/mesh-pool.zig b/engine/rend/src/sgpu/mesh-pool.zig index 624e8b9..b433171 100644 --- a/engine/rend/src/sgpu/mesh-pool.zig +++ b/engine/rend/src/sgpu/mesh-pool.zig @@ -46,7 +46,7 @@ pub const MeshPool = struct { core.graphics_log("mesh pool created {d}k vertices, {d}k indices", .{ settings.vertexCount / 1000, settings.indexCount / 1000 }); - try assets.gAssetSys.registerLoader(try core.createObject(MeshAssetLoader, .{})); + try assets.getAssets().registerLoader(try core.createObject(MeshAssetLoader, .{})); return self; } diff --git a/engine/rend/src/sgpu/renderer.zig b/engine/rend/src/sgpu/renderer.zig index 59241a0..fae2d39 100644 --- a/engine/rend/src/sgpu/renderer.zig +++ b/engine/rend/src/sgpu/renderer.zig @@ -85,7 +85,7 @@ pub const Renderer = struct { positionTargetFormat: gpu.GPUTextureFormat = .textureformatR16g16b16a16Float, normalTargetFormat: gpu.GPUTextureFormat = .textureformatB8g8r8a8Unorm, - pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); + pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "rend.Renderer"); pub const MaxObjectCount = 50000; @@ -913,8 +913,9 @@ pub const Renderer = struct { } }; -pub var gRenderer: *Renderer = undefined; -pub var gAllocator: std.mem.Allocator = undefined; +// pub var gRenderer: *Renderer = undefined; + +pub const context = core.EngineObject(Renderer).get; const rend = @import("../rend.zig"); @@ -949,45 +950,40 @@ const SkyboxSystem = @import("SkyboxSystem.zig"); // debug api pub fn reloadShaders() !void { - _ = core.shell.runCmd(gRenderer.allocator, &.{ "python", "../tools/scripts/cookShaders.py" }, ".") catch { + _ = core.shell.runCmd(context().allocator, &.{ "python", "../tools/scripts/cookShaders.py" }, ".") catch { core.graphics_logs("shader cook script failed"); return; }; - try gRenderer.createMeshPipeline(); - try gRenderer.createPostProcessingPipeline(); - try gRenderer.ssaoSystem.createPipeline(); + try context().createMeshPipeline(); + try context().createPostProcessingPipeline(); + try context().ssaoSystem.createPipeline(); } // ====== renderer API ======= pub fn createInstance() !void { - gRenderer = try core.createObject(Renderer, .{ .can_tick = true, .isCore = true }); - gAllocator = gRenderer.allocator; + _ = try core.createObject(Renderer, .{ .can_tick = true, .isCore = true }); } pub fn start() !void { - try gRenderer.startRenderer(); + try context().startRenderer(); } pub fn shutdown() void {} -pub fn context() *Renderer { - return gRenderer; -} - pub fn setActiveCamera(camera: ?*rend.CameraComponent) void { - gRenderer.activeCamera = camera; + context().activeCamera = camera; } pub fn createRendererObject(comptime T: type) !*T { - return try gRenderer.createRendererObject(T); + return try context().createRendererObject(T); } pub fn registerRendererObject(comptime T: type, object: *anyopaque) !void { - return try gRenderer.registerRendererObject(T, object); + return try context().registerRendererObject(T, object); } pub fn setSkyboxTexture(name: []const u8) void { - gRenderer.skyboxSystem.skyboxTextureName = core.MakeName(name); + context().skyboxSystem.skyboxTextureName = core.MakeName(name); } pub const getMesh = mesh_pool.getMesh; @@ -995,7 +991,7 @@ pub const getMeshByName = mesh_pool.getMeshByName; pub const pushMeshUpdate = mesh_pool.pushMeshUpdate; pub fn getTexture(name: *core.Name) ?*rend.Texture { - return gRenderer.textureList.map.get(name.handle()); + return context().textureList.map.get(name.handle()); } pub const RendererState = struct { @@ -1011,7 +1007,7 @@ pub const RendererState = struct { pub fn textureExists(name: []const u8) bool { var n = core.MakeName(name); - return gRenderer.textureList.requestMap.contains(n.handle()); + return context().textureList.requestMap.contains(n.handle()); } pub const CustomMeshRenderFunc = *const fn (?*anyopaque) void; diff --git a/engine/rend/src/sgpu/ssao.zig b/engine/rend/src/sgpu/ssao.zig index 234ebfc..6dd86c0 100644 --- a/engine/rend/src/sgpu/ssao.zig +++ b/engine/rend/src/sgpu/ssao.zig @@ -1,4 +1,4 @@ -pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); +pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "rend.Ssao"); allocator: std.mem.Allocator, diff --git a/extras/gameExtras/src/EngineTool.zig b/extras/gameExtras/src/EngineTool.zig index 2ee3743..2fc2be6 100644 --- a/extras/gameExtras/src/EngineTool.zig +++ b/extras/gameExtras/src/EngineTool.zig @@ -31,7 +31,7 @@ pub fn maybeUpdate(self: *@This()) !void { const alloc = self.arena.allocator(); for (engine.engineObjects.items) |x| { const newString = try std.fmt.allocPrint(alloc, "[{s}] {s} @ 0x{x} (size: {d} bytes) ", .{ - x.vtable.singletonName, + x.vtable.singletonName orelse "n/a", x.vtable.typeName, @intFromPtr(x.ptr), x.vtable.typeSize, diff --git a/extras/gameExtras/src/RendererDebug.zig b/extras/gameExtras/src/RendererDebug.zig index 1f47bc2..b3b6bcf 100644 --- a/extras/gameExtras/src/RendererDebug.zig +++ b/extras/gameExtras/src/RendererDebug.zig @@ -1,7 +1,7 @@ dtAverage: f64 = 0.0, allocator: std.mem.Allocator, -pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); +pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), null); pub fn create(allocator: std.mem.Allocator) !*@This() { const self = try allocator.create(@This()); diff --git a/lib/cimgui/_archive/vkImgui.zig b/lib/cimgui/_archive/vkImgui.zig index ce2b97e..515dcc8 100644 --- a/lib/cimgui/_archive/vkImgui.zig +++ b/lib/cimgui/_archive/vkImgui.zig @@ -38,7 +38,7 @@ fn vkCast(comptime T: type, handle: anytype) T { // largely don't need to touch this structure from the user's side. pub const NeonVkImGui = struct { const Self = @This(); - pub const NeonObjectTable = core.EngineObjectVTable.from(Self); + pub var NeonObjectTable = core.EngineObjectVTable.from(Self); pub const RendererInterfaceVTable = graphics.RendererInterface.from(Self); allocator: std.mem.Allocator, diff --git a/lib/cimgui/src/cimgui.zig b/lib/cimgui/src/cimgui.zig index a555160..b7aedaa 100644 --- a/lib/cimgui/src/cimgui.zig +++ b/lib/cimgui/src/cimgui.zig @@ -2297,7 +2297,7 @@ pub inline fn getCurrentContext() ?*Context { //igGetCurrentContext return @ptrCast(c.igGetCurrentContext()); } pub inline fn setCurrentContext(ctx: ?*Context) void { //igSetCurrentContext - c.igSetCurrentContext(ctx); + c.igSetCurrentContext(@ptrCast(ctx)); } pub inline fn getIO() ?*Io { //igGetIO return @ptrCast(c.igGetIO_Nil()); diff --git a/lib/p2/src/p2.zig b/lib/p2/src/p2.zig index e2385bf..3c7f0c1 100644 --- a/lib/p2/src/p2.zig +++ b/lib/p2/src/p2.zig @@ -66,6 +66,8 @@ pub const MakeName = names.MakeName; pub const DefineName = names.DefineName; pub const createNameRegistry = names.createNameRegistry; pub const destroyNameRegistry = names.destroyNameRegistry; +pub const setNameRegistry = names.setNameRegistry; +pub const NameRegistry = names.NameRegistry; pub const spans = @import("structures/spans.zig"); pub const MergedSpans = spans.MergedSpans; diff --git a/lib/p2/src/structures/names.zig b/lib/p2/src/structures/names.zig index f833378..33e8048 100644 --- a/lib/p2/src/structures/names.zig +++ b/lib/p2/src/structures/names.zig @@ -106,6 +106,11 @@ pub fn createNameRegistry(allocator: std.mem.Allocator) !*NameRegistry { return gRegistry; } +pub fn setNameRegistry(registry: *NameRegistry) void { + gRegistry = registry; + registryCreated = true; +} + pub fn getRegistry() *NameRegistry { // specifically in the case of unittests we can silently just initialize a temporary registry if (builtin.is_test) { diff --git a/projects/build.zig b/projects/build.zig index 9780f03..b9af453 100644 --- a/projects/build.zig +++ b/projects/build.zig @@ -30,6 +30,8 @@ pub fn build(b: *std.Build) void { .name = "externGame", }); + sampleGameExtern.root_module.addImport("backlog", blbuild.nw_mod); + const installExtern = b.addInstallArtifact(sampleGameExtern, .{ .dest_dir = .{ .override = .{ .custom = "modules" } }, }); diff --git a/projects/content/_shaders/dxil/skybox.frag.dxil b/projects/content/_shaders/dxil/skybox.frag.dxil index f75744d..5d52ebf 100644 Binary files a/projects/content/_shaders/dxil/skybox.frag.dxil and b/projects/content/_shaders/dxil/skybox.frag.dxil differ diff --git a/projects/content/_shaders/msl/skybox.frag.msl b/projects/content/_shaders/msl/skybox.frag.msl index 1abee72..f5bd5ba 100644 --- a/projects/content/_shaders/msl/skybox.frag.msl +++ b/projects/content/_shaders/msl/skybox.frag.msl @@ -8,7 +8,7 @@ struct type_Uniforms float brightnessFactor; }; -constant float4 _28 = {}; +constant float4 _29 = {}; struct main0_out { @@ -24,9 +24,11 @@ struct main0_in fragment main0_out main0(main0_in in [[stage_in]], constant type_Uniforms& Uniforms [[buffer(0)]], texturecube SkyboxTexture [[texture(0)]], sampler SkyboxSampler [[sampler(0)]]) { main0_out out = {}; - float4 _38 = SkyboxTexture.sample(SkyboxSampler, in.in_var_TEXCOORD0) * Uniforms.brightnessFactor; - out.out_var_SV_Target0 = _38; - out.out_var_SV_Target1 = select(_28, _38, bool4(length(_38) > 1.0)); + float4 _39 = SkyboxTexture.sample(SkyboxSampler, in.in_var_TEXCOORD0) * Uniforms.brightnessFactor; + float4 _44 = _39; + _44.z = 0.0; + out.out_var_SV_Target0 = _44; + out.out_var_SV_Target1 = select(_29, _39, bool4(length(_39) > 1.0)); return out; } diff --git a/projects/content/_shaders/spv/skybox.frag.spv b/projects/content/_shaders/spv/skybox.frag.spv index f33fd3d..5f8b438 100644 Binary files a/projects/content/_shaders/spv/skybox.frag.spv and b/projects/content/_shaders/spv/skybox.frag.spv differ diff --git a/projects/sampleGame/externGame/externGame.zig b/projects/sampleGame/externGame/externGame.zig index 9e250e9..0ffb950 100644 --- a/projects/sampleGame/externGame/externGame.zig +++ b/projects/sampleGame/externGame/externGame.zig @@ -1,3 +1,13 @@ +pub export fn startup(p_allocator: *anyopaque, p_a: ?*anyopaque) bool { + const allocator = core.modulePreamble(p_allocator, p_a) catch return false; + _ = allocator; + imgui.setupFromModule(); + + start_module(core.startup_getArgs(p_a.?)) catch return false; + + return true; +} + pub export fn add(a: i32, b: i32) i32 { return a + b; } @@ -6,4 +16,73 @@ pub export fn subtract(a: i32, b: i32) i32 { return a + b; } +var gAllocator: std.mem.Allocator = undefined; + +pub fn log(comptime fmt: []const u8, args: anytype) void { + core.engine_log("[ExternGame]: " ++ fmt, args); +} + +fn start_module(args: core.ModuleLoaderArgs) !void { + if (args.firstLoad) { + _ = core.createObject(ExternGameObject, .{}) catch {}; + return; + } + + log("extern game reloaded ", .{}); + log("hello mother fucker", .{}); + log("accessing old object at {x} same object? {d}", .{ @intFromPtr(core.EngineObject(ExternGameObject).get()), @sizeOf(ExternGameObject) }); + + log("gonna try something dumb- lets patch the vtable of that old object with my vtable's values", .{}); + const ref = core.getEngineObjectRef(ExternGameObject).?; + + ref.vtable.tick_func = ExternGameObject.NeonObjectTable.tick_func; +} + +pub const ExternGameObject = struct { + pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "game.ExternGameObject"); + + allocator: std.mem.Allocator, + + pub fn create(allocator: std.mem.Allocator) !*@This() { + const self = try allocator.create(@This()); + self.* = .{ .allocator = allocator }; + + return self; + } + + pub fn tick(self: *@This(), dt: f64) void { + _ = self; + _ = dt; + if (ig.begin("external game object", null, .{})) { + ig.textf("sup", .{}); + ig.textf("hello !", .{}); + + ig.textf("sup", .{}); + ig.textf("hello !", .{}); + ig.textf("sup", .{}); + ig.textf("hello !", .{}); + ig.textf("sup", .{}); + ig.textf("hello !", .{}); + ig.textf("sup", .{}); + ig.textf("hello !", .{}); + ig.textf("sup", .{}); + ig.textf("hello !", .{}); + + _ = ig.sliderFloat("skybox red", &rend.context().skyboxSystem.brightnessFactor, 0, 200, null, .{}); + } + ig.end(); + } + + pub fn destroy(self: *@This()) void { + self.allocator.destroy(self); + } +}; + +pub export fn shutdown() void {} + const std = @import("std"); +const backlog = @import("backlog"); +const core = backlog.core; +const imgui = backlog.imgui; +const rend = backlog.rend; +const ig = imgui.api; diff --git a/projects/sampleGame/main.zig b/projects/sampleGame/main.zig index 4486330..9cd29e4 100644 --- a/projects/sampleGame/main.zig +++ b/projects/sampleGame/main.zig @@ -28,13 +28,13 @@ rendererDebugger: *extras.RendererDebug = undefined, tbMap: ?*bsp.maploader.TBMap = null, -addFunc: ?*const fn (i32, i32) callconv(.C) i32 = undefined, +// addFunc: ?*const fn (i32, i32) callconv(.C) i32 = undefined, engineTool: *extras.EngineTool = undefined, modules: std.AutoHashMapUnmanaged(u32, []const u8) = .{}, -pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); +pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "SampleGame"); pub fn init(allocator: std.mem.Allocator) !*@This() { const self = try allocator.create(@This()); @@ -192,12 +192,14 @@ pub fn prepare(self: *@This()) !void { try script.loadTypes("scripts"); try script.runScriptFile("scripts/prepare.lua"); + try core.loadModule("externGame", true); + self.engineTool = try extras.EngineTool.create(self.allocator); - core.fs().watchPath("zig-out/modules"); - try core.fs().addFileChangedCallback(core.sharedLibName("externGame"), moduleChangedCallback, self); + // core.fs().watchPath("zig-out/modules"); + // try core.fs().addFileChangedCallback(core.sharedLibName("externGame"), moduleChangedCallback, self); - try self.tryLoadExtern("externGame"); + // try self.tryLoadExtern("externGame"); self.rendererDebugger = try extras.RendererDebug.create(self.allocator); //try core.createObject(extras.RendererDebug, .{}); @@ -413,7 +415,8 @@ pub fn tick(self: *@This(), dt: f64) void { s: @TypeOf(self), pub fn func(c: @This()) void { - c.s.tryLoadExtern("externGame") catch unreachable; + _ = c; + // c.s.tryLoadExtern("externGame") catch unreachable; } }, .{ .s = self }); @@ -463,7 +466,6 @@ pub fn tick(self: *@This(), dt: f64) void { // show a window with the current camera's position if (!self.mouseLook) { - ig.showDemoWindow(null); self.engineTool.tick(); self.objectSpawner.windowOpen = !self.mouseLook; self.objectSpawner.tick(dt); @@ -485,7 +487,7 @@ pub fn tick(self: *@This(), dt: f64) void { ig.textFmt("- f2 to route all inputs to the doom player", .{}) catch return; ig.textFmt("- movingLight checkbox makes the light stop moving with you", .{}) catch return; - ig.textf("1 + 2 = {d}", .{self.addFunc.?(1, 2)}); + //ig.textf("1 + 2 = {d}", .{self.addFunc.?(1, 2)}); { ig.textf("modules dirty: ", .{}); diff --git a/testing/test-all.zig b/testing/test-all.zig index 83d5f6c..12b9e30 100644 --- a/testing/test-all.zig +++ b/testing/test-all.zig @@ -26,7 +26,7 @@ const ModuleResults = struct { } }; -pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); +pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "testAll"); pub fn init(allocator: std.mem.Allocator) !*@This() { const self = try allocator.create(@This());