Files
GDevelop/Core/GDCore/Project/ImageManager.cpp
T
2016-07-12 11:34:14 +02:00

211 lines
7.2 KiB
C++

/*
* GDevelop Core
* Copyright 2008-2016 Florian Rival (Florian.Rival@gmail.com). All rights reserved.
* This project is released under the MIT License.
*/
#include "GDCore/Project/ImageManager.h"
#include "GDCore/Project/ResourcesManager.h"
#include "GDCore/Project/ResourcesLoader.h"
#include "GDCore/Tools/InvalidImage.h"
#include "GDCore/Project/ResourcesManager.h"
#include <SFML/OpenGL.hpp>
#if !defined(ANDROID)
#include <GL/glu.h>
#endif
#undef LoadImage //thx windows.h
namespace gd
{
ImageManager::ImageManager() :
resourcesManager(NULL)
{
#if !defined(EMSCRIPTEN)
badTexture = std::shared_ptr<SFMLTextureWrapper>(new SFMLTextureWrapper);
badTexture->texture.loadFromMemory(gd::InvalidImageData, sizeof(gd::InvalidImageData));
badTexture->texture.setSmooth(false);
badTexture->image = badTexture->texture.copyToImage();
#endif
}
std::shared_ptr<SFMLTextureWrapper> ImageManager::GetSFMLTexture(const gd::String & name) const
{
if ( !resourcesManager )
{
std::cout << "ImageManager has no ResourcesManager associated with.";
return badTexture;
}
if ( alreadyLoadedImages.find(name) != alreadyLoadedImages.end() && !alreadyLoadedImages.find(name)->second.expired() )
return alreadyLoadedImages.find(name)->second.lock();
std::cout << "ImageManager: Loading " << name << ".";
//Load only an image when necessary
try
{
ImageResource & image = dynamic_cast<ImageResource&>(resourcesManager->GetResource(name));
std::shared_ptr<SFMLTextureWrapper> texture(new SFMLTextureWrapper(ResourcesLoader::Get()->LoadSFMLTexture( image.GetFile() )));
texture->texture.setSmooth(image.smooth);
alreadyLoadedImages[name] = texture;
#if defined(GD_IDE_ONLY)
if ( preventUnloading ) unloadingPreventer.push_back(texture); //If unload prevention is activated, add the image to the list dedicated to prevent images from being unloaded.
#endif
return texture;
}
catch(...)
{
}
std::cout << " Resource not found." << std::endl;
return badTexture;
}
bool ImageManager::HasLoadedSFMLTexture(const gd::String & name) const
{
if ( alreadyLoadedImages.find(name) != alreadyLoadedImages.end() && !alreadyLoadedImages.find(name)->second.expired() )
return true;
return false;
}
void ImageManager::SetSFMLTextureAsPermanentlyLoaded(const gd::String & name, std::shared_ptr<SFMLTextureWrapper> & texture) const
{
if ( alreadyLoadedImages.find(name) == alreadyLoadedImages.end() || alreadyLoadedImages.find(name)->second.expired() )
alreadyLoadedImages[name] = texture;
if ( permanentlyLoadedImages.find(name) == permanentlyLoadedImages.end() )
permanentlyLoadedImages[name] = texture;
}
void ImageManager::ReloadImage(const gd::String & name) const
{
if ( !resourcesManager )
{
std::cout << "ImageManager has no ResourcesManager associated with.";
return;
}
//Verify if image is in memory. If not, it will be automatically reloaded when necessary.
if ( alreadyLoadedImages.find(name) == alreadyLoadedImages.end() || alreadyLoadedImages.find(name)->second.expired() ) return;
//Image still in memory, get it and update it.
std::shared_ptr<SFMLTextureWrapper> oldTexture = alreadyLoadedImages.find(name)->second.lock();
try
{
ImageResource & image = dynamic_cast<ImageResource&>(resourcesManager->GetResource(name));
std::cout << "ImageManager: Reload " << name << std::endl;
oldTexture->texture = ResourcesLoader::Get()->LoadSFMLTexture( image.GetFile() );
oldTexture->texture.setSmooth(image.smooth);
oldTexture->image = oldTexture->texture.copyToImage();
return;
}
catch(...) { /*The ressource is not an image*/ }
//Image not present anymore in image list.
std::cout << "ImageManager: " << name << " is not available anymore." << std::endl;
*oldTexture = *badTexture;
}
std::shared_ptr<OpenGLTextureWrapper> ImageManager::GetOpenGLTexture(const gd::String & name) const
{
if ( alreadyLoadedOpenGLTextures.find(name) != alreadyLoadedOpenGLTextures.end() && !alreadyLoadedOpenGLTextures.find(name)->second.expired() )
return alreadyLoadedOpenGLTextures.find(name)->second.lock();
std::cout << "Load OpenGL Texture" << name << std::endl;
std::shared_ptr<OpenGLTextureWrapper> texture = std::shared_ptr<OpenGLTextureWrapper>(new OpenGLTextureWrapper(GetSFMLTexture(name)));
alreadyLoadedOpenGLTextures[name] = texture;
return texture;
}
void ImageManager::LoadPermanentImages()
{
if ( !resourcesManager )
{
std::cout << "ImageManager has no ResourcesManager associated with.";
return;
}
//Create a new list of permanently loaded images but do not delete now the old list
//so as not to unload images that could be still present.
std::map < gd::String, std::shared_ptr<SFMLTextureWrapper> > newPermanentlyLoadedImages;
std::vector<gd::String> resources = resourcesManager->GetAllResourcesList();
for ( std::size_t i = 0;i <resources.size();i++ )
{
try
{
ImageResource & image = dynamic_cast<ImageResource&>(resourcesManager->GetResource(resources[i]));
if ( image.alwaysLoaded )
newPermanentlyLoadedImages[image.GetName()] = GetSFMLTexture(image.GetName());
}
catch(...) { /*The resource is not an image, we don't care about it.*/}
}
permanentlyLoadedImages = newPermanentlyLoadedImages;
}
#if defined(GD_IDE_ONLY)
void ImageManager::PreventImagesUnloading()
{
preventUnloading = true;
for (auto it = alreadyLoadedImages.begin();it != alreadyLoadedImages.end();++it)
{
std::shared_ptr<SFMLTextureWrapper> image = (it->second).lock();
if ( image != std::shared_ptr<SFMLTextureWrapper>() ) unloadingPreventer.push_back(image);
}
}
void ImageManager::EnableImagesUnloading()
{
preventUnloading = false;
unloadingPreventer.clear(); //Images which are not used anymore will thus be destroyed (As no shared pointer will be pointing to them).
}
#endif
}
SFMLTextureWrapper::SFMLTextureWrapper(const sf::Texture & texture_) :
texture(texture_),
image(texture.copyToImage())
{
}
SFMLTextureWrapper::SFMLTextureWrapper()
{
}
SFMLTextureWrapper::~SFMLTextureWrapper()
{
}
OpenGLTextureWrapper::OpenGLTextureWrapper(std::shared_ptr<SFMLTextureWrapper> sfmlTexture_)
{
sfmlTexture = sfmlTexture_;
#if !defined(ANDROID) //TODO: OpenGL
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, sfmlTexture->image.getSize().x, sfmlTexture->image.getSize().y, GL_RGBA, GL_UNSIGNED_BYTE, sfmlTexture->image.getPixelsPtr());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
#endif
}
OpenGLTextureWrapper::~OpenGLTextureWrapper()
{
#if !defined(ANDROID) //TODO: OpenGL
glDeleteTextures(1, &texture);
#endif
};