Files
Tower-Defense2/include/td/common/StateMachine.h
2025-08-22 11:41:58 +02:00

55 lines
1.3 KiB
C++

#pragma once
#include <cassert>
#include <td/misc/Signal.h>
namespace td {
template <typename TDerived, typename TReturn, typename... TArgs>
class StateMachine {
public:
class State {
public:
State(TDerived& a_StateMachine) : m_StateMachine(a_StateMachine) {}
virtual ~State() {}
virtual TReturn Update(TArgs... args) = 0;
template <typename T, typename... Args>
T* ChangeState(Args... args) {
return m_StateMachine.template ChangeState<T>(std::forward<Args>(args)...);
}
protected:
TDerived& m_StateMachine;
};
utils::Signal<State&> OnStateChange;
StateMachine() {}
StateMachine(StateMachine&&) = default;
virtual ~StateMachine() {}
virtual TReturn Update(TArgs... args) {
assert(m_State && "You must change state at least once before updating !");
return m_State->Update(std::forward<TArgs>(args)...);
}
template <typename T, typename... Args>
T* ChangeState(Args... args) {
auto* currentState = m_State.get();
auto newState = std::make_unique<T>(static_cast<TDerived&>(*this), std::forward<Args>(args)...);
// This allows chaining
if (m_State.get() == currentState)
m_State = std::move(newState);
OnStateChange(*m_State);
return static_cast<T*>(m_State.get());
}
private:
std::unique_ptr<State> m_State;
};
} // namespace td