加入 Node节点类 还未测试新框架

This commit is contained in:
2025-10-27 23:12:56 +08:00
parent 80d088316b
commit 0ae47e5d6a
52 changed files with 1642 additions and 458 deletions

View File

@@ -0,0 +1,62 @@
#include "Actor.h"
#include "EngineFrame/Scene/Scene.h"
#include "EngineCore/Game.h"
#include "EngineFrame/Component/RenderBase.h"
#include "EngineFrame/Render/RenderManager.h"
#include <algorithm>
Actor::Actor()
{
Init();
}
void Actor::Init()
{
addTag(Tag::ACTOR);
addTag(Tag::RENDER);
addTag(Tag::TRANSFORM);
addTag(Tag::UPDATE);
}
void Actor::Update(float deltaTime)
{
if (!Visible)
return;
BaseNode::Update(deltaTime);
}
void Actor::Render()
{
if (!Visible)
return;
// 如果有裁切视口
if (this->_CropViewportFlag)
{
RenderManager *renderer = Game::GetInstance().GetRenderer();
renderer->SetClipRect(&this->_CropViewport);
BaseNode::Render();
renderer->CloseClipRect();
}
else
{
BaseNode::Render();
}
}
void Actor::SetCropViewport(SDL_Rect CropViewport)
{
if (CropViewport.x == 0 && CropViewport.y == 0 && CropViewport.w == 0 && CropViewport.h == 0)
{
this->_CropViewportFlag = false;
}
else
{
this->_CropViewportFlag = true;
this->_CropViewport = CropViewport;
}
}
SDL_Rect Actor::GetCropViewport()
{
return this->_CropViewport;
}

View File

@@ -0,0 +1,30 @@
#pragma once
#include "EngineFrame/Base/BaseNode.h"
#include "Tool/IntrusiveList.hpp"
class Scene;
/**
* @brief Actor类继承自Actor_base类
*
* Actor类是一个基础的游戏对象类可以添加到场景中
*/
class Actor : public BaseNode
{
private:
//裁切视口Flag
bool _CropViewportFlag = false;
//裁切视口
SDL_Rect _CropViewport = {0, 0, 0, 0};
public:
Actor();
public:
void Init() override;
void Update(float deltaTime) override;
void Render() override;
// 设置裁切视口(放在Actor里 他与他的子对象都会被裁切)
void SetCropViewport(SDL_Rect CropViewport);
// 获取裁切视口
SDL_Rect GetCropViewport();
};

View File

@@ -27,11 +27,6 @@ void BaseNode::HandleEvents(SDL_Event *e)
void BaseNode::Update(float deltaTime)
{
// 如果有回调函数,则调用回调函数
if (cb_update_)
{
cb_update_(deltaTime);
}
// 如果有子节点并含有刷新标签,则更新子节点
RefPtr<BaseNode> child = m_BaseNodes.GetFirst();
while (child)
@@ -40,6 +35,14 @@ void BaseNode::Update(float deltaTime)
child->Update(deltaTime);
child = child->GetNext();
}
// 如果有回调函数,则调用回调函数
if (cb_update_.size() > 0)
{
for (auto &cb : cb_update_)
{
cb.second(deltaTime);
}
}
}
void BaseNode::PreRender()
@@ -53,7 +56,6 @@ void BaseNode::PreRender()
child = child->GetNext();
}
}
void BaseNode::Render()
{
// 如果有子节点并含有渲染标签,则渲染子节点
@@ -70,9 +72,14 @@ void BaseNode::Clear()
{
}
void BaseNode::SetCallbackOnUpdate(const UpdateCallback &cb)
void BaseNode::SetCallbackOnUpdate(std::string Key, const UpdateCallback &cb)
{
cb_update_ = cb;
cb_update_[Key] = cb;
}
void BaseNode::RemoveCallbackOnUpdate(std::string Key)
{
cb_update_.erase(Key);
}
void BaseNode::SetChildIterationTransform()

View File

@@ -20,7 +20,7 @@ public:
public:
// 更新时的回调函数
UpdateCallback cb_update_;
std::map<std::string ,UpdateCallback> cb_update_;
// 节点名称
std::string m_Name;
// 子节点列表
@@ -60,8 +60,9 @@ public:
/// \~chinese
/// @brief 设置更新时的回调函数
void SetCallbackOnUpdate(const UpdateCallback &cb);
void SetCallbackOnUpdate(std::string Key,const UpdateCallback &cb);
void RemoveCallbackOnUpdate(std::string Key);
void SetChildIterationTransform();
// 计算渲染信息

View File

@@ -0,0 +1,549 @@
#include "Node.h"
#include "EngineCore/Game.h"
void Node::Init()
{
}
void Node::HandleEvents(SDL_Event *e)
{
}
inline void Node::Update(float deltaTime)
{
if (children_.IsEmpty())
{
return;
}
RefPtr<Node> child = children_.GetFirst();
while (child)
{
if (child->GetZOrder() >= 0)
break;
child->Update(deltaTime);
child = child->GetNext();
}
UpdateSelf(deltaTime);
while (child)
{
child->Update(deltaTime);
child = child->GetNext();
}
}
inline void Node::PreRender()
{
}
inline void Node::Render()
{
}
void Node::Clear()
{
}
void Node::UpdateSelf(float deltaTime)
{
// 如果有回调函数,则调用回调函数
if (cb_update_.size() > 0)
{
for (auto &cb : cb_update_)
{
cb.second(deltaTime);
}
}
}
void Node::RemoveFromParent()
{
if (parent_)
{
parent_->RemoveChild(this);
}
}
inline void Node::PauseUpdating()
{
update_pausing_ = true;
}
inline void Node::ResumeUpdating()
{
update_pausing_ = false;
}
inline bool Node::IsUpdatePausing() const
{
return update_pausing_;
}
void Node::SetCallbackOnUpdate(std::string Key, const UpdateCallback &cb)
{
cb_update_[Key] = cb;
}
void Node::RemoveCallbackOnUpdate(std::string Key)
{
cb_update_.erase(Key);
}
bool Node::ContainsPoint(const glm::vec2 &point) const
{
// if (size_.x == 0.f || size_.y == 0.f)
return false;
// glm::vec2 local = ConvertToLocal(point);
// return local.x >= 0 && local.y >= 0 && local.x <= size_.x && local.y <= size_.y;
}
glm::vec2 Node::ConvertToLocal(const glm::vec2 &point) const
{
glm::vec2 local = GetTransformInverseMatrix().Transform(point);
return local;
}
glm::vec2 Node::ConvertToWorld(const glm::vec2 &point) const
{
glm::vec2 world = GetTransformMatrix().Transform(point);
return world;
}
void Node::ShowBorder(bool show)
{
show_border_ = show;
}
Node::Node() : visible_(true), update_pausing_(false), show_border_(false), parent_(nullptr), anchor_(0.0f, 0.0f), z_order_(0), opacity_(1.f), name_("Node")
{
Game::GetInstance().m_nodeCount++;
}
Node::~Node()
{
Game::GetInstance().m_nodeCount--;
RemoveAllChildren();
}
void Node::UpdateTransform() const
{
if (!dirty_flag_.Has(DirtyFlag::DirtyTransform))
return;
dirty_flag_.Unset(DirtyFlag::DirtyTransform);
dirty_flag_.Set(DirtyFlag::DirtyTransformInverse);
dirty_flag_.Set(DirtyFlag::DirtyVisibility);
if (transform_.IsFast())
{
transform_matrix_to_parent_ = Matrix3x2::Translation(transform_.position);
}
else
{
transform_matrix_to_parent_ = transform_.ToMatrix();
}
glm::vec2 anchor_offset(-size_.width * anchor_.x, -size_.height * anchor_.y);
transform_matrix_to_parent_.Translate(anchor_offset);
transform_matrix_ = transform_matrix_to_parent_;
if (parent_)
{
transform_matrix_ *= parent_->transform_matrix_;
}
for (const auto &child : children_)
child->dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
void Node::UpdateTransformUpwards() const
{
if (parent_)
{
parent_->UpdateTransformUpwards();
if (parent_->dirty_flag_.Has(DirtyFlag::DirtyTransform))
{
dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
}
UpdateTransform();
}
const Matrix3x2 &Node::GetTransformMatrix() const
{
UpdateTransformUpwards();
return transform_matrix_;
}
const Matrix3x2 &Node::GetTransformInverseMatrix() const
{
UpdateTransformUpwards();
if (dirty_flag_.Has(DirtyFlag::DirtyTransformInverse))
{
dirty_flag_.Unset(DirtyFlag::DirtyTransformInverse);
transform_matrix_inverse_ = transform_matrix_.Invert();
}
return transform_matrix_inverse_;
}
const Matrix3x2 &Node::GetTransformMatrixToParent() const
{
UpdateTransformUpwards();
return transform_matrix_to_parent_;
}
void Node::Reorder()
{
if (parent_)
{
RefPtr<Node> me = this;
parent_->children_.Remove(me);
RefPtr<Node> sibling = parent_->children_.GetLast();
if (sibling && sibling->GetZOrder() > z_order_)
{
sibling = sibling->GetPrev();
while (sibling)
{
if (sibling->GetZOrder() <= z_order_)
break;
sibling = sibling->GetPrev();
}
}
if (sibling)
{
parent_->children_.InsertAfter(me, sibling);
}
else
{
parent_->children_.PushFront(me);
}
}
}
inline void Node::RemoveAllChildren()
{
RefPtr<Node> next;
for (RefPtr<Node> child = children_.GetFirst(); child; child = next)
{
next = child->GetNext();
RemoveChild(child);
}
}
inline bool Node::IsVisible() const
{
return visible_;
}
inline int Node::GetZOrder() const
{
return z_order_;
}
inline glm::vec2 Node::GetPosition() const
{
return transform_.position;
}
inline float Node::GetPositionX() const
{
return GetPosition().x;
}
inline float Node::GetPositionY() const
{
return GetPosition().y;
}
inline VecSize Node::GetSize() const
{
return size_;
}
inline float Node::GetWidth() const
{
return GetSize().width;
}
inline float Node::GetHeight() const
{
return GetSize().height;
}
inline float Node::GetScaledWidth() const
{
return GetWidth() * GetScaleX();
}
inline float Node::GetScaledHeight() const
{
return GetHeight() * GetScaleY();
}
inline VecSize Node::GetScaledSize() const
{
return VecSize{GetScaledWidth(), GetScaledHeight()};
}
inline glm::vec2 Node::GetAnchor() const
{
return anchor_;
}
inline float Node::GetAnchorX() const
{
return GetAnchor().x;
}
inline float Node::GetAnchorY() const
{
return GetAnchor().y;
}
inline float Node::GetOpacity() const
{
return opacity_;
}
inline float Node::GetRotation() const
{
return transform_.rotation;
}
inline glm::vec2 Node::GetScale() const
{
return transform_.scale;
}
inline float Node::GetScaleX() const
{
return GetScale().x;
}
inline float Node::GetScaleY() const
{
return GetScale().y;
}
inline glm::vec2 Node::GetSkew() const
{
return transform_.skew;
}
inline float Node::GetSkewX() const
{
return GetSkew().x;
}
inline float Node::GetSkewY() const
{
return GetSkew().y;
}
inline Y_Transform Node::GetTransform() const
{
return transform_;
}
inline Node *Node::GetParent() const
{
return parent_;
}
inline void Node::SetVisible(bool val)
{
visible_ = val;
}
inline void Node::SetName(std::string name)
{
name_ = name;
}
inline void Node::SetPosition(const glm::vec2 &pos)
{
if (transform_.position == pos)
return;
transform_.position = pos;
dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
inline void Node::SetPosition(float x, float y)
{
this->SetPosition(glm::vec2(x, y));
}
inline void Node::SetPositionX(float x)
{
this->SetPosition(glm::vec2(x, GetPosition().y));
}
inline void Node::SetPositionY(float y)
{
this->SetPosition(glm::vec2(GetPosition().x, y));
}
inline void Node::MoveTo(const glm::vec2 &p)
{
this->SetPosition(p);
}
inline void Node::MoveTo(float x, float y)
{
this->SetPosition(glm::vec2(x, y));
}
inline void Node::MoveBy(const glm::vec2 &trans)
{
this->SetPosition(transform_.position.x + trans.x, transform_.position.y + trans.y);
}
inline void Node::MoveBy(float trans_x, float trans_y)
{
this->MoveBy(glm::vec2(trans_x, trans_y));
}
inline void Node::SetScale(const glm::vec2 &scale)
{
if (transform_.scale == scale)
return;
transform_.scale = scale;
dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
inline void Node::SetScale(float scalex, float scaley)
{
this->SetScale(glm::vec2(scalex, scaley));
}
inline void Node::SetSkew(const glm::vec2 &skew)
{
if (transform_.skew == skew)
return;
transform_.skew = skew;
dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
inline void Node::SetSkew(float skewx, float skewy)
{
this->SetSkew(glm::vec2(skewx, skewy));
}
inline void Node::SetRotation(float rotation)
{
if (transform_.rotation == rotation)
return;
transform_.rotation = rotation;
dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
inline void Node::SetAnchor(const glm::vec2 &anchor)
{
if (anchor_ == anchor)
return;
anchor_ = anchor;
dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
inline void Node::SetAnchor(float anchorx, float anchory)
{
this->SetAnchor(glm::vec2(anchorx, anchory));
}
inline void Node::SetSize(const VecSize &size)
{
if (size_ == size)
return;
size_ = size;
dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
inline void Node::SetSize(float width, float height)
{
this->SetSize(VecSize{width, height});
}
inline void Node::SetWidth(float width)
{
this->SetSize(width, GetHeight());
}
inline void Node::SetHeight(float height)
{
this->SetSize(GetWidth(), height);
}
inline void Node::SetOpacity(float opacity)
{
if (opacity_ == opacity)
return;
opacity_ = std::min(std::max(opacity, 0.f), 1.f);
dirty_flag_.Set(DirtyFlag::DirtyOpacity);
}
inline void Node::SetTransform(const Y_Transform &transform)
{
transform_ = transform;
dirty_flag_.Set(DirtyFlag::DirtyTransform);
}
inline void Node::SetZOrder(int zorder)
{
if (z_order_ != zorder)
{
z_order_ = zorder;
Reorder();
}
}
void Node::AddChild(RefPtr<Node> child)
{
if (child)
{
assert(!child->parent_ && "Actor::AddChild failed, the actor to be added already has a parent");
children_.PushBack(child);
child->parent_ = this;
child->dirty_flag_.Set(DirtyFlag::DirtyTransform);
child->dirty_flag_.Set(DirtyFlag::DirtyOpacity);
child->Reorder();
}
else
{
SDL_LogError(0, "Actor::AddChild failed, NULL pointer exception");
}
}
Node::NodeList &Node::GetAllChildren()
{
return children_;
}
const Node::NodeList &Node::GetAllChildren() const
{
return children_;
}
inline void Node::RemoveChild(RefPtr<Node> child)
{
if (children_.IsEmpty())
return;
if (child)
{
child->parent_ = nullptr;
children_.Remove(child);
}
else
{
SDL_LogError(0, "Actor::RemoveChild failed, NULL pointer exception");
}
}

View File

@@ -0,0 +1,355 @@
#pragma once
#include <SDL.h>
#include "EngineFrame/Attribute/Y_Transform.h"
#include "EngineFrame/Attribute/Flag.h"
#include "math/Math.h"
#include "Tool/RefObject.h"
#include "Tool/RefPtr.h"
#include "Tool/IntrusiveList.hpp"
class Node : public RefObject, protected IntrusiveListValue<RefPtr<Node>>
{
public:
typedef std::function<void(float deltaTime)> UpdateCallback;
typedef IntrusiveList<RefPtr<Node>> NodeList;
using IntrusiveListValue<RefPtr<Node>>::GetNext;
using IntrusiveListValue<RefPtr<Node>>::GetPrev;
private:
/**变换属性 */
Y_Transform transform_;
/**变换矩阵 */
mutable Matrix3x2 transform_matrix_;
mutable Matrix3x2 transform_matrix_inverse_;
mutable Matrix3x2 transform_matrix_to_parent_;
/**更新时的回调函数 */
std::map<std::string, UpdateCallback> cb_update_;
/**锚点 */
glm::vec2 anchor_;
/**Z轴显示层级 */
int z_order_;
/**大小 */
VecSize size_;
/**透明度 */
float opacity_;
/**是否可见 */
bool visible_;
/**是否暂停更新 */
bool update_pausing_;
/**是否显示边界 */
bool show_border_;
/**名称 */
std::string name_;
/**父对象 */
Node *parent_;
/**子对象链表 */
NodeList children_;
/**标志 */
mutable Flag<uint8_t> dirty_flag_;
public:
virtual void Init();
virtual void HandleEvents(SDL_Event *e);
virtual void Update(float deltaTime);
virtual void PreRender();
virtual void Render();
virtual void Clear();
void UpdateSelf(float dt);
public:
/// \~chinese
/// @brief 获取显示状态
bool IsVisible() const;
/// \~chinese
/// @brief 获取 Z 轴顺序
int GetZOrder() const;
/// \~chinese
/// @brief 获取坐标
glm::vec2 GetPosition() const;
/// \~chinese
/// @brief 获取 x 坐标
float GetPositionX() const;
/// \~chinese
/// @brief 获取 y 坐标
float GetPositionY() const;
/// \~chinese
/// @brief 获取大小
virtual VecSize GetSize() const;
/// \~chinese
/// @brief 获取宽度
float GetWidth() const;
/// \~chinese
/// @brief 获取高度
float GetHeight() const;
/// \~chinese
/// @brief 获取缩放后的宽度
float GetScaledWidth() const;
/// \~chinese
/// @brief 获取缩放后的高度
float GetScaledHeight() const;
/// \~chinese
/// @brief 获取缩放后的大小
VecSize GetScaledSize() const;
/// \~chinese
/// @brief 获取锚点
glm::vec2 GetAnchor() const;
/// \~chinese
/// @brief 获取 x 方向锚点
float GetAnchorX() const;
/// \~chinese
/// @brief 获取 y 方向锚点
float GetAnchorY() const;
/// \~chinese
/// @brief 获取透明度
float GetOpacity() const;
/// \~chinese
/// @brief 获取旋转角度
float GetRotation() const;
/// \~chinese
/// @brief 获取缩放比例
glm::vec2 GetScale() const;
/// \~chinese
/// @brief 获取横向缩放比例
float GetScaleX() const;
/// \~chinese
/// @brief 获取纵向缩放比例
float GetScaleY() const;
/// \~chinese
/// @brief 获取错切角度
glm::vec2 GetSkew() const;
/// \~chinese
/// @brief 获取横向错切角度
float GetSkewX() const;
/// \~chinese
/// @brief 获取纵向错切角度
float GetSkewY() const;
/// \~chinese
/// @brief 获取变换
Y_Transform GetTransform() const;
/// \~chinese
/// @brief 获取父角色
Node *GetParent() const;
/// \~chinese
/// @brief 设置角色是否可见
void SetVisible(bool val);
/// \~chinese
/// @brief 设置名称
void SetName(std::string name);
/// \~chinese
/// @brief 设置坐标
void SetPosition(const glm::vec2 &pos);
/// \~chinese
/// @brief 设置坐标
void SetPosition(float x, float y);
/// \~chinese
/// @brief 设置横坐标
void SetPositionX(float x);
/// \~chinese
/// @brief 设置纵坐标
void SetPositionY(float y);
/// \~chinese
/// @brief 移动至坐标
void MoveTo(const glm::vec2 &p);
/// \~chinese
/// @brief 移动至坐标
void MoveTo(float x, float y);
/// \~chinese
/// @brief 移动相对坐标
void MoveBy(const glm::vec2 &trans);
/// \~chinese
/// @brief 移动相对坐标
void MoveBy(float trans_x, float trans_y);
/// \~chinese
/// @brief 设置缩放比例,默认为 (1.0, 1.0)
void SetScale(const glm::vec2 &scale);
/// \~chinese
/// @brief 设置缩放比例,默认为 (1.0, 1.0)
void SetScale(float scalex, float scaley);
/// \~chinese
/// @brief 设置错切角度,默认为 (0, 0)
void SetSkew(const glm::vec2 &skew);
/// \~chinese
/// @brief 设置错切角度,默认为 (0, 0)
void SetSkew(float skewx, float skewy);
/// \~chinese
/// @brief 设置旋转角度,默认为 0
void SetRotation(float rotation);
/// \~chinese
/// @brief 设置锚点位置,默认为 (0, 0), 范围 [0, 1]
void SetAnchor(const glm::vec2 &anchor);
/// \~chinese
/// @brief 设置锚点位置,默认为 (0, 0), 范围 [0, 1]
void SetAnchor(float anchorx, float anchory);
/// \~chinese
/// @brief 修改大小
void SetSize(const VecSize &size);
/// \~chinese
/// @brief 修改大小
void SetSize(float width, float height);
/// \~chinese
/// @brief 修改宽度
void SetWidth(float width);
/// \~chinese
/// @brief 修改高度
void SetHeight(float height);
/// \~chinese
/// @brief 设置透明度,默认为 1.0, 范围 [0, 1]
void SetOpacity(float opacity);
/// \~chinese
/// @brief 设置二维仿射变换
void SetTransform(const Y_Transform &transform);
/// \~chinese
/// @brief 设置 Z 轴顺序,默认为 0
void SetZOrder(int zorder);
/// \~chinese
/// @brief 添加子角色
void AddChild(RefPtr<Node> child);
/// \~chinese
/// @brief 获取全部子角色
NodeList &GetAllChildren();
/// \~chinese
/// @brief 获取全部子角色
const NodeList &GetAllChildren() const;
/// \~chinese
/// @brief 移除子角色
void RemoveChild(RefPtr<Node> child);
/// \~chinese
/// @brief 移除所有节点
void RemoveAllChildren();
/// \~chinese
/// @brief 从父角色移除
void RemoveFromParent();
/// \~chinese
/// @brief 暂停角色更新
void PauseUpdating();
/// \~chinese
/// @brief 继续角色更新
void ResumeUpdating();
/// \~chinese
/// @brief 角色更新是否暂停
bool IsUpdatePausing() const;
/// \~chinese
/// @brief 设置更新时的回调函数
void SetCallbackOnUpdate(std::string Key, const UpdateCallback &cb);
/// \~chinese
/// @brief 移除更新时的回调函数
void RemoveCallbackOnUpdate(std::string Key);
/// \~chinese
/// @brief 判断点是否在角色内
virtual bool ContainsPoint(const glm::vec2 &point) const;
/// \~chinese
/// @brief 将世界坐标系点转换为局部坐标系点
glm::vec2 ConvertToLocal(const glm::vec2 &point) const;
/// \~chinese
/// @brief 将局部坐标系点转换为世界坐标系点
glm::vec2 ConvertToWorld(const glm::vec2 &point) const;
/// \~chinese
/// @brief 渲染角色边界
void ShowBorder(bool show);
public:
Node(/* args */);
~Node();
/// \~chinese
/// @brief 更新自己的二维变换,并通知所有子角色
void UpdateTransform() const;
/// \~chinese
/// @brief 向上追溯更新
/// @details 对于节点树 A->B(dirty)->C->D当对 D 执行 UpdateTransformUpwards 时会对 B、C、D 从上到下依次更新
void UpdateTransformUpwards() const;
/// \~chinese
/// @brief 获取二维变换矩阵
const Matrix3x2 &GetTransformMatrix() const;
/// \~chinese
/// @brief 获取二维变换的逆矩阵
const Matrix3x2 &GetTransformInverseMatrix() const;
/// \~chinese
/// @brief 获取变换到父角色的二维变换矩阵
const Matrix3x2 &GetTransformMatrixToParent() const;
/// \~chinese
/// @brief 将所有子角色按Z轴顺序排序
void Reorder();
enum DirtyFlag : uint8_t
{
Clean = 0,
DirtyTransform = 1,
DirtyTransformInverse = 1 << 1,
DirtyOpacity = 1 << 2,
DirtyVisibility = 1 << 3
};
};