synched with trunk at revision 32129
[blender.git] / source / gameengine / Ketsji / KX_GameObject.cpp
index bf80eec36d93a9637df87e5e9e6e91b967f8cc07..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,
- * 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.
  * 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
 
-#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 )     
@@ -66,10 +62,12 @@ typedef unsigned long uint_ptr;
 #include "KX_PythonInit.h"
 #include "KX_PyMath.h"
 #include "KX_PythonSeq.h"
+#include "KX_ConvertPhysicsObject.h"
 #include "SCA_IActuator.h"
 #include "SCA_ISensor.h"
 #include "SCA_IController.h"
 #include "NG_NetworkScene.h" //Needed for sendMessage()
+#include "KX_ObstacleSimulation.h"
 
 #include "PyObjectPlus.h" /* python stuff */
 
@@ -78,6 +76,8 @@ typedef unsigned long uint_ptr;
 
 #include "KX_SG_NodeRelationships.h"
 
+#include "BLI_math.h"
+
 static MT_Point3 dummy_point= MT_Point3(0.0, 0.0, 0.0);
 static MT_Vector3 dummy_scaling = MT_Vector3(1.0, 1.0, 1.0);
 static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3(  1.0, 0.0, 0.0,
@@ -100,11 +100,13 @@ KX_GameObject::KX_GameObject(
        m_bOccluder(false),
        m_pPhysicsController1(NULL),
        m_pGraphicController(NULL),
-       m_pPhysicsEnvironment(NULL),
        m_xray(false),
        m_pHitObject(NULL),
-       m_isDeformable(false),
-       m_attr_dict(NULL)
+       m_pObstacleSimulation(NULL),
+       m_isDeformable(false)
+#ifndef DISABLE_PYTHON
+       , m_attr_dict(NULL)
+#endif
 {
        m_ignore_activity_culling = false;
        m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR);
@@ -141,16 +143,25 @@ KX_GameObject::~KX_GameObject()
                        (*contit)->ClearObject();
                }
                m_pSGNode->SetSGClientObject(NULL);
+
+               /* m_pSGNode is freed in KX_Scene::RemoveNodeDestructObject */
        }
        if (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 */
                Py_DECREF(m_attr_dict);
        }
+#endif // DISABLE_PYTHON
 }
 
 KX_GameObject* KX_GameObject::GetClientObject(KX_ClientObjectInfo* info)
@@ -227,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
-       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();
@@ -339,8 +355,19 @@ void KX_GameObject::ProcessReplica()
        m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
        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);
+#endif
                
 }
 
@@ -454,6 +481,22 @@ double*    KX_GameObject::GetOpenGLMatrix()
        return fl;
 }
 
+void KX_GameObject::UpdateBlenderObjectMatrix(Object* blendobj)
+{
+       if (!blendobj)
+               blendobj = m_pBlenderObject;
+       if (blendobj) {
+               const MT_Matrix3x3& rot = NodeGetWorldOrientation();
+               const MT_Vector3& scale = NodeGetWorldScaling();
+               const MT_Vector3& pos = NodeGetWorldPosition();
+               rot.getValue(blendobj->obmat[0]);
+               pos.getValue(blendobj->obmat[3]);
+               mul_v3_fl(blendobj->obmat[0], scale[0]);
+               mul_v3_fl(blendobj->obmat[1], scale[1]);
+               mul_v3_fl(blendobj->obmat[2], scale[2]);
+       }
+}
+
 void KX_GameObject::AddMeshUser()
 {
        for (size_t i=0;i<m_meshes.size();i++)
@@ -464,7 +507,7 @@ void KX_GameObject::AddMeshUser()
        double* fl = GetOpenGLMatrixPtr()->getPointer();
 
        SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
-       RAS_MeshSlot* ms;
+//     RAS_MeshSlot* ms;
        for(mit.begin(); !mit.end(); ++mit)
        {
                (*mit)->m_OpenGLMatrix = fl;
@@ -785,6 +828,11 @@ void KX_GameObject::SetObjectColor(const MT_Vector4& rgbavec)
        m_objectColor = rgbavec;
 }
 
+const MT_Vector4& KX_GameObject::GetObjectColor()
+{
+       return m_objectColor;
+}
+
 void KX_GameObject::AlignAxisToVect(const MT_Vector3& dir, int axis, float fac)
 {
        MT_Matrix3x3 orimat;
@@ -814,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
-                       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;
@@ -1182,6 +1230,28 @@ CListValue* KX_GameObject::GetChildrenRecursive()
        return list;
 }
 
+/* ---------------------------------------------------------------------
+ * Some stuff taken from the header
+ * --------------------------------------------------------------------- */
+void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)
+{
+       // we will relink the sensors and actuators that use object references
+       // if the object is part of the replicated hierarchy, use the new
+       // object reference instead
+       SCA_SensorList& sensorlist = GetSensors();
+       SCA_SensorList::iterator sit;
+       for (sit=sensorlist.begin(); sit != sensorlist.end(); sit++)
+       {
+               (*sit)->Relink(map_parameter);
+       }
+       SCA_ActuatorList& actuatorlist = GetActuators();
+       SCA_ActuatorList::iterator ait;
+       for (ait=actuatorlist.begin(); ait != actuatorlist.end(); ait++)
+       {
+               (*ait)->Relink(map_parameter);
+       }
+}
+
 #ifdef USE_MATHUTILS
 
 /* These require an SGNode */
@@ -1190,98 +1260,134 @@ CListValue* KX_GameObject::GetChildrenRecursive()
 #define MATHUTILS_VEC_CB_SCALE_LOCAL 3
 #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_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;
 }
 
-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:
-                       self->NodeGetLocalPosition().getValue(vec_from);
+                       self->NodeGetLocalPosition().getValue(bmo->data);
                        break;
                case MATHUTILS_VEC_CB_POS_GLOBAL:
-                       self->NodeGetWorldPosition().getValue(vec_from);
+                       self->NodeGetWorldPosition().getValue(bmo->data);
                        break;
                case MATHUTILS_VEC_CB_SCALE_LOCAL:
-                       self->NodeGetLocalScaling().getValue(vec_from);
+                       self->NodeGetLocalScaling().getValue(bmo->data);
                        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;
-                       self->GetPhysicsController()->GetLocalInertia().getValue(vec_from);
+                       self->GetPhysicsController()->GetLocalInertia().getValue(bmo->data);
+                       break;
+               case MATHUTILS_VEC_CB_OBJECT_COLOR:
+                       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;
+                       
        }
        
        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:
-                       self->NodeSetLocalPosition(MT_Point3(vec_to));
+                       self->NodeSetLocalPosition(MT_Point3(bmo->data));
                        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->NodeSetLocalScale(MT_Point3(vec_to));
+                       self->NodeSetLocalScale(MT_Point3(bmo->data));
                        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:
+                       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;
 }
 
-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 */
-       if(!mathutils_kxgameob_vector_get(self_v, subtype, f))
+       if(!mathutils_kxgameob_vector_get(bmo, subtype))
                return 0;
-       
-       vec_from[index]= f[index];
        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 */
-       if(!mathutils_kxgameob_vector_get(self_v, subtype, vec_to))
+       if(!mathutils_kxgameob_vector_get(bmo, subtype))
                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 = {
@@ -1298,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_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;
-       
+
        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:
-                       self->NodeGetWorldOrientation().getValue3x3(mat_from);
+                       self->NodeGetWorldOrientation().getValue3x3(bmo->data);
                        break;
        }
        
@@ -1317,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:
-                       mat3x3.setValue3x3(mat_to);
+                       mat3x3.setValue3x3(bmo->data);
                        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;
@@ -1358,8 +1464,8 @@ void KX_GameObject_Mathutils_Callback_Init(void)
 
 #endif // USE_MATHUTILS
 
+#ifndef DISABLE_PYTHON
 /* ------- python stuff ---------------------------------------------------*/
-
 PyMethodDef KX_GameObject::Methods[] = {
        {"applyForce", (PyCFunction)    KX_GameObject::sPyApplyForce, METH_VARARGS},
        {"applyTorque", (PyCFunction)   KX_GameObject::sPyApplyTorque, METH_VARARGS},
@@ -1383,12 +1489,13 @@ PyMethodDef KX_GameObject::Methods[] = {
        {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS},
        {"setOcclusion",(PyCFunction) KX_GameObject::sPySetOcclusion, METH_VARARGS},
        {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS},
-       {"getChildren", (PyCFunction)KX_GameObject::sPyGetChildren,METH_NOARGS},
-       {"getChildrenRecursive", (PyCFunction)KX_GameObject::sPyGetChildrenRecursive,METH_NOARGS},
+
+
        {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_NOARGS},
        {"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS},
-       {"replaceMesh",(PyCFunction) KX_GameObject::sPyReplaceMesh, METH_O},
+       {"replaceMesh",(PyCFunction) KX_GameObject::sPyReplaceMesh, METH_VARARGS},
        {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS},
+       {"reinstancePhysicsMesh", (PyCFunction)KX_GameObject::sPyReinstancePhysicsMesh,METH_VARARGS},
        
        KX_PYMETHODTABLE(KX_GameObject, rayCastTo),
        KX_PYMETHODTABLE(KX_GameObject, rayCast),
@@ -1397,21 +1504,8 @@ PyMethodDef KX_GameObject::Methods[] = {
        KX_PYMETHODTABLE(KX_GameObject, sendMessage),
        
        // dict style access for props
-       {"has_key",(PyCFunction) KX_GameObject::sPyhas_key, METH_O},
        {"get",(PyCFunction) KX_GameObject::sPyget, METH_VARARGS},
        
-       // deprecated
-       {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS},
-       {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O},
-       {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O},
-       {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS},
-       {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O},
-       {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS},
-       {"setState",(PyCFunction) KX_GameObject::sPySetState, METH_O},
-       {"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_NOARGS},
-       {"getVisible",(PyCFunction) KX_GameObject::sPyGetVisible, METH_NOARGS},
-       {"getMass", (PyCFunction) KX_GameObject::sPyGetMass, METH_NOARGS},
-       {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS},
        {NULL,NULL} //Sentinel
 };
 
@@ -1436,9 +1530,16 @@ 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("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_RW_FUNCTION("color", KX_GameObject, pyattr_get_obcolor, pyattr_set_obcolor),
        
        /* Experemental, dont rely on these yet */
        KX_PYATTRIBUTE_RO_FUNCTION("sensors",           KX_GameObject, pyattr_get_sensors),
@@ -1447,32 +1548,21 @@ PyAttributeDef KX_GameObject::Attributes[] = {
        {NULL} //Sentinel
 };
 
-
-/*
-bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args,
-                                                                                       MT_Vector3& pos,
-                                                                                       MT_Vector3& pos2)
-{
-       PyObject* pylist;
-       PyObject* pylist2;
-       bool error = (PyArg_ParseTuple(args,"OO",&pylist,&pylist2)) != 0;
-
-       pos = ConvertPythonPylist(pylist);
-       pos2 = ConvertPythonPylist(pylist2);
-               
-       return error;
-}
-*/
-
-PyObject* KX_GameObject::PyReplaceMesh(PyObject* value)
+PyObject* KX_GameObject::PyReplaceMesh(PyObject* args)
 {
        KX_Scene *scene = KX_GetActiveScene();
-       RAS_MeshObject* new_mesh;
+       
+       PyObject *value;
+       int use_gfx= 1, use_phys= 0;
+       RAS_MeshObject *new_mesh;
+       
+       if (!PyArg_ParseTuple(args,"O|ii:replaceMesh", &value, &use_gfx, &use_phys))
+               return NULL;
        
        if (!ConvertPythonToMesh(value, &new_mesh, false, "gameOb.replaceMesh(value): KX_GameObject"))
                return NULL;
        
-       scene->ReplaceMesh(this, new_mesh);
+       scene->ReplaceMesh(this, new_mesh, (bool)use_gfx, (bool)use_phys);
        Py_RETURN_NONE;
 }
 
@@ -1486,11 +1576,26 @@ PyObject* KX_GameObject::PyEndObject()
 
 }
 
-
-PyObject* KX_GameObject::PyGetPosition()
+PyObject* KX_GameObject::PyReinstancePhysicsMesh(PyObject* args)
 {
-       ShowDeprecationWarning("getPosition()", "the position property");
-       return PyObjectFrom(NodeGetWorldPosition());
+       KX_GameObject *gameobj= NULL;
+       RAS_MeshObject *mesh= NULL;
+       
+       PyObject *gameobj_py= NULL;
+       PyObject *mesh_py= NULL;
+
+       if (    !PyArg_ParseTuple(args,"|OO:reinstancePhysicsMesh",&gameobj_py, &mesh_py) ||
+                       (gameobj_py && !ConvertPythonToGameObject(gameobj_py, &gameobj, true, "gameOb.reinstancePhysicsMesh(obj, mesh): KX_GameObject")) || 
+                       (mesh_py && !ConvertPythonToMesh(mesh_py, &mesh, true, "gameOb.reinstancePhysicsMesh(obj, mesh): KX_GameObject"))
+               ) {
+               return NULL;
+       }
+       
+       /* gameobj and mesh can be NULL */
+       if(KX_ReInstanceBulletShapeFromMesh(this, gameobj, mesh))
+               Py_RETURN_TRUE;
+
+       Py_RETURN_FALSE;
 }
 
 static PyObject *Map_GetItem(PyObject *self_v, PyObject *item)
@@ -1649,40 +1754,36 @@ PySequenceMethods KX_GameObject::Sequence = {
        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 = {
-#if (PY_VERSION_HEX >= 0x02060000)
        PyVarObject_HEAD_INIT(NULL, 0)
-#else
-       /* python 2.5 and below */
-       PyObject_HEAD_INIT( NULL )  /* required py macro */
-       0,                          /* ob_size */
-#endif
-               "KX_GameObject",
-               sizeof(PyObjectPlus_Proxy),
-               0,
-               py_base_dealloc,
-               0,
-               0,
-               0,
-               0,
-               py_base_repr,
-               0,
-               &Sequence,
-               &Mapping,
-               0,0,0,
-               NULL,
-               NULL,
-               0,
-               Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-               0,0,0,0,0,0,0,
-               Methods,
-               0,
-               0,
-               &SCA_IObject::Type,
-               0,0,0,0,0,0,
-               py_base_new
+       "KX_GameObject",
+       sizeof(PyObjectPlus_Proxy),
+       0,
+       py_base_dealloc,
+       0,
+       0,
+       0,
+       0,
+       py_base_repr,
+       0,
+       &Sequence,
+       &Mapping,
+       0,0,0,
+       NULL,
+       NULL,
+       0,
+       Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+       0,0,0,0,0,0,0,
+       Methods,
+       0,
+       0,
+       &SCA_IObject::Type,
+       0,0,0,0,0,0,
+       py_base_new
 };
 
 PyObject* KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1794,10 +1895,10 @@ int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *at
 
 PyObject* KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
-       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
 #ifdef USE_MATHUTILS
-       return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL);
+       return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL);
 #else
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        return PyObjectFrom(self->NodeGetWorldPosition());
 #endif
 }
@@ -1816,10 +1917,10 @@ int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_D
 
 PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
-       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
 #ifdef USE_MATHUTILS   
-       return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL);
+       return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL);
 #else  
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        return PyObjectFrom(self->NodeGetLocalPosition());
 #endif
 }
@@ -1838,10 +1939,10 @@ int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_D
 
 PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
-       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
 #ifdef USE_MATHUTILS
-       return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL);
+       return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL);
 #else
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        if (self->GetPhysicsController())
                return PyObjectFrom(self->GetPhysicsController()->GetLocalInertia());
        return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
@@ -1851,7 +1952,7 @@ PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIB
 PyObject* KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
 #ifdef USE_MATHUTILS
-       return newMatrixObject_cb((PyObject *)self_v, 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL);
+       return newMatrixObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL);
 #else
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        return PyObjectFrom(self->NodeGetWorldOrientation());
@@ -1876,7 +1977,7 @@ int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUT
 PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
 #ifdef USE_MATHUTILS
-       return newMatrixObject_cb((PyObject *)self_v, 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL);
+       return newMatrixObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL);
 #else
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        return PyObjectFrom(self->NodeGetLocalOrientation());
@@ -1899,20 +2000,20 @@ int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUT
 
 PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
-       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
 #ifdef USE_MATHUTILS
-       return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL);
+       return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL);
 #else
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        return PyObjectFrom(self->NodeGetWorldScaling());
 #endif
 }
 
 PyObject* KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
-       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
 #ifdef USE_MATHUTILS
-       return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL);
+       return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL);
 #else
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        return PyObjectFrom(self->NodeGetLocalScaling());
 #endif
 }
@@ -1929,6 +2030,96 @@ int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DE
        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);
@@ -1999,7 +2190,28 @@ PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DE
        return meshes;
 }
 
-/* experemental! */
+PyObject* KX_GameObject::pyattr_get_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+#ifdef USE_MATHUTILS
+       return newVectorObject_cb(BGE_PROXY_FROM_REF(self_v), 4, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_OBJECT_COLOR);
+#else
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       return PyObjectFrom(self->GetObjectColor());
+#endif
+}
+
+int KX_GameObject::pyattr_set_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       MT_Vector4 obcolor;
+       if (!PyVecTo(value, obcolor))
+               return PY_SET_ATTR_FAIL;
+
+       self->SetObjectColor(obcolor);
+       return PY_SET_ATTR_SUCCESS;
+}
+
+/* These are experimental! */
 PyObject* KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
        return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_SENSORS);
@@ -2014,6 +2226,7 @@ PyObject* KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE
 {
        return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_ACTUATORS);
 }
+/* End experimental */
 
 PyObject* KX_GameObject::pyattr_get_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
@@ -2178,41 +2391,6 @@ PyObject* KX_GameObject::PySetOcclusion(PyObject* args)
        Py_RETURN_NONE;
 }
 
-PyObject* KX_GameObject::PyGetVisible()
-{
-       ShowDeprecationWarning("getVisible()", "the visible property");
-       return PyLong_FromSsize_t(m_bVisible);  
-}
-
-PyObject* KX_GameObject::PyGetState()
-{
-       ShowDeprecationWarning("getState()", "the state property");
-       int state = 0;
-       state |= GetState();
-       return PyLong_FromSsize_t(state);
-}
-
-PyObject* KX_GameObject::PySetState(PyObject* value)
-{
-       ShowDeprecationWarning("setState()", "the state property");
-       int state_i = PyLong_AsSsize_t(value);
-       unsigned int state = 0;
-       
-       if (state_i == -1 && PyErr_Occurred()) {
-               PyErr_SetString(PyExc_TypeError, "expected an int bit field");
-               return NULL;
-       }
-       
-       state |= state_i;
-       if ((state & ((1<<30)-1)) == 0) {
-               PyErr_SetString(PyExc_AttributeError, "The state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
-               return NULL;
-       }
-       SetState(state);
-       
-       Py_RETURN_NONE;
-}
-
 PyObject* KX_GameObject::PyGetVelocity(PyObject* args)
 {
        // only can get the velocity if we have a physics object connected to us...
@@ -2231,14 +2409,6 @@ PyObject* KX_GameObject::PyGetVelocity(PyObject* args)
        }
 }
 
-
-
-PyObject* KX_GameObject::PyGetMass()
-{
-       ShowDeprecationWarning("getMass()", "the mass property");
-       return PyFloat_FromDouble((GetPhysicsController() != NULL) ? GetPhysicsController()->GetMass() : 0.0f);
-}
-
 PyObject* KX_GameObject::PyGetReactionForce()
 {
        // only can get the velocity if we have a physics object connected to us...
@@ -2275,18 +2445,6 @@ PyObject* KX_GameObject::PyDisableRigidBody()
 }
 
 
-
-PyObject* KX_GameObject::PyGetParent()
-{
-       ShowDeprecationWarning("getParent()", "the parent property");
-       KX_GameObject* parent = this->GetParent();
-       if (parent) {
-               parent->Release(); /* self->GetParent() AddRef's */
-               return parent->GetProxy();
-       }
-       Py_RETURN_NONE;
-}
-
 PyObject* KX_GameObject::PySetParent(PyObject* args)
 {
        KX_Scene *scene = KX_GetActiveScene();
@@ -2312,41 +2470,6 @@ PyObject* KX_GameObject::PyRemoveParent()
        Py_RETURN_NONE;
 }
 
-PyObject* KX_GameObject::PyGetChildren()
-{
-       ShowDeprecationWarning("getChildren()", "the children property");
-       
-       return GetChildren()->NewProxy(true);
-}
-
-PyObject* KX_GameObject::PyGetChildrenRecursive()
-{
-       ShowDeprecationWarning("getChildrenRecursive()", "the childrenRecursive property");
-       
-       return GetChildrenRecursive()->NewProxy(true);
-}
-
-PyObject* KX_GameObject::PyGetMesh(PyObject* args)
-{
-       ShowDeprecationWarning("getMesh()", "the meshes property (now a list of meshes)");
-       
-       int mesh = 0;
-
-       if (!PyArg_ParseTuple(args, "|i:getMesh", &mesh))
-               return NULL; // python sets a simple error
-       
-       if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0)
-       {
-               KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]);
-               return meshproxy->NewProxy(true); // XXX Todo Python own.
-       }
-       
-       Py_RETURN_NONE;
-}
-
-
-
-
 
 PyObject* KX_GameObject::PySetCollisionMargin(PyObject* value)
 {
@@ -2410,29 +2533,6 @@ PyObject* KX_GameObject::PyRestoreDynamics()
 }
 
 
-
-PyObject* KX_GameObject::PyGetOrientation() //keywords
-{
-       ShowDeprecationWarning("getOrientation()", "the orientation property");
-       return PyObjectFrom(NodeGetWorldOrientation());
-}
-
-
-
-PyObject* KX_GameObject::PySetOrientation(PyObject* value)
-{
-       ShowDeprecationWarning("setOrientation()", "the orientation property");
-       MT_Matrix3x3 rot;
-       
-       /* if value is not a sequence PyOrientationTo makes an error */
-       if (!PyOrientationTo(value, rot, "gameOb.setOrientation(sequence): KX_GameObject, "))
-               return NULL;
-
-       NodeSetLocalOrientation(rot);
-       NodeUpdateGS(0.f);
-       Py_RETURN_NONE;
-}
-
 PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* args)
 {
        PyObject* pyvect;
@@ -2465,33 +2565,6 @@ PyObject* KX_GameObject::PyGetAxisVect(PyObject* value)
        return NULL;
 }
 
-PyObject* KX_GameObject::PySetPosition(PyObject* value)
-{
-       ShowDeprecationWarning("setPosition()", "the localPosition property");
-       MT_Point3 pos;
-       if (PyVecTo(value, pos))
-       {
-               NodeSetLocalPosition(pos);
-               NodeUpdateGS(0.f);
-               Py_RETURN_NONE;
-       }
-
-       return NULL;
-}
-
-PyObject* KX_GameObject::PySetWorldPosition(PyObject* value)
-{
-       ShowDeprecationWarning("setWorldPosition()", "the worldPosition property");
-       MT_Point3 pos;
-       if (PyVecTo(value, pos))
-       {
-               NodeSetWorldPosition(pos);
-               NodeUpdateGS(0.f);
-               Py_RETURN_NONE;
-       }
-
-       return NULL;
-}
 
 PyObject* KX_GameObject::PyGetPhysicsId()
 {
@@ -2657,14 +2730,11 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
                }
        }
        MT_Point3 fromPoint = NodeGetWorldPosition();
+       
        if (dist != 0.0f)
-       {
-               MT_Vector3 toDir = toPoint-fromPoint;
-               toDir.normalize();
-               toPoint = fromPoint + (dist) * toDir;
-       }
-
-       PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
+               toPoint = fromPoint + dist * (toPoint-fromPoint).safe_normalized();
+       
+       PHY_IPhysicsEnvironment* pe = KX_GetActiveScene()->GetPhysicsEnvironment();
        KX_IPhysicsController *spc = GetPhysicsController();
        KX_GameObject *parent = GetParent();
        if (!spc && parent)
@@ -2680,7 +2750,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
        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;
@@ -2714,9 +2784,26 @@ static PyObject *none_tuple_4()
        return ret;
 }
 
+static PyObject *none_tuple_5()
+{
+       PyObject *ret= PyTuple_New(5);
+       PyTuple_SET_ITEM(ret, 0, Py_None);
+       PyTuple_SET_ITEM(ret, 1, Py_None);
+       PyTuple_SET_ITEM(ret, 2, Py_None);
+       PyTuple_SET_ITEM(ret, 3, Py_None);
+       PyTuple_SET_ITEM(ret, 4, Py_None);
+       
+       Py_INCREF(Py_None);
+       Py_INCREF(Py_None);
+       Py_INCREF(Py_None);
+       Py_INCREF(Py_None);
+       Py_INCREF(Py_None);
+       return ret;
+}
+
 KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
-                                  "rayCast(to,from,dist,prop,face,xray,poly): cast a ray and return 3-tuple (object,hit,normal) or 4-tuple (object,hit,normal,polygon) of contact point with object within dist that matches prop.\n"
-                                  " If no hit, return (None,None,None) or (None,None,None,None).\n"
+                                  "rayCast(to,from,dist,prop,face,xray,poly): cast a ray and return 3-tuple (object,hit,normal) or 4-tuple (object,hit,normal,polygon) or 4-tuple (object,hit,normal,polygon,hituv) of contact point with object within dist that matches prop.\n"
+                                  " If no hit, return (None,None,None) or (None,None,None,None) or (None,None,None,None,None).\n"
 " to   = 3-tuple or object reference for destination of ray (if object, use center of object)\n"
 " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n"
 "        Can be None or omitted => start from self object center\n"
@@ -2726,6 +2813,8 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
 " xray = X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object\n"
 " poly = polygon option: 1=>return value is a 4-tuple and the 4th element is a KX_PolyProxy object\n"
 "                           which can be None if hit object has no mesh or if there is no hit\n"
+"                        2=>return value is a 5-tuple, the 4th element is the KX_PolyProxy object\n"
+"                           and the 5th element is the vector of UV coordinates at the hit point of the None if there is no UV mapping\n"
 "        If 0 or omitted, return value is a 3-tuple\n"
 "Note: The object on which you call this method matters: the ray will ignore it.\n"
 "      prop and xray option interact as follow:\n"
@@ -2791,7 +2880,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
                return none_tuple_3();
        }
        
-       PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
+       PHY_IPhysicsEnvironment* pe = KX_GetActiveScene()->GetPhysicsEnvironment();
        KX_IPhysicsController *spc = GetPhysicsController();
        KX_GameObject *parent = GetParent();
        if (!spc && parent)
@@ -2806,12 +2895,12 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
                m_testPropName.SetLength(0);
        m_xray = xray;
        // to get the hit results
-       KX_RayCast::Callback<KX_GameObject> callback(this,spc,NULL,face);
+       KX_RayCast::Callback<KX_GameObject> callback(this,spc,NULL,face,(poly==2));
        KX_RayCast::RayTest(pe, fromPoint, toPoint, callback);
 
        if (m_pHitObject)
        {
-               PyObject* returnValue = (poly) ? PyTuple_New(4) : PyTuple_New(3);
+               PyObject* returnValue = (poly==2) ? PyTuple_New(5) : (poly) ? PyTuple_New(4) : PyTuple_New(3);
                if (returnValue) { // unlikely this would ever fail, if it does python sets an error
                        PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->GetProxy());
                        PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(callback.m_hitPoint));
@@ -2824,22 +2913,36 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
                                        RAS_Polygon* polygon = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon);
                                        KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, polygon);
                                        PyTuple_SET_ITEM(returnValue, 3, polyproxy->NewProxy(true));
+                                       if (poly == 2)
+                                       {
+                                               if (callback.m_hitUVOK)
+                                                       PyTuple_SET_ITEM(returnValue, 4, PyObjectFrom(callback.m_hitUV));
+                                               else {
+                                                       Py_INCREF(Py_None);
+                                                       PyTuple_SET_ITEM(returnValue, 4, Py_None);
+                                               }
+                                       }
                                }
                                else
                                {
                                        Py_INCREF(Py_None);
                                        PyTuple_SET_ITEM(returnValue, 3, Py_None);
+                                       if (poly==2)
+                                       {
+                                               Py_INCREF(Py_None);
+                                               PyTuple_SET_ITEM(returnValue, 4, Py_None);
+                                       }
                                }
                        }
                }
                return returnValue;
        }
        // no hit
-       if (poly)
-               //return Py_BuildValue("OOOO", Py_None, Py_None, Py_None, Py_None);
+       if (poly == 2)
+               return none_tuple_5();
+       else if (poly)
                return none_tuple_4();
        else
-               //return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
                return none_tuple_3();
 }
 
@@ -2856,7 +2959,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage,
        char* to = (char *)"";
        const STR_String& from = GetName();
 
-       if (!PyArg_ParseTuple(args, "s|sss:sendMessage", &subject, &body, &to))
+       if (!PyArg_ParseTuple(args, "s|ss:sendMessage", &subject, &body, &to))
                return NULL;
        
        scene->GetNetworkScene()->SendMessage(to, from, subject, body);
@@ -2897,37 +3000,6 @@ PyObject* KX_GameObject::Pyget(PyObject *args)
        return def;
 }
 
-/* Matches python dict.has_key() */
-PyObject* KX_GameObject::Pyhas_key(PyObject* value)
-{
-       // the ONLY error case is invalid data, this is checked by the macro'd static function
-       // that calls this one. but make sure Seq_Contains doesnt add extra errors later on.
-       return PyBool_FromLong(Seq_Contains((PyObject *)this, value));
-}
-
-/* --------------------------------------------------------------------- 
- * Some stuff taken from the header
- * --------------------------------------------------------------------- */
-void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)       
-{
-       // we will relink the sensors and actuators that use object references
-       // if the object is part of the replicated hierarchy, use the new
-       // object reference instead
-       SCA_SensorList& sensorlist = GetSensors();
-       SCA_SensorList::iterator sit;
-       for (sit=sensorlist.begin(); sit != sensorlist.end(); sit++)
-       {
-               (*sit)->Relink(map_parameter);
-       }
-       SCA_ActuatorList& actuatorlist = GetActuators();
-       SCA_ActuatorList::iterator ait;
-       for (ait=actuatorlist.begin(); ait != actuatorlist.end(); ait++)
-       {
-               (*ait)->Relink(map_parameter);
-       }
-}
-
-
 bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix)
 {
        if (value==NULL) {
@@ -2983,3 +3055,4 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py
        
        return false;
 }
+#endif // DISABLE_PYTHON