*pose code for python
authorJoseph Gilbert <ascotan@gmail.com>
Wed, 11 Jan 2006 19:40:06 +0000 (19:40 +0000)
committerJoseph Gilbert <ascotan@gmail.com>
Wed, 11 Jan 2006 19:40:06 +0000 (19:40 +0000)
- adds object.getPose
- ability to manipulate poses /posebones
- fixes a overflow bug in matrix sequence accessor
- adds code to get vec/roll from mat3
- few internal fixes to NLA
- ability to set bone matrices

source/blender/blenkernel/intern/armature.c
source/blender/python/api2_2x/Bone.c
source/blender/python/api2_2x/NLA.c
source/blender/python/api2_2x/NLA.h
source/blender/python/api2_2x/Object.c
source/blender/python/api2_2x/matrix.c

index 95a39c29a54faacf0eac8cb92323b01ac91837e7..4cdd1b71c30337ad97c127c50f5cd6abc4c02a15 100644 (file)
@@ -808,7 +808,22 @@ void get_objectspace_bone_matrix (struct Bone* bone, float M_accumulatedMatrix[]
   pose_mat(b)= arm_mat(b) * chan_mat(b)
   
   *************************************************************************** */
+/*  Computes vector and roll based on a rotation. "mat" must
+     contain only a rotation, and no scaling. */ 
+void mat3_to_vec_roll(float mat[][3], float *vec, float *roll) {
+     if (vec)
+         VecCopyf(vec, mat[1]);
 
+     if (roll) {
+         float vecmat[3][3], vecmatinv[3][3], rollmat[3][3];
+
+         vec_roll_to_mat3(mat[1], 0.0f, vecmat);
+         Mat3Inv(vecmatinv, vecmat);
+         Mat3MulMat3(rollmat, vecmatinv, mat);
+
+         *roll= atan2(rollmat[2][0], rollmat[2][2]);
+     }
+}
 
 /*     Calculates the rest matrix of a bone based
        On its vector and a roll around that vector */
index b4f8af4fe12ea5c5d311fa0ebbdac88f3d0ce143..04e7b16d978cb3f37ff9a097780d7511046a9c1b 100644 (file)
 #include "DNA_object_types.h" //1
 #include "BIF_editarmature.h"   //2
 
+//------------------UNDECLARED EXTERNAL PROTOTYPES--------------------
+extern void mat3_to_vec_roll(float mat[][3], float *vec, float *roll);
+
 //------------------------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 sEditBoneError[] = "EditBone - Error: ";
+static const char sEditBoneBadArgs[] = "EditBone - Bad Arguments: ";
 static const char sBoneError[] = "Bone - Error: ";
 static const char sBoneBadArgs[] = "Bone - Bad Arguments: ";
-static const char sConstListError[] = "ConstantList - Error: ";
-static const char sConstListBadArgs[] = "ConstantList - Bad Arguments: ";
 
 //----------------------(internal)
 //gets the bone->roll (which is a localspace roll) and puts it in parentspace
@@ -541,7 +542,6 @@ static int EditBone_setParent(BPy_EditBone *self, PyObject *value, void *closure
 AttributeError:
        return EXPP_intError(PyExc_AttributeError, "%s%s%s",
                sEditBoneError, ".parent: ", "expects a EditBone Object");
-
 AttributeError2:
        return EXPP_intError(PyExc_AttributeError, "%s%s%s",
                sEditBoneError, ".parent: ", "This object is not in the armature's bone list!");
@@ -565,8 +565,53 @@ static PyObject *EditBone_getMatrix(BPy_EditBone *self, void *closure)
 //------------------------EditBone.matrix (set)
 static int EditBone_setMatrix(BPy_EditBone *self, PyObject *value, void *closure)
 {  
-       printf("Sorry this isn't implemented yet.... :/");
-       return 1;
+       PyObject *matrix;
+       float roll, length, vec[3], axis[3], mat3[3][3];
+
+       if (!PyArg_Parse(value, "O!", &matrix_Type, &matrix))
+               goto AttributeError;
+
+       //make sure we have the right sizes
+       if (((MatrixObject*)matrix)->rowSize != 3 && ((MatrixObject*)matrix)->colSize != 3){
+               if(((MatrixObject*)matrix)->rowSize != 4 && ((MatrixObject*)matrix)->colSize != 4){
+                       goto AttributeError;
+               }
+       }
+               
+       /*vec will be a normalized directional vector
+       * together with the length of the old bone vec*length = the new vector*/
+       /*The default rotation is 0,1,0 on the Y axis (see mat3_to_vec_roll)*/
+       if (((MatrixObject*)matrix)->rowSize == 4){
+               Mat3CpyMat4(mat3, ((float (*)[4])*((MatrixObject*)matrix)->matrix));
+       }else{
+               Mat3CpyMat3(mat3, ((float (*)[3])*((MatrixObject*)matrix)->matrix));
+       }
+       mat3_to_vec_roll(mat3, vec, &roll);
+
+       //if a 4x4 matrix was passed we'll translate the vector otherwise not
+       if (self->editbone){
+               self->editbone->roll = roll;
+               VecSubf(axis, self->editbone->tail, self->editbone->head);
+               length =  VecLength(axis);
+               VecMulf(vec, length);
+               if (((MatrixObject*)matrix)->rowSize == 4)
+                       VecCopyf(self->editbone->head, ((MatrixObject*)matrix)->matrix[3]);
+               VecAddf(self->editbone->tail, self->editbone->head, vec);
+               return 0;
+       }else{
+               self->roll = roll;
+               VecSubf(axis, self->tail, self->head);
+               length =  VecLength(axis);
+               VecMulf(vec, length);
+               if (((MatrixObject*)matrix)->rowSize == 4)
+                       VecCopyf(self->head, ((MatrixObject*)matrix)->matrix[3]);
+               VecAddf(self->tail, self->head, vec);
+               return 0;
+       }
+
+AttributeError:
+       return EXPP_intError(PyExc_AttributeError, "%s%s%s",
+               sEditBoneError, ".matrix: ", "expects a 3x3 or 4x4 Matrix Object");
 }
 //------------------------Bone.length (get)
 static PyObject *EditBone_getLength(BPy_EditBone *self, void *closure)
index a07f15b3cab62719c9f685072d121cca1cc685c7..96701c124f5c4575a46f0ba852173bc5128d32b4 100644 (file)
@@ -447,11 +447,15 @@ PyObject *Action_CreatePyObject( struct bAction * act )
 {
        BPy_Action *blen_action;
 
+       if(!act)
+               return EXPP_incr_ret(Py_None);
+
        blen_action =
                ( BPy_Action * ) PyObject_NEW( BPy_Action, &Action_Type );
 
-       if( blen_action == NULL ) {
-               return ( NULL );
+       if( !blen_action) {
+               return ( EXPP_ReturnPyObjError
+                        ( PyExc_RuntimeError, "failure to create object!" ) );
        }
        blen_action->action = act;
        return ( ( PyObject * ) blen_action );
index 11b44f2401b2ccc0ad833ce8bc085c1991beedcb..59adc4a55dd900b019ec8d9a10771e2af69810f1 100644 (file)
@@ -39,6 +39,8 @@
 /** NLA module initialization function. */
 PyObject *NLA_Init( void );
 
+PyTypeObject Action_Type;
+
 /** Python BPy_NLA structure definition. */
 typedef struct {
        PyObject_HEAD 
index 31818a948efce5fcdf7983ffe6c1d9807499925e..f9b63c63a842e21151e1e67760d7880b48e1305d 100644 (file)
@@ -92,6 +92,7 @@ struct rctf;
 #include "NLA.h"
 #include "logic.h"
 #include "Effect.h"
+#include "Pose.h"
 #include "gen_utils.h"
 
 /* Defines for insertIpoKey */
@@ -171,6 +172,7 @@ struct PyMethodDef M_Object_methods[] = {
 int setupSB(Object* ob); /*Make sure Softbody Pointer is initialized */
 int setupPI(Object* ob);
 
+static PyObject *Object_getPose( BPy_Object *self);
 static PyObject *Object_buildParts( BPy_Object * self );
 static PyObject *Object_clearIpo( BPy_Object * self );
 static PyObject *Object_clrParent( BPy_Object * self, PyObject * args );
@@ -562,7 +564,8 @@ works only if self and the object specified are of the same type."},
         "([s1<,s2,s3...>]) - Delete specified scriptlinks from this object."},
        {"setDupliVerts", ( PyCFunction ) Object_setDupliVerts,
         METH_VARARGS, "() - set or reset duplicate child objects on all vertices"},
-       
+       {"getPose", (PyCFunction)Object_getPose, METH_NOARGS,
+       "() - returns the pose from an object if it exists, else None"},
        {NULL, NULL, 0, NULL}
 };
 
@@ -860,7 +863,7 @@ static PyObject *M_Object_Duplicate( PyObject * self, PyObject * args, PyObject
 /*****************************************************************************/
 PyObject *Object_Init( void )
 {
-       PyObject *module;
+       PyObject *module, *dict;
 
        Object_Type.ob_type = &PyType_Type;
 
@@ -885,6 +888,11 @@ PyObject *Object_Init( void )
        PyModule_AddIntConstant( module, "MAGNET",PFIELD_MAGNET );
        PyModule_AddIntConstant( module, "WIND",PFIELD_WIND );
 
+               //Add SUBMODULES to the module
+       dict = PyModule_GetDict( module ); //borrowed
+       PyDict_SetItemString(dict, "Pose", Pose_Init()); //creates a *new* module
+       //PyDict_SetItemString(dict, "Constraint", Constraint_Init()); //creates a *new* module
+
        return ( module );
 }
 
@@ -2771,6 +2779,12 @@ static PyObject *Object_getEffects( BPy_Object * self )
        return effect_list;
 }
 
+static PyObject * Object_getPose(BPy_Object *self)
+{
+       //if there is no pose will return PyNone
+       return PyPose_FromPose(self->object->pose, self->object->id.name+2);
+}
+
 /*****************************************************************************/
 /* Function:   Object_CreatePyObject                                    */
 /* Description: This function will create a new BlenObject from an existing  */
index c66482eab1ce063b4e1ae002dbd8d27b361ddf82..fcf0616b874d65a29a9b562ec575fac821feca1d 100644 (file)
@@ -458,7 +458,7 @@ static int Matrix_ass_item(MatrixObject * self, int i, PyObject * ob)
        float vec[4];
        PyObject *m, *f;
 
-       if(i > self->rowSize || i < 0){
+       if(i >= self->rowSize || i < 0){
                return EXPP_ReturnIntError(PyExc_TypeError,
                        "matrix[attribute] = x: bad row\n");
        }