/* * 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 #include "GDCore/Project/ResourcesLoader.h" #include "GDCore/Project/ResourcesManager.h" #include "GDCore/Tools/InvalidImage.h" #if !defined(ANDROID) && !defined(MACOS) #include #endif #undef LoadImage // thx windows.h namespace gd { ImageManager::ImageManager() : resourcesManager(NULL) { #if !defined(EMSCRIPTEN) badTexture = std::make_shared(); badTexture->texture.loadFromMemory(gd::InvalidImageData, sizeof(gd::InvalidImageData)); badTexture->texture.setSmooth(false); badTexture->image = badTexture->texture.copyToImage(); #endif } std::shared_ptr 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(resourcesManager->GetResource(name)); auto texture = std::make_shared(); ResourcesLoader::Get()->LoadSFMLImage(image.GetFile(), texture->image); texture->texture.loadFromImage(texture->image); 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& 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 oldTexture = alreadyLoadedImages.find(name)->second.lock(); try { ImageResource& image = dynamic_cast(resourcesManager->GetResource(name)); std::cout << "ImageManager: Reload " << name << std::endl; ResourcesLoader::Get()->LoadSFMLImage(image.GetFile(), oldTexture->image); oldTexture->texture.loadFromImage(oldTexture->image); oldTexture->texture.setSmooth(image.smooth); 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 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 texture = std::make_shared(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 > newPermanentlyLoadedImages; std::vector resources = resourcesManager->GetAllResourceNames(); for (std::size_t i = 0; i < resources.size(); i++) { try { ImageResource& image = dynamic_cast( 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 image = (it->second).lock(); if (image != std::shared_ptr()) 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 } // namespace gd SFMLTextureWrapper::SFMLTextureWrapper(const sf::Texture& texture_) : texture(texture_), image(texture.copyToImage()) {} SFMLTextureWrapper::SFMLTextureWrapper() {} SFMLTextureWrapper::~SFMLTextureWrapper() {} OpenGLTextureWrapper::OpenGLTextureWrapper( std::shared_ptr sfmlTexture_) { sfmlTexture = sfmlTexture_; #if !defined(ANDROID) // TODO: OpenGL glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); // glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, sfmlTexture->image.getSize().x, // sfmlTexture->image.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, // sfmlTexture->image.getPixelsPtr()); glGenerateMipmap(GL_TEXTURE_2D); 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 };