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;
This commit is contained in:
@@ -55,30 +55,10 @@ struct wmWindowManager;
|
||||
struct bContext;
|
||||
typedef struct bContext bContext;
|
||||
|
||||
struct bContextDataMember;
|
||||
typedef struct bContextDataMember bContextDataMember;
|
||||
typedef void 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;
|
||||
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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
|
||||
bContextDataMember CTX_DataEditObject = {&RNA_Object, "edit_object", 0};
|
||||
bContextDataMember CTX_DataEditArmature = {NULL, "edit_armature", 0};
|
||||
bContextDataMember CTX_DataEditMesh = {NULL, "edit_mesh", 0};
|
||||
|
||||
static int ctx_data_get(const bContext *C, const bContextDataMember *member, bContextDataResult *result)
|
||||
static int ctx_data_get(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;
|
||||
int done= 0, recursion= C->data.recursion;
|
||||
|
||||
return 0;
|
||||
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.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);
|
||||
}
|
||||
|
||||
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_DataObjects, iter);
|
||||
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_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 */
|
||||
|
||||
73
source/blender/editors/screen/screen_context.c
Normal file
73
source/blender/editors/screen/screen_context.c
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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, ... */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user