doxygen: prevent GPL license block from being parsed as doxygen comment.
[blender.git] / source / gameengine / Ketsji / KX_ObjectActuator.cpp
index 86ae082..4d17851 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * Do translation/rotation actions
  *
  * $Id$
@@ -17,7 +17,7 @@
  *
  * 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.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
 
 #include "KX_ObjectActuator.h"
 #include "KX_GameObject.h"
+#include "KX_PyMath.h" // For PyVecTo - should this include be put in PyObjectPlus?
 #include "KX_IPhysicsController.h"
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 /* ------------------------------------------------------------------------- */
 /* Native functions                                                          */
 /* ------------------------------------------------------------------------- */
@@ -44,6 +41,7 @@
 KX_ObjectActuator::
 KX_ObjectActuator(
        SCA_IObject* gameobj,
+       KX_GameObject* refobj,
        const MT_Vector3& force,
        const MT_Vector3& torque,
        const MT_Vector3& dloc,
@@ -51,10 +49,9 @@ KX_ObjectActuator(
        const MT_Vector3& linV,
        const MT_Vector3& angV,
        const short damping,
-       const KX_LocalFlags& flag,
-       PyTypeObject* T
+       const KX_LocalFlags& flag
 ) : 
-       SCA_IActuator(gameobj,T),
+       SCA_IActuator(gameobj, KX_ACT_OBJECT),
        m_force(force),
        m_torque(torque),
        m_dloc(dloc),
@@ -68,6 +65,7 @@ KX_ObjectActuator(
        m_previous_error(0.0,0.0,0.0),
        m_error_accumulator(0.0,0.0,0.0),
        m_bitLocalFlag (flag),
+       m_reference(refobj),
        m_active_combined_velocity (false),
        m_linear_damping_active(false),
        m_angular_damping_active(false)
@@ -76,10 +74,20 @@ KX_ObjectActuator(
        {
                // in servo motion, the force is local if the target velocity is local
                m_bitLocalFlag.Force = m_bitLocalFlag.LinearVelocity;
+
+               m_pid = m_torque;
        }
+       if (m_reference)
+               m_reference->RegisterActuator(this);
        UpdateFuzzyFlags();
 }
 
+KX_ObjectActuator::~KX_ObjectActuator()
+{
+       if (m_reference)
+               m_reference->UnregisterActuator(this);
+}
+
 bool KX_ObjectActuator::Update()
 {
        
@@ -128,11 +136,23 @@ bool KX_ObjectActuator::Update()
                        if (mass < MT_EPSILON)
                                return false;
                        MT_Vector3 v = parent->GetLinearVelocity(m_bitLocalFlag.LinearVelocity);
+                       if (m_reference)
+                       {
+                               const MT_Point3& mypos = parent->NodeGetWorldPosition();
+                               const MT_Point3& refpos = m_reference->NodeGetWorldPosition();
+                               MT_Point3 relpos;
+                               relpos = (mypos-refpos);
+                               MT_Vector3 vel= m_reference->GetVelocity(relpos);
+                               if (m_bitLocalFlag.LinearVelocity)
+                                       // must convert in local space
+                                       vel = parent->NodeGetWorldOrientation().transposed()*vel;
+                               v -= vel;
+                       }
                        MT_Vector3 e = m_linear_velocity - v;
                        MT_Vector3 dv = e - m_previous_error;
                        MT_Vector3 I = m_error_accumulator + e;
 
-                       m_force = m_torque.x()*e+m_torque.y()*I+m_torque.z()*dv;
+                       m_force = m_pid.x()*e+m_pid.y()*I+m_pid.z()*dv;
                        // to automatically adapt the PID coefficient to mass;
                        m_force *= mass;
                        if (m_bitLocalFlag.Torque) 
@@ -256,7 +276,34 @@ CValue* KX_ObjectActuator::GetReplica()
        return replica;
 }
 
+void KX_ObjectActuator::ProcessReplica()
+{
+       SCA_IActuator::ProcessReplica();
+       if (m_reference)
+               m_reference->RegisterActuator(this);
+}
+
+bool KX_ObjectActuator::UnlinkObject(SCA_IObject* clientobj)
+{
+       if (clientobj == (SCA_IObject*)m_reference)
+       {
+               // this object is being deleted, we cannot continue to use it as reference.
+               m_reference = NULL;
+               return true;
+       }
+       return false;
+}
 
+void KX_ObjectActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map)
+{
+       void **h_obj = (*obj_map)[m_reference];
+       if (h_obj) {
+               if (m_reference)
+                       m_reference->UnregisterActuator(this);
+               m_reference = (KX_GameObject*)(*h_obj);
+               m_reference->RegisterActuator(this);
+       }
+}
 
 /* some 'standard' utilities... */
 bool KX_ObjectActuator::isValid(KX_ObjectActuator::KX_OBJECT_ACT_VEC_TYPE type)
@@ -266,7 +313,7 @@ bool KX_ObjectActuator::isValid(KX_ObjectActuator::KX_OBJECT_ACT_VEC_TYPE type)
        return res;
 }
 
-
+#ifdef WITH_PYTHON
 
 /* ------------------------------------------------------------------------- */
 /* Python functions                                                          */
@@ -274,8 +321,7 @@ bool KX_ObjectActuator::isValid(KX_ObjectActuator::KX_OBJECT_ACT_VEC_TYPE type)
 
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_ObjectActuator::Type = {
-       PyObject_HEAD_INIT(NULL)
-       0,
+       PyVarObject_HEAD_INIT(NULL, 0)
        "KX_ObjectActuator",
        sizeof(PyObjectPlus_Proxy),
        0,
@@ -285,349 +331,311 @@ PyTypeObject KX_ObjectActuator::Type = {
        0,
        0,
        py_base_repr,
-       0,0,0,0,0,0,
-       py_base_getattro,
-       py_base_setattro,
        0,0,0,0,0,0,0,0,0,
-       Methods
-};
-
-PyParentObject KX_ObjectActuator::Parents[] = {
-       &KX_ObjectActuator::Type,
+       Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+       0,0,0,0,0,0,0,
+       Methods,
+       0,
+       0,
        &SCA_IActuator::Type,
-       &SCA_ILogicBrick::Type,
-       &CValue::Type,
-       NULL
+       0,0,0,0,0,0,
+       py_base_new
 };
 
 PyMethodDef KX_ObjectActuator::Methods[] = {
-       {"getForce", (PyCFunction) KX_ObjectActuator::sPyGetForce, METH_NOARGS},
-       {"setForce", (PyCFunction) KX_ObjectActuator::sPySetForce, METH_VARARGS},
-       {"getTorque", (PyCFunction) KX_ObjectActuator::sPyGetTorque, METH_NOARGS},
-       {"setTorque", (PyCFunction) KX_ObjectActuator::sPySetTorque, METH_VARARGS},
-       {"getDLoc", (PyCFunction) KX_ObjectActuator::sPyGetDLoc, METH_NOARGS},
-       {"setDLoc", (PyCFunction) KX_ObjectActuator::sPySetDLoc, METH_VARARGS},
-       {"getDRot", (PyCFunction) KX_ObjectActuator::sPyGetDRot, METH_NOARGS},
-       {"setDRot", (PyCFunction) KX_ObjectActuator::sPySetDRot, METH_VARARGS},
-       {"getLinearVelocity", (PyCFunction) KX_ObjectActuator::sPyGetLinearVelocity, METH_NOARGS},
-       {"setLinearVelocity", (PyCFunction) KX_ObjectActuator::sPySetLinearVelocity, METH_VARARGS},
-       {"getAngularVelocity", (PyCFunction) KX_ObjectActuator::sPyGetAngularVelocity, METH_NOARGS},
-       {"setAngularVelocity", (PyCFunction) KX_ObjectActuator::sPySetAngularVelocity, METH_VARARGS},
-       {"setDamping", (PyCFunction) KX_ObjectActuator::sPySetDamping, METH_VARARGS},
-       {"getDamping", (PyCFunction) KX_ObjectActuator::sPyGetDamping, METH_NOARGS},
-       {"setForceLimitX", (PyCFunction) KX_ObjectActuator::sPySetForceLimitX, METH_VARARGS},
-       {"getForceLimitX", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitX, METH_NOARGS},
-       {"setForceLimitY", (PyCFunction) KX_ObjectActuator::sPySetForceLimitY, METH_VARARGS},
-       {"getForceLimitY", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitY, METH_NOARGS},
-       {"setForceLimitZ", (PyCFunction) KX_ObjectActuator::sPySetForceLimitZ, METH_VARARGS},
-       {"getForceLimitZ", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitZ, METH_NOARGS},
-       {"setPID", (PyCFunction) KX_ObjectActuator::sPyGetPID, METH_NOARGS},
-       {"getPID", (PyCFunction) KX_ObjectActuator::sPySetPID, METH_VARARGS},
-
-
-
        {NULL,NULL} //Sentinel
 };
 
 PyAttributeDef KX_ObjectActuator::Attributes[] = {
-       //KX_PYATTRIBUTE_TODO("force"),
-       //KX_PYATTRIBUTE_TODO("torque"),
-       //KX_PYATTRIBUTE_TODO("dLoc"),
-       //KX_PYATTRIBUTE_TODO("dRot"),
-       //KX_PYATTRIBUTE_TODO("linV"),
-       //KX_PYATTRIBUTE_TODO("angV"),
-       //KX_PYATTRIBUTE_TODO("damping"),
-       //KX_PYATTRIBUTE_TODO("forceLimitX"),
-       //KX_PYATTRIBUTE_TODO("forceLimitY"),
-       //KX_PYATTRIBUTE_TODO("forceLimitZ"),
-       //KX_PYATTRIBUTE_TODO("pid"),
+       KX_PYATTRIBUTE_VECTOR_RW_CHECK("force", -1000, 1000, false, KX_ObjectActuator, m_force, PyUpdateFuzzyFlags),
+       KX_PYATTRIBUTE_BOOL_RW("useLocalForce", KX_ObjectActuator, m_bitLocalFlag.Force),
+       KX_PYATTRIBUTE_VECTOR_RW_CHECK("torque", -1000, 1000, false, KX_ObjectActuator, m_torque, PyUpdateFuzzyFlags),
+       KX_PYATTRIBUTE_BOOL_RW("useLocalTorque", KX_ObjectActuator, m_bitLocalFlag.Torque),
+       KX_PYATTRIBUTE_VECTOR_RW_CHECK("dLoc", -1000, 1000, false, KX_ObjectActuator, m_dloc, PyUpdateFuzzyFlags),
+       KX_PYATTRIBUTE_BOOL_RW("useLocalDLoc", KX_ObjectActuator, m_bitLocalFlag.DLoc),
+       KX_PYATTRIBUTE_VECTOR_RW_CHECK("dRot", -1000, 1000, false, KX_ObjectActuator, m_drot, PyUpdateFuzzyFlags),
+       KX_PYATTRIBUTE_BOOL_RW("useLocalDRot", KX_ObjectActuator, m_bitLocalFlag.DRot),
+#ifdef USE_MATHUTILS
+       KX_PYATTRIBUTE_RW_FUNCTION("linV", KX_ObjectActuator, pyattr_get_linV, pyattr_set_linV),
+       KX_PYATTRIBUTE_RW_FUNCTION("angV", KX_ObjectActuator, pyattr_get_angV, pyattr_set_angV),
+#else
+       KX_PYATTRIBUTE_VECTOR_RW_CHECK("linV", -1000, 1000, false, KX_ObjectActuator, m_linear_velocity, PyUpdateFuzzyFlags),
+       KX_PYATTRIBUTE_VECTOR_RW_CHECK("angV", -1000, 1000, false, KX_ObjectActuator, m_angular_velocity, PyUpdateFuzzyFlags),
+#endif
+       KX_PYATTRIBUTE_BOOL_RW("useLocalLinV", KX_ObjectActuator, m_bitLocalFlag.LinearVelocity),
+       KX_PYATTRIBUTE_BOOL_RW("useLocalAngV", KX_ObjectActuator, m_bitLocalFlag.AngularVelocity),
+       KX_PYATTRIBUTE_SHORT_RW("damping", 0, 1000, false, KX_ObjectActuator, m_damping),
+       KX_PYATTRIBUTE_RW_FUNCTION("forceLimitX", KX_ObjectActuator, pyattr_get_forceLimitX, pyattr_set_forceLimitX),
+       KX_PYATTRIBUTE_RW_FUNCTION("forceLimitY", KX_ObjectActuator, pyattr_get_forceLimitY, pyattr_set_forceLimitY),
+       KX_PYATTRIBUTE_RW_FUNCTION("forceLimitZ", KX_ObjectActuator, pyattr_get_forceLimitZ, pyattr_set_forceLimitZ),
+       KX_PYATTRIBUTE_VECTOR_RW_CHECK("pid", -100, 200, true, KX_ObjectActuator, m_pid, PyCheckPid),
+       KX_PYATTRIBUTE_RW_FUNCTION("reference", KX_ObjectActuator,pyattr_get_reference,pyattr_set_reference),
        { NULL }        //Sentinel
 };
 
-PyObject* KX_ObjectActuator::py_getattro(PyObject *attr) {
-       py_getattro_up(SCA_IActuator);
-};
+/* Attribute get/set functions */
 
-PyObject* KX_ObjectActuator::py_getattro_dict() {
-       py_getattro_dict_up(SCA_IActuator);
-}
+#ifdef USE_MATHUTILS
 
-/* 1. set ------------------------------------------------------------------ */
-/* Removed! */
+/* These require an SGNode */
+#define MATHUTILS_VEC_CB_LINV 1
+#define MATHUTILS_VEC_CB_ANGV 2
 
-/* 2. getForce                                                               */
-PyObject* KX_ObjectActuator::PyGetForce()
+static int mathutils_kxobactu_vector_cb_index= -1; /* index for our callbacks */
+
+static int mathutils_obactu_generic_check(BaseMathObject *bmo)
 {
-       PyObject *retVal = PyList_New(4);
+       KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(bmo->cb_user);
+       if(self==NULL)
+               return 0;
 
-       PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_force[0]));
-       PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_force[1]));
-       PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_force[2]));
-       PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.Force));
-       
-       return retVal;
+       return 1;
 }
-/* 3. setForce                                                               */
-PyObject* KX_ObjectActuator::PySetForce(PyObject* args)
+
+static int mathutils_obactu_vector_get(BaseMathObject *bmo, int subtype)
 {
-       float vecArg[3];
-       int bToggle = 0;
-       if (!PyArg_ParseTuple(args, "fffi:setForce", &vecArg[0], &vecArg[1], 
-                                                 &vecArg[2], &bToggle)) {
-               return NULL;
+       KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(bmo->cb_user);
+       if(self==NULL)
+               return 0;
+
+       switch(subtype) {
+               case MATHUTILS_VEC_CB_LINV:
+                       self->m_linear_velocity.getValue(bmo->data);
+                       break;
+               case MATHUTILS_VEC_CB_ANGV:
+                       self->m_angular_velocity.getValue(bmo->data);
+                       break;
        }
-       m_force.setValue(vecArg);
-       m_bitLocalFlag.Force = PyArgToBool(bToggle);
-       UpdateFuzzyFlags();
-       Py_RETURN_NONE;
+
+       return 1;
 }
 
-/* 4. getTorque                                                              */
-PyObject* KX_ObjectActuator::PyGetTorque()
+static int mathutils_obactu_vector_set(BaseMathObject *bmo, int subtype)
 {
-       PyObject *retVal = PyList_New(4);
+       KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>BGE_PROXY_REF(bmo->cb_user);
+       if(self==NULL)
+               return 0;
+
+       switch(subtype) {
+               case MATHUTILS_VEC_CB_LINV:
+                       self->m_linear_velocity.setValue(bmo->data);
+                       break;
+               case MATHUTILS_VEC_CB_ANGV:
+                       self->m_angular_velocity.setValue(bmo->data);
+                       break;
+       }
 
-       PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_torque[0]));
-       PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_torque[1]));
-       PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_torque[2]));
-       PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.Torque));
-       
-       return retVal;
+       return 1;
 }
-/* 5. setTorque                                                              */
-PyObject* KX_ObjectActuator::PySetTorque(PyObject* args)
+
+static int mathutils_obactu_vector_get_index(BaseMathObject *bmo, int subtype, int index)
 {
-       float vecArg[3];
-       int bToggle = 0;
-       if (!PyArg_ParseTuple(args, "fffi:setTorque", &vecArg[0], &vecArg[1], 
-                                                 &vecArg[2], &bToggle)) {
-               return NULL;
-       }
-       m_torque.setValue(vecArg);
-       m_bitLocalFlag.Torque = PyArgToBool(bToggle);
-       UpdateFuzzyFlags();
-       Py_RETURN_NONE;
+       /* lazy, avoid repeteing the case statement */
+       if(!mathutils_obactu_vector_get(bmo, subtype))
+               return 0;
+       return 1;
 }
 
-/* 6. getDLoc                                                                */
-PyObject* KX_ObjectActuator::PyGetDLoc()
+static int mathutils_obactu_vector_set_index(BaseMathObject *bmo, int subtype, int index)
 {
-       PyObject *retVal = PyList_New(4);
+       float f= bmo->data[index];
 
-       PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_dloc[0]));
-       PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
-       PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_dloc[2]));
-       PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.DLoc));
-       
-       return retVal;
+       /* lazy, avoid repeteing the case statement */
+       if(!mathutils_obactu_vector_get(bmo, subtype))
+               return 0;
+
+       bmo->data[index]= f;
+       return mathutils_obactu_vector_set(bmo, subtype);
 }
-/* 7. setDLoc                                                                */
-PyObject* KX_ObjectActuator::PySetDLoc(PyObject* args)
+
+Mathutils_Callback mathutils_obactu_vector_cb = {
+       mathutils_obactu_generic_check,
+       mathutils_obactu_vector_get,
+       mathutils_obactu_vector_set,
+       mathutils_obactu_vector_get_index,
+       mathutils_obactu_vector_set_index
+};
+
+PyObject* KX_ObjectActuator::pyattr_get_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
-       float vecArg[3];
-       int bToggle = 0;
-       if(!PyArg_ParseTuple(args, "fffi:setDLoc", &vecArg[0], &vecArg[1], 
-                                                &vecArg[2], &bToggle)) {
-               return NULL;
-       }
-       m_dloc.setValue(vecArg);
-       m_bitLocalFlag.DLoc = PyArgToBool(bToggle);
-       UpdateFuzzyFlags();
-       Py_RETURN_NONE;
+       return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV);
 }
 
-/* 8. getDRot                                                                */
-PyObject* KX_ObjectActuator::PyGetDRot()
+int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
-       PyObject *retVal = PyList_New(4);
+       KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>(self_v);
+       if (!PyVecTo(value, self->m_linear_velocity))
+               return PY_SET_ATTR_FAIL;
 
-       PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[0]));
-       PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_drot[1]));
-       PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_drot[2]));
-       PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.DRot));
-       
-       return retVal;
+       self->UpdateFuzzyFlags();
+
+       return PY_SET_ATTR_SUCCESS;
 }
-/* 9. setDRot                                                                */
-PyObject* KX_ObjectActuator::PySetDRot(PyObject* args)
+
+PyObject* KX_ObjectActuator::pyattr_get_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
-       float vecArg[3];
-       int bToggle = 0;
-       if (!PyArg_ParseTuple(args, "fffi:setDRot", &vecArg[0], &vecArg[1], 
-                                                 &vecArg[2], &bToggle)) {
-               return NULL;
-       }
-       m_drot.setValue(vecArg);
-       m_bitLocalFlag.DRot = PyArgToBool(bToggle);
-       UpdateFuzzyFlags();
-       Py_RETURN_NONE;
+       return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV);
 }
 
-/* 10. getLinearVelocity                                                 */
-PyObject* KX_ObjectActuator::PyGetLinearVelocity() {
-       PyObject *retVal = PyList_New(4);
+int KX_ObjectActuator::pyattr_set_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+       KX_ObjectActuator* self= static_cast<KX_ObjectActuator*>(self_v);
+       if (!PyVecTo(value, self->m_angular_velocity))
+               return PY_SET_ATTR_FAIL;
 
-       PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0]));
-       PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1]));
-       PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2]));
-       PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.LinearVelocity));
-       
-       return retVal;
-}
+       self->UpdateFuzzyFlags();
 
-/* 11. setLinearVelocity                                                 */
-PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* args) {
-       float vecArg[3];
-       int bToggle = 0;
-       if (!PyArg_ParseTuple(args, "fffi:setLinearVelocity", &vecArg[0], &vecArg[1], 
-                                                 &vecArg[2], &bToggle)) {
-               return NULL;
-       }
-       m_linear_velocity.setValue(vecArg);
-       m_bitLocalFlag.LinearVelocity = PyArgToBool(bToggle);
-       UpdateFuzzyFlags();
-       Py_RETURN_NONE;
+       return PY_SET_ATTR_SUCCESS;
 }
 
 
-/* 12. getAngularVelocity                                                */
-PyObject* KX_ObjectActuator::PyGetAngularVelocity() {
-       PyObject *retVal = PyList_New(4);
-
-       PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0]));
-       PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1]));
-       PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2]));
-       PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.AngularVelocity));
-       
-       return retVal;
-}
-/* 13. setAngularVelocity                                                */
-PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* args) {
-       float vecArg[3];
-       int bToggle = 0;
-       if (!PyArg_ParseTuple(args, "fffi:setAngularVelocity", &vecArg[0], &vecArg[1], 
-                                                 &vecArg[2], &bToggle)) {
-               return NULL;
-       }
-       m_angular_velocity.setValue(vecArg);
-       m_bitLocalFlag.AngularVelocity = PyArgToBool(bToggle);
-       UpdateFuzzyFlags();
-       Py_RETURN_NONE;
+void KX_ObjectActuator_Mathutils_Callback_Init(void)
+{
+       // register mathutils callbacks, ok to run more then once.
+       mathutils_kxobactu_vector_cb_index= Mathutils_RegisterCallback(&mathutils_obactu_vector_cb);
 }
 
-/* 13. setDamping                                                */
-PyObject* KX_ObjectActuator::PySetDamping(PyObject* args) {
-       int damping = 0;
-       if (!PyArg_ParseTuple(args, "i:setDamping", &damping) || damping < 0 || damping > 1000) {
-               return NULL;
-       }
-       m_damping = damping;
-       Py_RETURN_NONE;
-}
+#endif // USE_MATHUTILS
 
-/* 13. getVelocityDamping                                                */
-PyObject* KX_ObjectActuator::PyGetDamping() {
-       return Py_BuildValue("i",m_damping);
-}
-/* 6. getForceLimitX                                                                */
-PyObject* KX_ObjectActuator::PyGetForceLimitX()
+PyObject* KX_ObjectActuator::pyattr_get_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
+       KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
        PyObject *retVal = PyList_New(3);
 
-       PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[0]));
-       PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[0]));
-       PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.Torque));
+       PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(self->m_drot[0]));
+       PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(self->m_dloc[0]));
+       PyList_SET_ITEM(retVal, 2, PyBool_FromLong(self->m_bitLocalFlag.Torque));
        
        return retVal;
 }
-/* 7. setForceLimitX                                                         */
-PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* args)
+
+int KX_ObjectActuator::pyattr_set_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
-       float vecArg[2];
-       int bToggle = 0;
-       if(!PyArg_ParseTuple(args, "ffi:setForceLimitX", &vecArg[0], &vecArg[1], &bToggle)) {
-               return NULL;
+       KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
+
+       PyObject* seq = PySequence_Fast(value, "");
+       if (seq && PySequence_Fast_GET_SIZE(seq) == 3)
+       {
+               self->m_drot[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
+               self->m_dloc[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1));
+               self->m_bitLocalFlag.Torque = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0);
+
+               if (!PyErr_Occurred())
+               {
+                       Py_DECREF(seq);
+                       return PY_SET_ATTR_SUCCESS;
+               }
        }
-       m_drot[0] = vecArg[0];
-       m_dloc[0] = vecArg[1];
-       m_bitLocalFlag.Torque = PyArgToBool(bToggle);
-       Py_RETURN_NONE;
+
+       Py_XDECREF(seq);
+
+       PyErr_SetString(PyExc_ValueError, "expected a sequence of 2 floats and a bool");
+       return PY_SET_ATTR_FAIL;
 }
 
-/* 6. getForceLimitY                                                                */
-PyObject* KX_ObjectActuator::PyGetForceLimitY()
+PyObject* KX_ObjectActuator::pyattr_get_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
+       KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
        PyObject *retVal = PyList_New(3);
 
-       PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[1]));
-       PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[1]));
-       PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.DLoc));
+       PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(self->m_drot[1]));
+       PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(self->m_dloc[1]));
+       PyList_SET_ITEM(retVal, 2, PyBool_FromLong(self->m_bitLocalFlag.DLoc));
        
        return retVal;
 }
-/* 7. setForceLimitY                                                                */
-PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* args)
+
+int    KX_ObjectActuator::pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
-       float vecArg[2];
-       int bToggle = 0;
-       if(!PyArg_ParseTuple(args, "ffi:setForceLimitY", &vecArg[0], &vecArg[1], &bToggle)) {
-               return NULL;
+       KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
+
+       PyObject* seq = PySequence_Fast(value, "");
+       if (seq && PySequence_Fast_GET_SIZE(seq) == 3)
+       {
+               self->m_drot[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
+               self->m_dloc[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1));
+               self->m_bitLocalFlag.DLoc = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0);
+
+               if (!PyErr_Occurred())
+               {
+                       Py_DECREF(seq);
+                       return PY_SET_ATTR_SUCCESS;
+               }
        }
-       m_drot[1] = vecArg[0];
-       m_dloc[1] = vecArg[1];
-       m_bitLocalFlag.DLoc = PyArgToBool(bToggle);
-       Py_RETURN_NONE;
+
+       Py_XDECREF(seq);
+
+       PyErr_SetString(PyExc_ValueError, "expected a sequence of 2 floats and a bool");
+       return PY_SET_ATTR_FAIL;
 }
 
-/* 6. getForceLimitZ                                                                */
-PyObject* KX_ObjectActuator::PyGetForceLimitZ()
+PyObject* KX_ObjectActuator::pyattr_get_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
+       KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
        PyObject *retVal = PyList_New(3);
 
-       PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[2]));
-       PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[2]));
-       PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.DRot));
+       PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(self->m_drot[2]));
+       PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(self->m_dloc[2]));
+       PyList_SET_ITEM(retVal, 2, PyBool_FromLong(self->m_bitLocalFlag.DRot));
        
        return retVal;
 }
-/* 7. setForceLimitZ                                                                */
-PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* args)
+
+int    KX_ObjectActuator::pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
-       float vecArg[2];
-       int bToggle = 0;
-       if(!PyArg_ParseTuple(args, "ffi:setForceLimitZ", &vecArg[0], &vecArg[1], &bToggle)) {
-               return NULL;
+       KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v);
+
+       PyObject* seq = PySequence_Fast(value, "");
+       if (seq && PySequence_Fast_GET_SIZE(seq) == 3)
+       {
+               self->m_drot[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0));
+               self->m_dloc[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1));
+               self->m_bitLocalFlag.DRot = (PyLong_AsSsize_t(PySequence_Fast_GET_ITEM(value, 2)) != 0);
+
+               if (!PyErr_Occurred())
+               {
+                       Py_DECREF(seq);
+                       return PY_SET_ATTR_SUCCESS;
+               }
        }
-       m_drot[2] = vecArg[0];
-       m_dloc[2] = vecArg[1];
-       m_bitLocalFlag.DRot = PyArgToBool(bToggle);
-       Py_RETURN_NONE;
+
+       Py_XDECREF(seq);
+
+       PyErr_SetString(PyExc_ValueError, "expected a sequence of 2 floats and a bool");
+       return PY_SET_ATTR_FAIL;
 }
 
-/* 4. getPID                                                              */
-PyObject* KX_ObjectActuator::PyGetPID()
+PyObject* KX_ObjectActuator::pyattr_get_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
 {
-       PyObject *retVal = PyList_New(3);
-
-       PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_torque[0]));
-       PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_torque[1]));
-       PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_torque[2]));
+       KX_ObjectActuator* actuator = static_cast<KX_ObjectActuator*>(self);
+       if (!actuator->m_reference)
+               Py_RETURN_NONE;
        
-       return retVal;
+       return actuator->m_reference->GetProxy();
 }
-/* 5. setPID                                                              */
-PyObject* KX_ObjectActuator::PySetPID(PyObject* args)
+
+int KX_ObjectActuator::pyattr_set_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
-       float vecArg[3];
-       if (!PyArg_ParseTuple(args, "fff:setPID", &vecArg[0], &vecArg[1], &vecArg[2])) {
-               return NULL;
+       KX_ObjectActuator* actuator = static_cast<KX_ObjectActuator*>(self);
+       KX_GameObject *refOb;
+       
+       if (!ConvertPythonToGameObject(value, &refOb, true, "actu.reference = value: KX_ObjectActuator"))
+               return PY_SET_ATTR_FAIL;
+       
+       if (actuator->m_reference)
+               actuator->m_reference->UnregisterActuator(actuator);
+       
+       if(refOb==NULL) {
+               actuator->m_reference= NULL;
+       }
+       else {  
+               actuator->m_reference = refOb;
+               actuator->m_reference->RegisterActuator(actuator);
        }
-       m_torque.setValue(vecArg);
-       Py_RETURN_NONE;
+       
+       return PY_SET_ATTR_SUCCESS;
 }
 
-
-
-
+#endif // WITH_PYTHON
 
 /* eof */