destroyed global classes; view hierarchy instead
authorCharles McGarvey <chazmcgarvey@brokenzipper.com>
Mon, 1 Mar 2010 07:27:38 +0000 (00:27 -0700)
committerCharles McGarvey <chazmcgarvey@brokenzipper.com>
Mon, 1 Mar 2010 07:27:38 +0000 (00:27 -0700)
35 files changed:
configure.ac
src/Character.cc
src/GameLayer.cc
src/GameLayer.hh
src/Hud.cc
src/Hud.hh
src/Main.cc
src/Main.hh
src/Makefile.am
src/Moof/Backend.cc [new file with mode: 0644]
src/Moof/Backend.hh [new file with mode: 0644]
src/Moof/Contact.hh [new file with mode: 0644]
src/Moof/Core.cc [deleted file]
src/Moof/Core.hh [deleted file]
src/Moof/Dispatch.cc
src/Moof/Dispatch.hh
src/Moof/Image.cc
src/Moof/Layer.hh [deleted file]
src/Moof/Line.hh
src/Moof/ModalDialog.hh
src/Moof/Resource.cc
src/Moof/Settings.cc
src/Moof/Settings.hh
src/Moof/Shape.hh
src/Moof/Sphere.hh
src/Moof/Texture.cc
src/Moof/Transition.hh
src/Moof/Video.cc
src/Moof/Video.hh
src/Moof/View.cc [new file with mode: 0644]
src/Moof/View.hh [new file with mode: 0644]
src/Scene.cc
src/Scene.hh
src/TitleLayer.cc
src/TitleLayer.hh

index fa996164497112097c86a85f632056a99f660e60..7a01c45c1a5f7b23aeae3ad09b0cac4e2687cebc 100644 (file)
@@ -102,8 +102,8 @@ AC_ARG_ENABLE([qt4],
 
 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"
index 840099c8fcd97cd1cffb17d7a9010a635d0c383f..82d5e548e47beab288d6b262bb8cab9cca3ec66d 100644 (file)
@@ -73,7 +73,7 @@ Character::Character(const std::string& name) :
        // 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
index 331d04fbc9db98f81d02ba12a3c07c9fea618fed..0be8eb744f9fe1720acbb7ac2d9753bbf431987f 100644 (file)
@@ -9,7 +9,6 @@
 *
 **************************************************************************/
 
-#include <Moof/Core.hh>
 #include <Moof/Error.hh>
 #include <Moof/Log.hh>
 #include <Moof/Math.hh>
@@ -53,14 +52,15 @@ void GameLayer::loadSceneLoader()
        }
 }
 
-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;
@@ -85,22 +85,14 @@ void GameLayer::advanceScene()
 
 
 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);
 
@@ -109,14 +101,20 @@ GameLayer::GameLayer() :
 
        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);
 
@@ -128,21 +126,25 @@ void GameLayer::addedToCore()
 
        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()
@@ -162,8 +164,12 @@ void GameLayer::rayTimer()
        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);
@@ -186,6 +192,7 @@ void GameLayer::rayTimer()
 
 void GameLayer::draw(Mf::Scalar alpha) const
 {
+       if (!mState.scene) return;
        mState.camera.uploadToGL(alpha);
 
        // DRAW THE SCENE
@@ -200,10 +207,14 @@ void GameLayer::draw(Mf::Scalar alpha) const
        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:
@@ -234,7 +245,7 @@ bool GameLayer::handleEvent(const Mf::Event& event)
                        else if (event.key.keysym.sym == SDLK_r)
                        {
                                loadSceneLoader();
-                               advanceScene();
+                               advanceScene(settings());
                                return true;
                        }
                        return mState.heroine->handleEvent(event);
@@ -242,12 +253,12 @@ bool GameLayer::handleEvent(const Mf::Event& 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);
@@ -268,9 +279,7 @@ bool GameLayer::handleEvent(const Mf::Event& 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)
index c537af6391569230118af2ee7ff72f086b5f3d1f..145cf76cba75a0d58d6c3c77ecd8369fefc651e4 100644 (file)
@@ -23,7 +23,6 @@
 
 #include <boost/shared_ptr.hpp>
 
-#include <Moof/Layer.hh>
 #include <Moof/Math.hh>
 #include <Moof/Sound.hh>
 
@@ -32,6 +31,7 @@
 #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;
@@ -60,7 +59,7 @@ public:
 private:
 
        void loadSceneLoader();
-       void advanceScene();
+       void advanceScene(Mf::Settings& settings);
 
        void thinkTimer();
 
index f4134cf737fd468acee3b76acc5a3166bfc00611..28b7c3487f8fbbbd0184bf725bd164f5ae5dafa6 100644 (file)
@@ -10,7 +10,6 @@
 **************************************************************************/
 
 #include <Moof/Aabb.hh>
-#include <Moof/Core.hh>
 #include <Moof/Log.hh>
 #include <Moof/OpenGL.hh>
 #include <Moof/Video.hh>
@@ -111,9 +110,9 @@ Hud::Hud(GameState& state) :
        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());
 }
 
 
@@ -174,7 +173,8 @@ bool Hud::handleEvent(const Mf::Event& event)
                        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;
                        }
index bc8a313100e79d30315640e2eaac6ec78aab077f..0bc0a4676b12aad08a58053cb99fda89e1147418 100644 (file)
  */
 
 #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"
 
@@ -58,16 +58,16 @@ private:
 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)
        {
index 91a8d080ba04d14df9114e8a112f3ba179e4a63c..7b31ae4f83283ccbf65a91fe32e9e999f65ea626 100644 (file)
@@ -10,6 +10,7 @@
 **************************************************************************/
 
 #include <cstdlib>             // atexit, getenv
+#include <functional>
 #include <iostream>
 #include <string>
 #include <unistd.h>            // access
@@ -19,7 +20,6 @@
 #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
@@ -73,25 +66,25 @@ 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;
 
@@ -100,8 +93,8 @@ bool Main::handleEvent(const Mf::Event& event)
                        break;
 
                case SDL_QUIT:
-                       Mf::core.clear();
-                       break;
+                       stop();
+                       return true;
        }
 
        return false;
@@ -137,7 +130,7 @@ std::string Main::getConfigPath()
 
        std::string path = Mf::Resource::getPath("yoinkrc");
 
-#if !defined(_WIN32) && !defined(__WIN32__)
+#if !defined(_WIN32)
        path += ":/etc/yoinkrc";
 #endif
        path += ":$HOME/.yoinkrc";
@@ -178,14 +171,6 @@ void Main::setupGL()
        //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()
 {
@@ -283,6 +268,7 @@ void goodbye()
        std::cout << std::endl << "Goodbye..." << std::endl << std::endl;
 }
 
+
 int main(int argc, char* argv[])
 {
        if (argc > 1)
@@ -305,33 +291,32 @@ int main(int argc, char* argv[])
 
        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;
 }
 
index 91a4b4c3d2701922db35fde2f1e01fa29d81e70e..a5ce29336493c95c0115152ef2b0119e3b7116ab 100644 (file)
 #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;
@@ -59,9 +57,8 @@ private:
         * 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;
 };
 
 
index 4e8f65d0b26b0f47d252050332843f7e227426cd..c87c4126ffdff48ae4c4b8085882c5e360c93028 100644 (file)
@@ -13,12 +13,13 @@ noinst_LIBRARIES = libmoof.a
 
 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 \
@@ -33,7 +34,6 @@ libmoof_a_SOURCES = \
                                        Moof/Image.cc \
                                        Moof/Image.hh \
                                        Moof/Interpolator.hh \
-                                       Moof/Layer.hh \
                                        Moof/Line.hh \
                                        Moof/Log.cc \
                                        Moof/Log.hh \
@@ -62,9 +62,10 @@ libmoof_a_SOURCES = \
                                        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)
@@ -89,6 +90,7 @@ yoink_SOURCES = \
                                ErrorHandler.hh \
                                GameLayer.cc \
                                GameLayer.hh \
+                               GameState.hh \
                                Heroine.cc \
                                Heroine.hh \
                                Hud.cc \
@@ -123,5 +125,5 @@ run: all
        $(YOINK_ENVIRONMENT) ./yoink $(YOINK_OPTS)
 
 debug: all
-       $(YOINK_ENVIRONMENT) gdb ./yoink
+       $(YOINK_ENVIRONMENT) ddd ./yoink
 
diff --git a/src/Moof/Backend.cc b/src/Moof/Backend.cc
new file mode 100644 (file)
index 0000000..95f4dc3
--- /dev/null
@@ -0,0 +1,94 @@
+
+/*]  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
+
diff --git a/src/Moof/Backend.hh b/src/Moof/Backend.hh
new file mode 100644 (file)
index 0000000..8209b06
--- /dev/null
@@ -0,0 +1,46 @@
+
+/*]  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_
+
diff --git a/src/Moof/Contact.hh b/src/Moof/Contact.hh
new file mode 100644 (file)
index 0000000..82e049d
--- /dev/null
@@ -0,0 +1,40 @@
+
+/*]  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_
+
diff --git a/src/Moof/Core.cc b/src/Moof/Core.cc
deleted file mode 100644 (file)
index b659f98..0000000
+++ /dev/null
@@ -1,451 +0,0 @@
-
-/*]  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
-
diff --git a/src/Moof/Core.hh b/src/Moof/Core.hh
deleted file mode 100644 (file)
index eaa98b4..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-
-/*]  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_
-
index 52f28f88327e2591378819308cb3a832c44e1512..83fecae279fac9b336928531fa0b4c67a885d326 100644 (file)
@@ -21,46 +21,45 @@ class Dispatch::Impl
 {
 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)
                                {
@@ -70,16 +69,15 @@ public:
                        }
                }
 
-               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);
@@ -87,45 +85,49 @@ public:
        }
 
 
+       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);
 }
 
 
@@ -136,5 +138,12 @@ void Dispatch::dispatch(const std::string& event, const Message* message)
 }
 
 
+Dispatch& Dispatch::global()
+{
+       static Dispatch dispatch;
+       return dispatch;
+}
+
+
 } // namespace Mf
 
index fd328fe37d733a49dba95f84176a68f279923e99..4911c12367ccdd8a28ba11929c8e5a4b0eeab9e3 100644 (file)
@@ -17,6 +17,7 @@
 #include <boost/bind.hpp>
 #include <boost/function.hpp>
 #include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
 
 
 namespace Mf {
@@ -31,7 +32,7 @@ class Dispatch
        class Impl;
        boost::shared_ptr<Impl> mImpl;
 
-       void removeHandler(unsigned id);
+       void removeTarget(unsigned id);
 
 public:
 
@@ -46,32 +47,35 @@ 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;
                }
 
@@ -79,12 +83,13 @@ public:
                {
                        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;
@@ -92,11 +97,13 @@ public:
 
        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();
 };
 
 
index c5566d54e33f8bc0812a4328a5ad939d28ee78fe..54e9972d6264be65021286e3e2068340794527f7 100644 (file)
@@ -17,7 +17,7 @@
 #include <png.h>
 #include <SDL/SDL.h>
 
-#include "Core.hh"
+#include "Backend.hh"
 #include "Error.hh"
 #include "Image.hh"
 #include "Log.hh"
diff --git a/src/Moof/Layer.hh b/src/Moof/Layer.hh
deleted file mode 100644 (file)
index 8bbb94b..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-
-/*]  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_
-
index f8a2b66111f34a6de84a480fe461cd118064b77e..679e564fb378964c46c328d2a136c4ac54df917b 100644 (file)
 #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>
 
 
@@ -38,8 +41,131 @@ struct Line : public Drawable, public Shape<D>
                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
@@ -87,8 +213,10 @@ struct Line : public Drawable, public Shape<D>
                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();
@@ -135,6 +263,14 @@ typedef Polygon<2,3>       Triangle2;
 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_
index 8bb6741f80148dfbf5b9d3d8c3d1d11348d91a24..d56d8ea08f7dc217611bf17453574116975d9110 100644 (file)
@@ -18,7 +18,7 @@
 #include "../config.h"
 #endif
 
-#if defined(_WIN32) || defined(__WIN32__)
+#if defined(_WIN32)
 #include <windows.h>
 #elif defined(__APPLE__) && defined(__MACH__)
 #include <Carbon/Carbon.h>
@@ -57,6 +57,17 @@ struct ModalDialog
        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)
@@ -75,7 +86,7 @@ struct ModalDialog
                                break;
                }
 
-#if defined(_WIN32) || defined(__WIN32__)
+#if defined(_WIN32)
 
                int iconType;
                switch (type)
index ca127a9be54a101f6b501ecdc408cc6f9db4edb0..b04acd78f0c9d7e00424577602926fbf39151d3c 100644 (file)
@@ -48,7 +48,7 @@ void Resource::addSearchPaths(const std::vector<std::string>& path)
                        onePath += '/';
                }
 
-#if defined(_WIN32) || defined(__WIN32__)
+#if defined(_WIN32)
                boost::replace_all(onePath, "/", "\\");
 #endif
 
@@ -64,7 +64,7 @@ std::string Resource::getPath(const std::string& name)
 
        std::string path(name);
 
-#if defined(_WIN32) || defined(__WIN32__)
+#if defined(_WIN32)
        boost::replace_all(path, "/", "\\");
 #endif
 
index 94845c2b1380962352d6a86e80b034837efb1ad4..bc503c52a26f8064b86fe7d4529987b29b2ebe6c 100644 (file)
@@ -45,7 +45,7 @@ void Settings::loadFromFiles(const std::vector<std::string>& path)
        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 : "");
@@ -96,8 +96,5 @@ void Settings::save() const
 }
 
 
-Settings settings;     // global instance
-
-
 } // namepsace Mf
 
index f7503dd7b8d1f34806b5ccce86a185ababdb3065..42ef70ce54719d2431e0a9260899d63ecc658209 100644 (file)
@@ -33,10 +33,13 @@ class Settings
 {
 public:
 
-       Settings()
+       Settings(int argc, char* argv[], const std::string& path)
        {
                mScript.importBaseLibrary();
                importLogFunctions(mScript);
+
+               parseArgs(argc, argv);
+               loadFromFiles(path);
        }
 
        ~Settings();
@@ -93,9 +96,6 @@ bool Settings::get(const std::string& key, T& value) const
 }
 
 
-extern Settings settings;
-
-
 } // namepsace Mf
 
 #endif // _MOOF_SETTINGS_HH_
index c059d46bff1b1ec563dc471cebe13f84c3b3da7b..d21e84d464d8f3c4cca0788d76e2c167b8a11ced 100644 (file)
@@ -53,13 +53,17 @@ public:
         * 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_
index d42bfd8a98fa8e643494c7b242f8e659c1893da9..f5285545b17a3faa66ba3f4fdd0a250b1bf50a99 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef _MOOF_SPHERE_HH_
 #define _MOOF_SPHERE_HH_
 
+#include <Moof/Contact.hh>
 #include <Moof/Cullable.hh>
 #include <Moof/Drawable.hh>
 #include <Moof/Frustum.hh>
@@ -28,24 +29,22 @@ namespace Mf {
  * 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)
        {
@@ -59,9 +58,55 @@ struct Sphere : public Cullable, public Drawable, public Shape<D>
                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);
@@ -83,37 +128,6 @@ struct Sphere : public Cullable, public Drawable, public Shape<D>
                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;
-       }
 };
 
 
index 48e6e1b6193909766df411c85757ab6393201a41..7d82e2d093416cf5190475a803de81873405d662 100644 (file)
@@ -121,12 +121,13 @@ public:
                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()
@@ -388,7 +389,7 @@ public:
        GLuint                          mObject;        ///< GL texture handle.
        static GLuint           gObject;        ///< Global GL texture handle.
 
-       Dispatch::Handler       mDispatchHandler;
+       Dispatch::Handle        mNewContextDispatch;
 };
 
 GLuint Texture::Impl::gObject = 0;
index d65d82d20bd17321ac4288f2c651978f955aa017..194caf53f09c2a137c8e2504b3d9756abba7e031 100644 (file)
@@ -9,6 +9,7 @@
 *
 **************************************************************************/
 
+#define _MOOF_TRANSITION_HH_
 #ifndef _MOOF_TRANSITION_HH_
 #define _MOOF_TRANSITION_HH_
 
@@ -49,17 +50,17 @@ public:
        }
 
 
-       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())
                {
@@ -101,7 +102,7 @@ public:
                glPopMatrix();
        }
 
-       void draw(Scalar alpha) const
+       void draw(Core& core, Scalar alpha) const
        {
                Scalar a = mInterp.getState(alpha);
                logInfo << "transition state: " << a << std::endl;
@@ -113,7 +114,7 @@ public:
                        glPushMatrix();
                        glLoadIdentity();
                        glRotate(180.0 * a, 0.0, 1.0, 0.0);
-                       mFrom->draw(alpha);
+                       mFrom->draw(core, alpha);
                        glPopMatrix();
                }
                        //drawFade(a);
@@ -123,21 +124,21 @@ public:
                        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;
        }
index 9f6258652a374c5753d564326617176f88b42692..195f4130765a683ce4dbdf52dba423fa2f01e650 100644 (file)
@@ -9,7 +9,6 @@
 *
 **************************************************************************/
 
-#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();
@@ -56,7 +49,7 @@ void Video::init()
        setCursorGrab(mAttribs.cursorGrab);
        setVideoMode(mAttribs.mode);
 
-       video = this;
+       if (!gCurrentVideo) makeCurrent();
 }
 
 void Video::recreateContext()
@@ -109,11 +102,11 @@ Video::~Video()
 {
        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)
        {
@@ -130,7 +123,7 @@ void Video::setVideoMode(const long mode[3])
 
 #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();
@@ -145,7 +138,7 @@ Video::Attributes Video::getAttributes() const
 
 void Video::resize(int width, int height)
 {
-       long mode[] = {width, height, mAttribs.mode[2]};
+       int mode[] = {width, height, mAttribs.mode[2]};
        setVideoMode(mode);
 }
 
@@ -290,35 +283,28 @@ int Video::getHeight() const
 }
 
 
+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];
@@ -330,7 +316,7 @@ Video::Attributes::Attributes()
        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];
@@ -354,7 +340,7 @@ Video::Attributes::Attributes()
        settings.get("showcursor", cursorVisible);
        settings.get("grab", cursorGrab);
 
-       std::vector<long> dimensions;
+       std::vector<int> dimensions;
        settings.get("videomode", dimensions);
        if (dimensions.size() > 1)
        {
@@ -388,8 +374,37 @@ Video::Attributes::Attributes()
        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
index 9b1a092332203b3e31291109413cb31e6abaa8bf..d20ce4e5ff58c1d2d0af7dcd0611edd6844195ba 100644 (file)
 #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;
@@ -34,48 +36,48 @@ public:
        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);
@@ -107,6 +109,15 @@ public:
        int getWidth() const;
        int getHeight() const;
 
+       static Video* current()
+       {
+               return gCurrentVideo;
+       }
+
+       void makeCurrent() const;
+
+       void setDispatch(Dispatch& dispatch);
+
 private:
 
        void init();
@@ -118,13 +129,13 @@ private:
 
        // 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
diff --git a/src/Moof/View.cc b/src/Moof/View.cc
new file mode 100644 (file)
index 0000000..e2e84b5
--- /dev/null
@@ -0,0 +1,411 @@
+
+/*]  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
+
diff --git a/src/Moof/View.hh b/src/Moof/View.hh
new file mode 100644 (file)
index 0000000..9fae113
--- /dev/null
@@ -0,0 +1,88 @@
+
+/*]  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_
+
index 8b155e7dd96bf991df058a41806fe5d760214c99..bfc788af1a75f46ed0f5adfa19ac963be5420c74 100644 (file)
@@ -156,7 +156,7 @@ struct Scene::Impl : public Mf::Manager<Impl>
        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));
@@ -176,7 +176,7 @@ struct Scene::Impl : public Mf::Manager<Impl>
                                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");
@@ -193,7 +193,7 @@ struct Scene::Impl : public Mf::Manager<Impl>
        }
 
 
-       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 == "")
@@ -202,7 +202,7 @@ struct Scene::Impl : public Mf::Manager<Impl>
                        return Mf::Script::FILE_ERROR;
                }
 
-               importSceneBindings(script);
+               importSceneBindings(settings, script);
                return script.doFile(filePath);
        }
 
@@ -482,10 +482,10 @@ Scene::Scene(const std::string& name) :
        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);
 }
 
 
index 07db30dba32ac449cf3836e57682a5d6d9b33cc3..31a4ecd919f8cba737c8849fea1cbf9d22e5926a 100644 (file)
 class Character;
 
 
+namespace Mf {
+class Settings;
+}
+
 class Scene;
 typedef boost::shared_ptr<Scene> SceneP;
 
@@ -43,7 +47,7 @@ public:
                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;
index d31fe8702bff754e376a9cfd0cdc4d4ca2cd5a00..b865be05eff68ec0230c3c42f2ef7a3e33829865 100644 (file)
@@ -9,52 +9,57 @@
 *
 **************************************************************************/
 
-#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;
        }
index 90041ee5b7a6b6482f793281d106bd33886e7ca1..e2b74d37e2ce2802f2e9fbdfc83b05ad9150bbb9 100644 (file)
 #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:
 
@@ -31,7 +31,7 @@ public:
                return TitleLayerP(new TitleLayer);
        }
 
-       void addedToCore();
+       void didAddToView();
 
        void update(Mf::Scalar t, Mf::Scalar dt);
        void draw(Mf::Scalar alpha) const;
@@ -40,7 +40,7 @@ public:
 private:
 
        Mf::Lerp                mFadeIn;
-       Mf::LayerP              mGameLayer;
+       Mf::ViewP               mGameLayer;
 };
 
 
This page took 0.117943 seconds and 4 git commands to generate.