Extra2D/include/scene/node.h

335 lines
10 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 <core/color.h>
#include <core/math_types.h>
#include <core/types.h>
#include <event/event_dispatcher.h>
#include <graphics/render_backend.h>
#include <functional>
#include <memory>
#include <string>
#include <vector>
namespace extra2d {
// 前向声明
class Scene;
class RenderBackend;
struct RenderCommand;
class Tween;
enum class TweenEasing : uint8_t;
// ============================================================================
// 节点基类 - 场景图的基础
// ============================================================================
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;
// ------------------------------------------------------------------------
// 变换属性
// ------------------------------------------------------------------------
void setPosition(const Vec2 &pos);
void setPosition(float x, float y);
Vec2 pos() const { return position_; }
void setRotation(float degrees);
float rot() const { return rotation_; }
void setScale(const Vec2 &scale);
void setScale(float scale);
void setScale(float x, float y);
Vec2 scale() const { return scale_; }
void setAnchor(const Vec2 &anchor);
void setAnchor(float x, float y);
Vec2 anchor() const { return anchor_; }
void setSkew(const Vec2 &skew);
void setSkew(float x, float y);
Vec2 skew() const { return skew_; }
void setOpacity(float opacity);
float opacity() const { return opacity_; }
void setVisible(bool visible);
bool visible() const { return visible_; }
/**
* @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_; }
void setZOrder(int zOrder);
int zOrder() 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();
/**
* @brief 批量更新变换矩阵
* 在渲染前统一计算所有脏节点的变换矩阵,避免逐节点计算时的重复递归
*/
void batchUpdateTransforms();
/**
* @brief 获取变换脏标记状态
*/
bool isTransformDirty() const { return transformDirty_; }
bool isWorldTransformDirty() const { return worldTransformDirty_; }
// ------------------------------------------------------------------------
// 名称和标签
// ------------------------------------------------------------------------
void setName(const std::string &name) { name_ = name; }
const std::string &name() const { return name_; }
void setTag(int tag) { tag_ = tag; }
int tag() 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();
// ------------------------------------------------------------------------
// 事件系统
// ------------------------------------------------------------------------
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);
// ------------------------------------------------------------------------
// 内部方法
// ------------------------------------------------------------------------
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. 事件分发器
EventDispatcher eventDispatcher_; // 大小取决于实现
// 5. 父节点引用
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. 整数属性
int zOrder_ = 0; // 4 bytes
int tag_ = -1; // 4 bytes
// 12. 布尔属性
bool flipX_ = false; // 1 byte
bool flipY_ = false; // 1 byte
// 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_;
};
} // namespace extra2d