X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fyoink;a=blobdiff_plain;f=src%2FMoof%2FScene.cc;h=2e1a79363302ebb527e8a0c9d7ce8a13480495f3;hp=418c0512e3c690e4f29406181cac8346c67ada80;hb=542e50a284c7f5b144a5c97c17f6d89b2af0175c;hpb=b887538a8ccc1c904f6aa24f0f6dcc23e0cc2f72 diff --git a/src/Moof/Scene.cc b/src/Moof/Scene.cc index 418c051..2e1a793 100644 --- a/src/Moof/Scene.cc +++ b/src/Moof/Scene.cc @@ -31,395 +31,428 @@ #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 > 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 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 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 > 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 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 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 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 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; }