#include <cstdio> // FILE
#include <cstring> // strncmp
+#include <boost/algorithm/string.hpp>
#include <boost/bind.hpp>
#include "Dispatch.hh"
-#include "Core.hh"
#include "Error.hh"
-#include "Image.hh"
-#include "Library.hh"
+#include "Manager.hh"
#include "Log.hh"
#include "OpenGL.hh"
+#include "Script.hh"
#include "Texture.hh"
#include "Video.hh"
* which is worth having in memory. The image data itself is not worth keeping
* in memory if the texture has been loaded to GL, but the name of the resource
* is retained so that it can be reloaded if necessary. The implementation is a
- * library so that multiple texture objects can share the same internal objects
+ * manager so that multiple texture objects can share the same internal objects
* and avoid having duplicate textures loaded to GL.
*/
-class Texture::Impl : public Library<Impl>
+class Texture::Impl : public Manager<Impl>
{
/**
return value;
}
+
+ 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");
+ }
+
public:
/**
* Construction is initialization.
*/
- explicit Impl(const std::string& name) :
- Library<Impl>(name),
- //mContext(0),
- mImage(Texture::getPath(getName())),
- mWidth(0),
- mHeight(0),
- mMode(0),
+ Impl() :
mMinFilter(GL_NEAREST),
mMagFilter(GL_NEAREST),
mWrapS(GL_CLAMP),
mWrapT(GL_CLAMP),
+ mTilesS(1),
+ mTilesT(1),
mObject(0)
{
// make sure we have a video context
- //ASSERT(video && "cannot load textures without a current video context");
+ ASSERT(video && "cannot load textures without a current video context");
// we want to know when the GL context is recreated
mDispatchHandler = core.addHandler("video.newcontext",
boost::bind(&Impl::contextRecreated, this));
-
- loadFromFile();
}
~Impl()
* @return Image data.
*/
- void loadFromFile()
+ void init(const std::string& name)
{
- if (!mImage.isValid())
+ std::string path = Texture::getPath(name);
+
+ mImage = Image::alloc(path);
+ if (!mImage->isValid())
+ {
+ logWarning << "texture not found: " << path << std::endl;
+ Error(Error::RESOURCE_NOT_FOUND, path).raise();
+ }
+
+ mImage->flip();
+
+ Mf::Script script;
+
+ importLogFunctions(script);
+ bindScriptConstants(script);
+
+ if (script.doString(mImage->getComment()) != Mf::Script::SUCCESS)
{
- logWarning << "texture not found: " << getName() << std::endl;
- throw Error(Error::RESOURCE_NOT_FOUND, getName());
+ std::string str;
+ script[-1].get(str);
+ Mf::logWarning(str);
}
+ else
+ {
+ Mf::logInfo << "loading tiles from texture " << path << std::endl;
+
+ Mf::Script::Slot globals = script.getGlobalTable();
+ Mf::Script::Slot top = script[-1];
- mImage.flip();
+ globals.pushField("tiles_s");
+ top.get(mTilesS);
- mWidth = mImage.getWidth();
- mHeight = mImage.getHeight();
- mMode = mImage.getColorMode();
+ globals.pushField("tiles_t");
+ top.get(mTilesT);
+
+ globals.pushField("min_filter");
+ top.get(mMinFilter);
+
+ globals.pushField("mag_filter");
+ top.get(mMagFilter);
+
+ globals.pushField("wrap_s");
+ top.get(mWrapS);
+
+ globals.pushField("wrap_t");
+ top.get(mWrapT);
+ }
}
return;
}
- //if (!mContext) loadFromFile();
-
glGenTextures(1, &mObject);
glBindTexture(GL_TEXTURE_2D, mObject);
(
GL_TEXTURE_2D,
0,
- mMode,
+ mImage->getMode(),
//3,
- mWidth,
- mHeight,
+ mImage->getWidth(),
+ mImage->getHeight(),
0,
- mMode,
+ mImage->getMode(),
GL_UNSIGNED_BYTE,
- mImage.getPixels()
+ mImage->getPixels()
);
setProperties();
-
- //SDL_FreeSurface(mContext);
- //mContext = 0;
}
}
- Image mImage;
- unsigned mWidth; ///< Horizontal dimension of the image.
- unsigned mHeight; ///< Vertical dimension.
+ bool getTileCoords(Texture::TileIndex index, Scalar coords[8]) const
+ {
+ // make sure the index represents a real tile
+ if (index >= mTilesS * mTilesT) return false;
+
+ Scalar w = 1.0 / Scalar(mTilesS);
+ Scalar h = 1.0 / Scalar(mTilesT);
+
+ coords[0] = Scalar(index % mTilesS) * w;
+ coords[1] = (Scalar(mTilesT - 1) -
+ Scalar(index / mTilesS)) * 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;
+ }
+
+ ImageP mImage;
- GLuint mMode; ///< GL_RGB or GL_RGBA.
- GLuint mMinFilter; ///< Minifcation filter.
+ GLuint mMinFilter; ///< Minification filter.
GLuint mMagFilter; ///< Magnification filter.
GLuint mWrapS; ///< Wrapping behavior horizontally.
GLuint mWrapT; ///< Wrapping behavior vertically.
+ unsigned mTilesS;
+ unsigned mTilesT;
GLuint mObject; ///< GL texture handle.
static GLuint gObject; ///< Global GL texture handle.
Texture::Texture(const std::string& name) :
+ Image(Texture::getPath(name)),
// pass through
mImpl(Texture::Impl::getInstance(name)) {}
}
-unsigned Texture::getWidth() const
-{
- // pass through
- return mImpl->mWidth;
-}
-
-unsigned Texture::getHeight() const
-{
- // pass through
- return mImpl->mHeight;
-}
-
-
void Texture::setMinFilter(GLuint filter)
{
// pass through
}
+bool Texture::getTileCoords(TileIndex index, Scalar coords[8]) const
+{
+ // pass through
+ return mImpl->getTileCoords(index, coords);
+}
+
+bool Texture::getTileCoords(TileIndex index, 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 Texture::getPath(const std::string& name)
{
- std::string path = Resource::getPath("textures/" + name + ".png");
- return path;
+ if (boost::find_last(name, ".png"))
+ {
+ return Resource::getPath(name);
+ }
+ else
+ {
+ std::string path("textures/");
+ path += name;
+ path += ".png";
+ return Resource::getPath(path);
+ }
}