package simulator import emu "../machine" import rl "vendor:raylib" // @ Window WINDOW_WIDTH :: 1920 WINDOW_HEIGHT :: 1080 // @ Layout proportions // Sidebar takes 20% of screen width on each side; display takes the rest. // The center column splits vertically: 40% display, 60% debug panel. SIDEBAR_PERCENT :: f32(0.20) DISPLAY_V_RATIO :: f32(0.40) // @ Fixed heights CONTROL_BAR_H :: f32(50) STATUS_BAR_H :: f32(30) // @ Layout constants PADDING_X :: f32(10) PADDING_Y :: f32(8) PANEL_HEADER :: f32(24) // @ Buttons BUTTON_HEIGHT :: 30 BUTTON_WIDTH :: 120 // @ Fonts BIG_FONT_SIZE :: 20 KEYPAD_FONT_SIZE :: 18 Layout :: struct { control_bar : rl.Rectangle, file_loader : rl.Rectangle, keypad : rl.Rectangle, display : rl.Rectangle, bottom_panel : rl.Rectangle, cpu : rl.Rectangle, status_bar : rl.Rectangle, } // Initialize main the gui 'window' run_gui :: proc(sim: ^Simulator) { rl.SetConfigFlags({.WINDOW_RESIZABLE}) rl.InitWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "raylib") rl.InitAudioDevice() rl.SetTargetFPS(60) beep := rl.LoadSound("./assets/sounds/beep.wav") // Load fonts font := rl.LoadFontEx("./assets/fonts/Inter_18pt-Regular.ttf", 18, nil, 0) rl.SetTextureFilter(font.texture, .BILINEAR) sim.font = font rl.GuiLoadStyleDefault() rl.GuiLoadStyle("./assets/raygui_styles/style_dark.rgs") rl.GuiSetFont(font) rl.GuiSetStyle(.DEFAULT, i32(rl.GuiDefaultProperty.TEXT_SIZE), 18) // Draw each of the components in its own window within the main window for !rl.WindowShouldClose() { // Recalculate layout each frame based on current window size // Pass these down to gui functions so they can setup their sizes? screen_width := f32(rl.GetScreenWidth()) screen_height := f32(rl.GetScreenHeight()) sidebar_width := screen_width * 0.20 // set all the layout structs dynamically with the screen size layout := calc_layout(screen_width, screen_height) rl.BeginDrawing() rl.ClearBackground(rl.BLACK) if (!sim.paused) { // Cycle the machine to update memory etc emu.run_machine(sim.machine, 12) // Handle delay timer if sim.machine.delay_timer > 0 do sim.machine.delay_timer -= 1 // Current sound file is around 1s so stop // immediately when timer is 0 if sim.machine.sound_timer > 0 { sim.machine.sound_timer -= 1 if !rl.IsSoundPlaying(beep) do rl.PlaySound(beep) } else { rl.StopSound(beep) } } // Top // ------------------------------------------ gui_control_bar(layout.control_bar, sim) // Left // ------------------------------------------ gui_file_loader(layout.file_loader, sim) gui_key_pad(layout.keypad, sim.machine.keypad, sim.font) // Center // ------------------------------------------ gui_screen(layout.display, sim) // Right // ------------------------------------------ gui_cpu(layout.cpu, sim) // Bottom // ------------------------------------------ gui_bottom_tabs(layout.bottom_panel, sim) gui_status_bar(layout.status_bar, sim) rl.EndDrawing() } rl.UnloadFont(sim.font) rl.UnloadSound(beep) rl.CloseAudioDevice() rl.CloseWindow() } // @TODO: If this grows lets move it into its own file calc_layout :: proc(screen_width: f32, screen_height: f32) -> Layout { // Control bar is a fixed height frozen at top of gui, all items start below it. y_pos := CONTROL_BAR_H x_pos := f32(0) // Usable gui vertical space visible_height := screen_height - CONTROL_BAR_H - STATUS_BAR_H sidebar_width := screen_width * SIDEBAR_PERCENT display_width := screen_width - (sidebar_width * 2) - sidebar_width display_height := visible_height * DISPLAY_V_RATIO x_center := sidebar_width y_center := screen_width - sidebar_width * 2 return Layout { // Left Area control_bar = rl.Rectangle{ x = 0, y = 0, width = screen_width, height = CONTROL_BAR_H, }, file_loader = rl.Rectangle{ x = 0, y = y_pos, width = sidebar_width, height = visible_height / 3 }, keypad = rl.Rectangle{ x = 0, y = (y_pos + visible_height - visible_height / 2), width = sidebar_width, height = visible_height / 2 }, // ------------------------------------------ // Center Area display = rl.Rectangle{ x = sidebar_width, y = y_pos, width = display_width, height = display_height, }, // ------------------------------------------ // Bottom Area bottom_panel = rl.Rectangle{ x = sidebar_width, y = y_pos + display_height, width = screen_width - sidebar_width, height = visible_height - display_height, }, // ------------------------------------------ // Right Area cpu = rl.Rectangle { x = sidebar_width + display_width, y = y_pos, width = sidebar_width * 2, height = display_height }, // ------------------------------------------ // Bottom Area status_bar = rl.Rectangle{ x = x_pos, y = y_pos + visible_height, width = screen_width, height = STATUS_BAR_H, }, } }