2.5: Error reporting
[blender-staging.git] / source / blender / blenkernel / intern / context.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Blender Foundation (2008).
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include "MEM_guardedalloc.h"
29
30 #include "DNA_listBase.h"
31 #include "DNA_scene_types.h"
32 #include "DNA_screen_types.h"
33 #include "DNA_space_types.h"
34 #include "DNA_windowmanager_types.h"
35
36 #include "RNA_access.h"
37
38 #include "BLI_listbase.h"
39
40 #include "BKE_context.h"
41 #include "BKE_main.h"
42 #include "BKE_report.h"
43 #include "BKE_screen.h"
44
45 #include <string.h>
46
47 /* struct */
48
49 struct bContext {
50         bContextTask task;
51         ReportList *reports;
52         int thread;
53
54         /* windowmanager context */
55         struct {
56                 struct wmWindowManager *manager;
57                 struct wmWindow *window;
58                 struct bScreen *screen;
59                 struct ScrArea *area;
60                 struct ARegion *region;
61                 struct uiBlock *block;
62
63                 bContextDataCallback block_cb;
64         } wm;
65         
66         /* data context */
67         struct {
68                 struct Main *main;
69                 struct Scene *scene;
70
71                 int recursion;
72         } data;
73         
74         /* data evaluation */
75         struct {
76                 int render;
77         } eval;
78 };
79
80 /* context */
81
82 bContext *CTX_create()
83 {
84         bContext *C;
85         
86         C= MEM_callocN(sizeof(bContext), "bContext");
87
88         C->task= CTX_UNDEFINED;
89         C->thread= 0;
90
91         return C;
92 }
93
94 bContext *CTX_copy(const bContext *C, int thread)
95 {
96         bContext *newC;
97
98         if(C->task != CTX_UNDEFINED)
99                 BKE_report(C->reports, RPT_ERROR_INVALID_CONTEXT, "CTX_copy not allowed for this task");
100         
101         newC= MEM_dupallocN((void*)C);
102         newC->thread= thread;
103
104         return newC;
105 }
106
107 int CTX_thread(const bContext *C)
108 {
109         return C->thread;
110 }
111
112 void CTX_free(bContext *C)
113 {
114         MEM_freeN(C);
115 }
116
117 /* context task and reports */
118
119 bContextTask CTX_task(const bContext *C)
120 {
121         return C->task;
122 }
123
124 void CTX_task_set(bContext *C, bContextTask task)
125 {
126         C->task= task;
127 }
128
129 ReportList *CTX_reports(const bContext *C)
130 {
131         return C->reports;
132 }
133
134 void CTX_reports_set(bContext *C, ReportList *reports)
135 {
136         C->reports= reports;
137 }
138
139 /* window manager context */
140
141 wmWindowManager *CTX_wm_manager(const bContext *C)
142 {
143         return C->wm.manager;
144 }
145
146 wmWindow *CTX_wm_window(const bContext *C)
147 {
148         return C->wm.window;
149 }
150
151 bScreen *CTX_wm_screen(const bContext *C)
152 {
153         return C->wm.screen;
154 }
155
156 ScrArea *CTX_wm_area(const bContext *C)
157 {
158         return C->wm.area;
159 }
160
161 SpaceLink *CTX_wm_space_data(const bContext *C)
162 {
163         return (C->wm.area)? C->wm.area->spacedata.first: NULL;
164 }
165
166 ARegion *CTX_wm_region(const bContext *C)
167 {
168         return C->wm.region;
169 }
170
171 void *CTX_wm_region_data(const bContext *C)
172 {
173         return (C->wm.region)? C->wm.region->regiondata: NULL;
174 }
175
176 struct uiBlock *CTX_wm_ui_block(const bContext *C)
177 {
178         return C->wm.block;
179 }
180
181 void CTX_wm_manager_set(bContext *C, wmWindowManager *wm)
182 {
183         C->wm.manager= wm;
184 }
185
186 void CTX_wm_window_set(bContext *C, wmWindow *win)
187 {
188         C->wm.window= win;
189         C->wm.screen= (win)? win->screen: NULL;
190         C->data.scene= (C->wm.screen)? C->wm.screen->scene: NULL;
191 }
192
193 void CTX_wm_screen_set(bContext *C, bScreen *screen)
194 {
195         C->wm.screen= screen;
196         C->data.scene= (C->wm.screen)? C->wm.screen->scene: NULL;
197 }
198
199 void CTX_wm_area_set(bContext *C, ScrArea *area)
200 {
201         C->wm.area= area;
202 }
203
204 void CTX_wm_region_set(bContext *C, ARegion *region)
205 {
206         C->wm.region= region;
207 }
208
209 void CTX_wm_ui_block_set(bContext *C, struct uiBlock *block, bContextDataCallback cb)
210 {
211         C->wm.block= block;
212         C->wm.block_cb= cb;
213 }
214
215 /* data context utility functions */
216
217 struct bContextDataMember {
218         StructRNA *rna;
219         const char *name;
220         int collection;
221 };
222
223 struct bContextDataResult {
224         void *pointer;
225         ListBase list;
226 };
227
228 static int ctx_data_get(bContext *C, const bContextDataMember *member, bContextDataResult *result)
229 {
230         int done= 0, recursion= C->data.recursion;
231
232         memset(result, 0, sizeof(bContextDataResult));
233
234         /* we check recursion to ensure that we do not get infinite
235          * loops requesting data from ourselfs in a context callback */
236         if(!done && recursion < 1 && C->wm.block) {
237                 C->data.recursion= 1;
238                 done= C->wm.block_cb(C, member, result);
239         }
240         if(!done && recursion < 2 && C->wm.region) {
241                 C->data.recursion= 2;
242                 if(C->wm.region->type->context)
243                         done= C->wm.region->type->context(C, member, result);
244         }
245         if(!done && recursion < 3 && C->wm.area) {
246                 C->data.recursion= 3;
247                 if(C->wm.area->type->context)
248                         done= C->wm.area->type->context(C, member, result);
249         }
250         if(!done && recursion < 4 && C->wm.screen) {
251                 bContextDataCallback cb= C->wm.screen->context;
252                 C->data.recursion= 4;
253                 if(cb)
254                         done= cb(C, member, result);
255         }
256
257         C->data.recursion= recursion;
258
259         return done;
260 }
261
262 static void *ctx_data_pointer_get(const bContext *C, const bContextDataMember *member)
263 {
264         bContextDataResult result;
265
266         if(ctx_data_get((bContext*)C, member, &result))
267                 return result.pointer;
268
269         return NULL;
270 }
271
272 static int ctx_data_pointer_verify(const bContext *C, const bContextDataMember *member, void **pointer)
273 {
274         bContextDataResult result;
275
276         if(ctx_data_get((bContext*)C, member, &result)) {
277                 *pointer= result.pointer;
278                 return 1;
279         }
280         else {
281                 *pointer= NULL;
282                 return 0;
283         }
284 }
285
286 static int ctx_data_collection_get(const bContext *C, const bContextDataMember *member, ListBase *list)
287 {
288         bContextDataResult result;
289
290         if(ctx_data_get((bContext*)C, member, &result)) {
291                 *list= result.list;
292                 return 1;
293         }
294
295         return 0;
296 }
297
298 void CTX_data_pointer_set(bContextDataResult *result, void *data)
299 {
300         result->pointer= data;
301 }
302
303 void CTX_data_list_add(bContextDataResult *result, void *data)
304 {
305         LinkData *link;
306         
307         link= MEM_callocN(sizeof(LinkData), "LinkData");
308         link->data= data;
309
310         BLI_addtail(&result->list, link);
311 }
312
313 /* data context */
314
315 Main *CTX_data_main(const bContext *C)
316 {
317         Main *bmain;
318
319         if(ctx_data_pointer_verify(C, CTX_data_main, (void*)&bmain))
320                 return bmain;
321         else
322                 return C->data.main;
323 }
324
325 void CTX_data_main_set(bContext *C, Main *bmain)
326 {
327         C->data.main= bmain;
328 }
329
330 Scene *CTX_data_scene(const bContext *C)
331 {
332         Scene *scene;
333
334         if(ctx_data_pointer_verify(C, CTX_data_scene, (void*)&scene))
335                 return scene;
336         else
337                 return C->data.scene;
338 }
339
340 void CTX_data_scene_set(bContext *C, Scene *scene)
341 {
342         C->data.scene= scene;
343 }
344
345 ToolSettings *CTX_data_tool_settings(const bContext *C)
346 {
347         Scene *scene = CTX_data_scene(C);
348
349         if(scene)
350                 return scene->toolsettings;
351         else
352                 return NULL;
353 }
354
355 int CTX_data_selected_objects(const bContext *C, ListBase *list)
356 {
357         return ctx_data_collection_get(C, CTX_data_selected_objects, list);
358 }
359
360 int CTX_data_selected_bases(const bContext *C, ListBase *list)
361 {
362         return ctx_data_collection_get(C, CTX_data_selected_bases, list);
363 }
364
365 int CTX_data_visible_objects(const bContext *C, ListBase *list)
366 {
367         return ctx_data_collection_get(C, CTX_data_visible_objects, list);
368 }
369
370 int CTX_data_visible_bases(const bContext *C, ListBase *list)
371 {
372         return ctx_data_collection_get(C, CTX_data_visible_bases, list);
373 }
374
375 struct Object *CTX_data_active_object(const bContext *C)
376 {
377         return ctx_data_pointer_get(C, CTX_data_active_object);
378 }
379
380 struct Base *CTX_data_active_base(const bContext *C)
381 {
382         return ctx_data_pointer_get(C, CTX_data_active_base);
383 }
384
385 struct Object *CTX_data_edit_object(const bContext *C)
386 {
387         return ctx_data_pointer_get(C, CTX_data_edit_object);
388 }
389
390 struct EditMesh *CTX_data_edit_mesh(const bContext *C)
391 {
392         return ctx_data_pointer_get(C, CTX_data_edit_mesh);
393 }
394
395 ListBase *CTX_data_edit_armature(const bContext *C)
396 {
397         return ctx_data_pointer_get(C, CTX_data_edit_armature);
398 }
399
400 /* data evaluation */
401
402 float CTX_eval_frame(const bContext *C)
403 {
404         return (C->data.scene)? C->data.scene->r.cfra: 0.0f;
405 }
406
407 int CTX_eval_render_resolution(const bContext *C)
408 {
409         return C->eval.render;
410 }
411
412 void CTX_eval_render_resolution_set(bContext *C, int render)
413 {
414         C->eval.render= render;
415 }
416