@tool class_name Pickable2D extends Node2D signal triggered @export var enabled := true: set(val): enabled = val if is_node_ready(): _check_sign_display() var prop_key := "" @onready var sfx = $Sfx as Sfx @onready var sign_mark := %Sign as Sign @onready var area := %Area2D as Area2D var ground_archive: GroundArchive var picked: bool: set(val): picked = val if not Engine.is_editor_hint() and ground_archive: ground_archive.set_pair(name, "picked", picked) func reset() -> void: if picked: picked = false _check_sign_display() # 渐渐浮现 func enable_with_ease(duration := 1.0): enabled = true if not picked: var tween = create_tween() tween.tween_property(self, "modulate:a", 1.0, duration).from(0.0) # Called when the node enters the scene tree for the first time. func _ready() -> void: if Engine.is_editor_hint(): var animation_player = _get_animation_player() # 更新 hook_animation 的可选项 if animation_player: animation_player.animation_libraries_updated.connect(notify_property_list_changed) return # setup default value ground_archive = ArchiveManager.archive.ground_archive() picked = ground_archive.get_value(name, "picked", false) sign_mark.enabled = enabled _check_sign_display() if picked: if GlobalConfig.DEBUG: print("Prop has picked, name=", name, " key=", prop_key) sign_mark.interacted.connect(_interacted) func _check_sign_display(): visible = enabled and not picked sign_mark.enabled = visible func _get_animation_player() -> AnimationPlayer: var node = get_parent() while node and not node is Ground2D: node = node.get_parent() if node is Ground2D: return node.get_node("AnimationPlayer") as AnimationPlayer return null var trigger_mutex = Mutex.new() func _interacted(): if not enabled or picked: return # 确保只有一个线程进入该逻辑,因为有时 player 碰撞和首次进入 tree 都会触发该方法 if not trigger_mutex.try_lock(): print("pickable trigger mutex lock fail, name=", name) return print("pickable trigger mutex locked, name=", name) picked = true trigger_mutex.unlock() SceneManager.enable_prop_item(prop_key) triggered.emit() if GlobalConfig.DEBUG: print("pickable triggered! name=", name) _check_sign_display() static var item_config_res = preload("res://asset/dialogue/item_description.dialogue") func _get_property_list() -> Array[Dictionary]: var items = [] if Engine.is_editor_hint(): var id = item_config_res.titles["PropItems"] var current_line = item_config_res.lines[id] while current_line: if current_line.has("translation_key"): items.append(current_line.translation_key) if not current_line.has("next_id") or current_line.next_id == "end": break current_line = item_config_res.lines[current_line.next_id] return [ { "name": "prop_key", "type": TYPE_STRING, "hint": PROPERTY_HINT_ENUM_SUGGESTION, "hint_string": ",".join(items), } ] func _get(property: StringName) -> Variant: if property == "prop_key": return prop_key return null func _set(property: StringName, value: Variant) -> bool: if property == "prop_key": prop_key = value return true return false