diff options
author | Joseph Gilbert <ascotan@gmail.com> | 2006-01-11 22:41:01 +0300 |
---|---|---|
committer | Joseph Gilbert <ascotan@gmail.com> | 2006-01-11 22:41:01 +0300 |
commit | 6544ed3b647463d5e65692b684ff0dc19b0eb7b1 (patch) | |
tree | 83525e87ff620f888059c2f1787545b142d51956 | |
parent | 5f0232f68f1a3216b74e82a26a9c7952c55d1458 (diff) |
Probably need these....
-rw-r--r-- | source/blender/python/api2_2x/Pose.c | 911 | ||||
-rw-r--r-- | source/blender/python/api2_2x/Pose.h | 68 |
2 files changed, 979 insertions, 0 deletions
diff --git a/source/blender/python/api2_2x/Pose.c b/source/blender/python/api2_2x/Pose.c new file mode 100644 index 00000000000..4f9f9b77cfa --- /dev/null +++ b/source/blender/python/api2_2x/Pose.c @@ -0,0 +1,911 @@ +/* + * $Id: + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): Joseph Gilbert + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ + +#include "Pose.h" + + +#include "mydevice.h" +#include "BKE_armature.h" +#include "BKE_main.h" +#include "BKE_global.h" +#include "BKE_action.h" +#include "BKE_utildefines.h" +#include "BIF_editaction.h" +#include "BIF_space.h" +#include "BKE_depsgraph.h" +#include "DNA_object_types.h" +#include "DNA_ipo_types.h" +#include "DNA_scene_types.h" +#include "DNA_space_types.h" //1 - this order +#include "BSE_editipo.h" //2 +#include "BLI_blenlib.h" +#include "BLI_arithb.h" +#include "Mathutils.h" +#include "Object.h" +#include "Constraint.h" +#include "NLA.h" +#include "gen_utils.h" + +extern void chan_calc_mat(bPoseChannel *chan); + +//------------------------ERROR CODES--------------------------------- +//This is here just to make me happy and to have more consistant error strings :) +static const char sPoseError[] = "Pose - Error: "; +static const char sPoseBadArgs[] = "Pose - Bad Arguments: "; +static const char sPoseBoneError[] = "PoseBone - Error: "; +static const char sPoseBoneBadArgs[] = "PoseBone - Bad Arguments: "; +static const char sPoseBonesDictError[] = "PoseBone - Error: "; +static const char sPoseBonesDictBadArgs[] = "PoseBone - Bad Arguments: "; + +//################## PoseBonesDict_Type (internal) ######################## +/*This is an internal psuedo-dictionary type that allows for manipulation +* of posechannels inside of a pose structure. It is a subobject of pose. +* i.e. Pose.bones['key']*/ +//################################################################ + +//------------------METHOD IMPLEMENTATIONS----------------------------- +//------------------------Pose.bones.items() +//Returns a list of key:value pairs like dict.items() +PyObject* PoseBonesDict_items(BPy_PoseBonesDict *self) +{ + return PyDict_Items(self->bonesMap); +} +//------------------------Pose.bones.keys() +//Returns a list of keys like dict.keys() +PyObject* PoseBonesDict_keys(BPy_PoseBonesDict *self) +{ + return PyDict_Keys(self->bonesMap); +} +//------------------------Armature.bones.values() +//Returns a list of values like dict.values() +PyObject* PoseBonesDict_values(BPy_PoseBonesDict *self) +{ + return PyDict_Values(self->bonesMap); +} +//------------------ATTRIBUTE IMPLEMENTATION--------------------------- +//------------------TYPE_OBECT IMPLEMENTATION----------------------- +//------------------------tp_doc +//The __doc__ string for this object +static char BPy_PoseBonesDict_doc[] = "This is an internal subobject of pose\ +designed to act as a Py_PoseBone dictionary."; + +//------------------------tp_methods +//This contains a list of all methods the object contains +static PyMethodDef BPy_PoseBonesDict_methods[] = { + {"items", (PyCFunction) PoseBonesDict_items, METH_NOARGS, + "() - Returns the key:value pairs from the dictionary"}, + {"keys", (PyCFunction) PoseBonesDict_keys, METH_NOARGS, + "() - Returns the keys the dictionary"}, + {"values", (PyCFunction) PoseBonesDict_values, METH_NOARGS, + "() - Returns the values from the dictionary"}, + {NULL} +}; +//-----------------(internal) +static int PoseBoneMapping_Init(PyObject *dictionary, ListBase *posechannels){ + bPoseChannel *pchan = NULL; + PyObject *py_posechannel = NULL; + + for (pchan = posechannels->first; pchan; pchan = pchan->next){ + py_posechannel = PyPoseBone_FromPosechannel(pchan); + if (!py_posechannel) + return -1; + + if(PyDict_SetItem(dictionary, + PyString_FromString(pchan->name), py_posechannel) == -1){ + return -1; + } + Py_DECREF(py_posechannel); + } + return 0; +} + +//----------------- BonesDict_InitBones +static int PoseBonesDict_InitBones(BPy_PoseBonesDict *self) +{ + PyDict_Clear(self->bonesMap); + if (PoseBoneMapping_Init(self->bonesMap, self->bones) == -1) + return 0; + return 1; +} + +//------------------------tp_repr +//This is the string representation of the object +static PyObject *PoseBonesDict_repr(BPy_PoseBonesDict *self) +{ + char buffer[128], str[4096]; + PyObject *key, *value; + int pos = 0; + + BLI_strncpy(str,"",4096); + sprintf(buffer, "[Pose Bone Dict: {"); + strcat(str,buffer); + while (PyDict_Next(self->bonesMap, &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); +} + +//------------------------tp_dealloc +//This tells how to 'tear-down' our object when ref count hits 0 +static void PoseBonesDict_dealloc(BPy_PoseBonesDict * self) +{ + Py_DECREF(self->bonesMap); + PoseBonesDict_Type.tp_free(self); + return; +} +//------------------------mp_length +//This gets the size of the dictionary +int PoseBonesDict_len(BPy_PoseBonesDict *self) +{ + return BLI_countlist(self->bones); +} +//-----------------------mp_subscript +//This defines getting a bone from the dictionary - x = Bones['key'] +PyObject *PoseBonesDict_GetItem(BPy_PoseBonesDict *self, PyObject* key) +{ + PyObject *value = NULL; + + value = PyDict_GetItem(self->bonesMap, key); + if(value == NULL){ + return EXPP_incr_ret(Py_None); + } + return EXPP_incr_ret(value); +} +//------------------TYPE_OBECT DEFINITION-------------------------- +//Mapping Protocol +static PyMappingMethods PoseBonesDict_MapMethods = { + (inquiry) PoseBonesDict_len, //mp_length + (binaryfunc)PoseBonesDict_GetItem, //mp_subscript + 0, //mp_ass_subscript +}; +//PoseBonesDict TypeObject +PyTypeObject PoseBonesDict_Type = { + PyObject_HEAD_INIT(NULL) //tp_head + 0, //tp_internal + "PoseBonesDict", //tp_name + sizeof(BPy_PoseBonesDict), //tp_basicsize + 0, //tp_itemsize + (destructor)PoseBonesDict_dealloc, //tp_dealloc + 0, //tp_print + 0, //tp_getattr + 0, //tp_setattr + 0, //tp_compare + (reprfunc) PoseBonesDict_repr, //tp_repr + 0, //tp_as_number + 0, //tp_as_sequence + &PoseBonesDict_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_PoseBonesDict_doc, //tp_doc + 0, //tp_traverse + 0, //tp_clear + 0, //tp_richcompare + 0, //tp_weaklistoffset + 0, //tp_iter + 0, //tp_iternext + BPy_PoseBonesDict_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 + 0, //tp_new + 0, //tp_free + 0, //tp_is_gc + 0, //tp_bases + 0, //tp_mro + 0, //tp_cache + 0, //tp_subclasses + 0, //tp_weaklist + 0 //tp_del +}; +//-----------------------PyPoseBonesDict_FromPyPose +static PyObject *PyPoseBonesDict_FromPyPose(BPy_Pose *py_pose) +{ + BPy_PoseBonesDict *py_posebonesdict = NULL; + + //create py object + py_posebonesdict = (BPy_PoseBonesDict *)PoseBonesDict_Type.tp_alloc(&PoseBonesDict_Type, 0); + if (!py_posebonesdict) + goto RuntimeError; + + //create internal dictionaries + py_posebonesdict->bonesMap = PyDict_New(); + if (!py_posebonesdict->bonesMap) + goto RuntimeError; + + //set listbase pointer + py_posebonesdict->bones = &py_pose->pose->chanbase; + + //now that everything is setup - init the mappings + if (!PoseBonesDict_InitBones(py_posebonesdict)) + goto RuntimeError; + + return (PyObject*)py_posebonesdict; + +RuntimeError: + return EXPP_objError(PyExc_RuntimeError, "%s%s", + sPoseBonesDictError, "Failed to create class"); +} + +//################## Pose_Type ########################## +/*This type is a wrapper for a pose*/ +//#################################################### +//------------------METHOD IMPLEMENTATIONS------------------------------ +static PyObject *Pose_update(BPy_Pose *self) +{ + Object *daddy = NULL; + + self->pose->flag |= POSE_RECALC; + + for (daddy = G.main->object.first; daddy; daddy = daddy->id.next){ + if (daddy->pose == self->pose){ + break; + } + } + + if(daddy) + where_is_pose(daddy); + + return EXPP_incr_ret(Py_None); +} +//------------------------tp_methods +//This contains a list of all methods the object contains +static PyMethodDef BPy_Pose_methods[] = { + {"update", (PyCFunction) Pose_update, METH_NOARGS, + "() - Rebuilds the pose with new values"}, + {NULL} +}; +//------------------ATTRIBUTE IMPLEMENTATIONS--------------------------- +//------------------------Pose.bones (getter) +//Gets the bones attribute +static PyObject *Pose_getBoneDict(BPy_Pose *self, void *closure) +{ + return EXPP_incr_ret((PyObject*)self->Bones); +} +//------------------------Pose.bones (setter) +//Sets the bones attribute +static int Pose_setBoneDict(BPy_Pose *self, PyObject *value, void *closure) +{ + goto AttributeError; + +AttributeError: + return EXPP_intError(PyExc_AttributeError, "%s%s", + sPoseError, "You are not allowed to change the .bones attribute"); +} +//------------------TYPE_OBECT IMPLEMENTATION--------------------------- +//------------------------tp_getset +//This contains methods for attributes that require checking +static PyGetSetDef BPy_Pose_getset[] = { + {"bones", (getter)Pose_getBoneDict, (setter)Pose_setBoneDict, + "The pose's Bone dictionary", NULL}, + {NULL} +}; +//------------------------tp_dealloc +//This tells how to 'tear-down' our object when ref count hits 0 +static void Pose_dealloc(BPy_Pose *self) +{ + Py_DECREF(self->Bones); + Pose_Type.tp_free(self); + return; +} +//------------------------tp_repr +//This is the string representation of the object +static PyObject *Pose_repr(BPy_Pose *self) +{ + return PyString_FromFormat( "[Pose \"%s\"]", self->name); +} +//------------------------tp_doc +//The __doc__ string for this object +static char BPy_Pose_doc[] = "This object wraps a Blender Pose object."; + +//------------------TYPE_OBECT DEFINITION-------------------------- +PyTypeObject Pose_Type = { + PyObject_HEAD_INIT(NULL) //tp_head + 0, //tp_internal + "Pose", //tp_name + sizeof(BPy_Pose), //tp_basicsize + 0, //tp_itemsize + (destructor)Pose_dealloc, //tp_dealloc + 0, //tp_print + 0, //tp_getattr + 0, //tp_setattr + 0, //tp_compare + (reprfunc)Pose_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_Pose_doc, //tp_doc + 0, //tp_traverse + 0, //tp_clear + 0, //tp_richcompare + 0, //tp_weaklistoffset + 0, //tp_iter + 0, //tp_iternext + BPy_Pose_methods, //tp_methods + 0, //tp_members + BPy_Pose_getset, //tp_getset + 0, //tp_base + 0, //tp_dict + 0, //tp_descr_get + 0, //tp_descr_set + 0, //tp_dictoffset + 0, //tp_init + 0, //tp_alloc + 0, //tp_new + 0, //tp_free + 0, //tp_is_gc + 0, //tp_bases + 0, //tp_mro + 0, //tp_cache + 0, //tp_subclasses + 0, //tp_weaklist + 0 //tp_del +}; +//################## PoseBone_Type ##################### +/*This type is a wrapper for a posechannel*/ +//#################################################### +//------------------METHOD IMPLEMENTATIONS------------------------------ +//------------------------------PoseBone.insertKey() +static PyObject *PoseBone_insertKey(BPy_PoseBone *self, PyObject *args) +{ + PyObject *parent_object = NULL; + PyObject *constants = NULL, *item = NULL; + int frame = 1, oldframe, length, x, numeric_value = 0, oldflag; + bPoseChannel *pchan = NULL; + + + if (!PyArg_ParseTuple(args, "O!i|O", &Object_Type, &parent_object, &frame, &constants )) + goto AttributeError; + + //verify that this pchannel is part of the object->pose + for (pchan = ((BPy_Object*)parent_object)->object->pose->chanbase.first; + pchan; pchan = pchan->next){ + if (pchan == self->posechannel) + break; + } + if (!pchan) + goto AttributeError2; + + //verify that there is an action bound to this object + if (!((BPy_Object*)parent_object)->object->action){ + goto AttributeError5; + } + + oldflag = self->posechannel->flag; + self->posechannel->flag = 0; + //set the flags for this posechannel + if (constants){ + if(PySequence_Check(constants)){ + length = PySequence_Length(constants); + for (x = 0; x < length; x++){ + item = PySequence_GetItem(constants, x); + if (item == EXPP_GetModuleConstant("Blender.Object.Pose", "ROT")){ + numeric_value |= POSE_ROT; + }else if (item == EXPP_GetModuleConstant("Blender.Object.Pose", "LOC")){ + numeric_value |= POSE_LOC; + }else if (item == EXPP_GetModuleConstant("Blender.Object.Pose", "SIZE")){ + numeric_value |= POSE_SIZE; + }else{ + Py_DECREF(item); + self->posechannel->flag = (short)oldflag; + goto AttributeError4; + } + Py_DECREF(item); + } + self->posechannel->flag = (short)numeric_value; + }else if (BPy_Constant_Check(constants)){ + if (constants == EXPP_GetModuleConstant("Blender.Object.Pose", "ROT")){ + numeric_value |= POSE_ROT; + }else if (constants == EXPP_GetModuleConstant("Blender.Object.Pose", "LOC")){ + numeric_value |= POSE_LOC; + }else if (constants == EXPP_GetModuleConstant("Blender.Object.Pose", "SIZE")){ + numeric_value |= POSE_SIZE; + }else{ + self->posechannel->flag = (short)oldflag; + goto AttributeError4; + } + self->posechannel->flag = (short)numeric_value; + }else{ + goto AttributeError3; + } + }else{ //nothing passed so set them all + self->posechannel->flag |= POSE_ROT; + self->posechannel->flag |= POSE_LOC; + self->posechannel->flag |= POSE_SIZE; + } + + //set the frame we want insertion on + oldframe = G.scene->r.cfra; + G.scene->r.cfra = (short)frame; + + //add the action channel if it's not there + verify_action_channel(((BPy_Object*)parent_object)->object->action, + self->posechannel->name); + + //insert the pose keys + if (self->posechannel->flag & POSE_ROT){ + insertkey(&((BPy_Object*)parent_object)->object->id, + ID_PO, self->posechannel->name, NULL, AC_QUAT_X); + insertkey(&((BPy_Object*)parent_object)->object->id, + ID_PO, self->posechannel->name, NULL, AC_QUAT_Y); + insertkey(&((BPy_Object*)parent_object)->object->id, + ID_PO, self->posechannel->name, NULL, AC_QUAT_Z); + insertkey(&((BPy_Object*)parent_object)->object->id, + ID_PO, self->posechannel->name, NULL, AC_QUAT_W); + } + if (self->posechannel->flag & POSE_LOC){ + insertkey(&((BPy_Object*)parent_object)->object->id, + ID_PO, self->posechannel->name, NULL, AC_LOC_X); + insertkey(&((BPy_Object*)parent_object)->object->id, + ID_PO, self->posechannel->name, NULL, AC_LOC_Y); + insertkey(&((BPy_Object*)parent_object)->object->id, + ID_PO, self->posechannel->name, NULL, AC_LOC_Z); + } + if (self->posechannel->flag & POSE_SIZE){ + insertkey(&((BPy_Object*)parent_object)->object->id, + ID_PO, self->posechannel->name, NULL, AC_SIZE_X); + insertkey(&((BPy_Object*)parent_object)->object->id, + ID_PO, self->posechannel->name, NULL, AC_SIZE_Y); + insertkey(&((BPy_Object*)parent_object)->object->id, + ID_PO, self->posechannel->name, NULL, AC_SIZE_Z); + } + + //flip the frame back + G.scene->r.cfra = (short)oldframe; + + //update the IPOs + remake_action_ipos (((BPy_Object*)parent_object)->object->action); + + return EXPP_incr_ret(Py_None); + +AttributeError: + return EXPP_objError(PyExc_AttributeError, "%s%s%s", + sPoseBoneError, ".insertKey: ", "expects an Object, int, (optional) constants"); +AttributeError2: + return EXPP_objError(PyExc_AttributeError, "%s%s%s", + sPoseBoneError, ".insertKey: ", "wrong object detected. \ + Use the object this pose came from"); +AttributeError3: + return EXPP_objError(PyExc_AttributeError, "%s%s%s", + sPoseBoneError, ".insertKey: ", "Expects a constant or list of constants"); +AttributeError4: + return EXPP_objError(PyExc_AttributeError, "%s%s%s", + sPoseBoneError, ".insertKey: ", "Please use a constant defined in the Pose module"); +AttributeError5: + return EXPP_objError(PyExc_AttributeError, "%s%s%s", + sPoseBoneError, ".insertKey: ", "You must set up and link an Action to this object first"); +} +//------------------------tp_methods +//This contains a list of all methods the object contains +static PyMethodDef BPy_PoseBone_methods[] = { + {"insertKey", (PyCFunction) PoseBone_insertKey, METH_VARARGS, + "() - insert a key for this pose into an action"}, + {NULL} +}; +//------------------ATTRIBUTE IMPLEMENTATIONS--------------------------- +//------------------------PoseBone.name (getter) +//Gets the name attribute +static PyObject *PoseBone_getName(BPy_PoseBone *self, void *closure) +{ + return PyString_FromString(self->posechannel->name); +} +//------------------------PoseBone.name (setter) +//Sets the name attribute +static int PoseBone_setName(BPy_PoseBone *self, PyObject *value, void *closure) +{ + char *name = ""; + + if (!PyArg_Parse(value, "s", &name)) + goto AttributeError; + + BLI_strncpy(self->posechannel->name, name, 32); + return 0; + +AttributeError: + return EXPP_intError(PyExc_AttributeError, "%s%s%s", + sPoseBoneError, ".name: ", "expects a string"); +} +//------------------------PoseBone.loc (getter) +//Gets the loc attribute +static PyObject *PoseBone_getLoc(BPy_PoseBone *self, void *closure) +{ + return newVectorObject(self->posechannel->loc, 3, Py_WRAP); +} +//------------------------PoseBone.loc (setter) +//Sets the loc attribute +static int PoseBone_setLoc(BPy_PoseBone *self, PyObject *value, void *closure) +{ + VectorObject *vec = NULL; + int x; + + if (!PyArg_Parse(value, "O!", &vector_Type, &vec)) + goto AttributeError; + if (vec->size != 3) + goto AttributeError; + + for (x = 0; x < 3; x++){ + self->posechannel->loc[x] = vec->vec[x]; + } + return 0; + +AttributeError: + return EXPP_intError(PyExc_AttributeError, "%s%s%s", + sPoseBoneError, ".loc: ", "expects a 3d vector object"); +} +//------------------------PoseBone.size (getter) +//Gets the size attribute +static PyObject *PoseBone_getSize(BPy_PoseBone *self, void *closure) +{ + return newVectorObject(self->posechannel->size, 3, Py_WRAP); +} +//------------------------PoseBone.size (setter) +//Sets the size attribute +static int PoseBone_setSize(BPy_PoseBone *self, PyObject *value, void *closure) +{ + VectorObject *vec = NULL; + int x; + + if (!PyArg_Parse(value, "O!", &vector_Type, &vec)) + goto AttributeError; + if (vec->size != 3) + goto AttributeError; + + for (x = 0; x < 3; x++){ + self->posechannel->size[x] = vec->vec[x]; + } + return 0; + +AttributeError: + return EXPP_intError(PyExc_AttributeError, "%s%s%s", + sPoseBoneError, ".size: ", "expects a 3d vector object"); +} +//------------------------PoseBone.quat (getter) +//Gets the quat attribute +static PyObject *PoseBone_getQuat(BPy_PoseBone *self, void *closure) +{ + return newQuaternionObject(self->posechannel->quat, Py_WRAP); +} +//------------------------PoseBone.quat (setter) +//Sets the quat attribute +static int PoseBone_setQuat(BPy_PoseBone *self, PyObject *value, void *closure) +{ + QuaternionObject *quat = NULL; + int x; + + if (!PyArg_Parse(value, "O!", &quaternion_Type, &quat)) + goto AttributeError; + + for (x = 0; x < 4; x++){ + self->posechannel->quat[x] = quat->quat[x]; + } + return 0; + +AttributeError: + return EXPP_intError(PyExc_AttributeError, "%s%s%s", + sPoseBoneError, ".quat: ", "expects a quaternion object"); +} +//------------------------PoseBone.localMatrix (getter) +//Gets the chan_mat +static PyObject *PoseBone_getLocalMatrix(BPy_PoseBone *self, void *closure) +{ + return newMatrixObject((float*)self->posechannel->chan_mat, 4, 4, Py_WRAP); +} +//------------------------PoseBone.localMatrix (setter) +//Sets the chan_mat +static int PoseBone_setLocalMatrix(BPy_PoseBone *self, PyObject *value, void *closure) +{ + MatrixObject *matrix = NULL; + float size[3], quat[4], loc[3]; + float mat3[3][3], mat4[4][4]; + int matsize = 0; + + if (!PyArg_Parse(value, "O!", &matrix_Type, &matrix)) + goto AttributeError; + + if (matrix->rowSize == 3 && matrix->colSize == 3){ + matsize = 3; + Mat3CpyMat3(mat3, (float(*)[3])*matrix->matrix); + }else if (matrix->rowSize == 4 && matrix->colSize == 4){ + matsize = 4; + Mat4CpyMat4(mat4, (float(*)[4])*matrix->matrix); + } + + if (matsize != 3 && matsize != 4){ + goto AttributeError; + } + + //get size and rotation + if (matsize == 3){ + Mat3ToSize(mat3, size); + Mat3Ortho(mat3); + Mat3ToQuat(mat3, quat); + }else if (matsize == 4){ + Mat4ToSize(mat4, size); + Mat4Ortho(mat4); + Mat4ToQuat(mat4, quat); + } + + //get loc + if (matsize == 4){ + VECCOPY(loc, matrix->matrix[3]); + } + + //copy new attributes + VECCOPY(self->posechannel->size, size); + QUATCOPY(self->posechannel->quat, quat); + if (matsize == 4){ + VECCOPY(self->posechannel->loc, loc); + } + + //rebuild matrix + chan_calc_mat(self->posechannel); + return 0; + +AttributeError: + return EXPP_intError(PyExc_AttributeError, "%s%s%s", + sPoseBoneError, ".localMatrix: ", "expects a 3x3 or 4x4 matrix object"); +} +//------------------------PoseBone.poseMatrix (getter) +//Gets the pose_mat +static PyObject *PoseBone_getPoseMatrix(BPy_PoseBone *self, void *closure) +{ + return newMatrixObject((float*)self->posechannel->pose_mat, 4, 4, Py_WRAP); +} +//------------------------PoseBone.poseMatrix (setter) +//Sets the pose_mat +static int PoseBone_setPoseMatrix(BPy_PoseBone *self, PyObject *value, void *closure) +{ + return EXPP_intError(PyExc_AttributeError, "%s%s%s", + sPoseBoneError, ".poseMatrix: ", "not able to set this property"); +} +////------------------------PoseBone.constraints (getter) +////Gets the constraints list +//static PyObject *PoseBone_getConstraints(BPy_PoseBone *self, void *closure) +//{ +// PyObject *list = NULL, *py_constraint = NULL; +// bConstraint *constraint = NULL; +// +// list = PyList_New(0); +// for (constraint = self->posechannel->constraints.first; constraint; constraint = constraint->next){ +// py_constraint = PyConstraint_FromConstraint(constraint); +// if (!py_constraint) +// return NULL; +// if (PyList_Append(list, py_constraint) == -1){ +// Py_DECREF(py_constraint); +// goto RuntimeError; +// } +// Py_DECREF(py_constraint); +// } +// return list; +// +//RuntimeError: +// return EXPP_objError(PyExc_RuntimeError, "%s%s%s", +// sPoseBoneError, ".constraints: ", "unable to build constraint list"); +//} +////------------------------PoseBone.constraints (setter) +////Sets the constraints list +//static int PoseBone_setConstraints(BPy_PoseBone *self, PyObject *value, void *closure) +//{ +// printf("This is not implemented yet..."); +// return 1; +//} +//------------------TYPE_OBECT IMPLEMENTATION--------------------------- +//------------------------tp_getset +//This contains methods for attributes that require checking +static PyGetSetDef BPy_PoseBone_getset[] = { + {"name", (getter)PoseBone_getName, (setter)PoseBone_setName, + "The pose bone's name", NULL}, + {"loc", (getter)PoseBone_getLoc, (setter)PoseBone_setLoc, + "The pose bone's change in location as a vector", NULL}, + {"size", (getter)PoseBone_getSize, (setter)PoseBone_setSize, + "The pose bone's change in size as a vector", NULL}, + {"quat", (getter)PoseBone_getQuat, (setter)PoseBone_setQuat, + "The pose bone's change in rotation as a quat", NULL}, + {"localMatrix", (getter)PoseBone_getLocalMatrix, (setter)PoseBone_setLocalMatrix, + "The pose bone's change matrix built from the quat, loc, and size", NULL}, + {"poseMatrix", (getter)PoseBone_getPoseMatrix, (setter)PoseBone_setPoseMatrix, + "The pose bone's matrix", NULL}, + //{"constraints", (getter)PoseBone_getConstraints, (setter)PoseBone_setConstraints, + // "The list of contraints that pertain to this pose bone", NULL}, + {NULL} +}; +//------------------------tp_dealloc +//This tells how to 'tear-down' our object when ref count hits 0 +static void PoseBone_dealloc(BPy_PoseBone *self) +{ + PoseBone_Type.tp_free(self); + return; +} +//------------------------tp_repr +//This is the string representation of the object +static PyObject *PoseBone_repr(BPy_PoseBone *self) +{ + return PyString_FromFormat( "[PoseBone \"%s\"]", self->posechannel->name); +} +//------------------------tp_doc +//The __doc__ string for this object +static char BPy_PoseBone_doc[] = "This object wraps a Blender PoseBone object."; + +//------------------TYPE_OBECT DEFINITION-------------------------- +PyTypeObject PoseBone_Type = { + PyObject_HEAD_INIT(NULL) //tp_head + 0, //tp_internal + "PoseBone", //tp_name + sizeof(BPy_PoseBone), //tp_basicsize + 0, //tp_itemsize + (destructor)PoseBone_dealloc, //tp_dealloc + 0, //tp_print + 0, //tp_getattr + 0, //tp_setattr + 0, //tp_compare + (reprfunc)PoseBone_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_PoseBone_doc, //tp_doc + 0, //tp_traverse + 0, //tp_clear + 0, //tp_richcompare + 0, //tp_weaklistoffset + 0, //tp_iter + 0, //tp_iternext + BPy_PoseBone_methods, //tp_methods + 0, //tp_members + BPy_PoseBone_getset, //tp_getset + 0, //tp_base + 0, //tp_dict + 0, //tp_descr_get + 0, //tp_descr_set + 0, //tp_dictoffset + 0, //tp_init + 0, //tp_alloc + 0, //tp_new + 0, //tp_free + 0, //tp_is_gc + 0, //tp_bases + 0, //tp_mro + 0, //tp_cache + 0, //tp_subclasses + 0, //tp_weaklist + 0 //tp_del +}; +//-------------------MODULE METHODS IMPLEMENTATION------------------------ +//-------------------MODULE METHODS DEFINITION----------------------------- +struct PyMethodDef M_Pose_methods[] = { + {NULL} +}; +//-------------------MODULE INITIALIZATION-------------------------------- +PyObject *Pose_Init(void) +{ + PyObject *module; + + //Initializes TypeObject.ob_type + if (PyType_Ready(&Pose_Type) < 0 || PyType_Ready(&PoseBone_Type) < 0 || + PyType_Ready(&PoseBonesDict_Type) < 0) { + return EXPP_incr_ret(Py_None); + } + + //Register the module + module = Py_InitModule3("Blender.Object.Pose", M_Pose_methods, + "The Blender Pose module"); + + //Add TYPEOBJECTS to the module + PyModule_AddObject(module, "Pose", + EXPP_incr_ret((PyObject *)&Pose_Type)); //*steals* + PyModule_AddObject(module, "PoseBone", + EXPP_incr_ret((PyObject *)&PoseBone_Type)); //*steals* + + //Add CONSTANTS to the module + PyModule_AddObject(module, "ROT", + EXPP_incr_ret(PyConstant_NewInt("ROT", POSE_ROT))); + PyModule_AddObject(module, "LOC", + EXPP_incr_ret(PyConstant_NewInt("LOC", POSE_LOC))); + PyModule_AddObject(module, "SIZE", + EXPP_incr_ret(PyConstant_NewInt("SIZE", POSE_SIZE))); + + return module; +} +//------------------VISIBLE PROTOTYPE IMPLEMENTATION----------------------- +//------------------------------PyPose_FromPose (internal) +//Returns a PyPose from a bPose - return PyNone if bPose is NULL +PyObject *PyPose_FromPose(bPose *pose, char *name) +{ + BPy_Pose *py_pose = NULL; + + if (pose){ + py_pose = (BPy_Pose*)Pose_Type.tp_alloc(&Pose_Type, 0); + if (!py_pose) + goto RuntimeError; + + py_pose->pose = pose; + BLI_strncpy(py_pose->name, name, 24); + + //create armature.bones + py_pose->Bones = (BPy_PoseBonesDict*)PyPoseBonesDict_FromPyPose(py_pose); + if (!py_pose->Bones) + goto RuntimeError; + + return (PyObject*)py_pose; + }else{ + EXPP_incr_ret(Py_None); + } + +RuntimeError: + return EXPP_objError(PyExc_RuntimeError, "%s%s%s", + sPoseError, "PyPose_FromPose: ", "Internal Error Ocurred"); +} +//------------------------------PyPoseBone_FromPosechannel (internal) +//Returns a PyPoseBone from a bPoseChannel - return PyNone if bPoseChannel is NULL +PyObject *PyPoseBone_FromPosechannel(bPoseChannel *pchan) +{ + BPy_PoseBone *py_posechannel = NULL; + + if (pchan){ + py_posechannel = (BPy_PoseBone*)PoseBone_Type.tp_alloc(&PoseBone_Type, 0); + if (!py_posechannel) + goto RuntimeError; + py_posechannel->posechannel = pchan; + return (PyObject*)py_posechannel; + }else{ + EXPP_incr_ret(Py_None); + } + +RuntimeError: + return EXPP_objError(PyExc_RuntimeError, "%s%s%s", + sPoseBoneError, "PyPoseBone_FromPosechannel: ", "Internal Error Ocurred"); +} diff --git a/source/blender/python/api2_2x/Pose.h b/source/blender/python/api2_2x/Pose.h new file mode 100644 index 00000000000..9506afd01fa --- /dev/null +++ b/source/blender/python/api2_2x/Pose.h @@ -0,0 +1,68 @@ +/* + * $Id: + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): Joseph Gilbert + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** +*/ + +#ifndef EXPP_POSE_H +#define EXPP_POSE_H + +#include <Python.h> +#include "DNA_action_types.h" + +//-------------------TYPE CHECKS--------------------------------- +#define PoseObject_Check(v) ((v)->ob_type == &Pose_Type) +#define PoseBoneObject_Check(v) ((v)->ob_type == &PoseBone_Type) +#define PoseBonesDictObject_Check(v) ((v)->ob_type == &PoseBonesDict_Type) +//-------------------TYPEOBJECT---------------------------------- +PyTypeObject Pose_Type; +PyTypeObject PoseBone_Type; +PyTypeObject PoseBonesDict_Type; +//-------------------STRUCT DEFINITION---------------------------- +typedef struct { + PyObject_HEAD + PyObject *bonesMap; + ListBase *bones; +} BPy_PoseBonesDict; + +typedef struct { + PyObject_HEAD + bPose *pose; + char name[24]; //because poses have not names :( + BPy_PoseBonesDict *Bones; +} BPy_Pose; + +typedef struct { + PyObject_HEAD + bPoseChannel *posechannel; +} BPy_PoseBone; + +//-------------------VISIBLE PROTOTYPES------------------------- +PyObject *Pose_Init(void); +PyObject *PyPose_FromPose(bPose *pose, char *name); +PyObject *PyPoseBone_FromPosechannel(bPoseChannel *pchan); +#endif |