BGE patch: Add level option on sensor and fix sensor reset.

Level option is now available on all sensors but is only implemented on 
mouse and keyboard sensors. The purpose of that option is to make
the sensor react on level rather than edge by default. It's only
applicable to state engine system when there is a state transition:
the sensor will generate a pulse if the condition is met from the
start of the state. Normally, the keyboard sensor generate a pulse
only when the key is pressed and not when the key is already pressed.
This patch allows to select this behavior.
The second part of the patch corrects the reset method for sensors
with inverted output.
This commit is contained in:
Benoit Bolsee 2008-06-23 20:26:48 +00:00
parent 8b9503e0ec
commit 67c0b32375
10 changed files with 69 additions and 28 deletions

@ -144,7 +144,7 @@ typedef struct bSensor {
/* just add here, to avoid align errors... */
short invert; /* Whether or not to invert the output. */
short freq2; /* The negative pulsing frequency? Not used anymore... */
short level; /* Whether the sensor is level base (edge by default) */
int pad;
} bSensor;

@ -251,6 +251,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
bool neg_pulsemode = false;
int frequency = 0;
bool invert = false;
bool level = false;
while(sens)
{
@ -263,6 +264,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
frequency = sens->freq;
invert = !(sens->invert == 0);
level = !(sens->level == 0);
switch (sens->type)
{
@ -711,6 +713,7 @@ void BL_ConvertSensors(struct Object* blenderobject,
neg_pulsemode,
frequency);
gamesensor->SetInvert(invert);
gamesensor->SetLevel(level);
gamesensor->SetName(STR_String(sens->name));
gameobj->AddSensor(gamesensor);

@ -55,6 +55,7 @@ SCA_ISensor::SCA_ISensor(SCA_IObject* gameobj,
m_links = 0;
m_suspended = false;
m_invert = false;
m_level = false;
m_pos_ticks = 0;
m_neg_ticks = 0;
m_pos_pulsemode = false;
@ -95,6 +96,10 @@ void SCA_ISensor::SetInvert(bool inv) {
m_invert = inv;
}
void SCA_ISensor::SetLevel(bool lvl) {
m_level = lvl;
}
float SCA_ISensor::GetNumber() {
return IsPositiveTrigger();
@ -177,6 +182,10 @@ PyMethodDef SCA_ISensor::Methods[] = {
METH_VARARGS, GetInvert_doc},
{"setInvert", (PyCFunction) SCA_ISensor::sPySetInvert,
METH_VARARGS, SetInvert_doc},
{"getLevel", (PyCFunction) SCA_ISensor::sPyGetLevel,
METH_VARARGS, GetLevel_doc},
{"setLevel", (PyCFunction) SCA_ISensor::sPySetLevel,
METH_VARARGS, SetLevel_doc},
{NULL,NULL} //Sentinel
};
@ -328,6 +337,31 @@ PyObject* SCA_ISensor::PySetInvert(PyObject* self, PyObject* args, PyObject* kwd
Py_Return;
}
char SCA_ISensor::GetLevel_doc[] =
"getLevel()\n"
"\tReturns whether this sensor is a level detector or a edge detector.\n"
"\tIt makes a difference only in case of logic state transition (state actuator).\n"
"\tA level detector will immediately generate a pulse if the condition for the\n"
"\tdetector is met when entering the state. A edge detector will wait for an off-on\n"
"\ttransition to occur.\n"
"\tOnly some sensors implement this feature: keyboard.\n";
PyObject* SCA_ISensor::PyGetLevel(PyObject* self, PyObject* args, PyObject* kwds)
{
return BoolToPyArg(m_level);
}
char SCA_ISensor::SetLevel_doc[] =
"setLevel(level?)\n"
"\t- level?: Detect level instead of edge? (KX_TRUE, KX_FALSE)\n"
"\tSet whether to detect level or edge transition when entering a state.\n";
PyObject* SCA_ISensor::PySetLevel(PyObject* self, PyObject* args, PyObject* kwds)
{
int pyarg = 0;
if(!PyArg_ParseTuple(args, "i", &pyarg)) { return NULL; }
m_level = PyArgToBool(pyarg);
Py_Return;
}
char SCA_ISensor::GetUseNegPulseMode_doc[] =
"getUseNegPulseMode()\n"
"\tReturns whether negative pulse mode is active.\n";

@ -61,6 +61,9 @@ class SCA_ISensor : public SCA_ILogicBrick
/** invert the output signal*/
bool m_invert;
/** detect level instead of edge*/
bool m_level;
/** Sensor must ignore updates? */
bool m_suspended;
@ -105,6 +108,8 @@ public:
virtual void Delete() { Release(); }
/** Set inversion of pulses on or off. */
void SetInvert(bool inv);
/** set the level detection on or off */
void SetLevel(bool lvl);
void RegisterToManager();
virtual float GetNumber();
@ -134,6 +139,8 @@ public:
KX_PYMETHOD_DOC(SCA_ISensor,SetUseNegPulseMode);
KX_PYMETHOD_DOC(SCA_ISensor,GetInvert);
KX_PYMETHOD_DOC(SCA_ISensor,SetInvert);
KX_PYMETHOD_DOC(SCA_ISensor,GetLevel);
KX_PYMETHOD_DOC(SCA_ISensor,SetLevel);
};

@ -69,7 +69,7 @@ std::cout << " hat flag " << m_hatf << std::endl;
void SCA_JoystickSensor::Init()
{
m_istrig=0;
m_istrig=(m_invert)?1:0;
}
SCA_JoystickSensor::~SCA_JoystickSensor()

@ -77,7 +77,7 @@ void SCA_KeyboardSensor::Init()
// by the state engine. It reinitializes the sensor as if it was just created.
// However, if the target key is pressed when the sensor is reactivated, it
// will not generated an event (see remark in Evaluate()).
m_val = 0;
m_val = (m_invert)?1:0;
}
CValue* SCA_KeyboardSensor::GetReplica()
@ -176,10 +176,10 @@ bool SCA_KeyboardSensor::Evaluate(CValue* eventval)
{
if (m_val == 0)
{
//see comment below
//m_val = 1;
//result = true;
;
if (m_level) {
m_val = 1;
result = true;
}
}
} else
{
@ -229,15 +229,11 @@ bool SCA_KeyboardSensor::Evaluate(CValue* eventval)
{
if (m_val == 0)
{
//hmm, this abnormal situation may occur in the following cases:
//- the key was pressed while the scene was suspended
//- this is a new scene and the key is active from the start
//In the second case, it's dangerous to activate the sensor
//(think of a key to go to next scene)
//What we really need is a edge/level flag in the key sensor
//m_val = 1;
//result = true;
;
if (m_level)
{
m_val = 1;
result = true;
}
}
}
}

@ -83,7 +83,7 @@ SCA_MouseSensor::SCA_MouseSensor(SCA_MouseManager* eventmgr,
void SCA_MouseSensor::Init()
{
m_val = 0; /* stores the latest attribute */
m_val = (m_invert)?1:0; /* stores the latest attribute */
}
SCA_MouseSensor::~SCA_MouseSensor()
@ -168,10 +168,11 @@ bool SCA_MouseSensor::Evaluate(CValue* event)
{
if (m_val == 0)
{
//dangerous
//m_val = 1;
//result = true;
;
if (m_level)
{
m_val = 1;
result = true;
}
}
} else
{

@ -54,7 +54,6 @@ SCA_PropertySensor::SCA_PropertySensor(SCA_EventManager* eventmgr,
m_checkpropval(propval),
m_checkpropmaxval(propmaxval),
m_checkpropname(propname),
m_lastresult(false),
m_range_expr(NULL)
{
//CParser pars;
@ -78,6 +77,7 @@ SCA_PropertySensor::SCA_PropertySensor(SCA_EventManager* eventmgr,
void SCA_PropertySensor::Init()
{
m_recentresult = false;
m_lastresult = m_invert?true:false;
}
void SCA_PropertySensor::PrecalculateRangeExpression()

@ -74,7 +74,7 @@ KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr,
void KX_MouseFocusSensor::Init()
{
m_mouse_over_in_previous_frame = false;
m_mouse_over_in_previous_frame = (m_invert)?true:false;
m_positive_event = false;
m_hitObject = 0;
}
@ -92,13 +92,13 @@ bool KX_MouseFocusSensor::Evaluate(CValue* event)
obHasFocus = ParentObjectHasFocus();
if (!obHasFocus) {
if (m_mouse_over_in_previous_frame) {
m_positive_event = false;
if (m_mouse_over_in_previous_frame) {
result = true;
}
} else {
if (!m_mouse_over_in_previous_frame) {
m_positive_event = true;
if (!m_mouse_over_in_previous_frame) {
result = true;
}
}

@ -69,7 +69,7 @@ KX_RaySensor::KX_RaySensor(class SCA_EventManager* eventmgr,
void KX_RaySensor::Init()
{
m_bTriggered = false;
m_bTriggered = (m_invert)?true:false;
m_rayHit = false;
m_hitObject = NULL;
}