Blender  V2.93
blender_id_map.h
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef __BLENDER_ID_MAP_H__
18 #define __BLENDER_ID_MAP_H__
19 
20 #include <string.h>
21 
22 #include "render/geometry.h"
23 #include "render/scene.h"
24 
25 #include "util/util_map.h"
26 #include "util/util_set.h"
27 #include "util/util_vector.h"
28 
30 
31 /* ID Map
32  *
33  * Utility class to map between Blender datablocks and Cycles data structures,
34  * and keep track of recalc tags from the dependency graph. */
35 
36 template<typename K, typename T> class id_map {
37  public:
38  id_map(Scene *scene_) : scene(scene_)
39  {
40  }
41 
43  {
44  set<T *> nodes;
45 
46  typename map<K, T *>::iterator jt;
47  for (jt = b_map.begin(); jt != b_map.end(); jt++) {
48  nodes.insert(jt->second);
49  }
50 
51  scene->delete_nodes(nodes);
52  }
53 
54  T *find(const BL::ID &id)
55  {
56  return find(id.ptr.owner_id);
57  }
58 
59  T *find(const K &key)
60  {
61  if (b_map.find(key) != b_map.end()) {
62  T *data = b_map[key];
63  return data;
64  }
65 
66  return NULL;
67  }
68 
69  void set_recalc(const BL::ID &id)
70  {
71  b_recalc.insert(id.ptr.data);
72  }
73 
74  void set_recalc(void *id_ptr)
75  {
76  b_recalc.insert(id_ptr);
77  }
78 
79  bool has_recalc()
80  {
81  return !(b_recalc.empty());
82  }
83 
84  void pre_sync()
85  {
86  used_set.clear();
87  }
88 
89  /* Add new data. */
90  void add(const K &key, T *data)
91  {
92  assert(find(key) == NULL);
93  b_map[key] = data;
94  used(data);
95  }
96 
97  /* Update existing data. */
98  bool update(T *data, const BL::ID &id)
99  {
100  return update(data, id, id);
101  }
102  bool update(T *data, const BL::ID &id, const BL::ID &parent)
103  {
104  bool recalc = (b_recalc.find(id.ptr.data) != b_recalc.end());
105  if (parent.ptr.data && parent.ptr.data != id.ptr.data) {
106  recalc = recalc || (b_recalc.find(parent.ptr.data) != b_recalc.end());
107  }
108  used(data);
109  return recalc;
110  }
111 
112  /* Combined add and update as needed. */
113  bool add_or_update(T **r_data, const BL::ID &id)
114  {
115  return add_or_update(r_data, id, id, id.ptr.owner_id);
116  }
117  bool add_or_update(T **r_data, const BL::ID &id, const K &key)
118  {
119  return add_or_update(r_data, id, id, key);
120  }
121  bool add_or_update(T **r_data, const BL::ID &id, const BL::ID &parent, const K &key)
122  {
123  T *data = find(key);
124  bool recalc;
125 
126  if (!data) {
127  /* Add data if it didn't exist yet. */
128  data = scene->create_node<T>();
129  add(key, data);
130  recalc = true;
131  }
132  else {
133  /* check if updated needed. */
134  recalc = update(data, id, parent);
135  }
136 
137  *r_data = data;
138  return recalc;
139  }
140 
141  /* Combined add or update for convenience. */
142 
143  bool is_used(const K &key)
144  {
145  T *data = find(key);
146  return (data) ? used_set.find(data) != used_set.end() : false;
147  }
148 
149  void used(T *data)
150  {
151  /* tag data as still in use */
152  used_set.insert(data);
153  }
154 
156  {
157  b_map[NULL] = data;
158  }
159 
160  void post_sync(bool do_delete = true)
161  {
162  map<K, T *> new_map;
163  typedef pair<const K, T *> TMapPair;
164  typename map<K, T *>::iterator jt;
165 
166  for (jt = b_map.begin(); jt != b_map.end(); jt++) {
167  TMapPair &pair = *jt;
168 
169  if (do_delete && used_set.find(pair.second) == used_set.end()) {
170  scene->delete_node(pair.second);
171  }
172  else {
173  new_map[pair.first] = pair.second;
174  }
175  }
176 
177  used_set.clear();
178  b_recalc.clear();
179  b_map = new_map;
180  }
181 
182  const map<K, T *> &key_to_scene_data()
183  {
184  return b_map;
185  }
186 
187  protected:
188  map<K, T *> b_map;
189  set<T *> used_set;
190  set<void *> b_recalc;
192 };
193 
194 /* Object Key
195  *
196  * To uniquely identify instances, we use the parent, object and persistent instance ID.
197  * We also export separate object for a mesh and its particle hair. */
198 
199 enum { OBJECT_PERSISTENT_ID_SIZE = 8 /* MAX_DUPLI_RECUR in Blender. */ };
200 
201 struct ObjectKey {
202  void *parent;
204  void *ob;
206 
207  ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_, bool use_particle_hair_)
208  : parent(parent_), ob(ob_), use_particle_hair(use_particle_hair_)
209  {
210  if (id_)
211  memcpy(id, id_, sizeof(id));
212  else
213  memset(id, 0, sizeof(id));
214  }
215 
216  bool operator<(const ObjectKey &k) const
217  {
218  if (ob < k.ob) {
219  return true;
220  }
221  else if (ob == k.ob) {
222  if (parent < k.parent) {
223  return true;
224  }
225  else if (parent == k.parent) {
227  return true;
228  }
229  else if (use_particle_hair == k.use_particle_hair) {
230  return memcmp(id, k.id, sizeof(id)) < 0;
231  }
232  }
233  }
234 
235  return false;
236  }
237 };
238 
239 /* Geometry Key
240  *
241  * We export separate geometry for a mesh and its particle hair, so key needs to
242  * distinguish between them. */
243 
244 struct GeometryKey {
245  void *id;
247 
249  {
250  }
251 
252  bool operator<(const GeometryKey &k) const
253  {
254  if (id < k.id) {
255  return true;
256  }
257  else if (id == k.id) {
258  if (geometry_type < k.geometry_type) {
259  return true;
260  }
261  }
262 
263  return false;
264  }
265 };
266 
267 /* Particle System Key */
268 
270  void *ob;
272 
273  ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE]) : ob(ob_)
274  {
275  if (id_)
276  memcpy(id, id_, sizeof(id));
277  else
278  memset(id, 0, sizeof(id));
279  }
280 
281  bool operator<(const ParticleSystemKey &k) const
282  {
283  /* first id is particle index, we don't compare that */
284  if (ob < k.ob)
285  return true;
286  else if (ob == k.ob)
287  return memcmp(id + 1, k.id + 1, sizeof(int) * (OBJECT_PERSISTENT_ID_SIZE - 1)) < 0;
288 
289  return false;
290  }
291 };
292 
294 
295 #endif /* __BLENDER_ID_MAP_H__ */
struct ID ID
#define K(key)
@ OBJECT_PERSISTENT_ID_SIZE
T * find(const K &key)
bool has_recalc()
set< void * > b_recalc
map< K, T * > b_map
set< T * > used_set
void add(const K &key, T *data)
void set_recalc(void *id_ptr)
bool add_or_update(T **r_data, const BL::ID &id)
bool update(T *data, const BL::ID &id, const BL::ID &parent)
const map< K, T * > & key_to_scene_data()
bool add_or_update(T **r_data, const BL::ID &id, const BL::ID &parent, const K &key)
void set_recalc(const BL::ID &id)
Scene * scene
void pre_sync()
bool update(T *data, const BL::ID &id)
id_map(Scene *scene_)
void used(T *data)
T * find(const BL::ID &id)
void set_default(T *data)
bool add_or_update(T **r_data, const BL::ID &id, const K &key)
bool is_used(const K &key)
void post_sync(bool do_delete=true)
#define CCL_NAMESPACE_END
#define T
GeometryKey(void *id, Geometry::Type geometry_type)
Geometry::Type geometry_type
bool operator<(const GeometryKey &k) const
bool use_particle_hair
ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_, bool use_particle_hair_)
void * parent
bool operator<(const ObjectKey &k) const
int id[OBJECT_PERSISTENT_ID_SIZE]
ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE])
int id[OBJECT_PERSISTENT_ID_SIZE]
bool operator<(const ParticleSystemKey &k) const
void * data
Definition: RNA_types.h:52
struct ID * owner_id
Definition: RNA_types.h:50
T * create_node(Args &&... args)
Definition: scene.h:302
void delete_node(T *node)
Definition: scene.h:315
void delete_nodes(const set< T * > &nodes)
Definition: scene.h:333
PointerRNA * ptr
Definition: wm_files.c:3157