Defer ScreenStack actions to start of update
This commit is contained in:
parent
a617ef3fb6
commit
7a4c8ea0f5
3 changed files with 77 additions and 10 deletions
|
@ -5,9 +5,7 @@
|
||||||
|
|
||||||
Game::Game()
|
Game::Game()
|
||||||
: screen_stack(ScreenStack::new_instance()),
|
: screen_stack(ScreenStack::new_instance()),
|
||||||
prev_time(std::chrono::steady_clock::now()) {
|
prev_time(std::chrono::steady_clock::now()) {}
|
||||||
screen_stack->push_screen<TestScreen>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::update() {
|
void Game::update() {
|
||||||
auto next_time = std::chrono::steady_clock::now();
|
auto next_time = std::chrono::steady_clock::now();
|
||||||
|
|
|
@ -1,7 +1,24 @@
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
|
||||||
|
// standard library includes
|
||||||
|
#include <cassert>
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#include <iostream>
|
||||||
|
#endif // NDEBUG
|
||||||
|
|
||||||
|
// local includes
|
||||||
|
#include "screen_test.h"
|
||||||
|
|
||||||
Screen::Screen(std::weak_ptr<ScreenStack> stack) : stack(stack) {}
|
Screen::Screen(std::weak_ptr<ScreenStack> 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::Ptr>(screen)), action(Action::PUSH_SCREEN) {}
|
||||||
|
|
||||||
ScreenStack::Ptr ScreenStack::new_instance() {
|
ScreenStack::Ptr ScreenStack::new_instance() {
|
||||||
std::shared_ptr<ScreenStack> ptr =
|
std::shared_ptr<ScreenStack> ptr =
|
||||||
std::shared_ptr<ScreenStack>(new ScreenStack{});
|
std::shared_ptr<ScreenStack>(new ScreenStack{});
|
||||||
|
@ -10,7 +27,17 @@ ScreenStack::Ptr ScreenStack::new_instance() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenStack::update(float dt) {
|
void ScreenStack::update(float dt) {
|
||||||
|
handle_pending_actions();
|
||||||
|
|
||||||
auto idx = stack.size();
|
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<TestScreen>(self_weak));
|
||||||
|
update(dt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
while (idx > 0 && stack.at(--idx)->update(dt)) {
|
while (idx > 0 && stack.at(--idx)->update(dt)) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,13 +49,33 @@ void ScreenStack::draw() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenStack::push_screen(Screen::Ptr &&screen) {
|
void ScreenStack::push_screen(Screen::Ptr &&screen) {
|
||||||
stack.emplace_back(std::forward<Screen::Ptr>(screen));
|
actions.push_back(PendingAction(std::forward<Screen::Ptr>(screen)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenStack::pop_screen() {
|
void ScreenStack::pop_screen() {
|
||||||
|
actions.push_back(PendingAction(Action::POP_SCREEN));
|
||||||
|
}
|
||||||
|
|
||||||
|
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()) {
|
if (!stack.empty()) {
|
||||||
stack.pop_back();
|
stack.pop_back();
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case Action::NOP:
|
||||||
|
// Intentionally left blank.
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(!"unreachable");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
actions.pop_front();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ScreenStack::ScreenStack() : self_weak(), stack() {}
|
|
||||||
|
|
26
src/screen.h
26
src/screen.h
|
@ -1,6 +1,7 @@
|
||||||
#ifndef JUMPARTIFACT_DOT_COM_DEMO_0_SCREEN_H_
|
#ifndef JUMPARTIFACT_DOT_COM_DEMO_0_SCREEN_H_
|
||||||
#define JUMPARTIFACT_DOT_COM_DEMO_0_SCREEN_H_
|
#define JUMPARTIFACT_DOT_COM_DEMO_0_SCREEN_H_
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -31,12 +32,30 @@ class Screen {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Screen(std::weak_ptr<ScreenStack> stack);
|
Screen(std::weak_ptr<ScreenStack> stack);
|
||||||
|
|
||||||
private:
|
|
||||||
std::weak_ptr<ScreenStack> stack;
|
std::weak_ptr<ScreenStack> stack;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ScreenStack {
|
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:
|
public:
|
||||||
using Ptr = std::shared_ptr<ScreenStack>;
|
using Ptr = std::shared_ptr<ScreenStack>;
|
||||||
using Weak = std::weak_ptr<ScreenStack>;
|
using Weak = std::weak_ptr<ScreenStack>;
|
||||||
|
@ -64,8 +83,11 @@ class ScreenStack {
|
||||||
private:
|
private:
|
||||||
ScreenStack();
|
ScreenStack();
|
||||||
|
|
||||||
|
void handle_pending_actions();
|
||||||
|
|
||||||
Weak self_weak;
|
Weak self_weak;
|
||||||
std::vector<Screen::Ptr> stack;
|
std::vector<Screen::Ptr> stack;
|
||||||
|
std::deque<PendingAction> actions;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename SubScreen>
|
template <typename SubScreen>
|
||||||
|
|
Loading…
Reference in a new issue