doxygen: corrections/updates
[blender.git] / source / blender / depsgraph / intern / depsnode.cc
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2013 Blender Foundation.
19  * All rights reserved.
20  *
21  * Original Author: Joshua Leung
22  * Contributor(s): None Yet
23  *
24  * ***** END GPL LICENSE BLOCK *****
25  */
26
27 /** \file blender/depsgraph/intern/depsnode.cc
28  *  \ingroup depsgraph
29  */
30
31 #include <stdio.h>
32 #include <string.h>
33
34 #include "BLI_utildefines.h"
35
36 extern "C" {
37 #include "DNA_ID.h"
38 #include "DNA_anim_types.h"
39
40 #include "BKE_animsys.h"
41
42 #include "DEG_depsgraph.h"
43 }
44
45 #include "depsnode.h" /* own include */
46 #include "depsnode_component.h"
47 #include "depsnode_operation.h"
48 #include "depsgraph_intern.h"
49
50 /* *************** */
51 /* Node Management */
52
53 /* Add ------------------------------------------------ */
54
55 DepsNode::TypeInfo::TypeInfo(eDepsNode_Type type, const char *tname)
56 {
57         this->type = type;
58         if (type == DEPSNODE_TYPE_OPERATION)
59                 this->tclass = DEPSNODE_CLASS_OPERATION;
60         else if (type < DEPSNODE_TYPE_PARAMETERS)
61                 this->tclass = DEPSNODE_CLASS_GENERIC;
62         else
63                 this->tclass = DEPSNODE_CLASS_COMPONENT;
64         this->tname = tname;
65 }
66
67 DepsNode::DepsNode()
68 {
69         this->name[0] = '\0';
70 }
71
72 DepsNode::~DepsNode()
73 {
74         /* free links
75          * note: deleting relations will remove them from the node relations set,
76          * but only touch the same position as we are using here, which is safe.
77          */
78         DEPSNODE_RELATIONS_ITER_BEGIN(this->inlinks, rel)
79         {
80                 OBJECT_GUARDED_DELETE(rel, DepsRelation);
81         }
82         DEPSNODE_RELATIONS_ITER_END;
83
84         DEPSNODE_RELATIONS_ITER_BEGIN(this->outlinks, rel)
85         {
86                 OBJECT_GUARDED_DELETE(rel, DepsRelation);
87         }
88         DEPSNODE_RELATIONS_ITER_END;
89 }
90
91
92 /* Generic identifier for Depsgraph Nodes. */
93 string DepsNode::identifier() const
94 {
95         char typebuf[7];
96         sprintf(typebuf, "(%d)", type);
97
98         return string(typebuf) + " : " + name;
99 }
100
101 /* ************* */
102 /* Generic Nodes */
103
104 /* Time Source Node ============================================== */
105
106 void TimeSourceDepsNode::tag_update(Depsgraph *graph)
107 {
108         for (DepsNode::Relations::const_iterator it = outlinks.begin();
109              it != outlinks.end();
110              ++it)
111         {
112                 DepsRelation *rel = *it;
113                 DepsNode *node = rel->to;
114                 node->tag_update(graph);
115         }
116 }
117
118
119 /* Root Node ============================================== */
120
121 RootDepsNode::RootDepsNode() : time_source(NULL)
122 {
123 }
124
125 RootDepsNode::~RootDepsNode()
126 {
127         OBJECT_GUARDED_DELETE(time_source, TimeSourceDepsNode);
128 }
129
130 TimeSourceDepsNode *RootDepsNode::add_time_source(const string &name)
131 {
132         if (!time_source) {
133                 DepsNodeFactory *factory = DEG_get_node_factory(DEPSNODE_TYPE_TIMESOURCE);
134                 time_source = (TimeSourceDepsNode *)factory->create_node(NULL, "", name);
135                 /*time_source->owner = this;*/ // XXX
136         }
137         return time_source;
138 }
139
140 DEG_DEPSNODE_DEFINE(RootDepsNode, DEPSNODE_TYPE_ROOT, "Root DepsNode");
141 static DepsNodeFactoryImpl<RootDepsNode> DNTI_ROOT;
142
143 /* Time Source Node ======================================= */
144
145 DEG_DEPSNODE_DEFINE(TimeSourceDepsNode, DEPSNODE_TYPE_TIMESOURCE, "Time Source");
146 static DepsNodeFactoryImpl<TimeSourceDepsNode> DNTI_TIMESOURCE;
147
148 /* ID Node ================================================ */
149
150 /* Initialize 'id' node - from pointer data given. */
151 void IDDepsNode::init(const ID *id, const string &UNUSED(subdata))
152 {
153         /* Store ID-pointer. */
154         BLI_assert(id != NULL);
155         this->id = (ID *)id;
156         this->layers = (1 << 20) - 1;
157         this->eval_flags = 0;
158
159         /* NOTE: components themselves are created if/when needed.
160          * This prevents problems with components getting added
161          * twice if an ID-Ref needs to be created to house it...
162          */
163 }
164
165 /* Free 'id' node. */
166 IDDepsNode::~IDDepsNode()
167 {
168         clear_components();
169 }
170
171 /* Copy 'id' node. */
172 void IDDepsNode::copy(DepsgraphCopyContext *dcc, const IDDepsNode *src)
173 {
174         (void)src;  /* Ignored. */
175         /* Iterate over items in original hash, adding them to new hash. */
176         for (IDDepsNode::ComponentMap::const_iterator it = this->components.begin();
177              it != this->components.end();
178              ++it)
179         {
180                 /* Get current <type : component> mapping. */
181                 ComponentIDKey c_key    = it->first;
182                 DepsNode *old_component = it->second;
183
184                 /* Make a copy of component. */
185                 ComponentDepsNode *component = (ComponentDepsNode *)DEG_copy_node(dcc, old_component);
186
187                 /* Add new node to hash... */
188                 this->components[c_key] = component;
189         }
190
191         // TODO: perform a second loop to fix up links?
192         BLI_assert(!"Not expected to be used");
193 }
194
195 ComponentDepsNode *IDDepsNode::find_component(eDepsNode_Type type,
196                                               const string &name) const
197 {
198         ComponentIDKey key(type, name);
199         ComponentMap::const_iterator it = components.find(key);
200         return it != components.end() ? it->second : NULL;
201 }
202
203 ComponentDepsNode *IDDepsNode::add_component(eDepsNode_Type type,
204                                              const string &name)
205 {
206         ComponentIDKey key(type, name);
207         ComponentDepsNode *comp_node = find_component(type, name);
208         if (!comp_node) {
209                 DepsNodeFactory *factory = DEG_get_node_factory(type);
210                 comp_node = (ComponentDepsNode *)factory->create_node(this->id, "", name);
211
212                 /* Register. */
213                 this->components[key] = comp_node;
214                 comp_node->owner = this;
215         }
216         return comp_node;
217 }
218
219 void IDDepsNode::remove_component(eDepsNode_Type type, const string &name)
220 {
221         ComponentIDKey key(type, name);
222         ComponentDepsNode *comp_node = find_component(type, name);
223         if (comp_node) {
224                 /* Unregister. */
225                 this->components.erase(key);
226                 OBJECT_GUARDED_DELETE(comp_node, ComponentDepsNode);
227         }
228 }
229
230 void IDDepsNode::clear_components()
231 {
232         for (ComponentMap::const_iterator it = components.begin();
233              it != components.end();
234              ++it)
235         {
236                 ComponentDepsNode *comp_node = it->second;
237                 OBJECT_GUARDED_DELETE(comp_node, ComponentDepsNode);
238         }
239         components.clear();
240 }
241
242 void IDDepsNode::tag_update(Depsgraph *graph)
243 {
244         for (ComponentMap::const_iterator it = components.begin();
245              it != components.end();
246              ++it)
247         {
248                 ComponentDepsNode *comp_node = it->second;
249                 /* TODO(sergey): What about drievrs? */
250                 bool do_component_tag = comp_node->type != DEPSNODE_TYPE_ANIMATION;
251                 if (comp_node->type == DEPSNODE_TYPE_ANIMATION) {
252                         AnimData *adt = BKE_animdata_from_id(id);
253                         BLI_assert(adt != NULL);
254                         if (adt->recalc & ADT_RECALC_ANIM) {
255                                 do_component_tag = true;
256                         }
257                 }
258                 if (do_component_tag) {
259                         comp_node->tag_update(graph);
260                 }
261         }
262 }
263
264 DEG_DEPSNODE_DEFINE(IDDepsNode, DEPSNODE_TYPE_ID_REF, "ID Node");
265 static DepsNodeFactoryImpl<IDDepsNode> DNTI_ID_REF;
266
267 /* Subgraph Node ========================================== */
268
269 /* Initialize 'subgraph' node - from pointer data given. */
270 void SubgraphDepsNode::init(const ID *id, const string &UNUSED(subdata))
271 {
272         /* Store ID-ref if provided. */
273         this->root_id = (ID *)id;
274
275         /* NOTE: graph will need to be added manually,
276          * as we don't have any way of passing this down.
277          */
278 }
279
280 /* Free 'subgraph' node */
281 SubgraphDepsNode::~SubgraphDepsNode()
282 {
283         /* Only free if graph not shared, of if this node is the first
284          * reference to it...
285          */
286         // XXX: prune these flags a bit...
287         if ((this->flag & SUBGRAPH_FLAG_FIRSTREF) || !(this->flag & SUBGRAPH_FLAG_SHARED)) {
288                 /* Free the referenced graph. */
289                 DEG_graph_free(this->graph);
290                 this->graph = NULL;
291         }
292 }
293
294 /* Copy 'subgraph' node - Assume that the subgraph doesn't get copied for now... */
295 void SubgraphDepsNode::copy(DepsgraphCopyContext * /*dcc*/,
296                             const SubgraphDepsNode * /*src*/)
297 {
298         //const SubgraphDepsNode *src_node = (const SubgraphDepsNode *)src;
299         //SubgraphDepsNode *dst_node       = (SubgraphDepsNode *)dst;
300
301         /* for now, subgraph itself isn't copied... */
302         BLI_assert(!"Not expected to be used");
303 }
304
305 DEG_DEPSNODE_DEFINE(SubgraphDepsNode, DEPSNODE_TYPE_SUBGRAPH, "Subgraph Node");
306 static DepsNodeFactoryImpl<SubgraphDepsNode> DNTI_SUBGRAPH;
307
308
309 void DEG_register_base_depsnodes()
310 {
311         DEG_register_node_typeinfo(&DNTI_ROOT);
312         DEG_register_node_typeinfo(&DNTI_TIMESOURCE);
313
314         DEG_register_node_typeinfo(&DNTI_ID_REF);
315         DEG_register_node_typeinfo(&DNTI_SUBGRAPH);
316 }