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);
}
// 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());
return mod;

View File

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

View File

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

View File

@ -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;

View File

@ -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),

View File

@ -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;

View File

@ -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 {

View File

@ -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");

View File

@ -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;
}

View File

@ -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")) {

View File

@ -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);

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 {
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,
};
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/<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.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", .{});
}
}

View File

@ -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

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 {
gLoggerSys = try engine.createObject(LoggerSys, .{
.responds_to_events = true,

View File

@ -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;

View File

@ -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 },

View File

@ -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 {

View File

@ -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 {

View File

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

View File

@ -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);

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,
debugDraws: core.RingQueueU(DebugPrimitive),

View File

@ -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());

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,

View File

@ -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;
}

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 });
try assets.gAssetSys.registerLoader(try core.createObject(MeshAssetLoader, .{}));
try assets.getAssets().registerLoader(try core.createObject(MeshAssetLoader, .{}));
return self;
}

View File

@ -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;

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,

View File

@ -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,

View File

@ -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());

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.
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,

View File

@ -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());

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 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;

View File

@ -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) {

View File

@ -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" } },
});

View File

@ -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<float> 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;
}

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 {
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;

View File

@ -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: ", .{});

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() {
const self = try allocator.create(@This());