diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index d2bed9f7faa..23862c5c840 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -22,6 +22,17 @@ StructRNA = bpy.types.Struct.__bases__[0] # StructRNA = bpy.types.Struct +class Context(StructRNA): + + def copy(self): + new_context = {} + for item in dir(self): + if item not in StructRNA.__dict__ and item != "id_data": + new_context[item] = getattr(self, item) + + return new_context + + class Object(bpy.types.ID): def _get_children(self): diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index feba39ee11d..7f64538b10d 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -174,7 +174,7 @@ PointerRNA CTX_data_pointer_get(const bContext *C, const char *member); PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type); ListBase CTX_data_collection_get(const bContext *C, const char *member); ListBase CTX_data_dir_get(const bContext *C); -void CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb); +int CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb); void CTX_data_id_pointer_set(bContextDataResult *result, struct ID *id); void CTX_data_pointer_set(bContextDataResult *result, struct ID *id, StructRNA *type, void *data); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 7f2872c0797..1cd0e6cd677 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -408,6 +408,7 @@ struct bContextDataResult { static int ctx_data_get(bContext *C, const char *member, bContextDataResult *result) { int done= 0, recursion= C->data.recursion; + int ret= 0; memset(result, 0, sizeof(bContextDataResult)); @@ -417,7 +418,14 @@ static int ctx_data_get(bContext *C, const char *member, bContextDataResult *res /* 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) { + + /* Ok, this looks evil... + * if(ret) done= -(-ret | -done); + * + * Values in order of importance + * (0, -1, 1) - Where 1 is highest priority + * */ + if(done!=1 && recursion < 1 && C->wm.store) { bContextStoreEntry *entry; C->data.recursion= 1; @@ -429,21 +437,28 @@ static int ctx_data_get(bContext *C, const char *member, bContextDataResult *res } } } - if(!done && recursion < 2 && C->wm.region) { + if(done!=1 && 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(C->wm.region->type && C->wm.region->type->context) { + ret = C->wm.region->type->context(C, member, result); + if(ret) done= -(-ret | -done); + + } } - if(!done && recursion < 3 && C->wm.area) { + if(done!=1 && 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(C->wm.area->type && C->wm.area->type->context) { + ret = C->wm.area->type->context(C, member, result); + if(ret) done= -(-ret | -done); + } } - if(!done && recursion < 4 && C->wm.screen) { + if(done!=1 && recursion < 4 && C->wm.screen) { bContextDataCallback cb= C->wm.screen->context; C->data.recursion= 4; - if(cb) - done= cb(C, member, result); + if(cb) { + ret = cb(C, member, result); + if(ret) done= -(-ret | -done); + } } C->data.recursion= recursion; @@ -455,7 +470,7 @@ static void *ctx_data_pointer_get(const bContext *C, const char *member) { bContextDataResult result; - if(C && ctx_data_get((bContext*)C, member, &result)) + if(C && ctx_data_get((bContext*)C, member, &result)==1) return result.ptr.data; return NULL; @@ -465,7 +480,7 @@ static int ctx_data_pointer_verify(const bContext *C, const char *member, void * { bContextDataResult result; - if(ctx_data_get((bContext*)C, member, &result)) { + if(ctx_data_get((bContext*)C, member, &result)==1) { *pointer= result.ptr.data; return 1; } @@ -479,7 +494,7 @@ static int ctx_data_collection_get(const bContext *C, const char *member, ListBa { bContextDataResult result; - if(ctx_data_get((bContext*)C, member, &result)) { + if(ctx_data_get((bContext*)C, member, &result)==1) { *list= result.list; return 1; } @@ -494,7 +509,7 @@ PointerRNA CTX_data_pointer_get(const bContext *C, const char *member) { bContextDataResult result; - if(ctx_data_get((bContext*)C, member, &result)) + if(ctx_data_get((bContext*)C, member, &result)==1) return result.ptr; else return PointerRNA_NULL; @@ -514,7 +529,7 @@ ListBase CTX_data_collection_get(const bContext *C, const char *member) { bContextDataResult result; - if(ctx_data_get((bContext*)C, member, &result)) { + if(ctx_data_get((bContext*)C, member, &result)==1) { return result.list; } else { @@ -524,11 +539,13 @@ ListBase CTX_data_collection_get(const bContext *C, const char *member) } } -void CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb) +/* 1:found, -1:found but not set, 0:not found */ +int CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, ListBase *r_lb) { bContextDataResult result; + int ret= ctx_data_get((bContext*)C, member, &result); - if(ctx_data_get((bContext*)C, member, &result)) { + if(ret==1) { *r_ptr= result.ptr; *r_lb= result.list; } @@ -536,6 +553,8 @@ void CTX_data_get(const bContext *C, const char *member, PointerRNA *r_ptr, List memset(r_ptr, 0, sizeof(*r_ptr)); memset(r_lb, 0, sizeof(*r_lb)); } + + return ret; } static void data_dir_add(ListBase *lb, const char *member) diff --git a/source/blender/editors/screen/screen_context.c b/source/blender/editors/screen/screen_context.c index 31827e1b9c0..1a1def70717 100644 --- a/source/blender/editors/screen/screen_context.c +++ b/source/blender/editors/screen/screen_context.c @@ -67,7 +67,7 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult "visible_pchans", "selected_pchans", "active_bone", "active_pchan", "active_base", "active_object", "edit_object", "sculpt_object", "vertex_paint_object", "weight_paint_object", - "texture_paint_object", "brush", "particle_edit_object", NULL}; + "texture_paint_object", "particle_edit_object", NULL}; CTX_data_dir_set(result, dir); return 1; @@ -304,7 +304,10 @@ int ed_screen_context(const bContext *C, const char *member, bContextDataResult return 1; } + else { + return 0; /* not found */ + } - return 0; + return -1; /* found but not available */ } diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 71d5b59f253..0e2769a3557 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -707,8 +707,11 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r set_pointer_type(path, result, &RNA_Brush); return 1; } + else { + return 0; /* not found */ + } - return 0; + return -1; /* found but not available */ } /************************* Drawing the Path ************************/ diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 4a9042aa31c..5bde6e029e4 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -747,7 +747,11 @@ static int view3d_context(const bContext *C, const char *member, bContextDataRes return 1; } - return 0; + else { + return 0; /* not found */ + } + + return -1; /* found but not available */ } /* only called once, from space/spacetypes.c */ diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index bcc12eb4502..c06931feedb 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -1376,27 +1376,38 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname ) else if (self->ptr.type == &RNA_Context) { PointerRNA newptr; ListBase newlb; + int done; - CTX_data_get(self->ptr.data, name, &newptr, &newlb); + done= CTX_data_get(self->ptr.data, name, &newptr, &newlb); - if (newptr.data) { - ret = pyrna_struct_CreatePyObject(&newptr); - } - else if (newlb.first) { - CollectionPointerLink *link; - PyObject *linkptr; + if(done==1) { /* found */ + if (newptr.data) { + ret = pyrna_struct_CreatePyObject(&newptr); + } + else if (newlb.first) { + CollectionPointerLink *link; + PyObject *linkptr; - ret = PyList_New(0); + ret = PyList_New(0); - for(link=newlb.first; link; link=link->next) { - linkptr= pyrna_struct_CreatePyObject(&link->ptr); - PyList_Append(ret, linkptr); - Py_DECREF(linkptr); + for(link=newlb.first; link; link=link->next) { + linkptr= pyrna_struct_CreatePyObject(&link->ptr); + PyList_Append(ret, linkptr); + Py_DECREF(linkptr); + } + } + else { + ret = Py_None; + Py_INCREF(ret); } } - else { - ret = Py_None; - Py_INCREF(ret); + else if (done==-1) { /* found but not set */ + ret = Py_None; + Py_INCREF(ret); + } + else { /* not found in the context */ + /* lookup the subclass. raise an error if its not found */ + ret = PyObject_GenericGetAttr((PyObject *)self, pyname); } BLI_freelistN(&newlb); @@ -1405,10 +1416,11 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname ) if(self->ptr.id.data) { PointerRNA id_ptr; RNA_id_pointer_create((ID *)self->ptr.id.data, &id_ptr); - return pyrna_struct_CreatePyObject(&id_ptr); + ret = pyrna_struct_CreatePyObject(&id_ptr); } else { - Py_RETURN_NONE; + ret = Py_None; + Py_INCREF(ret); } } else {