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:
authorBenoit Bolsee <benoit.bolsee@online.be>2008-06-22 18:23:57 +0400
committerBenoit Bolsee <benoit.bolsee@online.be>2008-06-22 18:23:57 +0400
commit5372def2b069699809cf9439381b03364137adb5 (patch)
treeafe69a88cca198ee85617ee284c6fc5be48671c9 /source/gameengine/Ketsji
parent1ee7a20b93ee3c640b119e1a650e49dcb0f97de9 (diff)
BGE patch: add state engine support in the logic bricks.
This patch introduces a simple state engine system with the logic bricks. This system features full backward compatibility, multiple active states, multiple state transitions, automatic disabling of sensor and actuators, full GUI support and selective display of sensors and actuators. Note: Python API is available but not documented yet. It will be added asap. State internals =============== The state system is object based. The current state mask is stored in the object as a 32 bit value; each bit set in the mask is an active state. The controllers have a state mask too but only one bit can be set: a controller belongs to a single state. The game engine will only execute controllers that belong to active states. Sensors and actuators don't have a state mask but are effectively attached to states via their links to the controllers. Sensors and actuators can be connected to more than one state. When a controller becomes inactive because of a state change, its links to sensors and actuators are temporarily broken (until the state becomes active again). If an actuator gets isolated, i.e all the links to controllers are broken, it is automatically disabled. If a sensor gets isolated, the game engine will stop calling it to save CPU. It will also reset the sensor internal state so that it can react as if the game just started when it gets reconnected to an active controller. For example, an Always sensor in no pulse mode that is connected to a single state (i.e connected to one or more controllers of a single state) will generate a pulse each time the state becomes active. This feature is not available on all sensors, see the notes below. GUI === This system system is fully configurable through the GUI: the object state mask is visible under the object bar in the controller's colum as an array of buttons just like the 3D view layer mask. Click on a state bit to only display the controllers of that state. You can select more than one state with SHIFT-click. The All button sets all the bits so that you can see all the controllers of the object. The Ini button sets the state mask back to the object default state. You can change the default state of object by first selecting the desired state mask and storing using the menu under the State button. If you define a default state mask, it will be loaded into the object state make when you load the blend file or when you run the game under the blenderplayer. However, when you run the game under Blender, the current selected state mask will be used as the startup state for the object. This allows you to test specific state during the game design. The controller display the state they belong to with a new button in the controller header. When you add a new controller, it is added by default in the lowest enabled state. You can change the controller state by clicking on the button and selecting another state. If more than one state is enabled in the object state mask, controllers are grouped by state for more readibility. The new Sta button in the sensor and actuator column header allows you to display only the sensors and actuators that are linked to visible controllers. A new state actuator is available to modify the state during the game. It defines a bit mask and the operation to apply on the current object state mask: Cpy: the bit mask is copied to the object state mask. Add: the bits that set in the bit mask will be turned on in the object state mask. Sub: the bits that set in the bit mask will be turned off in the object state mask. Inv: the bits that set in the bit mask will be inverted in the objecyy state mask. Notes ===== - Although states have no name, a simply convention consists in using the name of the first controller of the state as the state name. The GUI will support that convention by displaying as a hint the name of the first controller of the state when you move the mouse over a state bit of the object state mask or of the state actuator bit mask. - Each object has a state mask and each object can have a state engine but if several objects are part of a logical group, it is recommended to put the state engine only in the main object and to link the controllers of that object to the sensors and actuators of the different objects. - When loading an old blend file, the state mask of all objects and controllers are initialized to 1 so that all the controllers belong to this single state. This ensures backward compatibility with existing game. - When the state actuator is activated at the same time as other actuators, these actuators are guaranteed to execute before being eventually disabled due to the state change. This is useful for example to send a message or update a property at the time of changing the state. - Sensors that depend on underlying resource won't reset fully when they are isolated. By the time they are acticated again, they will behave as follow: * keyboard sensor: keys already pressed won't be detected. The keyboard sensor is only sensitive to new key press. * collision sensor: objects already colliding won't be detected. Only new collisions are detected. * near and radar sensor: same as collision sensor.
Diffstat (limited to 'source/gameengine/Ketsji')
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp7
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h1
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.cpp5
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.h1
-rw-r--r--source/gameengine/Ketsji/KX_RadarSensor.cpp1
-rw-r--r--source/gameengine/Ketsji/KX_RaySensor.cpp14
-rw-r--r--source/gameengine/Ketsji/KX_RaySensor.h1
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_StateActuator.cpp207
-rw-r--r--source/gameengine/Ketsji/KX_StateActuator.h83
-rw-r--r--source/gameengine/Ketsji/KX_TouchSensor.cpp14
-rw-r--r--source/gameengine/Ketsji/KX_TouchSensor.h1
12 files changed, 321 insertions, 16 deletions
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
index e320453b7aa..027cb2a0ffa 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
@@ -58,10 +58,15 @@ KX_NetworkMessageSensor::KX_NetworkMessageSensor(
m_NetworkScene(NetworkScene),
m_subject(subject),
m_frame_message_count (0),
- m_IsUp(false),
m_BodyList(NULL),
m_SubjectList(NULL)
{
+ Init();
+}
+
+void KX_NetworkMessageSensor::Init()
+{
+ m_IsUp = false;
}
KX_NetworkMessageSensor::~KX_NetworkMessageSensor()
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
index d051b715aab..6fd92d17be3 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h
@@ -65,6 +65,7 @@ public:
virtual CValue* GetReplica();
virtual bool Evaluate(CValue* event);
virtual bool IsPositiveTrigger();
+ virtual void Init();
void EndFrame();
/* ------------------------------------------------------------- */
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
index 60b90138abe..f306f0dbfbb 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
@@ -69,11 +69,14 @@ KX_MouseFocusSensor::KX_MouseFocusSensor(SCA_MouseManager* eventmgr,
m_gp_canvas(canvas),
m_kxscene(kxscene)
{
+ Init();
+}
+void KX_MouseFocusSensor::Init()
+{
m_mouse_over_in_previous_frame = false;
m_positive_event = false;
m_hitObject = 0;
-
}
bool KX_MouseFocusSensor::Evaluate(CValue* event)
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h
index 86f32fbf4be..b011ebe1288 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h
@@ -68,6 +68,7 @@ class KX_MouseFocusSensor : public SCA_MouseSensor
* @attention Overrides default evaluate.
*/
virtual bool Evaluate(CValue* event);
+ virtual void Init();
virtual bool IsPositiveTrigger() {
bool result = m_positive_event;
diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp
index 31fffffa3c1..987e0b946b2 100644
--- a/source/gameengine/Ketsji/KX_RadarSensor.cpp
+++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp
@@ -71,7 +71,6 @@ KX_RadarSensor::KX_RadarSensor(SCA_EventManager* eventmgr,
//sumoObj->setClientObject(&m_client_info);
}
-
KX_RadarSensor::~KX_RadarSensor()
{
diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp
index a85dc61cac8..02b814105b4 100644
--- a/source/gameengine/Ketsji/KX_RaySensor.cpp
+++ b/source/gameengine/Ketsji/KX_RaySensor.cpp
@@ -60,17 +60,19 @@ KX_RaySensor::KX_RaySensor(class SCA_EventManager* eventmgr,
m_bFindMaterial(bFindMaterial),
m_distance(distance),
m_scene(ketsjiScene),
- m_bTriggered(false),
- m_axis(axis),
- m_rayHit(false),
- m_hitObject(NULL)
+ m_axis(axis)
{
-
+ Init();
}
-
+void KX_RaySensor::Init()
+{
+ m_bTriggered = false;
+ m_rayHit = false;
+ m_hitObject = NULL;
+}
KX_RaySensor::~KX_RaySensor()
{
diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h
index 8a317ffaa07..f4305b053d1 100644
--- a/source/gameengine/Ketsji/KX_RaySensor.h
+++ b/source/gameengine/Ketsji/KX_RaySensor.h
@@ -66,6 +66,7 @@ public:
virtual bool Evaluate(CValue* event);
virtual bool IsPositiveTrigger();
+ virtual void Init();
bool RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data);
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index fff33ca82fd..1526709f425 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -754,8 +754,6 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
for (SCA_ControllerList::iterator itc = controllers.begin();
!(itc==controllers.end());itc++)
{
- (*itc)->UnlinkAllSensors();
- (*itc)->UnlinkAllActuators();
m_logicmgr->RemoveController(*itc);
}
diff --git a/source/gameengine/Ketsji/KX_StateActuator.cpp b/source/gameengine/Ketsji/KX_StateActuator.cpp
new file mode 100644
index 00000000000..95a79f0c480
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_StateActuator.cpp
@@ -0,0 +1,207 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * Actuator to toggle visibility/invisibility of objects
+ */
+
+#include "KX_StateActuator.h"
+#include "KX_GameObject.h"
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+KX_StateActuator::KX_StateActuator(
+ SCA_IObject* gameobj,
+ int operation,
+ unsigned int mask,
+ PyTypeObject* T
+ )
+ : SCA_IActuator(gameobj,T),
+ m_operation(operation),
+ m_mask(mask)
+{
+ // intentionally empty
+}
+
+KX_StateActuator::~KX_StateActuator(
+ void
+ )
+{
+ // intentionally empty
+}
+
+CValue*
+KX_StateActuator::GetReplica(
+ void
+ )
+{
+ KX_StateActuator* replica = new KX_StateActuator(*this);
+ replica->ProcessReplica();
+ // this will copy properties and so on...
+ CValue::AddDataToReplica(replica);
+ return replica;
+}
+
+bool
+KX_StateActuator::Update()
+{
+ bool bNegativeEvent = IsNegativeEvent();
+ unsigned int objMask;
+
+ RemoveAllEvents();
+ if (bNegativeEvent) return false;
+
+ KX_GameObject *obj = (KX_GameObject*) GetParent();
+
+ objMask = obj->GetState();
+ switch (m_operation)
+ {
+ case OP_CPY:
+ objMask = m_mask;
+ break;
+ case OP_SET:
+ objMask |= m_mask;
+ break;
+ case OP_CLR:
+ objMask &= ~m_mask;
+ break;
+ case OP_NEG:
+ objMask ^= m_mask;
+ break;
+ default:
+ // unsupported operation, no nothing
+ return false;
+ }
+ obj->SetState(objMask);
+ return false;
+}
+
+/* ------------------------------------------------------------------------- */
+/* Python functions */
+/* ------------------------------------------------------------------------- */
+
+
+
+/* Integration hooks ------------------------------------------------------- */
+PyTypeObject
+KX_StateActuator::Type = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0,
+ "KX_StateActuator",
+ sizeof(KX_StateActuator),
+ 0,
+ PyDestructor,
+ 0,
+ __getattr,
+ __setattr,
+ 0, //&MyPyCompare,
+ __repr,
+ 0, //&cvalue_as_number,
+ 0,
+ 0,
+ 0,
+ 0
+};
+
+PyParentObject
+KX_StateActuator::Parents[] = {
+ &KX_StateActuator::Type,
+ &SCA_IActuator::Type,
+ &SCA_ILogicBrick::Type,
+ &CValue::Type,
+ NULL
+};
+
+PyMethodDef
+KX_StateActuator::Methods[] = {
+ {"setOperation", (PyCFunction) KX_StateActuator::sPySetOperation,
+ METH_VARARGS, SetOperation_doc},
+ {"setMask", (PyCFunction) KX_StateActuator::sPySetMask,
+ METH_VARARGS, SetMask_doc},
+ {NULL,NULL} //Sentinel
+};
+
+PyObject*
+KX_StateActuator::_getattr(
+ const STR_String& attr
+ )
+{
+ _getattr_up(SCA_IActuator);
+};
+
+
+
+/* set operation ---------------------------------------------------------- */
+char
+KX_StateActuator::SetOperation_doc[] =
+"setOperation(op)\n"
+"\t - op : bit operation (0=Copy, 1=Set, 2=Clear, 3=Negate)"
+"\tSet the type of bit operation to be applied on object state mask.\n"
+"\tUse setMask() to specify the bits that will be modified.\n";
+PyObject*
+
+KX_StateActuator::PySetOperation(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ int oper;
+
+ if(!PyArg_ParseTuple(args, "i", &oper)) {
+ return NULL;
+ }
+
+ m_operation = oper;
+
+ Py_Return;
+}
+
+/* set mask ---------------------------------------------------------- */
+char
+KX_StateActuator::SetMask_doc[] =
+"setMask(mask)\n"
+"\t - mask : bits that will be modified"
+"\tSet the value that defines the bits that will be modified by the operation.\n"
+"\tThe bits that are 1 in the value will be updated in the object state,\n"
+"\tthe bits that are 0 are will be left unmodified expect for the Copy operation\n"
+"\twhich copies the value to the object state.\n";
+PyObject*
+
+KX_StateActuator::PySetMask(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ int mask;
+
+ if(!PyArg_ParseTuple(args, "i", &mask)) {
+ return NULL;
+ }
+
+ m_mask = mask;
+
+ Py_Return;
+}
+
+
diff --git a/source/gameengine/Ketsji/KX_StateActuator.h b/source/gameengine/Ketsji/KX_StateActuator.h
new file mode 100644
index 00000000000..8698e51b2c1
--- /dev/null
+++ b/source/gameengine/Ketsji/KX_StateActuator.h
@@ -0,0 +1,83 @@
+/*
+ * $Id$
+ *
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ * Actuator to toggle visibility/invisibility of objects
+ */
+
+#ifndef __KX_STATEACTUATOR
+#define __KX_STATEACTUATOR
+
+#include "SCA_IActuator.h"
+
+class KX_StateActuator : public SCA_IActuator
+{
+ Py_Header;
+
+ /** Make visible? */
+ enum {
+ OP_CPY = 0,
+ OP_SET,
+ OP_CLR,
+ OP_NEG
+ };
+ int m_operation;
+ unsigned int m_mask;
+
+ public:
+
+ KX_StateActuator(
+ SCA_IObject* gameobj,
+ int operation,
+ unsigned int mask,
+ PyTypeObject* T=&Type
+ );
+
+ virtual
+ ~KX_StateActuator(
+ void
+ );
+
+ virtual CValue*
+ GetReplica(
+ void
+ );
+
+ virtual bool
+ Update();
+
+ /* --------------------------------------------------------------------- */
+ /* Python interface ---------------------------------------------------- */
+ /* --------------------------------------------------------------------- */
+
+ virtual PyObject* _getattr(const STR_String& attr);
+ //KX_PYMETHOD_DOC
+ KX_PYMETHOD_DOC(KX_StateActuator,SetOperation);
+ KX_PYMETHOD_DOC(KX_StateActuator,SetMask);
+};
+
+#endif
+
diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp
index 3f185359de0..56c2780871b 100644
--- a/source/gameengine/Ketsji/KX_TouchSensor.cpp
+++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp
@@ -77,18 +77,14 @@ KX_TouchSensor::KX_TouchSensor(SCA_EventManager* eventmgr,KX_GameObject* gameobj
:SCA_ISensor(gameobj,eventmgr,T),
m_touchedpropname(touchedpropname),
m_bFindMaterial(bFindMaterial),
-m_eventmgr(eventmgr),
+m_eventmgr(eventmgr)
/*m_sumoObj(sumoObj),*/
-m_bCollision(false),
-m_bTriggered(false),
-m_bLastTriggered(false)
{
// KX_TouchEventManager* touchmgr = (KX_TouchEventManager*) eventmgr;
// m_resptable = touchmgr->GetResponseTable();
// m_solidHandle = m_sumoObj->getObjectHandle();
- m_hitObject = NULL;
m_colliders = new CListValue();
KX_ClientObjectInfo *client_info = gameobj->getClientInfo();
@@ -98,8 +94,16 @@ m_bLastTriggered(false)
m_physCtrl = dynamic_cast<PHY_IPhysicsController*>(gameobj->GetPhysicsController());
MT_assert( !gameobj->GetPhysicsController() || m_physCtrl );
+ Init();
}
+void KX_TouchSensor::Init()
+{
+ m_bCollision = false;
+ m_bTriggered = false;
+ m_bLastTriggered = false;
+ m_hitObject = NULL;
+}
KX_TouchSensor::~KX_TouchSensor()
{
diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h
index f594196628a..056440ccd6c 100644
--- a/source/gameengine/Ketsji/KX_TouchSensor.h
+++ b/source/gameengine/Ketsji/KX_TouchSensor.h
@@ -72,6 +72,7 @@ public:
virtual CValue* GetReplica();
virtual void SynchronizeTransform();
virtual bool Evaluate(CValue* event);
+ virtual void Init();
virtual void ReParent(SCA_IObject* parent);
virtual void RegisterSumo(KX_TouchEventManager* touchman);