/* * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. The Blender * Foundation also sells licenses for use in proprietary software under * the Blender License. See http://www.blender.org/BL/ for information * about this. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 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 * * ***** END GPL/BL DUAL LICENSE BLOCK ***** */ #include "Bone.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "constant.h" #include "gen_utils.h" #include "NLA.h" #include "quat.h" #include "matrix.h" #include "vector.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 ); 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_setParent( BPy_Bone * self, PyObject * args ); static PyObject *Bone_setWeight( BPy_Bone * self, PyObject * args ); static PyObject *Bone_setPose( 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 ) { int x, y; 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 ); } 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]; } } 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 = 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 ); } 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 ); } //---------------BPy_Bone internal callbacks/methods--------------- //--------------- dealloc------------------------------------------ static void Bone_dealloc( BPy_Bone * self ) { PyMem_Free( self->name ); PyMem_Free( self->parent ); PyObject_DEL( self ); } //---------------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 ); } //--------------- setattr------------------------------------------- static int Bone_setAttr( BPy_Bone * self, char *name, PyObject * value ) { 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 */ } //--------------- repr--------------------------------------------- static PyObject *Bone_repr( BPy_Bone * self ) { if( self->bone ) return PyString_FromFormat( "[Bone \"%s\"]", self->bone->name ); else return PyString_FromString( "NULL" ); } //--------------- compare------------------------------------------ static int Bone_compare( BPy_Bone * a, BPy_Bone * b ) { Bone *pa = a->bone, *pb = b->bone; return ( pa == pb ) ? 0 : -1; } //--------------- 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( PyMem_Malloc( 3 * sizeof( float ) ), 3 ); blen_bone->tail = ( VectorObject * ) newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 ); blen_bone->loc = ( VectorObject * ) newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 ); blen_bone->dloc = ( VectorObject * ) newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 ); blen_bone->size = ( VectorObject * ) newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 ); blen_bone->dsize = ( VectorObject * ) newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 ); blen_bone->quat = ( QuaternionObject * ) newQuaternionObject( PyMem_Malloc( 4 * sizeof( float ) ) ); blen_bone->dquat = ( QuaternionObject * ) newQuaternionObject( PyMem_Malloc( 4 * sizeof( float ) ) ); blen_bone->obmat = ( MatrixObject * ) newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 ); blen_bone->parmat = ( MatrixObject * ) newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 ); blen_bone->defmat = ( MatrixObject * ) newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 ); blen_bone->irestmat = ( MatrixObject * ) newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 ); blen_bone->posemat = ( MatrixObject * ) newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 ); if( !updatePyBone( blen_bone ) ) return EXPP_ReturnPyObjError( PyExc_AttributeError, "bone struct empty" ); return ( ( PyObject * ) blen_bone ); } //--------------- Bone_CheckPyObject-------------------------------- int Bone_CheckPyObject( PyObject * py_obj ) { 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( PyMem_Malloc( 3 * sizeof( float ) ), 3 ); py_bone->tail = ( VectorObject * ) newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 ); py_bone->loc = ( VectorObject * ) newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 ); py_bone->dloc = ( VectorObject * ) newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 ); py_bone->size = ( VectorObject * ) newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 ); py_bone->dsize = ( VectorObject * ) newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 ); py_bone->quat = ( QuaternionObject * ) newQuaternionObject( PyMem_Malloc( 4 * sizeof( float ) ) ); py_bone->dquat = ( QuaternionObject * ) newQuaternionObject( PyMem_Malloc( 4 * sizeof( float ) ) ); py_bone->obmat = ( MatrixObject * ) newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 ); py_bone->parmat = ( MatrixObject * ) newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 ); py_bone->defmat = ( MatrixObject * ) newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 ); py_bone->irestmat = ( MatrixObject * ) newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 ); py_bone->posemat = ( MatrixObject * ) newMatrixObject( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 ); //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->boneclass = BONE_SKINNABLE; 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; int x; if( !self->bone ) { //test to see if linked to armature //use python vars vec = PyMem_Malloc( 3 * sizeof( float ) ); for( x = 0; x < 3; x++ ) vec[x] = self->head->vec[x]; attr = ( PyObject * ) newVectorObject( vec, 3 ); } else { //use bone datastruct attr = newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 ); ( ( 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" ) ); } //--------------- BPy_Bone.getTail()--------------------------------- static PyObject *Bone_getTail( BPy_Bone * self ) { PyObject *attr = NULL; float *vec; int x; if( !self->bone ) { //test to see if linked to armature //use python vars vec = PyMem_Malloc( 3 * sizeof( float ) ); for( x = 0; x < 3; x++ ) vec[x] = self->tail->vec[x]; attr = ( PyObject * ) newVectorObject( vec, 3 ); } else { //use bone datastruct attr = newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 ); ( ( 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; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Bone.tail attribute" ) ); } //--------------- BPy_Bone.getLoc()--------------------------------- static PyObject *Bone_getLoc( BPy_Bone * self ) { PyObject *attr = NULL; float *vec; int x; if( !self->bone ) { //test to see if linked to armature //use python vars vec = PyMem_Malloc( 3 * sizeof( float ) ); for( x = 0; x < 3; x++ ) vec[x] = self->loc->vec[x]; attr = ( PyObject * ) newVectorObject( vec, 3 ); } else { //use bone datastruct attr = newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 ); ( ( 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" ) ); } //--------------- BPy_Bone.getSize()----------------------------- static PyObject *Bone_getSize( BPy_Bone * self ) { PyObject *attr = NULL; float *vec; int x; if( !self->bone ) { //test to see if linked to armature //use python vars vec = PyMem_Malloc( 3 * sizeof( float ) ); for( x = 0; x < 3; x++ ) vec[x] = self->size->vec[x]; attr = ( PyObject * ) newVectorObject( vec, 3 ); } else { //use bone datastruct attr = newVectorObject( PyMem_Malloc( 3 * sizeof( float ) ), 3 ); ( ( 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; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Bone.size attribute" ) ); } //--------------- BPy_Bone.getQuat()-------------------------------- static PyObject *Bone_getQuat( BPy_Bone * self ) { PyObject *attr = NULL; float *quat; 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 quat = PyMem_Malloc( 4 * sizeof( float ) ); for( x = 0; x < 4; x++ ) quat[x] = self->quat->quat[x]; attr = ( PyObject * ) newQuaternionObject( quat ); } else { //use bone datastruct attr = newQuaternionObject( PyMem_Malloc ( 4 * sizeof( float ) ) ); ( ( 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; } //--------------- BPy_Bone.hasParent()--------------------------- static PyObject *Bone_hasParent( 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_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(); } } } //--------------- 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 ); } } } //--------------- 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; } return listbones; } } //--------------- BPy_Bone.setName()--------------------------------- static PyObject *Bone_setName( BPy_Bone * self, PyObject * args ) { 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 ); } //--------------- 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" ) ); 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 ) { 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_Bone.setSize()--------------------------------- static PyObject *Bone_setSize( 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->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 ); } //--------------- 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 ); } //--------------- BPy_Bone.clearParent()-------------------------- static PyObject *Bone_clearParent( BPy_Bone * self ) { bArmature *arm = NULL; 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 ); } //--------------- BPy_Bone.clearChildren()------------------------ static PyObject *Bone_clearChildren( BPy_Bone * self ) { 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; } //--------------- BPy_Bone.hide()----------------------------------- static PyObject *Bone_hide( 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 ) ) self->bone->flag |= BONE_HIDDEN; } return EXPP_incr_ret( Py_None ); } //--------------- BPy_Bone.unhide()------------------------------- static PyObject *Bone_unhide( 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 ) self->bone->flag &= ~BONE_HIDDEN; } return EXPP_incr_ret( Py_None ); } //--------------- BPy_Bone.setPose()------------------------------- static PyObject *Bone_setPose( BPy_Bone * self, PyObject * args ) { Bone *root = NULL; bPoseChannel *chan = NULL; bPoseChannel *setChan = NULL; bPoseChannel *test = 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; int makeCurve = 1; 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 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 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( ); object->ipowin = ID_AC; } else { //test if posechannel is already in action for( test = object->action->chanbase.first; test; test = test->next ) { if( test == setChan ) makeCurve = 0; //already there } } //set action keys if( setChan->flag & POSE_ROT ) { set_action_key( object->action, setChan, AC_QUAT_X, makeCurve ); set_action_key( object->action, setChan, AC_QUAT_Y, makeCurve ); set_action_key( object->action, setChan, AC_QUAT_Z, makeCurve ); set_action_key( object->action, setChan, AC_QUAT_W, makeCurve ); } if( setChan->flag & POSE_SIZE ) { set_action_key( object->action, setChan, AC_SIZE_X, makeCurve ); set_action_key( object->action, setChan, AC_SIZE_Y, makeCurve ); set_action_key( object->action, setChan, AC_SIZE_Z, makeCurve ); } if( setChan->flag & POSE_LOC ) { set_action_key( object->action, setChan, AC_LOC_X, makeCurve ); set_action_key( object->action, setChan, AC_LOC_Y, makeCurve ); set_action_key( object->action, setChan, AC_LOC_Z, makeCurve ); } //rebuild ipos remake_action_ipos( object->action ); //rebuild displists rebuild_all_armature_displists( ); } return EXPP_incr_ret( Py_None ); } //--------------- 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; return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Bone.Boneclass attribute" ) ); } //--------------- BPy_Bone.setBoneclass()--------------------------- static PyObject *Bone_setBoneclass( BPy_Bone * self, PyObject * args ) { 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 = boneclass; } return EXPP_incr_ret( Py_None ); } //--------------- 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_IK_TOPARENT ) { return EXPP_incr_ret_True(); } else { return EXPP_incr_ret_False(); } } else { //use bone datastruct if( self->bone->flag & BONE_IK_TOPARENT ) { return EXPP_incr_ret_True(); } else { return EXPP_incr_ret_False(); } } return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, "couldn't get Bone.Boneclass attribute" ) ); } //--------------- BPy_Bone.getRestMatrix()------------------------- static PyObject *Bone_getRestMatrix( BPy_Bone * self, PyObject * args ) { 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( PyMem_Malloc( 16 * sizeof( float ) ), 4, 4 ); 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; }