From e8ffed7feb260fc411a70f0f7358b52ccb1d0de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=A0=D0=BE=D0=BC=D0=B0=D0=BD=20=D0=95=D0=B2=D0=B3=D0=B5?= =?UTF-8?q?=D0=BD=D1=8C=D0=B5=D0=B2=D0=B8=D1=87=20=D0=9A=D0=BE=D0=B2=D0=B0?= =?UTF-8?q?=D0=BB=D0=B5=D0=B2?= Date: Tue, 17 Oct 2023 02:17:33 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9A=D0=BB=D0=B0=D1=81=D1=81=20=D1=81=D1=86?= =?UTF-8?q?=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/Scene.h | 30 ++++++++++++++++++ src/Scene.cpp | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) create mode 100644 include/Scene.h create mode 100644 src/Scene.cpp diff --git a/include/Scene.h b/include/Scene.h new file mode 100644 index 0000000..fd2ae01 --- /dev/null +++ b/include/Scene.h @@ -0,0 +1,30 @@ +#ifndef SCENE_H +#define SCENE_H + +#include "Model.h" + +// Класс сцены +class Scene +{ + public: + Scene(); // Конструктор пустой сцены + Scene(const Scene ©); // Конструктор копирования + Scene& operator=(const Scene& other); // Оператор присваивания + + void render(); // Рендер сцены + + Node root; // Корневой узел + + // Списки объектов, выступающих узлами + std::vector nodes; // Список пустых узлов + std::vector models; // Список моделей для рендера + + protected: + void rebuld_tree(const Scene& from); // Перестройка дерева после копирования или присваивания + template + void rebuild_Nodes_vector(T& nodes, const Scene& from); // Перестройка узлов выбранного списка + template + bool move_pointer(Node& for_node, const std::vector& from_nodes, std::vector& this_nodes); // Сдвигает родителя узла между двумя списками при условии его принадлежности к оригинальному, возвращает признак замены +}; + +#endif // SCENE_H diff --git a/src/Scene.cpp b/src/Scene.cpp new file mode 100644 index 0000000..51adf71 --- /dev/null +++ b/src/Scene.cpp @@ -0,0 +1,83 @@ +#include "Scene.h" + +// Конструктор пустой сцены +Scene::Scene() +{ + +} + +// Конструктор копирования +Scene::Scene(const Scene ©): root(copy.root), +nodes(copy.nodes), models(copy.models) +{ + rebuld_tree(copy); +} + +// Оператор присваивания +Scene& Scene::operator=(const Scene& other) +{ + root = other.root; + nodes = other.nodes; + models = other.models; + + rebuld_tree(other); + + return *this; +} + +// Рендер сцены +void Scene::render() +{ + for (auto & model : models) + model.render(); +} + +// Перестройка узлов выбранного списка +template +void Scene::rebuild_Nodes_vector(T& nodes, const Scene& from) +{ + for (int i = 0; i < nodes.size(); i++) + { + // Берем родителя, который указывает на оригинальный объект + Node* parent = nodes[i].getParent(); + + // Если родитель - оригинальный корневой узел, то меняем на собственный корневой узел + if (parent == &from.root) + { + nodes[i].setParent(&root); + continue; + } + + // Если наши родителя - меняем на него + if (move_pointer(nodes[i], from.nodes, this->nodes)) + continue; + if (move_pointer(nodes[i], from.models, models)) + continue; + + // Не нашли родителя - значит он не часть этой сцены + // и изменений по нему не требуется + } +} + +// Сдвигает родителя узла между двумя списками при условии его принадлежности к оригинальному, возвращает признак замены +template +bool Scene::move_pointer(Node& for_node, const std::vector& from_nodes, std::vector& this_nodes) +{ + // Определим отступ в памяти + std::ptrdiff_t offset = (T*)for_node.getParent() - from_nodes.data(); + // Если отступ является частью оригинального списка + if (offset >= 0 && offset < from_nodes.size()) + { + for_node.setParent(this_nodes.data() + offset); // Замена родителя + return true; + } + return false; +} + +// Перестройка дерева после копирования или присваивания +void Scene::rebuld_tree(const Scene& from) +{ + // Восстановим родителей в пустых узлах для копии + rebuild_Nodes_vector(nodes, from); + rebuild_Nodes_vector(models, from); +}