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

152 lines
4.5 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.

@tool
@icon("uid://p0oxphym6oqg")
'''
此类为一个level的最小单元其可以承载任意多的prop和act
你可以这样理解一个level大关卡带有n个小关卡n = scene的数量
Scene 必须带有:
1.Act Manager
2.复数个Prop
其中: ActManager下带有复数个Act其主要用于记录各个Prop的不同state当Act切换时Prop对应的状态也会切换。
ActManager的主要作用就是管理这些Act的切换。
Prop可以简单的理解为场景中的非地形碰撞的与玩家可交互的道具AI等。
所有的Prop会自带一个PropComponent其核心功能是负责管理Prop自身的state和state的切换
举例一个门从State1 -> State2state1是关闭状态state2是打开状态那么
1. 我们在State1中定义门是关的State2中定义门是开的。简单的实现比如我们去设置门的坐标
2. 我们会做一个State1 -> State2的流转函数其定义了State1->State2的具体行为比如播放一个门打开的动画。
对于任意的添加到Scene的Prop如果其自身的最上层子节点集中不含有PropComponentScene会默认的给他发一个PropComponent
注意我并不推荐在Prop上直接挂载PropComponent通过Scene来添加更为合适。
对于SceneScene通过PropComponent上的ID通过ID获取到PropComponent所挂载的组件这也是为什么我强制要求
PropComponent必须是处于Prop的最上层子节点集。
'''
class_name ReedScene extends Node2D
## ==============================
## Export Config
## ==============================
@export var props_root_path: NodePath = ^"Props"
@export var auto_attach_prop_component := true
@export var debug_log := true
## ==============================
## Internal State
## ==============================
var _act_manager: ActManager
var _props_root: Node
var _prop_map: Dictionary = {} # prop_id -> PropComponent
## ==============================
## Lifecycle
## ==============================
func _enter_tree() -> void:
if Engine.is_editor_hint():
_editor_auto_attach_prop_components()
## ==============================
## Resolve References
## ==============================
func _resolve_act_manager() -> void:
_act_manager = get_node_or_null("ActManager")
if _act_manager == null:
push_error("[ReedScene] ActManager not found.")
return
func _resolve_props_root() -> void:
_props_root = get_node_or_null(props_root_path)
if _props_root == null:
push_error("[ReedScene] Props root not found: %s" % props_root_path)
## ==============================
## Prop Collection
## ==============================
func _collect_props() -> void:
_prop_map.clear()
if _props_root == null:
return
for prop in _props_root.get_children():
if not prop is Node:
continue
var prop_comp := _find_prop_component(prop)
if prop_comp == null:
continue
var prop_id := prop_comp.prop_id
if prop_id < 0:
push_warning("[ReedScene] Prop has invaild ID: %s" % prop.name)
continue
if _prop_map.has(prop_id):
push_error("[ReedScene] Duplicate Prop ID: %s" % prop_id)
continue
_prop_map[prop_id] = prop_comp
if debug_log:
print("[ReedScene] Registered Prop:", prop_id)
func _find_prop_component(prop: Node) -> PropComponent:
for child in prop.get_children():
if child is PropComponent:
return child
return null
## ==============================
## Act Binding
## ==============================
func _bind_act_events() -> void:
if _act_manager == null:
return
_act_manager.act_changed.connect(_on_act_changed)
func _on_act_changed(from_act: StringName, to_act: StringName) -> void:
if debug_log:
print("[ReedScene] Act changed:", from_act, "->", to_act)
for prop_comp in _prop_map.values():
prop_comp.on_act_changed(from_act, to_act)
## ==============================
## Editor Helpers
## ==============================
func _editor_auto_attach_prop_components() -> void:
if not auto_attach_prop_component:
return
var props_root := get_node_or_null(props_root_path)
if props_root == null:
return
for prop in props_root.get_children():
if not prop is Node:
continue
if _find_prop_component(prop) != null:
continue
var comp := PropComponent.new()
prop.add_child(comp)
comp.owner = get_tree().edited_scene_root
if debug_log:
print("[ReedScene][Editor] Auto attached PropComponent to:", prop.name)
func _ready() -> void:
_resolve_act_manager()
_resolve_props_root()
_collect_props()
_bind_act_events()