merge with 2.5 at r18679
[blender.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_view3d_types.h"
35 #include "DNA_windowmanager_types.h"
36
37 #include "RNA_access.h"
38
39 #include "BLI_listbase.h"
40
41 #include "BKE_context.h"
42 #include "BKE_main.h"
43 #include "BKE_report.h"
44 #include "BKE_screen.h"
45
46 #include <string.h>
47
48 /* struct */
49
50 struct bContext {
51         bContextTask task;
52         ReportList *reports;
53         int thread;
54
55         /* windowmanager context */
56         struct {
57                 struct wmWindowManager *manager;
58                 struct wmWindow *window;
59                 struct bScreen *screen;
60                 struct ScrArea *area;
61                 struct ARegion *region;
62                 struct uiBlock *block;
63
64                 bContextDataCallback block_cb;
65         } wm;
66         
67         /* data context */
68         struct {
69                 struct Main *main;
70                 struct Scene *scene;
71
72                 int recursion;
73         } data;
74         
75         /* data evaluation */
76         struct {
77                 int render;
78         } eval;
79 };
80
81 /* context */
82
83 bContext *CTX_create()
84 {
85         bContext *C;
86         
87         C= MEM_callocN(sizeof(bContext), "bContext");
88
89         C->task= CTX_UNDEFINED;
90         C->thread= 0;
91
92         return C;
93 }
94
95 bContext *CTX_copy(const bContext *C, int thread)
96 {
97         bContext *newC;
98
99         if(C->task != CTX_UNDEFINED)
100                 BKE_report(C->reports, RPT_ERROR_INVALID_CONTEXT, "CTX_copy not allowed for this task");
101         
102         newC= MEM_dupallocN((void*)C);
103         newC->thread= thread;
104
105         return newC;
106 }
107
108 int CTX_thread(const bContext *C)
109 {
110         return C->thread;
111 }
112
113 void CTX_free(bContext *C)
114 {
115         MEM_freeN(C);
116 }
117
118 /* context task and reports */
119
120 bContextTask CTX_task(const bContext *C)
121 {
122         return C->task;
123 }
124
125 void CTX_task_set(bContext *C, bContextTask task)
126 {
127         C->task= task;
128 }
129
130 ReportList *CTX_reports(const bContext *C)
131 {
132         return C->reports;
133 }
134
135 void CTX_reports_set(bContext *C, ReportList *reports)
136 {
137         C->reports= reports;
138 }
139
140 /* window manager context */
141
142 wmWindowManager *CTX_wm_manager(const bContext *C)
143 {
144         return C->wm.manager;
145 }
146
147 wmWindow *CTX_wm_window(const bContext *C)
148 {
149         return C->wm.window;
150 }
151
152 bScreen *CTX_wm_screen(const bContext *C)
153 {
154         return C->wm.screen;
155 }
156
157 ScrArea *CTX_wm_area(const bContext *C)
158 {
159         return C->wm.area;
160 }
161
162 SpaceLink *CTX_wm_space_data(const bContext *C)
163 {
164         return (C->wm.area)? C->wm.area->spacedata.first: NULL;
165 }
166
167 View3D *CTX_wm_view3d(const bContext *C)
168 {
169         if(C->wm.area && C->wm.area->spacetype==SPACE_VIEW3D)
170                 return C->wm.area->spacedata.first;
171         return NULL;
172 }
173
174 RegionView3D *CTX_wm_region_view3d(const bContext *C)
175 {
176         if(C->wm.area && C->wm.area->spacetype==SPACE_VIEW3D)
177                 if(C->wm.region)
178                         return C->wm.region->regiondata;
179         return NULL;
180 }
181
182 ARegion *CTX_wm_region(const bContext *C)
183 {
184         return C->wm.region;
185 }
186
187 void *CTX_wm_region_data(const bContext *C)
188 {
189         return (C->wm.region)? C->wm.region->regiondata: NULL;
190 }
191
192 struct uiBlock *CTX_wm_ui_block(const bContext *C)
193 {
194         return C->wm.block;
195 }
196
197 void CTX_wm_manager_set(bContext *C, wmWindowManager *wm)
198 {
199         C->wm.manager= wm;
200         C->wm.window= NULL;
201         C->wm.screen= NULL;
202         C->wm.area= NULL;
203         C->wm.region= NULL;
204 }
205
206 void CTX_wm_window_set(bContext *C, wmWindow *win)
207 {
208         C->wm.window= win;
209         C->wm.screen= (win)? win->screen: NULL;
210         C->data.scene= (C->wm.screen)? C->wm.screen->scene: NULL;
211         C->wm.area= NULL;
212         C->wm.region= NULL;
213 }
214
215 void CTX_wm_screen_set(bContext *C, bScreen *screen)
216 {
217         C->wm.screen= screen;
218         C->data.scene= (C->wm.screen)? C->wm.screen->scene: NULL;
219         C->wm.area= NULL;
220         C->wm.region= NULL;
221 }
222
223 void CTX_wm_area_set(bContext *C, ScrArea *area)
224 {
225         C->wm.area= area;
226         C->wm.region= NULL;
227 }
228
229 void CTX_wm_region_set(bContext *C, ARegion *region)
230 {
231         C->wm.region= region;
232 }
233
234 void CTX_wm_ui_block_set(bContext *C, struct uiBlock *block, bContextDataCallback cb)
235 {
236         C->wm.block= block;
237         C->wm.block_cb= cb;
238 }
239
240 /* data context utility functions */
241
242 struct bContextDataMember {
243         StructRNA *rna;
244         const char *name;
245         int collection;
246 };
247
248 struct bContextDataResult {
249         void *pointer;
250         ListBase list;
251 };
252
253 static int ctx_data_get(bContext *C, const bContextDataMember *member, bContextDataResult *result)
254 {
255         int done= 0, recursion= C->data.recursion;
256
257         memset(result, 0, sizeof(bContextDataResult));
258
259         /* we check recursion to ensure that we do not get infinite
260          * loops requesting data from ourselfs in a context callback */
261         if(!done && recursion < 1 && C->wm.block) {
262                 C->data.recursion= 1;
263                 done= C->wm.block_cb(C, member, result);
264         }
265         if(!done && recursion < 2 && C->wm.region) {
266                 C->data.recursion= 2;
267                 if(C->wm.region->type && C->wm.region->type->context)
268                         done= C->wm.region->type->context(C, member, result);
269         }
270         if(!done && recursion < 3 && C->wm.area) {
271                 C->data.recursion= 3;
272                 if(C->wm.area->type && C->wm.area->type->context)
273                         done= C->wm.area->type->context(C, member, result);
274         }
275         if(!done && recursion < 4 && C->wm.screen) {
276                 bContextDataCallback cb= C->wm.screen->context;
277                 C->data.recursion= 4;
278                 if(cb)
279                         done= cb(C, member, result);
280         }
281
282         C->data.recursion= recursion;
283
284         return done;
285 }
286
287 static void *ctx_data_pointer_get(const bContext *C, const bContextDataMember *member)
288 {
289         bContextDataResult result;
290
291         if(ctx_data_get((bContext*)C, member, &result))
292                 return result.pointer;
293
294         return NULL;
295 }
296
297 static int ctx_data_pointer_verify(const bContext *C, const bContextDataMember *member, void **pointer)
298 {
299         bContextDataResult result;
300
301         if(ctx_data_get((bContext*)C, member, &result)) {
302                 *pointer= result.pointer;
303                 return 1;
304         }
305         else {
306                 *pointer= NULL;
307                 return 0;
308         }
309 }
310
311 static int ctx_data_collection_get(const bContext *C, const bContextDataMember *member, ListBase *list)
312 {
313         bContextDataResult result;
314
315         if(ctx_data_get((bContext*)C, member, &result)) {
316                 *list= result.list;
317                 return 1;
318         }
319
320         return 0;
321 }
322
323 void CTX_data_pointer_set(bContextDataResult *result, void *data)
324 {
325         result->pointer= data;
326 }
327
328 void CTX_data_list_add(bContextDataResult *result, void *data)
329 {
330         LinkData *link;
331         
332         link= MEM_callocN(sizeof(LinkData), "LinkData");
333         link->data= data;
334
335         BLI_addtail(&result->list, link);
336 }
337
338 int ctx_data_list_count(const bContext *C, int (*func)(const bContext*, ListBase*))
339 {
340         ListBase list;
341
342         if(func(C, &list))
343                 return BLI_countlist(&list);
344         else
345                 return 0;
346 }
347
348 /* data context */
349
350 Main *CTX_data_main(const bContext *C)
351 {
352         Main *bmain;
353
354         if(ctx_data_pointer_verify(C, CTX_data_main, (void*)&bmain))
355                 return bmain;
356         else
357                 return C->data.main;
358 }
359
360 void CTX_data_main_set(bContext *C, Main *bmain)
361 {
362         C->data.main= bmain;
363 }
364
365 Scene *CTX_data_scene(const bContext *C)
366 {
367         Scene *scene;
368
369         if(ctx_data_pointer_verify(C, CTX_data_scene, (void*)&scene))
370                 return scene;
371         else
372                 return C->data.scene;
373 }
374
375 void CTX_data_scene_set(bContext *C, Scene *scene)
376 {
377         C->data.scene= scene;
378 }
379
380 ToolSettings *CTX_data_tool_settings(const bContext *C)
381 {
382         Scene *scene = CTX_data_scene(C);
383
384         if(scene)
385                 return scene->toolsettings;
386         else
387                 return NULL;
388 }
389
390 int CTX_data_selected_nodes(const bContext *C, ListBase *list)
391 {
392         return ctx_data_collection_get(C, CTX_data_selected_nodes, list);
393 }
394
395 int CTX_data_selected_editable_objects(const bContext *C, ListBase *list)
396 {
397         return ctx_data_collection_get(C, CTX_data_selected_editable_objects, list);
398 }
399
400 int CTX_data_selected_editable_bases(const bContext *C, ListBase *list)
401 {
402         return ctx_data_collection_get(C, CTX_data_selected_editable_bases, list);
403 }
404
405 int CTX_data_selected_objects(const bContext *C, ListBase *list)
406 {
407         return ctx_data_collection_get(C, CTX_data_selected_objects, list);
408 }
409
410 int CTX_data_selected_bases(const bContext *C, ListBase *list)
411 {
412         return ctx_data_collection_get(C, CTX_data_selected_bases, list);
413 }
414
415 int CTX_data_visible_objects(const bContext *C, ListBase *list)
416 {
417         return ctx_data_collection_get(C, CTX_data_visible_objects, list);
418 }
419
420 int CTX_data_visible_bases(const bContext *C, ListBase *list)
421 {
422         return ctx_data_collection_get(C, CTX_data_visible_bases, list);
423 }
424
425 struct Object *CTX_data_active_object(const bContext *C)
426 {
427         return ctx_data_pointer_get(C, CTX_data_active_object);
428 }
429
430 struct Base *CTX_data_active_base(const bContext *C)
431 {
432         return ctx_data_pointer_get(C, CTX_data_active_base);
433 }
434
435 struct Object *CTX_data_edit_object(const bContext *C)
436 {
437         return ctx_data_pointer_get(C, CTX_data_edit_object);
438 }
439
440 struct Image *CTX_data_edit_image(const bContext *C)
441 {
442         return ctx_data_pointer_get(C, CTX_data_edit_image);
443 }
444
445 struct ImBuf *CTX_data_edit_image_buffer(const bContext *C)
446 {
447         return ctx_data_pointer_get(C, CTX_data_edit_image_buffer);
448 }
449
450 /* data evaluation */
451
452 float CTX_eval_frame(const bContext *C)
453 {
454         return (C->data.scene)? C->data.scene->r.cfra: 0.0f;
455 }
456
457 int CTX_eval_render_resolution(const bContext *C)
458 {
459         return C->eval.render;
460 }
461
462 void CTX_eval_render_resolution_set(bContext *C, int render)
463 {
464         C->eval.render= render;
465 }
466