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