xiandie/manager/event_manager/event_binder.gd
2025-07-04 21:03:51 +08:00

109 lines
3.5 KiB
GDScript

@tool
class_name EventBinder extends Node
@export_group("Updater", "updater")
@export var updater_event := &""
@export_enum("enabler", "disabler", "shower", "hider") var updater_mode := "enabler"
# 仅对 canvas item 生效; <=0 时无 ease
@export var updater_ease_duration := 1.0
@export_enum("include", "exclude") var updater_stage_mode := "include"
@export var updater_stages: Array[int] = [1]
@export_group("Trigger", "trigger")
@export var trigger_event := &""
@export_tool_button("AutoDetectMode") var trigger_auto_detect_mode := _auto_detect_mode
@export_enum("none", "interacted", "triggered", "played") var trigger_mode := "none"
@export_range(0, 10000, 1) var trigger_stage := 1
@export var trigger_set_stage_if_greater := true
var _local_enable_event_stage := 0
func _ready() -> void:
if Engine.is_editor_hint():
return
var parent = get_parent()
if not updater_event.is_empty():
if not parent:
printerr("[EventBinder] bind_enable is true but parent is null. path: %s" % get_path())
return
_local_enable_event_stage = EventManager.get_stage(updater_event)
_update_binding_state(_local_enable_event_stage)
EventManager.stage_updated.connect(_on_global_stage_updated)
if not trigger_event.is_empty():
# connect trigger_mode signal
if trigger_mode == "interacted":
parent.interacted.connect(_on_happened)
elif trigger_mode == "triggered":
parent.triggered.connect(_on_happened)
elif trigger_mode == "played":
parent.played.connect(_on_happened)
func _on_happened() -> void:
if trigger_set_stage_if_greater:
var updated = EventManager.set_stage_if_greater(trigger_event, trigger_stage)
if not updated:
print(
(
"[EventBinder] _on_happened not updated, event: %s, stage: %s"
% [trigger_event, EventManager.get_stage(trigger_event)]
)
)
else:
EventManager.set_stage(trigger_event, trigger_stage)
func _on_global_stage_updated(e: StringName, s: int):
if e == updater_event:
_local_enable_event_stage = s
_update_binding_state(s)
func _update_binding_state(stage: int):
var parent = get_parent()
if not parent:
printerr("[EventBinder] _update_updater_visibility parent is null. path: %s" % get_path())
return
# check stage in updater_stages
var updater_status = false
if updater_stage_mode == "exclude":
updater_status = not stage in updater_stages
elif updater_stage_mode == "include":
updater_status = stage in updater_stages
# check updater_mode
if updater_mode == "enabler":
parent.enabled = updater_status
elif updater_mode == "disabler":
parent.enabled = not updater_status
elif updater_mode == "shower":
_toggle_parent_visibility_with_ease(parent, updater_status)
elif updater_mode == "hider":
_toggle_parent_visibility_with_ease(parent, not updater_status)
func _toggle_parent_visibility_with_ease(parent, show: bool):
if parent is CanvasItem:
parent.visible = true
parent.modulate.a = 0.0 if show else 1.0
var target_a = 1.0 if show else 0.0
var tween = create_tween()
tween.tween_property(parent, "modulate:a", target_a, updater_ease_duration)
if not show:
tween.tween_callback(parent.hide)
func _auto_detect_mode():
# TODO 统一interacted played picked
var parent = get_parent()
if not parent:
printerr("[EventBinder] _auto_detect_mode parent is null. path: %s" % get_path())
if parent.has_signal("interacted"):
trigger_mode = "interacted"
elif parent.has_signal("triggered"):
trigger_mode = "triggered"
elif parent.has_signal("played"):
trigger_mode = "played"
else:
printerr("[EventBinder] _auto_detect_mode cannot detect trigger mode. path:", get_path())