diff --git a/src/simulator/control_bar.odin b/src/simulator/gui_control_bar.odin similarity index 52% rename from src/simulator/control_bar.odin rename to src/simulator/gui_control_bar.odin index 9073254..b037b2c 100644 --- a/src/simulator/control_bar.odin +++ b/src/simulator/gui_control_bar.odin @@ -3,15 +3,16 @@ package simulator import "core:log" import rl "vendor:raylib" -PADDING :: 10 - gui_control_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) { rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY) - // Cursor moves for every btn call places them left to right with padding - cursor : f32 = rect.x + PANEL_PADDING + rl.DrawTextEx(sim.font, "Octal Cookie Chip 8 Sim ", {rect.x + PADDING_X, rect.y + 12}, 25, 1, rl.WHITE) + text_size := rl.MeasureTextEx(sim.font, "Octal Cookie Chip 8 Sim ", 25, 1) - if btn(&cursor, rect, BUTTON_HEIGHT, BUTTON_WIDTH, PANEL_PADDING, "RUN") { + // Cursor moves for every btn call places them left to right with padding + cursor : f32 = text_size.x + 5 + rect.x + PADDING_X + + if btn(&cursor, rect, BUTTON_HEIGHT, BUTTON_WIDTH, PADDING_X, "RUN") { if sim.rom_loaded { sim.paused = false sim.running = true @@ -20,14 +21,18 @@ gui_control_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) { } } - if btn(&cursor, rect, BUTTON_HEIGHT, BUTTON_WIDTH, PANEL_PADDING, "PAUSE") { + if btn(&cursor, rect, BUTTON_HEIGHT, BUTTON_WIDTH, PADDING_X, "PAUSE") { sim.paused = true sim.running = false } + + if btn(&cursor, rect, BUTTON_HEIGHT, BUTTON_WIDTH, PADDING_X, "RESET") { + + } } btn :: proc(cursor: ^f32, rect: rl.Rectangle, h, w, gap: f32, label: cstring) -> bool { - r := rl.Rectangle{cursor^, rect.y + PADDING, w, h} + r := rl.Rectangle{cursor^, rect.y + PADDING_X, w, h} cursor^ += w + gap return rl.GuiButton(r, label) } diff --git a/src/simulator/screen.odin b/src/simulator/gui_screen.odin similarity index 77% rename from src/simulator/screen.odin rename to src/simulator/gui_screen.odin index 5d517e2..ec1e549 100644 --- a/src/simulator/screen.odin +++ b/src/simulator/gui_screen.odin @@ -3,6 +3,14 @@ package simulator import rl "vendor:raylib" gui_screen :: proc(rect: rl.Rectangle, sim: ^Simulator) { + bounds := rl.Rectangle { + x = rect.x + PADDING_X, + y = rect.y + PADDING_Y, + width = rect.width - (PADDING_X * 2), + height = rect.height - (PADDING_Y * 2), + } + rl.GuiPanel(bounds, nil) + s := sim.machine // 2 : 1 @@ -12,14 +20,14 @@ gui_screen :: proc(rect: rl.Rectangle, sim: ^Simulator) { // create viewport for the ratio view := rect - avail_space := rect.width / rect.height + avail_space := bounds.width / bounds.height if avail_space > aspect_ratio { - view.width = rect.height * aspect_ratio - view.x = rect.x + (rect.width - view.width) * 0.5 + view.width = bounds.height * aspect_ratio + view.x = bounds.x + (bounds.width - view.width) * 0.5 } else { - view.height = rect.width / aspect_ratio - view.y = rect.y + (rect.height - view.height) * 0.5 + view.height = bounds.width / aspect_ratio + view.y = bounds.y + (bounds.height - view.height) * 0.5 } // get scale @@ -32,9 +40,7 @@ gui_screen :: proc(rect: rl.Rectangle, sim: ^Simulator) { // center frame x := i32(view.x + (view.width - f32(draw_w)) * 0.5) y := i32(view.y + (view.height - f32(draw_h)) * 0.5) - rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY) - rl.DrawRectangleLinesEx(view, 2, rl.WHITE) if !sim.rom_loaded { // centered drop-zone text diff --git a/src/simulator/status_bar.odin b/src/simulator/gui_status_bar.odin similarity index 92% rename from src/simulator/status_bar.odin rename to src/simulator/gui_status_bar.odin index e7d18c6..ad11d6d 100644 --- a/src/simulator/status_bar.odin +++ b/src/simulator/gui_status_bar.odin @@ -3,12 +3,14 @@ package simulator import "core:fmt" import rl "vendor:raylib" +StatusIconShape :: enum { CIRCLE, SQUARE } + // @TODO: render status bar text gui_status_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) { // Left to right text draws rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY) - cursor: f32 = rect.x + PADDING + cursor: f32 = rect.x + PADDING_X cy := rect.y + rect.height * 0.5 if sim.running && !sim.paused { @@ -23,7 +25,7 @@ gui_status_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) { // FPS set far right fps_text := fmt.ctprintf("FPS: %d", rl.GetFPS()) fps_width := rl.MeasureTextEx(sim.font, fps_text, f32(sim.font.baseSize), 1).x - fps_x := rect.x + rect.width - PADDING - fps_width + fps_x := rect.x + rect.width - PADDING_X - fps_width rl.DrawTextEx( sim.font, @@ -35,8 +37,6 @@ gui_status_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) { ) } -StatusIconShape :: enum { CIRCLE, SQUARE } - status_icon :: proc(cursor: ^f32, cy: f32, color: rl.Color, shape: StatusIconShape, label: cstring, font: rl.Font) { size: f32 = 10 ix := cursor^ + size * 0.5 @@ -48,15 +48,15 @@ status_icon :: proc(cursor: ^f32, cy: f32, color: rl.Color, shape: StatusIconSha cursor^ += size + 6 rl.DrawTextEx(font, label, {cursor^, cy - f32(font.baseSize) * 0.5}, f32(font.baseSize), 1, rl.RAYWHITE) - cursor^ += rl.MeasureTextEx(font, label, f32(font.baseSize), 1).x + PADDING + cursor^ += rl.MeasureTextEx(font, label, f32(font.baseSize), 1).x + PADDING_X } status_divider :: proc(cursor: ^f32, cy: f32) { rl.DrawLineV({cursor^, cy - 8}, {cursor^, cy + 8}, rl.DARKGRAY) - cursor^ += PADDING + cursor^ += PADDING_X } status_text :: proc(cursor: ^f32, cy: f32, text: cstring, font: rl.Font) { rl.DrawTextEx(font, text, {cursor^, cy - f32(font.baseSize) * 0.5}, f32(font.baseSize), 1, rl.RAYWHITE) - cursor^ += rl.MeasureTextEx(font, text, f32(font.baseSize), 1).x + PADDING + cursor^ += rl.MeasureTextEx(font, text, f32(font.baseSize), 1).x + PADDING_X } diff --git a/src/simulator/left_panel.odin b/src/simulator/left_panel.odin deleted file mode 100644 index c6ba6e5..0000000 --- a/src/simulator/left_panel.odin +++ /dev/null @@ -1,155 +0,0 @@ -package simulator - -import "core:log" -import "core:strings" -import rl "vendor:raylib" - -import emu "../machine" -import tfd "../../external/tinyfiledialogs" - -gui_left_panel :: proc(rect: rl.Rectangle, sim: ^Simulator) { - // ── Top panel and components ── - top_panel := rl.Rectangle { - rect.x, - rect.y, - rect.width, - rect.height / 2, - } - rl.DrawRectangleLinesEx(top_panel, 1, rl.DARKGRAY) - - // Dropzone/file loader - file_loader_rect := rl.Rectangle { - top_panel.x, - top_panel.y, - top_panel.width, - (top_panel.height / 3) - PANEL_HEADER - PANEL_PADDING * 2, - } - gui_file_loader(file_loader_rect, sim) - - // ── Bottom panel and components ── - bottom_panel := rl.Rectangle { - rect.x, - rect.y + top_panel.height, - rect.width, - rect.height / 2, - } - rl.DrawRectangleLinesEx(bottom_panel, 1, rl.GREEN) - gui_key_pad(bottom_panel, sim.machine.keypad, sim.font) -} - -gui_file_loader :: proc(rect: rl.Rectangle, sim: ^Simulator) { - rl.GuiPanel(rect, "Rom / File") - - // drop-zone occupies the panel's content area, minus space for the button - drop_zone := rl.Rectangle { - rect.x + PANEL_PADDING, - rect.y + PANEL_HEADER + PANEL_PADDING, - rect.width - PANEL_PADDING * 2, - rect.height - PANEL_HEADER - PANEL_PADDING * 2 - BUTTON_HEIGHT - PANEL_PADDING, - } - rl.DrawRectangleLinesEx(drop_zone, 1, rl.GREEN) - - // centered drop-zone text - text: cstring = "Drop a CHIP-8 ROM here" - text_width := rl.MeasureText(text, BIG_FONT_SIZE) - text_x := drop_zone.x + (drop_zone.width - f32(text_width)) / 2 - text_y := drop_zone.y + (drop_zone.height - f32(BIG_FONT_SIZE)) / 2 - rl.DrawTextEx(sim.font, text, {text_x, text_y}, BIG_FONT_SIZE, 1, rl.WHITE) - - // open rom button below drop-zone - btn_rect := rl.Rectangle { - drop_zone.x, - drop_zone.y + drop_zone.height + PANEL_PADDING, - BUTTON_WIDTH, - BUTTON_HEIGHT, - } - - if rl.GuiButton(btn_rect, "Open ROM") { - ret := tfd.openFileDialog("Open File Dialog", nil, 0, nil, nil, 0,) - rom_path := string(ret) - if rom_path == "" do return - - // reset machine state - emu.reset_machine(sim.machine) - - // load new rom - err := emu.load_rom(sim.machine, rom_path) - if err != nil { - // @TODO: update status bar here - panic("failed to load rom!") - } - - sim.rom_loaded = true - sim.running = true - sim.paused = false - } - - // Handle file drop - if rl.IsFileDropped() { - dropped_file := rl.LoadDroppedFiles() - if dropped_file.count > 0 { - mouse := rl.GetMousePosition() - - if rl.CheckCollisionPointRec(mouse, drop_zone) { - path_str := string(dropped_file.paths[0]) - log.info("file dropped: ", path_str) - // @TODO: Stop sim, reset mem etc, load new rom - } else { - log.info("File dropped outside drop zone, ignoring") - } - } - rl.UnloadDroppedFiles(dropped_file) - } -} - -gui_key_pad :: proc(rect: rl.Rectangle, display: [16]bool, font: rl.Font) { - rl.GuiPanel(rect, "Input / Keypad") - - content := rl.Rectangle { - rect.x + PANEL_PADDING, - rect.y + PANEL_HEADER + PANEL_PADDING, - rect.width - PANEL_PADDING * 2, - rect.height - PANEL_HEADER - PANEL_PADDING * 2, - } - - Key :: struct { - label: string, - index: int, - } - - keys := [16]Key { - {"1", 1}, {"2", 2}, {"3", 3}, {"C", 12}, - {"4", 4}, {"5", 5}, {"6", 6}, {"D", 13}, - {"7", 7}, {"8", 8}, {"9", 9}, {"E", 14}, - {"A", 10}, {"0", 0}, {"B", 11}, {"F", 15}, - } - - btn_width := content.width / 4 - btn_height := content.height / 4 - - for val, idx in keys { - str := strings.clone_to_cstring(val.label) - defer delete(str) - - ri := idx / 4 - ci := idx % 4 - irect := rl.Rectangle { - x = content.x + btn_width * f32(ci), - y = content.y + btn_height * f32(ri), - width = btn_width, - height = btn_height, - } - - if display[val.index] { rl.DrawRectangleRec(irect, rl.BLACK) } - - rl.DrawRectangleLinesEx(irect, 1, rl.GRAY) - rl.DrawTextEx( - font, - str, - rl.Vector2{irect.x + btn_width / 2, irect.y + btn_height / 2}, - KEYPAD_FONT_SIZE, - 1, - rl.WHITE, - ) - } -} diff --git a/src/simulator/right_panel.odin b/src/simulator/right_panel.odin deleted file mode 100644 index 553bc91..0000000 --- a/src/simulator/right_panel.odin +++ /dev/null @@ -1,8 +0,0 @@ -package simulator - -import m "../machine" -import rl "vendor:raylib" - -gui_right_panel :: proc(rect: rl.Rectangle, s: ^m.System) { - rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY) -}