@tool class_name GroundLoader extends Node2D @export var ignore_archive := false @export var current_scene := "c02_s01" @export var entrance_portal := "left" var ground: Node2D var scenes_dir = "res://scene/ground/scene/" var ground_dict = {} func _ready() -> void: if not ignore_archive: _load_save() _read_grounds() if current_scene and entrance_portal and not Engine.is_editor_hint(): transition_to_scene(current_scene, entrance_portal, true) func _load_save(): if ArchiveManager.archive: if ArchiveManager.archive.current_scene: current_scene = ArchiveManager.archive.current_scene if ArchiveManager.archive.entrance_portal: entrance_portal = ArchiveManager.archive.entrance_portal func _read_grounds(): var dir = DirAccess.open(scenes_dir) for c_dir in dir.get_directories(): var c_path = scenes_dir + c_dir + "/" for s_file in DirAccess.open(c_path).get_files(): if s_file.ends_with(".tscn"): var s_path = c_path + s_file ground_dict[c_dir.substr(0, 3) + "_" + s_file.substr(0, 3)] = s_path func play_footstep_sound() -> void: if ground and ground.is_visible_in_tree(): ground.play_footstep_sound() func transition_to_scene(key: String, portal: String, load_save := false) -> void: var scene_path = ground_dict[key] if scene_path: var scene = load(scene_path).instantiate() current_scene = key entrance_portal = portal if load_save: _do_transition(scene) # 更新玩家位置 _update_player_position() else: var tween = create_tween() as Tween var player = SceneManager.get_player() as MainPlayer if player: player.action_locked = true #TODO 转场效果 # tween.tween_interval(0.2) tween.tween_callback(_do_transition.bind(scene)) tween.tween_callback(func(): player.action_locked = false) else: print("Scene not found: " + key) func _update_player_position(): if ignore_archive: return var player = SceneManager.get_player() as MainPlayer if player and ArchiveManager.archive: # if GlobalConfig.DEBUG: # print("update player position", ArchiveManager.archive.player_global_position) player.global_position = ArchiveManager.archive.player_global_position player.set_facing_direction(ArchiveManager.archive.player_direction) func _do_transition(scene: Node2D): if ground: ground.queue_free() # 提前移除,防止命名冲突 remove_child(ground) ground = scene.get_child(0) scene.remove_child(ground) scene.queue_free() ground.owner = null add_child(ground) ground.owner = self ground.name = "Ground" _set_camera_and_player_boundary() _update_archive() var portal_node = get_node_or_null("./Ground/DeployLayer/portal_" + entrance_portal) as Node2D if portal_node: print("set player and camera to portal:", entrance_portal, portal_node.global_position) var player = SceneManager.get_player() if player: player.global_position.x = portal_node.global_position.x var camera = SceneManager.get_camera() if camera: camera.global_position.x = portal_node.global_position.x if GlobalConfig.DEBUG: _watch_scene_update() func _set_camera_and_player_boundary(): var bg = ground.get_node("BGSprite2D") if bg.texture: SceneManager.set_camera_boundary(bg.texture.get_size()) SceneManager.set_player_boundary(bg.texture.get_size()) func _update_archive(): if ArchiveManager.archive: ArchiveManager.archive.current_scene = current_scene ArchiveManager.archive.entrance_portal = entrance_portal var update_watcher: Timer var last_modify = 0 func _watch_scene_update(): var scene_path = ground_dict[current_scene] if scene_path: last_modify = FileAccess.get_modified_time(scene_path) if not update_watcher: update_watcher = Timer.new() update_watcher.wait_time = 1 update_watcher.one_shot = false add_child(update_watcher) update_watcher.start() else: # remove all connections for c in update_watcher.timeout.get_connections(): update_watcher.timeout.disconnect(c.callable) update_watcher.timeout.connect(_check_scene_update.bind(scene_path)) func _check_scene_update(scene_path): var modify = FileAccess.get_modified_time(scene_path) if modify != last_modify: last_modify = modify _on_resources_reload(scene_path) func _on_resources_reload(res): print("resources_reload processing:", res) if res.ends_with(".tscn"): ArchiveManager.save_all() transition_to_scene(current_scene, entrance_portal, true)