@tool extends Interactable2D class_name Closeup2D # 退出信号,默认 arg 为 null,可能是一个 bool 值,从 packed_scene 的 exit 信号中传递过来 signal exit(arg) @export var packed_scene: PackedScene @export var quit_closeup_on_escape := true @export_tool_button("新建特写场景") var create_closeup_scene = _create_scene_with_script var current_child: Node func _ready() -> void: super._ready() if Engine.is_editor_hint(): return interacted.connect(display) # 可以直接调用 func display() -> void: if current_child: return if packed_scene: if GlobalConfig.DEBUG: print("[" + name + "] call lock") SceneManager.lock_player(0, action_key) # 展示时,禁用 sign_mark 的输入 sign_mark.pass_unhandled_input = true current_child = packed_scene.instantiate() add_child(current_child) if current_child.has_signal("exit"): current_child.connect("exit", _exit) elif GlobalConfig.DEBUG: print("[特写界面] no exit signal, packed_scene:", packed_scene) func _exit(arg = null): if current_child: if GlobalConfig.DEBUG: print("[" + name + "] call lock") SceneManager.unlock_player() if current_child: remove_child(current_child) current_child.queue_free() current_child = null print("quit [", name, "] arg=", arg) exit.emit(arg) # 退出时,恢复 sign_mark 的输入 sign_mark.pass_unhandled_input = false func _unhandled_input(event: InputEvent) -> void: if not current_child: return if ( quit_closeup_on_escape and (event.is_action_pressed("cancel") or event.is_action_pressed("escape")) ): _exit() get_viewport().set_input_as_handled() # 在有特写界面时,阻塞 interact 输入 elif event.is_action_pressed("interact"): get_viewport().set_input_as_handled() ###### TOOL BUTTON var scene_root_dir var script_template = preload("uid://dnrql1t0j6v8i") as Script var scene_template = preload("uid://beifpduqgoyvo") as PackedScene var script_root_dir = "res://scene/ground/script/" func _create_scene_with_script(): if packed_scene: print_rich("[color=orange][Closeup2D] packed_scene already exists, skip creating new scene and script.") return var script = script_template.duplicate(true) as Script var new_packed_scene = PackedScene.new() var ground = get_node("..") while ground and not ground is Ground2D: ground = ground.get_node("..") if not ground: printerr("[Closeup2D] _create_script Ground2D not found.") return var chapter = ground.scene_name.substr(0, 3) var section = ground.scene_name.substr(4, 3) if len(chapter) != 3 or len(section) != 3: printerr("[Closeup2D] ground scene_name error: %s" % ground.scene_name) return var base_file_name = script_root_dir + chapter + "/" + section + "_" + name.to_snake_case() script.resource_path = base_file_name + ".gd" new_packed_scene.resource_path = base_file_name + ".tscn" ResourceSaver.save(script, script.resource_path) var scene_node = scene_template.instantiate() scene_node.set_script(script) scene_node.name = name new_packed_scene.pack(scene_node) ResourceSaver.save(new_packed_scene) packed_scene = load(new_packed_scene.resource_path) print( ( "[Closeup2D] Script and scene created: %s, %s" % [script.resource_path, new_packed_scene.resource_path] ) )