Extra2D/include/scene/node.h

323 lines
6.6 KiB
C++
Raw Permalink 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 <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 渲染(收集渲染命令)
*/
virtual 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