-The man page (doc/yoink.6) might have a general list of broad, long-term goals.
+The man page (doc/yoink.6) might have a broad list of long-term goals.
Otherwise, the code itself is documented with stuff that needs doing:
-FIXME marks a bug and/or broken, incomplete code.
+FIXME marks a known bug and/or broken, incomplete code.
TODO marks code that could use some refactoring or possible new features.
* frame map which is probably loaded within an animation file.
*/
- Frame(Mf::Script& script, Mf::Script::Value table) :
+ Frame(Mf::Script& script, Mf::Script::Slot table) :
mIndex(0),
mDuration(1.0)
{
* constructor which loads each individual frame.
*/
- Sequence(Mf::Script& script, Mf::Script::Value table) :
+ Sequence(Mf::Script& script, Mf::Script::Slot table) :
mDelay(0.0),
mLoop(true)
{
// TODO - sequence class/type not yet implemented
table.pushField("frames");
- Mf::Script::Value frameTable = script.getTop();
+ Mf::Script::Slot frameTable = script.getTop();
if (frameTable.isTable())
{
- Mf::Script::Value top = script[-1];
+ Mf::Script::Slot top = script[-1];
int index = 1;
for (;;)
{
std::string str;
script[-1].get(str);
- Mf::logScript("%s", str.c_str());
+ Mf::logWarning(str);
}
}
int defineSequence(Mf::Script& script)
{
- Mf::Script::Value name = script[1].requireString();
- Mf::Script::Value table = script[2].requireTable();
+ Mf::Script::Slot name = script[1].requireString();
+ Mf::Script::Slot table = script[2].requireTable();
std::string nameStr;
name.get(nameStr);
throw Mf::Exception(Mf::ErrorCode::RESOURCE_NOT_FOUND, "loader");
}
- Mf::Script::Status status = mState.script.doFile(loaderPath);
+ Mf::Script::Result status = mState.script.doFile(loaderPath);
if (status != Mf::Script::SUCCESS)
{
std::string str;
mState.script[-1].get(str);
- Mf::logScript("%s", str.c_str());
throw Mf::Exception(Mf::ErrorCode::SCRIPT_ERROR, str);
}
mState.script.getTop().get(mState.sceneList);
if (mState.sceneList.size() == 0)
{
- Mf::logScript("no variable `scenes' within loader");
- throw Mf::Exception(Mf::ErrorCode::SCRIPT_ERROR, "no scenes to load");
+ throw Mf::Exception(Mf::ErrorCode::SCRIPT_ERROR,
+ "no variable `scenes' within loader");
}
}
mState.scene = Scene::alloc(mState.sceneList[0]);
mState.sceneList.erase(mState.sceneList.begin());
- Mf::Script::Status status = mState.scene->load(mState.script);
+ Mf::Script::Result status = mState.scene->load(mState.script);
if (status != Mf::Script::SUCCESS)
{
std::string str;
mState.script[-1].get(str);
- Mf::logScript("%s", str.c_str());
throw Mf::Exception(Mf::ErrorCode::SCRIPT_ERROR, str);
}
}
Mf::Settings::getInstance().get("nomusic", isMute);
if (!isMute) mMusic.play();
+ //mMusic.setPosition(Mf::Vector3(10.0, 5.0, 0.0));
+
loadSceneLoader();
advanceScene(); // load the first scene
engine.push(Hud::alloc(mState));
mRay.direction.set(1.0, 0.0);
- mRay3.direction.set(1.0, 0.0, 0.0);
mLine.a.set(20, 10);
mLine.b.set(19, 14);
- mPlane.normal.set(-1.0, 0.0, 0.0);
- mPlane.d = 0.0;
-
mSphere.point.set(22, 5);
mSphere.radius = 2;
+
+ mRayTimer.init(boost::bind(&GameLayer::rayTimer, this), 1.0, Mf::Timer::REPEAT);
}
-mState.heroine->getState().position[1], -9));
//mState.camera.lookAt(Mf::promote(mState.heroine->getState().position));
- //Mf::Vector3 heroinePosition = Mf::promote(mState.heroine->getState().position);
- //Mf::Sound::setListenerPosition(heroinePosition);
-
mRay.point = mState.heroine->getState().position;
- mRay3.point = Mf::promote(mRay.point);
- mRay3.direction = Mf::promote(mRay.direction);
+}
+
+void GameLayer::rayTimer()
+{
Mf::Ray<2>::Intersection meh;
- Mf::Ray<3>::Intersection meh3;
+ std::list<Mf::Ray<2>::Intersection> hits;
+ Mf::Vector2 point;
- Mf::Scalar d = mLine.intersectRay(mRay, meh);
- if (d > 0.0)
+ bool bam = mLine.intersectRay(mRay, meh);
+ if (bam)
{
- Mf::logDebug("line: d = %f", d);
- Mf::logDebug(" P = <%f,%f>", meh.point[0], meh.point[1]);
- Mf::logDebug(" n = <%f,%f>", meh.normal[0], meh.normal[1]);
+ meh.normal.normalize();
+ hits.push_back(meh);
}
- //d = mPlane.intersectRay(mRay3, meh3);
- //if (d > 0.0)
- //{
- //Mf::logDebug("plane: d = %f", d);
- //Mf::logDebug(" P = <%f,%f>", meh3.point[0], meh3.point[1]);
- //Mf::logDebug(" n = <%f,%f>", meh3.normal[0], meh3.normal[1]);
- //}
- d = mSphere.intersectRay(mRay, meh);
- if (d > 0.0)
+
+ bam = mSphere.intersectRay(mRay, meh);
+ if (bam)
{
- Mf::logDebug("sphere: d = %f", d);
- Mf::logDebug(" P = <%f,%f>", meh.point[0], meh.point[1]);
- Mf::logDebug(" n = <%f,%f>", meh.normal[0], meh.normal[1]);
+ meh.normal.normalize();
+ hits.push_back(meh);
}
- std::list<Mf::Ray<2>::Intersection> hits;
if (mState.scene->castRay(mRay, hits))
{
- Mf::logDebug("scene: d = %f", d);
- Mf::logDebug(" P = <%f,%f>", hits.front().point[0], hits.front().point[1]);
- Mf::logDebug(" n = <%f,%f>", hits.front().normal[0], hits.front().normal[1]);
+ hits.front().normal.normalize();
+ mRay.solve(point, hits.front().distance);
+ Mf::logDebug << "scene: d = " << hits.front().distance << std::endl;
+ Mf::logDebug << " P = " << point << std::endl;
+ Mf::logDebug << " n = " << hits.front().normal << std::endl;
}
}
}
else if (event.key.keysym.sym == SDLK_PAGEUP)
{
- mRay.direction = cml::rotate_vector_2D(mRay.direction, cml::rad(10.0));
+ mRay.direction = cml::rotate_vector_2D(mRay.direction,
+ cml::rad(10.0));
return true;
}
else if (event.key.keysym.sym == SDLK_PAGEDOWN)
{
- mRay.direction = cml::rotate_vector_2D(mRay.direction, cml::rad(-10.0));
+ mRay.direction = cml::rotate_vector_2D(mRay.direction,
+ cml::rad(-10.0));
return true;
}
return mState.heroine->handleEvent(event);
#include <Moof/Plane.hh>
#include <Moof/Ray.hh>
#include <Moof/Sphere.hh>
+#include <Moof/Timer.hh>
#include "Character.hh"
#include "Heroine.hh"
Mf::Sound mPunchSound;
Mf::Ray<2> mRay;
- Mf::Ray<3> mRay3;
Mf::Line<2> mLine;
- Mf::Plane mPlane;
Mf::Sphere<2> mSphere;
+
+ Mf::Timer mRayTimer;
+ void rayTimer();
};
*******************************************************************************/
+#include <Moof/Sound.hh>
+
#include "Heroine.hh"
#include "Log.hh"
Character("Heroine") {}
+void Heroine::update(Mf::Scalar t, Mf::Scalar dt)
+{
+ Character::update(t, dt);
+
+ Mf::Vector3 at(0.0, 0.0, 0.0);
+ const Mf::Vector3 up(0.0, 1.0, 0.0);
+
+ if (mState.velocity[0] < 0.0) at[0] = -1.0;
+ else at[0] = 1.0;
+
+ Mf::Sound::setListenerPosition(Mf::promote(mState.position));
+ Mf::Sound::setListenerVelocity(Mf::promote(mState.velocity));
+ Mf::Sound::setListenerOrientation(at, up);
+}
+
+
bool Heroine::handleEvent(const Mf::Event& event)
{
Mf::Scalar force = 40.0;
return HeroineP(new Heroine);
}
+ void update(Mf::Scalar t, Mf::Scalar dt);
bool handleEvent(const Mf::Event& event);
};
#if YOINK_LOGLEVEL >= 4
- Mf::setLogLevel(Mf::LOG_DEBUG);
+ Mf::Log::setLevel(Mf::Log::DEBUGG);
#elif YOINK_LOGLEVEL >= 3
- Mf::setLogLevel(Mf::LOG_INFO);
+ Mf::Log::setLevel(Mf::Log::INFO);
#elif YOINK_LOGLEVEL >= 2
- Mf::setLogLevel(Mf::LOG_SCRIPT);
+ Mf::Log::setLevel(Mf::Log::SCRIPT);
#elif YOINK_LOGLEVEL >= 1
- Mf::setLogLevel(Mf::LOG_ERROR);
+ Mf::Log::setLevel(Mf::Log::ERROR);
#elif YOINK_LOGLEVEL
- Mf::setLogLevel(Mf::LOG_NONE);
+ Mf::Log::setLevel(Mf::Log::NONE);
#endif
{
char vdName[128];
SDL_VideoDriverName(vdName, sizeof(vdName));
- logDebug("initialized SDL; using video driver `%s'", vdName);
+ logDebug << "initialized SDL; using video driver `"
+ << vdName << "'" << std::endl;
}
if (FE_Init() != 0)
if (!mAlDevice || !mAlContext)
{
const char* error = alcGetString(mAlDevice,alcGetError(mAlDevice));
- logError("error while creating audio context: %s", error);
+ logError << "error while creating audio context: "
+ << error << std::endl;
}
else
{
alcMakeContextCurrent(mAlContext);
- logDebug("opened sound device `%s'",
- alcGetString(mAlDevice, ALC_DEFAULT_DEVICE_SPECIFIER));
+ logDebug << "opened sound device `"
+ << alcGetString(mAlDevice, ALC_DEFAULT_DEVICE_SPECIFIER)
+ << "'" << std::endl;
}
// now load the settings the engine needs
if (mPrintFps)
{
- logInfo("%d fps", mFps);
+ logInfo << mFps << " fps" << std::endl;
}
}
{
ASSERT(layer && "cannot push null layer");
mStack.push_front(layer);
- logDebug("stack: %d [pushed %X]", mStack.size(), layer.get());
+ logDebug << "stack: " << mStack.size()
+ << " [pushed " << layer.get() << "]" << std::endl;
layer->pushed(mInterface);
}
LayerP layer = mStack.front();
mStack.pop_front();
- logDebug("stack: %d [popped %X]", mStack.size(), layer.get());
+ logDebug << "stack: " << mStack.size()
+ << " [popped " << layer.get() << "]" << std::endl;
layer->popped(mInterface);
if (fixIt) mStackIt = --mStack.begin();
for (it = layers.begin(); it != layers.end(); ++it)
{
(*it)->popped(mInterface);
- logDebug("stack: %d [popped %X]", mStack.size(), (*it).get());
+ logDebug << "stack: " << mStack.size()
+ << " [popped " << (*it).get() << "]" << std::endl;
}
if (fixIt) mStackIt = --mStack.begin();
{
if (mMaxFps < mTimestep)
{
- logWarning("capping maximum fps to timestep (%f)", mTimestep);
+ logWarning << "capping maximum fps to timestep ("
+ << mTimestep << ")" << std::endl;
mMaxFps = mTimestep;
}
}
public:
+ virtual ~Interpolator() {}
+
typedef enum
{
STOP = 0,
{
public:
+ virtual ~InterpolatorBase() {}
+
void init(Scalar seconds = 1.0, Mode mode = STOP)
{
Interpolator::init(seconds, mode);
a(point1),
b(point2) {}
- Scalar intersectRay(const Ray<2>& ray,
- Ray<2>::Intersection& intersection) const
+ bool intersectRay(const Ray<2>& ray, Ray<2>::Intersection& hit) const
{
// solve: Cx + r*Dx = Ax + s(Bx - Ax)
// Cy + r*Dy = Ay + s(By - Ay)
ray.direction[1] * (a[0] - b[0]);
// check if the ray and line are parallel
- if (isEqual(denom, SCALAR(0.0)))
+ //if (isEqual(denom, SCALAR(0.0)))
+ if (denom == SCALAR(0.0))
{
Scalar numer = a[0] * (ray.point[1] - b[1]) +
b[0] * (a[1] - ray.point[1]) +
// check if they are collinear
if (isEqual(numer, SCALAR(0.0)))
{
- intersection.point = ray.point;
- intersection.normal.set(0.0, 0.0);
- return SCALAR(0.0);
+ hit.distance = SCALAR(0.0);
+ hit.normal.set(0.0, 0.0);
+ return true;
}
- return SCALAR(-1.0);
+ return false;
}
Scalar s = (ray.direction[0] * (ray.point[1] - a[1]) +
ray.direction[1] * (a[0] - ray.point[0])) / denom;
// check if the ray hits the segment
- if (s < SCALAR(0.0) || s > SCALAR(1.0)) return SCALAR(-1.0);
+ if (s < SCALAR(0.0) || s > SCALAR(1.0)) return false;
- Scalar r = -(a[0] * (ray.point[1] - b[1]) +
- b[0] * (a[1] - ray.point[1]) +
- ray.point[0] * (b[1] - a[1])) / denom;
+ hit.distance = -(a[0] * (ray.point[1] - b[1]) +
+ b[0] * (a[1] - ray.point[1]) +
+ ray.point[0] * (b[1] - a[1])) / denom;
+ if (hit.distance < SCALAR(0.0)) return false;
- // make sure we're dealing with the right side of the ray
- if (r < SCALAR(0.0)) return SCALAR(-1.0);
-
- intersection.point = ray.point + r * ray.direction;
-
- // gotta use the correct normal
- Vector n = cml::perp(a - b);
- if (cml::dot(a - ray.point, n) < 0) intersection.normal = n;
- else intersection.normal = -n;
-
- return r;
+ Vector normal = cml::perp(a - b);
+ if (cml::dot(a - ray.point, normal) < 0) hit.normal = normal;
+ else hit.normal = -normal;
+ return true;
}
void draw(Scalar alpha = 0.0) const
*******************************************************************************/
-#include <cstdarg>
-#include <cstdio> // snprintf
-#include <cstring> // strcpy
+#include <fstream>
#include "Log.hh"
#include "Script.hh"
namespace Mf {
-static LogLevel logLevel_ = LOG_WARNING;
-
-inline void printLog_(int logLevel, const char* fmt, va_list args)
-{
- if (logLevel_ < logLevel) return;
-
- switch (logLevel)
- {
- case LOG_ERROR:
- fprintf(stderr, " error: ");
- break;
- case LOG_WARNING:
- fprintf(stderr, "warning: ");
- break;
- case LOG_SCRIPT:
- fprintf(stderr, " script: ");
- break;
- case LOG_INFO:
- fprintf(stderr, " info: ");
- break;
- case LOG_DEBUG:
- fprintf(stderr, " debug: ");
- break;
- }
-
- vfprintf(stderr, fmt, args);
- fprintf(stderr, "\n");
-}
+Log::Level Log::gLevel = Log::WARNING;
-LogLevel setLogLevel(LogLevel level)
+void Log::setLevel(Level level)
{
- if (level != 0)
- logLevel_ = level;
-
- return logLevel_;
+ if (level != 0) gLevel = level;
}
-
-void logError(const char* fmt, ...)
+Log::Level Log::getLevel()
{
- va_list args;
- va_start(args, fmt);
-
- printLog_(LOG_ERROR, fmt, args);
-
- va_end(args);
+ return gLevel;
}
-void logWarning(const char* fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- printLog_(LOG_WARNING, fmt, args);
+static std::ofstream nullLog_;
- va_end(args);
-}
+std::ostream& log(std::clog);
+std::ostream& nullLog(nullLog_);
-void logInfo(const char* fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
-
- printLog_(LOG_INFO, fmt, args);
-
- va_end(args);
-}
-
-void logDebug(const char* fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
+Log logError(Log::ERRORR, " error: ");
+Log logWarning(Log::WARNING, "warning: ");
+Log logInfo(Log::INFO, " info: ");
+Log logDebug(Log::DEBUGG, " debug: ");
- printLog_(LOG_DEBUG, fmt, args);
- va_end(args);
-}
-
-void logScript(const char* fmt, ...)
+static int logScript_(Script& script)
{
- va_list args;
- va_start(args, fmt);
-
- printLog_(LOG_SCRIPT, fmt, args);
+ static Log logScript(Log::SCRIPT, " script: ");
- va_end(args);
-}
-
-int logScript(Script& script)
-{
- Script::Value param = script[1];
+ Script::Slot param = script[1];
while (!param.isNone())
{
- if (param.isString())
- {
- std::string str;
- param.get(str);
- logScript("%s", str.c_str());
- }
- else if (param.isBoolean())
- {
- if (param) logScript("true");
- else logScript("false");
-
- }
- else if (param.isNil())
- {
- logScript("nil");
- }
- else
- {
- logScript("%s (%X)", param.getTypeName().c_str(),
- param.getIdentifier());
- }
-
- param.index++;
+ logScript(param);
+ ++param.index;
}
return 0;
void importLogPrintFunction(Script& script)
{
- script.importFunction("print", (int (*)(Script&))logScript);
+ script.importFunction("print", logScript_);
}
*/
#include <cstdlib> // exit
+#include <iostream>
/**
#if NDEBUG
#define ASSERT(X)
#else
-#define ASSERT(X) if (!(X)) Mf::logError("false assertion at %s:%d, " #X, \
- __FILE__, __LINE__), exit(1)
+#define ASSERT(X) if (!(X)) Mf::logError << \
+ "false assertion at " << __FILE__ << ":" << __LINE__ << ", " << #X, exit(1)
#endif
namespace Mf {
-/**
- * Possible values used for setting the log level using LogLevel(). Log
- * messages of lesser importance than the level specified are ignored.
- * @see LogLevel()
- */
-
-enum LogLevel
+class Log
{
- LOG_NONE = -1, ///< Disable all logging.
- LOG_ERROR = 1, ///< Log only errors.
- LOG_WARNING = 2, ///< Log warnings and errors.
- LOG_SCRIPT = 3, ///< Log messages from Lua, too.
- LOG_INFO = 4, ///< Log info, warnings, errors.
- LOG_DEBUG = 5, ///< Log all messages.
-};
+public:
+ enum Level
+ {
+ NONE = -1, ///< Disable all logging.
+ ERRORR = 1, ///< Log only errors.
+ WARNING = 2, ///< Log warnings and errors.
+ SCRIPT = 3, ///< Log messages from Lua, too.
+ INFO = 4, ///< Log info, warnings, errors.
+ DEBUGG = 5, ///< Log all messages.
+ };
-/**
- * Set and/or get the level of logs which will be logged. If not called,
- * defaults to WARNING
- * @param level LOG_LEVEL_* constant or 0 for no change.
- * @return The currently set log level.
- */
+ static void setLevel(Level level);
+ static Level getLevel();
-LogLevel setLogLevel(LogLevel level);
+ Log(Level level, const char* type) :
+ mLevel(level),
+ mType(type) /* only pass literal strings */ {}
-/**
- * Log an error.
- * @param fmt Log format string.
- * @param ... Extra format arguments.
- */
-void logError(const char* fmt, ...);
+ template <typename T>
+ void operator () (const T& item)
+ {
+ *this << item << std::endl;
+ }
-/**
- * Log a warning.
- * @param fmt Log format string.
- * @param ... Extra format arguments.
- */
+private:
-void logWarning(const char* fmt, ...);
+ template <typename T> friend std::ostream& operator << (Log&, const T&);
-/**
- * Log a message.
- * @param fmt Log format string.
- * @param ... Extra format arguments.
- */
+ static Level gLevel;
-void logInfo(const char* fmt, ...);
+ Level mLevel;
+ const char* mType;
+};
-/**
- * Log a debug message.
- * @param fmt Log format string.
- * @param ... Extra format arguments.
- */
-void logDebug(const char* fmt, ...);
+extern std::ostream& log;
+extern std::ostream& nullLog;
+
+extern Log logError;
+extern Log logWarning;
+extern Log logInfo;
+extern Log logDebug;
+
+
+template <typename T>
+inline std::ostream& operator << (Log& logObj, const T& item)
+{
+ if (Log::gLevel < logObj.mLevel) return nullLog;
+ return log << logObj.mType << item;
+}
+
-void logScript(const char* fmt, ...);
class Script;
-int logScript(Script& script);
void importLogPrintFunction(Script& script);
switch (type)
{
case WARNING:
- logWarning("%s", text1.c_str());
- logWarning("%s", text2.c_str());
+ logWarning(text1);
+ logWarning(text2);
break;
case CRITICAL:
- logError("%s", text1.c_str());
- logError("%s", text2.c_str());
+ logError(text1);
+ logError(text2);
break;
default:
- logInfo("%s", text1.c_str());
- logInfo("%s", text2.c_str());
+ logInfo(text1);
+ logInfo(text2);
break;
}
void printSize()
{
- logDebug("size of node %d", objects.size());
+ logDebug << "size of node " << objects.size() << std::endl;
}
void getAll(std::list<InsertableP>& insertables) const
void print(NodeP node)
{
logInfo("-----");
- logInfo("depth to node: %d", mTree.depth(node));
- logInfo("size of node: %d", mTree.size(node));
+ logInfo << "depth to node: " << mTree.depth(node) << std::endl;
+ logInfo << "size of node: " << mTree.size(node) << std::endl;
}
static Ptr alloc(const Node& rootNode)
d(scalar) {}
- Scalar intersectRay(const Ray<3>& ray, Ray<3>::Intersection& intersection)
+ bool intersectRay(const Ray<3>& ray, Ray<3>::Intersection& hit)
{
// solve: [(ray.point + t*ray.direction) dot normal] + d = 0
- Scalar denominator = cml::dot(ray.direction, normal);
+ Scalar denom = cml::dot(ray.direction, normal);
// check for parallel condition
- if (denominator == SCALAR(0.0))
+ if (denom == SCALAR(0.0))
{
if (isEqual(cml::dot(ray.point, normal), -d))
{
// the ray lies on the plane
- intersection.point = ray.point;
- intersection.normal.set(0.0, 0.0, 0.0);
- //intersection.normal = normal;
- return SCALAR(0.0);
+ hit.distance = SCALAR(0.0);
+ hit.normal.set(0.0, 0.0, 0.0);
+ return true;
}
// no solution
- return SCALAR(-1.0);
+ return false;
}
- Scalar distance = cml::dot(ray.point, normal) + d;
- Scalar t = -distance / denominator;
- if (t > SCALAR(0.0))
- {
- ray.solve(intersection.point, t);
-
- if (distance >= 0.0) intersection.normal = normal;
- else intersection.normal = -normal;
- }
+ Scalar numer = cml::dot(ray.point, normal) + d;
+ hit.distance = -numer / denom;
+ if (hit.distance < SCALAR(0.0)) return false;
- return t;
+ if (numer >= 0.0) hit.normal = normal;
+ else hit.normal = -normal;
+ return true;
}
struct Intersection
{
- Vector point; // nearest point of intersection
+ Scalar distance; // distance from the origin to the nearest point
Vector normal; // surface normal at intersection point
+
+ bool operator < (const Intersection& rhs)
+ {
+ return distance < rhs.distance;
+ }
};
void solve(Vector& p, Scalar t) const
{
direction.normalize();
}
-
};
if (access(fullPath.c_str(), R_OK) == 0) return fullPath;
}
- logWarning("cannot find resource %s", name.c_str());
+ logWarning << "cannot find resource " << name << std::endl;
// empty string
return std::string();
* more consistent API.
*/
+#include <iostream>
#include <list>
#include <map>
#include <string>
THREAD = LUA_TTHREAD
};
- enum Status
+ enum Result
{
SUCCESS = 0,
YIELD = LUA_YIELD,
/**
* This is the most prominent abstraction on top of the standard Lua API.
- * A Value object represents a value on the stack. More specifically, it
+ * A Slot object represents a value on the stack. More specifically, it
* represents a position on the stack. The distinction is only important
- * when values are moved around on the stack or if the Value represents a
+ * when objects are moved around on the stack or if the Slot represents a
* negative index on the stack (the value of which will change as things are
* pushed onto and popped from the stack).
*/
- struct Value
+ struct Slot
{
/**
* You have direct access to the index of the value on the stack being
/**
- * A default-constructed Value is invalid until a valid Value is
- * assigned to it. The only method that should be called on such a
- * Value is isValid(), otherwise chaos may ensue. In this case, the
- * Value will be invalid even if index is manually changed to a valid
- * index. You have to index the script itself to get a valid Value.
+ * A default-constructed Slot is invalid until a valid Slot is assigned
+ * to it. The only method that should be called on such a Slot is
+ * isValid(), otherwise chaos may ensue. In this case, the Slot will be
+ * invalid even if index is manually changed to a valid index. You have
+ * to index the script itself to get a valid Slot.
*/
- Value(lua_State* s = 0, int i = 0) :
+ Slot(lua_State* s = 0, int i = 0) :
index(i),
mState(s) {}
* copied into the new value object.
*/
- Value(const Value& copy) :
+ Slot(const Slot& copy) :
index(copy.getRealIndex()),
mState(copy.mState) {}
}
- Value& requireBoolean()
+ Slot& requireBoolean()
{
if (!isBoolean()) luaL_typerror(mState, index, "boolean");
return *this;
}
- Value& requireNumber()
+ Slot& requireNumber()
{
if (!isNumber()) luaL_typerror(mState, index, "number");
return *this;
}
- Value& requireString()
+ Slot& requireString()
{
if (!isString()) luaL_typerror(mState, index, "string");
return *this;
}
- Value& requireTable()
+ Slot& requireTable()
{
if (!isTable()) luaL_typerror(mState, index, "table");
return *this;
}
- Value& requireFunction()
+ Slot& requireFunction()
{
if (!isFunction()) luaL_typerror(mState, index, "function");
return *this;
}
- Value& requireData()
+ Slot& requireData()
{
if (!isData()) luaL_typerror(mState, index, "data");
return *this;
}
- Value& requireNil()
+ Slot& requireNil()
{
if (!isNil()) luaL_typerror(mState, index, "nil");
return *this;
}
- Value& requireThread()
+ Slot& requireThread()
{
if (!isThread()) luaL_typerror(mState, index, "thread");
return *this;
}
- bool operator == (const Value& rhs) const
+ bool operator == (const Slot& rhs) const
{
return (bool)lua_equal(mState, index, rhs.index);
}
- bool operator != (const Value& rhs) const
+ bool operator != (const Slot& rhs) const
{
return !(*this == rhs);
}
- bool operator < (const Value& rhs) const
+ bool operator < (const Slot& rhs) const
{
return (bool)lua_lessthan(mState, index, rhs.index);
}
- bool operator <= (const Value& rhs) const
+ bool operator <= (const Slot& rhs) const
{
return *this < rhs || *this == rhs;
}
- bool operator > (const Value& rhs) const
+ bool operator > (const Slot& rhs) const
{
return !(*this <= rhs);
}
- bool operator >= (const Value& rhs) const
+ bool operator >= (const Slot& rhs) const
{
return !(*this < rhs);
}
return (bool)lua_toboolean(mState, index);
}
- Value& operator = (const Value& rhs)
+ Slot& operator = (const Slot& rhs)
{
rhs.pushCopy();
replaceWithTop();
array.clear();
- Value value(mState, -1);
+ Slot value(mState, -1);
int realIndex = getRealIndex();
bool done = false;
dictionary.clear();
- Value key(mState, -2);
- Value value(mState, -1);
+ Slot key(mState, -2);
+ Slot value(mState, -1);
int realIndex = getRealIndex();
lua_pushnil(mState);
}
-
/**
* Copy the value and push the copy to the stack.
*/
if (mState) destroy();
mState = luaL_newstate();
lua_pushlightuserdata(mState, this);
- lua_setfield(mState, LUA_REGISTRYINDEX, "_script_obj");
+ lua_setfield(mState, LUA_REGISTRYINDEX, "Script_hh_Object");
}
}
- Status doString(const std::string& commands)
+ Result doString(const std::string& commands)
{
- return (Status)luaL_dostring(mState, commands.c_str());
+ return (Result)luaL_dostring(mState, commands.c_str());
}
- Status doFile(const std::string& file)
+ Result doFile(const std::string& file)
{
- return (Status)luaL_dofile(mState, file.c_str());
+ return (Result)luaL_dofile(mState, file.c_str());
}
lua_pushthread(mState);
}
- Status resume(int nargs)
+ Result resume(int nargs)
{
- return (Status)lua_resume(mState, nargs);
+ return (Result)lua_resume(mState, nargs);
}
- Status getStatus() const
+ Result getStatus() const
{
- return (Status)lua_status(mState);
+ return (Result)lua_status(mState);
}
int yield(int results)
* Get significant values.
*/
- Value getGlobalTable() const
+ Slot getGlobalTable() const
{
- return Value(mState, GLOBALS);
+ return Slot(mState, GLOBALS);
}
- Value getRegistryTable() const
+ Slot getRegistryTable() const
{
- return Value(mState, REGISTRY);
+ return Slot(mState, REGISTRY);
}
- Value getEnvironmentTable() const
+ Slot getEnvironmentTable() const
{
- return Value(mState, ENVIRONMENT);
+ return Slot(mState, ENVIRONMENT);
}
- Value getTop() const
+ Slot getTop() const
{
- return Value(mState, lua_gettop(mState));
+ return Slot(mState, lua_gettop(mState));
}
/**
/**
- * Concatenates the top-most n values on the stack.
+ * Concatenates the top-most n slots on the stack.
*/
- void concat(int n)
+ void concat(int n = 2)
{
lua_concat(mState, n);
}
lua_xmove(thread.mState, mState, n);
}
- Status pushCode(const std::string& filename)
+ Result pushCode(const std::string& filename)
{
- return (Status)luaL_loadfile(mState, filename.c_str());
+ return (Result)luaL_loadfile(mState, filename.c_str());
}
- Status pushCode(const std::string& name, const char* buffer, size_t size)
+ Result pushCode(const std::string& name, const char* buffer, size_t size)
{
- return (Status)luaL_loadbuffer(mState, buffer, size, name.c_str());
+ return (Result)luaL_loadbuffer(mState, buffer, size, name.c_str());
}
void* pushNewData(size_t size)
* is any number of return values, depending on the callee).
*/
- Status call(int nargs, int nresults = LUA_MULTRET)
+ Result call(int nargs, int nresults = LUA_MULTRET)
{
- return (Status)lua_pcall(mState, nargs, nresults, 0);
+ return (Result)lua_pcall(mState, nargs, nresults, 0);
}
/**
- * Index into the stack to get a Value.
+ * Index into the stack to get a Slot.
*/
- Value operator [] (int index) const
+ Slot operator [] (int index) const
{
- return Value(mState, index);
+ return Slot(mState, index);
}
* Getting and setting fields of a table.
*/
- void get(const std::string& field, int index = GLOBALS) const
+ void pushField(const std::string& field, int index = GLOBALS) const
{
lua_getfield(mState, index, field.c_str());
}
const Function* function = (const Function*)lua_touserdata(state,
lua_upvalueindex(1));
- lua_getfield(state, LUA_REGISTRYINDEX, "_script_obj");
+ lua_getfield(state, LUA_REGISTRYINDEX, "Script_hh_Object");
Script* script = (Script*)lua_touserdata(state, -1);
lua_pop(state, 1);
};
+inline std::ostream& operator << (std::ostream& stream,
+ const Script::Slot& slot)
+{
+ if (slot.isString())
+ {
+ std::string str;
+ slot.get(str);
+ stream << str;
+ }
+ else if (slot.isBoolean())
+ {
+ if (slot) stream << "true";
+ else stream << "false";
+ }
+ else if (slot.isNil())
+ {
+ stream << "nil";
+ }
+ else
+ {
+ stream << slot.getTypeName()
+ << " (" << slot.getIdentifier() << ")" << std::endl;
+ }
+
+ return stream;
+}
+
+
} // namespace Mf
#endif // _MOOF_SCRIPT_HH_
namespace Mf {
+Settings::~Settings()
+{
+ save();
+}
+
Settings& Settings::getInstance()
{
static Settings settings;
if (home)
{
boost::replace_all(path, "$HOME", home);
+
+ //Mf::logDebug("Copying global settings...");
+ //mUserFile = path;
+ //mGlobals.pushCopy();
+ //mScript.set("globals", Script::REGISTRY);
}
if (mScript.doFile(path) != Script::SUCCESS)
{
std::string str;
mScript[-1].get(str);
- logScript("%s", str.c_str());
+ logInfo(str);
mScript.clear();
}
}
}
+void Settings::saveAs(const std::string& filePath)
+{
+ mUserFile = filePath;
+ save();
+}
+
+void Settings::save() const
+{
+}
+
+
} // namepsace Mf
/** vim: set ts=4 sw=4 tw=80: *************************************************/
importLogPrintFunction(mScript);
}
+ ~Settings();
+
// get global instance
static Settings& getInstance();
void clear(); // remove all settings
+ void saveAs(const std::string& filePath);
+ void save() const;
+
template <typename T>
bool get(const std::string& key, T& value);
private:
Script mScript;
- Script::Value mGlobals, mTop;
+ Script::Slot mGlobals, mTop;
+
+ std::string mUserFile;
};
public:
virtual ~Shape() {}
+
/**
* Checks if this shape is intersected by a given ray. If so, returns the
* distance from the start of the ray to the shape and information about the
* intersection via the 2nd parameter. A negative value is returned if
* there is no intersection.
*/
- virtual Scalar intersectRay(const Ray<D>& ray,
- typename Ray<D>::Intersection& intersection)
+ virtual bool intersectRay(const Ray<D>& ray,
+ typename Ray<D>::Intersection& hit)
{
return SCALAR(-1.0);
}
if (result < 0)
{
- logWarning("error while loading sound %s",
- getName().c_str());
+ logWarning << "error while loading sound "
+ << getName() << std::endl;
throw Exception(ErrorCode::UNKNOWN_AUDIO_FORMAT, getName());
}
}
if (size == 0)
{
- logWarning("decoded no bytes from %s", getName().c_str());
+ logWarning << "decoded no bytes from "
+ << getName() << std::endl;
return;
}
// a ray inside the sphere will not intersect on its way out
- Scalar intersectRay(const Ray<D>& ray,
- typename Ray<D>::Intersection& intersection)
+ bool intersectRay(const Ray<D>& ray, typename Ray<D>::Intersection& hit)
{
Vector b = point - ray.point;
Scalar z = cml::dot(b, ray.direction);
// check if the ball is behind the ray
- if (z < SCALAR(0.0)) return SCALAR(-1.0);
+ if (z < SCALAR(0.0)) return false;
Scalar d2 = cml::dot(b, b) - z*z;
Scalar r2 = radius * radius;
// check for an intersection
- if (d2 > r2) return SCALAR(-1.0);
+ if (d2 > r2) return false;
- Scalar t = z - std::sqrt(r2 - d2);
- ray.solve(intersection.point, t);
- intersection.normal = intersection.point - point;
+ hit.distance = z - std::sqrt(r2 - d2);
+ if (hit.distance < SCALAR(0.0)) return false;
- return t;
+ Vector surfacePoint;
+ ray.solve(surfacePoint, hit.distance);
+ hit.normal = surfacePoint - point;
+ return true;
}
if (!surface)
{
- logWarning("texture not found: %s", getName().c_str());
+ logWarning << "texture not found: " << getName() << std::endl;
throw Exception(ErrorCode::FILE_NOT_FOUND, getName());
}
void draw(Engine& engine, Scalar alpha) const
{
Scalar a = mInterp.getState(alpha);
- logDebug("transition state: %f", a);
+ logDebug << "transition state: " << a << std::endl;
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
if (!mTilemap.getTileCoords(tileIndex, mTexCoords))
{
- Mf::logWarning("no index %d in texture %s", tileIndex,
- texture.c_str());
+ Mf::logWarning << "no index " << tileIndex <<
+ " in texture " << texture << std::endl;
mTexCoords[0] = mTexCoords[1] =
mTexCoords[3] = mTexCoords[6] = 0.0;
}
- Mf::Script::Status load(Mf::Script& script)
+ Mf::Script::Result load(Mf::Script& script)
{
std::string filePath = Scene::getPath(getName());
if (filePath == "")
static int loadBox(Mf::Script& script, Mf::Aabb<3>& aabb)
{
- Mf::Script::Value table[] =
- {
- script[1].requireTable(),
- script[2].requireTable()
- };
+ script[1].requireTable();
+ script[2].requireTable();
+ script.setSize(2);
- for (int i = 0; i <= 1; ++i)
+ for (int i = 1; i <= 2; ++i)
{
for (int j = 1; j <= 3; ++j)
{
- script.push(j);
- table[i].pushField();
+ script[i].pushField(j);
}
}
int translate(Mf::Script& script)
{
- Mf::Script::Value x = script[1].requireNumber();
- Mf::Script::Value y = script[2].requireNumber();
- Mf::Script::Value z = script[3].requireNumber();
-
Mf::Vector3 vec;
- x.get(vec[0]);
- y.get(vec[1]);
- z.get(vec[2]);
+
+ script[1].requireNumber().get(vec[0]);
+ script[2].requireNumber().get(vec[1]);
+ script[3].requireNumber().get(vec[2]);
Mf::Matrix4 translation;
cml::matrix_translation(translation, vec);
int rotate(Mf::Script& script)
{
- Mf::Script::Value axis = script[1].requireNumber();
- Mf::Script::Value angle = script[2].requireNumber();
-
size_t index = 0;
- axis.get(index);
+ script[1].requireNumber().get(index);
Mf::Scalar value;
- angle.get(value);
+ script[2].requireNumber().get(value);
cml::matrix_rotate_about_world_axis(mTransform, index, cml::rad(value));
int drawTilemap(Mf::Script& script)
{
- Mf::Script::Value table = script[1].requireTable();
- Mf::Script::Value top = script[-1];
+ Mf::Script::Slot table = script[1].requireTable();
+ Mf::Script::Slot top = script[-1];
int width = 1;
int height = 1;
// the indices are stored upside-down in the scene file so that they are
// easier to edit as text, so we'll need to load them last row first
- // do first row and first column of vertices
+ // do first row and first column of vertices
for (int w = 0; w <= width; ++w)
{
// scene is built, simply demoting the vector again should
// project the points to the xy-plane
- //Mf::Vector2 tr = Mf::demote(vertices[height+1][width+1]);
- //Mf::Vector2 bl = Mf::demote(vertices[0][0]);
-
Mf::Vector2 bl = Mf::demote(vertices[0][0]);
Mf::Vector2 tr = Mf::demote(vertices[height][width]);
- //Mf::logInfo("pt1: %f, %f", bl[0], bl[1]);
- //Mf::logInfo("pt2: %f, %f", tr[0], tr[1]);
mLines.push_back(Mf::Line<2>(bl, tr));
- Mf::logInfo("new line");
-
- //if (tl == tr)
- //{
- //mLines.push_back(Mf::Line<2>(bl, tl));
- //}
- //else
- //{
- //mLines.push_back(Mf::Line<2>(bl, tl));
- //}
+ Mf::logDebug("new line");
}
return 0;
int drawTile(Mf::Script& script)
{
- Mf::Script::Value param = script[1];
- Mf::Script::Value top = script[-1];
+ Mf::Script::Slot param = script[1];
+ Mf::Script::Slot top = script[-1];
Tilemap::Index index = 0;
int width = 1;
mImpl(Scene::Impl::getInstance(name)) {}
-Mf::Script::Status Scene::load(Mf::Script& script)
+Mf::Script::Result Scene::load(Mf::Script& script)
{
// pass through
return mImpl->load(script);
if (d > 0.0)
{
hits.push_back(hit);
- return true;
+ //return true;
}
}
- return false;
+ hits.sort();
+ return !hits.empty();
+ //return false;
}
bool Scene::checkForCollision(Character& character)
if (collisions > 0)
{
- Mf::logInfo("collisions: %d", collisions);
+ Mf::logInfo << "collisions: " << collisions << std::endl;
}
return false;
return SceneP(new Scene(name));
}
- Mf::Script::Status load(Mf::Script& script);
+ Mf::Script::Result load(Mf::Script& script);
void draw(Mf::Scalar alpha) const;
void drawIfVisible(Mf::Scalar alpha, const Mf::Frustum& frustum) const;
{
std::string str;
script[-1].get(str);
- Mf::logScript("%s", str.c_str());
+ Mf::logWarning(str);
return; // TODO needs a better exit strategy
}
- Mf::logInfo("loading tiles from tilemap %s", filePath.c_str());
+ Mf::logInfo << "loading tiles from tilemap " << filePath << std::endl;
- Mf::Script::Value globals = script.getGlobalTable();
- Mf::Script::Value top = script[-1];
+ Mf::Script::Slot globals = script.getGlobalTable();
+ Mf::Script::Slot top = script[-1];
globals.pushField("tiles_s");
top.get(mTilesS);