Depsgraph: Comb code to a better state all over
[blender.git] / source / blender / depsgraph / intern / node / deg_node_component.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/node/deg_node_component.cc
28  *  \ingroup depsgraph
29  */
30
31 #include "intern/node/deg_node_component.h"
32
33 #include <stdio.h>
34 #include <cstring>  /* required for STREQ later on. */
35
36 #include "BLI_utildefines.h"
37 #include "BLI_ghash.h"
38
39 extern "C" {
40 #include "DNA_object_types.h"
41
42 #include "BKE_action.h"
43 } /* extern "C" */
44
45 #include "intern/node/deg_node_id.h"
46 #include "intern/node/deg_node_factory.h"
47 #include "intern/node/deg_node_operation.h"
48
49 namespace DEG {
50
51 /* *********** */
52 /* Outer Nodes */
53
54 /* Standard Component Methods ============================= */
55
56 ComponentNode::OperationIDKey::OperationIDKey()
57         : opcode(OperationCode::OPERATION),
58           name(""),
59           name_tag(-1)
60 {
61 }
62
63 ComponentNode::OperationIDKey::OperationIDKey(OperationCode opcode)
64         : opcode(opcode),
65           name(""),
66           name_tag(-1)
67 {
68 }
69
70 ComponentNode::OperationIDKey::OperationIDKey(OperationCode opcode,
71                                                  const char *name,
72                                                  int name_tag)
73         : opcode(opcode),
74           name(name),
75           name_tag(name_tag)
76 {
77 }
78
79 string ComponentNode::OperationIDKey::identifier() const
80 {
81         const string codebuf = to_string(static_cast<int>(opcode));
82         return "OperationIDKey(" + codebuf + ", " + name + ")";
83 }
84
85 bool ComponentNode::OperationIDKey::operator==(
86         const OperationIDKey &other) const
87 {
88         return (opcode == other.opcode) &&
89                (STREQ(name, other.name)) &&
90                (name_tag == other.name_tag);
91 }
92
93 static unsigned int comp_node_hash_key(const void *key_v)
94 {
95         const ComponentNode::OperationIDKey *key =
96                 reinterpret_cast<const ComponentNode::OperationIDKey *>(key_v);
97         int opcode_as_int = static_cast<int>(key->opcode);
98         return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(opcode_as_int),
99                                           BLI_ghashutil_strhash_p(key->name));
100 }
101
102 static bool comp_node_hash_key_cmp(const void *a, const void *b)
103 {
104         const ComponentNode::OperationIDKey *key_a =
105                 reinterpret_cast<const ComponentNode::OperationIDKey *>(a);
106         const ComponentNode::OperationIDKey *key_b =
107                 reinterpret_cast<const ComponentNode::OperationIDKey *>(b);
108         return !(*key_a == *key_b);
109 }
110
111 static void comp_node_hash_key_free(void *key_v)
112 {
113         typedef ComponentNode::OperationIDKey OperationIDKey;
114         OperationIDKey *key = reinterpret_cast<OperationIDKey *>(key_v);
115         OBJECT_GUARDED_DELETE(key, OperationIDKey);
116 }
117
118 static void comp_node_hash_value_free(void *value_v)
119 {
120         OperationNode *op_node = reinterpret_cast<OperationNode *>(value_v);
121         OBJECT_GUARDED_DELETE(op_node, OperationNode);
122 }
123
124 ComponentNode::ComponentNode() :
125     entry_operation(NULL),
126     exit_operation(NULL),
127     affects_directly_visible(false)
128 {
129         operations_map = BLI_ghash_new(comp_node_hash_key,
130                                        comp_node_hash_key_cmp,
131                                        "Depsgraph id hash");
132 }
133
134 /* Initialize 'component' node - from pointer data given */
135 void ComponentNode::init(const ID * /*id*/,
136                              const char * /*subdata*/)
137 {
138         /* hook up eval context? */
139         // XXX: maybe this needs a special API?
140 }
141
142 /* Free 'component' node */
143 ComponentNode::~ComponentNode()
144 {
145         clear_operations();
146         if (operations_map != NULL) {
147                 BLI_ghash_free(operations_map,
148                                comp_node_hash_key_free,
149                                comp_node_hash_value_free);
150         }
151 }
152
153 string ComponentNode::identifier() const
154 {
155         const string idname = this->owner->name;
156         const string typebuf = "" + to_string(static_cast<int>(type)) + ")";
157         return typebuf + name + " : " + idname +
158                "( affects_directly_visible: " +
159                        (affects_directly_visible ? "true"
160                                                  : "false") + ")";
161 ;
162 }
163
164 OperationNode *ComponentNode::find_operation(OperationIDKey key) const
165 {
166         OperationNode *node = NULL;
167         if (operations_map != NULL) {
168                 node = (OperationNode *)BLI_ghash_lookup(operations_map, &key);
169         }
170         else {
171                 for (OperationNode *op_node : operations) {
172                         if (op_node->opcode == key.opcode &&
173                             op_node->name_tag == key.name_tag &&
174                             STREQ(op_node->name, key.name))
175                         {
176                                 node = op_node;
177                                 break;
178                         }
179                 }
180         }
181         return node;
182 }
183
184 OperationNode *ComponentNode::find_operation(OperationCode opcode,
185                                                     const char *name,
186                                                     int name_tag) const
187 {
188         OperationIDKey key(opcode, name, name_tag);
189         return find_operation(key);
190 }
191
192 OperationNode *ComponentNode::get_operation(OperationIDKey key) const
193 {
194         OperationNode *node = find_operation(key);
195         if (node == NULL) {
196                 fprintf(stderr, "%s: find_operation(%s) failed\n",
197                         this->identifier().c_str(), key.identifier().c_str());
198                 BLI_assert(!"Request for non-existing operation, should not happen");
199                 return NULL;
200         }
201         return node;
202 }
203
204 OperationNode *ComponentNode::get_operation(OperationCode opcode,
205                                                     const char *name,
206                                                     int name_tag) const
207 {
208         OperationIDKey key(opcode, name, name_tag);
209         return get_operation(key);
210 }
211
212 bool ComponentNode::has_operation(OperationIDKey key) const
213 {
214         return find_operation(key) != NULL;
215 }
216
217 bool ComponentNode::has_operation(OperationCode opcode,
218                                       const char *name,
219                                       int name_tag) const
220 {
221         OperationIDKey key(opcode, name, name_tag);
222         return has_operation(key);
223 }
224
225 OperationNode *ComponentNode::add_operation(const DepsEvalOperationCb& op,
226                                                     OperationCode opcode,
227                                                     const char *name,
228                                                     int name_tag)
229 {
230         OperationNode *op_node = find_operation(opcode, name, name_tag);
231         if (!op_node) {
232                 DepsNodeFactory *factory = type_get_factory(NodeType::OPERATION);
233                 op_node = (OperationNode *)factory->create_node(this->owner->id_orig, "", name);
234
235                 /* register opnode in this component's operation set */
236                 OperationIDKey *key = OBJECT_GUARDED_NEW(OperationIDKey, opcode, name, name_tag);
237                 BLI_ghash_insert(operations_map, key, op_node);
238
239                 /* set backlink */
240                 op_node->owner = this;
241         }
242         else {
243                 fprintf(stderr, "add_operation: Operation already exists - %s has %s at %p\n",
244                         this->identifier().c_str(), op_node->identifier().c_str(), op_node);
245                 BLI_assert(!"Should not happen!");
246         }
247
248         /* attach extra data */
249         op_node->evaluate = op;
250         op_node->opcode = opcode;
251         op_node->name = name;
252         op_node->name_tag = name_tag;
253
254         return op_node;
255 }
256
257 void ComponentNode::set_entry_operation(OperationNode *op_node)
258 {
259         BLI_assert(entry_operation == NULL);
260         entry_operation = op_node;
261 }
262
263 void ComponentNode::set_exit_operation(OperationNode *op_node)
264 {
265         BLI_assert(exit_operation == NULL);
266         exit_operation = op_node;
267 }
268
269 void ComponentNode::clear_operations()
270 {
271         if (operations_map != NULL) {
272                 BLI_ghash_clear(operations_map,
273                                 comp_node_hash_key_free,
274                                 comp_node_hash_value_free);
275         }
276         for (OperationNode *op_node : operations) {
277                 OBJECT_GUARDED_DELETE(op_node, OperationNode);
278         }
279         operations.clear();
280 }
281
282 void ComponentNode::tag_update(Depsgraph *graph, eUpdateSource source)
283 {
284         OperationNode *entry_op = get_entry_operation();
285         if (entry_op != NULL && entry_op->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
286                 return;
287         }
288         for (OperationNode *op_node : operations) {
289                 op_node->tag_update(graph, source);
290         }
291         // It is possible that tag happens before finalization.
292         if (operations_map != NULL) {
293                 GHASH_FOREACH_BEGIN(OperationNode *, op_node, operations_map)
294                 {
295                         op_node->tag_update(graph, source);
296                 }
297                 GHASH_FOREACH_END();
298         }
299 }
300
301 OperationNode *ComponentNode::get_entry_operation()
302 {
303         if (entry_operation) {
304                 return entry_operation;
305         }
306         else if (operations_map != NULL && BLI_ghash_len(operations_map) == 1) {
307                 OperationNode *op_node = NULL;
308                 /* TODO(sergey): This is somewhat slow. */
309                 GHASH_FOREACH_BEGIN(OperationNode *, tmp, operations_map)
310                 {
311                         op_node = tmp;
312                 }
313                 GHASH_FOREACH_END();
314                 /* Cache for the subsequent usage. */
315                 entry_operation = op_node;
316                 return op_node;
317         }
318         else if (operations.size() == 1) {
319                 return operations[0];
320         }
321         return NULL;
322 }
323
324 OperationNode *ComponentNode::get_exit_operation()
325 {
326         if (exit_operation) {
327                 return exit_operation;
328         }
329         else if (operations_map != NULL && BLI_ghash_len(operations_map) == 1) {
330                 OperationNode *op_node = NULL;
331                 /* TODO(sergey): This is somewhat slow. */
332                 GHASH_FOREACH_BEGIN(OperationNode *, tmp, operations_map)
333                 {
334                         op_node = tmp;
335                 }
336                 GHASH_FOREACH_END();
337                 /* Cache for the subsequent usage. */
338                 exit_operation = op_node;
339                 return op_node;
340         }
341         else if (operations.size() == 1) {
342                 return operations[0];
343         }
344         return NULL;
345 }
346
347 void ComponentNode::finalize_build(Depsgraph * /*graph*/)
348 {
349         operations.reserve(BLI_ghash_len(operations_map));
350         GHASH_FOREACH_BEGIN(OperationNode *, op_node, operations_map)
351         {
352                 operations.push_back(op_node);
353         }
354         GHASH_FOREACH_END();
355         BLI_ghash_free(operations_map,
356                        comp_node_hash_key_free,
357                        NULL);
358         operations_map = NULL;
359 }
360
361 /* Bone Component ========================================= */
362
363 /* Initialize 'bone component' node - from pointer data given */
364 void BoneComponentNode::init(const ID *id, const char *subdata)
365 {
366         /* generic component-node... */
367         ComponentNode::init(id, subdata);
368
369         /* name of component comes is bone name */
370         /* TODO(sergey): This sets name to an empty string because subdata is
371          * empty. Is it a bug? */
372         //this->name = subdata;
373
374         /* bone-specific node data */
375         Object *object = (Object *)id;
376         this->pchan = BKE_pose_channel_find_name(object->pose, subdata);
377 }
378
379 /* Register all components. =============================== */
380
381 DEG_COMPONENT_NODE_DEFINE(Animation,         ANIMATION,          ID_RECALC_ANIMATION);
382 /* TODO(sergey): Is this a correct tag? */
383 DEG_COMPONENT_NODE_DEFINE(BatchCache,        BATCH_CACHE,        ID_RECALC_SHADING);
384 DEG_COMPONENT_NODE_DEFINE(Bone,              BONE,               ID_RECALC_GEOMETRY);
385 DEG_COMPONENT_NODE_DEFINE(Cache,             CACHE,              0);
386 DEG_COMPONENT_NODE_DEFINE(CopyOnWrite,       COPY_ON_WRITE,      ID_RECALC_COPY_ON_WRITE);
387 DEG_COMPONENT_NODE_DEFINE(Geometry,          GEOMETRY,           ID_RECALC_GEOMETRY);
388 DEG_COMPONENT_NODE_DEFINE(LayerCollections,  LAYER_COLLECTIONS,  0);
389 DEG_COMPONENT_NODE_DEFINE(Parameters,        PARAMETERS,         0);
390 DEG_COMPONENT_NODE_DEFINE(Particles,         PARTICLE_SYSTEM,    ID_RECALC_GEOMETRY);
391 DEG_COMPONENT_NODE_DEFINE(ParticleSettings,  PARTICLE_SETTINGS,  0);
392 DEG_COMPONENT_NODE_DEFINE(PointCache,        POINT_CACHE,        0);
393 DEG_COMPONENT_NODE_DEFINE(Pose,              EVAL_POSE,          ID_RECALC_GEOMETRY);
394 DEG_COMPONENT_NODE_DEFINE(Proxy,             PROXY,              ID_RECALC_GEOMETRY);
395 DEG_COMPONENT_NODE_DEFINE(Sequencer,         SEQUENCER,          0);
396 DEG_COMPONENT_NODE_DEFINE(Shading,           SHADING,            ID_RECALC_SHADING);
397 DEG_COMPONENT_NODE_DEFINE(ShadingParameters, SHADING_PARAMETERS, ID_RECALC_SHADING);
398 DEG_COMPONENT_NODE_DEFINE(Transform,         TRANSFORM,          ID_RECALC_TRANSFORM);
399 DEG_COMPONENT_NODE_DEFINE(ObjectFromLayer,   OBJECT_FROM_LAYER,  0);
400 DEG_COMPONENT_NODE_DEFINE(Dupli,             DUPLI,              0);
401 DEG_COMPONENT_NODE_DEFINE(Synchronize,       SYNCHRONIZE,        0);
402 DEG_COMPONENT_NODE_DEFINE(GenericDatablock,  GENERIC_DATABLOCK,  0);
403
404 /* Node Types Register =================================== */
405
406 void deg_register_component_depsnodes()
407 {
408         register_node_typeinfo(&DNTI_ANIMATION);
409         register_node_typeinfo(&DNTI_BONE);
410         register_node_typeinfo(&DNTI_CACHE);
411         register_node_typeinfo(&DNTI_BATCH_CACHE);
412         register_node_typeinfo(&DNTI_COPY_ON_WRITE);
413         register_node_typeinfo(&DNTI_GEOMETRY);
414         register_node_typeinfo(&DNTI_LAYER_COLLECTIONS);
415         register_node_typeinfo(&DNTI_PARAMETERS);
416         register_node_typeinfo(&DNTI_PARTICLE_SYSTEM);
417         register_node_typeinfo(&DNTI_PARTICLE_SETTINGS);
418         register_node_typeinfo(&DNTI_POINT_CACHE);
419         register_node_typeinfo(&DNTI_PROXY);
420         register_node_typeinfo(&DNTI_EVAL_POSE);
421         register_node_typeinfo(&DNTI_SEQUENCER);
422         register_node_typeinfo(&DNTI_SHADING);
423         register_node_typeinfo(&DNTI_SHADING_PARAMETERS);
424         register_node_typeinfo(&DNTI_TRANSFORM);
425         register_node_typeinfo(&DNTI_OBJECT_FROM_LAYER);
426         register_node_typeinfo(&DNTI_DUPLI);
427         register_node_typeinfo(&DNTI_SYNCHRONIZE);
428         register_node_typeinfo(&DNTI_GENERIC_DATABLOCK);
429 }
430
431 }  // namespace DEG