Класс сцены

This commit is contained in:
parent 30ffd7e882
commit e8ffed7feb
2 changed files with 113 additions and 0 deletions

30
include/Scene.h Normal file
View File

@ -0,0 +1,30 @@
#ifndef SCENE_H
#define SCENE_H
#include "Model.h"
// Класс сцены
class Scene
{
public:
Scene(); // Конструктор пустой сцены
Scene(const Scene &copy); // Конструктор копирования
Scene& operator=(const Scene& other); // Оператор присваивания
void render(); // Рендер сцены
Node root; // Корневой узел
// Списки объектов, выступающих узлами
std::vector<Node> nodes; // Список пустых узлов
std::vector<Model> models; // Список моделей для рендера
protected:
void rebuld_tree(const Scene& from); // Перестройка дерева после копирования или присваивания
template <class T>
void rebuild_Nodes_vector(T& nodes, const Scene& from); // Перестройка узлов выбранного списка
template <class T>
bool move_pointer(Node& for_node, const std::vector<T>& from_nodes, std::vector<T>& this_nodes); // Сдвигает родителя узла между двумя списками при условии его принадлежности к оригинальному, возвращает признак замены
};
#endif // SCENE_H

83
src/Scene.cpp Normal file
View File

@ -0,0 +1,83 @@
#include "Scene.h"
// Конструктор пустой сцены
Scene::Scene()
{
}
// Конструктор копирования
Scene::Scene(const Scene &copy): 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 <class T>
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 <class T>
bool Scene::move_pointer(Node& for_node, const std::vector<T>& from_nodes, std::vector<T>& 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);
}