From: Daniel Karbach Date: Tue, 11 Aug 2015 08:06:11 +0000 (+0200) Subject: enhanced application state control X-Git-Url: https://git.localhorst.tv/?a=commitdiff_plain;h=f5e5e8522b94a6b81a137d4bca7665ef15bcd2c6;hp=29ee0558fdd951b25f41005ed721241b1f28aefa;p=blank.git enhanced application state control --- diff --git a/src/app/State.hpp b/src/app/State.hpp index 2bdd41b..86ff0ad 100644 --- a/src/app/State.hpp +++ b/src/app/State.hpp @@ -6,16 +6,28 @@ namespace blank { +class Application; class Viewport; struct State { + friend class Application; + virtual void Handle(const SDL_Event &) = 0; virtual void Update(int dt) = 0; virtual void Render(Viewport &) = 0; + +private: + int ref_count = 0; + + virtual void OnEnter() { } + virtual void OnResume() { } + virtual void OnPause() { } + virtual void OnExit() { } + }; }; diff --git a/src/app/UnloadState.cpp b/src/app/UnloadState.cpp index 49801bf..9da6989 100644 --- a/src/app/UnloadState.cpp +++ b/src/app/UnloadState.cpp @@ -22,6 +22,14 @@ UnloadState::UnloadState(Environment &env, ChunkLoader &loader) } +void UnloadState::OnResume() { + cur = loader.Loaded().begin(); + end = loader.Loaded().end(); + done = 0; + total = loader.Loaded().size(); +} + + void UnloadState::Handle(const SDL_Event &) { // ignore everything } diff --git a/src/app/UnloadState.hpp b/src/app/UnloadState.hpp index 56394bb..6d5cea7 100644 --- a/src/app/UnloadState.hpp +++ b/src/app/UnloadState.hpp @@ -1,5 +1,5 @@ -#ifndef BLANK_APP_PRELOADSTATE_HPP_ -#define BLANK_APP_PRELOADSTATE_HPP_ +#ifndef BLANK_APP_UNLOADSTATE_HPP_ +#define BLANK_APP_UNLOADSTATE_HPP_ #include "State.hpp" @@ -22,6 +22,8 @@ class UnloadState public: UnloadState(Environment &, ChunkLoader &); + void OnResume(); + void Handle(const SDL_Event &) override; void Update(int dt) override; void Render(Viewport &) override; diff --git a/src/app/WorldState.cpp b/src/app/WorldState.cpp index 86e3eac..372b659 100644 --- a/src/app/WorldState.cpp +++ b/src/app/WorldState.cpp @@ -1,7 +1,6 @@ #include "WorldState.hpp" #include "Environment.hpp" -#include "UnloadState.hpp" #include @@ -17,11 +16,18 @@ WorldState::WorldState( : env(env) , world(env.assets, wc, save) , spawner(world) -, interface(ic, env, world) { +, interface(ic, env, world) +, preload(env, world.Loader()) +, unload(env, world.Loader()) { } +void WorldState::OnEnter() { + env.state.Push(&preload); +} + + void WorldState::Handle(const SDL_Event &event) { switch (event.type) { case SDL_KEYDOWN: @@ -43,8 +49,7 @@ void WorldState::Handle(const SDL_Event &event) { interface.Handle(event.wheel); break; case SDL_QUIT: - // don't care about this leak just now - env.state.Switch(new UnloadState(env, world.Loader())); + env.state.Switch(&unload); break; default: break; diff --git a/src/app/WorldState.hpp b/src/app/WorldState.hpp index 38f8944..6ab613f 100644 --- a/src/app/WorldState.hpp +++ b/src/app/WorldState.hpp @@ -1,7 +1,9 @@ #ifndef BLANK_APP_WORLDSTATE_HPP_ #define BLANK_APP_WORLDSTATE_HPP_ +#include "PreloadState.hpp" #include "State.hpp" +#include "UnloadState.hpp" #include "../ai/Spawner.hpp" #include "../ui/Interface.hpp" #include "../world/World.hpp" @@ -22,6 +24,8 @@ public: const WorldSave & ); + void OnEnter() override; + void Handle(const SDL_Event &) override; void Update(int dt) override; void Render(Viewport &) override; @@ -34,6 +38,9 @@ private: Spawner spawner; Interface interface; + PreloadState preload; + UnloadState unload; + }; } diff --git a/src/app/app.cpp b/src/app/app.cpp index 4a4769b..880dc71 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -145,18 +145,41 @@ void Application::Render() { void Application::PushState(State *s) { + if (!states.empty()) { + states.top()->OnPause(); + } states.emplace(s); + ++s->ref_count; + if (s->ref_count == 1) { + s->OnEnter(); + } + s->OnResume(); } State *Application::PopState() { State *s = states.top(); states.pop(); + s->OnPause(); + s->OnExit(); + if (!states.empty()) { + states.top()->OnResume(); + } return s; } State *Application::SwitchState(State *s_new) { State *s_old = states.top(); states.top() = s_new; + --s_old->ref_count; + ++s_new->ref_count; + s_old->OnPause(); + if (s_old->ref_count == 0) { + s_old->OnExit(); + } + if (s_new->ref_count == 1) { + s_new->OnEnter(); + } + s_new->OnResume(); return s_old; } diff --git a/src/app/runtime.cpp b/src/app/runtime.cpp index 32a4012..85d8280 100644 --- a/src/app/runtime.cpp +++ b/src/app/runtime.cpp @@ -1,6 +1,5 @@ #include "Application.hpp" #include "Environment.hpp" -#include "PreloadState.hpp" #include "Runtime.hpp" #include "WorldState.hpp" @@ -244,9 +243,6 @@ int Runtime::Execute() { WorldState world_state(env, config.interface, config.world, save); app.PushState(&world_state); - PreloadState preloader(env, world_state.GetWorld().Loader()); - app.PushState(&preloader); - switch (mode) { default: case NORMAL: