svn merge -r 21041:21301 https://svn.blender.org/svnroot/bf-blender/branches/blender2...
[blender.git] / source / gameengine / Ketsji / KX_NearSensor.cpp
index 4766d837069d63e6d5fee2301fac21efff09011c..1a211a64b35ff87ed683c0b8e994233902475c97 100644 (file)
@@ -3,15 +3,12 @@
  *
  * $Id$
  *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** BEGIN GPL LICENSE BLOCK *****
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * of the License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -29,7 +26,7 @@
  *
  * Contributor(s): none yet.
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  */
 
 #include "KX_NearSensor.h"
 #include "KX_GameObject.h"
 #include "KX_TouchEventManager.h"
 #include "KX_Scene.h" // needed to create a replica
-
-#include "SM_Object.h"
+#include "PHY_IPhysicsEnvironment.h"
+#include "PHY_IPhysicsController.h"
+#include "PHY_IMotionState.h"
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr,
                                                         KX_GameObject* gameobj,
-                                                        void *vshape,
-                                                        double margin,
-                                                        double resetmargin,
+                                                        float margin,
+                                                        float resetmargin,
                                                         bool bFindMaterial,
                                                         const STR_String& touchedpropname,
                                                         class KX_Scene* scene,
-                                                        PyTypeObject* T)
+                                                        PHY_IPhysicsController* ctrl)
                         :KX_TouchSensor(eventmgr,
                                                         gameobj,
                                                         bFindMaterial,
-                                                        touchedpropname,
-                                                        /* scene, */
-                                                        T),
+                                                        false,
+                                                        touchedpropname
+                                                        /*, scene */),
                         m_Margin(margin),
                         m_ResetMargin(resetmargin)
 
 {
-       gameobj->getClientInfo()->m_sensors.remove(this);
-       m_client_info = new KX_ClientObjectInfo(gameobj, KX_ClientObjectInfo::NEAR);
-       m_client_info->m_sensors.push_back(this);
-       
-       DT_ShapeHandle shape = (DT_ShapeHandle) vshape;
-       m_sumoObj = new SM_Object(shape,NULL,NULL,NULL);
-       m_sumoObj->setMargin(m_Margin);
-       m_sumoObj->setClientObject(m_client_info);
-       
-       SynchronizeTransform();
-}
 
-KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr,
-                                                        KX_GameObject* gameobj,
-                                                        double margin,
-                                                        double resetmargin,
-                                                        bool bFindMaterial,
-                                                        const STR_String& touchedpropname,
-                                                        class KX_Scene* scene,
-                                                        PyTypeObject* T)
-                        :KX_TouchSensor(eventmgr,
-                                                        gameobj,
-                                                        bFindMaterial,
-                                                        touchedpropname,
-                                                        /* scene, */
-                                                        T),
-                        m_Margin(margin),
-                        m_ResetMargin(resetmargin)
-
-{
        gameobj->getClientInfo()->m_sensors.remove(this);
-       m_client_info = new KX_ClientObjectInfo(gameobj, KX_ClientObjectInfo::NEAR);
+       m_client_info = new KX_ClientObjectInfo(gameobj, KX_ClientObjectInfo::SENSOR);
        m_client_info->m_sensors.push_back(this);
        
-       m_sumoObj = new SM_Object(DT_NewSphere(0.0),NULL,NULL,NULL);
-       m_sumoObj->setMargin(m_Margin);
-       m_sumoObj->setClientObject(m_client_info);
-       
+       //DT_ShapeHandle shape = (DT_ShapeHandle) vshape;
+       m_physCtrl = ctrl;
+       if (m_physCtrl)
+       {
+               m_physCtrl->SetMargin(m_Margin);
+               m_physCtrl->setNewClientInfo(m_client_info);
+       }
        SynchronizeTransform();
 }
 
-void KX_NearSensor::RegisterSumo(KX_TouchEventManager *touchman)
+void KX_NearSensor::SynchronizeTransform()
 {
-       touchman->GetSumoScene()->addSensor(*m_sumoObj);
+       // The near and radar sensors are using a different physical object which is 
+       // not linked to the parent object, must synchronize it.
+       if (m_physCtrl)
+       {
+               PHY_IMotionState* motionState = m_physCtrl->GetMotionState();
+               KX_GameObject* parent = ((KX_GameObject*)GetParent());
+               const MT_Point3& pos = parent->NodeGetWorldPosition();
+               float ori[12];
+               parent->NodeGetWorldOrientation().getValue(ori);
+               motionState->setWorldPosition(pos[0], pos[1], pos[2]);
+               motionState->setWorldOrientation(ori);
+               m_physCtrl->WriteMotionStateToDynamics(true);
+       }
 }
 
 CValue* KX_NearSensor::GetReplica()
 {
        KX_NearSensor* replica = new KX_NearSensor(*this);
-       replica->m_colliders = new CListValue();
-       replica->m_bCollision = false;
-       replica->m_bTriggered= false;
-       replica->m_hitObject = NULL;
-       replica->m_bLastTriggered = false;
-       // this will copy properties and so on...
-       CValue::AddDataToReplica(replica);
-       
-       replica->m_client_info = new KX_ClientObjectInfo(m_client_info->m_gameobject, KX_ClientObjectInfo::NEAR);
-       
-       replica->m_sumoObj = new SM_Object(DT_NewSphere(0.0),NULL,NULL,NULL);
-       replica->m_sumoObj->setMargin(m_Margin);
-       replica->m_sumoObj->setClientObject(replica->m_client_info);
-       
-       replica->SynchronizeTransform();
-       
+       replica->ProcessReplica();
        return replica;
 }
 
-
+void KX_NearSensor::ProcessReplica()
+{
+       KX_TouchSensor::ProcessReplica();
+       
+       m_client_info = new KX_ClientObjectInfo(m_client_info->m_gameobject, KX_ClientObjectInfo::SENSOR);
+       
+       if (m_physCtrl)
+       {
+               m_physCtrl = m_physCtrl->GetReplica();
+               if (m_physCtrl)
+               {
+                       //static_cast<KX_TouchEventManager*>(m_eventmgr)->GetPhysicsEnvironment()->addSensor(replica->m_physCtrl);
+                       m_physCtrl->SetMargin(m_Margin);
+                       m_physCtrl->setNewClientInfo(m_client_info);
+               }
+               
+       }
+}
 
 void KX_NearSensor::ReParent(SCA_IObject* parent)
 {
        SCA_ISensor::ReParent(parent);
-       
        m_client_info->m_gameobject = static_cast<KX_GameObject*>(parent); 
        m_client_info->m_sensors.push_back(this);
-       
+       //Synchronize here with the actual parent.
        SynchronizeTransform();
 }
 
@@ -148,37 +132,38 @@ KX_NearSensor::~KX_NearSensor()
 {
        // for nearsensor, the sensor is the 'owner' of sumoobj
        // for touchsensor, it's the parent
-       if (m_sumoObj)
+       if (m_physCtrl)
        {
-               static_cast<KX_TouchEventManager*>(m_eventmgr)->GetSumoScene()->remove(*m_sumoObj);
-               delete m_sumoObj;
-               m_sumoObj = NULL;
+               //static_cast<KX_TouchEventManager*>(m_eventmgr)->GetPhysicsEnvironment()->removeSensor(m_physCtrl);
+               delete m_physCtrl;
+               m_physCtrl = NULL;
        }
+       
                
        if (m_client_info)
                delete m_client_info;
 }
 
 
-bool KX_NearSensor::Evaluate(CValue* event)
+bool KX_NearSensor::Evaluate()
 {
        bool result = false;
-       // KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent()); /*unused*/
+//     KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent());
 
        if (m_bTriggered != m_bLastTriggered)
        {
                m_bLastTriggered = m_bTriggered;
                if (m_bTriggered)
                {
-                       if (m_sumoObj)
+                       if (m_physCtrl)
                        {
-                               m_sumoObj->setMargin(m_ResetMargin);
+                               m_physCtrl->SetRadius(m_ResetMargin);
                        }
                } else
                {
-                       if (m_sumoObj)
+                       if (m_physCtrl)
                        {
-                               m_sumoObj->setMargin(m_Margin);
+                               m_physCtrl->SetRadius(m_Margin);
                        }
 
                }
@@ -188,18 +173,16 @@ bool KX_NearSensor::Evaluate(CValue* event)
        return result;
 }
 
-
-
-DT_Bool KX_NearSensor::HandleCollision(void* obj1,void* obj2,const DT_CollData * coll_data)
+// this function is called at broad phase stage to check if the two controller
+// need to interact at all. It is used for Near/Radar sensor that don't need to
+// check collision with object not included in filter
+bool   KX_NearSensor::BroadPhaseFilterCollision(void*obj1,void*obj2)
 {
-       // KX_TouchEventManager* toucheventmgr = static_cast<KX_TouchEventManager*>(m_eventmgr); /*unused*/
        KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent());
        
-       // need the mapping from SM_Objects to gameobjects now
-       
-       KX_ClientObjectInfo* client_info =static_cast<KX_ClientObjectInfo*> (obj1 == m_sumoObj? 
-                                       ((SM_Object*)obj2)->getClientObject() : 
-                                       ((SM_Object*)obj1)->getClientObject());
+       // need the mapping from PHY_IPhysicsController to gameobjects now
+       assert(obj1==m_physCtrl && obj2);
+       KX_ClientObjectInfo* client_info = static_cast<KX_ClientObjectInfo*>((static_cast<PHY_IPhysicsController*>(obj2))->getNewClientInfo());
 
        KX_GameObject* gameobj = ( client_info ? 
                        client_info->m_gameobject :
@@ -207,74 +190,104 @@ DT_Bool KX_NearSensor::HandleCollision(void* obj1,void* obj2,const DT_CollData *
        
        if (gameobj && (gameobj != parent))
        {
-               if (!m_colliders->SearchValue(gameobj))
-                       m_colliders->Add(gameobj->AddRef());
                // only take valid colliders
                if (client_info->m_type == KX_ClientObjectInfo::ACTOR)
                {
                        if ((m_touchedpropname.Length() == 0) || 
                                (gameobj->GetProperty(m_touchedpropname)))
                        {
-                               m_bTriggered = true;
-                               m_hitObject = gameobj;
+                               return true;
                        }
                }
        }
+
+       return false;
+}
+
+bool   KX_NearSensor::NewHandleCollision(void* obj1,void* obj2,const PHY_CollData * coll_data)
+{
+//     KX_TouchEventManager* toucheventmgr = static_cast<KX_TouchEventManager*>(m_eventmgr);
+//     KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent());
+       
+       // need the mapping from PHY_IPhysicsController to gameobjects now
        
-       return DT_CONTINUE;
+       KX_ClientObjectInfo* client_info =static_cast<KX_ClientObjectInfo*> (obj1 == m_physCtrl? 
+                                       ((PHY_IPhysicsController*)obj2)->getNewClientInfo() : 
+                                       ((PHY_IPhysicsController*)obj1)->getNewClientInfo());
+
+       KX_GameObject* gameobj = ( client_info ? 
+                       client_info->m_gameobject :
+                       NULL);
+       
+       // Add the same check as in SCA_ISensor::Activate(), 
+       // we don't want to record collision when the sensor is not active.
+       if (m_links && !m_suspended &&
+               gameobj /* done in BroadPhaseFilterCollision() && (gameobj != parent)*/)
+       {
+               if (!m_colliders->SearchValue(gameobj))
+                       m_colliders->Add(gameobj->AddRef());
+               // only take valid colliders
+               // These checks are done already in BroadPhaseFilterCollision()
+               //if (client_info->m_type == KX_ClientObjectInfo::ACTOR)
+               //{
+               //      if ((m_touchedpropname.Length() == 0) || 
+               //              (gameobj->GetProperty(m_touchedpropname)))
+               //      {
+                               m_bTriggered = true;
+                               m_hitObject = gameobj;
+               //      }
+               //}
+       }
+       
+       return false; // was DT_CONTINUE; but this was defined in Sumo as false
 }
 
 
+/* ------------------------------------------------------------------------- */
+/* Python Functions                                                                                                                     */
+/* ------------------------------------------------------------------------- */
+
+//No methods
+
+/* ------------------------------------------------------------------------- */
+/* Python Integration Hooks                                                  */
+/* ------------------------------------------------------------------------- */
 
-// python embedding
 PyTypeObject KX_NearSensor::Type = {
-       PyObject_HEAD_INIT(&PyType_Type)
-       0,
+#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_NearSensor",
-       sizeof(KX_NearSensor),
+       sizeof(PyObjectPlus_Proxy),
        0,
-       PyDestructor,
+       py_base_dealloc,
        0,
-       __getattr,
-       __setattr,
-       0, //&MyPyCompare,
-       __repr,
-       0, //&cvalue_as_number,
        0,
        0,
        0,
-       0
-};
-
-
-
-PyParentObject KX_NearSensor::Parents[] = {
-       &KX_NearSensor::Type,
+       py_base_repr,
+       0,0,0,0,0,0,0,0,0,
+       Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
+       0,0,0,0,0,0,0,
+       Methods,
+       0,
+       0,
        &KX_TouchSensor::Type,
-       &SCA_ISensor::Type,
-       &SCA_ILogicBrick::Type,
-       &CValue::Type,
-       NULL
+       0,0,0,0,0,0,
+       py_base_new
 };
 
-
-
 PyMethodDef KX_NearSensor::Methods[] = {
-       {"setProperty", 
-        (PyCFunction) KX_NearSensor::sPySetProperty,      METH_VARARGS, SetProperty_doc},
-       {"getProperty", 
-        (PyCFunction) KX_NearSensor::sPyGetProperty,      METH_VARARGS, GetProperty_doc},
-       {"getHitObject", 
-        (PyCFunction) KX_NearSensor::sPyGetHitObject,     METH_VARARGS, GetHitObject_doc},
-       {"getHitObjectList", 
-        (PyCFunction) KX_NearSensor::sPyGetHitObjectList, METH_VARARGS, GetHitObjectList_doc},
+       //No methods
        {NULL,NULL} //Sentinel
 };
 
-
-PyObject*
-KX_NearSensor::_getattr(const STR_String& attr)
-{
-  _getattr_up(KX_TouchSensor);
-}
-
+PyAttributeDef KX_NearSensor::Attributes[] = {
+       KX_PYATTRIBUTE_FLOAT_RW_CHECK("distance", 0, 100, KX_NearSensor, m_Margin, CheckResetDistance),
+       KX_PYATTRIBUTE_FLOAT_RW_CHECK("resetDistance", 0, 100, KX_NearSensor, m_ResetMargin, CheckResetDistance),
+       {NULL} //Sentinel
+};