Merging r46111 through r46136 from trunk into soc-2011-tomato
[blender-staging.git] / intern / cycles / blender / blender_util.h
1 /*
2  * Copyright 2011, Blender Foundation.
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
19 #ifndef __BLENDER_UTIL_H__
20 #define __BLENDER_UTIL_H__
21
22 #include "util_map.h"
23 #include "util_path.h"
24 #include "util_set.h"
25 #include "util_transform.h"
26 #include "util_types.h"
27 #include "util_vector.h"
28
29 /* Hacks to hook into Blender API
30    todo: clean this up ... */
31
32 extern "C" {
33
34 struct RenderEngine;
35 struct RenderResult;
36
37 ID *rna_Object_to_mesh(void *_self, void *reports, void *scene, int apply_modifiers, int settings);
38 void rna_Main_meshes_remove(void *bmain, void *reports, void *mesh);
39 void rna_Object_create_duplilist(void *ob, void *reports, void *sce);
40 void rna_Object_free_duplilist(void *ob, void *reports);
41 void rna_RenderLayer_rect_set(PointerRNA *ptr, const float *values);
42 void rna_RenderPass_rect_set(PointerRNA *ptr, const float *values);
43 struct RenderResult *RE_engine_begin_result(struct RenderEngine *engine, int x, int y, int w, int h);
44 void RE_engine_update_result(struct RenderEngine *engine, struct RenderResult *result);
45 void RE_engine_end_result(struct RenderEngine *engine, struct RenderResult *result);
46 int RE_engine_test_break(struct RenderEngine *engine);
47 void RE_engine_update_stats(struct RenderEngine *engine, const char *stats, const char *info);
48 void RE_engine_update_progress(struct RenderEngine *engine, float progress);
49 void engine_tag_redraw(void *engine);
50 void engine_tag_update(void *engine);
51 int rna_Object_is_modified(void *ob, void *scene, int settings);
52 int rna_Object_is_deform_modified(void *ob, void *scene, int settings);
53 void BLI_timestr(double _time, char *str);
54 void rna_ColorRamp_eval(void *coba, float position, float color[4]);
55 void rna_Scene_frame_set(void *scene, int frame, float subframe);
56
57 }
58
59 CCL_NAMESPACE_BEGIN
60
61 static inline BL::Mesh object_to_mesh(BL::Object self, BL::Scene scene, bool apply_modifiers, bool render)
62 {
63         ID *data = rna_Object_to_mesh(self.ptr.data, NULL, scene.ptr.data, apply_modifiers, (render)? 2: 1);
64         PointerRNA ptr;
65         RNA_id_pointer_create(data, &ptr);
66         return BL::Mesh(ptr);
67 }
68
69 static inline void colorramp_to_array(BL::ColorRamp ramp, float4 *data, int size)
70 {
71         for(int i = 0; i < size; i++) {
72                 float color[4];
73
74                 rna_ColorRamp_eval(ramp.ptr.data, i/(float)(size-1), color);
75                 data[i] = make_float4(color[0], color[1], color[2], color[3]);
76         }
77 }
78
79 static inline void object_remove_mesh(BL::BlendData data, BL::Mesh mesh)
80 {
81         rna_Main_meshes_remove(data.ptr.data, NULL, mesh.ptr.data);
82 }
83
84 static inline void object_create_duplilist(BL::Object self, BL::Scene scene)
85 {
86         rna_Object_create_duplilist(self.ptr.data, NULL, scene.ptr.data);
87 }
88
89 static inline void object_free_duplilist(BL::Object self)
90 {
91         rna_Object_free_duplilist(self.ptr.data, NULL);
92 }
93
94 static inline bool object_is_modified(BL::Object self, BL::Scene scene, bool preview)
95 {
96         return rna_Object_is_modified(self.ptr.data, scene.ptr.data, (preview)? (1<<0): (1<<1))? true: false;
97 }
98
99 static inline bool object_is_deform_modified(BL::Object self, BL::Scene scene, bool preview)
100 {
101         return rna_Object_is_deform_modified(self.ptr.data, scene.ptr.data, (preview)? (1<<0): (1<<1))? true: false;
102 }
103
104 static inline void scene_frame_set(BL::Scene scene, int frame)
105 {
106         rna_Scene_frame_set(scene.ptr.data, frame, 0.0f);
107 }
108
109 /* Utilities */
110
111 static inline Transform get_transform(BL::Array<float, 16> array)
112 {
113         Transform tfm;
114
115         /* we assume both types to be just 16 floats, and transpose because blender
116            use column major matrix order while we use row major */
117         memcpy(&tfm, &array, sizeof(float)*16);
118         tfm = transform_transpose(tfm);
119
120         return tfm;
121 }
122
123 static inline float2 get_float2(BL::Array<float, 2> array)
124 {
125         return make_float2(array[0], array[1]);
126 }
127
128 static inline float3 get_float3(BL::Array<float, 2> array)
129 {
130         return make_float3(array[0], array[1], 0.0f);
131 }
132
133 static inline float3 get_float3(BL::Array<float, 3> array)
134 {
135         return make_float3(array[0], array[1], array[2]);
136 }
137
138 static inline float3 get_float3(BL::Array<float, 4> array)
139 {
140         return make_float3(array[0], array[1], array[2]);
141 }
142
143 static inline int4 get_int4(BL::Array<int, 4> array)
144 {
145         return make_int4(array[0], array[1], array[2], array[3]);
146 }
147
148 static inline uint get_layer(BL::Array<int, 20> array)
149 {
150         uint layer = 0;
151
152         for(uint i = 0; i < 20; i++)
153                 if(array[i])
154                         layer |= (1 << i);
155         
156         return layer;
157 }
158
159 /*static inline float3 get_float3(PointerRNA& ptr, const char *name)
160 {
161         float3 f;
162         RNA_float_get_array(&ptr, name, &f.x);
163         return f;
164 }*/
165
166 static inline bool get_boolean(PointerRNA& ptr, const char *name)
167 {
168         return RNA_boolean_get(&ptr, name)? true: false;
169 }
170
171 static inline float get_float(PointerRNA& ptr, const char *name)
172 {
173         return RNA_float_get(&ptr, name);
174 }
175
176 static inline int get_int(PointerRNA& ptr, const char *name)
177 {
178         return RNA_int_get(&ptr, name);
179 }
180
181 static inline int get_enum(PointerRNA& ptr, const char *name)
182 {
183         return RNA_enum_get(&ptr, name);
184 }
185
186 static inline string get_enum_identifier(PointerRNA& ptr, const char *name)
187 {
188         PropertyRNA *prop = RNA_struct_find_property(&ptr, name);
189         const char *identifier = "";
190         int value = RNA_property_enum_get(&ptr, prop);
191
192         RNA_property_enum_identifier(NULL, &ptr, prop, value, &identifier);
193
194         return string(identifier);
195 }
196
197 /* Relative Paths */
198
199 static inline string blender_absolute_path(BL::BlendData b_data, BL::ID b_id, const string& path)
200 {
201         if(path.size() >= 2 && path[0] == '/' && path[1] == '/') {
202                 string dirname;
203                 
204                 if(b_id.library())
205                         dirname = blender_absolute_path(b_data, b_id.library(), b_id.library().filepath());
206                 else
207                         dirname = b_data.filepath();
208
209                 return path_join(path_dirname(dirname), path.substr(2));
210         }
211
212         return path;
213 }
214
215 /* ID Map
216  *
217  * Utility class to keep in sync with blender data.
218  * Used for objects, meshes, lights and shaders. */
219
220 template<typename K, typename T>
221 class id_map {
222 public:
223         id_map(vector<T*> *scene_data_)
224         {
225                 scene_data = scene_data_;
226         }
227
228         T *find(BL::ID id)
229         {
230                 return find(id.ptr.id.data);
231         }
232
233         T *find(const K& key)
234         {
235                 if(b_map.find(key) != b_map.end()) {
236                         T *data = b_map[key];
237                         return data;
238                 }
239
240                 return NULL;
241         }
242
243         void set_recalc(BL::ID id)
244         {
245                 b_recalc.insert(id.ptr.data);
246         }
247
248         bool has_recalc()
249         {
250                 return !(b_recalc.empty());
251         }
252
253         void pre_sync()
254         {
255                 used_set.clear();
256         }
257
258         bool sync(T **r_data, BL::ID id)
259         {
260                 return sync(r_data, id, id, id.ptr.id.data);
261         }
262
263         bool sync(T **r_data, BL::ID id, BL::ID parent, const K& key)
264         {
265                 T *data = find(key);
266                 bool recalc;
267
268                 if(!data) {
269                         /* add data if it didn't exist yet */
270                         data = new T();
271                         scene_data->push_back(data);
272                         b_map[key] = data;
273                         recalc = true;
274                 }
275                 else {
276                         recalc = (b_recalc.find(id.ptr.data) != b_recalc.end());
277                         if(parent.ptr.data)
278                                 recalc = recalc || (b_recalc.find(parent.ptr.data) != b_recalc.end());
279                 }
280
281                 used(data);
282
283                 *r_data = data;
284                 return recalc;
285         }
286
287         void used(T *data)
288         {
289                 /* tag data as still in use */
290                 used_set.insert(data);
291         }
292
293         void set_default(T *data)
294         {
295                 b_map[NULL] = data;
296         }
297
298         bool post_sync(bool do_delete = true)
299         {
300                 /* remove unused data */
301                 vector<T*> new_scene_data;
302                 typename vector<T*>::iterator it;
303                 bool deleted = false;
304
305                 for(it = scene_data->begin(); it != scene_data->end(); it++) {
306                         T *data = *it;
307
308                         if(do_delete && used_set.find(data) == used_set.end()) {
309                                 delete data;
310                                 deleted = true;
311                         }
312                         else
313                                 new_scene_data.push_back(data);
314                 }
315
316                 *scene_data = new_scene_data;
317
318                 /* update mapping */
319                 map<K, T*> new_map;
320                 typedef pair<const K, T*> TMapPair;
321                 typename map<K, T*>::iterator jt;
322
323                 for(jt = b_map.begin(); jt != b_map.end(); jt++) {
324                         TMapPair& pair = *jt;
325
326                         if(used_set.find(pair.second) != used_set.end())
327                                 new_map[pair.first] = pair.second;
328                 }
329
330                 used_set.clear();
331                 b_recalc.clear();
332                 b_map = new_map;
333
334                 return deleted;
335         }
336
337 protected:
338         vector<T*> *scene_data;
339         map<K, T*> b_map;
340         set<T*> used_set;
341         set<void*> b_recalc;
342 };
343
344 /* Object Key */
345
346 struct ObjectKey {
347         void *parent;
348         int index;
349         void *ob;
350
351         ObjectKey(void *parent_, int index_, void *ob_)
352         : parent(parent_), index(index_), ob(ob_) {}
353
354         bool operator<(const ObjectKey& k) const
355         { return (parent < k.parent || (parent == k.parent && (index < k.index || (index == k.index && ob < k.ob)))); }
356 };
357
358 CCL_NAMESPACE_END
359
360 #endif /* __BLENDER_UTIL_H__ */
361