godot-plateformer/addons/reedscene/scene/SceneRegistry.gd

104 lines
2.4 KiB
GDScript3
Raw Normal View History

2026-01-01 16:33:32 +08:00
# id (int) -> WeakRef(ReedScene)
var _by_id: Dictionary = {}
signal registered(id: int, node: ReedScene)
signal unregistered(id: int)
signal conflict(id: int, existing: ReedScene, incoming: ReedScene)
# -------------------------
# 注册
# -------------------------
func register(id: int, node: ReedScene) -> bool:
if id < 0:
push_error("[SceneRegistry] register(): invalid id (<0): %d" % id)
return false
if node == null:
push_error("[SceneRegistry] register(): node is null for id=%d" % id)
return false
_cleanup_dead(id)
if _by_id.has(id):
var existing: ReedScene = _by_id[id].get_ref()
if existing == node:
return true # 重复注册同一个实例,忽略
emit_signal("conflict", id, existing, node)
push_error(
"[SceneRegistry] Duplicate id=%d existing=%s incoming=%s"
% [id, existing, node]
)
return false
_by_id[id] = weakref(node)
emit_signal("registered", id, node)
return true
# -------------------------
# 注销
# -------------------------
func unregister(id: int, node: ReedScene = null) -> void:
if not _by_id.has(id):
return
var existing: ReedScene = _by_id[id].get_ref()
if node != null and existing != node:
# 防止误删
return
_by_id.erase(id)
emit_signal("unregistered", id)
# -------------------------
# 查询
# -------------------------
func get_scene(id: int) -> ReedScene:
_cleanup_dead(id)
var ref: WeakRef = _by_id.get(id)
return ref.get_ref() if ref else null
func has(id: int) -> bool:
return get_scene(id) != null
# -------------------------
# 调用
# -------------------------
func call_scene(id: int, method: String, args: Array = []) -> Variant:
var n := get_scene(id)
if n == null:
push_warning("[SceneRegistry] call_scene(): id not found: %d" % id)
return null
if not n.has_method(method):
push_warning(
"[SceneRegistry] call_scene(): id=%d has no method '%s'"
% [id, method]
)
return null
return n.callv(method, args)
# -------------------------
# 列表
# -------------------------
func list_ids() -> PackedInt32Array:
for id in _by_id.keys():
_cleanup_dead(id)
var result := PackedInt32Array()
for id in _by_id.keys():
result.append(id)
return result
# -------------------------
# 内部:清理死引用
# -------------------------
func _cleanup_dead(id: int) -> void:
if not _by_id.has(id):
return
var ref: WeakRef = _by_id[id]
if ref == null or ref.get_ref() == null:
_by_id.erase(id)