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