fixes gpa usage, we now have a lot of memory leaks

This commit is contained in:
peterino2 2025-06-30 18:28:55 -07:00
parent 8458a6e026
commit d1dd4961a5
6 changed files with 175 additions and 43 deletions

View File

@ -151,6 +151,7 @@ pub fn main() !void {
\\
\\ pub fn getSpec(comptime name:[]const u8) !core.SpecVariantMap {
\\ return try core.createSpecVariant(.{
\\ .useGPA = true,
\\ .name = name,
);

View File

@ -46,6 +46,7 @@ pub const RawInputObjectRef = struct {
// We are having some serious issues with this events pump.
pub const PlatformParams = struct {
extent: core.Vector2c = .{ .x = 1600, .y = 900 },
resizeable: bool = true,
windowName: []const u8,
icon: []const u8 = "textures/icon.png",
hasVideo: bool = true,
@ -97,6 +98,7 @@ pub const PlatformInstance = struct {
self.allocator.free(self.windowName);
self.allocator.free(self.iconPath);
self.processFuncs.deinit(self.allocator);
self.allocator.destroy(self);
// shutdown
}
@ -149,7 +151,7 @@ pub const PlatformInstance = struct {
pub fn setupWindow(self: *@This()) core.EngineDataEventError!void {
sdl3.init(.{ .video = true, .gamepad = true }) catch return error.BadInit;
self.window = sdl3.c.SDL_CreateWindow(self.windowName, self.windowExtent.x, self.windowExtent.y, 0).?; // resizeable
self.window = sdl3.c.SDL_CreateWindow(self.windowName, self.windowExtent.x, self.windowExtent.y, sdl3.c.SDL_WINDOW_RESIZABLE).?; // resizeable
self.extent = .{
.x = @floatFromInt(self.windowExtent.x),
.y = @floatFromInt(self.windowExtent.y),

View File

@ -34,8 +34,8 @@ pub const SubprocessTask = struct {
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.?.stdout_behavior = .Pipe;
self.child.?.stderr_behavior = .Pipe;
self.child.?.cwd = self.workingDir;
_ = self.child.?.spawn() catch {};

View File

@ -122,18 +122,50 @@ pub const WindowFlags = packed struct(c_int) { // ImGuiWindowFlags
no_docking: bool = false,
reserved: u11 = 0, // reserved, don't use
// Obsolete names
//ImGuiInputTextFlags_AlwaysInsertMode = ImGuiInputTextFlags_AlwaysOverwrite // [renamed in 1.82] name was not matching behavior
pub const no_nav: @This() = .{ .no_nav_inputs = true, .no_nav_focus = true };
pub const no_decoration: @This() = .{ .no_title_bar = true, .no_resize = true, .no_scrollbar = true, .no_collapse = true };
pub const no_inputs: @This() = .{ .no_mouse_inputs = true, .no_nav_inputs = true, .no_nav_focus = true };
};
// Inputs
// ImGuiInputTextFlags_AllowTabInput = 1 << 5, // Pressing TAB input a '\t' character into the text field
// ImGuiInputTextFlags_EnterReturnsTrue = 1 << 6, // Return 'true' when Enter is pressed (as opposed to every time the value was modified). Consider using IsItemDeactivatedAfterEdit() instead!
// ImGuiInputTextFlags_EscapeClearsAll = 1 << 7, // Escape key clears content if not empty, and deactivate otherwise (contrast to default behavior of Escape to revert)
// ImGuiInputTextFlags_CtrlEnterForNewLine = 1 << 8, // In multi-line mode, validate with Enter, add new line with Ctrl+Enter (default is opposite: validate with Ctrl+Enter, add line with Enter).
// // Other options
// ImGuiInputTextFlags_ReadOnly = 1 << 9, // Read-only mode
// ImGuiInputTextFlags_Password = 1 << 10, // Password mode, display all characters as '*', disable copy
// ImGuiInputTextFlags_AlwaysOverwrite = 1 << 11, // Overwrite mode
// ImGuiInputTextFlags_AutoSelectAll = 1 << 12, // Select entire text when first taking mouse focus
// ImGuiInputTextFlags_ParseEmptyRefVal = 1 << 13, // InputFloat(), InputInt(), InputScalar() etc. only: parse empty string as zero value.
// ImGuiInputTextFlags_DisplayEmptyRefVal = 1 << 14, // InputFloat(), InputInt(), InputScalar() etc. only: when value is zero, do not display it. Generally used with ImGuiInputTextFlags_ParseEmptyRefVal.
// ImGuiInputTextFlags_NoHorizontalScroll = 1 << 15, // Disable following the cursor horizontally
// ImGuiInputTextFlags_NoUndoRedo = 1 << 16, // Disable undo/redo. Note that input text owns the text data while active, if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID().
// // Elide display / Alignment
// ImGuiInputTextFlags_ElideLeft = 1 << 17, // When text doesn't fit, elide left side to ensure right side stays visible. Useful for path/filenames. Single-line only!
// // Callback features
// ImGuiInputTextFlags_CallbackCompletion = 1 << 18, // Callback on pressing TAB (for completion handling)
// ImGuiInputTextFlags_CallbackHistory = 1 << 19, // Callback on pressing Up/Down arrows (for history handling)
// ImGuiInputTextFlags_CallbackAlways = 1 << 20, // Callback on each iteration. User code may query cursor position, modify text buffer.
// ImGuiInputTextFlags_CallbackCharFilter = 1 << 21, // Callback on character inputs to replace or discard them. Modify 'EventChar' to replace or discard, or return 1 in callback to discard.
// ImGuiInputTextFlags_CallbackResize = 1 << 22, // Callback on buffer capacity changes request (beyond 'buf_size' parameter value), allowing the string to grow. Notify when the string wants to be resized (for string types which hold a cache of their Size). You will be provided a new BufSize in the callback and NEED to honor it. (see misc/cpp/imgui_stdlib.h for an example of using this)
// ImGuiInputTextFlags_CallbackEdit = 1 << 23, // Callback on any edit. Note that InputText() already returns true on edit + you can always use IsItemEdited(). The callback is useful to manipulate the underlying buffer while focus is active.
pub const InputTextFlags = packed struct(c_int) { // ImGuiInputTextFlags
chars_decimal: bool = false, // ImGuiInputTextFlags_CharsDecimal = 1 << 0
chars_hexadecimal: bool = false, // ImGuiInputTextFlags_CharsHexadecimal = 1 << 1
chars_uppercase: bool = false, // ImGuiInputTextFlags_CharsUppercase = 1 << 2
no_blank: bool = false, // ImGuiInputTextFlags_CharsNoBlank = 1 << 3
auto_select_all: bool = false, // ImGuiInputTextFlags_AutoSelectAll = 1 << 4
enter_returns_true: bool = false, // ImGuiInputTextFlags_EnterReturnsTrue = 1 << 5
chars_scientific: bool = false, // ImGuiInputTextFlags_CharsHexadecimal = 1 << 2
chars_uppercase: bool = false, // ImGuiInputTextFlags_CharsUppercase = 1 << 3
no_blank: bool = false, // ImGuiInputTextFlags_CharsNoBlank = 1 << 4
auto_select_all: bool = false, // ImGuiInputTextFlags_AutoSelectAll = 1 << 5
enter_returns_true: bool = false, // ImGuiInputTextFlags_EnterReturnsTrue = 1 << 6
// // todo verify these
callback_completion: bool = false, // ImGuiInputTextFlags_CallbackCompletion = 1 << 6,
callback_history: bool = false, // ImGuiInputTextFlags_CallbackHistory = 1 << 7,
callback_always: bool = false, // ImGuiInputTextFlags_CallbackAlways = 1 << 8,
@ -145,7 +177,6 @@ pub const InputTextFlags = packed struct(c_int) { // ImGuiInputTextFlags
read_only: bool = false, // ImGuiInputTextFlags_ReadOnly = 1 << 14,
password: bool = false, // ImGuiInputTextFlags_Password = 1 << 15,
no_undo_redo: bool = false, // ImGuiInputTextFlags_NoUndoRedo = 1 << 16,
chars_scientific: bool = false, // ImGuiInputTextFlags_CharsScientific = 1 << 17,
callback_resize: bool = false, // ImGuiInputTextFlags_CallbackResize = 1 << 18,
callback_edit: bool = false, // ImGuiInputTextFlags_CallbackEdit = 1 << 19
reserved: u12 = 0, // reserved, don't use

View File

@ -36,7 +36,7 @@ pub fn build(b: *std.Build) void {
// tools
const newProjectMaker = blbuild.program(.{
.name = "newProjectMaker",
.name = "newProject",
.desc = "new project maker",
.root_source_file = b.path("tools/newProjectMaker.zig"),
});

View File

@ -3,7 +3,8 @@ pub var NeonObjectTable = core.EngineObjectVTable.from(@This(), "main");
const GameContext = @This();
allocator: std.mem.Allocator,
textBuffer: [8192]u8,
pathBuffer: [8192]u8,
projectNameBuffer: [8192]u8,
commandQueue: core.RingQueue(Task),
@ -25,11 +26,14 @@ pub fn init(allocator: std.mem.Allocator) !*@This() {
const self = try allocator.create(@This());
self.* = .{
.allocator = allocator,
.textBuffer = std.mem.zeroes([8192]u8),
.pathBuffer = std.mem.zeroes([8192]u8),
.projectNameBuffer = 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"),
};
std.mem.copyForwards(u8, &self.projectNameBuffer, "newProject");
return self;
}
@ -41,6 +45,35 @@ pub fn prepare(self: *@This()) !void {
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.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();
return;
}
ig.setNextWindowPos(.{ .x = 200, .y = 200 }, .{}, .{});
if (ig.begin("New Project...", null, .{
@ -49,16 +82,27 @@ pub fn tick(self: *@This(), dt: f64) void {
.no_resize = true,
.no_collapse = true,
})) {
ig.setNextItemWidth(600);
if (ig.inputText(
"##Path",
&self.textBuffer,
self.textBuffer.len,
.{ .no_blank = true },
"##ProjectName",
&self.projectNameBuffer,
self.projectNameBuffer.len,
.{},
null,
null,
)) {
core.engine_log("huh", .{});
// core.engine_log("huh", .{});
}
ig.setNextItemWidth(600);
if (ig.inputText(
"##Path",
&self.pathBuffer,
self.pathBuffer.len,
.{},
null,
null,
)) {
// core.engine_log("huh", .{});
}
ig.sameLine(0, 3);
@ -72,31 +116,15 @@ pub fn tick(self: *@This(), dt: f64) void {
}
if (ig.button("Create", .{})) {
const asSlice = std.mem.span(@as([*c]const u8, @ptrCast(&self.textBuffer)));
core.engine_log("creating project: {s}", .{self.textBuffer});
const asSlice = std.mem.span(@as([*c]const u8, @ptrCast(&self.pathBuffer)));
core.engine_log("creating project: {s}", .{self.pathBuffer});
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.setNextWindowPos(.{ .x = 100, .y = 100 }, .{}, .{});
ig.setNextWindowSize(.{ .x = 800, .y = 500 }, .{});
if (ig.begin("Instructions", null, .{
.always_auto_resize = true,
@ -112,8 +140,6 @@ pub fn tick(self: *@This(), dt: f64) void {
}
ig.end();
}
self.tickTasks() catch {};
}
fn tickTasks(self: *@This()) !void {
@ -122,7 +148,7 @@ fn tickTasks(self: *@This()) !void {
switch (task) {
.subprocess => |t| {
self.activeCommand = t;
core.engine_log("starting task {any}", .{t.args});
// core.engine_log("starting task {any}", .{t.args});
try t.run();
},
.func => |f| {
@ -143,12 +169,24 @@ fn tickTasks(self: *@This()) !void {
pub fn createProject(self: *@This(), targetDir: []const u8) !void {
self.targetDir = try self.allocator.dupe(u8, targetDir);
{
const asSlice = std.mem.span(@as([*c]const u8, @ptrCast(&self.projectNameBuffer)));
self.targetName = try self.allocator.dupe(u8, asSlice);
}
try self.commandQueue.pushLocked(.{ .subprocess = try sys.runCommand(
self.allocator,
&.{ "zig", "init" },
targetDir,
) });
// const deployShaderDir = try std.fmt.allocPrint(self.allocator, "{s}/content/_shaders", .{self.targetDir.?});
if (builtin.os.tag == .windows) {
// os copy over the entire directory
} else {}
try self.commandQueue.pushLocked(.{ .func = updateBuildZig });
try self.commandQueue.pushLocked(.{ .subprocess = try sys.runCommand(
@ -157,9 +195,46 @@ pub fn createProject(self: *@This(), targetDir: []const u8) !void {
targetDir,
) });
try self.commandQueue.pushLocked(.{ .func = fingerprintGeneratePostbuild });
try self.commandQueue.pushLocked(.{ .func = copyShaders });
try self.commandQueue.pushLocked(.{ .func = displayInstructions });
}
fn fingerprintGeneratePostbuild(self: *@This()) void {
const task = sys.runCommand(
self.allocator,
&.{ "zig", "build", "install" },
self.targetDir.?,
) catch return;
defer task.destroy();
task.wait();
task.mutex.lock();
core.engine_log("task stdout: {s}", .{task.stdout.items});
task.mutex.unlock();
}
fn copyShaders(self: *@This()) void {
self.copyShadersWrap() catch {};
}
fn copyShadersWrap(self: *@This()) !void {
var srcDir = try std.fs.cwd().openDir("content/_shaders", .{ .iterate = true });
defer srcDir.close();
var targetDir = try std.fs.cwd().openDir(self.targetDir.?, .{});
defer targetDir.close();
try targetDir.makeDir("content");
try targetDir.makeDir("content/_shaders");
var dstDir = try targetDir.openDir("content/_shaders", .{});
defer dstDir.close();
try copyRecursiveDir(self.allocator, &srcDir, &dstDir);
}
fn loadFileAllocFromCwd(allocator: std.mem.Allocator, dir: std.fs.Dir, path: []const u8) ![]u8 {
var file = try dir.openFile(path, .{});
defer file.close();
@ -217,10 +292,10 @@ fn writeBuildZigFiles(self: *@This()) !void {
// 2. create src/main.zig
// 3. build.zig
// 4. build.zig.zon
var workingDir = try std.fs.cwd().openDir(self.targetDir.?, .{});
var workingDir = try std.fs.cwd().openDir(self.targetDir.?, .{ .iterate = true });
defer workingDir.close();
core.engine_logs("deliting files...");
core.engine_logs("deleting files...");
try workingDir.deleteFile("src/root.zig");
try workingDir.deleteFile("src/main.zig");
try workingDir.deleteFile("build.zig");
@ -413,8 +488,8 @@ pub fn onFolderSelected(
) void {
const self: *@This() = @ptrCast(@alignCast(ctx));
if (path) |p| {
std.mem.copyForwards(u8, &self.textBuffer, p);
self.textBuffer[p.len] = 0;
std.mem.copyForwards(u8, &self.pathBuffer, p);
self.pathBuffer[p.len] = 0;
}
}
@ -425,11 +500,34 @@ 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 });
_ = api.startEngine(&NeonObjectTable, &spec);
}
const builtin = @import("builtin");
const std = @import("std");
const api = @import("backlog");
const ig = api.imgui.api;