godot-plateformer/addons/reedscene/act/ActManager.gd

161 lines
4.1 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#@icon("")
@tool
class_name ActManager extends Node
##ActManager里记录了一系列的ActID和对应的Act主要用来同步场景的Act比如我们现在使用ActID = 0的Act那么就会让所有的Act的状态重置回到ActID = 0的Act的状态
@export var prop_state_map: Dictionary[int, Act] = {}
##用于生成一个基础的Act的工具按钮
@export_tool_button("Generate Default Act")
var _gen_default_act: Callable = Callable(self, "_editor_generate_default_act")
##用于生成一个Empty的工具按钮
@export_tool_button("Generate Empty Act")
var _gen_empty_act: Callable = Callable(self, "_editor_generate_empty_act")
##是否要输出报错信息
@export var debug_log: bool = false
##关卡的初始Act默认Clamp到Act的数量防止出现错误
@export var init_act_id: int = 0:
set(value):
var max_index := max(prop_state_map.size() - 1, 0)
init_act_id = clamp(value, 0, max_index)
signal act_changed(from_act_id: int, to_act_id: int)
##用来扫描prop
func _scan_scene_for_props(scene_root: Node) -> Dictionary:
var result := {}
if scene_root == null:
return result
_scan_node_recursive(scene_root, result)
return result
##递归扫描
func _scan_node_recursive(node: Node, out: Dictionary) -> void:
if node is PropComponent:
var prop := node as PropComponent
if out.has(prop.prop_id):
push_warning(
"[ActManagerInspector] Duplicate prop_id: %d (%s)"
% [prop.prop_id, node.get_path()]
)
else:
out[prop.prop_id] = {
"node": prop,
"path": node.get_path()
}
for child in node.get_children():
_scan_node_recursive(child, out)
##生成一个默认的Act
func _editor_generate_default_act() -> void:
if not Engine.is_editor_hint():
return
var scene := _get_owner_scene()
if scene == null:
_editor_popup(
"ActManager must be a child of ReedScene.",
"Generate Default Act - Failed"
)
return
var props_root := scene.get_node_or_null(scene.props_root_path)
if props_root == null:
_editor_popup(
"Props root not found:\n%s" % scene.props_root_path,
"Generate Default Act - Failed"
)
return
var act := Act.new()
act.prop_state_map.clear()
var count := 0
for prop_node in props_root.get_children():
if not prop_node is Node:
continue
var prop_comp := _find_prop_component_top(prop_node)
if prop_comp == null:
continue
var pid := prop_comp.prop_id
var init_state := prop_comp.initial_state_id
var single := SingleAct.new()
single.state_id = init_state
act.prop_state_map[pid] = single
count += 1
prop_state_map[0] = act
notify_property_list_changed()
_editor_popup(
"Default Act generated successfully.\n\nProp count: %d\nAct ID: 0" % count,
"Generate Default Act - Success"
)
if debug_log:
print("[ActManager][Editor] Generated Default Act with", count, "props.")
##生成一个空的Act
func _editor_generate_empty_act() -> void:
if not Engine.is_editor_hint():
return
var act := Act.new()
act.prop_state_map.clear() # 明确强调“空 Act”
var act_id := _find_next_free_act_id()
prop_state_map[act_id] = act
notify_property_list_changed()
_editor_popup(
"Empty Act generated successfully.\n\nAct ID: %d\nProp count: 0" % act_id,
"Generate Empty Act - Success"
)
if debug_log:
print("[ActManager][Editor] Generated EMPTY Act with id =", act_id)
## ==============================
## 工具函数
## ==============================
func _editor_popup(message: String, title: String = "ActManager") -> void:
if not Engine.is_editor_hint():
return
var dialog := AcceptDialog.new()
dialog.title = title
dialog.dialog_text = message
get_tree().root.add_child(dialog)
dialog.popup_centered()
##找到场景scene节点
func _get_owner_scene() -> ReedScene:
var p := get_parent()
if p is ReedScene:
return p as ReedScene
return null
##找到PropComp
func _find_prop_component_top(prop: Node) -> PropComponent:
for child in prop.get_children():
if child is PropComponent:
return child as PropComponent
return null
##找到最近的空位ActID
func _find_next_free_act_id() -> int:
var id := 0
while prop_state_map.has(id):
id += 1
return id