diff options
-rw-r--r-- | source/blender/makesdna/DNA_sensor_types.h | 3 | ||||
-rw-r--r-- | source/blender/src/buttons_logic.c | 36 | ||||
-rw-r--r-- | source/gameengine/Converter/KX_ConvertSensors.cpp | 3 | ||||
-rw-r--r-- | source/gameengine/GameLogic/SCA_ANDController.cpp | 2 | ||||
-rw-r--r-- | source/gameengine/GameLogic/SCA_ExpressionController.cpp | 2 | ||||
-rw-r--r-- | source/gameengine/GameLogic/SCA_ISensor.cpp | 78 | ||||
-rw-r--r-- | source/gameengine/GameLogic/SCA_ISensor.h | 19 | ||||
-rw-r--r-- | source/gameengine/GameLogic/SCA_KeyboardSensor.cpp | 3 | ||||
-rw-r--r-- | source/gameengine/GameLogic/SCA_NANDController.cpp | 2 | ||||
-rw-r--r-- | source/gameengine/GameLogic/SCA_NORController.cpp | 2 | ||||
-rw-r--r-- | source/gameengine/GameLogic/SCA_ORController.cpp | 2 | ||||
-rw-r--r-- | source/gameengine/GameLogic/SCA_XNORController.cpp | 2 | ||||
-rw-r--r-- | source/gameengine/GameLogic/SCA_XORController.cpp | 2 |
13 files changed, 126 insertions, 30 deletions
diff --git a/source/blender/makesdna/DNA_sensor_types.h b/source/blender/makesdna/DNA_sensor_types.h index 7a358ad0694..8b29ce1338d 100644 --- a/source/blender/makesdna/DNA_sensor_types.h +++ b/source/blender/makesdna/DNA_sensor_types.h @@ -158,7 +158,8 @@ typedef struct bSensor { /* just add here, to avoid align errors... */ short invert; /* Whether or not to invert the output. */ short level; /* Whether the sensor is level base (edge by default) */ - int pad; + short tap; + short pad; } bSensor; typedef struct bJoystickSensor { diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c index 941ed5ebe12..dccbc73787d 100644 --- a/source/blender/src/buttons_logic.c +++ b/source/blender/src/buttons_logic.c @@ -1026,6 +1026,19 @@ static void set_col_sensor(int type, int medium) BIF_ThemeColorShade(col, medium?30:0); } + +static void verify_logicbutton_func(void *data1, void *data2) +{ + bSensor *sens= (bSensor*)data1; + + if(sens->level && sens->tap) { + if(data2 == &(sens->level)) sens->tap= 0; + else sens->level= 0; + allqueue(REDRAWBUTSLOGIC, 0); + } +} + + /** * Draws a toggle for pulse mode, a frequency field and a toggle to invert * the value of this sensor. Operates on the shared data block of sensors. @@ -1036,30 +1049,39 @@ static void draw_default_sensor_header(bSensor *sens, short y, short w) { + uiBut *but; + /* Pulsing and frequency */ uiDefIconButBitS(block, TOG, SENS_PULSE_REPEAT, 1, ICON_DOTSUP, - (short)(x + 10 + 0. * (w-20)), (short)(y - 21), (short)(0.15 * (w-20)), 19, + (short)(x + 10 + 0. * (w-20)), (short)(y - 21), (short)(0.1 * (w-20)), 19, &sens->pulse, 0.0, 0.0, 0, 0, "Activate TRUE level triggering (pulse mode)"); uiDefIconButBitS(block, TOG, SENS_NEG_PULSE_MODE, 1, ICON_DOTSDOWN, - (short)(x + 10 + 0.15 * (w-20)), (short)(y - 21), (short)(0.15 * (w-20)), 19, + (short)(x + 10 + 0.1 * (w-20)), (short)(y - 21), (short)(0.1 * (w-20)), 19, &sens->pulse, 0.0, 0.0, 0, 0, "Activate FALSE level triggering (pulse mode)"); uiDefButS(block, NUM, 1, "f:", - (short)(x + 10 + 0.3 * (w-20)), (short)(y - 21), (short)(0.275 * (w-20)), 19, + (short)(x + 10 + 0.2 * (w-20)), (short)(y - 21), (short)(0.275 * (w-20)), 19, &sens->freq, 0.0, 10000.0, 0, 0, "Delay between repeated pulses (in logic tics, 0 = no delay)"); /* value or shift? */ + but= uiDefButS(block, TOG, 1, "Level", + (short)(x + 10 + 0.5 * (w-20)), (short)(y - 21), (short)(0.20 * (w-20)), 19, + &sens->level, 0.0, 0.0, 0, 0, + "Level detector, trigger controllers of new states (only applicable upon logic state transition)"); + uiButSetFunc(but, verify_logicbutton_func, sens, &(sens->level)); + but= uiDefButS(block, TOG, 1, "Tap", + (short)(x + 10 + 0.702 * (w-20)), (short)(y - 21), (short)(0.12 * (w-20)), 19, + &sens->tap, 0.0, 0.0, 0, 0, + "Trigger controllers only for an instant, even while the sensor remains true"); + uiButSetFunc(but, verify_logicbutton_func, sens, &(sens->tap)); + uiDefButS(block, TOG, 1, "Inv", (short)(x + 10 + 0.85 * (w-20)), (short)(y - 21), (short)(0.15 * (w-20)), 19, &sens->invert, 0.0, 0.0, 0, 0, "Invert the level (output) of this sensor"); - uiDefButS(block, TOG, 1, "Level", - (short)(x + 10 + 0.65 * (w-20)), (short)(y - 21), (short)(0.20 * (w-20)), 19, - &sens->level, 0.0, 0.0, 0, 0, - "Level detector, trigger controllers of new states (only applicable upon logic state transition)"); } static short draw_sensorbuttons(bSensor *sens, uiBlock *block, short xco, short yco, short width,char* objectname) diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index 19e594ff0cb..af57094b2b5 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -255,6 +255,7 @@ void BL_ConvertSensors(struct Object* blenderobject, int frequency = 0; bool invert = false; bool level = false; + bool tap = false; while(sens) { @@ -268,6 +269,7 @@ void BL_ConvertSensors(struct Object* blenderobject, frequency = sens->freq; invert = !(sens->invert == 0); level = !(sens->level == 0); + tap = !(sens->tap == 0); switch (sens->type) { @@ -755,6 +757,7 @@ void BL_ConvertSensors(struct Object* blenderobject, frequency); gamesensor->SetInvert(invert); gamesensor->SetLevel(level); + gamesensor->SetTap(tap); gamesensor->SetName(STR_String(sens->name)); gameobj->AddSensor(gamesensor); diff --git a/source/gameengine/GameLogic/SCA_ANDController.cpp b/source/gameengine/GameLogic/SCA_ANDController.cpp index 1b151cbe615..7991e82168f 100644 --- a/source/gameengine/GameLogic/SCA_ANDController.cpp +++ b/source/gameengine/GameLogic/SCA_ANDController.cpp @@ -66,7 +66,7 @@ void SCA_ANDController::Trigger(SCA_LogicManager* logicmgr) !(is==m_linkedsensors.end());is++) { SCA_ISensor* sensor = *is; - if (!sensor->IsPositiveTrigger()) + if (!sensor->GetState()) { sensorresult = false; break; diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.cpp b/source/gameengine/GameLogic/SCA_ExpressionController.cpp index e6bccef08d4..a4e898a808f 100644 --- a/source/gameengine/GameLogic/SCA_ExpressionController.cpp +++ b/source/gameengine/GameLogic/SCA_ExpressionController.cpp @@ -161,7 +161,7 @@ CValue* SCA_ExpressionController::FindIdentifier(const STR_String& identifiernam SCA_ISensor* sensor = *is; if (sensor->GetName() == identifiername) { - identifierval = new CBoolValue(sensor->IsPositiveTrigger()); + identifierval = new CBoolValue(sensor->GetState()); //identifierval = sensor->AddRef(); } diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index 4d69216ed0b..1e9a4521df5 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -52,19 +52,21 @@ void SCA_ISensor::ReParent(SCA_IObject* parent) SCA_ISensor::SCA_ISensor(SCA_IObject* gameobj, class SCA_EventManager* eventmgr, PyTypeObject* T ) : - SCA_ILogicBrick(gameobj,T), - m_triggered(false) + SCA_ILogicBrick(gameobj,T) { m_links = 0; m_suspended = false; m_invert = false; m_level = false; + m_tap = false; m_reset = false; m_pos_ticks = 0; m_neg_ticks = 0; m_pos_pulsemode = false; m_neg_pulsemode = false; m_pulse_frequency = 0; + m_state = false; + m_prev_state = false; m_eventmgr = eventmgr; } @@ -104,9 +106,13 @@ void SCA_ISensor::SetLevel(bool lvl) { m_level = lvl; } +void SCA_ISensor::SetTap(bool tap) { + m_tap = tap; +} + double SCA_ISensor::GetNumber() { - return IsPositiveTrigger(); + return GetState(); } void SCA_ISensor::Suspend() { @@ -143,6 +149,7 @@ void SCA_ISensor::RegisterToManager() { // sensor is just activated, initialize it Init(); + m_state = false; m_newControllers.erase(m_newControllers.begin(), m_newControllers.end()); m_eventmgr->RegisterSensor(this); } @@ -159,11 +166,20 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) // don't evaluate a sensor that is not connected to any controller if (m_links && !m_suspended) { bool result = this->Evaluate(event); + // store the state for the rest of the logic system + m_prev_state = m_state; + m_state = this->IsPositiveTrigger(); if (result) { - logicmgr->AddActivatedSensor(this); - // reset these counters so that pulse are synchronized with transition - m_pos_ticks = 0; - m_neg_ticks = 0; + // the sensor triggered this frame + if (m_state || !m_tap) { + logicmgr->AddActivatedSensor(this); + // reset these counters so that pulse are synchronized with transition + m_pos_ticks = 0; + m_neg_ticks = 0; + } else + { + result = false; + } } else { /* First, the pulsing behaviour, if pulse mode is @@ -172,19 +188,20 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) if (m_pos_pulsemode) { m_pos_ticks++; if (m_pos_ticks > m_pulse_frequency) { - if ( this->IsPositiveTrigger() ) + if ( m_state ) { logicmgr->AddActivatedSensor(this); + result = true; } m_pos_ticks = 0; } } - - if (m_neg_pulsemode) + // negative pulse doesn't make sense in tap mode, skip + if (m_neg_pulsemode && !m_tap) { m_neg_ticks++; if (m_neg_ticks > m_pulse_frequency) { - if (!this->IsPositiveTrigger() ) + if (!m_state ) { logicmgr->AddActivatedSensor(this); } @@ -192,6 +209,21 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) } } } + if (m_tap) + { + // in tap mode: we send always a negative pulse immediately after a positive pulse + if (!result) + { + // the sensor did not trigger on this frame + if (m_prev_state) + { + // but it triggered on previous frame => send a negative pulse + logicmgr->AddActivatedSensor(this); + } + // in any case, absence of trigger means sensor off + m_state = false; + } + } if (!m_newControllers.empty()) { if (!IsActive() && m_level) @@ -221,7 +253,7 @@ const char SCA_ISensor::IsPositive_doc[] = PyObject* SCA_ISensor::PyIsPositive() { ShowDeprecationWarning("isPositive()", "the read-only positive property"); - int retval = IsPositiveTrigger(); + int retval = GetState(); return PyInt_FromLong(retval); } @@ -385,6 +417,7 @@ KX_PYMETHODDEF_DOC_NOARGS(SCA_ISensor, reset, "\tThe sensor is put in its initial state as if it was just activated.\n") { Init(); + m_prev_state = false; Py_RETURN_NONE; } @@ -458,7 +491,8 @@ PyAttributeDef SCA_ISensor::Attributes[] = { KX_PYATTRIBUTE_BOOL_RW("useNegPulseMode",SCA_ISensor,m_neg_pulsemode), KX_PYATTRIBUTE_INT_RW("frequency",0,100000,true,SCA_ISensor,m_pulse_frequency), KX_PYATTRIBUTE_BOOL_RW("invert",SCA_ISensor,m_invert), - KX_PYATTRIBUTE_BOOL_RW("level",SCA_ISensor,m_level), + KX_PYATTRIBUTE_BOOL_RW_CHECK("level",SCA_ISensor,m_level,pyattr_check_level), + KX_PYATTRIBUTE_BOOL_RW_CHECK("tap",SCA_ISensor,m_tap,pyattr_check_tap), KX_PYATTRIBUTE_RO_FUNCTION("triggered", SCA_ISensor, pyattr_get_triggered), KX_PYATTRIBUTE_RO_FUNCTION("positive", SCA_ISensor, pyattr_get_positive), //KX_PYATTRIBUTE_TODO("links"), @@ -493,7 +527,23 @@ PyObject* SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_D PyObject* SCA_ISensor::pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v); - return PyInt_FromLong(self->IsPositiveTrigger()); + return PyInt_FromLong(self->GetState()); +} + +int SCA_ISensor::pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v); + if (self->m_level) + self->m_tap = false; + return 0; +} + +int SCA_ISensor::pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v); + if (self->m_tap) + self->m_level = false; + return 0; } /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index e2ceec19b69..7bbef5fef2f 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -43,7 +43,6 @@ class SCA_ISensor : public SCA_ILogicBrick { Py_Header; class SCA_EventManager* m_eventmgr; - bool m_triggered; /** Pulse positive pulses? */ bool m_pos_pulsemode; @@ -66,6 +65,9 @@ class SCA_ISensor : public SCA_ILogicBrick /** detect level instead of edge*/ bool m_level; + /** tap mode */ + bool m_tap; + /** sensor has been reset */ bool m_reset; @@ -75,6 +77,12 @@ class SCA_ISensor : public SCA_ILogicBrick /** number of connections to controller */ int m_links; + /** current sensor state */ + bool m_state; + + /** previous state (for tap option) */ + bool m_prev_state; + /** list of controllers that have just activated this sensor because of a state change */ std::vector<class SCA_IController*> m_newControllers; @@ -109,6 +117,7 @@ public: void SetInvert(bool inv); /** set the level detection on or off */ void SetLevel(bool lvl); + void SetTap(bool tap); virtual void RegisterToManager(); virtual void UnregisterToManager(); @@ -121,6 +130,12 @@ public: /** Is this sensor switched off? */ bool IsSuspended(); + /** get the state of the sensor: positive or negative */ + bool GetState() + { + return m_state; + } + /** Resume sensing. */ void Resume(); @@ -158,6 +173,8 @@ public: static PyObject* pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); }; #endif //__SCA_ISENSOR diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index 821d2155d2a..a9ea4272531 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -195,6 +195,9 @@ bool SCA_KeyboardSensor::Evaluate(CValue* eventval) } } } + if (m_tap) + // special case for tap mode: only generate event for new activation + result = false; } diff --git a/source/gameengine/GameLogic/SCA_NANDController.cpp b/source/gameengine/GameLogic/SCA_NANDController.cpp index 4643a42a4be..df62f91aaed 100644 --- a/source/gameengine/GameLogic/SCA_NANDController.cpp +++ b/source/gameengine/GameLogic/SCA_NANDController.cpp @@ -66,7 +66,7 @@ void SCA_NANDController::Trigger(SCA_LogicManager* logicmgr) !(is==m_linkedsensors.end());is++) { SCA_ISensor* sensor = *is; - if (!sensor->IsPositiveTrigger()) + if (!sensor->GetState()) { sensorresult = true; break; diff --git a/source/gameengine/GameLogic/SCA_NORController.cpp b/source/gameengine/GameLogic/SCA_NORController.cpp index a0e9fcb239c..b87af965a50 100644 --- a/source/gameengine/GameLogic/SCA_NORController.cpp +++ b/source/gameengine/GameLogic/SCA_NORController.cpp @@ -66,7 +66,7 @@ void SCA_NORController::Trigger(SCA_LogicManager* logicmgr) !(is==m_linkedsensors.end());is++) { SCA_ISensor* sensor = *is; - if (sensor->IsPositiveTrigger()) + if (sensor->GetState()) { sensorresult = false; break; diff --git a/source/gameengine/GameLogic/SCA_ORController.cpp b/source/gameengine/GameLogic/SCA_ORController.cpp index 87e6d19d008..7aa58b6c320 100644 --- a/source/gameengine/GameLogic/SCA_ORController.cpp +++ b/source/gameengine/GameLogic/SCA_ORController.cpp @@ -76,7 +76,7 @@ void SCA_ORController::Trigger(SCA_LogicManager* logicmgr) while ( (!sensorresult) && (!(is==m_linkedsensors.end())) ) { sensor = *is; - if (sensor->IsPositiveTrigger()) sensorresult = true; + if (sensor->GetState()) sensorresult = true; is++; } diff --git a/source/gameengine/GameLogic/SCA_XNORController.cpp b/source/gameengine/GameLogic/SCA_XNORController.cpp index 947e8b7a68a..9b0fe51c5b8 100644 --- a/source/gameengine/GameLogic/SCA_XNORController.cpp +++ b/source/gameengine/GameLogic/SCA_XNORController.cpp @@ -66,7 +66,7 @@ void SCA_XNORController::Trigger(SCA_LogicManager* logicmgr) !(is==m_linkedsensors.end());is++) { SCA_ISensor* sensor = *is; - if (sensor->IsPositiveTrigger()) + if (sensor->GetState()) { if (sensorresult == false) { diff --git a/source/gameengine/GameLogic/SCA_XORController.cpp b/source/gameengine/GameLogic/SCA_XORController.cpp index d9e41c2b27e..9232120075f 100644 --- a/source/gameengine/GameLogic/SCA_XORController.cpp +++ b/source/gameengine/GameLogic/SCA_XORController.cpp @@ -66,7 +66,7 @@ void SCA_XORController::Trigger(SCA_LogicManager* logicmgr) !(is==m_linkedsensors.end());is++) { SCA_ISensor* sensor = *is; - if (sensor->IsPositiveTrigger()) + if (sensor->GetState()) { if (sensorresult == true) { |