python api for collection add()/remove()
authorCampbell Barton <ideasman42@gmail.com>
Wed, 11 Nov 2009 16:28:53 +0000 (16:28 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 11 Nov 2009 16:28:53 +0000 (16:28 +0000)
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()

source/blender/blenkernel/BKE_group.h
source/blender/blenkernel/intern/group.c
source/blender/blenkernel/intern/object.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/object/object_add.c
source/blender/editors/object/object_group.c
source/blender/makesrna/RNA_access.h
source/blender/makesrna/intern/rna_access.c
source/blender/makesrna/intern/rna_group.c
source/blender/python/intern/bpy_rna.c
source/blender/python/intern/bpy_rna.h

index b66ddf13527a63beea134ecaee206e68973cccb0..877e09b037fbbe4c762523bf0d3715e2f0b03823 100644 (file)
@@ -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);
index 6bb47bc0f0f6bd31d11780951e2946fc2e6006fa..77bf5859385bc039a7fd688e02f89c89953933eb 100644 (file)
@@ -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;
index f363b7d9a0a4d12bbf050f33f0befec2ee9ec31a..078ff9d6eeb8e3e8d4f0fd79289e12da58b4ed9e 100644 (file)
@@ -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;
        }
        
index 4f63fdf07376df1eda0746b4b1cfb3c29c5c68ed..83899473cb4b7ae0bd51168a7e8542f94eb20d19 100644 (file)
@@ -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;
        }
index 61377d76c56b55ba0e4277b1737f4f1ce91145da..e58170ebab65854ee764a422a6ac0a19afad0928 100644 (file)
@@ -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 */
index ec8409e9aa1915410f4770700fd5272c623c4f62..1e5b93aa6dc1946747ae2b6bb0cf756282b860b2 100644 (file)
@@ -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);
        
index 8d3c3168e003ea85be37171981c36359a682659f..6a1ef195d1db77e28794a1bd4e271c396c103bbe 100644 (file)
@@ -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);
index 93e83492efad0c6d484358f7afb669e25bebbabb..dea593c78a5bf20bb9c35ab65fecbf9de713b8d3 100644 (file)
@@ -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;
index dddc2062f071a909388d24cb63d6552d01c612b2..8f6a5f1005c26d41e38d984feb3537b00660554d 100644 (file)
 
 #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
index d490debdce6522771f30d58c9d0fa4d0e4b25140..b47214bdded4ebf935cbf92f27ca50646c012199 100644 (file)
@@ -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; */
index fe38ddb6bd990f00b9a42fcedfa32519e677dfeb..0e40bf7258c4323eb09bbeb80d035cf31e2f14f8 100644 (file)
@@ -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   */