From 9ae9527c519716051a26a56c02a9b63af1f827b4 Mon Sep 17 00:00:00 2001 From: Joseph Gilbert Date: Mon, 12 Dec 2005 18:46:26 +0000 Subject: - 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. --- source/blender/python/api2_2x/Bone.c | 788 ++++++++++++++++++++++++----------- 1 file changed, 543 insertions(+), 245 deletions(-) (limited to 'source/blender/python/api2_2x/Bone.c') 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) { -- cgit v1.2.3