#ifndef JUMPARTIFACT_DOT_COM_DEMO_0_SCREEN_H_ #define JUMPARTIFACT_DOT_COM_DEMO_0_SCREEN_H_ #include #include #include // Forward declaration. class ScreenStack; class Screen { public: using Ptr = std::unique_ptr; template static Ptr new_screen(std::weak_ptr stack); virtual ~Screen() {} // No copy. Screen(const Screen&) = delete; Screen& operator=(const Screen&) = delete; // Allow move. Screen(Screen&&) = default; Screen& operator=(Screen&&) = default; /// Return true if next screen should be updated. virtual bool update(float dt) = 0; /// Return true if next screen should be drawn. virtual bool draw() = 0; protected: Screen(std::weak_ptr stack); std::weak_ptr stack; }; class ScreenStack { private: enum Action { PUSH_SCREEN, POP_SCREEN, NOP }; struct PendingAction { PendingAction(); PendingAction(Action action); PendingAction(Screen::Ptr&&); // No copy. PendingAction(const PendingAction&) = delete; PendingAction& operator=(const PendingAction&) = delete; // Allow move. PendingAction(PendingAction&&) = default; PendingAction& operator=(PendingAction&&) = default; Screen::Ptr screen; Action action; }; public: using Ptr = std::shared_ptr; using Weak = std::weak_ptr; static Ptr new_instance(); // No copy. ScreenStack(const ScreenStack&) = delete; ScreenStack& operator=(const ScreenStack&) = delete; // Allow move. ScreenStack(ScreenStack&&) = default; ScreenStack& operator=(ScreenStack&&) = default; void update(float dt); void draw(); void push_screen(Screen::Ptr&& screen); template void push_screen(); void pop_screen(); private: ScreenStack(); void handle_pending_actions(); Weak self_weak; std::vector stack; std::deque actions; }; template Screen::Ptr Screen::new_screen(std::weak_ptr stack) { return std::unique_ptr(new SubScreen{stack}); } template void ScreenStack::push_screen() { stack.emplace_back(Screen::new_screen(self_weak)); } #endif