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)
|
static std::vector<std::string> GetEnumNames(const std::string& enumNames)
|
||||||
{
|
{
|
||||||
std::vector<std::string> strs;
|
std::vector<std::string> strs;
|
||||||
size_t lastPos = 0;
|
size_t lastPos = 1;
|
||||||
size_t pos = enumNames.find(',', lastPos);
|
size_t pos = enumNames.find(',', lastPos);
|
||||||
while (pos != std::string::npos)
|
while (pos != std::string::npos)
|
||||||
{
|
{
|
||||||
@@ -41,7 +41,7 @@ namespace Copium
|
|||||||
lastPos++;
|
lastPos++;
|
||||||
pos = enumNames.find(',', lastPos);
|
pos = enumNames.find(',', lastPos);
|
||||||
}
|
}
|
||||||
strs.emplace_back(enumNames.substr(lastPos));
|
strs.emplace_back(enumNames.substr(lastPos, enumNames.size() - lastPos - 1));
|
||||||
return strs;
|
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