Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2007-08-01 16:57:59 +0400
committerCampbell Barton <ideasman42@gmail.com>2007-08-01 16:57:59 +0400
commitb38e987932b7a956210875d8bb7881921490ab02 (patch)
tree8dc31ffd7c55b477144fcb441e96a0a334ef6e14 /source/blender/python/api2_2x/Armature.c
parentc79e2666a22ab9da1b48645843cf7ceec19540c8 (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.c263
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");