#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 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 me = this; parent_->children_.Remove(me); RefPtr 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 next; for (RefPtr 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 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 child) { if (children_.IsEmpty()) return; if (child) { child->parent_ = nullptr; children_.Remove(child); } else { SDL_LogError(0, "Actor::RemoveChild failed, NULL pointer exception"); } }