2.5: Data Context
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 23 Dec 2008 02:07:13 +0000 (02:07 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Tue, 23 Dec 2008 02:07:13 +0000 (02:07 +0000)
* 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
source/blender/blenkernel/BKE_screen.h
source/blender/blenkernel/intern/context.c
source/blender/editors/screen/screen_context.c [new file with mode: 0644]
source/blender/editors/screen/screen_edit.c
source/blender/editors/screen/screen_intern.h
source/blender/editors/space_view3d/space_view3d.c
source/blender/makesdna/DNA_screen_types.h

index 90f158cd71498f5dca28c62139679870368c3fa1..e8bd72ac3f3a0ef399cba2d69ed25596b2049991 100644 (file)
@@ -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);
index 35bc40ded4c35b6770b074f978b91f380fb78043..60072ec2553ac0eea38f06d2e9e7316a28fb29e4 100644 (file)
@@ -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;
index b8633d8618e47632e13e5df22cdb505aa0718e46..703bb4c2b0000413cb3ffe634adf568080920832 100644 (file)
@@ -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 (file)
index 0000000..7e6fc25
--- /dev/null
@@ -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 <stdlib.h>
+
+#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;
+}
+
index b298799f2394b88780cc40f4bad760b315c9db8f..da0cb0b73c12ebb9a8bb745943bde9e95f5c8138 100644 (file)
@@ -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, ... */
index 3ccf3991236e9495c8e754c7afb20eb1e1496f85..a4da1e4813f9ddd6f81227969c252bb84552158d 100644 (file)
@@ -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 */
 
 
index 96116af1c06b6d6b59c8542c37f4e4fa8b99cb12..4a754ee6ce0e410dd75010054b2a3c85c368a583 100644 (file)
@@ -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");
index a15c57d67000c901a3144915af601ecab83a8e27..af8597ba54d3ccedb254f90e96a1e83b08e9aef1 100644 (file)
@@ -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;