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