[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [16236] trunk/blender/source/gameengine: 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 .

Benoit Bolsee benoit.bolsee at online.be
Sat Aug 23 13:54:28 CEST 2008


Revision: 16236
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=16236
Author:   ben2610
Date:     2008-08-23 13:54:27 +0200 (Sat, 23 Aug 2008)

Log Message:
-----------
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.

Modified Paths:
--------------
    trunk/blender/source/gameengine/GameLogic/SCA_IController.cpp
    trunk/blender/source/gameengine/GameLogic/SCA_ISensor.cpp
    trunk/blender/source/gameengine/GameLogic/SCA_ISensor.h
    trunk/blender/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
    trunk/blender/source/gameengine/GameLogic/SCA_LogicManager.cpp
    trunk/blender/source/gameengine/GameLogic/SCA_LogicManager.h
    trunk/blender/source/gameengine/GameLogic/SCA_PythonController.cpp
    trunk/blender/source/gameengine/GameLogic/SCA_PythonController.h
    trunk/blender/source/gameengine/PyDoc/SCA_ISensor.py

Modified: trunk/blender/source/gameengine/GameLogic/SCA_IController.cpp
===================================================================
--- trunk/blender/source/gameengine/GameLogic/SCA_IController.cpp	2008-08-22 20:17:39 UTC (rev 16235)
+++ trunk/blender/source/gameengine/GameLogic/SCA_IController.cpp	2008-08-23 11:54:27 UTC (rev 16236)
@@ -188,6 +188,8 @@
 			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);
 		}

Modified: trunk/blender/source/gameengine/GameLogic/SCA_ISensor.cpp
===================================================================
--- trunk/blender/source/gameengine/GameLogic/SCA_ISensor.cpp	2008-08-22 20:17:39 UTC (rev 16235)
+++ trunk/blender/source/gameengine/GameLogic/SCA_ISensor.cpp	2008-08-23 11:54:27 UTC (rev 16236)
@@ -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 @@
 	}
 	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 @@
 };
 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 @@
 
 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 @@
 				}
 			}
 		}
+		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)
  */

Modified: trunk/blender/source/gameengine/GameLogic/SCA_ISensor.h
===================================================================
--- trunk/blender/source/gameengine/GameLogic/SCA_ISensor.h	2008-08-22 20:17:39 UTC (rev 16235)
+++ trunk/blender/source/gameengine/GameLogic/SCA_ISensor.h	2008-08-23 11:54:27 UTC (rev 16236)
@@ -34,6 +34,8 @@
 
 #include "SCA_ILogicBrick.h"
 
+#include <vector>
+
 /**
  * Interface Class for all logic Sensors. Implements
  * pulsemode,pulsefrequency */
@@ -73,9 +75,9 @@
 	/** 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 @@
 	/** 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 @@
 		{ 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);

Modified: trunk/blender/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp
===================================================================
--- trunk/blender/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp	2008-08-22 20:17:39 UTC (rev 16235)
+++ trunk/blender/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp	2008-08-23 11:54:27 UTC (rev 16236)
@@ -505,7 +505,7 @@
 				       PyObject* kwds)
 {
 //	printf("sPyIsPositive\n");
-    return ((SCA_KeyboardSensor*) self)->PyIsPositive(self, args, kwds);
+    return ((SCA_KeyboardSensor*) self)->PyIsPositive(self);
 }
 
 

Modified: trunk/blender/source/gameengine/GameLogic/SCA_LogicManager.cpp
===================================================================
--- trunk/blender/source/gameengine/GameLogic/SCA_LogicManager.cpp	2008-08-22 20:17:39 UTC (rev 16235)
+++ trunk/blender/source/gameengine/GameLogic/SCA_LogicManager.cpp	2008-08-23 11:54:27 UTC (rev 16236)
@@ -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 @@
 	// 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 @@
 		{
 				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::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)

Modified: trunk/blender/source/gameengine/GameLogic/SCA_LogicManager.h
===================================================================
--- trunk/blender/source/gameengine/GameLogic/SCA_LogicManager.h	2008-08-22 20:17:39 UTC (rev 16235)
+++ trunk/blender/source/gameengine/GameLogic/SCA_LogicManager.h	2008-08-23 11:54:27 UTC (rev 16236)
@@ -99,6 +99,7 @@
 	
 	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 @@
 	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);

Modified: trunk/blender/source/gameengine/GameLogic/SCA_PythonController.cpp
===================================================================
--- trunk/blender/source/gameengine/GameLogic/SCA_PythonController.cpp	2008-08-22 20:17:39 UTC (rev 16235)
+++ trunk/blender/source/gameengine/GameLogic/SCA_PythonController.cpp	2008-08-23 11:54:27 UTC (rev 16236)
@@ -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 @@
 	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 @@
 	// 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 output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list