diff --git a/libs/app/include/psemek/app/app.hpp b/libs/app/include/psemek/app/app.hpp index 9f5a07ca..7c4d9c2b 100644 --- a/libs/app/include/psemek/app/app.hpp +++ b/libs/app/include/psemek/app/app.hpp @@ -29,7 +29,8 @@ namespace psemek::app void poll_events(); void run(); - scene * set_scene(scene * s); + void push_scene(std::unique_ptr s); + std::unique_ptr pop_scene(); void show_cursor(bool show); void vsync(bool on); diff --git a/libs/app/source/app.cpp b/libs/app/source/app.cpp index 4eafd637..d92a3038 100644 --- a/libs/app/source/app.cpp +++ b/libs/app/source/app.cpp @@ -5,6 +5,8 @@ #include +#include + namespace psemek::app { @@ -18,7 +20,7 @@ namespace psemek::app SDL_Window * window = nullptr; SDL_GLContext gl_context = nullptr; - scene * current_scene = nullptr; + std::vector> scene_stack; bool running = false; @@ -39,8 +41,8 @@ namespace psemek::app scene * get_scene() { - if (current_scene) - return current_scene; + if (!scene_stack.empty()) + return scene_stack.back().get(); return parent; } }; @@ -199,36 +201,50 @@ namespace psemek::app { SDL_ShowWindow(impl().window); impl().running = true; - if (impl().current_scene == nullptr) + if (impl().get_scene() == this) on_scene_enter(this); while (running()) { poll_events(); - auto handler = impl().get_scene(); + auto handler = [this]{ return impl().get_scene(); }; if (!impl().had_initial_resize) { int w, h; SDL_GetWindowSize(impl().window, &w, &h); impl().had_initial_resize = true; - handler->on_resize(w, h); + handler()->on_resize(w, h); } if (!running()) break; - handler->update(); - handler->present(); + handler()->update(); + handler()->present(); SDL_GL_SwapWindow(impl().window); } impl().get_scene()->on_scene_exit(); } - scene * app::set_scene(scene * s) + void app::push_scene(std::unique_ptr s) { impl().get_scene()->on_scene_exit(); impl().had_initial_resize = false; - std::swap(s, impl().current_scene); + impl().scene_stack.push_back(std::move(s)); + + impl().get_scene()->on_scene_enter(this); + } + + std::unique_ptr app::pop_scene() + { + if (impl().scene_stack.empty()) + return nullptr; + + impl().get_scene()->on_scene_exit(); + + impl().had_initial_resize = false; + auto s = std::move(impl().scene_stack.back()); + impl().scene_stack.pop_back(); impl().get_scene()->on_scene_enter(this);