destruction of previous slot api. if it returns, it'll
[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 }
201
202 void CTX_wm_window_set(bContext *C, wmWindow *win)
203 {
204         C->wm.window= win;
205         C->wm.screen= (win)? win->screen: NULL;
206         C->data.scene= (C->wm.screen)? C->wm.screen->scene: NULL;
207 }
208
209 void CTX_wm_screen_set(bContext *C, bScreen *screen)
210 {
211         C->wm.screen= screen;
212         C->data.scene= (C->wm.screen)? C->wm.screen->scene: NULL;
213 }
214
215 void CTX_wm_area_set(bContext *C, ScrArea *area)
216 {
217         C->wm.area= area;
218 }
219
220 void CTX_wm_region_set(bContext *C, ARegion *region)
221 {
222         C->wm.region= region;
223 }
224
225 void CTX_wm_ui_block_set(bContext *C, struct uiBlock *block, bContextDataCallback cb)
226 {
227         C->wm.block= block;
228         C->wm.block_cb= cb;
229 }
230
231 /* data context utility functions */
232
233 struct bContextDataMember {
234         StructRNA *rna;
235         const char *name;
236         int collection;
237 };
238
239 struct bContextDataResult {
240         void *pointer;
241         ListBase list;
242 };
243
244 static int ctx_data_get(bContext *C, const bContextDataMember *member, bContextDataResult *result)
245 {
246         int done= 0, recursion= C->data.recursion;
247
248         memset(result, 0, sizeof(bContextDataResult));
249
250         /* we check recursion to ensure that we do not get infinite
251          * loops requesting data from ourselfs in a context callback */
252         if(!done && recursion < 1 && C->wm.block) {
253                 C->data.recursion= 1;
254                 done= C->wm.block_cb(C, member, result);
255         }
256         if(!done && recursion < 2 && C->wm.region) {
257                 C->data.recursion= 2;
258                 if(C->wm.region->type && C->wm.region->type->context)
259                         done= C->wm.region->type->context(C, member, result);
260         }
261         if(!done && recursion < 3 && C->wm.area) {
262                 C->data.recursion= 3;
263                 if(C->wm.area->type && C->wm.area->type->context)
264                         done= C->wm.area->type->context(C, member, result);
265         }
266         if(!done && recursion < 4 && C->wm.screen) {
267                 bContextDataCallback cb= C->wm.screen->context;
268                 C->data.recursion= 4;
269                 if(cb)
270                         done= cb(C, member, result);
271         }
272
273         C->data.recursion= recursion;
274
275         return done;
276 }
277
278 static void *ctx_data_pointer_get(const bContext *C, const bContextDataMember *member)
279 {
280         bContextDataResult result;
281
282         if(ctx_data_get((bContext*)C, member, &result))
283                 return result.pointer;
284
285         return NULL;
286 }
287
288 static int ctx_data_pointer_verify(const bContext *C, const bContextDataMember *member, void **pointer)
289 {
290         bContextDataResult result;
291
292         if(ctx_data_get((bContext*)C, member, &result)) {
293                 *pointer= result.pointer;
294                 return 1;
295         }
296         else {
297                 *pointer= NULL;
298                 return 0;
299         }
300 }
301
302 static int ctx_data_collection_get(const bContext *C, const bContextDataMember *member, ListBase *list)
303 {
304         bContextDataResult result;
305
306         if(ctx_data_get((bContext*)C, member, &result)) {
307                 *list= result.list;
308                 return 1;
309         }
310
311         return 0;
312 }
313
314 void CTX_data_pointer_set(bContextDataResult *result, void *data)
315 {
316         result->pointer= data;
317 }
318
319 void CTX_data_list_add(bContextDataResult *result, void *data)
320 {
321         LinkData *link;
322         
323         link= MEM_callocN(sizeof(LinkData), "LinkData");
324         link->data= data;
325
326         BLI_addtail(&result->list, link);
327 }
328
329 int ctx_data_list_count(const bContext *C, int (*func)(const bContext*, ListBase*))
330 {
331         ListBase list;
332
333         if(func(C, &list))
334                 return BLI_countlist(&list);
335         else
336                 return 0;
337 }
338
339 /* data context */
340
341 Main *CTX_data_main(const bContext *C)
342 {
343         Main *bmain;
344
345         if(ctx_data_pointer_verify(C, CTX_data_main, (void*)&bmain))
346                 return bmain;
347         else
348                 return C->data.main;
349 }
350
351 void CTX_data_main_set(bContext *C, Main *bmain)
352 {
353         C->data.main= bmain;
354 }
355
356 Scene *CTX_data_scene(const bContext *C)
357 {
358         Scene *scene;
359
360         if(ctx_data_pointer_verify(C, CTX_data_scene, (void*)&scene))
361                 return scene;
362         else
363                 return C->data.scene;
364 }
365
366 void CTX_data_scene_set(bContext *C, Scene *scene)
367 {
368         C->data.scene= scene;
369 }
370
371 ToolSettings *CTX_data_tool_settings(const bContext *C)
372 {
373         Scene *scene = CTX_data_scene(C);
374
375         if(scene)
376                 return scene->toolsettings;
377         else
378                 return NULL;
379 }
380
381 int CTX_data_selected_nodes(const bContext *C, ListBase *list)
382 {
383         return ctx_data_collection_get(C, CTX_data_selected_nodes, list);
384 }
385
386 int CTX_data_selected_editable_objects(const bContext *C, ListBase *list)
387 {
388         return ctx_data_collection_get(C, CTX_data_selected_editable_objects, list);
389 }
390
391 int CTX_data_selected_editable_bases(const bContext *C, ListBase *list)
392 {
393         return ctx_data_collection_get(C, CTX_data_selected_editable_bases, list);
394 }
395
396 int CTX_data_selected_objects(const bContext *C, ListBase *list)
397 {
398         return ctx_data_collection_get(C, CTX_data_selected_objects, list);
399 }
400
401 int CTX_data_selected_bases(const bContext *C, ListBase *list)
402 {
403         return ctx_data_collection_get(C, CTX_data_selected_bases, list);
404 }
405
406 int CTX_data_visible_objects(const bContext *C, ListBase *list)
407 {
408         return ctx_data_collection_get(C, CTX_data_visible_objects, list);
409 }
410
411 int CTX_data_visible_bases(const bContext *C, ListBase *list)
412 {
413         return ctx_data_collection_get(C, CTX_data_visible_bases, list);
414 }
415
416 struct Object *CTX_data_active_object(const bContext *C)
417 {
418         return ctx_data_pointer_get(C, CTX_data_active_object);
419 }
420
421 struct Base *CTX_data_active_base(const bContext *C)
422 {
423         return ctx_data_pointer_get(C, CTX_data_active_base);
424 }
425
426 struct Object *CTX_data_edit_object(const bContext *C)
427 {
428         return ctx_data_pointer_get(C, CTX_data_edit_object);
429 }
430
431 struct Image *CTX_data_edit_image(const bContext *C)
432 {
433         return ctx_data_pointer_get(C, CTX_data_edit_image);
434 }
435
436 struct ImBuf *CTX_data_edit_image_buffer(const bContext *C)
437 {
438         return ctx_data_pointer_get(C, CTX_data_edit_image_buffer);
439 }
440
441 /* data evaluation */
442
443 float CTX_eval_frame(const bContext *C)
444 {
445         return (C->data.scene)? C->data.scene->r.cfra: 0.0f;
446 }
447
448 int CTX_eval_render_resolution(const bContext *C)
449 {
450         return C->eval.render;
451 }
452
453 void CTX_eval_render_resolution_set(bContext *C, int render)
454 {
455         C->eval.render= render;
456 }
457