From 4c2cc5135e8f1cb9862b920984ee08cb4319e532 Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Sun, 21 Jan 2024 14:31:21 +0200 Subject: [PATCH] dynamically show list of available roms --- src/assets/fonts/generic-mono.otf | Bin 34180 -> 0 bytes src/main-scene.zig | 99 +++++++++++++++++++++++++++--- src/main.zig | 5 -- src/roms.zig | 7 ++- 4 files changed, 96 insertions(+), 15 deletions(-) delete mode 100644 src/assets/fonts/generic-mono.otf diff --git a/src/assets/fonts/generic-mono.otf b/src/assets/fonts/generic-mono.otf deleted file mode 100644 index 422eed3b5c65e2888c02c402a50d137227e7170f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34180 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 diff --git a/src/main-scene.zig b/src/main-scene.zig index e4d8442..e8c31c9 100644 --- a/src/main-scene.zig +++ b/src/main-scene.zig @@ -12,16 +12,17 @@ const assert = std.debug.assert; const Allocator = std.mem.Allocator; const StringList = std.ArrayList([]const u8); -const example_roms = roms.listROMs(); +const rom_list = roms.listROMs(); allocator: Allocator, chip: *ChipContext, raylib_chip: *RaylibChip, chip_sound: rl.Sound, -rom: ?ROM = null, is_gui_open: bool = true, +selected_rom_index: i32 = 3, +rom_list_scroll_index: i32 = 0, pub fn genSinWave(wave: *rl.Wave, frequency: f32) void { assert(wave.sampleSize == 16); // Only 16 bits are supported @@ -68,7 +69,7 @@ pub fn init(allocator: Allocator) !Self { .chip_sound = chip_sound, }; - self.set_rom(example_roms[3]); + self.set_rom(3); return self; } @@ -81,8 +82,9 @@ pub fn deinit(self: *Self) void { self.allocator.destroy(self.chip); } -pub fn set_rom(self: *Self, rom: ROM) void { - self.rom = rom; +pub fn set_rom(self: *Self, index: i32) void { + self.selected_rom_index = index; + const rom = rom_list[@intCast(index)]; self.chip.reset(); self.chip.set_memory(0x200, rom.data); } @@ -115,10 +117,67 @@ pub fn draw(self: *Self) void { render_height ); - self.draw_gui(); + self.drawGui(self.allocator) catch @panic("GUI OOM"); } -pub fn draw_gui(self: *Self) void { +fn GuiListView( + allocator: Allocator, + bounds: rl.Rectangle, + items: []const []const u8, + 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; + } + } + + return gui.GuiListView(bounds, str_buffer, scroll_index, active); +} + +fn GuiListViewMinWidth(allocator: Allocator, height: i32, items: []const []const u8) !i32 { + const border_width = gui.GuiGetStyle(.DEFAULT , @intFromEnum(gui.GuiControlProperty.BORDER_WIDTH)); + const item_spacing = gui.GuiGetStyle(.LISTVIEW, @intFromEnum(gui.GuiListViewProperty.LIST_ITEMS_SPACING)); + const item_height = gui.GuiGetStyle(.LISTVIEW, @intFromEnum(gui.GuiListViewProperty.LIST_ITEMS_HEIGHT)); + const font_size = gui.GuiGetStyle(.DEFAULT , @intFromEnum(gui.GuiDefaultProperty.TEXT_SIZE)); + const scrollbar_width = gui.GuiGetStyle(.LISTVIEW, @intFromEnum(gui.GuiListViewProperty.SCROLLBAR_WIDTH)); + + var max_item_width: i32 = 0; + for (items) |item| { + const item_z = try allocator.dupeZ(u8, item); + defer allocator.free(item_z); + const item_width = rl.MeasureText(item_z, font_size); + + max_item_width = @max(max_item_width, item_width); + } + + const item_count: i32 = @intCast(items.len); + const need_scrollbar = ((item_height + item_spacing)*item_count > height); + + var min_width = max_item_width + 2*item_spacing + border_width; + if (need_scrollbar) { + min_width += scrollbar_width; + } + + return min_width; +} + +pub fn drawGui(self: *Self, allocator: Allocator) !void { if (rl.IsKeyPressed(.KEY_TAB)) { self.is_gui_open = !self.is_gui_open; } @@ -137,12 +196,34 @@ pub fn draw_gui(self: *Self) void { const window_width: f32 = 300; const window_height: f32 = 100; const window = rl.Rectangle{ - .x = (screen_width-window_width)/2, - .y = (screen_height-window_height)/2, + .x = @trunc((screen_width-window_width)/2), + .y = @trunc((screen_height-window_height)/2), .width = window_width, .height = window_height }; if (gui.GuiWindowBox(window, "CHIP-8 Settings") == 1) { self.is_gui_open = false; } + + rl.rlPushMatrix(); + rl.rlTranslatef(window.x, window.y, 0); + + const rom_list_names = try allocator.alloc([]const u8, rom_list.len); + defer allocator.free(rom_list_names); + + for (0.., rom_list) |i, rom| { + rom_list_names[i] = rom.name; + } + + const list_height = 100; + 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}, + rom_list_names, + &self.rom_list_scroll_index, + &self.selected_rom_index + ); + + rl.rlPopMatrix(); } diff --git a/src/main.zig b/src/main.zig index 82c49de..71c25f7 100755 --- a/src/main.zig +++ b/src/main.zig @@ -31,11 +31,6 @@ pub fn main() anyerror!void { var scene = try MainScene.init(allocator); defer scene.deinit(); - const font_size = 24; - const font_ttf_default_numchars = 95; // TTF font generation default charset: 95 glyphs (ASCII 32..126) - const font = rl.LoadFontEx("src/assets/fonts/generic-mono.otf", font_size, null, font_ttf_default_numchars); - defer rl.UnloadFont(font); - while (!rl.WindowShouldClose()) { var dt = rl.GetFrameTime(); scene.update(dt); diff --git a/src/roms.zig b/src/roms.zig index f4441a1..07f046e 100644 --- a/src/roms.zig +++ b/src/roms.zig @@ -1,3 +1,4 @@ +const std = @import("std"); const options = @import("options"); const rom_count = options.roms.len; @@ -10,8 +11,12 @@ pub fn listROMs() [options.roms.len]ROM { var roms: [options.roms.len]ROM = undefined; for (0.., options.roms) |i, file| { + const extension = std.mem.lastIndexOfScalar(u8, file, '.') orelse file.len; + const slash = std.mem.lastIndexOfScalar(u8, file, '/') orelse -1; + + const name = file[(slash+1)..extension]; roms[i] = ROM{ - .name = file, + .name = name, .data = @embedFile(file) }; }