diff --git a/engine/core/build.zig b/engine/core/build.zig index 8829e2a..55d98ed 100644 --- a/engine/core/build.zig +++ b/engine/core/build.zig @@ -2,14 +2,9 @@ const std = @import("std"); const dependencyList = [_][]const u8{ "p2", - "tracy", + "tracy", // usually doesnt have C deps... unless we're compiled with it on, in which case we only support static builds "zmath", - "packer", // packer might need to be split into another setup that doesn't have C deps. - - // these ones use c deps, but if i move them out to platform... then core will have zero c dependencies. - "lua", - "spng", - // "nfd", + "packer", // packer no longer has C deps. }; pub fn build(b: *std.Build) void { diff --git a/engine/core/build.zig.zon b/engine/core/build.zig.zon index 411ada3..ae9798c 100644 --- a/engine/core/build.zig.zon +++ b/engine/core/build.zig.zon @@ -2,7 +2,7 @@ .name = .core, .version = "0.0.0", .dependencies = .{ - .spng = .{ .path = "../../lib/spng" }, + // .spng = .{ .path = "../../lib/spng" }, // .nfd = .{ .path = "../../lib/nfd" }, // with -Dtracy = false, this one pulls in no C dependencies @@ -12,7 +12,7 @@ .zmath = .{ .path = "../../lib/zmath" }, .packer = .{ .path = "../../lib/packer" }, .p2 = .{ .path = "../../lib/p2" }, - .lua = .{ .path = "../../lib/lua" }, + // .lua = .{ .path = "../../lib/lua" }, // .zgltf = .{ .path = "../../lib/zgltf" }, }, .paths = .{ diff --git a/engine/core/src/core.zig b/engine/core/src/core.zig index 6cf4830..9b0447f 100644 --- a/engine/core/src/core.zig +++ b/engine/core/src/core.zig @@ -25,7 +25,6 @@ pub const debugBox = debug_draw.debugBox; pub const debugLine = debug_draw.debugLine; // pub const script_bindings = script.script_bindings; -pub const misc = @import("misc.zig"); pub const engineTime = @import("engineTime.zig"); pub const engineObject = @import("engineObject.zig"); pub const EngineObjectVTable = engineObject.EngineObjectVTable; @@ -43,12 +42,8 @@ pub const ThreadContext = jobs.ThreadContext; pub const JobManager = jobs.JobManager; pub const JobWorker = jobs.JobWorker; -pub const file_utils = @import("file_utils.zig"); -pub const string_utils = @import("string_utils.zig"); -pub const type_utils = @import("type_utils.zig"); pub const engine = @import("engine.zig"); pub const tracy = @import("tracy").t; -pub const png = @import("png.zig"); pub const colors = @import("colors.zig"); @@ -141,8 +136,6 @@ pub const SceneSystem = scene.SceneSystem; pub const Engine = engine.Engine; -pub const spng = @import("spng"); - pub const MemoryTracker = @import("MemoryTracker.zig"); pub const DefaultSavePath = "Saved"; @@ -173,14 +166,16 @@ pub const defaultHighlight = logging.defaultHighlight; pub const packer = @import("packer"); -pub const FileSystem = packer.PackerFS; -pub const PackerFS = packer.PackerFS; - pub const StackCompactor = stacks.StackCompactor; var staticsInitialized = false; var gEngine: *Engine = undefined; +pub const PackerFS = packer.PackerFS; var gPackerFS: *PackerFS = undefined; + +pub fn fs() *PackerFS { + return gPackerFS; +} var fsInitialized: bool = false; pub fn EngineObject(comptime T: type) type { @@ -217,8 +212,6 @@ pub const undefineComponentList = ecs.undefineComponentList; pub const Entity = ecs.Entity; pub const createEntity = ecs.createEntity; -pub const script = @import("script.zig"); - pub const stacks = @import("stacks.zig"); pub const walkAndPrintStack = stacks.walkAndPrintStack; @@ -237,10 +230,6 @@ pub fn registerObjectAdvanced(comptime T: type, name: []const u8, comptime funcN try get(GameObjectSystem).registerObjectAdvanced(name, T, funcName); } -pub fn fs() *PackerFS { - return gPackerFS; -} - pub const Module = ModuleDescription{ .name = "core", .enabledByDefault = true, @@ -295,15 +284,9 @@ pub fn start_module_(map: *SpecVariantMap, args: anytype, allocator: std.mem.All fatDump = true; } - script.lua.setupMiniDump(fatDump); _ = try algorithm.createNameRegistry(allocator); - // LUA BEGIN -- what if i want to make the scripting integration optional? - // try script.start_lua(allocator); - // LUA END try maybeInitPackerFs(allocator); - // load configs. - //const name = if (@hasField(@TypeOf(programSpec), "configName")) programSpec.configName else programSpec.name; var name = map.get("name").?.string; if (map.get("configName")) |x| { @@ -330,8 +313,6 @@ pub fn start_module_(map: *SpecVariantMap, args: anytype, allocator: std.mem.All try algorithm.string_pool.setup(allocator); - // _ = try gEngine.createObject(script_bindings.ScriptTicks, .{ .can_tick = true }); - _ = try createObject(GameObjectSystem, .{ .can_tick = true }); _ = try inputs.initInputStack(); @@ -344,7 +325,6 @@ pub fn start_module_(map: *SpecVariantMap, args: anytype, allocator: std.mem.All 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; @@ -368,9 +348,6 @@ pub fn shutdown_module(_: std.mem.Allocator) void { ecs.shutdown(); algorithm.destroyNameRegistry(); gPackerFS.destroy(); - // LUA BEGIN - // script.shutdown_lua(); - // LUA END console.shutdown(); algorithm.string_pool.shutdown(); @@ -386,22 +363,20 @@ pub fn parallelJob(capture: anytype, async: bool, maxWorkerCount: ?u32) !void { const requestedWorkers = if (maxWorkerCount) |m| m else jobManager.numWorkers; const baseWorkerCount = @min(requestedWorkers, @max(getEngine().jobManager.numWorkers - 2, 1)); - const workerStart:u32 = if (async) 0 else 1; + const workerStart: u32 = if (async) 0 else 1; - for (workerStart .. baseWorkerCount) |workerId| { - try jobManager.newJob(capture, .{ .threadId = @intCast(workerId), .threadCount = baseWorkerCount}); + for (workerStart..baseWorkerCount) |workerId| { + try jobManager.newJob(capture, .{ .threadId = @intCast(workerId), .threadCount = baseWorkerCount }); } // start working on the job locally if (!async) { - try jobManager.runLocally(capture, .{.threadId = 0, .threadCount = baseWorkerCount}); + try jobManager.runLocally(capture, .{ .threadId = 0, .threadCount = baseWorkerCount }); } - - } pub fn dispatchJob(capture: anytype) !void { - try gEngine.jobManager.newJob(capture, .{.threadId = 0, .threadCount = 1});//0, 1, null); + try gEngine.jobManager.newJob(capture, .{ .threadId = 0, .threadCount = 1 }); //0, 1, null); } pub fn createObject(comptime T: type, params: engine.NeonObjectParams) !*T { diff --git a/engine/core/src/extern/externModule.zig b/engine/core/src/extern/externModule.zig index c095b7c..c71df79 100644 --- a/engine/core/src/extern/externModule.zig +++ b/engine/core/src/extern/externModule.zig @@ -125,6 +125,7 @@ pub const ModuleLoader = struct { arena: std.heap.ArenaAllocator, loadedModules: std.ArrayListUnmanaged(*LoadedModule) = .{}, watchInitialized: bool = false, + watchInitializeFn: ?*const fn () void = null, pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "core.ModuleLoader"); pub fn create(allocator: std.mem.Allocator) !*@This() { @@ -150,8 +151,11 @@ pub const ModuleLoader = struct { const loaded = try self.arena.allocator().create(LoadedModule); if (self.watchInitialized == false) { - core.fs().watchPath("zig-out/modules/"); - self.watchInitialized = true; + // core.fs().watchPath("zig-out/modules/"); + if (self.watchInitializeFn) |watchInitializeFn| { + watchInitializeFn(); + self.watchInitialized = true; + } } loaded.* = LoadedModule{ diff --git a/engine/core/src/file_utils.zig b/engine/core/src/file_utils.zig deleted file mode 100644 index 74b3f5c..0000000 --- a/engine/core/src/file_utils.zig +++ /dev/null @@ -1,34 +0,0 @@ -const std = @import("std"); -const logging = @import("logging.zig"); - -pub fn writeToFile(data: []const u8, path: []const u8) !void { - const file = try std.fs.cwd().createFile( - path, - .{ - .read = true, - }, - ); - - const bytes_written = try file.writeAll(data); - _ = bytes_written; - logging.engine_log("written: bytes to {s}", .{path}); -} - -pub fn splitIntoLines(file_contents: []const u8) std.mem.SplitIterator(u8) { - // find a \n and see if it has \r\n - var index: u32 = 0; - while (index < file_contents.len) : (index += 1) { - if (file_contents[index] == '\n') { - if (index > 0) { - if (file_contents[index - 1] == '\r') { - return std.mem.split(u8, file_contents, "\r\n"); - } else { - return std.mem.split(u8, file_contents, "\n"); - } - } else { - return std.mem.split(u8, file_contents, "\n"); - } - } - } - return std.mem.split(u8, file_contents, "\n"); -} diff --git a/engine/core/src/inputs/pseudocode.lua b/engine/core/src/inputs/pseudocode.lua deleted file mode 100644 index ae740ec..0000000 --- a/engine/core/src/inputs/pseudocode.lua +++ /dev/null @@ -1,14 +0,0 @@ - -moveAxis = CreateInput2DAxis() -moveAxis:addKey(Keys.W, 1.0, Axis.Y) -moveAxis:addKey(Keys.S, -1.0, Axis.Y) - -moveAxis:addKey(Keys.A, -1.0, Axis.X) -moveAxis:addKey(Keys.D, 1.0, Axis.X) -moveAxis:addListener(balls, ) - -Input.addBinding("move", moveAxis, true) - -Input.removeBinding("move") - - diff --git a/engine/core/src/lua/core.lua b/engine/core/src/lua/core.lua deleted file mode 100644 index 11c67d8..0000000 --- a/engine/core/src/lua/core.lua +++ /dev/null @@ -1,33 +0,0 @@ - -tickables = {} -properties = {} - -local function registerTick(object, f) - table.insert(tickables, {obj = object, func = f}) -end - -function __TickScripts(deltaTime) - for index, entry in ipairs(tickables) do - entry.func(entry.obj, deltaTime) - end -end - -function __RegisterEntityProperty(userdata) - properties[userdata] = {} -end - -function SetProperty(entity, property) - properties[entity] = property -end - -function GetProperty(entity) - return properties[entity] -end - -function GetObject(entity) - return properties[entity] -end - -Core = { - registerTick = registerTick; -} diff --git a/engine/core/src/lua/startup.lua b/engine/core/src/lua/startup.lua deleted file mode 100644 index dae26d4..0000000 --- a/engine/core/src/lua/startup.lua +++ /dev/null @@ -1,2 +0,0 @@ -print("Hello from lua.") - diff --git a/engine/core/src/math.zig b/engine/core/src/math.zig index e974e73..a33dae2 100644 --- a/engine/core/src/math.zig +++ b/engine/core/src/math.zig @@ -1,14 +1,7 @@ const std = @import("std"); -const misc = @import("misc.zig"); const zm = @import("zmath"); const math = std.math; -// LUA BEGIN feel like I should mark up the parts of the engine that need to be -// sliced out should i ever decide I'm sick of lua -const lua = @import("lua"); -const pod = lua.pod; -// LUA END - // vector versions. pub const f32x4 = @Vector(4, f32); // __m128_int pub const f32x8 = @Vector(8, f32); // __m256_int @@ -72,23 +65,7 @@ pub fn Vector2Type(comptime T: type, comptime typeName: []const u8) type { x: T = 0, y: T = 0, - // LUA BEGIN - pub const PodDataTable: pod.DataTable = .{ - .name = typeName, - .funcs = &.{ - "fmul", - "dot", - "length", - "normalize", - }, - .operators = .{ - .add = "add", - .sub = "sub", - .mul = "vmul", - .eq = "equals", - }, - }; - // LUA END + pub const VectorTypeName = typeName; pub const Ones = @This(){ .x = 1, .y = 1 }; pub const Zeroes = @This(){ .x = 0, .y = 0 }; @@ -232,6 +209,8 @@ pub fn Vector3Type(comptime T: type, comptime typeName: []const u8) type { y: T = 0, z: T = 0, + pub const VectorTypeName = typeName; + pub const Ones = @This(){ .x = 1, .y = 1, .z = 1 }; pub const Zeroes = @This(){ .x = 0, .y = 0, .z = 0 }; @@ -239,24 +218,6 @@ pub fn Vector3Type(comptime T: type, comptime typeName: []const u8) type { pub const Right = @This(){ .x = 1 }; pub const Forward = @This(){ .z = 1 }; - // LUA BEGIN - pub const PodDataTable: pod.DataTable = .{ - .name = typeName, - .funcs = &.{ - "fmul", - "dot", - "length", - "normalize", - }, - .operators = .{ - .add = "add", - .sub = "sub", - .mul = "vmul", - .eq = "equals", - }, - }; - // LUA END - pub inline fn new(x: T, y: T, z: T) @This() { return .{ .x = x, diff --git a/engine/core/src/misc.zig b/engine/core/src/misc.zig deleted file mode 100644 index dc908b0..0000000 --- a/engine/core/src/misc.zig +++ /dev/null @@ -1,41 +0,0 @@ -// Random misc. utilities that aren't /totally/ categorized right now. - -const logging = @import("logging.zig"); - -// Creates a for-loopable range between [0, n) -pub fn count(comptime n: anytype) [n]u0 { - return comptime [1]u0{0} ** n; -} - -// Creates a for-loopable range between [start, end). -// reccomended for use with inline FORs -pub fn range(comptime start: usize, comptime end: anytype) [end - start]@TypeOf(start) { - comptime var r = [1]@TypeOf(start){start} ** (end - start); - - comptime { - for (r, 0..) |val, i| { - r[i] = val + i; - } - } - - return comptime r; -} - -pub fn slice_to_cstr(str: []const u8) ?[*:0]const u8 { - return @as(?[*:0]const u8, @ptrCast(str.ptr)); -} - -pub fn buf_to_cstr(str: anytype) ?[*:0]const u8 { - return @as(?[*:0]const u8, @ptrCast(&str[0])); -} - -pub const CStr = [*:0]const u8; - -pub fn debug_struct(preamble: []const u8, s: anytype) void { - logging.graphics_log("{s}:", .{preamble}); - logging.graphics_log(" {any}", .{s}); -} - -pub fn p_to_av(a: anytype) [*]@TypeOf(a.*) { - return @as([*]@TypeOf(a.*), @ptrCast(a)); -} diff --git a/engine/core/src/script.zig b/engine/core/src/script.zig deleted file mode 100644 index 539a575..0000000 --- a/engine/core/src/script.zig +++ /dev/null @@ -1,150 +0,0 @@ -// scripting integration using lua - -const std = @import("std"); -pub const lua = @import("lua"); -const core = @import("core.zig"); -const startup_script = @embedFile("lua/startup.lua"); -const core_script = @embedFile("lua/core.lua"); -const ecs = @import("ecs.zig"); -const ComponentRef = @import("script/ComponentRef.zig"); -const ComponentRegistration = @import("script/ComponentRegistration.zig"); - -pub const script_bindings = @import("script_bindings.zig"); - -const c = lua.c; - -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 }, - .{ .name = null, .func = null }, -}; - -// binds the default print() function in lua to print to the console -fn printWrapper(l: ?*lua.c.lua_State) callconv(.c) i32 { - const state: lua.LuaState = .{ .l = l }; - const argc = state.getTop(); - - if (core.getLogger() == null) { - core.printRaw("> ", .{}); - } - - if (argc >= 1) { - core.printRaw("[SCRIPT ]: ", .{}); - } - - var i: i32 = 1; - while (i <= argc) : (i += 1) { - if (state.isString(i)) { - if (i > 1) { - core.printRaw(" ", .{}); - } - core.printRaw("{s}", .{state.toString(i)}); - } else if (state.isUserdata(i)) { - const s = state.toStringL(i); - state.pop(1); - core.printRaw("{s}", .{s}); - } - } - - core.printRaw("\n", .{}); - state.pop(argc); - - return 0; -} - -// initialization of the lua scripting interface. -// this interface is only threadsafe to operate on from the main systems thread (at this time). -pub fn start_lua(allocator: std.mem.Allocator) !void { - gLuaAllocator = allocator; - gLuaState = try lua.LuaState.init(.{}); - try lua.pod.setupFormatBuffer(allocator); - - // overload and hook into global functions - _ = gLuaState.getGlobal("_G"); - c.luaL_setfuncs(gLuaState.l, luaRegLibs.ptr, 0); - gLuaState.pop(1); - - try lua.pod.registerPodType(&gLuaState, ecs.Entity); - try lua.pod.registerPodType(&gLuaState, ComponentRegistration); - - try script_bindings.registerTypes(); - - try gLuaState.loadString(startup_script); - try gLuaState.pcall(); - - try gLuaState.loadString(core_script); - try gLuaState.pcall(); -} - -pub fn createLuaComponentDefinitions(globalName: []const u8, container: ecs.EcsContainerRef, luaNew: anytype) !void { - const reg = try gLuaState.newZigUserdata(ComponentRegistration); - reg.ref = container; - reg.name = globalName; - reg.luaNew = luaNew; - try gLuaState.setGlobal(globalName); -} - -pub fn registerComponent(comptime Component: type, container: ecs.EcsContainerRef) !void { - const ReferenceType = ComponentRef.ComponentReferenceType(Component); - try createLuaComponentDefinitions(@ptrCast(Component.ComponentName), container, ReferenceType.luaNew); - try ReferenceType.registerType(getState()); -} - -pub fn shutdown_lua() void { - lua.pod.shutdownFormatBuffer(); - gLuaState.deinit(); -} - -pub fn getState() *lua.LuaState { - return &gLuaState; -} - -fn findScriptBasepath(s: []const u8) []const u8 { - var i: usize = s.len - 1; - - while (i > 0) : (i -= 1) { - if (s[i] == '\\' or s[i] == '/') { - break; - } - } - - if (s[i] == '\\' or s[i] == '/') { - return s[i + 1 ..]; - } - - return s; -} - -pub fn loadTypes(scriptPath: []const u8) !void { - // 1. scan filesystem for all files under the script path - var fileList = try core.fs().listAllSubpaths(gLuaAllocator, scriptPath); - defer fileList.deinit(); - for (fileList.data.items, 0..) |f, i| { - // 2. enforce naming scheme for each script. - const basePath = findScriptBasepath(f); - - // core.engine_log("checking script file: {s} path:{s} base {s}", .{ f, fileList.sources.items[i], basePath }); - // 3. for each one, load the script and assign them based on name. - if (std.ascii.isUpper(basePath[0])) { - core.engine_log("loading script file: {s} path:{s}", .{ f, fileList.sources.items[i] }); - const scriptFile = try core.fs().loadFile(f); - defer core.fs().unmap(scriptFile); - try gLuaState.loadString(scriptFile.bytes); - try gLuaState.pcall(); - } - } -} - -pub fn runScriptFile(scriptPath: []const u8) !void { - const scriptFile = try core.fs().loadFile(scriptPath); - defer core.fs().unmap(scriptFile); - try gLuaState.loadString(scriptFile.bytes); - try gLuaState.pcall(); -} diff --git a/engine/core/src/script/ComponentRef.zig b/engine/core/src/script/ComponentRef.zig deleted file mode 100644 index 06818b3..0000000 --- a/engine/core/src/script/ComponentRef.zig +++ /dev/null @@ -1,258 +0,0 @@ -// lwdt can't have meta tables so I'm going to create component references -// -// the way this works is -// - entities are created as POD types -// - entities can get components added to them via entity:addComponent -// - this returns a ComponentReference -// - you can also get components from an entity via enity:get() -// - this also returns a ComponentReference -// -// - ComponentReferences allow you to modify data on a component or call functions on them -// -// -// How the registration works -// -// - define component -// - ecs.zig defineComponent -// - ComponentRef.zig - ReferenceType -// - addComponentRegistration - script.zig -// - ComponentRef - ReferenceType.registerType - -// this represents the lua side of the object -pub fn ComponentReferenceType(comptime T: type) type { - return struct { - ptr: *T = undefined, - - // used for resolving deltas. - handle: core.ObjectHandle = undefined, - stateCount: u32 = 0, - containerRef: ecs.EcsContainerRef = undefined, - - pub const MetatableName = T.ComponentName; - - // argc = 1, - // 1. a componentRegistration userdata - // can only be called from entity.luaAddComponent - pub fn luaNew(state: lua.LuaState, handle: core.ObjectHandle, ptr: ?*anyopaque) void { - const ud = state.newZigUserdata(@This()) catch return; - const containerRef = ecs.getTypeContainer(T); - - ud.* = .{ - .handle = handle, - .containerRef = containerRef, - .stateCount = 0, - }; - - // std.debug.print("luaNew ComponentReferenceType: {x}\n", .{@intFromPtr(ud)}); - // std.debug.print("luaNew ContainerRef: {x}\n", .{@intFromPtr(containerRef.ptr)}); - // std.debug.print("luaNew " ++ @typeName(T) ++ " ud.ptr = {x}\n", .{@intFromPtr(ptr)}); - - if (ptr) |p| { - ud.ptr = @ptrCast(@alignCast(p)); - ud.stateCount = containerRef.vtable.getStateCount(containerRef.ptr); - } - - if (@hasDecl(@TypeOf(T.BaseContainer.*), "IsMultiset")) { - // ... there are several things that need to be reworked here... - ud.ptr = @ptrCast(@alignCast(@as(*anyopaque, @ptrCast(&ud.handle)))); - // std.debug.print("luaNew " ++ @typeName(T) ++ " v = {any}\n", .{ud.ptr.getPosition()}); - } - } - - pub fn resolve(self: *@This()) void { - const ref = self.containerRef; - // std.debug.print("self: {x}\n", .{@intFromPtr(self)}); - // std.debug.print("ptr: {x}\n", .{@intFromPtr(ref.ptr)}); - if (@hasDecl(@TypeOf(T.BaseContainer.*), "IsMultiset")) { - // - } - if (ref.vtable.getStateCount(ref.ptr) != self.stateCount) { - self.ptr = @ptrCast(@alignCast(ref.vtable.get(ref.ptr, self.handle))); - } - } - - pub fn get(self: *@This()) *T { - self.resolve(); - return self.ptr; - } - - pub fn luaToString(state: lua.LuaState) i32 { - // oh god... this isn't good - // I think i've been treating this component ref as the user type - // huge failure of type resolution - if (state.toUserdata(@This(), 1)) |self| { - self.resolve(); - Buffer.clearRetainingCapacity(); - - var writer = Buffer.writer(); - writer.print("{s}{{", .{MetatableName}) catch return 0; - - inline for (std.meta.fields(T), 0..) |field, i| { - if (i == 0) { - writer.print(" {s} = ", .{field.name}) catch return 0; - } else { - writer.print(", {s} = ", .{field.name}) catch return 0; - } - switch (field.type) { - f32, i32, u32, f64, i64, u64 => { - writer.print("{d}", .{@field(self.ptr, field.name)}) catch return 0; - }, - []const u8 => { - writer.print("\"{s}\"", .{@field(self.ptr, field.name)}) catch return 0; - }, - else => { - writer.print("", .{@typeName(field.type)}) catch return 0; - }, - } - } - - writer.print(" }}" ++ "\x00", .{}) catch return 0; - state.pop(1); - state.pushString(Buffer.items) catch return 0; - return 1; - } - - return 0; - } - - pub fn luaIndex(state: lua.LuaState) i32 { - if (state.toUserdata(@This(), 1)) |self| { - if (state.isString(2)) { - _ = self; - const argument = state.toString(2); - // core.engine_log(@typeName(@This()) ++ " got indexed. 0x{x}", .{self.handle.index}); - - // check metatable - if (state.getMetafield(1, @ptrCast(argument))) { - return 1; - } - } - } - - return 0; - } - - fn makeTypeTable() lua.LibSpec { - const methods = blk: { - comptime var m: lua.LibSpec = &.{}; - m = m ++ .{lua.luaL_Reg{ .name = "__index", .func = lua.CWrap(luaIndex) }}; - m = m ++ .{lua.luaL_Reg{ .name = "__tostring", .func = lua.CWrap(luaToString) }}; - - inline for (T.ScriptExports) |name| { - m = m ++ .{lua.luaL_Reg{ .name = @as([*c]const u8, @ptrCast(name)), .func = ComponentFuncWrapper(@field(T, name), T) }}; - } - - break :blk m ++ .{lua.luaL_Reg{ .name = null, .func = null }}; - }; - - return methods; - } - - pub fn registerType(state: *lua.LuaState) !void { - core.engine_log("creating lua metatable {s}", .{MetatableName}); - - const methods = comptime makeTypeTable(); - - try state.newMetatable(@ptrCast(MetatableName)); - try state.setFuncs(methods, 0); - } - }; -} - -pub fn ComponentFuncWrapper(comptime baseFunc: anytype, comptime baseType: type) lua.LuaCFunc { - return lua.CWrap(FuncWrapper(baseFunc, baseType).wrapper); -} - -pub fn FuncWrapper(comptime baseFunc: anytype, comptime baseType: type) type { - return struct { - pub fn wrapper(state: lua.LuaState) i32 { - const Args = std.meta.ArgsTuple(@TypeOf(baseFunc)); - - var args: Args = undefined; - inline for (std.meta.fields(Args), 0..) |field, index| { - // std.debug.print("typename = {s}\n", .{@typeName(field.type)}); - switch (field.type) { - f32 => { - args[index] = @as(f32, @floatCast(state.toNumber(index + 1))); - }, - f64 => { - args[index] = state.toNumber(index + 1); - }, - i32 => { - args[index] = @intFromFloat(state.toNumber(index + 1)); - }, - []const u8 => { - args[index] = state.toString(index + 1); - }, - // I'll be honest how the hell does this work? - // - // the pointer being passed in here isn't the actual resulting type... - // it's the reference type - *baseType => { - const ref = state.toUserdata(ComponentReferenceType(baseType), index + 1).?; - ref.resolve(); - args[index] = ref.ptr; - }, - baseType => { - const ref = state.toUserdata(ComponentReferenceType(baseType), index + 1).?; - ref.resolve(); - args[index] = ref.ptr.*; - }, - else => { - // if(isComponentType(field.type)) { - // const ref = state.toUserdata(field.type, index + 1).?; - // ref.resolve(); - // args[index] = ref.ptr.*; - // continue; - // } - // - lua.debugPrints(true); - args[index] = (state.toUserdata(field.type, index + 1) orelse { - std.debug.print("argument error in index: {d}\n", .{index}); - state.emitError("something's weird with this argument\n"); - @panic("lmao"); - }).*; - lua.debugPrints(false); - }, - } - } - state.pop(@intCast(args.len)); - - //const rv = @call(.always_inline, baseFunc, args); - const rv = @call(.auto, baseFunc, args); - switch (@TypeOf(rv)) { - i32, u32, i64, u64 => { - state.pushNumber(@floatFromInt(rv)); - }, - f32, f64 => { - state.pushNumber(@floatCast(rv)); - }, - void => { - return 0; - }, - else => { - const ud = state.newZigUserdata(@TypeOf(rv)) catch @panic("not implemented"); - ud.* = rv; - }, - } - - return 1; - } - }; -} - -var Buffer: std.ArrayList(u8) = undefined; - -pub fn setupFormatBuffer(allocator: std.mem.Allocator) !void { - Buffer = std.ArrayList(u8).init(allocator); -} -pub fn shutdownFormatBuffer() void { - Buffer.deinit(); -} - -const std = @import("std"); -const core = @import("../core.zig"); -const ecs = @import("../ecs.zig"); -const lua = @import("lua"); -const pod = lua.pod; -const scene = @import("../scene.zig"); diff --git a/engine/core/src/script/ComponentRegistration.zig b/engine/core/src/script/ComponentRegistration.zig deleted file mode 100644 index d01841e..0000000 --- a/engine/core/src/script/ComponentRegistration.zig +++ /dev/null @@ -1,33 +0,0 @@ -ref: ecs.EcsContainerRef = undefined, -name: []const u8 = undefined, -luaNew: *const fn (state: lua.LuaState, core.ObjectHandle, ?*anyopaque) void = undefined, - -pub const PodDataTable: pod.DataTable = .{ - .name = "ComponentRegistration", - .banInstantiation = true, - .toStringOverride = lua.CWrap(toString), -}; - -// I should really move all the registration to this file. -pub fn toString(state: lua.LuaState) i32 { - var workBuffer: [256]u8 = undefined; - const ud = state.toUserdata(@This(), 1).?; - state.pop(1); - const str = std.fmt.bufPrintZ(&workBuffer, "Component Data Table: {s} 0x{x}", .{ ud.name, ud.ref.ptr }) catch return 0; - state.pushString(str) catch return 0; - return 1; -} - -pub fn createComponent(self: @This(), handle: core.ObjectHandle) ?*anyopaque { - const ref = self.ref; - const rv = ref.vtable.createWithHandle(ref.ptr, handle); - // std.debug.print("createComponent: {p}\n", .{rv}); - - return rv; -} - -const lua = @import("lua"); -const ecs = @import("../ecs.zig"); -const std = @import("std"); -const core = @import("../core.zig"); -const pod = lua.pod; diff --git a/engine/core/src/script_bindings.zig b/engine/core/src/script_bindings.zig deleted file mode 100644 index 42cf497..0000000 --- a/engine/core/src/script_bindings.zig +++ /dev/null @@ -1,59 +0,0 @@ -const luaRegLibs: []const lua.c.luaL_Reg = &.{ - .{ .name = "registerTick", .func = lua.CWrap(registerTick) }, - .{ .name = null, .func = null }, -}; - -// register core types and subsystems into the scripting engine -pub fn registerTypes() !void { - // transform POD type - - const state = script.getState(); - try lua.pod.registerPodType(state, core.Vector); - try lua.pod.registerPodType(state, core.Vectorf); - try lua.pod.registerPodType(state, core.Vector2); - try lua.pod.registerPodType(state, core.Vector2f); - // try lua.pod.registerPodType(state, core.Transform); - - // lua.pod.registerPodType(state, core.Vector4, "Vector4"); - try state.createLibrary("Systems", luaRegLibs); -} - -pub fn registerTick(l: lua.LuaState) i32 { - // two arguments first one is going to be userdata entity - // second one is going to be a lua function. - _ = l; - return 0; -} - -pub const ScriptTicks = struct { - allocator: std.mem.Allocator, - - pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "core.ScriptTicks"); - - pub fn init(allocator: std.mem.Allocator) !*@This() { - const self = try allocator.create(@This()); - self.* = .{ - .allocator = allocator, - }; - return self; - } - - pub fn tick(self: *@This(), deltaTime: f64) void { - _ = self; - const state = script.getState(); - _ = state.getGlobal("__TickScripts"); - state.pushNumber(deltaTime); - state.pcallStack(1) catch { - core.engine_logs("could not execute lua script"); - }; - } - - pub fn deinit(self: *@This()) void { - self.allocator.destroy(self); - } -}; - -const lua = @import("lua"); -const std = @import("std"); -const script = @import("script.zig"); -const core = @import("core.zig"); diff --git a/engine/core/src/string_utils.zig b/engine/core/src/string_utils.zig deleted file mode 100644 index 3dbe728..0000000 --- a/engine/core/src/string_utils.zig +++ /dev/null @@ -1,18 +0,0 @@ -const std = @import("std"); - -pub fn dupeZ(comptime T: type, allocator: std.mem.Allocator, source: []const T) ![]T { - var buff: []T = try allocator.alloc(T, source.len + 1); - for (source, 0..source.len) |s, i| { - buff[i] = s; - } - buff[source.len] = 0; - return buff; -} - -pub fn dupe(comptime T: type, allocator: std.mem.Allocator, source: []const T) ![]T { - var buff: []T = try allocator.alloc(T, source.len); - for (source, 0..) |s, i| { - buff[i] = s; - } - return buff; -} diff --git a/engine/core/src/systemsObject.zig b/engine/core/src/systemsObject.zig deleted file mode 100644 index e69de29..0000000 diff --git a/engine/core/src/type_utils.zig b/engine/core/src/type_utils.zig deleted file mode 100644 index 5cbff60..0000000 --- a/engine/core/src/type_utils.zig +++ /dev/null @@ -1,19 +0,0 @@ -const std = @import("std"); - -pub fn implement_func_for_tagged_union_nonull( - self: anytype, - comptime funcName: []const u8, - comptime returnType: type, - args: anytype, -) returnType { - const Self = @TypeOf(self); - inline for (@typeInfo(std.meta.Tag(Self)).Enum.fields) |field| { - if (@as(std.meta.Tag(Self), @enumFromInt(field.value)) == self) { - if (@hasDecl(@TypeOf(@field(self, field.name)), funcName)) { - return @field(@field(self, field.name), funcName)(args); - } - } - } - - unreachable; -} diff --git a/engine/main.zig b/engine/main.zig index 58da28a..6f28d05 100644 --- a/engine/main.zig +++ b/engine/main.zig @@ -46,7 +46,7 @@ pub fn main() !void { core.engine_log("Working Dir set: {s}", .{try std.fs.cwd().realpath(".", &BUFFER)}); } - panickers.attachSegfaultHandler(); + // panickers.attachSegfaultHandler(); try realMain.main(); } diff --git a/engine/platform/src/minidumpsetup.cpp b/engine/platform/src/minidumpsetup.cpp new file mode 100644 index 0000000..ff114d6 --- /dev/null +++ b/engine/platform/src/minidumpsetup.cpp @@ -0,0 +1,78 @@ +// taken from lua 5.1's source code +#include +#include +#include + +bool gTakeFullDump = false; + +void make_minidump(EXCEPTION_POINTERS* e) +{ + auto hDbgHelp = LoadLibraryA("dbghelp"); + if(hDbgHelp == nullptr) + return; + auto pMiniDumpWriteDump = (decltype(&MiniDumpWriteDump))GetProcAddress(hDbgHelp, "MiniDumpWriteDump"); + if(pMiniDumpWriteDump == nullptr) + return; + + + char name[MAX_PATH]; + { + auto nameEnd = name + GetModuleFileNameA(GetModuleHandleA(0), name, MAX_PATH); + SYSTEMTIME t; + GetSystemTime(&t); + wsprintfA(nameEnd - strlen(".exe"), + "_%4d%02d%02d_%02d%02d%02d.dmp", + t.wYear, t.wMonth, t.wDay, t.wHour, t.wMinute, t.wSecond); + printf("creating minidump... %s \n", name); + } + + auto hFile = CreateFileA(name, GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); + if(hFile == INVALID_HANDLE_VALUE) + return; + + MINIDUMP_EXCEPTION_INFORMATION exceptionInfo; + exceptionInfo.ThreadId = GetCurrentThreadId(); + exceptionInfo.ExceptionPointers = e; + exceptionInfo.ClientPointers = FALSE; + + auto dumped = pMiniDumpWriteDump( + GetCurrentProcess(), + GetCurrentProcessId(), + hFile, + gTakeFullDump ? MINIDUMP_TYPE(MiniDumpWithFullMemory | MiniDumpIgnoreInaccessibleMemory| MiniDumpScanMemory | MiniDumpWithIndirectlyReferencedMemory) : MINIDUMP_TYPE(MiniDumpWithIndirectlyReferencedMemory | MiniDumpScanMemory), + e ? &exceptionInfo : nullptr, + nullptr, + nullptr); + + CloseHandle(hFile); + + return; +} + +LONG CALLBACK unhandled_handler(EXCEPTION_POINTERS* e) +{ + make_minidump(e); + return EXCEPTION_CONTINUE_SEARCH; +} + + +extern "C" { + + void takeDump() + { + make_minidump(nullptr); + } + + void setupMiniDump(bool takeFullDump) + { + gTakeFullDump = takeFullDump; + SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)make_minidump); + } + + void generateAnException() + { + const char* str = "Hello"; + char* mutable_str = const_cast(str); + mutable_str[0] = 'h'; // This will cause an access violation + } +} diff --git a/engine/platform/src/minidumpstub.cpp b/engine/platform/src/minidumpstub.cpp new file mode 100644 index 0000000..f9feb55 --- /dev/null +++ b/engine/platform/src/minidumpstub.cpp @@ -0,0 +1,5 @@ +extern "C" { + void setupMiniDump(bool takeFullDump){} + void takeDump(){} + void generateAnException() {} +} diff --git a/engine/platform/src/platform.zig b/engine/platform/src/platform.zig index 9c79c14..237987d 100644 --- a/engine/platform/src/platform.zig +++ b/engine/platform/src/platform.zig @@ -4,10 +4,15 @@ const test_vert = @import("test.vert"); pub const nfd = @import("nfd"); pub const file_dialogue = @import("file_dialogue.zig"); +const watcher = @import("watcher"); // controls glfw and general windowing // graphics depends on this one +pub extern fn setupMiniDump(takeFullDump: bool) callconv(.c) void; +pub extern fn generateAnException() callconv(.c) void; +pub extern fn takeDump() callconv(.c) void; + pub const windowing = @import("windowing.zig"); pub const Module: core.ModuleDescription = .{ @@ -49,6 +54,33 @@ pub fn getMouseVisible() bool { gPlatformInstance.isCursorEnabled(); } +pub fn watchPath(path: []const u8) void { + watchPathPacker(core.fs(), path) catch { + core.engine_log("unable to set up watch on path", .{path}); + }; +} + +fn watchPathPacker(self: *core.PackerFS, path: []const u8) !void { + // std.debug.print("self = {x}\n", .{@intFromPtr(self)}); + + std.fs.cwd().access(path, .{}) catch return; + // check the path exists before attempting to watch + + const p = self.stringArena.allocator().dupeZ(u8, path) catch return; + const watch = watcher.createWatchPoint( + p, + core.PackerFS.watchCallback, + self, + ) orelse { + return error.UnableToWatch; + }; + _ = watch; +} + +pub fn watchModules() void { + watchPath("zig-out/modules/"); +} + pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.mem.Allocator) !void { _ = args; _ = spec; @@ -57,6 +89,8 @@ pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.me return; } + core.getModuleLoader().watchInitializedFn = watchModules; + const parameters = windowing.PlatformParams.init(); gPlatformInstance = try core.createObject(windowing.PlatformInstance, .{}); //try allocator.create(windowing.PlatformInstance); diff --git a/engine/rend/build.zig b/engine/rend/build.zig index 01b28d7..a29c7be 100644 --- a/engine/rend/build.zig +++ b/engine/rend/build.zig @@ -5,6 +5,7 @@ const dependencyList = [_][]const u8{ "core", "assets", "sdl3", + "spng", "platform", "sys", "shaderTypes", diff --git a/engine/rend/build.zig.zon b/engine/rend/build.zig.zon index fd916b9..74f672f 100644 --- a/engine/rend/build.zig.zon +++ b/engine/rend/build.zig.zon @@ -12,6 +12,8 @@ .shaderTypes = .{ .path = "../../lib/sdl3/shaderTypes" }, .zgltf = .{ .path = "../../lib/zgltf" }, .objLoader = .{ .path = "../../lib/objLoader" }, + + .spng = .{ .path = "../../lib/spng" }, }, .paths = .{ "", diff --git a/engine/core/src/png.zig b/engine/rend/src/png.zig similarity index 98% rename from engine/core/src/png.zig rename to engine/rend/src/png.zig index 1273092..1b5a5d7 100644 --- a/engine/core/src/png.zig +++ b/engine/rend/src/png.zig @@ -2,7 +2,7 @@ const std = @import("std"); const spng = @import("spng"); -const core = @import("core.zig"); +const core = @import("core"); pub const PngContents = struct { path: []const u8, diff --git a/engine/rend/src/rend.zig b/engine/rend/src/rend.zig index cdc8cbf..eceaf5d 100644 --- a/engine/rend/src/rend.zig +++ b/engine/rend/src/rend.zig @@ -20,6 +20,9 @@ pub const renderer = @import("sgpu/renderer.zig"); pub const context = renderer.context; // context getter func pub const Renderer = renderer.Renderer; +pub const spng = @import("spng"); +pub const png = @import("png.zig"); + pub const MeshPool = renderer.MeshPool; pub const getMesh = renderer.getMesh; diff --git a/engine/rend/src/sgpu/DebugDrawSystem.zig b/engine/rend/src/sgpu/DebugDrawSystem.zig index 20be271..2d19170 100644 --- a/engine/rend/src/sgpu/DebugDrawSystem.zig +++ b/engine/rend/src/sgpu/DebugDrawSystem.zig @@ -323,8 +323,6 @@ pub const DebugPrimitive = struct { }, } unreachable; - - // return core.implement_func_for_tagged_union_nonull(self.primitive, "resolve", core.Transform, .{}); } }; diff --git a/engine/rend/src/sgpu/TextureList.zig b/engine/rend/src/sgpu/TextureList.zig index 9d41849..28b1375 100644 --- a/engine/rend/src/sgpu/TextureList.zig +++ b/engine/rend/src/sgpu/TextureList.zig @@ -65,7 +65,7 @@ pub fn uploadCubeFromPaths(self: *@This(), name: core.Name, paths: []const []con return error.CubeNeedsSixFaces; } - var cubeList = std.ArrayList(core.png.PngContents){}; //std.ArrayList(core.png.PngContents).init(self.allocator); + var cubeList = std.ArrayList(rend.png.PngContents){}; defer cubeList.deinit(self.allocator); var gpuTexture: *gpu.GPUTexture = undefined; @@ -262,7 +262,7 @@ pub fn uploadTextureFromBytes(self: *@This(), name: *core.Name, opts: UploadText } pub fn uploadTextureFromPath(self: *@This(), name: core.Name, path: []const u8) !*Texture { - var png = try core.png.PngContents.initFromFS(core.fs(), self.allocator, path); + var png = try rend.png.PngContents.initFromFS(core.fs(), self.allocator, path); defer png.deinit(); const cmd = self.device.acquireGPUCommandBuffer(); diff --git a/lib/filewatch/build.zig b/lib/filewatch/build.zig new file mode 100644 index 0000000..dd3fcb4 --- /dev/null +++ b/lib/filewatch/build.zig @@ -0,0 +1,40 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const static_build = b.option(bool, "static_build", "builds backlog dependencies for static linking") orelse false; + _ = static_build; + + const mod = b.addModule("watcher", .{ + .target = target, + .optimize = optimize, + .root_source_file = b.path("src/watcher.zig"), + .link_libc = true, + .link_libcpp = true, + }); + + mod.addCSourceFile(.{ .file = b.path("src/watcher.cpp") }); + + if (target.result.os.tag == .macos) { + mod.linkFramework("CoreFoundation", .{}); + mod.linkFramework("CoreServices", .{}); + } + + mod.addIncludePath(b.path("src/include")); + + const test_exe = b.addTest(.{ + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + .root_source_file = b.path("tests/test.zig"), + }), + }); + test_exe.root_module.addImport("watcher", mod); + + const test_step = b.step("test", "runs sample unit tests for watcher"); + test_step.dependOn(&b.addRunArtifact(test_exe).step); + + b.installArtifact(test_exe); +} diff --git a/lib/filewatch/build.zig.zon b/lib/filewatch/build.zig.zon new file mode 100644 index 0000000..cf152e6 --- /dev/null +++ b/lib/filewatch/build.zig.zon @@ -0,0 +1,9 @@ +.{ + .name = .filewatch, + .version = "0.0.0", + .dependencies = .{}, + .paths = .{ + "", + }, + .fingerprint = 0x84d25253a649dc52, +} diff --git a/lib/packer/src/include/FileWatch.hpp b/lib/filewatch/src/include/FileWatch.hpp similarity index 100% rename from lib/packer/src/include/FileWatch.hpp rename to lib/filewatch/src/include/FileWatch.hpp diff --git a/lib/packer/src/watcher.cpp b/lib/filewatch/src/watcher.cpp similarity index 100% rename from lib/packer/src/watcher.cpp rename to lib/filewatch/src/watcher.cpp diff --git a/lib/packer/src/watcher.zig b/lib/filewatch/src/watcher.zig similarity index 100% rename from lib/packer/src/watcher.zig rename to lib/filewatch/src/watcher.zig diff --git a/lib/filewatch/src/watcherstub.cpp b/lib/filewatch/src/watcherstub.cpp new file mode 100644 index 0000000..03c0eca --- /dev/null +++ b/lib/filewatch/src/watcherstub.cpp @@ -0,0 +1,7 @@ +extern "C" void* createWatchPoint( + const char* watchPath, + void(*cb)(const char*, void*), + void* ctx +){ + return nullptr; +} diff --git a/lib/filewatch/tests/test.zig b/lib/filewatch/tests/test.zig new file mode 100644 index 0000000..c02c483 --- /dev/null +++ b/lib/filewatch/tests/test.zig @@ -0,0 +1,3 @@ +const watcher = @import("watcher"); + +test "compile test" {} diff --git a/lib/lua/src/minidumpsetup.cpp b/lib/lua/src/minidumpsetup.cpp index a54203e..ff114d6 100644 --- a/lib/lua/src/minidumpsetup.cpp +++ b/lib/lua/src/minidumpsetup.cpp @@ -1,3 +1,4 @@ +// taken from lua 5.1's source code #include #include #include diff --git a/lib/p2/src/structures/pscopes.zig b/lib/p2/src/structures/pscopes.zig index 81087ab..1914f96 100644 --- a/lib/p2/src/structures/pscopes.zig +++ b/lib/p2/src/structures/pscopes.zig @@ -59,7 +59,7 @@ pub const TimingScope = struct { pub inline fn init(c: *ScopesContext) @This() { return .{ - .startTsc = rdtsc(), + .startTsc = timestampTicks(), .context = c, }; } @@ -76,7 +76,7 @@ pub const TimingScope = struct { } pub inline fn end(self: *@This()) void { - self.endTsc = rdtsc(); + self.endTsc = timestampTicks(); } }; diff --git a/lib/packer/build.zig b/lib/packer/build.zig index 907ff74..eeb7ee2 100644 --- a/lib/packer/build.zig +++ b/lib/packer/build.zig @@ -12,13 +12,8 @@ pub fn build(b: *std.Build) void { .target = target, .optimize = optimize, .root_source_file = b.path("src/packer.zig"), - .link_libc = true, - .link_libcpp = true, }); - mod.addIncludePath(b.path("src/include")); - mod.addCSourceFile(.{ .file = b.path("src/watcher.cpp"), .flags = &.{} }); - const p2mod = p2dep.module("p2"); mod.addImport("p2", p2mod); @@ -27,7 +22,6 @@ pub fn build(b: *std.Build) void { .target = target, .optimize = optimize, .root_source_file = b.path("tests/test.zig"), - // .link_libc = true, }), }); test_exe.root_module.addImport("packer", mod); diff --git a/lib/packer/src/packerfs.zig b/lib/packer/src/packerfs.zig index 44f3480..fc96657 100644 --- a/lib/packer/src/packerfs.zig +++ b/lib/packer/src/packerfs.zig @@ -178,24 +178,6 @@ pub const PackerFS = struct { } } - pub fn watchPath(self: *@This(), path: []const u8) void { - // std.debug.print("self = {x}\n", .{@intFromPtr(self)}); - - // check the path exists before attempting to watch - std.fs.cwd().access(path, .{}) catch return; - - const p = self.stringArena.allocator().dupeZ(u8, path) catch return; - const watch = watcher.createWatchPoint( - p, - watchCallback, - self, - ) orelse { - std.debug.print("Unable to create watch point, {s}\n", .{p}); - return; - }; - _ = watch; - } - // todo: implement load memory to file then-map setup. // for systems which do not support mmap @@ -525,5 +507,3 @@ pub const PackerFS = struct { return .{ .allocator = allocator, .data = rv, .sources = sourcePath }; } }; - -const watcher = @import("watcher.zig");