Add StateMachine class
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
||||
namespace copium
|
||||
{
|
||||
template <typename State, typename Trigger>
|
||||
class StateMachine
|
||||
{
|
||||
public:
|
||||
StateMachine(State initialState)
|
||||
: currentState{initialState},
|
||||
failOnInvalidTrigger{false}
|
||||
{
|
||||
}
|
||||
|
||||
StateMachine(State initialState, bool failOnInvalidTrigger)
|
||||
: currentState{initialState},
|
||||
failOnInvalidTrigger{failOnInvalidTrigger}
|
||||
{
|
||||
}
|
||||
|
||||
void AddTransition(State from, State to, Trigger trigger)
|
||||
{
|
||||
auto& map = transitionMap[from];
|
||||
CP_ASSERT(
|
||||
map.find(trigger) == map.end(), "Transition already exists for state {} using trigger {}", from, trigger);
|
||||
|
||||
map[trigger] = to;
|
||||
}
|
||||
|
||||
void HandleTrigger(Trigger trigger)
|
||||
{
|
||||
auto& map = transitionMap[currentState];
|
||||
auto it = map.find(trigger);
|
||||
if (it == map.end())
|
||||
{
|
||||
CP_ASSERT(!failOnInvalidTrigger, "Trigger {} doesn't exist for state {}", trigger, currentState);
|
||||
return;
|
||||
}
|
||||
|
||||
CP_DEBUG("Transitioning from state {} to state {} due to trigger {}", currentState, it->second, trigger);
|
||||
RunTrigger(leaveTriggers);
|
||||
currentState = it->second;
|
||||
RunTrigger(enterTriggers);
|
||||
}
|
||||
|
||||
void AddEnterTrigger(State from, std::function<void()> func)
|
||||
{
|
||||
CP_ASSERT(enterTriggers.find(from) == enterTriggers.end(), "State {} already has an enter trigger", from);
|
||||
enterTriggers[from] = func;
|
||||
}
|
||||
|
||||
void AddLeaveTrigger(State from, std::function<void()> func)
|
||||
{
|
||||
CP_ASSERT(leaveTriggers.find(from) == leaveTriggers.end(), "State {} already has a leave trigger", from);
|
||||
leaveTriggers[from] = func;
|
||||
}
|
||||
|
||||
State GetCurrentState() const
|
||||
{
|
||||
return currentState;
|
||||
}
|
||||
|
||||
private:
|
||||
State currentState;
|
||||
bool failOnInvalidTrigger;
|
||||
|
||||
std::map<State, std::map<Trigger, State>> transitionMap;
|
||||
|
||||
std::map<State, std::function<void()>> enterTriggers;
|
||||
std::map<State, std::function<void()>> leaveTriggers;
|
||||
|
||||
void RunTrigger(const std::map<State, std::function<void()>>& triggers)
|
||||
{
|
||||
auto it = triggers.find(currentState);
|
||||
if (it != triggers.end())
|
||||
{
|
||||
it->second();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user