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
path: root/source
diff options
context:
space:
mode:
authorBenoit Bolsee <benoit.bolsee@online.be>2008-08-23 15:54:27 +0400
committerBenoit Bolsee <benoit.bolsee@online.be>2008-08-23 15:54:27 +0400
commitbc8f002a4c68235db766fbd72bc383feb7836341 (patch)
treec56be248aa873c07af07f85061e4aa4f3bf8a3f4 /source
parent2076703a286a61b175441a0413f348b0596e1964 (diff)
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.
Diffstat (limited to 'source')
-rw-r--r--source/gameengine/GameLogic/SCA_IController.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_ISensor.cpp45
-rw-r--r--source/gameengine/GameLogic/SCA_ISensor.h13
-rw-r--r--source/gameengine/GameLogic/SCA_KeyboardSensor.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_LogicManager.cpp31
-rw-r--r--source/gameengine/GameLogic/SCA_LogicManager.h2
-rw-r--r--source/gameengine/GameLogic/SCA_PythonController.cpp11
-rw-r--r--source/gameengine/GameLogic/SCA_PythonController.h6
-rw-r--r--source/gameengine/PyDoc/SCA_ISensor.py7
9 files changed, 100 insertions, 19 deletions
diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp
index 8f156cc63e7..0bd20117f31 100644
--- a/source/gameengine/GameLogic/SCA_IController.cpp
+++ b/source/gameengine/GameLogic/SCA_IController.cpp
@@ -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);
}
diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp
index f99b9b789d7..c96eb82e29e 100644
--- a/source/gameengine/GameLogic/SCA_ISensor.cpp
+++ b/source/gameengine/GameLogic/SCA_ISensor.cpp
@@ -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)
*/
diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h
index fc8f0bd0011..0d65270dc7b 100644
--- a/source/gameengine/GameLogic/SCA_ISensor.h
+++ b/source/gameengine/GameLogic/SCA_ISensor.h
@@ -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);
diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
index a7a6fa93db4..fba1162993d 100644
--- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
@@ -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);
}
diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp
index 91e66aea359..b584b37180f 100644
--- a/source/gameengine/GameLogic/SCA_LogicManager.cpp
+++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp
@@ -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)
diff --git a/source/gameengine/GameLogic/SCA_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h
index e0d3d506702..50383879d8f 100644
--- a/source/gameengine/GameLogic/SCA_LogicManager.h
+++ b/source/gameengine/GameLogic/SCA_LogicManager.h
@@ -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);
diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp
index f9081c90288..e6f7b1dd143 100644
--- a/source/gameengine/GameLogic/SCA_PythonController.cpp
+++ b/source/gameengine/GameLogic/SCA_PythonController.cpp
@@ -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;
}
diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h
index 39b6c68c359..1b62e7ecb53 100644
--- a/source/gameengine/GameLogic/SCA_PythonController.h
+++ b/source/gameengine/GameLogic/SCA_PythonController.h
@@ -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);
diff --git a/source/gameengine/PyDoc/SCA_ISensor.py b/source/gameengine/PyDoc/SCA_ISensor.py
index 33f0e976284..14858505e24 100644
--- a/source/gameengine/PyDoc/SCA_ISensor.py
+++ b/source/gameengine/PyDoc/SCA_ISensor.py
@@ -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():