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.
This commit is contained in:
@@ -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())
|
||||
|
||||
@@ -33,8 +33,7 @@
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
@@ -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<SCA_ILogicBrick> 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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -212,17 +212,22 @@ void SCA_LogicManager::UpdateFrame(double curtime, bool frame)
|
||||
(*ie)->UpdateFrame();
|
||||
|
||||
SG_DList::iterator<SG_QList> io(m_activeActuators);
|
||||
for (io.begin(); !io.end(); ++io)
|
||||
for (io.begin(); !io.end(); )
|
||||
{
|
||||
SG_QList::iterator<SCA_IActuator> 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<SCA_IActuator> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,9 +87,6 @@ class SCA_LogicManager
|
||||
|
||||
GEN_Map<STR_HashedString,void*> m_map_gamemeshname_to_blendobj;
|
||||
GEN_Map<CHashedPtr,void*> m_map_blendobj_to_gameobj;
|
||||
|
||||
// head of actuators being deactivated during the logic update
|
||||
SG_DList m_removedActuators;
|
||||
public:
|
||||
SCA_LogicManager();
|
||||
virtual ~SCA_LogicManager();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
T* m_current;
|
||||
public:
|
||||
typedef iterator<T> _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()
|
||||
|
||||
Reference in New Issue
Block a user