187 lines
5.9 KiB
GDScript
187 lines
5.9 KiB
GDScript
@tool
|
|
class_name EventBinder extends Node
|
|
|
|
@export_tool_button("auto memo") var auto_memo = _auto_memo
|
|
@export_multiline var memo := ""
|
|
|
|
@export_group("Updater", "updater")
|
|
@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()
|
|
# 仅对 canvas item 生效; <=0 时无 ease
|
|
@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()
|
|
|
|
@export_group("Trigger", "trigger")
|
|
@export var trigger_event := &"":
|
|
set(val):
|
|
if trigger_event != val:
|
|
trigger_event = val
|
|
if is_node_ready() and Engine.is_editor_hint():
|
|
_auto_memo()
|
|
@export_tool_button("AutoDetectMode") var trigger_auto_detect_mode := _auto_detect_mode
|
|
@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()
|
|
|
|
var _local_enable_event_stage := 0
|
|
|
|
|
|
func _ready() -> void:
|
|
if Engine.is_editor_hint():
|
|
_auto_memo()
|
|
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())
|
|
|
|
|
|
#### 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 |