#pragma once #include #include namespace td { template class StateMachine { public: class State { public: State(TDerived& a_StateMachine) : m_StateMachine(a_StateMachine) {} virtual ~State() {} virtual TReturn Update(TArgs... args) = 0; template void ChangeState(Args... args) { m_StateMachine.template ChangeState(std::forward(args)...); } protected: TDerived& m_StateMachine; }; utils::Signal 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(args)...); } template void ChangeState(Args... args) { auto* currentState = m_State.get(); auto newState = std::make_unique(static_cast(*this), std::forward(args)...); // This allows chaining if (m_State.get() == currentState) { m_State = std::move(newState); OnStateChange(*m_State); } } private: std::unique_ptr m_State; }; } // namespace td