Extra2D/Extra2D/include/extra2d/scene/node.h

230 lines
8.0 KiB
C++
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.

#pragma once
#include <algorithm>
#include <extra2d/core/color.h>
#include <extra2d/core/math_types.h>
#include <extra2d/core/types.h>
#include <extra2d/event/event_dispatcher.h>
#include <extra2d/graphics/render_backend.h>
#include <functional>
#include <string>
#include <vector>
namespace extra2d {
// 前向声明
class Scene;
class Action;
class RenderBackend;
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();
Ptr<Node> getParent() const { return parent_.lock(); }
const std::vector<Ptr<Node>> &getChildren() const { return children_; }
Ptr<Node> getChildByName(const std::string &name) const;
Ptr<Node> getChildByTag(int tag) const;
// ------------------------------------------------------------------------
// 变换属性
// ------------------------------------------------------------------------
void setPosition(const Vec2 &pos);
void setPosition(float x, float y);
Vec2 getPosition() const { return position_; }
void setRotation(float degrees);
float getRotation() const { return rotation_; }
void setScale(const Vec2 &scale);
void setScale(float scale);
void setScale(float x, float y);
Vec2 getScale() const { return scale_; }
void setAnchor(const Vec2 &anchor);
void setAnchor(float x, float y);
Vec2 getAnchor() const { return anchor_; }
void setSkew(const Vec2 &skew);
void setSkew(float x, float y);
Vec2 getSkew() const { return skew_; }
void setOpacity(float opacity);
float getOpacity() const { return opacity_; }
void setVisible(bool visible);
bool isVisible() const { return visible_; }
void setZOrder(int zOrder);
int getZOrder() const { return zOrder_; }
// ------------------------------------------------------------------------
// 世界变换
// ------------------------------------------------------------------------
Vec2 convertToWorldSpace(const Vec2 &localPos) const;
Vec2 convertToNodeSpace(const Vec2 &worldPos) const;
glm::mat4 getLocalTransform() const;
glm::mat4 getWorldTransform() const;
/**
* @brief 标记变换矩阵为脏状态,并传播到所有子节点
*/
void markTransformDirty();
// ------------------------------------------------------------------------
// 名称和标签
// ------------------------------------------------------------------------
void setName(const std::string &name) { name_ = name; }
const std::string &getName() const { return name_; }
void setTag(int tag) { tag_ = tag; }
int getTag() const { return tag_; }
// ------------------------------------------------------------------------
// 生命周期回调
// ------------------------------------------------------------------------
virtual void onEnter();
virtual void onExit();
virtual void onUpdate(float dt);
virtual void onRender(RenderBackend &renderer);
virtual void onAttachToScene(Scene *scene);
virtual void onDetachFromScene();
// ------------------------------------------------------------------------
// 边界框(用于空间索引)
// ------------------------------------------------------------------------
virtual Rect getBoundingBox() const;
// 是否需要参与空间索引(默认 true
void setSpatialIndexed(bool indexed) { spatialIndexed_ = indexed; }
bool isSpatialIndexed() const { return spatialIndexed_; }
// 更新空间索引(手动调用,通常在边界框变化后)
void updateSpatialIndex();
// ------------------------------------------------------------------------
// 动作系统
// ------------------------------------------------------------------------
void runAction(Ptr<Action> action);
void stopAllActions();
void stopAction(Ptr<Action> action);
void stopActionByTag(int tag);
Ptr<Action> getActionByTag(int tag) const;
size_t getActionCount() const { return actions_.size(); }
// ------------------------------------------------------------------------
// 事件系统
// ------------------------------------------------------------------------
EventDispatcher &getEventDispatcher() { return eventDispatcher_; }
// ------------------------------------------------------------------------
// 内部方法
// ------------------------------------------------------------------------
void update(float dt);
void render(RenderBackend &renderer);
void sortChildren();
bool isRunning() const { return running_; }
Scene *getScene() const { return scene_; }
// 多线程渲染命令收集
virtual void collectRenderCommands(std::vector<RenderCommand> &commands,
int parentZOrder = 0);
protected:
// 子类重写
virtual void onDraw(RenderBackend &renderer) {}
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:
// ==========================================================================
// 成员变量按类型大小降序排列,减少内存对齐填充
// 64位系统对齐std::string(32) > glm::mat4(64) > std::vector(24) >
// double(8) > float(4) > int(4) > bool(1)
// ==========================================================================
// 1. 大块内存64字节
mutable glm::mat4 localTransform_; // 64 bytes
mutable glm::mat4 worldTransform_; // 64 bytes
// 2. 字符串和容器24-32字节
std::string name_; // 32 bytes
std::vector<Ptr<Node>> children_; // 24 bytes
// 3. 子节点索引(加速查找)
std::unordered_map<std::string, WeakPtr<Node>> nameIndex_; // 56 bytes
std::unordered_map<int, WeakPtr<Node>> tagIndex_; // 56 bytes
// 4. 动作系统(使用 unordered_map 加速 tag 查找)
std::unordered_map<int, Ptr<Action>> actionByTag_; // 56 bytes
std::vector<Ptr<Action>> actions_; // 24 bytes无 tag 的 Action
// 5. 事件分发器
EventDispatcher eventDispatcher_; // 大小取决于实现
// 6. 父节点引用
WeakPtr<Node> parent_; // 16 bytes
// 7. 变换属性(按访问频率分组)
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
// 8. 边界框(用于空间索引)
Rect lastSpatialBounds_; // 16 bytes
// 9. 浮点属性
float rotation_ = 0.0f; // 4 bytes
float opacity_ = 1.0f; // 4 bytes
// 10. 整数属性
int zOrder_ = 0; // 4 bytes
int tag_ = -1; // 4 bytes
// 11. 场景指针
Scene *scene_ = nullptr; // 8 bytes
// 12. 布尔标志(打包在一起)
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
bool spatialIndexed_ = true; // 1 byte
// 填充 2 bytes 到 8 字节对齐
};
} // namespace extra2d