Application::Application(sdl::InitScreen *screen, State *initialState)
: screen(screen)
, states()
-, last(SDL_GetTicks())
-, toPop(0) {
+, last(SDL_GetTicks()) {
assert(screen && "cannot create application without screen");
assert(initialState && "cannot create application without initial state");
RealPushState(initialState);
}
void Application::UpdateState() {
- while (toPop > 0) {
- RealPopState();
- --toPop;
- }
- while (!toPush.empty()) {
- State *s(toPush.front());
- toPush.pop();
- RealPushState(s);
+ while (!stateChanges.empty()) {
+ switch (stateChanges.front().type) {
+ case StateCommand::PUSH:
+ RealPushState(stateChanges.front().state);
+ break;
+ case StateCommand::POP:
+ RealPopState();
+ break;
+ case StateCommand::CHANGE:
+ RealChangeState(stateChanges.front().state);
+ break;
+ }
+ stateChanges.pop();
}
}
void Application::ChangeState(State *s) {
- PopState();
- PushState(s);
+ StateCommand cmd;
+ cmd.type = StateCommand::CHANGE;
+ cmd.state = s;
+ stateChanges.push(cmd);
}
void Application::PushState(State *s) {
- toPush.push(s);
+ StateCommand cmd;
+ cmd.type = StateCommand::PUSH;
+ cmd.state = s;
+ stateChanges.push(cmd);
}
-void Application::RealPushState(State *s) {
+void Application::PopState() {
+ StateCommand cmd;
+ cmd.type = StateCommand::POP;
+ cmd.state = 0;
+ stateChanges.push(cmd);
+}
+
+void Application::RealChangeState(State *s) {
+ if (!states.empty()) {
+ states.top()->PauseState(*this, screen->Screen());
+ states.top()->ExitState(*this, screen->Screen());
+ states.pop();
+ }
states.push(s);
s->EnterState(*this, screen->Screen());
+ s->ResumeState(*this, screen->Screen());
}
-void Application::PopState() {
- ++toPop;
+void Application::RealPushState(State *s) {
+ if (!states.empty()) {
+ states.top()->PauseState(*this, screen->Screen());
+ }
+ states.push(s);
+ s->EnterState(*this, screen->Screen());
+ s->ResumeState(*this, screen->Screen());
}
void Application::RealPopState() {
if (states.empty()) return;
- states.top()->ExitState();
+ states.top()->PauseState(*this, screen->Screen());
+ states.top()->ExitState(*this, screen->Screen());
delete states.top();
states.pop();
+ if (!states.empty()) {
+ states.top()->ResumeState(*this, screen->Screen());
+ }
}
void Application::Quit() {
if (deltaT > 34) deltaT = 34;
HandleEvents();
- UpdateWorld(deltaT);
- Render();
+ if (!StateChangePending()) {
+ UpdateWorld(deltaT);
+ Render();
+ }
last = now;
UpdateState();