diff --git a/client/mapView/MapRenderer.cpp b/client/mapView/MapRenderer.cpp index b541b30e3..8c7509f80 100644 --- a/client/mapView/MapRenderer.cpp +++ b/client/mapView/MapRenderer.cpp @@ -115,14 +115,11 @@ void MapTileStorage::load(size_t index, const AnimationPath & filename, EImageBl entry->getImage(i)->setBlitMode(blitMode); } - for(size_t i = 0; i < terrainAnimations[0]->size(); ++i) - { - terrainAnimations[1]->getImage(i)->verticalFlip(); - terrainAnimations[3]->getImage(i)->verticalFlip(); + terrainAnimations[1]->verticalFlip(); + terrainAnimations[3]->verticalFlip(); - terrainAnimations[2]->getImage(i)->horizontalFlip(); - terrainAnimations[3]->getImage(i)->horizontalFlip(); - } + terrainAnimations[2]->horizontalFlip(); + terrainAnimations[3]->horizontalFlip(); } std::shared_ptr MapTileStorage::find(size_t fileIndex, size_t rotationIndex, size_t imageIndex) diff --git a/client/render/CAnimation.cpp b/client/render/CAnimation.cpp index 9feaf51a4..39e373eb9 100644 --- a/client/render/CAnimation.cpp +++ b/client/render/CAnimation.cpp @@ -12,7 +12,6 @@ #include "CDefFile.h" -#include "Graphics.h" #include "../../lib/filesystem/Filesystem.h" #include "../../lib/json/JsonUtils.h" #include "../renderSDL/SDLImage.h" @@ -179,8 +178,8 @@ void CAnimation::init() source[defEntry.first].resize(defEntry.second); } - if (vstd::contains(graphics->imageLists, name.getName())) - initFromJson(graphics->imageLists[name.getName()]); +// if (vstd::contains(graphics->imageLists, name.getName())) +// initFromJson(graphics->imageLists[name.getName()]); auto jsonResource = name.toType(); auto configList = CResourceHandler::get()->getResourcesWithName(jsonResource); diff --git a/client/render/CDefFile.cpp b/client/render/CDefFile.cpp index 23377c4e5..1c8670a09 100644 --- a/client/render/CDefFile.cpp +++ b/client/render/CDefFile.cpp @@ -18,50 +18,6 @@ #include -// Extremely simple file cache. TODO: smarter, more general solution -class CFileCache -{ - static const int cacheSize = 50; //Max number of cached files - struct FileData - { - AnimationPath name; - size_t size; - std::unique_ptr data; - - std::unique_ptr getCopy() - { - auto ret = std::unique_ptr(new ui8[size]); - std::copy(data.get(), data.get() + size, ret.get()); - return ret; - } - FileData(AnimationPath name_, size_t size_, std::unique_ptr data_): - name{std::move(name_)}, - size{size_}, - data{std::move(data_)} - {} - }; - - std::deque cache; -public: - std::unique_ptr getCachedFile(AnimationPath rid) - { - for(auto & file : cache) - { - if (file.name == rid) - return file.getCopy(); - } - // Still here? Cache miss - if (cache.size() > cacheSize) - cache.pop_front(); - - auto data = CResourceHandler::get()->load(rid)->readAll(); - - cache.emplace_back(std::move(rid), data.second, std::move(data.first)); - - return cache.back().getCopy(); - } -}; - enum class DefType : uint32_t { SPELL = 0x40, @@ -76,8 +32,6 @@ enum class DefType : uint32_t BATTLE_HERO = 0x49 }; -static CFileCache animationCache; - /************************************************************************* * DefFile, class used for def loading * *************************************************************************/ @@ -124,7 +78,7 @@ CDefFile::CDefFile(const AnimationPath & Name): {0, 0, 0, 64 } // shadow border below selection ( used in battle def's ) }; - data = animationCache.getCachedFile(Name); + data = CResourceHandler::get()->load(Name)->readAll().first; palette = std::unique_ptr(new SDL_Color[256]); int it = 0; diff --git a/client/render/Graphics.cpp b/client/render/Graphics.cpp index ad8f90d92..8399ff698 100644 --- a/client/render/Graphics.cpp +++ b/client/render/Graphics.cpp @@ -131,7 +131,6 @@ Graphics::Graphics() loadPaletteAndColors(); initializeBattleGraphics(); loadErmuToPicture(); - initializeImageLists(); //(!) do not load any CAnimation here } @@ -244,51 +243,3 @@ void Graphics::loadErmuToPicture() } assert (etp_idx == 44); } - -void Graphics::addImageListEntry(size_t index, size_t group, const std::string & listName, const std::string & imageName) -{ - if (!imageName.empty()) - { - JsonNode entry; - if (group != 0) - entry["group"].Integer() = group; - entry["frame"].Integer() = index; - entry["file"].String() = imageName; - - imageLists["SPRITES/" + listName]["images"].Vector().push_back(entry); - } -} - -void Graphics::addImageListEntries(const EntityService * service) -{ - auto cb = std::bind(&Graphics::addImageListEntry, this, _1, _2, _3, _4); - - auto loopCb = [&](const Entity * entity, bool & stop) - { - entity->registerIcons(cb); - }; - - service->forEachBase(loopCb); -} - -void Graphics::initializeImageLists() -{ - addImageListEntries(CGI->creatures()); - addImageListEntries(CGI->heroTypes()); - addImageListEntries(CGI->artifacts()); - addImageListEntries(CGI->factions()); - addImageListEntries(CGI->spells()); - addImageListEntries(CGI->skills()); -} - -std::shared_ptr Graphics::getAnimation(const AnimationPath & path) -{ - if (cachedAnimations.count(path) != 0) - return cachedAnimations.at(path); - - auto newAnimation = GH.renderHandler().loadAnimation(path); - - newAnimation->preload(); - cachedAnimations[path] = newAnimation; - return newAnimation; -} diff --git a/client/render/Graphics.h b/client/render/Graphics.h index 4170f8e1a..845b14e3b 100644 --- a/client/render/Graphics.h +++ b/client/render/Graphics.h @@ -34,20 +34,12 @@ class IFont; /// Handles fonts, hero images, town images, various graphics class Graphics { - void addImageListEntry(size_t index, size_t group, const std::string & listName, const std::string & imageName); - void addImageListEntries(const EntityService * service); - void initializeBattleGraphics(); void loadPaletteAndColors(); void loadErmuToPicture(); void loadFonts(); - void initializeImageLists(); - - std::map> cachedAnimations; public: - std::shared_ptr getAnimation(const AnimationPath & path); - //Fonts static const int FONTS_NUMBER = 9; std::array< std::shared_ptr, FONTS_NUMBER> fonts; @@ -61,8 +53,6 @@ public: PlayerPalette neutralColorPalette; ColorRGBA neutralColor; - std::map imageLists; - //towns std::map ERMUtoPicture[GameConstants::F_NUMBER]; //maps building ID to it's picture's name for each town type //for battles diff --git a/client/render/IRenderHandler.h b/client/render/IRenderHandler.h index 880295170..551c61ea2 100644 --- a/client/render/IRenderHandler.h +++ b/client/render/IRenderHandler.h @@ -26,6 +26,8 @@ public: virtual std::shared_ptr loadImage(const ImagePath & path) = 0; virtual std::shared_ptr loadImage(const ImagePath & path, EImageBlitMode mode) = 0; + virtual std::shared_ptr loadImage(const AnimationPath & path, int frame, int group) = 0; + /// temporary compatibility method. Creates IImage from existing SDL_Surface /// Surface will be shared, caller must still free it with SDL_FreeSurface virtual std::shared_ptr createImage(SDL_Surface * source) = 0; diff --git a/client/renderSDL/RenderHandler.cpp b/client/renderSDL/RenderHandler.cpp index 87eb99091..98a3e680a 100644 --- a/client/renderSDL/RenderHandler.cpp +++ b/client/renderSDL/RenderHandler.cpp @@ -10,9 +10,66 @@ #include "StdInc.h" #include "RenderHandler.h" -#include "../render/CAnimation.h" #include "SDLImage.h" +#include "../render/CAnimation.h" +#include "../render/CDefFile.h" + +#include "../../lib/json/JsonNode.h" + +std::shared_ptr RenderHandler::getAnimationFile(const AnimationPath & path) +{ + auto it = animationFiles.find(path); + + if (it != animationFiles.end()) + return it->second; + + auto result = std::make_shared(path); + + animationFiles[path] = result; + return result; +} + +std::shared_ptr RenderHandler::getJsonFile(const JsonPath & path) +{ + auto it = jsonFiles.find(path); + + if (it != jsonFiles.end()) + return it->second; + + auto result = std::make_shared(path); + + jsonFiles[path] = result; + return result; +} + +std::shared_ptr RenderHandler::loadImage(const AnimationPath & path, int frame, int group) +{ + AnimationLocator locator{path, frame, group}; + + auto it = animationFrames.find(locator); + if (it != animationFrames.end()) + return it->second; + + auto defFile = getAnimationFile(path); + auto result = std::make_shared(defFile.get(), frame, group); + + animationFrames[locator] = result; + return result; +} + +//std::vector> RenderHandler::loadImageGroup(const AnimationPath & path, int group) +//{ +// const auto defFile = getAnimationFile(path); +// +// size_t groupSize = defFile->getEntries().at(group); +// +// std::vector> result; +// for (size_t i = 0; i < groupSize; ++i) +// loadImage(path, i, group); +// +// return result; +//} std::shared_ptr RenderHandler::loadImage(const ImagePath & path) { @@ -38,3 +95,52 @@ std::shared_ptr RenderHandler::createAnimation() { return std::make_shared(); } + +// +//void Graphics::addImageListEntry(size_t index, size_t group, const std::string & listName, const std::string & imageName) +//{ +// if (!imageName.empty()) +// { +// JsonNode entry; +// if (group != 0) +// entry["group"].Integer() = group; +// entry["frame"].Integer() = index; +// entry["file"].String() = imageName; +// +// imageLists["SPRITES/" + listName]["images"].Vector().push_back(entry); +// } +//} +// +//void Graphics::addImageListEntries(const EntityService * service) +//{ +// auto cb = std::bind(&Graphics::addImageListEntry, this, _1, _2, _3, _4); +// +// auto loopCb = [&](const Entity * entity, bool & stop) +// { +// entity->registerIcons(cb); +// }; +// +// service->forEachBase(loopCb); +//} +// +//void Graphics::initializeImageLists() +//{ +// addImageListEntries(CGI->creatures()); +// addImageListEntries(CGI->heroTypes()); +// addImageListEntries(CGI->artifacts()); +// addImageListEntries(CGI->factions()); +// addImageListEntries(CGI->spells()); +// addImageListEntries(CGI->skills()); +//} +// +//std::shared_ptr Graphics::getAnimation(const AnimationPath & path) +//{ +// if (cachedAnimations.count(path) != 0) +// return cachedAnimations.at(path); +// +// auto newAnimation = GH.renderHandler().loadAnimation(path); +// +// newAnimation->preload(); +// cachedAnimations[path] = newAnimation; +// return newAnimation; +//} diff --git a/client/renderSDL/RenderHandler.h b/client/renderSDL/RenderHandler.h index 76e30ee9c..1e6e7cc95 100644 --- a/client/renderSDL/RenderHandler.h +++ b/client/renderSDL/RenderHandler.h @@ -11,12 +11,39 @@ #include "../render/IRenderHandler.h" +class CDefFile; + class RenderHandler : public IRenderHandler { + struct AnimationLocator + { + AnimationPath animation; + int frame = -1; + int group = -1; + + bool operator < (const AnimationLocator & other) const + { + if (animation != other.animation) + return animation < other.animation; + if (group != other.group) + return group < other.group; + return frame < other.frame; + } + }; + + std::map> animationFiles; + std::map> jsonFiles; + std::map> imageFiles; + std::map> animationFrames; + + std::shared_ptr getAnimationFile(const AnimationPath & path); + std::shared_ptr getJsonFile(const JsonPath & path); public: std::shared_ptr loadImage(const ImagePath & path) override; std::shared_ptr loadImage(const ImagePath & path, EImageBlitMode mode) override; + std::shared_ptr loadImage(const AnimationPath & path, int frame, int group) override; + std::shared_ptr createImage(SDL_Surface * source) override; std::shared_ptr loadAnimation(const AnimationPath & path) override; diff --git a/client/widgets/CGarrisonInt.cpp b/client/widgets/CGarrisonInt.cpp index 6acf43b61..667cfdc22 100644 --- a/client/widgets/CGarrisonInt.cpp +++ b/client/widgets/CGarrisonInt.cpp @@ -17,7 +17,6 @@ #include "../gui/CGuiHandler.h" #include "../gui/WindowHandler.h" #include "../render/IImage.h" -#include "../render/Graphics.h" #include "../windows/CCreatureWindow.h" #include "../windows/CWindowWithArtifacts.h" #include "../windows/GUIClasses.h" @@ -437,10 +436,10 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt * Owner, int x, int y, SlotID IID, EGa AnimationPath imgName = AnimationPath::builtin(owner->smallIcons ? "cprsmall" : "TWCRPORT"); - creatureImage = std::make_shared(graphics->getAnimation(imgName), 0); + creatureImage = std::make_shared(imgName, 0); creatureImage->disable(); - selectionImage = std::make_shared(graphics->getAnimation(imgName), 1); + selectionImage = std::make_shared(imgName, 1); selectionImage->disable(); selectionImage->center(creatureImage->pos.center()); diff --git a/client/widgets/Images.cpp b/client/widgets/Images.cpp index 58f50dcda..66aa98c3c 100644 --- a/client/widgets/Images.cpp +++ b/client/widgets/Images.cpp @@ -19,7 +19,6 @@ #include "../render/CAnimation.h" #include "../render/Canvas.h" #include "../render/ColorFilter.h" -#include "../render/Graphics.h" #include "../battle/BattleInterface.h" #include "../battle/BattleInterfaceClasses.h" @@ -177,7 +176,7 @@ CAnimImage::CAnimImage(const AnimationPath & name, size_t Frame, size_t Group, i { pos.x += x; pos.y += y; - anim = graphics->getAnimation(name); + anim = GH.renderHandler().loadAnimation(name); init(); } diff --git a/client/widgets/MiscWidgets.cpp b/client/widgets/MiscWidgets.cpp index 1bdba2a75..d6d53038b 100644 --- a/client/widgets/MiscWidgets.cpp +++ b/client/widgets/MiscWidgets.cpp @@ -28,7 +28,6 @@ #include "../windows/CCastleInterface.h" #include "../windows/InfoWindows.h" #include "../render/Canvas.h" -#include "../render/Graphics.h" #include "../../CCallback.h" @@ -535,7 +534,7 @@ CreatureTooltip::CreatureTooltip(Point pos, const CGCreature * creature) auto creatureID = creature->getCreature(); int32_t creatureIconIndex = CGI->creatures()->getById(creatureID)->getIconIndex(); - creatureImage = std::make_shared(graphics->getAnimation(AnimationPath::builtin("TWCRPORT")), creatureIconIndex); + creatureImage = std::make_shared(AnimationPath::builtin("TWCRPORT"), creatureIconIndex); creatureImage->center(Point(parent->pos.x + parent->pos.w / 2, parent->pos.y + creatureImage->pos.h / 2 + 11)); bool isHeroSelected = LOCPLINT->localState->getCurrentHero() != nullptr; diff --git a/client/windows/CHeroOverview.cpp b/client/windows/CHeroOverview.cpp index 390d94674..81071598f 100644 --- a/client/windows/CHeroOverview.cpp +++ b/client/windows/CHeroOverview.cpp @@ -14,7 +14,6 @@ #include "../gui/CGuiHandler.h" #include "../render/Canvas.h" #include "../render/Colors.h" -#include "../render/Graphics.h" #include "../render/IImage.h" #include "../renderSDL/RenderHandler.h" #include "../widgets/CComponent.h"