X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2FEngine.cc;h=5bfaaf3cd8d715d0927c9a284a5199a6686e98a6;hp=18ce5d7e5f8c6d0b4664da080b16ba1ad2623ace;hb=892da43bf5796e7c5f593a6d0f53bd797a36bd3e;hpb=ca0f7bdfba63140dca0bd20586d31980f3938eb2 diff --git a/src/Moof/Engine.cc b/src/Moof/Engine.cc index 18ce5d7..5bfaaf3 100644 --- a/src/Moof/Engine.cc +++ b/src/Moof/Engine.cc @@ -26,7 +26,9 @@ *******************************************************************************/ +#include #include // exit +#include #include #include @@ -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::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::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 stack; + std::list::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