synched with trunk at revision 32129
[blender.git] / source / gameengine / Ketsji / KX_GameObject.cpp
index ba1bb7c5d7ce449aa8e1c7be1d87d7692a49923f..e955c344f0ab84c0b03f9b144f47f6dcdcb3d9c4 100644 (file)
@@ -15,7 +15,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,
  *
  * 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.
  *
  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
  * All rights reserved.
  * Game object wrapper
  */
 
  * Game object wrapper
  */
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #if defined(_WIN64)
 typedef unsigned __int64 uint_ptr;
 #else
 typedef unsigned long uint_ptr;
 #endif
 
 #if defined(_WIN64)
 typedef unsigned __int64 uint_ptr;
 #else
 typedef unsigned long uint_ptr;
 #endif
 
-#ifdef WIN32
+#if defined(WIN32) && !defined(FREE_WINDOWS)
 // This warning tells us about truncation of __long__ stl-generated names.
 // It can occasionally cause DevStudio to have internal compiler warnings.
 #pragma warning( disable : 4786 )     
 // This warning tells us about truncation of __long__ stl-generated names.
 // It can occasionally cause DevStudio to have internal compiler warnings.
 #pragma warning( disable : 4786 )     
@@ -71,6 +67,7 @@ typedef unsigned long uint_ptr;
 #include "SCA_ISensor.h"
 #include "SCA_IController.h"
 #include "NG_NetworkScene.h" //Needed for sendMessage()
 #include "SCA_ISensor.h"
 #include "SCA_IController.h"
 #include "NG_NetworkScene.h" //Needed for sendMessage()
+#include "KX_ObstacleSimulation.h"
 
 #include "PyObjectPlus.h" /* python stuff */
 
 
 #include "PyObjectPlus.h" /* python stuff */
 
@@ -105,6 +102,7 @@ KX_GameObject::KX_GameObject(
        m_pGraphicController(NULL),
        m_xray(false),
        m_pHitObject(NULL),
        m_pGraphicController(NULL),
        m_xray(false),
        m_pHitObject(NULL),
+       m_pObstacleSimulation(NULL),
        m_isDeformable(false)
 #ifndef DISABLE_PYTHON
        , m_attr_dict(NULL)
        m_isDeformable(false)
 #ifndef DISABLE_PYTHON
        , m_attr_dict(NULL)
@@ -152,6 +150,12 @@ KX_GameObject::~KX_GameObject()
        {
                delete m_pGraphicController;
        }
        {
                delete m_pGraphicController;
        }
+
+       if (m_pObstacleSimulation)
+       {
+               m_pObstacleSimulation->DestroyObstacleForObj(this);
+       }
+
 #ifndef DISABLE_PYTHON
        if (m_attr_dict) {
                PyDict_Clear(m_attr_dict); /* incase of circular refs or other weired cases */
 #ifndef DISABLE_PYTHON
        if (m_attr_dict) {
                PyDict_Clear(m_attr_dict); /* incase of circular refs or other weired cases */
@@ -234,7 +238,12 @@ KX_GameObject* KX_GameObject::GetParent()
 void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj, bool addToCompound, bool ghost)
 {
        // check on valid node in case a python controller holds a reference to a deleted object
 void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj, bool addToCompound, bool ghost)
 {
        // check on valid node in case a python controller holds a reference to a deleted object
-       if (obj && GetSGNode() && obj->GetSGNode() && GetSGNode()->GetSGParent() != obj->GetSGNode())
+       if (obj && 
+               GetSGNode() &&                  // object is not zombi
+               obj->GetSGNode() &&             // object is not zombi
+               GetSGNode()->GetSGParent() != obj->GetSGNode() &&       // not already parented to same object
+               !GetSGNode()->IsAncessor(obj->GetSGNode()) &&           // no parenting loop
+               this != obj)                                                                            // not the object itself
        {
                // Make sure the objects have some scale
                MT_Vector3 scale1 = NodeGetWorldScaling();
        {
                // Make sure the objects have some scale
                MT_Vector3 scale1 = NodeGetWorldScaling();
@@ -347,6 +356,14 @@ void KX_GameObject::ProcessReplica()
        m_pClient_info->m_gameobject = this;
        m_state = 0;
 
        m_pClient_info->m_gameobject = this;
        m_state = 0;
 
+       KX_Scene* scene = KX_GetActiveScene();
+       KX_ObstacleSimulation* obssimulation = scene->GetObstacleSimulation();
+       struct Object* blenderobject = GetBlenderObject();
+       if (obssimulation && (blenderobject->gameflag & OB_HASOBSTACLE))
+       {
+               obssimulation->AddObstacleForObj(this);
+       }
+
 #ifndef DISABLE_PYTHON
        if(m_attr_dict)
                m_attr_dict= PyDict_Copy(m_attr_dict);
 #ifndef DISABLE_PYTHON
        if(m_attr_dict)
                m_attr_dict= PyDict_Copy(m_attr_dict);
@@ -845,7 +862,7 @@ void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac)
        {       
                case 0: //x axis
                        ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis
        {       
                case 0: //x axis
                        ori.setValue(orimat[0][2], orimat[1][2], orimat[2][2]); //pivot axis
-                       if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) //is the vector paralell to the pivot?
+                       if (MT_abs(vect.dot(ori)) > 1.0-3.0*MT_EPSILON) //is the vector parallel to the pivot?
                                ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]); //change the pivot!
                        if (fac == 1.0) {
                                x = vect;
                                ori.setValue(orimat[0][1], orimat[1][1], orimat[2][1]); //change the pivot!
                        if (fac == 1.0) {
                                x = vect;
@@ -1244,104 +1261,133 @@ void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)
 #define MATHUTILS_VEC_CB_SCALE_GLOBAL 4
 #define MATHUTILS_VEC_CB_INERTIA_LOCAL 5
 #define MATHUTILS_VEC_CB_OBJECT_COLOR 6
 #define MATHUTILS_VEC_CB_SCALE_GLOBAL 4
 #define MATHUTILS_VEC_CB_INERTIA_LOCAL 5
 #define MATHUTILS_VEC_CB_OBJECT_COLOR 6
+#define MATHUTILS_VEC_CB_LINVEL_LOCAL 7
+#define MATHUTILS_VEC_CB_LINVEL_GLOBAL 8
+#define MATHUTILS_VEC_CB_ANGVEL_LOCAL 9
+#define MATHUTILS_VEC_CB_ANGVEL_GLOBAL 10
 
 static int mathutils_kxgameob_vector_cb_index= -1; /* index for our callbacks */
 
 
 static int mathutils_kxgameob_vector_cb_index= -1; /* index for our callbacks */
 
-static int mathutils_kxgameob_generic_check(PyObject *self_v)
+static int mathutils_kxgameob_generic_check(BaseMathObject *bmo)
 {
 {
-       KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
+       KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user);
        if(self==NULL)
                return 0;
        
        return 1;
 }
 
        if(self==NULL)
                return 0;
        
        return 1;
 }
 
-static int mathutils_kxgameob_vector_get(PyObject *self_v, int subtype, float *vec_from)
+static int mathutils_kxgameob_vector_get(BaseMathObject *bmo, int subtype)
 {
 {
-       KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
+       KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user);
        if(self==NULL)
                return 0;
        
        switch(subtype) {
                case MATHUTILS_VEC_CB_POS_LOCAL:
        if(self==NULL)
                return 0;
        
        switch(subtype) {
                case MATHUTILS_VEC_CB_POS_LOCAL:
-                       self->NodeGetLocalPosition().getValue(vec_from);
+                       self->NodeGetLocalPosition().getValue(bmo->data);
                        break;
                case MATHUTILS_VEC_CB_POS_GLOBAL:
                        break;
                case MATHUTILS_VEC_CB_POS_GLOBAL:
-                       self->NodeGetWorldPosition().getValue(vec_from);
+                       self->NodeGetWorldPosition().getValue(bmo->data);
                        break;
                case MATHUTILS_VEC_CB_SCALE_LOCAL:
                        break;
                case MATHUTILS_VEC_CB_SCALE_LOCAL:
-                       self->NodeGetLocalScaling().getValue(vec_from);
+                       self->NodeGetLocalScaling().getValue(bmo->data);
                        break;
                case MATHUTILS_VEC_CB_SCALE_GLOBAL:
                        break;
                case MATHUTILS_VEC_CB_SCALE_GLOBAL:
-                       self->NodeGetWorldScaling().getValue(vec_from);
+                       self->NodeGetWorldScaling().getValue(bmo->data);
                        break;
                case MATHUTILS_VEC_CB_INERTIA_LOCAL:
                        if(!self->GetPhysicsController()) return 0;
                        break;
                case MATHUTILS_VEC_CB_INERTIA_LOCAL:
                        if(!self->GetPhysicsController()) return 0;
-                       self->GetPhysicsController()->GetLocalInertia().getValue(vec_from);
+                       self->GetPhysicsController()->GetLocalInertia().getValue(bmo->data);
                        break;
                case MATHUTILS_VEC_CB_OBJECT_COLOR:
                        break;
                case MATHUTILS_VEC_CB_OBJECT_COLOR:
-                       self->GetObjectColor().getValue(vec_from);
+                       self->GetObjectColor().getValue(bmo->data);
+                       break;
+               case MATHUTILS_VEC_CB_LINVEL_LOCAL:
+                       if(!self->GetPhysicsController()) return 0;
+                       self->GetLinearVelocity(true).getValue(bmo->data);
+                       break;
+               case MATHUTILS_VEC_CB_LINVEL_GLOBAL:
+                       if(!self->GetPhysicsController()) return 0;
+                       self->GetLinearVelocity(false).getValue(bmo->data);
+                       break;
+               case MATHUTILS_VEC_CB_ANGVEL_LOCAL:
+                       if(!self->GetPhysicsController()) return 0;
+                       self->GetAngularVelocity(true).getValue(bmo->data);
+                       break;
+               case MATHUTILS_VEC_CB_ANGVEL_GLOBAL:
+                       if(!self->GetPhysicsController()) return 0;
+                       self->GetAngularVelocity(false).getValue(bmo->data);
                        break;
                        break;
+                       
        }
        
        return 1;
 }
 
        }
        
        return 1;
 }
 
-static int mathutils_kxgameob_vector_set(PyObject *self_v, int subtype, float *vec_to)
+static int mathutils_kxgameob_vector_set(BaseMathObject *bmo, int subtype)
 {
 {
-       KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
+       KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user);
        if(self==NULL)
                return 0;
        
        switch(subtype) {
                case MATHUTILS_VEC_CB_POS_LOCAL:
        if(self==NULL)
                return 0;
        
        switch(subtype) {
                case MATHUTILS_VEC_CB_POS_LOCAL:
-                       self->NodeSetLocalPosition(MT_Point3(vec_to));
+                       self->NodeSetLocalPosition(MT_Point3(bmo->data));
                        self->NodeUpdateGS(0.f);
                        break;
                case MATHUTILS_VEC_CB_POS_GLOBAL:
                        self->NodeUpdateGS(0.f);
                        break;
                case MATHUTILS_VEC_CB_POS_GLOBAL:
-                       self->NodeSetWorldPosition(MT_Point3(vec_to));
+                       self->NodeSetWorldPosition(MT_Point3(bmo->data));
                        self->NodeUpdateGS(0.f);
                        break;
                case MATHUTILS_VEC_CB_SCALE_LOCAL:
                        self->NodeUpdateGS(0.f);
                        break;
                case MATHUTILS_VEC_CB_SCALE_LOCAL:
-                       self->NodeSetLocalScale(MT_Point3(vec_to));
+                       self->NodeSetLocalScale(MT_Point3(bmo->data));
                        self->NodeUpdateGS(0.f);
                        break;
                case MATHUTILS_VEC_CB_SCALE_GLOBAL:
                        self->NodeUpdateGS(0.f);
                        break;
                case MATHUTILS_VEC_CB_SCALE_GLOBAL:
-                       break;
+                       PyErr_SetString(PyExc_AttributeError, "KX_GameObject.worldScale is read-only");
+                       return 0;
                case MATHUTILS_VEC_CB_INERTIA_LOCAL:
                        /* read only */
                        break;
                case MATHUTILS_VEC_CB_OBJECT_COLOR:
                case MATHUTILS_VEC_CB_INERTIA_LOCAL:
                        /* read only */
                        break;
                case MATHUTILS_VEC_CB_OBJECT_COLOR:
-                       self->SetObjectColor(MT_Vector4(vec_to));
+                       self->SetObjectColor(MT_Vector4(bmo->data));
+                       break;
+               case MATHUTILS_VEC_CB_LINVEL_LOCAL:
+                       self->setLinearVelocity(MT_Point3(bmo->data),true);
+                       break;
+               case MATHUTILS_VEC_CB_LINVEL_GLOBAL:
+                       self->setLinearVelocity(MT_Point3(bmo->data),false);
+                       break;
+               case MATHUTILS_VEC_CB_ANGVEL_LOCAL:
+                       self->setAngularVelocity(MT_Point3(bmo->data),true);
+                       break;
+               case MATHUTILS_VEC_CB_ANGVEL_GLOBAL:
+                       self->setAngularVelocity(MT_Point3(bmo->data),false);
                        break;
        }
        
        return 1;
 }
 
                        break;
        }
        
        return 1;
 }
 
-static int mathutils_kxgameob_vector_get_index(PyObject *self_v, int subtype, float *vec_from, int index)
+static int mathutils_kxgameob_vector_get_index(BaseMathObject *bmo, int subtype, int index)
 {
 {
-       float f[4];
        /* lazy, avoid repeteing the case statement */
        /* lazy, avoid repeteing the case statement */
-       if(!mathutils_kxgameob_vector_get(self_v, subtype, f))
+       if(!mathutils_kxgameob_vector_get(bmo, subtype))
                return 0;
                return 0;
-       
-       vec_from[index]= f[index];
        return 1;
 }
 
        return 1;
 }
 
-static int mathutils_kxgameob_vector_set_index(PyObject *self_v, int subtype, float *vec_to, int index)
+static int mathutils_kxgameob_vector_set_index(BaseMathObject *bmo, int subtype, int index)
 {
 {
-       float f= vec_to[index];
+       float f= bmo->data[index];
        
        /* lazy, avoid repeteing the case statement */
        
        /* lazy, avoid repeteing the case statement */
-       if(!mathutils_kxgameob_vector_get(self_v, subtype, vec_to))
+       if(!mathutils_kxgameob_vector_get(bmo, subtype))
                return 0;
        
                return 0;
        
-       vec_to[index]= f;
-       mathutils_kxgameob_vector_set(self_v, subtype, vec_to);
-       
-       return 1;
+       bmo->data[index]= f;
+       return mathutils_kxgameob_vector_set(bmo, subtype);
 }
 
 Mathutils_Callback mathutils_kxgameob_vector_cb = {
 }
 
 Mathutils_Callback mathutils_kxgameob_vector_cb = {
@@ -1358,18 +1404,18 @@ Mathutils_Callback mathutils_kxgameob_vector_cb = {
 
 static int mathutils_kxgameob_matrix_cb_index= -1; /* index for our callbacks */
 
 
 static int mathutils_kxgameob_matrix_cb_index= -1; /* index for our callbacks */
 
-static int mathutils_kxgameob_matrix_get(PyObject *self_v, int subtype, float *mat_from)
+static int mathutils_kxgameob_matrix_get(BaseMathObject *bmo, int subtype)
 {
 {
-       KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
+       KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user);
        if(self==NULL)
                return 0;
        if(self==NULL)
                return 0;
-       
+
        switch(subtype) {
                case MATHUTILS_MAT_CB_ORI_LOCAL:
        switch(subtype) {
                case MATHUTILS_MAT_CB_ORI_LOCAL:
-                       self->NodeGetLocalOrientation().getValue3x3(mat_from);
+                       self->NodeGetLocalOrientation().getValue3x3(bmo->data);
                        break;
                case MATHUTILS_MAT_CB_ORI_GLOBAL:
                        break;
                case MATHUTILS_MAT_CB_ORI_GLOBAL:
-                       self->NodeGetWorldOrientation().getValue3x3(mat_from);
+                       self->NodeGetWorldOrientation().getValue3x3(bmo->data);
                        break;
        }
        
                        break;
        }
        
@@ -1377,21 +1423,21 @@ static int mathutils_kxgameob_matrix_get(PyObject *self_v, int subtype, float *m
 }
 
 
 }
 
 
-static int mathutils_kxgameob_matrix_set(PyObject *self_v, int subtype, float *mat_to)
+static int mathutils_kxgameob_matrix_set(BaseMathObject *bmo, int subtype)
 {
 {
-       KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
+       KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(bmo->cb_user);
        if(self==NULL)
                return 0;
        
        MT_Matrix3x3 mat3x3;
        switch(subtype) {
                case MATHUTILS_MAT_CB_ORI_LOCAL:
        if(self==NULL)
                return 0;
        
        MT_Matrix3x3 mat3x3;
        switch(subtype) {
                case MATHUTILS_MAT_CB_ORI_LOCAL:
-                       mat3x3.setValue3x3(mat_to);
+                       mat3x3.setValue3x3(bmo->data);
                        self->NodeSetLocalOrientation(mat3x3);
                        self->NodeUpdateGS(0.f);
                        break;
                case MATHUTILS_MAT_CB_ORI_GLOBAL:
                        self->NodeSetLocalOrientation(mat3x3);
                        self->NodeUpdateGS(0.f);
                        break;
                case MATHUTILS_MAT_CB_ORI_GLOBAL:
-                       mat3x3.setValue3x3(mat_to);
+                       mat3x3.setValue3x3(bmo->data);
                        self->NodeSetLocalOrientation(mat3x3);
                        self->NodeUpdateGS(0.f);
                        break;
                        self->NodeSetLocalOrientation(mat3x3);
                        self->NodeUpdateGS(0.f);
                        break;
@@ -1484,6 +1530,12 @@ PyAttributeDef KX_GameObject::Attributes[] = {
        KX_PYATTRIBUTE_RW_FUNCTION("worldPosition",     KX_GameObject, pyattr_get_worldPosition,    pyattr_set_worldPosition),
        KX_PYATTRIBUTE_RW_FUNCTION("localScale",        KX_GameObject, pyattr_get_localScaling, pyattr_set_localScaling),
        KX_PYATTRIBUTE_RO_FUNCTION("worldScale",        KX_GameObject, pyattr_get_worldScaling),
        KX_PYATTRIBUTE_RW_FUNCTION("worldPosition",     KX_GameObject, pyattr_get_worldPosition,    pyattr_set_worldPosition),
        KX_PYATTRIBUTE_RW_FUNCTION("localScale",        KX_GameObject, pyattr_get_localScaling, pyattr_set_localScaling),
        KX_PYATTRIBUTE_RO_FUNCTION("worldScale",        KX_GameObject, pyattr_get_worldScaling),
+       KX_PYATTRIBUTE_RW_FUNCTION("linearVelocity", KX_GameObject, pyattr_get_localLinearVelocity, pyattr_set_worldLinearVelocity),
+       KX_PYATTRIBUTE_RW_FUNCTION("localLinearVelocity", KX_GameObject, pyattr_get_localLinearVelocity, pyattr_set_localLinearVelocity),
+       KX_PYATTRIBUTE_RW_FUNCTION("worldLinearVelocity", KX_GameObject, pyattr_get_worldLinearVelocity, pyattr_set_worldLinearVelocity),
+       KX_PYATTRIBUTE_RW_FUNCTION("angularVelocity", KX_GameObject, pyattr_get_localAngularVelocity, pyattr_set_worldAngularVelocity),
+       KX_PYATTRIBUTE_RW_FUNCTION("localAngularVelocity", KX_GameObject, pyattr_get_localAngularVelocity, pyattr_set_localAngularVelocity),
+       KX_PYATTRIBUTE_RW_FUNCTION("worldAngularVelocity", KX_GameObject, pyattr_get_worldAngularVelocity, pyattr_set_worldAngularVelocity),
        KX_PYATTRIBUTE_RO_FUNCTION("children",  KX_GameObject, pyattr_get_children),
        KX_PYATTRIBUTE_RO_FUNCTION("childrenRecursive", KX_GameObject, pyattr_get_children_recursive),
        KX_PYATTRIBUTE_RO_FUNCTION("attrDict",  KX_GameObject, pyattr_get_attrDict),
        KX_PYATTRIBUTE_RO_FUNCTION("children",  KX_GameObject, pyattr_get_children),
        KX_PYATTRIBUTE_RO_FUNCTION("childrenRecursive", KX_GameObject, pyattr_get_children_recursive),
        KX_PYATTRIBUTE_RO_FUNCTION("attrDict",  KX_GameObject, pyattr_get_attrDict),
@@ -1702,6 +1754,8 @@ PySequenceMethods KX_GameObject::Sequence = {
        NULL,           /* sq_ass_item */
        NULL,           /* sq_ass_slice */
        (objobjproc)Seq_Contains,       /* sq_contains */
        NULL,           /* sq_ass_item */
        NULL,           /* sq_ass_slice */
        (objobjproc)Seq_Contains,       /* sq_contains */
+       (binaryfunc) NULL, /* sq_inplace_concat */
+       (ssizeargfunc) NULL, /* sq_inplace_repeat */
 };
 
 PyTypeObject KX_GameObject::Type = {
 };
 
 PyTypeObject KX_GameObject::Type = {
@@ -1976,6 +2030,96 @@ int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DE
        return PY_SET_ATTR_SUCCESS;
 }
 
        return PY_SET_ATTR_SUCCESS;
 }
 
+
+PyObject* KX_GameObject::pyattr_get_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+#ifdef USE_MATHUTILS
+       return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_GLOBAL);
+#else
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       return PyObjectFrom(GetLinearVelocity(false));
+#endif
+}
+
+int KX_GameObject::pyattr_set_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       MT_Vector3 velocity;
+       if (!PyVecTo(value, velocity))
+               return PY_SET_ATTR_FAIL;
+
+       self->setLinearVelocity(velocity, false);
+
+       return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject* KX_GameObject::pyattr_get_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+#ifdef USE_MATHUTILS
+       return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_LOCAL);
+#else
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       return PyObjectFrom(GetLinearVelocity(true));
+#endif
+}
+
+int KX_GameObject::pyattr_set_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       MT_Vector3 velocity;
+       if (!PyVecTo(value, velocity))
+               return PY_SET_ATTR_FAIL;
+
+       self->setLinearVelocity(velocity, true);
+
+       return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject* KX_GameObject::pyattr_get_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+#ifdef USE_MATHUTILS
+       return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_GLOBAL);
+#else
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       return PyObjectFrom(GetAngularVelocity(false));
+#endif
+}
+
+int KX_GameObject::pyattr_set_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       MT_Vector3 velocity;
+       if (!PyVecTo(value, velocity))
+               return PY_SET_ATTR_FAIL;
+
+       self->setAngularVelocity(velocity, false);
+
+       return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject* KX_GameObject::pyattr_get_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+#ifdef USE_MATHUTILS
+       return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_LOCAL);
+#else
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       return PyObjectFrom(GetAngularVelocity(true));
+#endif
+}
+
+int KX_GameObject::pyattr_set_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       MT_Vector3 velocity;
+       if (!PyVecTo(value, velocity))
+               return PY_SET_ATTR_FAIL;
+
+       self->setAngularVelocity(velocity, true);
+
+       return PY_SET_ATTR_SUCCESS;
+}
+
+
 PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
 PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
@@ -2606,7 +2750,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
        KX_RayCast::Callback<KX_GameObject> callback(this,spc);
        KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
 
        KX_RayCast::Callback<KX_GameObject> callback(this,spc);
        KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
 
-    if (m_pHitObject)
+       if (m_pHitObject)
                return m_pHitObject->GetProxy();
        
        Py_RETURN_NONE;
                return m_pHitObject->GetProxy();
        
        Py_RETURN_NONE;