#include "screen.h" // standard library includes #include #ifndef NDEBUG #include #endif // NDEBUG // local includes #include "screen_test.h" Screen::Screen(std::weak_ptr stack) : stack(stack) {} ScreenStack::PendingAction::PendingAction() : screen(), action(Action::NOP) {} ScreenStack::PendingAction::PendingAction(Action action) : screen(), action(action) {} ScreenStack::PendingAction::PendingAction(Screen::Ptr &&screen) : screen(std::forward(screen)), action(Action::PUSH_SCREEN) {} ScreenStack::Ptr ScreenStack::new_instance() { std::shared_ptr ptr = std::shared_ptr(new ScreenStack{}); ptr->self_weak = ptr; return ptr; } void ScreenStack::update(float dt) { handle_pending_actions(); auto idx = stack.size(); if (idx == 0) { #ifndef NDEBUG std::cerr << "WARNING: Stack is empty, pushing TestScreen...\n"; #endif // NDEBUG push_screen(Screen::new_screen(self_weak)); update(dt); return; } while (idx > 0 && stack.at(--idx)->update(dt)) { } } void ScreenStack::draw() { auto idx = stack.size(); while (idx > 0 && stack.at(--idx)->draw()) { } } void ScreenStack::push_screen(Screen::Ptr &&screen) { actions.push_back(PendingAction(std::forward(screen))); } void ScreenStack::pop_screen() { actions.push_back(PendingAction(Action::POP_SCREEN)); } void ScreenStack::clear_screens() { actions.push_back(PendingAction(Action::CLEAR_SCREENS)); } ScreenStack::ScreenStack() : self_weak(), stack(), actions() {} void ScreenStack::handle_pending_actions() { while (!actions.empty()) { switch (actions.front().action) { case Action::PUSH_SCREEN: stack.push_back(std::move(actions.front().screen)); break; case Action::POP_SCREEN: if (!stack.empty()) { stack.pop_back(); } #ifndef NDEBUG else { std::cerr << "WARNING: Tried to pop screen when stack was empty!\n"; } #endif // NDEBUG break; case Action::CLEAR_SCREENS: #ifndef NDEBUG if (stack.empty()) { std::cerr << "WARNING: Clearing an empty screen stack!\n"; } #endif stack.clear(); break; case Action::NOP: // Intentionally left blank. break; default: assert(!"unreachable"); break; } actions.pop_front(); } }