Cleaning up ui components making uniform.
This commit is contained in:
@@ -7,27 +7,23 @@ PADDING :: 10
|
|||||||
|
|
||||||
gui_control_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) {
|
gui_control_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) {
|
||||||
rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY)
|
rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY)
|
||||||
// Small text area
|
|
||||||
|
|
||||||
// Control bar buttons
|
// Cursor moves for every btn call places them left to right with padding
|
||||||
btn_w : f32 = 80
|
cursor : f32 = rect.x + PANEL_PADDING
|
||||||
btn_h : f32 = rect.height - (PADDING * 2)
|
|
||||||
gap : f32 = 6
|
|
||||||
cursor : f32 = rect.x + PADDING
|
|
||||||
|
|
||||||
if btn(&cursor, rect, btn_h, btn_w, gap, "RUN") {
|
if btn(&cursor, rect, BUTTON_HEIGHT, BUTTON_WIDTH, PANEL_PADDING, "RUN") {
|
||||||
log.info("RUN clicked")
|
if sim.rom_loaded {
|
||||||
sim.paused = false
|
sim.paused = false
|
||||||
sim.running = true
|
sim.running = true
|
||||||
|
} else {
|
||||||
|
log.info("no rom selected, can't run")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if btn(&cursor, rect, btn_h, btn_w, gap, "PAUSE") {
|
if btn(&cursor, rect, BUTTON_HEIGHT, BUTTON_WIDTH, PANEL_PADDING, "PAUSE") {
|
||||||
log.info("PAUSE clicked")
|
|
||||||
sim.paused = true
|
sim.paused = true
|
||||||
sim.running = false
|
sim.running = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if btn(&cursor, rect, btn_h, btn_w, gap, "STEP") { log.info("STEP clicked") }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
btn :: proc(cursor: ^f32, rect: rl.Rectangle, h, w, gap: f32, label: cstring) -> bool {
|
btn :: proc(cursor: ^f32, rect: rl.Rectangle, h, w, gap: f32, label: cstring) -> bool {
|
||||||
|
|||||||
+47
-28
@@ -8,24 +8,23 @@ WINDOW_WIDTH :: 1920
|
|||||||
WINDOW_HEIGHT :: 1080
|
WINDOW_HEIGHT :: 1080
|
||||||
|
|
||||||
// @TODO: If this grows lets move it into its own file
|
// @TODO: If this grows lets move it into its own file
|
||||||
|
// ─── Layout constants ───────────────────────────────────────────────────
|
||||||
SIDEBAR_PERCENT :: 0.20
|
SIDEBAR_PERCENT :: 0.20
|
||||||
DISPLAY_PERCENT :: 0.30
|
DISPLAY_PERCENT :: 0.30
|
||||||
CONTROL_BAR_H :: f32(50)
|
CONTROL_BAR_H :: f32(50)
|
||||||
STATUS_BAR_H :: f32(30)
|
STATUS_BAR_H :: f32(30)
|
||||||
|
|
||||||
// ─── Layout constants ───────────────────────────────────────────────────
|
|
||||||
PANEL_PADDING :: 10
|
PANEL_PADDING :: 10
|
||||||
PANEL_HEADER :: 24
|
PANEL_HEADER :: 24
|
||||||
BUTTON_HEIGHT :: 30
|
BUTTON_HEIGHT :: 30
|
||||||
BUTTON_WIDTH :: 120
|
BUTTON_WIDTH :: 120
|
||||||
DROP_FONT_SIZE :: 20
|
BIG_FONT_SIZE :: 20
|
||||||
KEYPAD_FONT_SIZE :: 18
|
KEYPAD_FONT_SIZE :: 18
|
||||||
|
|
||||||
|
|
||||||
Layout :: struct {
|
Layout :: struct {
|
||||||
control_bar : rl.Rectangle,
|
control_bar : rl.Rectangle,
|
||||||
left_panel : rl.Rectangle,
|
left_panel : rl.Rectangle,
|
||||||
display : rl.Rectangle,
|
display : rl.Rectangle,
|
||||||
|
bottom_panel : rl.Rectangle,
|
||||||
right_panel : rl.Rectangle,
|
right_panel : rl.Rectangle,
|
||||||
status_bar : rl.Rectangle,
|
status_bar : rl.Rectangle,
|
||||||
}
|
}
|
||||||
@@ -63,8 +62,8 @@ run_gui :: proc(sim: ^Simulator) {
|
|||||||
rl.BeginDrawing()
|
rl.BeginDrawing()
|
||||||
rl.ClearBackground(rl.BLACK)
|
rl.ClearBackground(rl.BLACK)
|
||||||
|
|
||||||
// Cycle the machine to update memory etc
|
|
||||||
if (!sim.paused) {
|
if (!sim.paused) {
|
||||||
|
// Cycle the machine to update memory etc
|
||||||
emu.run_machine(sim.machine, 12)
|
emu.run_machine(sim.machine, 12)
|
||||||
|
|
||||||
// Handle delay timer
|
// Handle delay timer
|
||||||
@@ -78,16 +77,11 @@ run_gui :: proc(sim: ^Simulator) {
|
|||||||
} else {
|
} else {
|
||||||
rl.StopSound(beep)
|
rl.StopSound(beep)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gui_control_bar(layout.control_bar, sim)
|
gui_control_bar(layout.control_bar, sim)
|
||||||
gui_left_panel(layout.left_panel, sim)
|
gui_left_panel(layout.left_panel, sim)
|
||||||
// gui_right_panel(layout.right_panel, s.machine)
|
gui_screen(layout.display, sim)
|
||||||
|
|
||||||
// Screen is just drawing the display buffer just needs that as arg
|
|
||||||
// Not the whole sim struct
|
|
||||||
gui_screen(layout.display, sim.machine)
|
|
||||||
gui_status_bar(layout.status_bar, sim)
|
gui_status_bar(layout.status_bar, sim)
|
||||||
|
|
||||||
rl.EndDrawing()
|
rl.EndDrawing()
|
||||||
@@ -101,39 +95,64 @@ run_gui :: proc(sim: ^Simulator) {
|
|||||||
|
|
||||||
// @TODO: If this grows lets move it into its own file
|
// @TODO: If this grows lets move it into its own file
|
||||||
calc_layout :: proc(screen_width: f32, screen_height: f32) -> Layout {
|
calc_layout :: proc(screen_width: f32, screen_height: f32) -> Layout {
|
||||||
sidebar_width := screen_width * SIDEBAR_PERCENT
|
top_h := CONTROL_BAR_H
|
||||||
content_height := screen_height - CONTROL_BAR_H - STATUS_BAR_H
|
bottom_h := STATUS_BAR_H
|
||||||
display_height := screen_height * DISPLAY_PERCENT - CONTROL_BAR_H - STATUS_BAR_H
|
content_h := screen_height - top_h - bottom_h
|
||||||
|
content_y := top_h
|
||||||
|
|
||||||
|
sidebar_w := screen_width * SIDEBAR_PERCENT
|
||||||
|
|
||||||
|
screen_h_ratio := 0.40
|
||||||
|
bottom_panel_h := content_h * f32(1.0 - screen_h_ratio)
|
||||||
|
screen_h := content_h * f32(screen_h_ratio)
|
||||||
|
memory_h := content_h - screen_h
|
||||||
|
|
||||||
|
center_x := sidebar_w
|
||||||
|
center_w := screen_width - sidebar_w * 2
|
||||||
|
|
||||||
return Layout {
|
return Layout {
|
||||||
control_bar = rl.Rectangle{
|
control_bar = rl.Rectangle{
|
||||||
x = 0,
|
x = 0,
|
||||||
y = 0,
|
y = 0,
|
||||||
width = screen_width,
|
width = screen_width,
|
||||||
height = CONTROL_BAR_H,
|
height = top_h,
|
||||||
},
|
},
|
||||||
|
|
||||||
left_panel = rl.Rectangle{
|
left_panel = rl.Rectangle{
|
||||||
x = 0,
|
x = 0,
|
||||||
y = CONTROL_BAR_H,
|
y = top_h,
|
||||||
width = sidebar_width,
|
width = sidebar_w,
|
||||||
height = content_height,
|
height = content_h,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// CHIP-8 screen (top center)
|
||||||
display = rl.Rectangle{
|
display = rl.Rectangle{
|
||||||
x = sidebar_width,
|
x = center_x,
|
||||||
y = CONTROL_BAR_H,
|
y = top_h,
|
||||||
width = screen_width - (sidebar_width * 2),
|
width = center_w,
|
||||||
height = display_height,
|
height = screen_h,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// MEMORY / DEBUG panel (bottom center)
|
||||||
|
bottom_panel = rl.Rectangle{
|
||||||
|
x = center_x,
|
||||||
|
y = top_h + screen_h,
|
||||||
|
width = center_w,
|
||||||
|
height = memory_h,
|
||||||
|
},
|
||||||
|
|
||||||
right_panel = rl.Rectangle{
|
right_panel = rl.Rectangle{
|
||||||
x = screen_width - sidebar_width,
|
x = screen_width - sidebar_w,
|
||||||
y = CONTROL_BAR_H,
|
y = top_h,
|
||||||
width = sidebar_width,
|
width = sidebar_w,
|
||||||
height = content_height,
|
height = content_h,
|
||||||
},
|
},
|
||||||
|
|
||||||
status_bar = rl.Rectangle{
|
status_bar = rl.Rectangle{
|
||||||
x = 0,
|
x = 0,
|
||||||
y = screen_height - STATUS_BAR_H,
|
y = screen_height - bottom_h,
|
||||||
width = screen_width, height = STATUS_BAR_H,
|
width = screen_width,
|
||||||
|
height = bottom_h,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-22
@@ -1,38 +1,52 @@
|
|||||||
package simulator
|
package simulator
|
||||||
|
|
||||||
import m "../machine"
|
|
||||||
import rl "vendor:raylib"
|
import rl "vendor:raylib"
|
||||||
|
|
||||||
gui_screen :: proc(rect: rl.Rectangle, s: ^m.System) {
|
gui_screen :: proc(rect: rl.Rectangle, sim: ^Simulator) {
|
||||||
// Make sure screen is staying in its aspect ratio
|
s := sim.machine
|
||||||
chip8_aspect := f32(64.0 / 32.0)
|
|
||||||
available_aspect := rect.width / rect.height
|
|
||||||
screen_rect := rect
|
|
||||||
|
|
||||||
if available_aspect > chip8_aspect {
|
// 2 : 1
|
||||||
// Area is too wide
|
// 2 so, for every 1 unit of height I have 2 units of width
|
||||||
screen_rect.width = rect.height * chip8_aspect
|
// twice as wide as it is tall, or half as tall as it is wide
|
||||||
screen_rect.x = rect.x + (rect.width - screen_rect.width) / 2
|
aspect_ratio : f32 = 64.0 / 32.0
|
||||||
|
|
||||||
|
// create viewport for the ratio
|
||||||
|
view := rect
|
||||||
|
avail_space := rect.width / rect.height
|
||||||
|
|
||||||
|
if avail_space > aspect_ratio {
|
||||||
|
view.width = rect.height * aspect_ratio
|
||||||
|
view.x = rect.x + (rect.width - view.width) * 0.5
|
||||||
} else {
|
} else {
|
||||||
// Area is too tall
|
view.height = rect.width / aspect_ratio
|
||||||
screen_rect.height = rect.width / chip8_aspect
|
view.y = rect.y + (rect.height - view.height) * 0.5
|
||||||
screen_rect.y = rect.y + (rect.height - screen_rect.height) / 2
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pixel_size := min(int(screen_rect.width / 64), int(screen_rect.height / 32))
|
// get scale
|
||||||
pixel_size = max(pixel_size, 1)
|
pixel := min(int(view.width / 64), int(view.height / 32))
|
||||||
|
pixel = max(pixel, 1)
|
||||||
|
|
||||||
actual_width := pixel_size * 64
|
draw_w := pixel * 64
|
||||||
actual_height := pixel_size * 32
|
draw_h := pixel * 32
|
||||||
|
|
||||||
display_x := i32(screen_rect.x) + i32(int(screen_rect.width) - actual_width) / 2
|
// center frame
|
||||||
display_y := i32(screen_rect.y) + i32(int(screen_rect.height) - actual_height) / 2
|
x := i32(view.x + (view.width - f32(draw_w)) * 0.5)
|
||||||
|
y := i32(view.y + (view.height - f32(draw_h)) * 0.5)
|
||||||
|
|
||||||
// Debug borders
|
|
||||||
rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY)
|
rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY)
|
||||||
rl.DrawRectangleLinesEx(screen_rect, 2, rl.WHITE)
|
rl.DrawRectangleLinesEx(view, 2, rl.WHITE)
|
||||||
|
|
||||||
render_display(&s.display, display_x, display_y, i32(pixel_size))
|
if !sim.rom_loaded {
|
||||||
|
// centered drop-zone text
|
||||||
|
text: cstring = "PLEASE SELECT AND LOAD A CHIP 8 ROM"
|
||||||
|
text_width := rl.MeasureText(text, BIG_FONT_SIZE)
|
||||||
|
text_x := view.x + (view.width - f32(text_width)) * 0.6
|
||||||
|
text_y := view.y + (view.height - f32(BIG_FONT_SIZE)) * 0.5
|
||||||
|
|
||||||
|
rl.DrawTextEx(sim.font, text, {text_x,text_y}, BIG_FONT_SIZE, 1, rl.WHITE)
|
||||||
|
} else {
|
||||||
|
render_display(&s.display, x, y, i32(pixel))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private = "file")
|
@(private = "file")
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package simulator
|
|||||||
import "core:fmt"
|
import "core:fmt"
|
||||||
import rl "vendor:raylib"
|
import rl "vendor:raylib"
|
||||||
|
|
||||||
|
// @TODO: render status bar text
|
||||||
gui_status_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) {
|
gui_status_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) {
|
||||||
|
// Left to right text draws
|
||||||
rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY)
|
rl.DrawRectangleLinesEx(rect, 1, rl.DARKGRAY)
|
||||||
|
|
||||||
cursor: f32 = rect.x + PADDING
|
cursor: f32 = rect.x + PADDING
|
||||||
@@ -16,7 +18,21 @@ gui_status_bar :: proc(rect: rl.Rectangle, sim: ^Simulator) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
status_divider(&cursor, cy)
|
status_divider(&cursor, cy)
|
||||||
status_text(&cursor, cy, fmt.ctprintf("FPS: %d", rl.GetFPS()), sim.font)
|
status_text(&cursor, cy, fmt.ctprintf("Rom Loaded: %v", sim.rom_loaded), sim.font)
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
||||||
|
rl.DrawTextEx(
|
||||||
|
sim.font,
|
||||||
|
fps_text,
|
||||||
|
{fps_x, cy - f32(sim.font.baseSize) * 0.5},
|
||||||
|
f32(sim.font.baseSize),
|
||||||
|
1,
|
||||||
|
rl.RAYWHITE,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusIconShape :: enum { CIRCLE, SQUARE }
|
StatusIconShape :: enum { CIRCLE, SQUARE }
|
||||||
|
|||||||
Reference in New Issue
Block a user