#pragma once #include #include #include namespace td { template class StateStack { public: class State { public: State(TDerived& a_StateStack) : m_StateStack(a_StateStack) {} virtual ~State() {} virtual TReturn Update(TArgs... args) = 0; protected: /** * \brief Called when enabled (can be used to connect signals) */ virtual void OnEnable() {} /** * \brief Called when disabled (can be used to disconnect signals) */ virtual void OnDisable() {} protected: TDerived& m_StateStack; friend class StateStack; }; StateStack() {} StateStack(StateStack&&) = default; virtual ~StateStack() {} virtual TReturn Update(TArgs... args) { assert(!m_States.empty() && "You must push at least one state before updating !"); return m_States.back()->Update(args...); } void PopState() { assert(!m_States.empty() && "You must push at least one state before poping !"); m_States.back()->OnDisable(); m_States.pop_back(); if (m_States.empty()) return; m_States.back()->OnEnable(); } template T* PushState(Args&&... args) { if (!m_States.empty()) m_States.back()->OnDisable(); auto newState = std::make_unique(static_cast(*this), std::forward(args)...); newState->OnEnable(); m_States.push_back(std::move(newState)); return static_cast(newState.get()); } private: std::vector> m_States; }; } // namespace td