xiandie/scene/entity/ux/sign.gd
2024-12-27 21:52:11 +08:00

134 lines
3.4 KiB
GDScript

# @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:
set(val):
audio_collection = val
if random_audio_player:
random_audio_player.audio_collections.clear()
random_audio_player.audio_collections.append(audio_collection)
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