diff options
author | Campbell Barton <ideasman42@gmail.com> | 2007-08-01 16:57:59 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2007-08-01 16:57:59 +0400 |
commit | b38e987932b7a956210875d8bb7881921490ab02 (patch) | |
tree | 8dc31ffd7c55b477144fcb441e96a0a334ef6e14 /source/blender/python/api2_2x/Armature.c | |
parent | c79e2666a22ab9da1b48645843cf7ceec19540c8 (diff) |
armature weakref fix from stable, Curve.c removed unneeded cruft
Diffstat (limited to 'source/blender/python/api2_2x/Armature.c')
-rw-r--r-- | source/blender/python/api2_2x/Armature.c | 263 |
1 files changed, 143 insertions, 120 deletions
diff --git a/source/blender/python/api2_2x/Armature.c b/source/blender/python/api2_2x/Armature.c index c82597f9b00..e00ec339063 100644 --- a/source/blender/python/api2_2x/Armature.c +++ b/source/blender/python/api2_2x/Armature.c @@ -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"); |