323 lines
6.5 KiB
C
323 lines
6.5 KiB
C
|
|
#pragma once
|
|||
|
|
|
|||
|
|
#include <scene/component.h>
|
|||
|
|
#include <types/math/transform.h>
|
|||
|
|
#include <types/math/vec2.h>
|
|||
|
|
#include <types/math/mat4.h>
|
|||
|
|
#include <types/ptr/intrusive_ptr.h>
|
|||
|
|
#include <string>
|
|||
|
|
#include <vector>
|
|||
|
|
|
|||
|
|
namespace extra2d {
|
|||
|
|
|
|||
|
|
// 前向声明
|
|||
|
|
class Scene;
|
|||
|
|
class TransformComponent;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 场景节点类
|
|||
|
|
*
|
|||
|
|
* 节点是场景图的基本单元,可以包含多个组件和子节点
|
|||
|
|
*/
|
|||
|
|
class Node : public RefCounted {
|
|||
|
|
public:
|
|||
|
|
/**
|
|||
|
|
* @brief 构造函数
|
|||
|
|
*/
|
|||
|
|
Node();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 析构函数
|
|||
|
|
*/
|
|||
|
|
~Node() override;
|
|||
|
|
|
|||
|
|
// 禁止拷贝
|
|||
|
|
Node(const Node&) = delete;
|
|||
|
|
Node& operator=(const Node&) = delete;
|
|||
|
|
|
|||
|
|
// ========================================
|
|||
|
|
// 层级关系
|
|||
|
|
// ========================================
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 添加子节点
|
|||
|
|
* @param child 子节点
|
|||
|
|
*/
|
|||
|
|
void addChild(Ptr<Node> child);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 移除子节点
|
|||
|
|
* @param child 子节点
|
|||
|
|
*/
|
|||
|
|
void removeChild(Node* child);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 从父节点移除
|
|||
|
|
*/
|
|||
|
|
void removeFromParent();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取父节点
|
|||
|
|
* @return 父节点指针
|
|||
|
|
*/
|
|||
|
|
Node* getParent() const { return parent_; }
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取所有子节点
|
|||
|
|
* @return 子节点列表
|
|||
|
|
*/
|
|||
|
|
const std::vector<Ptr<Node>>& getChildren() const { return children_; }
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 移除所有子节点
|
|||
|
|
*/
|
|||
|
|
void removeAllChildren();
|
|||
|
|
|
|||
|
|
// ========================================
|
|||
|
|
// 组件管理
|
|||
|
|
// ========================================
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 添加组件
|
|||
|
|
* @tparam T 组件类型
|
|||
|
|
* @param component 组件
|
|||
|
|
* @return 组件指针
|
|||
|
|
*/
|
|||
|
|
template<typename T>
|
|||
|
|
T* addComponent(Ptr<T> component) {
|
|||
|
|
static_assert(std::is_base_of<Component, T>::value, "T must be derived from Component");
|
|||
|
|
T* ptr = component.get();
|
|||
|
|
components_.push_back(component);
|
|||
|
|
ptr->onAttach(this);
|
|||
|
|
|
|||
|
|
// 如果是 TransformComponent,缓存它
|
|||
|
|
if (auto* transform = dynamic_cast<TransformComponent*>(ptr)) {
|
|||
|
|
transform_ = transform;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return ptr;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取组件
|
|||
|
|
* @tparam T 组件类型
|
|||
|
|
* @return 组件指针,未找到返回 nullptr
|
|||
|
|
*/
|
|||
|
|
template<typename T>
|
|||
|
|
T* getComponent() const {
|
|||
|
|
for (const auto& comp : components_) {
|
|||
|
|
if (auto* ptr = dynamic_cast<T*>(comp.get())) {
|
|||
|
|
return ptr;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return nullptr;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 移除组件
|
|||
|
|
* @tparam T 组件类型
|
|||
|
|
*/
|
|||
|
|
template<typename T>
|
|||
|
|
void removeComponent() {
|
|||
|
|
for (auto it = components_.begin(); it != components_.end(); ++it) {
|
|||
|
|
if (dynamic_cast<T*>(it->get())) {
|
|||
|
|
(*it)->onDetach();
|
|||
|
|
components_.erase(it);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ========================================
|
|||
|
|
// 变换便捷接口
|
|||
|
|
// ========================================
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置位置
|
|||
|
|
* @param pos 位置
|
|||
|
|
*/
|
|||
|
|
void setPosition(const Vec2& pos);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置位置
|
|||
|
|
* @param x X坐标
|
|||
|
|
* @param y Y坐标
|
|||
|
|
*/
|
|||
|
|
void setPosition(float x, float y);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取位置
|
|||
|
|
* @return 位置
|
|||
|
|
*/
|
|||
|
|
Vec2 getPosition() const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置旋转角度
|
|||
|
|
* @param rot 角度(度)
|
|||
|
|
*/
|
|||
|
|
void setRotation(float rot);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @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 size 尺寸
|
|||
|
|
*/
|
|||
|
|
void setSize(const Vec2& size);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置尺寸
|
|||
|
|
* @param width 宽度
|
|||
|
|
* @param height 高度
|
|||
|
|
*/
|
|||
|
|
void setSize(float width, float height);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取尺寸
|
|||
|
|
* @return 尺寸
|
|||
|
|
*/
|
|||
|
|
Vec2 getSize() const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置锚点
|
|||
|
|
* @param anchor 锚点 [0,1]
|
|||
|
|
*/
|
|||
|
|
void setAnchor(const Vec2& anchor);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置锚点
|
|||
|
|
* @param x X锚点
|
|||
|
|
* @param y Y锚点
|
|||
|
|
*/
|
|||
|
|
void setAnchor(float x, float y);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取锚点
|
|||
|
|
* @return 锚点
|
|||
|
|
*/
|
|||
|
|
Vec2 getAnchor() const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取世界变换
|
|||
|
|
* @return 世界变换
|
|||
|
|
*/
|
|||
|
|
Transform getWorldTransform() const;
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取世界矩阵
|
|||
|
|
* @return 世界矩阵
|
|||
|
|
*/
|
|||
|
|
Mat4 getWorldMatrix() const;
|
|||
|
|
|
|||
|
|
// ========================================
|
|||
|
|
// 属性
|
|||
|
|
// ========================================
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @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(int32 tag) { tag_ = tag; }
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取标签
|
|||
|
|
* @return 标签
|
|||
|
|
*/
|
|||
|
|
int32 getTag() const { return tag_; }
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 设置是否可见
|
|||
|
|
* @param visible 是否可见
|
|||
|
|
*/
|
|||
|
|
void setVisible(bool visible) { visible_ = visible; }
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 是否可见
|
|||
|
|
* @return 是否可见
|
|||
|
|
*/
|
|||
|
|
bool isVisible() const { return visible_; }
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取 TransformComponent
|
|||
|
|
* @return TransformComponent 指针
|
|||
|
|
*/
|
|||
|
|
TransformComponent* getTransform() const { return transform_; }
|
|||
|
|
|
|||
|
|
// ========================================
|
|||
|
|
// 生命周期
|
|||
|
|
// ========================================
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 节点进入场景时调用
|
|||
|
|
*/
|
|||
|
|
void onEnter();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 节点离开场景时调用
|
|||
|
|
*/
|
|||
|
|
void onExit();
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 每帧更新
|
|||
|
|
* @param dt 帧间隔时间
|
|||
|
|
*/
|
|||
|
|
void update(float dt);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 渲染(收集渲染命令)
|
|||
|
|
*/
|
|||
|
|
void render();
|
|||
|
|
|
|||
|
|
private:
|
|||
|
|
std::string name_;
|
|||
|
|
int32 tag_ = 0;
|
|||
|
|
bool visible_ = true;
|
|||
|
|
Node* parent_ = nullptr;
|
|||
|
|
std::vector<Ptr<Node>> children_;
|
|||
|
|
std::vector<Ptr<Component>> components_;
|
|||
|
|
TransformComponent* transform_ = nullptr;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
} // namespace extra2d
|