Python/context: allow overriding window/screen/area/region context for running operators
[blender.git] / source / blender / blenkernel / intern / context.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
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  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation (2008).
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/blenkernel/intern/context.c
27  *  \ingroup bke
28  */
29
30
31 #include <string.h>
32 #include <stddef.h>
33
34 #include "MEM_guardedalloc.h"
35
36 #include "DNA_scene_types.h"
37 #include "DNA_screen_types.h"
38 #include "DNA_space_types.h"
39 #include "DNA_view3d_types.h"
40 #include "DNA_windowmanager_types.h"
41 #include "DNA_object_types.h"
42
43 #include "RNA_access.h"
44
45 #include "BLI_listbase.h"
46 #include "BLI_string.h"
47
48 #include "BKE_context.h"
49 #include "BKE_main.h"
50 #include "BKE_screen.h"
51
52 #ifdef WITH_PYTHON
53 #include "BPY_extern.h"
54 #endif
55
56 /* struct */
57
58 struct bContext {
59         int thread;
60
61         /* windowmanager context */
62         struct {
63                 struct wmWindowManager *manager;
64                 struct wmWindow *window;
65                 struct bScreen *screen;
66                 struct ScrArea *area;
67                 struct ARegion *region;
68                 struct ARegion *menu;
69                 struct bContextStore *store;
70                 const char *operator_poll_msg; /* reason for poll failing */
71         } wm;
72         
73         /* data context */
74         struct {
75                 struct Main *main;
76                 struct Scene *scene;
77
78                 int recursion;
79                 int py_init; /* true if python is initialized */
80                 void *py_context;
81         } data;
82         
83         /* data evaluation */
84         struct {
85                 int render;
86         } eval;
87 };
88
89 /* context */
90
91 bContext *CTX_create(void)
92 {
93         bContext *C;
94         
95         C= MEM_callocN(sizeof(bContext), "bContext");
96
97         return C;
98 }
99
100 bContext *CTX_copy(const bContext *C)
101 {
102         bContext *newC= MEM_dupallocN((void*)C);
103
104         return newC;
105 }
106
107 void CTX_free(bContext *C)
108 {
109         MEM_freeN(C);
110 }
111
112 /* store */
113
114 bContextStore *CTX_store_add(ListBase *contexts, const char *name, PointerRNA *ptr)
115 {
116         bContextStoreEntry *entry;
117         bContextStore *ctx, *lastctx;
118
119         /* ensure we have a context to put the entry in, if it was already used
120          * we have to copy the context to ensure */
121         ctx= contexts->last;
122
123         if (!ctx || ctx->used) {
124                 if (ctx) {
125                         lastctx= ctx;
126                         ctx= MEM_dupallocN(lastctx);
127                         BLI_duplicatelist(&ctx->entries, &lastctx->entries);
128                 }
129                 else
130                         ctx= MEM_callocN(sizeof(bContextStore), "bContextStore");
131
132                 BLI_addtail(contexts, ctx);
133         }
134
135         entry= MEM_callocN(sizeof(bContextStoreEntry), "bContextStoreEntry");
136         BLI_strncpy(entry->name, name, sizeof(entry->name));
137         entry->ptr= *ptr;
138
139         BLI_addtail(&ctx->entries, entry);
140
141         return ctx;
142 }
143
144 bContextStore *CTX_store_add_all(ListBase *contexts, bContextStore *context)
145 {
146         bContextStoreEntry *entry, *tentry;
147         bContextStore *ctx, *lastctx;
148
149         /* ensure we have a context to put the entries in, if it was already used
150          * we have to copy the context to ensure */
151         ctx= contexts->last;
152
153         if (!ctx || ctx->used) {
154                 if (ctx) {
155                         lastctx= ctx;
156                         ctx= MEM_dupallocN(lastctx);
157                         BLI_duplicatelist(&ctx->entries, &lastctx->entries);
158                 }
159                 else
160                         ctx= MEM_callocN(sizeof(bContextStore), "bContextStore");
161
162                 BLI_addtail(contexts, ctx);
163         }
164
165         for (tentry= context->entries.first; tentry; tentry= tentry->next) {
166                 entry= MEM_dupallocN(tentry);
167                 BLI_addtail(&ctx->entries, entry);
168         }
169
170         return ctx;
171 }
172
173 void CTX_store_set(bContext *C, bContextStore *store)
174 {
175         C->wm.store= store;
176 }
177
178 bContextStore *CTX_store_copy(bContextStore *store)
179 {
180         bContextStore *ctx;
181
182         ctx= MEM_dupallocN(store);
183         BLI_duplicatelist(&ctx->entries, &store->entries);
184
185         return ctx;
186 }
187
188 void CTX_store_free(bContextStore *store)
189 {
190         BLI_freelistN(&store->entries);
191         MEM_freeN(store);
192 }
193
194 void CTX_store_free_list(ListBase *contexts)
195 {
196         bContextStore *ctx;
197
198         while ((ctx= contexts->first)) {
199                 BLI_remlink(contexts, ctx);
200                 CTX_store_free(ctx);
201         }
202 }
203
204 /* is python initialied? */
205
206 int CTX_py_init_get(bContext *C)
207 {
208         return C->data.py_init;
209 }
210 void CTX_py_init_set(bContext *C, int value)
211 {
212         C->data.py_init= value;
213 }
214
215 void *CTX_py_dict_get(const bContext *C)
216 {
217         return C->data.py_context;
218 }
219 void CTX_py_dict_set(bContext *C, void *value)
220 {
221         C->data.py_context= value;
222 }
223
224 /* data context utility functions */
225
226 struct bContextDataResult {
227         PointerRNA ptr;
228         ListBase list;
229         const char **dir;
230         short type; /* 0: normal, 1: seq */
231 };
232
233 static void *ctx_wm_python_context_get(const bContext *C, const char *member, void *fall_through)
234 {
235 #ifdef WITH_PYTHON
236         bContextDataResult result;
237
238         if (C && CTX_py_dict_get(C)) {
239                 memset(&result, 0, sizeof(bContextDataResult));
240                 BPY_context_member_get((bContext*)C, member, &result);
241                 if(result.ptr.data)
242                         return result.ptr.data;
243         }
244 #endif
245
246         return fall_through;
247 }
248
249 static int ctx_data_get(bContext *C, const char *member, bContextDataResult *result)
250 {
251         int done= 0, recursion= C->data.recursion;
252         int ret= 0;
253
254         memset(result, 0, sizeof(bContextDataResult));
255 #ifdef WITH_PYTHON
256         if (CTX_py_dict_get(C)) {
257                 return BPY_context_member_get(C, member, result);
258 //              if (BPY_context_member_get(C, member, result))
259 //                      return 1;
260         }
261 #endif
262         /* we check recursion to ensure that we do not get infinite
263          * loops requesting data from ourselfs in a context callback */
264
265         /* Ok, this looks evil...
266          * if (ret) done= -(-ret | -done);
267          *
268          * Values in order of importance
269          * (0, -1, 1) - Where 1 is highest priority
270          * */
271         if (done!=1 && recursion < 1 && C->wm.store) {
272                 bContextStoreEntry *entry;
273
274                 C->data.recursion= 1;
275
276                 entry= BLI_rfindstring(&C->wm.store->entries, member, offsetof(bContextStoreEntry, name));
277                 if (entry) {
278                         result->ptr= entry->ptr;
279                         done= 1;
280                 }
281         }
282         if (done!=1 && recursion < 2 && C->wm.region) {
283                 C->data.recursion= 2;
284                 if (C->wm.region->type && C->wm.region->type->context) {
285                         ret = C->wm.region->type->context(C, member, result);
286                         if (ret) done= -(-ret | -done);
287
288                 }
289         }
290         if (done!=1 && recursion < 3 && C->wm.area) {
291                 C->data.recursion= 3;
292                 if (C->wm.area->type && C->wm.area->type->context) {
293                         ret = C->wm.area->type->context(C, member, result);
294                         if (ret) done= -(-ret | -done);
295                 }
296         }
297         if (done!=1 && recursion < 4 && C->wm.screen) {
298                 bContextDataCallback cb= C->wm.screen->context;
299                 C->data.recursion= 4;
300                 if (cb) {
301                         ret = cb(C, member, result);
302                         if (ret) done= -(-ret | -done);
303                 }
304         }
305
306         C->data.recursion= recursion;
307
308         return done;
309 }
310
311 static void *ctx_data_pointer_get(const bContext *C, const char *member)
312 {
313         bContextDataResult result;
314
315         if (C && ctx_data_get((bContext*)C, member, &result)==1)
316                 return result.ptr.data;
317
318         return NULL;
319 }
320
321 static int ctx_data_pointer_verify(const bContext *C, const char *member, void **pointer)
322 {
323         bContextDataResult result;
324
325         /* if context is NULL, pointer must be NULL too and that is a valid return */
326         if (C == NULL) {
327                 *pointer= NULL;
328                 return 1;
329         }
330         else if (ctx_data_get((bContext*)C, member, &result)==1) {
331                 *pointer= result.ptr.data;
332                 return 1;
333         }
334         else {
335                 *pointer= NULL;
336                 return 0;
337         }
338 }
339
340 static int ctx_data_collection_get(const bContext *C, const char *member, ListBase *list)
341 {
342         bContextDataResult result;
343
344         if (ctx_data_get((bContext*)C, member, &result)==1) {
345                 *list= result.list;
346                 return 1;
347         }
348
349         list->first= NULL;
350         list->last= NULL;
351
352         return 0;
353 }
354
355 PointerRNA CTX_data_pointer_get(const bContext *C, const char *member)
356 {
357         bContextDataResult result;
358
359         if (ctx_data_get((bContext*)C, member, &result)==1)
360                 return result.ptr;
361         else
362                 return PointerRNA_NULL;
363 }
364
365 PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
366 {
367         PointerRNA ptr = CTX_data_pointer_get(C, member);
368
369         if (ptr.data && RNA_struct_is_a(ptr.type, type))
370                 return ptr;
371         
372         return PointerRNA_NULL;
373 }
374
375 ListBase CTX_data_collection_get(const bContext *C, const char *member)
376 {
377         bContextDataResult result;
378
379         if (ctx_data_get((bContext*)C, member, &result)==1) {
380                 return result.list;
381         }
382         else {
383                 ListBase list= {NULL, NULL};
384                 return list;
385         }
386 }
387
388 /* 1:found,  -1:found but not set,  0:not found */
389 int CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb, short *r_type)
390 {
391         bContextDataResult result;
392         int ret= ctx_data_get((bContext*)C, member, &result);
393
394         if (ret==1) {
395                 *r_ptr= result.ptr;
396                 *r_lb= result.list;
397                 *r_type= result.type;
398         }
399         else {
400                 memset(r_ptr, 0, sizeof(*r_ptr));
401                 memset(r_lb, 0, sizeof(*r_lb));
402                 *r_type= 0;
403         }
404
405         return ret;
406 }
407
408 static void data_dir_add(ListBase *lb, const char *member)
409 {
410         LinkData *link;
411         
412         if (strcmp(member, "scene") == 0) /* exception */
413                 return;
414
415         if (BLI_findstring(lb, member, offsetof(LinkData, data)))
416                 return;
417         
418         link= MEM_callocN(sizeof(LinkData), "LinkData");
419         link->data= (void*)member;
420         BLI_addtail(lb, link);
421 }
422
423 ListBase CTX_data_dir_get(const bContext *C)
424 {
425         bContextDataResult result;
426         ListBase lb;
427         int a;
428
429         memset(&lb, 0, sizeof(lb));
430
431         if (C->wm.store) {
432                 bContextStoreEntry *entry;
433
434                 for (entry=C->wm.store->entries.first; entry; entry=entry->next)
435                         data_dir_add(&lb, entry->name);
436         }
437         if (C->wm.region && C->wm.region->type && C->wm.region->type->context) {
438                 memset(&result, 0, sizeof(result));
439                 C->wm.region->type->context(C, "", &result);
440
441                 if (result.dir)
442                         for (a=0; result.dir[a]; a++)
443                                 data_dir_add(&lb, result.dir[a]);
444         }
445         if (C->wm.area && C->wm.area->type && C->wm.area->type->context) {
446                 memset(&result, 0, sizeof(result));
447                 C->wm.area->type->context(C, "", &result);
448
449                 if (result.dir)
450                         for (a=0; result.dir[a]; a++)
451                                 data_dir_add(&lb, result.dir[a]);
452         }
453         if (C->wm.screen && C->wm.screen->context) {
454                 bContextDataCallback cb= C->wm.screen->context;
455                 memset(&result, 0, sizeof(result));
456                 cb(C, "", &result);
457
458                 if (result.dir)
459                         for (a=0; result.dir[a]; a++)
460                                 data_dir_add(&lb, result.dir[a]);
461         }
462
463         return lb;
464 }
465
466 int CTX_data_equals(const char *member, const char *str)
467 {
468         return (strcmp(member, str) == 0);
469 }
470
471 int CTX_data_dir(const char *member)
472 {
473         return member[0] == '\0';
474 }
475
476 void CTX_data_id_pointer_set(bContextDataResult *result, ID *id)
477 {
478         RNA_id_pointer_create(id, &result->ptr);
479 }
480
481 void CTX_data_pointer_set(bContextDataResult *result, ID *id, StructRNA *type, void *data)
482 {
483         RNA_pointer_create(id, type, data, &result->ptr);
484 }
485
486 void CTX_data_id_list_add(bContextDataResult *result, ID *id)
487 {
488         CollectionPointerLink *link;
489
490         link= MEM_callocN(sizeof(CollectionPointerLink), "CTX_data_id_list_add");
491         RNA_id_pointer_create(id, &link->ptr);
492
493         BLI_addtail(&result->list, link);
494 }
495
496 void CTX_data_list_add(bContextDataResult *result, ID *id, StructRNA *type, void *data)
497 {
498         CollectionPointerLink *link;
499
500         link= MEM_callocN(sizeof(CollectionPointerLink), "CTX_data_list_add");
501         RNA_pointer_create(id, type, data, &link->ptr);
502
503         BLI_addtail(&result->list, link);
504 }
505
506 int ctx_data_list_count(const bContext *C, int (*func)(const bContext*, ListBase*))
507 {
508         ListBase list;
509
510         if (func(C, &list)) {
511                 int tot= BLI_countlist(&list);
512                 BLI_freelistN(&list);
513                 return tot;
514         }
515         else
516                 return 0;
517 }
518
519 void CTX_data_dir_set(bContextDataResult *result, const char **dir)
520 {
521         result->dir= dir;
522 }
523
524 void CTX_data_type_set(bContextDataResult *result, short type)
525 {
526         result->type= type;
527 }
528
529 short CTX_data_type_get(bContextDataResult *result)
530 {
531         return result->type;
532 }
533
534
535
536 /* window manager context */
537
538 wmWindowManager *CTX_wm_manager(const bContext *C)
539 {
540         return C->wm.manager;
541 }
542
543 wmWindow *CTX_wm_window(const bContext *C)
544 {
545         return ctx_wm_python_context_get(C, "window", C->wm.window);
546 }
547
548 bScreen *CTX_wm_screen(const bContext *C)
549 {
550         return ctx_wm_python_context_get(C, "screen", C->wm.screen);
551 }
552
553 ScrArea *CTX_wm_area(const bContext *C)
554 {
555         return ctx_wm_python_context_get(C, "area", C->wm.area);
556 }
557
558 SpaceLink *CTX_wm_space_data(const bContext *C)
559 {
560         ScrArea *sa = CTX_wm_area(C);
561         return (sa)? sa->spacedata.first: NULL;
562 }
563
564 ARegion *CTX_wm_region(const bContext *C)
565 {
566         return ctx_wm_python_context_get(C, "region", C->wm.region);
567 }
568
569 void *CTX_wm_region_data(const bContext *C)
570 {
571         ARegion *ar = CTX_wm_region(C);
572         return (ar)? ar->regiondata: NULL;
573 }
574
575 struct ARegion *CTX_wm_menu(const bContext *C)
576 {
577         return C->wm.menu;
578 }
579
580 struct ReportList *CTX_wm_reports(const bContext *C)
581 {
582         if (C->wm.manager)
583                 return &(C->wm.manager->reports);
584
585         return NULL;
586 }
587
588 View3D *CTX_wm_view3d(const bContext *C)
589 {
590         ScrArea *sa = CTX_wm_area(C);
591         if (sa && sa->spacetype==SPACE_VIEW3D)
592                 return sa->spacedata.first;
593         return NULL;
594 }
595
596 RegionView3D *CTX_wm_region_view3d(const bContext *C)
597 {
598         ScrArea *sa = CTX_wm_area(C);
599         if (sa && sa->spacetype==SPACE_VIEW3D)
600                 if (C->wm.region)
601                         return C->wm.region->regiondata;
602         return NULL;
603 }
604
605 struct SpaceText *CTX_wm_space_text(const bContext *C)
606 {
607         ScrArea *sa = CTX_wm_area(C);
608         if (sa && sa->spacetype==SPACE_TEXT)
609                 return sa->spacedata.first;
610         return NULL;
611 }
612
613 struct SpaceConsole *CTX_wm_space_console(const bContext *C)
614 {
615         ScrArea *sa = CTX_wm_area(C);
616         if (sa && sa->spacetype==SPACE_CONSOLE)
617                 return sa->spacedata.first;
618         return NULL;
619 }
620
621 struct SpaceImage *CTX_wm_space_image(const bContext *C)
622 {
623         ScrArea *sa = CTX_wm_area(C);
624         if (sa && sa->spacetype==SPACE_IMAGE)
625                 return sa->spacedata.first;
626         return NULL;
627 }
628
629 struct SpaceButs *CTX_wm_space_buts(const bContext *C)
630 {
631         ScrArea *sa = CTX_wm_area(C);
632         if (sa && sa->spacetype==SPACE_BUTS)
633                 return sa->spacedata.first;
634         return NULL;
635 }
636
637 struct SpaceFile *CTX_wm_space_file(const bContext *C)
638 {
639         ScrArea *sa = CTX_wm_area(C);
640         if (sa && sa->spacetype==SPACE_FILE)
641                 return sa->spacedata.first;
642         return NULL;
643 }
644
645 struct SpaceSeq *CTX_wm_space_seq(const bContext *C)
646 {
647         ScrArea *sa = CTX_wm_area(C);
648         if (sa && sa->spacetype==SPACE_SEQ)
649                 return sa->spacedata.first;
650         return NULL;
651 }
652
653 struct SpaceOops *CTX_wm_space_outliner(const bContext *C)
654 {
655         ScrArea *sa = CTX_wm_area(C);
656         if (sa && sa->spacetype==SPACE_OUTLINER)
657                 return sa->spacedata.first;
658         return NULL;
659 }
660
661 struct SpaceNla *CTX_wm_space_nla(const bContext *C)
662 {
663         ScrArea *sa = CTX_wm_area(C);
664         if (sa && sa->spacetype==SPACE_NLA)
665                 return sa->spacedata.first;
666         return NULL;
667 }
668
669 struct SpaceTime *CTX_wm_space_time(const bContext *C)
670 {
671         ScrArea *sa = CTX_wm_area(C);
672         if (sa && sa->spacetype==SPACE_TIME)
673                 return sa->spacedata.first;
674         return NULL;
675 }
676
677 struct SpaceNode *CTX_wm_space_node(const bContext *C)
678 {
679         ScrArea *sa = CTX_wm_area(C);
680         if (sa && sa->spacetype==SPACE_NODE)
681                 return sa->spacedata.first;
682         return NULL;
683 }
684
685 struct SpaceLogic *CTX_wm_space_logic(const bContext *C)
686 {
687         ScrArea *sa = CTX_wm_area(C);
688         if (sa && sa->spacetype==SPACE_LOGIC)
689                 return sa->spacedata.first;
690         return NULL;
691 }
692
693 struct SpaceIpo *CTX_wm_space_graph(const bContext *C)
694 {
695         ScrArea *sa = CTX_wm_area(C);
696         if (sa && sa->spacetype==SPACE_IPO)
697                 return sa->spacedata.first;
698         return NULL;
699 }
700
701 struct SpaceAction *CTX_wm_space_action(const bContext *C)
702 {
703         ScrArea *sa = CTX_wm_area(C);
704         if (sa && sa->spacetype==SPACE_ACTION)
705                 return sa->spacedata.first;
706         return NULL;
707 }
708
709 struct SpaceInfo *CTX_wm_space_info(const bContext *C)
710 {
711         ScrArea *sa = CTX_wm_area(C);
712         if (sa && sa->spacetype==SPACE_INFO)
713                 return sa->spacedata.first;
714         return NULL;
715 }
716
717 struct SpaceUserPref *CTX_wm_space_userpref(const bContext *C)
718 {
719         ScrArea *sa = CTX_wm_area(C);
720         if (sa && sa->spacetype==SPACE_USERPREF)
721                 return sa->spacedata.first;
722         return NULL;
723 }
724
725 struct SpaceClip *CTX_wm_space_clip(const bContext *C)
726 {
727         ScrArea *sa = CTX_wm_area(C);
728         if (sa && sa->spacetype==SPACE_CLIP)
729                 return sa->spacedata.first;
730         return NULL;
731 }
732
733 void CTX_wm_manager_set(bContext *C, wmWindowManager *wm)
734 {
735         C->wm.manager= wm;
736         C->wm.window= NULL;
737         C->wm.screen= NULL;
738         C->wm.area= NULL;
739         C->wm.region= NULL;
740 }
741
742 void CTX_wm_window_set(bContext *C, wmWindow *win)
743 {
744         C->wm.window= win;
745         C->wm.screen= (win)? win->screen: NULL;
746         if (C->wm.screen)
747                 C->data.scene= C->wm.screen->scene;
748         C->wm.area= NULL;
749         C->wm.region= NULL;
750 }
751
752 void CTX_wm_screen_set(bContext *C, bScreen *screen)
753 {
754         C->wm.screen= screen;
755         if (C->wm.screen)
756                 C->data.scene= C->wm.screen->scene;
757         C->wm.area= NULL;
758         C->wm.region= NULL;
759 }
760
761 void CTX_wm_area_set(bContext *C, ScrArea *area)
762 {
763         C->wm.area= area;
764         C->wm.region= NULL;
765 }
766
767 void CTX_wm_region_set(bContext *C, ARegion *region)
768 {
769         C->wm.region= region;
770 }
771
772 void CTX_wm_menu_set(bContext *C, ARegion *menu)
773 {
774         C->wm.menu= menu;
775 }
776
777 void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
778 {
779         C->wm.operator_poll_msg= msg;
780 }
781
782 const char *CTX_wm_operator_poll_msg_get(bContext *C)
783 {
784         return C->wm.operator_poll_msg;
785 }
786
787 /* data context */
788
789 Main *CTX_data_main(const bContext *C)
790 {
791         Main *bmain;
792
793         if (ctx_data_pointer_verify(C, "blend_data", (void*)&bmain))
794                 return bmain;
795         else
796                 return C->data.main;
797 }
798
799 void CTX_data_main_set(bContext *C, Main *bmain)
800 {
801         C->data.main= bmain;
802 }
803
804 Scene *CTX_data_scene(const bContext *C)
805 {
806         Scene *scene;
807
808         if (ctx_data_pointer_verify(C, "scene", (void*)&scene))
809                 return scene;
810         else
811                 return C->data.scene;
812 }
813
814 int CTX_data_mode_enum(const bContext *C)
815 {
816         Object *obedit= CTX_data_edit_object(C);
817
818         if (obedit) {
819                 switch (obedit->type) {
820                         case OB_MESH:
821                                 return CTX_MODE_EDIT_MESH;
822                         case OB_CURVE:
823                                 return CTX_MODE_EDIT_CURVE;
824                         case OB_SURF:
825                                 return CTX_MODE_EDIT_SURFACE;
826                         case OB_FONT:
827                                 return CTX_MODE_EDIT_TEXT;
828                         case OB_ARMATURE:
829                                 return CTX_MODE_EDIT_ARMATURE;
830                         case OB_MBALL:
831                                 return CTX_MODE_EDIT_METABALL;
832                         case OB_LATTICE:
833                                 return CTX_MODE_EDIT_LATTICE;
834                 }
835         }
836         else {
837                 Object *ob = CTX_data_active_object(C);
838
839                 if (ob) {
840                         if (ob->mode & OB_MODE_POSE) return CTX_MODE_POSE;
841                         else if (ob->mode & OB_MODE_SCULPT)  return CTX_MODE_SCULPT;
842                         else if (ob->mode & OB_MODE_WEIGHT_PAINT) return CTX_MODE_PAINT_WEIGHT;
843                         else if (ob->mode & OB_MODE_VERTEX_PAINT) return CTX_MODE_PAINT_VERTEX;
844                         else if (ob->mode & OB_MODE_TEXTURE_PAINT) return CTX_MODE_PAINT_TEXTURE;
845                         else if (ob->mode & OB_MODE_PARTICLE_EDIT) return CTX_MODE_PARTICLE;
846                 }
847         }
848
849         return CTX_MODE_OBJECT;
850 }
851
852
853 /* would prefer if we can use the enum version below over this one - Campbell */
854 /* must be aligned with above enum  */
855 static const char *data_mode_strings[] = {
856         "mesh_edit",
857         "curve_edit",
858         "surface_edit",
859         "text_edit",
860         "armature_edit",
861         "mball_edit",
862         "lattice_edit",
863         "posemode",
864         "sculpt_mode",
865         "weightpaint",
866         "vertexpaint",
867         "imagepaint",
868         "particlemode",
869         "objectmode",
870         NULL
871 };
872 const char *CTX_data_mode_string(const bContext *C)
873 {
874         return data_mode_strings[CTX_data_mode_enum(C)];
875 }
876
877 void CTX_data_scene_set(bContext *C, Scene *scene)
878 {
879         C->data.scene= scene;
880 }
881
882 ToolSettings *CTX_data_tool_settings(const bContext *C)
883 {
884         Scene *scene = CTX_data_scene(C);
885
886         if (scene)
887                 return scene->toolsettings;
888         else
889                 return NULL;
890 }
891
892 int CTX_data_selected_nodes(const bContext *C, ListBase *list)
893 {
894         return ctx_data_collection_get(C, "selected_nodes", list);
895 }
896
897 int CTX_data_selected_editable_objects(const bContext *C, ListBase *list)
898 {
899         return ctx_data_collection_get(C, "selected_editable_objects", list);
900 }
901
902 int CTX_data_selected_editable_bases(const bContext *C, ListBase *list)
903 {
904         return ctx_data_collection_get(C, "selected_editable_bases", list);
905 }
906
907 int CTX_data_selected_objects(const bContext *C, ListBase *list)
908 {
909         return ctx_data_collection_get(C, "selected_objects", list);
910 }
911
912 int CTX_data_selected_bases(const bContext *C, ListBase *list)
913 {
914         return ctx_data_collection_get(C, "selected_bases", list);
915 }
916
917 int CTX_data_visible_objects(const bContext *C, ListBase *list)
918 {
919         return ctx_data_collection_get(C, "visible_objects", list);
920 }
921
922 int CTX_data_visible_bases(const bContext *C, ListBase *list)
923 {
924         return ctx_data_collection_get(C, "visible_bases", list);
925 }
926
927 int CTX_data_selectable_objects(const bContext *C, ListBase *list)
928 {
929         return ctx_data_collection_get(C, "selectable_objects", list);
930 }
931
932 int CTX_data_selectable_bases(const bContext *C, ListBase *list)
933 {
934         return ctx_data_collection_get(C, "selectable_bases", list);
935 }
936
937 struct Object *CTX_data_active_object(const bContext *C)
938 {
939         return ctx_data_pointer_get(C, "active_object");
940 }
941
942 struct Base *CTX_data_active_base(const bContext *C)
943 {
944         return ctx_data_pointer_get(C, "active_base");
945 }
946
947 struct Object *CTX_data_edit_object(const bContext *C)
948 {
949         return ctx_data_pointer_get(C, "edit_object");
950 }
951
952 struct Image *CTX_data_edit_image(const bContext *C)
953 {
954         return ctx_data_pointer_get(C, "edit_image");
955 }
956
957 struct Text *CTX_data_edit_text(const bContext *C)
958 {
959         return ctx_data_pointer_get(C, "edit_text");
960 }
961
962 struct MovieClip *CTX_data_edit_movieclip(const bContext *C)
963 {
964         return ctx_data_pointer_get(C, "edit_movieclip");
965 }
966
967 struct EditBone *CTX_data_active_bone(const bContext *C)
968 {
969         return ctx_data_pointer_get(C, "active_bone");
970 }
971
972 int CTX_data_selected_bones(const bContext *C, ListBase *list)
973 {
974         return ctx_data_collection_get(C, "selected_bones", list);
975 }
976
977 int CTX_data_selected_editable_bones(const bContext *C, ListBase *list)
978 {
979         return ctx_data_collection_get(C, "selected_editable_bones", list);
980 }
981
982 int CTX_data_visible_bones(const bContext *C, ListBase *list)
983 {
984         return ctx_data_collection_get(C, "visible_bones", list);
985 }
986
987 int CTX_data_editable_bones(const bContext *C, ListBase *list)
988 {
989         return ctx_data_collection_get(C, "editable_bones", list);
990 }
991
992 struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C)
993 {
994         return ctx_data_pointer_get(C, "active_pose_bone");
995 }
996
997 int CTX_data_selected_pose_bones(const bContext *C, ListBase *list)
998 {
999         return ctx_data_collection_get(C, "selected_pose_bones", list);
1000 }
1001
1002 int CTX_data_visible_pose_bones(const bContext *C, ListBase *list)
1003 {
1004         return ctx_data_collection_get(C, "visible_pose_bones", list);
1005 }
1006