BGE Python API cleanup - no functionality changes
[blender.git] / source / gameengine / Ketsji / KX_TouchSensor.cpp
index 6ae670a842ca7fbf6b737f30446b0d5aefb5b520..79da498474016b50b39c5ebab00821335f8bf2b2 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_TouchSensor.h"
 #include "SCA_LogicManager.h"
 #include "KX_GameObject.h"
 #include "KX_TouchEventManager.h"
-#include "SM_Object.h"
-#include "KX_SumoPhysicsController.h"
+
+#include "PHY_IPhysicsController.h"
+
 #include <iostream>
+#include "PHY_IPhysicsEnvironment.h"
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 
 void KX_TouchSensor::SynchronizeTransform()
 {
-
-       if (m_sumoObj)
-       {
-               m_sumoObj->setPosition(((KX_GameObject*)GetParent())->NodeGetWorldPosition());
-               m_sumoObj->setOrientation(
-                       ((KX_GameObject*)GetParent())->NodeGetWorldOrientation().getRotation()
-                       );
-               m_sumoObj->calcXform();
-       }
-       
+       // the touch sensor does not require any synchronization: it uses
+       // the same physical object which is already synchronized by Blender
 }
 
 
 void KX_TouchSensor::EndFrame() {
        m_colliders->ReleaseAndRemoveAll();
+       m_hitObject = NULL;
        m_bTriggered = false;
+       m_bColliderHash = 0;
+}
+
+void KX_TouchSensor::UnregisterToManager()
+{
+       // before unregistering the sensor, make sure we release all references
+       EndFrame();
+       m_eventmgr->RemoveSensor(this);
 }
 
 bool KX_TouchSensor::Evaluate(CValue* event)
 {
        bool result = false;
-
+       bool reset = m_reset && m_level;
+       m_reset = false;
        if (m_bTriggered != m_bLastTriggered)
        {
                m_bLastTriggered = m_bTriggered;
@@ -80,38 +81,57 @@ bool KX_TouchSensor::Evaluate(CValue* event)
                        m_hitObject = NULL;
                result = true;
        }
+       if (reset)
+               // force an event
+               result = true;
        
+       if (m_bTouchPulse) { /* pulse on changes to the colliders */
+               int count = m_colliders->GetCount();
+               
+               if (m_bLastCount!=count || m_bColliderHash!=m_bLastColliderHash) {
+                       m_bLastCount = count;
+                       m_bLastColliderHash= m_bColliderHash;
+                       result = true;
+               }
+       }
        return result;
 }
 
-KX_TouchSensor::KX_TouchSensor(SCA_EventManager* eventmgr,KX_GameObject* gameobj,/*SM_Object* sumoObj,*/bool bFindMaterial,const STR_String& touchedpropname,PyTypeObject* T)
+KX_TouchSensor::KX_TouchSensor(SCA_EventManager* eventmgr,KX_GameObject* gameobj,bool bFindMaterial,bool bTouchPulse,const STR_String& touchedpropname,PyTypeObject* T)
 :SCA_ISensor(gameobj,eventmgr,T),
 m_touchedpropname(touchedpropname),
 m_bFindMaterial(bFindMaterial),
-m_eventmgr(eventmgr),
+m_bTouchPulse(bTouchPulse),
+m_eventmgr(eventmgr)
 /*m_sumoObj(sumoObj),*/
-m_bCollision(false),
-m_bTriggered(false),
-m_bLastTriggered(false)
 {
-       KX_TouchEventManager* touchmgr = (KX_TouchEventManager*) eventmgr;
+//     KX_TouchEventManager* touchmgr = (KX_TouchEventManager*) eventmgr;
 //     m_resptable = touchmgr->GetResponseTable();
        
 //     m_solidHandle = m_sumoObj->getObjectHandle();
 
-       m_hitObject =  NULL;
        m_colliders = new CListValue();
        
        KX_ClientObjectInfo *client_info = gameobj->getClientInfo();
-       client_info->m_clientobject = gameobj;
-       client_info->m_auxilary_info = NULL;
+       //client_info->m_gameobject = gameobj;
+       //client_info->m_auxilary_info = NULL;
+       client_info->m_sensors.push_back(this);
        
-       KX_SumoPhysicsController *sphy = dynamic_cast<KX_SumoPhysicsController *>(gameobj->GetPhysicsController());
-       if (sphy)
-               m_sumoObj = sphy->GetSumoObject();
-
+       m_physCtrl = dynamic_cast<PHY_IPhysicsController*>(gameobj->GetPhysicsController());
+       MT_assert( !gameobj->GetPhysicsController() || m_physCtrl );
+       Init();
 }
 
+void KX_TouchSensor::Init()
+{
+       m_bCollision = false;
+       m_bTriggered = false;
+       m_bLastTriggered = (m_invert)?true:false;
+       m_bLastCount = 0;
+       m_bColliderHash = m_bLastColliderHash = 0;
+       m_hitObject =  NULL;
+       m_reset = true;
+}
 
 KX_TouchSensor::~KX_TouchSensor()
 {
@@ -119,50 +139,71 @@ KX_TouchSensor::~KX_TouchSensor()
        m_colliders->Release();
 }
 
+CValue* KX_TouchSensor::GetReplica() 
+{
+       KX_TouchSensor* replica = new KX_TouchSensor(*this);
+       replica->m_colliders = new CListValue();
+       replica->Init();
+       // this will copy properties and so on...
+       CValue::AddDataToReplica(replica);
+       return replica;
+}
+
 void   KX_TouchSensor::ReParent(SCA_IObject* parent)
 {
        KX_GameObject *gameobj = static_cast<KX_GameObject *>(parent);
-       KX_SumoPhysicsController *sphy = dynamic_cast<KX_SumoPhysicsController *>(((KX_GameObject*)parent)->GetPhysicsController());
+       PHY_IPhysicsController *sphy = dynamic_cast<PHY_IPhysicsController*>(((KX_GameObject*)parent)->GetPhysicsController());
        if (sphy)
-               m_sumoObj = sphy->GetSumoObject();
-
+               m_physCtrl = sphy;
+       
 //     m_solidHandle = m_sumoObj->getObjectHandle();
        KX_ClientObjectInfo *client_info = gameobj->getClientInfo();
-       client_info->m_clientobject = parent;
-       client_info->m_auxilary_info = NULL;
+       //client_info->m_gameobject = gameobj;
+       //client_info->m_auxilary_info = NULL;
+       
+       client_info->m_sensors.push_back(this);
        SCA_ISensor::ReParent(parent);
 }
 
 void KX_TouchSensor::RegisterSumo(KX_TouchEventManager *touchman)
 {
-       if (m_sumoObj)
+       if (m_physCtrl)
        {
-               touchman->GetSumoScene()->requestCollisionCallback(*m_sumoObj);
+               touchman->GetPhysicsEnvironment()->requestCollisionCallback(m_physCtrl);
                // collision
                // Deprecated   
 
        }
 }
 
-DT_Bool    KX_TouchSensor::HandleCollision(void* obj1,void* obj2,const DT_CollData * coll_data)
+void KX_TouchSensor::UnregisterSumo(KX_TouchEventManager* touchman)
 {
-       KX_TouchEventManager* toucheventmgr = (KX_TouchEventManager*)m_eventmgr;
+       if (m_physCtrl)
+       {
+               touchman->GetPhysicsEnvironment()->removeCollisionCallback(m_physCtrl);
+       }
+}
+
+bool   KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_CollData* colldata)
+{
+//     KX_TouchEventManager* toucheventmgr = (KX_TouchEventManager*)m_eventmgr;
        KX_GameObject* parent = (KX_GameObject*)GetParent();
 
-       // need the mapping from SM_Objects to gameobjects now
+       // need the mapping from PHY_IPhysicsController to gameobjects now
        
-       KX_ClientObjectInfo* client_info =(KX_ClientObjectInfo*) (obj1 == m_sumoObj
-                                       ((SM_Object*)obj2)->getClientObject() 
-                                       ((SM_Object*)obj1)->getClientObject());
+       KX_ClientObjectInfo* client_info = static_cast<KX_ClientObjectInfo*> (object1 == m_physCtrl
+                                       ((PHY_IPhysicsController*)object2)->getNewClientInfo()
+                                       ((PHY_IPhysicsController*)object1)->getNewClientInfo());
 
        KX_GameObject* gameobj = ( client_info ? 
-                       (KX_GameObject*)client_info->m_clientobject : 
+                       client_info->m_gameobject : 
                        NULL);
        
-       if (gameobj && (gameobj != parent))
+       // 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 && (gameobj != parent) && client_info->isActor())
        {
-               if (!m_colliders->SearchValue(gameobj))
-                       m_colliders->Add(gameobj->AddRef());
                
                bool found = m_touchedpropname.IsEmpty();
                if (!found)
@@ -171,14 +212,8 @@ DT_Bool    KX_TouchSensor::HandleCollision(void* obj1,void* obj2,const DT_CollDa
                        {
                                if (client_info->m_auxilary_info)
                                {
-                                       found = (m_touchedpropname == ((char*)client_info->m_auxilary_info));
+                                       found = (!strcmp(m_touchedpropname.Ptr(), (char*)client_info->m_auxilary_info));
                                }
-
-                               if (found)
-                               {
-                                       int i=0;
-                               }
-
                        } else
                        {
                                found = (gameobj->GetProperty(m_touchedpropname) != NULL);
@@ -186,13 +221,19 @@ DT_Bool    KX_TouchSensor::HandleCollision(void* obj1,void* obj2,const DT_CollDa
                }
                if (found)
                {
+                       if (!m_colliders->SearchValue(gameobj)) {
+                               m_colliders->Add(gameobj->AddRef());
+                               
+                               if (m_bTouchPulse)
+                                       m_bColliderHash += (uint_ptr)(static_cast<void *>(&gameobj));
+                       }
                        m_bTriggered = true;
                        m_hitObject = gameobj;
                        //printf("KX_TouchSensor::HandleCollision\n");
                }
                
        } 
-       return DT_CONTINUE;
+       return false; // was DT_CONTINUE but this was defined in sumo as false.
 }
 
 
@@ -201,22 +242,22 @@ DT_Bool    KX_TouchSensor::HandleCollision(void* obj1,void* obj2,const DT_CollDa
 /* ------------------------------------------------------------------------- */
 /* Integration hooks ------------------------------------------------------- */
 PyTypeObject KX_TouchSensor::Type = {
-       PyObject_HEAD_INIT(&PyType_Type)
+       PyObject_HEAD_INIT(NULL)
        0,
        "KX_TouchSensor",
-       sizeof(KX_TouchSensor),
+       sizeof(PyObjectPlus_Proxy),
        0,
-       PyDestructor,
+       py_base_dealloc,
        0,
-       __getattr,
-       __setattr,
-       0, //&MyPyCompare,
-       __repr,
-       0, //&cvalue_as_number,
        0,
        0,
        0,
-       0
+       py_base_repr,
+       0,0,0,0,0,0,
+       py_base_getattro,
+       py_base_setattro,
+       0,0,0,0,0,0,0,0,0,
+       Methods
 };
 
 PyParentObject KX_TouchSensor::Parents[] = {
@@ -228,174 +269,146 @@ PyParentObject KX_TouchSensor::Parents[] = {
 };
 
 PyMethodDef KX_TouchSensor::Methods[] = {
+       //Deprecated ----->
        {"setProperty", 
-        (PyCFunction) KX_TouchSensor::sPySetProperty,      METH_VARARGS, SetProperty_doc},
+        (PyCFunction) KX_TouchSensor::sPySetProperty,      METH_O, (PY_METHODCHAR)SetProperty_doc},
        {"getProperty", 
-        (PyCFunction) KX_TouchSensor::sPyGetProperty,      METH_VARARGS, GetProperty_doc},
+        (PyCFunction) KX_TouchSensor::sPyGetProperty,      METH_NOARGS, (PY_METHODCHAR)GetProperty_doc},
        {"getHitObject", 
-        (PyCFunction) KX_TouchSensor::sPyGetHitObject,     METH_VARARGS, GetHitObject_doc},
+        (PyCFunction) KX_TouchSensor::sPyGetHitObject,     METH_NOARGS, (PY_METHODCHAR)GetHitObject_doc},
        {"getHitObjectList", 
-        (PyCFunction) KX_TouchSensor::sPyGetHitObjectList, METH_VARARGS, GetHitObjectList_doc},
+        (PyCFunction) KX_TouchSensor::sPyGetHitObjectList, METH_NOARGS, (PY_METHODCHAR)GetHitObjectList_doc},
+        //<-----
        {NULL,NULL} //Sentinel
 };
 
-PyObject* KX_TouchSensor::_getattr(char* attr) {
-       _getattr_up(SCA_ISensor);
+PyAttributeDef KX_TouchSensor::Attributes[] = {
+       KX_PYATTRIBUTE_STRING_RW("property",0,100,false,KX_TouchSensor,m_touchedpropname),
+       KX_PYATTRIBUTE_BOOL_RW("useMaterial",KX_TouchSensor,m_bFindMaterial),
+       KX_PYATTRIBUTE_BOOL_RW("pulseCollisions",KX_TouchSensor,m_bTouchPulse),
+       KX_PYATTRIBUTE_RO_FUNCTION("objectHit", KX_TouchSensor, pyattr_get_object_hit),
+       KX_PYATTRIBUTE_RO_FUNCTION("objectHitList", KX_TouchSensor, pyattr_get_object_hit_list),
+       { NULL }        //Sentinel
+};
+
+PyObject* KX_TouchSensor::py_getattro(PyObject *attr)
+{
+       py_getattro_up(SCA_ISensor);
+}
+
+int KX_TouchSensor::py_setattro(PyObject *attr, PyObject *value)
+{
+       py_setattro_up(SCA_ISensor);
 }
 
 /* Python API */
 
 /* 1. setProperty */
-char KX_TouchSensor::SetProperty_doc[] = 
+const char KX_TouchSensor::SetProperty_doc[] = 
 "setProperty(name)\n"
 "\t- name: string\n"
 "\tSet the property or material to collide with. Use\n"
 "\tsetTouchMaterial() to switch between properties and\n"
 "\tmaterials.";
-PyObject* KX_TouchSensor::PySetProperty(PyObject* self, 
-                                                                               PyObject* args, 
-                                                                               PyObject* kwds) {
-       char *nameArg;
-       if (!PyArg_ParseTuple(args, "s", &nameArg)) {
+PyObject* KX_TouchSensor::PySetProperty(PyObject* self, PyObject* value)
+{
+       ShowDeprecationWarning("setProperty()", "the propertyName property");
+       char *nameArg= PyString_AsString(value);
+       if (nameArg==NULL) {
+               PyErr_SetString(PyExc_ValueError, "expected a ");
                return NULL;
        }
-
-       CValue* prop = GetParent()->FindIdentifier(nameArg);
-
-       if (!prop->IsError()) {
-               m_touchedpropname = nameArg;
-               prop->Release();
-       } else {
-               ; /* not found ... */
-       }
        
-       Py_Return;
+       m_touchedpropname = nameArg;
+       Py_RETURN_NONE;
 }
 /* 2. getProperty */
-char KX_TouchSensor::GetProperty_doc[] = 
+const char KX_TouchSensor::GetProperty_doc[] = 
 "getProperty(name)\n"
 "\tReturns the property or material to collide with. Use\n"
 "\tgetTouchMaterial() to find out whether this sensor\n"
 "\tlooks for properties or materials.";
-PyObject*  KX_TouchSensor::PyGetProperty(PyObject* self, 
-                                                                                PyObject* args, 
-                                                                                PyObject* kwds) {
+PyObject*  KX_TouchSensor::PyGetProperty(PyObject* self) {
        return PyString_FromString(m_touchedpropname);
 }
 
-char KX_TouchSensor::GetHitObject_doc[] = 
+const char KX_TouchSensor::GetHitObject_doc[] = 
 "getHitObject()\n"
 ;
-PyObject* KX_TouchSensor::PyGetHitObject(PyObject* self, 
-                                                                                PyObject* args, 
-                                                                                PyObject* kwds)
+PyObject* KX_TouchSensor::PyGetHitObject(PyObject* self)
 {
+       ShowDeprecationWarning("getHitObject()", "the objectHit property");
        /* to do: do Py_IncRef if the object is already known in Python */
        /* otherwise, this leaks memory */
        if (m_hitObject)
        {
-               return m_hitObject->AddRef();
+               return m_hitObject->GetProxy();
        }
-       Py_Return;
+       Py_RETURN_NONE;
 }
 
-char KX_TouchSensor::GetHitObjectList_doc[] = 
+const char KX_TouchSensor::GetHitObjectList_doc[] = 
 "getHitObjectList()\n"
 "\tReturn a list of the objects this object collided with,\n"
 "\tbut only those matching the property/material condition.\n";
-PyObject* KX_TouchSensor::PyGetHitObjectList(PyObject* self, 
-                                                                                PyObject* args, 
-                                                                                PyObject* kwds)
+PyObject* KX_TouchSensor::PyGetHitObjectList(PyObject* self)
 {
-
+       ShowDeprecationWarning("getHitObjectList()", "the objectHitList property");
        /* to do: do Py_IncRef if the object is already known in Python */
-       /* otherwise, this leaks memory */
-
-       if ( m_touchedpropname.IsEmpty() ) {
-               return m_colliders->AddRef();
-       } else {
-               CListValue* newList = new CListValue();
-               int i = 0;
-               while (i < m_colliders->GetCount()) {
-                       if (m_bFindMaterial) {
-                               /* need to associate the CValues from the list to material
-                                * names. The collider list _should_ contains only
-                                * KX_GameObjects. I am loathe to cast them, though... The
-                                * material name must be retrieved from Sumo. To a Sumo
-                                * object, a client-info block is attached. This block
-                                * contains the material name. 
-                                * - this also doesn't work (obviously) for multi-materials... 
-                                */
-                               KX_GameObject* gameob = (KX_GameObject*) m_colliders->GetValue(i);
-                               KX_SumoPhysicsController* spc = dynamic_cast<KX_SumoPhysicsController*>(gameob->GetPhysicsController());
-                               SM_Object* smob = spc?spc->GetSumoObject():NULL;
-                               
-                               if (smob) {
-                                       KX_ClientObjectInfo* cl_inf = (KX_ClientObjectInfo*) smob->getClientObject();
-                                       
-                                       if (m_touchedpropname == ((char*)cl_inf->m_auxilary_info)) {
-                                               newList->Add(m_colliders->GetValue(i)->AddRef());
-                                       } 
-                               }
-                               
-                       } else {
-                               CValue* val = m_colliders->GetValue(i)->FindIdentifier(m_touchedpropname);
-                               if (!val->IsError()) {
-                                       newList->Add(m_colliders->GetValue(i)->AddRef());
-                                       val->Release();
-                               }
-                       }
-                       
-                       i++;
-               }
-               return newList->AddRef();
-       }
-
+       /* otherwise, this leaks memory */ /* Edit, this seems ok and not to leak memory - Campbell */
+       return m_colliders->GetProxy();
 }
 
+/*getTouchMaterial and setTouchMaterial were never added to the api,
+they can probably be removed with out anyone noticing*/
+
 /* 5. getTouchMaterial */
-char KX_TouchSensor::GetTouchMaterial_doc[] = 
+const char KX_TouchSensor::GetTouchMaterial_doc[] = 
 "getTouchMaterial()\n"
 "\tReturns KX_TRUE if this sensor looks for a specific material,\n"
 "\tKX_FALSE if it looks for a specific property.\n" ;
-PyObject* KX_TouchSensor::PyGetTouchMaterial(PyObject* self, 
-                                                                                        PyObject* args, 
-                                                                                        PyObject* kwds)
+PyObject* KX_TouchSensor::PyGetTouchMaterial(PyObject* self)
 {
-       int retval = 0;
-       
-       if (m_bFindMaterial) {
-               retval = KX_TRUE;
-       } else {
-               retval = KX_FALSE;
-       }
-
-       return PyInt_FromLong(retval);
+       ShowDeprecationWarning("getTouchMaterial()", "the materialCheck property");
+       return PyInt_FromLong(m_bFindMaterial);
 }
 
 /* 6. setTouchMaterial */
-char KX_TouchSensor::SetTouchMaterial_doc[] = 
+#if 0
+const char KX_TouchSensor::SetTouchMaterial_doc[] = 
 "setTouchMaterial(flag)\n"
 "\t- flag: KX_TRUE or KX_FALSE.\n"
 "\tSet flag to KX_TRUE to switch on positive pulse mode,\n"
 "\tKX_FALSE to switch off positive pulse mode.\n" ;
-PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject* self, PyObject* args, PyObject* kwds)
+PyObject* KX_TouchSensor::PySetTouchMaterial(PyObject* self, PyObject *value)
 {
-       int pulseArg = 0;
+       int pulseArg = PyInt_AsLong(value);
 
-       if(!PyArg_ParseTuple(args, "i", &pulseArg)) {
+       if(pulseArg ==-1 && PyErr_Occurred()) {
+               PyErr_SetString(PyExc_ValueError, "expected a bool");
                return NULL;
        }
        
-       if (pulseArg == KX_TRUE) {
-               m_bFindMaterial = true;
-       } else if (pulseArg == KX_FALSE){
-               m_bFindMaterial = false;
-       } else {
-               ; /* internal error */
-       }
+       m_bFindMaterial = pulseArg != 0;
 
-       Py_Return;
+       Py_RETURN_NONE;
+}
+#endif
+
+PyObject* KX_TouchSensor::pyattr_get_object_hit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       KX_TouchSensor* self= static_cast<KX_TouchSensor*>(self_v);
+       
+       if (self->m_hitObject)
+               return self->m_hitObject->GetProxy();
+       else
+               Py_RETURN_NONE;
+}
+
+PyObject* KX_TouchSensor::pyattr_get_object_hit_list(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       KX_TouchSensor* self= static_cast<KX_TouchSensor*>(self_v);
+       return self->m_colliders->GetProxy();
 }