# @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 @export var volume_db := -5.0: set(val): volume_db = val if random_audio_player: random_audio_player.volume_db = volume_db @export var audio_collection: AudioStreamCollection 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 random_audio_player: RandomAudioStreamPlayer # 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) # # add child # add_child(sprite2d) # sprite2d.modulate.a = 0 # if Engine.is_editor_hint(): # sprite2d.modulate.a = 1 # _load_sprite() modulate.a = 0 if audio_collection: random_audio_player = RandomAudioStreamPlayer.new() random_audio_player.audio_collections.append(audio_collection) random_audio_player.bus = GlobalConfig.AUDIO_BUS_SFX random_audio_player.volume_db = volume_db add_child(random_audio_player) # 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() if show_sign and random_audio_player: random_audio_player.play_random() 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