d1e228f83b687c480ba80e3eb511a40e832908cc
[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_ID.h"
31 #include "DNA_listBase.h"
32 #include "DNA_scene_types.h"
33 #include "DNA_screen_types.h"
34 #include "DNA_space_types.h"
35 #include "DNA_view3d_types.h"
36 #include "DNA_windowmanager_types.h"
37
38 #include "RNA_access.h"
39
40 #include "BLI_listbase.h"
41 #include "BLI_string.h"
42
43 #include "BKE_context.h"
44 #include "BKE_main.h"
45 #include "BKE_screen.h"
46
47 #include <string.h>
48
49 /* struct */
50
51 struct bContext {
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 ARegion *menu;
62                 struct bContextStore *store;
63         } wm;
64         
65         /* data context */
66         struct {
67                 struct Main *main;
68                 struct Scene *scene;
69
70                 int recursion;
71                 int py_init; /* true if python is initialized */
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         return C;
89 }
90
91 bContext *CTX_copy(const bContext *C)
92 {
93         bContext *newC= MEM_dupallocN((void*)C);
94
95         return newC;
96 }
97
98 void CTX_free(bContext *C)
99 {
100         MEM_freeN(C);
101 }
102
103 /* store */
104
105 bContextStore *CTX_store_add(ListBase *contexts, char *name, PointerRNA *ptr)
106 {
107         bContextStoreEntry *entry;
108         bContextStore *ctx, *lastctx;
109
110         /* ensure we have a context to put the entry in, if it was already used
111          * we have to copy the context to ensure */
112         ctx= contexts->last;
113
114         if(!ctx || ctx->used) {
115                 if(ctx) {
116                         lastctx= ctx;
117                         ctx= MEM_dupallocN(lastctx);
118                         BLI_duplicatelist(&ctx->entries, &lastctx->entries);
119                 }
120                 else
121                         ctx= MEM_callocN(sizeof(bContextStore), "bContextStore");
122
123                 BLI_addtail(contexts, ctx);
124         }
125
126         entry= MEM_callocN(sizeof(bContextStoreEntry), "bContextStoreEntry");
127         BLI_strncpy(entry->name, name, sizeof(entry->name));
128         entry->ptr= *ptr;
129
130         BLI_addtail(&ctx->entries, entry);
131
132         return ctx;
133 }
134
135 void CTX_store_set(bContext *C, bContextStore *store)
136 {
137         C->wm.store= store;
138 }
139
140 bContextStore *CTX_store_copy(bContextStore *store)
141 {
142         bContextStore *ctx;
143
144         ctx= MEM_dupallocN(store);
145         BLI_duplicatelist(&ctx->entries, &store->entries);
146
147         return ctx;
148 }
149
150 void CTX_store_free(bContextStore *store)
151 {
152         BLI_freelistN(&store->entries);
153         MEM_freeN(store);
154 }
155
156 void CTX_store_free_list(ListBase *contexts)
157 {
158         bContextStore *ctx;
159
160         while((ctx= contexts->first)) {
161                 BLI_remlink(contexts, ctx);
162                 CTX_store_free(ctx);
163         }
164 }
165
166 /* is python initialied? */
167 int CTX_py_init_get(bContext *C)
168 {
169         return C->data.py_init;
170 }
171 void CTX_py_init_set(bContext *C, int value)
172 {
173         C->data.py_init= value;
174 }
175
176 /* window manager context */
177
178 wmWindowManager *CTX_wm_manager(const bContext *C)
179 {
180         return C->wm.manager;
181 }
182
183 wmWindow *CTX_wm_window(const bContext *C)
184 {
185         return C->wm.window;
186 }
187
188 bScreen *CTX_wm_screen(const bContext *C)
189 {
190         return C->wm.screen;
191 }
192
193 ScrArea *CTX_wm_area(const bContext *C)
194 {
195         return C->wm.area;
196 }
197
198 SpaceLink *CTX_wm_space_data(const bContext *C)
199 {
200         return (C->wm.area)? C->wm.area->spacedata.first: NULL;
201 }
202
203 ARegion *CTX_wm_region(const bContext *C)
204 {
205         return C->wm.region;
206 }
207
208 void *CTX_wm_region_data(const bContext *C)
209 {
210         return (C->wm.region)? C->wm.region->regiondata: NULL;
211 }
212
213 struct ARegion *CTX_wm_menu(const bContext *C)
214 {
215         return C->wm.menu;
216 }
217
218 struct ReportList *CTX_wm_reports(const bContext *C)
219 {
220         if (C->wm.manager)
221                 return &(C->wm.manager->reports);
222
223         return NULL;
224 }
225
226 View3D *CTX_wm_view3d(const bContext *C)
227 {
228         if(C->wm.area && C->wm.area->spacetype==SPACE_VIEW3D)
229                 return C->wm.area->spacedata.first;
230         return NULL;
231 }
232
233 RegionView3D *CTX_wm_region_view3d(const bContext *C)
234 {
235         if(C->wm.area && C->wm.area->spacetype==SPACE_VIEW3D)
236                 if(C->wm.region)
237                         return C->wm.region->regiondata;
238         return NULL;
239 }
240
241 struct SpaceText *CTX_wm_space_text(const bContext *C)
242 {
243         if(C->wm.area && C->wm.area->spacetype==SPACE_TEXT)
244                 return C->wm.area->spacedata.first;
245         return NULL;
246 }
247
248 struct SpaceConsole *CTX_wm_space_console(const bContext *C)
249 {
250         if(C->wm.area && C->wm.area->spacetype==SPACE_CONSOLE)
251                 return C->wm.area->spacedata.first;
252         return NULL;
253 }
254
255 struct SpaceImage *CTX_wm_space_image(const bContext *C)
256 {
257         if(C->wm.area && C->wm.area->spacetype==SPACE_IMAGE)
258                 return C->wm.area->spacedata.first;
259         return NULL;
260 }
261
262 struct SpaceButs *CTX_wm_space_buts(const bContext *C)
263 {
264         if(C->wm.area && C->wm.area->spacetype==SPACE_BUTS)
265                 return C->wm.area->spacedata.first;
266         return NULL;
267 }
268
269 struct SpaceFile *CTX_wm_space_file(const bContext *C)
270 {
271         if(C->wm.area && C->wm.area->spacetype==SPACE_FILE)
272                 return C->wm.area->spacedata.first;
273         return NULL;
274 }
275
276 struct SpaceSeq *CTX_wm_space_seq(const bContext *C)
277 {
278         if(C->wm.area && C->wm.area->spacetype==SPACE_SEQ)
279                 return C->wm.area->spacedata.first;
280         return NULL;
281 }
282
283 struct SpaceOops *CTX_wm_space_outliner(const bContext *C)
284 {
285         if(C->wm.area && C->wm.area->spacetype==SPACE_OUTLINER)
286                 return C->wm.area->spacedata.first;
287         return NULL;
288 }
289
290 struct SpaceNla *CTX_wm_space_nla(const bContext *C)
291 {
292         if(C->wm.area && C->wm.area->spacetype==SPACE_NLA)
293                 return C->wm.area->spacedata.first;
294         return NULL;
295 }
296
297 struct SpaceTime *CTX_wm_space_time(const bContext *C)
298 {
299         if(C->wm.area && C->wm.area->spacetype==SPACE_TIME)
300                 return C->wm.area->spacedata.first;
301         return NULL;
302 }
303
304 struct SpaceNode *CTX_wm_space_node(const bContext *C)
305 {
306         if(C->wm.area && C->wm.area->spacetype==SPACE_NODE)
307                 return C->wm.area->spacedata.first;
308         return NULL;
309 }
310
311 struct SpaceLogic *CTX_wm_space_logic(const bContext *C)
312 {
313         if(C->wm.area && C->wm.area->spacetype==SPACE_LOGIC)
314                 return C->wm.area->spacedata.first;
315         return NULL;
316 }
317
318 struct SpaceIpo *CTX_wm_space_graph(const bContext *C)
319 {
320         if(C->wm.area && C->wm.area->spacetype==SPACE_IPO)
321                 return C->wm.area->spacedata.first;
322         return NULL;
323 }
324
325 struct SpaceAction *CTX_wm_space_action(const bContext *C)
326 {
327         if(C->wm.area && C->wm.area->spacetype==SPACE_ACTION)
328                 return C->wm.area->spacedata.first;
329         return NULL;
330 }
331
332 struct SpaceInfo *CTX_wm_space_info(const bContext *C)
333 {
334         if(C->wm.area && C->wm.area->spacetype==SPACE_INFO)
335                 return C->wm.area->spacedata.first;
336         return NULL;
337 }
338
339 void CTX_wm_manager_set(bContext *C, wmWindowManager *wm)
340 {
341         C->wm.manager= wm;
342         C->wm.window= NULL;
343         C->wm.screen= NULL;
344         C->wm.area= NULL;
345         C->wm.region= NULL;
346 }
347
348 void CTX_wm_window_set(bContext *C, wmWindow *win)
349 {
350         C->wm.window= win;
351         C->wm.screen= (win)? win->screen: NULL;
352         C->data.scene= (C->wm.screen)? C->wm.screen->scene: NULL;
353         C->wm.area= NULL;
354         C->wm.region= NULL;
355 }
356
357 void CTX_wm_screen_set(bContext *C, bScreen *screen)
358 {
359         C->wm.screen= screen;
360         C->data.scene= (C->wm.screen)? C->wm.screen->scene: NULL;
361         C->wm.area= NULL;
362         C->wm.region= NULL;
363 }
364
365 void CTX_wm_area_set(bContext *C, ScrArea *area)
366 {
367         C->wm.area= area;
368         C->wm.region= NULL;
369 }
370
371 void CTX_wm_region_set(bContext *C, ARegion *region)
372 {
373         C->wm.region= region;
374 }
375
376 void CTX_wm_menu_set(bContext *C, ARegion *menu)
377 {
378         C->wm.menu= menu;
379 }
380
381 /* data context utility functions */
382
383 struct bContextDataResult {
384         PointerRNA ptr;
385         ListBase list;
386         const char **dir;
387 };
388
389 static int ctx_data_get(bContext *C, const char *member, bContextDataResult *result)
390 {
391         int done= 0, recursion= C->data.recursion;
392
393         memset(result, 0, sizeof(bContextDataResult));
394
395         /* we check recursion to ensure that we do not get infinite
396          * loops requesting data from ourselfs in a context callback */
397         if(!done && recursion < 1 && C->wm.store) {
398                 bContextStoreEntry *entry;
399
400                 C->data.recursion= 1;
401
402                 for(entry=C->wm.store->entries.first; entry; entry=entry->next) {
403                         if(strcmp(entry->name, member) == 0) {
404                                 result->ptr= entry->ptr;
405                                 done= 1;
406                         }
407                 }
408         }
409         if(!done && recursion < 2 && C->wm.region) {
410                 C->data.recursion= 2;
411                 if(C->wm.region->type && C->wm.region->type->context)
412                         done= C->wm.region->type->context(C, member, result);
413         }
414         if(!done && recursion < 3 && C->wm.area) {
415                 C->data.recursion= 3;
416                 if(C->wm.area->type && C->wm.area->type->context)
417                         done= C->wm.area->type->context(C, member, result);
418         }
419         if(!done && recursion < 4 && C->wm.screen) {
420                 bContextDataCallback cb= C->wm.screen->context;
421                 C->data.recursion= 4;
422                 if(cb)
423                         done= cb(C, member, result);
424         }
425
426         C->data.recursion= recursion;
427
428         return done;
429 }
430
431 static void *ctx_data_pointer_get(const bContext *C, const char *member)
432 {
433         bContextDataResult result;
434
435         if(ctx_data_get((bContext*)C, member, &result))
436                 return result.ptr.data;
437
438         return NULL;
439 }
440
441 static int ctx_data_pointer_verify(const bContext *C, const char *member, void **pointer)
442 {
443         bContextDataResult result;
444
445         if(ctx_data_get((bContext*)C, member, &result)) {
446                 *pointer= result.ptr.data;
447                 return 1;
448         }
449         else {
450                 *pointer= NULL;
451                 return 0;
452         }
453 }
454
455 static int ctx_data_collection_get(const bContext *C, const char *member, ListBase *list)
456 {
457         bContextDataResult result;
458
459         if(ctx_data_get((bContext*)C, member, &result)) {
460                 *list= result.list;
461                 return 1;
462         }
463
464         list->first= NULL;
465         list->last= NULL;
466
467         return 0;
468 }
469
470 PointerRNA CTX_data_pointer_get(const bContext *C, const char *member)
471 {
472         bContextDataResult result;
473
474         if(ctx_data_get((bContext*)C, member, &result))
475                 return result.ptr;
476         else
477                 return PointerRNA_NULL;
478 }
479
480 PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
481 {
482         PointerRNA ptr = CTX_data_pointer_get(C, member);
483
484         if(ptr.data && RNA_struct_is_a(ptr.type, type))
485                 return ptr;
486         
487         return PointerRNA_NULL;
488 }
489
490 ListBase CTX_data_collection_get(const bContext *C, const char *member)
491 {
492         bContextDataResult result;
493
494         if(ctx_data_get((bContext*)C, member, &result)) {
495                 return result.list;
496         }
497         else {
498                 ListBase list;
499                 memset(&list, 0, sizeof(list));
500                 return list;
501         }
502 }
503
504 void CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb)
505 {
506         bContextDataResult result;
507
508         if(ctx_data_get((bContext*)C, member, &result)) {
509                 *r_ptr= result.ptr;
510                 *r_lb= result.list;
511         }
512         else {
513                 memset(r_ptr, 0, sizeof(*r_ptr));
514                 memset(r_lb, 0, sizeof(*r_lb));
515         }
516 }
517
518 static void data_dir_add(ListBase *lb, const char *member)
519 {
520         LinkData *link;
521
522         if(strcmp(member, "scene") == 0) /* exception */
523                 return;
524
525         for(link=lb->first; link; link=link->next)
526                 if(strcmp(link->data, member) == 0)
527                         return;
528         
529         link= MEM_callocN(sizeof(LinkData), "LinkData");
530         link->data= (void*)member;
531         BLI_addtail(lb, link);
532 }
533
534 ListBase CTX_data_dir_get(const bContext *C)
535 {
536         bContextDataResult result;
537         ListBase lb;
538         int a;
539
540         memset(&lb, 0, sizeof(lb));
541
542         if(C->wm.store) {
543                 bContextStoreEntry *entry;
544
545                 for(entry=C->wm.store->entries.first; entry; entry=entry->next)
546                         data_dir_add(&lb, entry->name);
547         }
548         if(C->wm.region && C->wm.region->type && C->wm.region->type->context) {
549                 memset(&result, 0, sizeof(result));
550                 C->wm.region->type->context(C, "", &result);
551
552                 if(result.dir)
553                         for(a=0; result.dir[a]; a++)
554                                 data_dir_add(&lb, result.dir[a]);
555         }
556         if(C->wm.area && C->wm.area->type && C->wm.area->type->context) {
557                 memset(&result, 0, sizeof(result));
558                 C->wm.area->type->context(C, "", &result);
559
560                 if(result.dir)
561                         for(a=0; result.dir[a]; a++)
562                                 data_dir_add(&lb, result.dir[a]);
563         }
564         if(C->wm.screen && C->wm.screen->context) {
565                 bContextDataCallback cb= C->wm.screen->context;
566                 memset(&result, 0, sizeof(result));
567                 cb(C, "", &result);
568
569                 if(result.dir)
570                         for(a=0; result.dir[a]; a++)
571                                 data_dir_add(&lb, result.dir[a]);
572         }
573
574         return lb;
575 }
576
577 int CTX_data_equals(const char *member, const char *str)
578 {
579         return (strcmp(member, str) == 0);
580 }
581
582 int CTX_data_dir(const char *member)
583 {
584         return (strcmp(member, "") == 0);
585 }
586
587 void CTX_data_id_pointer_set(bContextDataResult *result, ID *id)
588 {
589         RNA_id_pointer_create(id, &result->ptr);
590 }
591
592 void CTX_data_pointer_set(bContextDataResult *result, ID *id, StructRNA *type, void *data)
593 {
594         RNA_pointer_create(id, type, data, &result->ptr);
595 }
596
597 void CTX_data_id_list_add(bContextDataResult *result, ID *id)
598 {
599         CollectionPointerLink *link;
600
601         link= MEM_callocN(sizeof(CollectionPointerLink), "CTX_data_id_list_add");
602         RNA_id_pointer_create(id, &link->ptr);
603
604         BLI_addtail(&result->list, link);
605 }
606
607 void CTX_data_list_add(bContextDataResult *result, ID *id, StructRNA *type, void *data)
608 {
609         CollectionPointerLink *link;
610
611         link= MEM_callocN(sizeof(CollectionPointerLink), "CTX_data_list_add");
612         RNA_pointer_create(id, type, data, &link->ptr);
613
614         BLI_addtail(&result->list, link);
615 }
616
617 int ctx_data_list_count(const bContext *C, int (*func)(const bContext*, ListBase*))
618 {
619         ListBase list;
620
621         if(func(C, &list)) {
622                 int tot= BLI_countlist(&list);
623                 BLI_freelistN(&list);
624                 return tot;
625         }
626         else
627                 return 0;
628 }
629
630 void CTX_data_dir_set(bContextDataResult *result, const char **dir)
631 {
632         result->dir= dir;
633 }
634
635 /* data context */
636
637 Main *CTX_data_main(const bContext *C)
638 {
639         Main *bmain;
640
641         if(ctx_data_pointer_verify(C, "main", (void*)&bmain))
642                 return bmain;
643         else
644                 return C->data.main;
645 }
646
647 void CTX_data_main_set(bContext *C, Main *bmain)
648 {
649         C->data.main= bmain;
650 }
651
652 Scene *CTX_data_scene(const bContext *C)
653 {
654         Scene *scene;
655
656         if(ctx_data_pointer_verify(C, "scene", (void*)&scene))
657                 return scene;
658         else
659                 return C->data.scene;
660 }
661
662 void CTX_data_scene_set(bContext *C, Scene *scene)
663 {
664         C->data.scene= scene;
665 }
666
667 ToolSettings *CTX_data_tool_settings(const bContext *C)
668 {
669         Scene *scene = CTX_data_scene(C);
670
671         if(scene)
672                 return scene->toolsettings;
673         else
674                 return NULL;
675 }
676
677 int CTX_data_selected_nodes(const bContext *C, ListBase *list)
678 {
679         return ctx_data_collection_get(C, "selected_nodes", list);
680 }
681
682 int CTX_data_selected_editable_objects(const bContext *C, ListBase *list)
683 {
684         return ctx_data_collection_get(C, "selected_editable_objects", list);
685 }
686
687 int CTX_data_selected_editable_bases(const bContext *C, ListBase *list)
688 {
689         return ctx_data_collection_get(C, "selected_editable_bases", list);
690 }
691
692 int CTX_data_selected_objects(const bContext *C, ListBase *list)
693 {
694         return ctx_data_collection_get(C, "selected_objects", list);
695 }
696
697 int CTX_data_selected_bases(const bContext *C, ListBase *list)
698 {
699         return ctx_data_collection_get(C, "selected_bases", list);
700 }
701
702 int CTX_data_visible_objects(const bContext *C, ListBase *list)
703 {
704         return ctx_data_collection_get(C, "visible_objects", list);
705 }
706
707 int CTX_data_visible_bases(const bContext *C, ListBase *list)
708 {
709         return ctx_data_collection_get(C, "visible_bases", list);
710 }
711
712 int CTX_data_selectable_objects(const bContext *C, ListBase *list)
713 {
714         return ctx_data_collection_get(C, "selectable_objects", list);
715 }
716
717 int CTX_data_selectable_bases(const bContext *C, ListBase *list)
718 {
719         return ctx_data_collection_get(C, "selectable_bases", list);
720 }
721
722 struct Object *CTX_data_active_object(const bContext *C)
723 {
724         return ctx_data_pointer_get(C, "active_object");
725 }
726
727 struct Base *CTX_data_active_base(const bContext *C)
728 {
729         return ctx_data_pointer_get(C, "active_base");
730 }
731
732 struct Object *CTX_data_edit_object(const bContext *C)
733 {
734         return ctx_data_pointer_get(C, "edit_object");
735 }
736
737 struct Image *CTX_data_edit_image(const bContext *C)
738 {
739         return ctx_data_pointer_get(C, "edit_image");
740 }
741
742 struct Text *CTX_data_edit_text(const bContext *C)
743 {
744         return ctx_data_pointer_get(C, "edit_text");
745 }
746
747 struct EditBone *CTX_data_active_bone(const bContext *C)
748 {
749         return ctx_data_pointer_get(C, "active_bone");
750 }
751
752 int CTX_data_selected_bones(const bContext *C, ListBase *list)
753 {
754         return ctx_data_collection_get(C, "selected_bones", list);
755 }
756
757 int CTX_data_selected_editable_bones(const bContext *C, ListBase *list)
758 {
759         return ctx_data_collection_get(C, "selected_editable_bones", list);
760 }
761
762 int CTX_data_visible_bones(const bContext *C, ListBase *list)
763 {
764         return ctx_data_collection_get(C, "visible_bones", list);
765 }
766
767 int CTX_data_editable_bones(const bContext *C, ListBase *list)
768 {
769         return ctx_data_collection_get(C, "editable_bones", list);
770 }
771
772 struct bPoseChannel *CTX_data_active_pchan(const bContext *C)
773 {
774         return ctx_data_pointer_get(C, "active_pchan");
775 }
776
777 int CTX_data_selected_pchans(const bContext *C, ListBase *list)
778 {
779         return ctx_data_collection_get(C, "selected_pchans", list);
780 }
781
782 int CTX_data_visible_pchans(const bContext *C, ListBase *list)
783 {
784         return ctx_data_collection_get(C, "visible_pchans", list);
785 }
786