xiandie/manager/event_manager/event_binder.gd

187 lines
5.9 KiB
GDScript3
Raw Normal View History

2025-07-04 13:02:27 +00:00
@tool
class_name EventBinder extends Node
2025-07-06 12:44:06 +00:00
@export_tool_button("auto memo") var auto_memo = _auto_memo
@export_multiline var memo := ""
2025-07-04 13:02:27 +00:00
@export_group("Updater", "updater")
2025-07-06 12:44:06 +00:00
@export var updater_event := &"":
set(val):
if updater_event != val:
updater_event = val
if is_node_ready() and Engine.is_editor_hint():
_auto_memo()
@export_enum("enabler", "shower") var updater_mode := "enabler":
set(val):
if updater_mode != val:
updater_mode = val
if is_node_ready() and Engine.is_editor_hint():
_auto_memo()
2025-07-04 13:02:27 +00:00
# 仅对 canvas item 生效; <=0 时无 ease
2025-07-06 12:44:06 +00:00
@export var updater_ease_duration := 1.0:
set(val):
if updater_ease_duration != val:
updater_ease_duration = val
if is_node_ready() and Engine.is_editor_hint():
_auto_memo()
@export_enum("include", "exclude") var updater_stage_mode := "include":
set(val):
if updater_stage_mode != val:
updater_stage_mode = val
if is_node_ready() and Engine.is_editor_hint():
_auto_memo()
@export var updater_stages: Array[int] = [1]:
set(val):
if updater_stages != val:
updater_stages = val
if is_node_ready() and Engine.is_editor_hint():
_auto_memo()
2025-07-04 13:02:27 +00:00
@export_group("Trigger", "trigger")
2025-07-06 12:44:06 +00:00
@export var trigger_event := &"":
set(val):
if trigger_event != val:
trigger_event = val
if is_node_ready() and Engine.is_editor_hint():
_auto_memo()
2025-07-04 13:02:27 +00:00
@export_tool_button("AutoDetectMode") var trigger_auto_detect_mode := _auto_detect_mode
2025-07-06 12:44:06 +00:00
@export_enum("none", "interacted", "triggered", "played") var trigger_mode := "none":
set(val):
if trigger_mode != val:
trigger_mode = val
if is_node_ready() and Engine.is_editor_hint():
_auto_memo()
@export_range(0, 10000, 1) var trigger_stage := 1:
set(val):
if trigger_stage != val:
trigger_stage = val
if is_node_ready() and Engine.is_editor_hint():
_auto_memo()
@export var trigger_set_stage_if_greater := true:
set(val):
if trigger_set_stage_if_greater != val:
trigger_set_stage_if_greater = val
if is_node_ready() and Engine.is_editor_hint():
_auto_memo()
2025-07-04 13:02:27 +00:00
var _local_enable_event_stage := 0
func _ready() -> void:
if Engine.is_editor_hint():
2025-07-06 12:44:06 +00:00
_auto_memo()
2025-07-04 13:02:27 +00:00
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 == "shower":
_toggle_parent_visibility_with_ease(parent, 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())
2025-07-06 12:44:06 +00:00
#### TOOL BUTTON
func _auto_memo() -> void:
# updater release_stage[(!)=0|1] 时[显示|启用][parent.name.replace("Closeup", "")]
# trigger [parent] [picked|played...] 时 release_stage=1(greater|any)
var parent_name = get_parent().name.to_lower()
# replace english letters
var matcher = RegEx.create_from_string("^[a-z]*(.*)$")
var parent_name_match = matcher.search(parent_name).get_string(1)
if parent_name_match != "":
parent_name = parent_name_match
var memo_str = ""
if updater_event != "":
memo_str = updater_event
memo_str += "=" if updater_stage_mode == "include" else "!="
memo_str += "|".join(updater_stages) + ""
memo_str += "显示" if updater_mode == "shower" else "启用"
memo_str += " [" + parent_name + "]\n"
if trigger_event != "" and trigger_mode != "none":
memo_str += "[" + parent_name + "] " + trigger_mode + ""
memo_str += trigger_event + "=" + str(trigger_stage)
memo_str += "(greater)" if trigger_set_stage_if_greater else "(any)"
var existing_lines = memo.split("\n")
# 保留 # 开头的 line
var kept_lines = []
for line in existing_lines:
if line.begins_with("#"):
kept_lines.append(line)
memo = "\n".join(kept_lines)
memo += "\n" if kept_lines else ""
memo += memo_str