Extra2D/include/scene/node.h

335 lines
10 KiB
C
Raw Normal View History

2026-02-11 19:40:26 +08:00
#pragma once
#include <algorithm>
#include <core/color.h>
#include <core/math_types.h>
#include <core/types.h>
#include <event/event_dispatcher.h>
#include <graphics/render_backend.h>
2026-02-11 19:40:26 +08:00
#include <functional>
#include <memory>
2026-02-11 19:40:26 +08:00
#include <string>
#include <vector>
namespace extra2d {
// 前向声明
class Scene;
class RenderBackend;
struct RenderCommand;
class Tween;
enum class TweenEasing : uint8_t;
2026-02-11 19:40:26 +08:00
// ============================================================================
// 节点基类 - 场景图的基础
// ============================================================================
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> 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);
Vec2 pos() const { return position_; }
2026-02-11 19:40:26 +08:00
void setRotation(float degrees);
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);
Vec2 scale() const { return scale_; }
2026-02-11 19:40:26 +08:00
void setAnchor(const Vec2 &anchor);
void setAnchor(float x, float y);
Vec2 anchor() const { return anchor_; }
2026-02-11 19:40:26 +08:00
void setSkew(const Vec2 &skew);
void setSkew(float x, float y);
Vec2 skew() const { return skew_; }
2026-02-11 19:40:26 +08:00
void setOpacity(float opacity);
float opacity() const { return opacity_; }
2026-02-11 19:40:26 +08:00
void setVisible(bool visible);
bool visible() const { return visible_; }
2026-02-11 19:40:26 +08:00
/**
* @brief
* @param color RGB颜色
*/
void setColor(const Color3B& color);
Color3B getColor() const { return color_; }
/**
* @brief X轴翻转
*/
void setFlipX(bool flipX);
bool flipX() const { return flipX_; }
/**
* @brief Y轴翻转
*/
void setFlipY(bool flipY);
bool flipY() const { return flipY_; }
2026-02-11 19:40:26 +08:00
void setZOrder(int zOrder);
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();
/**
* @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; }
const std::string &name() const { return name_; }
2026-02-11 19:40:26 +08:00
void setTag(int tag) { tag_ = tag; }
int tag() const { return tag_; }
2026-02-11 19:40:26 +08:00
// ------------------------------------------------------------------------
// 生命周期回调
// ------------------------------------------------------------------------
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();
// ------------------------------------------------------------------------
// 事件系统
// ------------------------------------------------------------------------
EventDispatcher &getEventDispatcher() { return eventDispatcher_; }
// ------------------------------------------------------------------------
// Tween 动画系统
// ------------------------------------------------------------------------
/**
* @brief Tween
* @return Tween
*/
Tween& tween();
/**
* @brief Tween
*/
Tween& tween(const std::string &name);
/**
* @brief
*/
Tween &moveTo(const Vec2 &pos, float duration,
TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief
*/
Tween &moveBy(const Vec2 &delta, float duration,
TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief
*/
Tween &scaleTo(float scale, float duration,
TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief
*/
Tween &scaleBy(float delta, float duration,
TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief
*/
Tween &rotateTo(float degrees, float duration,
TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief
*/
Tween &rotateBy(float degrees, float duration,
TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief 1
*/
Tween &fadeIn(float duration, TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief 0
*/
Tween &fadeOut(float duration, TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief
*/
Tween &fadeTo(float opacity, float duration,
TweenEasing easing = static_cast<TweenEasing>(0));
/**
* @brief Tween
*/
void stopAllTweens();
/**
* @brief Tween
*/
void updateTweens(float dt);
2026-02-11 19:40:26 +08:00
// ------------------------------------------------------------------------
// 内部方法
// ------------------------------------------------------------------------
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. 事件分发器
2026-02-11 19:40:26 +08:00
EventDispatcher eventDispatcher_; // 大小取决于实现
// 5. 父节点引用
2026-02-11 19:40:26 +08:00
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. 颜色属性
Color3B color_ = Color3B(255, 255, 255); // 3 bytes
// 11. 整数属性
2026-02-11 19:40:26 +08:00
int zOrder_ = 0; // 4 bytes
int tag_ = -1; // 4 bytes
// 12. 布尔属性
bool flipX_ = false; // 1 byte
bool flipY_ = false; // 1 byte
2026-02-11 19:40:26 +08:00
// 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
// 13. Tween 动画列表
std::vector<std::shared_ptr<Tween>> tweens_;
2026-02-11 19:40:26 +08:00
};
} // namespace extra2d