@tool class_name GroundLoader extends Node2D @export_group("Scene") @export var ignore_archive := false @export var current_scene := "c02_s01" @export var entrance_portal := "left" @export var debug_reload := false: set(new_val): debug_reload = false if current_scene and entrance_portal: transition_to_scene(current_scene, entrance_portal, true) @export var archive_scene := "" @export var archive_portal := "" var first_entered := true var ground: Ground2D var scenes_dir = "res://scene/ground/scene/" var ground_dict = {} func _ready() -> void: _read_grounds() ground = get_node_or_null("Ground") # load save if not ignore_archive: _load_save() if archive_scene and archive_portal: current_scene = archive_scene entrance_portal = archive_portal if current_scene and entrance_portal: transition_to_scene(current_scene, entrance_portal, true) elif ground: ground.queue_free() ground = null func _read_grounds() -> void: # 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 # # 确保每个 ground 都初始化 archive # for key in ground_dict.keys(): # if GlobalConfig.DEBUG: # print("check ground_archive:", key) # ArchiveManager.archive.ground_archive(key) func _load_save(): if not Engine.is_editor_hint() and ArchiveManager.archive: if ArchiveManager.archive.current_scene: archive_scene = ArchiveManager.archive.current_scene if ArchiveManager.archive.entrance_portal: archive_portal = ArchiveManager.archive.entrance_portal func transition_to_scene(key: String, portal: String, immediately := false) -> void: var scene_path = ground_dict[key] if scene_path: var scene = load(scene_path).instantiate() current_scene = key entrance_portal = portal # 优先更新 archive,使 ground 可以访问自己的 current_scene 键值 _update_archive() if immediately: _do_transition(scene) # 更新玩家位置 if first_entered: _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)) if player: tween.tween_callback(func(): player.action_locked = false) first_entered = false else: print("Scene not found: " + key) func _update_player_position(): if ignore_archive or Engine.is_editor_hint(): 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 # fixed y if ground.player_y_fixed: player.global_position.y = ground.player_y player.set_facing_direction(ArchiveManager.archive.player_direction) func _do_transition(scene: Node2D): if ground: # 提前移除,防止命名冲突 remove_child(ground) ground.queue_free() ground = scene.get_child(0) scene.remove_child(ground) ground.owner = null scene.queue_free() add_child(ground) ground.name = "Ground" if not Engine.is_editor_hint(): var portal_node = ground.get_node_or_null("DeployLayer/portal_" + entrance_portal) as Node2D if portal_node: var player = SceneManager.get_player() if player: # player.global_position.x = -20.0 player.global_position.x = portal_node.global_position.x if GlobalConfig.DEBUG: print("move player to portal:", entrance_portal, portal_node.global_position) else: printerr(current_scene + " portal not found: " + entrance_portal) if GlobalConfig.DEBUG and not Engine.is_editor_hint(): _watch_scene_update() func _update_archive(): if not Engine.is_editor_hint() and ArchiveManager.archive: ArchiveManager.archive.current_scene = current_scene ArchiveManager.archive.entrance_portal = entrance_portal archive_scene = current_scene archive_portal = entrance_portal var update_watcher: Timer var last_modify_time = 0 # DEBUG 时重新加载资源 func _watch_scene_update(): var scene_path = ground_dict[current_scene] if scene_path: last_modify_time = 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_time: last_modify_time = modify _on_resources_reload(scene_path) func _on_resources_reload(res): print("resources_reload processing:", res) if not Engine.is_editor_hint() and res.ends_with(".tscn"): ArchiveManager.save_all() transition_to_scene(current_scene, entrance_portal, true)