Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/makesdna/DNA_sensor_types.h3
-rw-r--r--source/blender/src/buttons_logic.c36
-rw-r--r--source/gameengine/Converter/KX_ConvertSensors.cpp3
-rw-r--r--source/gameengine/GameLogic/SCA_ANDController.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_ExpressionController.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_ISensor.cpp78
-rw-r--r--source/gameengine/GameLogic/SCA_ISensor.h19
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardSensor.cpp3
-rw-r--r--source/gameengine/GameLogic/SCA_NANDController.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_NORController.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_ORController.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_XNORController.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_XORController.cpp2
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)
{