--- /dev/null
+
+/*******************************************************************************
+
+ Copyright (c) 2009, Charles McGarvey
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include <Moof/Mippleton.hh>
+#include <Moof/OpenGL.hh>
+#include <Moof/Script.hh>
+
+#include "Tilemap.hh"
+
+
+struct Tilemap::Impl : public Mf::Mippleton<Impl>
+{
+ Impl(const std::string& name) :
+ Mf::Mippleton<Impl>(name),
+ magFilter_(GL_NEAREST),
+ minFilter_(GL_NEAREST),
+ nTilesS_(1),
+ nTilesT_(1),
+ wrapS_(GL_CLAMP),
+ wrapT_(GL_CLAMP)
+ {
+ loadFromFile();
+ }
+
+
+ static void bindScriptConstants(Mf::Script& script)
+ {
+ script.push(GL_CLAMP); script.set("CLAMP");
+ script.push(GL_REPEAT); script.set("REPEAT");
+ script.push(GL_LINEAR); script.set("LINEAR");
+ script.push(GL_NEAREST); script.set("NEAREST");
+ script.push(GL_LINEAR_MIPMAP_LINEAR); script.set("LINEAR_MIPMAP_LINEAR");
+ script.push(GL_LINEAR_MIPMAP_NEAREST); script.set("LINEAR_MIPMAP_NEAREST");
+ script.push(GL_NEAREST_MIPMAP_LINEAR); script.set("NEAREST_MIPMAP_LINEAR");
+ script.push(GL_NEAREST_MIPMAP_NEAREST); script.set("NEAREST_MIPMAP_NEAREST");
+ }
+
+ void loadFromFile()
+ {
+ Mf::Script script;
+ std::string filePath = Tilemap::getPath(getName());
+
+ script.importStandardLibraries();
+ importLogScript(script);
+ bindScriptConstants(script);
+
+ if (script.doFile(filePath) != Mf::Script::SUCCESS)
+ {
+ std::string str;
+ script[-1].get(str);
+ Mf::logScript("%s", str.c_str());
+ return; // TODO needs a better exit strategy
+ }
+
+ Mf::logInfo("loading tiles from tilemap %s", filePath.c_str());
+
+ Mf::Script::Value globals = script.getGlobalTable();
+ Mf::Script::Value top = script[-1];
+
+ globals.pushField("tiles_s");
+ top.get(nTilesS_);
+
+ globals.pushField("tiles_t");
+ top.get(nTilesT_);
+
+ globals.pushField("min_filter");
+ top.get(minFilter_);
+
+ globals.pushField("mag_filter");
+ top.get(magFilter_);
+
+ globals.pushField("wrap_s");
+ top.get(wrapS_);
+
+ globals.pushField("wrap_t");
+ top.get(wrapT_);
+ }
+
+
+ bool getTileCoords(Tilemap::Index index, Mf::Scalar coords[8]) const
+ {
+ // make sure the index represents a real tile
+ if (index >= nTilesS_ * nTilesT_) return false;
+
+ Mf::Scalar w = 1.0 / Mf::Scalar(nTilesS_);
+ Mf::Scalar h = 1.0 / Mf::Scalar(nTilesT_);
+
+ coords[0] = Mf::Scalar(index % nTilesS_) * w;
+ coords[1] = (Mf::Scalar(nTilesT_ - 1) -
+ Mf::Scalar(index / nTilesS_)) * h;
+ coords[2] = coords[0] + w;
+ coords[3] = coords[1];
+ coords[4] = coords[2];
+ coords[5] = coords[1] + h;
+ coords[6] = coords[0];
+ coords[7] = coords[5];
+
+ return true;
+ }
+
+
+ GLuint magFilter_;
+ GLuint minFilter_;
+ unsigned nTilesS_;
+ unsigned nTilesT_;
+ GLuint wrapS_;
+ GLuint wrapT_;
+};
+
+
+Tilemap::Tilemap(const std::string& name) :
+ Texture(name),
+ impl_(Tilemap::Impl::getInstance(name))
+{
+ setMinFilter(impl_->minFilter_);
+ setMagFilter(impl_->magFilter_);
+ setWrapS(impl_->wrapS_);
+ setWrapT(impl_->wrapT_);
+}
+
+
+bool Tilemap::getTileCoords(Index index, Mf::Scalar coords[8]) const
+{
+ // pass through
+ return impl_->getTileCoords(index, coords);
+}
+
+bool Tilemap::getTileCoords(Index index, Mf::Scalar coords[8],
+ Orientation orientation) const
+{
+ if (getTileCoords(index, coords))
+ {
+ if (orientation & FLIP)
+ {
+ // this looks kinda weird, but it's just swapping in a way that
+ // doesn't require an intermediate variable
+ coords[1] = coords[5];
+ coords[5] = coords[3];
+ coords[3] = coords[7];
+ coords[7] = coords[5];
+ }
+ if (orientation & REVERSE)
+ {
+ coords[0] = coords[2];
+ coords[2] = coords[6];
+ coords[4] = coords[6];
+ coords[6] = coords[0];
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+
+std::string Tilemap::getPath(const std::string& name)
+{
+ return Resource::getPath("tilemaps/" + name + ".lua");
+}
+
+
+/** vim: set ts=4 sw=4 tw=80: *************************************************/
+