Compare commits
2 Commits
9a3b3aa13c
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 72c2bb5336 | |||
| f27911fe28 |
@@ -30,7 +30,7 @@ namespace Copium
|
||||
static std::vector<std::string> GetEnumNames(const std::string& enumNames)
|
||||
{
|
||||
std::vector<std::string> strs;
|
||||
size_t lastPos = 0;
|
||||
size_t lastPos = 1;
|
||||
size_t pos = enumNames.find(',', lastPos);
|
||||
while (pos != std::string::npos)
|
||||
{
|
||||
@@ -41,7 +41,7 @@ namespace Copium
|
||||
lastPos++;
|
||||
pos = enumNames.find(',', lastPos);
|
||||
}
|
||||
strs.emplace_back(enumNames.substr(lastPos));
|
||||
strs.emplace_back(enumNames.substr(lastPos, enumNames.size() - lastPos - 1));
|
||||
return strs;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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