diff --git a/libs/raygui/bindings.json b/libs/raygui/bindings.json index 615db63..11fe9f1 100644 --- a/libs/raygui/bindings.json +++ b/libs/raygui/bindings.json @@ -826,12 +826,12 @@ }, { "name": "focus", - "typ": "*i32" + "typ": "?*i32" } ], "returnType": "i32", "description": "List View with extended parameters", - "custom": false + "custom": true }, { "name": "GuiMessageBox", @@ -3416,4 +3416,4 @@ "custom": false } ] -} \ No newline at end of file +} diff --git a/libs/raygui/generate.zig b/libs/raygui/generate.zig index fa044f0..f303ad4 100644 --- a/libs/raygui/generate.zig +++ b/libs/raygui/generate.zig @@ -204,7 +204,12 @@ fn writeFunctions( try file.writeAll(try allocPrint(allocator, "@intToPtr([*c]raygui.{s}, @ptrToInt(&{s})),\n", .{ stripType(param.typ), param.name })); } else if (isPointer(param.typ)) { if (isConst(param.typ)) { - try file.writeAll(try allocPrint(allocator, "@intToPtr([*c]const {s}, @ptrToInt({s})),\n", .{ stripType(param.typ), param.name })); + const stripped = stripType(param.typ); + if (isPointer(stripped) and isConst(stripped)) { + try file.writeAll(try allocPrint(allocator, "@intToPtr([*c][*c]const {s}, @ptrToInt({s})),\n", .{ stripType(stripped), param.name })); + } else { + try file.writeAll(try allocPrint(allocator, "@intToPtr([*c]const {s}, @ptrToInt({s})),\n", .{ stripped, param.name })); + } } else { try file.writeAll(try allocPrint(allocator, "@ptrCast([*c]{s}, {s}),\n", .{ stripType(param.typ), param.name })); } diff --git a/libs/raygui/raygui.zig b/libs/raygui/raygui.zig index 0363212..4523d2b 100644 --- a/libs/raygui/raygui.zig +++ b/libs/raygui/raygui.zig @@ -290,7 +290,7 @@ pub fn GuiTabBar( ) i32 { return raygui.mGuiTabBar( @as([*c]raygui.Rectangle, @ptrFromInt(@intFromPtr(&bounds))), - @as([*c]const [*:0]const u8, @ptrFromInt(@intFromPtr(text))), + @as([*c][*c]const u8, @ptrFromInt(@intFromPtr(text))), count, @as([*c]i32, @ptrCast(active)), ); @@ -597,11 +597,11 @@ pub fn GuiListViewEx( count: i32, scrollIndex: *i32, active: *i32, - focus: *i32, + focus: ?*i32, ) i32 { return raygui.mGuiListViewEx( @as([*c]raygui.Rectangle, @ptrFromInt(@intFromPtr(&bounds))), - @as([*c]const [*:0]const u8, @ptrFromInt(@intFromPtr(text))), + @as([*c][*c]const u8, @ptrFromInt(@intFromPtr(text))), count, @as([*c]i32, @ptrCast(scrollIndex)), @as([*c]i32, @ptrCast(active)), diff --git a/src/gui-layout.zig b/src/gui-layout.zig new file mode 100644 index 0000000..dc050d1 --- /dev/null +++ b/src/gui-layout.zig @@ -0,0 +1,70 @@ +const Self = @This(); +const rl = @import("raylib"); +const std = @import("std"); + +const LayoutFrame = struct { + ox: f32, + oy: f32, + sx: f32, + sy: f32, +}; + +const LayoutStack = std.BoundedArray(LayoutFrame, 16); + +stack: LayoutStack, + +pub fn init() Self { + var stack = LayoutStack.init(0) catch unreachable; + stack.append(.{ + .ox = 0, + .oy = 0, + .sx = 1, + .sy = 1, + }) catch unreachable; + + return Self { .stack = stack }; +} + +pub fn deinit(self: *Self) void { + if (self.stack.len > 1) { + @panic(".push() was called more times than .pop()"); + } +} + +pub fn top(self: *Self) *LayoutFrame { + return &self.stack.buffer[self.stack.len-1]; +} + +pub fn push(self: *Self) void { + const top_frame = self.top(); + self.stack.append(top_frame.*) catch @panic("LayoutStack is too small, increase hard-coded limit"); +} + +pub fn pop(self: *Self) void { + if (self.stack.len == 1) { + @panic(".pop() was called more times than .push()"); + } + _ = self.stack.pop(); +} + +pub fn translate(self: *Self, x: f32, y: f32) void { + const top_frame = self.top(); + top_frame.ox += x * top_frame.sx; + top_frame.oy += y * top_frame.sy; +} + +pub fn scale(self: *Self, x: f32, y: f32) void { + const top_frame = self.top(); + top_frame.sx *= x; + top_frame.sy *= y; +} + +pub fn rect(self: *Self, x: f32, y: f32, width: f32, height: f32) rl.Rectangle { + const top_frame = self.top(); + return rl.Rectangle { + .x = x * top_frame.sx + top_frame.ox, + .y = y * top_frame.sy + top_frame.oy, + .width = width * top_frame.sx, + .height = height * top_frame.sy + }; +} diff --git a/src/main-scene.zig b/src/main-scene.zig index e8c31c9..70cb97c 100644 --- a/src/main-scene.zig +++ b/src/main-scene.zig @@ -3,6 +3,7 @@ const rl = @import("raylib"); const gui = @import("raygui"); const std = @import("std"); const roms = @import("./roms.zig"); +const GUILayout = @import("./gui-layout.zig"); const ROM = roms.ROM; const ChipContext = @import("chip.zig"); @@ -127,27 +128,24 @@ fn GuiListView( scroll_index: *i32, active: *i32, ) !i32 { - var needed_size: usize = 0; - needed_size += items.len-1; // N-1 character are needed for the separators - for (items) |item| { - needed_size += item.len; - } - - var str_buffer = try allocator.allocSentinel(u8, needed_size, 0); - defer allocator.free(str_buffer); - - var idx: usize = 0; - for (0.., items) |i, item| { - @memcpy(str_buffer[idx..(idx+item.len)], item); - idx += item.len; - - if (i != items.len-1) { - str_buffer[idx] = ';'; - idx += 1; + var allocated_count: usize = 0; + var items_z = try allocator.alloc([:0]const u8, items.len); + var items_zn = try allocator.alloc([*:0]const u8, items.len); + defer { + for (0..allocated_count) |i| { + allocator.free(items_z[i]); } + allocator.free(items_z); + allocator.free(items_zn); } - return gui.GuiListView(bounds, str_buffer, scroll_index, active); + for (0.., items) |i, item| { + items_z[i] = try allocator.dupeZ(u8, item); + items_zn[i] = items_z[i].ptr; + allocated_count += 1; + } + + return gui.GuiListViewEx(bounds, items_zn.ptr, @intCast(items_z.len), scroll_index, active, null); } fn GuiListViewMinWidth(allocator: Allocator, height: i32, items: []const []const u8) !i32 { @@ -184,6 +182,9 @@ pub fn drawGui(self: *Self, allocator: Allocator) !void { if (!self.is_gui_open) return; + var layout = GUILayout.init(); + defer layout.deinit(); + const screen_width: f32 = @floatFromInt(rl.GetScreenWidth()); const screen_height: f32 = @floatFromInt(rl.GetScreenHeight()); rl.DrawRectangle(0, 0, rl.GetScreenWidth(), rl.GetScreenHeight(), .{ @@ -205,8 +206,8 @@ pub fn drawGui(self: *Self, allocator: Allocator) !void { self.is_gui_open = false; } - rl.rlPushMatrix(); - rl.rlTranslatef(window.x, window.y, 0); + layout.push(); + layout.translate(window.x, window.y); const rom_list_names = try allocator.alloc([]const u8, rom_list.len); defer allocator.free(rom_list_names); @@ -219,11 +220,11 @@ pub fn drawGui(self: *Self, allocator: Allocator) !void { const list_width = try GuiListViewMinWidth(allocator, list_height, rom_list_names) + 20; _ = try GuiListView( allocator, - .{.x=10,.y=24, .width=@floatFromInt(list_width), .height=list_height}, + layout.rect(10, 24, @floatFromInt(list_width), list_height), rom_list_names, &self.rom_list_scroll_index, &self.selected_rom_index ); - rl.rlPopMatrix(); + layout.pop(); }