small merge needed for testing new animsys in 2.5 BGE, mixing own changes with merge...
[blender.git] / source / gameengine / Converter / BL_ActionActuator.cpp
index 646a65d347bcda63c625ce44db02a2cf0e1bb734..0c7b99df3879cf21914e2126f119f9f716ce1718 100644 (file)
@@ -43,6 +43,7 @@
 #include "BKE_action.h"
 #include "DNA_action_types.h"
 #include "DNA_armature_types.h"
+#include "DNA_scene_types.h"
 #include "MEM_guardedalloc.h"
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"
@@ -50,7 +51,7 @@
 #include "BKE_utildefines.h"
 #include "FloatValue.h"
 #include "PyObjectPlus.h"
-#include "blendef.h"
+#include "KX_PyMath.h"
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -156,16 +157,9 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
        // maybe there are events for us in the queue !
        if (frame)
        {
-               for (vector<CValue*>::iterator i=m_events.begin(); !(i==m_events.end());i++)
-               {
-                       if ((*i)->GetNumber() == 0.0f)
-                               bNegativeEvent = true;
-                       else
-                               bPositiveEvent= true;
-                       (*i)->Release();
-               
-               }
-               m_events.clear();
+               bNegativeEvent = m_negevent;
+               bPositiveEvent = m_posevent;
+               RemoveAllEvents();
                
                if (bPositiveEvent)
                        m_flag |= ACT_FLAG_ACTIVE;
@@ -368,13 +362,12 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
                        obj->GetPose(&m_pose);
                        
                        /* Override the necessary channels with ones from the action */
-                       extract_pose_from_action(m_pose, m_action, m_localtime);
+                       // XXX extract_pose_from_action(m_pose, m_action, m_localtime);
 
                        /* 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
@@ -388,7 +381,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
                                
                                /* Find percentages */
                                newweight = (m_blendframe/(float)m_blendin);
-                               blend_poses(m_pose, m_blendpose, 1.0 - newweight, ACTSTRIPMODE_BLEND);
+                               // XXX blend_poses(m_pose, m_blendpose, 1.0 - newweight, ACTSTRIPMODE_BLEND);
 
                                /* Increment current blending percentage */
                                m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate();
@@ -774,22 +767,55 @@ PyObject* BL_ActionActuator::PySetFrameProperty(PyObject* args,
        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))
-       {
-               m_propname = string;
+       if (!string) {
+               PyErr_SetString(PyExc_TypeError, "expected a single string");
+               return NULL;
        }
-       else {
+       
+       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))  )
+       {
+               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[] =
@@ -864,76 +890,69 @@ KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel,
 "\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 */
-       
-       if (!PyArg_ParseTuple(args,"sO|i:setChannel", &string, &pylist, &mode))
-               return NULL;
+       PyObject *pymat= NULL;
+       PyObject *pyloc= NULL, *pysize= NULL, *pyquat= NULL;
+       bPoseChannel *pchan;
        
-       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();
-                                       
-                               }
-                       }
-               }
-               else
-               {
-                       error = true;
-               }
+       if(PyTuple_Size(args)==2) {
+               if (!PyArg_ParseTuple(args,"sO:setChannel", &string, &pymat)) // matrix
+                       return NULL;
        }
-       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
-               {
-                       error = true;
-               }
+       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 (!error)
-       {
-
-/*     DO IT HERE */
-               bPoseChannel *pchan= verify_pose_channel(m_userpose, string);
-
-               Mat4ToQuat(matrix, pchan->quat);
-               Mat4ToSize(matrix, pchan->size);
+       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);
+               }
+               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 {
+               MT_Vector3 loc;
+               MT_Vector3 size;
+               MT_Vector4 quat;
                
-               pchan->flag |= POSE_ROT|POSE_LOC|POSE_SIZE;
-
-               if (!m_userpose){
-                       m_userpose = (bPose*)MEM_callocN(sizeof(bPose), "userPose");
+               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);
                }
+               pchan= verify_pose_channel(m_userpose, string);
+               
+               // 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;
 }
 
@@ -993,7 +1012,7 @@ PyMethodDef BL_ActionActuator::Methods[] = {
        {"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},       
@@ -1004,17 +1023,17 @@ PyMethodDef BL_ActionActuator::Methods[] = {
 };
 
 PyAttributeDef BL_ActionActuator::Attributes[] = {
-       KX_PYATTRIBUTE_FLOAT_RW("start", 0, MAXFRAMEF, BL_ActionActuator, m_startframe),
-       KX_PYATTRIBUTE_FLOAT_RW("end", 0, MAXFRAMEF, BL_ActionActuator, m_endframe),
-       KX_PYATTRIBUTE_FLOAT_RW("blendin", 0, MAXFRAMEF, BL_ActionActuator, m_blendin),
+       KX_PYATTRIBUTE_FLOAT_RW("frameStart", 0, MAXFRAMEF, BL_ActionActuator, m_startframe),
+       KX_PYATTRIBUTE_FLOAT_RW("frameEnd", 0, MAXFRAMEF, BL_ActionActuator, m_endframe),
+       KX_PYATTRIBUTE_FLOAT_RW("blendIn", 0, MAXFRAMEF, BL_ActionActuator, m_blendin),
        KX_PYATTRIBUTE_RW_FUNCTION("action", BL_ActionActuator, pyattr_get_action, pyattr_set_action),
        KX_PYATTRIBUTE_SHORT_RW("priority", 0, 100, false, BL_ActionActuator, m_priority),
        KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ActionActuator, m_localtime, CheckFrame),
-       KX_PYATTRIBUTE_STRING_RW("property", 0, 31, false, BL_ActionActuator, m_propname),
-       KX_PYATTRIBUTE_STRING_RW("frameProperty", 0, 31, false, BL_ActionActuator, m_framepropname),
+       KX_PYATTRIBUTE_STRING_RW("propName", 0, 31, false, BL_ActionActuator, m_propname),
+       KX_PYATTRIBUTE_STRING_RW("framePropName", 0, 31, false, BL_ActionActuator, m_framepropname),
        KX_PYATTRIBUTE_BOOL_RW("useContinue", BL_ActionActuator, m_end_reset),
        KX_PYATTRIBUTE_FLOAT_RW_CHECK("blendTime", 0, MAXFRAMEF, BL_ActionActuator, m_blendframe, CheckBlendTime),
-       KX_PYATTRIBUTE_SHORT_RW_CHECK("type",0,100,false,BL_ActionActuator,m_playtype,CheckType),
+       KX_PYATTRIBUTE_SHORT_RW_CHECK("mode",0,100,false,BL_ActionActuator,m_playtype,CheckType),
        { NULL }        //Sentinel
 };
 
@@ -1044,7 +1063,7 @@ int BL_ActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF
        if (!PyString_Check(value))
        {
                PyErr_SetString(PyExc_ValueError, "actuator.action = val: Action Actuator, expected the string name of the action");
-               return -1;
+               return PY_SET_ATTR_FAIL;
        }
 
        bAction *action= NULL;
@@ -1056,11 +1075,11 @@ int BL_ActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF
                if (!action)
                {
                        PyErr_SetString(PyExc_ValueError, "actuator.action = val: Action Actuator, action not found!");
-                       return 1;
+                       return PY_SET_ATTR_FAIL;
                }
        }
        
        self->SetAction(action);
-       return 0;
+       return PY_SET_ATTR_SUCCESS;
 
 }