class_name RootUI extends CanvasLayer @export var startup_scene:PackedScene @export var game_scene:PackedScene @export var autostart_game_scene:bool = true @onready var scene = %Scene @onready var ui_panels:Array = [ %MainMenuUI, %StartGameMenuUI, %CreateGameUI, %GameUI ] @onready var active_ui_panel:Control = null enum ROOT_UI_STATE { UNDEFINED, MENU, GAME } var _root_ui_state:ROOT_UI_STATE = ROOT_UI_STATE.UNDEFINED var current_level_resource:String var current_game_profile:GameProfileResource = null var current_game_profile_directory:String = "" var _game_build_system:BuildSystem = null func _ready(): if autostart_game_scene: load_scene(game_scene) set_root_ui_state(ROOT_UI_STATE.GAME) else: set_root_ui_state(ROOT_UI_STATE.MENU) %CreateGameUI.start_game.connect(_on_start_game_profile) %StartGameMenuUI.start_game.connect(_on_start_game_profile) func activate_ui_panel(ui_panel:Control): for control in ui_panels: if control == ui_panel: control.visible = true else: control.visible = false active_ui_panel = ui_panel func load_scene(scene_resource:PackedScene): for scene_child in scene.get_children(): scene_child.queue_free() scene_child.get_parent().remove_child(scene_child) print("Loading level '" + scene_resource.resource_path + "'") scene.add_child(scene_resource .instantiate()) current_level_resource = scene_resource.resource_path _game_build_system = scene.find_child("BuildSystem", true, false) as BuildSystem var player:Player = scene.find_child("Player", true, false) InteractionSystem.player = player func save_game(): var player:Player = scene.find_child("Player", true, false) if player == null: push_error("Cannot load game: no player found!") return var save_data:SaveGameResource = SaveGameResource.new() save_data.level = current_level_resource save_data.level_pickup_items = %GameUI.picked_up_level_items save_data.player_transform = player.global_transform for node:Node in get_tree().get_nodes_in_group("quest_state"): save_data.quest_states[node.name] = {} for property in node.get_property_list(): if (property.usage & PROPERTY_USAGE_STORAGE != 0) and (property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE) != 0: save_data.quest_states[node.name][property.name] = node.get(property.name) for item_stack in player.inventory.get_item_stacks(): save_data.inventory.append({"item": item_stack.item, "count": item_stack.count}) for structure:BuiltStructure in get_tree().get_nodes_in_group("built_structure"): var built_structure_resource = BuiltStructureResource.new() built_structure_resource.global_transform = structure.global_transform built_structure_resource.item = structure.item var item_array = save_data.built_structures.find_key(structure.item) if item_array == null: item_array = [] save_data.built_structures[structure.item] = item_array item_array.append(structure.global_transform) print("Saving game: " + current_game_profile_directory + "/savegame.tres") ResourceSaver.save(save_data, current_game_profile_directory + "/savegame.tres") activate_ui_panel(%GameUI) func load_game(): set_root_ui_state(RootUI.ROOT_UI_STATE.UNDEFINED) %GameUI.picked_up_level_items.clear() print("Loading game: " + current_game_profile_directory + "/savegame.tres") var save_data:SaveGameResource = load(current_game_profile_directory + "/savegame.tres") as SaveGameResource var level_resource:PackedScene = load(save_data.level) load_scene(level_resource) var player:Player = scene.find_child("Player", true, false) if player == null: push_error("Cannot load game: no player found!") return player.global_transform = save_data.player_transform player.init_look_target_direction() # Quest state for quest_state:Node in get_tree().get_nodes_in_group("quest_state"): for property in quest_state.get_property_list(): if (property.usage & PROPERTY_USAGE_STORAGE != 0) and (property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE) != 0 and (save_data.quest_states.has(quest_state.name)) and (save_data.quest_states[quest_state.name].has(property.name)): quest_state.set(property.name, save_data.quest_states[quest_state.name][property.name]) # Inventory player.inventory.clear() var inventory_item_stacks:Array[ItemStack] = player.inventory.get_item_stacks() assert(inventory_item_stacks.size() >= save_data.inventory.size()) for i in range(save_data.inventory.size()): inventory_item_stacks[i].item = save_data.inventory[i]["item"] inventory_item_stacks[i].count = save_data.inventory[i]["count"] # Picked up items for item_path in save_data.level_pickup_items: if get_tree().root.has_node(item_path): var item_node = get_tree().root.get_node(item_path) %GameUI.picked_up_level_items.append(item_path) item_node.queue_free() # Built structures for item:ItemResource in save_data.built_structures.keys(): var item_transform_array = save_data.built_structures[item] as Array[Transform3D] for structure_transform in item_transform_array: _game_build_system.build_structure(item, structure_transform) set_root_ui_state(RootUI.ROOT_UI_STATE.GAME) func set_root_ui_state(state:ROOT_UI_STATE): if _root_ui_state == state: return if state == ROOT_UI_STATE.GAME: %GameUI.activate_game_scene(scene.get_child(0)) activate_ui_panel(%GameUI) elif state == ROOT_UI_STATE.MENU: load_scene(startup_scene) %GameUI.activate_game_scene(null) activate_ui_panel(%MainMenuUI) _root_ui_state = state func _on_start_game_profile(profile_path:String) -> void: current_game_profile = null current_game_profile_directory = "" print ("Root UI: Starting game from profile path " + profile_path) current_game_profile = ResourceLoader.load(profile_path) if current_game_profile == null: push_error("Error loading game profile " + profile_path) return # Update last_played timestamp current_game_profile.last_played = Time.get_datetime_string_from_system() ResourceSaver.save(current_game_profile, profile_path) current_game_profile_directory = profile_path.get_base_dir() if not _is_savegame_available(): var level_resource:PackedScene = game_scene load_scene(level_resource) save_game() load_game() activate_ui_panel(%GameUI) func _is_savegame_available() -> bool: if current_game_profile_directory == "": return false var game_profile_directory = DirAccess.open(current_game_profile_directory) return game_profile_directory.file_exists("savegame.tres") func _on_start_game_button_pressed(): load_scene(game_scene) set_root_ui_state(ROOT_UI_STATE.GAME) func _on_quit_game_scene(): save_game() set_root_ui_state(ROOT_UI_STATE.MENU) func _on_quit_button_pressed(): get_tree().quit() func _activate_main_menu_ui(): activate_ui_panel(%MainMenuUI) func _activate_start_game_menu_ui(): activate_ui_panel(%StartGameMenuUI) func _activate_create_game_ui(): %CreateGameUI.game_name_edit.text = "" activate_ui_panel(%CreateGameUI) func _activate_game_ui(): activate_ui_panel(%GameUI)