Backlog/projects/tools/toolbox.zig

175 lines
4.8 KiB
Zig

pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "main");
const GameContext = @This();
allocator: std.mem.Allocator,
commandQueue: core.RingQueue(Task),
activeCommand: ?*sys.SubprocessTask = null,
showInstructions: bool = false,
dockingInitialized: bool = false,
const Task = union(enum(u8)) {
subprocess: *sys.SubprocessTask,
func: *const fn (*GameContext) void,
};
pub fn init(allocator: std.mem.Allocator) !*@This() {
const self = try allocator.create(@This());
self.* = .{
.allocator = allocator,
.commandQueue = try core.RingQueue(Task).init(self.allocator, 4096),
};
return self;
}
pub fn prepare(self: *@This()) !void {
_ = self;
core.engine_log("program ready", .{});
if (core.getEngineObject(imgui.utils.TopBar)) |topbar| {
topbar.menuOpen = true;
}
}
pub fn tick(self: *@This(), dt: f64) void {
_ = dt;
self.tickTasks() catch {};
if (self.activeCommand != null or self.commandQueue.count() > 0) {
ig.setNextWindowPos(.{ .x = 20, .y = 20 }, .{}, .{});
if (ig.begin("tasks", null, .{
.always_auto_resize = true,
.no_title_bar = true,
.no_move = true,
.no_resize = true,
.no_collapse = true,
})) {}
ig.end();
}
// Initialize docking layout on first run
if (!self.dockingInitialized) {
// Get the main viewport dockspace ID (created by dockSpaceOverViewport)
const main_dockspace_id = ig.getID_Str("##DockSpaceViewport_11111111");
// Dock our toolbox window to the center of the main dockspace
ig.dockBuilderDockWindow("Toolbox Window", main_dockspace_id);
ig.dockBuilderFinish(main_dockspace_id);
self.dockingInitialized = true;
}
// Create a docked window
if (ig.begin("Toolbox Window", null, .{})) {
ig.textf("This is a docked toolbox window", .{});
if (ig.button("Recompile Shaders", .{})) {
start_RecompileShaders() catch {};
}
ig.separator();
ig.textf("Additional toolbox content can go here", .{});
if (self.activeCommand != null or self.commandQueue.count() > 0) {
ig.textf("outstanding tasks: {d}", .{self.commandQueue.count() + 1});
if (self.activeCommand) |cmd| {
ig.textf("current command: ", .{});
for (cmd.args) |arg| {
ig.textf("{s}", .{arg});
ig.sameLine(0, 4);
}
}
}
}
ig.end();
}
fn start_RecompileShaders() !void {}
fn tickTasks(self: *@This()) !void {
if (self.activeCommand == null) {
if (self.commandQueue.popFromLocked()) |task| {
switch (task) {
.subprocess => |t| {
self.activeCommand = t;
// core.engine_log("starting task {any}", .{t.args});
try t.run();
},
.func => |f| {
f(self);
},
}
}
}
if (self.activeCommand) |active| {
if (active.checkComplete()) {
active.destroy();
core.engine_logs("task complete");
self.activeCommand = null;
}
}
}
fn loadFileAllocFromCwd(allocator: std.mem.Allocator, dir: std.fs.Dir, path: []const u8) ![]u8 {
var file = try dir.openFile(path, .{});
defer file.close();
const filesize = (try file.stat()).size + 1; // add null byte
const buffer: []u8 = try allocator.alloc(u8, filesize);
errdefer allocator.free(buffer);
try file.reader().readNoEof(buffer[0 .. buffer.len - 1]);
buffer[buffer.len - 1] = 0;
return buffer;
}
fn displayInstructions(self: *@This()) void {
self.showInstructions = true;
}
pub fn deinit(self: *@This()) void {
self.allocator.destroy(self);
}
fn copyRecursiveDir(
allocator: std.mem.Allocator,
src_dir: *std.fs.Dir,
dest_dir: *std.fs.Dir,
) !void {
var walker = try src_dir.walk(allocator);
defer walker.deinit();
while (try walker.next()) |entry| {
switch (entry.kind) {
.file => {
try entry.dir.copyFile(entry.basename, dest_dir.*, entry.path, .{});
},
.directory => {
try dest_dir.makeDir(entry.path);
},
else => {},
}
}
}
pub fn main() anyerror!void {
var spec = try api.getSpec("New Project Dialogue");
try spec.put("useGPA", .{ .boolean = false });
try spec.put("configName", .{ .string = "toolbox" });
_ = api.startEngine(&NeonObjectTable, &spec);
}
const builtin = @import("builtin");
const std = @import("std");
const api = @import("backlog");
const imgui = api.imgui;
const ig = api.imgui.api;
const core = api.core;
const sys = api.sys;