From c0844b7938ec21e1fcd2ceea11ef5ae18e39c070 Mon Sep 17 00:00:00 2001 From: Benoit Bolsee Date: Wed, 20 May 2009 08:45:42 +0000 Subject: [PATCH] BGE logic patch: fix another incompatibility with YF. Previous patch was not sorting the state actuators. This was causing some problems with YoFrankie that relies on the order of actuators when multiple state actuators are activated at once. Active state actuators will now be sorted per object. This doesn't change the fact that state actuators are executed before all other actuators as before. Incidently, made the logic loop faster. --- source/gameengine/GameLogic/SCA_IActuator.cpp | 2 ++ source/gameengine/GameLogic/SCA_IActuator.h | 3 +- source/gameengine/GameLogic/SCA_ILogicBrick.h | 28 +++++++++++++++++ source/gameengine/GameLogic/SCA_IObject.cpp | 3 +- source/gameengine/GameLogic/SCA_IObject.h | 6 ++++ .../gameengine/GameLogic/SCA_LogicManager.cpp | 30 ++++++++++--------- .../gameengine/GameLogic/SCA_LogicManager.h | 3 -- source/gameengine/Ketsji/KX_StateActuator.cpp | 12 ++++++-- source/gameengine/SceneGraph/SG_QList.h | 2 +- 9 files changed, 65 insertions(+), 24 deletions(-) diff --git a/source/gameengine/GameLogic/SCA_IActuator.cpp b/source/gameengine/GameLogic/SCA_IActuator.cpp index c2be36d5108..be7c2651686 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.cpp +++ b/source/gameengine/GameLogic/SCA_IActuator.cpp @@ -67,6 +67,8 @@ void SCA_IActuator::Activate(SG_DList& head) } } +// this function is only used to deactivate actuators outside the logic loop +// e.g. when an object is deleted. void SCA_IActuator::Deactivate() { if (QDelink()) diff --git a/source/gameengine/GameLogic/SCA_IActuator.h b/source/gameengine/GameLogic/SCA_IActuator.h index 2bd92c343b9..27afcbc386b 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.h +++ b/source/gameengine/GameLogic/SCA_IActuator.h @@ -33,8 +33,7 @@ #include /* - * Use of SG_DList : element of actuator being deactivated - * Head: SCA_LogicManager::m_removedActuators + * Use of SG_DList : None * Use of SG_QList : element of activated actuator list of their owner * Head: SCA_IObject::m_activeActuators */ diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h index 90881c0536f..779e5397a6a 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.h +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h @@ -92,6 +92,34 @@ public: it.add_back(this); } + // insert in a QList at position corresponding to m_Execute_Priority + // inside a longer list that contains elements of other objects. + // Sorting is done only between the elements of the same object. + // head is the head of the combined list + // current points to the first element of the object in the list, NULL if none yet + void InsertSelfActiveQList(SG_QList& head, SG_QList** current) + { + if (!*current) + { + // first element can be put anywhere + head.QAddBack(this); + *current = this; + return; + } + // note: we assume current points actually to one o our element, skip the tests + SG_QList::iterator it(head,*current); + if (m_Execute_Priority <= (*it)->m_Execute_Priority) + { + // this element comes before the first + *current = this; + } + else + { + for(++it; !it.end() && (*it)->m_gameobj == m_gameobj && m_Execute_Priority > (*it)->m_Execute_Priority; ++it); + } + it.add_back(this); + } + virtual bool LessComparedTo(SCA_ILogicBrick* other); virtual PyObject* py_getattro(PyObject *attr); diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index 2b87a7c1526..9876f2512c0 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -41,7 +41,8 @@ MT_Point3 SCA_IObject::m_sDummy=MT_Point3(0,0,0); SG_QList SCA_IObject::m_activeBookmarkedControllers; -SCA_IObject::SCA_IObject(PyTypeObject* T): CValue(T), m_initState(0), m_state(0) +SCA_IObject::SCA_IObject(PyTypeObject* T): CValue(T), m_initState(0), m_state(0), m_firstState(NULL) + { m_suspended = false; } diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h index c4f346059d4..eae427741ca 100644 --- a/source/gameengine/GameLogic/SCA_IObject.h +++ b/source/gameengine/GameLogic/SCA_IObject.h @@ -52,6 +52,7 @@ class SCA_IObject : public CValue Py_Header; protected: + friend class KX_StateActuator; friend class SCA_IActuator; friend class SCA_IController; SCA_SensorList m_sensors; @@ -97,6 +98,11 @@ protected: */ unsigned int m_state; + /** + * pointer inside state actuator list for sorting + */ + SG_QList* m_firstState; + public: SCA_IObject(PyTypeObject* T=&Type); diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp index 7acec465921..83271288154 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.cpp +++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp @@ -212,17 +212,22 @@ void SCA_LogicManager::UpdateFrame(double curtime, bool frame) (*ie)->UpdateFrame(); SG_DList::iterator io(m_activeActuators); - for (io.begin(); !io.end(); ++io) + for (io.begin(); !io.end(); ) { - SG_QList::iterator ia(*(*io)); - for (ia.begin(); !ia.end(); ++ia) + SG_QList* ahead = *io; + // increment now so that we can remove the current element + ++io; + SG_QList::iterator ia(*ahead); + for (ia.begin(); !ia.end(); ) { SCA_IActuator* actua = *ia; + // increment first to allow removal of inactive actuators. + ++ia; if (!actua->Update(curtime, frame)) { - // cannot deactive the actuator now as it will disturb the list - m_removedActuators.AddBack(actua); - actua->SetActive(false); + // this actuator is not active anymore, remove + actua->QDelink(); + actua->SetActive(false); } else if (actua->IsNoLink()) { // This actuator has no more links but it still active @@ -235,14 +240,11 @@ void SCA_LogicManager::UpdateFrame(double curtime, bool frame) actua->AddEvent(event); } } - } - - for (SCA_IActuator* act = (SCA_IActuator*)m_removedActuators.Remove(); - act != NULL; - act = (SCA_IActuator*)m_removedActuators.Remove()) - { - act->Deactivate(); - act->SetActive(false); + if (ahead->QEmpty()) + { + // no more active controller, remove from main list + ahead->Delink(); + } } } diff --git a/source/gameengine/GameLogic/SCA_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h index fe7b40b3ba4..53e75e1eaee 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.h +++ b/source/gameengine/GameLogic/SCA_LogicManager.h @@ -87,9 +87,6 @@ class SCA_LogicManager GEN_Map m_map_gamemeshname_to_blendobj; GEN_Map m_map_blendobj_to_gameobj; - - // head of actuators being deactivated during the logic update - SG_DList m_removedActuators; public: SCA_LogicManager(); virtual ~SCA_LogicManager(); diff --git a/source/gameengine/Ketsji/KX_StateActuator.cpp b/source/gameengine/Ketsji/KX_StateActuator.cpp index 5f9730d7e10..f6979eee0f4 100644 --- a/source/gameengine/Ketsji/KX_StateActuator.cpp +++ b/source/gameengine/Ketsji/KX_StateActuator.cpp @@ -73,7 +73,10 @@ KX_StateActuator::Update() { bool bNegativeEvent = IsNegativeEvent(); unsigned int objMask; - + + // execution of state actuator means that we are in the execution phase, reset this pointer + // because all the active actuator of this object will be removed for sure. + m_gameobj->m_firstState = NULL; RemoveAllEvents(); if (bNegativeEvent) return false; @@ -102,6 +105,8 @@ KX_StateActuator::Update() return false; } +// this function is only used to deactivate actuators outside the logic loop +// e.g. when an object is deleted. void KX_StateActuator::Deactivate() { if (QDelink()) @@ -115,9 +120,10 @@ void KX_StateActuator::Deactivate() void KX_StateActuator::Activate(SG_DList& head) { - // no need to sort the state actuators - if (m_stateActuatorHead.QAddBack(this)) + // sort the state actuators per object on the global list + if (QEmpty()) { + InsertSelfActiveQList(m_stateActuatorHead, &m_gameobj->m_firstState); // add front to make sure it runs before other actuators head.AddFront(&m_stateActuatorHead); } diff --git a/source/gameengine/SceneGraph/SG_QList.h b/source/gameengine/SceneGraph/SG_QList.h index 7a6b2e466c9..d8afc33ea4f 100644 --- a/source/gameengine/SceneGraph/SG_QList.h +++ b/source/gameengine/SceneGraph/SG_QList.h @@ -49,7 +49,7 @@ public: T* m_current; public: typedef iterator _myT; - iterator(SG_QList& head) : m_head(head), m_current(NULL) {} + iterator(SG_QList& head, SG_QList* current=NULL) : m_head(head) { m_current = (T*)current; } ~iterator() {} void begin()