Merging r46414 through r46455 from trunk into soc-2011-tomato
[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         bScreen *sc;
252         ScrArea *sa;
253         ARegion *ar;
254         int done = 0, recursion = C->data.recursion;
255         int ret = 0;
256
257         memset(result, 0, sizeof(bContextDataResult));
258 #ifdef WITH_PYTHON
259         if (CTX_py_dict_get(C)) {
260                 return BPY_context_member_get(C, member, result);
261 //              if (BPY_context_member_get(C, member, result))
262 //                      return 1;
263         }
264 #endif
265         /* we check recursion to ensure that we do not get infinite
266          * loops requesting data from ourselfs in a context callback */
267
268         /* Ok, this looks evil...
269          * if (ret) done= -(-ret | -done);
270          *
271          * Values in order of importance
272          * (0, -1, 1) - Where 1 is highest priority
273          * */
274         if (done != 1 && recursion < 1 && C->wm.store) {
275                 bContextStoreEntry *entry;
276
277                 C->data.recursion = 1;
278
279                 entry = BLI_rfindstring(&C->wm.store->entries, member, offsetof(bContextStoreEntry, name));
280                 if (entry) {
281                         result->ptr = entry->ptr;
282                         done = 1;
283                 }
284         }
285         if (done != 1 && recursion < 2 && (ar = CTX_wm_region(C))) {
286                 C->data.recursion = 2;
287                 if (ar->type && ar->type->context) {
288                         ret = ar->type->context(C, member, result);
289                         if (ret) done = -(-ret | -done);
290
291                 }
292         }
293         if (done != 1 && recursion < 3 && (sa = CTX_wm_area(C))) {
294                 C->data.recursion = 3;
295                 if (sa->type && sa->type->context) {
296                         ret = sa->type->context(C, member, result);
297                         if (ret) done = -(-ret | -done);
298                 }
299         }
300         if (done != 1 && recursion < 4 && (sc = CTX_wm_screen(C))) {
301                 bContextDataCallback cb = sc->context;
302                 C->data.recursion = 4;
303                 if (cb) {
304                         ret = cb(C, member, result);
305                         if (ret) done = -(-ret | -done);
306                 }
307         }
308
309         C->data.recursion = recursion;
310
311         return done;
312 }
313
314 static void *ctx_data_pointer_get(const bContext *C, const char *member)
315 {
316         bContextDataResult result;
317
318         if (C && ctx_data_get((bContext *)C, member, &result) == 1)
319                 return result.ptr.data;
320
321         return NULL;
322 }
323
324 static int ctx_data_pointer_verify(const bContext *C, const char *member, void **pointer)
325 {
326         bContextDataResult result;
327
328         /* if context is NULL, pointer must be NULL too and that is a valid return */
329         if (C == NULL) {
330                 *pointer = NULL;
331                 return 1;
332         }
333         else if (ctx_data_get((bContext *)C, member, &result) == 1) {
334                 *pointer = result.ptr.data;
335                 return 1;
336         }
337         else {
338                 *pointer = NULL;
339                 return 0;
340         }
341 }
342
343 static int ctx_data_collection_get(const bContext *C, const char *member, ListBase *list)
344 {
345         bContextDataResult result;
346
347         if (ctx_data_get((bContext *)C, member, &result) == 1) {
348                 *list = result.list;
349                 return 1;
350         }
351
352         list->first = NULL;
353         list->last = NULL;
354
355         return 0;
356 }
357
358 PointerRNA CTX_data_pointer_get(const bContext *C, const char *member)
359 {
360         bContextDataResult result;
361
362         if (ctx_data_get((bContext *)C, member, &result) == 1)
363                 return result.ptr;
364         else
365                 return PointerRNA_NULL;
366 }
367
368 PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
369 {
370         PointerRNA ptr = CTX_data_pointer_get(C, member);
371
372         if (ptr.data && RNA_struct_is_a(ptr.type, type))
373                 return ptr;
374         
375         return PointerRNA_NULL;
376 }
377
378 ListBase CTX_data_collection_get(const bContext *C, const char *member)
379 {
380         bContextDataResult result;
381
382         if (ctx_data_get((bContext *)C, member, &result) == 1) {
383                 return result.list;
384         }
385         else {
386                 ListBase list = {NULL, NULL};
387                 return list;
388         }
389 }
390
391 /* 1:found,  -1:found but not set,  0:not found */
392 int CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb, short *r_type)
393 {
394         bContextDataResult result;
395         int ret = ctx_data_get((bContext *)C, member, &result);
396
397         if (ret == 1) {
398                 *r_ptr = result.ptr;
399                 *r_lb = result.list;
400                 *r_type = result.type;
401         }
402         else {
403                 memset(r_ptr, 0, sizeof(*r_ptr));
404                 memset(r_lb, 0, sizeof(*r_lb));
405                 *r_type = 0;
406         }
407
408         return ret;
409 }
410
411 static void data_dir_add(ListBase *lb, const char *member)
412 {
413         LinkData *link;
414         
415         if (strcmp(member, "scene") == 0) /* exception */
416                 return;
417
418         if (BLI_findstring(lb, member, offsetof(LinkData, data)))
419                 return;
420         
421         link = MEM_callocN(sizeof(LinkData), "LinkData");
422         link->data = (void *)member;
423         BLI_addtail(lb, link);
424 }
425
426 ListBase CTX_data_dir_get(const bContext *C)
427 {
428         bContextDataResult result;
429         ListBase lb;
430         bScreen *sc;
431         ScrArea *sa;
432         ARegion *ar;
433         int a;
434
435         memset(&lb, 0, sizeof(lb));
436
437         if (C->wm.store) {
438                 bContextStoreEntry *entry;
439
440                 for (entry = C->wm.store->entries.first; entry; entry = entry->next)
441                         data_dir_add(&lb, entry->name);
442         }
443         if ((ar = CTX_wm_region(C)) && ar->type && ar->type->context) {
444                 memset(&result, 0, sizeof(result));
445                 ar->type->context(C, "", &result);
446
447                 if (result.dir)
448                         for (a = 0; result.dir[a]; a++)
449                                 data_dir_add(&lb, result.dir[a]);
450         }
451         if ((sa = CTX_wm_area(C)) && sa->type && sa->type->context) {
452                 memset(&result, 0, sizeof(result));
453                 sa->type->context(C, "", &result);
454
455                 if (result.dir)
456                         for (a = 0; result.dir[a]; a++)
457                                 data_dir_add(&lb, result.dir[a]);
458         }
459         if ((sc = CTX_wm_screen(C)) && sc->context) {
460                 bContextDataCallback cb = sc->context;
461                 memset(&result, 0, sizeof(result));
462                 cb(C, "", &result);
463
464                 if (result.dir)
465                         for (a = 0; result.dir[a]; a++)
466                                 data_dir_add(&lb, result.dir[a]);
467         }
468
469         return lb;
470 }
471
472 int CTX_data_equals(const char *member, const char *str)
473 {
474         return (strcmp(member, str) == 0);
475 }
476
477 int CTX_data_dir(const char *member)
478 {
479         return member[0] == '\0';
480 }
481
482 void CTX_data_id_pointer_set(bContextDataResult *result, ID *id)
483 {
484         RNA_id_pointer_create(id, &result->ptr);
485 }
486
487 void CTX_data_pointer_set(bContextDataResult *result, ID *id, StructRNA *type, void *data)
488 {
489         RNA_pointer_create(id, type, data, &result->ptr);
490 }
491
492 void CTX_data_id_list_add(bContextDataResult *result, ID *id)
493 {
494         CollectionPointerLink *link;
495
496         link = MEM_callocN(sizeof(CollectionPointerLink), "CTX_data_id_list_add");
497         RNA_id_pointer_create(id, &link->ptr);
498
499         BLI_addtail(&result->list, link);
500 }
501
502 void CTX_data_list_add(bContextDataResult *result, ID *id, StructRNA *type, void *data)
503 {
504         CollectionPointerLink *link;
505
506         link = MEM_callocN(sizeof(CollectionPointerLink), "CTX_data_list_add");
507         RNA_pointer_create(id, type, data, &link->ptr);
508
509         BLI_addtail(&result->list, link);
510 }
511
512 int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBase *))
513 {
514         ListBase list;
515
516         if (func(C, &list)) {
517                 int tot = BLI_countlist(&list);
518                 BLI_freelistN(&list);
519                 return tot;
520         }
521         else
522                 return 0;
523 }
524
525 void CTX_data_dir_set(bContextDataResult *result, const char **dir)
526 {
527         result->dir = dir;
528 }
529
530 void CTX_data_type_set(bContextDataResult *result, short type)
531 {
532         result->type = type;
533 }
534
535 short CTX_data_type_get(bContextDataResult *result)
536 {
537         return result->type;
538 }
539
540
541
542 /* window manager context */
543
544 wmWindowManager *CTX_wm_manager(const bContext *C)
545 {
546         return C->wm.manager;
547 }
548
549 wmWindow *CTX_wm_window(const bContext *C)
550 {
551         return ctx_wm_python_context_get(C, "window", C->wm.window);
552 }
553
554 bScreen *CTX_wm_screen(const bContext *C)
555 {
556         return ctx_wm_python_context_get(C, "screen", C->wm.screen);
557 }
558
559 ScrArea *CTX_wm_area(const bContext *C)
560 {
561         return ctx_wm_python_context_get(C, "area", C->wm.area);
562 }
563
564 SpaceLink *CTX_wm_space_data(const bContext *C)
565 {
566         ScrArea *sa = CTX_wm_area(C);
567         return (sa) ? sa->spacedata.first : NULL;
568 }
569
570 ARegion *CTX_wm_region(const bContext *C)
571 {
572         return ctx_wm_python_context_get(C, "region", C->wm.region);
573 }
574
575 void *CTX_wm_region_data(const bContext *C)
576 {
577         ARegion *ar = CTX_wm_region(C);
578         return (ar) ? ar->regiondata : NULL;
579 }
580
581 struct ARegion *CTX_wm_menu(const bContext *C)
582 {
583         return C->wm.menu;
584 }
585
586 struct ReportList *CTX_wm_reports(const bContext *C)
587 {
588         if (C->wm.manager)
589                 return &(C->wm.manager->reports);
590
591         return NULL;
592 }
593
594 View3D *CTX_wm_view3d(const bContext *C)
595 {
596         ScrArea *sa = CTX_wm_area(C);
597         if (sa && sa->spacetype == SPACE_VIEW3D)
598                 return sa->spacedata.first;
599         return NULL;
600 }
601
602 RegionView3D *CTX_wm_region_view3d(const bContext *C)
603 {
604         ScrArea *sa = CTX_wm_area(C);
605         ARegion *ar = CTX_wm_region(C);
606
607         if (sa && sa->spacetype == SPACE_VIEW3D)
608                 if (ar)
609                         return ar->regiondata;
610         return NULL;
611 }
612
613 struct SpaceText *CTX_wm_space_text(const bContext *C)
614 {
615         ScrArea *sa = CTX_wm_area(C);
616         if (sa && sa->spacetype == SPACE_TEXT)
617                 return sa->spacedata.first;
618         return NULL;
619 }
620
621 struct SpaceConsole *CTX_wm_space_console(const bContext *C)
622 {
623         ScrArea *sa = CTX_wm_area(C);
624         if (sa && sa->spacetype == SPACE_CONSOLE)
625                 return sa->spacedata.first;
626         return NULL;
627 }
628
629 struct SpaceImage *CTX_wm_space_image(const bContext *C)
630 {
631         ScrArea *sa = CTX_wm_area(C);
632         if (sa && sa->spacetype == SPACE_IMAGE)
633                 return sa->spacedata.first;
634         return NULL;
635 }
636
637 struct SpaceButs *CTX_wm_space_buts(const bContext *C)
638 {
639         ScrArea *sa = CTX_wm_area(C);
640         if (sa && sa->spacetype == SPACE_BUTS)
641                 return sa->spacedata.first;
642         return NULL;
643 }
644
645 struct SpaceFile *CTX_wm_space_file(const bContext *C)
646 {
647         ScrArea *sa = CTX_wm_area(C);
648         if (sa && sa->spacetype == SPACE_FILE)
649                 return sa->spacedata.first;
650         return NULL;
651 }
652
653 struct SpaceSeq *CTX_wm_space_seq(const bContext *C)
654 {
655         ScrArea *sa = CTX_wm_area(C);
656         if (sa && sa->spacetype == SPACE_SEQ)
657                 return sa->spacedata.first;
658         return NULL;
659 }
660
661 struct SpaceOops *CTX_wm_space_outliner(const bContext *C)
662 {
663         ScrArea *sa = CTX_wm_area(C);
664         if (sa && sa->spacetype == SPACE_OUTLINER)
665                 return sa->spacedata.first;
666         return NULL;
667 }
668
669 struct SpaceNla *CTX_wm_space_nla(const bContext *C)
670 {
671         ScrArea *sa = CTX_wm_area(C);
672         if (sa && sa->spacetype == SPACE_NLA)
673                 return sa->spacedata.first;
674         return NULL;
675 }
676
677 struct SpaceTime *CTX_wm_space_time(const bContext *C)
678 {
679         ScrArea *sa = CTX_wm_area(C);
680         if (sa && sa->spacetype == SPACE_TIME)
681                 return sa->spacedata.first;
682         return NULL;
683 }
684
685 struct SpaceNode *CTX_wm_space_node(const bContext *C)
686 {
687         ScrArea *sa = CTX_wm_area(C);
688         if (sa && sa->spacetype == SPACE_NODE)
689                 return sa->spacedata.first;
690         return NULL;
691 }
692
693 struct SpaceLogic *CTX_wm_space_logic(const bContext *C)
694 {
695         ScrArea *sa = CTX_wm_area(C);
696         if (sa && sa->spacetype == SPACE_LOGIC)
697                 return sa->spacedata.first;
698         return NULL;
699 }
700
701 struct SpaceIpo *CTX_wm_space_graph(const bContext *C)
702 {
703         ScrArea *sa = CTX_wm_area(C);
704         if (sa && sa->spacetype == SPACE_IPO)
705                 return sa->spacedata.first;
706         return NULL;
707 }
708
709 struct SpaceAction *CTX_wm_space_action(const bContext *C)
710 {
711         ScrArea *sa = CTX_wm_area(C);
712         if (sa && sa->spacetype == SPACE_ACTION)
713                 return sa->spacedata.first;
714         return NULL;
715 }
716
717 struct SpaceInfo *CTX_wm_space_info(const bContext *C)
718 {
719         ScrArea *sa = CTX_wm_area(C);
720         if (sa && sa->spacetype == SPACE_INFO)
721                 return sa->spacedata.first;
722         return NULL;
723 }
724
725 struct SpaceUserPref *CTX_wm_space_userpref(const bContext *C)
726 {
727         ScrArea *sa = CTX_wm_area(C);
728         if (sa && sa->spacetype == SPACE_USERPREF)
729                 return sa->spacedata.first;
730         return NULL;
731 }
732
733 struct SpaceClip *CTX_wm_space_clip(const bContext *C)
734 {
735         ScrArea *sa = CTX_wm_area(C);
736         if (sa && sa->spacetype == SPACE_CLIP)
737                 return sa->spacedata.first;
738         return NULL;
739 }
740
741 void CTX_wm_manager_set(bContext *C, wmWindowManager *wm)
742 {
743         C->wm.manager = wm;
744         C->wm.window = NULL;
745         C->wm.screen = NULL;
746         C->wm.area = NULL;
747         C->wm.region = NULL;
748 }
749
750 void CTX_wm_window_set(bContext *C, wmWindow *win)
751 {
752         C->wm.window = win;
753         C->wm.screen = (win) ? win->screen : NULL;
754         if (C->wm.screen)
755                 C->data.scene = C->wm.screen->scene;
756         C->wm.area = NULL;
757         C->wm.region = NULL;
758 }
759
760 void CTX_wm_screen_set(bContext *C, bScreen *screen)
761 {
762         C->wm.screen = screen;
763         if (C->wm.screen)
764                 C->data.scene = C->wm.screen->scene;
765         C->wm.area = NULL;
766         C->wm.region = NULL;
767 }
768
769 void CTX_wm_area_set(bContext *C, ScrArea *area)
770 {
771         C->wm.area = area;
772         C->wm.region = NULL;
773 }
774
775 void CTX_wm_region_set(bContext *C, ARegion *region)
776 {
777         C->wm.region = region;
778 }
779
780 void CTX_wm_menu_set(bContext *C, ARegion *menu)
781 {
782         C->wm.menu = menu;
783 }
784
785 void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
786 {
787         C->wm.operator_poll_msg = msg;
788 }
789
790 const char *CTX_wm_operator_poll_msg_get(bContext *C)
791 {
792         return C->wm.operator_poll_msg;
793 }
794
795 /* data context */
796
797 Main *CTX_data_main(const bContext *C)
798 {
799         Main *bmain;
800
801         if (ctx_data_pointer_verify(C, "blend_data", (void *)&bmain))
802                 return bmain;
803         else
804                 return C->data.main;
805 }
806
807 void CTX_data_main_set(bContext *C, Main *bmain)
808 {
809         C->data.main = bmain;
810 }
811
812 Scene *CTX_data_scene(const bContext *C)
813 {
814         Scene *scene;
815
816         if (ctx_data_pointer_verify(C, "scene", (void *)&scene))
817                 return scene;
818         else
819                 return C->data.scene;
820 }
821
822 int CTX_data_mode_enum(const bContext *C)
823 {
824         Object *obedit = CTX_data_edit_object(C);
825
826         if (obedit) {
827                 switch (obedit->type) {
828                         case OB_MESH:
829                                 return CTX_MODE_EDIT_MESH;
830                         case OB_CURVE:
831                                 return CTX_MODE_EDIT_CURVE;
832                         case OB_SURF:
833                                 return CTX_MODE_EDIT_SURFACE;
834                         case OB_FONT:
835                                 return CTX_MODE_EDIT_TEXT;
836                         case OB_ARMATURE:
837                                 return CTX_MODE_EDIT_ARMATURE;
838                         case OB_MBALL:
839                                 return CTX_MODE_EDIT_METABALL;
840                         case OB_LATTICE:
841                                 return CTX_MODE_EDIT_LATTICE;
842                 }
843         }
844         else {
845                 Object *ob = CTX_data_active_object(C);
846
847                 if (ob) {
848                         if (ob->mode & OB_MODE_POSE) return CTX_MODE_POSE;
849                         else if (ob->mode & OB_MODE_SCULPT) return CTX_MODE_SCULPT;
850                         else if (ob->mode & OB_MODE_WEIGHT_PAINT) return CTX_MODE_PAINT_WEIGHT;
851                         else if (ob->mode & OB_MODE_VERTEX_PAINT) return CTX_MODE_PAINT_VERTEX;
852                         else if (ob->mode & OB_MODE_TEXTURE_PAINT) return CTX_MODE_PAINT_TEXTURE;
853                         else if (ob->mode & OB_MODE_PARTICLE_EDIT) return CTX_MODE_PARTICLE;
854                 }
855         }
856
857         return CTX_MODE_OBJECT;
858 }
859
860
861 /* would prefer if we can use the enum version below over this one - Campbell */
862 /* must be aligned with above enum  */
863 static const char *data_mode_strings[] = {
864         "mesh_edit",
865         "curve_edit",
866         "surface_edit",
867         "text_edit",
868         "armature_edit",
869         "mball_edit",
870         "lattice_edit",
871         "posemode",
872         "sculpt_mode",
873         "weightpaint",
874         "vertexpaint",
875         "imagepaint",
876         "particlemode",
877         "objectmode",
878         NULL
879 };
880 const char *CTX_data_mode_string(const bContext *C)
881 {
882         return data_mode_strings[CTX_data_mode_enum(C)];
883 }
884
885 void CTX_data_scene_set(bContext *C, Scene *scene)
886 {
887         C->data.scene = scene;
888 }
889
890 ToolSettings *CTX_data_tool_settings(const bContext *C)
891 {
892         Scene *scene = CTX_data_scene(C);
893
894         if (scene)
895                 return scene->toolsettings;
896         else
897                 return NULL;
898 }
899
900 int CTX_data_selected_nodes(const bContext *C, ListBase *list)
901 {
902         return ctx_data_collection_get(C, "selected_nodes", list);
903 }
904
905 int CTX_data_selected_editable_objects(const bContext *C, ListBase *list)
906 {
907         return ctx_data_collection_get(C, "selected_editable_objects", list);
908 }
909
910 int CTX_data_selected_editable_bases(const bContext *C, ListBase *list)
911 {
912         return ctx_data_collection_get(C, "selected_editable_bases", list);
913 }
914
915 int CTX_data_selected_objects(const bContext *C, ListBase *list)
916 {
917         return ctx_data_collection_get(C, "selected_objects", list);
918 }
919
920 int CTX_data_selected_bases(const bContext *C, ListBase *list)
921 {
922         return ctx_data_collection_get(C, "selected_bases", list);
923 }
924
925 int CTX_data_visible_objects(const bContext *C, ListBase *list)
926 {
927         return ctx_data_collection_get(C, "visible_objects", list);
928 }
929
930 int CTX_data_visible_bases(const bContext *C, ListBase *list)
931 {
932         return ctx_data_collection_get(C, "visible_bases", list);
933 }
934
935 int CTX_data_selectable_objects(const bContext *C, ListBase *list)
936 {
937         return ctx_data_collection_get(C, "selectable_objects", list);
938 }
939
940 int CTX_data_selectable_bases(const bContext *C, ListBase *list)
941 {
942         return ctx_data_collection_get(C, "selectable_bases", list);
943 }
944
945 struct Object *CTX_data_active_object(const bContext *C)
946 {
947         return ctx_data_pointer_get(C, "active_object");
948 }
949
950 struct Base *CTX_data_active_base(const bContext *C)
951 {
952         return ctx_data_pointer_get(C, "active_base");
953 }
954
955 struct Object *CTX_data_edit_object(const bContext *C)
956 {
957         return ctx_data_pointer_get(C, "edit_object");
958 }
959
960 struct Image *CTX_data_edit_image(const bContext *C)
961 {
962         return ctx_data_pointer_get(C, "edit_image");
963 }
964
965 struct Text *CTX_data_edit_text(const bContext *C)
966 {
967         return ctx_data_pointer_get(C, "edit_text");
968 }
969
970 struct MovieClip *CTX_data_edit_movieclip(const bContext *C)
971 {
972         return ctx_data_pointer_get(C, "edit_movieclip");
973 }
974
975 struct Mask *CTX_data_edit_mask(const bContext *C)
976 {
977         return ctx_data_pointer_get(C, "edit_mask");
978 }
979
980 struct EditBone *CTX_data_active_bone(const bContext *C)
981 {
982         return ctx_data_pointer_get(C, "active_bone");
983 }
984
985 int CTX_data_selected_bones(const bContext *C, ListBase *list)
986 {
987         return ctx_data_collection_get(C, "selected_bones", list);
988 }
989
990 int CTX_data_selected_editable_bones(const bContext *C, ListBase *list)
991 {
992         return ctx_data_collection_get(C, "selected_editable_bones", list);
993 }
994
995 int CTX_data_visible_bones(const bContext *C, ListBase *list)
996 {
997         return ctx_data_collection_get(C, "visible_bones", list);
998 }
999
1000 int CTX_data_editable_bones(const bContext *C, ListBase *list)
1001 {
1002         return ctx_data_collection_get(C, "editable_bones", list);
1003 }
1004
1005 struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C)
1006 {
1007         return ctx_data_pointer_get(C, "active_pose_bone");
1008 }
1009
1010 int CTX_data_selected_pose_bones(const bContext *C, ListBase *list)
1011 {
1012         return ctx_data_collection_get(C, "selected_pose_bones", list);
1013 }
1014
1015 int CTX_data_visible_pose_bones(const bContext *C, ListBase *list)
1016 {
1017         return ctx_data_collection_get(C, "visible_pose_bones", list);
1018 }
1019