adding sys module

This commit is contained in:
peterino2 2025-06-15 20:43:17 -07:00
parent b35d5405cb
commit dedb811c29
12 changed files with 347 additions and 22 deletions

View File

@ -545,7 +545,7 @@ 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\n", .{programName});
if (self.generatedApis.get(programName)) |m| {
return m;
}

View File

@ -41,6 +41,12 @@ pub fn main() !void {
\\ const args = core.externModule.getModuleLoaderArgs(true);
);
if (modlist.len == 0) {
_ = try writer.write(
\\ _ = args;
);
}
for (modlist) |mod| {
try writer.print("try {s}.start_module(args);\n", .{mod});
}
@ -65,7 +71,7 @@ pub fn main() !void {
var ast = try std.zig.Ast.parse(allocator, @as([:0]const u8, @ptrCast(content.items[0 .. content.items.len - 1])), .zig);
std.debug.print("output=\n{s}", .{content.items[0 .. content.items.len - 1]});
// std.debug.print("output=\n{s}", .{content.items[0 .. content.items.len - 1]});
defer ast.deinit(allocator);
const out = try ast.render(allocator);

37
engine/sys/build.zig Normal file
View File

@ -0,0 +1,37 @@
const std = @import("std");
const sdl3 = @import("sdl3");
const dependencyList = [_][]const u8{
"core",
};
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;
const mod = b.addModule("sys", .{
.target = target,
.optimize = optimize,
.root_source_file = b.path("src/sys.zig"),
});
for (dependencyList) |depName| {
const dep = b.dependency(depName, .{ .target = target, .optimize = optimize, .static_build = static_build });
const dep_mod = dep.module(depName);
mod.addImport(depName, dep_mod);
}
// ========== tests ==========
const tests = b.addTest(.{
.target = target,
.optimize = optimize,
.root_source_file = b.path("tests/tests.zig"),
});
const test_step = b.step("test", "run unit tests for ui");
tests.root_module.addImport("sys", mod);
const runArtifact = b.addRunArtifact(tests);
test_step.dependOn(&runArtifact.step);
b.installArtifact(tests);
}

16
engine/sys/build.zig.zon Normal file
View File

@ -0,0 +1,16 @@
.{
.name = .ui,
.version = "0.0.0",
.dependencies = .{
.core = .{ .path = "../core" },
.platform = .{ .path = "../platform" },
.papyrus = .{ .path = "../papyrus" },
.rend = .{ .path = "../rend" },
.sdl3 = .{ .path = "../../lib/sdl3" },
.shaderTypes = .{ .path = "../../lib/sdl3/shaderTypes" },
},
.paths = .{
"",
},
.fingerprint = 0x27ff46b0db01e0ab,
}

View File

@ -0,0 +1,137 @@
pub const SystemTaskRunner = struct {
allocator: std.mem.Allocator,
jobs: std.ArrayListUnmanaged(*SystemTask),
pub fn create(allocator: std.mem.Allocator) *@This() {
const self = allocator.create(@This());
self.* = .{
.allocator = allocator,
};
const Job = struct {
ctx: *SystemTaskRunner,
pub fn func(ctx: @This(), job: *core.JobContext) void {
_ = job;
_ = ctx;
while (true) {
// pump events
// if nothing pumped this frame, wait 100ms
}
}
};
try core.dispatchJob(Job{ .ctx = self });
return self;
}
pub fn pushJob(self: *@This()) !*SystemTask {
const task = try self.allocator.create(SystemTask);
try self.jobs.append(self.allocator, task);
}
// check completion from the task thread
pub fn checkCompletionTT(self: *@This()) bool {
if (builtin.os.tag == .windows) {
_ = self;
}
}
pub fn destroy(self: *@This()) void {
self.allocator.destroy(self);
}
};
pub const SystemTask = struct {
status: ExecutionStatus,
taskRunner: *SystemTaskRunner,
};
pub const ExecutionStatus = enum {
ready,
failed,
success,
};
pub const Execution = struct {
mutex: std.Thread.Mutex = .{},
status: ExecutionStatus = .ready,
payload: ?*anyopaque = null,
command: std.ArrayListUnmanaged([]const u8) = .{},
outputStream: std.ArrayListUnmanaged(u8) = .{},
backing: std.mem.Allocator,
arena: std.heap.ArenaAllocator,
child: ?std.process.Child,
lastUpdateTime: i64 = 0,
timeout: i64 = 1000000000,
pub fn startAlloc(allocator: std.mem.Allocator, command: []const []const u8) !*@This() {
const self = try allocator.create(@This());
self.* = .{
.command = undefined,
.backing = allocator,
.arena = std.heap.ArenaAllocator.init(allocator),
};
const alloc = self.arena.allocator();
for (command) |arg| {
const a = try alloc.dupe(u8, arg);
try self.command.append(alloc, a);
}
return self;
}
pub fn run(self: *@This()) void {
self.child = std.process.Child.init(self.command.items, self.arena.allocator());
self.child.?.spawn();
}
pub fn clearOutputStream(self: *@This()) void {
self.outputStream.clearRetainingCapacity();
}
// returns true if the status changed at all
// can access output via Execution.outputStream
pub fn tick(self: *@This()) bool {
const lastStatus = self.status;
_ = lastStatus;
const lastOutputStreamLen = self.outputStream.len;
var rv: bool = false;
// const allocator = self.arena.allocator();
// try self.child.?.collectOutput(allocator, &self.outputStream, &self.outputStream, 8192 * 2);
if (lastOutputStreamLen != self.outputStream.len) {
self.lastUpdateTime = std.time.microTimestamp();
rv = true;
}
const ts = std.time.microTimestamp();
if (self.lastUpdateTime - self.timeout > ts) {}
if (self.child.?) {}
return rv;
}
pub fn start(command: []const []const u8) !*@This() {
return try startAlloc(sys.getAllocator(), command);
}
pub fn destroy(self: *@This()) void {
self.arena.deinit();
self.backing.destroy(self);
}
};
const std = @import("std");
pub const core = @import("core");
const sys = @import("../sys.zig");
const builtin = @import("builtin");

30
engine/sys/src/sys.zig Normal file
View File

@ -0,0 +1,30 @@
const std = @import("std");
pub const core = @import("core");
// TODO get rid of core.ModuleDescription
// it's really not needed anymore with the
// new backlog API
pub const Module: core.ModuleDescription = .{
.name = "sys",
.enabledByDefault = true,
};
// Module: sys
//
// this module is not enabled by default
// not intended for shipping builds
// but provides utilities for file manipulation among other things.
pub fn getAllocator() std.mem.Allocator {
return core.getEngine().allocator;
}
pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.mem.Allocator) !void {
_ = args;
_ = spec;
_ = allocator;
}
pub fn shutdown_module(allocator: std.mem.Allocator) void {
_ = allocator;
}

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,22 @@
const sys = @import("sys");
const core = sys.core;
const std = @import("std");
test "testing threadrunner" {
var spec = core.SpecVariantMap.init(std.testing.allocator);
try spec.put("name", .{ .string = "test" });
defer spec.deinit();
try core.start_module(&spec, .{}, std.testing.allocator);
defer core.shutdown_module(std.testing.allocator);
try sys.start_module(&spec, .{}, std.testing.allocator);
defer sys.shutdown_module(std.testing.allocator);
const command = sys.runSystemCommand(&.{ "timeout", "/t", "3" });
defer command.destroy();
while (command.isComplete()) {}
if (command.ensureCompleted()) {}
}

View File

@ -81,7 +81,7 @@ pub const Wchar = c_ushort; // ImWchar;
pub const Wchar16 = c_ushort; // ImWchar16;
pub const Wchar32 = c_int; // ImWchar32;
pub const InputTextCallback = *const fn (data: *InputTextCallbackData) callconv(.C) c_int; // ImGuiInputTextCallback
pub const InputTextCallback = ?*const fn (data: *InputTextCallbackData) callconv(.C) c_int; // ImGuiInputTextCallback
pub const SizeCallback = *const fn (data: *SizeCallbackData) callconv(.C) void; // ImGuiInputTextCallback
pub const MemAllocFunc = *const fn (sz: usize, user_data: ?*anyopaque) callconv(.C) ?*anyopaque; // ImGuiMemAllocFunc
pub const MemFreeFunc = *const fn (ptr: ?*anyopaque, user_data: ?*anyopaque) callconv(.C) void; // ImMemAllocFunction
@ -2759,13 +2759,13 @@ pub inline fn vSliderScalar(label: [*c]const u8, size: Vec2, data_type: DataType
return c.igVSliderScalar(label, @bitCast(size), @intFromEnum(data_type), p_data, p_min, p_max, format, @bitCast(flags));
}
pub inline fn inputText(label: [*c]const u8, buf: [*c]u8, buf_size: usize, flags: InputTextFlags, callback: InputTextCallback, user_data: ?*anyopaque) bool { //igInputText
return c.igInputText(label, buf, buf_size, @bitCast(flags), callback, user_data);
return c.igInputText(label, buf, buf_size, @bitCast(flags), @ptrCast(callback), user_data);
}
pub inline fn inputTextMultiline(label: [*c]const u8, buf: [*c]u8, buf_size: usize, size: Vec2, flags: InputTextFlags, callback: InputTextCallback, user_data: ?*anyopaque) bool { //igInputTextMultiline
return c.igInputTextMultiline(label, buf, buf_size, @bitCast(size), @bitCast(flags), callback, user_data);
return c.igInputTextMultiline(label, buf, buf_size, @bitCast(size), @bitCast(flags), @ptrCast(callback), user_data);
}
pub inline fn inputTextWithHint(label: [*c]const u8, hint: [*c]const u8, buf: [*c]u8, buf_size: usize, flags: InputTextFlags, callback: InputTextCallback, user_data: ?*anyopaque) bool { //igInputTextWithHint
return c.igInputTextWithHint(label, hint, buf, buf_size, @bitCast(flags), callback, user_data);
return c.igInputTextWithHint(label, hint, buf, buf_size, @bitCast(flags), @ptrCast(callback), user_data);
}
pub inline fn inputFloat(label: [*c]const u8, v: [*c]f32, step: f32, step_fast: f32, format: [*c]const u8, flags: InputTextFlags) bool { //igInputFloat
return c.igInputFloat(label, v, step, step_fast, format, @bitCast(flags));

View File

@ -30,26 +30,19 @@ pub fn build(b: *std.Build) void {
_ = externGame.compileInstall();
}
_ = sampleGame.compileInstall();
// external reload modules
// const sampleGameExtern = b.addSharedLibrary(.{
// .root_source_file = b.path("sampleGame/externGame/externGame.zig"),
// .link_libc = true,
// .optimize = optimize,
// .target = target,
// .name = "externGame",
// });
// tools
// blbuild.addExtraModule(sampleGameExtern.root_module, "gameExtras");
// blbuild.addExtraModule(sampleGameExtern.root_module, "bsp");
// sampleGameExtern.root_module.addImport("backlog", blbuild.nw_mod);
const newProjectMaker = blbuild.program(.{
.name = "newProjectMaker",
.desc = "new project maker",
.root_source_file = b.path("tools/newProjectMaker.zig"),
});
// const installExtern = b.addInstallArtifact(sampleGameExtern, .{
// .dest_dir = .{ .override = .{ .custom = "modules" } },
// });
// b.getInstallStep().dependOn(&installExtern.step);
newProjectMaker.setModuleEnabled("imgui", true);
newProjectMaker.setModuleEnabled("audio", false);
_ = newProjectMaker.compileInstall();
blbuild.addDependencyInstalls(b, .ReleaseFast); //.ReleaseFast);
}

View File

@ -0,0 +1,83 @@
pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "main");
allocator: std.mem.Allocator,
textBuffer: [8192]u8,
pub fn init(allocator: std.mem.Allocator) !*@This() {
const self = try allocator.create(@This());
self.* = .{
.allocator = allocator,
.textBuffer = std.mem.zeroes([8192]u8),
};
return self;
}
pub fn prepare(self: *@This()) !void {
_ = self;
core.engine_log("program ready", .{});
}
pub fn tick(self: *@This(), dt: f64) void {
_ = dt;
ig.setNextWindowPos(.{ .x = 200, .y = 200 }, .{}, .{});
if (ig.begin("New Project...", null, .{
.always_auto_resize = true,
.no_move = true,
.no_resize = true,
.no_collapse = true,
})) {
ig.setNextItemWidth(600);
if (ig.inputText(
"##Path",
&self.textBuffer,
self.textBuffer.len,
.{ .no_blank = true },
null,
null,
)) {
core.engine_log("huh", .{});
}
ig.sameLine(0, 3);
if (ig.button("...", .{})) {
core.engine_log("opening NFD", .{});
core.asyncOpenFolder(.{
.callback = onFolderSelected,
.callbackContext = self,
}) catch @panic(" unable to open dialog");
}
if (ig.button("Create", .{})) {
core.engine_log("creating project: ", .{});
}
}
ig.end();
}
pub fn onFolderSelected(
ctx: ?*anyopaque,
path: ?[]const u8,
) void {
const self: *@This() = @ptrCast(@alignCast(ctx));
if (path) |p| {
std.mem.copyForwards(u8, &self.textBuffer, p);
self.textBuffer[p.len] = 0;
}
}
pub fn deinit(self: *@This()) void {
self.allocator.destroy(self);
}
pub fn main() anyerror!void {
var spec = try api.getSpec("New Project Dialogue");
_ = api.startEngine(&NeonObjectTable, &spec);
}
const std = @import("std");
const api = @import("backlog");
const ig = api.imgui.api;
const core = api.core;