diff options
author | Campbell Barton <ideasman42@gmail.com> | 2009-11-11 19:28:53 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2009-11-11 19:28:53 +0300 |
commit | bc6190f3e370d21aff0bd9d96fd43d92382c6466 (patch) | |
tree | 94bdbadbeb908085e86fd73b447df1ec1ed05858 /source | |
parent | f24392805515416bdba35f531457183e67ef274c (diff) |
python api for collection add()/remove()
Added a group example
C = bpy.context
ob = C.active_object
bpy.data.groups[0].objects.add(ob)
- add_to_group and rem_from_group now take optional scene and base flags and deal with updating the object & base flags
- operators that add objects to groups were setting ob->recalc= OB_RECALC_OB; looks like its not needed.
- previously add() ignored python args, now add and remove are called like any other FunctionRNA from python.
- made the pyrna api use tp_getset's for collestions active/add()/remove()
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_group.h | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/group.c | 51 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 2 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 2 | ||||
-rw-r--r-- | source/blender/editors/object/object_add.c | 3 | ||||
-rw-r--r-- | source/blender/editors/object/object_group.c | 43 | ||||
-rw-r--r-- | source/blender/makesrna/RNA_access.h | 3 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_access.c | 25 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_group.c | 52 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.c | 194 | ||||
-rw-r--r-- | source/blender/python/intern/bpy_rna.h | 8 |
11 files changed, 253 insertions, 134 deletions
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h index b66ddf13527..877e09b037f 100644 --- a/source/blender/blenkernel/BKE_group.h +++ b/source/blender/blenkernel/BKE_group.h @@ -42,8 +42,8 @@ void free_group(struct Group *group); void unlink_group(struct Group *group); struct Group *add_group(char *name); struct Group *copy_group(struct Group *group); -void add_to_group(struct Group *group, struct Object *ob); -int rem_from_group(struct Group *group, struct Object *ob); +int add_to_group(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); +int rem_from_group(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); struct Group *find_group(struct Object *ob, struct Group *group); int object_in_group(struct Object *ob, struct Group *group); int group_is_animated(struct Object *parent, struct Group *group); diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 6bb47bc0f0f..77bf5859385 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -95,7 +95,7 @@ void unlink_group(Group *group) /* ensure objects are not in this group */ for(; base; base= base->next) { - if(rem_from_group(group, base->object) && find_group(base->object, NULL)==NULL) { + if(rem_from_group(group, base->object, sce, base) && find_group(base->object, NULL)==NULL) { base->object->flag &= ~OB_FROMGROUP; base->flag &= ~OB_FROMGROUP; } @@ -153,15 +153,15 @@ Group *copy_group(Group *group) } /* external */ -void add_to_group(Group *group, Object *ob) +static int add_to_group_internal(Group *group, Object *ob) { GroupObject *go; - if(group==NULL || ob==NULL) return; + if(group==NULL || ob==NULL) return 0; /* check if the object has been added already */ for(go= group->gobject.first; go; go= go->next) { - if(go->ob==ob) return; + if(go->ob==ob) return 0; } go= MEM_callocN(sizeof(GroupObject), "groupobject"); @@ -169,10 +169,31 @@ void add_to_group(Group *group, Object *ob) go->ob= ob; + return 1; +} + +int add_to_group(Group *group, Object *object, Scene *scene, Base *base) +{ + if(add_to_group_internal(group, object)) { + if((object->flag & OB_FROMGROUP)==0) { + + if(scene && base==NULL) + base= object_in_scene(object, scene); + + object->flag |= OB_FROMGROUP; + + if(base) + base->flag |= OB_FROMGROUP; + } + return 1; + } + else { + return 0; + } } /* also used for ob==NULL */ -int rem_from_group(Group *group, Object *ob) +static int rem_from_group_internal(Group *group, Object *ob) { GroupObject *go, *gon; int removed = 0; @@ -192,6 +213,26 @@ int rem_from_group(Group *group, Object *ob) return removed; } +int rem_from_group(Group *group, Object *object, Scene *scene, Base *base) +{ + if(rem_from_group_internal(group, object)) { + + if(find_group(object, NULL) == NULL) { + if(scene && base==NULL) + base= object_in_scene(object, scene); + + object->flag &= ~OB_FROMGROUP; + + if(base) + base->flag &= ~OB_FROMGROUP; + } + return 1; + } + else { + return 0; + } +} + int object_in_group(Object *ob, Group *group) { GroupObject *go; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index f363b7d9a0a..078ff9d6eeb 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -622,7 +622,7 @@ void unlink_object(Scene *scene, Object *ob) /* groups */ group= G.main->group.first; while(group) { - rem_from_group(group, ob); + rem_from_group(group, ob, NULL, NULL); group= group->id.next; } diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 4f63fdf0737..83899473cb4 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -5261,7 +5261,7 @@ static void lib_link_group(FileData *fd, Main *main) go= go->next; } if(add_us) group->id.us++; - rem_from_group(group, NULL); /* removes NULL entries */ + rem_from_group(group, NULL, NULL, NULL); /* removes NULL entries */ } group= group->id.next; } diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 61377d76c56..e58170ebab6 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1262,9 +1262,8 @@ static Base *object_add_duplicate_internal(Scene *scene, Base *base, int dupflag Group *group; for(group= G.main->group.first; group; group= group->id.next) { if(object_in_group(ob, group)) - add_to_group(group, obn); + add_to_group(group, obn, scene, basen); } - obn->flag |= OB_FROMGROUP; /* this flag is unset with copy_object() */ } /* duplicates using userflags */ diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c index ec8409e9aa1..1e5b93aa6dc 100644 --- a/source/blender/editors/object/object_group.c +++ b/source/blender/editors/object/object_group.c @@ -60,7 +60,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op) { Scene *scene= CTX_data_scene(C); - Object *ob= OBACT, *obt; + Object *ob= OBACT; Group *group; int ok = 0; @@ -73,11 +73,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op) if(object_in_group(ob, group)) { /* Assign groups to selected objects */ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { - obt= base->object; - add_to_group(group, obt); - obt->flag |= OB_FROMGROUP; - base->flag |= OB_FROMGROUP; - base->object->recalc= OB_RECALC_OB; + add_to_group(group, base->object, scene, base); ok = 1; } CTX_DATA_END; @@ -110,7 +106,7 @@ void GROUP_OT_objects_add_active(wmOperatorType *ot) static int objects_remove_active_exec(bContext *C, wmOperator *op) { Scene *scene= CTX_data_scene(C); - Object *ob= OBACT, *obt; + Object *ob= OBACT; Group *group; int ok = 0; @@ -123,11 +119,7 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op) if(object_in_group(ob, group)) { /* Assign groups to selected objects */ CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { - obt= base->object; - rem_from_group(group, obt); - obt->flag &= ~OB_FROMGROUP; - base->flag &= ~OB_FROMGROUP; - base->object->recalc= OB_RECALC_OB; + rem_from_group(group, base->object, scene, base); ok = 1; } CTX_DATA_END; @@ -165,11 +157,7 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { group = NULL; while((group = find_group(base->object, group))) - rem_from_group(group, base->object); - - base->object->flag &= ~OB_FROMGROUP; - base->flag &= ~OB_FROMGROUP; - base->object->recalc= OB_RECALC_OB; + rem_from_group(group, base->object, scene, base); } CTX_DATA_END; @@ -205,10 +193,7 @@ static int group_create_exec(bContext *C, wmOperator *op) group= add_group(name); CTX_DATA_BEGIN(C, Base*, base, selected_editable_bases) { - add_to_group(group, base->object); - base->object->flag |= OB_FROMGROUP; - base->flag |= OB_FROMGROUP; - base->object->recalc= OB_RECALC_OB; + add_to_group(group, base->object, scene, base); } CTX_DATA_END; @@ -259,9 +244,7 @@ static int group_add_exec(bContext *C, wmOperator *op) group= BLI_findlink(&bmain->group, value); if(group) { - add_to_group(group, ob); - ob->flag |= OB_FROMGROUP; - base->flag |= OB_FROMGROUP; + add_to_group(group, ob, scene, NULL); /* base will be used if found */ } WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); @@ -323,21 +306,11 @@ static int group_remove_exec(bContext *C, wmOperator *op) Scene *scene= CTX_data_scene(C); Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; Group *group= CTX_data_pointer_get_type(C, "group", &RNA_Group).data; - Base *base; if(!ob || !group) return OPERATOR_CANCELLED; - base= object_in_scene(ob, scene); - if(!base) - return OPERATOR_CANCELLED; - - rem_from_group(group, ob); - - if(find_group(ob, NULL) == NULL) { - ob->flag &= ~OB_FROMGROUP; - base->flag &= ~OB_FROMGROUP; - } + rem_from_group(group, ob, scene, NULL); /* base will be used if found */ WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob); diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h index 8d3c3168e00..6a1ef195d1d 100644 --- a/source/blender/makesrna/RNA_access.h +++ b/source/blender/makesrna/RNA_access.h @@ -683,7 +683,10 @@ int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop); int RNA_property_collection_lookup_index(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *t_ptr); int RNA_property_collection_lookup_int(PointerRNA *ptr, PropertyRNA *prop, int key, PointerRNA *r_ptr); int RNA_property_collection_lookup_string(PointerRNA *ptr, PropertyRNA *prop, const char *key, PointerRNA *r_ptr); + PropertyRNA *RNA_property_collection_active(PropertyRNA *prop); +FunctionRNA *RNA_property_collection_add_func(PropertyRNA *prop); +FunctionRNA *RNA_property_collection_remove_func(PropertyRNA *prop); /* efficient functions to set properties for arrays */ int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, RawArray *array); diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 93e83492efa..dea593c78a5 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -1567,7 +1567,7 @@ int RNA_property_collection_length(PointerRNA *ptr, PropertyRNA *prop) void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA *r_ptr) { IDProperty *idprop; - CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop; +// CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop; if((idprop=rna_idproperty_check(&prop, ptr))) { IDPropertyTemplate val = {0}; @@ -1593,6 +1593,9 @@ void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA MEM_freeN(item); } } + + /* py api calls directly */ +#if 0 else if(cprop->add){ if(!(cprop->add->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */ ParameterList params; @@ -1603,6 +1606,7 @@ void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA } /*else printf("RNA_property_collection_add %s.%s: not implemented for this property.\n", ptr->type->identifier, prop->identifier);*/ +#endif if(r_ptr) { if(idprop) { @@ -1620,7 +1624,7 @@ void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key) { IDProperty *idprop; - CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop; +// CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop; if((idprop=rna_idproperty_check(&prop, ptr))) { IDProperty tmp, *array; @@ -1644,6 +1648,9 @@ int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key) } else if(prop->flag & PROP_IDPROPERTY) return 1; + + /* py api calls directly */ +#if 0 else if(cprop->remove){ if(!(cprop->remove->flag & FUNC_USE_CONTEXT)) { /* XXX check for this somewhere else */ ParameterList params; @@ -1656,7 +1663,7 @@ int RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key) } /*else printf("RNA_property_collection_remove %s.%s: only supported for id properties.\n", ptr->type->identifier, prop->identifier);*/ - +#endif return 0; } @@ -1767,6 +1774,18 @@ PropertyRNA *RNA_property_collection_active(PropertyRNA *prop) return cprop->active; } +FunctionRNA *RNA_property_collection_add_func(PropertyRNA *prop) +{ + CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop; + return cprop->add; +} + +FunctionRNA *RNA_property_collection_remove_func(PropertyRNA *prop) +{ + CollectionPropertyRNA *cprop= (CollectionPropertyRNA*)prop; + return cprop->remove; +} + int RNA_property_collection_raw_array(PointerRNA *ptr, PropertyRNA *prop, PropertyRNA *itemprop, RawArray *array) { CollectionPropertyIterator iter; diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c index dddc2062f07..8f6a5f1005c 100644 --- a/source/blender/makesrna/intern/rna_group.c +++ b/source/blender/makesrna/intern/rna_group.c @@ -33,6 +33,11 @@ #ifdef RNA_RUNTIME +#include "DNA_scene_types.h" +#include "DNA_object_types.h" + +#include "BKE_group.h" + static PointerRNA rna_Group_objects_get(CollectionPropertyIterator *iter) { ListBaseIterator *internal= iter->internal; @@ -41,6 +46,16 @@ static PointerRNA rna_Group_objects_get(CollectionPropertyIterator *iter) return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ((GroupObject*)internal->link)->ob); } +static int rna_Group_objects_add(Group *group, bContext *C, Object *object) +{ + return add_to_group(group, object, CTX_data_scene(C), NULL); +} + +static int rna_Group_objects_remove(Group *group, bContext *C, Object *object) +{ + return rem_from_group(group, object, CTX_data_scene(C), NULL); +} + #else void RNA_def_group(BlenderRNA *brna) @@ -57,16 +72,41 @@ void RNA_def_group(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Dupli Offset", "Offset from the center to use when instancing as DupliGroup."); RNA_def_property_ui_range(prop, -10000.0, 10000.0, 10, 4); + prop= RNA_def_property(srna, "layer", PROP_BOOLEAN, PROP_LAYER); + RNA_def_property_boolean_sdna(prop, NULL, "layer", 1); + RNA_def_property_array(prop, 20); + RNA_def_property_ui_text(prop, "Dupli Layers", "Layers visible when this groups is instanced as a dupli."); + + + /* add object */ + FunctionRNA *func; + PropertyRNA *parm; + func= RNA_def_function(srna, "add_object", "rna_Group_objects_add"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + RNA_def_function_ui_description(func, "Add this object to a group"); + /* return type */ + parm= RNA_def_boolean(func, "success", 0, "Success", "Newly created Group Target."); + RNA_def_function_return(func, parm); + /* object to add */ + parm= RNA_def_pointer(func, "object", "Object", "", "Object to add."); + RNA_def_property_flag(parm, PROP_REQUIRED); + + /* remove object */ + func= RNA_def_function(srna, "remove_object", "rna_Group_objects_remove"); + RNA_def_function_ui_description(func, "Remove this object to a group"); + RNA_def_function_flag(func, FUNC_USE_CONTEXT); + /* return type */ + parm= RNA_def_boolean(func, "success", 0, "Success", "Newly created Group Target."); + RNA_def_function_return(func, parm); + /* object to remove */ + parm= RNA_def_pointer(func, "object", "Object", "", "Object to remove."); + RNA_def_property_flag(parm, PROP_REQUIRED); + prop= RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "gobject", NULL); RNA_def_property_struct_type(prop, "Object"); RNA_def_property_ui_text(prop, "Objects", "A collection of this groups objects."); - RNA_def_property_collection_funcs(prop, 0, 0, 0, "rna_Group_objects_get", 0, 0, 0, 0, 0); - - prop= RNA_def_property(srna, "layer", PROP_BOOLEAN, PROP_LAYER); - RNA_def_property_boolean_sdna(prop, NULL, "layer", 1); - RNA_def_property_array(prop, 20); - RNA_def_property_ui_text(prop, "Dupli Layers", "Layers visible when this groups is instanced as a dupli."); + RNA_def_property_collection_funcs(prop, 0, 0, 0, "rna_Group_objects_get", 0, 0, 0, "add_object", "remove_object"); } #endif diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index d490debdce6..b47214bdded 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -519,7 +519,7 @@ int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const cha static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw); -PyObject *pyrna_func_to_py(BPy_StructRNA *pyrna, FunctionRNA *func) +PyObject *pyrna_func_to_py(BPy_DummyPointerRNA *pyrna, FunctionRNA *func) { static PyMethodDef func_meth = {"<generic rna function>", (PyCFunction)pyrna_func_call, METH_VARARGS|METH_KEYWORDS, "python rna function"}; PyObject *self; @@ -595,7 +595,7 @@ int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *v case PROP_INT: { int param = PyLong_AsSsize_t(value); - if (PyErr_Occurred()) { + if (param==-1 && PyErr_Occurred()) { PyErr_Format(PyExc_TypeError, "%.200s expected an int type", error_prefix); return -1; } else { @@ -816,7 +816,7 @@ static int pyrna_py_to_prop_index(BPy_PropertyRNA *self, int index, PyObject *va case PROP_INT: { int param = PyLong_AsSsize_t(value); - if (PyErr_Occurred()) { + if (param==-1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "expected an int type"); ret = -1; } else { @@ -1371,7 +1371,7 @@ static PyObject *pyrna_struct_getattro( BPy_StructRNA * self, PyObject *pyname ) ret = pyrna_prop_to_py(&self->ptr, prop); } else if ((func = RNA_struct_find_function(&self->ptr, name))) { - ret = pyrna_func_to_py(self, func); + ret = pyrna_func_to_py((BPy_DummyPointerRNA *)self, func); } else if (self->ptr.type == &RNA_Context) { PointerRNA newptr; @@ -1470,54 +1470,130 @@ static int pyrna_struct_setattro( BPy_StructRNA * self, PyObject *pyname, PyObje return pyrna_py_to_prop(&self->ptr, prop, NULL, value, "StructRNA - Attribute (setattr):"); } -static PyObject *pyrna_prop_getattro( BPy_PropertyRNA * self, PyObject *pyname ) +static PyObject *pyrna_prop_get_active( BPy_PropertyRNA * self ) { - char *name = _PyUnicode_AsString(pyname); + PropertyRNA *prop_act; - if(strcmp(name, "active")==0) { - PropertyRNA *prop_act; + if (RNA_property_type(self->prop) != PROP_COLLECTION) { + PyErr_SetString( PyExc_TypeError, "this BPy_PropertyRNA object is not a collection"); + return NULL; + } - if (RNA_property_type(self->prop) != PROP_COLLECTION) { - PyErr_SetString( PyExc_TypeError, "this BPy_PropertyRNA object is not a collection"); - return NULL; - } + prop_act= RNA_property_collection_active(self->prop); + if (prop_act==NULL) { + PyErr_SetString( PyExc_TypeError, "collection has no active"); + return NULL; + } - prop_act= RNA_property_collection_active(self->prop); - if (prop_act==NULL) { - PyErr_SetString( PyExc_TypeError, "collection has no active"); - return NULL; - } + return pyrna_prop_to_py(&self->ptr, prop_act); +} - return pyrna_prop_to_py(&self->ptr, prop_act); +static int pyrna_prop_set_active( BPy_PropertyRNA * self, PyObject * value ) +{ + PropertyRNA *prop_act; + + if (RNA_property_type(self->prop) != PROP_COLLECTION) { + PyErr_SetString( PyExc_TypeError, "this BPy_PropertyRNA object is not a collection"); + return -1; + } + + prop_act= RNA_property_collection_active(self->prop); + if (prop_act==NULL) { + PyErr_SetString( PyExc_TypeError, "collection has no active"); + return -1; } - return PyObject_GenericGetAttr((PyObject *)self, pyname); + return pyrna_py_to_prop(&self->ptr, prop_act, NULL, value, "StructRNA - Attribute (setattr):"); } -//--------------- setattr------------------------------------------- -static int pyrna_prop_setattro( BPy_PropertyRNA * self, PyObject *pyname, PyObject * value ) +/* odd case, we need to be able return a python method from a tp_getset */ +static PyObject *pyrna_prop_add(BPy_PropertyRNA *self); +static PyMethodDef pyrna_prop_add_meth[] = {{"add", (PyCFunction)pyrna_prop_add, METH_NOARGS, NULL}}; +static PyObject *pyrna_prop_add(BPy_PropertyRNA *self) { - char *name = _PyUnicode_AsString(pyname); - if(strcmp(name, "active")==0) { - PropertyRNA *prop_act; + PointerRNA r_ptr; - if (RNA_property_type(self->prop) != PROP_COLLECTION) { - PyErr_SetString( PyExc_TypeError, "this BPy_PropertyRNA object is not a collection"); - return -1; - } + RNA_property_collection_add(&self->ptr, self->prop, &r_ptr); + if(!r_ptr.data) { + PyErr_SetString( PyExc_TypeError, "add() not supported for this collection"); + return NULL; + } + else { + return pyrna_struct_CreatePyObject(&r_ptr); + } +} - prop_act= RNA_property_collection_active(self->prop); - if (prop_act==NULL) { - PyErr_SetString( PyExc_TypeError, "collection has no active"); - return -1; + +static PyObject *pyrna_prop_remove(BPy_PropertyRNA *self, PyObject *value); +static PyMethodDef pyrna_prop_remove_meth[] = {{"remove", (PyCFunction)pyrna_prop_remove, METH_O, NULL}}; +static PyObject *pyrna_prop_remove(BPy_PropertyRNA *self, PyObject *value) +{ + PyObject *ret; + int key= PyLong_AsSsize_t(value); + + if (key==-1 && PyErr_Occurred()) { + PyErr_SetString( PyExc_TypeError, "remove() expected one int argument"); + return NULL; + } + + if(!RNA_property_collection_remove(&self->ptr, self->prop, key)) { + PyErr_SetString( PyExc_TypeError, "remove() not supported for this collection"); + return NULL; + } + + ret = Py_None; + Py_INCREF(ret); + + return ret; +} + +static PyObject *pyrna_prop_get_add_func( BPy_PropertyRNA * self ) +{ + FunctionRNA *func; + + if (RNA_property_type(self->prop) == PROP_COLLECTION) { + func = RNA_property_collection_add_func(self->prop); + if (func==NULL) { + PyErr_SetString( PyExc_TypeError, "this BPy_PropertyRNA collection has no add() function"); + return NULL; } - return pyrna_py_to_prop(&self->ptr, prop_act, NULL, value, "StructRNA - Attribute (setattr):"); + return pyrna_func_to_py((BPy_DummyPointerRNA *)self, func); } + else { + return PyCFunction_New(pyrna_prop_add_meth, (PyObject *)self); + } +} - return PyObject_GenericSetAttr((PyObject *)self, pyname, value); +static PyObject *pyrna_prop_get_remove_func( BPy_PropertyRNA * self ) +{ + FunctionRNA *func; + + if (RNA_property_type(self->prop) == PROP_COLLECTION) { + func = RNA_property_collection_remove_func(self->prop); + if (func==NULL) { + PyErr_SetString( PyExc_TypeError, "this BPy_PropertyRNA collection has no add() function"); + return NULL; + } + + return pyrna_func_to_py((BPy_DummyPointerRNA *)self, func); + } + else { + return PyCFunction_New(pyrna_prop_remove_meth, (PyObject *)self); + } } +/*****************************************************************************/ +/* Python attributes get/set structure: */ +/*****************************************************************************/ +static PyGetSetDef pyrna_prop_getseters[] = { + {"active", (getter)pyrna_prop_get_active, (setter)pyrna_prop_set_active, "", NULL}, + /* rna functions */ + {"add", (getter)pyrna_prop_get_add_func, NULL, "", NULL}, + {"remove", (getter)pyrna_prop_get_remove_func, NULL, "", NULL}, + {NULL,NULL,NULL,NULL,NULL} /* Sentinel */ +}; + static PyObject *pyrna_prop_keys(BPy_PropertyRNA *self) { PyObject *ret; @@ -1630,40 +1706,6 @@ static PyObject *pyrna_prop_get(BPy_PropertyRNA *self, PyObject *args) return def; } - -static PyObject *pyrna_prop_add(BPy_PropertyRNA *self, PyObject *args) -{ - PointerRNA newptr; - - RNA_property_collection_add(&self->ptr, self->prop, &newptr); - if(!newptr.data) { - PyErr_SetString( PyExc_TypeError, "add() not supported for this collection"); - return NULL; - } - else { - return pyrna_struct_CreatePyObject(&newptr); - } -} - -static PyObject *pyrna_prop_remove(BPy_PropertyRNA *self, PyObject *args) -{ - PyObject *ret; - int key= 0; - - if (!PyArg_ParseTuple(args, "i:remove", &key)) - return NULL; - - if(!RNA_property_collection_remove(&self->ptr, self->prop, key)) { - PyErr_SetString( PyExc_TypeError, "remove() not supported for this collection"); - return NULL; - } - - ret = Py_None; - Py_INCREF(ret); - - return ret; -} - static void foreach_attr_type( BPy_PropertyRNA *self, char *attr, /* values to assign */ RawPropertyType *raw_type, int *attr_tot, int *attr_signed ) @@ -1951,8 +1993,11 @@ static struct PyMethodDef pyrna_prop_methods[] = { {"get", (PyCFunction)pyrna_prop_get, METH_VARARGS, NULL}, - {"add", (PyCFunction)pyrna_prop_add, METH_VARARGS, NULL}, - {"remove", (PyCFunction)pyrna_prop_remove, METH_VARARGS, NULL}, + /* moved into a getset */ +#if 0 + {"add", (PyCFunction)pyrna_prop_add, METH_NOARGS, NULL}, + {"remove", (PyCFunction)pyrna_prop_remove, METH_O, NULL}, +#endif /* array accessor function */ {"foreach_get", (PyCFunction)pyrna_prop_foreach_get, METH_VARARGS, NULL}, @@ -2123,7 +2168,8 @@ PyObject *pyrna_param_to_py(PointerRNA *ptr, PropertyRNA *prop, void *data) static PyObject * pyrna_func_call(PyObject * self, PyObject *args, PyObject *kw) { - PointerRNA *self_ptr= &(((BPy_StructRNA *)PyTuple_GET_ITEM(self, 0))->ptr); + /* Note, both BPy_StructRNA and BPy_PropertyRNA can be used here */ + PointerRNA *self_ptr= &(((BPy_DummyPointerRNA *)PyTuple_GET_ITEM(self, 0))->ptr); FunctionRNA *self_func= PyCObject_AsVoidPtr(PyTuple_GET_ITEM(self, 1)); PointerRNA funcptr; @@ -2429,8 +2475,8 @@ PyTypeObject pyrna_prop_Type = { NULL, /* reprfunc tp_str; */ /* will only use these if this is a subtype of a py class */ - ( getattrofunc ) pyrna_prop_getattro, /* getattrofunc tp_getattro; */ - ( setattrofunc ) pyrna_prop_setattro, /* setattrofunc tp_setattro; */ + ( getattrofunc ) NULL, /* getattrofunc tp_getattro; */ + ( setattrofunc ) NULL, /* setattrofunc tp_setattro; */ /* Functions to access object as input/output buffer */ NULL, /* PyBufferProcs *tp_as_buffer; */ @@ -2461,7 +2507,7 @@ PyTypeObject pyrna_prop_Type = { /*** Attribute descriptor and subclassing stuff ***/ pyrna_prop_methods, /* struct PyMethodDef *tp_methods; */ NULL, /* struct PyMemberDef *tp_members; */ - NULL, /* struct PyGetSetDef *tp_getset; */ + pyrna_prop_getseters, /* struct PyGetSetDef *tp_getset; */ NULL, /* struct _typeobject *tp_base; */ NULL, /* PyObject *tp_dict; */ NULL, /* descrgetfunc tp_descr_get; */ diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index fe38ddb6bd9..0e40bf7258c 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -39,11 +39,9 @@ extern PyTypeObject pyrna_prop_Type; #define BPy_PropertyRNA_CheckExact(v) (Py_TYPE(v) == &pyrna_prop_Type) typedef struct { - void * _a; - void * _b; - PyTypeObject *py_type; -} BPy_StructFakeType; - + PyObject_HEAD /* required python macro */ + PointerRNA ptr; +} BPy_DummyPointerRNA; typedef struct { PyObject_HEAD /* required python macro */ |