From aa68511ad3d339be8c8f42fc6c083b696d8e687b Mon Sep 17 00:00:00 2001 From: Andrei Karas Date: Wed, 20 Jun 2012 00:34:39 +0300 Subject: Add delayed images load. Can work for now only in OpenGL modes. --- src/CMakeLists.txt | 2 ++ src/Makefile.am | 2 ++ src/actorsprite.cpp | 5 +-- src/animatedsprite.cpp | 52 +++++++++++++++++++++++++++-- src/animatedsprite.h | 16 +++++++++ src/animationdelayload.cpp | 63 +++++++++++++++++++++++++++++++++++ src/animationdelayload.h | 50 ++++++++++++++++++++++++++++ src/being.cpp | 2 +- src/game.cpp | 5 +++ src/resources/resourcemanager.cpp | 69 +++++++++++++++++++++++++++++++++++++-- src/resources/resourcemanager.h | 18 +++++++++- 11 files changed, 275 insertions(+), 9 deletions(-) create mode 100644 src/animationdelayload.cpp create mode 100644 src/animationdelayload.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4cb8bd869..cba2c3450 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -491,6 +491,8 @@ SET(SRCS actorspritemanager.h animatedsprite.cpp animatedsprite.h + animationdelayload.cpp + animationdelayload.h animationparticle.cpp animationparticle.h auctionmanager.cpp diff --git a/src/Makefile.am b/src/Makefile.am index 0bf3c056c..8b798adc0 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -507,6 +507,8 @@ manaplus_SOURCES += gui/widgets/avatarlistbox.cpp \ actorspritemanager.h \ animatedsprite.cpp \ animatedsprite.h \ + animationdelayload.cpp \ + animationdelayload.h \ animationparticle.cpp \ animationparticle.h \ auctionmanager.cpp \ diff --git a/src/actorsprite.cpp b/src/actorsprite.cpp index 7bd496d30..b78f6bb91 100644 --- a/src/actorsprite.cpp +++ b/src/actorsprite.cpp @@ -332,7 +332,7 @@ void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display, + combineDye2((*it)->sprite, color); int variant = (*it)->variant; - addSprite(AnimatedSprite::load(file, variant)); + addSprite(AnimatedSprite::delayedLoad(file, variant)); } // Ensure that something is shown, if desired @@ -340,7 +340,8 @@ void ActorSprite::setupSpriteDisplay(const SpriteDisplay &display, { if (display.image.empty()) { - addSprite(AnimatedSprite::load(paths.getStringValue("sprites") + addSprite(AnimatedSprite::delayedLoad( + paths.getStringValue("sprites") + paths.getStringValue("spriteErrorFile"))); } else diff --git a/src/animatedsprite.cpp b/src/animatedsprite.cpp index 1dc5b16c8..77ec69126 100644 --- a/src/animatedsprite.cpp +++ b/src/animatedsprite.cpp @@ -22,6 +22,7 @@ #include "animatedsprite.h" +#include "animationdelayload.h" #include "graphics.h" #include "logger.h" @@ -34,6 +35,8 @@ #include "debug.h" +bool AnimatedSprite::mEnableCache = false; + AnimatedSprite::AnimatedSprite(SpriteDef *sprite): mDirection(DIRECTION_DOWN), mLastTime(0), @@ -44,7 +47,8 @@ AnimatedSprite::AnimatedSprite(SpriteDef *sprite): mAnimation(nullptr), mFrame(nullptr), mNumber(100), - mNumber1(100) + mNumber1(100), + mDelayLoad(nullptr) { mAlpha = 1.0f; @@ -67,6 +71,20 @@ AnimatedSprite *AnimatedSprite::load(const std::string &filename, int variant) return as; } +AnimatedSprite *AnimatedSprite::delayedLoad(const std::string &filename, + int variant) +{ + if (!mEnableCache) + return load(filename, variant); + ResourceManager *resman = ResourceManager::getInstance(); + if (resman->getFromCache(filename, variant)) + return load(filename, variant); + + AnimatedSprite *as = new AnimatedSprite(nullptr); + as->setDelayLoad(filename, variant); + return as; +} + AnimatedSprite::~AnimatedSprite() { if (mSprite) @@ -74,6 +92,13 @@ AnimatedSprite::~AnimatedSprite() mSprite->decRef(); mSprite = nullptr; } + if (mDelayLoad) + { + mDelayLoad->clearSprite(); + ResourceManager::removeDelayLoad(mDelayLoad); + delete mDelayLoad; + mDelayLoad = nullptr; + } } bool AnimatedSprite::reset() @@ -94,7 +119,12 @@ bool AnimatedSprite::reset() bool AnimatedSprite::play(std::string spriteAction) { if (!mSprite) - return false; + { + if (!mDelayLoad) + return false; + mDelayLoad->setAction(spriteAction); + return true; + } Action *action = mSprite->getAction(spriteAction, mNumber); if (!action) @@ -343,3 +373,21 @@ bool AnimatedSprite::updateNumber(unsigned num) } return false; } + +void AnimatedSprite::setDelayLoad(const std::string &filename, + int variant) +{ + if (mDelayLoad) + { + mDelayLoad->clearSprite(); + ResourceManager::removeDelayLoad(mDelayLoad); + delete mDelayLoad; + } + mDelayLoad = new AnimationDelayLoad(filename, variant, this); + ResourceManager::addDelayedAnimation(mDelayLoad); +} + +void AnimatedSprite::clearDelayLoad() +{ + mDelayLoad = nullptr; +} diff --git a/src/animatedsprite.h b/src/animatedsprite.h index d28badfc1..4f4caff16 100644 --- a/src/animatedsprite.h +++ b/src/animatedsprite.h @@ -29,6 +29,7 @@ #include class Animation; +class AnimationDelayLoad; struct Frame; /** @@ -53,6 +54,9 @@ class AnimatedSprite : public Sprite static AnimatedSprite *load(const std::string &filename, int variant = 0); + static AnimatedSprite *delayedLoad(const std::string &filename, + int variant = 0); + virtual ~AnimatedSprite(); bool reset(); @@ -86,9 +90,19 @@ class AnimatedSprite : public Sprite bool updateNumber(unsigned num); + void clearDelayLoad(); + + void setSprite(SpriteDef *sprite) + { mSprite = sprite; } + + static void setEnableCache(bool b) + { mEnableCache = b; } + private: bool updateCurrentAnimation(unsigned int dt); + void setDelayLoad(const std::string &filename, int variant); + SpriteDirection mDirection; /**< The sprite direction. */ int mLastTime; /**< The last time update was called. */ @@ -101,6 +115,8 @@ class AnimatedSprite : public Sprite Frame *mFrame; /**< The currently active frame. */ unsigned mNumber; unsigned mNumber1; + AnimationDelayLoad *mDelayLoad; + static bool mEnableCache; }; #endif diff --git a/src/animationdelayload.cpp b/src/animationdelayload.cpp new file mode 100644 index 000000000..0ce50ec2c --- /dev/null +++ b/src/animationdelayload.cpp @@ -0,0 +1,63 @@ +/* + * 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 "animationdelayload.h" + +#include "animatedsprite.h" + +#include "resources/resourcemanager.h" + +#include "debug.h" + +AnimationDelayLoad::AnimationDelayLoad(const std::string &fileName, + int variant, AnimatedSprite *sprite) : + mFileName(fileName), + mVariant(variant), + mSprite(sprite), + mAction(SpriteAction::STAND) +{ +} + +AnimationDelayLoad::~AnimationDelayLoad() +{ + if (mSprite) + { + mSprite->clearDelayLoad(); + mSprite = nullptr; + } +} + +void AnimationDelayLoad::clearSprite() +{ + mSprite = nullptr; +} + +void AnimationDelayLoad::load() +{ + if (mSprite) + { + ResourceManager *resman = ResourceManager::getInstance(); + SpriteDef *s = resman->getSprite(mFileName, mVariant); + if (!s) + return; + mSprite->setSprite(s); + mSprite->play(mAction); + } +} diff --git a/src/animationdelayload.h b/src/animationdelayload.h new file mode 100644 index 000000000..b6b8a3321 --- /dev/null +++ b/src/animationdelayload.h @@ -0,0 +1,50 @@ +/* + * 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 ANIMATIONDELAYLOAD_H +#define ANIMATIONDELAYLOAD_H + +#include + +class AnimatedSprite; + +class AnimationDelayLoad +{ + public: + AnimationDelayLoad(const std::string &fileName, + int variant, AnimatedSprite *sprite); + + ~AnimationDelayLoad(); + + void clearSprite(); + + void load(); + + void setAction(std::string action) + { mAction = action; } + + private: + std::string mFileName; + int mVariant; + AnimatedSprite *mSprite; + std::string mAction; +}; + +#endif // ANIMATIONDELAYLOAD_H diff --git a/src/being.cpp b/src/being.cpp index 89aa5275d..740989993 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -1786,7 +1786,7 @@ void Being::setSprite(unsigned int slot, int id, std::string color, color = info.getDyeColorsString(colorId); filename = combineDye(filename, color); - equipmentSprite = AnimatedSprite::load( + equipmentSprite = AnimatedSprite::delayedLoad( paths.getStringValue("sprites") + filename); } diff --git a/src/game.cpp b/src/game.cpp index 8fdb2b230..75317edac 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -23,6 +23,7 @@ #include "game.h" #include "auctionmanager.h" +#include "animatedsprite.h" #include "channelmanager.h" #include "commandhandler.h" #include "effectmanager.h" @@ -386,6 +387,8 @@ Game::Game(): top->add(viewport); viewport->requestMoveToBottom(); + AnimatedSprite::setEnableCache(mainGraphics->getOpenGL()); + createGuiWindows(); windowMenu = new WindowMenu; @@ -569,6 +572,8 @@ void Game::slowLogic() killStats->recalcStats(); if (shopWindow) shopWindow->updateTimes(); + if (mainGraphics->getOpenGL()) + ResourceManager::delayedLoad(); PacketCounters::update(); // Handle network stuff diff --git a/src/resources/resourcemanager.cpp b/src/resources/resourcemanager.cpp index 37975cf16..16214661c 100644 --- a/src/resources/resourcemanager.cpp +++ b/src/resources/resourcemanager.cpp @@ -22,6 +22,7 @@ #include "resources/resourcemanager.h" +#include "animationdelayload.h" #include "client.h" #include "configuration.h" #include "logger.h" @@ -52,6 +53,7 @@ #include "debug.h" ResourceManager *ResourceManager::instance = nullptr; +DelayedAnim ResourceManager::mDelayedAnimations; ResourceManager::ResourceManager() : mOldestOrphan(0), @@ -354,8 +356,15 @@ bool ResourceManager::addResource(const std::string &idPath, return false; } -Resource *ResourceManager::get(const std::string &idPath, generator fun, - void *data) +Resource *ResourceManager::getFromCache(const std::string &filename, + int variant) +{ + std::stringstream ss; + ss << filename << "[" << variant << "]"; + return getFromCache(ss.str()); +} + +Resource *ResourceManager::getFromCache(const std::string &idPath) { // Check if the id exists, and return the value if it does. ResourceIterator resIter = mResources.find(idPath); @@ -376,8 +385,17 @@ Resource *ResourceManager::get(const std::string &idPath, generator fun, res->incRef(); return res; } + return nullptr; +} - Resource *resource = fun(data); +Resource *ResourceManager::get(const std::string &idPath, generator fun, + void *data) +{ + Resource *resource = getFromCache(idPath); + if (resource) + return resource; + + resource = fun(data); if (resource) { @@ -745,3 +763,48 @@ Image *ResourceManager::getRescaled(Image *image, int width, int height) Image *img = static_cast(get(idPath, RescaledLoader::load, &rl)); return img; } + +void ResourceManager::delayedLoad() +{ + static int loadTime = 0; + if (loadTime < cur_time) + { +// loadTime = tick_time + 10; + loadTime = tick_time; + + int k = 0; + DelayedAnimIter it = mDelayedAnimations.begin(); + DelayedAnimIter it_end = mDelayedAnimations.end(); + while (it != it_end && k < 1) + { + (*it)->load(); + AnimationDelayLoad *tmp = *it; + it = mDelayedAnimations.erase(it); + delete tmp; + k ++; + } + const int time2 = tick_time; +// if (time2 != loadTime) +// { +// logger->log("diff %d", time2 - loadTime); +// } + if (time2 > loadTime) + loadTime = time2 + (time2 - loadTime) * 2 + 10; +// loadTime += 10 - time2; + else + loadTime = time2 + 3; + } +} + +void ResourceManager::removeDelayLoad(AnimationDelayLoad *delayedLoad) +{ + for(DelayedAnimIter it = mDelayedAnimations.begin(), + it_end = mDelayedAnimations.end(); it != it_end; ++ it) + { + if (*it == delayedLoad) + { + mDelayedAnimations.erase(it); + return; + } + } +} diff --git a/src/resources/resourcemanager.h b/src/resources/resourcemanager.h index ca6bdb373..4900b7ce3 100644 --- a/src/resources/resourcemanager.h +++ b/src/resources/resourcemanager.h @@ -28,9 +28,11 @@ #include "utils/stringvector.h" #include +#include #include #include +class AnimationDelayLoad; class Image; class ImageSet; class Music; @@ -41,6 +43,9 @@ class SpriteDef; struct SDL_Surface; struct SDL_RWops; +typedef std::list DelayedAnim; +typedef DelayedAnim::iterator DelayedAnimIter; + /** * A class for loading and managing resources. */ @@ -139,6 +144,10 @@ class ResourceManager */ Resource *get(const std::string &idPath, generator fun, void *data); + Resource *getFromCache(const std::string &idPath); + + Resource *getFromCache(const std::string &filename, int variant); + /** * Loads a resource from a file and adds it to the resource map. * @@ -269,13 +278,19 @@ class ResourceManager void cleanOrphans(bool always = false); + static void addDelayedAnimation(AnimationDelayLoad *animation) + { mDelayedAnimations.push_back(animation); } + + static void delayedLoad(); + + static void removeDelayLoad(AnimationDelayLoad *delayedLoad); + private: /** * Deletes the resource after logging a cleanup message. */ static void cleanUp(Resource *resource); - static ResourceManager *instance; std::set deletedSurfaces; Resources mResources; @@ -284,6 +299,7 @@ class ResourceManager std::string mSelectedSkin; std::string mSkinName; bool mDestruction; + static DelayedAnim mDelayedAnimations; }; #endif -- cgit v1.2.3-60-g2f50