From 72c564b24acdcabcf5d22df3991acc2a0b79f325 Mon Sep 17 00:00:00 2001 From: Jason Hilder Date: Mon, 21 Sep 2026 07:32:28 +0200 Subject: [PATCH] Updated scene manager. Scene manager now uses multiple event types. UI updates, todo must move to its own file at some point. --- src/scene_manager.odin | 100 +++++++++++++++++++++++++---------------- 1 file changed, 62 insertions(+), 38 deletions(-) diff --git a/src/scene_manager.odin b/src/scene_manager.odin index 3331601..c87ddc9 100644 --- a/src/scene_manager.odin +++ b/src/scene_manager.odin @@ -64,14 +64,11 @@ scene_update :: proc(scene: ^Scene, game: ^Game, input: Input_Event, dt: f32) { update_level(level, input, dt) if input.pause_pressed { - emit_event(Event{ type = .Game_Pause }) + emit_event(.Game_Pause) } - - case .Game_Over: - update_game_over(scene, input) } - // Now handle any events triggered + // Process events triggered during scene updates process_events(game) } @@ -114,9 +111,15 @@ UI_Slider :: struct { step: f32, } +UI_Selector :: struct { + label: cstring, + value_label: cstring, +} + UI_Item :: union { UI_Button, UI_Slider, + UI_Selector, } UI_Menu :: struct { @@ -169,8 +172,17 @@ list_menu_items :: proc(canvas: Canvas, menu: UI_Menu) { minValue = 0.0, maxValue = 1.0, ) - } + case UI_Selector: + // draw label left half + lbl_y := i32(item_rec.y + (item_rec.height * 0.5)) - 10 + rl.DrawText(v.label, i32(item_rec.x + 15), lbl_y, 20, text_color) + + display_str := fmt.ctprintf("< %s >", v.value_label) + str_w := rl.MeasureText(display_str, 20) + val_x := i32(item_rec.x + item_rec.width) - str_w - 15 + rl.DrawText(display_str, val_x, lbl_y, 20, text_color) + } } } @@ -226,21 +238,21 @@ update_main_menu :: proc(scene: ^Scene, input: Input_Event) { if input.up_pressed { menu.selected_index = (menu.selected_index - 1 + menu.count) % menu.count - emit_event(Event{ type = .UI_Select }) + emit_event(.UI_Select) } if input.down_pressed { menu.selected_index = (menu.selected_index + 1) % menu.count - emit_event(Event{ type = .UI_Select }) + emit_event(.UI_Select) } if input.confirm_pressed { switch menu.selected_index { case 0: - emit_event(Event{ type = .Game_Start }) + emit_event(.Game_Start) case 1: - emit_event(Event { type = .Game_Settings }) + emit_event(.Game_Settings) case 2: - emit_event(Event{ type = .Game_Quit }) + emit_event(.Game_Quit) } } } @@ -278,7 +290,8 @@ render_pause_menu :: proc(scene: Scene) { menu, menu_ok := canvas.menu.? assert(menu_ok, "render_pause_menu: Canvas is missing a UI_Menu component") - rl.DrawRectangleRec(canvas.bounds, rl.Color{0, 0, 0, 220}) + // Semi-transparent overlay so gameplay stays visible behind menu + rl.DrawRectangleRec(canvas.bounds, rl.Color{0, 0, 0, 200}) t_text: cstring = "PAUSE MENU" t_width := rl.MeasureText(t_text, 40) @@ -297,36 +310,39 @@ update_pause_menu :: proc(scene: ^Scene, input: Input_Event) { if input.up_pressed { menu.selected_index = (menu.selected_index - 1 + menu.count) % menu.count - emit_event(Event{ type = .UI_Select }) + emit_event(.UI_Select) } if input.down_pressed { menu.selected_index = (menu.selected_index + 1) % menu.count - emit_event(Event{ type = .UI_Select }) + emit_event(.UI_Select) } if input.confirm_pressed { switch menu.selected_index { case 0: - emit_event(Event{ type = .Game_Resume }) + emit_event(.Game_Back) case 1: - emit_event(Event { type = .Game_Settings }) + emit_event(.Game_Settings) case 2: - emit_event(Event{ type = .Game_Main_Menu }) + emit_event(.Game_Main_Menu) } } if input.pause_pressed { - emit_event(Event{ type = .Game_Resume }) + emit_event(.Game_Back) } } // ------------------------------------------------------------------------------ // Settings Menu // ------------------------------------------------------------------------------ -make_settings_menu :: proc(audio: ^Audio_Manager) -> Scene { +make_settings_menu :: proc(audio: ^Audio_Manager, current_res_label: cstring) -> Scene { ui_items:[8]UI_Item = { 0 = UI_Button{"Back"}, - 1 = UI_Button{"Resolution"}, + 1 = UI_Selector{ + label = "Resolution", + value_label = current_res_label, + }, 2 = UI_Slider{ label = "Music Volume", value = &audio.user_music_vol, @@ -362,6 +378,7 @@ render_settings_menu :: proc(scene: Scene) { menu, menu_ok := canvas.menu.? assert(menu_ok, "render_settings_menu: Canvas is missing a UI_Menu component") + // Dark semi-transparent overlay rl.DrawRectangleRec(canvas.bounds, rl.Color{0, 0, 0, 255}) t_text: cstring = "SETTINGS" @@ -381,11 +398,11 @@ update_settings_menu :: proc(scene: ^Scene, input: Input_Event) { if input.up_pressed { menu.selected_index = (menu.selected_index - 1 + menu.count) % menu.count - emit_event(Event{ type = .UI_Select }) + emit_event(.UI_Select) } if input.down_pressed { menu.selected_index = (menu.selected_index + 1) % menu.count - emit_event(Event{ type = .UI_Select }) + emit_event(.UI_Select) } current_item := &menu.items[menu.selected_index] @@ -395,22 +412,29 @@ update_settings_menu :: proc(scene: ^Scene, input: Input_Event) { if input.confirm_pressed { switch menu.selected_index { case 0: - emit_event(Event{ type = .Game_Main_Menu }) + emit_event(.Game_Back) } } - case UI_Slider: + + case UI_Selector: if input.left_pressed { - // Decrement value by step and keep within normalized 0.0 - 1.0 bounds + emit_event(Change_Resolution_Data{-1}) + + } + if input.right_pressed { + emit_event(Change_Resolution_Data{1}) + } + + case UI_Slider: + if input.left_pressed { v.value^ = clamp(v.value^ - v.step, 0.0, 1.0) - emit_event(Event{ type = .UI_Select }) + emit_event(.UI_Select) } if input.right_pressed { - // Increment value by step and keep within normalized 0.0 - 1.0 bounds v.value^ = clamp(v.value^ + v.step, 0.0, 1.0) - emit_event(Event{ type = .UI_Select }) + emit_event(.UI_Select) } } - } // ------------------------------------------------------------------------------ @@ -423,7 +447,7 @@ make_game_over_overlay :: proc(winner_is_player: bool) -> Scene { } return Scene{ - type = .Game_Over, + type = .Game_Over, winner_is_player = winner_is_player, canvas = Canvas{ bounds = rl.Rectangle{0, 0, VIEWPORT_W, VIEWPORT_H}, @@ -441,12 +465,12 @@ make_game_over_overlay :: proc(winner_is_player: bool) -> Scene { render_game_over :: proc(scene: Scene) { canvas, canvas_ok := scene.canvas.? - assert(canvas_ok, "update_game_over: Scene is missing a Canvas component") + assert(canvas_ok, "render_game_over: Scene is missing a Canvas component") menu, menu_ok := canvas.menu.? - assert(menu_ok, "update_game_over: Canvas is missing a UI_Menu component") + assert(menu_ok, "render_game_over: Canvas is missing a UI_Menu component") - rl.DrawRectangleRec(canvas.bounds, rl.Color{0, 0, 0, 255}) + rl.DrawRectangleRec(canvas.bounds, rl.Color{0, 0, 0, 220}) t_text: cstring = scene.winner_is_player ? "YOU WIN!" : "GAME OVER" t_width := rl.MeasureText(t_text, 40) @@ -466,25 +490,25 @@ update_game_over :: proc(scene: ^Scene, input: Input_Event) { if input.up_pressed { menu.selected_index = (menu.selected_index - 1 + menu.count) % menu.count - emit_event(Event{ type = .UI_Select }) + emit_event(.UI_Select) } if input.down_pressed { menu.selected_index = (menu.selected_index + 1) % menu.count - emit_event(Event{ type = .UI_Select }) + emit_event(.UI_Select) } if input.confirm_pressed { switch menu.selected_index { case 0: - emit_event(Event{ type = .Game_Start }) + emit_event(.Game_Start) case 1: - emit_event(Event{ type = .Game_Main_Menu }) + emit_event(.Game_Main_Menu) } } } // ------------------------------------------------------------------------------ -// Game Play Scene +// Gameplay Scene // ------------------------------------------------------------------------------ make_gameplay_scene :: proc() -> Scene { return Scene{