new project maker
This commit is contained in:
parent
b269188c72
commit
8458a6e026
|
|
@ -32,6 +32,7 @@ const engineDepList = [_][]const u8{
|
|||
"imgui",
|
||||
"physics",
|
||||
"ui",
|
||||
"sys",
|
||||
};
|
||||
|
||||
const BuildSystem = @This();
|
||||
|
|
@ -267,6 +268,7 @@ pub const defaultEnabledModules: []const []const u8 = &.{
|
|||
|
||||
pub const moduleOrder: []const []const u8 = &.{
|
||||
"core",
|
||||
"sys",
|
||||
"assets",
|
||||
"platform",
|
||||
"physics",
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
.platform = .{ .path = "engine/platform" },
|
||||
.imgui = .{ .path = "engine/imgui" },
|
||||
.ui = .{ .path = "engine/ui" },
|
||||
.sys = .{ .path = "engine/sys" },
|
||||
.rend = .{.path = "engine/rend" },
|
||||
.SpirvReflect = .{ .path = "lib/spirv-reflect-zig" },
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ pub const ui = @import("ui").module;
|
|||
pub const papyrus = @import("papyrus").module;
|
||||
pub const physics = @import("physics").module;
|
||||
pub const imgui = @import("imgui").module;
|
||||
pub const sys = @import("sys").module;
|
||||
|
||||
const modulelist = @import("modulelist.zig").list;
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ pub const list = [_][]const u8{
|
|||
"rend",
|
||||
"imgui",
|
||||
"ui",
|
||||
"sys",
|
||||
// to be implemented
|
||||
// "graphics",
|
||||
// "vkImgui",
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ pub fn build(b: *std.Build) void {
|
|||
|
||||
tests.root_module.addImport("sys", mod);
|
||||
const runArtifact = b.addRunArtifact(tests);
|
||||
b.installArtifact(tests);
|
||||
test_step.dependOn(&runArtifact.step);
|
||||
b.installArtifact(tests);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@ pub const SystemTaskRunner = struct {
|
|||
while (true) {
|
||||
// pump events
|
||||
// if nothing pumped this frame, wait 100ms
|
||||
if (self.jobs.items.len > 0) {
|
||||
for (self.jobs.items) |j| {
|
||||
_ = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -35,7 +40,9 @@ pub const SystemTaskRunner = struct {
|
|||
}
|
||||
|
||||
// check completion from the task thread
|
||||
pub fn checkCompletionTT(self: *@This()) bool {
|
||||
// returns true if
|
||||
pub fn checkCompletionTT(self: *@This(), task: *SystemTask) bool {
|
||||
_ = task;
|
||||
if (builtin.os.tag == .windows) {
|
||||
_ = self;
|
||||
}
|
||||
|
|
@ -44,6 +51,8 @@ pub const SystemTaskRunner = struct {
|
|||
pub fn destroy(self: *@This()) void {
|
||||
self.allocator.destroy(self);
|
||||
}
|
||||
|
||||
pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "SystemTaskRunner");
|
||||
};
|
||||
|
||||
pub const SystemTask = struct {
|
||||
|
|
@ -51,6 +60,16 @@ pub const SystemTask = struct {
|
|||
taskRunner: *SystemTaskRunner,
|
||||
};
|
||||
|
||||
pub const SystemTaskExecution = struct {
|
||||
task: *SystemTask,
|
||||
|
||||
pub fn deinit(self: *@This()) void {
|
||||
if (core.getEngineObject(SystemTaskRunner)) |taskRunner| {
|
||||
try taskRunner.pushJobRemoval(self.task);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub const ExecutionStatus = enum {
|
||||
ready,
|
||||
failed,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,15 @@
|
|||
const std = @import("std");
|
||||
pub const core = @import("core");
|
||||
|
||||
pub const SubprocessTask = @import("systemProc.zig").SubprocessTask;
|
||||
pub const runCommand = SubprocessTask.runCommand;
|
||||
|
||||
// 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,
|
||||
.enabledByDefault = false,
|
||||
};
|
||||
|
||||
// Module: sys
|
||||
|
|
|
|||
|
|
@ -0,0 +1,131 @@
|
|||
pub const std = @import("std");
|
||||
pub const core = @import("core");
|
||||
|
||||
fn __debugPrint(comptime fmt: []const u8, args: anytype) void {
|
||||
std.debug.print(fmt ++ "\n", args);
|
||||
}
|
||||
|
||||
fn noprint(comptime fmt: []const u8, args: anytype) void {
|
||||
_ = fmt;
|
||||
_ = args;
|
||||
}
|
||||
|
||||
const debugPrint = noprint;
|
||||
|
||||
pub const SubprocessTask = struct {
|
||||
mutex: std.Thread.Mutex = .{},
|
||||
allocator: std.mem.Allocator,
|
||||
args: []const []const u8,
|
||||
|
||||
child: ?std.process.Child = null,
|
||||
completed: bool = false,
|
||||
success: bool = false,
|
||||
|
||||
workingDir: ?[]const u8 = null,
|
||||
stdout: std.ArrayListUnmanaged(u8) = .{},
|
||||
stderr: std.ArrayListUnmanaged(u8) = .{},
|
||||
|
||||
pub fn run(task: *@This()) !void {
|
||||
const L = struct {
|
||||
self: *SubprocessTask,
|
||||
|
||||
pub fn func(ctx: @This(), _: *core.JobContext) void {
|
||||
const self = ctx.self;
|
||||
self.mutex.lock();
|
||||
debugPrint("running task", .{});
|
||||
self.child = std.process.Child.init(self.args, self.allocator);
|
||||
self.child.?.stdout_behavior = .Inherit;
|
||||
self.child.?.stderr_behavior = .Inherit;
|
||||
self.child.?.cwd = self.workingDir;
|
||||
|
||||
_ = self.child.?.spawn() catch {};
|
||||
self.mutex.unlock();
|
||||
|
||||
// close and cleanup everything
|
||||
self.waitInner() catch unreachable;
|
||||
}
|
||||
};
|
||||
|
||||
try core.dispatchJob(L{ .self = task });
|
||||
}
|
||||
|
||||
pub fn create(allocator: std.mem.Allocator, argv: []const []const u8) !*@This() {
|
||||
const self = try allocator.create(@This());
|
||||
|
||||
self.* = .{
|
||||
.child = null,
|
||||
.allocator = allocator,
|
||||
.args = argv,
|
||||
};
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn destroy(self: *@This()) void {
|
||||
self.mutex.lock();
|
||||
if (self.child) |*child| {
|
||||
_ = child;
|
||||
debugPrint("destroying child process", .{});
|
||||
}
|
||||
self.mutex.unlock();
|
||||
self.stdout.deinit(self.allocator);
|
||||
self.stderr.deinit(self.allocator);
|
||||
self.allocator.destroy(self);
|
||||
}
|
||||
|
||||
pub fn checkComplete(self: *@This()) bool {
|
||||
return self.completed;
|
||||
}
|
||||
|
||||
pub fn wait(self: *@This()) void {
|
||||
var completed: bool = self.completed;
|
||||
while (completed == false) {
|
||||
std.time.sleep(1 * 1000 * 1000);
|
||||
self.mutex.lock();
|
||||
completed = self.completed;
|
||||
self.mutex.unlock();
|
||||
}
|
||||
debugPrint("task completed", .{});
|
||||
}
|
||||
|
||||
pub fn waitInner(self: *@This()) !void {
|
||||
self.mutex.lock();
|
||||
if (self.child.?.stdout_behavior == .Pipe) {
|
||||
try self.child.?.collectOutput(self.allocator, &self.stdout, &self.stderr, 150 * 1024 * 1024);
|
||||
}
|
||||
|
||||
debugPrint("task completed stdout: {s}", .{self.stdout.items});
|
||||
const term = try self.child.?.wait();
|
||||
debugPrint("wait completed", .{});
|
||||
self.mutex.unlock();
|
||||
|
||||
switch (term) {
|
||||
.Exited => |m| {
|
||||
if (m == 0) self.success = true;
|
||||
},
|
||||
.Signal => |m| {
|
||||
core.engine_log("process Signaled {d}", .{m});
|
||||
},
|
||||
.Stopped => |m| {
|
||||
core.engine_log("process Stopped {d}", .{m});
|
||||
},
|
||||
.Unknown => |m| {
|
||||
core.engine_log("process Unknown {d}", .{m});
|
||||
},
|
||||
}
|
||||
|
||||
self.mutex.lock();
|
||||
self.child = null;
|
||||
self.completed = true;
|
||||
self.mutex.unlock();
|
||||
}
|
||||
|
||||
pub fn runCommand(allocator: std.mem.Allocator, argv: []const []const u8, cwd: ?[]const u8) !*@This() {
|
||||
const task = try @This().create(allocator, argv);
|
||||
task.workingDir = cwd;
|
||||
|
||||
try task.run();
|
||||
|
||||
return task;
|
||||
}
|
||||
};
|
||||
|
|
@ -13,10 +13,14 @@ test "testing threadrunner" {
|
|||
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();
|
||||
const task = try sys.SubprocessTask.create(std.testing.allocator, &.{ "echo", "this is an echo: hello world\n" });
|
||||
defer task.destroy();
|
||||
|
||||
while (command.isComplete()) {}
|
||||
std.debug.print("beginning destroy\n", .{});
|
||||
try task.run();
|
||||
task.wait();
|
||||
|
||||
if (command.ensureCompleted()) {}
|
||||
const task2 = try sys.runCommand(std.testing.allocator, &.{ "echo", "sup homies" }, null);
|
||||
defer task2.destroy();
|
||||
task2.wait();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ const gpu = sdl.gpu;
|
|||
allocator: std.mem.Allocator,
|
||||
runtime: *papyrus.PapyrusRuntime,
|
||||
screenContext: *papyrus.Context,
|
||||
screenBuffers: ScreenBuffers,
|
||||
|
||||
quadMesh: ?rend.IndexedMesh = null,
|
||||
quadMeshName: core.Name,
|
||||
|
|
@ -19,6 +20,58 @@ first: bool = true,
|
|||
rectPipeline: *gpu.GPUGraphicsPipeline = undefined,
|
||||
// textPipeline: *gpu.GPUGraphicsPipeline = undefined,
|
||||
|
||||
tempDrawCommand: std.ArrayListUnmanaged(DrawCommand) = .{},
|
||||
|
||||
const DrawCommand = union(enum(u8)) {
|
||||
rect: struct {
|
||||
ssboIndex: u32,
|
||||
},
|
||||
text: struct {
|
||||
ssboIndex: u32,
|
||||
},
|
||||
};
|
||||
|
||||
const SsboBuffer = struct {
|
||||
buffer: *gpu.GPUBuffer,
|
||||
staging: *gpu.GPUTransferBuffer,
|
||||
|
||||
pub fn init(device: *gpu.GPUDevice, elementSize: u32, count: u32) @This() {
|
||||
var self: @This() = undefined;
|
||||
|
||||
{
|
||||
const bci = gpu.GPUBufferCreateInfo{
|
||||
.size = elementSize * count,
|
||||
.usage = .{
|
||||
.bufferusageGraphicsStorageRead = true,
|
||||
},
|
||||
};
|
||||
self.buffer = device.createGPUBuffer(&bci);
|
||||
}
|
||||
|
||||
{
|
||||
const bci = gpu.GPUTransferBufferCreateInfo{
|
||||
.usage = .transferbufferusageUpload,
|
||||
.size = elementSize * count,
|
||||
};
|
||||
|
||||
self.staging = device.createGPUTransferBuffer(&bci);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
};
|
||||
|
||||
const ScreenBuffers = struct {
|
||||
text: SsboBuffer,
|
||||
rect: SsboBuffer,
|
||||
|
||||
pub fn init(device: *gpu.GPUDevice) @This() {
|
||||
return .{
|
||||
.rect = SsboBuffer.init(device, @sizeOf(rect_frag.Scene), 4096),
|
||||
.text = undefined,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "ui.runtime");
|
||||
|
||||
pub fn create(allocator: std.mem.Allocator) !*@This() {
|
||||
|
|
@ -32,6 +85,7 @@ pub fn create(allocator: std.mem.Allocator) !*@This() {
|
|||
.stringArena = std.heap.ArenaAllocator.init(allocator),
|
||||
.quadMeshName = core.MakeName("m_screenPlane"),
|
||||
.drawList = papyrus.DrawList.init(allocator),
|
||||
.screenBuffers = undefined,
|
||||
};
|
||||
|
||||
self.screenContext = try self.runtime.addContext();
|
||||
|
|
@ -83,6 +137,8 @@ pub fn createRectPipeline(self: *@This()) !void {
|
|||
|
||||
pci.rasterizer_state.fill_mode = .fillmodeFill;
|
||||
self.rectPipeline = ctx.device.createGPUGraphicsPipeline(&pci);
|
||||
|
||||
self.screenBuffers = ScreenBuffers.init(ctx.device);
|
||||
}
|
||||
|
||||
pub fn postRender(p: *anyopaque, cmd: *gpu.GPUCommandBuffer) void {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,11 @@ pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.me
|
|||
// gets the main context
|
||||
pub const context = core.EngineObject(PapyrusIntegration).get;
|
||||
|
||||
pub fn getScreen() *papyrus.Context {
|
||||
return context().screenContext;
|
||||
}
|
||||
|
||||
pub fn shutdown_module(allocator: std.mem.Allocator) void {
|
||||
_ = allocator;
|
||||
}
|
||||
pub const ModernStyle = papyrus.ModernStyle;
|
||||
|
|
|
|||
|
|
@ -50,6 +50,11 @@ pub fn build(b: *std.Build) void {
|
|||
"Additionally install 'SDL_build_config.h' when installing SDL (default: false)",
|
||||
) orelse false;
|
||||
|
||||
if (target.result.abi.isAndroid()) {
|
||||
// do the android build instead here... we dont use any of the other shit below
|
||||
return;
|
||||
}
|
||||
|
||||
var windows = false;
|
||||
var linux = false;
|
||||
var linux_deps_values: ?LinuxDepsValues = null;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ pub fn build(b: *std.Build) void {
|
|||
sampleGame.setModuleEnabled("imgui", true);
|
||||
sampleGame.setModuleEnabled("audio", true);
|
||||
sampleGame.setModuleEnabled("physics", true);
|
||||
sampleGame.setModuleEnabled("ui", true);
|
||||
sampleGame.addExtraModule("gameExtras");
|
||||
sampleGame.addExtraModule("videoplayer");
|
||||
sampleGame.addExtraModule("doomplayer");
|
||||
|
|
@ -42,6 +43,7 @@ pub fn build(b: *std.Build) void {
|
|||
|
||||
newProjectMaker.setModuleEnabled("imgui", true);
|
||||
newProjectMaker.setModuleEnabled("audio", false);
|
||||
newProjectMaker.setModuleEnabled("sys", true);
|
||||
_ = newProjectMaker.compileInstall();
|
||||
|
||||
blbuild.addDependencyInstalls(b, .ReleaseFast); //.ReleaseFast);
|
||||
|
|
|
|||
|
|
@ -92,6 +92,24 @@ pub const ExternGameObject = struct {
|
|||
defer settings.release();
|
||||
try physics.addShape("ph_small_box", settings);
|
||||
|
||||
{
|
||||
const ctx = ui.getScreen();
|
||||
const panel2 = try ctx.addPanel(.{});
|
||||
{
|
||||
ctx.getPanel(panel2).hasTitle = false;
|
||||
ctx.get(panel2).anchor = .TopRight;
|
||||
// ctx.get(panel2).fill = .FillY; todo, this is a bug. why.
|
||||
ctx.get(panel2).pos = .{ .x = -105, .y = 1 };
|
||||
ctx.get(panel2).size = .{ .x = 100, .y = 1 };
|
||||
ctx.getPanel(panel2).titleColor = ui.ModernStyle.GreyDark;
|
||||
|
||||
// add some text to this panel
|
||||
const text = try ctx.addText(panel2, "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.");
|
||||
ctx.get(text).pos = .{ .x = 32, .y = 32 };
|
||||
ctx.get(text).size = .{ .x = 300, .y = 400 };
|
||||
}
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
|
|
@ -229,6 +247,7 @@ const imgui = backlog.imgui;
|
|||
const physics = backlog.physics;
|
||||
const rend = backlog.rend;
|
||||
const ig = imgui.api;
|
||||
const ui = backlog.ui;
|
||||
const platform = backlog.platform;
|
||||
const extras = @import("gameExtras");
|
||||
const bsp = @import("bsp");
|
||||
|
|
|
|||
|
|
@ -1,13 +1,34 @@
|
|||
pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "main");
|
||||
|
||||
const GameContext = @This();
|
||||
|
||||
allocator: std.mem.Allocator,
|
||||
textBuffer: [8192]u8,
|
||||
|
||||
commandQueue: core.RingQueue(Task),
|
||||
|
||||
activeCommand: ?*sys.SubprocessTask = null,
|
||||
|
||||
targetName: ?[]u8 = null,
|
||||
targetDir: ?[]u8 = null,
|
||||
engineRelative: ?[]u8 = null,
|
||||
fingerprint: ?[]const u8 = null,
|
||||
|
||||
showInstructions: 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,
|
||||
.textBuffer = std.mem.zeroes([8192]u8),
|
||||
.commandQueue = try core.RingQueue(Task).init(self.allocator, 4096),
|
||||
.targetName = try allocator.dupe(u8, "sample"),
|
||||
.engineRelative = try allocator.dupe(u8, "Backlog"),
|
||||
};
|
||||
return self;
|
||||
}
|
||||
|
|
@ -51,10 +72,339 @@ pub fn tick(self: *@This(), dt: f64) void {
|
|||
}
|
||||
|
||||
if (ig.button("Create", .{})) {
|
||||
core.engine_log("creating project: ", .{});
|
||||
const asSlice = std.mem.span(@as([*c]const u8, @ptrCast(&self.textBuffer)));
|
||||
core.engine_log("creating project: {s}", .{self.textBuffer});
|
||||
self.createProject(asSlice) catch {};
|
||||
}
|
||||
}
|
||||
ig.end();
|
||||
|
||||
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.textf("outstanding tasks: {d}", .{self.commandQueue.count() + 1});
|
||||
}
|
||||
|
||||
ig.end();
|
||||
}
|
||||
|
||||
if (self.showInstructions) {
|
||||
ig.setNextWindowPos(.{ .x = 20, .y = 20 }, .{}, .{});
|
||||
ig.setNextWindowSize(.{ .x = 800, .y = 500 }, .{});
|
||||
if (ig.begin("Instructions", null, .{
|
||||
.always_auto_resize = true,
|
||||
.no_move = true,
|
||||
.no_resize = true,
|
||||
.no_collapse = true,
|
||||
})) {
|
||||
ig.textf("project generated and git repo cloned, run zig build install and you might need to update the fingerprint", .{});
|
||||
|
||||
if (ig.button("close..", .{})) {
|
||||
self.showInstructions = false;
|
||||
}
|
||||
}
|
||||
ig.end();
|
||||
}
|
||||
|
||||
self.tickTasks() catch {};
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn createProject(self: *@This(), targetDir: []const u8) !void {
|
||||
self.targetDir = try self.allocator.dupe(u8, targetDir);
|
||||
try self.commandQueue.pushLocked(.{ .subprocess = try sys.runCommand(
|
||||
self.allocator,
|
||||
&.{ "zig", "init" },
|
||||
targetDir,
|
||||
) });
|
||||
|
||||
try self.commandQueue.pushLocked(.{ .func = updateBuildZig });
|
||||
|
||||
try self.commandQueue.pushLocked(.{ .subprocess = try sys.runCommand(
|
||||
self.allocator,
|
||||
&.{ "git", "clone", "git@github.com:peterino2/BacklogEngine.git", "Backlog" },
|
||||
targetDir,
|
||||
) });
|
||||
|
||||
try self.commandQueue.pushLocked(.{ .func = displayInstructions });
|
||||
}
|
||||
|
||||
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.alignedAlloc(u8, 8, 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;
|
||||
}
|
||||
|
||||
fn updateBuildZig(self: *@This()) void {
|
||||
core.engine_logs("updating build.zig.zon");
|
||||
|
||||
var workingDir = std.fs.cwd().openDir(self.targetDir.?, .{}) catch return;
|
||||
defer workingDir.close();
|
||||
|
||||
const buildZigZonPath = std.fmt.allocPrint(self.allocator, "{s}/build.zig.zon", .{self.targetDir.?}) catch return;
|
||||
defer self.allocator.free(buildZigZonPath);
|
||||
|
||||
const buildZigContents = loadFileAllocFromCwd(self.allocator, workingDir, buildZigZonPath) catch return;
|
||||
defer self.allocator.free(buildZigContents);
|
||||
|
||||
// walk forward until we find the fingerprint value
|
||||
var window: []const u8 = buildZigContents[0..];
|
||||
var offset: usize = 0;
|
||||
|
||||
while (offset < buildZigContents.len) : (offset += 1) {
|
||||
window = buildZigContents[offset..buildZigContents.len];
|
||||
if (std.mem.startsWith(u8, window, ".fingerprint")) {
|
||||
// walk forward until i find the comma
|
||||
var windowEnd: usize = offset;
|
||||
while (windowEnd < buildZigContents.len) : (windowEnd += 1) {
|
||||
if (buildZigContents[windowEnd] == ',') {
|
||||
self.updateFingerPrint(buildZigContents[offset..windowEnd]);
|
||||
|
||||
self.writeBuildZigFiles() catch {};
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
core.engine_logs("unable to update window");
|
||||
}
|
||||
|
||||
fn writeBuildZigFiles(self: *@This()) !void {
|
||||
// copy over the entire templates directory.
|
||||
// 1. make a content folder
|
||||
// 2. create src/main.zig
|
||||
// 3. build.zig
|
||||
// 4. build.zig.zon
|
||||
var workingDir = try std.fs.cwd().openDir(self.targetDir.?, .{});
|
||||
defer workingDir.close();
|
||||
|
||||
core.engine_logs("deliting files...");
|
||||
try workingDir.deleteFile("src/root.zig");
|
||||
try workingDir.deleteFile("src/main.zig");
|
||||
try workingDir.deleteFile("build.zig");
|
||||
try workingDir.deleteFile("build.zig.zon");
|
||||
|
||||
// 1. write src/main.zig
|
||||
try self.writeMainZig(&workingDir);
|
||||
try self.writeBuildZig(&workingDir);
|
||||
try self.writeBuildZigZon(&workingDir);
|
||||
}
|
||||
|
||||
fn writeBuildZig(self: *@This(), workingDir: *std.fs.Dir) !void {
|
||||
const out_path = "build.zig";
|
||||
|
||||
var content = std.ArrayList(u8).init(self.allocator);
|
||||
defer content.deinit();
|
||||
|
||||
var writer = content.writer();
|
||||
|
||||
const template =
|
||||
\\ const std = @import("std");
|
||||
\\ const Backlog = @import("Backlog");
|
||||
\\
|
||||
\\ pub fn build(b: *std.Build) void {{
|
||||
\\ const target = b.standardTargetOptions(.{{}});
|
||||
\\ const optimize = b.standardOptimizeOption(.{{}});
|
||||
\\
|
||||
\\ var blbuild = Backlog.init(b, .{{
|
||||
\\ .target = target,
|
||||
\\ .optimize = optimize,
|
||||
\\ .backlogRoot = "{s}",
|
||||
\\ }});
|
||||
;
|
||||
|
||||
try writer.print(template, .{self.engineRelative.?});
|
||||
|
||||
const template2 =
|
||||
\\ const program = blbuild.program(.{{
|
||||
\\ .name = "{s}",
|
||||
\\ .desc = "simple program built with backlog",
|
||||
\\ .root_source_file = b.path("src/main.zig"),
|
||||
\\ }});
|
||||
\\
|
||||
\\ program.setModuleEnabled("imgui", true);
|
||||
\\
|
||||
\\ _ = program.compileInstall();
|
||||
\\ }}
|
||||
;
|
||||
|
||||
try writer.print(template2, .{self.targetName.?});
|
||||
|
||||
try writer.writeByte(0);
|
||||
|
||||
try self.writeZigFile(workingDir, out_path, content.items);
|
||||
}
|
||||
|
||||
const entries: []const struct { name: []const u8, path: []const u8 } = &.{
|
||||
.{ .name = "SpirvReflect", .path = "lib/spirv-reflect-zig" },
|
||||
.{ .name = "zphysics", .path = "lib/zphysics" },
|
||||
.{ .name = "spng", .path = "lib/spng" },
|
||||
.{ .name = "ozz", .path = "lib/ozz" },
|
||||
.{ .name = "sdl3", .path = "lib/sdl3" },
|
||||
.{ .name = "miniaudio", .path = "lib/miniaudio" },
|
||||
.{ .name = "lua", .path = "lib/lua" },
|
||||
};
|
||||
|
||||
fn writeBuildZigZon(self: *@This(), workingDir: *std.fs.Dir) !void {
|
||||
var content = std.ArrayList(u8).init(self.allocator);
|
||||
defer content.deinit();
|
||||
|
||||
var writer = content.writer();
|
||||
try writer.print(".{{\n", .{});
|
||||
|
||||
try writer.print(
|
||||
\\ .name = .MyProjects,
|
||||
\\ .version = "0.0.0",
|
||||
\\ .dependencies = .{{
|
||||
\\ .Backlog = .{{ .path = "{s}" }},
|
||||
, .{self.engineRelative.?});
|
||||
|
||||
for (entries) |entry| {
|
||||
try writer.print(" .{s} = .{{ .path = \"{s}/{s}\" }},\n", .{ entry.name, self.engineRelative.?, entry.path });
|
||||
}
|
||||
|
||||
try writer.print(
|
||||
\\ }},
|
||||
\\
|
||||
, .{});
|
||||
|
||||
try writer.print(
|
||||
\\ .paths = .{{ "" }},
|
||||
\\
|
||||
, .{});
|
||||
|
||||
try writer.print(
|
||||
\\ .fingerprint = {s},
|
||||
\\
|
||||
, .{self.fingerprint.?});
|
||||
|
||||
try writer.print("}}", .{});
|
||||
|
||||
const file = try workingDir.createFile("build.zig.zon", .{});
|
||||
defer file.close();
|
||||
try file.writeAll(content.items);
|
||||
}
|
||||
|
||||
fn writeMainZig(self: *@This(), workingDir: *std.fs.Dir) !void {
|
||||
var content = std.ArrayList(u8).init(self.allocator);
|
||||
defer content.deinit();
|
||||
|
||||
const template =
|
||||
\\ pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "main");
|
||||
\\
|
||||
\\ allocator: std.mem.Allocator,
|
||||
\\
|
||||
\\ pub fn init(allocator: std.mem.Allocator) !*@This() {
|
||||
\\ const self = try allocator.create(@This());
|
||||
\\ self.* = .{
|
||||
\\ .allocator = allocator,
|
||||
\\ };
|
||||
\\ return self;
|
||||
\\ }
|
||||
\\
|
||||
\\ pub fn prepare(self: *@This()) !void {
|
||||
\\ _ = self;
|
||||
\\ core.engine_log("program ready", .{});
|
||||
\\ }
|
||||
\\
|
||||
\\ pub fn tick(self: *@This(), dt: f64) void {
|
||||
\\ _ = self;
|
||||
\\ _ = dt;
|
||||
\\ ig.showDemoWindow(null);
|
||||
\\ }
|
||||
\\
|
||||
\\ pub fn deinit(self: *@This()) void {
|
||||
\\ self.allocator.destroy(self);
|
||||
\\ }
|
||||
\\
|
||||
\\ pub fn main() anyerror!void {
|
||||
\\ var spec = try api.getSpec("
|
||||
;
|
||||
|
||||
const template2 =
|
||||
\\");
|
||||
\\ _ = api.startEngine(&NeonObjectTable, &spec);
|
||||
\\ }
|
||||
\\
|
||||
\\ const std = @import("std");
|
||||
\\ const api = @import("backlog");
|
||||
\\ const ig = api.imgui.api;
|
||||
\\ const core = api.core;
|
||||
\\
|
||||
;
|
||||
|
||||
try content.appendSlice(template);
|
||||
try content.appendSlice(self.targetName.?);
|
||||
try content.appendSlice(template2);
|
||||
try content.append(0);
|
||||
|
||||
const out_path = "src/main.zig";
|
||||
|
||||
std.debug.print("{s}", .{content.items});
|
||||
|
||||
try self.writeZigFile(workingDir, out_path, content.items);
|
||||
}
|
||||
|
||||
fn writeZigFile(self: *@This(), workingDir: *std.fs.Dir, out_path: []const u8, contents: []const u8) !void {
|
||||
var ast = try std.zig.Ast.parse(self.allocator, @as([:0]const u8, @ptrCast(contents[0 .. contents.len - 1])), .zig);
|
||||
|
||||
defer ast.deinit(self.allocator);
|
||||
const out = try ast.render(self.allocator);
|
||||
|
||||
const file = try workingDir.createFile(out_path, .{});
|
||||
defer file.close();
|
||||
try file.writeAll(out);
|
||||
}
|
||||
|
||||
fn updateFingerPrint(self: *@This(), zonEntry: []const u8) void {
|
||||
// find the first number
|
||||
var left: usize = 0;
|
||||
while (zonEntry[left] != '0') : (left += 1) {}
|
||||
|
||||
core.engine_log(">> FINGERPRINT '{s}'", .{zonEntry[left .. zonEntry.len - 1]});
|
||||
self.fingerprint = zonEntry[left .. zonEntry.len - 1];
|
||||
}
|
||||
|
||||
pub fn onFolderSelected(
|
||||
|
|
@ -69,6 +419,9 @@ pub fn onFolderSelected(
|
|||
}
|
||||
|
||||
pub fn deinit(self: *@This()) void {
|
||||
if (self.targetDir) |t| {
|
||||
self.allocator.free(t);
|
||||
}
|
||||
self.allocator.destroy(self);
|
||||
}
|
||||
|
||||
|
|
@ -81,3 +434,4 @@ const std = @import("std");
|
|||
const api = @import("backlog");
|
||||
const ig = api.imgui.api;
|
||||
const core = api.core;
|
||||
const sys = api.sys;
|
||||
|
|
|
|||
Loading…
Reference in New Issue