/** * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * * Contributor(s): Blender Foundation (2008). * * ***** END GPL LICENSE BLOCK ***** */ #include "MEM_guardedalloc.h" #include "DNA_ID.h" #include "DNA_listBase.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_view3d_types.h" #include "DNA_windowmanager_types.h" #include "RNA_access.h" #include "BLI_listbase.h" #include "BLI_string.h" #include "BKE_context.h" #include "BKE_main.h" #include "BKE_screen.h" #include /* struct */ struct bContext { int thread; /* windowmanager context */ struct { struct wmWindowManager *manager; struct wmWindow *window; struct bScreen *screen; struct ScrArea *area; struct ARegion *region; struct ARegion *menu; struct bContextStore *store; } wm; /* data context */ struct { struct Main *main; struct Scene *scene; int recursion; } data; /* data evaluation */ struct { int render; } eval; }; /* context */ bContext *CTX_create() { bContext *C; C= MEM_callocN(sizeof(bContext), "bContext"); return C; } bContext *CTX_copy(const bContext *C) { bContext *newC= MEM_dupallocN((void*)C); return newC; } void CTX_free(bContext *C) { MEM_freeN(C); } /* store */ bContextStore *CTX_store_add(ListBase *contexts, char *name, PointerRNA *ptr) { bContextStoreEntry *entry; bContextStore *ctx, *lastctx; /* ensure we have a context to put the entry in, if it was already used * we have to copy the context to ensure */ ctx= contexts->last; if(!ctx || ctx->used) { if(ctx) { lastctx= ctx; ctx= MEM_dupallocN(lastctx); BLI_duplicatelist(&ctx->entries, &lastctx->entries); } else ctx= MEM_callocN(sizeof(bContextStore), "bContextStore"); BLI_addtail(contexts, ctx); } entry= MEM_callocN(sizeof(bContextStoreEntry), "bContextStoreEntry"); BLI_strncpy(entry->name, name, sizeof(entry->name)); entry->ptr= *ptr; BLI_addtail(&ctx->entries, entry); return ctx; } void CTX_store_set(bContext *C, bContextStore *store) { C->wm.store= store; } bContextStore *CTX_store_copy(bContextStore *store) { bContextStore *ctx; ctx= MEM_dupallocN(store); BLI_duplicatelist(&ctx->entries, &store->entries); return ctx; } void CTX_store_free(bContextStore *store) { BLI_freelistN(&store->entries); MEM_freeN(store); } void CTX_store_free_list(ListBase *contexts) { bContextStore *ctx; while((ctx= contexts->first)) { BLI_remlink(contexts, ctx); CTX_store_free(ctx); } } /* window manager context */ wmWindowManager *CTX_wm_manager(const bContext *C) { return C->wm.manager; } wmWindow *CTX_wm_window(const bContext *C) { return C->wm.window; } bScreen *CTX_wm_screen(const bContext *C) { return C->wm.screen; } ScrArea *CTX_wm_area(const bContext *C) { return C->wm.area; } SpaceLink *CTX_wm_space_data(const bContext *C) { return (C->wm.area)? C->wm.area->spacedata.first: NULL; } ARegion *CTX_wm_region(const bContext *C) { return C->wm.region; } void *CTX_wm_region_data(const bContext *C) { return (C->wm.region)? C->wm.region->regiondata: NULL; } struct ARegion *CTX_wm_menu(const bContext *C) { return C->wm.menu; } View3D *CTX_wm_view3d(const bContext *C) { if(C->wm.area && C->wm.area->spacetype==SPACE_VIEW3D) return C->wm.area->spacedata.first; return NULL; } RegionView3D *CTX_wm_region_view3d(const bContext *C) { if(C->wm.area && C->wm.area->spacetype==SPACE_VIEW3D) if(C->wm.region) return C->wm.region->regiondata; return NULL; } struct SpaceText *CTX_wm_space_text(const bContext *C) { if(C->wm.area && C->wm.area->spacetype==SPACE_TEXT) return C->wm.area->spacedata.first; return NULL; } struct SpaceImage *CTX_wm_space_image(const bContext *C) { if(C->wm.area && C->wm.area->spacetype==SPACE_IMAGE) return C->wm.area->spacedata.first; return NULL; } void CTX_wm_manager_set(bContext *C, wmWindowManager *wm) { C->wm.manager= wm; C->wm.window= NULL; C->wm.screen= NULL; C->wm.area= NULL; C->wm.region= NULL; } void CTX_wm_window_set(bContext *C, wmWindow *win) { C->wm.window= win; C->wm.screen= (win)? win->screen: NULL; C->data.scene= (C->wm.screen)? C->wm.screen->scene: NULL; C->wm.area= NULL; C->wm.region= NULL; } void CTX_wm_screen_set(bContext *C, bScreen *screen) { C->wm.screen= screen; C->data.scene= (C->wm.screen)? C->wm.screen->scene: NULL; C->wm.area= NULL; C->wm.region= NULL; } void CTX_wm_area_set(bContext *C, ScrArea *area) { C->wm.area= area; C->wm.region= NULL; } void CTX_wm_region_set(bContext *C, ARegion *region) { C->wm.region= region; } void CTX_wm_menu_set(bContext *C, ARegion *menu) { C->wm.menu= menu; } /* data context utility functions */ struct bContextDataResult { PointerRNA ptr; ListBase list; }; static int ctx_data_get(bContext *C, const char *member, bContextDataResult *result) { int done= 0, recursion= C->data.recursion; memset(result, 0, sizeof(bContextDataResult)); /* we check recursion to ensure that we do not get infinite * loops requesting data from ourselfs in a context callback */ if(!done && recursion < 1 && C->wm.store) { bContextStoreEntry *entry; C->data.recursion= 1; for(entry=C->wm.store->entries.first; entry; entry=entry->next) { if(strcmp(entry->name, member) == 0) { result->ptr= entry->ptr; done= 1; } } } if(!done && recursion < 2 && C->wm.region) { C->data.recursion= 2; if(C->wm.region->type && C->wm.region->type->context) done= C->wm.region->type->context(C, member, result); } if(!done && recursion < 3 && C->wm.area) { C->data.recursion= 3; if(C->wm.area->type && C->wm.area->type->context) done= C->wm.area->type->context(C, member, result); } if(!done && recursion < 4 && C->wm.screen) { bContextDataCallback cb= C->wm.screen->context; C->data.recursion= 4; if(cb) done= cb(C, member, result); } C->data.recursion= recursion; return done; } static void *ctx_data_pointer_get(const bContext *C, const char *member) { bContextDataResult result; if(ctx_data_get((bContext*)C, member, &result)) return result.ptr.data; return NULL; } static int ctx_data_pointer_verify(const bContext *C, const char *member, void **pointer) { bContextDataResult result; if(ctx_data_get((bContext*)C, member, &result)) { *pointer= result.ptr.data; return 1; } else { *pointer= NULL; return 0; } } static int ctx_data_collection_get(const bContext *C, const char *member, ListBase *list) { bContextDataResult result; if(ctx_data_get((bContext*)C, member, &result)) { *list= result.list; return 1; } return 0; } PointerRNA CTX_data_pointer_get(bContext *C, const char *member) { bContextDataResult result; if(ctx_data_get((bContext*)C, member, &result)) { return result.ptr; } else { PointerRNA ptr; memset(&ptr, 0, sizeof(ptr)); return ptr; } } ListBase CTX_data_collection_get(bContext *C, const char *member) { bContextDataResult result; if(ctx_data_get((bContext*)C, member, &result)) { return result.list; } else { ListBase list; memset(&list, 0, sizeof(list)); return list; } } void CTX_data_get(bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb) { bContextDataResult result; if(ctx_data_get((bContext*)C, member, &result)) { *r_ptr= result.ptr; *r_lb= result.list; } else { memset(r_ptr, 0, sizeof(*r_ptr)); memset(r_lb, 0, sizeof(*r_lb)); } } int CTX_data_equals(const char *member, const char *str) { return (strcmp(member, str) == 0); } void CTX_data_id_pointer_set(bContextDataResult *result, ID *id) { RNA_id_pointer_create(id, &result->ptr); } void CTX_data_pointer_set(bContextDataResult *result, ID *id, StructRNA *type, void *data) { RNA_pointer_create(id, type, data, &result->ptr); } void CTX_data_id_list_add(bContextDataResult *result, ID *id) { CollectionPointerLink *link; link= MEM_callocN(sizeof(CollectionPointerLink), "CTX_data_id_list_add"); RNA_id_pointer_create(id, &link->ptr); BLI_addtail(&result->list, link); } void CTX_data_list_add(bContextDataResult *result, ID *id, StructRNA *type, void *data) { CollectionPointerLink *link; link= MEM_callocN(sizeof(CollectionPointerLink), "CTX_data_list_add"); RNA_pointer_create(id, type, data, &link->ptr); BLI_addtail(&result->list, link); } int ctx_data_list_count(const bContext *C, int (*func)(const bContext*, ListBase*)) { ListBase list; if(func(C, &list)) { int tot= BLI_countlist(&list); BLI_freelistN(&list); return tot; } else return 0; } /* data context */ Main *CTX_data_main(const bContext *C) { Main *bmain; if(ctx_data_pointer_verify(C, "main", (void*)&bmain)) return bmain; else return C->data.main; } void CTX_data_main_set(bContext *C, Main *bmain) { C->data.main= bmain; } Scene *CTX_data_scene(const bContext *C) { Scene *scene; if(ctx_data_pointer_verify(C, "scene", (void*)&scene)) return scene; else return C->data.scene; } void CTX_data_scene_set(bContext *C, Scene *scene) { C->data.scene= scene; } ToolSettings *CTX_data_tool_settings(const bContext *C) { Scene *scene = CTX_data_scene(C); if(scene) return scene->toolsettings; else return NULL; } int CTX_data_selected_nodes(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_nodes", list); } int CTX_data_selected_editable_objects(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_editable_objects", list); } int CTX_data_selected_editable_bases(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_editable_bases", list); } int CTX_data_selected_objects(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_objects", list); } int CTX_data_selected_bases(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_bases", list); } int CTX_data_visible_objects(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "visible_objects", list); } int CTX_data_visible_bases(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "visible_bases", list); } struct Object *CTX_data_active_object(const bContext *C) { return ctx_data_pointer_get(C, "active_object"); } struct Base *CTX_data_active_base(const bContext *C) { return ctx_data_pointer_get(C, "active_base"); } struct Object *CTX_data_edit_object(const bContext *C) { return ctx_data_pointer_get(C, "edit_object"); } struct Image *CTX_data_edit_image(const bContext *C) { return ctx_data_pointer_get(C, "edit_image"); } struct Text *CTX_data_edit_text(const bContext *C) { return ctx_data_pointer_get(C, "edit_text"); } struct EditBone *CTX_data_active_bone(const bContext *C) { return ctx_data_pointer_get(C, "active_bone"); } int CTX_data_selected_bones(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_bones", list); } int CTX_data_selected_editable_bones(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_editable_bones", list); } int CTX_data_visible_bones(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "visible_bones", list); } int CTX_data_editable_bones(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "editable_bones", list); } struct bPoseChannel *CTX_data_active_pchan(const bContext *C) { return ctx_data_pointer_get(C, "active_pchan"); } int CTX_data_selected_pchans(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "selected_pchans", list); } int CTX_data_visible_pchans(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "visible_pchans", list); }