#include "Aabb.hh"
#include "Camera.hh"
-#include "Deserializer.hh"
#include "Entity.hh"
#include "Log.hh"
#include "Math.hh"
#include "Scene.hh"
-#include "Serializable.hh"
+#include "Script.hh"
+#include "Settings.hh"
#include "Tilemap.hh"
namespace Mf {
-static void loadBox(Aabb& theBox, SerializableP obj)
+static std::string getPath(const std::string& name)
{
- Serializable::Array numbers;
-
- if (obj->get(numbers) && numbers.size() == 6)
- {
- Serializable::Float num;
-
- if (numbers[0]->getNumber(num)) theBox.min[0] = Scalar(num);
- if (numbers[1]->getNumber(num)) theBox.min[1] = Scalar(num);
- if (numbers[2]->getNumber(num)) theBox.min[2] = Scalar(num);
- if (numbers[3]->getNumber(num)) theBox.max[0] = Scalar(num);
- if (numbers[4]->getNumber(num)) theBox.max[1] = Scalar(num);
- if (numbers[5]->getNumber(num)) theBox.max[2] = Scalar(num);
- }
+ return Resource::getPath("scenes/" + name + ".lua");
}
-static void loadTilemap(SerializableP root, const Matrix4& transform,
- const std::string& texture, OctreeP octree)
+struct Meh
{
- Serializable::Map rootObj;
- Serializable::Map::iterator it;
+ Matrix4 transform;
+ std::string texture;
+
+ OctreeP octree;
- if (!root->get(rootObj))
+ Meh()
{
- logError("invalid tilemap instruction");
- return;
+ octree = Octree::alloc(Aabb());
}
- long width = 1;
- long height = 1;
- std::vector< std::vector<Tilemap::Index> > indices;
-
- if ((it = rootObj.find("width")) != rootObj.end())
+ static int loadBox(Script& script, Aabb& aabb)
{
- (*it).second->get(width);
+ Script::Value table[] = {script[1], script[2]};
+
+ if (!table[0].isTable() || !table[1].isTable())
+ {
+ logWarning("wrong arguments to setPlayfieldBounds; ignoring...");
+ return 0;
+ }
+
+ for (int i = 0; i <= 1; ++i)
+ {
+ for (int j = 1; j <= 3; ++j)
+ {
+ script.push((long)j);
+ table[i].pushField();
+ }
+ }
+
+ script[3].get(aabb.min[0]);
+ script[4].get(aabb.min[1]);
+ script[5].get(aabb.min[2]);
+ script[6].get(aabb.max[0]);
+ script[7].get(aabb.max[1]);
+ script[8].get(aabb.max[2]);
+
+ return 0;
}
- else
+
+ int setPlayfieldBounds(Script& script)
{
- logError("missing required field width for tilemap instruction");
- return;
+ Aabb bounds;
+ return loadBox(script, bounds);
}
- Serializable::Array tiles;
-
- if ((it = rootObj.find("tiles")) != rootObj.end() &&
- (*it).second->get(tiles) &&
- tiles.size() % width == 0)
+ int setMaximumBounds(Script& script)
{
- Serializable::Array::iterator jt;
- int w, h;
+ Aabb bounds;
+ int ret = loadBox(script, bounds);
+ octree = Octree::alloc(bounds);
+ return ret;
+ }
- height = tiles.size() / width;
- indices.resize(height);
+ int resetTransform(Script& script)
+ {
+ transform.identity();
+ return 0;
+ }
- // 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
+ int translate(Script& script)
+ {
+ Script::Value x = script[1];
+ Script::Value y = script[2];
+ Script::Value z = script[3];
- for (h = height - 1, jt = tiles.begin(); jt != tiles.end(); --h)
+ if (!x.isNumber() || !y.isNumber() || !z.isNumber())
{
- std::vector<Tilemap::Index> row;
+ logWarning("wrong arguments to translate; ignoring...");
+ return 0;
+ }
- for (w = 0; w < width && jt != tiles.end(); ++w, ++jt)
- {
- Serializable::Integer index;
+ Vector3 vec;
+ x.get(vec[0]);
+ y.get(vec[1]);
+ z.get(vec[2]);
- if ((*jt)->get(index))
- {
- row.push_back(Tilemap::Index(index));
- }
- }
+ Matrix4 translation;
+ cml::matrix_translation(translation, vec);
+ transform = translation * transform;
- indices[h] = row;
- }
+ return 0;
}
- else
+
+ int scale(Script& script)
{
- logError("invalid tiles in tilemap instruction");
- return;
- }
+ if (script.getSize() == 3)
+ {
+ Vector3 vec;
+ script[1].get(vec[0]);
+ script[2].get(vec[1]);
+ script[3].get(vec[2]);
+
+ Matrix4 scaling;
+ cml::matrix_scale(scaling, vec);
+ transform = scaling * transform;
+ }
+ else if (script.getSize() == 1)
+ {
+ Scalar value = 1.0;
+ script[1].get(value);
- Vector4 vertices[height+1][width+1];
+ Matrix4 scaling;
+ cml::matrix_uniform_scale(scaling,
+ Scalar(value));
+ transform = scaling * transform;
+ }
+ else
+ {
+ logWarning("wrong arguments to scale; ignoring...");
+ }
- Matrix4 transposedTransform = transform;
- transposedTransform.transpose();
+ return 0;
+ }
- for (int h = 0; h <= height; ++h)
+ int rotate(Script& script)
{
- for (int w = 0; w <= width; ++w)
+ Script::Value a = script[1];
+ Script::Value d = script[2];
+
+ if (!a.isString() || !d.isNumber())
{
- vertices[h][w] = Vector4(Scalar(w), Scalar(h), 0.0, 1.0) *
- transposedTransform;
+ logWarning("wrong arguments to rotate; ignoring...");
+ return 0;
}
+
+ std::string axis;
+ a.get(axis);
+
+ size_t index = 0;
+ if (axis == "x") index = 0;
+ else if (axis == "y") index = 1;
+ else if (axis == "z") index = 2;
+
+ Scalar value;
+ d.get(value);
+
+ cml::matrix_rotate_about_world_axis(transform,
+ index, cml::rad(Scalar(value)));
+
+ return 0;
}
- for (int h = 0; h < height; ++h)
+ int setTexture(Script& script)
{
- for (int w = 0; w < width; ++w)
- {
- if (indices[h][w] == Tilemap::NO_TILE) continue;
+ Script::Value t = script[1];
- Vector3 quadVertices[4];
+ if (t.isString()) t.get(texture);
+ else logWarning("wrong arguments to setTexture; ignoring...");
- demoteVector(quadVertices[0], vertices[h][w]);
- demoteVector(quadVertices[1], vertices[h][w+1]);
- demoteVector(quadVertices[2], vertices[h+1][w+1]);
- demoteVector(quadVertices[3], vertices[h+1][w]);
+ return 0;
+ }
- Quad* quad = new Quad(quadVertices, texture, indices[h][w]);
- boost::shared_ptr<Quad> quadPtr(quad);
+ int makeTilemap(Script& script)
+ {
+ Script::Value table = script[1];
+ Script::Value top = script[-1];
- octree->insert(quadPtr);
+ if (!table.isTable())
+ {
+ logWarning("wrong arguments to makeTilemap; ignoring...");
+ return 0;
}
- }
-}
-static void loadBillboard(SerializableP root, const Matrix4& transform,
- const std::string& texture, OctreeP octree)
-{
- Serializable::Map rootObj;
- Serializable::Map::iterator it;
+ long width = 1;
+ long height = 1;
- Tilemap::Index index = 0;
- long width = 1;
- bool blending = false;
- bool fog = false;
+ table.pushField("width");
+ top.get(width);
- if (root->get(rootObj))
- {
- if ((it = rootObj.find("tile")) != rootObj.end())
+ long nTiles = 0;
+
+ table.pushField("tiles");
+ Script::Value tiles = script.getTop();
+ nTiles = tiles.getLength();
+
+ std::vector< std::vector<Tilemap::Index> > indices;
+
+ if (nTiles % width == 0)
{
- Serializable::Integer value;
- if ((*it).second->get(value))
+ int i, w, h;
+
+ height = nTiles / width;
+ indices.resize(height);
+
+ // 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
+
+ i = 1;
+ for (h = height - 1; h >= 0; --h)
{
- index = Tilemap::Index(value);
+ std::vector<Tilemap::Index> row;
+
+ for (w = 0; w < width; ++w, ++i)
+ {
+ script.checkStack(2);
+ script.push(long(i));
+ tiles.pushField();
+
+ long index;
+ top.get(index);
+
+ row.push_back(Tilemap::Index(index));
+ }
+
+ indices[h] = row;
}
}
-
- if ((it = rootObj.find("u_scale")) != rootObj.end())
+ else
{
- (*it).second->get(width);
+ logError("invalid tiles in tilemap instruction");
+ return 0;
}
- if ((it = rootObj.find("blend")) != rootObj.end())
- {
- (*it).second->get(blending);
- }
+ Vector4 vertices[height+1][width+1];
+
+ Matrix4 transposedTransform = transform;
+ transposedTransform.transpose();
- if ((it = rootObj.find("fog")) != rootObj.end())
+ for (int h = 0; h <= height; ++h)
{
- (*it).second->get(fog);
+ for (int w = 0; w <= width; ++w)
+ {
+ vertices[h][w] = Vector4(Scalar(w), Scalar(h), 0.0, 1.0) *
+ transposedTransform;
+ }
}
- }
+ for (int h = 0; h < height; ++h)
+ {
+ for (int w = 0; w < width; ++w)
+ {
+ if (indices[h][w] == Tilemap::NO_TILE) continue;
- Vector4 vertices[2][width+1];
+ Vector3 quadVertices[4];
- Matrix4 transposedTransform = transform;
- transposedTransform.transpose();
+ demoteVector(quadVertices[0], vertices[h][w]);
+ demoteVector(quadVertices[1], vertices[h][w+1]);
+ demoteVector(quadVertices[2], vertices[h+1][w+1]);
+ demoteVector(quadVertices[3], vertices[h+1][w]);
- Scalar xf;
- Scalar increment = 1.0 / Scalar(width);
+ Quad* quad = new Quad(quadVertices, texture, indices[h][w]);
+ boost::shared_ptr<Quad> quadPtr(quad);
- for (int h = 0; h <= 1; ++h)
- {
- xf = 0.0;
- for (int w = 0; w <= width; ++w, xf += increment)
- {
- vertices[h][w] = Vector4(xf, Scalar(h), 0.0, 1.0) *
- transposedTransform;
+ octree->insert(quadPtr);
+ }
}
+
+ return 0;
}
- for (int w = 0; w < width; ++w)
+ int makeBillboard(Script& script)
{
- Vector3 quadVertices[4];
-
- demoteVector(quadVertices[0], vertices[0][w]);
- demoteVector(quadVertices[1], vertices[0][w+1]);
- demoteVector(quadVertices[2], vertices[1][w+1]);
- demoteVector(quadVertices[3], vertices[1][w]);
+ Script::Value table = script[1];
+ Script::Value top = script[-1];
- Quad* quad = new Quad(quadVertices, texture, index);
- quad->setBlending(blending);
- quad->setFog(fog);
+ long index = 0;
+ long width = 1;
+ bool blending = false;
+ bool fog = false;
- boost::shared_ptr<Quad> quadPtr(quad);
+ if (table.isTable())
+ {
+ table.pushField("tile");
+ if (top.isNumber()) top.get(index);
- octree->insert(quadPtr);
- }
-}
+ table.pushField("u_scale");
+ if (top.isNumber()) top.get(width);
+ table.pushField("blend");
+ if (top.isBoolean()) top.get(blending);
-static void loadInstructions(SerializableP root, OctreeP octree)
-{
- Serializable::Array rootObj;
- Serializable::Array::iterator it;
+ table.pushField("fog");
+ if (top.isBoolean()) top.get(fog);
+ }
- if (!root->get(rootObj))
- {
- logError("scene instructions must be an array");
- return;
- }
+ Vector4 vertices[2][width+1];
- Matrix4 transform;
- std::string texture;
+ Matrix4 transposedTransform = transform;
+ transposedTransform.transpose();
- for (it = rootObj.begin(); it != rootObj.end(); ++it)
- {
- std::string instruction;
+ Scalar xf;
+ Scalar increment = 1.0 / Scalar(width);
- if ((*it)->get(instruction))
+ for (int h = 0; h <= 1; ++h)
{
- if (instruction == "reset_transform")
+ xf = 0.0;
+ for (int w = 0; w <= width; ++w, xf += increment)
{
- transform.identity();
+ vertices[h][w] = Vector4(xf, Scalar(h), 0.0, 1.0) *
+ transposedTransform;
}
- else if (instruction == "translate")
- {
- Serializable::Array values;
+ }
- ++it;
- if ((*it)->get(values))
- {
- Vector3 vec;
+ for (int w = 0; w < width; ++w)
+ {
+ Vector3 quadVertices[4];
- for (size_t i = 0; i < values.size(); ++i)
- {
- Serializable::Float value;
+ demoteVector(quadVertices[0], vertices[0][w]);
+ demoteVector(quadVertices[1], vertices[0][w+1]);
+ demoteVector(quadVertices[2], vertices[1][w+1]);
+ demoteVector(quadVertices[3], vertices[1][w]);
- if (values[i]->getNumber(value))
- {
- vec[i] = value;
- }
- }
+ Quad* quad = new Quad(quadVertices, texture, Tilemap::Index(index));
+ quad->setBlending(blending);
+ quad->setFog(fog);
- Matrix4 translation;
- cml::matrix_translation(translation, vec);
- transform = translation * transform;
- }
- }
- else if (instruction == "scale")
- {
- Serializable::Array values;
+ boost::shared_ptr<Quad> quadPtr(quad);
- ++it;
- if ((*it)->get(values))
- {
- if (values.size() == 1)
- {
- Serializable::Float value = 1.0;
-
- values[0]->getNumber(value);
-
- Matrix4 scaling;
- cml::matrix_uniform_scale(scaling,
- Scalar(value));
- transform = scaling * transform;
- }
- else if (values.size() == 3)
- {
- Vector3 vec;
-
- for (size_t i = 0; i < values.size(); ++i)
- {
- Serializable::Float value;
-
- if (values[i]->getNumber(value))
- {
- vec[i] = value;
- }
- }
-
- Matrix4 scaling;
- cml::matrix_scale(scaling, vec);
- transform = scaling * transform;
- }
- }
- }
- else if (instruction == "rotate")
- {
- Serializable::Array values;
+ octree->insert(quadPtr);
+ }
- ++it;
- if ((*it)->get(values))
- {
- if (values.size() == 2)
- {
- std::string axis;
- size_t index = 0;
- Serializable::Float value = 0.0;
-
- if (values[0]->get(axis))
- {
- if (axis == "x") index = 0;
- else if (axis == "y") index = 1;
- else if (axis == "z") index = 2;
-
- values[1]->getNumber(value);
- }
-
- cml::matrix_rotate_about_world_axis(transform,
- index, cml::rad(Scalar(value)));
- }
- }
- }
- else if (instruction == "texture")
- {
- ++it;
- (*it)->get(texture);
- }
- else if (instruction == "tilemap")
- {
- ++it;
- loadTilemap(*it, transform, texture, octree);
- }
- else if (instruction == "billboard")
- {
- ++it;
- loadBillboard(*it, transform, texture, octree);
- }
+ return 0;
+ }
+};
+
+
+static int luaPrint(Script& script)
+{
+ Script::Value param = script[1];
+
+ while (!param.isNone())
+ {
+ if (param.isString())
+ {
+ std::string str;
+ param.get(str);
+ logInfo("lua: %s", str.c_str());
+ }
+ else if (param.isBoolean())
+ {
+ if (param) logInfo("lua: true");
+ else logInfo("lua: false");
+
+ }
+ else if (param.isNil())
+ {
+ logInfo("lua: nil");
}
+ else
+ {
+ logInfo("lua: %s (%X)", param.getTypeName().c_str(),
+ param.getIdentifier());
+ }
+
+ param.index++;
}
-}
+ return 0;
+}
-static std::string getPath(const std::string& name)
+static void importScriptBindings(Script& script, Meh& scene)
{
- return Resource::getPath("scenes/" + name + ".json");
+ script.importFunction("SetPlayfieldBounds",
+ boost::bind(&Meh::setPlayfieldBounds, &scene, _1));
+ script.importFunction("SetMaximumBounds",
+ boost::bind(&Meh::setMaximumBounds, &scene, _1));
+ script.importFunction("ResetTransform",
+ boost::bind(&Meh::resetTransform, &scene, _1));
+ script.importFunction("Translate",
+ boost::bind(&Meh::translate, &scene, _1));
+ script.importFunction("Scale",
+ boost::bind(&Meh::scale, &scene, _1));
+ script.importFunction("Rotate",
+ boost::bind(&Meh::rotate, &scene, _1));
+ script.importFunction("SetTexture",
+ boost::bind(&Meh::setTexture, &scene, _1));
+ script.importFunction("MakeTilemap",
+ boost::bind(&Meh::makeTilemap, &scene, _1));
+ script.importFunction("MakeBillboard",
+ boost::bind(&Meh::makeBillboard, &scene, _1));
+ script.importFunction("print", luaPrint);
}
+
OctreeP loadScene(const std::string& name)
{
std::string filePath = getPath(name);
- Deserializer deserializer(filePath, true);
- SerializableP root = deserializer.deserialize();
-
- Serializable::Map rootObj;
- Serializable::Map::iterator it;
-
- if (!root || !root->get(rootObj))
- {
- logError("no root map in scene file");
- return OctreeP();
- }
+ Script script;
+ script.importStandardLibraries();
- Aabb playfieldBounds;
- Aabb maximumBounds;
+ Meh cool;
+ importScriptBindings(script, cool);
- if ((it = rootObj.find("playfield_bounds")) != rootObj.end())
- {
- loadBox(playfieldBounds, (*it).second);
- }
- if ((it = rootObj.find("maximum_bounds")) != rootObj.end())
- {
- loadBox(maximumBounds, (*it).second);
- }
- else
- {
- logError("missing required maximum bounds");
- return OctreeP();
- }
+ long detail = 3;
+ Settings::getInstance().getNumber("game.detail", detail);
- // create the tree to store the quads
- OctreeP octree = Octree::alloc(maximumBounds);
+ script.push(detail);
+ script.set("detail");
- if ((it = rootObj.find("instructions")) != rootObj.end())
+ logInfo("doing file...");
+ if (script.doFile(filePath) != 0)
{
- loadInstructions((*it).second, octree);
+ std::string str;
+ script[-1].get(str);
+ logError("lua error: %s", str.c_str());
}
+ logInfo("done");
- octree->sort();
-
- return octree;
+ cool.octree->sort();
+ return cool.octree;
}