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