*******************************************************************************/
-#include <iostream>
#include <map>
#include <vector>
#include "Aabb.hh"
#include "Camera.hh"
-#include "Deserializer.hh"
#include "Entity.hh"
+#include "Log.hh"
#include "Math.hh"
-#include "Mippleton.hh"
-#include "OpenGL.hh"
#include "Scene.hh"
-#include "Serializable.hh"
+#include "Script.hh"
+#include "Settings.hh"
#include "Tilemap.hh"
namespace Mf {
-class Scene::Impl : public Mippleton<Impl>
+static std::string getPath(const std::string& name)
{
- class Quad : public Entity
- {
- public:
- Quad(const Vector3 vertices[4], const std::string& texture,
- Tilemap::Index tileIndex) :
- tilemap_(texture),
- detail_(0),
- blending_(false),
- fog_(false)
- {
- for (int i = 0, num = 0; i < 4; ++i)
- {
- for (int j = 0; j < 3; ++j, ++num)
- {
- vertices_[num] = vertices[i][j];
- }
- }
+ return Resource::getPath("scenes/" + name + ".lua");
+}
- if (!tilemap_.getTileCoords(tileIndex, texCoords_))
- {
- std::cerr << "no coords for tile's texture" << std::endl;
- }
- aabb_.encloseVertices(vertices, 4);
- sphere_.point = aabb_.getCenter();
- sphere_.radius = (aabb_.min - sphere_.point).length();
- }
+struct Meh
+{
+ Matrix4 transform;
+ std::string texture;
- void setDetail(long detail)
- {
- detail_ = detail;
- }
+ OctreeP octree;
- void setBlending(bool blending)
- {
- blending_ = blending;
- }
+ Meh()
+ {
+ octree = Octree::alloc(Aabb());
+ }
+
+ static int loadBox(Script& script, Aabb& aabb)
+ {
+ Script::Value table[] = {script[1], script[2]};
- void setFog(bool fog)
+ if (!table[0].isTable() || !table[1].isTable())
{
- fog_ = fog;
+ logWarning("wrong arguments to setPlayfieldBounds; ignoring...");
+ return 0;
}
- void draw(Scalar alpha = 0.0) const
+ for (int i = 0; i <= 1; ++i)
{
- if (blending_)
+ for (int j = 1; j <= 3; ++j)
{
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ script.push((long)j);
+ table[i].pushField();
}
+ }
- if (fog_)
- {
- glEnable(GL_FOG);
- glFogi(GL_FOG_MODE, GL_LINEAR);
- }
+ 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;
+ }
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- tilemap_.bind();
+ int setPlayfieldBounds(Script& script)
+ {
+ Aabb bounds;
+ return loadBox(script, bounds);
+ }
- glVertexPointer(3, GL_SCALAR, 0, vertices_);
- glTexCoordPointer(2, GL_SCALAR, 0, texCoords_);
+ int setMaximumBounds(Script& script)
+ {
+ Aabb bounds;
+ int ret = loadBox(script, bounds);
+ octree = Octree::alloc(bounds);
+ return ret;
+ }
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ int resetTransform(Script& script)
+ {
+ transform.identity();
+ return 0;
+ }
- glDisable(GL_BLEND);
- glDisable(GL_FOG);
- }
+ int translate(Script& script)
+ {
+ Script::Value x = script[1];
+ Script::Value y = script[2];
+ Script::Value z = script[3];
- bool isVisible(const Camera& cam) const
+ if (!x.isNumber() || !y.isNumber() || !z.isNumber())
{
- return sphere_.isVisible(cam);
+ logWarning("wrong arguments to translate; ignoring...");
+ return 0;
}
- private:
- Scalar vertices_[12];
- Scalar texCoords_[8];
-
- Tilemap tilemap_;
+ Vector3 vec;
+ x.get(vec[0]);
+ y.get(vec[1]);
+ z.get(vec[2]);
- long detail_;
- bool blending_;
- bool fog_;
- };
+ Matrix4 translation;
+ cml::matrix_translation(translation, vec);
+ transform = translation * transform;
+ return 0;
+ }
- static void loadBox(Aabb& theBox, SerializableP obj)
+ int scale(Script& script)
{
- Serializable::Array numbers;
+ 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);
- if (obj->get(numbers) && numbers.size() == 6)
+ Matrix4 scaling;
+ cml::matrix_uniform_scale(scaling,
+ Scalar(value));
+ transform = scaling * transform;
+ }
+ else
{
- 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);
+ logWarning("wrong arguments to scale; ignoring...");
}
- }
-public:
- Impl(const std::string& name) :
- Mippleton<Impl>(name)
- {
- loadFromFile();
+ return 0;
}
-
- void loadInstructions(SerializableP root)
+ int rotate(Script& script)
{
- Serializable::Array rootObj;
- Serializable::Array::iterator it;
+ Script::Value a = script[1];
+ Script::Value d = script[2];
- if (!root->get(rootObj))
+ if (!a.isString() || !d.isNumber())
{
- std::cerr << "error loading scene instructions" << std::endl;
- return;
+ logWarning("wrong arguments to rotate; ignoring...");
+ return 0;
}
- Matrix4 transform;
- std::string texture;
+ std::string axis;
+ a.get(axis);
- for (it = rootObj.begin(); it != rootObj.end(); ++it)
- {
- std::string instruction;
+ size_t index = 0;
+ if (axis == "x") index = 0;
+ else if (axis == "y") index = 1;
+ else if (axis == "z") index = 2;
- if ((*it)->get(instruction))
- {
- if (instruction == "reset_transform")
- {
- transform.identity();
- }
- else if (instruction == "translate")
- {
- Serializable::Array values;
-
- ++it;
- if ((*it)->get(values))
- {
- Vector3 vec;
-
- for (size_t i = 0; i < values.size(); ++i)
- {
- Serializable::Float value;
-
- if (values[i]->getNumber(value))
- {
- vec[i] = value;
- }
- }
-
- Matrix4 translation;
- cml::matrix_translation(translation, vec);
- transform = translation * transform;
- }
- }
- else if (instruction == "scale")
- {
- Serializable::Array values;
-
- ++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;
-
- ++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);
- }
- else if (instruction == "billboard")
- {
- ++it;
- loadBillboard(*it, transform, texture);
- }
- }
- }
+ Scalar value;
+ d.get(value);
+
+ cml::matrix_rotate_about_world_axis(transform,
+ index, cml::rad(Scalar(value)));
+
+ return 0;
}
+ int setTexture(Script& script)
+ {
+ Script::Value t = script[1];
+
+ if (t.isString()) t.get(texture);
+ else logWarning("wrong arguments to setTexture; ignoring...");
- void loadTilemap(SerializableP root, const Matrix4& transform,
- const std::string& texture)
+ return 0;
+ }
+
+ int makeTilemap(Script& script)
{
- Serializable::Map rootObj;
- Serializable::Map::iterator it;
+ Script::Value table = script[1];
+ Script::Value top = script[-1];
- if (!root->get(rootObj))
+ if (!table.isTable())
{
- std::cerr << "error loading scene tilemap object" << std::endl;
- return;
+ logWarning("wrong arguments to makeTilemap; ignoring...");
+ return 0;
}
long width = 1;
long height = 1;
- std::vector< std::vector<Tilemap::Index> > indices;
- if ((it = rootObj.find("width")) != rootObj.end())
- {
- (*it).second->get(width);
- }
- else
- {
- std::cerr << "width is a required field of a tilemap" << std::endl;
- return;
- }
+ table.pushField("width");
+ top.get(width);
- Serializable::Array tiles;
+ long nTiles = 0;
- if ((it = rootObj.find("tiles")) != rootObj.end() &&
- (*it).second->get(tiles) &&
- tiles.size() % width == 0)
+ table.pushField("tiles");
+ Script::Value tiles = script.getTop();
+ nTiles = tiles.getLength();
+
+ std::vector< std::vector<Tilemap::Index> > indices;
+
+ if (nTiles % width == 0)
{
- Serializable::Array::iterator jt;
- int w, h;
+ int i, w, h;
- height = tiles.size() / width;
+ 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
- for (h = height - 1, jt = tiles.begin(); jt != tiles.end(); --h)
+ i = 1;
+ for (h = height - 1; h >= 0; --h)
{
std::vector<Tilemap::Index> row;
- for (w = 0; w < width && jt != tiles.end(); ++w, ++jt)
+ for (w = 0; w < width; ++w, ++i)
{
- Serializable::Integer index;
+ script.checkStack(2);
+ script.push(long(i));
+ tiles.pushField();
+
+ long index;
+ top.get(index);
- if ((*jt)->get(index))
- {
- row.push_back(Tilemap::Index(index));
- }
+ row.push_back(Tilemap::Index(index));
}
indices[h] = row;
}
else
{
- std::cerr << "error loading tiles from tilemap object" << std::endl;
- return;
+ logError("invalid tiles in tilemap instruction");
+ return 0;
}
Vector4 vertices[height+1][width+1];
octree->insert(quadPtr);
}
}
+
+ return 0;
}
- void loadBillboard(SerializableP root, const Matrix4& transform,
- const std::string& texture)
+ int makeBillboard(Script& script)
{
- Serializable::Map rootObj;
- Serializable::Map::iterator it;
+ Script::Value table = script[1];
+ Script::Value top = script[-1];
- Tilemap::Index index = 0;
- long width = 1;
- bool blending = false;
- bool fog = false;
+ long index = 0;
+ long width = 1;
+ bool blending = false;
+ bool fog = false;
- if (root->get(rootObj))
+ if (table.isTable())
{
- if ((it = rootObj.find("tile")) != rootObj.end())
- {
- Serializable::Integer value;
- if ((*it).second->get(value))
- {
- index = Tilemap::Index(value);
- }
- }
+ table.pushField("tile");
+ if (top.isNumber()) top.get(index);
- if ((it = rootObj.find("u_scale")) != rootObj.end())
- {
- (*it).second->get(width);
- }
+ table.pushField("u_scale");
+ if (top.isNumber()) top.get(width);
- if ((it = rootObj.find("blend")) != rootObj.end())
- {
- (*it).second->get(blending);
- }
+ table.pushField("blend");
+ if (top.isBoolean()) top.get(blending);
- if ((it = rootObj.find("fog")) != rootObj.end())
- {
- (*it).second->get(fog);
- }
+ table.pushField("fog");
+ if (top.isBoolean()) top.get(fog);
}
-
Vector4 vertices[2][width+1];
Matrix4 transposedTransform = transform;
demoteVector(quadVertices[2], vertices[1][w+1]);
demoteVector(quadVertices[3], vertices[1][w]);
- Quad* quad = new Quad(quadVertices, texture, index);
+ Quad* quad = new Quad(quadVertices, texture, Tilemap::Index(index));
quad->setBlending(blending);
quad->setFog(fog);
octree->insert(quadPtr);
}
- }
-
- void loadFromFile()
- {
- std::string filePath = Scene::getPath(getName());
+ return 0;
+ }
+};
- Deserializer deserializer(filePath, true);
- SerializableP root = deserializer.deserialize();
- Serializable::Map rootObj;
- Serializable::Map::iterator it;
+static int luaPrint(Script& script)
+{
+ Script::Value param = script[1];
- if (!root || !root->get(rootObj))
+ while (!param.isNone())
+ {
+ if (param.isString())
{
- std::cerr << "error loading scene file" << std::endl;
- return;
+ std::string str;
+ param.get(str);
+ logInfo("lua: %s", str.c_str());
}
-
- if ((it = rootObj.find("playfield_bounds")) != rootObj.end())
+ else if (param.isBoolean())
{
- loadBox(playfieldBounds, (*it).second);
+ if (param) logInfo("lua: true");
+ else logInfo("lua: false");
+
}
- if ((it = rootObj.find("maximum_bounds")) != rootObj.end())
+ else if (param.isNil())
{
- loadBox(maximumBounds, (*it).second);
+ logInfo("lua: nil");
}
else
{
- std::cerr << "maximum bounds required in scene" << std::endl;
- return;
- }
-
- // create the tree to store the quads
- octree = Octree::alloc(maximumBounds);
-
- if ((it = rootObj.find("instructions")) != rootObj.end())
- {
- loadInstructions((*it).second);
+ logInfo("lua: %s (%X)", param.getTypeName().c_str(),
+ param.getIdentifier());
}
- octree->sort();
- }
-
-
- void draw(Scalar alpha, const Camera& cam) const
- {
- glEnableClientState(GL_VERTEX_ARRAY);
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-
- octree->drawIfVisible(alpha, cam);
-
- //glDisableClientState(GL_VERTEX_ARRAY);
- //glDisableClientState(GL_TEXTURE_COORD_ARRAY);
-
- //glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-
- //Texture::resetBind();
- //glColor3f(0.0f, 1.0f, 0.0f);
- //playfieldBounds.draw();
- //glColor3f(0.0f, 0.0f, 1.0f);
- //maximumBounds.draw();
-
- //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ param.index++;
}
-
- Aabb playfieldBounds;
- Aabb maximumBounds;
-
- OctreeP octree;
-};
-
-
-Scene::Scene(const std::string& name) :
- // pass through
- impl_(Scene::Impl::getInstance(name)) {}
-
-
-void Scene::draw(Scalar alpha, const Camera& cam) const
-{
- // pass through
- impl_->draw(alpha, cam);
+ return 0;
}
-void Scene::refresh()
+static void importScriptBindings(Script& script, Meh& scene)
{
- //impl_->objects.clear();
- impl_->loadFromFile();
+ 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 Scene::getOctree() const
+OctreeP loadScene(const std::string& name)
{
- // pass through
- return impl_->octree;
-}
+ std::string filePath = getPath(name);
-/**
- * Specialized search location for scene files. They can be found in the
- * "scenes" subdirectory of any of the searched directories.
- */
+ Script script;
+ script.importStandardLibraries();
-std::string Scene::getPath(const std::string& name)
-{
- return Resource::getPath("scenes/" + name + ".json");
+ Meh cool;
+ importScriptBindings(script, cool);
+
+ long detail = 3;
+ Settings::getInstance().getNumber("game.detail", detail);
+
+ script.push(detail);
+ script.set("detail");
+
+ logInfo("doing file...");
+ if (script.doFile(filePath) != 0)
+ {
+ std::string str;
+ script[-1].get(str);
+ logError("lua error: %s", str.c_str());
+ }
+ logInfo("done");
+
+ cool.octree->sort();
+ return cool.octree;
}