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

615 lines
14 KiB
C
Raw Normal View History

2026-02-11 19:40:26 +08:00
#pragma once
#include <extra2d/core/color.h>
#include <extra2d/core/math_types.h>
#include <extra2d/core/types.h>
#include <extra2d/event/event_dispatcher.h>
#include <extra2d/render/core/render_backend.h>
#include <extra2d/scene/component.h>
#include <extra2d/scene/components/transform_component.h>
#include <memory>
2026-02-11 19:40:26 +08:00
#include <string>
#include <unordered_map>
2026-02-11 19:40:26 +08:00
#include <vector>
namespace extra2d {
class Scene;
class RenderBackend;
struct RenderCommand;
class RenderQueue;
2026-02-11 19:40:26 +08:00
/**
* @brief -
*
*
*/
2026-02-11 19:40:26 +08:00
class Node : public std::enable_shared_from_this<Node> {
public:
/**
* @brief
* @param name
* @return
*/
static Ptr<Node> create(const std::string &name = "");
Node();
virtual ~Node();
// -------------------------------------------------------------------------
// 层级管理
// -------------------------------------------------------------------------
/**
* @brief
* @param child
*/
void addChild(Ptr<Node> child);
/**
* @brief
* @param children
*/
void addChildren(std::vector<Ptr<Node>> &&children);
/**
* @brief
* @param child
*/
void removeChild(Ptr<Node> child);
/**
* @brief
* @param name
*/
void removeChildByName(const std::string &name);
/**
* @brief
*/
void detach();
/**
* @brief
*/
void clearChildren();
/**
* @brief
* @return
*/
Ptr<Node> getParent() const { return parent_.lock(); }
/**
* @brief
* @return
*/
const std::vector<Ptr<Node>> &getChildren() const { return children_; }
/**
* @brief
* @param name
* @return nullptr
*/
Ptr<Node> findChild(const std::string &name) const;
/**
* @brief
* @param tag
* @return nullptr
*/
Ptr<Node> findChildByTag(int tag) const;
// -------------------------------------------------------------------------
// 组件系统
// -------------------------------------------------------------------------
/**
* @brief
* @tparam T
* @tparam Args
* @param args
* @return
*/
template <typename T, typename... Args> T *addComponent(Args &&...args) {
static_assert(std::is_base_of<Component, T>::value,
"T must derive from Component");
uint32_t typeId = T::getStaticTypeId();
// 检查是否已存在相同类型的组件
auto it = components_.find(typeId);
if (it != components_.end()) {
return static_cast<T *>(it->second.get());
}
// 创建新组件
auto component = makePtr<T>(std::forward<Args>(args)...);
component->setNode(this);
component->init();
component->setInitialized(true);
components_[typeId] = component;
return component.get();
}
/**
* @brief
* @tparam T
* @return nullptr
*/
template <typename T> T *getComponent() const {
static_assert(std::is_base_of<Component, T>::value,
"T must derive from Component");
uint32_t typeId = T::getStaticTypeId();
auto it = components_.find(typeId);
if (it != components_.end()) {
return static_cast<T *>(it->second.get());
}
return nullptr;
}
/**
* @brief
* @tparam T
* @return true
*/
template <typename T> bool hasComponent() const {
return getComponent<T>() != nullptr;
}
/**
* @brief
* @tparam T
*/
template <typename T> void removeComponent() {
static_assert(std::is_base_of<Component, T>::value,
"T must derive from Component");
uint32_t typeId = T::getStaticTypeId();
auto it = components_.find(typeId);
if (it != components_.end()) {
it->second->destroy();
it->second->setInitialized(false);
it->second->setNode(nullptr);
components_.erase(it);
}
}
/**
* @brief
* @return
*/
TransformComponent *getTransform() const { return transform_; }
// -------------------------------------------------------------------------
// 变换属性便捷方法委托给TransformComponent
// -------------------------------------------------------------------------
/**
* @brief
* @param pos
*/
void setPos(const Vec2 &pos);
/**
* @brief
* @param x X坐标
* @param y Y坐标
*/
void setPos(float x, float y);
/**
* @brief
* @return
*/
Vec2 getPosition() const;
/**
* @brief
* @param degrees
*/
void setRotation(float degrees);
/**
* @brief
* @return
*/
float getRotation() const;
/**
* @brief
* @param scale
*/
void setScale(const Vec2 &scale);
/**
* @brief
* @param scale
*/
void setScale(float scale);
/**
* @brief
* @param x X轴缩放值
* @param y Y轴缩放值
*/
void setScale(float x, float y);
/**
* @brief
* @return
*/
Vec2 getScale() const;
/**
* @brief
* @param anchor 0-1
*/
void setAnchor(const Vec2 &anchor);
/**
* @brief
* @param x X坐标0-1
* @param y Y坐标0-1
*/
void setAnchor(float x, float y);
/**
* @brief
* @return
*/
Vec2 getAnchor() const;
/**
* @brief
* @param skew
*/
void setSkew(const Vec2 &skew);
/**
* @brief
* @param x X轴斜切角度
* @param y Y轴斜切角度
*/
void setSkew(float x, float y);
/**
* @brief
* @return
*/
Vec2 getSkew() const;
// -------------------------------------------------------------------------
// 世界变换
// -------------------------------------------------------------------------
/**
* @brief
* @param localPos
* @return
*/
Vec2 toWorld(const Vec2 &localPos) const;
/**
* @brief
* @param worldPos
* @return
*/
Vec2 toLocal(const Vec2 &worldPos) const;
/**
* @brief
* @return
*/
glm::mat4 getLocalTransform() const;
/**
* @brief
* @return
*/
glm::mat4 getWorldTransform() const;
/**
* @brief
*/
void markTransformDirty();
/**
* @brief
*/
void batchTransforms();
/**
* @brief
*/
bool isTransformDirty() const;
bool isWorldTransformDirty() const;
// -------------------------------------------------------------------------
// 可见性和外观
// -------------------------------------------------------------------------
/**
* @brief
* @param opacity 0.0-1.0
*/
void setOpacity(float opacity);
/**
* @brief
* @return
*/
float getOpacity() const { return opacity_; }
/**
* @brief
* @param visible
*/
void setVisible(bool visible);
/**
* @brief
* @return
*/
bool isVisible() const { return visible_; }
/**
* @brief
* @param color RGB颜色
*/
void setColor(const Color3B &color);
/**
* @brief
* @return RGB颜色
*/
Color3B getColor() const { return color_; }
/**
* @brief X轴翻转
*/
void setFlipX(bool flipX);
/**
* @brief X轴翻转状态
*/
bool isFlipX() const { return flipX_; }
/**
* @brief Y轴翻转
*/
void setFlipY(bool flipY);
/**
* @brief Y轴翻转状态
*/
bool isFlipY() const { return flipY_; }
/**
* @brief Z序
* @param zOrder
*/
void setZOrder(int zOrder);
/**
* @brief Z序
* @return
*/
int getZOrder() const { return zOrder_; }
// -------------------------------------------------------------------------
// 名称和标签
// -------------------------------------------------------------------------
/**
* @brief
* @param name
*/
void setName(const std::string &name) { name_ = name; }
/**
* @brief
* @return
*/
const std::string &getName() const { return name_; }
/**
* @brief
* @param tag
*/
void setTag(int tag) { tag_ = tag; }
/**
* @brief
* @return
*/
int getTag() const { return tag_; }
// -------------------------------------------------------------------------
// 生命周期回调
// -------------------------------------------------------------------------
/**
* @brief
*/
virtual void onEnter();
/**
* @brief 退
*/
virtual void onExit();
/**
* @brief
* @param dt
*/
virtual void onUpdate(float dt);
/**
* @brief
* @param renderer
*/
virtual void onRender(RenderBackend &renderer);
/**
* @brief
* @param scene
*/
virtual void onAttachToScene(Scene *scene);
/**
* @brief
*/
virtual void onDetachFromScene();
// -------------------------------------------------------------------------
// 边界框
// -------------------------------------------------------------------------
/**
* @brief
* @return
*/
virtual Rect getBounds() const;
// -------------------------------------------------------------------------
// 事件系统
// -------------------------------------------------------------------------
/**
* @brief
* @return
*/
EventDispatcher &getEventDispatcher() { return eventDispatcher_; }
// -------------------------------------------------------------------------
// 内部方法
// -------------------------------------------------------------------------
/**
* @brief
* @param dt
*/
void update(float dt);
/**
* @brief
* @param renderer
*/
void render(RenderBackend &renderer);
/**
* @brief
*/
void sortChildren();
/**
* @brief
* @return
*/
bool isRunning() const { return running_; }
/**
* @brief
* @return
*/
Scene *getScene() const { return scene_; }
/**
* @brief
* @param commands
* @param parentZOrder Z序
*/
virtual void collectRenderCommands(std::vector<RenderCommand> &commands,
int parentZOrder = 0);
/**
* @brief
* @param queue
*/
virtual void collectRenderCommandsToQueue(RenderQueue &queue);
2026-02-11 19:40:26 +08:00
protected:
/**
* @brief
* @param renderer
*/
virtual void onDraw(RenderBackend &renderer) {}
/**
* @brief
* @param dt
*/
virtual void onUpdateNode(float dt) {}
/**
* @brief
* @param commands
* @param zOrder Z序
*/
virtual void generateRenderCommand(std::vector<RenderCommand> &commands,
int zOrder) {}
/**
* @brief
* @param queue
*/
virtual void generateRenderCommandToQueue(RenderQueue &queue) { (void)queue; }
2026-02-11 19:40:26 +08:00
private:
// ==========================================================================
// 成员变量按类型大小降序排列,减少内存对齐填充
// ==========================================================================
// 1. 大块内存64字节
mutable glm::mat4 localTransform_ = glm::mat4(1.0f);
mutable glm::mat4 worldTransform_ = glm::mat4(1.0f);
// 2. 字符串和容器24-32字节
std::string name_;
std::vector<Ptr<Node>> children_;
std::unordered_map<uint32_t, Ptr<Component>> components_;
// 3. 子节点索引(加速查找)
std::unordered_map<std::string, WeakPtr<Node>> nameIndex_;
std::unordered_map<int, WeakPtr<Node>> tagIndex_;
// 4. 事件分发器
EventDispatcher eventDispatcher_;
// 5. 父节点引用
WeakPtr<Node> parent_;
// 6. 变换组件(内置)
TransformComponent *transform_ = nullptr;
// 7. 浮点属性
float opacity_ = 1.0f;
// 8. 颜色属性
Color3B color_ = Color3B(255, 255, 255);
// 9. 整数属性
int zOrder_ = 0;
int tag_ = -1;
// 10. 布尔属性
bool flipX_ = false;
bool flipY_ = false;
// 11. 场景指针
Scene *scene_ = nullptr;
// 12. 布尔标志(打包在一起)
mutable bool transformDirty_ = true;
mutable bool worldTransformDirty_ = true;
bool childrenOrderDirty_ = false;
bool visible_ = true;
bool running_ = false;
2026-02-11 19:40:26 +08:00
};
} // namespace extra2d