From b5572c5de0116d35400ddb85b4331399c1679754 Mon Sep 17 00:00:00 2001 From: "re.kovalev" Date: Tue, 2 Jan 2024 20:13:44 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D1=81=D1=82=D1=80?= =?UTF-8?q?=D0=BE=D0=B9=D0=BA=D0=B0=20=D1=83=D0=B7=D0=BB=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=B2=20=D0=B0=D0=BD=D0=B8=D0=BC=D0=B0=D1=86=D0=B8=D1=8F=D1=85?= =?UTF-8?q?=20=D1=81=D1=86=D0=B5=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/Scene.h | 2 ++ src/Scene.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/include/Scene.h b/include/Scene.h index 60d2571..cd27a6f 100644 --- a/include/Scene.h +++ b/include/Scene.h @@ -43,6 +43,8 @@ class Scene void rebuild_Nodes_list(T& nodes, const Scene& from); // Перестройка узлов выбранного списка template void move_parent(Node& for_node, const std::list& from_nodes, std::list& this_nodes); // Сдвигает родителя узла между двумя списками при условии его принадлежности к оригинальному + template + void move_animation_target(Node*& target, const std::list& from_nodes, std::list& this_nodes); // Перестройка узлов анимации }; #endif // SCENE_H diff --git a/src/Scene.cpp b/src/Scene.cpp index b46e664..ab6d81c 100644 --- a/src/Scene.cpp +++ b/src/Scene.cpp @@ -8,7 +8,8 @@ Scene::Scene() // Конструктор копирования Scene::Scene(const Scene ©): root(copy.root), -nodes(copy.nodes), models(copy.models), cameras(copy.cameras) +nodes(copy.nodes), models(copy.models), cameras(copy.cameras), +animations(copy.animations), animation_names(copy.animation_names) { rebuld_tree(copy); } @@ -20,7 +21,9 @@ Scene& Scene::operator=(const Scene& other) nodes = other.nodes; models = other.models; cameras = other.cameras; - + animations = other.animations; + animation_names = other.animation_names; + rebuld_tree(other); return *this; @@ -79,6 +82,18 @@ void Scene::move_parent(Node& for_node, const std::list& from_nodes, std::lis for_node.setParent(&(*it_this)); } +// Перестройка узлов анимации +template +void Scene::move_animation_target(Node*& target, const std::list& from_nodes, std::list& this_nodes) +{ + // Цикл по элементам списков для перемещения родителя + // Списки в процессе копирования идеинтичные, вторая проверка не требуется + for (auto it_from = from_nodes.begin(), it_this = this_nodes.begin(); it_from != from_nodes.end(); ++it_from, ++it_this) + // Если адрес объекта, на который указывает итератор, совпадает с родителем - меняем родителя по второму итератору (it_this) + if (&(*it_from) == target) + target = &(*it_this); +} + // Перестройка дерева после копирования или присваивания void Scene::rebuld_tree(const Scene& from) { @@ -86,6 +101,32 @@ void Scene::rebuld_tree(const Scene& from) rebuild_Nodes_list(nodes, from); rebuild_Nodes_list(models, from); rebuild_Nodes_list(cameras, from); + + // Восстановим указатели на узлы для каналов анимаций + for (auto & animation : animations) + for (auto & channel : animation.channels) + { + // Если целевой узел - оригинальный корневой узел, то меняем на собственный корневой узел + if (channel.target == &from.root) + { + channel.target = &root; + continue; + } + + // Если можно привести к модели, то ищем родителя среди моделей + if (dynamic_cast(channel.target)) + move_animation_target(channel.target, from.models, this->models); + else + // Иначе проверяем на принадлежность к камерам + if (dynamic_cast(channel.target)) + move_animation_target(channel.target, from.cameras, this->cameras); + // Иначе это пустой узел + else + move_animation_target(channel.target, from.nodes, this->nodes); + + // Не нашли узел - значит он не часть этой сцены + // и изменений по каналу не требуется + } } #define TINYOBJLOADER_IMPLEMENTATION