From 76c035bd11ac6dc07796566aa2ebce9acf799d68 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 23 Dec 2008 02:07:13 +0000 Subject: 2.5: Data Context * Worked out data context implementation more, now with initial context callbacks implemented for the screen and 3d view. * For collections, switch from iterators to simpler ListBase. Though that still means it uses LinkData* rather than the actual Object* for example, since those can only be part of one list. So I added a macro as well to make iteration easier when possible. CTX_DATA_BEGIN(C, Object*, ob, selected_objects) { printf("object name: %s\n", ob->id.name); } CTX_DATA_END; --- source/blender/blenkernel/BKE_context.h | 57 ++++++----- source/blender/blenkernel/BKE_screen.h | 5 +- source/blender/blenkernel/intern/context.c | 106 +++++++++++++++------ source/blender/editors/screen/screen_context.c | 73 ++++++++++++++ source/blender/editors/screen/screen_edit.c | 2 + source/blender/editors/screen/screen_intern.h | 3 + source/blender/editors/space_view3d/space_view3d.c | 43 +++++++++ source/blender/makesdna/DNA_screen_types.h | 1 + 8 files changed, 232 insertions(+), 58 deletions(-) create mode 100644 source/blender/editors/screen/screen_context.c (limited to 'source') diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 90f158cd714..e8bd72ac3f3 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -55,30 +55,10 @@ struct wmWindowManager; struct bContext; typedef struct bContext bContext; -struct bContextDataMember; -typedef struct bContextDataMember bContextDataMember; - -extern bContextDataMember CTX_DataMain; -extern bContextDataMember CTX_DataScene; -extern bContextDataMember CTX_DataObjects; -extern bContextDataMember CTX_DataEditObject; -extern bContextDataMember CTX_DataEditArmature; -extern bContextDataMember CTX_DataEditMesh; - -typedef struct bContextDataIterator { - void *data; - int valid; - - void (*begin)(bContext *C, struct bContextDataIterator *iter); - void (*next)(struct bContextDataIterator *iter); - void (*end)(struct bContextDataIterator *iter); - void *internal; -} bContextDataIterator; - -typedef struct bContextDataResult { - void *pointer; - bContextDataIterator iterator; -} bContextDataResult; +typedef void bContextDataMember; + +struct bContextDataResult; +typedef struct bContextDataResult bContextDataResult; typedef int (*bContextDataCallback)(const bContext *C, const bContextDataMember *member, bContextDataResult *result); @@ -124,7 +104,28 @@ void CTX_wm_area_set(bContext *C, struct ScrArea *win); void CTX_wm_region_set(bContext *C, struct ARegion *win); void CTX_wm_ui_block_set(bContext *C, struct uiBlock *block, bContextDataCallback cb); -/* Data Context */ +/* Data Context + + - note: listbases consist of LinkData items and must be + freed with BLI_freelistN! */ + +void CTX_data_pointer_set(bContextDataResult *result, void *data); +void CTX_data_list_add(bContextDataResult *result, void *data); + +#define CTX_DATA_BEGIN(C, Type, instance, member) \ + { \ + ListBase ctx_data_list; \ + LinkData *link; \ + CTX_data_##member(C, &ctx_data_list); \ + for(link=ctx_data_list.first; link; link=link->next) { \ + Type instance= link->data; + +#define CTX_DATA_END \ + } \ + BLI_freelistN(&ctx_data_list); \ + } + +/* Data Context Members */ struct Main *CTX_data_main(const bContext *C); struct Scene *CTX_data_scene(const bContext *C); @@ -133,7 +134,11 @@ struct ToolSettings *CTX_data_tool_settings(const bContext *C); void CTX_data_main_set(bContext *C, struct Main *bmain); void CTX_data_scene_set(bContext *C, struct Scene *bmain); -int CTX_data_objects(const bContext *C, bContextDataIterator *iter); +int CTX_data_selected_objects(const bContext *C, ListBase *list); +int CTX_data_selected_bases(const bContext *C, ListBase *list); + +struct Object *CTX_data_active_object(const bContext *C); +struct Base *CTX_data_active_base(const bContext *C); struct Object *CTX_data_edit_object(const bContext *C); struct EditMesh *CTX_data_edit_mesh(const bContext *C); diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 35bc40ded4c..60072ec2553 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -33,7 +33,6 @@ struct ARegion; struct bContext; -struct bContextDataMember; struct bContextDataResult; struct bScreen; struct ListBase; @@ -77,7 +76,7 @@ typedef struct SpaceType { void (*cursor)(struct wmWindow *win, struct ARegion *ar); /* return context data */ - int (*context)(const struct bContext *, const struct bContextDataMember *, struct bContextDataResult *); + int (*context)(const struct bContext *, const void *, struct bContextDataResult *); /* region type definitions */ ListBase regiontypes; @@ -111,7 +110,7 @@ typedef struct ARegionType { void (*keymap)(struct wmWindowManager *); /* return context data */ - int (*context)(const struct bContext *, const struct bContextDataMember *, struct bContextDataResult *); + int (*context)(const struct bContext *, const void *, struct bContextDataResult *); /* hardcoded constraints, smaller than these values region is not visible */ int minsizex, minsizey; diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index b8633d8618e..703bb4c2b00 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -35,6 +35,8 @@ #include "RNA_access.h" +#include "BLI_listbase.h" + #include "BKE_context.h" #include "BKE_main.h" #include "BKE_report.h" @@ -58,8 +60,6 @@ struct bContext { struct ARegion *region; struct uiBlock *block; - bContextDataCallback manager_cb; - bContextDataCallback window_cb; bContextDataCallback screen_cb; bContextDataCallback area_cb; bContextDataCallback region_cb; @@ -70,6 +70,8 @@ struct bContext { struct { struct Main *main; struct Scene *scene; + + int recursion; } data; /* data evaluation */ @@ -189,12 +191,14 @@ 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.screen_cb= (C->wm.screen)? C->wm.screen->context: 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.screen_cb= (C->wm.screen)? C->wm.screen->context: NULL; } void CTX_wm_area_set(bContext *C, ScrArea *area) @@ -223,32 +227,46 @@ struct bContextDataMember { int collection; }; -bContextDataMember CTX_DataMain = {&RNA_Main, "main", 0}; -bContextDataMember CTX_DataScene = {&RNA_Scene, "scene", 0}; +struct bContextDataResult { + void *pointer; + ListBase list; +}; -bContextDataMember CTX_DataObjects = {&RNA_Object, "objects", 1}; +static int ctx_data_get(bContext *C, const bContextDataMember *member, bContextDataResult *result) +{ + int done= 0, recursion= C->data.recursion; -bContextDataMember CTX_DataEditObject = {&RNA_Object, "edit_object", 0}; -bContextDataMember CTX_DataEditArmature = {NULL, "edit_armature", 0}; -bContextDataMember CTX_DataEditMesh = {NULL, "edit_mesh", 0}; + memset(result, 0, sizeof(bContextDataResult)); -static int ctx_data_get(const bContext *C, const bContextDataMember *member, bContextDataResult *result) -{ - if(C->wm.block_cb && C->wm.block_cb(C, member, result)) return 1; - if(C->wm.region_cb && C->wm.region_cb(C, member, result)) return 1; - if(C->wm.area_cb && C->wm.area_cb(C, member, result)) return 1; - if(C->wm.screen_cb && C->wm.screen_cb(C, member, result)) return 1; - if(C->wm.window_cb && C->wm.window_cb(C, member, result)) return 1; - if(C->wm.manager_cb && C->wm.manager_cb(C, member, result)) return 1; + /* 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.block_cb) { + C->data.recursion= 1; + done= C->wm.block_cb(C, member, result); + } + if(!done && recursion < 2 && C->wm.region_cb) { + C->data.recursion= 2; + done= C->wm.region_cb(C, member, result); + } + if(!done && recursion < 3 && C->wm.area_cb) { + C->data.recursion= 3; + done= C->wm.area_cb(C, member, result); + } + if(!done && recursion < 4 && C->wm.screen_cb) { + C->data.recursion= 4; + done= C->wm.screen_cb(C, member, result); + } - return 0; + C->data.recursion= recursion; + + return done; } static void *ctx_data_pointer_get(const bContext *C, const bContextDataMember *member) { bContextDataResult result; - if(ctx_data_get(C, member, &result)) + if(ctx_data_get((bContext*)C, member, &result)) return result.pointer; return NULL; @@ -258,7 +276,7 @@ static int ctx_data_pointer_verify(const bContext *C, const bContextDataMember * { bContextDataResult result; - if(ctx_data_get(C, member, &result)) { + if(ctx_data_get((bContext*)C, member, &result)) { *pointer= result.pointer; return 1; } @@ -268,25 +286,40 @@ static int ctx_data_pointer_verify(const bContext *C, const bContextDataMember * } } -static int ctx_data_collection_get(const bContext *C, const bContextDataMember *member, bContextDataIterator *iter) +static int ctx_data_collection_get(const bContext *C, const bContextDataMember *member, ListBase *list) { bContextDataResult result; - if(ctx_data_get(C, member, &result)) { - *iter= result.iterator; + if(ctx_data_get((bContext*)C, member, &result)) { + *list= result.list; return 1; } return 0; } +void CTX_data_pointer_set(bContextDataResult *result, void *data) +{ + result->pointer= data; +} + +void CTX_data_list_add(bContextDataResult *result, void *data) +{ + LinkData *link; + + link= MEM_callocN(sizeof(LinkData), "LinkData"); + link->data= data; + + BLI_addtail(&result->list, link); +} + /* data context */ Main *CTX_data_main(const bContext *C) { Main *bmain; - if(ctx_data_pointer_verify(C, &CTX_DataMain, (void*)&bmain)) + if(ctx_data_pointer_verify(C, CTX_data_main, (void*)&bmain)) return bmain; else return C->data.main; @@ -301,7 +334,7 @@ Scene *CTX_data_scene(const bContext *C) { Scene *scene; - if(ctx_data_pointer_verify(C, &CTX_DataScene, (void*)&scene)) + if(ctx_data_pointer_verify(C, CTX_data_scene, (void*)&scene)) return scene; else return C->data.scene; @@ -322,24 +355,39 @@ ToolSettings *CTX_data_tool_settings(const bContext *C) return NULL; } -int CTX_data_objects(const bContext *C, bContextDataIterator *iter) +int CTX_data_selected_objects(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, CTX_data_selected_objects, list); +} + +int CTX_data_selected_bases(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, CTX_data_selected_bases, list); +} + +struct Object *CTX_data_active_object(const bContext *C) +{ + return ctx_data_pointer_get(C, CTX_data_active_object); +} + +struct Base *CTX_data_active_base(const bContext *C) { - return ctx_data_collection_get(C, &CTX_DataObjects, iter); + return ctx_data_pointer_get(C, CTX_data_active_base); } struct Object *CTX_data_edit_object(const bContext *C) { - return ctx_data_pointer_get(C, &CTX_DataEditObject); + return ctx_data_pointer_get(C, CTX_data_edit_object); } struct EditMesh *CTX_data_edit_mesh(const bContext *C) { - return ctx_data_pointer_get(C, &CTX_DataEditMesh); + return ctx_data_pointer_get(C, CTX_data_edit_mesh); } ListBase *CTX_data_edit_armature(const bContext *C) { - return ctx_data_pointer_get(C, &CTX_DataEditArmature); + return ctx_data_pointer_get(C, CTX_data_edit_armature); } /* data evaluation */ diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c new file mode 100644 index 00000000000..7e6fc251086 --- /dev/null +++ b/source/blender/editors/screen/screen_context.c @@ -0,0 +1,73 @@ +/** + * $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) 2008 Blender Foundation. + * All rights reserved. + * + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include + +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" + +#include "BKE_context.h" +#include "BKE_utildefines.h" + +int ed_screen_context(const bContext *C, const bContextDataMember *member, bContextDataResult *result) +{ + bScreen *sc= CTX_wm_screen(C); + Scene *scene= sc->scene; + Base *base; + + if(member == CTX_data_scene) { + CTX_data_pointer_set(result, scene); + return 1; + } + else if(ELEM(member, CTX_data_selected_objects, &CTX_data_selected_bases)) { + for(base=scene->base.first; base; base=base->next) { + if((base->flag & SELECT) && (base->lay & scene->lay)) { + if(member == CTX_data_selected_objects) + CTX_data_list_add(result, base->object); + else + CTX_data_list_add(result, base); + } + } + + return 1; + } + else if(member == CTX_data_active_base) { + if(scene->basact) + CTX_data_pointer_set(result, scene->basact); + + return 1; + } + else if(member == CTX_data_active_object) { + if(scene->basact) + CTX_data_pointer_set(result, scene->basact->object); + + return 1; + } + + return 0; +} + diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index b298799f239..da0cb0b73c1 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1001,6 +1001,8 @@ void ED_screen_refresh(wmWindowManager *wm, wmWindow *win) if(G.f & G_DEBUG) printf("set screen\n"); win->screen->do_refresh= 0; + + win->screen->context= ed_screen_context; } /* file read, set all screens, ... */ diff --git a/source/blender/editors/screen/screen_intern.h b/source/blender/editors/screen/screen_intern.h index 3ccf3991236..a4da1e4813f 100644 --- a/source/blender/editors/screen/screen_intern.h +++ b/source/blender/editors/screen/screen_intern.h @@ -55,6 +55,9 @@ AZone *is_in_area_actionzone(ScrArea *sa, int x, int y); void ed_screen_set(bContext *C, bScreen *sc); void ed_screen_fullarea(bContext *C); +/* screen_context.c */ +void ed_screen_context(const bContext *C, const bContextDataMember *member, bContextDataResult *result); + #endif /* ED_SCREEN_INTERN_H */ diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 96116af1c06..4a754ee6ce0 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -44,6 +44,7 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_screen.h" +#include "BKE_utildefines.h" #include "ED_space_api.h" #include "ED_screen.h" @@ -228,6 +229,47 @@ static void view3d_header_area_draw(const bContext *C, ARegion *ar) UI_view2d_view_restore(C); } +static int view3d_context(const bContext *C, const bContextDataMember *member, bContextDataResult *result) +{ + View3D *v3d= (View3D*)CTX_wm_space_data(C); + Scene *scene= CTX_data_scene(C); + Base *base; + + if(ELEM(member, CTX_data_selected_objects, CTX_data_selected_bases)) { + for(base=scene->base.first; base; base=base->next) { + if((base->flag & SELECT) && (base->lay & v3d->lay)) { + if((base->object->restrictflag & OB_RESTRICT_VIEW)==0) { + if(member == CTX_data_selected_objects) + CTX_data_list_add(result, base->object); + else + CTX_data_list_add(result, base); + } + } + } + + return 1; + } + else if(member == CTX_data_active_base) { + if(scene->basact && (scene->basact->lay & v3d->lay)) + if((scene->basact->object->restrictflag & OB_RESTRICT_VIEW)==0) + CTX_data_pointer_set(result, scene->basact); + + return 1; + } + else if(member == CTX_data_active_object) { + if(scene->basact && (scene->basact->lay & v3d->lay)) + if((scene->basact->object->restrictflag & OB_RESTRICT_VIEW)==0) + CTX_data_pointer_set(result, scene->basact->object); + + return 1; + } + else if(member == CTX_data_edit_object) { + CTX_data_pointer_set(result, G.obedit); + return 1; + } + + return 0; +} /* only called once, from space/spacetypes.c */ void ED_spacetype_view3d(void) @@ -243,6 +285,7 @@ void ED_spacetype_view3d(void) st->duplicate= view3d_duplicate; st->operatortypes= view3d_operatortypes; st->keymap= view3d_keymap; + st->context= view3d_context; /* regions: main window */ art= MEM_callocN(sizeof(ARegionType), "spacetype time region"); diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index a15c57d6700..af8597ba54d 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -60,6 +60,7 @@ typedef struct bScreen { short subwinactive; /* active subwindow */ struct wmTimer *animtimer; /* if set, screen has timer handler added in window */ + void *context; /* context callback */ short handler[8]; /* similar to space handler */ } bScreen; -- cgit v1.2.3