BGE state system improvement: the sensor with Level option enabled will trigger the controller of a newly activated state, even if the sensor is already connected to an active state; new isTriggered() python function to determine which sensor triggered the current controller.

Previously, this behaviour was available only for sensors
that were not connected to any active state, which was
forcing the game designer to duplicate sensors in some 
cases.
For example the Always sensors used to initialize the 
states needed to be duplicated for each state. With this
patch, a single Always sensor with Level option enabled
will suffice to initialize all the states. 
A Python controller can determine which sensor did trigger
with the new SCA_ISensor::isTriggered() function.

Notes:
- When a sensor with level option enabled is connected
  to multiple controllers, only those of newly activated
  states will be triggered. The controllers of already
  activated states will receive no trigger, unless the 
  sensor internal state toggled, in which case all the
  controllers are triggered as always.
- The old isPositive() function returns the internal
  state of the sensor, positive or negative; the new 
  isTriggered() function returns 1 only for sensors
  that generated an event in the current frame.
This commit is contained in:
2008-08-23 11:54:27 +00:00
parent 2076703a28
commit bc8f002a4c
9 changed files with 100 additions and 19 deletions

View File

@@ -188,6 +188,8 @@ void SCA_IController::ApplyState(unsigned int state)
for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit)
{
(*sensit)->IncLink();
// remember that this controller just activated that sensor
(*sensit)->AddNewController(this);
}
SetActive(true);
}

View File

@@ -32,6 +32,8 @@
#include "SCA_ISensor.h"
#include "SCA_EventManager.h"
#include "SCA_LogicManager.h"
// needed for IsTriggered()
#include "SCA_PythonController.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -132,10 +134,8 @@ void SCA_ISensor::DecLink() {
}
if (!m_links)
{
// sensor is detached from all controllers, initialize it so that it
// is fresh as at startup when it is reattached again.
// sensor is detached from all controllers, remove it from manager
UnregisterToManager();
Init();
}
}
@@ -168,7 +168,9 @@ PyParentObject SCA_ISensor::Parents[] = {
};
PyMethodDef SCA_ISensor::Methods[] = {
{"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive,
METH_VARARGS, IsPositive_doc},
METH_NOARGS, IsPositive_doc},
{"isTriggered", (PyCFunction) SCA_ISensor::sPyIsTriggered,
METH_VARARGS, IsTriggered_doc},
{"getUsePosPulseMode", (PyCFunction) SCA_ISensor::sPyGetUsePosPulseMode,
METH_NOARGS, GetUsePosPulseMode_doc},
{"setUsePosPulseMode", (PyCFunction) SCA_ISensor::sPySetUsePosPulseMode,
@@ -204,6 +206,9 @@ SCA_ISensor::_getattr(const STR_String& attr)
void SCA_ISensor::RegisterToManager()
{
// sensor is just activated, initialize it
Init();
m_newControllers.erase(m_newControllers.begin(), m_newControllers.end());
m_eventmgr->RegisterSensor(this);
}
@@ -249,19 +254,47 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event)
}
}
}
if (!m_newControllers.empty())
{
if (!IsActive() && m_level)
{
// This level sensor is connected to at least one controller that was just made
// active but it did not generate an event yet, do it now to those controllers only
for (std::vector<SCA_IController*>::iterator ci=m_newControllers.begin();
ci != m_newControllers.end(); ci++)
{
logicmgr->AddTriggeredController(*ci, this);
}
}
// clear the list. Instead of using clear, which also release the memory,
// use erase, which keeps the memory available for next time.
m_newControllers.erase(m_newControllers.begin(), m_newControllers.end());
}
}
}
/* Python functions: */
char SCA_ISensor::IsPositive_doc[] =
"isPositive()\n"
"\tReturns whether the sensor is registered a positive event.\n";
PyObject* SCA_ISensor::PyIsPositive(PyObject* self, PyObject* args, PyObject* kwds)
"\tReturns whether the sensor is in an active state.\n";
PyObject* SCA_ISensor::PyIsPositive(PyObject* self)
{
int retval = IsPositiveTrigger();
return PyInt_FromLong(retval);
}
char SCA_ISensor::IsTriggered_doc[] =
"isTriggered()\n"
"\tReturns whether the sensor has triggered the current controller.\n";
PyObject* SCA_ISensor::PyIsTriggered(PyObject* self)
{
// check with the current controller
int retval = 0;
if (SCA_PythonController::m_sCurrentController)
retval = SCA_PythonController::m_sCurrentController->IsTriggered(this);
return PyInt_FromLong(retval);
}
/**
* getUsePulseMode: getter for the pulse mode (KX_TRUE = on)
*/

View File

@@ -34,6 +34,8 @@
#include "SCA_ILogicBrick.h"
#include <vector>
/**
* Interface Class for all logic Sensors. Implements
* pulsemode,pulsefrequency */
@@ -73,9 +75,9 @@ class SCA_ISensor : public SCA_ILogicBrick
/** number of connections to controller */
int m_links;
/** Pass the activation on to the logic manager.*/
void SignalActivation(class SCA_LogicManager* logicmgr);
/** list of controllers that have just activated this sensor because of a state change */
std::vector<class SCA_IController*> m_newControllers;
public:
SCA_ISensor(SCA_IObject* gameobj,
class SCA_EventManager* eventmgr,
@@ -128,6 +130,8 @@ public:
/** Resume sensing. */
void Resume();
void AddNewController(class SCA_IController* controller)
{ m_newControllers.push_back(controller); }
void ClrLink()
{ m_links = 0; }
void IncLink()
@@ -137,7 +141,8 @@ public:
{ return !m_links; }
/* Python functions: */
KX_PYMETHOD_DOC(SCA_ISensor,IsPositive);
KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsPositive);
KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,IsTriggered);
KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetUsePosPulseMode);
KX_PYMETHOD_DOC(SCA_ISensor,SetUsePosPulseMode);
KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetFrequency);

View File

@@ -505,7 +505,7 @@ PyObject* SCA_KeyboardSensor::sPySetAllMode(PyObject* self,
PyObject* kwds)
{
// printf("sPyIsPositive\n");
return ((SCA_KeyboardSensor*) self)->PyIsPositive(self, args, kwds);
return ((SCA_KeyboardSensor*) self)->PyIsPositive(self);
}

View File

@@ -33,6 +33,7 @@
#include "SCA_IController.h"
#include "SCA_IActuator.h"
#include "SCA_EventManager.h"
#include "SCA_PythonController.h"
#include <set>
#ifdef HAVE_CONFIG_H
@@ -232,8 +233,6 @@ void SCA_LogicManager::BeginFrame(double curtime, double fixedtime)
// for this frame, look up for activated sensors, and build the collection of triggered controllers
// int numsensors = this->m_activatedsensors.size(); /*unused*/
set<SmartControllerPtr> triggeredControllerSet;
for (vector<SCA_ISensor*>::const_iterator is=m_activatedsensors.begin();
!(is==m_activatedsensors.end());is++)
{
@@ -244,19 +243,28 @@ void SCA_LogicManager::BeginFrame(double curtime, double fixedtime)
{
SCA_IController* contr = *c;//controllerarray->at(c);
if (contr->IsActive())
triggeredControllerSet.insert(SmartControllerPtr(contr,0));
{
m_triggeredControllerSet.insert(SmartControllerPtr(contr,0));
// So that the controller knows which sensor has activited it.
// Only needed for the python controller though.
if (contr->GetType() == &SCA_PythonController::Type)
{
SCA_PythonController* pythonController = (SCA_PythonController*)contr;
pythonController->AddTriggeredSensor(sensor);
}
}
}
//sensor->SetActive(false);
}
// int numtriggered = triggeredControllerSet.size(); /*unused*/
for (set<SmartControllerPtr>::iterator tit=triggeredControllerSet.begin();
!(tit==triggeredControllerSet.end());tit++)
for (set<SmartControllerPtr>::iterator tit=m_triggeredControllerSet.begin();
!(tit==m_triggeredControllerSet.end());tit++)
{
(*tit)->Trigger(this);
}
triggeredControllerSet.clear();
m_triggeredControllerSet.clear();
}
@@ -382,6 +390,17 @@ void SCA_LogicManager::AddActivatedSensor(SCA_ISensor* sensor)
}
}
void SCA_LogicManager::AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor)
{
m_triggeredControllerSet.insert(SmartControllerPtr(controller,0));
// so that the controller knows which sensor has activited it
// only needed for python controller
if (controller->GetType() == &SCA_PythonController::Type)
{
SCA_PythonController* pythonController = (SCA_PythonController*)controller;
pythonController->AddTriggeredSensor(sensor);
}
}
void SCA_LogicManager::AddActiveActuator(SCA_IActuator* actua,CValue* event)

View File

@@ -99,6 +99,7 @@ class SCA_LogicManager
vector<class SCA_ISensor*> m_activatedsensors;
set<class SmartActuatorPtr> m_activeActuators;
set<class SmartControllerPtr> m_triggeredControllerSet;
map<SCA_ISensor*,controllerlist > m_sensorcontrollermapje;
@@ -127,6 +128,7 @@ public:
void EndFrame();
void AddActivatedSensor(SCA_ISensor* sensor);
void AddActiveActuator(SCA_IActuator* sensor,class CValue* event);
void AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor);
SCA_EventManager* FindEventManager(int eventmgrtype);
void RemoveGameObject(const STR_String& gameobjname);

View File

@@ -35,6 +35,7 @@
#include "SCA_IActuator.h"
#include "compile.h"
#include "eval.h"
#include <algorithm>
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -139,6 +140,14 @@ void SCA_PythonController::SetDictionary(PyObject* pythondictionary)
m_pythondictionary = PyDict_Copy(pythondictionary); /* new reference */
}
int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor)
{
if (std::find(m_triggeredSensors.begin(), m_triggeredSensors.end(), sensor) !=
m_triggeredSensors.end())
return 1;
return 0;
}
#if 0
static char* sPyGetCurrentController__doc__;
#endif
@@ -294,7 +303,7 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr)
// something in this dictionary and crash?
PyDict_Clear(excdict);
Py_DECREF(excdict);
m_triggeredSensors.erase(m_triggeredSensors.begin(), m_triggeredSensors.end());
m_sCurrentController = NULL;
}

View File

@@ -36,6 +36,8 @@
#include "SCA_LogicManager.h"
#include "BoolValue.h"
#include <vector>
class SCA_IObject;
class SCA_PythonController : public SCA_IController
{
@@ -47,6 +49,7 @@ class SCA_PythonController : public SCA_IController
STR_String m_scriptText;
STR_String m_scriptName;
PyObject* m_pythondictionary;
std::vector<class SCA_ISensor*> m_triggeredSensors;
public:
static SCA_PythonController* m_sCurrentController; // protected !!!
@@ -64,6 +67,9 @@ class SCA_PythonController : public SCA_IController
void SetScriptText(const STR_String& text);
void SetScriptName(const STR_String& name);
void SetDictionary(PyObject* pythondictionary);
void AddTriggeredSensor(class SCA_ISensor* sensor)
{ m_triggeredSensors.push_back(sensor); }
int IsTriggered(class SCA_ISensor* sensor);
static char* sPyGetCurrentController__doc__;
static PyObject* sPyGetCurrentController(PyObject* self);

View File

@@ -9,7 +9,12 @@ class SCA_ISensor(SCA_ILogicBrick):
def isPositive():
"""
True if this sensor brick has been activated.
True if this sensor brick is in a positive state.
"""
def isTriggered():
"""
True if this sensor brick has triggered the current controller.
"""
def getUsePosPulseMode():