hot reloading is working now

This commit is contained in:
Peter Li 2025-05-18 17:56:23 -07:00
parent db49ef3606
commit 252a5271a1
41 changed files with 364 additions and 210 deletions

View File

@ -139,65 +139,6 @@ pub fn addProgram(self: *BuildSystem, opts: AddProgramOptions) *std.Build.Module
run_exe.dependOn(&cookShadersCommand.step); 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/<module names>/shaders/**
// - shaders must have a unique name across the entire project, naming scheme should be <module>.shadername.<stage>.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/<msl|dxil|dxil>/<shader-name>.<msl|spv|dxil>
// 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()); b.getInstallStep().dependOn(self.nw_builder.getInstallStep());
return mod; return mod;

View File

@ -157,12 +157,17 @@ pub const AssetReferenceSys = struct {
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
outstandingAssetJobs: std.atomic.Value(i32), outstandingAssetJobs: std.atomic.Value(i32),
pub fn init(allocator: std.mem.Allocator) @This() { pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "AssetReference");
return @This(){
pub fn init(allocator: std.mem.Allocator) !*@This() {
const self = try allocator.create(@This());
self.* = @This(){
.loaders = .{}, .loaders = .{},
.allocator = allocator, .allocator = allocator,
.outstandingAssetJobs = std.atomic.Value(i32).init(0), .outstandingAssetJobs = std.atomic.Value(i32).init(0),
}; };
return self;
} }
pub fn registerLoader(self: *@This(), loader: anytype) !void { pub fn registerLoader(self: *@This(), loader: anytype) !void {
@ -205,5 +210,6 @@ pub const AssetReferenceSys = struct {
// i.destroy(self.allocator); // i.destroy(self.allocator);
// } // }
self.loaders.deinit(self.allocator); self.loaders.deinit(self.allocator);
self.allocator.destroy(self);
} }
}; };

View File

@ -19,8 +19,6 @@ pub const MakeImportRefOptions = asset_references.MakeImportRefOptions;
pub const AsyncAssetJobContext = asset_jobs.AsyncAssetJobContext; pub const AsyncAssetJobContext = asset_jobs.AsyncAssetJobContext;
pub var gAssetSys: *AssetReferenceSys = undefined;
pub const Module = core.ModuleDescription{ pub const Module = core.ModuleDescription{
.name = "assets", .name = "assets",
.enabledByDefault = true, .enabledByDefault = true,
@ -28,6 +26,8 @@ pub const Module = core.ModuleDescription{
var cooking: bool = false; 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 { pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.mem.Allocator) !void {
_ = args; _ = args;
@ -38,8 +38,9 @@ pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.me
try cook.startup(allocator); try cook.startup(allocator);
} }
gAssetSys = allocator.create(AssetReferenceSys) catch @panic("unable to initialize asset reference"); //gAssetSys = allocator.create(AssetReferenceSys) catch @panic("unable to initialize asset reference");
gAssetSys.* = AssetReferenceSys.init(allocator); //gAssetSys.* = AssetReferenceSys.init(allocator);
_ = try core.createObject(AssetReferenceSys, .{});
memory.MTPrintStatsDelta(); memory.MTPrintStatsDelta();
} }
@ -48,9 +49,7 @@ pub fn shutdown_module(allocator: std.mem.Allocator) void {
if (cooking) { if (cooking) {
cook.shutdown(); cook.shutdown();
} }
_ = allocator;
gAssetSys.deinit();
allocator.destroy(gAssetSys);
} }
pub fn loadList(assetList: anytype) !void { pub fn loadList(assetList: anytype) !void {
@ -64,6 +63,6 @@ pub fn load(assetImport: AssetImportReference) !void {
var assetRefName = assetImport.assetRef.name; var assetRefName = assetImport.assetRef.name;
core.tracy.Message(assetRefName.utf8()); core.tracy.Message(assetRefName.utf8());
core.tracy.Message(assetImport.properties.path); core.tracy.Message(assetImport.properties.path);
try gAssetSys.loadRef(assetImport.assetRef, assetImport.properties); try getAssets().loadRef(assetImport.assetRef, assetImport.properties);
z1.End(); z1.End();
} }

View File

@ -20,12 +20,12 @@ pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.me
return; 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 = allocator.create(soundEngine.SoundLoader) catch unreachable;
gSoundLoader.* = soundEngine.SoundLoader.init(gSoundEngine); gSoundLoader.* = soundEngine.SoundLoader.init(gSoundEngine);
assets.gAssetSys.registerLoader(gSoundLoader) catch unreachable; assets.getAssets().registerLoader(gSoundLoader) catch unreachable;
var name = core.MakeName("s_test"); var name = core.MakeName("s_test");
gSoundEngine.loadSound(&name, "content/sounds/engineTick.wav", .{}) catch unreachable; gSoundEngine.loadSound(&name, "content/sounds/engineTick.wav", .{}) catch unreachable;

View File

@ -66,7 +66,7 @@ fn ma_res(value: anytype) !void {
} }
// On init, SoundEngine will spawn a // On init, SoundEngine will spawn a
pub const NeonSoundEngine = struct { 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, engine: *ma.ma_engine,
sounds: AutoHashMapUnmanaged(u32, *ma.ma_sound), sounds: AutoHashMapUnmanaged(u32, *ma.ma_sound),

View File

@ -85,7 +85,7 @@ pub fn shutdown_everything(allocator: std.mem.Allocator) void {
shutdown_modules(allocator); 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"); core.engine_logs("creating Game context");
//_ = try core.createObject(GameContext, .{}); //_ = try core.createObject(GameContext, .{});
@ -93,9 +93,9 @@ pub fn run_everything_vtable(gameVtable: *const core.EngineObjectVTable) !void {
core.engine_logs("calling gEngine.run"); 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"); const z = core.tracy.ZoneN(@src(), "shutdown poll");
z.End(); z.End();
} }
@ -109,9 +109,9 @@ pub fn run_everything(gameVtable: *const core.EngineObjectVTable) !void {
core.engine_logs("calling gEngine.run"); 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"); const z = core.tracy.ZoneN(@src(), "shutdown poll");
z.End(); z.End();
} }
@ -119,7 +119,7 @@ pub fn run_everything(gameVtable: *const core.EngineObjectVTable) !void {
pub const createSpecVariant = core.createSpecVariant; 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; const args = getArgs() catch return false;
var backingAllocator: std.mem.Allocator = std.heap.c_allocator; var backingAllocator: std.mem.Allocator = std.heap.c_allocator;

View File

@ -1,5 +1,3 @@
var gConfigsObject: *ConfigRegistry = undefined;
pub const ConfigRegistry = struct { pub const ConfigRegistry = struct {
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "core.ConfigRegistry"); 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; return getConfigVar(T, configName) orelse default;
} }
pub const getConfigRegistry = core.EngineObject(ConfigRegistry).get;
pub fn getConfigVar(comptime T: type, configName: []const u8) ?T { pub fn getConfigVar(comptime T: type, configName: []const u8) ?T {
const ctx = gConfigsObject; const ctx = getConfigRegistry();
if (ctx.configMap) |map| { if (ctx.configMap) |map| {
if (map.mapValues.get(configName)) |v| { if (map.mapValues.get(configName)) |v| {
@ -314,8 +314,8 @@ pub const Parser = struct {
}; };
pub fn setupConfigs(configFilePath: []const u8) !void { pub fn setupConfigs(configFilePath: []const u8) !void {
gConfigsObject = try core.createObject(ConfigRegistry, .{}); _ = try core.createObject(ConfigRegistry, .{});
try gConfigsObject.loadConfigFile(configFilePath); try getConfigRegistry().loadConfigFile(configFilePath);
} }
pub fn ConfigEntry(comptime T: type) type { pub fn ConfigEntry(comptime T: type) type {

View File

@ -6,7 +6,7 @@ pub const ConsoleCommand = struct {
}; };
pub const Console = 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, allocator: std.mem.Allocator,
arena: std.heap.ArenaAllocator, 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 { pub fn start() !void {
gConsoleObject = try core.createObject(Console, .{}); _ = try core.createObject(Console, .{});
} }
pub fn shutdown() void {} pub fn shutdown() void {}
pub fn addCommand(funcName: []const u8, func: ConsoleFunc) !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 { pub fn evaluate(cmd: []const u8) void {
gConsoleObject.eval(cmd); getConsole.eval(cmd);
} }
const core = @import("core.zig"); const core = @import("core.zig");

View File

@ -73,15 +73,31 @@ const log = logging.engine_log;
pub const packer = @import("packer"); pub const packer = @import("packer");
pub const FileSystem = packer.PackerFS; pub const FileSystem = packer.PackerFS;
const PackerFS = packer.PackerFS; pub const PackerFS = packer.PackerFS;
pub const StackCompactor = stacks.StackCompactor; pub const StackCompactor = stacks.StackCompactor;
var staticsInitialized = false; var staticsInitialized = false;
var gEngine: *Engine = undefined; var gEngine: *Engine = undefined;
var gPackerFS: *PackerFS = 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; var gIsUtility: bool = false;
@ -89,6 +105,7 @@ pub const Scene = scene.Scene;
pub const externModule = @import("extern/externModule.zig"); pub const externModule = @import("extern/externModule.zig");
pub const ModuleLoader = externModule.ModuleLoader; pub const ModuleLoader = externModule.ModuleLoader;
pub const ModuleLoaderArgs = externModule.ModuleLoaderArgs;
pub const ecs = @import("ecs.zig"); pub const ecs = @import("ecs.zig");
pub usingnamespace ecs; pub usingnamespace ecs;
@ -118,6 +135,10 @@ pub fn checkArgBool(args: anytype, comptime field: []const u8) bool {
return false; return false;
} }
pub fn getSessionStamp() i64 {
return gEngine.sessionStamp;
}
pub fn start_module(map: *SpecVariantMap, args: anytype, allocator: std.mem.Allocator) !void { pub fn start_module(map: *SpecVariantMap, args: anytype, allocator: std.mem.Allocator) !void {
staticsInitialized = true; 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 allocator.create(Engine);
gEngine.* = try Engine.init(allocator); gEngine.* = try Engine.init(allocator);
gModuleLoader = try createObject(ModuleLoader, .{}); _ = try createObject(ModuleLoader, .{});
try console.start(); try console.start();
const engineName = try std.fmt.allocPrint(allocator, "{s}Engine.ini", .{name}); 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); 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); try algorithm.string_pool.setup(allocator);
@ -175,6 +196,15 @@ pub fn start_module(map: *SpecVariantMap, args: anytype, allocator: std.mem.Allo
return; 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 { pub fn shutdown_module(_: std.mem.Allocator) void {
MemoryTracker.MTPrintStatsDelta(); MemoryTracker.MTPrintStatsDelta();
@ -201,7 +231,7 @@ pub fn createObject(comptime T: type, params: engine.NeonObjectParams) !*T {
return gEngine.createObject(T, params); 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); return gEngine.createObjectVTable(vtable, params);
} }
@ -298,6 +328,17 @@ pub fn createSpecVariant(comptime spec: anytype, allocator: std.mem.Allocator) !
return variantMap; 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 { pub fn getEngineObject(comptime T: type) ?*T {
if (T.NeonObjectTable.singletonName) |name| { if (T.NeonObjectTable.singletonName) |name| {
if (getEngine().engineObjectsByName.get(name)) |ref| { 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 { pub fn loadModule(moduleName: []const u8, watch: bool) !void {
if (watch == false) unreachable; // not implemented 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;
} }

View File

@ -1,5 +1,3 @@
var gEcsRegistry: *EcsRegistry = undefined;
// wew lad. this is definitely an exploratory implementation I think. // wew lad. this is definitely an exploratory implementation I think.
// //
// todo: cruft // todo: cruft
@ -112,19 +110,20 @@ var gEcsRegistry: *EcsRegistry = undefined;
// SparseMultiSet (AOS version of sparseSet Really specialized, only used for core engine systems) // SparseMultiSet (AOS version of sparseSet Really specialized, only used for core engine systems)
pub fn createEntity() !Entity { 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}); core.engine_log("entity created: {d}", .{rv.handle.index});
return rv; return rv;
} }
pub fn destroyEntity(e: Entity) void { pub fn destroyEntity(e: Entity) void {
core.engine_log("entity destroyed: {d}", .{e.handle.index}); 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| { for (entityEntry.containers.items) |ref| {
ref.vtable.destroyObject(ref.ptr, e.handle); ref.vtable.destroyObject(ref.ptr, e.handle);
} }
entityEntry.containers.deinit(gEcsRegistry.allocator); entityEntry.containers.deinit(registry.allocator);
gEcsRegistry.baseSet.destroyObject(e.handle); registry.baseSet.destroyObject(e.handle);
} else { } else {
core.engine_log("UNABLE TO DESTROY ENTITY {d}", .{e.handle.index}); 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 { pub fn setup(allocator: std.mem.Allocator) !void {
try ComponentRef.setupFormatBuffer(allocator); try ComponentRef.setupFormatBuffer(allocator);
gEcsRegistry = try core.createObject(EcsRegistry, .{ .can_tick = true }); _ = try core.createObject(EcsRegistry, .{ .can_tick = true });
} }
pub fn shutdown() void { pub fn shutdown() void {
ComponentRef.shutdownFormatBuffer(); ComponentRef.shutdownFormatBuffer();
} }
pub fn getRegistry() *EcsRegistry { pub const getRegistry = core.EngineObject(EcsRegistry).get;
return gEcsRegistry;
}
pub fn registerEcsContainer(ref: EcsContainerRef, name: core.Name) !void { 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 { 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); const ref = p2.refFromPtr(EcsSystemInterface, system);
core.engine_log("ptr = {any}", .{ref.vtable.tick}); 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) { if (ref.vtable.tick != null) {
try gEcsRegistry.tickableSystems.append(gEcsRegistry.allocator, ref); try registry.tickableSystems.append(registry.allocator, ref);
} }
return system; return system;
@ -193,7 +191,7 @@ pub const EcsRegistry = struct {
containerNames: std.ArrayListUnmanaged(core.Name) = .{}, containerNames: std.ArrayListUnmanaged(core.Name) = .{},
containersByName: std.AutoHashMapUnmanaged(u32, u32) = .{}, 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() { pub fn init(allocator: std.mem.Allocator) !*@This() {
const self = try allocator.create(@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) }); core.engine_log("adding component: {d} {s}", .{ self.handle.index, @typeName(Component) });
const rv = Component.BaseContainer.createWithHandleECS(self.handle); const rv = Component.BaseContainer.createWithHandleECS(self.handle);
const list = &gEcsRegistry.baseSet.get(self.handle).?.containers; const list = &getRegistry().baseSet.get(self.handle).?.containers;
const allocator = gEcsRegistry.allocator; const allocator = getRegistry().allocator;
list.append(allocator, getTypeContainer(Component)) catch return null; list.append(allocator, getTypeContainer(Component)) catch return null;
// if (@hasDecl(Component, "init")) { // if (@hasDecl(Component, "init")) {

View File

@ -80,6 +80,7 @@ pub const Engine = struct {
rendererSetupFunc: ?PollFuncFn = null, rendererSetupFunc: ?PollFuncFn = null,
engineStartTime: f64 = 0, engineStartTime: f64 = 0,
sessionStamp: i64 = 0,
nfdRuntime: *nfd.NFDRuntime, nfdRuntime: *nfd.NFDRuntime,
@ -153,7 +154,7 @@ pub const Engine = struct {
} }
// creates an engine object using the engine's allocator. // 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) { if (self.createObjectLock) {
core.engine_err("RECURSIVE OBJECT CREATION NOT ALLOWED", .{}); core.engine_err("RECURSIVE OBJECT CREATION NOT ALLOWED", .{});
return error.BadInit; return error.BadInit;
@ -239,6 +240,7 @@ pub const Engine = struct {
self.first = false; self.first = false;
self.engineStartTime = newTime; self.engineStartTime = newTime;
self.lastEngineTime = newTime; self.lastEngineTime = newTime;
self.sessionStamp = std.time.microTimestamp();
} }
if (newTime < self.lastEngineTime) { 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 __timeleft: f64 = 0.0;
pub var __interval: f64 = 0.0; pub var __interval: f64 = 0.0;
}; };
C.__interval -= dt; C.__timeleft -= dt;
if (C.__timeleft <= 0.0) { if (C.__timeleft <= 0.0) {
S.func(capture); S.func(capture);

View File

@ -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 { pub fn MakeTypeName(comptime TargetType: type) Name {
const hashedName = comptime std.fmt.comptimePrint("{s}_{d}", .{ @typeName(TargetType), @sizeOf(TargetType) }); 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);

View File

@ -6,6 +6,15 @@ const ModuleInterface = struct {
shutdown: *const fn () callconv(.C) void = undefined, 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 { pub const LoadedModule = struct {
baseModulePath: []const u8, baseModulePath: []const u8,
moduleName: []const u8, moduleName: []const u8,
@ -18,6 +27,7 @@ pub const LoadedModule = struct {
startOnLoad: bool = true, startOnLoad: bool = true,
started: bool = false, started: bool = false,
initialLoad: bool = true,
pub fn getInterface(self: @This()) ?ModuleInterface { pub fn getInterface(self: @This()) ?ModuleInterface {
return self.loaded.getLastOrNull(); return self.loaded.getLastOrNull();
@ -25,7 +35,8 @@ pub const LoadedModule = struct {
pub fn stageModule(self: *@This(), allocator: std.mem.Allocator) !void { pub fn stageModule(self: *@This(), allocator: std.mem.Allocator) !void {
//const stagingDirectory = ".modulecache/<name>/0/"; //const stagingDirectory = ".modulecache/<name>/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.moduleName,
self.stagedPaths.items.len, self.stagedPaths.items.len,
}); });
@ -53,35 +64,56 @@ pub const LoadedModule = struct {
try self.loaded.append(allocator, mod); 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 // logic for testing if we should stage and load
// //
// 1. modification check time > last load time // 1. modification check time > last load time
// 2. current time > modification check time + debounce // 2. current time > modification check time + debounce
pub fn maybeStageAndLoad(self: *@This(), allocator: std.mem.Allocator) !bool { pub fn maybeStageAndLoad(self: *@This(), allocator: std.mem.Allocator) !bool {
core.engine_log("[tick]:", .{}); var shouldLoad: bool = false;
if (self.lastModification > self.lastLoad) { if (self.lastModification > self.lastLoad) {
const currentTime = std.time.microTimestamp(); const currentTime = std.time.microTimestamp();
// give 100ms for debouncing // give 100ms for debouncing
if (currentTime > self.lastModification + 50_000) { if (currentTime > self.lastModification + 50_000) {
self.lastLoad = currentTime; shouldLoad = true;
core.engine_log("[ModuleLoader] loading module: ", .{});
try self.stageModule(allocator);
try self.loadStagedModule(allocator);
return true;
} }
} }
if (self.initialLoad) {
self.initialLoad = false;
shouldLoad = true;
}
if (shouldLoad) {
try self.load(allocator);
return true;
}
return false; 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 { pub const ModuleLoader = struct {
backingAllocator: std.mem.Allocator, backingAllocator: std.mem.Allocator,
arena: std.heap.ArenaAllocator, 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() { pub fn create(allocator: std.mem.Allocator) !*@This() {
const self = try allocator.create(@This()); const self = try allocator.create(@This());
@ -90,6 +122,8 @@ pub const ModuleLoader = struct {
.arena = std.heap.ArenaAllocator.init(allocator), .arena = std.heap.ArenaAllocator.init(allocator),
}; };
core.fs().watchPath("zig-out/modules/");
return self; return self;
} }
@ -97,18 +131,22 @@ pub const ModuleLoader = struct {
// modules are always looked for under zig-out/modules // modules are always looked for under zig-out/modules
core.engine_log("[ModuleLoader]: adding module to watch '{s}'", .{moduleName}); core.engine_log("[ModuleLoader]: adding module to watch '{s}'", .{moduleName});
const libFileName = try p2.sharedLibNameAlloc(self.arena.allocator(), 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}), .baseModulePath = try std.fmt.allocPrint(self.arena.allocator(), "zig-out/modules/{s}", .{libFileName}),
.moduleName = moduleName, .moduleName = moduleName,
.lastModification = std.time.microTimestamp(), .lastModification = std.time.microTimestamp(),
}; };
try core.fs().addFileChangedCallback(libFileName, dllChangedCallback, loaded);
try self.loadedModules.append(self.arena.allocator(), loaded); try self.loadedModules.append(self.arena.allocator(), loaded);
} }
pub fn tick(self: *@This(), dt: f64) void { pub fn tick(self: *@This(), dt: f64) void {
_ = dt; _ = dt;
for (self.loadedModules.items) |*loaded| { for (self.loadedModules.items) |loaded| {
const didLoad = loaded.maybeStageAndLoad(self.arena.allocator()) catch |err| { const didLoad = loaded.maybeStageAndLoad(self.arena.allocator()) catch |err| {
core.engine_log("unable to load module error: {any}", .{err}); core.engine_log("unable to load module error: {any}", .{err});
if (@errorReturnTrace()) |trace| { if (@errorReturnTrace()) |trace| {
@ -124,7 +162,15 @@ pub const ModuleLoader = struct {
if (loaded.startOnLoad) { if (loaded.startOnLoad) {
if (!loaded.started) { if (!loaded.started) {
var a = self.backingAllocator; 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", .{}); core.engine_log("[ModuleLoader] module startup done", .{});
} }
} }

View File

@ -71,7 +71,7 @@ pub const ActionBindingKey = struct {
}; };
fn arenaAlloc() std.mem.Allocator { fn arenaAlloc() std.mem.Allocator {
return gInputStack.arena.allocator(); return getInputStack().arena.allocator();
} }
fn BindingData(Listener: type, Func: type) type { fn BindingData(Listener: type, Func: type) type {
@ -151,11 +151,11 @@ pub const ActionBinding = struct {
} }
// pushes this binding to the active layer // pushes this binding to the active layer
pub fn activate(self: *@This()) void { 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 { 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 { 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 // pushes this binding to the active layer
pub fn activate(self: *@This()) void { 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 { pub fn setClamp(self: *@This(), clampValue: ?f32) void {
@ -213,7 +213,7 @@ pub const Axis1dBinding = struct {
} }
pub fn deactivate(self: *@This()) void { 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 { 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 // pushes this binding to the active layer
pub fn activate(self: *@This()) void { 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 { 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 { 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), .active = try BindingLayer.create(allocator),
}; };
gInputStack = self; core.EngineObject(@This()).gInstance = self;
return self; return self;
} }
@ -677,14 +677,12 @@ pub const InputStack = struct {
} }
}; };
var gInputStack: *InputStack = undefined;
pub fn getInputStack() *InputStack { pub fn getInputStack() *InputStack {
return gInputStack; return core.EngineObject(InputStack).get();
} }
pub fn initInputStack() !void { pub fn initInputStack() !void {
gInputStack = try core.createObject(InputStack, .{}); _ = try core.createObject(InputStack, .{});
} }
// creates a binding for a lua type // creates a binding for a lua type

View File

@ -297,6 +297,10 @@ pub fn forceFlush() void {
} }
} }
pub fn setupLoggingFromModule() void {
gLoggerSys = core.getEngineObject(LoggerSys);
}
pub fn setupLogging(engine: *core.Engine) !void { pub fn setupLogging(engine: *core.Engine) !void {
gLoggerSys = try engine.createObject(LoggerSys, .{ gLoggerSys = try engine.createObject(LoggerSys, .{
.responds_to_events = true, .responds_to_events = true,

View File

@ -216,8 +216,8 @@ pub const Scene = struct {
pub fn getAndResolveTransform(self: @This()) core.Transform { pub fn getAndResolveTransform(self: @This()) core.Transform {
const repr: *SceneObjectRepr = SceneObjectContainer.get(self.handle, ._repr).?; const repr: *SceneObjectRepr = SceneObjectContainer.get(self.handle, ._repr).?;
if (repr.lastUpdate != gSceneSystem.tickCount) { if (repr.lastUpdate != getSceneSystem().tickCount) {
gSceneSystem.updateTransform(repr, SceneObjectContainer.get(self.handle, .posRot).?); getSceneSystem().updateTransform(repr, SceneObjectContainer.get(self.handle, .posRot).?);
} }
return repr.transform; 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 { fn childAllocator() std.mem.Allocator {
return gSceneSystem.childrenArena.allocator(); return getSceneSystem().childrenArena.allocator();
} }
pub const SceneSystem = struct { pub const SceneSystem = struct {
@ -364,7 +364,7 @@ pub const SceneSystem = struct {
.allocator = allocator, .allocator = allocator,
.childrenArena = std.heap.ArenaAllocator.init(allocator), .childrenArena = std.heap.ArenaAllocator.init(allocator),
}; };
gSceneSystem = self; core.EngineObject(@This()).gInstance = self;
try core.defineComponent(Scene, allocator); try core.defineComponent(Scene, allocator);
Scene.SceneObjectContainer = try SceneObjectSet.create(allocator); Scene.SceneObjectContainer = try SceneObjectSet.create(allocator);
return self; return self;

View File

@ -13,8 +13,13 @@ pub const script_bindings = @import("script_bindings.zig");
const c = lua.c; const c = lua.c;
var gLuaState: lua.LuaState = undefined; pub var gLuaState: lua.LuaState = undefined;
var gLuaAllocator: std.mem.Allocator = 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 = &.{ const luaRegLibs: []const c.luaL_Reg = &.{
.{ .name = "print", .func = printWrapper }, .{ .name = "print", .func = printWrapper },

View File

@ -9,17 +9,18 @@ pub const Module: core.ModuleDescription = .{
.enabledByDefault = false, .enabledByDefault = false,
}; };
var gImgui: *Impl = undefined;
pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.mem.Allocator) !void { pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.mem.Allocator) !void {
_ = allocator; _ = allocator;
_ = args; _ = args;
_ = spec; _ = spec;
// gImgui = try rend.createRendererObject(Impl); const gimgui = try core.createObject(Impl, .{});
// try gImgui.setup(); try gimgui.setup();
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 { pub fn shutdown_module(allocator: std.mem.Allocator) void {

View File

@ -4,8 +4,9 @@ pub const Impl = struct {
drawData: [*c]ig.DrawData = undefined, drawData: [*c]ig.DrawData = undefined,
rendererDebug: bool = true, 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 { pub const Settings = struct {
x: u32 = 0, x: u32 = 0,
@ -29,6 +30,8 @@ pub const Impl = struct {
c.Imgui_SDL3_Init(@ptrCast(platform.getInstance().window), @ptrCast(self.device)); c.Imgui_SDL3_Init(@ptrCast(platform.getInstance().window), @ptrCast(self.device));
try platform.getInstance().addSDLProcessFunction(processSDLEvents); try platform.getInstance().addSDLProcessFunction(processSDLEvents);
self.context = ig.getCurrentContext().?;
} }
pub fn processSDLEvents(event: *sdl3.Event) void { pub fn processSDLEvents(event: *sdl3.Event) void {

View File

@ -38,15 +38,15 @@ pub const PrimitiveType = enum {
// low level helpers - old api // low level helpers - old api
pub fn addPrimitiveBody(primitive: PrimitiveType, settings: BodyCreationSettings, activationMode: Activation) !BodyId { pub fn addPrimitiveBody(primitive: PrimitiveType, settings: BodyCreationSettings, activationMode: Activation) !BodyId {
const interface = gPhysicsRuntime.system.getBodyInterfaceMut(); const interface = context().system.getBodyInterfaceMut();
var s = settings; var s = settings;
switch (primitive) { switch (primitive) {
.box => { .box => {
s.shape = gPhysicsRuntime.primBoxShape; s.shape = context().primBoxShape;
}, },
.sphere => { .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 { 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); interface.setPosition(id, pos.toArr3(), .activate);
} }
pub fn setBodyRotation(id: BodyId, rot: core.Rotation) void { 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); interface.setRotation(id, rot.quat, .activate);
} }
pub fn optimizeBroadPhase() void { 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 { pub fn addShape(name: []const u8, settings: ShapeSettings) !void {
var n = core.MakeName(name); 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 { 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; _ = spec;
try zphysics.init(allocator, .{}); 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 { 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 { pub fn releaseShape(name: core.Name) void {
var n = name; var n = name;
gPhysicsRuntime.shapes.get(n.handle()).?.shape.release(); context().shapes.get(n.handle()).?.shape.release();
} }
pub const RayCastSettings = struct { pub const RayCastSettings = struct {
@ -109,7 +109,7 @@ pub const RayCastResult = struct {
}; };
pub fn traceLine(start: core.Vectorf, direction: core.Vectorf, settings: RayCastSettings) ?RayCastResult { 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(.{ const result = query.castRay(.{
.origin = start.toZm(), .origin = start.toZm(),
.direction = direction.toZm(), .direction = direction.toZm(),
@ -127,13 +127,13 @@ pub fn traceLine(start: core.Vectorf, direction: core.Vectorf, settings: RayCast
}; };
if (settings.entityLookup) { if (settings.entityLookup) {
rv.entity = gPhysicsRuntime.idToEntity.get(rv.body).?; rv.entity = context().idToEntity.get(rv.body).?;
} }
return rv; return rv;
} }
pub fn applyForce(body: BodyId, impulse: core.Vectorf, position: core.Vectorf) void { 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()); interface.addImpulseAtPosition(body, impulse.toArr3(), position.toArr3());
} }

View File

@ -144,7 +144,7 @@ pub const PhysicsRuntime = struct {
timeSinceUpdate: f64 = 0.0, timeSinceUpdate: f64 = 0.0,
idToEntity: std.AutoHashMapUnmanaged(zphysics.BodyId, core.Entity) = .{}, 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 { pub fn registerBodyEntity(self: *@This(), bodyId: zphysics.BodyId, entity: core.Entity) !void {
try self.idToEntity.put(self.allocator, bodyId, entity); try self.idToEntity.put(self.allocator, bodyId, entity);

View File

@ -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, allocator: std.mem.Allocator,
debugDraws: core.RingQueueU(DebugPrimitive), debugDraws: core.RingQueueU(DebugPrimitive),

View File

@ -3,7 +3,7 @@
allocator: std.mem.Allocator, allocator: std.mem.Allocator,
pub var LoaderInterfaceVTable = assets.AssetLoaderInterface.from("Mesh", @This()); 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() { pub fn create(allocator: std.mem.Allocator) !*@This() {
const self = try allocator.create(@This()); const self = try allocator.create(@This());

View File

@ -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, allocator: std.mem.Allocator,

View File

@ -7,7 +7,7 @@
// //
pub var LoaderInterfaceVTable = assets.AssetLoaderInterface.from("Texture", @This()); 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, allocator: std.mem.Allocator,
device: *gpu.GPUDevice = undefined, 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 { pub fn setup(self: *@This(), device: *gpu.GPUDevice) !void {
core.engine_log("Texture List Added", .{}); core.engine_log("Texture List Added", .{});
try assets.gAssetSys.registerLoader(self); try assets.getAssets().registerLoader(self);
self.device = device; self.device = device;
} }

View File

@ -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 }); 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; return self;
} }

View File

@ -85,7 +85,7 @@ pub const Renderer = struct {
positionTargetFormat: gpu.GPUTextureFormat = .textureformatR16g16b16a16Float, positionTargetFormat: gpu.GPUTextureFormat = .textureformatR16g16b16a16Float,
normalTargetFormat: gpu.GPUTextureFormat = .textureformatB8g8r8a8Unorm, 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; pub const MaxObjectCount = 50000;
@ -913,8 +913,9 @@ pub const Renderer = struct {
} }
}; };
pub var gRenderer: *Renderer = undefined; // pub var gRenderer: *Renderer = undefined;
pub var gAllocator: std.mem.Allocator = undefined;
pub const context = core.EngineObject(Renderer).get;
const rend = @import("../rend.zig"); const rend = @import("../rend.zig");
@ -949,45 +950,40 @@ const SkyboxSystem = @import("SkyboxSystem.zig");
// debug api // debug api
pub fn reloadShaders() !void { 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"); core.graphics_logs("shader cook script failed");
return; return;
}; };
try gRenderer.createMeshPipeline(); try context().createMeshPipeline();
try gRenderer.createPostProcessingPipeline(); try context().createPostProcessingPipeline();
try gRenderer.ssaoSystem.createPipeline(); try context().ssaoSystem.createPipeline();
} }
// ====== renderer API ======= // ====== renderer API =======
pub fn createInstance() !void { pub fn createInstance() !void {
gRenderer = try core.createObject(Renderer, .{ .can_tick = true, .isCore = true }); _ = try core.createObject(Renderer, .{ .can_tick = true, .isCore = true });
gAllocator = gRenderer.allocator;
} }
pub fn start() !void { pub fn start() !void {
try gRenderer.startRenderer(); try context().startRenderer();
} }
pub fn shutdown() void {} pub fn shutdown() void {}
pub fn context() *Renderer {
return gRenderer;
}
pub fn setActiveCamera(camera: ?*rend.CameraComponent) void { pub fn setActiveCamera(camera: ?*rend.CameraComponent) void {
gRenderer.activeCamera = camera; context().activeCamera = camera;
} }
pub fn createRendererObject(comptime T: type) !*T { 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 { 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 { 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; pub const getMesh = mesh_pool.getMesh;
@ -995,7 +991,7 @@ pub const getMeshByName = mesh_pool.getMeshByName;
pub const pushMeshUpdate = mesh_pool.pushMeshUpdate; pub const pushMeshUpdate = mesh_pool.pushMeshUpdate;
pub fn getTexture(name: *core.Name) ?*rend.Texture { 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 { pub const RendererState = struct {
@ -1011,7 +1007,7 @@ pub const RendererState = struct {
pub fn textureExists(name: []const u8) bool { pub fn textureExists(name: []const u8) bool {
var n = core.MakeName(name); 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; pub const CustomMeshRenderFunc = *const fn (?*anyopaque) void;

View File

@ -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, allocator: std.mem.Allocator,

View File

@ -31,7 +31,7 @@ pub fn maybeUpdate(self: *@This()) !void {
const alloc = self.arena.allocator(); const alloc = self.arena.allocator();
for (engine.engineObjects.items) |x| { for (engine.engineObjects.items) |x| {
const newString = try std.fmt.allocPrint(alloc, "[{s}] {s} @ 0x{x} (size: {d} bytes) ", .{ 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, x.vtable.typeName,
@intFromPtr(x.ptr), @intFromPtr(x.ptr),
x.vtable.typeSize, x.vtable.typeSize,

View File

@ -1,7 +1,7 @@
dtAverage: f64 = 0.0, dtAverage: f64 = 0.0,
allocator: std.mem.Allocator, 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() { pub fn create(allocator: std.mem.Allocator) !*@This() {
const self = try allocator.create(@This()); const self = try allocator.create(@This());

View File

@ -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. // largely don't need to touch this structure from the user's side.
pub const NeonVkImGui = struct { pub const NeonVkImGui = struct {
const Self = @This(); const Self = @This();
pub const NeonObjectTable = core.EngineObjectVTable.from(Self); pub var NeonObjectTable = core.EngineObjectVTable.from(Self);
pub const RendererInterfaceVTable = graphics.RendererInterface.from(Self); pub const RendererInterfaceVTable = graphics.RendererInterface.from(Self);
allocator: std.mem.Allocator, allocator: std.mem.Allocator,

View File

@ -2297,7 +2297,7 @@ pub inline fn getCurrentContext() ?*Context { //igGetCurrentContext
return @ptrCast(c.igGetCurrentContext()); return @ptrCast(c.igGetCurrentContext());
} }
pub inline fn setCurrentContext(ctx: ?*Context) void { //igSetCurrentContext pub inline fn setCurrentContext(ctx: ?*Context) void { //igSetCurrentContext
c.igSetCurrentContext(ctx); c.igSetCurrentContext(@ptrCast(ctx));
} }
pub inline fn getIO() ?*Io { //igGetIO pub inline fn getIO() ?*Io { //igGetIO
return @ptrCast(c.igGetIO_Nil()); return @ptrCast(c.igGetIO_Nil());

2
lib/p2/src/p2.zig vendored
View File

@ -66,6 +66,8 @@ pub const MakeName = names.MakeName;
pub const DefineName = names.DefineName; pub const DefineName = names.DefineName;
pub const createNameRegistry = names.createNameRegistry; pub const createNameRegistry = names.createNameRegistry;
pub const destroyNameRegistry = names.destroyNameRegistry; pub const destroyNameRegistry = names.destroyNameRegistry;
pub const setNameRegistry = names.setNameRegistry;
pub const NameRegistry = names.NameRegistry;
pub const spans = @import("structures/spans.zig"); pub const spans = @import("structures/spans.zig");
pub const MergedSpans = spans.MergedSpans; pub const MergedSpans = spans.MergedSpans;

View File

@ -106,6 +106,11 @@ pub fn createNameRegistry(allocator: std.mem.Allocator) !*NameRegistry {
return gRegistry; return gRegistry;
} }
pub fn setNameRegistry(registry: *NameRegistry) void {
gRegistry = registry;
registryCreated = true;
}
pub fn getRegistry() *NameRegistry { pub fn getRegistry() *NameRegistry {
// specifically in the case of unittests we can silently just initialize a temporary registry // specifically in the case of unittests we can silently just initialize a temporary registry
if (builtin.is_test) { if (builtin.is_test) {

View File

@ -30,6 +30,8 @@ pub fn build(b: *std.Build) void {
.name = "externGame", .name = "externGame",
}); });
sampleGameExtern.root_module.addImport("backlog", blbuild.nw_mod);
const installExtern = b.addInstallArtifact(sampleGameExtern, .{ const installExtern = b.addInstallArtifact(sampleGameExtern, .{
.dest_dir = .{ .override = .{ .custom = "modules" } }, .dest_dir = .{ .override = .{ .custom = "modules" } },
}); });

View File

@ -8,7 +8,7 @@ struct type_Uniforms
float brightnessFactor; float brightnessFactor;
}; };
constant float4 _28 = {}; constant float4 _29 = {};
struct main0_out 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<float> SkyboxTexture [[texture(0)]], sampler SkyboxSampler [[sampler(0)]]) fragment main0_out main0(main0_in in [[stage_in]], constant type_Uniforms& Uniforms [[buffer(0)]], texturecube<float> SkyboxTexture [[texture(0)]], sampler SkyboxSampler [[sampler(0)]])
{ {
main0_out out = {}; main0_out out = {};
float4 _38 = SkyboxTexture.sample(SkyboxSampler, in.in_var_TEXCOORD0) * Uniforms.brightnessFactor; float4 _39 = SkyboxTexture.sample(SkyboxSampler, in.in_var_TEXCOORD0) * Uniforms.brightnessFactor;
out.out_var_SV_Target0 = _38; float4 _44 = _39;
out.out_var_SV_Target1 = select(_28, _38, bool4(length(_38) > 1.0)); _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; return out;
} }

View File

@ -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 { pub export fn add(a: i32, b: i32) i32 {
return a + b; return a + b;
} }
@ -6,4 +16,73 @@ pub export fn subtract(a: i32, b: i32) i32 {
return a + b; 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 std = @import("std");
const backlog = @import("backlog");
const core = backlog.core;
const imgui = backlog.imgui;
const rend = backlog.rend;
const ig = imgui.api;

View File

@ -28,13 +28,13 @@ rendererDebugger: *extras.RendererDebug = undefined,
tbMap: ?*bsp.maploader.TBMap = null, 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, engineTool: *extras.EngineTool = undefined,
modules: std.AutoHashMapUnmanaged(u32, []const u8) = .{}, 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() { pub fn init(allocator: std.mem.Allocator) !*@This() {
const self = try allocator.create(@This()); const self = try allocator.create(@This());
@ -192,12 +192,14 @@ pub fn prepare(self: *@This()) !void {
try script.loadTypes("scripts"); try script.loadTypes("scripts");
try script.runScriptFile("scripts/prepare.lua"); try script.runScriptFile("scripts/prepare.lua");
try core.loadModule("externGame", true);
self.engineTool = try extras.EngineTool.create(self.allocator); self.engineTool = try extras.EngineTool.create(self.allocator);
core.fs().watchPath("zig-out/modules"); // core.fs().watchPath("zig-out/modules");
try core.fs().addFileChangedCallback(core.sharedLibName("externGame"), moduleChangedCallback, self); // 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, .{}); 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), s: @TypeOf(self),
pub fn func(c: @This()) void { pub fn func(c: @This()) void {
c.s.tryLoadExtern("externGame") catch unreachable; _ = c;
// c.s.tryLoadExtern("externGame") catch unreachable;
} }
}, .{ .s = self }); }, .{ .s = self });
@ -463,7 +466,6 @@ pub fn tick(self: *@This(), dt: f64) void {
// show a window with the current camera's position // show a window with the current camera's position
if (!self.mouseLook) { if (!self.mouseLook) {
ig.showDemoWindow(null);
self.engineTool.tick(); self.engineTool.tick();
self.objectSpawner.windowOpen = !self.mouseLook; self.objectSpawner.windowOpen = !self.mouseLook;
self.objectSpawner.tick(dt); 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("- 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.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: ", .{}); ig.textf("modules dirty: ", .{});

View File

@ -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() { pub fn init(allocator: std.mem.Allocator) !*@This() {
const self = try allocator.create(@This()); const self = try allocator.create(@This());