]> git.localhorst.tv Git - l2e.git/blobdiff - src/app/Application.cpp
better handling of nested state changes
[l2e.git] / src / app / Application.cpp
index 819882e7251f43e66b7ed77311f97c498e74d456..4de48d4f90541ad55481587c092c772015f88cd2 100644 (file)
@@ -16,7 +16,8 @@ namespace app {
 Application::Application(sdl::InitScreen *screen, State *initialState)
 : screen(screen)
 , states()
-, last(SDL_GetTicks()) {
+, last(SDL_GetTicks())
+, inStateChage(false) {
        assert(screen && "cannot create application without screen");
        assert(initialState && "cannot create application without initial state");
        RealPushState(initialState);
@@ -28,10 +29,11 @@ Application::~Application() {
 
 
 State *Application::CurrentState() {
-       return states.top();
+       return states.empty() ? 0 : states.top();
 }
 
 void Application::UpdateState() {
+       inStateChage = true;
        while (!stateChanges.empty()) {
                switch (stateChanges.front().type) {
                        case StateCommand::PUSH:
@@ -46,27 +48,40 @@ void Application::UpdateState() {
                }
                stateChanges.pop();
        }
+       inStateChage = false;
 }
 
 void Application::ChangeState(State *s) {
-       StateCommand cmd;
-       cmd.type = StateCommand::CHANGE;
-       cmd.state = s;
-       stateChanges.push(cmd);
+       if (inStateChage) {
+               RealChangeState(s);
+       } else {
+               StateCommand cmd;
+               cmd.type = StateCommand::CHANGE;
+               cmd.state = s;
+               stateChanges.push(cmd);
+       }
 }
 
 void Application::PushState(State *s) {
-       StateCommand cmd;
-       cmd.type = StateCommand::PUSH;
-       cmd.state = s;
-       stateChanges.push(cmd);
+       if (inStateChage) {
+               RealPushState(s);
+       } else {
+               StateCommand cmd;
+               cmd.type = StateCommand::PUSH;
+               cmd.state = s;
+               stateChanges.push(cmd);
+       }
 }
 
 void Application::PopState() {
-       StateCommand cmd;
-       cmd.type = StateCommand::POP;
-       cmd.state = 0;
-       stateChanges.push(cmd);
+       if (inStateChage) {
+               RealPopState();
+       } else {
+               StateCommand cmd;
+               cmd.type = StateCommand::POP;
+               cmd.state = 0;
+               stateChanges.push(cmd);
+       }
 }
 
 void Application::RealChangeState(State *s) {
@@ -106,7 +121,10 @@ void Application::Quit() {
 
 void Application::PopAllStates() {
        while (!states.empty()) {
-               RealPopState();
+               states.top()->PauseState(*this, screen->Screen());
+               states.top()->ExitState(*this, screen->Screen());
+               delete states.top();
+               states.pop();
        }
 }
 
@@ -121,7 +139,7 @@ void Application::Loop() {
        Uint32 now(SDL_GetTicks());
        Uint32 deltaT(now - last);
        GlobalTimers().Update(deltaT);
-       if (deltaT > 34) deltaT = 34;
+       if (deltaT > 30) deltaT = 30;
 
        if (CurrentState()) {
                CurrentState()->GraphicsTimers().Update(deltaT);
@@ -159,12 +177,12 @@ void Application::HandleEvents() {
                                break;
                }
        }
-       CurrentState()->HandleEvents(input);
+       if (CurrentState()) CurrentState()->HandleEvents(input);
 }
 
 void Application::UpdateWorld(Uint32 deltaT) {
        if (!CurrentState()) return;
-       for (Uint32 i(0); i < deltaT; ++i) {
+       for (Uint32 i(0); i < deltaT && !StateChangePending(); ++i) {
                CurrentState()->PhysicsTimers().Update(0.001f);
                CurrentState()->UpdateWorld(0.001f);
        }