110 lines
2.7 KiB
GDScript
110 lines
2.7 KiB
GDScript
@tool
|
||
class_name PropManager
|
||
extends Node2D
|
||
|
||
##是否要自动的向其子集中添加一个PropComp
|
||
@export var auto_attach_prop_component := true
|
||
|
||
##是否要输出Debug Message
|
||
@export var debug_log := true
|
||
|
||
##输出一个ID的前缀,方便策划调整
|
||
const PREFIX := "[Prop_%04d]"
|
||
|
||
func _ready() -> void:
|
||
if not Engine.is_editor_hint():
|
||
return
|
||
|
||
_ensure_existing_props()
|
||
child_entered_tree.connect(_on_child_entered_tree)
|
||
|
||
# 强制让 Editor 重新计算 configuration warnings
|
||
update_configuration_warnings()
|
||
|
||
func _on_child_entered_tree(node: Node) -> void:
|
||
if not Engine.is_editor_hint():
|
||
return
|
||
|
||
_try_attach_and_assign(node)
|
||
|
||
# 子节点变化后,刷新 Inspector 警告
|
||
update_configuration_warnings()
|
||
|
||
func _ensure_existing_props() -> void:
|
||
for child in get_children():
|
||
_try_attach_and_assign(child)
|
||
|
||
func _try_attach_and_assign(prop: Node) -> void:
|
||
if not auto_attach_prop_component:
|
||
return
|
||
if prop == null:
|
||
return
|
||
if prop is PropComponent:
|
||
return
|
||
|
||
var comp := _find_prop_component_top(prop)
|
||
if comp == null:
|
||
comp = PropComponent.new()
|
||
comp.name = "PropComponent" # 临时名
|
||
prop.add_child(comp)
|
||
comp.owner = get_tree().edited_scene_root
|
||
|
||
# 确保 prop_id 唯一且有效
|
||
if int(comp.prop_id) < 0 or _is_prop_id_used_elsewhere(int(comp.prop_id), comp):
|
||
comp.prop_id = _alloc_prop_id()
|
||
|
||
# 用 prop_id 重命名 PropComponent
|
||
comp.name = PREFIX % int(comp.prop_id)
|
||
|
||
if debug_log:
|
||
print("[PropManager][Editor] Ensure PropComponent:", prop.name, "->", comp.name, "id=", comp.prop_id)
|
||
|
||
func _find_prop_component_top(prop: Node) -> PropComponent:
|
||
for child in prop.get_children():
|
||
if child is PropComponent:
|
||
return child as PropComponent
|
||
return null
|
||
|
||
func _alloc_prop_id() -> int:
|
||
var max_id := -1
|
||
|
||
for prop in get_children():
|
||
var comp := _find_prop_component_top(prop)
|
||
if comp == null:
|
||
continue
|
||
max_id = maxi(max_id, int(comp.prop_id))
|
||
|
||
return max_id + 1
|
||
|
||
func _is_prop_id_used_elsewhere(prop_id: int, self_comp: PropComponent) -> bool:
|
||
for prop in get_children():
|
||
var comp := _find_prop_component_top(prop)
|
||
if comp == null:
|
||
continue
|
||
if comp == self_comp:
|
||
continue
|
||
if int(comp.prop_id) == prop_id:
|
||
return true
|
||
return false
|
||
|
||
# =====================================================
|
||
# Editor Configuration Warnings(Inspector 黄色警告)
|
||
# =====================================================
|
||
func _get_configuration_warnings() -> PackedStringArray:
|
||
var warnings := PackedStringArray()
|
||
|
||
if not Engine.is_editor_hint():
|
||
return warnings
|
||
|
||
for prop in get_children():
|
||
if prop is PropComponent:
|
||
continue
|
||
|
||
var comp := _find_prop_component_top(prop)
|
||
if comp == null:
|
||
warnings.append(
|
||
"Prop '%s' has no PropComponent as a top-level child." % prop.name
|
||
)
|
||
|
||
return warnings
|