From a6a32cf50414b5660c802dcd9067d422aaf5537f Mon Sep 17 00:00:00 2001 From: Joseph Gilbert Date: Mon, 19 Apr 2004 06:57:41 +0000 Subject: -NLA module added -ability to set poses for the armatures - allows for keyframing armatures -adds support for actions/actionchannels -additional checking for addBone and clear parenting -moved getActionIpos from object module to NLA module --- source/blender/python/api2_2x/Bone.c | 206 ++++++++++++++++++++++++++++++----- 1 file changed, 176 insertions(+), 30 deletions(-) (limited to 'source/blender/python/api2_2x/Bone.c') diff --git a/source/blender/python/api2_2x/Bone.c b/source/blender/python/api2_2x/Bone.c index 4a86e0c5c5b..539d2213547 100644 --- a/source/blender/python/api2_2x/Bone.c +++ b/source/blender/python/api2_2x/Bone.c @@ -38,12 +38,17 @@ #include #include #include +#include +#include +#include +#include +#include #include "constant.h" #include "gen_utils.h" #include "modules.h" #include "quat.h" - +#include "NLA.h" /*****************************************************************************/ /* Python API function prototypes for the Bone module. */ @@ -102,6 +107,7 @@ static PyObject *Bone_setSize (BPy_Bone * self, PyObject * args); static PyObject *Bone_setQuat (BPy_Bone * self, PyObject * args); static PyObject *Bone_setParent(BPy_Bone *self, PyObject *args); static PyObject *Bone_setWeight(BPy_Bone *self, PyObject *args); +static PyObject *Bone_setPose (BPy_Bone *self, PyObject *args); /*****************************************************************************/ /* Python BPy_Bone methods table: */ @@ -157,6 +163,8 @@ static PyMethodDef BPy_Bone_methods[] = { "() - 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."}, {NULL, NULL, 0, NULL} }; @@ -254,6 +262,10 @@ Bone_Init (void) 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); + return (submodule); } @@ -728,7 +740,7 @@ Bone_setWeight(BPy_Bone *self, PyObject *args) float weight; if (!self->bone) - (EXPP_ReturnPyObjError (PyExc_RuntimeError, + return (EXPP_ReturnPyObjError (PyExc_RuntimeError, "couldn't get attribute from a NULL bone")); if (!PyArg_ParseTuple (args, "f", &weight)) @@ -753,7 +765,7 @@ Bone_clearParent(BPy_Bone *self) float M_boneObjectspace[4][4]; if (!self->bone) - (EXPP_ReturnPyObjError (PyExc_RuntimeError, "bone contains no data!")); + return (EXPP_ReturnPyObjError (PyExc_RuntimeError, "bone contains no data!")); if(self->bone->parent == NULL) return EXPP_incr_ret(Py_None); @@ -810,46 +822,43 @@ Bone_clearParent(BPy_Bone *self) static PyObject * Bone_clearChildren(BPy_Bone *self) { + Bone *root = NULL; Bone *child = NULL; bArmature *arm = NULL; Bone *bone = NULL; - Bone *parent = NULL; Bone *prev = NULL; Bone *next = NULL; float M_boneObjectspace[4][4]; int first; if (!self->bone) - (EXPP_ReturnPyObjError (PyExc_RuntimeError, "bone contains no data!")); + return (EXPP_ReturnPyObjError (PyExc_RuntimeError, "bone contains no data!")); if(self->bone->childbase.first == NULL) return EXPP_incr_ret(Py_None); - //get the root bone - parent = bone->parent; - - if(parent != NULL){ - while(parent->parent != NULL){ - parent = parent->parent; - } - }else{ - parent = bone; - } - - //get 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 - goto gotArmature; - } - } - } - -gotArmature: + //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) - (EXPP_ReturnPyObjError (PyExc_RuntimeError, "couldn't find armature that contains this bone")); + 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); @@ -888,7 +897,7 @@ static PyObject * Bone_hide(BPy_Bone *self) { if (!self->bone) - (EXPP_ReturnPyObjError (PyExc_RuntimeError, "bone contains no data!")); + return (EXPP_ReturnPyObjError (PyExc_RuntimeError, "bone contains no data!")); if(!(self->bone->flag & BONE_HIDDEN)) self->bone->flag |= BONE_HIDDEN; @@ -902,7 +911,7 @@ static PyObject * Bone_unhide(BPy_Bone *self) { if (!self->bone) - (EXPP_ReturnPyObjError (PyExc_RuntimeError, "bone contains no data!")); + return (EXPP_ReturnPyObjError (PyExc_RuntimeError, "bone contains no data!")); if(self->bone->flag & BONE_HIDDEN) self->bone->flag &= ~BONE_HIDDEN; @@ -912,7 +921,144 @@ Bone_unhide(BPy_Bone *self) } +static PyObject * +Bone_setPose (BPy_Bone *self, PyObject *args) +{ + Bone *root = NULL; + bPoseChannel *chan = NULL; + bPoseChannel *setChan = NULL; + bPoseChannel *test = NULL; + Object *object =NULL; + bArmature *arm = NULL; + Bone *bone = NULL; + PyObject *flaglist = NULL; + PyObject *item = NULL; + BPy_Action *py_action = NULL; + int x; + int flagValue = 0; + int makeCurve = 1; + + if (!PyArg_ParseTuple (args, "O!|O!", &PyList_Type, &flaglist, &Action_Type, &py_action)) + return (EXPP_ReturnPyObjError (PyExc_AttributeError, + "expected list of flags and optional action")); + + for(x = 0; x < PyList_Size(flaglist); x++){ + item = PyList_GetItem(flaglist, x); + if(PyInt_Check(item)){ + flagValue |= PyInt_AsLong(item); + }else{ + return (EXPP_ReturnPyObjError (PyExc_AttributeError, + "expected list of flags (ints)")); + } + } + + //is this bone a part of an armature.... + //get root bone for testing + root = self->bone->parent; + if(root != NULL){ + while (root->parent != NULL){ + root = root->parent; + } + }else{ + root = self->bone; + } + //test armatures for root bone + for(arm= G.main->armature.first; arm; arm = arm->id.next){ + for(bone = arm->bonebase.first; bone; bone = bone->next){ + if(bone == root) + break; + } + if(bone == root) + break; + } + if(arm == NULL) + return (EXPP_ReturnPyObjError (PyExc_RuntimeError, + "bone must belong to an armature to set it's pose!")); + + //find if armature is object linked.... + for(object = G.main->object.first; object; object = object->id.next){ + if(object->data == arm){ + break; + } + } + + if(object == NULL) + return (EXPP_ReturnPyObjError (PyExc_RuntimeError, + "armature must be linked to an object to set a pose!")); + + //set the active action as this one + if(py_action !=NULL){ + if(py_action->action != NULL){ + object->action = py_action->action; + } + } + + //if object doesn't have a pose create one + if (!object->pose) + object->pose = MEM_callocN(sizeof(bPose), "Pose"); + + //if bone does have a channel create one + verify_pose_channel(object->pose, self->bone->name); + + //create temp Pose Channel + chan = MEM_callocN(sizeof(bPoseChannel), "PoseChannel"); + //set the variables for this pose + memcpy (chan->loc, self->bone->loc, sizeof (chan->loc)); + memcpy (chan->quat, self->bone->quat, sizeof (chan->quat)); + memcpy (chan->size, self->bone->size, sizeof (chan->size)); + strcpy (chan->name, self->bone->name); + chan->flag |= flagValue; + + //set it to the channel + setChan = set_pose_channel(object->pose, chan); + + //frees unlinked pose/bone channels from object + collect_pose_garbage(object); + + //create an action if one not already assigned to object + if (!py_action && !object->action){ + object->action = (bAction*)add_empty_action(); + object->ipowin= ID_AC; + }else{ + //test if posechannel is already in action + for(test = object->action->chanbase.first; test; test = test->next){ + if(test == setChan) + makeCurve = 0; //already there + } + } + + //set posekey flag + filter_pose_keys (); + + //set action keys + if (setChan->flag & POSE_ROT){ + set_action_key(object->action, setChan, AC_QUAT_X, makeCurve); + set_action_key(object->action, setChan, AC_QUAT_Y, makeCurve); + set_action_key(object->action, setChan, AC_QUAT_Z, makeCurve); + set_action_key(object->action, setChan, AC_QUAT_W, makeCurve); + } + if (setChan->flag & POSE_SIZE){ + set_action_key(object->action, setChan, AC_SIZE_X, makeCurve); + set_action_key(object->action, setChan, AC_SIZE_Y, makeCurve); + set_action_key(object->action, setChan, AC_SIZE_Z, makeCurve); + } + if (setChan->flag & POSE_LOC){ + set_action_key(object->action, setChan, AC_LOC_X, makeCurve); + set_action_key(object->action, setChan, AC_LOC_Y, makeCurve); + set_action_key(object->action, setChan, AC_LOC_Z, makeCurve); + } + + //rebuild ipos + remake_action_ipos(object->action); + + //rebuild displists + rebuild_all_armature_displists(); + + Py_INCREF(Py_None); + return Py_None; +} + /*****************************************************************************/ /* Function: Bone_dealloc */ /* Description: This is a callback function for the BPy_Bone type. It is */ -- cgit v1.2.3