#include "TextureResource.h" #include "../Log.h" #include "../platform.h" #include GLHEADER #include "../ImageIO.h" #include "../Renderer.h" std::map< TextureResource::TextureKeyType, std::weak_ptr > TextureResource::sTextureMap; TextureResource::TextureResource(const std::string& path, bool tile) : mTextureID(0), mPath(path), mTextureSize(Eigen::Vector2i::Zero()), mTile(tile) { reload(ResourceManager::getInstance()); } TextureResource::~TextureResource() { deinit(); } void TextureResource::unload(std::shared_ptr& rm) { deinit(); } void TextureResource::reload(std::shared_ptr& rm) { if(!mPath.empty()) initFromResource(rm->getFileData(mPath)); } void TextureResource::initFromResource(const ResourceData data) { //make sure we aren't going to leak an old texture deinit(); size_t width, height; std::vector imageRGBA = ImageIO::loadFromMemoryRGBA32(const_cast(data.ptr.get()), data.length, width, height); if(imageRGBA.size() == 0) { LOG(LogError) << "Could not initialize texture (invalid resource data)!"; return; } //now for the openGL texture stuff glGenTextures(1, &mTextureID); glBindTexture(GL_TEXTURE_2D, mTextureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageRGBA.data()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); const GLint wrapMode = mTile ? GL_REPEAT : GL_CLAMP_TO_EDGE; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode); mTextureSize << width, height; } void TextureResource::initFromMemory(const char* data, size_t length) { deinit(); size_t width, height; std::vector imageRGBA = ImageIO::loadFromMemoryRGBA32((const unsigned char*)(data), length, width, height); if(imageRGBA.size() == 0) { LOG(LogError) << "Could not initialize texture from memory (invalid data)!"; return; } //now for the openGL texture stuff glGenTextures(1, &mTextureID); glBindTexture(GL_TEXTURE_2D, mTextureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageRGBA.data()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); const GLint wrapMode = mTile ? GL_REPEAT : GL_CLAMP_TO_EDGE; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode); mTextureSize << width, height; } void TextureResource::deinit() { if(mTextureID != 0) { glDeleteTextures(1, &mTextureID); mTextureID = 0; } } Eigen::Vector2i TextureResource::getSize() const { return mTextureSize; } bool TextureResource::isTiled() const { return mTile; } void TextureResource::bind() const { if(mTextureID != 0) glBindTexture(GL_TEXTURE_2D, mTextureID); else LOG(LogError) << "Tried to bind uninitialized texture!"; } std::shared_ptr TextureResource::get(const std::string& path, bool tile) { std::shared_ptr& rm = ResourceManager::getInstance(); if(path.empty()) { std::shared_ptr tex(new TextureResource("", tile)); rm->addReloadable(tex); //make sure we get properly deinitialized even though we do nothing on reinitialization return tex; } TextureKeyType key(path, tile); auto foundTexture = sTextureMap.find(key); if(foundTexture != sTextureMap.end()) { if(!foundTexture->second.expired()) return foundTexture->second.lock(); } std::shared_ptr tex = std::shared_ptr(new TextureResource(path, tile)); sTextureMap[key] = std::weak_ptr(tex); rm->addReloadable(tex); return tex; }