From 135c19b4337e1ab45cff40a306eadc52a061ddef Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Mon, 13 Aug 2012 22:18:03 +0300 Subject: add atlas textures support. --- src/CMakeLists.txt | 2 + src/Makefile.am | 2 + src/client.cpp | 8 +- src/defaults.cpp | 1 + src/game.cpp | 1 + src/graphicsmanager.cpp | 9 +- src/graphicsmanager.h | 5 + src/map.cpp | 8 +- src/map.h | 5 + src/resources/atlasmanager.cpp | 302 ++++++++++++++++++++++++++++++++++++ src/resources/atlasmanager.h | 104 +++++++++++++ src/resources/image.h | 1 + src/resources/imagehelper.cpp | 3 +- src/resources/imagehelper.h | 7 +- src/resources/imageset.cpp | 10 ++ src/resources/mapdb.cpp | 13 ++ src/resources/mapdb.h | 5 + src/resources/mapreader.cpp | 12 ++ src/resources/openglimagehelper.cpp | 17 +- src/resources/openglimagehelper.h | 7 +- src/resources/resourcemanager.cpp | 28 ++++ src/resources/resourcemanager.h | 2 + src/resources/sdlimagehelper.cpp | 2 +- src/resources/sdlimagehelper.h | 2 +- src/utils/mathutils.h | 8 + 25 files changed, 541 insertions(+), 23 deletions(-) create mode 100644 src/resources/atlasmanager.cpp create mode 100644 src/resources/atlasmanager.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f8255c7a2..ea9de836b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -403,6 +403,8 @@ SET(SRCS resources/ambientlayer.h resources/animation.cpp resources/animation.h + resources/atlasmanager.cpp + resources/atlasmanager.h resources/beinginfo.cpp resources/beinginfo.h resources/chardb.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 35ec3f0a0..38a0f4181 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -407,6 +407,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ resources/ambientlayer.h \ resources/animation.cpp \ resources/animation.h \ + resources/atlasmanager.cpp \ + resources/atlasmanager.h \ resources/beinginfo.cpp \ resources/beinginfo.h \ resources/chardb.cpp \ diff --git a/src/client.cpp b/src/client.cpp index d034df76e..8a3f6f026 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -531,15 +531,10 @@ void Client::gameInit() SDLImageHelper::SDLSetEnableAlphaCache(config.getBoolValue("alphaCache")); ImageHelper::setEnableAlpha(config.getFloatValue("guialpha") != 1.0f); #endif - graphicsManager.initGraphics(mOptions.noOpenGL); - runCounters = config.getBoolValue("packetcounters"); - applyVSync(); - graphicsManager.setVideoMode(); - applyGrabMode(); applyGamma(); @@ -730,6 +725,9 @@ void Client::gameClear() delete mainGraphics; mainGraphics = nullptr; + if (imageHelper != sdlImageHelper) + delete sdlImageHelper; + sdlImageHelper = nullptr; delete imageHelper; imageHelper = nullptr; diff --git a/src/defaults.cpp b/src/defaults.cpp index 024521d62..3f92d60ce 100644 --- a/src/defaults.cpp +++ b/src/defaults.cpp @@ -262,6 +262,7 @@ DefaultsData* getConfigDefaults() AddDEF("enableDelayedAnimations", true); AddDEF("enableCompoundSpriteDelay", true); AddDEF("npcfontSize", 13); + AddDEF("useAtlases", true); return configData; } diff --git a/src/game.cpp b/src/game.cpp index 69c0e3fdc..2ebda2032 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -426,6 +426,7 @@ Game::Game(): if (guildManager && GuildManager::getEnableGuildBot()) guildManager->requestGuildInfo(); + DepricatedEvent::trigger(CHANNEL_GAME, DepricatedEvent(EVENT_CONSTRUCTED)); } diff --git a/src/graphicsmanager.cpp b/src/graphicsmanager.cpp index 2d2740023..d10b5de9e 100644 --- a/src/graphicsmanager.cpp +++ b/src/graphicsmanager.cpp @@ -55,7 +55,8 @@ GraphicsManager::GraphicsManager() : mMajor(0), mPlatformMinor(0), mPlatformMajor(0), - mMaxVertices(500) + mMaxVertices(500), + mUseAtlases(false) { } @@ -174,21 +175,27 @@ void GraphicsManager::initGraphics(bool noOpenGL) { case 0: imageHelper = new SDLImageHelper; + sdlImageHelper = imageHelper; mainGraphics = new Graphics; break; case 1: default: imageHelper = new OpenGLImageHelper; + sdlImageHelper = new SDLImageHelper; mainGraphics = new NormalOpenGLGraphics; break; case 2: imageHelper = new OpenGLImageHelper; + sdlImageHelper = new SDLImageHelper; mainGraphics = new SafeOpenGLGraphics; break; }; + mUseAtlases = imageHelper->useOpenGL() + && config.getBoolValue("useAtlases"); #else // Create the graphics context imageHelper = new SDLImageHelper; + sdlImageHelper = imageHelper; mainGraphics = new Graphics; #endif } diff --git a/src/graphicsmanager.h b/src/graphicsmanager.h index 8799d681e..84523d19f 100644 --- a/src/graphicsmanager.h +++ b/src/graphicsmanager.h @@ -78,6 +78,9 @@ class GraphicsManager final int getMaxVertices() const { return mMaxVertices; } + bool getUseAtlases() const + { return mUseAtlases; } + private: std::set mExtensions; @@ -94,6 +97,8 @@ class GraphicsManager final int mPlatformMajor; int mMaxVertices; + + bool mUseAtlases; }; extern GraphicsManager graphicsManager; diff --git a/src/map.cpp b/src/map.cpp index 71d0f5ee4..e68f063d9 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -159,7 +159,8 @@ Map::Map(const int width, const int height, mDrawScrollY(-1), mRedrawMap(true), mBeingOpacity(false), - mCustom(false) + mCustom(false), + mAtlas(nullptr) { const int size = mWidth * mHeight; for (int i = 0; i < NB_BLOCKTYPES; i++) @@ -200,6 +201,11 @@ Map::~Map() delete mObjects; mObjects = nullptr; delete_all(mMapPortals); + if (mAtlas) + { + mAtlas->decRef(); + mAtlas = nullptr; + } } void Map::optionChanged(const std::string &value) diff --git a/src/map.h b/src/map.h index 4892bc590..0dbfbd44f 100644 --- a/src/map.h +++ b/src/map.h @@ -35,6 +35,7 @@ class Animation; class AmbientLayer; class MapLayer; class Particle; +class Resource; class SimpleAnimation; class Tileset; class SpecialLayer; @@ -395,6 +396,9 @@ class Map final : public Properties, public ConfigListener std::map &getTileAnimations() { return mTileAnimations; } + void setAtlas(Resource *atlas) + { mAtlas = atlas; } + protected: friend class Actor; friend class Minimap; @@ -503,6 +507,7 @@ class Map final : public Properties, public ConfigListener bool mRedrawMap; bool mBeingOpacity; bool mCustom; + Resource *mAtlas; }; #endif diff --git a/src/resources/atlasmanager.cpp b/src/resources/atlasmanager.cpp new file mode 100644 index 000000000..770e43412 --- /dev/null +++ b/src/resources/atlasmanager.cpp @@ -0,0 +1,302 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "main.h" + +#ifdef USE_OPENGL + +#include "resources/atlasmanager.h" +#include "resources/openglimagehelper.h" + +#include "client.h" +#include "graphics.h" +#include "graphicsmanager.h" +#include "logger.h" + +#include "utils/mathutils.h" +#include "utils/physfsrwops.h" + +#include "resources/fboinfo.h" +#include "resources/imagehelper.h" +#include "resources/imagewriter.h" +#include "resources/resourcemanager.h" + +#include "debug.h" + +AtlasManager::AtlasManager() +{ +} + +AtlasResource *AtlasManager::loadTextureAtlas(const std::string &name, + const StringVect &files) +{ + std::vector atlases; + std::vector images; + AtlasResource *resource = new AtlasResource; + + loadImages(files, images); + int maxSize = OpenGLImageHelper::getTextureSize(); +// int maxSize = 1024; + + // sorting images on atlases. + simpleSort(name, atlases, images, maxSize); + + int k = 0; + for (std::vector::iterator it = atlases.begin(), + it_end = atlases.end(); it != it_end; ++ it) + { + TextureAtlas *atlas = *it; + if (!atlas) + continue; + + // create atlas base on sorted images + SDL_Surface *surface = createSDLAtlas(atlas); + + if (!surface) + continue; + + // debug save + ImageWriter::writePNG(surface, Client::getTempDirectory() + + "/atlas" + name + toString(k) + ".png"); + k ++; + + // covert SDL images to OpenGL + convertAtlas(atlas); + + // free SDL atlas surface + SDL_FreeSurface(surface); + + resource->atlases.push_back(atlas); + } + + return resource; +} + +void AtlasManager::loadImages(const StringVect &files, + std::vector &images) +{ + for (StringVectCIter it = files.begin(), it_end = files.end(); + it != it_end; ++ it) + { + const std::string str = *it; + SDL_RWops *rw = PHYSFSRWOPS_openRead(str.c_str()); + Image *image = sdlImageHelper->load(rw); + if (image) + { + image->mIdPath = str; + images.push_back(image); + } + } +} + +void AtlasManager::simpleSort(const std::string &name, + std::vector &atlases, + std::vector &images, int size) +{ + int x = 0; + int y = 0; + int tempHeight = 0; + TextureAtlas *atlas = new TextureAtlas(); + std::vector::iterator it = images.begin(); + const std::vector::const_iterator it_end = images.end(); + for (it = images.begin(); it != it_end; ++ it) + { + Image *img = *it; + if (img) + { + atlas->name = "atlas_" + name + "_" + img->getIdPath(); + break; + } + } + + for (it = images.begin(); it != it_end; ++ it) + { + Image *img = *it; + if (img) + { + AtlasItem *item = new AtlasItem(img); + item->name = img->getIdPath(); + // start next line + if (x + img->mBounds.w > size) + { + x = 0; + y += tempHeight; + tempHeight = 0; + } + + // cant put image with this height + if (y + img->mBounds.h > size) + { + x = 0; + y = 0; + atlases.push_back(atlas); + atlas = new TextureAtlas(); + atlas->name = "atlas_" + name + "_" + img->getIdPath(); + } + + if (img->mBounds.h > tempHeight) + tempHeight = img->mBounds.h; + + logger->log("image draw position: %d,%d (%d,%d)", + x, y, img->mBounds.w, img->mBounds.h); + item->x = x; + item->y = y; + atlas->items.push_back(item); + + // continue put textures in line + x += img->mBounds.w; + if (x > atlas->width) + atlas->width = x; + if (y + img->mBounds.h > atlas->height) + atlas->height = y + img->mBounds.h; + } + } + if (!atlas->items.empty()) + atlases.push_back(atlas); + else + delete atlas; +} + +SDL_Surface *AtlasManager::createSDLAtlas(TextureAtlas *atlas) +{ +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + const int rmask = 0xff000000; + const int gmask = 0x00ff0000; + const int bmask = 0x0000ff00; + const int amask = 0x000000ff; +#else + const int rmask = 0x000000ff; + const int gmask = 0x0000ff00; + const int bmask = 0x00ff0000; + const int amask = 0xff000000; +#endif + + // do not create atlas based on only one image + if (atlas->items.size() == 1) + return nullptr; + + // using only power of two sizes. + atlas->width = powerOfTwo(atlas->width); + atlas->height = powerOfTwo(atlas->height); + + // temp SDL surface for atlas + SDL_Surface *surface = SDL_CreateRGBSurface(SDL_SWSURFACE, + atlas->width, atlas->height, 32, rmask, gmask, bmask, amask); + + if (!surface) + return nullptr; + + Graphics *graphics = new Graphics(); + graphics->setTarget(surface); + graphics->_beginDraw(); + + // drawing SDL images to surface + for (std::vector::iterator it = atlas->items.begin(), + it_end = atlas->items.end(); + it != it_end; ++ it) + { + AtlasItem *item = *it; + Image *image = item->image; + + if (image) + { + SDL_SetAlpha(image->mSDLSurface, 0, SDL_ALPHA_OPAQUE); + graphics->drawImage(image, item->x, item->y); + } + } + + delete graphics; + atlas->surface = surface; + return surface; +} + +void AtlasManager::convertAtlas(TextureAtlas *atlas) +{ + // convert surface to OpemGL image + atlas->atlasImage = imageHelper->load(atlas->surface); + Image *const image = atlas->atlasImage; + + for (std::vector::iterator it = atlas->items.begin(), + it_end = atlas->items.end(); + it != it_end; ++ it) + { + AtlasItem *const item = *it; + // delete SDL Image + delete item->image; + // store OpenGL image + item->image = image->getSubImage(item->x, item->y, + item->width, item->height); + } +} + +void AtlasManager::injectToResources(AtlasResource *resource) +{ + ResourceManager *const resman = ResourceManager::getInstance(); + int k = 0; + for (std::vector::iterator it = resource->atlases.begin(), + it_end = resource->atlases.end(); it != it_end; ++ it, k ++) + { + // add each atlas image to resources + TextureAtlas *const atlas = *it; + resman->addResource(atlas->name, atlas->atlasImage); + if (atlas) + { + for (std::vector::iterator it2 = atlas->items.begin(), + it2_end = atlas->items.end(); + it2 != it2_end; ++ it2) + { + AtlasItem *const item = *it2; + // add each atlas sub image to resources + resman->addResource(item->name, item->image); + } + } + } +} + +AtlasResource::~AtlasResource() +{ + for (std::vector::iterator it = atlases.begin(), + it_end = atlases.end(); it != it_end; ++ it) + { + TextureAtlas *const atlas = *it; + if (atlas) + { + for (std::vector::iterator it2 = atlas->items.begin(), + it2_end = atlas->items.end(); + it2 != it2_end; ++ it2) + { + AtlasItem *const item = *it2; + if (item) + { + Image *const image = item->image; + if (image) + image->decRef(); + delete item; + } + } + Image *const image = atlas->atlasImage; + if (image) + image->decRef(); + delete atlas; + } + } +} + +#endif diff --git a/src/resources/atlasmanager.h b/src/resources/atlasmanager.h new file mode 100644 index 000000000..41aae86e5 --- /dev/null +++ b/src/resources/atlasmanager.h @@ -0,0 +1,104 @@ +/* + * The ManaPlus Client + * Copyright (C) 2012 The ManaPlus Developers + * + * This file is part of The ManaPlus Client. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef ATLASMANAGER_H +#define ATLASMANAGER_H + +#ifdef USE_OPENGL + +#include "resources/image.h" + +#include "utils/stringvector.h" + +#include + +class Resource; + +struct AtlasItem +{ + AtlasItem(Image *image0) : + image(image0), + x(0), + y(0), + width(image0->mBounds.w), + height(image0->mBounds.h) + { + } + + Image *image; + std::string name; + int x; + int y; + int width; + int height; +}; + +struct TextureAtlas +{ + TextureAtlas() : + atlasImage(nullptr), + surface(nullptr), + width(0), + height(0) + { + } + + std::string name; + Image *atlasImage; + SDL_Surface *surface; + int width; + int height; + std::vector items; +}; + +class AtlasResource : public Resource +{ + public: + ~AtlasResource(); + + std::vector atlases; +}; + +class AtlasManager +{ + public: + AtlasManager(); + + static AtlasResource *loadTextureAtlas(const std::string &name, + const StringVect &files); + + static void injectToResources(AtlasResource *resource); + + private: + static void loadImages(const StringVect &files, + std::vector &images); + + static void simpleSort(const std::string &name, + std::vector &atlases, + std::vector &images, int size); + + static SDL_Surface *createSDLAtlas(TextureAtlas *atlas); + + + static void convertAtlas(TextureAtlas *atlas); +}; + +#endif +#endif diff --git a/src/resources/image.h b/src/resources/image.h index 11d3828fd..8fafc87aa 100644 --- a/src/resources/image.h +++ b/src/resources/image.h @@ -59,6 +59,7 @@ class Image : public Resource friend class OpenGLImageHelper; friend class SDLImageHelper; #ifdef USE_OPENGL + friend class AtlasManager; friend class NormalOpenGLGraphics; friend class SafeOpenGLGraphics; #endif diff --git a/src/resources/imagehelper.cpp b/src/resources/imagehelper.cpp index 7ddf3221a..d2d0a78ed 100644 --- a/src/resources/imagehelper.cpp +++ b/src/resources/imagehelper.cpp @@ -37,10 +37,11 @@ #include "debug.h" ImageHelper *imageHelper = nullptr; +ImageHelper *sdlImageHelper = nullptr; bool ImageHelper::mEnableAlpha = true; -Resource *ImageHelper::load(SDL_RWops *const rw) +Image *ImageHelper::load(SDL_RWops *const rw) { SDL_Surface *const tmpImage = IMG_Load_RW(rw, 1); diff --git a/src/resources/imagehelper.h b/src/resources/imagehelper.h index 27132b7d9..fdda3b00f 100644 --- a/src/resources/imagehelper.h +++ b/src/resources/imagehelper.h @@ -54,10 +54,10 @@ class ImageHelper * @return NULL if an error occurred, a valid pointer * otherwise. */ - Resource *load(SDL_RWops *const rw); + Image *load(SDL_RWops *const rw); #ifdef __GNUC__ - virtual Resource *load(SDL_RWops *rw, Dye const &dye) = 0; + virtual Image *load(SDL_RWops *rw, Dye const &dye) = 0; virtual Image *load(SDL_Surface *) = 0; @@ -66,7 +66,7 @@ class ImageHelper virtual int useOpenGL() = 0; #else - virtual Resource *load(SDL_RWops *rw, Dye const &dye) + virtual Image *load(SDL_RWops *rw, Dye const &dye) { return nullptr; } virtual Image *load(SDL_Surface *) @@ -92,4 +92,5 @@ class ImageHelper }; extern ImageHelper *imageHelper; +extern ImageHelper *sdlImageHelper; #endif diff --git a/src/resources/imageset.cpp b/src/resources/imageset.cpp index 2e10f74a2..6876a7b14 100644 --- a/src/resources/imageset.cpp +++ b/src/resources/imageset.cpp @@ -55,6 +55,16 @@ ImageSet::ImageSet(Image *const img, const int width, const int height, ImageSet::~ImageSet() { delete_all(mImages); +/* + for (std::vector::iterator it = mImages.begin(), + it_end = mImages.end(); it != it_end; ++ it) + { + Image *image = *it; + if (image) + image->decRef(); + } + mImages.clear(); +*/ } Image* ImageSet::get(const size_type i) const diff --git a/src/resources/mapdb.cpp b/src/resources/mapdb.cpp index 55c3d7306..2b2beed89 100644 --- a/src/resources/mapdb.cpp +++ b/src/resources/mapdb.cpp @@ -149,3 +149,16 @@ std::string MapDB::getMapName(const std::string &name) return it->second; return name; } + +MapDB::MapInfo *MapDB::getMapAtlas(const std::string &name) +{ + MapInfoIter it = mInfos.find(name); + if (it == mInfos.end()) + return nullptr; + MapInfo *const info = &(*it).second; + AtlasIter it2 = mAtlases.find(info->atlas); + if (it2 == mAtlases.end()) + return nullptr; + info->files = &((*it2).second); + return info; +} diff --git a/src/resources/mapdb.h b/src/resources/mapdb.h index b8fd954fa..32e9f5695 100644 --- a/src/resources/mapdb.h +++ b/src/resources/mapdb.h @@ -34,6 +34,7 @@ namespace MapDB struct MapInfo { std::string atlas; + StringVect *files; }; /** @@ -52,13 +53,17 @@ namespace MapDB std::string getMapName(const std::string &name); + MapInfo *getMapAtlas(const std::string &name); + // Maps DB typedef std::map Maps; typedef Maps::iterator MapIterator; // map to infos map typedef std::map MapInfos; + typedef MapInfos::iterator MapInfoIter; // atlas to files map typedef std::map Atlases; + typedef Atlases::iterator AtlasIter; } #endif diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index db53e6518..f81741227 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -24,7 +24,9 @@ #include "client.h" #include "configuration.h" +#include "graphicsmanager.h" #include "logger.h" +#include "main.h" #include "map.h" #include "maplayer.h" #include "tileset.h" @@ -252,6 +254,7 @@ Map *MapReader::readMap(XmlNodePtr node, const std::string &path) // Take the filename off the path const std::string pathDir = path.substr(0, path.rfind("/") + 1); + const std::string fileName = path.substr(path.rfind("/") + 1); const int w = XML::getProperty(node, "width", 0); const int h = XML::getProperty(node, "height", 0); @@ -272,6 +275,15 @@ Map *MapReader::readMap(XmlNodePtr node, const std::string &path) Map *const map = new Map(w, h, tilew, tileh); +#ifdef USE_OPENGL + if (graphicsManager.getUseAtlases()) + { + const MapDB::MapInfo *const info = MapDB::getMapAtlas(fileName); + map->setAtlas(ResourceManager::getInstance()->getAtlas( + info->atlas, *info->files)); + } +#endif + for_each_xml_child_node(childNode, node) { if (xmlNameEqual(childNode, "tileset")) diff --git a/src/resources/openglimagehelper.cpp b/src/resources/openglimagehelper.cpp index 2ae819a11..8aed5330e 100644 --- a/src/resources/openglimagehelper.cpp +++ b/src/resources/openglimagehelper.cpp @@ -24,19 +24,19 @@ #ifdef USE_OPENGL -#include "resources/dye.h" -#include "resources/resourcemanager.h" - +#include "client.h" +#include "game.h" +#include "graphicsmanager.h" +#include "logger.h" #include "normalopenglgraphics.h" #include "safeopenglgraphics.h" -#include "client.h" -#include "logger.h" +#include "resources/dye.h" +#include "resources/image.h" +#include "resources/resourcemanager.h" #include "utils/stringutils.h" -#include "resources/image.h" - #include #include @@ -48,7 +48,7 @@ int OpenGLImageHelper::mTextureSize = 0; bool OpenGLImageHelper::mBlur = true; int OpenGLImageHelper::mUseOpenGL = 0; -Resource *OpenGLImageHelper::load(SDL_RWops *const rw, Dye const &dye) +Image *OpenGLImageHelper::load(SDL_RWops *const rw, Dye const &dye) { SDL_Surface *const tmpImage = IMG_Load_RW(rw, 1); @@ -300,5 +300,4 @@ int OpenGLImageHelper::useOpenGL() { return mUseOpenGL; } - #endif diff --git a/src/resources/openglimagehelper.h b/src/resources/openglimagehelper.h index c93216e12..292e18138 100644 --- a/src/resources/openglimagehelper.h +++ b/src/resources/openglimagehelper.h @@ -26,6 +26,8 @@ #include "localconsts.h" #include "main.h" +#include "utils/stringvector.h" + #include "resources/imagehelper.h" #include @@ -67,7 +69,7 @@ class OpenGLImageHelper final : public ImageHelper * @return NULL if an error occurred, a valid pointer * otherwise. */ - Resource *load(SDL_RWops *const rw, Dye const &dye); + Image *load(SDL_RWops *const rw, Dye const &dye); /** * Loads an image from an SDL surface. @@ -107,6 +109,9 @@ class OpenGLImageHelper final : public ImageHelper */ int useOpenGL(); + static int getTextureSize() + { return mTextureSize; } + protected: /** * Returns the first power of two equal or bigger than the input. diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 9f2947dfc..5270e6f60 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -27,11 +27,13 @@ #include "configuration.h" #include "logger.h" +#include "resources/atlasmanager.h" #include "resources/dye.h" #include "resources/image.h" #include "resources/imagehelper.h" #include "resources/imageset.h" #include "resources/music.h" +#include "resources/openglimagehelper.h" #include "resources/soundeffect.h" #include "resources/spritedef.h" @@ -652,6 +654,32 @@ Image *ResourceManager::getSubImage(Image *const parent, return static_cast(get(ss.str(), SubImageLoader::load, &rl)); } +struct AtlasLoader +{ + const std::string name; + const StringVect *files; + + static Resource *load(const void *const v) + { + if (!v) + return nullptr; + + const AtlasLoader *const rl = static_cast(v); + AtlasResource *const resource = AtlasManager::loadTextureAtlas( + rl->name, *rl->files); + AtlasManager::injectToResources(resource); + return resource; + } +}; + +Resource *ResourceManager::getAtlas(const std::string &name, + const StringVect &files) +{ + AtlasLoader rl = { name, &files }; + + return get("atlas_" + name, AtlasLoader::load, &rl); +} + struct SpriteDefLoader { std::string path; diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h index e20e4b3ac..551b00a33 100644 --- a/src/resources/resourcemanager.h +++ b/src/resources/resourcemanager.h @@ -212,6 +212,8 @@ class ResourceManager final Image *getSubImage(Image *const parent, const int x, const int y, const int width, const int height); + Resource *getAtlas(const std::string &name, const StringVect &files); + /** * Creates a sprite definition based on a given path and the supplied * variant. diff --git a/src/resources/sdlimagehelper.cpp b/src/resources/sdlimagehelper.cpp index 5c02d0e2e..a5423bc62 100644 --- a/src/resources/sdlimagehelper.cpp +++ b/src/resources/sdlimagehelper.cpp @@ -38,7 +38,7 @@ bool SDLImageHelper::mEnableAlphaCache = false; -Resource *SDLImageHelper::load(SDL_RWops *const rw, Dye const &dye) +Image *SDLImageHelper::load(SDL_RWops *const rw, Dye const &dye) { SDL_Surface *const tmpImage = IMG_Load_RW(rw, 1); diff --git a/src/resources/sdlimagehelper.h b/src/resources/sdlimagehelper.h index 2742755c2..6884af28d 100644 --- a/src/resources/sdlimagehelper.h +++ b/src/resources/sdlimagehelper.h @@ -52,7 +52,7 @@ class SDLImageHelper final : public ImageHelper * @return NULL if an error occurred, a valid pointer * otherwise. */ - Resource *load(SDL_RWops *const rw, Dye const &dye); + Image *load(SDL_RWops *const rw, Dye const &dye); /** * Loads an image from an SDL surface. diff --git a/src/utils/mathutils.h b/src/utils/mathutils.h index 7e43a3574..60f96729d 100644 --- a/src/utils/mathutils.h +++ b/src/utils/mathutils.h @@ -119,4 +119,12 @@ inline int roundDouble(const double v) return (v > 0.0) ? (v + 0.5) : (v - 0.5); } +inline int powerOfTwo(int input) +{ + int value = 1; + while (value < input) + value <<= 1; + return value; +} + #endif // UTILS_MATHUTILS_H -- cgit v1.2.3-60-g2f50