From 6eb9de2b7fa1b269d5263f9820d03a004cfe3efc Mon Sep 17 00:00:00 2001 From: Tiger Jove Date: Mon, 15 Dec 2025 17:57:26 +0100 Subject: [PATCH] feat: room loading --- .../youth_room/youth_room.gd | 3 +- .../youth_room/youth_room.tscn | 1 + src/dev-util/room_template.gd | 6 +- src/singletons/main/main.gd | 92 +++++++++++++------ src/singletons/main/main.tscn | 9 +- src/ui/credits_roll/credits_roll.gd | 5 +- src/ui/curtain/curtain.gd | 18 ++-- src/ui/menu_main/main_menu.gd | 25 +++-- src/ui/menu_main/pause_menu.gd | 2 +- src/ui/menu_main/save_game_list.gd | 29 +++--- 10 files changed, 116 insertions(+), 74 deletions(-) diff --git a/src/base-environments/youth_room/youth_room.gd b/src/base-environments/youth_room/youth_room.gd index deac423..010f5c4 100644 --- a/src/base-environments/youth_room/youth_room.gd +++ b/src/base-environments/youth_room/youth_room.gd @@ -9,6 +9,7 @@ signal ini_room @onready var card_picker: CardPicker = %Picker func start_room(): + $UI.show() save_game = State.save_game save_game.current_room = State.rooms.YOUTH Scenes.completed_sequences = save_game.mementos_complete @@ -28,11 +29,11 @@ func start_room(): func get_ready(): id = State.rooms.YOUTH + %UI.hide() self.show() $sfx/distant_rain.play() $"sfx/rain on window".play() await get_tree().process_frame #TODO: this was 0.1s, not sure if needed at all - %Board.hide() func _ready(): super._ready() diff --git a/src/base-environments/youth_room/youth_room.tscn b/src/base-environments/youth_room/youth_room.tscn index 7c7ba46..2bf8d18 100644 --- a/src/base-environments/youth_room/youth_room.tscn +++ b/src/base-environments/youth_room/youth_room.tscn @@ -1928,6 +1928,7 @@ transform = Transform3D(0.707304, 0, 0.706909, 0, 1, 0, -0.706909, 0, 0.707304, shape = SubResource("BoxShape3D_bq15k") [node name="UI" type="Control" parent="logic"] +unique_name_in_owner = true layout_mode = 3 anchors_preset = 15 anchor_right = 1.0 diff --git a/src/dev-util/room_template.gd b/src/dev-util/room_template.gd index 40cabec..16a3693 100644 --- a/src/dev-util/room_template.gd +++ b/src/dev-util/room_template.gd @@ -18,12 +18,16 @@ func _ready() -> void: State.room = self State.current_room = id +func disable()-> void: + has_stage = false + set_process_input(false) + set_process(false) + func load(): # Override this function to load the state of the chapter from State.save_game pass func play() -> String: - get_ready() start_room() return await proceed diff --git a/src/singletons/main/main.gd b/src/singletons/main/main.gd index 12c94b0..75f0bb4 100644 --- a/src/singletons/main/main.gd +++ b/src/singletons/main/main.gd @@ -20,35 +20,62 @@ var normal_boot : bool = false State.rooms.ENDING: ending_path } +enum AppState {BOOT, MENU, PLAY, PAUSE, CREDITS} + +var app_state: AppState = AppState.BOOT: + set(value): + app_state = value + print_debug("main.gd: app_state changing to: %s" % str(app_state)) + match app_state: + AppState.BOOT: + credits_roll.hide() + main_menu.hide() + pause_menu.hide() + AppState.MENU: + credits_roll.hide() + pause_menu.hide() + main_menu.execute() + AppState.PLAY: + credits_roll.hide() + main_menu.hide() + pause_menu.hide() + curtain.hide() + AppState.PAUSE: + credits_roll.hide() + main_menu.hide() + pause_menu.show() + AppState.CREDITS: + main_menu.hide() + pause_menu.hide() + await credits_roll.play() + +func _enter_tree() -> void: + print_debug("main.gd: _enter_tree()") + func _ready() -> void: print_debug("main.gd: _ready()") await get_tree().process_frame - if normal_boot: - print_debug("main.gd: normal boot") - var path := await main_menu.execute() - await _load_room(path) - else: - print_debug("main.gd: direct boot") - credits_roll.hide() - main_menu.hide() - pause_menu.hide() + main_menu.continue_button.pressed.connect(func(): app_state = AppState.PLAY) + main_menu.credits_button.pressed.connect(func(): app_state = AppState.CREDITS) - await curtain.hide() + if normal_boot: + print_debug("main.gd: normal boot (loading last save and showing main menu)") + app_state = AppState.MENU + else: + print_debug("main.gd: direct boot (hiding menus and entering main loop)") + app_state = AppState.PLAY #await _mainloop() # Debug functionality +func load_game(save: SaveGame) -> void: + print_debug("main.gd: _load_game()") + var room_path := room_paths.get(save.current_room, youth_room_path) as String + await _load_room(room_path) -func _mainloop() -> void: - while true: - var next_scene := await State.room.play() - if (next_scene == null): - break - else: - await _load_room(youth_room_path) - - -func _load_room(next_path: String) -> void: +func _load_room(next_path: String) -> bool: if State.room != null: State.room.unload() + State.room = null + await curtain.show() ResourceLoader.load_threaded_request(next_path, "PackedScene", true) while true: await get_tree().process_frame @@ -58,11 +85,13 @@ func _load_room(next_path: String) -> void: var next_scene := ResourceLoader.load_threaded_get(youth_room_path) as PackedScene State.room = next_scene.instantiate() as RoomTemplate get_tree().root.add_child(State.room) - hide() - break + await State.room.get_ready() + await curtain.hide() + return true ResourceLoader.THREAD_LOAD_FAILED: push_error("Failed to load youth room scene.") - return + break + return false # @@ -113,12 +142,17 @@ func _load_room(next_path: String) -> void: # func _unhandled_input(event: InputEvent) -> void: if event is InputEvent: - if event.is_action_pressed("ui_menu"): - toggle_pause_menu() - -func toggle_pause_menu(): - print_debug("Toggling pause menu") - pass + match app_state: + AppState.BOOT: + pass + AppState.MENU: + pass + AppState.PLAY: + if event.is_action_pressed("ui_menu"): + app_state = AppState.PAUSE + AppState.PAUSE: + if event.is_action_pressed("ui_menu"): + app_state = AppState.PLAY # if not get_tree().paused: # get_tree().paused = true diff --git a/src/singletons/main/main.tscn b/src/singletons/main/main.tscn index 50d7a53..99394a5 100644 --- a/src/singletons/main/main.tscn +++ b/src/singletons/main/main.tscn @@ -201,14 +201,7 @@ text = "Skip this Story" unique_name_in_owner = true visible = false modulate = Color(1, 1, 1, 0) -layout_mode = 0 -anchors_preset = 0 -anchor_right = 0.0 -anchor_bottom = 0.0 -offset_top = 220.0 -offset_bottom = 220.0 -grow_horizontal = 1 -grow_vertical = 1 +layout_mode = 1 [node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] bus = &"music" diff --git a/src/ui/credits_roll/credits_roll.gd b/src/ui/credits_roll/credits_roll.gd index cb284c6..3efcd6c 100644 --- a/src/ui/credits_roll/credits_roll.gd +++ b/src/ui/credits_roll/credits_roll.gd @@ -10,7 +10,7 @@ var playing : bool func _ready() -> void: print_debug("credits_roll.gd: _ready()") original = Handle.position - play() + set_process_input(false) func _process(delta: float) -> void: if playing: @@ -23,6 +23,7 @@ func _input(event: InputEvent) -> void: func play() -> void: print_debug("credits_roll.gd: show()") + set_process_input(true) offset = original Handle.position = original playing = true @@ -34,10 +35,10 @@ func play() -> void: func stop() -> void: print_debug("credits_roll.gd: hide()") + set_process_input(false) var tween := create_tween() tween.tween_property(self, "modulate:a", 0.0, 2.0) await tween.finished playing = false visible = false - \ No newline at end of file diff --git a/src/ui/curtain/curtain.gd b/src/ui/curtain/curtain.gd index 9da5edf..e819b13 100644 --- a/src/ui/curtain/curtain.gd +++ b/src/ui/curtain/curtain.gd @@ -1,6 +1,8 @@ extends Panel class_name Curtain +var _tween : Tween = null + func _ready() -> void: print_debug("curtain.gd: ready()") show() @@ -8,13 +10,17 @@ func _ready() -> void: func show() -> void: visible = true print_debug("curtain.gd: show()") - var tween := create_tween() - tween.tween_property(self, "modulate:a", 1.0, 2.0) - await tween.finished + if _tween != null: + _tween.kill() + _tween = create_tween() + _tween.tween_property(self, "modulate:a", 1.0, 1.0) + await _tween.finished func hide() -> void: print_debug("curtain.gd: hide()") - var tween := create_tween() - tween.tween_property(self, "modulate:a", 0.0, 2.0) - await tween.finished + if _tween != null: + _tween.kill() + _tween = create_tween() + _tween.tween_property(self, "modulate:a", 0.0, 1.0) + await _tween.finished visible = false diff --git a/src/ui/menu_main/main_menu.gd b/src/ui/menu_main/main_menu.gd index 0902f65..eee5058 100644 --- a/src/ui/menu_main/main_menu.gd +++ b/src/ui/menu_main/main_menu.gd @@ -7,7 +7,7 @@ class_name MainMenu extends Panel @onready var settings_popup: SettingsPopup = %SettingsPopup @onready var credits_button: Button = $PanelContainer/CreditsButton @onready var quit_button: Button = $PanelContainer/QuitButton -@onready var save_game_handle: SaveGameList = %SaveGameList +@onready var save_game_list: SaveGameList = %SaveGameList # Internal Signals signal _next_room(result: String) @@ -26,8 +26,6 @@ func execute() -> String: continue_button.disabled = false new_game_button.theme_type_variation = "" - #save_game_handle.visible = save_game_handle.has_existing_saves() - _activate() var result = await _next_room _deactivate() @@ -46,7 +44,6 @@ func _ready() -> void: credits_button.pressed.connect(_choose.bind("credits")) #FIXME: Needs some other encoding, like path quit_button.pressed.connect(get_tree().quit) - func _new_game() -> void: print_debug("main_menu.gd: start_new_game()") State.save_game = SaveGame.new() @@ -60,8 +57,12 @@ func _start_game() -> void: func _load_save_game() -> void: print_debug("main_menu.gd: _load_save_game()") - var save: SaveGame = await save_game_handle.pick_save_slot() - _on_save_picked(save) + _deactivate() + var save: SaveGame = await save_game_list.pick_save_slot() + if (save != null): + State.save_game = save + await Main.load_game(save) + _activate() func _choose(choice: String) -> void: @@ -70,7 +71,10 @@ func _choose(choice: String) -> void: func _activate() -> void: - load_game_button.disabled = not save_game_handle.has_existing_saves() + load_game_button.disabled = not save_game_list.has_more_saves() + continue_button.disabled = (State.save_game == null or State.save_game.is_empty) + + load_game_button.disabled = not save_game_list.has_more_saves() for child: Control in $PanelContainer.get_children(): child.focus_mode = Control.FOCUS_ALL @@ -88,10 +92,3 @@ func _deactivate() -> void: child.focus_mode = FOCUS_NONE child.modulate = Color.WEB_GRAY child.mouse_filter = Control.MOUSE_FILTER_IGNORE - - -func _on_save_picked(save: SaveGame): - print_debug("main_menu.gd: _on_save_picked(", save, ")") - if (save != null): - State.save_game = save - _next_room.emit("start_game") diff --git a/src/ui/menu_main/pause_menu.gd b/src/ui/menu_main/pause_menu.gd index 1d8ea3e..d825bb1 100644 --- a/src/ui/menu_main/pause_menu.gd +++ b/src/ui/menu_main/pause_menu.gd @@ -9,7 +9,7 @@ class_name PauseManu extends PanelContainer # Called when the node enters the scene tree for the first time. func _ready() -> void: - resume_button.pressed.connect(owner.toggle_pause_menu) + resume_button.pressed.connect(func(): Main.app_state = Main.AppState.PLAY) #to_menu_button.pressed.connect(_process) to_desktop_button.pressed.connect(func(): get_tree().quit()) #to_settings_button.pressed.connect(_process) diff --git a/src/ui/menu_main/save_game_list.gd b/src/ui/menu_main/save_game_list.gd index a7359fa..08669aa 100644 --- a/src/ui/menu_main/save_game_list.gd +++ b/src/ui/menu_main/save_game_list.gd @@ -15,6 +15,7 @@ func _validate_property(property: Dictionary) -> void: if property.name == "saves": property.usage = PROPERTY_USAGE_READ_ONLY + PROPERTY_USAGE_SCRIPT_VARIABLE + PROPERTY_USAGE_EDITOR +var _tween: Tween = null func _ready() -> void: _load_games() @@ -74,16 +75,18 @@ func _rebuild_buttons() -> void: func _on_game_picked(id: int) -> void: - hide() - #_picked.emit(saves[id]) + _picked.emit(saves[id]) func get_most_recent_save() -> SaveGame: _sort_saves() return saves[0] if saves.size() > 0 else SaveGame.new() -func has_existing_saves() -> bool: - return saves.size() > 1 +func has_more_saves() -> bool: + for save in saves: + if save != State.save_game: + return true + return false func _input(event: InputEvent) -> void: if event.is_action_pressed("ui_cancel"): @@ -102,16 +105,18 @@ func pick_save_slot() -> SaveGame: # TODO: ugh, godot tweens are the wurst func open() -> void: show() - set_process_input(true) save_buttons[0].grab_focus() modulate = Color.TRANSPARENT - var tween := get_tree().create_tween() - tween.tween_property(self, "modulate", Color.WHITE, 0.5) - await tween.finished + if _tween != null: + _tween.kill() + _tween = create_tween() + _tween.tween_property(self, "modulate", Color.WHITE, 0.5) + await _tween.finished func close() -> void: - set_process_input(false) - var tween := get_tree().create_tween() - tween.tween_property(self, "modulate", Color.TRANSPARENT, 0.5) - await tween.finished + if _tween != null: + _tween.kill() + _tween = create_tween() + _tween.tween_property(self, "modulate", Color.TRANSPARENT, 0.5) + await _tween.finished hide()