diff options
-rw-r--r-- | source/blender/python/api2_2x/Armature.c | 1307 | ||||
-rw-r--r-- | source/blender/python/api2_2x/Armature.h | 37 | ||||
-rw-r--r-- | source/blender/python/api2_2x/Bone.c | 2289 | ||||
-rw-r--r-- | source/blender/python/api2_2x/Bone.h | 75 | ||||
-rw-r--r-- | source/blender/python/api2_2x/Object.c | 14 |
5 files changed, 1625 insertions, 2097 deletions
diff --git a/source/blender/python/api2_2x/Armature.c b/source/blender/python/api2_2x/Armature.c index 1a1a9ea3498..3ea6b81b000 100644 --- a/source/blender/python/api2_2x/Armature.c +++ b/source/blender/python/api2_2x/Armature.c @@ -1,4 +1,4 @@ -/* +/* * $Id$ * * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** @@ -23,19 +23,17 @@ * 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 "Armature.h" /*This must come first*/ +#include "Armature.h" //This must come first #include "BKE_main.h" #include "BKE_global.h" #include "BKE_armature.h" #include "BKE_library.h" +#include "BKE_depsgraph.h" +#include "BKE_utildefines.h" #include "BLI_blenlib.h" #include "BLI_arithb.h" #include "MEM_guardedalloc.h" @@ -43,628 +41,889 @@ #include "NLA.h" #include "gen_utils.h" -//---------------- Python API function prototypes for the Armature module--- -static PyObject *M_Armature_New( PyObject * self, PyObject * args ); -static PyObject *M_Armature_Get( PyObject * self, PyObject * args ); - -//------------- Python API Doc Strings for the Armature module----------- -static char M_Armature_doc[] = "The Blender Armature module\n\n\ - This module provides control over **Armature Data** objects in Blender.\n"; -static char M_Armature_New_doc[] = - "(name) - return a new Armature datablock of \n\ - optional name 'name'."; -static char M_Armature_Get_doc[] = - "(name) - return the armature with the name 'name', \ - returns None if not found.\n If 'name' is not specified, it returns a list of all armatures in the\ncurrent scene."; -static char M_Armature_get_doc[] = "(name) - DEPRECATED. Use 'Get' instead. \ - return the armature with the name 'name', returns None if not found.\n If 'name' is not specified, \ - it returns a list of all armatures in the\ncurrent scene."; - -//------Python method structure definition for Blender.Armature module----- -struct PyMethodDef M_Armature_methods[] = { - {"New", ( PyCFunction ) M_Armature_New, METH_VARARGS, - M_Armature_New_doc}, - {"Get", M_Armature_Get, METH_VARARGS, M_Armature_Get_doc}, - {"get", M_Armature_Get, METH_VARARGS, M_Armature_get_doc}, - {NULL, NULL, 0, NULL} -}; -//--------Python BPy_Armature methods declarations---------------------------- -static PyObject *Armature_getName( BPy_Armature * self ); -static PyObject *Armature_getBones( BPy_Armature * self ); -static PyObject *Armature_addBone( BPy_Armature * self, PyObject * args ); -static PyObject *Armature_setName( BPy_Armature * self, PyObject * args ); -static PyObject *Armature_drawAxes( BPy_Armature * self, PyObject * args ); -static PyObject *Armature_drawNames( BPy_Armature * self, PyObject * args ); -//----------------Python BPy_Armature methods table--------------------------- -static PyMethodDef BPy_Armature_methods[] = { - {"getName", ( PyCFunction ) Armature_getName, METH_NOARGS, - "() - return Armature name"}, - {"getBones", ( PyCFunction ) Armature_getBones, METH_NOARGS, - "() - return Armature root bones"}, - {"setName", ( PyCFunction ) Armature_setName, METH_VARARGS, - "(str) - rename Armature"}, - {"addBone", ( PyCFunction ) Armature_addBone, METH_VARARGS, - "(bone)-add bone"}, - {"drawAxes", ( PyCFunction ) Armature_drawAxes, METH_VARARGS, - "will draw the axis of each bone in armature"}, - {"drawNames", ( PyCFunction ) Armature_drawNames, METH_VARARGS, - "will draw the names of each bone in armature"}, - {NULL, NULL, 0, NULL} +#include "DNA_object_types.h" //This must come before BIF_editarmature.h... +#include "BIF_editarmature.h" + +//------------------UNDECLARED EXTERNAL PROTOTYPES-------------------- +//These are evil 'extern' declarations for functions with no anywhere +extern void free_editArmature(void); +extern void make_boneList(ListBase* list, ListBase *bones, EditBone *parent); +extern void editbones_to_armature (ListBase *list, Object *ob, bArmature *armature); + +//------------------------ERROR CODES--------------------------------- +//This is here just to make me happy and to have more consistant error strings :) +static const char sBoneDictError[] = "ArmatureType.bones - Error: "; +static const char sBoneDictBadArgs[] = "ArmatureType.bones - Bad Arguments: "; +static const char sArmatureError[] = "ArmatureType - Error: "; +static const char sArmatureBadArgs[] = "ArmatureType - Bad Arguments: "; +static const char sModuleError[] = "Blender.Armature - Error: "; +static const char sModuleBadArgs[] = "Blender.Armature - Bad Arguments: "; + +//################## BonesDict_Type (internal) ######################## +/*This is an internal psuedo-dictionary type that allows for manipulation +* of bones inside of an armature. It is a subobject of armature. +* i.e. Armature.bones['key']*/ +//##################################################################### + +//------------------METHOD IMPLEMENTATIONS----------------------------- +//------------------------Armature.bones.items() +//Returns a list of key:value pairs like dict.items() +PyObject* BonesDict_items(BPy_BonesDict *self) +{ + if (self->editmode_flag){ + return PyDict_Items(self->editBoneDict); + }else{ + return PyDict_Items(self->dict); + } +} +//------------------------Armature.bones.keys() +//Returns a list of keys like dict.keys() +PyObject* BonesDict_keys(BPy_BonesDict *self) +{ + if (self->editmode_flag){ + return PyDict_Keys(self->editBoneDict); + }else{ + return PyDict_Keys(self->dict); + } +} +//------------------------Armature.bones.values() +//Returns a list of values like dict.values() +PyObject* BonesDict_values(BPy_BonesDict *self) +{ + if (self->editmode_flag){ + return PyDict_Values(self->editBoneDict); + }else{ + return PyDict_Values(self->dict); + } +} +//------------------ATTRIBUTE IMPLEMENTATION--------------------------- +//------------------TYPE_OBECT IMPLEMENTATION-------------------------- +//------------------------tp_doc +//The __doc__ string for this object +static char BPy_BonesDict_doc[] = "This is an internal subobject of armature\ +designed to act as a Py_Bone dictionary."; + +//------------------------tp_methods +//This contains a list of all methods the object contains +static PyMethodDef BPy_BonesDict_methods[] = { + {"items", (PyCFunction) BonesDict_items, METH_NOARGS, + "() - Returns the key:value pairs from the dictionary"}, + {"keys", (PyCFunction) BonesDict_keys, METH_NOARGS, + "() - Returns the keys the dictionary"}, + {"values", (PyCFunction) BonesDict_values, METH_NOARGS, + "() - Returns the values from the dictionary"}, + {NULL} }; -//----------------Python TypeArmature callback function prototypes----------- -static void Armature_dealloc( BPy_Armature * armature ); -static PyObject *Armature_getAttr( BPy_Armature * armature, char *name ); -static int Armature_setAttr( BPy_Armature * armature, char *name, - PyObject * v ); -static int Armature_compare( BPy_Armature * a1, BPy_Armature * a2 ); -static PyObject *Armature_repr( BPy_Armature * armature ); -static int doesBoneName_exist( char *name, bArmature * arm ); - -//---------------- Python TypeArmature structure definition:----------- -PyTypeObject Armature_Type = { - PyObject_HEAD_INIT( NULL ) - 0, /* ob_size */ - "Blender Armature", /* tp_name */ - sizeof( BPy_Armature ), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - ( destructor ) Armature_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - ( getattrfunc ) Armature_getAttr, /* tp_getattr */ - ( setattrfunc ) Armature_setAttr, /* tp_setattr */ - ( cmpfunc ) Armature_compare, /* tp_compare */ - ( reprfunc ) Armature_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_Armature_methods, /* tp_methods */ - 0, /* tp_members */ -}; -//-------------------Blender Armature Module Init----------------- -PyObject *Armature_Init( void ) +//------------------------tp_new +//This methods creates a new object (note it does not initialize it - only the building) +static PyObject *BonesDict_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyObject *submodule; - PyObject *dict; + BPy_BonesDict *py_BonesDict = NULL; - Armature_Type.ob_type = &PyType_Type; + py_BonesDict = (BPy_BonesDict*)type->tp_alloc(type, 0); + if (!py_BonesDict) + goto RuntimeError; - submodule = Py_InitModule3( "Blender.Armature", - M_Armature_methods, M_Armature_doc ); + py_BonesDict->dict = PyDict_New(); + if(!py_BonesDict->dict) + goto RuntimeError; - /* Add the Bone submodule to this module */ - dict = PyModule_GetDict( submodule ); - PyDict_SetItemString( dict, "Bone", Bone_Init( ) ); - PyDict_SetItemString( dict, "NLA", NLA_Init( ) ); + py_BonesDict->editBoneDict = PyDict_New(); + if (py_BonesDict->editBoneDict == NULL) + goto RuntimeError; - return ( submodule ); -} + py_BonesDict->editmode_flag = 0; -//----------------------Blender Armature Module internal callbacks---- + return (PyObject*)py_BonesDict; -//------------------append_childrenToList----------------------------------- -static void append_childrenToList( Bone * parent, PyObject * listbones ) +RuntimeError: + return EXPP_objError(PyExc_RuntimeError, "%s%s", + sBoneDictError, "Failed to create dictionary!"); +} +//------------------------tp_repr +//This is the string representation of the object +static PyObject *BonesDict_repr(BPy_BonesDict *self) { - Bone *child = NULL; - - //append children - for( child = parent->childbase.first; child; child = child->next ) { - PyList_Append( listbones, Bone_CreatePyObject( child ) ); - if( child->childbase.first ) { //has children? - append_childrenToList( child, listbones ); + char buffer[128], str[4096]; + PyObject *key, *value; + int pos = 0; + + BLI_strncpy(str,"",4096); + sprintf(buffer, "[Bone Dict: {"); + strcat(str,buffer); + if (self->editmode_flag){ + while (PyDict_Next(self->editBoneDict, &pos, &key, &value)) { + sprintf(buffer, "%s : %s, ", PyString_AsString(key), + PyString_AsString(value->ob_type->tp_repr(value))); + strcat(str,buffer); + } + }else{ + while (PyDict_Next(self->dict, &pos, &key, &value)) { + sprintf(buffer, "%s : %s, ", PyString_AsString(key), + PyString_AsString(value->ob_type->tp_repr(value))); + strcat(str,buffer); } } + sprintf(buffer, "}]\n"); + strcat(str,buffer); + return PyString_FromString(str); } -//------------------unique_BoneName---------------------------- -static void unique_BoneName( char *name, bArmature * arm ) +//------------------------tp_dealloc +//This tells how to 'tear-down' our object when ref count hits 0 +static void BonesDict_dealloc(BPy_BonesDict * self) { - char tempname[64]; - int number; - char *dot; - - if( doesBoneName_exist( name, arm ) ) { - /* Strip off the suffix */ - dot = strchr( name, '.' ); - if( dot ) - *dot = 0; - - for( number = 1; number <= 999; number++ ) { - sprintf( tempname, "%s.%03d", name, number ); - if( !doesBoneName_exist( tempname, arm ) ) { - strcpy( name, tempname ); - return; - } - } + Py_DECREF(self->dict); + Py_DECREF(self->editBoneDict); + ((PyObject*)self)->ob_type->tp_free((PyObject*)self); + return; +} +//------------------------mp_length +//This gets the size of the dictionary +int BonesDict_len(BPy_BonesDict *self) +{ + if (self->editmode_flag){ + return PyDict_Size(self->editBoneDict); + }else{ + return PyDict_Size(self->dict); } } - -//------------------doesBoneName_exist---------------------------- -static int doesBoneName_exist( char *name, bArmature * arm ) +//-----------------------mp_subscript +//This defines getting a bone from the dictionary - x = Bones['key'] +PyObject *BonesDict_GetItem(BPy_BonesDict *self, PyObject* key) +{ + PyObject *value = NULL; + + if (self->editmode_flag){ + value = PyDict_GetItem(self->editBoneDict, key); + }else{ + value = PyDict_GetItem(self->dict, key); + } + if(value == NULL){ + return EXPP_incr_ret(Py_None); + } + return EXPP_incr_ret(value); +} +//-----------------------mp_ass_subscript +//This does dict assignment - Bones['key'] = value +int BonesDict_SetItem(BPy_BonesDict *self, PyObject *key, PyObject *value) { - Bone *parent = NULL; - Bone *child = NULL; - - for( parent = arm->bonebase.first; parent; parent = parent->next ) { - if( !strcmp( name, parent->name ) ) - return 1; - for( child = parent->childbase.first; child; - child = child->next ) { - if( !strcmp( name, child->name ) ) - return 1; + char *key_str = "", *name = "", *misc = ""; + static char *kwlist[] = {"name", "misc", NULL}; + + //Get the key name + if(key && PyString_Check(key)){ + key_str = PyString_AsString(key); + }else{ + goto AttributeError; + } + + //Parse the value for assignment + if(value && PyDict_Check(value)){ + if(!PyArg_ParseTupleAndKeywords(Py_BuildValue("()"), value, "|ss", kwlist, &name, &misc)){ + goto AttributeError; } + }else{ + goto AttributeError; } return 0; -} -//------------------testChildInChildbase-------------------------- -static int testChildInChildbase( Bone * bone, Bone * test ) -{ - Bone *child; - for( child = bone->childbase.first; child; child = child->next ) { - if( child == test ) { - return 1; - } else { - if( child->childbase.first != NULL ) { - if( testChildInChildbase( child, test ) ) { - return 1; - } - } +AttributeError: + return EXPP_intError(PyExc_AttributeError, "%s%s", + sBoneDictBadArgs, "Expects (optional) name='string', misc='string'"); +} +//------------------TYPE_OBECT DEFINITION-------------------------- +//Mapping Protocol +static PyMappingMethods BonesDict_MapMethods = { + (inquiry) BonesDict_len, //mp_length + (binaryfunc)BonesDict_GetItem, //mp_subscript + (objobjargproc)BonesDict_SetItem, //mp_ass_subscript +}; +//BonesDict TypeObject +PyTypeObject BonesDict_Type = { + PyObject_HEAD_INIT(NULL) //tp_head + 0, //tp_internal + "BonesDict", //tp_name + sizeof(BPy_BonesDict), //tp_basicsize + 0, //tp_itemsize + (destructor)BonesDict_dealloc, //tp_dealloc + 0, //tp_print + 0, //tp_getattr + 0, //tp_setattr + 0, //tp_compare + (reprfunc) BonesDict_repr, //tp_repr + 0, //tp_as_number + 0, //tp_as_sequence + &BonesDict_MapMethods, //tp_as_mapping + 0, //tp_hash + 0, //tp_call + 0, //tp_str + 0, //tp_getattro + 0, //tp_setattro + 0, //tp_as_buffer + Py_TPFLAGS_DEFAULT, //tp_flags + BPy_BonesDict_doc, //tp_doc + 0, //tp_traverse + 0, //tp_clear + 0, //tp_richcompare + 0, //tp_weaklistoffset + 0, //tp_iter + 0, //tp_iternext + BPy_BonesDict_methods, //tp_methods + 0, //tp_members + 0, //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)BonesDict_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 +}; +//-----------------(internal) +static int BonesDict_Init(PyObject *dictionary, ListBase *bones){ + Bone *bone = NULL; + PyObject *py_bone = NULL; + + for (bone = bones->first; bone; bone = bone->next){ + py_bone = PyBone_FromBone(bone); + if (py_bone == NULL) + return -1; + + if(PyDict_SetItem(dictionary, PyString_FromString(bone->name), py_bone) == -1){ + goto RuntimeError; } + if (bone->childbase.first) + BonesDict_Init(dictionary, &bone->childbase); } return 0; + +RuntimeError: + return EXPP_intError(PyExc_RuntimeError, "%s%s", + sBoneDictError, "Internal error trying to wrap blender bones!"); } -//------------------testBoneInArmature----------------------------- -static int testBoneInArmature( bArmature * arm, Bone * test ) +//######################### Armature_Type ############################# +/*This type represents a thin wrapper around bArmature data types +* internal to blender. It contains the psuedo-dictionary BonesDict +* as an assistant in manipulating it's own bone collection*/ +//##################################################################### + +//------------------METHOD IMPLEMENTATION------------------------------ +//This is a help function for Armature_makeEditable +static int PyArmature_InitEditBoneDict(PyObject *dictionary, ListBase *branch) { - Bone *root; - for( root = arm->bonebase.first; root; root = root->next ) { - if( root == test ) { - return 1; - } else { - if( root->childbase.first != NULL ) { - if( testChildInChildbase( root, test ) ) { - return 1; - } - } + struct Bone *bone = NULL; + PyObject *args, *py_editBone = NULL, *py_bone = NULL; + + for (bone = branch->first; bone; bone = bone->next){ + + //create a new editbone based on the bone data + py_bone = PyBone_FromBone(bone); //new + if (py_bone == NULL) + goto RuntimeError; + + args = Py_BuildValue("(O)",py_bone); //new + + py_editBone = EditBone_Type.tp_new(&EditBone_Type, args, NULL); //new + if (py_editBone == NULL) + goto RuntimeError; + + //add the new editbone to the dictionary + if (PyDict_SetItemString(dictionary, bone->name, py_editBone) == -1) + goto RuntimeError; + + if(bone->childbase.first){ + PyArmature_InitEditBoneDict(dictionary, &bone->childbase); } } return 0; -} -//-----------------testChildNameInChildbase-------------------------- -static Bone *testChildNameInChildbase( Bone * bone, char *name ) +RuntimeError: + return EXPP_intError(PyExc_RuntimeError, "%s%s", + sArmatureError, "Internal error trying to construct an edit armature!"); + +} +//------------------------Armature.makeEditable() +static PyObject *Armature_makeEditable(BPy_Armature *self) { - Bone *child; - Bone *test; - for( child = bone->childbase.first; child; child = child->next ) { - if( BLI_streq( child->name, name ) ) { - return child; - } else { - if( child->childbase.first != NULL ) { - test = testChildNameInChildbase( child, name ); - if( test ) - return test; - } - } + if (PyArmature_InitEditBoneDict(((BPy_BonesDict*)self->Bones)->editBoneDict, + &self->armature->bonebase) == -1){ + return NULL; //error already set } - return NULL; + ((BPy_BonesDict*)self->Bones)->editmode_flag = 1; + return EXPP_incr_ret(Py_None); } -//----------------testBoneNameInArmature---------------------------- -static Bone *testBoneNameInArmature( bArmature * arm, char *name ) +static void PyArmature_FixRolls(ListBase *branch, PyObject *dictionary) { - Bone *bone; - Bone *test; - for( bone = arm->bonebase.first; bone; bone = bone->next ) { - if( BLI_streq( bone->name, name ) ) { - return bone; //found it - } else { - if( bone->childbase.first != NULL ) { - test = testChildNameInChildbase( bone, name ); - if( test ) - return test; + float premat[3][3],postmat[3][3]; + float difmat[3][3],imat[3][3], delta[3]; + BPy_EditBone *py_editBone = NULL; + struct Bone *bone = NULL; + int keyCheck = -1; + + for (bone = branch->first; bone; bone = bone->next){ + + where_is_armature_bone(bone, bone->parent); //set bone_mat, arm_mat, length, etc. + + keyCheck = PySequence_Contains(dictionary, PyString_FromString(bone->name)); + if (keyCheck == 1){ + + py_editBone = (BPy_EditBone*)PyDict_GetItem(dictionary, + PyString_FromString(bone->name)); //borrowed + VecSubf (delta, py_editBone->tail, py_editBone->head); + vec_roll_to_mat3(delta, py_editBone->roll, premat); //pre-matrix + Mat3CpyMat4(postmat, bone->arm_mat); //post-matrix + Mat3Inv(imat, premat); + Mat3MulMat3(difmat, imat, postmat); + + bone->roll = (float)-atan(difmat[2][0]/difmat[2][2]); //YEA!! + if (difmat[0][0]<0.0){ + bone->roll += (float)M_PI; } + + where_is_armature_bone(bone, bone->parent); //gotta do it again... + }else if (keyCheck == 0){ + //oops we couldn't find it + }else{ + //error } + PyArmature_FixRolls (&bone->childbase, dictionary); } - return NULL; -} - -//-------------------BPy_Armature internal methods------------------ - -//------------------dealloc----------------------------------------- -static void Armature_dealloc( BPy_Armature * self ) -{ - PyObject_DEL( self ); } - -//-----------------getattr-------------------------------------------- -static PyObject *Armature_getAttr( BPy_Armature * self, char *name ) +//------------------------(internal)EditBoneDict_CheckForKey +static BPy_EditBone *EditBoneDict_CheckForKey(BPy_BonesDict *dictionary, char *name) { - PyObject *attr = Py_None; - - if( strcmp( name, "name" ) == 0 ) - attr = Armature_getName( self ); - if( strcmp( name, "bones" ) == 0 ) - attr = Armature_getBones( self ); - else if( strcmp( name, "__members__" ) == 0 ) { - /* 2 entries */ - attr = Py_BuildValue( "[s,s]", "name", "bones" ); + BPy_EditBone *editbone; + PyObject *value, *key; + int pos = 0; + + while (PyDict_Next(dictionary->editBoneDict, &pos, &key, &value)) { + editbone = (BPy_EditBone *)value; + if (STREQ(editbone->name, name)){ + Py_INCREF(editbone); + return editbone; + } } - - 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_Armature_methods, ( PyObject * ) self, - name ); + return NULL; } - -//-----------------setattr-------------------------------------------- -static int -Armature_setAttr( BPy_Armature * self, char *name, PyObject * value ) +//------------------------Armature.saveChanges() +static PyObject *Armature_saveChanges(BPy_Armature *self) { - PyObject *valtuple; - PyObject *error = NULL; - - valtuple = Py_BuildValue( "(O)", value ); /*the set* functions expect a tuple */ - - if( !valtuple ) - return EXPP_ReturnIntError( PyExc_MemoryError, - "ArmatureSetAttr: couldn't create tuple" ); - - if( strcmp( name, "name" ) == 0 ) - error = Armature_setName( self, valtuple ); - else { /* Error */ - Py_DECREF( valtuple ); + float M_boneRest[3][3], M_parentRest[3][3]; + float iM_parentRest[3][3], delta[3]; + BPy_EditBone *parent = NULL, *editbone = NULL; + struct Bone *bone = NULL; + struct Object *obj = NULL; + PyObject *key, *value; + int pos = 0; + + //empty armature of old bones + free_bones(self->armature); + + //create a new set based on the editbones + while (PyDict_Next(((BPy_BonesDict*)self->Bones)->editBoneDict, &pos, &key, &value)) { + + editbone = (BPy_EditBone*)value; + bone = MEM_callocN (sizeof(Bone), "bone"); + editbone->temp = bone; //save temp pointer + + strcpy (bone->name, editbone->name); + memcpy (bone->head, editbone->head, sizeof(float)*3); + memcpy (bone->tail, editbone->tail, sizeof(float)*3); + bone->flag= editbone->flag; + bone->roll = 0.0f; //is fixed later + bone->weight = editbone->weight; + bone->dist = editbone->dist; + bone->xwidth = editbone->xwidth; + bone->zwidth = editbone->zwidth; + bone->ease1= editbone->ease1; + bone->ease2= editbone->ease2; + bone->rad_head= editbone->rad_head; + bone->rad_tail= editbone->rad_tail; + bone->segments= editbone->segments; + bone->boneclass = 0; + } - /* ... member with the given name was found */ - return ( EXPP_ReturnIntError - ( PyExc_KeyError, "attribute not found" ) ); + pos = 0; + //place bones in their correct heirarchy + while (PyDict_Next(((BPy_BonesDict*)self->Bones)->editBoneDict, + &pos, &key, &value)) { + + editbone = (BPy_EditBone*)value; + bone = editbone->temp; //get bone pointer + + if (!STREQ(editbone->parent, "")){ + parent = EditBoneDict_CheckForKey((BPy_BonesDict*)self->Bones, editbone->parent); + if(parent != NULL){ + + //parent found in dictionary + bone->parent = parent->temp; + BLI_addtail (&parent->temp->childbase, bone); + //Parenting calculations + VecSubf (delta, parent->tail, parent->head); + vec_roll_to_mat3(delta, parent->roll, M_parentRest); //M_parentRest = parent matrix + VecSubf (delta, editbone->tail, editbone->head); + vec_roll_to_mat3(delta, editbone->roll, M_boneRest); //M_boneRest = bone matrix + Mat3Inv(iM_parentRest, M_parentRest); //iM_parentRest = 1/parent matrix + //get head/tail + VecSubf (bone->head, editbone->head, parent->tail); + VecSubf (bone->tail, editbone->tail, parent->tail); + //put them in parentspace + Mat3MulVecfl(iM_parentRest, bone->head); + Mat3MulVecfl(iM_parentRest, bone->tail); + + Py_DECREF(parent); + }else{ + //was not found - most likely parent was deleted + parent = NULL; + BLI_addtail (&self->armature->bonebase, bone); + } + }else{ + BLI_addtail (&self->armature->bonebase, bone); + } + } + //fix rolls and generate matrices + PyArmature_FixRolls(&self->armature->bonebase, + ((BPy_BonesDict*)self->Bones)->editBoneDict); + + //update linked objects + for(obj = G.main->object.first; obj; obj = obj->id.next) { + if(obj->data == self->armature){ + armature_rebuild_pose(obj, self->armature); + } } + DAG_object_flush_update(G.scene, obj, OB_RECALC_DATA); - Py_DECREF( valtuple ); + //clear the editbone dictionary and set edit flag + PyDict_Clear(((BPy_BonesDict*)self->Bones)->editBoneDict); + ((BPy_BonesDict*)self->Bones)->editmode_flag = 0; - if( error != Py_None ) - return -1; + //rebuild py_bones + PyDict_Clear(((BPy_BonesDict*)self->Bones)->dict); + if (BonesDict_Init(((BPy_BonesDict*)self->Bones)->dict, + &self->armature->bonebase) == -1) + return NULL; //error string already set - Py_DECREF( Py_None ); /* was incref'ed by the called Armature_set* function */ - return 0; /* normal exit */ + return EXPP_incr_ret(Py_None); } - -//-----------------repr----------------------------------------------- -static PyObject *Armature_repr( BPy_Armature * self ) +//------------------ATTRIBUTE IMPLEMENTATION--------------------------- +//------------------------Armature.name (getter) +//Gets the name of the armature +static PyObject *Armature_getName(BPy_Armature *self, void *closure) { - return PyString_FromFormat( "[Armature \"%s\"]", - self->armature->id.name + 2 ); + return PyString_FromString(self->armature->id.name +2); //*new* } - -//-----------------compare-------------------------------------------- -static int Armature_compare( BPy_Armature * a, BPy_Armature * b ) +//------------------------Armature.name (setter) +//Sets the name of the armature +static int Armature_setName(BPy_Armature *self, PyObject *value, void *closure) { - bArmature *pa = a->armature, *pb = b->armature; - return ( pa == pb ) ? 0 : -1; -} - -//-----------------Armature_CreatePyObject---------------------------- -PyObject *Armature_CreatePyObject( struct bArmature * obj ) -{ - BPy_Armature *blen_armature; - - blen_armature = - ( BPy_Armature * ) PyObject_NEW( BPy_Armature, - &Armature_Type ); - - if( blen_armature == NULL ) { - return ( NULL ); + char buffer[24]; + char *name = ""; + + if(value){ + if(PyString_Check(value)){ + name = PyString_AsString(value); + PyOS_snprintf(buffer, sizeof(buffer), "%s", name); + rename_id(&self->armature->id, buffer); + return 0; + } } - blen_armature->armature = obj; + goto AttributeError; - return ( ( PyObject * ) blen_armature ); +AttributeError: + return EXPP_intError(PyExc_AttributeError, "%s%s", + sArmatureBadArgs, "Expects string"); } - -//-----------------Armature_CheckPyObject ---------------------------- -int Armature_CheckPyObject( PyObject * py_obj ) +//------------------------Armature.bones (getter) +//Gets the name of the armature +static PyObject *Armature_getBoneDict(BPy_Armature *self, void *closure) { - return ( py_obj->ob_type == &Armature_Type ); + return EXPP_incr_ret(self->Bones); } - -//-----------------Armature_FromPyObject ----------------------------- -struct bArmature *Armature_FromPyObject( PyObject * py_obj ) +//------------------------Armature.bones (setter) +//Sets the name of the armature +/*TODO*/ +/*Copy Bones through x = y*/ +static int Armature_setBoneDict(BPy_Armature *self, PyObject *value, void *closure) { - BPy_Armature *blen_obj; + goto AttributeError; - blen_obj = ( BPy_Armature * ) py_obj; - return ( blen_obj->armature ); +AttributeError: + return EXPP_intError(PyExc_AttributeError, "%s%s", + sArmatureError, "You are not allowed to change the .Bones attribute"); } +//------------------TYPE_OBECT IMPLEMENTATION-------------------------- +//------------------------tp_doc +//The __doc__ string for this object +static char BPy_Armature_doc[] = "This object wraps a Blender Armature object."; -//-----------------Blender Module function prototypes----------------- +//------------------------tp_methods +//This contains a list of all methods the object contains +static PyMethodDef BPy_Armature_methods[] = { + {"makeEditable", (PyCFunction) Armature_makeEditable, METH_NOARGS, + "() - Unlocks the ability to modify armature bones"}, + {"saveChanges", (PyCFunction) Armature_saveChanges, METH_NOARGS, + "() - Rebuilds the armature based on changes to bones since the last call to makeEditable"}, + {NULL} +}; -//----------------Blender.Armature.New()------------------------------ -static PyObject *M_Armature_New( PyObject * self, PyObject * args ) +//------------------------tp_getset +//This contains methods for attributes that require checking +static PyGetSetDef BPy_Armature_getset[] = { + {"name", (getter)Armature_getName, (setter)Armature_setName, + "The armature's name", NULL}, + {"bones", (getter)Armature_getBoneDict, (setter)Armature_setBoneDict, + "The armature's Bone dictionary", NULL}, + {NULL} +}; +//------------------------tp_new +//This methods creates a new object (note it does not initialize it - only the building) +//This can be called through python by myObject.__new__() however, tp_init is not called +static PyObject *Armature_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - char *name_str = "ArmatureData"; - BPy_Armature *py_armature; /* for Armature Data object wrapper in Python */ - bArmature *bl_armature; /* for actual Armature Data we create in Blender */ - char buf[21]; - - if( !PyArg_ParseTuple( args, "|s", &name_str ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected string or empty argument" ) ); + BPy_Armature *py_armature = NULL; + bArmature *bl_armature; + int success; - bl_armature = add_armature( ); /* first create in Blender */ + bl_armature = add_armature(); + if(bl_armature) { + bl_armature->id.us = 0; // return count to 0 - add_armature() inc'd it - if( bl_armature ) { - /* return user count to zero because add_armature() inc'd it */ - bl_armature->id.us = 0; - /* now create the wrapper obj in Python */ - py_armature = - ( BPy_Armature * ) PyObject_NEW( BPy_Armature, - &Armature_Type ); - } else { - return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, - "couldn't create Armature Data in Blender" ) ); - } + py_armature = (BPy_Armature*)type->tp_alloc(type, 0); //*new* + if (py_armature == NULL) + goto RuntimeError; - if( py_armature == NULL ) - return ( EXPP_ReturnPyObjError( PyExc_MemoryError, - "couldn't create ArmaturePyObject" ) ); + py_armature->armature = bl_armature; - /* link Python armature wrapper with Blender Armature: */ - py_armature->armature = bl_armature; + py_armature->Bones = BonesDict_new(&BonesDict_Type, NULL, NULL); + if (py_armature->Bones == NULL) + goto RuntimeError; - if( strcmp( name_str, "ArmatureData" ) == 0 ) - return ( PyObject * ) py_armature; - else { /* user gave us a name for the armature, use it */ - PyOS_snprintf( buf, sizeof( buf ), "%s", name_str ); - rename_id( &bl_armature->id, buf ); + success = BonesDict_Init(((BPy_BonesDict*)py_armature->Bones)->dict, &bl_armature->bonebase); + if (success == -1) + return NULL; //error string already set + } else { + goto RuntimeError; } + return (PyObject*)py_armature; - return ( PyObject * ) py_armature; +RuntimeError: + return EXPP_objError(PyExc_RuntimeError, "%s%s%s", + sArmatureError, " __new__: ", "couldn't create Armature Data in Blender"); } - -//----------------Blender.Armature.Get()------------------------------ -static PyObject *M_Armature_Get( PyObject * self, PyObject * args ) +//------------------------tp_init +//This methods does initialization of the new object +//This method will get called in python by 'myObject(argument, keyword=value)' +//tp_new will be automatically called before this +static int Armature_init(BPy_Armature *self, PyObject *args, PyObject *kwds) { - char *name = NULL; - bArmature *armature_iter; - BPy_Armature *wanted_armature; - - if( !PyArg_ParseTuple( args, "|s", &name ) ) - return ( EXPP_ReturnPyObjError( PyExc_TypeError, - "expected string argument (or nothing)" ) ); - - armature_iter = G.main->armature.first; - - /* Use the name to search for the armature requested. */ - - if( name ) { /* (name) - Search armature by name */ - wanted_armature = NULL; - while( ( armature_iter ) && ( wanted_armature == NULL ) ) { - if( strcmp( name, armature_iter->id.name + 2 ) == 0 ) { - wanted_armature = - ( BPy_Armature * ) - PyObject_NEW( BPy_Armature, - &Armature_Type ); - if( wanted_armature ) - wanted_armature->armature = - armature_iter; - } - armature_iter = armature_iter->id.next; - } - - if( wanted_armature == NULL ) { /* Requested Armature doesn't exist */ - char error_msg[64]; - PyOS_snprintf( error_msg, sizeof( error_msg ), - "Armature \"%s\" not found", name ); - return ( EXPP_ReturnPyObjError - ( PyExc_NameError, error_msg ) ); - } - return ( PyObject * ) wanted_armature; - } else { - /* Return a list of with armatures in the scene */ - int index = 0; - PyObject *armlist, *pyobj; - - armlist = PyList_New( BLI_countlist( &( G.main->armature ) ) ); - - if( armlist == NULL ) - return ( EXPP_ReturnPyObjError( PyExc_MemoryError, - "couldn't create PyList" ) ); - - while( armature_iter ) { - pyobj = Armature_CreatePyObject( armature_iter ); + char buf[21]; + char *name = "myArmature"; + static char *kwlist[] = {"name", NULL}; - if( !pyobj ) - return ( EXPP_ReturnPyObjError - ( PyExc_MemoryError, - "couldn't create PyString" ) ); + if(!PyArg_ParseTupleAndKeywords(args, kwds, "|s", kwlist, &name)){ + goto AttributeError; + } - PyList_SET_ITEM( armlist, index, pyobj ); - armature_iter = armature_iter->id.next; - index++; - } - return ( armlist ); + //rename the armature if a name is supplied + if(!BLI_streq(name, "myArmature")){ + PyOS_snprintf(buf, sizeof(buf), "%s", name); + rename_id(&self->armature->id, buf); } -} -//--------------------------Python BPy_Armature methods--------------- + return 0; -//---------------------BPy_Armature.getName()------------------------- -static PyObject *Armature_getName( BPy_Armature * self ) +AttributeError: + return EXPP_intError(PyExc_AttributeError, "%s%s%s", + sArmatureBadArgs, " __init__: ", "Expects string(name)"); +} +//------------------------tp_richcompare +//This method allows the object to use comparison operators +//TODO: We need some armature comparisons +static PyObject *Armature_richcmpr(BPy_Armature *self, PyObject *v, int op) { - PyObject *attr = PyString_FromString( self->armature->id.name + 2 ); - - if( attr ) - return attr; - - return ( EXPP_ReturnPyObjError( PyExc_RuntimeError, - "couldn't get Armature.name attribute" ) ); + return EXPP_incr_ret(Py_None); } -//---------------------BPy_Armature.getBones()------------------------ -static PyObject *Armature_getBones( BPy_Armature * self ) +//------------------------tp_repr +//This is the string representation of the object +static PyObject *Armature_repr(BPy_Armature *self) { + return PyString_FromFormat( "[Armature: \"%s\"]", self->armature->id.name + 2 ); //*new* +} - PyObject *listbones = NULL; - Bone *parent = NULL; - - listbones = PyList_New( 0 ); - - //append root bones - for( parent = self->armature->bonebase.first; parent; - parent = parent->next ) { - PyList_Append( listbones, Bone_CreatePyObject( parent ) ); - if( parent->childbase.first ) { //has children? - append_childrenToList( parent, listbones ); - } - } - - return listbones; +//------------------------tp_dealloc +//This tells how to 'tear-down' our object when ref count hits 0 +///tp_dealloc +static void Armature_dealloc(BPy_Armature * self) +{ + Py_DECREF(self->Bones); + ((PyObject*)self)->ob_type->tp_free((PyObject*)self); + return; } +//------------------TYPE_OBECT DEFINITION-------------------------- +PyTypeObject Armature_Type = { + PyObject_HEAD_INIT(NULL) //tp_head + 0, //tp_internal + "Armature", //tp_name + sizeof(BPy_Armature), //tp_basicsize + 0, //tp_itemsize + (destructor)Armature_dealloc, //tp_dealloc + 0, //tp_print + 0, //tp_getattr + 0, //tp_setattr + 0, //tp_compare + (reprfunc) Armature_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_Armature_doc, //tp_doc + 0, //tp_traverse + 0, //tp_clear + (richcmpfunc)Armature_richcmpr, //tp_richcompare + 0, //tp_weaklistoffset + 0, //tp_iter + 0, //tp_iternext + BPy_Armature_methods, //tp_methods + 0, //tp_members + BPy_Armature_getset, //tp_getset + 0, //tp_base + 0, //tp_dict + 0, //tp_descr_get + 0, //tp_descr_set + 0, //tp_dictoffset + (initproc)Armature_init, //tp_init + 0, //tp_alloc + (newfunc)Armature_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 +}; -//---------------------BPy_Armature.addBone()------------------------- -static PyObject *Armature_addBone( BPy_Armature * self, PyObject * args ) +//-------------------MODULE METHODS IMPLEMENTATION------------------------ +//----------------Blender.Armature.Get() +/* This function will return a Py_Armature when a single string is passed +* or else it will return a {key:value} dictionary when mutliple strings are passed +* or it will return a {key:value} dictionary of all armatures when nothing is passed*/ +static PyObject *M_Armature_Get(PyObject * self, PyObject * args) { - BPy_Bone *py_bone = NULL; - float M_boneObjectspace[4][4]; - float iM_parentRest[4][4]; - Bone *blen_bone; - char *parent_str = ""; - Bone *parent; - - if( !PyArg_ParseTuple( args, "O!", &Bone_Type, &py_bone ) ) - return ( EXPP_ReturnPyObjError( PyExc_TypeError, - "expected bone object argument (or nothing)" ) ); - - if( py_bone->bone != NULL ) - return EXPP_ReturnPyObjError( PyExc_TypeError, - "this bone has already been linked to an armature" ); - - //check to see if we can parent this bone if it will be attempted - //otherwise exit - if( !BLI_streq( py_bone->parent, parent_str ) ) { //parenting being attempted - //get parent if exists in this armature - parent = testBoneNameInArmature( self->armature, - py_bone->parent ); - if( !parent ) { //could find the parent's name - return ( EXPP_ReturnPyObjError( PyExc_TypeError, - "cannot find parent's name in armature - check to see if name of parent is correct" ) ); + PyObject *seq = NULL, *item = NULL, *dict = NULL, *py_armature = NULL; + char *name = "", buffer[24]; + int size = 0, i; + void *data; + + //GET ARGUMENTS - () ('s') ('s',..) (['s',..]) are exceptable + size = PySequence_Length(args); + if (size == 1) { + seq = PySequence_GetItem(args, 0); //*new* + if (seq == NULL) + goto RuntimeError; + if(!PyString_Check(seq)){ + if (PySequence_Check(seq)) { + size = PySequence_Length(seq); + } else { + Py_DECREF(seq); + goto AttributeError; + } + } + } else { + seq = EXPP_incr_ret(args); //*take ownership* + } + //'seq' should be a list, empty tuple or string - check list for strings + if(!PyString_Check(seq)){ + for(i = 0; i < size; i++){ + item = PySequence_GetItem(seq, i); //*new* + if (item == NULL) { + Py_DECREF(seq); + goto RuntimeError; + } + if(!PyString_Check(item)){ + EXPP_decr2(item, seq); + goto AttributeError; + } + Py_DECREF(item); } - } else { //no parent for this bone - parent = NULL; } - //create a bone struct - blen_bone = ( Bone * ) MEM_callocN( sizeof( Bone ), "DefaultBone" ); - - //set the bone struct pointer - py_bone->bone = blen_bone; - //update the bonestruct data from py data - if( !updateBoneData( py_bone, parent ) ) - return EXPP_ReturnPyObjError( PyExc_AttributeError, - "bone struct empty" ); - - //make sure the name is unique for this armature - unique_BoneName( py_bone->bone->name, self->armature ); - - //if bone has a parent.... - if( py_bone->bone->parent ) { - - //then check to see if parent has been added to the armature - bone loop test - if( !testBoneInArmature - ( self->armature, py_bone->bone->parent ) ) - return ( EXPP_ReturnPyObjError - ( PyExc_TypeError, - "cannot parent to a bone not yet added to armature!" ) ); - - //add to parent's childbase - BLI_addtail( &py_bone->bone->parent->childbase, - py_bone->bone ); - - //get the worldspace coords for the parent - get_objectspace_bone_matrix( py_bone->bone->parent, - M_boneObjectspace, 0, 0 ); + //GET ARMATURES + if(size != 1){ + dict = PyDict_New(); //*new* + if(dict == NULL){ + Py_DECREF(seq); + goto RuntimeError; + } + if(size == 0){ //GET ALL ARMATURES + data = &(G.main->armature).first; //get the first data ID from the armature library + while (data){ + py_armature = PyArmature_FromArmature(data); //*new* + sprintf(buffer, "%s", ((bArmature*)data)->id.name +2); + if(PyDict_SetItemString(dict, buffer, py_armature) == -1){ //add to dictionary + EXPP_decr3(seq, dict, py_armature); + goto RuntimeError; + } + data = ((ID*)data)->next; + } + Py_DECREF(seq); + }else{ //GET ARMATURE LIST + for (i = 0; i < size; i++) { + item = PySequence_GetItem(seq, i); //*new* + name = PyString_AsString(item); + Py_DECREF(item); + data = find_id("AR", name); //get data from library + if (data != NULL){ + py_armature = PyArmature_FromArmature(data); //*new* + if(PyDict_SetItemString(dict, name, py_armature) == -1){ //add to dictionary + EXPP_decr3(seq, dict, py_armature); + goto RuntimeError; + } + }else{ + if(PyDict_SetItemString(dict, name, Py_None) == -1){ //add to dictionary + EXPP_decr2(seq, dict); + goto RuntimeError; + } + } + } + Py_DECREF(seq); + } + return dict; //transfering ownership to caller + }else{ //GET SINGLE ARMATURE + if(!PyString_Check(seq)){ //This handles the bizarre case where (['s']) is passed + item = PySequence_GetItem(seq, 0); //*new* + name = PyString_AsString(item); + Py_DECREF(item); + }else{ + name = PyString_AsString(seq); + } + Py_DECREF(seq); + data = find_id("AR", name); //get data from library + if (data != NULL){ + return PyArmature_FromArmature(data); //*new* + }else{ + return EXPP_incr_ret(Py_None); + } + } - // Invert the parent rest matrix - Mat4Invert( iM_parentRest, M_boneObjectspace ); +RuntimeError: + return EXPP_objError(PyExc_RuntimeError, "%s%s%s", + sModuleError, "Get(): ", "Internal Error Ocurred"); - //transformation of local bone - Mat4MulVecfl( iM_parentRest, py_bone->bone->tail ); - Mat4MulVecfl( iM_parentRest, py_bone->bone->head ); +AttributeError: + return EXPP_objError(PyExc_AttributeError, "%s%s%s", + sModuleBadArgs, "Get(): ", "- Expects (optional) string sequence"); +} - } else //no parent.... - BLI_addtail( &self->armature->bonebase, py_bone->bone ); +//-------------------MODULE METHODS DEFINITION----------------------------- +static PyObject *M_Armature_Get( PyObject * self, PyObject * args ); - //rebuild_bone_parent_matrix(py_bone->bone); +static char M_Armature_Get_doc[] = "(name) - return the armature with the name 'name', \ + returns None if not found.\n If 'name' is not specified, it returns a list of all \ + armatures in the\ncurrent scene."; - //precalc_bonelist_irestmats( &self->armature->bonebase ); - //precalc_armature_posemats( self->armature ); - //precalc_bone_defmat( py_bone->bone ); +struct PyMethodDef M_Armature_methods[] = { + {"Get", M_Armature_Get, METH_VARARGS, M_Armature_Get_doc}, + {NULL} +}; +//------------------VISIBLE PROTOTYPE IMPLEMENTATION----------------------- +//-----------------(internal) +//Converts a bArmature to a PyArmature +PyObject *PyArmature_FromArmature(struct bArmature *armature) +{ + BPy_Armature *py_armature = NULL; + int success; - Py_INCREF( Py_None ); - return Py_None; -} + py_armature = (BPy_Armature*)Armature_Type.tp_alloc(&Armature_Type, 0); //*new* + if (py_armature == NULL) + goto RuntimeError; -//---------------------BPy_Armature.setName()------------------------- -static PyObject *Armature_setName( BPy_Armature * self, PyObject * args ) -{ - char *name; - char buf[21]; + py_armature->armature = armature; - if( !PyArg_ParseTuple( args, "s", &name ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected string argument" ) ); + py_armature->Bones = BonesDict_new(&BonesDict_Type, NULL, NULL); //*new* + if (py_armature->Bones == NULL) + goto RuntimeError; - PyOS_snprintf( buf, sizeof( buf ), "%s", name ); + success = BonesDict_Init(((BPy_BonesDict*)py_armature->Bones)->dict, &armature->bonebase); + if (success == -1) + return NULL; //error string already set - rename_id( &self->armature->id, buf ); + return (PyObject *) py_armature; - Py_INCREF( Py_None ); - return Py_None; +RuntimeError: + return EXPP_objError(PyExc_RuntimeError, "%s%s%s", + sModuleError, "PyArmature_FromArmature: ", "Internal Error Ocurred"); } - -//---------------------BPy_Armature.drawAxes()------------------------ -static PyObject *Armature_drawAxes( BPy_Armature * self, PyObject * args ) +//-----------------(internal) +//Converts a PyArmature to a bArmature +struct bArmature *PyArmature_AsArmature(BPy_Armature *py_armature) { - int toggle; - - if( !PyArg_ParseTuple( args, "i", &toggle ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected 1 or 0 as integer" ) ); - - if( toggle ) - self->armature->flag |= ARM_DRAWAXES; - else - self->armature->flag &= ~ARM_DRAWAXES; - - Py_INCREF( Py_None ); - return Py_None; + return (py_armature->armature); } - -//---------------------BPy_Armature.drawNames()------------------------- -static PyObject *Armature_drawNames( BPy_Armature * self, PyObject * args ) +//-------------------MODULE INITIALIZATION-------------------------------- +PyObject *Armature_Init(void) { - int toggle; + PyObject *module, *dict; - if( !PyArg_ParseTuple( args, "i", &toggle ) ) - return ( EXPP_ReturnPyObjError( PyExc_AttributeError, - "expected 1 or 0 as integer" ) ); - - if( toggle ) - self->armature->flag |= ARM_DRAWNAMES; - else - self->armature->flag &= ~ARM_DRAWNAMES; + //Initializes TypeObject.ob_type + if (PyType_Ready(&Armature_Type) < 0 || PyType_Ready(&BonesDict_Type) < 0 || + PyType_Ready(&EditBone_Type) < 0 || PyType_Ready(&Bone_Type) < 0){ + return EXPP_incr_ret(Py_None); + } - Py_INCREF( Py_None ); - return Py_None; + //Register the module + module = Py_InitModule3("Blender.Armature", M_Armature_methods, + "The Blender Armature module"); + + //Add TYPEOBJECTS to the module + PyModule_AddObject(module, "ArmatureType", + EXPP_incr_ret((PyObject *)&Armature_Type)); //*steals* + PyModule_AddObject(module, "BoneType", + EXPP_incr_ret((PyObject *)&Bone_Type)); //*steals* + + //Add CONSTANTS to the module + PyModule_AddObject(module, "CONNECTED", + EXPP_incr_ret(PyConstant_NewInt("CONNECTED", BONE_CONNECTED))); + PyModule_AddObject(module, "HINGE", + EXPP_incr_ret(PyConstant_NewInt("HINGE", BONE_HINGE))); + PyModule_AddObject(module, "NO_DEFORM", + EXPP_incr_ret(PyConstant_NewInt("NO_DEFORM", BONE_NO_DEFORM))); + PyModule_AddObject(module, "MULTIPLY", + EXPP_incr_ret(PyConstant_NewInt("MULTIPLY", BONE_MULT_VG_ENV))); + PyModule_AddObject(module, "HIDDEN_EDIT", + EXPP_incr_ret(PyConstant_NewInt("HIDDEN_EDIT", BONE_HIDDEN_A))); + + PyModule_AddObject(module, "BONESPACE", + EXPP_incr_ret(PyConstant_NewString("BONESPACE", "bone_space"))); + PyModule_AddObject(module, "ARMATURESPACE", + EXPP_incr_ret(PyConstant_NewString("ARMATURESPACE", "armature_space"))); + PyModule_AddObject(module, "WORLDSPACE", + EXPP_incr_ret(PyConstant_NewString("WORLDSPACE", "world_space"))); + + //Add SUBMODULES to the module + dict = PyModule_GetDict( module ); //borrowed + PyDict_SetItemString(dict, "NLA", NLA_Init()); //creates a *new* module + + return module; } diff --git a/source/blender/python/api2_2x/Armature.h b/source/blender/python/api2_2x/Armature.h index 91a409100b1..473a2392931 100644 --- a/source/blender/python/api2_2x/Armature.h +++ b/source/blender/python/api2_2x/Armature.h @@ -23,9 +23,7 @@ * 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 ***** */ @@ -36,18 +34,31 @@ #include <Python.h> #include "DNA_armature_types.h" -//---------------------Python BPy_Armature structure definition------- +//-------------------TYPE CHECKS--------------------------------- +#define ArmatureObject_Check(v) ((v)->ob_type == &Armature_Type) +#define BonesDictObject_Check(v) ((v)->ob_type == &BonesDict_Type) +//-------------------MODULE INIT--------------------------------- +PyObject *Armature_Init( void ); +//-------------------TYPEOBJECT---------------------------------- +PyTypeObject Armature_Type; +PyTypeObject BonesDict_Type; +//-------------------STRUCT DEFINITION--------------------------- + typedef struct { PyObject_HEAD - bArmature * armature; -} BPy_Armature; - -//--------------------visible prototypes------------------------------ + PyObject *dict; + PyObject *editBoneDict; + short editmode_flag; //1 = in , 0 = not in +} BPy_BonesDict; -PyObject *Armature_Init( void ); -PyObject *Armature_CreatePyObject( bArmature * armature ); -bArmature *Armature_FromPyObject( PyObject * py_obj ); -int Armature_CheckPyObject( PyObject * py_obj ); +typedef struct { + PyObject_HEAD + struct bArmature * armature; + PyObject *Bones; +} BPy_Armature; +//-------------------VISIBLE PROTOTYPES------------------------- +PyObject *PyArmature_FromArmature(struct bArmature *armature); +struct bArmature *PyArmature_AsArmature(BPy_Armature *py_armature); -#endif /* EXPP_ARMATURE_H */ +#endif 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); } diff --git a/source/blender/python/api2_2x/Bone.h b/source/blender/python/api2_2x/Bone.h index b63bfc2d491..bcc0685a9df 100644 --- a/source/blender/python/api2_2x/Bone.h +++ b/source/blender/python/api2_2x/Bone.h @@ -23,9 +23,7 @@ * 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 ***** */ @@ -35,6 +33,75 @@ #include <Python.h> #include "DNA_armature_types.h" + +//-------------------TYPE CHECKS--------------------------------- +#define BoneObject_Check(v) ((v)->ob_type == &Bone_Type) +#define EditBoneObject_Check(v) ((v)->ob_type == &EditBone_Type) +//-------------------TYPEOBJECT---------------------------------- +PyTypeObject EditBone_Type; +PyTypeObject Bone_Type; +//-------------------STRUCT DEFINITION---------------------------- +typedef struct { + PyObject_HEAD + Bone * bone; +} BPy_Bone; + +typedef struct { + PyObject_HEAD + struct Bone *temp; //temp tracking + char parent[32]; + char name[32]; + float roll; + float head[3]; + float tail[3]; + int flag; + float length; + float dist; + float weight; + float xwidth; + float zwidth; + float ease1; + float ease2; + float rad_head; + float rad_tail; + short segments; +} BPy_EditBone; +//-------------------VISIBLE PROTOTYPES------------------------- +PyObject *PyBone_FromBone(struct Bone *bone); +struct Bone *PyBone_AsBone(BPy_Bone *py_Bone); + +#endif + + + + + + + + + + + + + + + + + + + + + + + + + +/* +#ifndef EXPP_BONE_H +#define EXPP_BONE_H + +#include <Python.h> +#include "DNA_armature_types.h" #include "Mathutils.h" //--------------------------Python BPy_Bone structure definition.------- @@ -73,3 +140,5 @@ PyObject *Bone_Init( void ); int updateBoneData( BPy_Bone * self, Bone * parent ); #endif + +*/
\ No newline at end of file diff --git a/source/blender/python/api2_2x/Object.c b/source/blender/python/api2_2x/Object.c index 1c7d87d047c..56859543f08 100644 --- a/source/blender/python/api2_2x/Object.c +++ b/source/blender/python/api2_2x/Object.c @@ -638,7 +638,6 @@ PyObject *M_Object_New( PyObject * self, PyObject * args ) } object = alloc_libblock( &( G.main->object ), ID_OB, name ); - object->id.us = 0; object->flag = 0; object->type = (short)type; @@ -724,6 +723,7 @@ PyObject *M_Object_Get( PyObject * self, PyObject * args ) ( BPy_Object * ) PyObject_NEW( BPy_Object, &Object_Type ); blen_object->object = object; + object->id.us++; return ( ( PyObject * ) blen_object ); } else { @@ -747,6 +747,7 @@ PyObject *M_Object_Get( PyObject * self, PyObject * args ) ( BPy_Object * ) PyObject_NEW( BPy_Object, &Object_Type ); blen_object->object = object; + object->id.us++; PyList_SetItem( obj_list, index, ( PyObject * ) blen_object ); @@ -1022,7 +1023,7 @@ static PyObject *Object_getData( BPy_Object *self, PyObject *args, PyObject *kwd switch ( object->type ) { case OB_ARMATURE: - data_object = Armature_CreatePyObject( object->data ); + data_object = PyArmature_FromArmature( object->data ); break; case OB_CAMERA: data_object = Camera_CreatePyObject( object->data ); @@ -1479,10 +1480,9 @@ static PyObject *Object_link( BPy_Object * self, PyObject * args ) return ( EXPP_ReturnPyObjError( PyExc_AttributeError, "expected an object as argument" ) ); } - - if( Armature_CheckPyObject( py_data ) ) - data = ( void * ) Armature_FromPyObject( py_data ); - else if( Camera_CheckPyObject( py_data ) ) + if( ArmatureObject_Check( py_data ) ) + data = ( void * ) PyArmature_AsArmature((BPy_Armature*)py_data); + if( Camera_CheckPyObject( py_data ) ) data = ( void * ) Camera_FromPyObject( py_data ); else if( Lamp_CheckPyObject( py_data ) ) data = ( void * ) Lamp_FromPyObject( py_data ); @@ -2594,6 +2594,7 @@ PyObject *Object_CreatePyObject( struct Object * obj ) return ( NULL ); } blen_object->object = obj; + obj->id.us++; return ( ( PyObject * ) blen_object ); } @@ -2651,6 +2652,7 @@ Object *GetObjectByName( char *name ) /*****************************************************************************/ static void Object_dealloc( BPy_Object * obj ) { + obj->object->id.us--; PyObject_DEL( obj ); } |