Depsgraph: Cleanup, make naming more understandable
[blender.git] / source / blender / depsgraph / intern / nodes / 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/nodes/deg_node_component.cc
28  *  \ingroup depsgraph
29  */
30
31 #include "intern/nodes/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/nodes/deg_node_operation.h"
46 #include "intern/depsgraph_intern.h"
47 #include "util/deg_util_foreach.h"
48
49 namespace DEG {
50
51 /* *********** */
52 /* Outer Nodes */
53
54 /* Standard Component Methods ============================= */
55
56 ComponentDepsNode::OperationIDKey::OperationIDKey()
57         : opcode(DEG_OPCODE_OPERATION),
58           name(""),
59           name_tag(-1)
60 {
61 }
62
63 ComponentDepsNode::OperationIDKey::OperationIDKey(eDepsOperation_Code opcode)
64         : opcode(opcode),
65           name(""),
66           name_tag(-1)
67 {
68 }
69
70 ComponentDepsNode::OperationIDKey::OperationIDKey(eDepsOperation_Code 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 ComponentDepsNode::OperationIDKey::identifier() const
80 {
81         char codebuf[5];
82         BLI_snprintf(codebuf, sizeof(codebuf), "%d", opcode);
83         return string("OperationIDKey(") + codebuf + ", " + name + ")";
84 }
85
86 bool ComponentDepsNode::OperationIDKey::operator==(
87         const OperationIDKey &other) const
88 {
89         return (opcode == other.opcode) &&
90                (STREQ(name, other.name)) &&
91                (name_tag == other.name_tag);
92 }
93
94 static unsigned int comp_node_hash_key(const void *key_v)
95 {
96         const ComponentDepsNode::OperationIDKey *key =
97                 reinterpret_cast<const ComponentDepsNode::OperationIDKey *>(key_v);
98         return BLI_ghashutil_combine_hash(BLI_ghashutil_uinthash(key->opcode),
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 ComponentDepsNode::OperationIDKey *key_a =
105                 reinterpret_cast<const ComponentDepsNode::OperationIDKey *>(a);
106         const ComponentDepsNode::OperationIDKey *key_b =
107                 reinterpret_cast<const ComponentDepsNode::OperationIDKey *>(b);
108         return !(*key_a == *key_b);
109 }
110
111 static void comp_node_hash_key_free(void *key_v)
112 {
113         typedef ComponentDepsNode::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         OperationDepsNode *op_node = reinterpret_cast<OperationDepsNode *>(value_v);
121         OBJECT_GUARDED_DELETE(op_node, OperationDepsNode);
122 }
123
124 ComponentDepsNode::ComponentDepsNode() :
125     entry_operation(NULL),
126     exit_operation(NULL),
127     layers(0)
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 ComponentDepsNode::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 ComponentDepsNode::~ComponentDepsNode()
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 ComponentDepsNode::identifier() const
154 {
155         string idname = this->owner->name;
156
157         char typebuf[16];
158         sprintf(typebuf, "(%d)", type);
159
160         char layers[16];
161         sprintf(layers, "%u", this->layers);
162
163         return string(typebuf) + name + " : " + idname + " (Layers: " + layers + ")";
164 }
165
166 OperationDepsNode *ComponentDepsNode::find_operation(OperationIDKey key) const
167 {
168         OperationDepsNode *node;
169         if (operations_map != NULL) {
170                 node = (OperationDepsNode *)BLI_ghash_lookup(operations_map, &key);
171         }
172         else {
173                 BLI_assert(key.name_tag == -1);
174                 foreach (OperationDepsNode *op_node, operations) {
175                         if (op_node->opcode == key.opcode &&
176                             STREQ(op_node->name, key.name))
177                         {
178                                 node = op_node;
179                                 break;
180                         }
181                 }
182         }
183         return node;
184 }
185
186 OperationDepsNode *ComponentDepsNode::find_operation(eDepsOperation_Code opcode,
187                                                     const char *name,
188                                                     int name_tag) const
189 {
190         OperationIDKey key(opcode, name, name_tag);
191         return find_operation(key);
192 }
193
194 OperationDepsNode *ComponentDepsNode::get_operation(OperationIDKey key) const
195 {
196         OperationDepsNode *node = find_operation(key);
197         if (node == NULL) {
198                 fprintf(stderr, "%s: find_operation(%s) failed\n",
199                         this->identifier().c_str(), key.identifier().c_str());
200                 BLI_assert(!"Request for non-existing operation, should not happen");
201                 return NULL;
202         }
203         return node;
204 }
205
206 OperationDepsNode *ComponentDepsNode::get_operation(eDepsOperation_Code opcode,
207                                                     const char *name,
208                                                     int name_tag) const
209 {
210         OperationIDKey key(opcode, name, name_tag);
211         return get_operation(key);
212 }
213
214 bool ComponentDepsNode::has_operation(OperationIDKey key) const
215 {
216         return find_operation(key) != NULL;
217 }
218
219 bool ComponentDepsNode::has_operation(eDepsOperation_Code opcode,
220                                       const char *name,
221                                       int name_tag) const
222 {
223         OperationIDKey key(opcode, name, name_tag);
224         return has_operation(key);
225 }
226
227 OperationDepsNode *ComponentDepsNode::add_operation(const DepsEvalOperationCb& op,
228                                                     eDepsOperation_Code opcode,
229                                                     const char *name,
230                                                     int name_tag)
231 {
232         OperationDepsNode *op_node = find_operation(opcode, name, name_tag);
233         if (!op_node) {
234                 DepsNodeFactory *factory = deg_type_get_factory(DEG_NODE_TYPE_OPERATION);
235                 op_node = (OperationDepsNode *)factory->create_node(this->owner->id, "", name);
236
237                 /* register opnode in this component's operation set */
238                 OperationIDKey *key = OBJECT_GUARDED_NEW(OperationIDKey, opcode, name, name_tag);
239                 BLI_ghash_insert(operations_map, key, op_node);
240
241                 /* set backlink */
242                 op_node->owner = this;
243         }
244         else {
245                 fprintf(stderr, "add_operation: Operation already exists - %s has %s at %p\n",
246                         this->identifier().c_str(), op_node->identifier().c_str(), op_node);
247                 BLI_assert(!"Should not happen!");
248         }
249
250         /* attach extra data */
251         op_node->evaluate = op;
252         op_node->opcode = opcode;
253         op_node->name = name;
254
255         return op_node;
256 }
257
258 void ComponentDepsNode::set_entry_operation(OperationDepsNode *op_node)
259 {
260         BLI_assert(entry_operation == NULL);
261         entry_operation = op_node;
262 }
263
264 void ComponentDepsNode::set_exit_operation(OperationDepsNode *op_node)
265 {
266         BLI_assert(exit_operation == NULL);
267         exit_operation = op_node;
268 }
269
270 void ComponentDepsNode::clear_operations()
271 {
272         if (operations_map != NULL) {
273                 BLI_ghash_clear(operations_map,
274                                 comp_node_hash_key_free,
275                                 comp_node_hash_value_free);
276         }
277         foreach (OperationDepsNode *op_node, operations) {
278                 OBJECT_GUARDED_DELETE(op_node, OperationDepsNode);
279         }
280         operations.clear();
281 }
282
283 void ComponentDepsNode::tag_update(Depsgraph *graph)
284 {
285         OperationDepsNode *entry_op = get_entry_operation();
286         if (entry_op != NULL && entry_op->flag & DEPSOP_FLAG_NEEDS_UPDATE) {
287                 return;
288         }
289         foreach (OperationDepsNode *op_node, operations) {
290                 op_node->tag_update(graph);
291         }
292         // It is possible that tag happens before finalization.
293         if (operations_map != NULL) {
294                 GHASH_FOREACH_BEGIN(OperationDepsNode *, op_node, operations_map)
295                 {
296                         op_node->tag_update(graph);
297                 }
298                 GHASH_FOREACH_END();
299         }
300 }
301
302 OperationDepsNode *ComponentDepsNode::get_entry_operation()
303 {
304         if (entry_operation) {
305                 return entry_operation;
306         }
307         else if (operations_map != NULL && BLI_ghash_size(operations_map) == 1) {
308                 OperationDepsNode *op_node = NULL;
309                 /* TODO(sergey): This is somewhat slow. */
310                 GHASH_FOREACH_BEGIN(OperationDepsNode *, tmp, operations_map)
311                 {
312                         op_node = tmp;
313                 }
314                 GHASH_FOREACH_END();
315                 /* Cache for the subsequent usage. */
316                 entry_operation = op_node;
317                 return op_node;
318         }
319         else if (operations.size() == 1) {
320                 return operations[0];
321         }
322         return NULL;
323 }
324
325 OperationDepsNode *ComponentDepsNode::get_exit_operation()
326 {
327         if (exit_operation) {
328                 return exit_operation;
329         }
330         else if (operations_map != NULL && BLI_ghash_size(operations_map) == 1) {
331                 OperationDepsNode *op_node = NULL;
332                 /* TODO(sergey): This is somewhat slow. */
333                 GHASH_FOREACH_BEGIN(OperationDepsNode *, tmp, operations_map)
334                 {
335                         op_node = tmp;
336                 }
337                 GHASH_FOREACH_END();
338                 /* Cache for the subsequent usage. */
339                 exit_operation = op_node;
340                 return op_node;
341         }
342         else if (operations.size() == 1) {
343                 return operations[0];
344         }
345         return NULL;
346 }
347
348 void ComponentDepsNode::finalize_build()
349 {
350         operations.reserve(BLI_ghash_size(operations_map));
351         GHASH_FOREACH_BEGIN(OperationDepsNode *, op_node, operations_map)
352         {
353                 operations.push_back(op_node);
354         }
355         GHASH_FOREACH_END();
356         BLI_ghash_free(operations_map,
357                        comp_node_hash_key_free,
358                        NULL);
359         operations_map = NULL;
360 }
361
362 /* Register all components. =============================== */
363
364 #define DEG_COMPONENT_DEFINE(name, NAME)                             \
365   DEG_DEPSNODE_DEFINE(name ## ComponentDepsNode,                     \
366                       DEG_NODE_TYPE_ ## NAME,                        \
367                       #name  " Component");                          \
368 static DepsNodeFactoryImpl<name ## ComponentDepsNode> DNTI_ ## NAME
369
370
371 DEG_COMPONENT_DEFINE(Animation, ANIMATION);
372 DEG_COMPONENT_DEFINE(Cache, CACHE);
373 DEG_COMPONENT_DEFINE(Geometry, GEOMETRY);
374 DEG_COMPONENT_DEFINE(Parameters, PARAMETERS);
375 DEG_COMPONENT_DEFINE(Particles, EVAL_PARTICLES);
376 DEG_COMPONENT_DEFINE(Proxy, PROXY);
377 DEG_COMPONENT_DEFINE(Pose, EVAL_POSE);
378 DEG_COMPONENT_DEFINE(Sequencer, SEQUENCER);
379 DEG_COMPONENT_DEFINE(Shading, SHADING);
380 DEG_COMPONENT_DEFINE(Transform, TRANSFORM);
381
382 /* Bone Component ========================================= */
383
384 /* Initialize 'bone component' node - from pointer data given */
385 void BoneComponentDepsNode::init(const ID *id, const char *subdata)
386 {
387         /* generic component-node... */
388         ComponentDepsNode::init(id, subdata);
389
390         /* name of component comes is bone name */
391         /* TODO(sergey): This sets name to an empty string because subdata is
392          * empty. Is it a bug?
393          */
394         //this->name = subdata;
395
396         /* bone-specific node data */
397         Object *object = (Object *)id;
398         this->pchan = BKE_pose_channel_find_name(object->pose, subdata);
399 }
400
401 DEG_COMPONENT_DEFINE(Bone, BONE);
402
403 /* Node Types Register =================================== */
404
405 void deg_register_component_depsnodes()
406 {
407         deg_register_node_typeinfo(&DNTI_PARAMETERS);
408         deg_register_node_typeinfo(&DNTI_PROXY);
409         deg_register_node_typeinfo(&DNTI_ANIMATION);
410         deg_register_node_typeinfo(&DNTI_TRANSFORM);
411         deg_register_node_typeinfo(&DNTI_GEOMETRY);
412         deg_register_node_typeinfo(&DNTI_SEQUENCER);
413
414         deg_register_node_typeinfo(&DNTI_EVAL_POSE);
415         deg_register_node_typeinfo(&DNTI_BONE);
416
417         deg_register_node_typeinfo(&DNTI_EVAL_PARTICLES);
418         deg_register_node_typeinfo(&DNTI_SHADING);
419
420         deg_register_node_typeinfo(&DNTI_CACHE);
421 }
422
423 }  // namespace DEG