App uses a scene stack & owns scenes

This commit is contained in:
Nikita Lisitsa 2021-03-03 18:03:40 +03:00
parent 908b6cc5c9
commit 4ba85c9e79
2 changed files with 28 additions and 11 deletions

View file

@ -29,7 +29,8 @@ namespace psemek::app
void poll_events(); void poll_events();
void run(); void run();
scene * set_scene(scene * s); void push_scene(std::unique_ptr<scene> s);
std::unique_ptr<scene> pop_scene();
void show_cursor(bool show); void show_cursor(bool show);
void vsync(bool on); void vsync(bool on);

View file

@ -5,6 +5,8 @@
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <vector>
namespace psemek::app namespace psemek::app
{ {
@ -18,7 +20,7 @@ namespace psemek::app
SDL_Window * window = nullptr; SDL_Window * window = nullptr;
SDL_GLContext gl_context = nullptr; SDL_GLContext gl_context = nullptr;
scene * current_scene = nullptr; std::vector<std::unique_ptr<scene>> scene_stack;
bool running = false; bool running = false;
@ -39,8 +41,8 @@ namespace psemek::app
scene * get_scene() scene * get_scene()
{ {
if (current_scene) if (!scene_stack.empty())
return current_scene; return scene_stack.back().get();
return parent; return parent;
} }
}; };
@ -199,36 +201,50 @@ namespace psemek::app
{ {
SDL_ShowWindow(impl().window); SDL_ShowWindow(impl().window);
impl().running = true; impl().running = true;
if (impl().current_scene == nullptr) if (impl().get_scene() == this)
on_scene_enter(this); on_scene_enter(this);
while (running()) while (running())
{ {
poll_events(); poll_events();
auto handler = impl().get_scene(); auto handler = [this]{ return impl().get_scene(); };
if (!impl().had_initial_resize) if (!impl().had_initial_resize)
{ {
int w, h; int w, h;
SDL_GetWindowSize(impl().window, &w, &h); SDL_GetWindowSize(impl().window, &w, &h);
impl().had_initial_resize = true; impl().had_initial_resize = true;
handler->on_resize(w, h); handler()->on_resize(w, h);
} }
if (!running()) break; if (!running()) break;
handler->update(); handler()->update();
handler->present(); handler()->present();
SDL_GL_SwapWindow(impl().window); SDL_GL_SwapWindow(impl().window);
} }
impl().get_scene()->on_scene_exit(); impl().get_scene()->on_scene_exit();
} }
scene * app::set_scene(scene * s) void app::push_scene(std::unique_ptr<scene> s)
{ {
impl().get_scene()->on_scene_exit(); impl().get_scene()->on_scene_exit();
impl().had_initial_resize = false; 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<scene> 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); impl().get_scene()->on_scene_enter(this);