Blender  V3.3
deg_node_component.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2013 Blender Foundation. All rights reserved. */
3 
9 
10 #include <cstdio>
11 #include <cstring> /* required for STREQ later on. */
12 
13 #include "BLI_ghash.h"
14 #include "BLI_hash.hh"
15 #include "BLI_utildefines.h"
16 
17 #include "DNA_object_types.h"
18 
19 #include "BKE_action.h"
20 
24 
25 namespace blender::deg {
26 
27 /* *********** */
28 /* Outer Nodes */
29 
30 /* -------------------------------------------------------------------- */
35  : opcode(OperationCode::OPERATION), name(""), name_tag(-1)
36 {
37 }
38 
40  : opcode(opcode), name(""), name_tag(-1)
41 {
42 }
43 
45  : opcode(opcode), name(name), name_tag(name_tag)
46 {
47 }
48 
50 {
51  const string codebuf = to_string(static_cast<int>(opcode));
52  return "OperationIDKey(" + codebuf + ", " + name + ")";
53 }
54 
56 {
57  return (opcode == other.opcode) && (STREQ(name, other.name)) && (name_tag == other.name_tag);
58 }
59 
61 {
62  const int opcode_as_int = static_cast<int>(opcode);
64  name_tag,
67 }
68 
70  : entry_operation(nullptr),
71  exit_operation(nullptr),
73  affects_visible_id(false)
74 {
76 }
77 
78 void ComponentNode::init(const ID * /*id*/, const char * /*subdata*/)
79 {
80  /* hook up eval context? */
81  /* XXX: maybe this needs a special API? */
82 }
83 
84 /* Free 'component' node */
86 {
88  delete operations_map;
89 }
90 
92 {
93  const string idname = this->owner->name;
94  const string typebuf = "" + to_string(static_cast<int>(type)) + ")";
95  return typebuf + name + " : " + idname +
96  "( affects_visible_id: " + (affects_visible_id ? "true" : "false") + ")";
97 }
98 
100 {
101  OperationNode *node = nullptr;
102  if (operations_map != nullptr) {
103  node = operations_map->lookup_default(key, nullptr);
104  }
105  else {
106  for (OperationNode *op_node : operations) {
107  if (op_node->opcode == key.opcode && op_node->name_tag == key.name_tag &&
108  STREQ(op_node->name.c_str(), key.name)) {
109  node = op_node;
110  break;
111  }
112  }
113  }
114  return node;
115 }
116 
118  const char *name,
119  int name_tag) const
120 {
121  OperationIDKey key(opcode, name, name_tag);
122  return find_operation(key);
123 }
124 
126 {
128  if (node == nullptr) {
129  fprintf(stderr,
130  "%s: find_operation(%s) failed\n",
131  this->identifier().c_str(),
132  key.identifier().c_str());
133  BLI_assert_msg(0, "Request for non-existing operation, should not happen");
134  return nullptr;
135  }
136  return node;
137 }
138 
140  const char *name,
141  int name_tag) const
142 {
143  OperationIDKey key(opcode, name, name_tag);
144  return get_operation(key);
145 }
146 
148 {
149  return find_operation(key) != nullptr;
150 }
151 
152 bool ComponentNode::has_operation(OperationCode opcode, const char *name, int name_tag) const
153 {
154  OperationIDKey key(opcode, name, name_tag);
155  return has_operation(key);
156 }
157 
159  OperationCode opcode,
160  const char *name,
161  int name_tag)
162 {
163  OperationNode *op_node = find_operation(opcode, name, name_tag);
164  if (!op_node) {
166  op_node = (OperationNode *)factory->create_node(this->owner->id_orig, "", name);
167 
168  /* register opnode in this component's operation set */
169  OperationIDKey key(opcode, name, name_tag);
170  operations_map->add(key, op_node);
171 
172  /* Set back-link. */
173  op_node->owner = this;
174  }
175  else {
176  fprintf(stderr,
177  "add_operation: Operation already exists - %s has %s at %p\n",
178  this->identifier().c_str(),
179  op_node->identifier().c_str(),
180  op_node);
181  BLI_assert_msg(0, "Should not happen!");
182  }
183 
184  /* attach extra data */
185  op_node->evaluate = op;
186  op_node->opcode = opcode;
187  op_node->name = name;
188  op_node->name_tag = name_tag;
189 
190  return op_node;
191 }
192 
194 {
195  BLI_assert(entry_operation == nullptr);
196  entry_operation = op_node;
197 }
198 
200 {
201  BLI_assert(exit_operation == nullptr);
202  exit_operation = op_node;
203 }
204 
206 {
207  if (operations_map != nullptr) {
208  for (OperationNode *op_node : operations_map->values()) {
209  delete op_node;
210  }
211  operations_map->clear();
212  }
213  for (OperationNode *op_node : operations) {
214  delete op_node;
215  }
216  operations.clear();
217 }
218 
220 {
221  /* Note that the node might already be tagged for an update due invisible state of the node
222  * during previous dependency evaluation. Here the node gets re-tagged, so we need to give
223  * the evaluated clues that evaluation needs to happen again. */
224  for (OperationNode *op_node : operations) {
225  op_node->tag_update(graph, source);
226  }
227  /* It is possible that tag happens before finalization. */
228  if (operations_map != nullptr) {
229  for (OperationNode *op_node : operations_map->values()) {
230  op_node->tag_update(graph, source);
231  }
232  }
233 }
234 
236 {
237  if (entry_operation) {
238  return entry_operation;
239  }
240  if (operations_map != nullptr && operations_map->size() == 1) {
241  OperationNode *op_node = nullptr;
242  /* TODO(sergey): This is somewhat slow. */
243  for (OperationNode *tmp : operations_map->values()) {
244  op_node = tmp;
245  }
246  /* Cache for the subsequent usage. */
247  entry_operation = op_node;
248  return op_node;
249  }
250  if (operations.size() == 1) {
251  return operations[0];
252  }
253  return nullptr;
254 }
255 
257 {
258  if (exit_operation) {
259  return exit_operation;
260  }
261  if (operations_map != nullptr && operations_map->size() == 1) {
262  OperationNode *op_node = nullptr;
263  /* TODO(sergey): This is somewhat slow. */
264  for (OperationNode *tmp : operations_map->values()) {
265  op_node = tmp;
266  }
267  /* Cache for the subsequent usage. */
268  exit_operation = op_node;
269  return op_node;
270  }
271  if (operations.size() == 1) {
272  return operations[0];
273  }
274  return nullptr;
275 }
276 
278 {
280  for (OperationNode *op_node : operations_map->values()) {
281  operations.append(op_node);
282  }
283  delete operations_map;
284  operations_map = nullptr;
285 }
286 
289 /* -------------------------------------------------------------------- */
293 void BoneComponentNode::init(const ID *id, const char *subdata)
294 {
295  /* generic component-node... */
296  ComponentNode::init(id, subdata);
297 
298  /* name of component comes is bone name */
299  /* TODO(sergey): This sets name to an empty string because subdata is
300  * empty. Is it a bug? */
301  // this->name = subdata;
302 
303  /* bone-specific node data */
304  Object *object = (Object *)id;
305  this->pchan = BKE_pose_channel_find_name(object->pose, subdata);
306 }
307 
310 /* -------------------------------------------------------------------- */
315 /* TODO(sergey): Is this a correct tag? */
318 DEG_COMPONENT_NODE_DEFINE(Cache, CACHE, 0);
320 DEG_COMPONENT_NODE_DEFINE(ImageAnimation, IMAGE_ANIMATION, 0);
322 DEG_COMPONENT_NODE_DEFINE(LayerCollections, LAYER_COLLECTIONS, 0);
323 DEG_COMPONENT_NODE_DEFINE(Parameters, PARAMETERS, 0);
324 DEG_COMPONENT_NODE_DEFINE(Particles, PARTICLE_SYSTEM, ID_RECALC_GEOMETRY);
328 DEG_COMPONENT_NODE_DEFINE(Sequencer, SEQUENCER, 0);
331 DEG_COMPONENT_NODE_DEFINE(ObjectFromLayer, OBJECT_FROM_LAYER, 0);
332 DEG_COMPONENT_NODE_DEFINE(Dupli, DUPLI, 0);
333 DEG_COMPONENT_NODE_DEFINE(Synchronization, SYNCHRONIZATION, 0);
334 DEG_COMPONENT_NODE_DEFINE(Audio, AUDIO, 0);
335 DEG_COMPONENT_NODE_DEFINE(Armature, ARMATURE, 0);
336 DEG_COMPONENT_NODE_DEFINE(GenericDatablock, GENERIC_DATABLOCK, 0);
337 DEG_COMPONENT_NODE_DEFINE(Visibility, VISIBILITY, 0);
340 
343 /* -------------------------------------------------------------------- */
348 {
349  register_node_typeinfo(&DNTI_ANIMATION);
350  register_node_typeinfo(&DNTI_BONE);
351  register_node_typeinfo(&DNTI_CACHE);
352  register_node_typeinfo(&DNTI_BATCH_CACHE);
353  register_node_typeinfo(&DNTI_COPY_ON_WRITE);
354  register_node_typeinfo(&DNTI_GEOMETRY);
355  register_node_typeinfo(&DNTI_LAYER_COLLECTIONS);
356  register_node_typeinfo(&DNTI_PARAMETERS);
357  register_node_typeinfo(&DNTI_PARTICLE_SYSTEM);
358  register_node_typeinfo(&DNTI_PARTICLE_SETTINGS);
359  register_node_typeinfo(&DNTI_POINT_CACHE);
360  register_node_typeinfo(&DNTI_IMAGE_ANIMATION);
361  register_node_typeinfo(&DNTI_EVAL_POSE);
362  register_node_typeinfo(&DNTI_SEQUENCER);
363  register_node_typeinfo(&DNTI_SHADING);
364  register_node_typeinfo(&DNTI_TRANSFORM);
365  register_node_typeinfo(&DNTI_OBJECT_FROM_LAYER);
366  register_node_typeinfo(&DNTI_DUPLI);
367  register_node_typeinfo(&DNTI_SYNCHRONIZATION);
368  register_node_typeinfo(&DNTI_AUDIO);
369  register_node_typeinfo(&DNTI_ARMATURE);
370  register_node_typeinfo(&DNTI_GENERIC_DATABLOCK);
371  register_node_typeinfo(&DNTI_VISIBILITY);
372  register_node_typeinfo(&DNTI_SIMULATION);
373  register_node_typeinfo(&DNTI_NTREE_OUTPUT);
374 }
375 
378 } // namespace blender::deg
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition: BLI_assert.h:53
size_t BLI_ghashutil_combine_hash(size_t hash_a, size_t hash_b)
unsigned int BLI_ghashutil_uinthash(unsigned int key)
unsigned int BLI_ghashutil_strhash_p(const void *ptr)
#define STREQ(a, b)
@ ID_RECALC_TRANSFORM
Definition: DNA_ID.h:771
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:834
@ ID_RECALC_SHADING
Definition: DNA_ID.h:811
@ ID_RECALC_NTREE_OUTPUT
Definition: DNA_ID.h:871
@ ID_RECALC_ANIMATION
Definition: DNA_ID.h:794
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
Object is a sort of wrapper for general info.
int64_t size() const
Definition: BLI_vector.hh:694
void append(const T &value)
Definition: BLI_vector.hh:433
void reserve(const int64_t min_capacity)
Definition: BLI_vector.hh:340
OperationNode * node
Depsgraph * graph
static const char * to_string(const Interpolation &interp)
Definition: gl_shader.cc:63
DEG_COMPONENT_NODE_DEFINE(Animation, ANIMATION, ID_RECALC_ANIMATION)
void register_node_typeinfo(DepsNodeFactory *factory)
void deg_register_component_depsnodes()
DepsNodeFactory * type_get_factory(const NodeType type)
function< void(struct ::Depsgraph *)> DepsEvalOperationCb
unsigned __int64 uint64_t
Definition: stdint.h:90
Definition: DNA_ID.h:368
struct bPose * pose
void init(const ID *id, const char *subdata)
bool operator==(const OperationIDKey &other) const
virtual OperationNode * get_entry_operation() override
OperationNode * get_operation(OperationIDKey key) const
void init(const ID *id, const char *subdata) override
virtual void tag_update(Depsgraph *graph, eUpdateSource source) override
Vector< OperationNode * > operations
OperationNode * find_operation(OperationIDKey key) const
virtual OperationNode * get_exit_operation() override
OperationNode * add_operation(const DepsEvalOperationCb &op, OperationCode opcode, const char *name="", int name_tag=-1)
bool has_operation(OperationIDKey key) const
void set_exit_operation(OperationNode *op_node)
void finalize_build(Depsgraph *graph)
virtual string identifier() const override
Map< ComponentNode::OperationIDKey, OperationNode * > * operations_map
void set_entry_operation(OperationNode *op_node)
virtual Node * create_node(const ID *id, const char *subdata, const char *name) const =0
virtual string identifier() const override