*******************************************************************************/
-#include <iostream>
#include <map>
#include <vector>
#include "Aabb.hh"
#include "Camera.hh"
-#include "Cullable.hh"
-#include "Deserializer.hh"
-#include "Drawable.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::SceneImpl : public Mippleton<SceneImpl>
+static std::string getPath(const std::string& name)
{
- class Scenery : public Drawable, public Cullable
+ return Resource::getPath("scenes/" + name + ".lua");
+}
+
+
+struct Meh
+{
+ Matrix4 transform;
+ std::string texture;
+
+ OctreeP octree;
+
+ Meh()
{
- public:
- Scenery(const Matrix4& transform, const std::string& textureName) :
- transformation(transform),
- image(textureName) {}
-
- protected:
- Matrix4 transformation;
- Tilemap image;
- bool blending;
- long detail;
- bool fog;
- };
-
- class TilePanel : public Scenery
+ octree = Octree::alloc(Aabb());
+ }
+
+ static int loadBox(Script& script, Aabb& aabb)
{
- public:
- TilePanel(const Matrix4& transform, const std::string& textureName,
- SerializablePtr root) :
- Scenery(transform, textureName),
- width(1),
- height(1)
+ Script::Value table[] = {script[1], script[2]};
+
+ if (!table[0].isTable() || !table[1].isTable())
{
- std::map<std::string,SerializablePtr> rootObj;
+ logWarning("wrong arguments to setPlayfieldBounds; ignoring...");
+ return 0;
+ }
- if (root->get(rootObj))
+ for (int i = 0; i <= 1; ++i)
+ {
+ for (int j = 1; j <= 3; ++j)
{
- std::map<std::string,SerializablePtr>::iterator it;
-
- if ((it = rootObj.find("width")) != rootObj.end())
- {
- (*it).second->get(width);
- }
- if ((it = rootObj.find("tiles")) != rootObj.end())
- {
- std::vector<SerializablePtr> theTiles;
+ script.push((long)j);
+ table[i].pushField();
+ }
+ }
- if ((*it).second->get(theTiles))
- {
- std::vector<SerializablePtr>::iterator jt;
+ 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]);
- height = theTiles.size() / width;
- int w, h;
+ return 0;
+ }
- indices.resize(height);
+ int setPlayfieldBounds(Script& script)
+ {
+ Aabb bounds;
+ return loadBox(script, bounds);
+ }
- for (h = height - 1, jt = theTiles.begin();
- jt != theTiles.end(); h--)
- {
- std::vector<Tilemap::Index> row;
+ int setMaximumBounds(Script& script)
+ {
+ Aabb bounds;
+ int ret = loadBox(script, bounds);
+ octree = Octree::alloc(bounds);
+ return ret;
+ }
- for (w = 0; w < width && jt != theTiles.end();
- w++, jt++)
- {
- long index;
+ int resetTransform(Script& script)
+ {
+ transform.identity();
+ return 0;
+ }
- if ((*jt)->get(index))
- {
- row.push_back(Tilemap::Index(index));
- }
- }
+ int translate(Script& script)
+ {
+ Script::Value x = script[1];
+ Script::Value y = script[2];
+ Script::Value z = script[3];
- indices[h] = row;
- }
- }
- }
- }
+ if (!x.isNumber() || !y.isNumber() || !z.isNumber())
+ {
+ logWarning("wrong arguments to translate; ignoring...");
+ return 0;
}
- void draw(Scalar alpha)
- {
- glPushMatrix();
- //std::cout << "transforming..." << std::endl;
- //std::cout << transformation << std::endl;
- glMultMatrixf(transformation.data());
+ Vector3 vec;
+ x.get(vec[0]);
+ y.get(vec[1]);
+ z.get(vec[2]);
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- image.bind();
+ Matrix4 translation;
+ cml::matrix_translation(translation, vec);
+ transform = translation * transform;
- long x, y;
- Scalar xf, yf;
+ return 0;
+ }
- for (y = 0, yf = 0.0; y < height; y++, yf += 1.0)
- {
- for (x = 0, xf = 0.0; x < width; x++, xf += 1.0)
- {
- Scalar texCoords[8];
-
- Tilemap::Index index = indices[y][x];
-
- if (image.getTileCoords(index, texCoords))
- {
- glBegin(GL_TRIANGLE_FAN);
- glTexCoord2f(texCoords[0], texCoords[1]);
- glVertex3f(xf, yf, 0.0f);
- glTexCoord2f(texCoords[2], texCoords[3]);
- glVertex3f(xf+1.0, yf, 0.0f);
- glTexCoord2f(texCoords[4], texCoords[5]);
- glVertex3f(xf+1.0, yf+1.0, 0.0f);
- glTexCoord2f(texCoords[6], texCoords[7]);
- glVertex3f(xf, yf+1.0, 0.0f);
- glEnd();
- }
- }
- }
+ int scale(Script& script)
+ {
+ 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);
- glPopMatrix();
+ Matrix4 scaling;
+ cml::matrix_uniform_scale(scaling,
+ Scalar(value));
+ transform = scaling * transform;
+ }
+ else
+ {
+ logWarning("wrong arguments to scale; ignoring...");
}
- bool isVisible(const Camera& cam)
+ return 0;
+ }
+
+ int rotate(Script& script)
+ {
+ Script::Value a = script[1];
+ Script::Value d = script[2];
+
+ if (!a.isString() || !d.isNumber())
{
- return true;
+ logWarning("wrong arguments to rotate; ignoring...");
+ return 0;
}
- private:
- long width, height;
- std::vector<std::vector<Tilemap::Index> > indices;
- };
+ std::string axis;
+ a.get(axis);
- class Billboard : public Scenery
+ 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;
+ }
+
+ int setTexture(Script& script)
+ {
+ Script::Value t = script[1];
+
+ if (t.isString()) t.get(texture);
+ else logWarning("wrong arguments to setTexture; ignoring...");
+
+ return 0;
+ }
+
+ int makeTilemap(Script& script)
{
- public:
- Billboard(const Matrix4& transform, const std::string& textureName,
- SerializablePtr root) :
- Scenery(transform, textureName),
- index(0)
+ Script::Value table = script[1];
+ Script::Value top = script[-1];
+
+ if (!table.isTable())
+ {
+ logWarning("wrong arguments to makeTilemap; ignoring...");
+ return 0;
+ }
+
+ long width = 1;
+ long height = 1;
+
+ table.pushField("width");
+ top.get(width);
+
+ 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)
{
- std::map<std::string,SerializablePtr> rootObj;
+ int i, w, h;
- if (root->get(rootObj))
+ 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)
{
- std::map<std::string,SerializablePtr>::iterator it;
+ std::vector<Tilemap::Index> row;
- if ((it = rootObj.find("tile")) != rootObj.end())
+ for (w = 0; w < width; ++w, ++i)
{
- long value;
- if ((*it).second->get(value))
- {
- index = Tilemap::Index(value);
- }
- }
- }
+ script.checkStack(2);
+ script.push(long(i));
+ tiles.pushField();
- image.getTileCoords(index, texCoords);
- }
+ long index;
+ top.get(index);
- void draw(Scalar alpha)
- {
- glPushMatrix();
- glMultMatrixf(transformation.data());
-
- glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
- image.bind();
-
- glBegin(GL_TRIANGLE_FAN);
- glTexCoord2f(texCoords[0], texCoords[1]);
- glVertex2f(0.0f, 0.0f);
- glTexCoord2f(texCoords[2], texCoords[3]);
- glVertex2f(1.0f, 0.0f);
- glTexCoord2f(texCoords[4], texCoords[5]);
- glVertex2f(1.0f, 1.0f);
- glTexCoord2f(texCoords[6], texCoords[7]);
- glVertex2f(0.0f, 1.0f);
- glEnd();
-
- glPopMatrix();
- }
+ row.push_back(Tilemap::Index(index));
+ }
- bool isVisible(const Camera& cam)
+ indices[h] = row;
+ }
+ }
+ else
{
- return false;
+ logError("invalid tiles in tilemap instruction");
+ return 0;
}
- private:
- Tilemap::Index index;
- Scalar texCoords[8];
- };
+ Vector4 vertices[height+1][width+1];
+ Matrix4 transposedTransform = transform;
+ transposedTransform.transpose();
- static bool loadBox(Aabb& theBox, SerializablePtr obj)
- {
- std::vector<SerializablePtr> numbers;
+ for (int h = 0; h <= height; ++h)
+ {
+ for (int w = 0; w <= width; ++w)
+ {
+ vertices[h][w] = Vector4(Scalar(w), Scalar(h), 0.0, 1.0) *
+ transposedTransform;
+ }
+ }
- if (obj->get(numbers))
+ for (int h = 0; h < height; ++h)
{
- if (numbers.size() == 6)
+ for (int w = 0; w < width; ++w)
{
- double num;
+ if (indices[h][w] == Tilemap::NO_TILE) continue;
- if (numbers[0]->getNumber(num))
- {
+ Vector3 quadVertices[4];
- }
+ 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]);
+
+ Quad* quad = new Quad(quadVertices, texture, indices[h][w]);
+ boost::shared_ptr<Quad> quadPtr(quad);
+
+ octree->insert(quadPtr);
}
}
- return false;
+ return 0;
}
-public:
- SceneImpl(const std::string& name) :
- Mippleton<SceneImpl>(name)
+ int makeBillboard(Script& script)
{
- loadFromFile();
- }
+ Script::Value table = script[1];
+ Script::Value top = script[-1];
+ long index = 0;
+ long width = 1;
+ bool blending = false;
+ bool fog = false;
- void loadInstructions(SerializablePtr root)
- {
- std::vector<SerializablePtr> rootObj;
-
- if (root->get(rootObj))
+ if (table.isTable())
{
- std::vector<SerializablePtr>::iterator it;
+ table.pushField("tile");
+ if (top.isNumber()) top.get(index);
- Matrix4 transform;
- std::string texture;
+ table.pushField("u_scale");
+ if (top.isNumber()) top.get(width);
- for (it = rootObj.begin(); it != rootObj.end(); it++)
- {
- std::string instruction;
+ table.pushField("blend");
+ if (top.isBoolean()) top.get(blending);
- if ((*it)->get(instruction))
- {
- if (instruction == "reset_transform")
- {
- transform.identity();
- //std::cout << "===================RESET=====================" << std::endl;
- }
- else if (instruction == "translate")
- {
- std::vector<SerializablePtr> values;
-
- it++;
- if ((*it)->get(values))
- {
- Vector3 vec;
-
- for (size_t i = 0; i < values.size(); i++)
- {
- double value;
-
- if (values[i]->getNumber(value))
- {
- vec[i] = value;
- }
- }
-
- Matrix4 translation;
- cml::matrix_translation(translation, vec);
- transform = translation * transform;
- //std::cout << "TRANSLATE\t" << vec << std::endl
- //<< transform << std::endl;
- }
- }
- else if (instruction == "scale")
- {
- std::vector<SerializablePtr> values;
-
- it++;
- if ((*it)->get(values))
- {
- if (values.size() == 1)
- {
- double value = 1.0;
-
- values[0]->getNumber(value);
-
- Matrix4 scaling;
- cml::matrix_uniform_scale(scaling, Scalar(value));
- transform = scaling * transform;
- //std::cout << "SCALE\t\t" << value << std::endl
- //<< transform << std::endl;
- }
- else if (values.size() == 3)
- {
- Vector3 vec;
-
- for (size_t i = 0; i < values.size(); i++)
- {
- double value;
-
- if (values[i]->getNumber(value))
- {
- vec[i] = value;
- }
- }
-
- Matrix4 scaling;
- cml::matrix_scale(scaling, vec);
- transform = scaling * transform;
- //std::cout << "SCALE\t\t" << vec << std::endl
- //<< transform << std::endl;
- }
- }
- }
- else if (instruction == "rotate")
- {
- std::vector<SerializablePtr> values;
-
- it++;
- if ((*it)->get(values))
- {
- if (values.size() == 2)
- {
- std::string axis;
- size_t axisIndex = 0;
- double value = 0.0;
-
- if (values[0]->get(axis))
- {
- if (axis == "x")
- {
- axisIndex = 0;
- }
- else if (axis == "y")
- {
- axisIndex = 1;
- }
- else if (axis == "z")
- {
- axisIndex = 2;
- }
- values[1]->getNumber(value);
- }
-
- cml::matrix_rotate_about_local_axis(transform,
- axisIndex, Scalar(value * cml::constantsd::rad_per_deg()));
- //std::cout << "ROTATE\t" << axis << " " << value << std::endl
- //<< transform << std::endl;
- }
- }
- }
- else if (instruction == "texture")
- {
- it++;
- (*it)->get(texture);
- }
- else if (instruction == "tilemap")
- {
- //std::cout << "TILEMAP\t" << texture<< std::endl;
- //std::cout << transform << std::endl;
-
- it++;
- TilePanel* tilePanel = new TilePanel(transform, texture,
- *it);
- boost::shared_ptr<Scenery> sceneItem(tilePanel);
- objects.push_back(sceneItem);
- }
- else if (instruction == "billboard")
- {
- //std::cout << "BILLBOARD\t" << texture << std::endl;
- //std::cout << transform << std::endl;
-
- it++;
- Billboard* billboard = new Billboard(transform, texture,
- *it);
- boost::shared_ptr<Scenery> sceneItem(billboard);
- objects.push_back(sceneItem);
- }
- }
- }
+ table.pushField("fog");
+ if (top.isBoolean()) top.get(fog);
}
- }
+ Vector4 vertices[2][width+1];
- void loadFromFile()
- {
- std::string filePath = Scene::getPathToResource(getName());
+ Matrix4 transposedTransform = transform;
+ transposedTransform.transpose();
- Deserializer deserializer(filePath, true);
+ Scalar xf;
+ Scalar increment = 1.0 / Scalar(width);
- SerializablePtr root = deserializer.deserialize();
+ 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;
+ }
+ }
- if (root)
+ for (int w = 0; w < width; ++w)
{
- std::map<std::string,SerializablePtr> rootObj;
+ Vector3 quadVertices[4];
- if (root->get(rootObj))
- {
- std::map<std::string,SerializablePtr>::iterator it;
+ 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 ((it = rootObj.find("playfield_bounds")) != rootObj.end())
- {
- loadBox(playfieldBounds, (*it).second);
- }
- if ((it = rootObj.find("maximum_bounds")) != rootObj.end())
- {
- loadBox(maximumBounds, (*it).second);
- }
- if ((it = rootObj.find("instructions")) != rootObj.end())
- {
- loadInstructions((*it).second);
- }
- }
+ Quad* quad = new Quad(quadVertices, texture, Tilemap::Index(index));
+ quad->setBlending(blending);
+ quad->setFog(fog);
+
+ boost::shared_ptr<Quad> quadPtr(quad);
+
+ octree->insert(quadPtr);
}
+
+ return 0;
}
+};
- void draw(Scalar alpha)
+static int luaPrint(Script& script)
+{
+ Script::Value param = script[1];
+
+ while (!param.isNone())
{
- SceneryVector::iterator it;
+ 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");
- for (it = objects.begin(); it != objects.end(); it++)
+ }
+ else if (param.isNil())
+ {
+ logInfo("lua: nil");
+ }
+ else
{
- //std::cout << "draw object";
- (*it)->draw(alpha);
+ logInfo("lua: %s (%X)", param.getTypeName().c_str(),
+ param.getIdentifier());
}
+
+ param.index++;
}
+ return 0;
+}
- Aabb playfieldBounds;
- Aabb maximumBounds;
+static void importScriptBindings(Script& script, Meh& scene)
+{
+ 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);
+}
- typedef std::vector<boost::shared_ptr<Scenery> > SceneryVector;
- SceneryVector objects;
-};
+OctreeP loadScene(const std::string& name)
+{
+ std::string filePath = getPath(name);
-Scene::Scene(const std::string& name) :
- // pass through
- impl_(Scene::SceneImpl::retain(name), &Scene::SceneImpl::release) {}
+ Script script;
+ script.importStandardLibraries();
+ Meh cool;
+ importScriptBindings(script, cool);
-void Scene::draw(Scalar alpha)
-{
- // pass through
- impl_->draw(alpha);
-}
+ long detail = 3;
+ Settings::getInstance().getNumber("game.detail", detail);
+ script.push(detail);
+ script.set("detail");
-/**
- * Specialized search location for scene files. They can be found in the
- * "scenes" subdirectory of any of the searched directories.
- */
+ logInfo("doing file...");
+ if (script.doFile(filePath) != 0)
+ {
+ std::string str;
+ script[-1].get(str);
+ logError("lua error: %s", str.c_str());
+ }
+ logInfo("done");
-std::string Scene::getPathToResource(const std::string& name)
-{
- return Resource::getPathToResource("scenes/" + name + ".json");
+ cool.octree->sort();
+ return cool.octree;
}