if test x$debug = xyes
then
- CFLAGS="$CFLAGS -DDEBUG -Wall -Wno-uninitialized"
- CXXFLAGS="$CXXFLAGS -DDEBUG -Wall -Wno-uninitialized"
+ CFLAGS="$CFLAGS -DDEBUG -ggdb -O0 -Wall -Wno-uninitialized"
+ CXXFLAGS="$CXXFLAGS -DDEBUG -ggdb -O0 -Wall -Wno-uninitialized"
else
CFLAGS="$CFLAGS -DNDEBUG"
CXXFLAGS="$CXXFLAGS -DNDEBUG"
// forces
mState.force = Mf::Vector2(0.0, 0.0);
//mState.forces.push_back(SpringForce(Mf::Vector2(5.0, 4.0)));
- //mState.forces.push_back(ResistanceForce(2.0));
+ mState.forces.push_back(ResistanceForce(2.0));
//mState.forces.push_back(Mf::LinearState<2>::GravityForce(-9.8));
// starting position
*
**************************************************************************/
-#include <Moof/Core.hh>
#include <Moof/Error.hh>
#include <Moof/Log.hh>
#include <Moof/Math.hh>
}
}
-void GameLayer::advanceScene()
+void GameLayer::advanceScene(Mf::Settings& settings)
{
if (mState.sceneList.size() != 0)
{
mState.scene = Scene::alloc(mState.sceneList[0]);
mState.sceneList.erase(mState.sceneList.begin());
- Mf::Script::Result status = mState.scene->load(mState.script);
+ Mf::Script::Result status = mState.scene->load(settings,
+ mState.script);
if (status != Mf::Script::SUCCESS)
{
std::string str;
GameLayer::GameLayer() :
- mHud(Hud::alloc(mState)),
mMusic("NightFusionIntro"),
mPunchSound("Thump")
{
mMusic.setLooping(true);
mMusic.enqueue("NightFusionLoop");
- bool isMute = false;
- Mf::settings.get("nomusic", isMute);
- if (!isMute) mMusic.play();
-
//mMusic.setPosition(Mf::Vector3(10.0, 5.0, 0.0));
- loadSceneLoader();
- advanceScene(); // load the first scene
-
mThinkTimer.init(boost::bind(&GameLayer::thinkTimer, this),
0.1, Mf::Timer::REPEAT);
mState.interp.init(0.0, 1.0);
mState.interp.reset(4.0, Mf::Interp::OSCILLATE);
-
- setProjection();
}
-void GameLayer::addedToCore()
+void GameLayer::didAddToView()
{
- Mf::core.push(mHud);
+ bool isMute = false;
+ settings().get("nomusic", isMute);
+ if (!isMute) mMusic.play();
+
+ loadSceneLoader();
+ advanceScene(settings()); // load the first scene
+
+ mHud = Hud::alloc(mState);
+ addChild(mHud);
mRay.direction.set(1.0, 0.0);
mRayTimer.init(boost::bind(&GameLayer::rayTimer, this),
1.0, Mf::Timer::REPEAT);
+
+ setProjection();
}
void GameLayer::update(Mf::Scalar t, Mf::Scalar dt)
{
+ if (!mState.scene) return;
mState.camera.update(t, dt);
mState.heroine->update(t, dt);
mState.scene->checkForCollision(*mState.heroine);
- Mf::Vector3 camPosition(-mState.heroine->getState().position[0],
- -mState.heroine->getState().position[1], -8);
- mState.camera.setPosition(camPosition);
+ Mf::Vector3 cam= -Mf::promote(mState.heroine->getState().position, 8);
+ mState.camera.setPosition(cam);
mRay.point = mState.heroine->getState().position;
+
+ Mf::View::update(t, dt);
}
void GameLayer::thinkTimer()
bool bam = mLine.intersectRay(mRay, meh);
if (bam)
{
- meh.normal.normalize();
- hits.push_back(meh);
+ //meh.normal.normalize();
+ //hits.push_back(meh);
+ mRay.solve(point, meh.distance);
+ Mf::logInfo << "line: d = " << meh.distance << std::endl;
+ Mf::logInfo << " P = " << point << std::endl;
+ Mf::logInfo << " n = " << meh.normal << std::endl;
}
bam = mCircle.intersectRay(mRay, meh);
void GameLayer::draw(Mf::Scalar alpha) const
{
+ if (!mState.scene) return;
mState.camera.uploadToGL(alpha);
// DRAW THE SCENE
mRay.draw();
mLine.draw();
mCircle.draw();
+
+ Mf::View::draw(alpha);
}
bool GameLayer::handleEvent(const Mf::Event& event)
{
+ if (Mf::View::handleEvent(event)) return true;
+
switch (event.type)
{
case SDL_KEYDOWN:
else if (event.key.keysym.sym == SDLK_r)
{
loadSceneLoader();
- advanceScene();
+ advanceScene(settings());
return true;
}
return mState.heroine->handleEvent(event);
case SDL_KEYUP:
if (event.key.keysym.sym == SDLK_ESCAPE)
{
- Mf::core.pop(this);
+ parent().removeChild(this);
return true;
}
else if (event.key.keysym.sym == SDLK_h)
{
- Mf::core.push(mHud);
+ addChild(mHud);
return true;
}
return mState.heroine->handleEvent(event);
void GameLayer::setProjection()
{
- ASSERT(Mf::video &&
- "no current video context from which to get dimensions");
- setProjection(Mf::video->getWidth(), Mf::video->getHeight());
+ setProjection(video().getWidth(), video().getHeight());
}
void GameLayer::setProjection(Mf::Scalar width, Mf::Scalar height)
#include <boost/shared_ptr.hpp>
-#include <Moof/Layer.hh>
#include <Moof/Math.hh>
#include <Moof/Sound.hh>
#include <Moof/Ray.hh>
#include <Moof/Sphere.hh>
#include <Moof/Timer.hh>
+#include <Moof/View.hh>
#include "GameState.hh"
#include "Hud.hh"
class GameLayer;
typedef boost::shared_ptr<GameLayer> GameLayerP;
-class GameLayer : public Mf::Layer
+class GameLayer : public Mf::View
{
public:
- GameLayer();
-
static GameLayerP alloc()
{
return GameLayerP(new GameLayer);
}
+ GameLayer();
- void addedToCore();
+ void didAddToView();
void update(Mf::Scalar t, Mf::Scalar dt);
void draw(Mf::Scalar alpha) const;
private:
void loadSceneLoader();
- void advanceScene();
+ void advanceScene(Mf::Settings& settings);
void thinkTimer();
**************************************************************************/
#include <Moof/Aabb.hh>
-#include <Moof/Core.hh>
#include <Moof/Log.hh>
#include <Moof/OpenGL.hh>
#include <Moof/Video.hh>
mBar2(Mf::Texture("StatusBars"), 2),
mFont("Font")
{
- ASSERT(Mf::video &&
- "no current video context from which to get dimensions");
- resize(Mf::video->getWidth(), Mf::video->getHeight());
+ Mf::Video* video = Mf::Video::current();
+ ASSERT(video && "a current video context should be set");
+ resize(video->getWidth(), video->getHeight());
}
if (event.key.keysym.sym == SDLK_h)
{
// don't want the hud anymore
- Mf::core.pop(this);
+ parent().removeChild(this);
+
Mf::logWarning("okay bye bye hud");
return true;
}
*/
#include <Moof/Drawable.hh>
-#include <Moof/Layer.hh>
#include <Moof/Math.hh>
//#include <Moof/Rectangle.hh>
#include <Moof/Texture.hh>
+#include <Moof/View.hh>
#include "GameState.hh"
class Hud;
typedef boost::shared_ptr<Hud> HudP;
-class Hud : public Mf::Layer
+class Hud : public Mf::View
{
public:
- Hud(GameState& state);
-
static HudP alloc(GameState& state)
{
return HudP(new Hud(state));
}
+ Hud(GameState& state);
+
void setBar1Progress(Mf::Scalar progress)
{
**************************************************************************/
#include <cstdlib> // atexit, getenv
+#include <functional>
#include <iostream>
#include <string>
#include <unistd.h> // access
#include <Moof/OpenGL.hh>
#include <Moof/Resource.hh>
#include <Moof/Settings.hh>
-#include <Moof/Transition.hh>
#include <Moof/Video.hh>
#include "ErrorHandler.hh"
#include "version.h"
-Main::Main()
+Main::Main(Mf::Settings& settings, Mf::Video& video) :
+ Mf::View(settings, video)
{
- mDispatchHandler = Mf::core.addHandler("video.newcontext",
- boost::bind(&Main::contextCreated));
+ Mf::Dispatch& dispatch = Mf::Dispatch::global();
+ mNewContextDispatch = dispatch.addTarget("video.newcontext",
+ boost::bind(&Main::setupGL));
setupGL();
-}
-void Main::addedToCore()
-{
- //Mf::Scalar coeff[] = {0.0, 1.0};
- //Mf::Lerp interp(coeff, 0.25);
-
- //Mf::LayerP gameLayer = GameLayer::alloc();
- //Mf::Transition<Mf::Lerp>::Ptr transition =
- //Mf::Transition<Mf::Lerp>::alloc(gameLayer, Mf::LayerP(), interp);
- //core.push(transition);
- //core.push(GameLayer::alloc());
- Mf::core.push(TitleLayer::alloc());
+ addChild(TitleLayer::alloc());
}
void Main::update(Mf::Scalar t, Mf::Scalar dt)
{
- if (Mf::core.getSize() == 1)
+ if (children().size() == 0)
{
- // this is the only layer left on the stack
- //Mf::core.push(TitleLayer::alloc());
- Mf::core.clear();
+ Mf::logWarning("main view has no children");
+ stop();
+ return;
}
+
+ Mf::View::update(t, dt);
}
void Main::draw(Mf::Scalar alpha) const
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
+
+ Mf::View::draw(alpha);
}
bool Main::handleEvent(const Mf::Event& event)
{
+ if (Mf::View::handleEvent(event)) return true;
+
switch (event.type)
{
case SDL_KEYUP:
- if (event.key.keysym.sym == SDLK_ESCAPE)
+ if (event.key.keysym.sym == SDLK_f)
{
- Mf::core.clear();
- }
- else if (event.key.keysym.sym == SDLK_f)
- {
- Mf::video->toggleFull();
+ video().toggleFull();
}
else if (event.key.keysym.sym == SDLK_l)
{
- Mf::video->toggleCursorGrab();
- Mf::video->toggleCursorVisible();
+ video().toggleCursorGrab();
+ video().toggleCursorVisible();
}
break;
break;
case SDL_QUIT:
- Mf::core.clear();
- break;
+ stop();
+ return true;
}
return false;
std::string path = Mf::Resource::getPath("yoinkrc");
-#if !defined(_WIN32) && !defined(__WIN32__)
+#if !defined(_WIN32)
path += ":/etc/yoinkrc";
#endif
path += ":$HOME/.yoinkrc";
//glMatrixMode(GL_MODELVIEW);
}
-void Main::contextCreated()
-{
- // 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
- setupGL();
-}
-
-
void Main::printUsage()
{
std::cout << std::endl << "Goodbye..." << std::endl << std::endl;
}
+
int main(int argc, char* argv[])
{
if (argc > 1)
Mf::Resource::addSearchPaths(Main::getSearchPath());
- Mf::settings.loadFromFiles(Main::getConfigPath());
- Mf::settings.parseArgs(argc, argv);
+ Mf::Settings settings(argc, argv, Main::getConfigPath());
Mf::Log::Level logLevel = Mf::Log::INFO;
- Mf::settings.get("loglevel", logLevel);
+ settings.get("loglevel", logLevel);
Mf::Log::setLevel(logLevel);
try
{
- Mf::Video video(PACKAGE_STRING,
- Mf::Resource::getPath(PACKAGE".png"));
- MainP app = Main::alloc();
- Mf::core.push(app);
- Mf::core.run();
+ Mf::Video::Attributes attributes(settings);
+ attributes.caption = PACKAGE_STRING;
+ attributes.icon = Mf::Resource::getPath(PACKAGE".png");
+
+ Mf::Video video(attributes);
+ Main mainView(settings, video);
+
+ mainView.run();
+ return 0;
}
catch (const Mf::Error& error)
{
- Mf::ModalDialog dialog;
- dialog.title = PACKAGE_STRING;
- dialog.text1 = "Unhandled Exception";
- dialog.text2 = getErrorString(error);
- dialog.type = Mf::ModalDialog::CRITICAL;
- dialog.run();
+ Mf::ModalDialog dialog(Mf::ModalDialog::CRITICAL,
+ PACKAGE_STRING, "Unhandled Exception",
+ getErrorString(error));
+ dialog.run();
return 1;
}
-
- return 0;
}
#include <boost/shared_ptr.hpp>
#include <Moof/Dispatch.hh>
-#include <Moof/Layer.hh>
#include <Moof/Math.hh>
+#include <Moof/View.hh>
+namespace Mf {
+class Settings;
+class View;
+}
+
class Main;
typedef boost::shared_ptr<Main> MainP;
-class Main : public Mf::Layer
+class Main : public Mf::View
{
public:
- Main();
-
- static MainP alloc()
- {
- return MainP(new Main);
- }
-
- void addedToCore();
+ Main(Mf::Settings& settings, Mf::Video& video);
void update(Mf::Scalar t, Mf::Scalar dt);
void draw(Mf::Scalar alpha) const;
* Set OpenGL to a state we can know and depend on.
*/
static void setupGL();
- static void contextCreated();
- Mf::Dispatch::Handler mDispatchHandler;
+ Mf::Dispatch::Handle mNewContextDispatch;
};
libmoof_a_SOURCES = \
Moof/Aabb.hh \
+ Moof/Backend.cc \
+ Moof/Backend.hh \
Moof/Camera.cc \
Moof/Camera.hh \
+ Moof/Contact.hh \
Moof/ConvertUTF.c \
Moof/ConvertUTF.h \
- Moof/Core.cc \
- Moof/Core.hh \
Moof/Cullable.hh \
Moof/Dispatch.cc \
Moof/Dispatch.hh \
Moof/Image.cc \
Moof/Image.hh \
Moof/Interpolator.hh \
- Moof/Layer.hh \
Moof/Line.hh \
Moof/Log.cc \
Moof/Log.hh \
Moof/Thread.hh \
Moof/Timer.cc \
Moof/Timer.hh \
- Moof/Transition.hh \
Moof/Video.cc \
Moof/Video.hh \
+ Moof/View.cc \
+ Moof/View.hh \
Moof/fastevents.c \
Moof/fastevents.h \
$(ENDLIST)
ErrorHandler.hh \
GameLayer.cc \
GameLayer.hh \
+ GameState.hh \
Heroine.cc \
Heroine.hh \
Hud.cc \
$(YOINK_ENVIRONMENT) ./yoink $(YOINK_OPTS)
debug: all
- $(YOINK_ENVIRONMENT) gdb ./yoink
+ $(YOINK_ENVIRONMENT) ddd ./yoink
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#include <SDL/SDL.h>
+#include "fastevents.h"
+
+#include "Backend.hh"
+#include "Error.hh"
+#include "Log.hh"
+
+
+namespace Mf {
+
+
+struct Impl
+{
+ static Error error;
+ static int retainCount;
+};
+
+Error Impl::error(Error::UNINITIALIZED);
+int Impl::retainCount = 0;
+
+
+Backend::Backend()
+{
+ if (Impl::retainCount++ == 0)
+ {
+#if 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();
+ Impl::error.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();
+ Impl::error.init(Error::FASTEVENTS_INIT, error);
+ return; // fatal
+ }
+
+ Impl::error.init(Error::NONE);
+ }
+}
+
+Backend::Backend(const Backend& backend)
+{
+ ++Impl::retainCount;
+}
+
+Backend::~Backend()
+{
+ if (--Impl::retainCount == 0)
+ {
+ FE_Quit();
+ SDL_Quit();
+
+ Impl::error.reset();
+ }
+}
+
+bool Backend::isInitialized()
+{
+ return Impl::error.code() == Error::NONE;
+}
+
+const Error& Backend::getError()
+{
+ return Impl::error;
+}
+
+
+} // namespace Mf
+
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_BACKEND_HH_
+#define _MOOF_BACKEND_HH_
+
+
+namespace Mf {
+
+
+class Error;
+
+
+/*
+ * 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(const Backend& backend);
+ ~Backend();
+
+ static bool isInitialized();
+ static const Error& getError();
+};
+
+
+} // namespace Mf
+
+#endif // _MOOF_BACKEND_HH_
+
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_CONTACT_HH_
+#define _MOOF_CONTACT_HH_
+
+#include <Moof/Math.hh>
+
+
+namespace Mf {
+
+
+template <int D = 3>
+struct Contact
+{
+ typedef cml::vector< Scalar, cml::fixed<D> > Vector;
+
+ Vector point; // point of contact
+ Scalar distance; // distance of penetration
+ Vector normal; // normal of surface at point of contact
+
+ bool operator < (const Contact& rhs)
+ {
+ return distance < rhs.distance;
+ }
+};
+
+
+} // namespace Mf
+
+#endif // _MOOF_CONTACT_HH_
+
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#include <algorithm>
-#include <cstdlib> // exit, srand
-#include <ctime> // time
-#include <list>
-#include <string>
-
-#include <SDL/SDL.h>
-#include "fastevents.h"
-
-#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 Core::Impl
-{
-public:
-
- Impl() :
- mError(Error::NONE),
- mTimestep(0.01),
- mFramerate(0.02),
- mShowFps(false) {}
-
- void init()
- {
- unsigned randomSeed;
- if (settings.get("rngseed", randomSeed)) srand(randomSeed);
- else srand(time(0));
-
- Scalar timestep = 80.0;
- settings.get("timestep", timestep);
- mTimestep = 1.0 / timestep;
-
- Scalar framerate = 40.0;
- settings.get("framerate", framerate);
- mFramerate = 1.0 / framerate;
-
- mShowFps = false;
- settings.get("showfps", mShowFps);
- }
-
-
- /**
- * The main loop. This just calls dispatchEvents(), update(), and
- * draw() over and over again. The timing of the update and draw are
- * decoupled. The actual frame rate is also calculated here. This
- * function will return the exit code used to stop the loop.
- */
-
- void run()
- {
- init();
- ASSERT(video && "cannot run core without a current video context");
-
- Scalar totalTime = 0.0;
- Scalar ticks = Timer::getTicks();
-
- Scalar nextUpdate = ticks;
- Scalar nextDraw = ticks;
- Scalar nextSecond = ticks + SCALAR(1.0);
-
- mFps = 0;
- int frameCount = 0;
-
- const Scalar timestep = mTimestep;
- const Scalar framerate = mFramerate;
-
- const int MAX_FRAMESKIP = 15;
- const Scalar inverseTimestep = SCALAR(1.0) / timestep;
-
- do
- {
- Timer::fireIfExpired(); // 1. fire timers
- dispatchEvents(); // 2. dispatch events
-
- int i = 0;
- while (nextUpdate < Timer::getTicks() && i < MAX_FRAMESKIP)
- {
- totalTime += timestep;
- update(totalTime, timestep); // 3. update state
-
- nextUpdate += timestep;
- ++i;
- }
-
- if (nextDraw < (ticks = Timer::getTicks()))
- {
- draw((ticks + timestep - nextUpdate) * inverseTimestep);
- video->swap(); // 4. draw state
-
- nextDraw += framerate;
- ++frameCount;
-
- if (nextSecond < Timer::getTicks())
- {
- mFps = frameCount;
- frameCount = 0;
-
- if (mShowFps) logInfo << mFps << " fps" << std::endl;
-
- nextSecond += SCALAR(1.0);
- }
- }
-
- ticks = Timer::getTicks(); // 5. yield timeslice
- if (ticks < nextUpdate && ticks < nextDraw) Timer::sleep(0.0);
- }
- while (!mStack.empty());
-
- mDispatch.dispatch("engine.stopping");
- }
-
-
- void dispatchEvents()
- {
- SDL_Event event;
-
- while (FE_PollEvent(&event) == 1)
- {
- switch (event.type)
- {
- case SDL_KEYDOWN:
- if (event.key.keysym.sym == SDLK_ESCAPE &&
- (SDL_GetModState() & KMOD_CTRL) )
- {
- // emergency escape
- logWarning("escape forced");
- exit(1);
- }
- break;
-
- case SDL_VIDEORESIZE:
- video->resize(event.resize.w, event.resize.h);
- break;
- }
-
- handleEvent(event);
- }
- }
-
-
- void update(Scalar t, Scalar dt)
- {
- for (mStackIt = mStack.begin(); mStackIt != mStack.end();
- ++mStackIt)
- {
- (*mStackIt)->update(t, dt);
- }
- }
-
- void draw(Scalar alpha)
- {
- // FIXME - this will crash if the layer being drawn pops itself
- std::list<LayerP>::reverse_iterator it;
- for (it = mStack.rbegin(); it != mStack.rend(); ++it)
- {
- (*it)->draw(alpha);
- }
- }
-
- void handleEvent(const Event& event)
- {
- for (mStackIt = mStack.begin(); mStackIt != mStack.end();
- ++mStackIt)
- {
- if ((*mStackIt)->handleEvent(event)) break;
- }
- }
-
-
- void push(LayerP layer)
- {
- ASSERT(layer && "cannot push null layer");
- mStack.push_front(layer);
- logInfo << "stack: " << mStack.size()
- << " [pushed " << layer.get() << "]" << std::endl;
- layer->addedToCore();
- }
-
- LayerP pop()
- {
- bool fixIt = false;
- if (mStack.begin() == mStackIt) fixIt = true;
-
- LayerP layer = mStack.front();
- mStack.pop_front();
- logInfo << "stack: " << mStack.size()
- << " [popped " << layer.get() << "]" << std::endl;
- layer->removedFromCore();
-
- if (fixIt) mStackIt = --mStack.begin();
-
- return layer;
- }
-
- LayerP pop(Layer* layer)
- {
- bool fixIt = false;
-
- std::list<LayerP> layers;
-
- std::list<LayerP>::iterator it;
- for (it = mStack.begin(); it != mStack.end(); ++it)
- {
- layers.push_back(*it);
-
- if (it == mStackIt) fixIt = true;
-
- if ((*it).get() == layer)
- {
- ++it;
- mStack.erase(mStack.begin(), it);
-
- for (it = layers.begin(); it != layers.end(); ++it)
- {
- (*it)->removedFromCore();
- logInfo << "stack: " << mStack.size()
- << " [popped " << (*it).get() << "]"
- << std::endl;
- }
-
- if (fixIt) mStackIt = --mStack.begin();
-
- return layers.back();
- }
- }
-
- return LayerP();
- }
-
- void clear()
- {
- mStack.clear();
- mStackIt = mStack.begin();
- logInfo("stack: 0 [cleared]");
- }
-
-
- Error mError;
-
- Dispatch mDispatch;
-
- std::list<LayerP> mStack;
- std::list<LayerP>::iterator mStackIt;
-
- Scalar mTimestep;
- Scalar mFramerate;
-
- int mFps;
- bool mShowFps;
-};
-
-
-Core::Core() :
- // pass through
- mImpl(new Core::Impl) {}
-
-
-void Core::init()
-{
- // pass through
- mImpl->init();
-}
-
-
-int Core::getFps() const
-{
- return mImpl->mFps;
-}
-
-
-void Core::push(LayerP layer)
-{
- // pass through
- mImpl->push(layer);
-}
-
-LayerP Core::pop()
-{
- // pass through
- return mImpl->pop();
-}
-
-LayerP Core::pop(Layer* layer)
-{
- // pass through
- return mImpl->pop(layer);
-}
-
-void Core::clear()
-{
- // pass through
- mImpl->clear();
-}
-
-int Core::getSize() const
-{
- return mImpl->mStack.size();
-}
-
-
-void Core::run()
-{
- // pass through
- return mImpl->run();
-}
-
-
-Dispatch::Handler Core::addHandler(const std::string& event,
- const Dispatch::Function& callback)
-{
- return mImpl->mDispatch.addHandler(event, callback);
-}
-
-Dispatch::Handler Core::addHandler(const std::string& event,
- const Dispatch::Function& callback,
- Dispatch::Handler handler)
-{
- return mImpl->mDispatch.addHandler(event, callback, handler);
-}
-
-void Core::dispatch(const std::string& event,
- const Dispatch::Message* message)
-{
- mImpl->mDispatch.dispatch(event, message);
-}
-
-
-Core core;
-
-
-class Backend_;
-typedef boost::shared_ptr<Backend_> BackendP;
-
-class Backend_
-{
-public:
-
- Backend_()
- {
-#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
- }
-
- gError.init(Error::NONE);
- }
-
- ~Backend_()
- {
- FE_Quit();
- SDL_Quit();
- }
-
- static void retain()
- {
- if (gRetainCount++ == 0)
- {
- gInstance = BackendP(new Backend_);
- }
- }
-
- static void release()
- {
- if (--gRetainCount == 0)
- {
- gInstance.reset();
- gError.reset();
- }
- }
-
- static const Error& getError()
- {
- return gError;
- }
-
-private:
-
- 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::isInitialized()
-{
- return getError().code() == Error::NONE;
-}
-
-const Error& Backend::getError()
-{
- return Backend_::getError();
-}
-
-
-} // namespace Mf
-
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_CORE_HH_
-#define _MOOF_CORE_HH_
-
-#include <string>
-
-#include <boost/shared_ptr.hpp>
-
-#include <Moof/Dispatch.hh>
-#include <Moof/Error.hh>
-#include <Moof/Layer.hh>
-
-
-namespace Mf {
-
-
-/**
- * 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 core is also responsible for firing timers on time. The
- * core will continue running as long as there are layers on the stack.
- */
-
-class Core
-{
-public:
-
- Core();
-
- // loads settings: rngseed, timestep, framerate, showfps
- 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 layers above it
- void clear(); // remove all layers (the core will stop)
-
- int getSize() const; // get the size of the stack
-
- // set this machine in motion
- void run();
-
- Dispatch::Handler addHandler(const std::string& event,
- const Dispatch::Function& callback);
- Dispatch::Handler addHandler(const std::string& event,
- const Dispatch::Function& callback,
- Dispatch::Handler handler);
-
- void dispatch(const std::string& event,
- const Dispatch::Message* message = 0);
-
-private:
-
- class Impl;
- boost::shared_ptr<Impl> 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();
-
- static bool isInitialized();
- static const Error& getError();
-};
-
-
-} // namespace Mf
-
-#endif // _MOOF_CORE_HH_
-
{
public:
- Impl() :
+ Impl(Dispatch* dispatch) :
+ mDispatch(dispatch),
mId(0) {}
- Dispatch::Handler getNewHandler()
+ Dispatch::Handle getNewHandle()
{
++mId;
- //return Dispatch::Handler(this, mId);
- Dispatch::Handler handler(this, mId);
- return handler;
+ Dispatch::Handle handle(mDispatch->mImpl, mId);
+ return handle;
}
typedef std::pair<unsigned,Dispatch::Function> Callback;
typedef std::multimap<std::string,Callback> CallbackLookup;
- typedef CallbackLookup::iterator CallbackIter;
+ typedef CallbackLookup::iterator CallbackIt;
- typedef std::multimap<unsigned,std::string> HandlerLookup;
- typedef HandlerLookup::iterator HandlerIter;
+ typedef std::multimap<unsigned,std::string> HandleLookup;
+ typedef HandleLookup::iterator HandleIt;
- inline Handler addHandler(const std::string& event,
- const Function& callback, Handler handler)
+ inline Handle addTarget(const std::string& event,
+ const Function& callback, Handle handle)
{
mCallbacks.insert(std::make_pair(event,
- std::make_pair(handler.getId(), callback)));
- mHandlers.insert(std::make_pair(handler.getId(), event));
+ std::make_pair(handle.getId(), callback)));
+ mHandles.insert(std::make_pair(handle.getId(), event));
- return handler;
+ return handle;
}
- inline void removeHandler(unsigned id)
+ inline void removeTarget(unsigned id)
{
- std::pair<HandlerIter,HandlerIter>
- matching(mHandlers.equal_range(id));
+ std::pair<HandleIt,HandleIt> matching(mHandles.equal_range(id));
- for (HandlerIter it = matching.first; it != matching.second; ++it)
+ for (HandleIt it = matching.first; it != matching.second; ++it)
{
- CallbackIter first = mCallbacks.find((*it).second);
- CallbackIter last = mCallbacks.end();
+ CallbackIt first = mCallbacks.find((*it).second);
+ CallbackIt last = mCallbacks.end();
- for (CallbackIter jt = first; jt != last; ++jt)
+ for (CallbackIt jt = first; jt != last; ++jt)
{
if ((*jt).second.first == id)
{
}
}
- mHandlers.erase(id);
+ mHandles.erase(id);
}
void dispatch(const std::string& event, const Message* message)
{
- std::pair<CallbackIter,CallbackIter>
+ std::pair<CallbackIt,CallbackIt>
callbacks(mCallbacks.equal_range(event));
- for (CallbackIter it = callbacks.first; it != callbacks.second;
- ++it)
+ for (CallbackIt it = callbacks.first; it != callbacks.second; ++it)
{
Function callback = (*it).second.second;
callback(message);
}
+ Dispatch* mDispatch;
+
unsigned mId;
CallbackLookup mCallbacks;
- HandlerLookup mHandlers;
+ HandleLookup mHandles;
};
-Dispatch::Handler::~Handler()
+void Dispatch::Handle::clear()
{
- if (mId)
+ boost::shared_ptr<Impl> dispatch;
+ if (mId && (dispatch = mDispatch.lock()))
{
- mDispatch->removeHandler(mId);
+ dispatch->removeTarget(mId);
+ mId = 0;
}
}
Dispatch::Dispatch() :
- mImpl(new Dispatch::Impl) {}
+ mImpl(new Dispatch::Impl(this)) {}
-Dispatch::Handler Dispatch::addHandler(const std::string& event,
- const Function& callback)
+Dispatch::Handle Dispatch::addTarget(const std::string& event,
+ const Function& callback)
{
- return addHandler(event, callback, mImpl->getNewHandler());
+ return addTarget(event, callback, mImpl->getNewHandle());
}
-Dispatch::Handler Dispatch::addHandler(const std::string& event,
- const Function& callback,
- Handler handler)
+Dispatch::Handle Dispatch::addTarget(const std::string& event,
+ const Function& callback,
+ Handle handle)
{
// pass through
- return mImpl->addHandler(event, callback, handler);
+ return mImpl->addTarget(event, callback, handle);
}
-void Dispatch::removeHandler(unsigned id)
+void Dispatch::removeTarget(unsigned id)
{
// pass through
- return mImpl->removeHandler(id);
+ return mImpl->removeTarget(id);
}
}
+Dispatch& Dispatch::global()
+{
+ static Dispatch dispatch;
+ return dispatch;
+}
+
+
} // namespace Mf
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
namespace Mf {
class Impl;
boost::shared_ptr<Impl> mImpl;
- void removeHandler(unsigned id);
+ void removeTarget(unsigned id);
public:
};
- class Handler
+ class Handle
{
public:
- Handler() :
- mDispatch(0),
+ Handle() :
mId(0) {}
- Handler(Impl* dispatch, unsigned id) :
+ Handle(boost::weak_ptr<Impl> dispatch, unsigned id) :
mDispatch(dispatch),
mId(id) {}
- Handler(const Handler& handler) :
- mDispatch(handler.mDispatch),
- mId(handler.mId)
+ Handle(const Handle& handle) :
+ mDispatch(handle.mDispatch),
+ mId(handle.mId)
{
- handler.mId = 0;
+ handle.mId = 0;
}
- ~Handler();
+ ~Handle()
+ {
+ clear();
+ }
- Handler& operator = (const Handler& handler)
+ Handle& operator = (const Handle& handle)
{
- mDispatch = handler.mDispatch;
- mId = handler.mId;
- handler.mId = 0;
+ clear();
+ mDispatch = handle.mDispatch;
+ mId = handle.mId;
+ handle.mId = 0;
return *this;
}
{
return mId;
}
+
+ void clear();
private:
- Impl* mDispatch;
- mutable unsigned mId;
-
+ boost::weak_ptr<Impl> mDispatch;
+ mutable unsigned mId;
};
typedef boost::function<void(const Message*)> Function;
Dispatch();
- Handler addHandler(const std::string& event, const Function& callback);
- Handler addHandler(const std::string& event, const Function& callback,
- Handler handler);
+ Handle addTarget(const std::string& event, const Function& callback);
+ Handle addTarget(const std::string& event, const Function& callback,
+ Handle handle);
void dispatch(const std::string& event, const Message* message = 0);
+
+ static Dispatch& global();
};
#include <png.h>
#include <SDL/SDL.h>
-#include "Core.hh"
+#include "Backend.hh"
#include "Error.hh"
#include "Image.hh"
#include "Log.hh"
+++ /dev/null
-
-/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
-**] All rights reserved.
-*
-* vi:ts=4 sw=4 tw=75
-*
-* Distributable under the terms and conditions of the 2-clause BSD license;
-* see the file COPYING for a complete text of the license.
-*
-**************************************************************************/
-
-#ifndef _MOOF_LAYER_HH_
-#define _MOOF_LAYER_HH_
-
-#include <boost/shared_ptr.hpp>
-
-#include <Moof/Event.hh>
-#include <Moof/Math.hh>
-
-
-namespace Mf {
-
-
-class Layer
-{
-public:
-
- virtual ~Layer() {}
-
- virtual void addedToCore() {}
- virtual void removedFromCore() {}
-
- virtual void update(Scalar t, Scalar dt) {}
- virtual void draw(Scalar alpha) const {}
- virtual bool handleEvent(const Event& event)
- {
- return false;
- }
-};
-
-typedef boost::shared_ptr<Layer> LayerP;
-
-
-} // namespace Mf
-
-#endif // _MOOF_LAYER_HH_
-
#ifndef _MOOF_LINE_HH_
#define _MOOF_LINE_HH_
+#include <Moof/Contact.hh>
#include <Moof/Drawable.hh>
+#include <Moof/Log.hh>
#include <Moof/Math.hh>
#include <Moof/OpenGL.hh>
#include <Moof/Ray.hh>
#include <Moof/Shape.hh>
+#include <Moof/Sphere.hh>
#include <Moof/Texture.hh>
a(point1),
b(point2) {}
+
+ Vector getDirection() const
+ {
+ return b - a;
+ }
+
+ Scalar getLength() const
+ {
+ return getDirection().length();
+ }
+
+
+ bool intersect(const Line& other, Contact<D>& hit) const
+ {
+ Scalar d = (other.b[1] - other.a[1]) * (b[0] - a[0]) -
+ (other.b[0] - other.a[0]) * (b[1] - a[1]);
+
+ if (d == SCALAR(0.0)) return false; // lines are parallel
+ // ignoring the (somewhat remote) possibility of coincidence
+
+ Scalar m = ((other.b[0] - other.a[0]) * (a[1] - other.a[1]) -
+ (other.b[1] - other.a[1]) * (a[0] - other.a[0])) / d;
+
+ Scalar n = ((b[0] - a[0]) * (b[1] - other.a[1]) -
+ (b[1] - a[1]) * (b[0] - other.a[0])) / d;
+
+ if (m < SCALAR(0.0) || m > SCALAR(1.0) || // not intersecting
+ n < SCALAR(0.0) || n > SCALAR(1.0)) return false;
+
+ Vector2 tangent = b - a;
+ Vector2 normal = cml::perp(tangent).normalize();
+
+ if (cml::dot(normal, other.a - other.b) < SCALAR(0.0))
+ {
+ normal = -normal;
+ }
+
+ hit.point = a + m * tangent;
+ hit.normal = normal;
+ hit.distance = (other.b - hit.point).length();
+
+ return true;
+ }
+
+ bool intersect(const Sphere<D>& other, Contact<D>& hit) const
+ {
+ Vector surface = b - a;
+ Vector toPoint = other.point - a;
+
+ Scalar surfaceLength = surface.length();
+ surface.normalize();
+
+ Scalar projection = cml::dot(surface, toPoint);
+
+ if (projection < SCALAR(0.0) || projection > surfaceLength)
+ {
+ // try endpoints
+
+ if (other.intersect(a, hit))
+ {
+ hit.normal = -hit.normal;
+ hit.point = a;
+ return true;
+ }
+ else if (other.intersect(b, hit))
+ {
+ hit.normal = -hit.normal;
+ hit.point = b;
+ return true;
+ }
+
+ return false;
+ }
+
+ Vector point = a + surface * projection;
+ Vector normal = other.point - point;
+
+ Scalar distance = normal.length();
+
+ if (distance > other.radius) false; // not intersecting
+
+ normal.normalize();
+
+ hit.distance = other.radius - distance;
+ hit.point = point;
+ hit.normal = normal;
+
+ return true;
+ }
+
+
bool intersectRay(const Ray<2>& ray, Ray<2>::Contact& hit) const
{
+ Vector2 v1 = a - ray.point;
+ Scalar a1 = cml::signed_angle_2D(v1, b - ray.point);
+
+ //logWarning << "angle:::::::::: " << a1 << std::endl;
+
+ if (a1 == Constants::pi())
+ {
+ hit.distance = 5.4321;
+ return true;
+ }
+ else if (a1 == SCALAR(0.0))
+ {
+ hit.distance = 99999.0;
+ return true;
+ }
+
+ Scalar a2 = cml::signed_angle_2D(v1, ray.direction);
+
+ if (a2 < SCALAR(0.0) || a2 > a1) return false;
+
+ //hit.distance = 1.23456;
+ //hit.normal = Vector2(0.0, 0.0);
+
+ Vector2 n = (b - a).normalize();
+ Scalar z = cml::dot(ray.point - a, n);
+ Vector2 p = a + n * z;
+ hit.distance = (ray.point - p).length();
+ hit.normal = cml::perp(a - b);
+ return true;
+
+
+ /*
// solve: Cx + r*Dx = Ax + s(Bx - Ax)
// Cy + r*Dy = Ay + s(By - Ay)
// where: 0 <= s <= 1 if intersection
if (cml::dot(a - ray.point, normal) < 0) hit.normal = normal;
else hit.normal = -normal;
return true;
+ */
}
+
void draw(Scalar alpha = 0.0) const
{
Mf::Texture::resetBind();
typedef Polygon<3,3> Triangle3;
+template <int D>
+bool intersect(const Line<D>& line, const Sphere<D>& sphere,
+ Contact<D>& hit)
+{
+ return false;
+}
+
+
} // namespace Mf
#endif // _MOOF_LINE_HH_
#include "../config.h"
#endif
-#if defined(_WIN32) || defined(__WIN32__)
+#if defined(_WIN32)
#include <windows.h>
#elif defined(__APPLE__) && defined(__MACH__)
#include <Carbon/Carbon.h>
std::string text2;
+
+ ModalDialog(Type pType = INFO,
+ const std::string& pTitle = "",
+ const std::string& pText1 = "",
+ const std::string& pText2 = "") :
+ title(pTitle),
+ type(pType),
+ text1(pText1),
+ text2(pText2) {}
+
+
void run() const
{
switch (type)
break;
}
-#if defined(_WIN32) || defined(__WIN32__)
+#if defined(_WIN32)
int iconType;
switch (type)
onePath += '/';
}
-#if defined(_WIN32) || defined(__WIN32__)
+#if defined(_WIN32)
boost::replace_all(onePath, "/", "\\");
#endif
std::string path(name);
-#if defined(_WIN32) || defined(__WIN32__)
+#if defined(_WIN32)
boost::replace_all(path, "/", "\\");
#endif
std::vector<std::string> copy(path);
std::vector<std::string>::iterator it;
-#if defined(_WIN32) || defined(__WIN32__)
+#if defined(_WIN32)
char* homeDrive = getenv("HOMEDRIVE");
char* homePath = getenv("HOMEPATH");
std::string home(homeDrive ? homeDrive : "");
}
-Settings settings; // global instance
-
-
} // namepsace Mf
{
public:
- Settings()
+ Settings(int argc, char* argv[], const std::string& path)
{
mScript.importBaseLibrary();
importLogFunctions(mScript);
+
+ parseArgs(argc, argv);
+ loadFromFiles(path);
}
~Settings();
}
-extern Settings settings;
-
-
} // namepsace Mf
#endif // _MOOF_SETTINGS_HH_
* returned if there is no contact.
*/
virtual bool intersectRay(const Ray<D>& ray,
- typename Ray<D>::Contact& hit)
+ typename Ray<D>::Contact& hit) const
{
return false;
}
};
+typedef Shape<2> Shape2;
+typedef Shape<3> Shape3;
+
+
} // namespace Mf
#endif // _MOOF_SHAPE_HH_
#ifndef _MOOF_SPHERE_HH_
#define _MOOF_SPHERE_HH_
+#include <Moof/Contact.hh>
#include <Moof/Cullable.hh>
#include <Moof/Drawable.hh>
#include <Moof/Frustum.hh>
* A round object.
*/
+
template <int D = 3>
struct Sphere : public Cullable, public Drawable, public Shape<D>
{
typedef cml::vector< Scalar, cml::fixed<D> > Vector;
- // (solution - point)^2 - radius^2 = 0
Vector point;
Scalar radius;
+
Sphere() {}
Sphere(const Vector& p, Scalar r) :
point(p),
radius(r) {}
- //Sphere(Scalar x, Scalar y, Scalar z, Scalar r) :
- //point(x, y, z),
- //radius(r) {}
void init(const Vector& p, Scalar r)
{
radius = (o - p).length();
}
+ //void encloseVertices(const Vector vertices[], unsigned count);
+
+ //void draw(Scalar alpha = 0.0) const;
+ //bool isVisible(const Frustum& frustum) const;
+
+ void encloseVertices(const Vector vertices[], unsigned count)
+ {
+ // TODO
+ }
+
+ void draw(Scalar alpha = 0.0) const;
+
+ bool isVisible(const Frustum& frustum) const
+ {
+ return true;
+ }
+
+
+ bool intersect(const Sphere<D>& sphere, Contact<D>& hit) const
+ {
+ Vector n = sphere.point - point;
+ Scalar distance = n.length();
+ Scalar limit = radius + sphere.radius;
+
+ if (distance > limit) return false;
+
+ hit.normal = n.normalize();
+ hit.distance = limit - distance;
+ hit.point = hit.normal * radius;
+
+ return true;
+ }
+
+ bool intersect(const Vector& point2, Contact<D>& hit) const
+ {
+ Vector n = point2 - point;
+ Scalar distance = n.length();
+
+ if (distance > radius) return false;
+
+ hit.normal = n.normalize();
+ hit.distance = radius - distance;
+ hit.point = point2;
+
+ return true;
+ }
// a ray inside the sphere will not intersect on its way out
- bool intersectRay(const Ray<D>& ray, typename Ray<D>::Contact& hit)
+ bool intersect(const Ray<D>& ray, typename Ray<D>::Contact& hit) const
{
Vector b = point - ray.point;
Scalar z = cml::dot(b, ray.direction);
hit.normal = surfacePoint - point;
return true;
}
-
-
- //void encloseVertices(const Vector vertices[], unsigned count);
-
- //void draw(Scalar alpha = 0.0) const;
- //bool isVisible(const Frustum& frustum) const;
-
- void encloseVertices(const Vector vertices[], unsigned count)
- {
- // TODO
- }
-
- void draw(Scalar alpha = 0.0) const;
- //{
- //GLUquadricObj* sphereObj = gluNewQuadric();
- //gluQuadricDrawStyle(sphereObj, GLU_LINE);
-
- //glPushMatrix();
-
- //glTranslate(point);
- //gluSphere(sphereObj, GLdouble(radius), 16, 16);
-
- //glPopMatrix();
-
- //gluDeleteQuadric(sphereObj);
- //}
-
- bool isVisible(const Frustum& frustum) const
- {
- return true;
- }
};
mObject(0)
{
// make sure we have a video context
- ASSERT(video &&
- "cannot load textures without a current video context");
+ Video* video = Video::current();
+ ASSERT(video && "should have a video context set");
// we want to know when the GL context is recreated
- mDispatchHandler = core.addHandler("video.newcontext",
- boost::bind(&Impl::contextRecreated, this));
+ Dispatch& dispatch = Dispatch::global();
+ mNewContextDispatch = dispatch.addTarget("video.newcontext",
+ boost::bind(&Impl::contextRecreated, this));
}
~Impl()
GLuint mObject; ///< GL texture handle.
static GLuint gObject; ///< Global GL texture handle.
- Dispatch::Handler mDispatchHandler;
+ Dispatch::Handle mNewContextDispatch;
};
GLuint Texture::Impl::gObject = 0;
*
**************************************************************************/
+#define _MOOF_TRANSITION_HH_
#ifndef _MOOF_TRANSITION_HH_
#define _MOOF_TRANSITION_HH_
}
- void removedFromCore()
+ void removedFromCore(Core& core)
{
if (mTo) core.push(mTo);
}
- void update(Scalar t, Scalar dt)
+ void update(Core& core, Scalar t, Scalar dt)
{
mInterp.update(t, dt);
- if (mFrom) mFrom->update(t, dt);
- if (mTo) mTo->update(t, dt);
+ if (mFrom) mFrom->update(core, t, dt);
+ if (mTo) mTo->update(core, t, dt);
if (mInterp.isDone())
{
glPopMatrix();
}
- void draw(Scalar alpha) const
+ void draw(Core& core, Scalar alpha) const
{
Scalar a = mInterp.getState(alpha);
logInfo << "transition state: " << a << std::endl;
glPushMatrix();
glLoadIdentity();
glRotate(180.0 * a, 0.0, 1.0, 0.0);
- mFrom->draw(alpha);
+ mFrom->draw(core, alpha);
glPopMatrix();
}
//drawFade(a);
glPushMatrix();
glLoadIdentity();
glRotate(180.0 * (1.0 - a), 0.0, 1.0, 0.0);
- mTo->draw(alpha);
+ mTo->draw(core, alpha);
glPopMatrix();
}
//drawFade(1.0 - a);
}
- bool handleEvent(const Event& event)
+ bool handleEvent(Core& core, const Event& event)
{
if (mTo)
{
- return mTo->handleEvent(event);
+ return mTo->handleEvent(core, event);
}
else if (mFrom)
{
- return mFrom->handleEvent(event);
+ return mFrom->handleEvent(core, event);
}
return false;
}
*
**************************************************************************/
-#include "Dispatch.hh"
#include "Error.hh"
#include "Image.hh"
#include "Log.hh"
namespace Mf {
-Video::Video()
+Video::Video() :
+ mDispatch(Dispatch::global())
{
init();
}
Video::Video(const Attributes& attribs) :
- mAttribs(attribs)
+ mAttribs(attribs),
+ mDispatch(Dispatch::global())
{
init();
}
-Video::Video(const std::string& caption, const std::string& icon)
-{
- mAttribs.caption = caption;
- mAttribs.icon = icon;
-
- init();
-}
-
void Video::init()
{
Error error = Backend::getError();
setCursorGrab(mAttribs.cursorGrab);
setVideoMode(mAttribs.mode);
- video = this;
+ if (!gCurrentVideo) makeCurrent();
}
void Video::recreateContext()
{
SDL_FreeSurface(mContext);
- if (video == this) video = 0;
+ if (gCurrentVideo == this) gCurrentVideo = 0;
}
-void Video::setVideoMode(const long mode[3])
+void Video::setVideoMode(const int mode[3])
{
if (mode != mAttribs.mode || !mContext)
{
#if !defined(linux) && !defined(__linux) && !defined(__linux__)
logInfo("video context recreated");
- core.dispatch("video.newcontext");
+ mDispatch.dispatch("video.newcontext");
#endif
}
else Error(Error::SDL_VIDEOMODE).raise();
void Video::resize(int width, int height)
{
- long mode[] = {width, height, mAttribs.mode[2]};
+ int mode[] = {width, height, mAttribs.mode[2]};
setVideoMode(mode);
}
}
+void Video::makeCurrent() const
+{
+ gCurrentVideo = const_cast<Video*>(this);
+}
+
+
+void Video::setDispatch(Dispatch& dispatch)
+{
+ mDispatch = dispatch;
+}
+
+
Video::Attributes::Attributes()
{
- // set some sane GL and window defaults (see SDL_video.c:217)
- colorBuffer[0] = 3;
- colorBuffer[1] = 3;
- colorBuffer[2] = 2;
- colorBuffer[3] = 0;
- frameBuffer = 0;
- doubleBuffer = true;
- depthBuffer = 16;
- stencilBuffer = 0;
- accumBuffer[0] = 0;
- accumBuffer[1] = 0;
- accumBuffer[2] = 0;
- accumBuffer[3] = 0;
- stereo = false;
- multisampleBuffers = 0;
- multisampleSamples = 0;
- swapControl = false;
- hardwareOnly = false;
- mode[0] = 640;
- mode[1] = 480;
- mode[2] = 0;
- fullscreen = false;
- resizable = false;
- cursorVisible = true;
- cursorGrab = false;
+ init();
+}
- std::vector<long> colors;
+Video::Attributes::Attributes(const Settings& settings)
+{
+ init();
+
+ std::vector<int> colors;
settings.get("colorbuffers", colors);
if (colors.size() > 0) colorBuffer[0] = colors[0];
if (colors.size() > 1) colorBuffer[1] = colors[1];
settings.get("depthbuffer", depthBuffer);
settings.get("stencilbuffer", stencilBuffer);
- std::vector<long> accum;
+ std::vector<int> accum;
settings.get("accumbuffers", accum);
if (accum.size() > 0) accumBuffer[0] = accum[0];
if (accum.size() > 1) accumBuffer[1] = accum[1];
settings.get("showcursor", cursorVisible);
settings.get("grab", cursorGrab);
- std::vector<long> dimensions;
+ std::vector<int> dimensions;
settings.get("videomode", dimensions);
if (dimensions.size() > 1)
{
if (dimensions.size() > 2) mode[2] = dimensions[2];
}
+void Video::Attributes::init()
+{
+ // set some sane GL and window defaults (see SDL_video.c:217)
+ colorBuffer[0] = 3;
+ colorBuffer[1] = 3;
+ colorBuffer[2] = 2;
+ colorBuffer[3] = 0;
+ frameBuffer = 0;
+ doubleBuffer = true;
+ depthBuffer = 16;
+ stencilBuffer = 0;
+ accumBuffer[0] = 0;
+ accumBuffer[1] = 0;
+ accumBuffer[2] = 0;
+ accumBuffer[3] = 0;
+ stereo = false;
+ multisampleBuffers = 0;
+ multisampleSamples = 0;
+ swapControl = false;
+ hardwareOnly = false;
+ mode[0] = 640;
+ mode[1] = 480;
+ mode[2] = 0;
+ fullscreen = false;
+ resizable = false;
+ cursorVisible = true;
+ cursorGrab = false;
+}
+
-Video* video = 0; // most recently instantiated instance
+Video* Video::gCurrentVideo = 0; // most recently instantiated instance
} // namespace Mf
#include <boost/shared_ptr.hpp>
#include <SDL/SDL.h>
-#include <Moof/Core.hh>
+#include <Moof/Backend.hh>
+#include <Moof/Dispatch.hh>
namespace Mf {
+class Settings;
class Video;
typedef boost::shared_ptr<Video> VideoP;
struct Attributes
{
// OpenGL attributes
- long colorBuffer[4]; // rgba
- long frameBuffer;
+ int colorBuffer[4]; // rgba
+ int frameBuffer;
bool doubleBuffer;
- long depthBuffer;
- long stencilBuffer;
- long accumBuffer[4]; // rgba
+ int depthBuffer;
+ int stencilBuffer;
+ int accumBuffer[4]; // rgba
bool stereo;
- long multisampleBuffers;
- long multisampleSamples;
+ int multisampleBuffers;
+ int multisampleSamples;
bool swapControl;
bool hardwareOnly;
// Window attributes
std::string caption;
std::string icon;
- long mode[3]; // width, height, bpp
+ int mode[3]; // width, height, bpp
bool fullscreen;
bool resizable;
bool cursorVisible;
bool cursorGrab;
Attributes();
+ Attributes(const Settings& settings);
private:
- Backend mBackend;
+ void init();
+ Backend mBackend;
};
- static VideoP alloc(const std::string& caption,
- const std::string& icon)
+ static VideoP alloc(const Attributes& attribs)
{
- return VideoP(new Video(caption, icon));
+ return VideoP(new Video(attribs));
}
Video();
explicit Video(const Attributes& attribs);
- Video(const std::string& caption, const std::string& icon);
~Video();
- void setVideoMode(const long mode[3]);
+ void setVideoMode(const int mode[3]);
Attributes getAttributes() const;
void resize(int width, int height);
int getWidth() const;
int getHeight() const;
+ static Video* current()
+ {
+ return gCurrentVideo;
+ }
+
+ void makeCurrent() const;
+
+ void setDispatch(Dispatch& dispatch);
+
private:
void init();
// TODO this implementation should be hidden
- SDL_Surface* mContext;
- unsigned mFlags;
- Attributes mAttribs;
-};
+ SDL_Surface* mContext;
+ unsigned mFlags;
+ Attributes mAttribs;
+ Dispatch& mDispatch;
-
-extern Video* video;
+ static Video* gCurrentVideo;
+};
} // namespace Mf
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#include <algorithm>
+#include <cstdlib> // exit, srand
+#include <ctime> // time
+#include <string>
+
+#include <SDL/SDL.h>
+#include "fastevents.h"
+
+#include "Error.hh"
+#include "Event.hh"
+#include "Log.hh"
+#include "Math.hh"
+#include "ModalDialog.hh"
+#include "Settings.hh"
+#include "Timer.hh"
+#include "Video.hh"
+#include "View.hh"
+
+
+namespace Mf {
+
+
+class RootView : public View
+{
+ void update(Scalar t, Scalar dt)
+ {
+ if (children().size() == 0) stop();
+ }
+};
+
+static RootView gRootView;
+
+
+class View::Impl
+{
+public:
+
+ Impl(View* view, Settings& settings, Video& video) :
+ mView(*view),
+ mSettings(&settings),
+ mVideo(&video),
+ mParent(&gRootView)
+ {
+ init();
+
+ unsigned randomSeed;
+ if (settings.get("rngseed", randomSeed)) srand(randomSeed);
+ else srand(time(0));
+
+ Scalar timestep = 80.0;
+ settings.get("timestep", timestep);
+ mTimestep = 1.0 / timestep;
+
+ Scalar framerate = 40.0;
+ settings.get("framerate", framerate);
+ mFramerate = 1.0 / framerate;
+
+ mShowFps = false;
+ settings.get("showfps", mShowFps);
+ }
+
+ Impl(View* view) :
+ mView(*view),
+ mSettings(0),
+ mVideo(0),
+ mParent(&gRootView)
+ {
+ init();
+ }
+
+ void init()
+ {
+ mTimestep = SCALAR(0.01);
+ mFramerate = SCALAR(0.02);
+ mShowFps = false;
+ }
+
+
+ /**
+ * The main loop. This just calls dispatchEvents(), update(), and
+ * draw() over and over again. The timing of the update and draw are
+ * decoupled. The actual frame rate is also calculated here. This
+ * function will return the exit code used to stop the loop.
+ */
+
+ void run()
+ {
+ ASSERT(mVideo && "running without video set");
+
+ Scalar totalTime = 0.0;
+ Scalar ticks = Timer::getTicks();
+
+ Scalar nextUpdate = ticks;
+ Scalar nextDraw = ticks;
+ Scalar nextSecond = ticks + SCALAR(1.0);
+
+ mFps = 0;
+ int frameCount = 0;
+
+ const Scalar timestep = mTimestep;
+ const Scalar framerate = mFramerate;
+
+ const int MAX_FRAMESKIP = 15;
+ const Scalar inverseTimestep = SCALAR(1.0) / timestep;
+
+ mIsRunning = true;
+ for (;;)
+ {
+ Timer::fireIfExpired(); // 1. fire timers
+ dispatchEvents(); // 2. dispatch events
+
+ if (!mIsRunning) break;
+
+ int i = 0;
+ while (nextUpdate < Timer::getTicks() && i < MAX_FRAMESKIP)
+ {
+ totalTime += timestep; // 3. update state
+ mView.update(totalTime, timestep);
+
+ nextUpdate += timestep;
+ ++i;
+
+ if (!mIsRunning) break;
+ }
+
+ if (nextDraw < (ticks = Timer::getTicks()))
+ {
+ mView.draw(
+ (ticks + timestep - nextUpdate) * inverseTimestep);
+ mVideo->swap(); // 4. draw state
+
+ nextDraw += framerate;
+ ++frameCount;
+
+ if (nextSecond < Timer::getTicks())
+ {
+ mFps = frameCount;
+ frameCount = 0;
+
+ if (mShowFps) logInfo << mFps << " fps" << std::endl;
+
+ nextSecond += SCALAR(1.0);
+ }
+ }
+
+ if (!mIsRunning) break;
+
+ ticks = Timer::getTicks(); // 5. yield timeslice
+ if (ticks < nextUpdate && ticks < nextDraw) Timer::sleep(0.0);
+ }
+ }
+
+ void stop()
+ {
+ mIsRunning = false;
+ }
+
+
+ void dispatchEvents()
+ {
+ Event event;
+
+ while (FE_PollEvent(&event) == 1)
+ {
+ switch (event.type)
+ {
+ case SDL_KEYDOWN:
+ if (event.key.keysym.sym == SDLK_ESCAPE &&
+ (SDL_GetModState() & KMOD_CTRL) )
+ {
+ // emergency escape
+ logWarning("escape forced");
+ exit(1);
+ }
+ break;
+
+ case SDL_VIDEORESIZE:
+ mVideo->resize(event.resize.w, event.resize.h);
+ break;
+ }
+
+ mView.handleEvent(event);
+ }
+ }
+
+ bool handleEvent(const Event& event)
+ {
+ std::list<ViewP>::iterator it;
+ for (it = mChildren.begin(); it != mChildren.end(); ++it)
+ {
+ if ((*it)->handleEvent(event)) return true;
+ }
+
+ return false;
+ }
+
+ void update(Scalar t, Scalar dt)
+ {
+ std::list<ViewP>::iterator it;
+ for (it = mChildren.begin(); it != mChildren.end(); ++it)
+ {
+ (*it)->update(t, dt);
+ }
+ }
+
+ void draw(Scalar alpha)
+ {
+ std::list<ViewP>::iterator it;
+ for (it = mChildren.begin(); it != mChildren.end(); ++it)
+ {
+ (*it)->draw(alpha);
+ }
+ }
+
+
+ void addChild(ViewP child)
+ {
+ ASSERT(child && "adding null view");
+ ASSERT(child.get() != &mView && "adding view to itself");
+
+ child->mImpl->mParent->removeChild(child);
+ mChildren.push_back(child);
+
+ child->mImpl->mParent = &mView;
+ child->mImpl->percolateObjects();
+
+ child->didAddToView();
+ }
+
+ void percolateObjects()
+ {
+ bool recurseAgain = false;
+
+ if (mParent->mImpl->mVideo && mParent->mImpl->mVideo != mVideo)
+ {
+ mVideo = mParent->mImpl->mVideo;
+ recurseAgain = true;
+ }
+
+ if (mParent->mImpl->mSettings &&
+ mParent->mImpl->mSettings != mSettings)
+ {
+ mSettings = mParent->mImpl->mSettings;
+ recurseAgain = true;
+ }
+
+ if (recurseAgain)
+ {
+ std::list<ViewP>::iterator it;
+ for (it = mChildren.begin(); it != mChildren.end(); ++it)
+ {
+ (*it)->mImpl->percolateObjects();
+ }
+ }
+ }
+
+ ViewP removeChild(View* child)
+ {
+ ASSERT(child && "cannot remove null child");
+
+ std::list<ViewP>::iterator it;
+ for (it = mChildren.begin(); it != mChildren.end(); ++it)
+ {
+ if ((*it).get() == child)
+ {
+ ViewP found = *it;
+ found->willRemoveFromView();
+ mChildren.erase(it);
+
+ found->mImpl->mParent = &gRootView;
+
+ return found;
+ }
+ }
+
+ return ViewP();
+ }
+
+ void clear()
+ {
+ mChildren.clear();
+ }
+
+
+ bool mIsRunning;
+ View& mView;
+
+ Settings* mSettings;
+ Video* mVideo;
+
+ View* mParent;
+ std::list<ViewP> mChildren;
+
+ Scalar mTimestep;
+ Scalar mFramerate;
+
+ int mFps;
+ bool mShowFps;
+};
+
+
+View::View(Settings& settings, Video& video) :
+ // pass through
+ mImpl(new View::Impl(this, settings, video)) {}
+
+View::View() :
+ mImpl(new View::Impl(this)) {}
+
+
+void View::update(Scalar t, Scalar dt)
+{
+ // pass through
+ mImpl->update(t, dt);
+}
+
+void View::draw(Scalar alpha) const
+{
+ // pass through
+ mImpl->draw(alpha);
+}
+
+bool View::handleEvent(const Event& event)
+{
+ // pass through
+ return mImpl->handleEvent(event);
+}
+
+
+void View::addChild(ViewP view)
+{
+ // pass through
+ mImpl->addChild(view);
+}
+
+ViewP View::removeChild(View* view)
+{
+ // pass through
+ return mImpl->removeChild(view);
+}
+
+ViewP View::removeChild(ViewP view)
+{
+ // pass through
+ return mImpl->removeChild(view.get());
+}
+
+void View::clear()
+{
+ // pass through
+ mImpl->clear();
+}
+
+
+View& View::parent() const
+{
+ return *(mImpl->mParent);
+}
+
+const std::list<ViewP>& View::children() const
+{
+ return mImpl->mChildren;
+}
+
+
+Settings& View::settings() const
+{
+ ASSERT(mImpl->mSettings && "accessing null reference");
+ // pass through
+ return *(mImpl->mSettings);
+}
+
+Video& View::video() const
+{
+ ASSERT(mImpl->mVideo && "accessing null reference");
+ // pass through
+ return *(mImpl->mVideo);
+}
+
+
+void View::run()
+{
+ // pass through
+ return mImpl->run();
+}
+
+void View::stop()
+{
+ // pass through
+ return mImpl->stop();
+}
+
+bool View::isRunning() const
+{
+ // pass through
+ return mImpl->mIsRunning;
+}
+
+
+} // namespace Mf
+
--- /dev/null
+
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
+
+#ifndef _MOOF_VIEW_HH_
+#define _MOOF_VIEW_HH_
+
+#include <list>
+#include <string>
+
+#include <boost/shared_ptr.hpp>
+
+#include <Moof/Event.hh>
+#include <Moof/Math.hh>
+
+
+namespace Mf {
+
+
+class Settings;
+class Video;
+
+class View;
+typedef boost::shared_ptr<View> ViewP;
+
+/**
+ * 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 core is also responsible for firing timers on time. The
+ * core will continue running as long as there are layers on the stack.
+ */
+
+class View
+{
+public:
+
+ // loads settings: rngseed, timestep, framerate, showfps
+ View(Settings& settings, Video& video);
+ View();
+
+ virtual ~View() {}
+
+ virtual void didAddToView() {}
+ virtual void willRemoveFromView() {}
+
+ virtual void update(Scalar t, Scalar dt);
+ virtual void draw(Scalar alpha) const;
+ virtual bool handleEvent(const Event& event);
+
+
+ void addChild(ViewP view);
+ ViewP removeChild(View* view);
+ ViewP removeChild(ViewP view);
+ void clear();
+
+ View& parent() const;
+ const std::list<ViewP>& children() const;
+
+ // do not call these without adding the view to a hierarchy with a base
+ // view constructed with settings and a video context
+ Settings& settings() const;
+ Video& video() const;
+
+ // set this machine in motion
+ void run();
+ void stop();
+ bool isRunning() const;
+
+private:
+
+ class Impl;
+ boost::shared_ptr<Impl> mImpl;
+};
+
+
+} // namespace Mf
+
+#endif // _MOOF_VIEW_HH_
+
void init(const std::string& name) {}
- void importSceneBindings(Mf::Script& script)
+ void importSceneBindings(Mf::Settings& settings, Mf::Script& script)
{
script.importFunction("SetBounds",
boost::bind(&Impl::setBounds, this, _1));
boost::bind(&Impl::drawTile, this, _1));
int detail = 3;
- Mf::settings.get("detail", detail);
+ settings.get("detail", detail);
script.push(detail); script.set("detail");
script.push(1); script.set("LOW");
}
- Mf::Script::Result load(Mf::Script& script)
+ Mf::Script::Result load(Mf::Settings& settings, Mf::Script& script)
{
std::string filePath = Scene::getPath(getName());
if (filePath == "")
return Mf::Script::FILE_ERROR;
}
- importSceneBindings(script);
+ importSceneBindings(settings, script);
return script.doFile(filePath);
}
mImpl(Scene::Impl::getInstance(name)) {}
-Mf::Script::Result Scene::load(Mf::Script& script)
+Mf::Script::Result Scene::load(Mf::Settings& settings, Mf::Script& script)
{
// pass through
- return mImpl->load(script);
+ return mImpl->load(settings, script);
}
class Character;
+namespace Mf {
+class Settings;
+}
+
class Scene;
typedef boost::shared_ptr<Scene> SceneP;
return SceneP(new Scene(name));
}
- Mf::Script::Result load(Mf::Script& script);
+ Mf::Script::Result load(Mf::Settings& settings, Mf::Script& script);
void draw(Mf::Scalar alpha) const;
void drawIfVisible(Mf::Scalar alpha, const Mf::Frustum& frustum) const;
*
**************************************************************************/
-#include <Moof/Core.hh>
#include <Moof/OpenGL.hh>
-#include <Moof/Transition.hh>
#include "GameLayer.hh"
#include "TitleLayer.hh"
-void TitleLayer::addedToCore()
+void TitleLayer::didAddToView()
{
mFadeIn.init(0.0, 1.0);
mFadeIn.reset(0.1);
- mGameLayer = GameLayer::alloc();
+ //mGameLayer = GameLayer::alloc();
}
void TitleLayer::update(Mf::Scalar t, Mf::Scalar dt)
{
mFadeIn.update(t, dt);
+ Mf::View::update(t, dt);
}
void TitleLayer::draw(Mf::Scalar alpha) const
{
glClearColor(0.0, 0.0, mFadeIn.getState(alpha), 1.0);
glClear(GL_COLOR_BUFFER_BIT);
+ Mf::View::draw(alpha);
}
bool TitleLayer::handleEvent(const Mf::Event& event)
{
+ if (Mf::View::handleEvent(event)) return true;
+
switch (event.type)
{
case SDL_KEYUP:
if (event.key.keysym.sym == SDLK_ESCAPE)
{
- break;
+ parent().removeChild(this);
+ return true;
}
- Mf::LayerP titleLayer = Mf::core.pop(this);
+ mGameLayer = GameLayer::alloc();
+ parent().addChild(mGameLayer);
+
+ parent().removeChild(this);
- Mf::Lerp interp(0.1);
- interp.init(0.0, 1.0);
+ //Mf::Lerp interp(0.1);
+ //interp.init(0.0, 1.0);
- Mf::Transition<Mf::Lerp>::Ptr transition =
- Mf::Transition<Mf::Lerp>::alloc(mGameLayer, titleLayer,
- interp);
- Mf::core.push(transition);
+ //Mf::Transition<Mf::Lerp>::Ptr transition =
+ //Mf::Transition<Mf::Lerp>::alloc(mGameLayer, titleLayer,
+ //interp);
return true;
}
#include <boost/shared_ptr.hpp>
#include <Moof/Interpolator.hh>
-#include <Moof/Layer.hh>
#include <Moof/Math.hh>
+#include <Moof/View.hh>
class TitleLayer;
typedef boost::shared_ptr<TitleLayer> TitleLayerP;
-class TitleLayer : public Mf::Layer
+class TitleLayer : public Mf::View
{
public:
return TitleLayerP(new TitleLayer);
}
- void addedToCore();
+ void didAddToView();
void update(Mf::Scalar t, Mf::Scalar dt);
void draw(Mf::Scalar alpha) const;
private:
Mf::Lerp mFadeIn;
- Mf::LayerP mGameLayer;
+ Mf::ViewP mGameLayer;
};