xiandie/scene/character/reenter_lock.gd

160 lines
4.1 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
func _ready() -> void:
process_mode = Node.PROCESS_MODE_PAUSABLE
func _exit_tree() -> void:
if _freeze_requests > 0:
if GlobalConfig.DEBUG:
push_warning(
"[Lock] Remains %d freeze requests on exit_tree. parent=" % _freeze_requests,
get_parent()
)
if _hold_requests > 0:
if GlobalConfig.DEBUG:
print(
"[Lock] 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 GlobalConfig.DEBUG:
print("[Lock] Freeze applied: ", _freeze_requests)
freeze_changed.emit(_freeze_requests, true)
func release() -> void:
_freeze_requests -= 1
if _freeze_requests < 0:
printerr(
(
"[Lock] Attempting to release more times than frozen! Current local count: %d"
% _freeze_requests
),
" Reset to 0."
)
_freeze_requests = 0
if GlobalConfig.DEBUG:
print("[Lock] 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 GlobalConfig.DEBUG:
print("[Lock] Hold applied: ", _hold_requests)
hold_changed.emit(_hold_requests, true)
func unhold() -> void:
_hold_requests -= 1
if _hold_requests < 0:
printerr(
(
"[Lock] Attempting to unhold more times than held! Current local count: %d"
% _hold_requests
),
" Reset to 0."
)
_hold_requests = 0
if GlobalConfig.DEBUG:
print("[Lock] 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 GlobalConfig.DEBUG:
prints("[Lock] LockAll applied (hold, freeze): ", _hold_requests, _freeze_requests)
hold_changed.emit(_hold_requests, true)
freeze_changed.emit(_freeze_requests, true)
func unlock_all() -> void:
_freeze_requests -= 1
_hold_requests -= 1
if _freeze_requests < 0:
printerr(
(
"[Lock] Attempting to unlock more times than frozen! Current local count: %d"
% _freeze_requests
),
" Reset to 0."
)
_freeze_requests = 0
if _hold_requests < 0:
printerr(
(
"[Lock] Attempting to unhold more times than held! Current local count: %d"
% _hold_requests
),
" Reset to 0."
)
_hold_requests = 0
freeze_changed.emit(_freeze_requests, false)
hold_changed.emit(_hold_requests, false)
if GlobalConfig.DEBUG:
prints("[Lock] UnlockAll applied (hold, freeze): ", _hold_requests, _freeze_requests)
func _to_string() -> String:
return "[Lock] Freeze: %d, Hold: %d" % [_freeze_requests, _hold_requests]