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() { }
+
};
};
}
+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
}
-#ifndef BLANK_APP_PRELOADSTATE_HPP_
-#define BLANK_APP_PRELOADSTATE_HPP_
+#ifndef BLANK_APP_UNLOADSTATE_HPP_
+#define BLANK_APP_UNLOADSTATE_HPP_
#include "State.hpp"
public:
UnloadState(Environment &, ChunkLoader &);
+ void OnResume();
+
void Handle(const SDL_Event &) override;
void Update(int dt) override;
void Render(Viewport &) override;
#include "WorldState.hpp"
#include "Environment.hpp"
-#include "UnloadState.hpp"
#include <SDL.h>
: 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:
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;
#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"
const WorldSave &
);
+ void OnEnter() override;
+
void Handle(const SDL_Event &) override;
void Update(int dt) override;
void Render(Viewport &) override;
Spawner spawner;
Interface interface;
+ PreloadState preload;
+ UnloadState unload;
+
};
}
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;
}
#include "Application.hpp"
#include "Environment.hpp"
-#include "PreloadState.hpp"
#include "Runtime.hpp"
#include "WorldState.hpp"
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: