Files
XCEngine/docs/plan/UI-Editor-GameObject缺口分析.md

18 KiB
Raw Blame History

UI-Editor GameObject 缺口分析

基于XCEngine渲染引擎架构设计.md
目标:识别 UI 编辑器 GameObject.h 相对于 Engine 架构设计文档的缺失功能
日期2026-03-20


一、Component 基类缺口

架构设计接口 函数签名 状态 说明
transform() TransformComponent& transform() const 缺失 返回所在实体的 TransformComponent 引用
GetScene() Scene* GetScene() const 缺失 返回所属 Scene 指针
FixedUpdate() virtual void FixedUpdate() 缺失 物理更新(每固定帧)
LateUpdate() virtual void LateUpdate(float deltaTime) 缺失 晚于 Update 执行
OnEnable() virtual void OnEnable() 缺失 组件启用时调用
OnDisable() virtual void OnDisable() 缺失 组件禁用时调用
friend class friend class GameObject ⚠️ 差异 UI Editor 是 friend class Entity

补充说明

  • UI Editor 的 Component 需要增加 TransformComponent* 获取方法以支持 Inspector 面板的变换编辑
  • Engine 的 m_gameObject 在 UI Editor 中对应 m_entity

二、TransformComponent 缺口

2.1 World 空间方法

架构设计接口 函数签名 状态 说明
GetPosition() Vector3 GetPosition() const 缺失 获取世界坐标
SetPosition() void SetPosition(const Vector3& position) 缺失 设置世界坐标
GetRotation() Quaternion GetRotation() const 缺失 获取世界旋转
SetRotation() void SetRotation(const Quaternion& rotation) 缺失 设置世界旋转
GetScale() Vector3 GetScale() const 缺失 获取世界缩放
SetScale() void SetScale(const Vector3& scale) 缺失 设置世界缩放

2.2 方向向量

架构设计接口 函数签名 状态 说明
GetForward() Vector3 GetForward() const 缺失 获取前向向量
GetRight() Vector3 GetRight() const 缺失 获取右向量
GetUp() Vector3 GetUp() const 缺失 获取上向量

2.3 矩阵变换

架构设计接口 函数签名 状态 说明
GetLocalToWorldMatrix() const Matrix4x4& GetLocalToWorldMatrix() const 缺失 本地到世界矩阵(含缓存)
GetWorldToLocalMatrix() Matrix4x4 GetWorldToLocalMatrix() const 缺失 世界到本地矩阵

2.4 父子层级

架构设计接口 函数签名 状态 说明
GetParent() TransformComponent* GetParent() const 缺失 获取父变换
SetParent() void SetParent(TransformComponent* parent, bool worldPositionStays = true) 缺失 设置父变换
GetChild() TransformComponent* GetChild(int index) const 缺失 按索引获取子变换
Find() TransformComponent* Find(const String& name) const 缺失 按名称查找子变换
DetachChildren() void DetachChildren() 缺失 断开所有子节点
SetAsFirstSibling() void SetAsFirstSibling() 缺失 设为第一个同级
SetAsLastSibling() void SetAsLastSibling() 缺失 设为最后一个同级
GetSiblingIndex() int GetSiblingIndex() const 缺失 获取同级索引
SetSiblingIndex() void SetSiblingIndex(int index) 缺失 设置同级索引

2.5 变换操作

架构设计接口 函数签名 状态 说明
LookAt(target) void LookAt(const Vector3& target) 缺失 朝向目标点
LookAt(target, up) void LookAt(const Vector3& target, const Vector3& up) 缺失 朝向目标点(指定上向量)
Rotate(eulers) void Rotate(const Vector3& eulers) 缺失 欧拉角旋转
Rotate(axis, angle) void Rotate(const Vector3& axis, float angle) 缺失 轴角旋转
Translate(translation) void Translate(const Vector3& translation) 缺失 平移(世界空间)
Translate(translation, relativeTo) void Translate(const Vector3& translation, Space relativeTo) 缺失 平移(指定空间)

2.6 点/方向变换

架构设计接口 函数签名 状态 说明
TransformPoint() Vector3 TransformPoint(const Vector3& point) const 缺失 变换点(含平移旋转)
InverseTransformPoint() Vector3 InverseTransformPoint(const Vector3& point) const 缺失 逆变换点
TransformDirection() Vector3 TransformDirection(const Vector3& direction) const 缺失 变换方向(仅旋转)
InverseTransformDirection() Vector3 InverseTransformDirection(const Vector3& direction) const 缺失 逆变换方向

2.7 脏标记与缓存

架构设计接口 函数签名 状态 说明
SetDirty() void SetDirty() ⚠️ 局部 UI Editor 只有简单 flag缺少完整缓存机制
缓存成员 mutable Matrix4x4 m_localToWorldMatrix 缺失 矩阵缓存
更新方法 void UpdateWorldTransform() const 缺失 缓存失效时重新计算

当前 UI Editor 实现

class TransformComponent : public Component {
public:
    float position[3] = {0.0f, 0.0f, 0.0f};   // 仅有本地坐标
    float rotation[3] = {0.0f, 0.0f, 0.0f};    // 欧拉角
    float scale[3] = {1.0f, 1.0f, 1.0f};       // 仅有本地缩放
    // 缺少世界空间方法、矩阵缓存、父子指针等
};

架构设计要求

class TransformComponent : public Component {
private:
    Vector3 m_localPosition = Vector3::Zero();
    Quaternion m_localRotation = Quaternion::Identity();
    Vector3 m_localScale = Vector3::One();
    
    TransformComponent* m_parent = nullptr;
    std::vector<TransformComponent*> m_children;
    
    mutable Matrix4x4 m_localToWorldMatrix;
    mutable Matrix4x4 m_worldToLocalMatrix;
    mutable Vector3 m_worldPosition;
    mutable Quaternion m_worldRotation;
    mutable Vector3 m_worldScale;
    mutable bool m_dirty = true;
    
    void UpdateWorldTransform() const;
};

三、EntityGameObject缺口

3.1 基础方法

架构设计接口 函数签名 状态 说明
GetTransform() TransformComponent& GetTransform() 缺失 获取变换组件引用
GetScene() Scene* GetScene() const 缺失 获取所属场景

3.2 组件查找

架构设计接口 函数签名 状态 说明
GetComponentInChildren<T>() T* GetComponentInChildren() const 缺失 在子实体中查找组件
GetComponentsInChildren<T>() std::vector<T*> GetComponentsInChildren() const 缺失 获取所有子实体中的组件
GetComponentInParent<T>() T* GetComponentInParent() const 缺失 在父实体中查找组件

3.3 父子层级

架构设计接口 函数签名 状态 说明
SetParent(parent) void SetParent(GameObject* parent) 缺失 2参数版本含 worldPositionStays
GetChildren() const std::vector<GameObject*>& GetChildren() const 缺失 获取子实体列表
GetChild() GameObject* GetChild(int index) const 缺失 按索引获取子实体

3.4 激活状态

架构设计接口 函数签名 状态 说明
active 成员 bool active = true 缺失 实体激活状态
SetActive() void SetActive(bool active) 缺失 设置激活状态
IsActive() bool IsActive() const 缺失 检查激活状态
IsActiveInHierarchy() bool IsActiveInHierarchy() const 缺失 检查层级中的激活状态

3.5 静态查找

架构设计接口 函数签名 状态 说明
Find() static GameObject* Find(const String& name) 缺失 按名称查找实体
FindObjectsOfType() static std::vector<GameObject*> FindObjectsOfType() 缺失 查找所有实体
FindGameObjectsWithTag() static std::vector<GameObject*> FindGameObjectsWithTag(const String& tag) 缺失 按标签查找

3.6 销毁

架构设计接口 函数签名 状态 说明
Destroy() void Destroy() 缺失 实例方法销毁(通过 Scene

四、Scene / SceneManager 缺口

4.1 Scene 类

架构设计接口 函数签名 状态 说明
GetName() const String& GetName() const 缺失 获取场景名称
SetName() void SetName(const String& name) 缺失 设置场景名称
CreateGameObject(name, parent) GameObject* CreateGameObject(const String& name, GameObject* parent) 缺失 带父实体创建
GetRootGameObjects() std::vector<GameObject*> GetRootGameObjects() const 缺失 获取根实体列表
Find() GameObject* Find(const String& name) const 缺失 查找实体
FindGameObjectWithTag() GameObject* FindGameObjectWithTag(const String& tag) const 缺失 按标签查找
FindObjectsOfType<T>() std::vector<T*> FindObjectsOfType() const 缺失 模板查找
FindObjectOfType<T>() T* FindObjectOfType() const 缺失 查找单个
IsActive() bool IsActive() const 缺失 场景激活状态
SetActive() void SetActive(bool active) 缺失 设置激活状态
Load() void Load(const String& filePath) 缺失 加载场景
Save() void Save(const String& filePath) 缺失 保存场景
Update() void Update(float deltaTime) 缺失 场景更新
FixedUpdate() void FixedUpdate(float fixedDeltaTime) 缺失 物理更新
LateUpdate() void LateUpdate(float deltaTime) 缺失 晚更新

当前 UI Editor 缺失 Scene 概念,所有实体都在 SceneManager 全局管理。

4.2 SceneManager 类

架构设计接口 函数签名 状态 说明
CreateScene() Scene* CreateScene(const String& name) 缺失 创建场景
LoadScene() void LoadScene(const String& filePath) 缺失 同步加载
LoadSceneAsync() void LoadSceneAsync(const String& filePath, std::function<void(Scene*)> callback) 缺失 异步加载
UnloadScene(scene) void UnloadScene(Scene* scene) 缺失 卸载场景
UnloadScene(name) void UnloadScene(const String& sceneName) 缺失 按名称卸载
SetActiveScene(scene) void SetActiveScene(Scene* scene) 缺失 设置激活场景
SetActiveScene(name) void SetActiveScene(const String& sceneName) 缺失 按名称设置
GetActiveScene() Scene* GetActiveScene() const 缺失 获取激活场景
GetScene(name) Scene* GetScene(const String& name) const 缺失 按名称获取场景
GetAllScenes() std::vector<Scene*> GetAllScenes() const 缺失 获取所有场景
OnSceneLoaded Event<Scene*> ⚠️ 差异 UI Editor 是 OnSceneChanged
OnSceneUnloaded Event<Scene*> 缺失 场景卸载事件
OnActiveSceneChanged Event<Scene*> 缺失 激活场景变更事件

4.3 GameObjectBuilder 类

架构设计接口 函数签名 状态 说明
完整类 class GameObjectBuilder 缺失 实体创建辅助类

五、实现优先级

P0 - 核心缺失(必须实现)

模块 原因 涉及文件
TransformComponent 世界空间方法 Editor 变换编辑基础 GameObject.h
Entity GetTransform() Inspector 面板需要 GameObject.h
Component transform() 组件访问变换 GameObject.h

P1 - 功能完整(应该实现)

模块 原因 涉及文件
TransformComponent 矩阵缓存 性能优化 GameObject.h
TransformComponent 父子指针 层级操作 GameObject.h
Entity 激活状态 运行时状态 GameObject.h
Entity 父子层级操作 层级编辑 GameObject.h
Scene 概念 多场景支持 SceneManager.h
SceneManager 多场景管理 场景隔离 SceneManager.h

P2 - 高级功能(可选实现)

模块 原因 涉及文件
Scene 序列化/反序列化 持久化 SceneManager.h
TransformComponent 点/方向变换 Gizmos 操作 GameObject.h
SceneManager 异步加载 体验优化 SceneManager.h
Entity 静态查找 Editor 操作 GameObject.h

六、数据结构对齐表

6.1 当前 UI Editor vs 架构设计

项目 UI Editor 当前 架构设计 对齐建议
实体内组件存储 vector<unique_ptr<Component>> vector<unique_ptr<Component>> 已对齐
变换存储 float[3] 数组 Vector3 / Quaternion ⚠️ UI Editor 自行实现,接口对齐即可
父子关系 EntityID (uint64) GameObject* 指针 ⚠️ UI 用 IDEngine 用指针
场景管理 全局单例 SceneManager 多 Scene + SceneManager 需要重构

6.2 命名差异

UI Editor Engine 架构设计 说明
Entity GameObject UI Editor 使用 Entity 避免与 std 冲突
EntityID uint64_t UI Editor 自定义类型别名
INVALID_ENTITY_ID N/A UI Editor 自定义常量
ComponentRegistry ComponentTypeRegistry 功能相似,命名不同

七、依赖关系分析

实现优先级 - 依赖链:

P0: TransformComponent 世界空间
    │
    ├── 需要: Vector3/Quaternion 数学类型
    ├── 需要: 矩阵计算方法
    └── 影响: Entity::GetTransform()

P0: Component::transform()
    │
    └── 依赖: Entity::GetTransform()

P1: TransformComponent 父子指针
    │
    ├── 需要: TransformComponent* parent
    ├── 需要: vector<TransformComponent*> children
    └── 影响: Entity 父子操作

P1: Entity 激活状态
    │
    ├── 需要: active 成员
    └── 影响: IsActiveInHierarchy()

P1: Scene 多场景
    │
    ├── 需要: Scene 类
    ├── 需要: Scene::CreateGameObject()
    └── 影响: SceneManager 重构

八、附录:当前 GameObject.h 完整内容

// ui_editor/src/Core/GameObject.h 当前实现

#pragma once

#include <string>
#include <vector>
#include <memory>
#include <unordered_map>
#include <functional>
#include <cstdint>

#include <XCEngine/Core/Event.h>

namespace UI {

using EntityID = uint64_t;
constexpr EntityID INVALID_ENTITY_ID = 0;

class Component {
public:
    virtual ~Component() = default;
    virtual std::string GetName() const = 0;
    
    virtual void Awake() {}
    virtual void Start() {}
    virtual void Update(float deltaTime) {}
    virtual void OnDestroy() {}
    
    class Entity* GetEntity() const { return m_entity; }
    bool IsEnabled() const { return m_enabled; }
    void SetEnabled(bool enabled) { m_enabled = enabled; }
    
protected:
    class Entity* m_entity = nullptr;
    bool m_enabled = true;
    
    friend class Entity;
};

class TransformComponent : public Component {
public:
    float position[3] = {0.0f, 0.0f, 0.0f};
    float rotation[3] = {0.0f, 0.0f, 0.0f};
    float scale[3] = {1.0f, 1.0f, 1.0f};
    
    std::string GetName() const override { return "Transform"; }
};

class MeshRendererComponent : public Component {
public:
    std::string materialName = "Default-Material";
    std::string meshName = "";
    
    std::string GetName() const override { return "Mesh Renderer"; }
};

class Entity {
public:
    EntityID id = INVALID_ENTITY_ID;
    std::string name;
    EntityID parent = INVALID_ENTITY_ID;
    std::vector<EntityID> children;
    std::vector<std::unique_ptr<Component>> components;
    bool selected = false;
    
    template<typename T, typename... Args>
    T* AddComponent(Args&&... args) {
        auto comp = std::make_unique<T>(std::forward<Args>(args)...);
        comp->m_entity = this;
        T* ptr = comp.get();
        components.push_back(std::move(comp));
        return ptr;
    }
    
    template<typename T>
    T* GetComponent() {
        for (auto& comp : components) {
            if (auto casted = dynamic_cast<T*>(comp.get())) {
                return casted;
            }
        }
        return nullptr;
    }
    
    template<typename T>
    std::vector<T*> GetComponents() {
        std::vector<T*> result;
        for (auto& comp : components) {
            if (auto casted = dynamic_cast<T*>(comp.get())) {
                result.push_back(casted);
            }
        }
        return result;
    }
};

using ComponentInspectorFn = std::function<void(Component*)>;

struct ComponentInspectorInfo {
    std::string name;
    ComponentInspectorFn renderFn;
};

class ComponentRegistry {
public:
    static ComponentRegistry& Get() {
        static ComponentRegistry instance;
        return instance;
    }
    
    template<typename T>
    void RegisterComponent(const std::string& name, ComponentInspectorFn inspectorFn) {
        m_inspectors[name] = {name, inspectorFn};
        m_factories[name] = []() -> std::unique_ptr<Component> {
            return std::make_unique<T>();
        };
    }
    
    ComponentInspectorInfo* GetInspector(const std::string& name) {
        auto it = m_inspectors.find(name);
        if (it != m_inspectors.end()) {
            return &it->second;
        }
        return nullptr;
    }
    
private:
    ComponentRegistry() = default;
    std::unordered_map<std::string, ComponentInspectorInfo> m_inspectors;
    std::unordered_map<std::string, std::function<std::unique_ptr<Component>()>> m_factories;
};

} // namespace UI

文档结束