]> Dogcows Code - chaz/yoink/blobdiff - src/Moof/Engine.cc
new level-based controllers
[chaz/yoink] / src / Moof / Engine.cc
index 18ce5d7e5f8c6d0b4664da080b16ba1ad2623ace..5bfaaf3cd8d715d0927c9a284a5199a6686e98a6 100644 (file)
@@ -26,7 +26,9 @@
 
 *******************************************************************************/
 
+#include <algorithm>
 #include <cstdlib>                     // exit
+#include <list>
 #include <string>
 
 #include <SDL/SDL.h>
@@ -35,6 +37,7 @@
 
 #include "Dispatcher.hh"
 #include "Engine.hh"
+#include "Event.hh"
 #include "Log.hh"
 #include "Random.hh"
 #include "Settings.hh"
@@ -48,10 +51,10 @@ namespace Mf {
 class Engine::Impl
 {
 public:
-       Impl(int argc, char* argv[], const std::string& configFile,
-                       const std::string& name, const std::string& iconFile,
-                       Engine* outer) :
-               interface(outer),
+       Impl(int argc, char* argv[], const std::string& name,
+                       const std::string& iconFile, const std::string& configFile,
+                       Engine& engine) :
+               interface(engine),
                timestep(0.01),
                printFps(false)
        {
@@ -109,7 +112,7 @@ public:
         * the exit code used to stop the loop.
         */
 
-       int run()
+       void run()
        {
                Scalar ticksNow = Timer::getTicks();
 
@@ -124,7 +127,6 @@ public:
                fps = 0;
                int frameAccum = 0;
 
-               running = true;
                do
                {
                        Scalar newTicks = Timer::getTicks();
@@ -139,7 +141,7 @@ public:
                        while (accumulator >= timestep)
                        {
                                dispatchEvents();
-                               interface->update(totalTime, timestep);
+                               update(totalTime, timestep);
 
                                totalTime += timestep;
                                accumulator -= timestep;
@@ -172,7 +174,7 @@ public:
                                        }
                                }
 
-                               interface->draw(accumulator / timestep);
+                               draw(accumulator / timestep);
                                video->swap();
 
                                nextDraw += drawRate;
@@ -187,12 +189,9 @@ public:
                        Timer::sleep(std::min(std::min(nextStep, nextDraw),
                                                Timer::getNextFire()), true);
                }
-               while (running);
-
-               return exitCode;
+               while (!stack.empty());
        }
 
-
        void dispatchEvents()
        {
                SDL_Event event;
@@ -205,7 +204,8 @@ public:
                                        if (event.key.keysym.sym == SDLK_ESCAPE &&
                                                        (SDL_GetModState() & KMOD_CTRL) )
                                        {
-                                          exit(0);
+                                               // emergency escape
+                                               exit(0);
                                        }
                                        break;
 
@@ -214,51 +214,133 @@ public:
                                        break;
                        }
 
-                       interface->handleEvent(event);
+                       handleEvent(event);
                }
        }
 
 
-       Engine*         interface;
+       void update(Scalar t, Scalar dt)
+       {
+               for (stackIt = stack.begin(); stackIt != stack.end(); ++stackIt)
+               {
+                       (*stackIt)->update(t, dt);
+               }
+       }
 
-       VideoP          video;
+       void draw(Scalar alpha)
+       {
+               // FIXME - this will crash if the layer being drawn pops itself
+               std::list<LayerP>::reverse_iterator it;
+               for (it = stack.rbegin(); it != stack.rend(); ++it)
+               {
+                       (*it)->draw(alpha);
+               }
+       }
 
-       bool            running;
-       int                     exitCode;
+       void handleEvent(const Event& event)
+       {
+               for (stackIt = stack.begin(); stackIt != stack.end(); ++stackIt)
+               {
+                       if ((*stackIt)->handleEvent(event)) break;
+               }
+       }
 
-       Scalar          timestep;
-       Scalar          drawRate;
 
-       long            fps;
-       bool            printFps;
-};
+       void pushLayer(LayerP layer)
+       {
+               ASSERT(layer && "cannot push null layer");
+               stack.push_front(layer);
+               layer->pushed(interface);
+       }
+
+       void popLayer()
+       {
+               bool fixIt = false;
+               if (stack.begin() == stackIt) fixIt = true;
 
+               LayerP popped = stack.front();
+               stack.pop_front();
+               popped->popped(interface);
 
-Engine::Engine(int argc, char* argv[], const std::string& configFile,
-               const std::string& name, const std::string& iconFile) :
-       impl_(new Engine::Impl(argc, argv, configFile, name, iconFile, this)) {}
+               if (fixIt) stackIt = --stack.begin();
+       }
+
+       void popLayer(Layer* layer)
+       {
+               bool fixIt = false;
 
-Engine::~Engine() {}
+               std::list<LayerP>::iterator it;
+               for (it = stack.begin(); it != stack.end(); ++it)
+               {
+                       if (it == stackIt) fixIt = true;
 
+                       if ((*it).get() == layer)
+                       {
+                               ++it;
+                               do
+                               {
+                                       LayerP popped = stack.front();
+                                       stack.pop_front();
+                                       popped->popped(interface);
+                               }
+                               while (stack.begin() != it);
+
+                               if (fixIt) stackIt = --stack.begin();
+                               return;
+                       }
+               }
+       }
 
-int Engine::run()
+       void clearLayers()
+       {
+               stack.clear();
+               stackIt = stack.begin();
+       }
+
+
+       Engine&                         interface;
+
+       VideoP                          video;
+
+       std::list<LayerP>                       stack;
+       std::list<LayerP>::iterator     stackIt;
+
+       Scalar                          timestep;
+       Scalar                          drawRate;
+
+       long                            fps;
+       bool                            printFps;
+};
+
+
+static Engine* instance = 0;
+
+Engine::Engine(int argc, char* argv[], const std::string& name,
+               const std::string& iconFile, const std::string& configFile) :
+       impl_(new Engine::Impl(argc, argv, name, iconFile, configFile, *this))
 {
-       return impl_->run();
+       instance = this;
 }
 
-void Engine::stop(int exitCode)
+
+Engine& Engine::getInstance()
 {
-       impl_->running = false;
-       impl_->exitCode = exitCode;
+       ASSERT(instance && "dereferencing null pointer");
+       return *instance;
 }
 
 
+void Engine::run()
+{
+       return impl_->run();
+}
+
 void Engine::setTimestep(Scalar ts)
 {
        impl_->timestep = ts;
 }
 
-Scalar Engine::getTimestep()
+Scalar Engine::getTimestep() const
 {
        return impl_->timestep;
 }
@@ -268,26 +350,46 @@ void Engine::setMaxFrameRate(long maxFps)
        impl_->drawRate = 1.0 / Scalar(maxFps);
 }
 
-long Engine::getMaxFrameRate()
+long Engine::getMaxFrameRate() const
 {
        return long(1.0 / impl_->drawRate);
 }
 
 
-Video& Engine::getVideo()
+Video& Engine::getVideo() const
 {
        return *impl_->video;
 }
 
-long Engine::getFrameRate()
+long Engine::getFrameRate() const
 {
        return impl_->fps;
 }
 
 
-void Engine::update(Scalar t, Scalar dt) {}
-void Engine::draw(Scalar alpha) {}
-void Engine::handleEvent(const Event& event) {}
+void Engine::pushLayer(LayerP layer)
+{
+       // pass through
+       impl_->pushLayer(layer);
+}
+
+void Engine::popLayer()
+{
+       // pass through
+       impl_->popLayer();
+}
+
+void Engine::popLayer(Layer* layer)
+{
+       // pass through
+       impl_->popLayer(layer);
+}
+
+void Engine::clearLayers()
+{
+       // pass through
+       impl_->clearLayers();
+}
 
 
 } // namespace Mf
This page took 0.026054 seconds and 4 git commands to generate.