136 lines
3.1 KiB
C++
136 lines
3.1 KiB
C++
/*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#include "Node.hpp"
|
|
#include "Base/Utils.hpp"
|
|
#include "Base/Logger.hpp"
|
|
#include <stdexcept>
|
|
|
|
namespace OpenVulkano::Scene
|
|
{
|
|
Node::Node()
|
|
: localMat(1), worldMat(1), enabled(true)
|
|
{}
|
|
|
|
Node::~Node() noexcept
|
|
{
|
|
if (parent || scene || !children.empty() || !drawables.empty())
|
|
{
|
|
Node::Close();
|
|
}
|
|
}
|
|
|
|
void Node::Init()
|
|
{
|
|
if (parent || scene || !children.empty() || !drawables.empty()) throw std::runtime_error("Node already initialized");
|
|
localMat = worldMat = Math::Matrix4f(1);
|
|
enabled = true;
|
|
}
|
|
|
|
void Node::Close()
|
|
{
|
|
children.clear();
|
|
if (renderNode) renderNode->Close();
|
|
parent = nullptr;
|
|
scene = nullptr;
|
|
enabled = false;
|
|
if (!children.empty()) Logger::SCENE->warn("Closing Node that has children!");
|
|
for (Node* child : children)
|
|
{
|
|
child->SetParent(nullptr);
|
|
}
|
|
children.clear();
|
|
for(Drawable* drawable : drawables)
|
|
{
|
|
drawable->RemoveNode(this);
|
|
}
|
|
drawables.clear();
|
|
}
|
|
|
|
void Node::AddChild(Node* node)
|
|
{
|
|
node->SetParent(this);
|
|
children.push_back(node);
|
|
node->UpdateWorldMatrix(worldMat);
|
|
}
|
|
|
|
void Node::AddChildIfParentless(Node* node)
|
|
{
|
|
if (!node->parent) AddChild(node);
|
|
}
|
|
|
|
void Node::RemoveChild(Node* node)
|
|
{
|
|
if (node->parent == this)
|
|
{
|
|
Utils::Remove(children, node);
|
|
node->SetParent(nullptr);
|
|
}
|
|
}
|
|
|
|
void Node::AddDrawable(Drawable* drawable)
|
|
{
|
|
if (scene) drawable->SetScene(scene);
|
|
else if (drawable->GetScene()) Logger::SCENE->warn("Drawable is already associated with a scene, but the node it was added to is not!");
|
|
drawable->AddNode(this);
|
|
drawables.push_back(drawable);
|
|
}
|
|
|
|
void Node::AddDrawableIfParentless(Drawable* drawable)
|
|
{
|
|
if (drawable->GetNodes().empty())
|
|
AddDrawable(drawable);
|
|
}
|
|
|
|
void Node::RemoveDrawable(Drawable* drawable)
|
|
{
|
|
drawable->RemoveNode(this);
|
|
Utils::Remove(drawables, drawable);
|
|
}
|
|
|
|
void Node::SetMatrix(const Math::Matrix4f& mat)
|
|
{
|
|
localMat = mat;
|
|
UpdateWorldMatrix(parent ? parent->GetWorldMatrix() : Math::Matrix4f(1));
|
|
}
|
|
|
|
void Node::UpdateWorldMatrix(const Math::Matrix4f& parentWorldMat)
|
|
{
|
|
worldMat = parentWorldMat * localMat;
|
|
for (const auto& node : children)
|
|
{
|
|
node->UpdateWorldMatrix(worldMat);
|
|
}
|
|
}
|
|
|
|
void Node::SetParent(Node* parent)
|
|
{
|
|
if (this->parent && parent) throw std::runtime_error("Node already has a parent! Nodes must not be used multiple times!");
|
|
this->parent = parent;
|
|
if(parent && parent != this) SetScene(parent->scene);
|
|
if (!parent) SetScene(nullptr);
|
|
}
|
|
|
|
void Node::SetScene(Scene* scene)
|
|
{
|
|
if (this->scene && scene) throw std::runtime_error("Node already has a scene!");
|
|
this->scene = scene;
|
|
for (const auto& node : children)
|
|
{
|
|
node->SetScene(scene);
|
|
}
|
|
for (auto& drawable : drawables)
|
|
{
|
|
Scene* drawableScene = drawable->GetScene();
|
|
if(drawableScene && drawableScene != scene) [[unlikely]]
|
|
{
|
|
throw std::runtime_error("Drawable is already associated with a scene! Creating copy.");
|
|
}
|
|
drawable->SetScene(scene);
|
|
}
|
|
}
|
|
}
|