remove python2.x support
[blender.git] / source / gameengine / Ketsji / KX_GameObject.cpp
index 79519bfb4913f5714ad0e32fe9ead75680a3b92a..146b83abd17f47914048e45c9ab0ea2da2315def 100644 (file)
@@ -49,6 +49,8 @@ typedef unsigned long uint_ptr;
 #include "RAS_IPolygonMaterial.h"
 #include "KX_BlenderMaterial.h"
 #include "KX_GameObject.h"
+#include "KX_Camera.h" // only for their ::Type
+#include "KX_Light.h"  // only for their ::Type
 #include "RAS_MeshObject.h"
 #include "KX_MeshProxy.h"
 #include "KX_PolyProxy.h"
@@ -64,6 +66,7 @@ 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"
@@ -84,10 +87,8 @@ static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3(        1.0, 0.0, 0.0,
 
 KX_GameObject::KX_GameObject(
        void* sgReplicationInfo,
-       SG_Callbacks callbacks,
-       PyTypeObject* T
-) : 
-       SCA_IObject(T),
+       SG_Callbacks callbacks)
+       : SCA_IObject(),
        m_bDyna(false),
        m_layer(0),
        m_pBlenderObject(NULL),
@@ -100,7 +101,6 @@ 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),
@@ -224,7 +224,7 @@ KX_GameObject* KX_GameObject::GetParent()
        
 }
 
-void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
+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())
@@ -245,7 +245,7 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
 
                if (m_pPhysicsController1) 
                {
-                       m_pPhysicsController1->SuspendDynamics(true);
+                       m_pPhysicsController1->SuspendDynamics(ghost);
                }
                // Set us to our new scale, position, and orientation
                scale2[0] = 1.0/scale2[0];
@@ -266,7 +266,7 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
                        Release();
                // if the new parent is a compound object, add this object shape to the compound shape.
                // step 0: verify this object has physical controller
-               if (m_pPhysicsController1)
+               if (m_pPhysicsController1 && addToCompound)
                {
                        // step 1: find the top parent (not necessarily obj)
                        KX_GameObject* rootobj = (KX_GameObject*)obj->GetSGNode()->GetRootSGParent()->GetSGClientObject();
@@ -312,6 +312,18 @@ void KX_GameObject::RemoveParent(KX_Scene *scene)
                                rootobj->m_pPhysicsController1->RemoveCompoundChild(m_pPhysicsController1);
                        }
                        m_pPhysicsController1->RestoreDynamics();
+                       if (m_pPhysicsController1->IsDyna() && rootobj->m_pPhysicsController1)
+                       {
+                               // dynamic object should remember the velocity they had while being parented
+                               MT_Point3 childPoint = GetSGNode()->GetWorldPosition();
+                               MT_Point3 rootPoint = rootobj->GetSGNode()->GetWorldPosition();
+                               MT_Point3 relPoint;
+                               relPoint = (childPoint-rootPoint);
+                               MT_Vector3 linVel = rootobj->m_pPhysicsController1->GetVelocity(relPoint);
+                               MT_Vector3 angVel = rootobj->m_pPhysicsController1->GetAngularVelocity();
+                               m_pPhysicsController1->SetLinearVelocity(linVel, false);
+                               m_pPhysicsController1->SetAngularVelocity(angVel, false);
+                       }
                }
                // graphically, the object hasn't change place, no need to update m_pGraphicController
        }
@@ -332,7 +344,7 @@ void KX_GameObject::ProcessReplica()
                
 }
 
-static void setGraphicController_recursive(SG_Node* node, bool v)
+static void setGraphicController_recursive(SG_Node* node)
 {
        NodeList& children = node->GetSGChildren();
 
@@ -341,24 +353,24 @@ static void setGraphicController_recursive(SG_Node* node, bool v)
                SG_Node* childnode = (*childit);
                KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
                if (clientgameobj != NULL) // This is a GameObject
-                       clientgameobj->ActivateGraphicController(v, false);
+                       clientgameobj->ActivateGraphicController(false);
                
                // if the childobj is NULL then this may be an inverse parent link
                // so a non recursive search should still look down this node.
-               setGraphicController_recursive(childnode, v);
+               setGraphicController_recursive(childnode);
        }
 }
 
 
-void KX_GameObject::ActivateGraphicController(bool active, bool recurse)
+void KX_GameObject::ActivateGraphicController(bool recurse)
 {
        if (m_pGraphicController)
        {
-               m_pGraphicController->Activate(active);
+               m_pGraphicController->Activate(m_bVisible);
        }
        if (recurse)
        {
-               setGraphicController_recursive(GetSGNode(), active);
+               setGraphicController_recursive(GetSGNode());
        }
 }
 
@@ -446,17 +458,16 @@ void KX_GameObject::AddMeshUser()
 {
        for (size_t i=0;i<m_meshes.size();i++)
        {
-               m_meshes[i]->AddMeshUser(this, &m_meshSlots);
+               m_meshes[i]->AddMeshUser(this, &m_meshSlots, GetDeformer());
        }
        // set the part of the mesh slot that never change
        double* fl = GetOpenGLMatrixPtr()->getPointer();
-       RAS_Deformer *deformer = GetDeformer();
 
        SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
+       RAS_MeshSlot* ms;
        for(mit.begin(); !mit.end(); ++mit)
        {
                (*mit)->m_OpenGLMatrix = fl;
-               (*mit)->SetDeformer(deformer);
        }
        UpdateBuckets(false);
 }
@@ -538,6 +549,20 @@ void KX_GameObject::UpdateTransformFunc(SG_IObject* node, void* gameobj, void* s
        ((KX_GameObject*)gameobj)->UpdateTransform();
 }
 
+void KX_GameObject::SynchronizeTransform()
+{
+       // only used for sensor object, do full synchronization as bullet doesn't do it
+       if (m_pPhysicsController1)
+               m_pPhysicsController1->SetTransform();
+       if (m_pGraphicController)
+               m_pGraphicController->SetGraphicTransform();
+}
+
+void KX_GameObject::SynchronizeTransformFunc(SG_IObject* node, void* gameobj, void* scene)
+{
+       ((KX_GameObject*)gameobj)->SynchronizeTransform();
+}
+
 
 void KX_GameObject::SetDebugColor(unsigned int bgra)
 {
@@ -956,7 +981,17 @@ void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot)
        GetSGNode()->SetLocalOrientation(rot);
 }
 
+void KX_GameObject::NodeSetGlobalOrientation(const MT_Matrix3x3& rot)
+{
+       // check on valid node in case a python controller holds a reference to a deleted object
+       if (!GetSGNode())
+               return;
 
+       if (GetSGNode()->GetSGParent())
+               GetSGNode()->SetLocalOrientation(GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot);
+       else
+               GetSGNode()->SetLocalOrientation(rot);
+}
 
 void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale)
 {
@@ -1035,7 +1070,13 @@ const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
        return GetSGNode()->GetWorldOrientation();
 }
 
-
+const MT_Matrix3x3& KX_GameObject::NodeGetLocalOrientation() const
+{
+       // check on valid node in case a python controller holds a reference to a deleted object
+       if (!GetSGNode())
+               return dummy_orientation;
+       return GetSGNode()->GetLocalOrientation();
+}
 
 const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
 {
@@ -1046,7 +1087,14 @@ const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
        return GetSGNode()->GetWorldScaling();
 }
 
+const MT_Vector3& KX_GameObject::NodeGetLocalScaling() const
+{
+       // check on valid node in case a python controller holds a reference to a deleted object
+       if (!GetSGNode())
+               return dummy_scaling;
 
+       return GetSGNode()->GetLocalScale();
+}
 
 const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
 {
@@ -1057,6 +1105,16 @@ const MT_Point3& KX_GameObject::NodeGetWorldPosition() const
                return dummy_point;
 }
 
+const MT_Point3& KX_GameObject::NodeGetLocalPosition() const
+{
+       // check on valid node in case a python controller holds a reference to a deleted object
+       if (GetSGNode())
+               return GetSGNode()->GetLocalPosition();
+       else
+               return dummy_point;
+}
+
+
 /* Suspend/ resume: for the dynamic behaviour, there is a simple
  * method. For the residual motion, there is not. I wonder what the
  * correct solution is for Sumo. Remove from the motion-update tree?
@@ -1124,6 +1182,181 @@ CListValue* KX_GameObject::GetChildrenRecursive()
        return list;
 }
 
+#ifdef USE_MATHUTILS
+
+/* These require an SGNode */
+#define MATHUTILS_VEC_CB_POS_LOCAL 1
+#define MATHUTILS_VEC_CB_POS_GLOBAL 2
+#define MATHUTILS_VEC_CB_SCALE_LOCAL 3
+#define MATHUTILS_VEC_CB_SCALE_GLOBAL 4
+#define MATHUTILS_VEC_CB_INERTIA_LOCAL 5
+
+static int mathutils_kxgameob_vector_cb_index= -1; /* index for our callbacks */
+
+static int mathutils_kxgameob_generic_check(PyObject *self_v)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
+       if(self==NULL)
+               return 0;
+       
+       return 1;
+}
+
+static int mathutils_kxgameob_vector_get(PyObject *self_v, int subtype, float *vec_from)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
+       if(self==NULL)
+               return 0;
+       
+       switch(subtype) {
+               case MATHUTILS_VEC_CB_POS_LOCAL:
+                       self->NodeGetLocalPosition().getValue(vec_from);
+                       break;
+               case MATHUTILS_VEC_CB_POS_GLOBAL:
+                       self->NodeGetWorldPosition().getValue(vec_from);
+                       break;
+               case MATHUTILS_VEC_CB_SCALE_LOCAL:
+                       self->NodeGetLocalScaling().getValue(vec_from);
+                       break;
+               case MATHUTILS_VEC_CB_SCALE_GLOBAL:
+                       self->NodeGetWorldScaling().getValue(vec_from);
+                       break;
+               case MATHUTILS_VEC_CB_INERTIA_LOCAL:
+                       if(!self->GetPhysicsController()) return 0;
+                       self->GetPhysicsController()->GetLocalInertia().getValue(vec_from);
+                       break;
+       }
+       
+       return 1;
+}
+
+static int mathutils_kxgameob_vector_set(PyObject *self_v, int subtype, float *vec_to)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
+       if(self==NULL)
+               return 0;
+       
+       switch(subtype) {
+               case MATHUTILS_VEC_CB_POS_LOCAL:
+                       self->NodeSetLocalPosition(MT_Point3(vec_to));
+                       self->NodeUpdateGS(0.f);
+                       break;
+               case MATHUTILS_VEC_CB_POS_GLOBAL:
+                       self->NodeSetWorldPosition(MT_Point3(vec_to));
+                       self->NodeUpdateGS(0.f);
+                       break;
+               case MATHUTILS_VEC_CB_SCALE_LOCAL:
+                       self->NodeSetLocalScale(MT_Point3(vec_to));
+                       self->NodeUpdateGS(0.f);
+                       break;
+               case MATHUTILS_VEC_CB_SCALE_GLOBAL:
+                       break;
+               case MATHUTILS_VEC_CB_INERTIA_LOCAL:
+                       /* read only */
+                       break;
+       }
+       
+       return 1;
+}
+
+static int mathutils_kxgameob_vector_get_index(PyObject *self_v, int subtype, float *vec_from, int index)
+{
+       float f[4];
+       /* lazy, avoid repeteing the case statement */
+       if(!mathutils_kxgameob_vector_get(self_v, subtype, f))
+               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)
+{
+       float f= vec_to[index];
+       
+       /* lazy, avoid repeteing the case statement */
+       if(!mathutils_kxgameob_vector_get(self_v, subtype, vec_to))
+               return 0;
+       
+       vec_to[index]= f;
+       mathutils_kxgameob_vector_set(self_v, subtype, vec_to);
+       
+       return 1;
+}
+
+Mathutils_Callback mathutils_kxgameob_vector_cb = {
+       mathutils_kxgameob_generic_check,
+       mathutils_kxgameob_vector_get,
+       mathutils_kxgameob_vector_set,
+       mathutils_kxgameob_vector_get_index,
+       mathutils_kxgameob_vector_set_index
+};
+
+/* Matrix */
+#define MATHUTILS_MAT_CB_ORI_LOCAL 1
+#define MATHUTILS_MAT_CB_ORI_GLOBAL 2
+
+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)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
+       if(self==NULL)
+               return 0;
+       
+       switch(subtype) {
+               case MATHUTILS_MAT_CB_ORI_LOCAL:
+                       self->NodeGetLocalOrientation().getValue3x3(mat_from);
+                       break;
+               case MATHUTILS_MAT_CB_ORI_GLOBAL:
+                       self->NodeGetWorldOrientation().getValue3x3(mat_from);
+                       break;
+       }
+       
+       return 1;
+}
+
+
+static int mathutils_kxgameob_matrix_set(PyObject *self_v, int subtype, float *mat_to)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
+       if(self==NULL)
+               return 0;
+       
+       MT_Matrix3x3 mat3x3;
+       switch(subtype) {
+               case MATHUTILS_MAT_CB_ORI_LOCAL:
+                       mat3x3.setValue3x3(mat_to);
+                       self->NodeSetLocalOrientation(mat3x3);
+                       self->NodeUpdateGS(0.f);
+                       break;
+               case MATHUTILS_MAT_CB_ORI_GLOBAL:
+                       mat3x3.setValue3x3(mat_to);
+                       self->NodeSetLocalOrientation(mat3x3);
+                       self->NodeUpdateGS(0.f);
+                       break;
+       }
+       
+       return 1;
+}
+
+Mathutils_Callback mathutils_kxgameob_matrix_cb = {
+       mathutils_kxgameob_generic_check,
+       mathutils_kxgameob_matrix_get,
+       mathutils_kxgameob_matrix_set,
+       NULL,
+       NULL
+};
+
+
+void KX_GameObject_Mathutils_Callback_Init(void)
+{
+       // register mathutils callbacks, ok to run more then once.
+       mathutils_kxgameob_vector_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_vector_cb);
+       mathutils_kxgameob_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_matrix_cb);
+}
+
+#endif // USE_MATHUTILS
 
 /* ------- python stuff ---------------------------------------------------*/
 
@@ -1146,7 +1379,7 @@ PyMethodDef KX_GameObject::Methods[] = {
        {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS},
        {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS},
        {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O},
-       {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_O},
+       {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_VARARGS},
        {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS},
        {"setOcclusion",(PyCFunction) KX_GameObject::sPySetOcclusion, METH_VARARGS},
        {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS},
@@ -1154,15 +1387,20 @@ PyMethodDef KX_GameObject::Methods[] = {
        {"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),
        KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo),
        KX_PYMETHODTABLE_O(KX_GameObject, getVectTo),
        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},
@@ -1199,6 +1437,8 @@ 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_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),
        
        /* Experemental, dont rely on these yet */
@@ -1225,15 +1465,21 @@ bool KX_GameObject::ConvertPythonVectorArgs(PyObject* args,
 }
 */
 
-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;
 }
 
@@ -1247,6 +1493,28 @@ PyObject* KX_GameObject::PyEndObject()
 
 }
 
+PyObject* KX_GameObject::PyReinstancePhysicsMesh(PyObject* args)
+{
+       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;
+}
+
 
 PyObject* KX_GameObject::PyGetPosition()
 {
@@ -1254,15 +1522,15 @@ PyObject* KX_GameObject::PyGetPosition()
        return PyObjectFrom(NodeGetWorldPosition());
 }
 
-PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item)
+static PyObject *Map_GetItem(PyObject *self_v, PyObject *item)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
-       const char *attr_str= PyString_AsString(item);
+       const char *attr_str= _PyUnicode_AsString(item);
        CValue* resultattr;
        PyObject* pyconvert;
        
        if (self==NULL) {
-               PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+               PyErr_SetString(PyExc_SystemError, "val = gameOb[key]: KX_GameObject, "BGE_PROXY_ERROR_MSG);
                return NULL;
        }
        
@@ -1288,15 +1556,15 @@ PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item)
 }
 
 
-int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
+static int Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
-       const char *attr_str= PyString_AsString(key);
+       const char *attr_str= _PyUnicode_AsString(key);
        if(attr_str==NULL)
                PyErr_Clear();
        
        if (self==NULL) {
-               PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
+               PyErr_SetString(PyExc_SystemError, "gameOb[key] = value: KX_GameObject, "BGE_PROXY_ERROR_MSG);
                return -1;
        }
        
@@ -1312,7 +1580,7 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
                
                if (del==0) {
                        if(attr_str)    PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" could not be set", attr_str);
-                       else                    PyErr_SetString(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key could not be set");
+                       else                    PyErr_SetString(PyExc_KeyError, "del gameOb[key]: KX_GameObject, key could not be deleted");
                        return -1;
                }
                else if (self->m_attr_dict) {
@@ -1323,7 +1591,7 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
                int set= 0;
                
                /* as CValue */
-               if(attr_str && BGE_PROXY_CHECK_TYPE(val)==0) /* dont allow GameObjects for eg to be assigned to CValue props */
+               if(attr_str && PyObject_TypeCheck(val, &PyObjectPlus::Type)==0) /* dont allow GameObjects for eg to be assigned to CValue props */
                {
                        CValue* vallie = self->ConvertPythonToValue(val, ""); /* error unused */
                        
@@ -1376,55 +1644,74 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
        return 0; /* success */
 }
 
-/* Cant set the len otherwise it can evaluate as false */
+static int Seq_Contains(PyObject *self_v, PyObject *value)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
+       
+       if (self==NULL) {
+               PyErr_SetString(PyExc_SystemError, "val in gameOb: KX_GameObject, "BGE_PROXY_ERROR_MSG);
+               return -1;
+       }
+       
+       if(PyUnicode_Check(value) && self->GetProperty(_PyUnicode_AsString(value)))
+               return 1;
+       
+       if (self->m_attr_dict && PyDict_GetItem(self->m_attr_dict, value))
+               return 1;
+       
+       return 0;
+}
+
+
 PyMappingMethods KX_GameObject::Mapping = {
        (lenfunc)NULL                                   ,                       /*inquiry mp_length */
-       (binaryfunc)KX_GameObject::Map_GetItem,         /*binaryfunc mp_subscript */
-       (objobjargproc)KX_GameObject::Map_SetItem,      /*objobjargproc mp_ass_subscript */
+       (binaryfunc)Map_GetItem,                /*binaryfunc mp_subscript */
+       (objobjargproc)Map_SetItem,     /*objobjargproc mp_ass_subscript */
 };
 
-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,0,
-               &Mapping,
-               0,0,0,
-               py_base_getattro,
-               py_base_setattro,
-               0,0,0,0,0,0,0,0,0,
-               Methods
+PySequenceMethods KX_GameObject::Sequence = {
+       NULL,           /* Cant set the len otherwise it can evaluate as false */
+       NULL,           /* sq_concat */
+       NULL,           /* sq_repeat */
+       NULL,           /* sq_item */
+       NULL,           /* sq_slice */
+       NULL,           /* sq_ass_item */
+       NULL,           /* sq_ass_slice */
+       (objobjproc)Seq_Contains,       /* sq_contains */
 };
 
-
-
-
-
-
-PyParentObject KX_GameObject::Parents[] = {
-       &KX_GameObject::Type,
-               &SCA_IObject::Type,
-               &CValue::Type,
-               NULL
+PyTypeObject KX_GameObject::Type = {
+       PyVarObject_HEAD_INIT(NULL, 0)
+       "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)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-       return PyString_FromString(self->GetName().ReadPtr());
+       return PyUnicode_FromString(self->GetName().ReadPtr());
 }
 
 PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1452,13 +1739,13 @@ int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrd
        MT_Scalar val = PyFloat_AsDouble(value);
        if (val < 0.0f) { /* also accounts for non float */
                PyErr_SetString(PyExc_AttributeError, "gameOb.mass = float: KX_GameObject, expected a float zero or above");
-               return 1;
+               return PY_SET_ATTR_FAIL;
        }
 
        if (spc)
                spc->SetMass(val);
 
-       return 0;
+       return PY_SET_ATTR_SUCCESS;
 }
 
 PyObject* KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1475,13 +1762,13 @@ int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF
        MT_Scalar val = PyFloat_AsDouble(value);
        if (val < 0.0f) { /* also accounts for non float */
                PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMin = float: KX_GameObject, expected a float zero or above");
-               return 1;
+               return PY_SET_ATTR_FAIL;
        }
 
        if (spc)
                spc->SetLinVelocityMin(val);
 
-       return 0;
+       return PY_SET_ATTR_SUCCESS;
 }
 
 PyObject* KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1498,13 +1785,13 @@ int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF
        MT_Scalar val = PyFloat_AsDouble(value);
        if (val < 0.0f) { /* also accounts for non float */
                PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMax = float: KX_GameObject, expected a float zero or above");
-               return 1;
+               return PY_SET_ATTR_FAIL;
        }
 
        if (spc)
                spc->SetLinVelocityMax(val);
 
-       return 0;
+       return PY_SET_ATTR_SUCCESS;
 }
 
 
@@ -1520,18 +1807,22 @@ int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *at
        int param = PyObject_IsTrue( value );
        if (param == -1) {
                PyErr_SetString(PyExc_AttributeError, "gameOb.visible = bool: KX_GameObject, expected True or False");
-               return 1;
+               return PY_SET_ATTR_FAIL;
        }
 
        self->SetVisible(param, false);
        self->UpdateBuckets(false);
-       return 0;
+       return PY_SET_ATTR_SUCCESS;
 }
 
 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);
+#else
        return PyObjectFrom(self->NodeGetWorldPosition());
+#endif
 }
 
 int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
@@ -1539,20 +1830,21 @@ int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_D
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        MT_Point3 pos;
        if (!PyVecTo(value, pos))
-               return 1;
+               return PY_SET_ATTR_FAIL;
        
        self->NodeSetWorldPosition(pos);
        self->NodeUpdateGS(0.f);
-       return 0;
+       return PY_SET_ATTR_SUCCESS;
 }
 
 PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-       if (self->GetSGNode())
-               return PyObjectFrom(self->GetSGNode()->GetLocalPosition());
-       else
-               return PyObjectFrom(dummy_point);
+#ifdef USE_MATHUTILS   
+       return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL);
+#else  
+       return PyObjectFrom(self->NodeGetLocalPosition());
+#endif
 }
 
 int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
@@ -1560,27 +1852,33 @@ int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_D
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        MT_Point3 pos;
        if (!PyVecTo(value, pos))
-               return 1;
+               return PY_SET_ATTR_FAIL;
        
        self->NodeSetLocalPosition(pos);
        self->NodeUpdateGS(0.f);
-       return 0;
+       return PY_SET_ATTR_SUCCESS;
 }
 
 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);
+#else
        if (self->GetPhysicsController())
-       {
                return PyObjectFrom(self->GetPhysicsController()->GetLocalInertia());
-       }
        return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
+#endif
 }
 
 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);
+#else
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        return PyObjectFrom(self->NodeGetWorldOrientation());
+#endif
 }
 
 int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
@@ -1590,26 +1888,22 @@ int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUT
        /* if value is not a sequence PyOrientationTo makes an error */
        MT_Matrix3x3 rot;
        if (!PyOrientationTo(value, rot, "gameOb.worldOrientation = sequence: KX_GameObject, "))
-               return NULL;
+               return PY_SET_ATTR_FAIL;
 
-       if (self->GetSGNode() && self->GetSGNode()->GetSGParent()) {
-               self->NodeSetLocalOrientation(self->GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot);
-       }
-       else {
-               self->NodeSetLocalOrientation(rot);
-       }
+       self->NodeSetGlobalOrientation(rot);
        
        self->NodeUpdateGS(0.f);
-       return 0;
+       return PY_SET_ATTR_SUCCESS;
 }
 
 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);
+#else
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-       if (self->GetSGNode())
-               return PyObjectFrom(self->GetSGNode()->GetLocalOrientation());
-       else
-               return PyObjectFrom(dummy_orientation);
+       return PyObjectFrom(self->NodeGetLocalOrientation());
+#endif
 }
 
 int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
@@ -1619,26 +1913,31 @@ int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUT
        /* if value is not a sequence PyOrientationTo makes an error */
        MT_Matrix3x3 rot;
        if (!PyOrientationTo(value, rot, "gameOb.localOrientation = sequence: KX_GameObject, "))
-               return NULL;
+               return PY_SET_ATTR_FAIL;
 
        self->NodeSetLocalOrientation(rot);
        self->NodeUpdateGS(0.f);
-       return 0;
+       return PY_SET_ATTR_SUCCESS;
 }
 
 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);
+#else
        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);
-       if (self->GetSGNode())
-               return PyObjectFrom(self->GetSGNode()->GetLocalScale());
-       else
-               return PyObjectFrom(dummy_scaling);
+#ifdef USE_MATHUTILS
+       return newVectorObject_cb((PyObject *)self_v, 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL);
+#else
+       return PyObjectFrom(self->NodeGetLocalScaling());
+#endif
 }
 
 int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
@@ -1646,11 +1945,11 @@ int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DE
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        MT_Vector3 scale;
        if (!PyVecTo(value, scale))
-               return 1;
+               return PY_SET_ATTR_FAIL;
 
        self->NodeSetLocalScale(scale);
        self->NodeUpdateGS(0.f);
-       return 0;
+       return PY_SET_ATTR_SUCCESS;
 }
 
 PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1672,12 +1971,12 @@ int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF
                SG_Node* sg_parent= self->GetSGNode()->GetSGParent();
                if (val < 0.0f) { /* also accounts for non float */
                        PyErr_SetString(PyExc_AttributeError, "gameOb.timeOffset = float: KX_GameObject, expected a float zero or above");
-                       return 1;
+                       return PY_SET_ATTR_FAIL;
                }
                if (sg_parent && sg_parent->IsSlowParent())
                        static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->SetTimeOffset(val);
        }
-       return 0;
+       return PY_SET_ATTR_SUCCESS;
 }
 
 PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1685,27 +1984,27 @@ PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        int state = 0;
        state |= self->GetState();
-       return PyInt_FromLong(state);
+       return PyLong_FromSsize_t(state);
 }
 
 int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-       int state_i = PyInt_AsLong(value);
+       int state_i = PyLong_AsSsize_t(value);
        unsigned int state = 0;
        
        if (state_i == -1 && PyErr_Occurred()) {
                PyErr_SetString(PyExc_TypeError, "gameOb.state = int: KX_GameObject, expected an int bit field");
-               return 1;
+               return PY_SET_ATTR_FAIL;
        }
        
        state |= state_i;
        if ((state & ((1<<30)-1)) == 0) {
                PyErr_SetString(PyExc_AttributeError, "gameOb.state = int: KX_GameObject, state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
-               return 1;
+               return PY_SET_ATTR_FAIL;
        }
        self->SetState(state);
-       return 0;
+       return PY_SET_ATTR_SUCCESS;
 }
 
 PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1739,137 +2038,29 @@ 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);
 }
 
-PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject* KX_GameObject::pyattr_get_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-       
-       if(self->m_attr_dict==NULL)
-               self->m_attr_dict= PyDict_New();
-       
-       Py_INCREF(self->m_attr_dict);
-       return self->m_attr_dict;
-}
-
-/* We need these because the macros have a return in them */
-PyObject* KX_GameObject::py_getattro__internal(PyObject *attr)
-{
-       py_getattro_up(SCA_IObject);
+       return self->GetChildren()->NewProxy(true);
 }
 
-int KX_GameObject::py_setattro__internal(PyObject *attr, PyObject *value)      // py_setattro method
+PyObject* KX_GameObject::pyattr_get_children_recursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
-       py_setattro_up(SCA_IObject);
-}
-
-
-PyObject* KX_GameObject::py_getattro(PyObject *attr)
-{
-       PyObject *object= py_getattro__internal(attr);
-       
-       if (object==NULL && m_attr_dict)
-       {
-               /* backup the exception incase the attr doesnt exist in the dict either */
-               PyObject *err_type, *err_value, *err_tb;
-               PyErr_Fetch(&err_type, &err_value, &err_tb);
-               
-               object= PyDict_GetItem(m_attr_dict, attr);
-               if (object) {
-                       Py_INCREF(object);
-                       
-                       PyErr_Clear();
-                       Py_XDECREF( err_type );
-                       Py_XDECREF( err_value );
-                       Py_XDECREF( err_tb );
-               }
-               else {
-                       PyErr_Restore(err_type, err_value, err_tb); /* use the error from the parent function */
-               }
-       }
-       return object;
-}
-
-PyObject* KX_GameObject::py_getattro_dict() {
-       //py_getattro_dict_up(SCA_IObject);
-       PyObject *dict= py_getattr_dict(SCA_IObject::py_getattro_dict(), Type.tp_dict);
-       if(dict==NULL)
-               return NULL;
-       
-       /* normally just return this but KX_GameObject has some more items */
-
-       
-       /* Not super fast getting as a list then making into dict keys but its only for dir() */
-       PyObject *list= ConvertKeysToPython();
-       if(list)
-       {
-               int i;
-               for(i=0; i<PyList_Size(list); i++)
-                       PyDict_SetItem(dict, PyList_GET_ITEM(list, i), Py_None);
-       }
-       else
-               PyErr_Clear();
-       
-       Py_DECREF(list);
-       
-       /* Add m_attr_dict if we have it */
-       if(m_attr_dict)
-               PyDict_Update(dict, m_attr_dict);
-       
-       return dict;
-}
-
-int KX_GameObject::py_setattro(PyObject *attr, PyObject *value)        // py_setattro method
-{
-       int ret= py_setattro__internal(attr, value);
-       
-       if (ret==PY_SET_ATTR_SUCCESS) {
-               /* remove attribute in our own dict to avoid double ups */
-               /* NOTE: Annoying that we also do this for setting builtin attributes like mass and visibility :/ */
-               if (m_attr_dict) {
-                       if (PyDict_DelItem(m_attr_dict, attr) != 0)
-                               PyErr_Clear();
-               }
-       }
-       
-       if (ret==PY_SET_ATTR_COERCE_FAIL) {
-               /* CValue attribute exists, remove CValue and add PyDict value */
-               RemoveProperty(PyString_AsString(attr));
-               ret= PY_SET_ATTR_MISSING;
-       }
-       
-       if (ret==PY_SET_ATTR_MISSING) {
-               /* Lazy initialization */
-               if (m_attr_dict==NULL)
-                       m_attr_dict = PyDict_New();
-               
-               if (PyDict_SetItem(m_attr_dict, attr, value)==0) {
-                       PyErr_Clear();
-                       ret= PY_SET_ATTR_SUCCESS;
-               }
-               else {
-                       PyErr_Format(PyExc_AttributeError, "gameOb.myAttr = value: KX_GameObject, failed assigning value to internal dictionary");
-                       ret= PY_SET_ATTR_FAIL;
-               }
-       }
-       
-       return ret;     
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       return self->GetChildrenRecursive()->NewProxy(true);
 }
 
-
-int    KX_GameObject::py_delattro(PyObject *attr)
+PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
-       char *attr_str= PyString_AsString(attr); 
-       
-       if (RemoveProperty(attr_str)) // XXX - should call CValues instead but its only 2 lines here
-               return 0;
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        
-       if (m_attr_dict && (PyDict_DelItem(m_attr_dict, attr) == 0))
-               return 0;
+       if(self->m_attr_dict==NULL)
+               self->m_attr_dict= PyDict_New();
        
-       PyErr_Format(PyExc_AttributeError, "del gameOb.myAttr: KX_GameObject, attribute \"%s\" dosnt exist", attr_str);
-       return 1;
+       Py_INCREF(self->m_attr_dict);
+       return self->m_attr_dict;
 }
 
-
 PyObject* KX_GameObject::PyApplyForce(PyObject* args)
 {
        int local = 0;
@@ -2013,7 +2204,7 @@ PyObject* KX_GameObject::PySetOcclusion(PyObject* args)
 PyObject* KX_GameObject::PyGetVisible()
 {
        ShowDeprecationWarning("getVisible()", "the visible property");
-       return PyInt_FromLong(m_bVisible);      
+       return PyLong_FromSsize_t(m_bVisible);  
 }
 
 PyObject* KX_GameObject::PyGetState()
@@ -2021,13 +2212,13 @@ PyObject* KX_GameObject::PyGetState()
        ShowDeprecationWarning("getState()", "the state property");
        int state = 0;
        state |= GetState();
-       return PyInt_FromLong(state);
+       return PyLong_FromSsize_t(state);
 }
 
 PyObject* KX_GameObject::PySetState(PyObject* value)
 {
        ShowDeprecationWarning("setState()", "the state property");
-       int state_i = PyInt_AsLong(value);
+       int state_i = PyLong_AsSsize_t(value);
        unsigned int state = 0;
        
        if (state_i == -1 && PyErr_Occurred()) {
@@ -2119,15 +2310,20 @@ PyObject* KX_GameObject::PyGetParent()
        Py_RETURN_NONE;
 }
 
-PyObject* KX_GameObject::PySetParent(PyObject* value)
+PyObject* KX_GameObject::PySetParent(PyObject* args)
 {
        KX_Scene *scene = KX_GetActiveScene();
+       PyObject* pyobj;
        KX_GameObject *obj;
+       int addToCompound=1, ghost=1;
        
-       if (!ConvertPythonToGameObject(value, &obj, false, "gameOb.setParent(value): KX_GameObject"))
+       if (!PyArg_ParseTuple(args,"O|ii:setParent", &pyobj, &addToCompound, &ghost)) {
+               return NULL; // Python sets a simple error
+       }
+       if (!ConvertPythonToGameObject(pyobj, &obj, true, "gameOb.setParent(obj): KX_GameObject"))
                return NULL;
-       
-       this->SetParent(scene, obj);
+       if (obj)
+               this->SetParent(scene, obj, addToCompound, ghost);
        Py_RETURN_NONE;
 }
 
@@ -2141,17 +2337,21 @@ PyObject* KX_GameObject::PyRemoveParent()
 
 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");
+       ShowDeprecationWarning("getMesh()", "the meshes property (now a list of meshes)");
        
        int mesh = 0;
 
@@ -2290,7 +2490,7 @@ PyObject* KX_GameObject::PyGetAxisVect(PyObject* value)
 
 PyObject* KX_GameObject::PySetPosition(PyObject* value)
 {
-       ShowDeprecationWarning("setPosition()", "the position property");
+       ShowDeprecationWarning("setPosition()", "the localPosition property");
        MT_Point3 pos;
        if (PyVecTo(value, pos))
        {
@@ -2324,7 +2524,7 @@ PyObject* KX_GameObject::PyGetPhysicsId()
        {
                physid= (uint_ptr)ctrl->GetUserData();
        }
-       return PyInt_FromLong((long)physid);
+       return PyLong_FromSsize_t((long)physid);
 }
 
 PyObject* KX_GameObject::PyGetPropertyNames()
@@ -2486,8 +2686,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
                toDir.normalize();
                toPoint = fromPoint + (dist) * toDir;
        }
-
-       PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
+       PHY_IPhysicsEnvironment* pe = KX_GetActiveScene()->GetPhysicsEnvironment();
        KX_IPhysicsController *spc = GetPhysicsController();
        KX_GameObject *parent = GetParent();
        if (!spc && parent)
@@ -2614,7 +2813,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)
@@ -2686,6 +2885,48 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage,
        Py_RETURN_NONE;
 }
 
+/* dict style access */
+
+
+/* Matches python dict.get(key, [default]) */
+PyObject* KX_GameObject::Pyget(PyObject *args)
+{
+       PyObject *key;
+       PyObject* def = Py_None;
+       PyObject* ret;
+
+       if (!PyArg_ParseTuple(args, "O|O:get", &key, &def))
+               return NULL;
+       
+       
+       if(PyUnicode_Check(key)) {
+               CValue *item = GetProperty(_PyUnicode_AsString(key));
+               if (item) {
+                       ret = item->ConvertValueToPython();
+                       if(ret)
+                               return ret;
+                       else
+                               return item->GetProxy();
+               }
+       }
+       
+       if (m_attr_dict && (ret=PyDict_GetItem(m_attr_dict, key))) {
+               Py_INCREF(ret);
+               return ret;
+       }
+       
+       Py_INCREF(def);
+       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
  * --------------------------------------------------------------------- */
@@ -2708,6 +2949,7 @@ void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)
        }
 }
 
+
 bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix)
 {
        if (value==NULL) {
@@ -2727,18 +2969,21 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py
                }
        }
        
-       if (PyString_Check(value)) {
-               *object = (KX_GameObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( PyString_AsString(value) ));
+       if (PyUnicode_Check(value)) {
+               *object = (KX_GameObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String( _PyUnicode_AsString(value) ));
                
                if (*object) {
                        return true;
                } else {
-                       PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, PyString_AsString(value));
+                       PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_GameObject in this scene", error_prefix, _PyUnicode_AsString(value));
                        return false;
                }
        }
        
-       if (PyObject_TypeCheck(value, &KX_GameObject::Type)) {
+       if (    PyObject_TypeCheck(value, &KX_GameObject::Type) ||
+                       PyObject_TypeCheck(value, &KX_LightObject::Type)        ||
+                       PyObject_TypeCheck(value, &KX_Camera::Type)     )
+       {
                *object = static_cast<KX_GameObject*>BGE_PROXY_REF(value);
                
                /* sets the error */