2026-02-11 19:40:26 +08:00
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
|
|
#include <algorithm>
|
2026-02-25 06:23:53 +08:00
|
|
|
|
#include <core/color.h>
|
|
|
|
|
|
#include <core/math_types.h>
|
|
|
|
|
|
#include <core/types.h>
|
|
|
|
|
|
#include <event/event_dispatcher.h>
|
2026-02-11 19:40:26 +08:00
|
|
|
|
#include <functional>
|
2026-02-26 19:57:16 +08:00
|
|
|
|
#include <renderer/renderer.h>
|
2026-02-25 21:22:35 +08:00
|
|
|
|
#include <memory>
|
2026-02-11 19:40:26 +08:00
|
|
|
|
#include <string>
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
|
|
namespace extra2d {
|
|
|
|
|
|
|
|
|
|
|
|
// 前向声明
|
|
|
|
|
|
class Scene;
|
2026-02-26 00:59:16 +08:00
|
|
|
|
class Renderer;
|
2026-02-11 19:40:26 +08:00
|
|
|
|
struct RenderCommand;
|
|
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
// 节点基类 - 场景图的基础
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
class Node : public std::enable_shared_from_this<Node> {
|
|
|
|
|
|
public:
|
|
|
|
|
|
Node();
|
|
|
|
|
|
virtual ~Node();
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
// 层级管理
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
void addChild(Ptr<Node> child);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 批量添加子节点
|
|
|
|
|
|
* @param children 子节点列表
|
|
|
|
|
|
*/
|
|
|
|
|
|
void addChildren(std::vector<Ptr<Node>> &&children);
|
|
|
|
|
|
|
|
|
|
|
|
void removeChild(Ptr<Node> child);
|
|
|
|
|
|
void removeChildByName(const std::string &name);
|
|
|
|
|
|
void removeFromParent();
|
|
|
|
|
|
void removeAllChildren();
|
|
|
|
|
|
|
2026-02-26 00:38:31 +08:00
|
|
|
|
Ptr<Node> parent() const { return parent_.lock(); }
|
|
|
|
|
|
const std::vector<Ptr<Node>> &children() const { return children_; }
|
|
|
|
|
|
Ptr<Node> childByName(const std::string &name) const;
|
|
|
|
|
|
Ptr<Node> childByTag(int tag) const;
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
// 变换属性
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
void setPosition(const Vec2 &pos);
|
|
|
|
|
|
void setPosition(float x, float y);
|
2026-02-26 00:38:31 +08:00
|
|
|
|
Vec2 pos() const { return position_; }
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
void setRotation(float degrees);
|
2026-02-26 00:38:31 +08:00
|
|
|
|
float rot() const { return rotation_; }
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
void setScale(const Vec2 &scale);
|
|
|
|
|
|
void setScale(float scale);
|
|
|
|
|
|
void setScale(float x, float y);
|
2026-02-26 00:38:31 +08:00
|
|
|
|
Vec2 scale() const { return scale_; }
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
void setAnchor(const Vec2 &anchor);
|
|
|
|
|
|
void setAnchor(float x, float y);
|
2026-02-26 00:38:31 +08:00
|
|
|
|
Vec2 anchor() const { return anchor_; }
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
void setSkew(const Vec2 &skew);
|
|
|
|
|
|
void setSkew(float x, float y);
|
2026-02-26 00:38:31 +08:00
|
|
|
|
Vec2 skew() const { return skew_; }
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
void setOpacity(float opacity);
|
2026-02-26 00:38:31 +08:00
|
|
|
|
float opacity() const { return opacity_; }
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
void setVisible(bool visible);
|
2026-02-26 00:38:31 +08:00
|
|
|
|
bool visible() const { return visible_; }
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
2026-02-13 18:46:42 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 设置颜色
|
|
|
|
|
|
* @param color RGB颜色
|
|
|
|
|
|
*/
|
2026-02-26 00:55:13 +08:00
|
|
|
|
void setColor(const Color3B &color);
|
2026-02-13 18:46:42 +08:00
|
|
|
|
Color3B getColor() const { return color_; }
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 设置X轴翻转
|
|
|
|
|
|
*/
|
|
|
|
|
|
void setFlipX(bool flipX);
|
2026-02-26 00:38:31 +08:00
|
|
|
|
bool flipX() const { return flipX_; }
|
2026-02-13 18:46:42 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 设置Y轴翻转
|
|
|
|
|
|
*/
|
|
|
|
|
|
void setFlipY(bool flipY);
|
2026-02-26 00:38:31 +08:00
|
|
|
|
bool flipY() const { return flipY_; }
|
2026-02-13 18:46:42 +08:00
|
|
|
|
|
2026-02-11 19:40:26 +08:00
|
|
|
|
void setZOrder(int zOrder);
|
2026-02-26 00:38:31 +08:00
|
|
|
|
int zOrder() const { return zOrder_; }
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
// 世界变换
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
Vec2 convertToWorldSpace(const Vec2 &localPos) const;
|
|
|
|
|
|
Vec2 convertToNodeSpace(const Vec2 &worldPos) const;
|
|
|
|
|
|
|
|
|
|
|
|
glm::mat4 getLocalTransform() const;
|
|
|
|
|
|
glm::mat4 getWorldTransform() const;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 标记变换矩阵为脏状态,并传播到所有子节点
|
|
|
|
|
|
*/
|
|
|
|
|
|
void markTransformDirty();
|
|
|
|
|
|
|
2026-02-11 22:30:57 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 批量更新变换矩阵
|
|
|
|
|
|
* 在渲染前统一计算所有脏节点的变换矩阵,避免逐节点计算时的重复递归
|
|
|
|
|
|
*/
|
|
|
|
|
|
void batchUpdateTransforms();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取变换脏标记状态
|
|
|
|
|
|
*/
|
|
|
|
|
|
bool isTransformDirty() const { return transformDirty_; }
|
|
|
|
|
|
bool isWorldTransformDirty() const { return worldTransformDirty_; }
|
|
|
|
|
|
|
2026-02-11 19:40:26 +08:00
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
// 名称和标签
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
void setName(const std::string &name) { name_ = name; }
|
2026-02-26 00:38:31 +08:00
|
|
|
|
const std::string &name() const { return name_; }
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
void setTag(int tag) { tag_ = tag; }
|
2026-02-26 00:38:31 +08:00
|
|
|
|
int tag() const { return tag_; }
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
// 生命周期回调
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
virtual void onEnter();
|
|
|
|
|
|
virtual void onExit();
|
|
|
|
|
|
virtual void onUpdate(float dt);
|
2026-02-26 00:59:16 +08:00
|
|
|
|
virtual void onRender(Renderer &renderer);
|
2026-02-11 19:40:26 +08:00
|
|
|
|
virtual void onAttachToScene(Scene *scene);
|
|
|
|
|
|
virtual void onDetachFromScene();
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
2026-02-26 19:41:57 +08:00
|
|
|
|
// 边界框
|
2026-02-11 19:40:26 +08:00
|
|
|
|
// ------------------------------------------------------------------------
|
2026-02-26 00:55:13 +08:00
|
|
|
|
virtual Rect boundingBox() const;
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
// 事件系统
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
EventDispatcher &getEventDispatcher() { return eventDispatcher_; }
|
|
|
|
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
// 内部方法
|
|
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
void update(float dt);
|
2026-02-26 00:59:16 +08:00
|
|
|
|
void render(Renderer &renderer);
|
2026-02-11 19:40:26 +08:00
|
|
|
|
void sortChildren();
|
|
|
|
|
|
|
|
|
|
|
|
bool isRunning() const { return running_; }
|
|
|
|
|
|
Scene *getScene() const { return scene_; }
|
|
|
|
|
|
|
|
|
|
|
|
// 多线程渲染命令收集
|
|
|
|
|
|
virtual void collectRenderCommands(std::vector<RenderCommand> &commands,
|
|
|
|
|
|
int parentZOrder = 0);
|
|
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
// 子类重写
|
2026-02-26 00:59:16 +08:00
|
|
|
|
virtual void onDraw(Renderer &renderer) {}
|
2026-02-11 19:40:26 +08:00
|
|
|
|
virtual void onUpdateNode(float dt) {}
|
|
|
|
|
|
virtual void generateRenderCommand(std::vector<RenderCommand> &commands,
|
|
|
|
|
|
int zOrder) {};
|
|
|
|
|
|
|
|
|
|
|
|
// 供子类访问的内部状态
|
|
|
|
|
|
Vec2 &getPositionRef() { return position_; }
|
|
|
|
|
|
Vec2 &getScaleRef() { return scale_; }
|
|
|
|
|
|
Vec2 &getAnchorRef() { return anchor_; }
|
|
|
|
|
|
float getRotationRef() { return rotation_; }
|
|
|
|
|
|
float getOpacityRef() { return opacity_; }
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
// ==========================================================================
|
|
|
|
|
|
// 成员变量按类型大小降序排列,减少内存对齐填充
|
2026-02-26 00:55:13 +08:00
|
|
|
|
// 64位系统对齐:std::string(32) > glm::mat4(64) > std::vector(24) >
|
2026-02-11 19:40:26 +08:00
|
|
|
|
// double(8) > float(4) > int(4) > bool(1)
|
|
|
|
|
|
// ==========================================================================
|
|
|
|
|
|
|
|
|
|
|
|
// 1. 大块内存(64字节)
|
2026-02-26 00:55:13 +08:00
|
|
|
|
mutable glm::mat4 localTransform_; // 64 bytes
|
|
|
|
|
|
mutable glm::mat4 worldTransform_; // 64 bytes
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
// 2. 字符串和容器(24-32字节)
|
2026-02-26 00:55:13 +08:00
|
|
|
|
std::string name_; // 32 bytes
|
|
|
|
|
|
std::vector<Ptr<Node>> children_; // 24 bytes
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
// 3. 子节点索引(加速查找)
|
|
|
|
|
|
std::unordered_map<std::string, WeakPtr<Node>> nameIndex_; // 56 bytes
|
|
|
|
|
|
std::unordered_map<int, WeakPtr<Node>> tagIndex_; // 56 bytes
|
|
|
|
|
|
|
2026-02-13 18:46:42 +08:00
|
|
|
|
// 4. 事件分发器
|
2026-02-26 00:55:13 +08:00
|
|
|
|
EventDispatcher eventDispatcher_; // 大小取决于实现
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
2026-02-13 18:46:42 +08:00
|
|
|
|
// 5. 父节点引用
|
2026-02-26 00:55:13 +08:00
|
|
|
|
WeakPtr<Node> parent_; // 16 bytes
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
|
|
|
|
|
// 7. 变换属性(按访问频率分组)
|
2026-02-26 00:55:13 +08:00
|
|
|
|
Vec2 position_ = Vec2::Zero(); // 8 bytes
|
|
|
|
|
|
Vec2 scale_ = Vec2(1.0f, 1.0f); // 8 bytes
|
|
|
|
|
|
Vec2 anchor_ = Vec2(0.5f, 0.5f); // 8 bytes
|
|
|
|
|
|
Vec2 skew_ = Vec2::Zero(); // 8 bytes
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
2026-02-26 19:41:57 +08:00
|
|
|
|
// 8. 浮点属性
|
2026-02-26 00:55:13 +08:00
|
|
|
|
float rotation_ = 0.0f; // 4 bytes
|
|
|
|
|
|
float opacity_ = 1.0f; // 4 bytes
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
2026-02-13 18:46:42 +08:00
|
|
|
|
// 10. 颜色属性
|
|
|
|
|
|
Color3B color_ = Color3B(255, 255, 255); // 3 bytes
|
|
|
|
|
|
|
|
|
|
|
|
// 11. 整数属性
|
2026-02-26 00:55:13 +08:00
|
|
|
|
int zOrder_ = 0; // 4 bytes
|
|
|
|
|
|
int tag_ = -1; // 4 bytes
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
2026-02-13 18:46:42 +08:00
|
|
|
|
// 12. 布尔属性
|
2026-02-26 00:55:13 +08:00
|
|
|
|
bool flipX_ = false; // 1 byte
|
|
|
|
|
|
bool flipY_ = false; // 1 byte
|
2026-02-13 18:46:42 +08:00
|
|
|
|
|
2026-02-11 19:40:26 +08:00
|
|
|
|
// 11. 场景指针
|
2026-02-26 00:55:13 +08:00
|
|
|
|
Scene *scene_ = nullptr; // 8 bytes
|
2026-02-11 19:40:26 +08:00
|
|
|
|
|
2026-02-26 19:41:57 +08:00
|
|
|
|
// 9. 布尔标志(打包在一起)
|
2026-02-26 00:55:13 +08:00
|
|
|
|
mutable bool transformDirty_ = true; // 1 byte
|
|
|
|
|
|
mutable bool worldTransformDirty_ = true; // 1 byte
|
|
|
|
|
|
bool childrenOrderDirty_ = false; // 1 byte
|
|
|
|
|
|
bool visible_ = true; // 1 byte
|
|
|
|
|
|
bool running_ = false; // 1 byte
|
2026-02-25 21:22:35 +08:00
|
|
|
|
|
2026-02-26 19:57:16 +08:00
|
|
|
|
|
2026-02-11 19:40:26 +08:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace extra2d
|