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