@tool extends Node2D # @export var texture: Texture: # set(val): # texture = val # sprite2d.texture = texture # # @export var base_scale := Vector2.ONE: # # set(val): # # base_scale = val # # sprite2d.scale = base_scale @export var show_sign := true signal interacted signal cancel # 同时只能有一个物品被激活交互态,其他物品进入等待队列 static var occupied: NodePath # 使用互斥锁保证线程安全 static var mutex = Mutex.new() static var _pending_callables: Array[Callable] var own_callable var activated = false # var sprite2d = Sprite2D.new() var base_scale = Vector2.ONE func _ready() -> void: base_scale = scale # layer = GlobalConfig.CANVAS_LAYER_FG var point_light = get_node_or_null("../PointLight2D") if point_light: point_light.energy = 0.0 var area2d = get_node_or_null("../Area2D") if area2d: area2d.body_entered.connect(activate) area2d.body_exited.connect(disactivate) if not Engine.is_editor_hint(): modulate.a = 0 # func _load_sprite() -> void: # sprite2d.texture = texture # sprite2d.scale = base_scale func activate(_body: Node2D) -> void: # point_light.energy = 1.0 mutex.lock() if occupied and occupied != get_path(): own_callable = activate.bind(_body) _pending_callables.append(own_callable) else: occupied = get_path() activated = true mutex.unlock() if activated and show_sign: var tween = create_tween() tween.tween_property(self, "modulate:a", 1.0, 0.2) var p_tween = tween.parallel() p_tween.tween_property(self, "scale", base_scale * Vector2(1.2, 1.2), 0.3) p_tween.tween_property(self, "scale", base_scale, 0.1) func disactivate(_body: Node2D) -> void: activated = false if _unoccupy(): while _pending_callables.size() > 0: var callable = _pending_callables.pop_front() as Callable if callable.is_valid(): callable.call() break # point_light.energy = 0.0 if show_sign: create_tween().tween_property(self, "modulate:a", 0.0, 0.2) func _input(event: InputEvent) -> void: if activated: if event.is_action_pressed("interact"): interacted.emit() elif event.is_action_pressed("cancel"): cancel.emit() func _exit_tree() -> void: if _unoccupy(): while _pending_callables.size() > 0: var callable = _pending_callables.pop_front() as Callable if callable.is_valid(): callable.call() break cancel.emit() func _unoccupy() -> bool: var self_occupied = false mutex.lock() if occupied == get_path(): occupied = "" self_occupied = true elif own_callable: _pending_callables.erase(own_callable) own_callable = null mutex.unlock() return self_occupied