xiandie/scene/character/reenter_lock.gd

135 lines
3.5 KiB
GDScript

# ReenterLock.gd
extends Node
class_name PlayerReenterLock
#### 目前无需全局,仅需跟随 ground
#### 因此无需在 exit 时重置锁,也无需推迟计数
#### 因为 PlayerReenterLock 生命周期与 ground 一致
####### PlayerReenterLock 系统提供了以下特性 #############
# 可重入性:每个事件可以多次锁定/解锁,通过计数器管理
# 全局状态追踪:使用静态变量追踪整体锁定状态 [无需启用]
# 生命周期管理:自动处理节点进入/退出场景树的情况 [无需启用]
# 错误保护:防止过度释放,并在出现问题时发出警告
# 调试支持:可选的调试模式输出详细信息
# 便捷方法:提供同时锁定/解锁两种状态的方法
#################################################
signal freeze_changed(count: int, is_add: bool)
signal hold_changed(count: int, is_add: bool)
# 实例级别的锁定请求追踪
var _freeze_requests: int = 0
var _hold_requests: int = 0
# 调试模式
var debug_mode := GlobalConfig.DEBUG
func _exit_tree() -> void:
if _freeze_requests > 0:
if debug_mode:
push_warning(
"[ReenterLock] Remains %d freeze requests on exit_tree. parent=" % _freeze_requests,
get_parent()
)
if _hold_requests > 0:
if debug_mode:
print(
"[ReenterLock] Remains %d hold requests on exit_tree. parent=" % _hold_requests,
get_parent()
)
func _create_timer(duration: float, callable: Callable):
if duration > 0 and callable:
get_tree().create_timer(duration).timeout.connect(callable)
# Freeze 相关方法
func freeze(duration := 0.0) -> void:
if duration > 0:
_create_timer(duration, release)
_freeze_requests += 1
if debug_mode:
print("[ReenterLock] Freeze applied: ", _freeze_requests)
freeze_changed.emit(_freeze_requests, true)
func release() -> void:
if _freeze_requests <= 0:
push_warning(
(
"[ReenterLock] Attempting to release more times than frozen! Current local count: %d"
% _freeze_requests
)
)
return
_freeze_requests -= 1
if debug_mode:
print("[ReenterLock] Release applied: ", _freeze_requests)
freeze_changed.emit(_freeze_requests, false)
# Hold 相关方法
func hold(duration := 0.0) -> void:
if duration > 0:
_create_timer(duration, unhold)
_hold_requests += 1
if debug_mode:
print("[ReenterLock] Hold applied: ", _hold_requests)
hold_changed.emit(_hold_requests, true)
func unhold() -> void:
if _hold_requests <= 0:
push_warning(
(
"[ReenterLock] Attempting to unhold more times than held! Current local count: %d"
% _hold_requests
)
)
return
_hold_requests -= 1
if debug_mode:
print("[ReenterLock] Unhold applied: ", _hold_requests)
hold_changed.emit(_hold_requests, false)
# 静态方法:查询当前状态
func is_frozen() -> bool:
return _freeze_requests > 0
func is_held() -> bool:
return _hold_requests > 0
func get_freeze_count() -> int:
return _freeze_requests
func get_hold_count() -> int:
return _hold_requests
# 便捷方法:同时锁定移动和输入
func lock_all(duration := 0.0) -> void:
if duration > 0:
_create_timer(duration, unlock_all)
_hold_requests += 1
_freeze_requests += 1
if debug_mode:
prints("[ReenterLock] LockAll applied (hold, freeze): ", _hold_requests, _freeze_requests)
hold_changed.emit(_hold_requests, true)
freeze_changed.emit(_freeze_requests, true)
func unlock_all() -> void:
release()
unhold()
func _to_string() -> String:
return "[ReenterLock] Freeze: %d, Hold: %d" % [_freeze_requests, _hold_requests]