Warning, file /graphics/glaxnimate/src/core/model/comp_graph.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best> 0003 * 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 0007 #include "comp_graph.hpp" 0008 0009 #include <unordered_set> 0010 #include <unordered_map> 0011 #include <deque> 0012 0013 #include "model/document.hpp" 0014 #include "model/assets/assets.hpp" 0015 #include "model/shapes/precomp_layer.hpp" 0016 0017 void glaxnimate::model::CompGraph::add_composition(glaxnimate::model::Composition* comp) 0018 { 0019 std::vector<glaxnimate::model::PreCompLayer*>& comp_layers = layers[comp]; 0020 std::deque<glaxnimate::model::DocumentNode*> nodes(comp->docnode_children().begin(), comp->docnode_children().end()); 0021 0022 while ( !nodes.empty() ) 0023 { 0024 auto front = nodes.front(); 0025 nodes.pop_front(); 0026 if ( auto layer = front->cast<glaxnimate::model::PreCompLayer>() ) 0027 comp_layers.push_back(layer); 0028 else 0029 nodes.insert(nodes.end(), front->docnode_children().begin(), front->docnode_children().end()); 0030 } 0031 } 0032 0033 void glaxnimate::model::CompGraph::remove_composition(glaxnimate::model::Composition* comp) 0034 { 0035 layers.erase(comp); 0036 } 0037 0038 bool glaxnimate::model::CompGraph::is_ancestor_of(glaxnimate::model::Composition* ancestor, glaxnimate::model::Composition* descendant) const 0039 { 0040 std::unordered_set<glaxnimate::model::Composition*> checked; 0041 std::unordered_set<glaxnimate::model::Composition*> not_checked; 0042 not_checked.insert(ancestor); 0043 0044 while ( !not_checked.empty() ) 0045 { 0046 std::unordered_set<glaxnimate::model::Composition*> next; 0047 0048 for ( glaxnimate::model::Composition* comp : not_checked ) 0049 { 0050 if ( comp == descendant ) 0051 return true; 0052 0053 auto it = layers.find(comp); 0054 if ( it == layers.end() ) 0055 continue; 0056 0057 for ( auto layer : layers.at(comp) ) 0058 { 0059 auto laycomp = layer->composition.get(); 0060 if ( laycomp && !checked.count(laycomp) ) 0061 next.insert(laycomp); 0062 } 0063 0064 checked.insert(comp); 0065 } 0066 0067 not_checked = std::move(next); 0068 } 0069 0070 return false; 0071 } 0072 0073 std::vector<glaxnimate::model::Composition *> glaxnimate::model::CompGraph::children(glaxnimate::model::Composition* comp) const 0074 { 0075 std::unordered_set<glaxnimate::model::Composition*> vals; 0076 for ( auto layer : layers.at(comp) ) 0077 { 0078 if ( auto laycomp = layer->composition.get() ) 0079 vals.insert(laycomp); 0080 } 0081 0082 return std::vector<glaxnimate::model::Composition *>(vals.begin(), vals.end()); 0083 } 0084 0085 static bool recursive_is_ancestor_of( 0086 glaxnimate::model::Composition* ancestor, 0087 glaxnimate::model::Composition* descendant, 0088 std::unordered_map<glaxnimate::model::Composition*, bool>& cache, 0089 const std::unordered_map<glaxnimate::model::Composition*, std::vector<glaxnimate::model::PreCompLayer*>>& layers 0090 ) 0091 { 0092 if ( ancestor == descendant ) 0093 return cache[ancestor] = true; 0094 0095 auto it = cache.find(ancestor); 0096 if ( it != cache.end() ) 0097 return it->second; 0098 0099 int is_ancestor = 0; 0100 0101 for ( auto layer : layers.at(ancestor) ) 0102 { 0103 if ( auto laycomp = layer->composition.get() ) 0104 is_ancestor += recursive_is_ancestor_of(laycomp, descendant, cache, layers); 0105 } 0106 0107 return cache[ancestor] = is_ancestor; 0108 } 0109 0110 std::vector<glaxnimate::model::Composition *> glaxnimate::model::CompGraph::possible_descendants(glaxnimate::model::Composition* ancestor, glaxnimate::model::Document* document) const 0111 { 0112 std::unordered_map<glaxnimate::model::Composition*, bool> cache; 0113 std::vector<glaxnimate::model::Composition*> valid; 0114 0115 for ( const auto& precomp : document->assets()->compositions->values ) 0116 { 0117 if ( !recursive_is_ancestor_of(precomp.get(), ancestor, cache, layers) ) 0118 valid.push_back(precomp.get()); 0119 } 0120 0121 return valid; 0122 } 0123 0124 void glaxnimate::model::CompGraph::add_connection(glaxnimate::model::Composition* comp, glaxnimate::model::PreCompLayer* layer) 0125 { 0126 auto it = layers.find(comp); 0127 if ( it != layers.end() ) 0128 it->second.push_back(layer); 0129 } 0130 0131 void glaxnimate::model::CompGraph::remove_connection(glaxnimate::model::Composition* comp, glaxnimate::model::PreCompLayer* layer) 0132 { 0133 auto it_map = layers.find(comp); 0134 if ( it_map != layers.end() ) 0135 { 0136 auto it_v = std::find(it_map->second.begin(), it_map->second.end(), layer); 0137 if ( it_v != it_map->second.end() ) 0138 { 0139 if ( it_v != it_map->second.end() - 1 ) 0140 std::swap(*it_v, it_map->second.back()); 0141 it_map->second.pop_back(); 0142 } 0143 } 0144 } 0145