From: Charles McGarvey Date: Sat, 16 Jan 2010 19:06:37 +0000 (-0700) Subject: refactoring needed for win32 crash X-Git-Url: https://git.brokenzipper.com/gitweb?a=commitdiff_plain;h=987971a961454d97082c6448fdc0bbeb540281bb;p=chaz%2Fyoink refactoring needed for win32 crash --- diff --git a/doc/yoink.6.in b/doc/yoink.6.in index ce90f1d..7e100d3 100644 --- a/doc/yoink.6.in +++ b/doc/yoink.6.in @@ -105,16 +105,12 @@ artifacts caused by the animation of the game. Otherwise, a single buffer will be used. The default value is true. .TP .B framerate -The maximum number of frames to be drawn per second. If your computer is +The target number of frames to be drawn per second. If your computer is really old, you can get away with decreasing this value and still have reasonably smooth animation. You can set this to a very high number to effectively render as many frames as is possible, but the actual rate could be limited by vertical display synchronization, depending on the X11 driver -and settings used. You should not set this option higher than the point -where the vertical synchronization effectively limits the draw rate or else -the game may not be able to update the physics on schedule which could -actually significantly lower the quality of the animation. The default -value is 40. +and settings used. The default value is 50. .TP .B fullscreen If true, the window will capture the display and render the game in full @@ -150,20 +146,17 @@ need to. .SH EXAMPLES Here are some examples of typical usage: .TP -$ yoink framerate=60 -Cap the allowable frame-rate to 60Hz. +$ yoink detail=2 +Set the level of detail to 2 so that less stuff is drawn to the screen. .TP -$ yoink fullscreen=true -Run \fByoink\fP in full-screen mode. -.TP -$ yoink videomode=\\{1024,768\\} -Run \fByoink\fP with a resolution of 1024x768. Notice the escapes for the -curly braces so the shell doesn't parse them. +$ yoink fullscreen=true videomode=\\{1024,768\\} +Run \fByoink\fP at full screen with a resolution of 1024x768. Notice the +escapes for the curly braces so the shell doesn't parse them. .SH ENVIRONMENT \fByoink\fP responds to some variables in the environment: .TP .I HOME -If set to a path of a valid directory (presumably a user's home directory), +If set to a path of a valid directory (presumably your home directory), \fByoink\fP will look for a file at \fI$HOME/.yoinkrc\fP and load it as a config file. .TP @@ -198,11 +191,16 @@ This can speed up a software renderer considerably. .TP 2. Decrease the level of rendering detail. Use the \fBdetail\fP option. The game world may look sparse or incomplete, -but that's probably better than choppy animation. -.TP -3. Decrease the timestep. -You can set the \fBtimestep\fP to be as low as the your \fBframerate\fP -option. Remember the trade-off here is decreased simulation accuracy. +but that's probably better than choppy animation if you can avoid it. +.TP +3. Decrease the framerate and/or timestep. +If your machine can't meet the target framerate, your actual framerate will +probably vary. You will have a better visual experience if you can reduce +the \fBframerate\fP to a point such that the actual framerate is basically +constant. A constant 20fps or 30fps will look better than a sporadic +40-60fps. You can also decrease the \fBtimestep\fP at the expense of +decreased simulation accuracy. You'll have to experiment with this value +to find out acceptable levels. .PP If you are having audio problems, you may need to upgrade OpenAL. Some systems still provide an old, busted version of OpenAL which may result in diff --git a/src/GameLayer.cc b/src/GameLayer.cc index 46c3263..493aa6c 100644 --- a/src/GameLayer.cc +++ b/src/GameLayer.cc @@ -26,7 +26,7 @@ *******************************************************************************/ -#include +#include #include #include #include @@ -110,7 +110,7 @@ GameLayer::GameLayer() : mMusic.enqueue("NightFusionLoop"); bool isMute = false; - Mf::Settings::getInstance().get("nomusic", isMute); + Mf::settings.get("nomusic", isMute); if (!isMute) mMusic.play(); //mMusic.setPosition(Mf::Vector3(10.0, 5.0, 0.0)); @@ -133,7 +133,7 @@ GameLayer::GameLayer() : void GameLayer::pushedOntoEngine() { - Mf::engine.push(mHud); + Mf::core.push(mHud); mRay.direction.set(1.0, 0.0); @@ -259,12 +259,12 @@ bool GameLayer::handleEvent(const Mf::Event& event) case SDL_KEYUP: if (event.key.keysym.sym == SDLK_ESCAPE) { - Mf::engine.pop(this); + Mf::core.pop(this); return true; } else if (event.key.keysym.sym == SDLK_h) { - Mf::engine.push(mHud); + Mf::core.push(mHud); return true; } return mState.heroine->handleEvent(event); @@ -285,8 +285,8 @@ bool GameLayer::handleEvent(const Mf::Event& event) void GameLayer::setProjection() { - Mf::VideoP video = Mf::engine.getVideo(); - setProjection(video->getWidth(), video->getHeight()); + ASSERT(Mf::video && "no current video context from which to get dimensions"); + setProjection(Mf::video->getWidth(), Mf::video->getHeight()); } void GameLayer::setProjection(Mf::Scalar width, Mf::Scalar height) diff --git a/src/Hud.cc b/src/Hud.cc index d77bf57..1fdf39b 100644 --- a/src/Hud.cc +++ b/src/Hud.cc @@ -26,7 +26,7 @@ *******************************************************************************/ -#include +#include #include #include @@ -124,8 +124,8 @@ Hud::Hud(GameState& state) : mBar2(Tilemap("StatusBars"), 2), mFont("Font") { - Mf::VideoP video = Mf::engine.getVideo(); - resize(video->getWidth(), video->getHeight()); + ASSERT(Mf::video && "no current video context from which to get dimensions"); + resize(Mf::video->getWidth(), Mf::video->getHeight()); } @@ -147,14 +147,14 @@ void Hud::resize(int width, int height) } -void Hud::update(Mf::Engine& engine, Mf::Scalar t, Mf::Scalar dt) +void Hud::update(Mf::Scalar t, Mf::Scalar dt) { mState.interp.update(t, dt); setBar1Progress(mState.interp.getState(dt)); setBar2Progress(1.0 - mState.interp.getState(dt)); } -void Hud::draw(Mf::Engine& engine, Mf::Scalar alpha) const +void Hud::draw(Mf::Scalar alpha) const { glMatrixMode(GL_PROJECTION); glPushMatrix(); @@ -180,7 +180,7 @@ void Hud::draw(Mf::Engine& engine, Mf::Scalar alpha) const glPopMatrix(); } -bool Hud::handleEvent(Mf::Engine& engine, const Mf::Event& event) +bool Hud::handleEvent(const Mf::Event& event) { switch (event.type) { @@ -188,7 +188,7 @@ bool Hud::handleEvent(Mf::Engine& engine, const Mf::Event& event) if (event.key.keysym.sym == SDLK_h) { // don't want the hud anymore - engine.pop(this); + Mf::core.pop(this); return true; } break; diff --git a/src/Hud.hh b/src/Hud.hh index 016767a..75ced92 100644 --- a/src/Hud.hh +++ b/src/Hud.hh @@ -100,9 +100,9 @@ public: void resize(int width, int height); - void update(Mf::Engine& engine, Mf::Scalar t, Mf::Scalar dt); - void draw(Mf::Engine& engine, Mf::Scalar alpha = 0.0) const; - bool handleEvent(Mf::Engine& engine, const Mf::Event& event); + void update(Mf::Scalar t, Mf::Scalar dt); + void draw(Mf::Scalar alpha = 0.0) const; + bool handleEvent(const Mf::Event& event); private: diff --git a/src/MainLayer.cc b/src/Main.cc similarity index 75% rename from src/MainLayer.cc rename to src/Main.cc index ad2dbbc..2cd0f0c 100644 --- a/src/MainLayer.cc +++ b/src/Main.cc @@ -41,7 +41,7 @@ #include "ErrorHandler.hh" #include "GameLayer.hh" -#include "MainLayer.hh" +#include "Main.hh" #include "TitleLayer.hh" #if HAVE_CONFIG_H @@ -50,14 +50,14 @@ #include "version.h" -MainLayer::MainLayer() +Main::Main() { - mDispatchHandler = Mf::engine.addHandler("video.newcontext", - boost::bind(&MainLayer::contextRecreated, this)); + mDispatchHandler = Mf::core.addHandler("video.newcontext", + boost::bind(&Main::contextRecreated)); setupGL(); } -void MainLayer::pushedOntoEngine() +void Main::addedToCore() { //Mf::Scalar coeff[] = {0.0, 1.0}; //Mf::Lerp interp(coeff, 0.25); @@ -65,23 +65,23 @@ void MainLayer::pushedOntoEngine() //Mf::LayerP gameLayer = GameLayer::alloc(); //Mf::Transition::Ptr transition = //Mf::Transition::alloc(gameLayer, Mf::LayerP(), interp); - //engine->push(transition); - //engine->push(GameLayer::alloc()); - Mf::engine.push(TitleLayer::alloc()); + //core.push(transition); + //core.push(GameLayer::alloc()); + Mf::core.push(TitleLayer::alloc()); } -void MainLayer::update(Mf::Scalar t, Mf::Scalar dt) +void Main::update(Mf::Scalar t, Mf::Scalar dt) { - if (Mf::engine.getSize() == 1) + if (Mf::core.getSize() == 1) { // this is the only layer left on the stack - //Mf::engine.push(TitleLayer::alloc()); - Mf::engine.clear(); + //Mf::core.push(TitleLayer::alloc()); + Mf::core.clear(); } } -void MainLayer::draw(Mf::Scalar alpha) const +void Main::draw(Mf::Scalar alpha) const { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -92,24 +92,23 @@ void MainLayer::draw(Mf::Scalar alpha) const glLoadIdentity(); } -bool MainLayer::handleEvent(const Mf::Event& event) +bool Main::handleEvent(const Mf::Event& event) { switch (event.type) { case SDL_KEYUP: if (event.key.keysym.sym == SDLK_ESCAPE) { - Mf::engine.clear(); + Mf::core.clear(); } else if (event.key.keysym.sym == SDLK_f) { - Mf::engine.getVideo()->toggleFull(); + Mf::video->toggleFull(); } else if (event.key.keysym.sym == SDLK_l) { - Mf::VideoP video = Mf::engine.getVideo(); - video->toggleCursorGrab(); - video->toggleCursorVisible(); + Mf::video->toggleCursorGrab(); + Mf::video->toggleCursorVisible(); } break; @@ -118,7 +117,7 @@ bool MainLayer::handleEvent(const Mf::Event& event) break; case SDL_QUIT: - Mf::engine.clear(); + Mf::core.clear(); break; } @@ -126,7 +125,52 @@ bool MainLayer::handleEvent(const Mf::Event& event) } -void MainLayer::setupGL() +std::string Main::getSearchPath() +{ + // Add search paths; they should be searched in this order: + // 1. YOINK_DATADIR (environment) + // 2. YOINK_DATADIR (configure) + + std::string path; + + char* dataDir = getenv("YOINK_DATADIR"); + if (dataDir) + { + path += dataDir; + path += ":"; + } + path += YOINK_DATADIR; + + return path; +} + +std::string Main::getConfigPath() +{ + // Build the list of config files to search for, in this order: + // 1. YOINK_DATADIR/yoinkrc + // 2. /etc/yoinkrc (not for Windows) + // 3. $HOME/.yoinkrc + // 4. YOINKRC (environment) + + std::string path = Mf::Resource::getPath("yoinkrc"); + +#if !defined(_WIN32) && !defined(__WIN32__) + path += ":/etc/yoinkrc"; +#endif + path += ":$HOME/.yoinkrc"; + + char* configFile = getenv("YOINKRC"); + if (configFile) + { + path += ":"; + path += configFile; + } + + return path; +} + + +void Main::setupGL() { glEnable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); @@ -144,14 +188,14 @@ void MainLayer::setupGL() //glMatrixMode(GL_PROJECTION); //glLoadIdentity(); - //Mf::Scalar ratio = Mf::engine.getVideo()->getWidth() / - //Mf::engine.getVideo()->getHeight(); + //Mf::Scalar ratio = Mf::core.getVideo()->getWidth() / + //Mf::core.getVideo()->getHeight(); //gluPerspective(60.0, ratio, 1.0, 250.0); //glMatrixMode(GL_MODELVIEW); } -void MainLayer::contextRecreated() +void Main::contextRecreated() { // whenever the context is destroyed and a new one created, it probably // won't contain our state so we need to set that up again @@ -160,7 +204,7 @@ void MainLayer::contextRecreated() -void printUsage() +void Main::printUsage() { std::cout << "Usage: "PACKAGE" [-h|--help] [-i|--info] [OPTION=VALUE]..." << std::endl @@ -175,13 +219,13 @@ void printUsage() << " the level of detail of game scenes" << std::endl << " fullscreen=true|false" << std::endl << " if true, uses the entire display" << std::endl - << " maxfps=num" << std::endl - << " the maximum number of frames per second" << std::endl + << " framerate=num" << std::endl + << " the target number of frames per second" << std::endl << std::endl << "See documentation for more options." << std::endl; } -void printInfo(int argc, char* argv[]) +void Main::printInfo(int argc, char* argv[]) { std::string assets; std::string datadir; @@ -241,12 +285,20 @@ void printInfo(int argc, char* argv[]) << "YOINK_DATADIR: " << datadir << std::endl; } + +void hello() +{ + std::cout << std::endl << PACKAGE_STRING << std::endl + << "Compiled " << __TIME__ " " __DATE__ << std::endl + << "Send patches and bug reports to <" + PACKAGE_BUGREPORT << ">." << std::endl << std::endl; +} + void goodbye() { std::cout << std::endl << "Goodbye..." << std::endl << std::endl; } - int main(int argc, char* argv[]) { if (argc > 1) @@ -254,91 +306,33 @@ int main(int argc, char* argv[]) std::string arg(argv[1]); if (arg == "-h" || arg == "--help") { - printUsage(); + Main::printUsage(); return 0; } else if (arg == "-i" || arg == "--info") { - printInfo(argc, argv); + Main::printInfo(argc, argv); return 0; } } - - std::cout << std::endl << PACKAGE_STRING << std::endl - << "Compiled " << __TIME__ " " __DATE__ << std::endl - << "Send patches and bug reports to <" - PACKAGE_BUGREPORT << ">." << std::endl << std::endl; - + hello(); atexit(goodbye); + Mf::Resource::addSearchPaths(Main::getSearchPath()); - // make sure the engine started up okay - const Mf::Error& error = Mf::engine.getError(); - if (error.isError()) - { - Mf::ModalDialog dialog; - dialog.title = PACKAGE_STRING; - dialog.text1 = "Uh oh!"; - dialog.text2 = getErrorString(error); - dialog.type = Mf::ModalDialog::CRITICAL; - dialog.run(); - - // openal errors are not fatal - if (error.code() != Mf::Error::OPENAL_INIT) return 1; - } - - - // Add search paths; they should be searched in this order: - // 1. YOINK_DATADIR (environment) - // 2. YOINK_DATADIR (configure) - - char* dataDir = getenv("YOINK_DATADIR"); - if (dataDir) - { - Mf::Resource::addSearchPath(dataDir); - } - - Mf::Resource::addSearchPath(YOINK_DATADIR); - - - // Build the list of config files to search for, in this order: - // 1. YOINK_DATADIR/yoinkrc - // 2. /etc/yoinkrc (not for Windows) - // 3. $HOME/.yoinkrc - // 4. YOINKRC (environment) - - std::string configFiles = Mf::Resource::getPath("yoinkrc"); -#if !defined(_WIN32) && !defined(__WIN32__) - configFiles += ":/etc/yoinkrc"; -#endif - configFiles += ":$HOME/.yoinkrc"; - - char* configFile = getenv("YOINKRC"); - if (configFile) - { - configFiles += ":"; - configFiles += configFile; - } - - Mf::Settings& settings = Mf::Settings::getInstance(); - settings.loadFromFile(configFiles); - settings.parseArgs(argc, argv); + Mf::settings.loadFromFiles(Main::getConfigPath()); + Mf::settings.parseArgs(argc, argv); Mf::Log::Level logLevel; - if (settings.get("loglevel", logLevel)) Mf::Log::setLevel(logLevel); - - Mf::engine.initWithSettings(settings); - - std::string iconFile = Mf::Resource::getPath(PACKAGE".png"); - + if (Mf::settings.get("loglevel", logLevel)) Mf::Log::setLevel(logLevel); try { - Mf::engine.setVideo(Mf::Video::alloc(PACKAGE_STRING, iconFile)); - Mf::engine.push(MainLayer::alloc()); - - Mf::engine.run(); + Mf::Video video(PACKAGE_STRING, Mf::Resource::getPath(PACKAGE".png")); + MainP app = Main::alloc(); + Mf::core.push(app); + Mf::core.run(); } catch (const Mf::Error& error) { diff --git a/src/MainLayer.hh b/src/Main.hh similarity index 82% rename from src/MainLayer.hh rename to src/Main.hh index 4f0fc77..1e9ecc9 100644 --- a/src/MainLayer.hh +++ b/src/Main.hh @@ -26,11 +26,11 @@ *******************************************************************************/ -#ifndef _MAINLAYER_HH_ -#define _MAINLAYER_HH_ +#ifndef _YOINKAPP_HH_ +#define _YOINKAPP_HH_ /** - * @file MainLayer.hh + * @file Main.hh * This is where all the fun begins. */ @@ -40,44 +40,49 @@ #include #include -#include #include #include -class MainLayer; -typedef boost::shared_ptr MainLayerP; +class Main; +typedef boost::shared_ptr
MainP; -class MainLayer : public Mf::Layer +class Main : public Mf::Layer { public: - MainLayer(); + Main(); - static MainLayerP alloc() + static MainP alloc() { - return MainLayerP(new MainLayer); + return MainP(new Main); } - void pushedOntoEngine(); + void addedToCore(); void update(Mf::Scalar t, Mf::Scalar dt); void draw(Mf::Scalar alpha) const; bool handleEvent(const Mf::Event& event); + static std::string getSearchPath(); + static std::string getConfigPath(); + + static void printUsage(); + static void printInfo(int argc, char* argv[]); + private: /** * Set OpenGL to a state we can know and depend on. */ - void setupGL(); - void contextRecreated(); + static void setupGL(); + static void contextRecreated(); Mf::Dispatch::Handler mDispatchHandler; }; -#endif // _MAINLAYER_HH_ +#endif // _YOINKAPP_HH_ /** vim: set ts=4 sw=4 tw=80: *************************************************/ diff --git a/src/Makefile.am b/src/Makefile.am index ee59088..ede2a88 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -18,12 +18,12 @@ libmoof_a_SOURCES = \ Moof/Camera.hh \ Moof/ConvertUTF.c \ Moof/ConvertUTF.h \ + Moof/Core.cc \ + Moof/Core.hh \ Moof/Cullable.hh \ Moof/Dispatch.cc \ Moof/Dispatch.hh \ Moof/Drawable.hh \ - Moof/Engine.cc \ - Moof/Engine.hh \ Moof/Entity.hh \ Moof/Event.hh \ Moof/Exception.hh \ @@ -96,8 +96,8 @@ yoink_SOURCES = \ Heroine.hh \ Hud.cc \ Hud.hh \ - MainLayer.cc \ - MainLayer.hh \ + Main.cc \ + Main.hh \ Scene.cc \ Scene.hh \ Tilemap.cc \ diff --git a/src/Moof/Engine.cc b/src/Moof/Core.cc similarity index 81% rename from src/Moof/Engine.cc rename to src/Moof/Core.cc index 5d703da..cc86a91 100644 --- a/src/Moof/Engine.cc +++ b/src/Moof/Core.cc @@ -36,19 +36,20 @@ #include #include "fastevents.h" - -#include "Engine.hh" +#include "Core.hh" #include "Event.hh" #include "Log.hh" #include "Math.hh" +#include "ModalDialog.hh" #include "Settings.hh" #include "Timer.hh" +#include "Video.hh" namespace Mf { -class Engine::Impl +class Core::Impl { public: @@ -56,50 +57,9 @@ public: mError(Error::NONE), mTimestep(0.01), mFramerate(0.02), - mShowFps(false) - { -#if defined(_WIN32) || defined(__WIN32__) - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) -#else - if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTTHREAD) != 0) -#endif - { - const char* error = SDL_GetError(); - mError.init(Error::SDL_INIT, error); - return; // fatal - } - else - { - char name[128]; - SDL_VideoDriverName(name, sizeof(name)); - logInfo << "initialized SDL; using video driver `" - << name << "'" << std::endl; - } - - if (FE_Init() != 0) - { - const char* error = FE_GetError(); - mError.init(Error::FASTEVENTS_INIT, error); - return; // fatal - } - - mAlDevice = alcOpenDevice(0); - mAlContext = alcCreateContext(mAlDevice, 0); - if (!mAlDevice || !mAlContext) - { - const char* error = alcGetString(mAlDevice,alcGetError(mAlDevice)); - mError.init(Error::OPENAL_INIT, error); - } - else - { - alcMakeContextCurrent(mAlContext); - logInfo << "opened sound device `" - << alcGetString(mAlDevice, ALC_DEFAULT_DEVICE_SPECIFIER) - << "'" << std::endl; - } - } + mShowFps(false) {} - bool initWithSettings(const Settings& settings) + void init() { unsigned randomSeed; if (settings.get("rngseed", randomSeed)) srand(randomSeed); @@ -112,25 +72,9 @@ public: Scalar framerate = 40.0; settings.get("framerate", framerate); mFramerate = 1.0 / framerate; - capFps(); mShowFps = false; settings.get("showfps", mShowFps); - - return true; - } - - ~Impl() - { - // the video object must be destroyed before we can shutdown SDL - mVideo.reset(); - - alcMakeContextCurrent(0); - alcDestroyContext(mAlContext); - alcCloseDevice(mAlDevice); - - FE_Quit(); - SDL_Quit(); } @@ -143,6 +87,8 @@ public: void run() { + init(); + Scalar totalTime = 0.0; Scalar ticks = Timer::getTicks(); @@ -156,6 +102,8 @@ public: const int MAX_FRAMESKIP = 15; const Scalar inverseTimestep = SCALAR(1.0) / mTimestep; + ASSERT(video && "cannot run core without a current video context"); + do { Timer::fireIfExpired(); @@ -175,7 +123,7 @@ public: { ++frames; draw((ticks + mTimestep - nextUpdate) * inverseTimestep); - mVideo->swap(); + video->swap(); nextDraw += mFramerate; @@ -198,6 +146,7 @@ public: mDispatch.dispatch("engine.stopping"); } + void dispatchEvents() { SDL_Event event; @@ -217,7 +166,7 @@ public: break; case SDL_VIDEORESIZE: - mVideo->resize(event.resize.w, event.resize.h); + video->resize(event.resize.w, event.resize.h); break; } @@ -259,7 +208,7 @@ public: mStack.push_front(layer); logInfo << "stack: " << mStack.size() << " [pushed " << layer.get() << "]" << std::endl; - layer->pushedOntoEngine(); + layer->addedToCore(); } LayerP pop() @@ -271,7 +220,7 @@ public: mStack.pop_front(); logInfo << "stack: " << mStack.size() << " [popped " << layer.get() << "]" << std::endl; - layer->poppedFromEngine(); + layer->removedFromCore(); if (fixIt) mStackIt = --mStack.begin(); @@ -298,7 +247,7 @@ public: for (it = layers.begin(); it != layers.end(); ++it) { - (*it)->poppedFromEngine(); + (*it)->removedFromCore(); logInfo << "stack: " << mStack.size() << " [popped " << (*it).get() << "]" << std::endl; } @@ -320,25 +269,10 @@ public: } - void capFps() - { - //if (mFramerate < mTimestep) - //{ - //logWarning << "capping maximum fps to timestep (" - //<< mTimestep << ")" << std::endl; - //mFramerate = mTimestep; - //} - } - - Error mError; - VideoP mVideo; Dispatch mDispatch; - ALCdevice* mAlDevice; - ALCcontext* mAlContext; - std::list mStack; std::list::iterator mStackIt; @@ -350,105 +284,199 @@ public: }; -Engine::Engine() : +Core::Core() : // pass through - mImpl(new Engine::Impl) {} + mImpl(new Core::Impl) {} -bool Engine::initWithSettings(const Settings& settings) +void Core::init() { // pass through - return mImpl->initWithSettings(settings); -} - -const Error& Engine::getError() const -{ - // pass through - return mImpl->mError; -} - -void Engine::clearError() -{ - // pass through - mImpl->mError.init(Error::NONE); + mImpl->init(); } -void Engine::setVideo(VideoP video) -{ - // pass through - mImpl->mVideo = video; -} - -VideoP Engine::getVideo() const -{ - return mImpl->mVideo; -} - - -int Engine::getFps() const +int Core::getFps() const { return mImpl->mFps; } -void Engine::push(LayerP layer) +void Core::push(LayerP layer) { // pass through mImpl->push(layer); } -LayerP Engine::pop() +LayerP Core::pop() { // pass through return mImpl->pop(); } -LayerP Engine::pop(Layer* layer) +LayerP Core::pop(Layer* layer) { // pass through return mImpl->pop(layer); } -void Engine::clear() +void Core::clear() { // pass through mImpl->clear(); } -int Engine::getSize() const +int Core::getSize() const { return mImpl->mStack.size(); } -void Engine::run() +void Core::run() { // pass through return mImpl->run(); } -Dispatch::Handler Engine::addHandler(const std::string& event, +Dispatch::Handler Core::addHandler(const std::string& event, const Dispatch::Function& callback) { return mImpl->mDispatch.addHandler(event, callback); } -Dispatch::Handler Engine::addHandler(const std::string& event, +Dispatch::Handler Core::addHandler(const std::string& event, const Dispatch::Function& callback, Dispatch::Handler handler) { return mImpl->mDispatch.addHandler(event, callback, handler); } -void Engine::dispatch(const std::string& event, +void Core::dispatch(const std::string& event, const Dispatch::Message* message) { mImpl->mDispatch.dispatch(event, message); } -Engine engine; +Core core; + + +class Backend_; +typedef boost::shared_ptr BackendP; + +class Backend_ +{ +public: + + void init() + { +#if defined(_WIN32) || defined(__WIN32__) + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) +#else + if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTTHREAD) != 0) +#endif + { + const char* error = SDL_GetError(); + gError.init(Error::SDL_INIT, error); + return; // fatal + } + else + { + char name[128]; + SDL_VideoDriverName(name, sizeof(name)); + logInfo << "initialized SDL; using video driver `" + << name << "'" << std::endl; + } + + if (FE_Init() != 0) + { + const char* error = FE_GetError(); + gError.init(Error::FASTEVENTS_INIT, error); + return; // fatal + } + + mAlDevice = alcOpenDevice(0); + mAlContext = alcCreateContext(mAlDevice, 0); + if (!mAlDevice || !mAlContext) + { + const char* error = alcGetString(mAlDevice,alcGetError(mAlDevice)); + gError.init(Error::OPENAL_INIT, error); + return; + } + else + { + alcMakeContextCurrent(mAlContext); + logInfo << "opened sound device `" + << alcGetString(mAlDevice, ALC_DEFAULT_DEVICE_SPECIFIER) + << "'" << std::endl; + } + + gError.init(Error::NONE); + } + + ~Backend_() + { + alcMakeContextCurrent(0); + alcDestroyContext(mAlContext); + alcCloseDevice(mAlDevice); + + FE_Quit(); + SDL_Quit(); + } + + static void retain() + { + if (gRetainCount++ == 0) + { + gInstance = BackendP(new Backend_); + gInstance->init(); + } + } + + static void release() + { + if (--gRetainCount == 0) + { + gInstance.reset(); + gError.reset(); + } + } + + static bool check(Error& error) + { + error = gError; + return error.code() == Error::NONE; + } + +private: + + ALCdevice* mAlDevice; + ALCcontext* mAlContext; + + static Error gError; + static int gRetainCount; + static BackendP gInstance; +}; + +Error Backend_::gError(Error::UNINITIALIZED); +int Backend_::gRetainCount = 0; +BackendP Backend_::gInstance; + + +Backend::Backend() +{ + Backend_::retain(); +} + +Backend::~Backend() +{ + Backend_::release(); +} + +bool Backend::check(Error& error) +{ + return Backend_::check(error); +} } // namespace Mf diff --git a/src/Moof/Engine.hh b/src/Moof/Core.hh similarity index 78% rename from src/Moof/Engine.hh rename to src/Moof/Core.hh index 28d7fa0..fcb0340 100644 --- a/src/Moof/Engine.hh +++ b/src/Moof/Core.hh @@ -26,56 +26,43 @@ *******************************************************************************/ -#ifndef _MOOF_ENGINE_HH_ -#define _MOOF_ENGINE_HH_ +#ifndef _MOOF_CORE_HH_ +#define _MOOF_CORE_HH_ #include #include #include -#include #include namespace Mf { -class Settings; - - /** - * The engine is essentially a stack of layers. While running, it updates each + * The core is essentially a stack of layers. While running, it updates each * layer from the bottom up every timestep. It also draws each layer from the * bottom up, adhering to the maximum frame-rate. Events are sent to each layer - * from the top down until a layer signals the event was handled. The engine is - * also responsible for firing timers on time. The engine will continue running + * from the top down until a layer signals the event was handled. The core is + * also responsible for firing timers on time. The core will continue running * as long as there are layers on the stack. */ -class Engine +class Core { public: - Engine(); - ~Engine() {} + Core(); // loads settings: rngseed, timestep, framerate, showfps - bool initWithSettings(const Settings& settings); - - const Error& getError() const; - void clearError(); - - // setting the video is required before you can run the engine and should - // probably be done before adding any layers - void setVideo(VideoP video); - VideoP getVideo() const; + void init(); int getFps() const; void push(LayerP layer); // push a layer onto the top LayerP pop(); // pop the top layer LayerP pop(Layer* layer); // pops a specific layer and all layers above it - void clear(); // remove all layers (the engine will stop) + void clear(); // remove all layers (the core will stop) int getSize() const; // get the size of the stack @@ -96,13 +83,30 @@ private: boost::shared_ptr mImpl; }; +extern Core core; + + +/* + * Some classes and subsystems require certain backend libraries to be + * initialized. This is the mechanism to accomplish that. Classes which rely + * on any backend libraries just need to instantiate this class as a member. + * Backend cleanup will occur automagically when there are no more instances. + */ + +class Backend +{ +public: + + Backend(); + ~Backend(); -extern Engine engine; + static bool check(Error& error); +}; } // namespace Mf -#endif // _MOOF_ENGINE_HH_ +#endif // _MOOF_CORE_HH_ /** vim: set ts=4 sw=4 tw=80: *************************************************/ diff --git a/src/Moof/Error.hh b/src/Moof/Error.hh index 86b8a12..05c6377 100644 --- a/src/Moof/Error.hh +++ b/src/Moof/Error.hh @@ -90,6 +90,12 @@ public: return mCode != NONE; } + void reset() throw() + { + mCode = NONE; + mWhat[0] = '\0'; + } + private: unsigned mCode; diff --git a/src/Moof/Image.cc b/src/Moof/Image.cc index 31d6b02..ba17769 100644 --- a/src/Moof/Image.cc +++ b/src/Moof/Image.cc @@ -32,6 +32,8 @@ #include #include +#include "Core.hh" +#include "Error.hh" #include "Image.hh" #include "Library.hh" #include "Log.hh" @@ -98,6 +100,8 @@ public: private: + Backend mBackend; + bool init(const std::string& filePath, bool flipped) { logInfo("opening image file..."); diff --git a/src/Moof/Layer.hh b/src/Moof/Layer.hh index 01a4145..31607fb 100644 --- a/src/Moof/Layer.hh +++ b/src/Moof/Layer.hh @@ -44,8 +44,8 @@ public: virtual ~Layer() {} - virtual void pushedOntoEngine() {} - virtual void poppedFromEngine() {} + virtual void addedToCore() {} + virtual void removedFromCore() {} virtual void update(Scalar t, Scalar dt) {} virtual void draw(Scalar alpha) const {} diff --git a/src/Moof/Log.cc b/src/Moof/Log.cc index 3094642..783aec5 100644 --- a/src/Moof/Log.cc +++ b/src/Moof/Log.cc @@ -49,9 +49,9 @@ Log::Level Log::getLevel() } -static std::ofstream nullLog_; - std::ostream& log(std::clog); + +static std::ofstream nullLog_; std::ostream& nullLog(nullLog_); Log logError(Log::ERRORR, " error: "); diff --git a/src/Moof/Resource.cc b/src/Moof/Resource.cc index ff4213e..ec94025 100644 --- a/src/Moof/Resource.cc +++ b/src/Moof/Resource.cc @@ -38,28 +38,43 @@ namespace Mf { // static member -std::vector Resource::searchPaths_; +std::vector Resource::gSearchPaths; -void Resource::addSearchPath(const std::string& directory) +void Resource::addSearchPaths(const std::string& path) { - std::string path(directory); + std::vector paths; + boost::split(paths, path, boost::is_any_of(":")); - ASSERT(path.length() > 0 && "empty search path string"); + addSearchPaths(paths); +} + +void Resource::addSearchPaths(const std::vector& path) +{ + std::vector::const_iterator it; - // add a slash if there isn't one already - if (*path.rbegin() != '/') + for (it = path.begin(); it != path.end(); ++it) { - path += '/'; - } + std::string onePath(*it); + + ASSERT(!onePath.empty() && "empty search path string"); + + // add a slash if there isn't one already + if (*onePath.rbegin() != '/') + { + onePath += '/'; + } #if defined(_WIN32) || defined(__WIN32__) - boost::replace_all(path, "/", "\\"); + boost::replace_all(onePath, "/", "\\"); #endif - searchPaths_.push_back(path); + gSearchPaths.push_back(onePath); + logInfo << "added search path " << onePath << std::endl; + } } + std::string Resource::getPath(const std::string& name) { std::vector::iterator it; @@ -70,7 +85,7 @@ std::string Resource::getPath(const std::string& name) boost::replace_all(path, "/", "\\"); #endif - for (it = searchPaths_.begin(); it != searchPaths_.end(); ++it) + for (it = gSearchPaths.begin(); it != gSearchPaths.end(); ++it) { std::string fullPath(*it); fullPath += path; diff --git a/src/Moof/Resource.hh b/src/Moof/Resource.hh index 39b76a4..671aeb6 100644 --- a/src/Moof/Resource.hh +++ b/src/Moof/Resource.hh @@ -57,7 +57,8 @@ public: * @param directory Path to a directory. */ - static void addSearchPath(const std::string& directory); + static void addSearchPaths(const std::string& path); + static void addSearchPaths(const std::vector& path); /** * Get the path to a resource of a given name. @@ -70,7 +71,7 @@ public: private: - static std::vector searchPaths_; + static std::vector gSearchPaths; }; diff --git a/src/Moof/Settings.cc b/src/Moof/Settings.cc index 9f0538b..5e19ed5 100644 --- a/src/Moof/Settings.cc +++ b/src/Moof/Settings.cc @@ -26,7 +26,6 @@ *******************************************************************************/ -#include #include // getenv #include "Settings.hh" @@ -40,11 +39,11 @@ Settings::~Settings() save(); } -Settings& Settings::getInstance() -{ - static Settings settings; - return settings; -} +//Settings& Settings::getInstance() +//{ + //static Settings settings; + //return settings; +//} void Settings::parseArgs(int argc, char* argv[]) @@ -56,35 +55,42 @@ void Settings::parseArgs(int argc, char* argv[]) } -void Settings::loadFromFile(const std::string& filePath) +void Settings::loadFromFiles(const std::string& path) { std::vector paths; - boost::split(paths, filePath, boost::is_any_of(":")); + boost::split(paths, path, boost::is_any_of(":")); loadFromFiles(paths); } -void Settings::loadFromFiles(const std::vector& filePaths) +void Settings::loadFromFiles(const std::vector& path) { - std::vector::const_iterator it; - - char* home = getenv("HOME"); - - for (it = filePaths.begin(); it != filePaths.end(); ++it) + std::vector copy(path); + std::vector::iterator it; + +#if defined(_WIN32) || defined(__WIN32__) + char* homeDrive = getenv("HOMEDRIVE"); + char* homePath = getenv("HOMEPATH"); + std::string home(homeDrive ? homeDrive : ""); + if (homePath) home += homePath; +#else + char *homePath = getenv("HOME"); + std::string home(homePath ? homePath : ""); +#endif + + for (it = copy.begin(); it != copy.end(); ++it) { - std::string path = *it; - - if (home) + if (!home.empty()) { - boost::replace_all(path, "$HOME", home); + boost::replace_all(*it, "$HOME", home); //Mf::logDebug("Copying global settings..."); - //mUserFile = path; + //mUserFile = *it; //mGlobals.pushCopy(); //mScript.set("globals", Script::REGISTRY); } - if (mScript.doFile(path) != Script::SUCCESS) + if (mScript.doFile(*it) != Script::SUCCESS) { std::string str; mScript[-1].get(str); @@ -101,9 +107,9 @@ void Settings::clear() } -void Settings::saveAs(const std::string& filePath) +void Settings::saveAs(const std::string& path) { - mUserFile = filePath; + mUserFile = path; save(); } @@ -112,6 +118,9 @@ void Settings::save() const } +Settings settings; + + } // namepsace Mf /** vim: set ts=4 sw=4 tw=80: *************************************************/ diff --git a/src/Moof/Settings.hh b/src/Moof/Settings.hh index 6cd8629..d4cbb9f 100644 --- a/src/Moof/Settings.hh +++ b/src/Moof/Settings.hh @@ -58,17 +58,14 @@ public: ~Settings(); - // get global instance - static Settings& getInstance(); - void parseArgs(int argc, char* argv[]); - void loadFromFile(const std::string& filePath); - void loadFromFiles(const std::vector& filePaths); + void loadFromFiles(const std::string& path); + void loadFromFiles(const std::vector& path); void clear(); // remove all settings - void saveAs(const std::string& filePath); + void saveAs(const std::string& path); void save() const; template @@ -113,6 +110,9 @@ bool Settings::get(const std::string& key, T& value) const } +extern Settings settings; + + } // namepsace Mf #endif // _MOOF_SETTINGS_HH_ diff --git a/src/Moof/Sound.cc b/src/Moof/Sound.cc index f9bdfd7..ca3ecfe 100644 --- a/src/Moof/Sound.cc +++ b/src/Moof/Sound.cc @@ -35,7 +35,8 @@ #include #include -#include "Engine.hh" +#include "Core.hh" +#include "Error.hh" #include "Library.hh" #include "Log.hh" #include "Sound.hh" @@ -65,7 +66,7 @@ public: { public: - Buffer(const std::string& name) : + explicit Buffer(const std::string& name) : Library(name), mBuffer(-1) { @@ -436,6 +437,8 @@ public: std::deque mQueue; Timer mStreamTimer; + + Backend mBackend; }; diff --git a/src/Moof/Texture.cc b/src/Moof/Texture.cc index 6769d88..5341af3 100644 --- a/src/Moof/Texture.cc +++ b/src/Moof/Texture.cc @@ -32,13 +32,14 @@ #include #include "Dispatch.hh" -#include "Engine.hh" +#include "Core.hh" #include "Error.hh" #include "Image.hh" #include "Library.hh" #include "Log.hh" #include "OpenGL.hh" #include "Texture.hh" +#include "Video.hh" namespace Mf { @@ -121,12 +122,11 @@ public: mWrapT(GL_CLAMP), mObject(0) { - // make sure we have a video - VideoP video = engine.getVideo(); - ASSERT(video && "cannot load textures without a current video context"); + // make sure we have a video context + //ASSERT(video && "cannot load textures without a current video context"); // we want to know when the GL context is recreated - mDispatchHandler = engine.addHandler("video.newcontext", + mDispatchHandler = core.addHandler("video.newcontext", boost::bind(&Impl::contextRecreated, this)); loadFromFile(); diff --git a/src/Moof/Transition.hh b/src/Moof/Transition.hh index f200729..dfc2602 100644 --- a/src/Moof/Transition.hh +++ b/src/Moof/Transition.hh @@ -31,7 +31,7 @@ #include -#include +#include #include #include #include @@ -66,9 +66,9 @@ public: } - void poppedFromEngine() + void removedFromCore() { - if (mTo) engine.push(mTo); + if (mTo) core.push(mTo); } void update(Scalar t, Scalar dt) @@ -81,7 +81,7 @@ public: if (mInterp.isDone()) { // to should /replace/ this - engine.pop(this); + core.pop(this); } } diff --git a/src/Moof/Video.cc b/src/Moof/Video.cc index 544e172..9e74acb 100644 --- a/src/Moof/Video.cc +++ b/src/Moof/Video.cc @@ -27,7 +27,6 @@ *******************************************************************************/ #include "Dispatch.hh" -#include "Engine.hh" #include "Error.hh" #include "Image.hh" #include "Log.hh" @@ -76,6 +75,8 @@ void Video::init(const Attributes& attribs) setCursorVisible(attribs.cursorVisible); setCursorGrab(attribs.cursorGrab); setVideoMode(attribs.mode); + + video = this; } void Video::recreateContext() @@ -110,6 +111,8 @@ void Video::setOpenGLAttributes() Video::~Video() { SDL_FreeSurface(mContext); + + if (video == this) video = 0; } @@ -132,8 +135,7 @@ void Video::setVideoMode(const long mode[3]) // on win32, creating a new context via SDL_SetVideoMode will wipe // out the GL state, so we gotta notify everyone to reload their // state after the change - engine.dispatch("video.newcontext"); - + core.dispatch("video.newcontext"); logInfo("video context recreated"); #endif } @@ -296,7 +298,7 @@ int Video::getHeight() const Video::Attributes::Attributes() { - // Set some sane GL and window defaults (see SDL_video.c:217) + // set some sane GL and window defaults (see SDL_video.c:217) colorBuffer[0] = 3; colorBuffer[1] = 3; colorBuffer[2] = 2; @@ -322,8 +324,6 @@ Video::Attributes::Attributes() cursorVisible = true; cursorGrab = false; - Settings& settings = Settings::getInstance(); - std::vector colors; settings.get("colorbuffers", colors); if (colors.size() > 0) colorBuffer[0] = colors[0]; @@ -395,6 +395,9 @@ Video::Attributes::Attributes() } +Video* video = 0; + + } // namespace Mf /** vim: set ts=4 sw=4 tw=80: *************************************************/ diff --git a/src/Moof/Video.hh b/src/Moof/Video.hh index 91eecb7..0199bc5 100644 --- a/src/Moof/Video.hh +++ b/src/Moof/Video.hh @@ -35,6 +35,8 @@ #include +#include + namespace Mf { @@ -72,6 +74,10 @@ public: bool cursorGrab; Attributes(); + + private: + + Backend backend; }; @@ -134,6 +140,9 @@ private: }; +extern Video* video; + + } // namespace Mf #endif // _MOOF_VIDEO_HH_ diff --git a/src/Scene.cc b/src/Scene.cc index 175f216..aa2249c 100644 --- a/src/Scene.cc +++ b/src/Scene.cc @@ -193,7 +193,7 @@ struct Scene::Impl : public Mf::Library boost::bind(&Impl::drawTile, this, _1)); int detail = 3; - Mf::Settings::getInstance().get("detail", detail); + Mf::settings.get("detail", detail); script.push(detail); script.set("detail"); script.push(1); script.set("LOW"); diff --git a/src/TitleLayer.cc b/src/TitleLayer.cc index ed8f4c1..9c60913 100644 --- a/src/TitleLayer.cc +++ b/src/TitleLayer.cc @@ -26,7 +26,7 @@ *******************************************************************************/ -#include +#include #include #include @@ -34,7 +34,7 @@ #include "TitleLayer.hh" -void TitleLayer::pushedOntoEngine() +void TitleLayer::addedToCore() { Mf::Scalar coeff[] = {0.0, 1.0}; mFadeIn.init(coeff, 0.1); @@ -63,8 +63,8 @@ bool TitleLayer::handleEvent(const Mf::Event& event) //break; //} - Mf::LayerP titleLayer = Mf::engine.pop(this); - //engine.pushLayer(GameLayer::alloc()); + Mf::LayerP titleLayer = Mf::core.pop(this); + //core.pushLayer(GameLayer::alloc()); Mf::Scalar coeff[] = {0.0, 0.75, 0.99, 1.0}; Mf::PolynomialInterpolator<3> interp(coeff, 0.1); @@ -72,7 +72,7 @@ bool TitleLayer::handleEvent(const Mf::Event& event) //Mf::LayerP mGameLayer = GameLayer::alloc(); Mf::Transition >::Ptr transition = Mf::Transition >::alloc(mGameLayer, titleLayer, interp); - Mf::engine.push(transition); + Mf::core.push(transition); return true; } diff --git a/src/TitleLayer.hh b/src/TitleLayer.hh index 20f42a7..fe745ee 100644 --- a/src/TitleLayer.hh +++ b/src/TitleLayer.hh @@ -48,7 +48,7 @@ public: return TitleLayerP(new TitleLayer); } - void pushedOntoEngine(); + void addedToCore(); void update(Mf::Scalar t, Mf::Scalar dt); void draw(Mf::Scalar alpha) const; diff --git a/win32/mkpackage.sh.in b/win32/mkpackage.sh.in index d3b28ee..784e0fa 100644 --- a/win32/mkpackage.sh.in +++ b/win32/mkpackage.sh.in @@ -24,12 +24,12 @@ rm -rf "$BUILD_DIR" mkdir -p "$BUILD_DIR" cp -f "$ROOT_DIR/src/yoink.exe" "$BUILD_DIR" -"${STRIP:-strip}" "$BUILD_DIR/yoink.exe" +#"${STRIP:-strip}" "$BUILD_DIR/yoink.exe" for dll in $DLLS do cp -f "@prefix@/bin/$dll.dll" "$BUILD_DIR" - "${STRIP:-strip}" "BUILD_DIR/$dll.dll" + #"${STRIP:-strip}" "BUILD_DIR/$dll.dll" done cd "$ROOT_DIR" @@ -65,5 +65,5 @@ then exit 1 fi -rm -rf "$BUILD_DIR" +#rm -rf "$BUILD_DIR"