New Pulse option for the collision sensor (off by default wont change existing logic)
authorCampbell Barton <ideasman42@gmail.com>
Wed, 25 Feb 2009 17:19:30 +0000 (17:19 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 25 Feb 2009 17:19:30 +0000 (17:19 +0000)
Previously only the first collision would trigger an event (no collisions a negative event ofcourse)

With the Pulse option enabled, any change to the set of colliding objects will trigger an event.

Added this because there was no way to count how many sheep were on a platform in YoFrankie without running a script periodically.

Changes in collision are detected by comparing the number of objects colliding with the last event, as well as a hash made from the object pointers.

Also changed the touch sensors internal list of colliding objects to only contain objects that match the property or material.

- pulse isnt a great name, could change this.

source/blender/makesdna/DNA_sensor_types.h
source/blender/src/buttons_logic.c
source/gameengine/Converter/KX_ConvertSensors.cpp
source/gameengine/Ketsji/KX_NearSensor.cpp
source/gameengine/Ketsji/KX_TouchSensor.cpp
source/gameengine/Ketsji/KX_TouchSensor.h

index d8a1ffc6c2429c47f19672a12071c40ac8db4fcf..2cae2cc8ccbd4112faa427954b1a0306391b35be 100644 (file)
@@ -238,6 +238,7 @@ typedef struct bJoystickSensor {
  * */
 /*  #define SENS_COLLISION_PROPERTY 0  */
 #define SENS_COLLISION_MATERIAL 1
+#define SENS_COLLISION_PULSE 2
 /* ray specific mode */
 /* X-Ray means that the ray will traverse objects that don't have the property/material */
 #define SENS_RAY_XRAY                  2
index 494dc05d8f95dca3b18b2b36f2ebde7ab1f313bf..775175ba3328a2e775974f5d38ad303a8d18ab5c 100644 (file)
@@ -1131,17 +1131,21 @@ static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short
                        /* The collision sensor will become a generic collision (i.e. it     */
                        /* absorb the old touch sensor).                                     */
 
-                       uiDefButBitS(block, TOG, SENS_COLLISION_MATERIAL, B_REDR, "M/P",(short)(xco + 10),(short)(yco - 44),
+                       uiDefButBitS(block, TOG, SENS_COLLISION_PULSE, B_REDR, "Pulse",(short)(xco + 10),(short)(yco - 44),
+                               (short)(0.20 * (width-20)), 19, &cs->mode, 0.0, 0.0, 0, 0,
+                               "Changes to the set of colliding objects generate pulses");
+                       
+                       uiDefButBitS(block, TOG, SENS_COLLISION_MATERIAL, B_REDR, "M/P",(short)(xco + 10 + (0.20 * (width-20))),(short)(yco - 44),
                                (short)(0.20 * (width-20)), 19, &cs->mode, 0.0, 0.0, 0, 0,
                                "Toggle collision on material or property.");
                        
                        if (cs->mode & SENS_COLLISION_MATERIAL) {
-                               uiDefBut(block, TEX, 1, "Material:", (short)(xco + 10 + 0.20 * (width-20)),
-                                       (short)(yco-44), (short)(0.8*(width-20)), 19, &cs->materialName, 0, 31, 0, 0,
+                               uiDefBut(block, TEX, 1, "Material:", (short)(xco + 10 + 0.40 * (width-20)),
+                                       (short)(yco-44), (short)(0.6*(width-20)), 19, &cs->materialName, 0, 31, 0, 0,
                                        "Only look for Objects with this material");
                        } else {
-                               uiDefBut(block, TEX, 1, "Property:", (short)(xco + 10 + 0.20 * (width-20)), (short)(yco-44),
-                                       (short)(0.8*(width-20)), 19, &cs->name, 0, 31, 0, 0,
+                               uiDefBut(block, TEX, 1, "Property:", (short)(xco + 10 + 0.40 * (width-20)), (short)(yco-44),
+                                       (short)(0.6*(width-20)), 19, &cs->name, 0, 31, 0, 0,
                                        "Only look for Objects with this property");
                        }
        
index 13b7f43195d7d15f163568392f17aaa07c77d9ca..c9b51807767963ff2064414aca76c1c8b3b9e0de 100644 (file)
@@ -306,12 +306,12 @@ void BL_ConvertSensors(struct Object* blenderobject,
                                {
                                        // collision sensor can sense both materials and properties. 
                                        
-                                       bool bFindMaterial = false;
+                                       bool bFindMaterial = false, bTouchPulse = false;
                                        
                                        bCollisionSensor* blendertouchsensor = (bCollisionSensor*)sens->data;
                                        
-                                       bFindMaterial = (blendertouchsensor->mode 
-                                               & SENS_COLLISION_MATERIAL);
+                                       bFindMaterial = (blendertouchsensor->mode & SENS_COLLISION_MATERIAL);
+                                       bTouchPulse = (blendertouchsensor->mode & SENS_COLLISION_PULSE);
                                        
                                        
                                        STR_String touchPropOrMatName = ( bFindMaterial ? 
@@ -324,6 +324,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
                                                gamesensor = new KX_TouchSensor(eventmgr,
                                                        gameobj,
                                                        bFindMaterial,
+                                                       bTouchPulse,
                                                        touchPropOrMatName);
                                        }
                                        
@@ -349,6 +350,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
                                                gamesensor = new KX_TouchSensor(eventmgr,
                                                        gameobj,
                                                        bFindMaterial,
+                                                       false,
                                                        touchpropertyname);
                                        }
                                }
index 5b1df8b1fe140fb4e75c70633de412e05c62ec51..a4aebdd8b6b155c6c655b08b2bab11ee37b40904 100644 (file)
@@ -52,6 +52,7 @@ KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr,
                         :KX_TouchSensor(eventmgr,
                                                         gameobj,
                                                         bFindMaterial,
+                                                        false,
                                                         touchedpropname,
                                                         /* scene, */
                                                         T),
index 0b4d66dbb3444704c542a4663fa08f5edd989a6d..a30dc34e2fa8d92e073a05767bf362aee8b810ab 100644 (file)
@@ -59,6 +59,7 @@ void KX_TouchSensor::EndFrame() {
        m_colliders->ReleaseAndRemoveAll();
        m_hitObject = NULL;
        m_bTriggered = false;
+       m_bColliderHash = 0;
 }
 
 void KX_TouchSensor::UnregisterToManager()
@@ -72,7 +73,6 @@ bool KX_TouchSensor::Evaluate(CValue* event)
 {
        bool result = false;
        bool reset = m_reset && m_level;
-
        m_reset = false;
        if (m_bTriggered != m_bLastTriggered)
        {
@@ -84,13 +84,24 @@ bool KX_TouchSensor::Evaluate(CValue* event)
        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,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_bTouchPulse(bTouchPulse),
 m_eventmgr(eventmgr)
 /*m_sumoObj(sumoObj),*/
 {
@@ -116,6 +127,8 @@ 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;
 }
@@ -191,8 +204,6 @@ bool        KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_Coll
        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)
@@ -210,6 +221,12 @@ bool       KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_Coll
                }
                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");
@@ -334,46 +351,7 @@ PyObject* KX_TouchSensor::PyGetHitObjectList(PyObject* self,
 
        /* 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);
-                               PHY_IPhysicsController* spc = dynamic_cast<PHY_IPhysicsController*>(gameob->GetPhysicsController());
-                               
-                               if (spc) {
-                                       KX_ClientObjectInfo* cl_inf = static_cast<KX_ClientObjectInfo*>(spc->getNewClientInfo());
-                                       
-                                       if (NULL != cl_inf->m_auxilary_info && 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();
-       }
-
+       return m_colliders->AddRef();
 }
 
 /* 5. getTouchMaterial */
index e07f89f0a3174da6fdae9f838be2ffc753919130..c463226a5be534aeb5466e8567d468e4cf6e1952 100644 (file)
@@ -39,6 +39,12 @@ struct PHY_CollData;
 
 #include "KX_ClientObjectInfo.h"
 
+#if defined(_WIN64)
+typedef unsigned __int64 uint_ptr;
+#else
+typedef unsigned long uint_ptr;
+#endif
+
 class KX_TouchEventManager;
 
 class KX_TouchSensor : public SCA_ISensor
@@ -51,6 +57,7 @@ protected:
         */
        STR_String                              m_touchedpropname;      
        bool                                    m_bFindMaterial;
+       bool                                    m_bTouchPulse;          /* changes in the colliding objects trigger pulses */
        class SCA_EventManager* m_eventmgr;
        
        class PHY_IPhysicsController*   m_physCtrl;
@@ -58,13 +65,20 @@ protected:
        bool                                    m_bCollision;
        bool                                    m_bTriggered;
        bool                                    m_bLastTriggered;
+
+       // Use with m_bTouchPulse to detect changes
+       int                                             m_bLastCount;           /* size of m_colliders last tick */
+       uint_ptr                                m_bColliderHash;        /* hash collision objects pointers to trigger incase one object collides and another takes its place */
+       uint_ptr                                m_bLastColliderHash;
+
        SCA_IObject*                m_hitObject;
        class CListValue*               m_colliders;
        
 public:
        KX_TouchSensor(class SCA_EventManager* eventmgr,
                class KX_GameObject* gameobj,
-               bool fFindMaterial,
+               bool bFindMaterial,
+               bool bTouchPulse,
                const STR_String& touchedpropname,
                PyTypeObject* T=&Type) ;
        virtual ~KX_TouchSensor();