diff --git a/autoloads/ui_manager.gd b/autoloads/ui_manager.gd new file mode 100644 index 0000000..c85d784 --- /dev/null +++ b/autoloads/ui_manager.gd @@ -0,0 +1,53 @@ +extends Node + +@export var ui_stack: Array[Control] = [] +signal screen_pushed(screen: Control) +signal screen_popped(screen: Control) + + +func push_screen(screen: Control) -> void: + if not screen: + push_error("Cannot push a null screen.") + return + + ui_stack.append(screen) + screen.show() + screen.set_process_input(true) + screen.set_focus_mode(Control.FOCUS_ALL) + screen.grab_focus() + screen_pushed.emit(screen) + + +func pop_screen() -> void: + if ui_stack.is_empty(): + return + + var top: Control = ui_stack.pop_back() + top.hide() + top.set_process_input(false) + screen_popped.emit(top) + + if not ui_stack.is_empty(): + ui_stack.back().grab_focus() + + +func top_screen() -> Control: + return ui_stack.back() if not ui_stack.is_empty() else null + + +func is_screen_on_top(screen: Control) -> bool: + return not ui_stack.is_empty() and ui_stack.back() == screen + + +func is_visible_on_stack(screen: Control) -> bool: + return ui_stack.has(screen) and screen.visible + + +func close_all() -> void: + while not ui_stack.is_empty(): + pop_screen() + + +func hide_and_disable(screen: Control) -> void: + screen.hide() + screen.set_process_input(false) \ No newline at end of file diff --git a/autoloads/ui_manager.gd.uid b/autoloads/ui_manager.gd.uid new file mode 100644 index 0000000..ba8dbd0 --- /dev/null +++ b/autoloads/ui_manager.gd.uid @@ -0,0 +1 @@ +uid://vmhlsc3fu3bn diff --git a/objects/ui_manager.tscn b/objects/ui_manager.tscn new file mode 100644 index 0000000..2898ece --- /dev/null +++ b/objects/ui_manager.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://dyjumgjkqrufa"] + +[ext_resource type="Script" uid="uid://vmhlsc3fu3bn" path="res://autoloads/ui_manager.gd" id="1_53w4j"] + +[node name="UiManager" type="Node"] +script = ExtResource("1_53w4j") diff --git a/project.godot b/project.godot index 0dc192d..3e5f450 100644 --- a/project.godot +++ b/project.godot @@ -34,6 +34,7 @@ SteamControllerInput="*res://autoloads/steam_controller_input.gd" Console="*res://addons/console/console.gd" AchievementsManager="*res://objects/achievements.tscn" ConfigFileHandler="*res://autoloads/config_file_handler.gd" +UiManager="*res://autoloads/ui_manager.gd" [debug] diff --git a/scripts/ui/pause_menu.gd b/scripts/ui/pause_menu.gd index 0c68b5a..1426e65 100644 --- a/scripts/ui/pause_menu.gd +++ b/scripts/ui/pause_menu.gd @@ -11,7 +11,6 @@ extends Node @onready var gm: GM = $"/root/GameManager" -var is_paused: bool = false var is_console_open: bool = false @@ -46,23 +45,19 @@ func _ready() -> void: Console.console_closed.connect(_on_console_close) -func _input(event: InputEvent) -> void: + +func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed("pause") and not is_console_open: - if is_paused: + if UiManager.is_visible_on_stack(pause_menu_control): _on_resume_button_pressed() else: + UiManager.push_screen(pause_menu_control) gm.pause_game() - is_paused = true - pause_menu_control.show() - resume_button.grab_focus() func _on_resume_button_pressed() -> void: - pause_menu_control.hide() - if settings_menu: - settings_menu.hide() + UiManager.pop_screen() gm.resume_game() - is_paused = false func _on_quit_button_pressed() -> void: @@ -74,9 +69,8 @@ func _on_settings_button_pressed() -> void: printerr("PauseMenu: Settings menu scene not set.") return - settings_menu.show() + UiManager.push_screen(settings_menu) gm.pause_game() - is_paused = true func _on_exit_to_menu_button_pressed() -> void: diff --git a/scripts/ui/settings_menu.gd b/scripts/ui/settings_menu.gd index a8c3b58..8fa30cc 100644 --- a/scripts/ui/settings_menu.gd +++ b/scripts/ui/settings_menu.gd @@ -26,7 +26,6 @@ func _ready() -> void: audio_settings.hide() if display_settings: - display_settings_button.pressed.connect(_on_display_settings_button_pressed) display_settings.hide() @@ -35,61 +34,38 @@ func _ready() -> void: gameplay_settings.hide() -func _input(event: InputEvent) -> void: + +func _unhandled_input(event: InputEvent) -> void: if event.is_action_pressed("ui_cancel"): - if settings_menu_control.is_visible(): - settings_menu_control.hide() + if UiManager.is_screen_on_top(settings_menu_control): + UiManager.pop_screen() func _on_input_settings_button_pressed() -> void: if not input_settings: return - if input_settings.is_visible(): - input_settings.hide() - else: - input_settings.show() - audio_settings.hide() - display_settings.hide() - gameplay_settings.hide() + UiManager.push_screen(input_settings) func _on_audio_settings_button_pressed() -> void: if not audio_settings: return - if audio_settings.is_visible(): - audio_settings.hide() - else: - audio_settings.show() - input_settings.hide() - display_settings.hide() - gameplay_settings.hide() + UiManager.push_screen(audio_settings) func _on_display_settings_button_pressed() -> void: if not display_settings: return - if display_settings.is_visible(): - display_settings.hide() - else: - display_settings.show() - input_settings.hide() - audio_settings.hide() - gameplay_settings.hide() + UiManager.push_screen(display_settings) func _on_gameplay_settings_button_pressed() -> void: if not gameplay_settings: return - if gameplay_settings.is_visible(): - gameplay_settings.hide() - else: - gameplay_settings.show() - input_settings.hide() - audio_settings.hide() - display_settings.hide() + UiManager.push_screen(gameplay_settings)