Add StateMachine class

This commit is contained in:
Thraix
2026-06-28 20:41:40 +02:00
parent f27911fe28
commit 72c2bb5336
@@ -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();
}
}
};
}