Compare commits

...

2 Commits

Author SHA1 Message Date
Thraix 72c2bb5336 Add StateMachine class 2026-06-28 20:44:16 +02:00
Thraix f27911fe28 Fix enums printing " for first and last enum 2026-06-26 07:26:46 +02:00
2 changed files with 86 additions and 2 deletions
+2 -2
View File
@@ -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();
}
}
};
}