1
0
forked from 0ad/0ad

Constrain the FSM-transition to have at most one action.

Accepted By: @vladislavbelov
Differential Revision: https://code.wildfiregames.com/D5059
This was SVN commit r27768.
This commit is contained in:
phosit 2023-07-19 12:23:53 +00:00
parent 1ff0b8f69f
commit 8b761fec29
2 changed files with 24 additions and 78 deletions

View File

@ -35,26 +35,10 @@ void CFsmEvent::SetParamRef(void* pParam)
m_Param = pParam;
}
CFsmTransition::CFsmTransition(unsigned int state)
{
m_CurrState = state;
}
CFsmTransition::~CFsmTransition()
{
m_Actions.clear();
}
void CFsmTransition::RegisterAction(void* pAction, void* pContext)
{
CallbackFunction callback;
// Add action at the end of actions list
callback.pFunction = pAction;
callback.pContext = pContext;
m_Actions.push_back(callback);
}
CFsmTransition::CFsmTransition(const unsigned int state, const CallbackFunction action)
: m_CurrState{state},
m_Action{action}
{}
void CFsmTransition::SetEvent(CFsmEvent* pEvent)
{
@ -66,22 +50,10 @@ void CFsmTransition::SetNextState(unsigned int nextState)
m_NextState = nextState;
}
bool CFsmTransition::RunActions() const
bool CFsmTransition::RunAction() const
{
bool result = true;
CallbackList::const_iterator it = m_Actions.begin();
for (; it != m_Actions.end(); ++it)
{
if (it->pFunction)
{
// Run action
Action* action = reinterpret_cast<Action*>(it->pFunction);
result &= action(it->pContext, m_Event);
}
}
return result;
return !m_Action.pFunction ||
reinterpret_cast<Action*>(m_Action.pFunction)(m_Action.pContext, m_Event);
}
CFsm::CFsm()
@ -150,7 +122,8 @@ CFsmEvent* CFsm::AddEvent(unsigned int eventType)
return pEvent;
}
CFsmTransition* CFsm::AddTransition(unsigned int state, unsigned int eventType, unsigned int nextState )
CFsmTransition* CFsm::AddTransition(unsigned int state, unsigned int eventType, unsigned int nextState,
void* pAction /* = nullptr */, void* pContext /* = nullptr*/)
{
// Make sure we store the current state
AddState(state);
@ -164,7 +137,7 @@ CFsmTransition* CFsm::AddTransition(unsigned int state, unsigned int eventType,
return nullptr;
// Create new transition
CFsmTransition* pNewTransition = new CFsmTransition(state);
CFsmTransition* pNewTransition = new CFsmTransition(state, {pAction, pContext});
// Setup new transition
pNewTransition->SetEvent(pEvent);
@ -176,20 +149,6 @@ CFsmTransition* CFsm::AddTransition(unsigned int state, unsigned int eventType,
return pNewTransition;
}
CFsmTransition* CFsm::AddTransition(unsigned int state, unsigned int eventType, unsigned int nextState,
void* pAction, void* pContext)
{
CFsmTransition* pTransition = AddTransition(state, eventType, nextState);
if (!pTransition)
return nullptr;
// If action specified, register it
if (pAction)
pTransition->RegisterAction(pAction, pContext);
return pTransition;
}
CFsmTransition* CFsm::GetTransition(unsigned int state, unsigned int eventType) const
{
if (!IsValidState(state))
@ -259,7 +218,7 @@ bool CFsm::Update(unsigned int eventType, void* pEventParam)
// to override this)
SetNextState(pTransition->GetNextState());
if (!pTransition->RunActions())
if (!pTransition->RunAction())
return false;
SetCurrState(GetNextState());

View File

@ -34,14 +34,13 @@ using Action = bool(void* pContext, const CFsmEvent* pEvent);
struct CallbackFunction
{
void* pFunction;
void* pContext;
void* pFunction{nullptr};
void* pContext{nullptr};
};
using StateSet = std::set<unsigned int>;
using EventMap = std::map<unsigned int, CFsmEvent*>;
using TransitionList = std::vector<CFsmTransition*>;
using CallbackList = std::vector<CallbackFunction>;
/**
* Represents a signal in the state machine that a change has occurred.
@ -81,16 +80,10 @@ class CFsmTransition
{
NONCOPYABLE(CFsmTransition);
public:
CFsmTransition(unsigned int state);
~CFsmTransition();
/**
* Registers an action that will be executed when the transition occurs.
* @param pAction the function which will be executed.
* @param pContext data passed to the function.
* @param action Object executed upon transition.
*/
void RegisterAction(void* pAction, void* pContext);
CFsmTransition(const unsigned int state, const CallbackFunction action);
/**
* Set event for which transition will occur.
@ -115,23 +108,23 @@ public:
return m_CurrState;
}
const CallbackList& GetActions() const
CallbackFunction GetAction() const
{
return m_Actions;
return m_Action;
}
/**
* Executes actions for the transition.
* @note If there are no actions, assume true.
* @return whether all the actions returned true.
* Executes action for the transition.
* @note If there are no action, assume true.
* @return whether the action returned true.
*/
bool RunActions() const;
bool RunAction() const;
private:
unsigned int m_CurrState;
unsigned int m_NextState;
CFsmEvent* m_Event;
CallbackList m_Actions;
CallbackFunction m_Action;
};
/**
@ -160,7 +153,7 @@ public:
virtual void Setup();
/**
* Clear event, action lists and reset state machine.
* Clear event, transition lists and reset state machine.
*/
void Shutdown();
@ -181,14 +174,8 @@ public:
* Adds a new transistion to the state machine.
* @return a pointer to the new transition.
*/
CFsmTransition* AddTransition(unsigned int state, unsigned int eventType, unsigned int nextState );
/**
* Adds a new transition to the state machine.
* @return a pointer to the new transition.
*/
CFsmTransition* AddTransition(unsigned int state, unsigned int eventType, unsigned int nextState,
void* pAction, void* pContext);
void* pAction = nullptr, void* pContext = nullptr);
/**
* Looks up the transition given the state, event and next state to transition to.