Extra2D/src/scene/node.cpp

217 lines
4.5 KiB
C++
Raw 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.

#include <scene/node.h>
#include <scene/components/transform_component.h>
namespace extra2d {
Node::Node() {
// 自动添加 TransformComponent
auto transform = makePtr<TransformComponent>();
transform_ = transform.get();
components_.push_back(transform);
transform_->onAttach(this);
}
Node::~Node() {
// 先分离所有组件
for (auto& comp : components_) {
comp->onDetach();
}
components_.clear();
// 移除所有子节点
removeAllChildren();
// 从父节点移除
if (parent_) {
parent_->removeChild(this);
}
}
void Node::addChild(Ptr<Node> child) {
if (!child || child.get() == this) return;
if (childIndices_.find(child.get()) != childIndices_.end()) return;
// 从原父节点移除
if (child->parent_) {
child->parent_->removeChild(child.get());
}
child->parent_ = this;
childIndices_[child.get()] = children_.size();
children_.push_back(child);
}
void Node::removeChild(Node* child) {
if (!child) return;
auto indexIt = childIndices_.find(child);
if (indexIt == childIndices_.end()) {
return;
}
const size_t removeIndex = indexIt->second;
child->parent_ = nullptr;
children_.erase(children_.begin() + removeIndex);
childIndices_.erase(indexIt);
for (size_t i = removeIndex; i < children_.size(); ++i) {
childIndices_[children_[i].get()] = i;
}
}
void Node::removeFromParent() {
if (parent_) {
parent_->removeChild(this);
}
}
void Node::removeAllChildren() {
for (auto& child : children_) {
child->parent_ = nullptr;
}
children_.clear();
childIndices_.clear();
}
// ========================================
// 变换便捷接口
// ========================================
void Node::setPosition(const Vec2& pos) {
if (transform_) {
transform_->setPosition(pos);
}
}
void Node::setPosition(float x, float y) {
setPosition(Vec2(x, y));
}
Vec2 Node::getPosition() const {
return transform_ ? transform_->getPosition() : Vec2(0, 0);
}
void Node::setRotation(float rot) {
if (transform_) {
transform_->setRotation(rot);
}
}
float Node::getRotation() const {
return transform_ ? transform_->getRotation() : 0.0f;
}
void Node::setScale(const Vec2& scale) {
if (transform_) {
transform_->setScale(scale);
}
}
void Node::setScale(float scale) {
setScale(Vec2(scale, scale));
}
void Node::setScale(float x, float y) {
setScale(Vec2(x, y));
}
Vec2 Node::getScale() const {
return transform_ ? transform_->getScale() : Vec2(1, 1);
}
void Node::setSize(const Vec2& size) {
if (transform_) {
transform_->setSize(size);
}
}
void Node::setSize(float width, float height) {
setSize(Vec2(width, height));
}
Vec2 Node::getSize() const {
return transform_ ? transform_->getSize() : Vec2(100, 100);
}
void Node::setAnchor(const Vec2& anchor) {
if (transform_) {
transform_->setAnchor(anchor);
}
}
void Node::setAnchor(float x, float y) {
setAnchor(Vec2(x, y));
}
Vec2 Node::getAnchor() const {
return transform_ ? transform_->getAnchor() : Vec2(0.5f, 0.5f);
}
Transform Node::getWorldTransform() const {
return transform_ ? transform_->getWorldTransform() : Transform();
}
Mat4 Node::getWorldMatrix() const {
return transform_ ? transform_->getWorldMatrix() : Mat4();
}
// ========================================
// 生命周期
// ========================================
void Node::onEnter() {
// 通知所有组件
for (auto& comp : components_) {
// 组件没有 onEnter可以在这里扩展
}
// 递归通知子节点
for (auto& child : children_) {
child->onEnter();
}
}
void Node::onExit() {
// 递归通知子节点
for (auto& child : children_) {
child->onExit();
}
// 通知所有组件
for (auto& comp : components_) {
// 组件没有 onExit可以在这里扩展
}
}
void Node::update(float dt) {
for (auto& comp : components_) {
if (comp.get() != transform_ && comp->isEnabled()) {
comp->update(dt);
}
}
for (auto& child : children_) {
child->update(dt);
}
}
void Node::render() {
if (!visible_) return;
if (children_.empty() && components_.size() == 1) {
return;
}
for (auto& comp : components_) {
if (comp.get() != transform_ && comp->isEnabled()) {
comp->render();
}
}
for (auto& child : children_) {
child->render();
}
}
} // namespace extra2d