diff options
Diffstat (limited to 'source/blender/python/api2_2x/Bone.c')
-rw-r--r-- | source/blender/python/api2_2x/Bone.c | 2289 |
1 files changed, 738 insertions, 1551 deletions
diff --git a/source/blender/python/api2_2x/Bone.c b/source/blender/python/api2_2x/Bone.c index 9fd751248aa..2fe7faf3b90 100644 --- a/source/blender/python/api2_2x/Bone.c +++ b/source/blender/python/api2_2x/Bone.c @@ -23,1630 +23,817 @@ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * - * This is a new part of Blender. - * - * Contributor(s): Jordi Rovira i Bonet, Joseph Gilbert + * Contributor(s): Joseph Gilbert * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ -struct ScrArea; /*keep me up here */ - -#include "Bone.h" /*This must come first */ - -#include "MEM_guardedalloc.h" -#include "DNA_object_types.h" -#include "DNA_ipo_types.h" +#include "Bone.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" - -#include "BKE_armature.h" -#include "BKE_action.h" -#include "BKE_global.h" -#include "BKE_main.h" #include "BKE_utildefines.h" - -#include "BIF_editaction.h" -#include "BSE_editipo.h" - -#include "NLA.h" - #include "gen_utils.h" - -//--------------------Python API function prototypes for the Bone module---- -static PyObject *M_Bone_New( PyObject * self, PyObject * args ); - -//------------------------Python API Doc strings for the Bone module-------- -char M_Bone_doc[] = "The Blender Bone module\n\n\ -This module provides control over **Bone Data** objects in Blender.\n\n\ -Example::\n\n\ - from Blender import Armature.Bone\n\ - l = Armature.Bone.New()\n"; -char M_Bone_New_doc[] = "(name) - return a new Bone of name 'name'."; - -//----- Python method structure definition for Blender.Armature.Bone module--- -struct PyMethodDef M_Bone_methods[] = { - {"New", ( PyCFunction ) M_Bone_New, METH_VARARGS, M_Bone_New_doc}, - {NULL, NULL, 0, NULL} -}; -//--------------- Python BPy_Bone methods declarations:------------------- -static PyObject *Bone_getName( BPy_Bone * self ); -static PyObject *Bone_getRoll( BPy_Bone * self ); -static PyObject *Bone_getHead( BPy_Bone * self ); -static PyObject *Bone_getTail( BPy_Bone * self ); -static PyObject *Bone_getLoc( BPy_Bone * self ); -static PyObject *Bone_getSize( BPy_Bone * self ); -static PyObject *Bone_getQuat( BPy_Bone * self ); -static PyObject *Bone_getParent( BPy_Bone * self ); -static PyObject *Bone_hasParent( BPy_Bone * self ); -static PyObject *Bone_getWeight( BPy_Bone * self ); -static PyObject *Bone_getBoneclass( BPy_Bone * self ); -static PyObject *Bone_hasIK( BPy_Bone * self ); -static PyObject *Bone_getChildren( BPy_Bone * self ); -static PyObject *Bone_clearParent( BPy_Bone * self ); -static PyObject *Bone_clearChildren( BPy_Bone * self ); -static PyObject *Bone_hide( BPy_Bone * self ); -static PyObject *Bone_unhide( BPy_Bone * self ); -static PyObject *Bone_setName( BPy_Bone * self, PyObject * args ); -static PyObject *Bone_setRoll( BPy_Bone * self, PyObject * args ); -static PyObject *Bone_setHead( BPy_Bone * self, PyObject * args ); -static PyObject *Bone_setTail( BPy_Bone * self, PyObject * args ); - // note; this can only be done as POSE operation -static PyObject *Bone_setLoc( BPy_Bone * self, PyObject * args ); -static PyObject *Bone_setSize( BPy_Bone * self, PyObject * args ); -static PyObject *Bone_setQuat( BPy_Bone * self, PyObject * args ); -static PyObject *Bone_setPose( BPy_Bone * self, PyObject * args ); - -static PyObject *Bone_setParent( BPy_Bone * self, PyObject * args ); -static PyObject *Bone_setWeight( BPy_Bone * self, PyObject * args ); -static PyObject *Bone_setBoneclass( BPy_Bone * self, PyObject * args ); -static PyObject *Bone_getRestMatrix( BPy_Bone * self, PyObject * args ); - -//--------------- Python BPy_Bone methods table:-------------------------- -static PyMethodDef BPy_Bone_methods[] = { - {"getName", ( PyCFunction ) Bone_getName, METH_NOARGS, - "() - return Bone name"}, - {"getRoll", ( PyCFunction ) Bone_getRoll, METH_NOARGS, - "() - return Bone roll"}, - {"getHead", ( PyCFunction ) Bone_getHead, METH_NOARGS, - "() - return Bone head"}, - {"getTail", ( PyCFunction ) Bone_getTail, METH_NOARGS, - "() - return Bone tail"}, - {"getLoc", ( PyCFunction ) Bone_getLoc, METH_NOARGS, - "() - return Bone loc"}, - {"getSize", ( PyCFunction ) Bone_getSize, METH_NOARGS, - "() - return Bone size"}, - {"getQuat", ( PyCFunction ) Bone_getQuat, METH_NOARGS, - "() - return Bone quat"}, - {"hide", ( PyCFunction ) Bone_hide, METH_NOARGS, - "() - hides the bone"}, - {"unhide", ( PyCFunction ) Bone_unhide, METH_NOARGS, - "() - unhides the bone"}, - {"getWeight", ( PyCFunction ) Bone_getWeight, METH_NOARGS, - "() - return Bone weight"}, - {"getBoneclass", ( PyCFunction ) Bone_getBoneclass, METH_NOARGS, - "() - return Bone boneclass"}, - {"hasIK", ( PyCFunction ) Bone_hasIK, METH_VARARGS, - "() - get the Bone IKToParent flag."}, - {"getParent", ( PyCFunction ) Bone_getParent, METH_NOARGS, - "() - return the parent bone of this one if it exists." - " None if not found. You can check this condition with the " - "hasParent() method."}, - {"hasParent", ( PyCFunction ) Bone_hasParent, METH_NOARGS, - "() - return true if bone has a parent"}, - {"getChildren", ( PyCFunction ) Bone_getChildren, METH_NOARGS, - "() - return Bone children list"}, - {"clearParent", ( PyCFunction ) Bone_clearParent, METH_NOARGS, - "() - clears the bone's parent in the armature and makes it root"}, - {"clearChildren", ( PyCFunction ) Bone_clearChildren, METH_NOARGS, - "() - remove the children associated with this bone"}, - {"setName", ( PyCFunction ) Bone_setName, METH_VARARGS, - "(str) - rename Bone"}, - {"setRoll", ( PyCFunction ) Bone_setRoll, METH_VARARGS, - "(float) - set Bone roll"}, - {"setHead", ( PyCFunction ) Bone_setHead, METH_VARARGS, - "(float,float,float) - set Bone head pos"}, - {"setTail", ( PyCFunction ) Bone_setTail, METH_VARARGS, - "(float,float,float) - set Bone tail pos"}, - {"setLoc", ( PyCFunction ) Bone_setLoc, METH_VARARGS, - "(float,float,float) - set Bone loc"}, - {"setSize", ( PyCFunction ) Bone_setSize, METH_VARARGS, - "(float,float,float) - set Bone size"}, - {"setQuat", ( PyCFunction ) Bone_setQuat, METH_VARARGS, - "(float,float,float,float) - set Bone quat"}, - {"setParent", ( PyCFunction ) Bone_setParent, METH_VARARGS, - "() - set the Bone parent of this one."}, - {"setWeight", ( PyCFunction ) Bone_setWeight, METH_VARARGS, - "() - set the Bone weight."}, - {"setPose", ( PyCFunction ) Bone_setPose, METH_VARARGS, - "() - set a pose for this bone at a frame."}, - {"setBoneclass", ( PyCFunction ) Bone_setBoneclass, METH_VARARGS, - "() - set the Bone boneclass."}, - {"getRestMatrix", ( PyCFunction ) Bone_getRestMatrix, METH_VARARGS, - "() - return the rest matrix for this bone"}, - {NULL, NULL, 0, NULL} -}; - -//--------------- Python TypeBone callback function prototypes---------- -static void Bone_dealloc( BPy_Bone * bone ); -static PyObject *Bone_getAttr( BPy_Bone * bone, char *name ); -static int Bone_setAttr( BPy_Bone * bone, char *name, PyObject * v ); -static int Bone_compare( BPy_Bone * a1, BPy_Bone * a2 ); -static PyObject *Bone_repr( BPy_Bone * bone ); - -//--------------- Python TypeBone structure definition------------- -PyTypeObject Bone_Type = { - PyObject_HEAD_INIT( NULL ) - 0, /* ob_size */ - "Blender Bone", /* tp_name */ - sizeof( BPy_Bone ), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - ( destructor ) Bone_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - ( getattrfunc ) Bone_getAttr, /* tp_getattr */ - ( setattrfunc ) Bone_setAttr, /* tp_setattr */ - ( cmpfunc ) Bone_compare, /* tp_compare */ - ( reprfunc ) Bone_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_as_hash */ - 0, 0, 0, 0, 0, 0, - 0, /* tp_doc */ - 0, 0, 0, 0, 0, 0, - BPy_Bone_methods, /* tp_methods */ - 0, /* tp_members */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, -}; - -//--------------- Bone Module Init----------------------------- -PyObject *Bone_Init( void ) -{ - PyObject *submodule; - - Bone_Type.ob_type = &PyType_Type; - - submodule = Py_InitModule3( "Blender.Armature.Bone", - M_Bone_methods, M_Bone_doc ); - - PyModule_AddIntConstant( submodule, "ROT", POSE_ROT ); - PyModule_AddIntConstant( submodule, "LOC", POSE_LOC ); - PyModule_AddIntConstant( submodule, "SIZE", POSE_SIZE ); - PyModule_AddIntConstant( submodule, "SKINNABLE", 0 ); - PyModule_AddIntConstant( submodule, "UNSKINNABLE", 1 ); - PyModule_AddIntConstant( submodule, "HEAD", 2 ); - PyModule_AddIntConstant( submodule, "NECK", 3 ); - PyModule_AddIntConstant( submodule, "BACK", 4 ); - PyModule_AddIntConstant( submodule, "SHOULDER", 5 ); - PyModule_AddIntConstant( submodule, "ARM", 6 ); - PyModule_AddIntConstant( submodule, "HAND", 7 ); - PyModule_AddIntConstant( submodule, "FINGER", 8 ); - PyModule_AddIntConstant( submodule, "THUMB", 9 ); - PyModule_AddIntConstant( submodule, "PELVIS", 10 ); - PyModule_AddIntConstant( submodule, "LEG", 11 ); - PyModule_AddIntConstant( submodule, "FOOT", 12 ); - PyModule_AddIntConstant( submodule, "TOE", 13 ); - PyModule_AddIntConstant( submodule, "TENTACLE", 14 ); - - return ( submodule ); -} - -//--------------- Bone module internal callbacks----------------- - -//--------------- updatePyBone------------------------------------ -static int updatePyBone( BPy_Bone * self ) -{ - char *parent_str = ""; - - if( !self->bone ) { - //nothing to update - not linked - return 0; - } else { - BLI_strncpy( self->name, self->bone->name, - strlen( self->bone->name ) + 1 ); - self->roll = self->bone->roll; - self->flag = self->bone->flag; - self->boneclass = self->bone->boneclass; - self->dist = self->bone->dist; - self->weight = self->bone->weight; - - if( self->bone->parent ) { - self->parent = - BLI_strncpy( self->parent, - self->bone->parent->name, - strlen( self->bone->parent-> - name ) + 1 ); - } else { - self->parent = - BLI_strncpy( self->parent, parent_str, - strlen( parent_str ) + 1 ); - } -#if 0 - for( x = 0; x < 3; x++ ) { - self->head->vec[x] = self->bone->head[x]; - self->tail->vec[x] = self->bone->tail[x]; - self->loc->vec[x] = self->bone->loc[x]; - self->dloc->vec[x] = self->bone->dloc[x]; - self->size->vec[x] = self->bone->size[x]; - self->dsize->vec[x] = self->bone->dsize[x]; - } - for( x = 0; x < 4; x++ ) { - self->quat->quat[x] = self->bone->quat[x]; - self->dquat->quat[x] = self->bone->dquat[x]; - } - for( x = 0; x < 4; x++ ) { - for( y = 0; y < 4; y++ ) { - self->obmat->matrix[x][y] = - self->bone->obmat[x][y]; - self->parmat->matrix[x][y] = - self->bone->parmat[x][y]; - self->defmat->matrix[x][y] = - self->bone->defmat[x][y]; - self->irestmat->matrix[x][y] = - self->bone->irestmat[x][y]; - self->posemat->matrix[x][y] = - self->bone->posemat[x][y]; - } - } -#endif - return 1; - } -} - -//--------------- updateBoneData------------------------------------ -int updateBoneData( BPy_Bone * self, Bone * parent ) -{ - //called from Armature.addBone() - int x, y; - - //called in Armature.addBone() to update the Bone * data - if( !self->bone ) { - //nothing to update - not linked - return 0; - } else { - BLI_strncpy( self->bone->name, self->name, - strlen( self->name ) + 1 ); - self->bone->roll = self->roll; - self->bone->flag = self->flag; - self->bone->boneclass = (short)self->boneclass; - self->bone->dist = self->dist; - self->bone->weight = self->weight; - self->bone->parent = parent; //parent will be checked from self->parent string in addBone() - - for( x = 0; x < 3; x++ ) { - self->bone->head[x] = self->head->vec[x]; - self->bone->tail[x] = self->tail->vec[x]; -// self->bone->loc[x] = self->loc->vec[x]; -// self->bone->dloc[x] = self->dloc->vec[x]; -// self->bone->size[x] = self->size->vec[x]; -// self->bone->dsize[x] = self->dsize->vec[x]; - } - for( x = 0; x < 4; x++ ) { -// self->bone->quat[x] = self->quat->quat[x]; -// self->bone->dquat[x] = self->dquat->quat[x]; - } - for( x = 0; x < 4; x++ ) { - for( y = 0; y < 4; y++ ) { -// self->bone->obmat[x][y] = -// self->obmat->matrix[x][y]; -// self->bone->parmat[x][y] = -// self->parmat->matrix[x][y]; -// self->bone->defmat[x][y] = -// self->defmat->matrix[x][y]; -// self->bone->irestmat[x][y] = -// self->irestmat->matrix[x][y]; -// self->bone->posemat[x][y] = -// self->posemat->matrix[x][y]; - } - } - return 1; - } -} - -//--------------- testChildbase---------------------------------- -static int testChildbase( Bone * bone, Bone * test ) -{ - Bone *child; - - for( child = bone->childbase.first; child; child = child->next ) { - if( child == test ) { - return 1; - } - if( child->childbase.first != NULL ) - testChildbase( child, test ); - } - +#include "BKE_armature.h" +#include "Mathutils.h" + +//------------------------ERROR CODES--------------------------------- +//This is here just to make me happy and to have more consistant error strings :) +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: "; + +//----------------------(internal) +//gets the bone->roll (which is a localspace roll) and puts it in parentspace +//(which is the 'roll' value the user sees) +double boneRoll_ToArmatureSpace(struct Bone *bone) +{ + float head[3], tail[3], delta[3]; + float premat[3][3], postmat[3][3]; + float imat[3][3], difmat[3][3]; + double roll = 0.0f; + + VECCOPY(head, bone->arm_head); + VECCOPY(tail, bone->arm_tail); + VECSUB (delta, tail, head); + vec_roll_to_mat3(delta, 0.0f, postmat); + Mat3CpyMat4(premat, bone->arm_mat); + Mat3Inv(imat, postmat); + Mat3MulMat3(difmat, imat, premat); + + roll = atan(difmat[2][0] / difmat[2][2]); + if (difmat[0][0] < 0.0){ + roll += M_PI; + } + return roll; //result is in radians +} +//################## EditBone_Type (internal) ######################## +/*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----------------------------- +//------------------ATTRIBUTE IMPLEMENTATION--------------------------- +//------------------------EditBone.name (get) +static PyObject *EditBone_getName(BPy_EditBone *self, void *closure) +{ + return PyString_FromString(self->name); +} +//------------------------EditBone.name (set) +//check for char[] overflow here... +static int EditBone_setName(BPy_EditBone *self, PyObject *value, void *closure) +{ + char *name = ""; + + if (!PyArg_Parse(value, "s", &name)) + goto AttributeError; + + BLI_strncpy(self->name, name, 32); return 0; -} - -//--------------- returnBoneclassEnum---------------------------- -static PyObject *returnBoneclassEnum( int value ) -{ - char *str; - str = PyMem_Malloc( 32 + 1 ); - switch ( value ) { - case 0: - BLI_strncpy( str, "SKINNABLE", 32 ); - break; - case 1: - BLI_strncpy( str, "UNSKINNABLE", 32 ); - break; - case 2: - BLI_strncpy( str, "HEAD", 32 ); - break; - case 3: - BLI_strncpy( str, "NECK", 32 ); - break; - case 4: - BLI_strncpy( str, "BACK", 32 ); - break; - case 5: - BLI_strncpy( str, "SHOULDER", 32 ); - break; - case 6: - BLI_strncpy( str, "ARM", 32 ); - break; - case 7: - BLI_strncpy( str, "HAND", 32 ); - break; - case 8: - BLI_strncpy( str, "FINGER", 32 ); - break; - case 9: - BLI_strncpy( str, "THUMB", 32 ); - break; - case 10: - BLI_strncpy( str, "PELVIS", 32 ); - break; - case 11: - BLI_strncpy( str, "LEG", 32 ); - break; - case 12: - BLI_strncpy( str, "FOOT", 32 ); - break; - case 13: - BLI_strncpy( str, "TOE", 32 ); - break; - case 14: - BLI_strncpy( str, "TENTACLE", 32 ); - break; - default: - BLI_strncpy( str, "SKINNABLE", 32 ); - break; - } - return ( PyObject * ) PyString_FromString( str ); +AttributeError: + return EXPP_intError(PyExc_AttributeError, "%s%s%s", + sEditBoneError, ".name: ", "expects a string"); } - -//---------------BPy_Bone internal callbacks/methods--------------- - -//--------------- dealloc------------------------------------------ -static void Bone_dealloc( BPy_Bone * self ) +//------------------------EditBone.roll (get) +static PyObject *EditBone_getRoll(BPy_EditBone *self, void *closure) { - PyMem_Free( self->name ); - PyMem_Free( self->parent ); - PyObject_DEL( self ); + return Py_BuildValue("{s:O}", + "ARMATURESPACE", PyFloat_FromDouble((self->roll * (180/Py_PI)))); } - -//---------------getattr------------------------------------------- -static PyObject *Bone_getAttr( BPy_Bone * self, char *name ) -{ - PyObject *attr = Py_None; - - if( strcmp( name, "name" ) == 0 ) - attr = Bone_getName( self ); - else if( strcmp( name, "roll" ) == 0 ) - attr = Bone_getRoll( self ); - else if( strcmp( name, "head" ) == 0 ) - attr = Bone_getHead( self ); - else if( strcmp( name, "tail" ) == 0 ) - attr = Bone_getTail( self ); - else if( strcmp( name, "size" ) == 0 ) - attr = Bone_getSize( self ); - else if( strcmp( name, "loc" ) == 0 ) - attr = Bone_getLoc( self ); - else if( strcmp( name, "quat" ) == 0 ) - attr = Bone_getQuat( self ); - else if( strcmp( name, "parent" ) == 0 ) - /* Skip the checks for Py_None as its a valid result to this call. */ - return Bone_getParent( self ); - else if( strcmp( name, "children" ) == 0 ) - attr = Bone_getChildren( self ); - else if( strcmp( name, "weight" ) == 0 ) - attr = Bone_getWeight( self ); - else if( strcmp( name, "boneclass" ) == 0 ) - attr = Bone_getBoneclass( self ); - else if( strcmp( name, "ik" ) == 0 ) - attr = Bone_hasIK( self ); - else if( strcmp( name, "__members__" ) == 0 ) { - /* 9 entries */ - attr = Py_BuildValue( "[s,s,s,s,s,s,s,s,s,s,s]", - "name", "roll", "head", "tail", "loc", - "size", "quat", "parent", "children", - "weight", "boneclass", "ik" ); - } - - if( !attr ) - return ( EXPP_ReturnPyObjError( PyExc_MemoryError, - "couldn't create PyObject" ) ); - - if( attr != Py_None ) - return attr; /* member attribute found, return it */ - - /* not an attribute, search the methods table */ - return Py_FindMethod( BPy_Bone_methods, ( PyObject * ) self, name ); +//------------------------EditBone.roll (set) +static int EditBone_setRoll(BPy_EditBone *self, PyObject *value, void *closure) +{ + printf("Sorry this isn't implemented yet.... :/"); + return 1; } - -//--------------- setattr------------------------------------------- -static int Bone_setAttr( BPy_Bone * self, char *name, PyObject * value ) +//------------------------EditBone.head (get) +static PyObject *EditBone_getHead(BPy_EditBone *self, void *closure) { - PyObject *valtuple; - PyObject *error = NULL; - - valtuple = Py_BuildValue( "(O)", value ); /* the set* functions expect a tuple */ - - if( !valtuple ) - return EXPP_ReturnIntError( PyExc_MemoryError, - "BoneSetAttr: couldn't create tuple" ); - - if( strcmp( name, "name" ) == 0 ) - error = Bone_setName( self, valtuple ); - else { /* Error */ - Py_DECREF( valtuple ); - - /* ... member with the given name was found */ - return ( EXPP_ReturnIntError - ( PyExc_KeyError, "attribute not found" ) ); - } - - Py_DECREF( valtuple ); - - if( error != Py_None ) - return -1; - - Py_DECREF( Py_None ); /* was incref'ed by the called Bone_set* function */ - return 0; /* normal exit */ + return Py_BuildValue("{s:O, s:O}", + "BONESPACE", newVectorObject(self->head, 3, Py_WRAP));; } - -//--------------- repr--------------------------------------------- -static PyObject *Bone_repr( BPy_Bone * self ) -{ - if( self->bone ) - return PyString_FromFormat( "[Bone \"%s\"]", - self->bone->name ); - else - return PyString_FromString( "NULL" ); +//------------------------EditBone.head (set) +static int EditBone_setHead(BPy_EditBone *self, PyObject *value, void *closure) +{ + printf("Sorry this isn't implemented yet.... :/"); + return 1; } - -//--------------- compare------------------------------------------ -static int Bone_compare( BPy_Bone * a, BPy_Bone * b ) +//------------------------EditBone.tail (get) +static PyObject *EditBone_getTail(BPy_EditBone *self, void *closure) { - Bone *pa = a->bone, *pb = b->bone; - return ( pa == pb ) ? 0 : -1; + return Py_BuildValue("{s:O, s:O}", + "BONESPACE", newVectorObject(self->tail, 3, Py_WRAP)); } - -//--------------- Bone_CreatePyObject--------------------------------- -PyObject *Bone_CreatePyObject( struct Bone * bone ) -{ - BPy_Bone *blen_bone; - - blen_bone = ( BPy_Bone * ) PyObject_NEW( BPy_Bone, &Bone_Type ); - - //set the all important Bone flag - blen_bone->bone = bone; - - //allocate space for python vars - blen_bone->name = PyMem_Malloc( 32 + 1 ); - blen_bone->parent = PyMem_Malloc( 32 + 1 ); - blen_bone->head = ( VectorObject *)newVectorObject( NULL, 3, Py_NEW ); - blen_bone->tail = ( VectorObject *)newVectorObject( NULL, 3, Py_NEW ); - blen_bone->loc = ( VectorObject *)newVectorObject( NULL, 3, Py_NEW ); - blen_bone->dloc = ( VectorObject *)newVectorObject( NULL, 3, Py_NEW ); - blen_bone->size = ( VectorObject *)newVectorObject( NULL, 3, Py_NEW ); - blen_bone->dsize = ( VectorObject *)newVectorObject( NULL, 3, Py_NEW ); - blen_bone->quat = blen_bone->quat = ( QuaternionObject *)newQuaternionObject( NULL, Py_NEW ); - blen_bone->dquat = blen_bone->quat = ( QuaternionObject *)newQuaternionObject( NULL, Py_NEW ); - blen_bone->obmat = blen_bone->obmat = ( MatrixObject *)newMatrixObject( NULL, 4, 4 , Py_NEW); - blen_bone->parmat = blen_bone->obmat = ( MatrixObject *)newMatrixObject( NULL, 4, 4 , Py_NEW); - blen_bone->defmat = blen_bone->obmat = ( MatrixObject *)newMatrixObject( NULL, 4, 4 , Py_NEW); - blen_bone->irestmat = blen_bone->obmat = ( MatrixObject *)newMatrixObject( NULL, 4, 4 , Py_NEW); - blen_bone->posemat = blen_bone->obmat = ( MatrixObject *)newMatrixObject( NULL, 4, 4 , Py_NEW); - - if( !updatePyBone( blen_bone ) ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "bone struct empty" ); - - return ( ( PyObject * ) blen_bone ); +//------------------------EditBone.tail (set) +static int EditBone_setTail(BPy_EditBone *self, PyObject *value, void *closure) +{ + printf("Sorry this isn't implemented yet.... :/"); + return 1; } - -//--------------- Bone_CheckPyObject-------------------------------- -int Bone_CheckPyObject( PyObject * py_obj ) +//------------------------EditBone.weight (get) +static PyObject *EditBone_getWeight(BPy_EditBone *self, void *closure) { - return ( py_obj->ob_type == &Bone_Type ); -} - -//--------------- Bone_FromPyObject--------------------------------- -struct Bone *Bone_FromPyObject( PyObject * py_obj ) -{ - BPy_Bone *blen_obj; - - blen_obj = ( BPy_Bone * ) py_obj; - if( !( ( BPy_Bone * ) py_obj )->bone ) { //test to see if linked to armature - //use python vars - return NULL; - } else { - //use bone datastruct - return ( blen_obj->bone ); - } -} - -//--------------- Python Bone Module methods------------------------ - -//--------------- Blender.Armature.Bone.New()----------------------- -static PyObject *M_Bone_New( PyObject * self, PyObject * args ) -{ - char *name_str = "BoneName"; - char *parent_str = ""; - BPy_Bone *py_bone = NULL; /* for Bone Data object wrapper in Python */ - - if( !PyArg_ParseTuple( args, "|s", &name_str ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected string or empty argument" ) ); - - //create python bone - py_bone = ( BPy_Bone * ) PyObject_NEW( BPy_Bone, &Bone_Type ); - - //allocate space for python vars - py_bone->name = PyMem_Malloc( 32 + 1 ); - py_bone->parent = PyMem_Malloc( 32 + 1 ); - py_bone->head = ( VectorObject *)newVectorObject( NULL, 3, Py_NEW ); - py_bone->tail = ( VectorObject *)newVectorObject( NULL, 3, Py_NEW ); - py_bone->loc = ( VectorObject *)newVectorObject( NULL, 3, Py_NEW ); - py_bone->dloc = ( VectorObject *)newVectorObject( NULL, 3, Py_NEW ); - py_bone->size = ( VectorObject *)newVectorObject( NULL, 3, Py_NEW ); - py_bone->dsize = ( VectorObject *)newVectorObject( NULL, 3, Py_NEW ); - py_bone->quat = ( QuaternionObject *)newQuaternionObject( NULL, Py_NEW ); - py_bone->dquat = ( QuaternionObject *)newQuaternionObject( NULL, Py_NEW ); - py_bone->obmat = ( MatrixObject *)newMatrixObject( NULL, 4, 4 , Py_NEW); - py_bone->parmat = ( MatrixObject *)newMatrixObject( NULL, 4, 4 , Py_NEW); - py_bone->defmat = ( MatrixObject *)newMatrixObject( NULL, 4, 4 , Py_NEW); - py_bone->irestmat = ( MatrixObject *)newMatrixObject( NULL, 4, 4 , Py_NEW); - py_bone->posemat = ( MatrixObject *)newMatrixObject( NULL, 4, 4 , Py_NEW); - - //default py values - BLI_strncpy( py_bone->name, name_str, strlen( name_str ) + 1 ); - BLI_strncpy( py_bone->parent, parent_str, strlen( parent_str ) + 1 ); - py_bone->roll = 0.0f; - py_bone->flag = 32; - py_bone->dist = 1.0f; - py_bone->weight = 1.0f; - Vector_Zero( py_bone->head ); - Vector_Zero( py_bone->loc ); - Vector_Zero( py_bone->dloc ); - Vector_Zero( py_bone->size ); - Vector_Zero( py_bone->dsize ); - Quaternion_Identity( py_bone->quat ); - Quaternion_Identity( py_bone->dquat ); - Matrix_Identity( py_bone->obmat ); - Matrix_Identity( py_bone->parmat ); - Matrix_Identity( py_bone->defmat ); - Matrix_Identity( py_bone->irestmat ); - Matrix_Identity( py_bone->posemat ); - - //default tail of 2,0,0 - py_bone->tail->vec[0] = 2.0f; - py_bone->tail->vec[1] = 0.0f; - py_bone->tail->vec[2] = 0.0f; - - //set the datapointer to null (unlinked) - py_bone->bone = NULL; - - return ( PyObject * ) py_bone; -} - -//--------------- Python BPy_Bone methods--------------------------- - -//--------------- BPy_Bone.getName()-------------------------------- -static PyObject *Bone_getName( BPy_Bone * self ) -{ - PyObject *attr = NULL; - - if( !self->bone ) { //test to see if linked to armature - //use python vars - attr = PyString_FromString( self->name ); - } else { - //use bone datastruct - attr = PyString_FromString( self->bone->name ); - } - if( attr ) - return attr; - - return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, - "couldn't get Bone.name attribute" ) ); -} - -//--------------- BPy_Bone.getRoll()--------------------------------- -static PyObject *Bone_getRoll( BPy_Bone * self ) -{ - PyObject *attr = NULL; - - if( !self->bone ) { //test to see if linked to armature - //use python vars - attr = Py_BuildValue( "f", self->roll ); - } else { - //use bone datastruct - attr = Py_BuildValue( "f", self->bone->roll ); - } - if( attr ) - return attr; - - return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, - "couldn't get Bone.roll attribute" ) ); -} - -//--------------- BPy_Bone.getWeight()--------------------------------- -static PyObject *Bone_getWeight( BPy_Bone * self ) -{ - PyObject *attr = NULL; - - if( !self->bone ) { //test to see if linked to armature - //use python vars - attr = Py_BuildValue( "f", self->weight ); - } else { - //use bone datastruct - attr = Py_BuildValue( "f", self->bone->weight ); - } - if( attr ) - return attr; - - return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, - "couldn't get Bone.weight attribute" ) ); -} - -//--------------- BPy_Bone.getHead()---------------------------------- -static PyObject *Bone_getHead( BPy_Bone * self ) -{ - PyObject *attr = NULL; - float vec[3]; - int x; - - if( !self->bone ) { //test to see if linked to armature - //use python vars - for( x = 0; x < 3; x++ ) - vec[x] = self->head->vec[x]; - attr = ( PyObject * ) newVectorObject( vec, 3, Py_NEW ); - } else { - //use bone datastruct - attr = newVectorObject( NULL, 3, Py_NEW ); - ( ( VectorObject * ) attr )->vec[0] = self->bone->head[0]; - ( ( VectorObject * ) attr )->vec[1] = self->bone->head[1]; - ( ( VectorObject * ) attr )->vec[2] = self->bone->head[2]; - } - if( attr ) - return attr; - - return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, - "couldn't get Bone.head attribute" ) ); + return PyFloat_FromDouble(self->weight); } +//------------------------EditBone.weight (set) +static int EditBone_setWeight(BPy_EditBone *self, PyObject *value, void *closure) +{ + float weight; -//--------------- BPy_Bone.getTail()--------------------------------- -static PyObject *Bone_getTail( BPy_Bone * self ) -{ - PyObject *attr = NULL; - float vec[3]; - int x; + if (!PyArg_Parse(value, "f", &weight)) + goto AttributeError; + CLAMP(weight, 0.0f, 1000.0f); - if( !self->bone ) { //test to see if linked to armature - //use python vars - for( x = 0; x < 3; x++ ) - vec[x] = self->tail->vec[x]; - attr = ( PyObject * ) newVectorObject( vec, 3, Py_NEW ); - } else { - //use bone datastruct - attr = newVectorObject( NULL, 3, Py_NEW ); - ( ( VectorObject * ) attr )->vec[0] = self->bone->tail[0]; - ( ( VectorObject * ) attr )->vec[1] = self->bone->tail[1]; - ( ( VectorObject * ) attr )->vec[2] = self->bone->tail[2]; - } - if( attr ) - return attr; + self->weight = weight; + return 0; - return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, - "couldn't get Bone.tail attribute" ) ); +AttributeError: + return EXPP_intError(PyExc_AttributeError, "%s%s%s", + sEditBoneError, ".weight: ", "expects a float"); } - -//--------------- BPy_Bone.getLoc()--------------------------------- -static PyObject *Bone_getLoc( BPy_Bone * self ) +//------------------------EditBone.deform_dist (get) +static PyObject *EditBone_getDeform_dist(BPy_EditBone *self, void *closure) { - PyObject *attr = NULL; - float vec[3]; - int x; - - if( !self->bone ) { //test to see if linked to armature - //use python vars - for( x = 0; x < 3; x++ ) - vec[x] = self->loc->vec[x]; - attr = ( PyObject * ) newVectorObject( vec, 3, Py_NEW ); - } else { - //use bone datastruct - attr = newVectorObject( NULL, 3, Py_NEW ); - -// ( ( VectorObject * ) attr )->vec[0] = self->bone->loc[0]; -// ( ( VectorObject * ) attr )->vec[1] = self->bone->loc[1]; -// ( ( VectorObject * ) attr )->vec[2] = self->bone->loc[2]; - } - if( attr ) - return attr; - - return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, - "couldn't get Bone.loc attribute" ) ); + return PyFloat_FromDouble(self->dist); } +//------------------------EditBone.deform_dist (set) +static int EditBone_setDeform_dist(BPy_EditBone *self, PyObject *value, void *closure) +{ + float deform; -//--------------- BPy_Bone.getSize()----------------------------- -static PyObject *Bone_getSize( BPy_Bone * self ) -{ - PyObject *attr = NULL; - float vec[3]; - int x; + if (!PyArg_Parse(value, "f", &deform)) + goto AttributeError; + CLAMP(deform, 0.0f, 1000.0f); - if( !self->bone ) { //test to see if linked to armature - //use python vars - for( x = 0; x < 3; x++ ) - vec[x] = self->size->vec[x]; - attr = ( PyObject * ) newVectorObject( vec, 3, Py_NEW ); - } else { - //use bone datastruct - attr = newVectorObject( NULL, 3, Py_NEW ); -// ( ( VectorObject * ) attr )->vec[0] = self->bone->size[0]; -// ( ( VectorObject * ) attr )->vec[1] = self->bone->size[1]; -// ( ( VectorObject * ) attr )->vec[2] = self->bone->size[2]; - } - if( attr ) - return attr; + self->dist = deform; + return 0; - return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, - "couldn't get Bone.size attribute" ) ); +AttributeError: + return EXPP_intError(PyExc_AttributeError, "%s%s%s", + sEditBoneError, ".deform_dist: ", "expects a float"); } - -//--------------- BPy_Bone.getQuat()-------------------------------- -static PyObject *Bone_getQuat( BPy_Bone * self ) +//------------------------EditBone.subdivisions (get) +static PyObject *EditBone_getSubdivisions(BPy_EditBone *self, void *closure) { - PyObject *attr = NULL; - float quat[4]; - int x; - - if( !self->bone ) { //test to see if linked to armature - //use python vars - p.s. - you must return a copy or else - //python will trash the internal var - for( x = 0; x < 4; x++ ) - quat[x] = self->quat->quat[x]; - attr = ( PyObject * ) newQuaternionObject( quat, Py_NEW ); - } else { - //use bone datastruct - attr = newQuaternionObject( NULL, Py_NEW ); -// ( ( QuaternionObject * ) attr )->quat[0] = self->bone->quat[0]; -// ( ( QuaternionObject * ) attr )->quat[1] = self->bone->quat[1]; -// ( ( QuaternionObject * ) attr )->quat[2] = self->bone->quat[2]; -// ( ( QuaternionObject * ) attr )->quat[3] = self->bone->quat[3]; - } - - return attr; + return PyInt_FromLong(self->segments); } +//------------------------EditBone.subdivisions (set) +static int EditBone_setSubdivisions(BPy_EditBone *self, PyObject *value, void *closure) +{ + int segs; -//--------------- BPy_Bone.hasParent()--------------------------- -static PyObject *Bone_hasParent( BPy_Bone * self ) -{ - char *parent_str = ""; + if (!PyArg_Parse(value, "i", &segs)) + goto AttributeError; + CLAMP(segs, 1, 32); - if( !self->bone ) { //test to see if linked to armature - //use python vars - if( BLI_streq( self->parent, parent_str ) ) { - return EXPP_incr_ret_False(); - } else { - return EXPP_incr_ret_True(); - } - } else { - //use bone datastruct - if( self->bone->parent ) { - return EXPP_incr_ret_True(); - } else { - return EXPP_incr_ret_False(); - } - } -} + self->segments = (short)segs; + return 0; -//--------------- BPy_Bone.getParent()------------------------------ -static PyObject *Bone_getParent( BPy_Bone * self ) -{ - char *parent_str = ""; - if( !self->bone ) { //test to see if linked to armature - //use python vars - if( BLI_streq( self->parent, parent_str ) ) { - return EXPP_incr_ret( Py_None ); - } else { - return PyString_FromString( self->parent ); - } - } else { - //use bone datastruct - if( self->bone->parent ) { - return Bone_CreatePyObject( self->bone->parent ); - } else { - return EXPP_incr_ret( Py_None ); +AttributeError: + return EXPP_intError(PyExc_AttributeError, "%s%s%s", + sEditBoneError, ".subdivisions: ", "expects a integer"); +} +//------------------------EditBone.options (get) +static PyObject *EditBone_getOptions(BPy_EditBone *self, void *closure) +{ + PyObject *list = NULL; + + list = PyList_New(0); + if (list == NULL) + 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; + + return EXPP_incr_ret(list); + +RuntimeError: + return EXPP_objError(PyExc_RuntimeError, "%s%s%s", + sEditBoneError, ".options: ", "Internal failure!"); +} +//----------------------(internal) EditBone_CheckValidConstant +static int EditBone_CheckValidConstant(PyObject *constant) +{ + PyObject *name = NULL; + + 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; + } + }else{ + return 0; } + }else{ + return 0; } } -//--------------- BPy_Bone.getChildren()----------------------------- -static PyObject *Bone_getChildren( BPy_Bone * self ) -{ - int totbones = 0; - Bone *current = NULL; - PyObject *listbones = NULL; - int i; - - if( !self->bone ) { //test to see if linked to armature - //use python vars - return EXPP_incr_ret( Py_None ); - } else { - //use bone datastruct - current = self->bone->childbase.first; - for( ; current; current = current->next ) - totbones++; - - /* Create a list with a bone wrapper for each bone */ - current = self->bone->childbase.first; - listbones = PyList_New( totbones ); - for( i = 0; i < totbones; i++ ) { - assert( current ); - PyList_SetItem( listbones, i, - Bone_CreatePyObject( current ) ); - current = current->next; +//------------------------EditBone.options (set) +static int EditBone_setOptions(BPy_EditBone *self, PyObject *value, void *closure) +{ + int length, numeric_value, new_flag = 0, x; + PyObject *val = NULL, *index = NULL; + + if (PyList_Check(value)){ + length = PyList_Size(value); + for (x = 0; x < length; x++){ + index = PyList_GetItem(value, x); + if (!EditBone_CheckValidConstant(index)) + goto AttributeError2; + val = PyDict_GetItemString(((BPy_constant*)index)->dict, "value"); + if (PyInt_Check(val)){ + numeric_value = (int)PyInt_AS_LONG(val); + new_flag |= numeric_value; + }else{ + goto AttributeError2; + } } - return listbones; - } -} + self->flag = new_flag; + return 0; + }else if (BPy_Constant_Check(value)){ + if (!EditBone_CheckValidConstant(value)) + goto AttributeError2; + val = PyDict_GetItemString(((BPy_constant*)value)->dict, "value"); + if (PyInt_Check(val)){ + numeric_value = (int)PyInt_AS_LONG(val); + self->flag = numeric_value; + return 0; + }else{ + goto AttributeError2; + } + }else{ + goto AttributeError1; + } + +AttributeError1: + return EXPP_intError(PyExc_AttributeError, "%s%s%s", + 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"); +} +//------------------------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); +} +//------------------------EditBone.parent (set) +static int EditBone_setParent(BPy_EditBone *self, PyObject *value, void *closure) +{ + printf("Sorry this isn't implemented yet.... :/"); + return 1; +} + +//------------------------EditBone.children (get) +static PyObject *EditBone_getChildren(BPy_EditBone *self, void *closure) +{ + printf("Sorry this isn't implemented yet.... :/"); + return EXPP_incr_ret(Py_None); +} +//------------------------EditBone.children (set) +static int EditBone_setChildren(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) +{ + printf("Sorry this isn't implemented yet.... :/"); + return EXPP_incr_ret(Py_None); +} +//------------------------EditBone.matrix (set) +static int EditBone_setMatrix(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 +//This contains methods for attributes that require checking +static PyGetSetDef BPy_EditBone_getset[] = { + {"name", (getter)EditBone_getName, (setter)EditBone_setName, + "The name of the bone", NULL}, + {"roll", (getter)EditBone_getRoll, (setter)EditBone_setRoll, + "The roll (or rotation around the axis) of the bone", NULL}, + {"head", (getter)EditBone_getHead, (setter)EditBone_setHead, + "The start point of the bone", NULL}, + {"tail", (getter)EditBone_getTail, (setter)EditBone_setTail, + "The end point of the bone", NULL}, + {"matrix", (getter)EditBone_getMatrix, (setter)EditBone_setMatrix, + "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, + "The distance at which deformation has effect", NULL}, + {"subdivisions", (getter)EditBone_getSubdivisions, (setter)EditBone_setSubdivisions, + "The number of subdivisions (for B-Bones)", NULL}, + {"options", (getter)EditBone_getOptions, (setter)EditBone_setOptions, + "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}, + {NULL} +}; -//--------------- BPy_Bone.setName()--------------------------------- -static PyObject *Bone_setName( BPy_Bone * self, PyObject * args ) +//------------------------tp_repr +//This is the string representation of the object +static PyObject *EditBone_repr(BPy_EditBone *self) { - char *name; - char buf[25]; - - if( !PyArg_ParseTuple( args, "s", &name ) ) - return ( EXPP_ReturnPyObjError - ( PyExc_AttributeError, - "expected string argument" ) ); - /* - note: - a nicer way to do this is to have #defines for the size of names. - stivs 25-jan-200 - */ - - /* guarantee a null terminated string of reasonable size */ - PyOS_snprintf( buf, sizeof( buf ), "%s", name ); - - if( !self->bone ) { //test to see if linked to armature - //use python vars - BLI_strncpy( self->name, buf, sizeof( buf ) ); - } else { - //use bone datastruct - BLI_strncpy( self->bone->name, buf, sizeof( buf ) ); - } - return EXPP_incr_ret( Py_None ); + return PyString_FromFormat( "[EditBone \"%s\"]", self->name ); } -//--------------- BPy_Bone.setRoll()-------------------------------- -PyObject *Bone_setRoll( BPy_Bone * self, PyObject * args ) -{ - float roll; - - if( !PyArg_ParseTuple( args, "f", &roll ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); +//------------------------tp_doc +//The __doc__ string for this object +static char BPy_EditBone_doc[] = "This is an internal subobject of armature\ +designed to act as a wrapper for an 'edit bone'."; - if( !self->bone ) { //test to see if linked to armature - //use python vars - self->roll = roll; - } else { - //use bone datastruct - self->bone->roll = roll; - } - return EXPP_incr_ret( Py_None ); -} - -//--------------- BPy_Bone.setHead()--------------------------------- -static PyObject *Bone_setHead( BPy_Bone * self, PyObject * args ) -{ - float f1, f2, f3; - int status; - - if( PyObject_Length( args ) == 3 ) - status = PyArg_ParseTuple( args, "fff", &f1, &f2, &f3 ); - else - status = PyArg_ParseTuple( args, "(fff)", &f1, &f2, &f3 ); - - if( !status ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected 3 (or a list of 3) float arguments" ) ); - - if( !self->bone ) { //test to see if linked to armature - //use python vars - self->head->vec[0] = f1; - self->head->vec[1] = f2; - self->head->vec[2] = f3; - } else { - //use bone datastruct - self->bone->head[0] = f1; - self->bone->head[1] = f2; - self->bone->head[2] = f3; - } - return EXPP_incr_ret( Py_None ); -} - -//--------------- BPy_Bone.setTail()--------------------------------- -static PyObject *Bone_setTail( BPy_Bone * self, PyObject * args ) +//------------------------tp_new +//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) { - float f1, f2, f3; - int status; - - if( PyObject_Length( args ) == 3 ) - status = PyArg_ParseTuple( args, "fff", &f1, &f2, &f3 ); - else - status = PyArg_ParseTuple( args, "(fff)", &f1, &f2, &f3 ); - - if( !status ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected 3 (or a list of 3) float arguments" ) ); - - if( !self->bone ) { //test to see if linked to armature - //use python vars - self->tail->vec[0] = f1; - self->tail->vec[1] = f2; - self->tail->vec[2] = f3; - } else { - //use bone datastruct - self->bone->tail[0] = f1; - self->bone->tail[1] = f2; - self->bone->tail[2] = f3; - } - return EXPP_incr_ret( Py_None ); -} - -//--------------- BPy_Bone.setLoc()---------------------------------- -static PyObject *Bone_setLoc( BPy_Bone * self, PyObject * args ) -{ - float f1, f2, f3; - int status; - - if( PyObject_Length( args ) == 3 ) - status = PyArg_ParseTuple( args, "fff", &f1, &f2, &f3 ); - else - status = PyArg_ParseTuple( args, "(fff)", &f1, &f2, &f3 ); - - if( !status ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected 3 (or a list of 3) float arguments" ) ); - - if( !self->bone ) { //test to see if linked to armature - //use python vars - self->loc->vec[0] = f1; - self->loc->vec[1] = f2; - self->loc->vec[2] = f3; - } else { - //use bone datastruct -// self->bone->loc[0] = f1; -// self->bone->loc[1] = f2; -// self->bone->loc[2] = f3; - } - return EXPP_incr_ret( Py_None ); -} + BPy_EditBone *py_editBone = NULL; + PyObject *py_bone; + struct Bone *bone; + int i; -//--------------- BPy_Bone.setSize()--------------------------------- -static PyObject *Bone_setSize( BPy_Bone * self, PyObject * args ) -{ - float f1, f2, f3; - int status; + if(!PyArg_ParseTuple(args, "O!", &Bone_Type, &py_bone)) + goto AttributeError; + + 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); + } + + py_editBone->roll = (float)boneRoll_ToArmatureSpace(bone); + + 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 +static void EditBone_dealloc(BPy_EditBone * self) +{ + ((PyObject*)self)->ob_type->tp_free((PyObject*)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 +}; - if( PyObject_Length( args ) == 3 ) - status = PyArg_ParseTuple( args, "fff", &f1, &f2, &f3 ); +//------------------METHOD IMPLEMENTATIONS-------------------------------- +//------------------ATTRIBUTE IMPLEMENTATIONS----------------------------- +//------------------------Bone.name (get) +static PyObject *Bone_getName(BPy_Bone *self, void *closure) +{ + return PyString_FromString(self->bone->name); +} +//------------------------Bone.name (set) +//check for char[] overflow here... +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"); +} +//------------------------Bone.roll (get) +static PyObject *Bone_getRoll(BPy_Bone *self, void *closure) +{ + return Py_BuildValue("{s:O, s:O}", + "BONESPACE", PyFloat_FromDouble((self->bone->roll * (180/Py_PI))), + "ARMATURESPACE", PyFloat_FromDouble((boneRoll_ToArmatureSpace(self->bone) * (180/Py_PI)))); +} +//------------------------Bone.roll (set) +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"); +} +//------------------------Bone.head (get) +static PyObject *Bone_getHead(BPy_Bone *self, void *closure) +{ + return Py_BuildValue("{s:O, s:O}", + "BONESPACE", newVectorObject(self->bone->head, 3, Py_WRAP), + "ARMATURESPACE", newVectorObject(self->bone->arm_head, 3, Py_WRAP)); +} +//------------------------Bone.head (set) +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"); +} +//------------------------Bone.tail (get) +static PyObject *Bone_getTail(BPy_Bone *self, void *closure) +{ + return Py_BuildValue("{s:O, s:O}", + "BONESPACE", newVectorObject(self->bone->tail, 3, Py_WRAP), + "ARMATURESPACE", newVectorObject(self->bone->arm_tail, 3, Py_WRAP)); +} +//------------------------Bone.tail (set) +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"); +} +//------------------------Bone.weight (get) +static PyObject *Bone_getWeight(BPy_Bone *self, void *closure) +{ + return PyFloat_FromDouble(self->bone->weight); +} +//------------------------Bone.weight (set) +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"); +} +//------------------------Bone.deform_dist (get) +static PyObject *Bone_getDeform_dist(BPy_Bone *self, void *closure) +{ + return PyFloat_FromDouble(self->bone->dist); +} +//------------------------Bone.deform_dist (set) +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"); +} +//------------------------Bone.subdivisions (get) +static PyObject *Bone_getSubdivisions(BPy_Bone *self, void *closure) +{ + return PyInt_FromLong(self->bone->segments); +} +//------------------------Bone.subdivisions (set) +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"); +} +//------------------------Bone.connected (get) +static PyObject *Bone_getOptions(BPy_Bone *self, void *closure) +{ + PyObject *list = NULL; + + list = PyList_New(0); + if (list == NULL) + goto RuntimeError; + + if(self->bone->flag & BONE_CONNECTED) + if (PyList_Append(list, + EXPP_GetModuleConstant("Blender.Armature", "CONNECTED")) == -1) + goto RuntimeError; + if(self->bone->flag & BONE_HINGE) + if (PyList_Append(list, + EXPP_GetModuleConstant("Blender.Armature", "HINGE")) == -1) + goto RuntimeError; + if(self->bone->flag & BONE_NO_DEFORM) + if (PyList_Append(list, + EXPP_GetModuleConstant("Blender.Armature", "NO_DEFORM")) == -1) + goto RuntimeError; + if(self->bone->flag & BONE_MULT_VG_ENV) + if (PyList_Append(list, + EXPP_GetModuleConstant("Blender.Armature", "MULTIPLY")) == -1) + goto RuntimeError; + if(self->bone->flag & BONE_HIDDEN_A) + if (PyList_Append(list, + EXPP_GetModuleConstant("Blender.Armature", "HIDDEN_EDIT")) == -1) + goto RuntimeError; + + return EXPP_incr_ret(list); + +RuntimeError: + return EXPP_objError(PyExc_RuntimeError, "%s%s%s", + sBoneError, "getOptions(): ", "Internal failure!"); +} +//------------------------Bone.connected (set) +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"); +} +//------------------------Bone.parent (get) +static PyObject *Bone_getParent(BPy_Bone *self, void *closure) +{ + if (self->bone->parent) + return PyBone_FromBone(self->bone->parent); else - status = PyArg_ParseTuple( args, "(fff)", &f1, &f2, &f3 ); - - if( !status ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected 3 (or a list of 3) float arguments" ) ); - - if( !self->bone ) { //test to see if linked to armature - //use python vars - self->size->vec[0] = f1; - self->size->vec[1] = f2; - self->size->vec[2] = f3; - } else { - //use bone datastruct -// self->bone->size[0] = f1; -// self->bone->size[1] = f2; -// self->bone->size[2] = f3; - } - return EXPP_incr_ret( Py_None ); -} - -//--------------- BPy_Bone.setQuat()------------------------------- -static PyObject *Bone_setQuat( BPy_Bone * self, PyObject * args ) -{ - float f1, f2, f3, f4; - PyObject *argument; - QuaternionObject *quatOb; - int status; - - if( !PyArg_ParseTuple( args, "O", &argument ) ) - return ( EXPP_ReturnPyObjError - ( PyExc_TypeError, - "expected quaternion or float list" ) ); - - if( QuaternionObject_Check( argument ) ) { - status = PyArg_ParseTuple( args, "O!", &quaternion_Type, - &quatOb ); - f1 = quatOb->quat[0]; - f2 = quatOb->quat[1]; - f3 = quatOb->quat[2]; - f4 = quatOb->quat[3]; - } else { - status = PyArg_ParseTuple( args, "(ffff)", &f1, &f2, &f3, - &f4 ); - } - - if( !status ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "unable to parse argument" ) ); - - if( !self->bone ) { //test to see if linked to armature - //use python vars - self->quat->quat[0] = f1; - self->quat->quat[1] = f2; - self->quat->quat[2] = f3; - self->quat->quat[3] = f4; - } else { - //use bone datastruct -// self->bone->quat[0] = f1; -// self->bone->quat[1] = f2; -// self->bone->quat[2] = f3; -// self->bone->quat[3] = f4; - } - return EXPP_incr_ret( Py_None ); + return EXPP_incr_ret(Py_None); } - -//--------------- BPy_Bone.setParent()------------------------------ -static PyObject *Bone_setParent( BPy_Bone * self, PyObject * args ) -{ - BPy_Bone *py_bone; - float M_boneObjectspace[4][4]; - float iM_parentRest[4][4]; - - if( !PyArg_ParseTuple( args, "O", &py_bone ) ) - return ( EXPP_ReturnPyObjError - ( PyExc_TypeError, - "expected bone object argument" ) ); - - if( !self->bone ) { //test to see if linked to armature - //use python vars - BLI_strncpy( self->parent, py_bone->name, - strlen( py_bone->name ) + 1 ); - } else { - //use bone datastruct - if( !py_bone->bone ) - return ( EXPP_ReturnPyObjError - ( PyExc_TypeError, - "Parent bone must be linked to armature first!" ) ); - - if( py_bone->bone == self->bone ) - return ( EXPP_ReturnPyObjError - ( PyExc_AttributeError, - "Cannot parent to self" ) ); - - //test to see if were creating an illegal loop by parenting to child - if( testChildbase( self->bone, py_bone->bone ) ) - return ( EXPP_ReturnPyObjError - ( PyExc_AttributeError, - "Cannot parent to child" ) ); - - //set the parent of self - in this case - //we are changing the parenting after this bone - //has been linked in it's armature - if( self->bone->parent ) { //we are parenting something previously parented - - //remove the childbase link from the parent bone - BLI_remlink( &self->bone->parent->childbase, - self->bone ); - - //now get rid of the parent transformation - get_objectspace_bone_matrix( self->bone->parent, - M_boneObjectspace, 0, 0 ); - Mat4MulVecfl( M_boneObjectspace, self->bone->head ); - Mat4MulVecfl( M_boneObjectspace, self->bone->tail ); - - //add to the childbase of new parent - BLI_addtail( &py_bone->bone->childbase, self->bone ); - - //transform bone according to new parent - get_objectspace_bone_matrix( py_bone->bone, - M_boneObjectspace, 0, 0 ); - Mat4Invert( iM_parentRest, M_boneObjectspace ); - Mat4MulVecfl( iM_parentRest, self->bone->head ); - Mat4MulVecfl( iM_parentRest, self->bone->tail ); - - //set parent - self->bone->parent = py_bone->bone; - - } else { //not previously parented - - //add to the childbase of new parent - BLI_addtail( &py_bone->bone->childbase, self->bone ); - - //transform bone according to new parent - get_objectspace_bone_matrix( py_bone->bone, - M_boneObjectspace, 0, 0 ); - Mat4Invert( iM_parentRest, M_boneObjectspace ); - Mat4MulVecfl( iM_parentRest, self->bone->head ); - Mat4MulVecfl( iM_parentRest, self->bone->tail ); - - self->bone->parent = py_bone->bone; - } - } - return EXPP_incr_ret( Py_None ); -} - -//--------------- BPy_Bone.setWeight()---------------------------- -static PyObject *Bone_setWeight( BPy_Bone * self, PyObject * args ) -{ - float weight; - - if( !PyArg_ParseTuple( args, "f", &weight ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected float argument" ) ); - - if( !self->bone ) { //test to see if linked to armature - //use python vars - self->weight = weight; - } else { - //use bone datastruct - self->bone->weight = weight; - } - return EXPP_incr_ret( Py_None ); +//------------------------Bone.parent (set) +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"); } - -//--------------- BPy_Bone.clearParent()-------------------------- -static PyObject *Bone_clearParent( BPy_Bone * self ) -{ - bArmature *arm = NULL; +//------------------------(internal) PyBone_ChildrenAsList +static int PyBone_ChildrenAsList(PyObject *list, ListBase *bones){ Bone *bone = NULL; - Bone *parent = NULL; - Bone *child = NULL; - Bone *childPrev = NULL; - int firstChild; - float M_boneObjectspace[4][4]; - char *parent_str = ""; - - if( !self->bone ) { //test to see if linked to armature - //use python vars - BLI_strncpy( self->parent, parent_str, - strlen( parent_str ) + 1 ); - } else { - //use bone datastruct - if( self->bone->parent == NULL ) - return EXPP_incr_ret( Py_None ); - - //get parent and remove link - parent = self->bone->parent; - self->bone->parent = NULL; - - //remove the childbase link from the parent bone - firstChild = 1; - for( child = parent->childbase.first; child; - child = child->next ) { - if( child == self->bone && firstChild ) { - parent->childbase.first = child->next; - child->next = NULL; - break; - } - if( child == self->bone && !firstChild ) { - childPrev->next = child->next; - child->next = NULL; - break; - } - firstChild = 0; - childPrev = child; - } - - //now get rid of the parent transformation - get_objectspace_bone_matrix( parent, M_boneObjectspace, 0, 0 ); - - //transformation of local bone - Mat4MulVecfl( M_boneObjectspace, self->bone->head ); - Mat4MulVecfl( M_boneObjectspace, self->bone->tail ); - - //get the root bone - while( parent->parent != NULL ) { - parent = parent->parent; - } - - //add unlinked bone to the bonebase of the armature - for( arm = G.main->armature.first; arm; arm = arm->id.next ) { - for( bone = arm->bonebase.first; bone; - bone = bone->next ) { - if( parent == bone ) { - //we found the correct armature - now add it as root bone - BLI_addtail( &arm->bonebase, - self->bone ); - break; - } - } - } - } - return EXPP_incr_ret( Py_None ); -} + PyObject *py_bone = NULL; + + for (bone = bones->first; bone; bone = bone->next){ + py_bone = PyBone_FromBone(bone); + if (py_bone == NULL) + return 0; + + if(PyList_Append(list, py_bone) == -1){ + goto RuntimeError; + } + if (bone->childbase.first) + PyBone_ChildrenAsList(list, &bone->childbase); + } + return 1; + +RuntimeError: + return EXPP_intError(PyExc_RuntimeError, "%s%s", + sBoneError, "Internal error trying to wrap blender bones!"); +} + +//------------------------Bone.children (get) +static PyObject *Bone_getChildren(BPy_Bone *self, void *closure) +{ + PyObject *list = NULL; + + if (self->bone->childbase.first){ + list = PyList_New(0); + if (!PyBone_ChildrenAsList(list, &self->bone->childbase)) + return NULL; + return EXPP_incr_ret(list); + }else{ + return EXPP_incr_ret(Py_None); + } +} +//------------------------Bone.children (set) +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"); +} +//------------------------Bone.matrix (get) +static PyObject *Bone_getMatrix(BPy_Bone *self, void *closure) +{ + return Py_BuildValue("{s:O, s:O}", + "BONESPACE", newMatrixObject((float*)self->bone->bone_mat, 3,3, Py_WRAP), + "ARMATURESPACE", newMatrixObject((float*)self->bone->arm_mat, 4,4, Py_WRAP)); +} +//------------------------Bone.matrix (set) +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"); +} +//------------------TYPE_OBECT IMPLEMENTATION-------------------------- +//------------------------tp_getset +//This contains methods for attributes that require checking +static PyGetSetDef BPy_Bone_getset[] = { + {"name", (getter)Bone_getName, (setter)Bone_setName, + "The name of the bone", NULL}, + {"roll", (getter)Bone_getRoll, (setter)Bone_setRoll, + "The roll (or rotation around the axis) of the bone", NULL}, + {"head", (getter)Bone_getHead, (setter)Bone_setHead, + "The start point of the bone", NULL}, + {"tail", (getter)Bone_getTail, (setter)Bone_setTail, + "The end point of the bone", NULL}, + {"matrix", (getter)Bone_getMatrix, (setter)Bone_setMatrix, + "The matrix of the bone", NULL}, + {"weight", (getter)Bone_getWeight, (setter)Bone_setWeight, + "The weight of the bone in relation to a parented mesh", NULL}, + {"deform_dist", (getter)Bone_getDeform_dist, (setter)Bone_setDeform_dist, + "The distance at which deformation has effect", NULL}, + {"subdivisions", (getter)Bone_getSubdivisions, (setter)Bone_setSubdivisions, + "The number of subdivisions (for B-Bones)", NULL}, + {"options", (getter)Bone_getOptions, (setter)Bone_setOptions, + "The options effective on this bone", NULL}, + {"parent", (getter)Bone_getParent, (setter)Bone_setParent, + "The parent bone of this bone", NULL}, + {"children", (getter)Bone_getChildren, (setter)Bone_setChildren, + "The child bones of this bone", NULL}, + {NULL} +}; -//--------------- BPy_Bone.clearChildren()------------------------ -static PyObject *Bone_clearChildren( BPy_Bone * self ) +//------------------------tp_new +static PyObject *Bone_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - Bone *root = NULL; - Bone *child = NULL; - bArmature *arm = NULL; - Bone *bone = NULL; - Bone *prev = NULL; - Bone *next = NULL; - float M_boneObjectspace[4][4]; - int first; - - if( !self->bone ) { //test to see if linked to armature - //use python vars - return EXPP_incr_ret( Py_None ); - } else { - //use bone datastruct - if( self->bone->childbase.first == NULL ) - return EXPP_incr_ret( Py_None ); - - //is this bone a part of an armature.... - //get root bone for testing - root = self->bone->parent; - if( root != NULL ) { - while( root->parent != NULL ) { - root = root->parent; - } - } else { - root = self->bone; - } - //test armatures for root bone - for( arm = G.main->armature.first; arm; arm = arm->id.next ) { - for( bone = arm->bonebase.first; bone; - bone = bone->next ) { - if( bone == root ) - break; - } - if( bone == root ) - break; - } - - if( arm == NULL ) - return ( EXPP_ReturnPyObjError - ( PyExc_RuntimeError, - "couldn't find armature that contains this bone" ) ); - - //now get rid of the parent transformation - get_objectspace_bone_matrix( self->bone, M_boneObjectspace, 0, - 0 ); - - //set children as root - first = 1; - for( child = self->bone->childbase.first; child; child = next ) { - //undo transformation of local bone - Mat4MulVecfl( M_boneObjectspace, child->head ); - Mat4MulVecfl( M_boneObjectspace, child->tail ); - - //set next pointers to NULL - if( first ) { - prev = child; - first = 0; - } else { - prev->next = NULL; - prev = child; - } - next = child->next; - - //remove parenting and linking - child->parent = NULL; - BLI_remlink( &self->bone->childbase, child ); - - //add as root - BLI_addtail( &arm->bonebase, child ); - } - } - Py_INCREF( Py_None ); - return Py_None; + return EXPP_incr_ret(Py_None); } -//--------------- BPy_Bone.hide()----------------------------------- -static PyObject *Bone_hide( BPy_Bone * self ) +//------------------------tp_richcompare +//This method allows the object to use comparison operators +static PyObject *Bone_richcmpr(BPy_Bone *self, PyObject *v, int op) { - if( !self->bone ) { //test to see if linked to armature - //use python vars - return EXPP_ReturnPyObjError( PyExc_TypeError, - "link bone to armature before attempting to hide/unhide" ); - } else { - //use bone datastruct - if( !( self->bone->flag & BONE_HIDDEN_P ) ) - self->bone->flag |= BONE_HIDDEN_P; - } - return EXPP_incr_ret( Py_None ); + return EXPP_incr_ret(Py_None); } -//--------------- BPy_Bone.unhide()------------------------------- -static PyObject *Bone_unhide( BPy_Bone * self ) +//------------------------tp_repr +//This is the string representation of the object +static PyObject *Bone_repr(BPy_Bone *self) { - if( !self->bone ) { //test to see if linked to armature - //use python vars - return EXPP_ReturnPyObjError( PyExc_TypeError, - "link bone to armature before attempting to hide/unhide" ); - } else { - //use bone datastruct - if( self->bone->flag & BONE_HIDDEN_P ) - self->bone->flag &= ~BONE_HIDDEN_P; - } - return EXPP_incr_ret( Py_None ); + return PyString_FromFormat( "[Bone \"%s\"]", self->bone->name ); } -//--------------- BPy_Bone.setPose()------------------------------- -static PyObject *Bone_setPose( BPy_Bone * self, PyObject * args ) +//------------------------tp_dealloc +//This tells how to 'tear-down' our object when ref count hits 0 +static void Bone_dealloc(BPy_Bone * self) { - Bone *root = NULL; - bPoseChannel *chan = NULL; - bPoseChannel *setChan = NULL; - Object *object = NULL; - bArmature *arm = NULL; - Bone *bone = NULL; - PyObject *flaglist = NULL; - PyObject *item = NULL; - BPy_Action *py_action = NULL; - int x; - int flagValue = 0; - - if( !self->bone ) { //test to see if linked to armature - //use python vars - return EXPP_ReturnPyObjError( PyExc_TypeError, - "cannot set pose unless bone is linked to armature" ); - } else { - //use bone datastruct - if( !PyArg_ParseTuple - ( args, "O!|O!", &PyList_Type, &flaglist, &Action_Type, - &py_action ) ) - return ( EXPP_ReturnPyObjError - ( PyExc_AttributeError, - "expected list of flags and optional action" ) ); - - for( x = 0; x < PyList_Size( flaglist ); x++ ) { - item = PyList_GetItem( flaglist, x ); - if( PyInt_Check( item ) ) { - flagValue |= PyInt_AsLong( item ); - } else { - return ( EXPP_ReturnPyObjError - ( PyExc_AttributeError, - "expected list of flags (ints)" ) ); - } - } - - //is this bone a part of an armature.... - //get root bone for testing - root = self->bone->parent; - if( root != NULL ) { - while( root->parent != NULL ) { - root = root->parent; - } - } else { - root = self->bone; - } - //test armatures for root bone - for( arm = G.main->armature.first; arm; arm = arm->id.next ) { - for( bone = arm->bonebase.first; bone; - bone = bone->next ) { - if( bone == root ) - break; - } - if( bone == root ) - break; - } - if( arm == NULL ) - return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, - "bone must belong to an armature to set it's pose!" ) ); - - //find if armature is object linked.... - for( object = G.main->object.first; object; - object = object->id.next ) { - if( object->data == arm ) { - break; - } - } - - if( object == NULL ) - return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, - "armature must be linked to an object to set a pose!" ) ); - - //set the active action as this one - if( py_action != NULL ) { - if( py_action->action != NULL ) { - object->action = py_action->action; - } - } - //if object doesn't have a pose create one - if( !object->pose ) - object->pose = MEM_callocN( sizeof( bPose ), "Pose" ); - - //if bone does have a channel create one - // do not use anymore! (ton) - chan= verify_pose_channel( object->pose, self->bone->name ); - - //create temp Pose Channel - // chan = MEM_callocN( sizeof( bPoseChannel ), "PoseChannel" ); - //set the variables for this pose -// memcpy( chan->loc, self->bone->loc, sizeof( chan->loc ) ); -// memcpy( chan->quat, self->bone->quat, sizeof( chan->quat ) ); -// memcpy( chan->size, self->bone->size, sizeof( chan->size ) ); - strcpy( chan->name, self->bone->name ); - chan->flag |= flagValue; - //set it to the channel - // setChan = set_pose_channel( object->pose, chan ); - //frees unlinked pose/bone channels from object -/* note; changing an Armature requires building poses again, consult me! (ton) */ - // collect_pose_garbage( object ); - - //create an action if one not already assigned to object - if( !py_action && !object->action ) { - object->action = ( bAction * ) add_empty_action(ID_PO); - object->ipowin = ID_PO; - } - - //set action keys (note, new uniform API for Pose ipos (ton) - if( setChan->flag & POSE_ROT ) { - insertkey(&object->id, ID_PO, setChan->name, NULL, AC_QUAT_X); - insertkey(&object->id, ID_PO, setChan->name, NULL, AC_QUAT_Y); - insertkey(&object->id, ID_PO, setChan->name, NULL, AC_QUAT_Z); - insertkey(&object->id, ID_PO, setChan->name, NULL, AC_QUAT_W); - } - if( setChan->flag & POSE_SIZE ) { - insertkey(&object->id, ID_PO, setChan->name, NULL, AC_SIZE_X); - insertkey(&object->id, ID_PO, setChan->name, NULL, AC_SIZE_Y); - insertkey(&object->id, ID_PO, setChan->name, NULL, AC_SIZE_Z); - } - if( setChan->flag & POSE_LOC ) { - insertkey(&object->id, ID_PO, setChan->name, NULL, AC_LOC_X); - insertkey(&object->id, ID_PO, setChan->name, NULL, AC_LOC_Y); - insertkey(&object->id, ID_PO, setChan->name, NULL, AC_LOC_Z); - } - //rebuild ipos - remake_action_ipos( object->action ); - - //signal to rebuild displists (new! added by ton) - object->recalc |= OB_RECALC_DATA; - } - return EXPP_incr_ret( Py_None ); + ((PyObject*)self)->ob_type->tp_free((PyObject*)self); + return; } -//--------------- BPy_Bone.getBoneclass()-------------------------- -static PyObject *Bone_getBoneclass( BPy_Bone * self ) -{ - PyObject *attr = NULL; - - if( !self->bone ) { //test to see if linked to armature - //use python vars - attr = returnBoneclassEnum( self->boneclass ); - } else { - //use bone datastruct - attr = returnBoneclassEnum( self->bone->boneclass ); - } - if( attr ) - return attr; +//------------------------tp_doc +//The __doc__ string for this object +static char BPy_Bone_doc[] = "This object wraps a Blender Boneobject.\n\ + This object is a subobject of the Armature object."; - return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, - "couldn't get Bone.Boneclass attribute" ) ); -} - -//--------------- BPy_Bone.setBoneclass()--------------------------- -static PyObject *Bone_setBoneclass( BPy_Bone * self, PyObject * args ) +//------------------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 +}; +//------------------VISIBLE PROTOTYPE IMPLEMENTATION----------------------- +//-----------------(internal) +//Converts a struct Bone to a BPy_Bone +PyObject *PyBone_FromBone(struct Bone *bone) { - int boneclass; - - if( !PyArg_ParseTuple( args, "i", &boneclass ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected enum argument" ) ); - - if( !self->bone ) { //test to see if linked to armature - //use python vars - self->boneclass = boneclass; - } else { - //use bone datastruct - self->bone->boneclass = (short)boneclass; - } - return EXPP_incr_ret( Py_None ); -} + BPy_Bone *py_Bone = NULL; -//--------------- BPy_Bone.hasIK()------------------------------- -static PyObject *Bone_hasIK( BPy_Bone * self ) -{ - if( !self->bone ) { //test to see if linked to armature - //use python vars - if( self->flag & BONE_CONNECTED ) { - return EXPP_incr_ret_True(); - } else { - return EXPP_incr_ret_False(); - } - } else { - //use bone datastruct - if( self->bone->flag & BONE_CONNECTED ) { - return EXPP_incr_ret_True(); - } else { - return EXPP_incr_ret_False(); - } - } -} + py_Bone = (BPy_Bone*)Bone_Type.tp_alloc(&Bone_Type, 0); //*new* + if (py_Bone == NULL) + goto RuntimeError; -//--------------- BPy_Bone.getRestMatrix()------------------------- + py_Bone->bone = bone; -/* we now got BoneSpace, ArmatureSpace, PoseSpace, WorldSpace. - check DNA_armature.h, only read from data itself, dont use evil calls - that evaluate animation system anymore (ton) */ + return (PyObject *) py_Bone; -static PyObject *Bone_getRestMatrix( BPy_Bone * self, PyObject * args ) +RuntimeError: + return EXPP_objError(PyExc_RuntimeError, "%s%s%s", + sBoneError, "PyBone_FromBone: ", "Internal Error Ocurred"); +} +//-----------------(internal) +//Converts a PyBone to a bBone +struct Bone *PyBone_AsBone(BPy_Bone *py_Bone) { - char *local = "worldspace"; - char *bonespace = "bonespace"; - char *worldspace = "worldspace"; - PyObject *matrix; - float delta[3]; - float root[3]; - float p_root[3]; - - if( !PyArg_ParseTuple( args, "|s", &local ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected string" ) ); - - if( !BLI_streq( local, bonespace ) && !BLI_streq( local, worldspace ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected 'bonespace' or 'worldspace'" ) ); - - matrix = newMatrixObject( NULL, 4, 4 , Py_NEW); - - if( !self->bone ) { //test to see if linked to armature - //use python vars - if( BLI_streq( local, worldspace ) ) { - VecSubf( delta, self->tail->vec, self->head->vec ); -// make_boneMatrixvr( (float ( * )[4]) *( ( MatrixObject * ) matrix )-> -// matrix, delta, self->roll ); - } else if( BLI_streq( local, bonespace ) ) { - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "bone not yet linked to an armature....'" ) ); - } - } else { - //use bone datastruct - if( BLI_streq( local, worldspace ) ) { - get_objectspace_bone_matrix( self->bone, - ( float ( * )[4] ) *( ( MatrixObject * ) - matrix )->matrix, 1, - 1 ); - } else if( BLI_streq( local, bonespace ) ) { - VecSubf( delta, self->bone->tail, self->bone->head ); -// make_boneMatrixvr( (float ( * )[4]) *( ( MatrixObject * ) matrix )-> -// matrix, delta, self->bone->roll ); - if( self->bone->parent ) { - -// get_bone_root_pos( self->bone, root, 1 ); -// get_bone_root_pos( self->bone->parent, p_root, -// 1 ); - VecSubf( delta, root, p_root ); - VECCOPY( ( ( MatrixObject * ) matrix )-> - matrix[3], delta ); - } - } - } - - return matrix; + return (py_Bone->bone); } |