hot reloading is working now
This commit is contained in:
parent
db49ef3606
commit
252a5271a1
59
build.zig
59
build.zig
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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");
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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")) {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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", .{});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 },
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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" } },
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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: ", .{});
|
||||||
|
|
|
||||||
|
|
@ -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());
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue