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
path: root/source
diff options
context:
space:
mode:
authorJoseph Gilbert <ascotan@gmail.com>2005-12-12 21:46:26 +0300
committerJoseph Gilbert <ascotan@gmail.com>2005-12-12 21:46:26 +0300
commit9ae9527c519716051a26a56c02a9b63af1f827b4 (patch)
treef4ef50f37a681dd2cd4927702ee80d7267eedd91 /source
parentd32b100464d3d1778a76ae00354ed5885acd574c (diff)
- Armature/Bone API for python
* this resolves a number of outstanding issues with the armature api and gets this ready for release - add/remove bones possible - rolls work correctly now! - ik'ing to parent should work - flags for tip/root/bone selection - etc.
Diffstat (limited to 'source')
-rw-r--r--source/blender/python/api2_2x/Armature.c561
-rw-r--r--source/blender/python/api2_2x/Armature.h11
-rw-r--r--source/blender/python/api2_2x/Bone.c788
-rw-r--r--source/blender/python/api2_2x/Bone.h78
-rw-r--r--source/blender/src/editarmature.c4
5 files changed, 812 insertions, 630 deletions
diff --git a/source/blender/python/api2_2x/Armature.c b/source/blender/python/api2_2x/Armature.c
index f9aa80c5aaf..d732ad38d71 100644
--- a/source/blender/python/api2_2x/Armature.c
+++ b/source/blender/python/api2_2x/Armature.c
@@ -48,7 +48,7 @@
//These are evil 'extern' declarations for functions with no anywhere
extern void free_editArmature(void);
extern void make_boneList(ListBase* list, ListBase *bones, EditBone *parent);
-extern void editbones_to_armature (ListBase *list, Object *ob, bArmature *armature);
+extern void editbones_to_armature (ListBase *list, Object *ob);
//------------------------ERROR CODES---------------------------------
//This is here just to make me happy and to have more consistant error strings :)
@@ -71,9 +71,9 @@ static const char sModuleBadArgs[] = "Blender.Armature - Bad Arguments: ";
PyObject* BonesDict_items(BPy_BonesDict *self)
{
if (self->editmode_flag){
- return PyDict_Items(self->editBoneDict);
+ return PyDict_Items(self->editbonesMap);
}else{
- return PyDict_Items(self->dict);
+ return PyDict_Items(self->bonesMap);
}
}
//------------------------Armature.bones.keys()
@@ -81,9 +81,9 @@ PyObject* BonesDict_items(BPy_BonesDict *self)
PyObject* BonesDict_keys(BPy_BonesDict *self)
{
if (self->editmode_flag){
- return PyDict_Keys(self->editBoneDict);
+ return PyDict_Keys(self->editbonesMap);
}else{
- return PyDict_Keys(self->dict);
+ return PyDict_Keys(self->bonesMap);
}
}
//------------------------Armature.bones.values()
@@ -91,13 +91,13 @@ PyObject* BonesDict_keys(BPy_BonesDict *self)
PyObject* BonesDict_values(BPy_BonesDict *self)
{
if (self->editmode_flag){
- return PyDict_Values(self->editBoneDict);
+ return PyDict_Values(self->editbonesMap);
}else{
- return PyDict_Values(self->dict);
+ return PyDict_Values(self->bonesMap);
}
}
//------------------ATTRIBUTE IMPLEMENTATION---------------------------
-//------------------TYPE_OBECT IMPLEMENTATION--------------------------
+//------------------TYPE_OBECT IMPLEMENTATION-----------------------
//------------------------tp_doc
//The __doc__ string for this object
static char BPy_BonesDict_doc[] = "This is an internal subobject of armature\
@@ -114,32 +114,59 @@ static PyMethodDef BPy_BonesDict_methods[] = {
"() - Returns the values from the dictionary"},
{NULL}
};
+//-----------------(internal)
+static int BoneMapping_Init(PyObject *dictionary, ListBase *bones){
+ Bone *bone = NULL;
+ PyObject *py_bone = NULL;
-//------------------------tp_new
-//This methods creates a new object (note it does not initialize it - only the building)
-static PyObject *BonesDict_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- BPy_BonesDict *py_BonesDict = NULL;
-
- py_BonesDict = (BPy_BonesDict*)type->tp_alloc(type, 0);
- if (!py_BonesDict)
- goto RuntimeError;
-
- py_BonesDict->dict = PyDict_New();
- if(!py_BonesDict->dict)
- goto RuntimeError;
-
- py_BonesDict->editBoneDict = PyDict_New();
- if (py_BonesDict->editBoneDict == NULL)
- goto RuntimeError;
+ for (bone = bones->first; bone; bone = bone->next){
+ py_bone = PyBone_FromBone(bone);
+ if (!py_bone)
+ return -1;
- py_BonesDict->editmode_flag = 0;
+ if(PyDict_SetItem(dictionary,
+ PyString_FromString(bone->name), py_bone) == -1){
+ return -1;
+ }
+ Py_DECREF(py_bone);
+ if (bone->childbase.first)
+ BoneMapping_Init(dictionary, &bone->childbase);
+ }
+ return 0;
+}
+//-----------------(internal)
+static int EditBoneMapping_Init(PyObject *dictionary, ListBase *editbones){
+ EditBone *editbone = NULL;
+ PyObject *py_editbone = NULL;
- return (PyObject*)py_BonesDict;
+ for (editbone = editbones->first; editbone; editbone = editbone->next){
+ py_editbone = PyEditBone_FromEditBone(editbone);
+ if (!py_editbone)
+ return -1;
-RuntimeError:
- return EXPP_objError(PyExc_RuntimeError, "%s%s",
- sBoneDictError, "Failed to create dictionary!");
+ if(PyDict_SetItem(dictionary,
+ PyString_FromString(editbone->name), py_editbone) == -1){
+ return -1;
+ }
+ Py_DECREF(py_editbone);
+ }
+ return 0;
+}
+//----------------- BonesDict_InitBones
+static int BonesDict_InitBones(BPy_BonesDict *self)
+{
+ PyDict_Clear(self->bonesMap);
+ if (BoneMapping_Init(self->bonesMap, self->bones) == -1)
+ return 0;
+ return 1;
+}
+//----------------- BonesDict_InitEditBones
+static int BonesDict_InitEditBones(BPy_BonesDict *self)
+{
+ PyDict_Clear(self->editbonesMap);
+ if (EditBoneMapping_Init(self->editbonesMap, &self->editbones) == -1)
+ return 0;
+ return 1;
}
//------------------------tp_repr
//This is the string representation of the object
@@ -153,13 +180,13 @@ static PyObject *BonesDict_repr(BPy_BonesDict *self)
sprintf(buffer, "[Bone Dict: {");
strcat(str,buffer);
if (self->editmode_flag){
- while (PyDict_Next(self->editBoneDict, &pos, &key, &value)) {
+ while (PyDict_Next(self->editbonesMap, &pos, &key, &value)) {
sprintf(buffer, "%s : %s, ", PyString_AsString(key),
PyString_AsString(value->ob_type->tp_repr(value)));
strcat(str,buffer);
}
}else{
- while (PyDict_Next(self->dict, &pos, &key, &value)) {
+ while (PyDict_Next(self->bonesMap, &pos, &key, &value)) {
sprintf(buffer, "%s : %s, ", PyString_AsString(key),
PyString_AsString(value->ob_type->tp_repr(value)));
strcat(str,buffer);
@@ -174,9 +201,10 @@ static PyObject *BonesDict_repr(BPy_BonesDict *self)
//This tells how to 'tear-down' our object when ref count hits 0
static void BonesDict_dealloc(BPy_BonesDict * self)
{
- Py_DECREF(self->dict);
- Py_DECREF(self->editBoneDict);
- ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
+ Py_DECREF(self->bonesMap);
+ Py_DECREF(self->editbonesMap);
+ BLI_freelistN(&self->editbones);
+ BonesDict_Type.tp_free(self);
return;
}
//------------------------mp_length
@@ -184,9 +212,9 @@ static void BonesDict_dealloc(BPy_BonesDict * self)
int BonesDict_len(BPy_BonesDict *self)
{
if (self->editmode_flag){
- return PyDict_Size(self->editBoneDict);
+ return BLI_countlist(&self->editbones);
}else{
- return PyDict_Size(self->dict);
+ return BLI_countlist(self->bones);
}
}
//-----------------------mp_subscript
@@ -196,9 +224,9 @@ PyObject *BonesDict_GetItem(BPy_BonesDict *self, PyObject* key)
PyObject *value = NULL;
if (self->editmode_flag){
- value = PyDict_GetItem(self->editBoneDict, key);
+ value = PyDict_GetItem(self->editbonesMap, key);
}else{
- value = PyDict_GetItem(self->dict, key);
+ value = PyDict_GetItem(self->bonesMap, key);
}
if(value == NULL){
return EXPP_incr_ret(Py_None);
@@ -209,29 +237,106 @@ PyObject *BonesDict_GetItem(BPy_BonesDict *self, PyObject* key)
//This does dict assignment - Bones['key'] = value
int BonesDict_SetItem(BPy_BonesDict *self, PyObject *key, PyObject *value)
{
- char *key_str = "", *name = "", *misc = "";
- static char *kwlist[] = {"name", "misc", NULL};
+ BPy_EditBone *editbone_for_deletion;
+ struct EditBone *editbone = NULL;
+ char *key_str = "";
- //Get the key name
- if(key && PyString_Check(key)){
- key_str = PyString_AsString(key);
- }else{
- goto AttributeError;
- }
-
- //Parse the value for assignment
- if(value && PyDict_Check(value)){
- if(!PyArg_ParseTupleAndKeywords(Py_BuildValue("()"), value, "|ss", kwlist, &name, &misc)){
+ 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(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);
+
+ //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);
+ }
+ }
+
+ //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);
+ 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;
+ /*any parent's were connected to this we must remove the flag
+ or else the 'root' ball doesn't get draw*/
+ if (editbone->flag & BONE_CONNECTED)
+ editbone->flag &= ~BONE_CONNECTED;
+ }
+ BLI_freelinkN(&self->editbones, editbone_for_deletion->editbone);
+ if(PyDict_DelItem(self->editbonesMap, key) == -1)
+ goto RuntimeError;
+ }else{
+ goto KeyError;
+ }
+ }
+ return 0;
}else{
- goto AttributeError;
+ goto AttributeError2;
}
- return 0;
+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 (optional) name='string', misc='string'");
+ 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!");
}
//------------------TYPE_OBECT DEFINITION--------------------------
//Mapping Protocol
@@ -242,35 +347,35 @@ static PyMappingMethods BonesDict_MapMethods = {
};
//BonesDict TypeObject
PyTypeObject BonesDict_Type = {
- PyObject_HEAD_INIT(NULL) //tp_head
+ PyObject_HEAD_INIT(NULL) //tp_head
0, //tp_internal
"BonesDict", //tp_name
- sizeof(BPy_BonesDict), //tp_basicsize
+ sizeof(BPy_BonesDict), //tp_basicsize
0, //tp_itemsize
- (destructor)BonesDict_dealloc, //tp_dealloc
+ (destructor)BonesDict_dealloc, //tp_dealloc
0, //tp_print
0, //tp_getattr
0, //tp_setattr
0, //tp_compare
- (reprfunc) BonesDict_repr, //tp_repr
+ (reprfunc) BonesDict_repr, //tp_repr
0, //tp_as_number
0, //tp_as_sequence
- &BonesDict_MapMethods, //tp_as_mapping
+ &BonesDict_MapMethods, //tp_as_mapping
0, //tp_hash
0, //tp_call
0, //tp_str
0, //tp_getattro
0, //tp_setattro
0, //tp_as_buffer
- Py_TPFLAGS_DEFAULT, //tp_flags
- BPy_BonesDict_doc, //tp_doc
+ Py_TPFLAGS_DEFAULT, //tp_flags
+ BPy_BonesDict_doc, //tp_doc
0, //tp_traverse
0, //tp_clear
0, //tp_richcompare
0, //tp_weaklistoffset
0, //tp_iter
0, //tp_iternext
- BPy_BonesDict_methods, //tp_methods
+ BPy_BonesDict_methods, //tp_methods
0, //tp_members
0, //tp_getset
0, //tp_base
@@ -278,9 +383,9 @@ PyTypeObject BonesDict_Type = {
0, //tp_descr_get
0, //tp_descr_set
0, //tp_dictoffset
- 0, //tp_init
+ 0, //tp_init
0, //tp_alloc
- (newfunc)BonesDict_new, //tp_new
+ 0, //tp_new
0, //tp_free
0, //tp_is_gc
0, //tp_bases
@@ -290,233 +395,87 @@ PyTypeObject BonesDict_Type = {
0, //tp_weaklist
0 //tp_del
};
-//-----------------(internal)
-static int BonesDict_Init(PyObject *dictionary, ListBase *bones){
- Bone *bone = NULL;
- PyObject *py_bone = NULL;
+//-----------------------PyBonesDict_FromPyArmature
+static PyObject *PyBonesDict_FromPyArmature(BPy_Armature *py_armature)
+{
+ BPy_BonesDict *py_BonesDict = NULL;
- for (bone = bones->first; bone; bone = bone->next){
- py_bone = PyBone_FromBone(bone);
- if (py_bone == NULL)
- return -1;
+ //create py object
+ py_BonesDict = (BPy_BonesDict *)BonesDict_Type.tp_alloc(&BonesDict_Type, 0);
+ if (!py_BonesDict)
+ goto RuntimeError;
- if(PyDict_SetItem(dictionary, PyString_FromString(bone->name), py_bone) == -1){
- goto RuntimeError;
- }
- if (bone->childbase.first)
- BonesDict_Init(dictionary, &bone->childbase);
- }
- return 0;
+ //create internal dictionaries
+ py_BonesDict->bonesMap = PyDict_New();
+ py_BonesDict->editbonesMap = PyDict_New();
+ if (!py_BonesDict->bonesMap || !py_BonesDict->editbonesMap)
+ goto RuntimeError;
+
+ //set listbase pointer
+ py_BonesDict->bones = &py_armature->armature->bonebase;
+
+ //now that everything is setup - init the mappings
+ if (!BonesDict_InitBones(py_BonesDict))
+ goto RuntimeError;
+ if (!BonesDict_InitEditBones(py_BonesDict))
+ goto RuntimeError;
+
+ //set editmode flag
+ py_BonesDict->editmode_flag = 0;
+
+ return (PyObject*)py_BonesDict;
RuntimeError:
- return EXPP_intError(PyExc_RuntimeError, "%s%s",
- sBoneDictError, "Internal error trying to wrap blender bones!");
+ return EXPP_objError(PyExc_RuntimeError, "%s%s",
+ sBoneDictError, "Failed to create class");
}
//######################### Armature_Type #############################
/*This type represents a thin wrapper around bArmature data types
* internal to blender. It contains the psuedo-dictionary BonesDict
* as an assistant in manipulating it's own bone collection*/
-//#####################################################################
+//#################################################################
//------------------METHOD IMPLEMENTATION------------------------------
-//This is a help function for Armature_makeEditable
-static int PyArmature_InitEditBoneDict(PyObject *dictionary, ListBase *branch)
-{
- struct Bone *bone = NULL;
- PyObject *args, *py_editBone = NULL, *py_bone = NULL;
-
- for (bone = branch->first; bone; bone = bone->next){
-
- //create a new editbone based on the bone data
- py_bone = PyBone_FromBone(bone); //new
- if (py_bone == NULL)
- goto RuntimeError;
-
- args = Py_BuildValue("(O)",py_bone); //new
-
- py_editBone = EditBone_Type.tp_new(&EditBone_Type, args, NULL); //new
- if (py_editBone == NULL)
- goto RuntimeError;
-
- //add the new editbone to the dictionary
- if (PyDict_SetItemString(dictionary, bone->name, py_editBone) == -1)
- goto RuntimeError;
-
- if(bone->childbase.first){
- PyArmature_InitEditBoneDict(dictionary, &bone->childbase);
- }
- }
- return 0;
-
-RuntimeError:
- return EXPP_intError(PyExc_RuntimeError, "%s%s",
- sArmatureError, "Internal error trying to construct an edit armature!");
-
-}
//------------------------Armature.makeEditable()
static PyObject *Armature_makeEditable(BPy_Armature *self)
{
- if (PyArmature_InitEditBoneDict(((BPy_BonesDict*)self->Bones)->editBoneDict,
- &self->armature->bonebase) == -1){
- return NULL; //error already set
- }
- ((BPy_BonesDict*)self->Bones)->editmode_flag = 1;
- return EXPP_incr_ret(Py_None);
-}
-
-static void PyArmature_FixRolls(ListBase *branch, PyObject *dictionary)
-{
- float premat[3][3],postmat[3][3];
- float difmat[3][3],imat[3][3], delta[3];
- BPy_EditBone *py_editBone = NULL;
- struct Bone *bone = NULL;
- int keyCheck = -1;
-
- for (bone = branch->first; bone; bone = bone->next){
-
- where_is_armature_bone(bone, bone->parent); //set bone_mat, arm_mat, length, etc.
-
- keyCheck = PySequence_Contains(dictionary, PyString_FromString(bone->name));
- if (keyCheck == 1){
-
- py_editBone = (BPy_EditBone*)PyDict_GetItem(dictionary,
- PyString_FromString(bone->name)); //borrowed
- VecSubf (delta, py_editBone->tail, py_editBone->head);
- vec_roll_to_mat3(delta, py_editBone->roll, premat); //pre-matrix
- Mat3CpyMat4(postmat, bone->arm_mat); //post-matrix
- Mat3Inv(imat, premat);
- Mat3MulMat3(difmat, imat, postmat);
-
- bone->roll = (float)-atan(difmat[2][0]/difmat[2][2]); //YEA!!
- if (difmat[0][0]<0.0){
- bone->roll += (float)M_PI;
- }
+ if (self->armature->flag & ARM_EDITMODE)
+ goto AttributeError;
- where_is_armature_bone(bone, bone->parent); //gotta do it again...
- }else if (keyCheck == 0){
- //oops we couldn't find it
- }else{
- //error
- }
- PyArmature_FixRolls (&bone->childbase, dictionary);
- }
-}
-//------------------------(internal)EditBoneDict_CheckForKey
-static BPy_EditBone *EditBoneDict_CheckForKey(BPy_BonesDict *dictionary, char *name)
-{
- BPy_EditBone *editbone;
- PyObject *value, *key;
- int pos = 0;
+ make_boneList(&self->Bones->editbones, self->Bones->bones, NULL);
+ if (!BonesDict_InitEditBones(self->Bones))
+ return NULL;
+ self->Bones->editmode_flag = 1;
+ return EXPP_incr_ret(Py_None);
- while (PyDict_Next(dictionary->editBoneDict, &pos, &key, &value)) {
- editbone = (BPy_EditBone *)value;
- if (STREQ(editbone->name, name)){
- Py_INCREF(editbone);
- return editbone;
- }
- }
- return NULL;
+AttributeError:
+ return EXPP_objError(PyExc_AttributeError, "%s%s",
+ sArmatureBadArgs, "The armature cannot be placed manually in editmode before you call makeEditable()!");
}
-//------------------------Armature.saveChanges()
-static PyObject *Armature_saveChanges(BPy_Armature *self)
+//------------------------Armature.update()
+//This is a bit ugly because you need an object link to do this
+static PyObject *Armature_update(BPy_Armature *self)
{
- float M_boneRest[3][3], M_parentRest[3][3];
- float iM_parentRest[3][3], delta[3];
- BPy_EditBone *parent = NULL, *editbone = NULL;
- struct Bone *bone = NULL;
- struct Object *obj = NULL;
- PyObject *key, *value;
- int pos = 0;
+ Object *obj = NULL;
- //empty armature of old bones
- free_bones(self->armature);
-
- //create a new set based on the editbones
- while (PyDict_Next(((BPy_BonesDict*)self->Bones)->editBoneDict, &pos, &key, &value)) {
-
- editbone = (BPy_EditBone*)value;
- bone = MEM_callocN (sizeof(Bone), "bone");
- editbone->temp = bone; //save temp pointer
-
- strcpy (bone->name, editbone->name);
- memcpy (bone->head, editbone->head, sizeof(float)*3);
- memcpy (bone->tail, editbone->tail, sizeof(float)*3);
- bone->flag= editbone->flag;
- bone->roll = 0.0f; //is fixed later
- bone->weight = editbone->weight;
- bone->dist = editbone->dist;
- bone->xwidth = editbone->xwidth;
- bone->zwidth = editbone->zwidth;
- bone->ease1= editbone->ease1;
- bone->ease2= editbone->ease2;
- bone->rad_head= editbone->rad_head;
- bone->rad_tail= editbone->rad_tail;
- bone->segments= editbone->segments;
- bone->boneclass = 0;
- }
-
- pos = 0;
- //place bones in their correct heirarchy
- while (PyDict_Next(((BPy_BonesDict*)self->Bones)->editBoneDict,
- &pos, &key, &value)) {
-
- editbone = (BPy_EditBone*)value;
- bone = editbone->temp; //get bone pointer
-
- if (!STREQ(editbone->parent, "")){
- parent = EditBoneDict_CheckForKey((BPy_BonesDict*)self->Bones, editbone->parent);
- if(parent != NULL){
-
- //parent found in dictionary
- bone->parent = parent->temp;
- BLI_addtail (&parent->temp->childbase, bone);
- //Parenting calculations
- VecSubf (delta, parent->tail, parent->head);
- vec_roll_to_mat3(delta, parent->roll, M_parentRest); //M_parentRest = parent matrix
- VecSubf (delta, editbone->tail, editbone->head);
- vec_roll_to_mat3(delta, editbone->roll, M_boneRest); //M_boneRest = bone matrix
- Mat3Inv(iM_parentRest, M_parentRest); //iM_parentRest = 1/parent matrix
- //get head/tail
- VecSubf (bone->head, editbone->head, parent->tail);
- VecSubf (bone->tail, editbone->tail, parent->tail);
- //put them in parentspace
- Mat3MulVecfl(iM_parentRest, bone->head);
- Mat3MulVecfl(iM_parentRest, bone->tail);
-
- Py_DECREF(parent);
- }else{
- //was not found - most likely parent was deleted
- parent = NULL;
- BLI_addtail (&self->armature->bonebase, bone);
- }
- }else{
- BLI_addtail (&self->armature->bonebase, bone);
- }
+ for (obj = G.main->object.first; obj; obj = obj->id.next){
+ if (obj->data == self->armature)
+ break;
}
- //fix rolls and generate matrices
- PyArmature_FixRolls(&self->armature->bonebase,
- ((BPy_BonesDict*)self->Bones)->editBoneDict);
-
- //update linked objects
- for(obj = G.main->object.first; obj; obj = obj->id.next) {
- if(obj->data == self->armature){
- armature_rebuild_pose(obj, self->armature);
- }
+ if (obj){
+ editbones_to_armature (&self->Bones->editbones, obj);
+ if (!BonesDict_InitBones(self->Bones))
+ return NULL;
+ self->Bones->editmode_flag = 0;
+ }else{
+ goto AttributeError;
}
- DAG_object_flush_update(G.scene, obj, OB_RECALC_DATA);
-
- //clear the editbone dictionary and set edit flag
- PyDict_Clear(((BPy_BonesDict*)self->Bones)->editBoneDict);
- ((BPy_BonesDict*)self->Bones)->editmode_flag = 0;
-
- //rebuild py_bones
- PyDict_Clear(((BPy_BonesDict*)self->Bones)->dict);
- if (BonesDict_Init(((BPy_BonesDict*)self->Bones)->dict,
- &self->armature->bonebase) == -1)
- return NULL; //error string already set
-
return EXPP_incr_ret(Py_None);
+
+AttributeError:
+ return EXPP_objError(PyExc_AttributeError, "%s%s",
+ sArmatureBadArgs, "The armature must be linked to an object before you can save changes!");
}
//------------------ATTRIBUTE IMPLEMENTATION---------------------------
//------------------------Armature.autoIK (getter)
@@ -881,7 +840,7 @@ AttributeError:
//Gets the name of the armature
static PyObject *Armature_getBoneDict(BPy_Armature *self, void *closure)
{
- return EXPP_incr_ret(self->Bones);
+ return EXPP_incr_ret((PyObject*)self->Bones);
}
//------------------------Armature.bones (setter)
//Sets the name of the armature
@@ -899,17 +858,15 @@ AttributeError:
//------------------------tp_doc
//The __doc__ string for this object
static char BPy_Armature_doc[] = "This object wraps a Blender Armature object.";
-
//------------------------tp_methods
//This contains a list of all methods the object contains
static PyMethodDef BPy_Armature_methods[] = {
{"makeEditable", (PyCFunction) Armature_makeEditable, METH_NOARGS,
"() - Unlocks the ability to modify armature bones"},
- {"saveChanges", (PyCFunction) Armature_saveChanges, METH_NOARGS,
+ {"update", (PyCFunction) Armature_update, METH_NOARGS,
"() - Rebuilds the armature based on changes to bones since the last call to makeEditable"},
{NULL}
};
-
//------------------------tp_getset
//This contains methods for attributes that require checking
static PyGetSetDef BPy_Armature_getset[] = {
@@ -948,7 +905,6 @@ static PyObject *Armature_new(PyTypeObject *type, PyObject *args, PyObject *kwds
{
BPy_Armature *py_armature = NULL;
bArmature *bl_armature;
- int success;
bl_armature = add_armature();
if(bl_armature) {
@@ -960,13 +916,11 @@ static PyObject *Armature_new(PyTypeObject *type, PyObject *args, PyObject *kwds
py_armature->armature = bl_armature;
- py_armature->Bones = BonesDict_new(&BonesDict_Type, NULL, NULL);
- if (py_armature->Bones == NULL)
+ //create armature.bones
+ py_armature->Bones = (BPy_BonesDict*)PyBonesDict_FromPyArmature(py_armature);
+ if (!py_armature->Bones)
goto RuntimeError;
- success = BonesDict_Init(((BPy_BonesDict*)py_armature->Bones)->dict, &bl_armature->bonebase);
- if (success == -1)
- return NULL; //error string already set
} else {
goto RuntimeError;
}
@@ -995,7 +949,6 @@ static int Armature_init(BPy_Armature *self, PyObject *args, PyObject *kwds)
PyOS_snprintf(buf, sizeof(buf), "%s", name);
rename_id(&self->armature->id, buf);
}
-
return 0;
AttributeError:
@@ -1009,21 +962,19 @@ static PyObject *Armature_richcmpr(BPy_Armature *self, PyObject *v, int op)
{
return EXPP_incr_ret(Py_None);
}
-
//------------------------tp_repr
//This is the string representation of the object
static PyObject *Armature_repr(BPy_Armature *self)
{
return PyString_FromFormat( "[Armature: \"%s\"]", self->armature->id.name + 2 ); //*new*
}
-
//------------------------tp_dealloc
//This tells how to 'tear-down' our object when ref count hits 0
///tp_dealloc
static void Armature_dealloc(BPy_Armature * self)
{
Py_DECREF(self->Bones);
- ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
+ Armature_Type.tp_free(self);
return;
}
//------------------TYPE_OBECT DEFINITION--------------------------
@@ -1093,7 +1044,7 @@ static PyObject *M_Armature_Get(PyObject * self, PyObject * args)
size = PySequence_Length(args);
if (size == 1) {
seq = PySequence_GetItem(args, 0); //*new*
- if (seq == NULL)
+ if (!seq)
goto RuntimeError;
if(!PyString_Check(seq)){
if (PySequence_Check(seq)) {
@@ -1110,7 +1061,7 @@ static PyObject *M_Armature_Get(PyObject * self, PyObject * args)
if(!PyString_Check(seq)){
for(i = 0; i < size; i++){
item = PySequence_GetItem(seq, i); //*new*
- if (item == NULL) {
+ if (!item) {
Py_DECREF(seq);
goto RuntimeError;
}
@@ -1125,7 +1076,7 @@ static PyObject *M_Armature_Get(PyObject * self, PyObject * args)
//GET ARMATURES
if(size != 1){
dict = PyDict_New(); //*new*
- if(dict == NULL){
+ if(!dict){
Py_DECREF(seq);
goto RuntimeError;
}
@@ -1138,6 +1089,7 @@ static PyObject *M_Armature_Get(PyObject * self, PyObject * args)
EXPP_decr3(seq, dict, py_armature);
goto RuntimeError;
}
+ Py_DECREF(py_armature);
data = ((ID*)data)->next;
}
Py_DECREF(seq);
@@ -1153,16 +1105,18 @@ static PyObject *M_Armature_Get(PyObject * self, PyObject * args)
EXPP_decr3(seq, dict, py_armature);
goto RuntimeError;
}
+ Py_DECREF(py_armature);
}else{
if(PyDict_SetItemString(dict, name, Py_None) == -1){ //add to dictionary
EXPP_decr2(seq, dict);
goto RuntimeError;
}
+ Py_DECREF(Py_None);
}
}
Py_DECREF(seq);
}
- return dict; //transfering ownership to caller
+ return dict;
}else{ //GET SINGLE ARMATURE
if(!PyString_Check(seq)){ //This handles the bizarre case where (['s']) is passed
item = PySequence_GetItem(seq, 0); //*new*
@@ -1206,22 +1160,18 @@ struct PyMethodDef M_Armature_methods[] = {
PyObject *PyArmature_FromArmature(struct bArmature *armature)
{
BPy_Armature *py_armature = NULL;
- int success;
+ //create armature type
py_armature = (BPy_Armature*)Armature_Type.tp_alloc(&Armature_Type, 0); //*new*
- if (py_armature == NULL)
+ if (!py_armature)
goto RuntimeError;
-
py_armature->armature = armature;
- py_armature->Bones = BonesDict_new(&BonesDict_Type, NULL, NULL); //*new*
- if (py_armature->Bones == NULL)
+ //create armature.bones
+ py_armature->Bones = (BPy_BonesDict*)PyBonesDict_FromPyArmature(py_armature);
+ if (!py_armature->Bones)
goto RuntimeError;
- success = BonesDict_Init(((BPy_BonesDict*)py_armature->Bones)->dict, &armature->bonebase);
- if (success == -1)
- return NULL; //error string already set
-
return (PyObject *) py_armature;
RuntimeError:
@@ -1241,7 +1191,7 @@ PyObject *Armature_Init(void)
//Initializes TypeObject.ob_type
if (PyType_Ready(&Armature_Type) < 0 || PyType_Ready(&BonesDict_Type) < 0 ||
- PyType_Ready(&EditBone_Type) < 0 || PyType_Ready(&Bone_Type) < 0){
+ PyType_Ready(&EditBone_Type) < 0 || PyType_Ready(&Bone_Type) < 0) {
return EXPP_incr_ret(Py_None);
}
@@ -1250,10 +1200,12 @@ PyObject *Armature_Init(void)
"The Blender Armature module");
//Add TYPEOBJECTS to the module
- PyModule_AddObject(module, "ArmatureType",
+ PyModule_AddObject(module, "Armature",
EXPP_incr_ret((PyObject *)&Armature_Type)); //*steals*
- PyModule_AddObject(module, "BoneType",
+ PyModule_AddObject(module, "Bone",
EXPP_incr_ret((PyObject *)&Bone_Type)); //*steals*
+ PyModule_AddObject(module, "Editbone",
+ EXPP_incr_ret((PyObject *)&EditBone_Type)); //*steals*
//Add CONSTANTS to the module
PyModule_AddObject(module, "CONNECTED",
@@ -1266,13 +1218,12 @@ PyObject *Armature_Init(void)
EXPP_incr_ret(PyConstant_NewInt("MULTIPLY", BONE_MULT_VG_ENV)));
PyModule_AddObject(module, "HIDDEN_EDIT",
EXPP_incr_ret(PyConstant_NewInt("HIDDEN_EDIT", BONE_HIDDEN_A)));
-
- PyModule_AddObject(module, "BONESPACE",
- EXPP_incr_ret(PyConstant_NewString("BONESPACE", "bone_space")));
- PyModule_AddObject(module, "ARMATURESPACE",
- EXPP_incr_ret(PyConstant_NewString("ARMATURESPACE", "armature_space")));
- PyModule_AddObject(module, "WORLDSPACE",
- EXPP_incr_ret(PyConstant_NewString("WORLDSPACE", "world_space")));
+ PyModule_AddObject(module, "ROOT_SELECTED",
+ EXPP_incr_ret(PyConstant_NewInt("ROOT_SELECTED", BONE_ROOTSEL)));
+ PyModule_AddObject(module, "BONE_SELECTED",
+ EXPP_incr_ret(PyConstant_NewInt("BONE_SELECTED", BONE_SELECTED)));
+ PyModule_AddObject(module, "TIP_SELECTED",
+ EXPP_incr_ret(PyConstant_NewInt("TIP_SELECTED", BONE_TIPSEL)));
PyModule_AddObject(module, "OCTAHEDRON",
EXPP_incr_ret(PyConstant_NewInt("OCTAHEDRON", ARM_OCTA)));
diff --git a/source/blender/python/api2_2x/Armature.h b/source/blender/python/api2_2x/Armature.h
index 473a2392931..4d14b41fdc8 100644
--- a/source/blender/python/api2_2x/Armature.h
+++ b/source/blender/python/api2_2x/Armature.h
@@ -43,18 +43,19 @@ PyObject *Armature_Init( void );
PyTypeObject Armature_Type;
PyTypeObject BonesDict_Type;
//-------------------STRUCT DEFINITION---------------------------
-
typedef struct {
PyObject_HEAD
- PyObject *dict;
- PyObject *editBoneDict;
- short editmode_flag; //1 = in , 0 = not in
+ PyObject *bonesMap; //wrapper for bones
+ PyObject *editbonesMap; //wrapper for editbones
+ ListBase *bones; //pointer to armature->bonebase
+ ListBase editbones; //allocated list of EditBones
+ short editmode_flag; //1 = in , 0 = not in
} BPy_BonesDict;
typedef struct {
PyObject_HEAD
struct bArmature * armature;
- PyObject *Bones;
+ BPy_BonesDict *Bones; //BPy_BonesDict
} BPy_Armature;
//-------------------VISIBLE PROTOTYPES-------------------------
diff --git a/source/blender/python/api2_2x/Bone.c b/source/blender/python/api2_2x/Bone.c
index 2fe7faf3b90..d4f59e67ee5 100644
--- a/source/blender/python/api2_2x/Bone.c
+++ b/source/blender/python/api2_2x/Bone.c
@@ -36,6 +36,11 @@
#include "gen_utils.h"
#include "BKE_armature.h"
#include "Mathutils.h"
+#include "BKE_library.h"
+
+//these must come in this order
+#include "DNA_object_types.h" //1
+#include "BIF_editarmature.h" //2
//------------------------ERROR CODES---------------------------------
//This is here just to make me happy and to have more consistant error strings :)
@@ -43,6 +48,8 @@ static const char sEditBoneError[] = "EditBone (internal) - Error: ";
static const char sEditBoneBadArgs[] = "EditBone (internal) - Bad Arguments: ";
static const char sBoneError[] = "Bone - Error: ";
static const char sBoneBadArgs[] = "Bone - Bad Arguments: ";
+static const char sConstListError[] = "ConstantList - Error: ";
+static const char sConstListBadArgs[] = "ConstantList - Bad Arguments: ";
//----------------------(internal)
//gets the bone->roll (which is a localspace roll) and puts it in parentspace
@@ -68,18 +75,53 @@ double boneRoll_ToArmatureSpace(struct Bone *bone)
}
return roll; //result is in radians
}
-//################## EditBone_Type (internal) ########################
+
+//################## EditBone_Type ########################
/*This type is a wrapper for a tempory bone. This is an 'unparented' bone
*object. The armature->bonebase will be calculated from these temporary
*python tracked objects.*/
-//#####################################################################
+//####################################################
//------------------METHOD IMPLEMENTATIONS-----------------------------
+//-------------------------EditBone.hasParent()
+PyObject *EditBone_hasParent(BPy_EditBone *self)
+{
+ if (self->editbone){
+ if (self->editbone->parent)
+ return EXPP_incr_ret(Py_True);
+ else
+ return EXPP_incr_ret(Py_False);
+ }else{
+ goto AttributeError;
+ }
+
+AttributeError:
+ return EXPP_objError(PyExc_AttributeError, "%s%s%s",
+ sEditBoneError, ".hasParent: ", "EditBone must be added to the armature first");
+}
+//-------------------------EditBone.clearParent()
+PyObject *EditBone_clearParent(BPy_EditBone *self)
+{
+ if (self->editbone){
+ if (self->editbone->parent)
+ self->editbone->parent = NULL;
+ return EXPP_incr_ret(Py_None);
+ }else{
+ goto AttributeError;
+ }
+
+AttributeError:
+ return EXPP_objError(PyExc_AttributeError, "%s%s%s",
+ sEditBoneError, ".clearParent: ", "EditBone must be added to the armature first");
+}
//------------------ATTRIBUTE IMPLEMENTATION---------------------------
//------------------------EditBone.name (get)
static PyObject *EditBone_getName(BPy_EditBone *self, void *closure)
{
- return PyString_FromString(self->name);
+ if (self->editbone)
+ return PyString_FromString(self->editbone->name);
+ else
+ return PyString_FromString(self->name);
}
//------------------------EditBone.name (set)
//check for char[] overflow here...
@@ -90,7 +132,10 @@ static int EditBone_setName(BPy_EditBone *self, PyObject *value, void *closure)
if (!PyArg_Parse(value, "s", &name))
goto AttributeError;
- BLI_strncpy(self->name, name, 32);
+ if (self->editbone)
+ BLI_strncpy(self->editbone->name, name, 32);
+ else
+ BLI_strncpy(self->name, name, 32);
return 0;
AttributeError:
@@ -100,43 +145,116 @@ AttributeError:
//------------------------EditBone.roll (get)
static PyObject *EditBone_getRoll(BPy_EditBone *self, void *closure)
{
- return Py_BuildValue("{s:O}",
- "ARMATURESPACE", PyFloat_FromDouble((self->roll * (180/Py_PI))));
+ if (self->editbone){
+ return Py_BuildValue("f", PyFloat_FromDouble((self->editbone->roll * (180/Py_PI))));
+ }else{
+ return Py_BuildValue("f", PyFloat_FromDouble((self->roll * (180/Py_PI))));
+ }
}
//------------------------EditBone.roll (set)
static int EditBone_setRoll(BPy_EditBone *self, PyObject *value, void *closure)
{
- printf("Sorry this isn't implemented yet.... :/");
- return 1;
+ float roll = 0.0f;
+
+ if (!PyArg_Parse(value, "f", &roll))
+ goto AttributeError;
+
+ if (self->editbone){
+ self->editbone->roll = (float)(roll * (Py_PI/180));
+ }else{
+ self->roll = (float)(roll * (Py_PI/180));
+ }
+ return 0;
+
+AttributeError:
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sEditBoneError, ".roll: ", "expects a float");
}
//------------------------EditBone.head (get)
static PyObject *EditBone_getHead(BPy_EditBone *self, void *closure)
{
- return Py_BuildValue("{s:O, s:O}",
- "BONESPACE", newVectorObject(self->head, 3, Py_WRAP));;
+ if (self->editbone){
+ return newVectorObject(self->editbone->head, 3, Py_WRAP);
+ }else{
+ return newVectorObject(self->head, 3, Py_NEW);
+ }
}
//------------------------EditBone.head (set)
static int EditBone_setHead(BPy_EditBone *self, PyObject *value, void *closure)
{
- printf("Sorry this isn't implemented yet.... :/");
- return 1;
+ VectorObject *vec = NULL;
+ int x;
+
+ if (!PyArg_Parse(value, "O!", &vector_Type, &vec))
+ goto AttributeError;
+ if (vec->size != 3)
+ goto AttributeError2;
+
+ if (self->editbone){
+ for (x = 0; x < 3; x++){
+ self->editbone->head[x] = vec->vec[x];
+ }
+ }else{
+ for (x = 0; x < 3; x++){
+ self->head[x] = vec->vec[x];
+ }
+ }
+ return 0;
+
+AttributeError:
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sEditBoneError, ".head: ", "expects a Vector Object");
+
+AttributeError2:
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sEditBoneError, ".head: ", "Vector Object needs to be (x,y,z)");
}
//------------------------EditBone.tail (get)
static PyObject *EditBone_getTail(BPy_EditBone *self, void *closure)
{
- return Py_BuildValue("{s:O, s:O}",
- "BONESPACE", newVectorObject(self->tail, 3, Py_WRAP));
+ if (self->editbone){
+ return newVectorObject(self->editbone->tail, 3, Py_WRAP);
+ }else{
+ return newVectorObject(self->tail, 3, Py_NEW);
+ }
}
//------------------------EditBone.tail (set)
static int EditBone_setTail(BPy_EditBone *self, PyObject *value, void *closure)
{
- printf("Sorry this isn't implemented yet.... :/");
- return 1;
+ VectorObject *vec = NULL;
+ int x;
+
+ if (!PyArg_Parse(value, "O!", &vector_Type, &vec))
+ goto AttributeError;
+ if (vec->size != 3)
+ goto AttributeError2;
+
+ if (self->editbone){
+ for (x = 0; x < 3; x++){
+ self->editbone->tail[x] = vec->vec[x];
+ }
+ }else{
+ for (x = 0; x < 3; x++){
+ self->tail[x] = vec->vec[x];
+ }
+ }
+ return 0;
+
+AttributeError:
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sEditBoneError, ".tail: ", "expects a Vector Object");
+
+AttributeError2:
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sEditBoneError, ".tail: ", "Vector Object needs to be (x,y,z)");
}
//------------------------EditBone.weight (get)
static PyObject *EditBone_getWeight(BPy_EditBone *self, void *closure)
{
- return PyFloat_FromDouble(self->weight);
+ if (self->editbone)
+ return PyFloat_FromDouble(self->editbone->weight);
+ else
+ return PyFloat_FromDouble(self->weight);
}
//------------------------EditBone.weight (set)
static int EditBone_setWeight(BPy_EditBone *self, PyObject *value, void *closure)
@@ -147,7 +265,10 @@ static int EditBone_setWeight(BPy_EditBone *self, PyObject *value, void *closure
goto AttributeError;
CLAMP(weight, 0.0f, 1000.0f);
- self->weight = weight;
+ if (self->editbone)
+ self->editbone->weight = weight;
+ else
+ self->weight = weight;
return 0;
AttributeError:
@@ -157,7 +278,10 @@ AttributeError:
//------------------------EditBone.deform_dist (get)
static PyObject *EditBone_getDeform_dist(BPy_EditBone *self, void *closure)
{
- return PyFloat_FromDouble(self->dist);
+ if (self->editbone)
+ return PyFloat_FromDouble(self->editbone->dist);
+ else
+ return PyFloat_FromDouble(self->dist);
}
//------------------------EditBone.deform_dist (set)
static int EditBone_setDeform_dist(BPy_EditBone *self, PyObject *value, void *closure)
@@ -168,7 +292,10 @@ static int EditBone_setDeform_dist(BPy_EditBone *self, PyObject *value, void *cl
goto AttributeError;
CLAMP(deform, 0.0f, 1000.0f);
- self->dist = deform;
+ if (self->editbone)
+ self->editbone->dist = deform;
+ else
+ self->dist = deform;
return 0;
AttributeError:
@@ -178,7 +305,10 @@ AttributeError:
//------------------------EditBone.subdivisions (get)
static PyObject *EditBone_getSubdivisions(BPy_EditBone *self, void *closure)
{
- return PyInt_FromLong(self->segments);
+ if (self->editbone)
+ return PyInt_FromLong(self->editbone->segments);
+ else
+ return PyInt_FromLong(self->segments);
}
//------------------------EditBone.subdivisions (set)
static int EditBone_setSubdivisions(BPy_EditBone *self, PyObject *value, void *closure)
@@ -189,7 +319,10 @@ static int EditBone_setSubdivisions(BPy_EditBone *self, PyObject *value, void *c
goto AttributeError;
CLAMP(segs, 1, 32);
- self->segments = (short)segs;
+ if (self->editbone)
+ self->editbone->segments = (short)segs;
+ else
+ self->segments = (short)segs;
return 0;
AttributeError:
@@ -202,29 +335,76 @@ static PyObject *EditBone_getOptions(BPy_EditBone *self, void *closure)
PyObject *list = NULL;
list = PyList_New(0);
- if (list == NULL)
+ if (!list)
goto RuntimeError;
- if(self->flag & BONE_CONNECTED)
- if (PyList_Append(list,
- EXPP_GetModuleConstant("Blender.Armature", "CONNECTED")) == -1)
- goto RuntimeError;
- if(self->flag & BONE_HINGE)
- if (PyList_Append(list,
- EXPP_GetModuleConstant("Blender.Armature", "HINGE")) == -1)
- goto RuntimeError;
- if(self->flag & BONE_NO_DEFORM)
- if (PyList_Append(list,
- EXPP_GetModuleConstant("Blender.Armature", "NO_DEFORM")) == -1)
- goto RuntimeError;
- if(self->flag & BONE_MULT_VG_ENV)
- if (PyList_Append(list,
- EXPP_GetModuleConstant("Blender.Armature", "MULTIPLY")) == -1)
- goto RuntimeError;
- if(self->flag & BONE_HIDDEN_A)
- if (PyList_Append(list,
- EXPP_GetModuleConstant("Blender.Armature", "HIDDEN_EDIT")) == -1)
- goto RuntimeError;
+ if(self->editbone){
+ if(self->editbone->flag & BONE_CONNECTED)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "CONNECTED")) == -1)
+ goto RuntimeError;
+ if(self->editbone->flag & BONE_HINGE)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "HINGE")) == -1)
+ goto RuntimeError;
+ if(self->editbone->flag & BONE_NO_DEFORM)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "NO_DEFORM")) == -1)
+ goto RuntimeError;
+ if(self->editbone->flag & BONE_MULT_VG_ENV)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "MULTIPLY")) == -1)
+ goto RuntimeError;
+ if(self->editbone->flag & BONE_HIDDEN_A)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "HIDDEN_EDIT")) == -1)
+ goto RuntimeError;
+ if(self->editbone->flag & BONE_ROOTSEL)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "ROOT_SELECTED")) == -1)
+ goto RuntimeError;
+ if(self->editbone->flag & BONE_SELECTED)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "BONE_SELECTED")) == -1)
+ goto RuntimeError;
+ if(self->editbone->flag & BONE_TIPSEL)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "TIP_SELECTED")) == -1)
+ goto RuntimeError;
+ }else{
+ if(self->flag & BONE_CONNECTED)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "CONNECTED")) == -1)
+ goto RuntimeError;
+ if(self->flag & BONE_HINGE)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "HINGE")) == -1)
+ goto RuntimeError;
+ if(self->flag & BONE_NO_DEFORM)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "NO_DEFORM")) == -1)
+ goto RuntimeError;
+ if(self->flag & BONE_MULT_VG_ENV)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "MULTIPLY")) == -1)
+ goto RuntimeError;
+ if(self->flag & BONE_HIDDEN_A)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "HIDDEN_EDIT")) == -1)
+ goto RuntimeError;
+ if(self->flag & BONE_ROOTSEL)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "ROOT_SELECTED")) == -1)
+ goto RuntimeError;
+ if(self->flag & BONE_SELECTED)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "BONE_SELECTED")) == -1)
+ goto RuntimeError;
+ if(self->flag & BONE_TIPSEL)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "TIP_SELECTED")) == -1)
+ goto RuntimeError;
+ }
return EXPP_incr_ret(list);
@@ -240,13 +420,14 @@ static int EditBone_CheckValidConstant(PyObject *constant)
if (constant){
if (BPy_Constant_Check(constant)){
name = PyDict_GetItemString(((BPy_constant*)constant)->dict, "name");
- if (!name) return 0;
- if (!(STREQ3(PyString_AsString(name), "CONNECTED", "HINGE", "NO_DEFORM")
- || STREQ2(PyString_AsString(name), "MULTIPLY", "HIDDEN_EDIT"))){
- return 0;
- }else{
- return 1;
- }
+ if (!name)
+ return 0;
+ if (!STREQ3(PyString_AsString(name), "CONNECTED", "HINGE", "NO_DEFORM") &&
+ !STREQ3(PyString_AsString(name), "ROOT_SELECTED", "BONE_SELECTED", "TIP_SELECTED") &&
+ !STREQ2(PyString_AsString(name), "MULTIPLY", "HIDDEN_EDIT"))
+ return 0;
+ else
+ return 1;
}else{
return 0;
}
@@ -275,7 +456,19 @@ static int EditBone_setOptions(BPy_EditBone *self, PyObject *value, void *closur
goto AttributeError2;
}
}
- self->flag = new_flag;
+
+ //set the options
+ if(self->editbone){
+ //make sure the 'connected' property is set up correctly
+ if (new_flag & BONE_CONNECTED)
+ if(!self->editbone->parent)
+ goto AttributeError3;
+ else
+ VECCOPY(self->editbone->head, self->editbone->parent->tail);
+ self->editbone->flag = new_flag;
+ }else{
+ self->flag = new_flag;
+ }
return 0;
}else if (BPy_Constant_Check(value)){
if (!EditBone_CheckValidConstant(value))
@@ -283,7 +476,18 @@ static int EditBone_setOptions(BPy_EditBone *self, PyObject *value, void *closur
val = PyDict_GetItemString(((BPy_constant*)value)->dict, "value");
if (PyInt_Check(val)){
numeric_value = (int)PyInt_AS_LONG(val);
- self->flag = numeric_value;
+
+ if(self->editbone){
+ //make sure the 'connected' property is set up correctly
+ if (numeric_value & BONE_CONNECTED)
+ if(!self->editbone->parent)
+ goto AttributeError3;
+ else
+ VECCOPY(self->editbone->head, self->editbone->parent->tail);
+ self->editbone->flag = numeric_value;
+ }else{
+ self->flag = numeric_value;
+ }
return 0;
}else{
goto AttributeError2;
@@ -294,64 +498,112 @@ static int EditBone_setOptions(BPy_EditBone *self, PyObject *value, void *closur
AttributeError1:
return EXPP_intError(PyExc_AttributeError, "%s%s%s",
- sEditBoneError, ".options(): ", "Expects a constant or list of constants");
-
+ sEditBoneError, ".options: ", "Expects a constant or list of constants");
AttributeError2:
return EXPP_intError(PyExc_AttributeError, "%s%s%s",
- sEditBoneError, ".options(): ", "Please use a constant defined in the Armature module");
+ sEditBoneError, ".options: ", "Please use a constant defined in the Armature module");
+AttributeError3:
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sEditBoneError, ".options: ", "You can't connect to parent because no parent is set");
}
//------------------------EditBone.parent (get)
static PyObject *EditBone_getParent(BPy_EditBone *self, void *closure)
{
- //if (!STREQ(self->parent, ""))
- // return PyString_FromString(PyBone_FromBone(self->parent));
- //else
- printf("Sorry this isn't implemented yet.... :/");
- return EXPP_incr_ret(Py_None);
+ if (self->editbone){
+ if (self->editbone->parent)
+ return PyEditBone_FromEditBone(self->editbone->parent);
+ else
+ return EXPP_incr_ret(Py_None);
+ }else{
+ return EXPP_incr_ret(Py_None); //not in the list yet can't have a parent
+ }
}
//------------------------EditBone.parent (set)
static int EditBone_setParent(BPy_EditBone *self, PyObject *value, void *closure)
{
- printf("Sorry this isn't implemented yet.... :/");
- return 1;
-}
+ BPy_EditBone *parent = NULL;
+
+ if (!PyArg_Parse(value, "O!", &EditBone_Type, &parent))
+ goto AttributeError;
+
+ if (!parent->editbone)
+ goto AttributeError2;
-//------------------------EditBone.children (get)
-static PyObject *EditBone_getChildren(BPy_EditBone *self, void *closure)
+ if (self->editbone){
+ self->editbone->parent = parent->editbone;
+ }else{
+ self->parent = parent->editbone;
+ }
+ return 0;
+
+AttributeError:
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sEditBoneError, ".parent: ", "expects a EditBone Object");
+
+AttributeError2:
+ return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+ sEditBoneError, ".parent: ", "This object is not in the armature's bone list!");
+}
+//------------------------EditBone.matrix (get)
+static PyObject *EditBone_getMatrix(BPy_EditBone *self, void *closure)
{
- printf("Sorry this isn't implemented yet.... :/");
- return EXPP_incr_ret(Py_None);
+ float boneMatrix[3][3];
+ float axis[3];
+
+ if (self->editbone){
+ VECSUB(axis, self->editbone->tail, self->editbone->head);
+ vec_roll_to_mat3(axis, self->editbone->roll, boneMatrix);
+ }else{
+ VECSUB(axis, self->tail, self->head);
+ vec_roll_to_mat3(axis, self->roll, boneMatrix);
+ }
+
+ return newMatrixObject((float*)boneMatrix, 3, 3, Py_NEW);
}
-//------------------------EditBone.children (set)
-static int EditBone_setChildren(BPy_EditBone *self, PyObject *value, void *closure)
+//------------------------EditBone.matrix (set)
+static int EditBone_setMatrix(BPy_EditBone *self, PyObject *value, void *closure)
{
printf("Sorry this isn't implemented yet.... :/");
return 1;
}
-//------------------------EditBone.matrix (get)
-static PyObject *EditBone_getMatrix(BPy_EditBone *self, void *closure)
+//------------------------Bone.length (get)
+static PyObject *EditBone_getLength(BPy_EditBone *self, void *closure)
{
- printf("Sorry this isn't implemented yet.... :/");
- return EXPP_incr_ret(Py_None);
+ float delta[3];
+ double dot = 0.0f;
+ int x;
+
+ if (self->editbone){
+ VECSUB(delta, self->editbone->tail, self->editbone->head);
+ for(x = 0; x < 3; x++){
+ dot += (delta[x] * delta[x]);
+ }
+ return PyFloat_FromDouble(sqrt(dot));
+ }else{
+ VECSUB(delta, self->tail, self->head);
+ for(x = 0; x < 3; x++){
+ dot += (delta[x] * delta[x]);
+ }
+ return PyFloat_FromDouble(sqrt(dot));
+ }
}
-//------------------------EditBone.matrix (set)
-static int EditBone_setMatrix(BPy_EditBone *self, PyObject *value, void *closure)
+//------------------------Bone.length (set)
+static int EditBone_setLength(BPy_EditBone *self, PyObject *value, void *closure)
{
printf("Sorry this isn't implemented yet.... :/");
return 1;
}
//------------------TYPE_OBECT IMPLEMENTATION--------------------------
-//TODO: We need to think about the below methods
//------------------------tp_methods
//This contains a list of all methods the object contains
-//static PyMethodDef BPy_Bone_methods[] = {
-// {"clearParent", (PyCFunction) Bone_clearParent, METH_NOARGS,
-// "() - disconnects this bone from it's parent"},
-// {"clearChildren", (PyCFunction) Bone_clearChildren, METH_NOARGS,
-// "() - disconnects all the children from this bone"},
-// {NULL}
-//};
-//------------------------tp_getset
+static PyMethodDef BPy_EditBone_methods[] = {
+ {"hasParent", (PyCFunction) EditBone_hasParent, METH_NOARGS,
+ "() - True/False - Bone has a parent"},
+ {"clearParent", (PyCFunction) EditBone_clearParent, METH_NOARGS,
+ "() - sets the parent to None"},
+ {NULL}
+};
+///------------------------tp_getset
//This contains methods for attributes that require checking
static PyGetSetDef BPy_EditBone_getset[] = {
{"name", (getter)EditBone_getName, (setter)EditBone_setName,
@@ -366,7 +618,7 @@ static PyGetSetDef BPy_EditBone_getset[] = {
"The matrix of the bone", NULL},
{"weight", (getter)EditBone_getWeight, (setter)EditBone_setWeight,
"The weight of the bone in relation to a parented mesh", NULL},
- {"deform_dist", (getter)EditBone_getDeform_dist, (setter)EditBone_setDeform_dist,
+ {"deformDist", (getter)EditBone_getDeform_dist, (setter)EditBone_setDeform_dist,
"The distance at which deformation has effect", NULL},
{"subdivisions", (getter)EditBone_getSubdivisions, (setter)EditBone_setSubdivisions,
"The number of subdivisions (for B-Bones)", NULL},
@@ -374,8 +626,8 @@ static PyGetSetDef BPy_EditBone_getset[] = {
"The options effective on this bone", NULL},
{"parent", (getter)EditBone_getParent, (setter)EditBone_setParent,
"The parent bone of this bone", NULL},
- {"children", (getter)EditBone_getChildren, (setter)EditBone_setChildren,
- "The child bones of this bone", NULL},
+ {"length", (getter)EditBone_getLength, (setter)EditBone_setLength,
+ "The length of this bone", NULL},
{NULL}
};
@@ -383,7 +635,10 @@ static PyGetSetDef BPy_EditBone_getset[] = {
//This is the string representation of the object
static PyObject *EditBone_repr(BPy_EditBone *self)
{
- return PyString_FromFormat( "[EditBone \"%s\"]", self->name );
+ if (self->editbone)
+ return PyString_FromFormat( "[EditBone \"%s\"]", self->editbone->name );
+ else
+ return PyString_FromFormat( "[EditBone \"%s\"]", self->name );
}
//------------------------tp_doc
@@ -395,114 +650,121 @@ designed to act as a wrapper for an 'edit bone'.";
//This methods creates a new object (note it does not initialize it - only the building)
static PyObject *EditBone_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
+ char *name = "myEditBone";
BPy_EditBone *py_editBone = NULL;
- PyObject *py_bone;
- struct Bone *bone;
- int i;
-
- if(!PyArg_ParseTuple(args, "O!", &Bone_Type, &py_bone))
- goto AttributeError;
+ float head[3], tail[3];
py_editBone = (BPy_EditBone*)type->tp_alloc(type, 0); //new
if (py_editBone == NULL)
goto RuntimeError;
- bone = ((BPy_Bone*)py_bone)->bone;
-
- BLI_strncpy(py_editBone->name, bone->name, 32);
- py_editBone->flag = bone->flag;
- py_editBone->length = bone->length;
- py_editBone->weight = bone->weight;
- py_editBone->dist = bone->dist;
- py_editBone->xwidth = bone->xwidth;
- py_editBone->zwidth = bone->zwidth;
- py_editBone->ease1 = bone->ease1;
- py_editBone->ease2 = bone->ease2;
- py_editBone->rad_head = bone->rad_head;
- py_editBone->rad_tail = bone->rad_tail;
- py_editBone->segments = bone->segments;
- py_editBone->temp = NULL;
-
- if (bone->parent){
- BLI_strncpy(py_editBone->parent, bone->parent->name, 32);
- }else{
- BLI_strncpy(py_editBone->parent, "", 32);
- }
+ //this pointer will be set when this bone is placed in ListBase
+ //otherwise this will act as a py_object
+ py_editBone->editbone = NULL;
- py_editBone->roll = (float)boneRoll_ToArmatureSpace(bone);
+ unique_editbone_name(name);
+ BLI_strncpy(py_editBone->name, name, 32);
+ py_editBone->parent = NULL;
+ py_editBone->weight= 1.0f;
+ py_editBone->dist= 0.25f;
+ py_editBone->xwidth= 0.1f;
+ py_editBone->zwidth= 0.1f;
+ py_editBone->ease1= 1.0f;
+ py_editBone->ease2= 1.0f;
+ py_editBone->rad_head= 0.10f;
+ py_editBone->rad_tail= 0.05f;
+ py_editBone->segments= 1;
+ py_editBone->flag = 0;
+ py_editBone->roll = 0.0f;
+
+ head[0] = head[1] = head[2] = 0.0f;
+ tail[1] = tail[2] = 0.0f;
+ tail[0] = 1.0f;
+ VECCOPY(py_editBone->head, head);
+ VECCOPY(py_editBone->tail, tail);
- for (i = 0; i < 3; i++){
- py_editBone->head[i] = bone->arm_head[i];
- py_editBone->tail[i] = bone->arm_tail[i];
- }
return (PyObject*)py_editBone;
RuntimeError:
return EXPP_objError(PyExc_RuntimeError, "%s%s%s",
sEditBoneError, " __new__: ", "Internal Error");
-AttributeError:
- return EXPP_objError(PyExc_AttributeError, "%s%s%s",
- sEditBoneBadArgs, " __new__: ", "Expects PyBone and optional float");
}
//------------------------tp_dealloc
//This tells how to 'tear-down' our object when ref count hits 0
+//the struct EditBone pointer will be handled by the BPy_BonesDict class
static void EditBone_dealloc(BPy_EditBone * self)
{
- ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
+ EditBone_Type.tp_free(self);
return;
}
//------------------TYPE_OBECT DEFINITION--------------------------
PyTypeObject EditBone_Type = {
PyObject_HEAD_INIT(NULL) //tp_head
- 0, //tp_internal
- "EditBone", //tp_name
- sizeof(BPy_EditBone), //tp_basicsize
- 0, //tp_itemsize
- (destructor)EditBone_dealloc, //tp_dealloc
- 0, //tp_print
- 0, //tp_getattr
- 0, //tp_setattr
- 0, //tp_compare
- (reprfunc)EditBone_repr, //tp_repr
- 0, //tp_as_number
- 0, //tp_as_sequence
- 0, //tp_as_mapping
- 0, //tp_hash
- 0, //tp_call
- 0, //tp_str
- 0, //tp_getattro
- 0, //tp_setattro
- 0, //tp_as_buffer
- Py_TPFLAGS_DEFAULT, //tp_flags
- BPy_EditBone_doc, //tp_doc
- 0, //tp_traverse
- 0, //tp_clear
- 0, //tp_richcompare
- 0, //tp_weaklistoffset
- 0, //tp_iter
- 0, //tp_iternext
- 0, //tp_methods
- 0, //tp_members
- BPy_EditBone_getset, //tp_getset
- 0, //tp_base
- 0, //tp_dict
- 0, //tp_descr_get
- 0, //tp_descr_set
- 0, //tp_dictoffset
- 0, //tp_init
- 0, //tp_alloc
- (newfunc)EditBone_new, //tp_new
- 0, //tp_free
- 0, //tp_is_gc
- 0, //tp_bases
- 0, //tp_mro
- 0, //tp_cache
- 0, //tp_subclasses
- 0, //tp_weaklist
- 0 //tp_del
+ 0, //tp_internal
+ "EditBone", //tp_name
+ sizeof(BPy_EditBone), //tp_basicsize
+ 0, //tp_itemsize
+ (destructor)EditBone_dealloc, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ (reprfunc)EditBone_repr, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT, //tp_flags
+ BPy_EditBone_doc, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ BPy_EditBone_methods, //tp_methods
+ 0, //tp_members
+ BPy_EditBone_getset, //tp_getset
+ 0, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ 0, //tp_init
+ 0, //tp_alloc
+ (newfunc)EditBone_new, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0 //tp_del
};
//------------------METHOD IMPLEMENTATIONS--------------------------------
+//-------------------------Bone.hasParent()
+PyObject *Bone_hasParent(BPy_Bone *self)
+{
+ if (self->bone->parent)
+ return EXPP_incr_ret(Py_True);
+ else
+ return EXPP_incr_ret(Py_False);
+}
+//-------------------------Bone.hasChildren()
+PyObject *Bone_hasChildren(BPy_Bone *self)
+{
+ if (self->bone->childbase.first)
+ return EXPP_incr_ret(Py_True);
+ else
+ return EXPP_incr_ret(Py_False);
+}
//------------------ATTRIBUTE IMPLEMENTATIONS-----------------------------
//------------------------Bone.name (get)
static PyObject *Bone_getName(BPy_Bone *self, void *closure)
@@ -514,7 +776,7 @@ static PyObject *Bone_getName(BPy_Bone *self, void *closure)
static int Bone_setName(BPy_Bone *self, PyObject *value, void *closure)
{
return EXPP_intError(PyExc_ValueError, "%s%s",
- sBoneError, "You must first call Armature.makeEditable() to edit the armature");
+ sBoneError, "You must first call .makeEditable() to edit the armature");
}
//------------------------Bone.roll (get)
static PyObject *Bone_getRoll(BPy_Bone *self, void *closure)
@@ -527,7 +789,7 @@ static PyObject *Bone_getRoll(BPy_Bone *self, void *closure)
static int Bone_setRoll(BPy_Bone *self, PyObject *value, void *closure)
{
return EXPP_intError(PyExc_ValueError, "%s%s",
- sBoneError, "You must first call Armature.makeEditable() to edit the armature");
+ sBoneError, "You must first call .makeEditable() to edit the armature");
}
//------------------------Bone.head (get)
static PyObject *Bone_getHead(BPy_Bone *self, void *closure)
@@ -540,7 +802,7 @@ static PyObject *Bone_getHead(BPy_Bone *self, void *closure)
static int Bone_setHead(BPy_Bone *self, PyObject *value, void *closure)
{
return EXPP_intError(PyExc_ValueError, "%s%s",
- sBoneError, "You must first call Armature.makeEditable() to edit the armature");
+ sBoneError, "You must first call .makeEditable() to edit the armature");
}
//------------------------Bone.tail (get)
static PyObject *Bone_getTail(BPy_Bone *self, void *closure)
@@ -553,7 +815,7 @@ static PyObject *Bone_getTail(BPy_Bone *self, void *closure)
static int Bone_setTail(BPy_Bone *self, PyObject *value, void *closure)
{
return EXPP_intError(PyExc_ValueError, "%s%s",
- sBoneError, "You must first call Armature.makeEditable() to edit the armature");
+ sBoneError, "You must first call .makeEditable() to edit the armature");
}
//------------------------Bone.weight (get)
static PyObject *Bone_getWeight(BPy_Bone *self, void *closure)
@@ -564,7 +826,7 @@ static PyObject *Bone_getWeight(BPy_Bone *self, void *closure)
static int Bone_setWeight(BPy_Bone *self, PyObject *value, void *closure)
{
return EXPP_intError(PyExc_ValueError, "%s%s",
- sBoneError, "You must first call Armature.makeEditable() to edit the armature");
+ sBoneError, "You must first call .makeEditable() to edit the armature");
}
//------------------------Bone.deform_dist (get)
static PyObject *Bone_getDeform_dist(BPy_Bone *self, void *closure)
@@ -575,7 +837,7 @@ static PyObject *Bone_getDeform_dist(BPy_Bone *self, void *closure)
static int Bone_setDeform_dist(BPy_Bone *self, PyObject *value, void *closure)
{
return EXPP_intError(PyExc_ValueError, "%s%s",
- sBoneError, "You must first call Armature.makeEditable() to edit the armature");
+ sBoneError, "You must first call .makeEditable() to edit the armature");
}
//------------------------Bone.subdivisions (get)
static PyObject *Bone_getSubdivisions(BPy_Bone *self, void *closure)
@@ -586,7 +848,7 @@ static PyObject *Bone_getSubdivisions(BPy_Bone *self, void *closure)
static int Bone_setSubdivisions(BPy_Bone *self, PyObject *value, void *closure)
{
return EXPP_intError(PyExc_ValueError, "%s%s",
- sBoneError, "You must first call Armature.makeEditable() to edit the armature");
+ sBoneError, "You must first call .makeEditable() to edit the armature");
}
//------------------------Bone.connected (get)
static PyObject *Bone_getOptions(BPy_Bone *self, void *closure)
@@ -617,6 +879,18 @@ static PyObject *Bone_getOptions(BPy_Bone *self, void *closure)
if (PyList_Append(list,
EXPP_GetModuleConstant("Blender.Armature", "HIDDEN_EDIT")) == -1)
goto RuntimeError;
+ if(self->bone->flag & BONE_ROOTSEL)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "ROOT_SELECTED")) == -1)
+ goto RuntimeError;
+ if(self->bone->flag & BONE_SELECTED)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "BONE_SELECTED")) == -1)
+ goto RuntimeError;
+ if(self->bone->flag & BONE_TIPSEL)
+ if (PyList_Append(list,
+ EXPP_GetModuleConstant("Blender.Armature", "TIP_SELECTED")) == -1)
+ goto RuntimeError;
return EXPP_incr_ret(list);
@@ -628,7 +902,7 @@ RuntimeError:
static int Bone_setOptions(BPy_Bone *self, PyObject *value, void *closure)
{
return EXPP_intError(PyExc_ValueError, "%s%s",
- sBoneError, "You must first call Armature.makeEditable() to edit the armature");
+ sBoneError, "You must first call .makeEditable() to edit the armature");
}
//------------------------Bone.parent (get)
static PyObject *Bone_getParent(BPy_Bone *self, void *closure)
@@ -642,7 +916,7 @@ static PyObject *Bone_getParent(BPy_Bone *self, void *closure)
static int Bone_setParent(BPy_Bone *self, PyObject *value, void *closure)
{
return EXPP_intError(PyExc_ValueError, "%s%s",
- sBoneError, "You must first call Armature.makeEditable() to edit the armature");
+ sBoneError, "You must first call .makeEditable() to edit the armature");
}
//------------------------(internal) PyBone_ChildrenAsList
static int PyBone_ChildrenAsList(PyObject *list, ListBase *bones){
@@ -685,7 +959,7 @@ static PyObject *Bone_getChildren(BPy_Bone *self, void *closure)
static int Bone_setChildren(BPy_Bone *self, PyObject *value, void *closure)
{
return EXPP_intError(PyExc_ValueError, "%s%s",
- sBoneError, "You must first call Armature.makeEditable() to edit the armature");
+ sBoneError, "You must first call .makeEditable() to edit the armature");
}
//------------------------Bone.matrix (get)
static PyObject *Bone_getMatrix(BPy_Bone *self, void *closure)
@@ -698,9 +972,29 @@ static PyObject *Bone_getMatrix(BPy_Bone *self, void *closure)
static int Bone_setMatrix(BPy_Bone *self, PyObject *value, void *closure)
{
return EXPP_intError(PyExc_ValueError, "%s%s",
- sBoneError, "You must first call Armature.makeEditable() to edit the armature");
+ sBoneError, "You must first call .makeEditable() to edit the armature");
+}
+//------------------------Bone.length (get)
+static PyObject *Bone_getLength(BPy_Bone *self, void *closure)
+{
+ return Py_BuildValue("f", self->bone->length);
+}
+//------------------------Bone.length (set)
+static int Bone_setLength(BPy_Bone *self, PyObject *value, void *closure)
+{
+ return EXPP_intError(PyExc_ValueError, "%s%s",
+ sBoneError, "You must first call .makeEditable() to edit the armature");
}
//------------------TYPE_OBECT IMPLEMENTATION--------------------------
+//------------------------tp_methods
+//This contains a list of all methods the object contains
+static PyMethodDef BPy_Bone_methods[] = {
+ {"hasParent", (PyCFunction) Bone_hasParent, METH_NOARGS,
+ "() - True/False - Bone has a parent"},
+ {"hasChildren", (PyCFunction) Bone_hasChildren, METH_NOARGS,
+ "() - True/False - Bone has 1 or more children"},
+ {NULL}
+};
//------------------------tp_getset
//This contains methods for attributes that require checking
static PyGetSetDef BPy_Bone_getset[] = {
@@ -726,37 +1020,23 @@ static PyGetSetDef BPy_Bone_getset[] = {
"The parent bone of this bone", NULL},
{"children", (getter)Bone_getChildren, (setter)Bone_setChildren,
"The child bones of this bone", NULL},
+ {"length", (getter)Bone_getLength, (setter)Bone_setLength,
+ "The length of this bone", NULL},
{NULL}
};
-
-//------------------------tp_new
-static PyObject *Bone_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
-{
- return EXPP_incr_ret(Py_None);
-}
-
-//------------------------tp_richcompare
-//This method allows the object to use comparison operators
-static PyObject *Bone_richcmpr(BPy_Bone *self, PyObject *v, int op)
-{
- return EXPP_incr_ret(Py_None);
-}
-
//------------------------tp_repr
//This is the string representation of the object
static PyObject *Bone_repr(BPy_Bone *self)
{
return PyString_FromFormat( "[Bone \"%s\"]", self->bone->name );
}
-
//------------------------tp_dealloc
//This tells how to 'tear-down' our object when ref count hits 0
static void Bone_dealloc(BPy_Bone * self)
{
- ((PyObject*)self)->ob_type->tp_free((PyObject*)self);
+ Bone_Type.tp_free(self);
return;
}
-
//------------------------tp_doc
//The __doc__ string for this object
static char BPy_Bone_doc[] = "This object wraps a Blender Boneobject.\n\
@@ -764,56 +1044,74 @@ static char BPy_Bone_doc[] = "This object wraps a Blender Boneobject.\n\
//------------------TYPE_OBECT DEFINITION--------------------------
PyTypeObject Bone_Type = {
- PyObject_HEAD_INIT(NULL) //tp_head
- 0, //tp_internal
- "Bone", //tp_name
- sizeof(BPy_Bone), //tp_basicsize
- 0, //tp_itemsize
- (destructor)Bone_dealloc, //tp_dealloc
- 0, //tp_print
- 0, //tp_getattr
- 0, //tp_setattr
- 0, //tp_compare
- (reprfunc) Bone_repr, //tp_repr
- 0, //tp_as_number
- 0, //tp_as_sequence
- 0, //tp_as_mapping
- 0, //tp_hash
- 0, //tp_call
- 0, //tp_str
- 0, //tp_getattro
- 0, //tp_setattro
- 0, //tp_as_buffer
- Py_TPFLAGS_DEFAULT, //tp_flags
- BPy_Bone_doc, //tp_doc
- 0, //tp_traverse
- 0, //tp_clear
- (richcmpfunc)Bone_richcmpr, //tp_richcompare
- 0, //tp_weaklistoffset
- 0, //tp_iter
- 0, //tp_iternext
- 0, //tp_methods
- 0, //tp_members
- BPy_Bone_getset, //tp_getset
- 0, //tp_base
- 0, //tp_dict
- 0, //tp_descr_get
- 0, //tp_descr_set
- 0, //tp_dictoffset
- 0, //tp_init
- 0, //tp_alloc
- (newfunc)Bone_new, //tp_new
- 0, //tp_free
- 0, //tp_is_gc
- 0, //tp_bases
- 0, //tp_mro
- 0, //tp_cache
- 0, //tp_subclasses
- 0, //tp_weaklist
- 0 //tp_del
+ PyObject_HEAD_INIT(NULL) //tp_head
+ 0, //tp_internal
+ "Bone", //tp_name
+ sizeof(BPy_Bone), //tp_basicsize
+ 0, //tp_itemsize
+ (destructor)Bone_dealloc, //tp_dealloc
+ 0, //tp_print
+ 0, //tp_getattr
+ 0, //tp_setattr
+ 0, //tp_compare
+ (reprfunc) Bone_repr, //tp_repr
+ 0, //tp_as_number
+ 0, //tp_as_sequence
+ 0, //tp_as_mapping
+ 0, //tp_hash
+ 0, //tp_call
+ 0, //tp_str
+ 0, //tp_getattro
+ 0, //tp_setattro
+ 0, //tp_as_buffer
+ Py_TPFLAGS_DEFAULT, //tp_flags
+ BPy_Bone_doc, //tp_doc
+ 0, //tp_traverse
+ 0, //tp_clear
+ 0, //tp_richcompare
+ 0, //tp_weaklistoffset
+ 0, //tp_iter
+ 0, //tp_iternext
+ BPy_Bone_methods, //tp_methods
+ 0, //tp_members
+ BPy_Bone_getset, //tp_getset
+ 0, //tp_base
+ 0, //tp_dict
+ 0, //tp_descr_get
+ 0, //tp_descr_set
+ 0, //tp_dictoffset
+ 0, //tp_init
+ 0, //tp_alloc
+ 0, //tp_new
+ 0, //tp_free
+ 0, //tp_is_gc
+ 0, //tp_bases
+ 0, //tp_mro
+ 0, //tp_cache
+ 0, //tp_subclasses
+ 0, //tp_weaklist
+ 0 //tp_del
};
//------------------VISIBLE PROTOTYPE IMPLEMENTATION-----------------------
//-----------------(internal)
+//Converts a struct EditBone to a BPy_EditBone
+PyObject *PyEditBone_FromEditBone(struct EditBone *editbone)
+{
+ BPy_EditBone *py_editbone = NULL;
+
+ py_editbone = (BPy_EditBone*)EditBone_Type.tp_alloc(&EditBone_Type, 0); //*new*
+ if (!py_editbone)
+ goto RuntimeError;
+
+ py_editbone->editbone = editbone;
+
+ return (PyObject *) py_editbone;
+
+RuntimeError:
+ return EXPP_objError(PyExc_RuntimeError, "%s%s%s",
+ sEditBoneError, "PyEditBone_FromEditBone: ", "Internal Error Ocurred");
+}
+//-----------------(internal)
//Converts a struct Bone to a BPy_Bone
PyObject *PyBone_FromBone(struct Bone *bone)
{
diff --git a/source/blender/python/api2_2x/Bone.h b/source/blender/python/api2_2x/Bone.h
index e534ad65d9a..a99f2bdf393 100644
--- a/source/blender/python/api2_2x/Bone.h
+++ b/source/blender/python/api2_2x/Bone.h
@@ -41,6 +41,7 @@
PyTypeObject EditBone_Type;
PyTypeObject Bone_Type;
//-------------------STRUCT DEFINITION----------------------------
+
typedef struct {
PyObject_HEAD
Bone * bone;
@@ -48,14 +49,13 @@ typedef struct {
typedef struct {
PyObject_HEAD
- struct Bone *temp; //temp tracking
- char parent[32];
+ struct EditBone *editbone;
+ struct EditBone *parent;
char name[32];
float roll;
float head[3];
float tail[3];
int flag;
- float length;
float dist;
float weight;
float xwidth;
@@ -69,76 +69,8 @@ typedef struct {
//-------------------VISIBLE PROTOTYPES-------------------------
PyObject *PyBone_FromBone(struct Bone *bone);
struct Bone *PyBone_AsBone(BPy_Bone *py_Bone);
+PyObject *PyEditBone_FromBone(Bone *bone);
+PyObject *PyEditBone_FromEditBone(struct EditBone *editbone);
#endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/*
-#ifndef EXPP_BONE_H
-#define EXPP_BONE_H
-
-#include <Python.h>
-#include "DNA_armature_types.h"
-#include "Mathutils.h"
-
-//--------------------------Python BPy_Bone structure definition.-------
-typedef struct {
- PyObject_HEAD
- //reference to data if bone is linked to an armature
- Bone * bone;
- //list of vars that define the boneclass
- char *name;
- char *parent;
- float roll;
- int flag;
- int boneclass;
- float dist;
- float weight;
- VectorObject *head;
- VectorObject *tail;
- VectorObject *loc;
- VectorObject *dloc;
- VectorObject *size;
- VectorObject *dsize;
- QuaternionObject *quat;
- QuaternionObject *dquat;
- MatrixObject *obmat;
- MatrixObject *parmat;
- MatrixObject *defmat;
- MatrixObject *irestmat;
- MatrixObject *posemat;
-} BPy_Bone;
-
-//------------------------------visible prototypes----------------------
-PyObject *Bone_CreatePyObject( struct Bone *obj );
-int Bone_CheckPyObject( PyObject * py_obj );
-Bone *Bone_FromPyObject( PyObject * py_obj );
-PyObject *Bone_Init( void );
-int updateBoneData( BPy_Bone * self, Bone * parent );
-
-#endif
-
-*/
diff --git a/source/blender/src/editarmature.c b/source/blender/src/editarmature.c
index c533f9e64bd..b8630a4ea5a 100644
--- a/source/blender/src/editarmature.c
+++ b/source/blender/src/editarmature.c
@@ -111,7 +111,7 @@ extern float centre[3], centroid[3]; /* Originally defined in editobject.c */
/* **************** tools on Editmode Armature **************** */
/* converts Bones to EditBone list, used for tools as well */
-static void make_boneList(ListBase* list, ListBase *bones, EditBone *parent)
+void make_boneList(ListBase* list, ListBase *bones, EditBone *parent)
{
EditBone *eBone;
Bone *curBone;
@@ -226,7 +226,7 @@ static void fix_bonelist_roll (ListBase *bonelist, ListBase *editbonelist)
}
/* converts the editbones back to the armature */
-static void editbones_to_armature (ListBase *list, Object *ob)
+void editbones_to_armature (ListBase *list, Object *ob)
{
bArmature *arm;
EditBone *eBone;