synched with trunk at revision 36569
[blender.git] / source / gameengine / Ketsji / KX_GameObject.cpp
index 637b874..d4ef462 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  * Game object wrapper
  */
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
+/** \file gameengine/Ketsji/KX_GameObject.cpp
+ *  \ingroup ketsji
+ */
+
 
 #if defined(_WIN64)
 typedef unsigned __int64 uint_ptr;
@@ -38,7 +39,7 @@ typedef unsigned __int64 uint_ptr;
 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 )     
@@ -51,6 +52,7 @@ typedef unsigned long uint_ptr;
 #include "KX_GameObject.h"
 #include "KX_Camera.h" // only for their ::Type
 #include "KX_Light.h"  // only for their ::Type
+#include "KX_FontObject.h"  // only for their ::Type
 #include "RAS_MeshObject.h"
 #include "KX_MeshProxy.h"
 #include "KX_PolyProxy.h"
@@ -71,6 +73,7 @@ typedef unsigned long uint_ptr;
 #include "SCA_ISensor.h"
 #include "SCA_IController.h"
 #include "NG_NetworkScene.h" //Needed for sendMessage()
+#include "KX_ObstacleSimulation.h"
 
 #include "PyObjectPlus.h" /* python stuff */
 
@@ -105,8 +108,9 @@ KX_GameObject::KX_GameObject(
        m_pGraphicController(NULL),
        m_xray(false),
        m_pHitObject(NULL),
-       m_isDeformable(false)
-#ifndef DISABLE_PYTHON
+       m_isDeformable(false),
+       m_pObstacleSimulation(NULL)
+#ifdef WITH_PYTHON
        , m_attr_dict(NULL)
 #endif
 {
@@ -152,12 +156,19 @@ KX_GameObject::~KX_GameObject()
        {
                delete m_pGraphicController;
        }
-#ifndef DISABLE_PYTHON
+
+       if (m_pObstacleSimulation)
+       {
+               m_pObstacleSimulation->DestroyObstacleForObj(this);
+       }
+
+#ifdef WITH_PYTHON
        if (m_attr_dict) {
-               PyDict_Clear(m_attr_dict); /* incase of circular refs or other weired cases */
-               Py_DECREF(m_attr_dict);
+               PyDict_Clear(m_attr_dict); /* incase of circular refs or other weird cases */
+               /* Py_CLEAR: Py_DECREF's and NULL's */
+               Py_CLEAR(m_attr_dict);
        }
-#endif // DISABLE_PYTHON
+#endif // WITH_PYTHON
 }
 
 KX_GameObject* KX_GameObject::GetClientObject(KX_ClientObjectInfo* info)
@@ -352,7 +363,15 @@ void KX_GameObject::ProcessReplica()
        m_pClient_info->m_gameobject = this;
        m_state = 0;
 
-#ifndef DISABLE_PYTHON
+       KX_Scene* scene = KX_GetActiveScene();
+       KX_ObstacleSimulation* obssimulation = scene->GetObstacleSimulation();
+       struct Object* blenderobject = GetBlenderObject();
+       if (obssimulation && (blenderobject->gameflag & OB_HASOBSTACLE))
+       {
+               obssimulation->AddObstacleForObj(this);
+       }
+
+#ifdef WITH_PYTHON
        if(m_attr_dict)
                m_attr_dict= PyDict_Copy(m_attr_dict);
 #endif
@@ -850,7 +869,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;
@@ -1026,7 +1045,7 @@ void KX_GameObject::NodeSetGlobalOrientation(const MT_Matrix3x3& rot)
        if (GetSGNode()->GetSGParent())
                GetSGNode()->SetLocalOrientation(GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot);
        else
-               GetSGNode()->SetLocalOrientation(rot);
+               NodeSetLocalOrientation(rot);
 }
 
 void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale)
@@ -1221,7 +1240,7 @@ CListValue* KX_GameObject::GetChildrenRecursive()
 /* ---------------------------------------------------------------------
  * Some stuff taken from the header
  * --------------------------------------------------------------------- */
-void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)
+void KX_GameObject::Relink(CTR_Map<CTR_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
@@ -1256,130 +1275,130 @@ void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)
 
 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;
        
-       return 1;
+       return 0;
 }
 
-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;
-       
+               return -1;
+
+#define PHYS_ERR(attr) PyErr_SetString(PyExc_AttributeError, "KX_GameObject." attr ", is missing a physics controller")
+
        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);
+                       if(!self->GetPhysicsController()) return PHYS_ERR("localInertia"), -1;
+                       self->GetPhysicsController()->GetLocalInertia().getValue(bmo->data);
                        break;
                case MATHUTILS_VEC_CB_OBJECT_COLOR:
-                       self->GetObjectColor().getValue(vec_from);
+                       self->GetObjectColor().getValue(bmo->data);
                        break;
                case MATHUTILS_VEC_CB_LINVEL_LOCAL:
-                       if(!self->GetPhysicsController()) return 0;
-                       self->GetLinearVelocity(true).getValue(vec_from);
+                       if(!self->GetPhysicsController()) return PHYS_ERR("localLinearVelocity"), -1;
+                       self->GetLinearVelocity(true).getValue(bmo->data);
                        break;
                case MATHUTILS_VEC_CB_LINVEL_GLOBAL:
-                       if(!self->GetPhysicsController()) return 0;
-                       self->GetLinearVelocity(false).getValue(vec_from);
+                       if(!self->GetPhysicsController()) return PHYS_ERR("worldLinearVelocity"), -1;
+                       self->GetLinearVelocity(false).getValue(bmo->data);
                        break;
                case MATHUTILS_VEC_CB_ANGVEL_LOCAL:
-                       if(!self->GetPhysicsController()) return 0;
-                       self->GetAngularVelocity(true).getValue(vec_from);
+                       if(!self->GetPhysicsController()) return PHYS_ERR("localLinearVelocity"), -1;
+                       self->GetAngularVelocity(true).getValue(bmo->data);
                        break;
                case MATHUTILS_VEC_CB_ANGVEL_GLOBAL:
-                       if(!self->GetPhysicsController()) return 0;
-                       self->GetAngularVelocity(false).getValue(vec_from);
+                       if(!self->GetPhysicsController()) return PHYS_ERR("worldLinearVelocity"), -1;
+                       self->GetAngularVelocity(false).getValue(bmo->data);
                        break;
                        
        }
        
-       return 1;
+#undef PHYS_ERR
+       
+       return 0;
 }
 
-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;
+               return -1;
        
        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 -1;
                case MATHUTILS_VEC_CB_INERTIA_LOCAL:
                        /* read only */
                        break;
                case MATHUTILS_VEC_CB_OBJECT_COLOR:
-                       self->SetObjectColor(MT_Vector4(vec_to));
+                       self->SetObjectColor(MT_Vector4(bmo->data));
                        break;
                case MATHUTILS_VEC_CB_LINVEL_LOCAL:
-                       self->setLinearVelocity(MT_Point3(vec_to),true);
+                       self->setLinearVelocity(MT_Point3(bmo->data),true);
                        break;
                case MATHUTILS_VEC_CB_LINVEL_GLOBAL:
-                       self->setLinearVelocity(MT_Point3(vec_to),false);
+                       self->setLinearVelocity(MT_Point3(bmo->data),false);
                        break;
                case MATHUTILS_VEC_CB_ANGVEL_LOCAL:
-                       self->setAngularVelocity(MT_Point3(vec_to),true);
+                       self->setAngularVelocity(MT_Point3(bmo->data),true);
                        break;
                case MATHUTILS_VEC_CB_ANGVEL_GLOBAL:
-                       self->setAngularVelocity(MT_Point3(vec_to),false);
+                       self->setAngularVelocity(MT_Point3(bmo->data),false);
                        break;
        }
        
-       return 1;
+       return 0;
 }
 
-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))
-               return 0;
-       
-       vec_from[index]= f[index];
-       return 1;
+       if(mathutils_kxgameob_vector_get(bmo, subtype) == -1)
+               return -1;
+       return 0;
 }
 
-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))
-               return 0;
-       
-       vec_to[index]= f;
-       mathutils_kxgameob_vector_set(self_v, subtype, vec_to);
+       if(mathutils_kxgameob_vector_get(bmo, subtype) == -1)
+               return -1;
        
-       return 1;
+       bmo->data[index]= f;
+       return mathutils_kxgameob_vector_set(bmo, subtype);
 }
 
 Mathutils_Callback mathutils_kxgameob_vector_cb = {
@@ -1396,46 +1415,46 @@ 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;
-       
+               return -1;
+
        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;
        }
        
-       return 1;
+       return 0;
 }
 
 
-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;
+               return -1;
        
        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;
        }
        
-       return 1;
+       return 0;
 }
 
 Mathutils_Callback mathutils_kxgameob_matrix_cb = {
@@ -1456,7 +1475,7 @@ void KX_GameObject_Mathutils_Callback_Init(void)
 
 #endif // USE_MATHUTILS
 
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
 /* ------- python stuff ---------------------------------------------------*/
 PyMethodDef KX_GameObject::Methods[] = {
        {"applyForce", (PyCFunction)    KX_GameObject::sPyApplyForce, METH_VARARGS},
@@ -1504,6 +1523,7 @@ PyMethodDef KX_GameObject::Methods[] = {
 PyAttributeDef KX_GameObject::Attributes[] = {
        KX_PYATTRIBUTE_RO_FUNCTION("name",              KX_GameObject, pyattr_get_name),
        KX_PYATTRIBUTE_RO_FUNCTION("parent",    KX_GameObject, pyattr_get_parent),
+       KX_PYATTRIBUTE_RO_FUNCTION("life",              KX_GameObject, pyattr_get_life),
        KX_PYATTRIBUTE_RW_FUNCTION("mass",              KX_GameObject, pyattr_get_mass,         pyattr_set_mass),
        KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin",            KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min),
        KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax",            KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max),
@@ -1582,11 +1602,11 @@ PyObject* KX_GameObject::PyReinstancePhysicsMesh(PyObject* args)
                ) {
                return NULL;
        }
-       
+#ifdef USE_BULLET
        /* gameobj and mesh can be NULL */
        if(KX_ReInstanceBulletShapeFromMesh(this, gameobj, mesh))
                Py_RETURN_TRUE;
-
+#endif
        Py_RETURN_FALSE;
 }
 
@@ -1746,6 +1766,8 @@ 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 = {
@@ -1793,6 +1815,19 @@ PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DE
        Py_RETURN_NONE;
 }
 
+PyObject* KX_GameObject::pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+
+       CValue *life = self->GetProperty("::timebomb");
+       if (life)
+               // this convert the timebomb seconds to frames, hard coded 50.0 (assuming 50fps)
+               // value hardcoded in KX_Scene::AddReplicaObject()
+               return PyFloat_FromDouble(life->GetNumber() * 50.0);
+       else
+               Py_RETURN_NONE;
+}
+
 PyObject* KX_GameObject::pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
@@ -2740,7 +2775,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;
@@ -3022,7 +3057,8 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py
        
        if (    PyObject_TypeCheck(value, &KX_GameObject::Type) ||
                        PyObject_TypeCheck(value, &KX_LightObject::Type)        ||
-                       PyObject_TypeCheck(value, &KX_Camera::Type)     )
+                       PyObject_TypeCheck(value, &KX_Camera::Type)                     ||
+                       PyObject_TypeCheck(value, &KX_FontObject::Type))
        {
                *object = static_cast<KX_GameObject*>BGE_PROXY_REF(value);
                
@@ -3045,4 +3081,4 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py
        
        return false;
 }
-#endif // DISABLE_PYTHON
+#endif // WITH_PYTHON