#include <SDL/SDL.h>
#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:
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);
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();
}
void run()
{
+ init();
+
Scalar totalTime = 0.0;
Scalar ticks = Timer::getTicks();
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();
{
++frames;
draw((ticks + mTimestep - nextUpdate) * inverseTimestep);
- mVideo->swap();
+ video->swap();
nextDraw += mFramerate;
mDispatch.dispatch("engine.stopping");
}
+
void dispatchEvents()
{
SDL_Event event;
break;
case SDL_VIDEORESIZE:
- mVideo->resize(event.resize.w, event.resize.h);
+ video->resize(event.resize.w, event.resize.h);
break;
}
mStack.push_front(layer);
logInfo << "stack: " << mStack.size()
<< " [pushed " << layer.get() << "]" << std::endl;
- layer->pushedOntoEngine();
+ layer->addedToCore();
}
LayerP pop()
mStack.pop_front();
logInfo << "stack: " << mStack.size()
<< " [popped " << layer.get() << "]" << std::endl;
- layer->poppedFromEngine();
+ layer->removedFromCore();
if (fixIt) mStackIt = --mStack.begin();
for (it = layers.begin(); it != layers.end(); ++it)
{
- (*it)->poppedFromEngine();
+ (*it)->removedFromCore();
logInfo << "stack: " << mStack.size()
<< " [popped " << (*it).get() << "]" << std::endl;
}
}
- 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<LayerP> mStack;
std::list<LayerP>::iterator mStackIt;
};
-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<Backend_> 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