xiandie/scene/entity/ux/sign.gd

117 lines
3.0 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

@tool
class_name Sign extends TextureRect
# @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:
set(val):
show_sign = val
if val:
modulate.a = 1.0
else:
modulate.a = 0.0
signal interacted
signal cancel
# 同时只能有一个物品被激活交互态,其他物品进入等待队列
static var occupied: NodePath
static var _pending_activate_sign := [] as Array[NodePath]
# 使用互斥锁保证线程安全。在操作 occupied 或 _pending_activate_sign 时需要先锁定,操作完成后解锁
static var mutex = Mutex.new()
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
if not is_node_ready():
await ready
var path := get_path()
mutex.lock()
if occupied and occupied != path:
_pending_activate_sign.append(path)
mutex.unlock()
return
else:
occupied = 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)
# if activated:
# focus_mode = FOCUS_ALL
# grab_focus()
func disactivate(_body: Node2D) -> void:
# release_focus()
mutex.lock()
if activated:
activated = false
occupied = ""
while _pending_activate_sign.size() > 0:
var path = _pending_activate_sign.pop_front()
var _sign = get_node_or_null(path)
if _sign:
_sign.activate(null)
break
else:
# make sure the sign is not in the pending list
_pending_activate_sign.erase(get_path())
# double check. because the sign may be activated by other body
if activated:
disactivate(_body)
mutex.unlock()
# point_light.energy = 0.0
if show_sign:
create_tween().tween_property(self, "modulate:a", 0.0, 0.2)
func _unhandled_input(event: InputEvent) -> void:
if activated:
if event.is_action_pressed("interact"):
interacted.emit()
if is_inside_tree():
# grab focus 放在 emit 后面,避免在 emit 时 prop hud 失去 focus
# 传送时会导致 is_inside_tree 为 false此时也无需与 prop hud 抢占 focus
focus_mode = FOCUS_ALL
grab_focus()
elif event.is_action_pressed("cancel"):
cancel.emit()
release_focus()
var viewport = get_viewport()
if viewport:
viewport.set_input_as_handled()