Revision: 20937
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=20937
Author:   campbellbarton
Date:     2009-06-16 20:25:48 +0200 (Tue, 16 Jun 2009)

Log Message:
-----------
BGE Action Actuator setChannel() function was broken in a number of ways. 
* extract_pose_from_pose only checked one of the list items for NULL when 
looping over them yet its possible they are different sizes.
* game_free_pose needed to be used rather then MEM_freeN, channels would never 
be freed leaking memory.
* setChannel() would make a new pose that wasnt aligned with the existing pose, 
the lists are assumed aligned so when extracting the channels its unlikely this 
was ever useful.
* Added getChannel() - returns pose loc/size/quat
* Added option args for setChannel(channel, matrix) or setChannel(channel, loc, 
size, quat)

Modified Paths:
--------------
    trunk/blender/source/blender/blenkernel/intern/action.c
    trunk/blender/source/gameengine/Converter/BL_ActionActuator.cpp
    trunk/blender/source/gameengine/Converter/BL_ActionActuator.h
    trunk/blender/source/gameengine/PyDoc/GameTypes.py

Modified: trunk/blender/source/blender/blenkernel/intern/action.c
===================================================================
--- trunk/blender/source/blender/blenkernel/intern/action.c     2009-06-16 
18:02:38 UTC (rev 20936)
+++ trunk/blender/source/blender/blenkernel/intern/action.c     2009-06-16 
18:25:48 UTC (rev 20937)
@@ -798,6 +798,7 @@
 /* Copy the data from the action-pose (src) into the pose */
 /* both args are assumed to be valid */
 /* exported to game engine */
+/* Note! this assumes both poses are aligned, this isnt always true when 
dealing with user poses */
 void extract_pose_from_pose(bPose *pose, const bPose *src)
 {
        const bPoseChannel *schan;
@@ -808,7 +809,7 @@
                return;
        }
 
-       for (schan=src->chanbase.first; schan; schan=schan->next, pchan= 
pchan->next) {
+       for (schan=src->chanbase.first; (schan && pchan); schan=schan->next, 
pchan= pchan->next) {
                copy_pose_channel_data(pchan, schan);
        }
 }

Modified: trunk/blender/source/gameengine/Converter/BL_ActionActuator.cpp
===================================================================
--- trunk/blender/source/gameengine/Converter/BL_ActionActuator.cpp     
2009-06-16 18:02:38 UTC (rev 20936)
+++ trunk/blender/source/gameengine/Converter/BL_ActionActuator.cpp     
2009-06-16 18:25:48 UTC (rev 20937)
@@ -50,6 +50,7 @@
 #include "BKE_utildefines.h"
 #include "FloatValue.h"
 #include "PyObjectPlus.h"
+#include "KX_PyMath.h"
 #include "blendef.h"
 
 #ifdef HAVE_CONFIG_H
@@ -366,8 +367,7 @@
                        /* Perform the user override (if any) */
                        if (m_userpose){
                                extract_pose_from_pose(m_pose, m_userpose);
-//                             clear_pose(m_userpose);
-                               MEM_freeN(m_userpose);
+                               game_free_pose(m_userpose); //cant use 
MEM_freeN(m_userpose) because the channels need freeing too.
                                m_userpose = NULL;
                        }
 #if 1
@@ -767,22 +767,55 @@
        Py_RETURN_NONE;
 }
 
-/*
-PyObject* BL_ActionActuator::PyGetChannel(PyObject* args, 
-                                                                               
   PyObject* kwds) {
-       char *string;
+PyObject* BL_ActionActuator::PyGetChannel(PyObject* value) {
+       char *string= PyString_AsString(value);
        
-       if (PyArg_ParseTuple(args,"s:getChannel",&string))
+       if (!string) {
+               PyErr_SetString(PyExc_TypeError, "expected a single string");
+               return NULL;
+       }
+       
+       bPoseChannel *pchan;
+       
+       
+       // get_pose_channel accounts for NULL pose, run on both incase one 
exists but
+       // the channel doesnt
+       if(             !(pchan=get_pose_channel(m_userpose, string)) &&
+                       !(pchan=get_pose_channel(m_pose, string))  )
        {
-               m_propname = string;
-       }
-       else {
+               PyErr_SetString(PyExc_ValueError, "channel doesnt exist");
                return NULL;
        }
+
+       PyObject *ret = PyTuple_New(3);
        
-       Py_RETURN_NONE;
+       PyObject *list = PyList_New(3); 
+       PyList_SET_ITEM(list, 0, PyFloat_FromDouble(pchan->loc[0]));
+       PyList_SET_ITEM(list, 1, PyFloat_FromDouble(pchan->loc[1]));
+       PyList_SET_ITEM(list, 2, PyFloat_FromDouble(pchan->loc[2]));
+       PyTuple_SET_ITEM(ret, 0, list);
+       
+       list = PyList_New(3);
+       PyList_SET_ITEM(list, 0, PyFloat_FromDouble(pchan->size[0]));
+       PyList_SET_ITEM(list, 1, PyFloat_FromDouble(pchan->size[1]));
+       PyList_SET_ITEM(list, 2, PyFloat_FromDouble(pchan->size[2]));
+       PyTuple_SET_ITEM(ret, 1, list);
+       
+       list = PyList_New(4);
+       PyList_SET_ITEM(list, 0, PyFloat_FromDouble(pchan->quat[0]));
+       PyList_SET_ITEM(list, 1, PyFloat_FromDouble(pchan->quat[1]));
+       PyList_SET_ITEM(list, 2, PyFloat_FromDouble(pchan->quat[2]));
+       PyList_SET_ITEM(list, 3, PyFloat_FromDouble(pchan->quat[3]));
+       PyTuple_SET_ITEM(ret, 2, list);
+
+       return ret;
+/*
+       return Py_BuildValue("([fff][fff][ffff])",
+               pchan->loc[0], pchan->loc[1], pchan->loc[2],
+               pchan->size[0], pchan->size[1], pchan->size[2],
+               pchan->quat[0], pchan->quat[1], pchan->quat[2], pchan->quat[3] 
);
+*/
 }
-*/
 
 /* getType */
 const char BL_ActionActuator::GetType_doc[] =
@@ -857,76 +890,69 @@
 "\t - matrix    : A 4x4 matrix specifying the overriding transformation\n"
 "\t               as an offset from the bone's rest position.\n")
 {
-       float matrix[4][4];
+       BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
        char *string;
-       PyObject* pylist;
-       bool    error = false;
-       int row,col;
-       int     mode = 0;       /* 0 for bone space, 1 for armature/world space 
*/
+       PyObject *pymat= NULL;
+       PyObject *pyloc= NULL, *pysize= NULL, *pyquat= NULL;
+       bPoseChannel *pchan;
        
-       if (!PyArg_ParseTuple(args,"sO|i:setChannel", &string, &pylist, &mode))
+       if(PyTuple_Size(args)==2) {
+               if (!PyArg_ParseTuple(args,"sO:setChannel", &string, &pymat)) 
// matrix
+                       return NULL;
+       }
+       else if(PyTuple_Size(args)==4) {
+               if (!PyArg_ParseTuple(args,"sOOO:setChannel", &string, &pyloc, 
&pysize, &pyquat)) // loc/size/quat
+                       return NULL;
+       }
+       else {
+               PyErr_SetString(PyExc_ValueError, "Expected a string and a 4x4 
matrix (2 args) or a string and loc/size/quat sequences (4 args)");
                return NULL;
+       }
        
-       if (pylist->ob_type == &CListValue::Type)
-       {
-               CListValue* listval = (CListValue*) pylist;
-               if (listval->GetCount() == 4)
-               {
-                       for (row=0;row<4;row++) // each row has a 4-vector 
[x,y,z, w]
-                       {
-                               CListValue* vecval = 
(CListValue*)listval->GetValue(row);
-                               for (col=0;col<4;col++)
-                               {
-                                       matrix[row][col] = 
vecval->GetValue(col)->GetNumber();
-                                       
-                               }
-                       }
+       if(pymat) {
+               float matrix[4][4];
+               MT_Matrix4x4 mat;
+               
+               if(!PyMatTo(pymat, mat))
+                       return NULL;
+               
+               mat.setValue((const float *)matrix);
+               
+               BL_ArmatureObject *obj = (BL_ArmatureObject*)GetParent();
+               obj->GetPose(&m_pose); /* Get the underlying pose from the 
armature */
+               
+               if (!m_userpose) {
+                       obj->GetPose(&m_pose); /* Get the underlying pose from 
the armature */
+                       game_copy_pose(&m_userpose, m_pose);
                }
-               else
-               {
-                       error = true;
-               }
+               pchan= verify_pose_channel(m_userpose, string); // adds the 
channel if its not there.
+               
+               VECCOPY (pchan->loc, matrix[3]);
+               Mat4ToSize(matrix, pchan->size);
+               Mat4ToQuat(matrix, pchan->quat);
        }
-       else
-       {
-               // assert the list is long enough...
-               int numitems = PyList_Size(pylist);
-               if (numitems == 4)
-               {
-                       for (row=0;row<4;row++) // each row has a 4-vector 
[x,y,z, w]
-                       {
-                               
-                               PyObject* veclist = PyList_GetItem(pylist,row); 
// here we have a vector4 list
-                               for (col=0;col<4;col++)
-                               {
-                                       matrix[row][col] =  
PyFloat_AsDouble(PyList_GetItem(veclist,col));
-                                       
-                               }
-                       }
+       else {
+               MT_Vector3 loc;
+               MT_Vector3 size;
+               MT_Vector4 quat;
+               
+               if (!PyVecTo(pyloc, loc) || !PyVecTo(pysize, size) || 
!PyVecTo(pyquat, quat))
+                       return NULL;
+               
+               // same as above
+               if (!m_userpose) {
+                       obj->GetPose(&m_pose); /* Get the underlying pose from 
the armature */
+                       game_copy_pose(&m_userpose, m_pose);
                }
-               else
-               {
-                       error = true;
-               }
-       }
-       
-       if (!error)
-       {
-
-/*     DO IT HERE */
-               bPoseChannel *pchan= verify_pose_channel(m_userpose, string);
-
-               Mat4ToQuat(matrix, pchan->quat);
-               Mat4ToSize(matrix, pchan->size);
-               VECCOPY (pchan->loc, matrix[3]);
+               pchan= verify_pose_channel(m_userpose, string);
                
-               pchan->flag |= POSE_ROT|POSE_LOC|POSE_SIZE;
-
-               if (!m_userpose){
-                       m_userpose = (bPose*)MEM_callocN(sizeof(bPose), 
"userPose");
-               }
+               // for some reason loc.setValue(pchan->loc) fails
+               pchan->loc[0]= loc[0]; pchan->loc[1]= loc[1]; pchan->loc[2]= 
loc[2];
+               pchan->size[0]= size[0]; pchan->size[1]= size[1]; 
pchan->size[2]= size[2];
+               pchan->quat[0]= quat[0]; pchan->quat[1]= quat[1]; 
pchan->quat[2]= quat[2]; pchan->quat[3]= quat[3];
        }
        
+       pchan->flag |= POSE_ROT|POSE_LOC|POSE_SIZE;
        Py_RETURN_NONE;
 }
 
@@ -986,7 +1012,7 @@
        {"getFrame", (PyCFunction) BL_ActionActuator::sPyGetFrame, 
METH_VARARGS, (PY_METHODCHAR)GetFrame_doc},
        {"getProperty", (PyCFunction) BL_ActionActuator::sPyGetProperty, 
METH_VARARGS, (PY_METHODCHAR)GetProperty_doc},
        {"getFrameProperty", (PyCFunction) 
BL_ActionActuator::sPyGetFrameProperty, METH_VARARGS, 
(PY_METHODCHAR)GetFrameProperty_doc},
-//     {"getChannel", (PyCFunction) BL_ActionActuator::sPyGetChannel, 
METH_VARARGS},
+       {"getChannel", (PyCFunction) BL_ActionActuator::sPyGetChannel, METH_O},
        {"getType", (PyCFunction) BL_ActionActuator::sPyGetType, METH_VARARGS, 
(PY_METHODCHAR)GetType_doc},
        {"setType", (PyCFunction) BL_ActionActuator::sPySetType, METH_VARARGS, 
(PY_METHODCHAR)SetType_doc},
        {"getContinue", (PyCFunction) BL_ActionActuator::sPyGetContinue, 
METH_NOARGS, 0},       

Modified: trunk/blender/source/gameengine/Converter/BL_ActionActuator.h
===================================================================
--- trunk/blender/source/gameengine/Converter/BL_ActionActuator.h       
2009-06-16 18:02:38 UTC (rev 20936)
+++ trunk/blender/source/gameengine/Converter/BL_ActionActuator.h       
2009-06-16 18:25:48 UTC (rev 20937)
@@ -104,7 +104,7 @@
        KX_PYMETHOD_DOC(BL_ActionActuator,GetFrame);
        KX_PYMETHOD_DOC(BL_ActionActuator,GetProperty);
        KX_PYMETHOD_DOC(BL_ActionActuator,GetFrameProperty);
-//     KX_PYMETHOD(BL_ActionActuator,GetChannel);
+       KX_PYMETHOD_O(BL_ActionActuator,GetChannel);
        KX_PYMETHOD_DOC(BL_ActionActuator,GetType);
        KX_PYMETHOD_DOC(BL_ActionActuator,SetType);
        KX_PYMETHOD_NOARGS(BL_ActionActuator,GetContinue);

Modified: trunk/blender/source/gameengine/PyDoc/GameTypes.py
===================================================================
--- trunk/blender/source/gameengine/PyDoc/GameTypes.py  2009-06-16 18:02:38 UTC 
(rev 20936)
+++ trunk/blender/source/gameengine/PyDoc/GameTypes.py  2009-06-16 18:25:48 UTC 
(rev 20937)
@@ -336,17 +336,25 @@
        @ivar framePropName: The name of the property that is set to the 
current frame number.
        @type framePropName: string
        """
-       def setChannel(channel, matrix, mode = False):
+       def setChannel(channel, matrix):
                """
-               @param channel: A string specifying the name of the bone 
channel.
+               Alternative to the 2 arguments, 4 arguments (channel, matrix, 
loc, size, quat) are also supported.
+               
+               @param channel: A string specifying the name of the bone 
channel, created if missing.
                @type channel: string
                @param matrix: A 4x4 matrix specifying the overriding 
transformation
                               as an offset from the bone's rest position.
                @type matrix: list [[float]]
-               @param mode: True for armature/world space, False for bone space
-               @type mode: boolean
                """
 
+       def getChannel(channel):
+               """
+               @param channel: A string specifying the name of the bone 
channel. error raised if missing.
+               @type channel: string
+               @rtype: tuple
+               @return: (loc, size, quat)
+               """
+
 #{ Deprecated
        def setAction(action, reset = True):
                """


_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to