armature weakref fix from stable, Curve.c removed unneeded cruft
authorCampbell Barton <ideasman42@gmail.com>
Wed, 1 Aug 2007 12:57:59 +0000 (12:57 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 1 Aug 2007 12:57:59 +0000 (12:57 +0000)
source/blender/python/api2_2x/Armature.c
source/blender/python/api2_2x/Curve.c

index c82597f9b00d5878425619f43b04b8e3516271be..e00ec339063700f39849e8261929750f1b40ae14 100644 (file)
@@ -60,6 +60,10 @@ static const char sArmatureBadArgs[] = "ArmatureType - Bad Arguments: ";
 static const char sModuleError[] = "Blender.Armature - Error: ";
 static const char sModuleBadArgs[] = "Blender.Armature - Bad Arguments: ";
 
+PyObject * arm_weakref_callback_weakref_dealloc(PyObject *self, PyObject *weakref);
+/* python callable */
+PyObject * arm_weakref_callback_weakref_dealloc__pyfunc;
+
 //################## BonesDict_Type (internal) ########################
 /*This is an internal psuedo-dictionary type that allows for manipulation
 * of bones inside of an armature. It is a subobject of armature.
@@ -118,18 +122,19 @@ static PyMethodDef BPy_BonesDict_methods[] = {
 //-----------------(internal)
 static int BoneMapping_Init(PyObject *dictionary, ListBase *bones){
        Bone *bone = NULL;
-       PyObject *py_bone = NULL, *str;
+       PyObject *py_bone = NULL;
 
        for (bone = bones->first; bone; bone = bone->next){
                py_bone = PyBone_FromBone(bone);
                if (!py_bone)
                        return -1;
                
-               str = PyString_FromString(bone->name);
-               if(PyDict_SetItem(dictionary, str, py_bone) == -1)
+               if(PyDict_SetItemString(dictionary, bone->name, py_bone) == -1) {
+                       /* unlikely but possible */
+                       Py_DECREF(py_bone);
                        return -1;
+               }
                
-               Py_DECREF(str);
                Py_DECREF(py_bone);
                if (bone->childbase.first) 
                        BoneMapping_Init(dictionary, &bone->childbase);
@@ -139,18 +144,17 @@ static int BoneMapping_Init(PyObject *dictionary, ListBase *bones){
 //-----------------(internal)
 static int EditBoneMapping_Init(PyObject *dictionary, ListBase *editbones){
        EditBone *editbone = NULL;
-       PyObject *py_editbone = NULL, *str;
+       PyObject *py_editbone = NULL;
 
        for (editbone = editbones->first; editbone; editbone = editbone->next){
                py_editbone = PyEditBone_FromEditBone(editbone);
                if (!py_editbone)
                        return -1;
                
-               str = PyString_FromString(editbone->name);
-               if(PyDict_SetItem(dictionary, str, py_editbone) == -1)
+               if(PyDict_SetItemString(dictionary, editbone->name, py_editbone) == -1) {
+                       Py_DECREF(py_editbone);
                        return -1;
-               
-               Py_DECREF(str);
+               }
                Py_DECREF(py_editbone);
        }
        return 0;
@@ -242,17 +246,14 @@ static PyObject *BonesDict_GetItem(BPy_BonesDict *self, PyObject* key)
                value = PyDict_GetItem(self->bonesMap, key);
        }
        if(value == NULL){  /* item not found in dict. throw exception */
-               char buffer[128];
-               char* key_str;
-               key_str = PyString_AsString( key );
-               if( !key_str ){  /* key not a py string */
-                       key_str = "";  /* use empty string for printing */
+               char* key_str = PyString_AsString( key );
+               if (key_str) {
+                       return EXPP_ReturnPyObjError(PyExc_KeyError, "bone key must be a string" );
+               } else {
+                       char buffer[128];
+                       PyOS_snprintf( buffer, sizeof(buffer), "bone %s not found", key_str);
+                       return EXPP_ReturnPyObjError(PyExc_KeyError, buffer );
                }
-  
-               PyOS_snprintf( buffer, sizeof(buffer),
-                                          "bone %s not found", key_str);
-                       
-        return EXPP_ReturnPyObjError(PyExc_KeyError, buffer );
        }
        return EXPP_incr_ret(value);
 }
@@ -262,107 +263,98 @@ static int BonesDict_SetItem(BPy_BonesDict *self, PyObject *key, PyObject *value
 {
        BPy_EditBone *editbone_for_deletion;
        struct EditBone *editbone = NULL;
-       char *key_str = "";
-
-       if (self->editmode_flag){
-               //Get the key name
-               if(key && PyString_Check(key)){
-                       key_str = PyString_AsString(key);
-               }else{
-                       goto AttributeError;
-               }
-               //parse value for assignment
-               if (value && EditBoneObject_Check(value)){
-                       //create a new editbone
-                       editbone = MEM_callocN(sizeof(EditBone), "eBone");
-                       BLI_strncpy(editbone->name, key_str, 32);
-                       unique_editbone_name(NULL, editbone->name);
-                       editbone->dist = ((BPy_EditBone*)value)->dist;
-                       editbone->ease1 = ((BPy_EditBone*)value)->ease1;
-                       editbone->ease2 = ((BPy_EditBone*)value)->ease2;
-                       editbone->flag = ((BPy_EditBone*)value)->flag;
-                       editbone->parent = ((BPy_EditBone*)value)->parent;
-                       editbone->rad_head = ((BPy_EditBone*)value)->rad_head;
-                       editbone->rad_tail = ((BPy_EditBone*)value)->rad_tail;
-                       editbone->roll = ((BPy_EditBone*)value)->roll;
-                       editbone->segments = ((BPy_EditBone*)value)->segments;
-                       editbone->weight = ((BPy_EditBone*)value)->weight;
-                       editbone->xwidth = ((BPy_EditBone*)value)->xwidth;
-                       editbone->zwidth = ((BPy_EditBone*)value)->zwidth;
-                       VECCOPY(editbone->head, ((BPy_EditBone*)value)->head);
-                       VECCOPY(editbone->tail, ((BPy_EditBone*)value)->tail);
-                       
-                       // FIXME, should be exposed via python. this avoids creating bones with no layers.
-                       editbone->layer= 1;
-                       
-                       //set object pointer
-                       ((BPy_EditBone*)value)->editbone = editbone;
-
-                       //fix the bone's head position if flags indicate that it is 'connected'
-                       if (editbone->flag & BONE_CONNECTED){
-                               if(!editbone->parent){
-                                       ((BPy_EditBone*)value)->editbone = NULL;
-                                       MEM_freeN(editbone);
-                                       goto AttributeError3;
-                               }else{
-                                       VECCOPY(editbone->head, editbone->parent->tail);
-                               }
-                       }
+       char *key_str = PyString_AsString(key);
 
-                       //set in editbonelist
-                       BLI_addtail(&self->editbones, editbone);
+       if (!self->editmode_flag)
+               return EXPP_intError(PyExc_AttributeError, "%s%s", 
+                               sBoneDictBadArgs,  "You must call makeEditable() first");
+       
+       if (!key_str)
+               return EXPP_intError(PyExc_AttributeError, "%s%s", 
+                               sBoneDictBadArgs,  "The key must be the name of an editbone");
+       
+       if (value && !EditBoneObject_Check(value))
+               return EXPP_intError(PyExc_AttributeError, "%s%s",
+                               sBoneDictBadArgs,  "Can only assign editbones as values");
+       
+       //parse value for assignment
+       if (value){ /* we know this must be an editbone from the above check */
+               //create a new editbone
+               editbone = MEM_callocN(sizeof(EditBone), "eBone");
+               BLI_strncpy(editbone->name, key_str, 32);
+               unique_editbone_name(NULL, editbone->name);
+               editbone->dist = ((BPy_EditBone*)value)->dist;
+               editbone->ease1 = ((BPy_EditBone*)value)->ease1;
+               editbone->ease2 = ((BPy_EditBone*)value)->ease2;
+               editbone->flag = ((BPy_EditBone*)value)->flag;
+               editbone->parent = ((BPy_EditBone*)value)->parent;
+               editbone->rad_head = ((BPy_EditBone*)value)->rad_head;
+               editbone->rad_tail = ((BPy_EditBone*)value)->rad_tail;
+               editbone->roll = ((BPy_EditBone*)value)->roll;
+               editbone->segments = ((BPy_EditBone*)value)->segments;
+               editbone->weight = ((BPy_EditBone*)value)->weight;
+               editbone->xwidth = ((BPy_EditBone*)value)->xwidth;
+               editbone->zwidth = ((BPy_EditBone*)value)->zwidth;
+               VECCOPY(editbone->head, ((BPy_EditBone*)value)->head);
+               VECCOPY(editbone->tail, ((BPy_EditBone*)value)->tail);
+               
+               // FIXME, should be exposed via python. this avoids creating bones with no layers.
+               editbone->layer= 1;
+               
+               //set object pointer
+               ((BPy_EditBone*)value)->editbone = editbone;
 
-                       //set the new editbone in the mapping
-                       if(PyDict_SetItemString(self->editbonesMap, key_str, value) == -1){
+               //fix the bone's head position if flags indicate that it is 'connected'
+               if (editbone->flag & BONE_CONNECTED){
+                       if(!editbone->parent){
                                ((BPy_EditBone*)value)->editbone = NULL;
-                               BLI_freelinkN(&self->editbones, editbone);
-                               goto RuntimeError;
-                       }
-               }else if(!value){
-                       //they are trying to delete the bone using 'del'
-                       if(PyDict_GetItem(self->editbonesMap, key) != NULL){
-                               /*first kill the datastruct then remove the item from the dict
-                               and wait for GC to pick it up.
-                               We have to delete the datastruct here because the tp_dealloc
-                               doesn't handle it*/
-                               editbone_for_deletion = (BPy_EditBone*)PyDict_GetItem(self->editbonesMap, key);
-                               /*this is ugly but you have to set the parent to NULL for else 
-                               editbones_to_armature will crash looking for this bone*/
-                               for (editbone = self->editbones.first; editbone; editbone = editbone->next){
-                                       if (editbone->parent == editbone_for_deletion->editbone) {
-                                               editbone->parent = NULL;
-                                                /* remove the connected flag or else the 'root' ball
-                                                 * doesn't get drawn */
-                                               editbone->flag &= ~BONE_CONNECTED;
-                                       }
-                               }
-                               BLI_freelinkN(&self->editbones, editbone_for_deletion->editbone);
-                               if(PyDict_DelItem(self->editbonesMap, key) == -1)
-                                       goto RuntimeError;
+                               MEM_freeN(editbone);
+                                       return EXPP_intError(PyExc_AttributeError, "%s%s", 
+                                                       sBoneDictBadArgs,  "The 'connected' flag is set but the bone has no parent!");
                        }else{
-                               goto KeyError;
+                               VECCOPY(editbone->head, editbone->parent->tail);
                        }
                }
-               return 0;
-       }else{
-               goto AttributeError2;
-       }
 
-KeyError:
-return EXPP_intError(PyExc_KeyError, "%s%s%s%s", 
-           sBoneDictError,  "The key: ", key_str, " is not present in this dictionary!");
-RuntimeError:
-       return EXPP_intError(PyExc_RuntimeError, "%s%s", 
-               sBoneDictError,  "Unable to access dictionary!");
-AttributeError:
-       return EXPP_intError(PyExc_AttributeError, "%s%s", 
-               sBoneDictBadArgs,  "Expects EditboneType Object");
-AttributeError2:
-       return EXPP_intError(PyExc_AttributeError, "%s%s", 
-               sBoneDictBadArgs,  "You must call makeEditable() first");
-AttributeError3:
-       return EXPP_intError(PyExc_AttributeError, "%s%s", 
-               sBoneDictBadArgs,  "The 'connected' flag is set but the bone has no parent!");
+               //set in editbonelist
+               BLI_addtail(&self->editbones, editbone);
+
+               //set the new editbone in the mapping
+               if(PyDict_SetItemString(self->editbonesMap, key_str, value) == -1){
+                       ((BPy_EditBone*)value)->editbone = NULL;
+                       BLI_freelinkN(&self->editbones, editbone);
+                       return EXPP_intError(PyExc_RuntimeError, "%s%s", 
+                                       sBoneDictError,  "Unable to access dictionary!");
+               }
+       }else {
+               //they are trying to delete the bone using 'del'
+               editbone_for_deletion = (BPy_EditBone*)PyDict_GetItem(self->editbonesMap, key);
+
+               if (!editbone_for_deletion)
+                       return EXPP_intError(PyExc_KeyError, "%s%s%s%s", 
+                                       sBoneDictError,  "The key: ", key_str, " is not present in this dictionary!");
+
+               /*first kill the datastruct then remove the item from the dict
+               and wait for GC to pick it up.
+               We have to delete the datastruct here because the tp_dealloc
+               doesn't handle it*/
+               
+               /*this is ugly but you have to set the parent to NULL for else 
+               editbones_to_armature will crash looking for this bone*/
+               for (editbone = self->editbones.first; editbone; editbone = editbone->next){
+                       if (editbone->parent == editbone_for_deletion->editbone) {
+                               editbone->parent = NULL;
+                                /* remove the connected flag or else the 'root' ball
+                                 * doesn't get drawn */
+                               editbone->flag &= ~BONE_CONNECTED;
+                       }
+               }
+               BLI_freelinkN(&self->editbones, editbone_for_deletion->editbone);
+               if(PyDict_DelItem(self->editbonesMap, key) == -1)
+                       return EXPP_intError(PyExc_RuntimeError, "%s%s", 
+                                       sBoneDictError,  "Unable to access dictionary!");
+       }
+       return 0;
 }
 //------------------TYPE_OBJECT DEFINITION--------------------------
 //Mapping Protocol
@@ -1068,7 +1060,7 @@ static PyObject *Armature_repr(BPy_Armature *self)
 static void Armature_dealloc(BPy_Armature * self)
 {
        if (self->weaklist != NULL)
-        PyObject_ClearWeakRefs((PyObject *) self);
+               PyObject_ClearWeakRefs((PyObject *) self); /* this causes the weakref dealloc func to be called */
        
        Py_DECREF(self->Bones);
        PyObject_DEL( self );
@@ -1293,11 +1285,32 @@ PyObject *Armature_RebuildBones(PyObject *pyarmature)
 {
        return Armature_update((BPy_Armature*)pyarmature);
 }
+
+/* internal func to remove weakref from weakref list */
+PyObject * arm_weakref_callback_weakref_dealloc(PyObject *self, PyObject *weakref)
+{
+       char *list_name = ARM_WEAKREF_LIST_NAME;
+       PyObject *maindict = NULL, *armlist = NULL;
+       int i;
+       
+       maindict= PyModule_GetDict(PyImport_AddModule(  "__main__"));
+       armlist = PyDict_GetItemString(maindict, list_name);
+       if( !armlist){
+               printf("Oops - update_armature_weakrefs()\n");
+               Py_RETURN_NONE;
+       }
+       
+       i = PySequence_Index(armlist, weakref);
+       if (i==-1) {
+               printf("callback weakref internal error, weakref not in list\n\tthis should never happen.\n");
+               Py_RETURN_NONE;
+       }
+       PySequence_DelItem(armlist, i);
+       Py_RETURN_NONE;
+}
+
 /*-----------------(internal)
- * Converts a bArmature to a PyArmature
- * 
- * WARNING!!! - MEMORY LEAK HERE, Run in a loop and loose your ram.
- * cannot find out why but doesn't seem to be the weakref */
+ * Converts a bArmature to a PyArmature */
 
 PyObject *Armature_CreatePyObject(struct bArmature *armature)
 {
@@ -1329,12 +1342,14 @@ PyObject *Armature_CreatePyObject(struct bArmature *armature)
 
        armlist = PyDict_GetItemString(maindict, list_name);
        if( armlist){
-               weakref = PyWeakref_NewProxy((PyObject*)py_armature, Py_None);
+               weakref = PyWeakref_NewProxy((PyObject*)py_armature, arm_weakref_callback_weakref_dealloc__pyfunc);
                if (PyList_Append(armlist, weakref) == -1){
                        printf("Oops - list-append failed\n");
                        goto RuntimeError;
                }
+               Py_DECREF(weakref);
        }
+
        return (PyObject *) py_armature;
 
 RuntimeError:
@@ -1353,7 +1368,10 @@ struct bArmature *Armature_FromPyObject( PyObject * py_obj )
        return PyArmature_AsArmature((BPy_Armature*)py_obj);
 }
 
-
+/* internal use only */
+static PyMethodDef bpy_arm_weakref_callback_weakref_dealloc[] = {
+       {"arm_weakref_callback_weakref_dealloc", arm_weakref_callback_weakref_dealloc, METH_O, ""}
+};
 
 //-------------------MODULE INITIALIZATION--------------------------------
 PyObject *Armature_Init(void)
@@ -1366,6 +1384,11 @@ PyObject *Armature_Init(void)
                return EXPP_incr_ret(Py_None);
        }
 
+       /* Weakref management - used for callbacks so we can
+        * tell when a callback has been removed that a UI button referenced */
+       arm_weakref_callback_weakref_dealloc__pyfunc = PyCFunction_New(bpy_arm_weakref_callback_weakref_dealloc, NULL);
+       
+       
        //Register the module
        module = Py_InitModule3("Blender.Armature", M_Armature_methods, 
                "The Blender Armature module"); 
index b620593d6b876353d0850206a2c519e2dcff9d43..790736862664d413b67b0bf4ea7c88601dcc4afb 100644 (file)
@@ -769,7 +769,6 @@ static PyObject *Curve_appendPoint( BPy_Curve * self, PyObject * args )
        int i;
        int nurb_num;           /* index of curve we append to */
        PyObject *coord_args;   /* coords for new point */
-       PyObject *retval = NULL;
        Nurb *nurb = self->curve->nurb.first;   /* first nurb in Curve */
 
 /* fixme - need to malloc new Nurb */
@@ -791,14 +790,7 @@ static PyObject *Curve_appendPoint( BPy_Curve * self, PyObject * args )
                        return EXPP_ReturnPyObjError( PyExc_ValueError,
                                        "curve index out of range" );
        }
-
-       /* rebuild our arg tuple for appendPointToNurb() */
-       //valtuple = Py_BuildValue( "(O)", coord_args );
-       
-       retval =  CurNurb_appendPointToNurb( nurb, coord_args );
-       // Py_DECREF( valtuple );
-
-       return retval;
+       return CurNurb_appendPointToNurb( nurb, coord_args );
 }