/* * 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 namespace openVulkanoCpp::Scene { Node::Node() : localMat(1), worldMat(1) {} 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::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::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) this->scene = 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) { Logger::SCENE->warn("Drawable is already associated with a scene! Creating copy."); drawable = drawable->Copy(); } drawable->SetScene(scene); } } }