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