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