moving nfd and lua and a sdl out of core

This commit is contained in:
peterino2 2025-10-09 21:00:43 -07:00
parent 6a0a533e0a
commit d89915ee4e
25 changed files with 202 additions and 122 deletions

View File

@ -579,7 +579,13 @@ pub fn build(b: *std.Build) void {
}
pub fn generateApi(self: *@This(), programName: []const u8, moduleList: []const []const u8, dynamicModules: ?[]const *DynamicModule) *std.Build.Module {
// std.debug.print("GENERATE API:: {s}\n\n", .{programName});
// std.debug.print("GENERATE API:: {s}\n", .{programName});
for (moduleList) |mod| {
_ = mod;
// std.debug.print("{s}\n", .{mod});
}
//
if (self.generatedApis.get(programName)) |m| {
return m;
}

View File

@ -4,11 +4,12 @@ const dependencyList = [_][]const u8{
"p2",
"tracy",
"zmath",
"packer",
"sdl3",
"lua",
"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",
// "nfd",
};
pub fn build(b: *std.Build) void {

View File

@ -3,13 +3,15 @@
.version = "0.0.0",
.dependencies = .{
.spng = .{ .path = "../../lib/spng" },
.nfd = .{ .path = "../../lib/nfd" },
.p2 = .{ .path = "../../lib/p2" },
// .nfd = .{ .path = "../../lib/nfd" },
// with -Dtracy = false, this one pulls in no C dependencies
.tracy = .{ .path = "../../lib/tracy" },
// these are zig only
.zmath = .{ .path = "../../lib/zmath" },
.packer = .{ .path = "../../lib/packer" },
.lua = .{ .path = "../../lib/lua" },
.sdl3 = .{.path = "../../lib/sdl3"},
.p2 = .{ .path = "../../lib/p2" },
// .zgltf = .{ .path = "../../lib/zgltf" },
},
.paths = .{

View File

@ -24,7 +24,7 @@ pub const debugSphere = debug_draw.debugSphere;
pub const debugSphereTransform = debug_draw.debugSphereTransform;
pub const debugBox = debug_draw.debugBox;
pub const debugLine = debug_draw.debugLine;
pub const script_bindings = script.script_bindings;
// pub const script_bindings = script.script_bindings;
pub const engineObject = @import("engineObject.zig");
@ -47,10 +47,8 @@ pub const zgltf = @import("zgltf");
pub const zm = @import("zmath");
pub usingnamespace @import("p2");
pub const algorithm = @import("p2");
pub const nfd = @import("nfd");
pub usingnamespace @import("math.zig");
pub usingnamespace @import("args.zig");
pub usingnamespace @import("file_dialogue.zig");
pub const panickers = @import("panickers.zig");
pub const scene = @import("scene.zig");
@ -113,7 +111,7 @@ pub const ModuleLoaderArgs = externModule.ModuleLoaderArgs;
pub const ecs = @import("ecs.zig");
pub usingnamespace ecs;
pub const script = @import("script.zig");
// pub const script = @import("script.zig");
pub const stacks = @import("stacks.zig");
pub const walkAndPrintStack = stacks.walkAndPrintStack;
@ -191,10 +189,10 @@ pub fn start_module_(map: *SpecVariantMap, args: anytype, allocator: std.mem.All
fatDump = true;
}
script.lua.setupMiniDump(fatDump);
// 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);
// try script.start_lua(allocator);
// LUA END
try maybeInitPackerFs(allocator);
@ -226,7 +224,7 @@ 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 gEngine.createObject(script_bindings.ScriptTicks, .{ .can_tick = true });
_ = try createObject(GameObjectSystem, .{ .can_tick = true });
_ = try inputs.initInputStack();
@ -240,7 +238,7 @@ 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);
// script.setupLuaFromModule(__args.luaState, __args.luaAllocator);
algorithm.names.gRegistry = __args.nameRegistry;
logging.setupLoggingFromModule();
staticsInitialized = true;
@ -266,7 +264,7 @@ pub fn shutdown_module(_: std.mem.Allocator) void {
gEngine.deinit();
gPackerFS.destroy();
// LUA BEGIN
script.shutdown_lua();
// script.shutdown_lua();
// LUA END
console.shutdown();
algorithm.string_pool.shutdown();

View File

@ -146,12 +146,13 @@ pub fn CreateEntity_Lua(state: lua.LuaState) i32 {
}
pub fn setup(allocator: std.mem.Allocator) !void {
try ComponentRef.setupFormatBuffer(allocator);
_ = allocator;
// try ComponentRef.setupFormatBuffer(allocator);
_ = try core.createObject(EcsRegistry, .{ .can_tick = true, .isCore = true });
}
pub fn shutdown() void {
ComponentRef.shutdownFormatBuffer();
// ComponentRef.shutdownFormatBuffer();
}
pub const getRegistry = core.EngineObject(EcsRegistry).get;
@ -329,7 +330,7 @@ pub fn defineComponent(comptime Component: type, allocator: std.mem.Allocator) !
const container = makeEcsContainerRef(Component.BaseContainer);
try registerEcsContainer(container, core.MakeName(Component.ComponentName));
try script.registerComponent(Component, container);
// try script.registerComponent(Component, container);
}
pub fn undefineComponent(comptime Component: type) void {
@ -403,19 +404,19 @@ pub const Entity = struct {
return 0;
}
if (state.toUserdata(@This(), 1)) |self| {
if (state.toUserdata(ComponentRegistration, 2)) |componentRegistration| {
// core.engine_log("component Registration: name: {s}", .{componentRegistration.name});
// if (state.toUserdata(@This(), 1)) |self| {
// if (state.toUserdata(ComponentRegistration, 2)) |componentRegistration| {
// // core.engine_log("component Registration: name: {s}", .{componentRegistration.name});
// create the zig version of the component
const comp = componentRegistration.createComponent(self.handle);
// // create the zig version of the component
// const comp = componentRegistration.createComponent(self.handle);
// call luaNew on ComponentReferenceType
// create the lua binding for the component
// this pushes one onto the stack
componentRegistration.luaNew(state, self.handle, comp);
}
}
// // call luaNew on ComponentReferenceType
// // create the lua binding for the component
// // this pushes one onto the stack
// componentRegistration.luaNew(state, self.handle, comp);
// }
// }
return 1;
}
@ -469,9 +470,9 @@ pub const EcsSystemInterface = p2.MakeInterface("EcsSystemVTable", struct {
}
});
const ComponentRegistration = @import("script/ComponentRegistration.zig");
const ComponentRef = @import("script/ComponentRef.zig");
const script = @import("script.zig");
// const ComponentRegistration = @import("script/ComponentRegistration.zig");
// const ComponentRef = @import("script/ComponentRef.zig");
// const script = @import("script.zig");
const std = @import("std");
const p2 = @import("p2");
const core = @import("core.zig");

View File

@ -82,8 +82,6 @@ pub const Engine = struct {
engineStartTime: f64 = 0,
sessionStamp: i64 = 0,
nfdRuntime: *nfd.NFDRuntime,
delegates: EngineDelegates,
first: bool = true,
@ -100,7 +98,7 @@ pub const Engine = struct {
.eventors = .{},
.frameNumber = 1,
.exitListeners = .{},
.nfdRuntime = try nfd.NFDRuntime.create(allocator, .{}),
// .nfdRuntime = try nfd.NFDRuntime.create(allocator, .{}),
.delegates = EngineDelegates.init(allocator),
};
@ -139,7 +137,7 @@ pub const Engine = struct {
self.prepares.deinit(self.allocator);
self.tickables.deinit(self.allocator);
self.preTickables.deinit(self.allocator);
self.nfdRuntime.destroy();
// self.nfdRuntime.destroy();
self.delegates.deinit();
core.engine_logs("calling onexit listeners");
@ -276,8 +274,6 @@ pub const Engine = struct {
objectRef.vtable.processEvents.?(objectRef.ptr, self.frameNumber) catch @panic("process event error");
}
self.nfdRuntime.processCallbacks();
var z4 = tracy.ZoneN(@src(), "pretick event updates");
for (self.preTickables.items) |*objectRef| {
objectRef.vtable.preTick_func.?(objectRef.ptr, self.deltaTime) catch @panic("pretick event error");
@ -364,7 +360,10 @@ pub const Engine = struct {
while (true) {
self.tick() catch unreachable;
self.jobManager.bump();
try self.nfdRuntime.processMessages();
// try self.nfdRuntime.processMessages();
if (self.platformPollFunc) |func| {
try func(self.platformCtx);
}
if (!exitSignaled and self.exitSignal.load(.seq_cst)) {
exitSignaled = true;

View File

@ -11,8 +11,8 @@ pub const ModuleLoaderArgs = extern struct {
engine: *core.Engine,
nameRegistry: *p2.NameRegistry,
packerFS: *core.PackerFS,
luaState: *anyopaque,
luaAllocator: *anyopaque,
// luaState: *anyopaque,
// luaAllocator: *anyopaque,
debugDrawInterface: *debug.DebugDrawInterface,
};
@ -223,8 +223,8 @@ pub fn getModuleLoaderArgs(first: bool) ModuleLoaderArgs {
.engine = core.getEngine(),
.nameRegistry = core.names.gRegistry,
.packerFS = core.fs(),
.luaState = @ptrCast(core.script.gLuaState.l),
.luaAllocator = &core.script.gLuaAllocator,
// .luaState = @ptrCast(core.script.gLuaState.l),
// .luaAllocator = &core.script.gLuaAllocator,
.debugDrawInterface = debug.gDebugDrawInterface.?,
};
}

View File

@ -6,49 +6,6 @@ pub const BindingType = enum(u8) {
const glfw_release = 0;
pub fn convertEvent(event: *const sdl3.Event) ?IOEvent {
switch (event.type) {
sdl3.events.key_down, sdl3.events.key_up => {
const scan: Key = @enumFromInt(event.key.scancode);
if (event.key.repeat) {
return null;
}
return IOEvent{
.key = .{
.key = scan,
.scancode = scan,
.action = if (event.key.down) .keyDown else .keyUp,
.mods = 0,
},
};
},
sdl3.events.mouse_button_down, sdl3.events.mouse_button_up => {
const scan: Key = @enumFromInt(@as(u32, @intCast(event.button.button)) + 10000);
return IOEvent{
.key = .{
.key = scan,
.scancode = scan,
.action = if (event.button.down) .keyDown else .keyUp,
.mods = 0,
},
};
},
sdl3.events.mouse_motion => {
const motion = core.Vector2f{ .x = event.motion.xrel, .y = event.motion.yrel };
return .{ .mouseRelative = motion };
},
else => {
return null;
},
}
return null;
}
pub const IOEvent = union(enum(u8)) {
windowFocused: struct { focused: c_int },
mousePosition: struct { x: f64, y: f64 },
@ -791,6 +748,5 @@ const lua = core.lua;
const pod = lua.pod;
pub const Key = @import("keys.zig").Key;
const sdl3 = @import("sdl3");
const std = @import("std");
const core = @import("../core.zig");

5
engine/dynamicMain.zig Normal file
View File

@ -0,0 +1,5 @@
// ok this is a new experiment,
// we basically have a near empty main.exe
// that launches the game as a dll by calling
pub fn main() !void {}

View File

@ -49,3 +49,11 @@ pub fn main() !void {
panickers.attachSegfaultHandler();
try realMain.main();
}
pub export fn start_engine_main() bool {
std.debug.print("launching from extern function", .{});
main() catch return false;
return true;
}

View File

@ -1 +0,0 @@
pub const module = @import("module");

View File

@ -1,18 +0,0 @@
pub const SpecVariantMap = std.StringHashMap(SpecVariant);
pub const SpecVariant = union(enum(u8)) {
boolean: bool,
string: []const u8,
};
pub fn start_module(map: *SpecVariantMap, args: anytype, allocator: std.mem.Allocator) !void {
_ = map;
_ = args;
_ = allocator;
std.debug.print("Module init stub. this should never be called");
}
pub fn shutdown_module(_: std.mem.Allocator) void {}
const std = @import("std");

View File

View File

@ -4,6 +4,7 @@ const sdl3 = @import("sdl3");
const dependencyList = [_][]const u8{
"core",
"sdl3",
"nfd",
};
pub fn build(b: *std.Build) void {

View File

@ -4,6 +4,7 @@
.dependencies = .{
.core = .{ .path = "../core" },
.sdl3 = .{ .path = "../../lib/sdl3" },
.nfd = .{ .path = "../../lib/nfd" },
.shaderTypes = .{ .path = "../../lib/sdl3/shaderTypes" },
},
.paths = .{

View File

@ -1,21 +1,21 @@
const std = @import("std");
const core = @import("core.zig");
const platform = @import("platform.zig");
const nfd = @import("nfd");
pub const AsyncOpenFileDialogArgs = nfd.AsyncOpenFileDialogArgs;
pub fn openFileDialog(defaultPath: []const u8, filters: []const u8) ![*c]const u8 {
return try core.getEngine().nfdRuntime.openFileDialog(defaultPath, filters);
return try platform.context().nfdRuntime.openFileDialog(defaultPath, filters);
}
pub fn openFolderDialog(defaultPath: []const u8, context: ?*anyopaque) ![*c]const u8 {
return try core.getEngine().nfdRuntime.openFolderDialog(defaultPath, context);
return try platform.context().nfdRuntime.openFolderDialog(defaultPath, context);
}
pub fn asyncOpenFile(args: AsyncOpenFileDialogArgs) !void {
return try core.getEngine().nfdRuntime.asyncOpenFileDialog(args);
return try platform.context().nfdRuntime.asyncOpenFileDialog(args);
}
pub fn asyncOpenFolder(args: AsyncOpenFileDialogArgs) !void {
return try core.getEngine().nfdRuntime.asyncOpenFolderDialog(args);
return try platform.context().nfdRuntime.asyncOpenFolderDialog(args);
}

View File

@ -2,6 +2,9 @@ const std = @import("std");
const core = @import("core");
const test_vert = @import("test.vert");
pub const nfd = @import("nfd");
pub const file_dialogue = @import("file_dialogue.zig");
// controls glfw and general windowing
// graphics depends on this one

View File

@ -2,6 +2,8 @@ const std = @import("std");
const core = @import("core");
const platform = @import("platform.zig");
const nfd = @import("nfd");
const RingQueue = core.RingQueue;
pub const sdl3 = @import("sdl3");
const tracy = core.tracy;
@ -10,6 +12,49 @@ pub const InputListenerError = error{
UnknownError,
};
pub fn convertEvent(event: *const sdl3.Event) ?core.inputs.IOEvent {
switch (event.type) {
sdl3.events.key_down, sdl3.events.key_up => {
const scan: core.inputs.Key = @enumFromInt(event.key.scancode);
if (event.key.repeat) {
return null;
}
return IOEvent{
.key = .{
.key = scan,
.scancode = scan,
.action = if (event.key.down) .keyDown else .keyUp,
.mods = 0,
},
};
},
sdl3.events.mouse_button_down, sdl3.events.mouse_button_up => {
const scan: core.inputs.Key = @enumFromInt(@as(u32, @intCast(event.button.button)) + 10000);
return IOEvent{
.key = .{
.key = scan,
.scancode = scan,
.action = if (event.button.down) .keyDown else .keyUp,
.mods = 0,
},
};
},
sdl3.events.mouse_motion => {
const motion = core.Vector2f{ .x = event.motion.xrel, .y = event.motion.yrel };
return .{ .mouseRelative = motion };
},
else => {
return null;
},
}
return null;
}
pub const RawInputListenerInterface = struct {
// required functions
@ -94,6 +139,8 @@ pub const PlatformInstance = struct {
cursorPos: core.Vector2f = .{},
nfdRuntime: *nfd.NFDRuntime,
pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "platform.Instance");
pub const PlatformRequest = union(enum(u32)) {
@ -140,6 +187,7 @@ pub const PlatformInstance = struct {
pub fn deinit(self: *@This()) void {
self.allocator.free(self.windowName);
self.nfdRuntime.destroy();
self.allocator.free(self.iconPath);
self.processFuncs.deinit(self.allocator);
self.platformRequests.deinit(self.allocator);
@ -162,6 +210,7 @@ pub const PlatformInstance = struct {
const self = try allocator.create(@This());
self.* = .{
.allocator = allocator,
.nfdRuntime = try nfd.NFDRuntime.create(allocator, .{}),
//.windowName = try allocator.dupeZ(u8, params.windowName),
//.iconPath = try allocator.dupeZ(u8, params.icon),
//.windowExtent = params.extent,
@ -210,7 +259,8 @@ pub const PlatformInstance = struct {
// runs pinned on io thread.
// old glfw needed to do it's polling here.
pub fn enginePoll(opaqueSelf: *anyopaque) core.EngineDataEventError!void {
_ = opaqueSelf;
const self = core.cast(*@This(), opaqueSelf);
self.nfdRuntime.processMessages() catch {};
// this polling event should probably be used for IO, now that we have a free thread for doing w.e
// var self: *@This() = @alignCast(@ptrCast(opaqueSelf));
// self.pollEvents();
@ -228,6 +278,8 @@ pub const PlatformInstance = struct {
_ = frameNumber;
const self: *@This() = @ptrCast(@alignCast(ptr));
self.nfdRuntime.processCallbacks();
self.handlePlatformRequests();
// const self: *@This() = @ptrCast(@alignCast(ptr));
@ -251,7 +303,7 @@ pub const PlatformInstance = struct {
func(@ptrCast(event));
}
if (core.inputs.convertEvent(event)) |converted| {
if (convertEvent(event)) |converted| {
var shouldSkip: bool = false;
if (self.imguiMouseConsumed and (event.type == sdl3.events.mouse_button_down or event.type == sdl3.events.mouse_button_up)) {
shouldSkip = true;

View File

@ -0,0 +1,10 @@
# headless renderer
where sgpu is a renderer implemented for sdl_gpu
headless renderer is a renderer meant to stub out all operations, resources are still created but only their headers are created and their contents are not available.
eg IndexedMesh will still be available, and so will *Textures. but... no texture data will ever be loaded.
mesh and animation data may still be loaded.
no gpu or transfer buffers will ever be constructed.

5
lib/p2/build.zig vendored
View File

@ -3,7 +3,7 @@ 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 unreachable;
const static_build = b.option(bool, "static_build", "builds backlog dependencies for static linking") orelse true;
_ = static_build;
const mod = b.addModule("p2", .{
@ -17,7 +17,7 @@ pub fn build(b: *std.Build) void {
.target = target,
.optimize = optimize,
.root_source_file = b.path("src/p2.zig"),
.link_libc = true,
// .link_libc = true,
});
tests.root_module.addImport("p2", mod);
@ -26,4 +26,5 @@ pub fn build(b: *std.Build) void {
if (b.args) |args| {
runArtifact.addArgs(args);
}
b.installArtifact(tests);
}

View File

@ -99,6 +99,8 @@ pub const NameRegistry = struct {
pub var gRegistry: *NameRegistry = undefined;
var registryCreated: bool = false;
pub var gStringArena: std.heap.ArenaAllocator = undefined;
pub fn createNameRegistry(allocator: std.mem.Allocator) !*NameRegistry {
if (!registryCreated) {
gRegistry = try allocator.create(NameRegistry);
@ -117,8 +119,9 @@ pub fn getRegistry() *NameRegistry {
// specifically in the case of unittests we can silently just initialize a temporary registry
if (builtin.is_test) {
if (!registryCreated) {
gStringArena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
// leaking here is fine? might piss off valgrind
_ = createNameRegistry(std.heap.c_allocator) catch unreachable;
_ = createNameRegistry(gStringArena.allocator()) catch unreachable;
}
}
@ -129,6 +132,7 @@ pub fn destroyNameRegistry() void {
var allocator = gRegistry.allocator;
gRegistry.deinit();
allocator.destroy(gRegistry);
gStringArena.deinit();
}
pub fn DefineName(comptime string: []const u8) Name {

View File

@ -26,11 +26,13 @@ pub fn build(b: *std.Build) void {
.target = target,
.optimize = optimize,
.root_source_file = b.path("tests/test.zig"),
.link_libc = true,
// .link_libc = true,
});
test_exe.root_module.addImport("packer", mod);
test_exe.root_module.addImport("p2", p2mod);
const test_step = b.step("test", "runs sample unit tests for packer");
test_step.dependOn(&b.addRunArtifact(test_exe).step);
b.installArtifact(test_exe);
}

View File

@ -71,5 +71,17 @@ pub fn build(b: *std.Build) void {
});
}
const headless = blbuild.program(.{
.name = "headless",
.desc = "headless program, core-only",
.root_source_file = b.path("headless/main.zig"),
});
headless.setModuleEnabled("assets", false);
headless.setModuleEnabled("platform", false);
headless.setModuleEnabled("rend", false);
_ = headless.compileInstall();
blbuild.addDependencyInstalls(b, .ReleaseFast); //.ReleaseFast);
}

View File

@ -0,0 +1,36 @@
allocator: std.mem.Allocator = undefined,
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "Headless");
pub fn create(allocator: std.mem.Allocator) !*@This() {
const self = try allocator.create(@This());
self.* = .{
.allocator = allocator,
};
return self;
}
pub fn prepare(self: *@This()) !void {
_ = self;
}
pub fn tick(self: *@This(), dt: f64) void {
_ = self;
_ = dt;
core.exitNow();
}
pub fn deinit(self: *@This()) void {
self.allocator.destroy(self);
}
pub fn main() anyerror!void {
var spec = try backlog.getSpec("headless");
// try spec.put("useGPA", .{ .boolean = false });
_ = backlog.startEngine(&NeonObjectTable, &spec);
}
const std = @import("std");
const backlog = @import("backlog");
const core = backlog.core;

View File

@ -109,7 +109,7 @@ pub fn tick(self: *@This(), dt: f64) void {
if (ig.button("...", .{})) {
core.engine_log("opening NFD", .{});
core.asyncOpenFolder(.{
platform.file_dialogue.asyncOpenFolder(.{
.callback = onFolderSelected,
.callbackContext = self,
}) catch @panic(" unable to open dialog");
@ -516,5 +516,6 @@ const builtin = @import("builtin");
const std = @import("std");
const api = @import("backlog");
const ig = api.imgui.api;
const platform = api.platform;
const core = api.core;
const sys = api.sys;