mirror of https://github.com/axmolengine/axmol.git
SpriteFrameCache: keep plist filenames when trying to remove sprite (#19083)
This commit is contained in:
parent
d1e6b8ace9
commit
7770234367
|
@ -68,15 +68,13 @@ void SpriteFrameCache::destroyInstance()
|
|||
|
||||
bool SpriteFrameCache::init()
|
||||
{
|
||||
_spriteFrames.reserve(20);
|
||||
_spriteFramesAliases.reserve(20);
|
||||
_loadedFileNames = new std::set<std::string>();
|
||||
_spriteFramesCache.init();
|
||||
return true;
|
||||
}
|
||||
|
||||
SpriteFrameCache::~SpriteFrameCache()
|
||||
{
|
||||
CC_SAFE_DELETE(_loadedFileNames);
|
||||
}
|
||||
|
||||
void SpriteFrameCache::parseIntegerList(const std::string &string, std::vector<int> &res)
|
||||
|
@ -136,7 +134,7 @@ void SpriteFrameCache::initializePolygonInfo(const Size &textureSize,
|
|||
info.setRect(Rect(0, 0, spriteSize.width, spriteSize.height));
|
||||
}
|
||||
|
||||
void SpriteFrameCache::addSpriteFramesWithDictionary(ValueMap& dictionary, Texture2D* texture)
|
||||
void SpriteFrameCache::addSpriteFramesWithDictionary(ValueMap& dictionary, Texture2D* texture, const std::string &plist)
|
||||
{
|
||||
/*
|
||||
Supported Zwoptex Formats:
|
||||
|
@ -180,7 +178,7 @@ void SpriteFrameCache::addSpriteFramesWithDictionary(ValueMap& dictionary, Textu
|
|||
{
|
||||
ValueMap& frameDict = iter.second.asValueMap();
|
||||
std::string spriteFrameName = iter.first;
|
||||
SpriteFrame* spriteFrame = _spriteFrames.at(spriteFrameName);
|
||||
SpriteFrame* spriteFrame = _spriteFramesCache.at(spriteFrameName);
|
||||
if (spriteFrame)
|
||||
{
|
||||
continue;
|
||||
|
@ -293,12 +291,12 @@ void SpriteFrameCache::addSpriteFramesWithDictionary(ValueMap& dictionary, Textu
|
|||
texture->addSpriteFrameCapInset(spriteFrame, parser.parseCapInset());
|
||||
}
|
||||
// add sprite frame
|
||||
_spriteFrames.insert(spriteFrameName, spriteFrame);
|
||||
_spriteFramesCache.insertFrame(plist, spriteFrameName, spriteFrame);
|
||||
}
|
||||
CC_SAFE_DELETE(image);
|
||||
}
|
||||
|
||||
void SpriteFrameCache::addSpriteFramesWithDictionary(ValueMap& dict, const std::string &texturePath)
|
||||
void SpriteFrameCache::addSpriteFramesWithDictionary(ValueMap& dict, const std::string &texturePath, const std::string &plist)
|
||||
{
|
||||
std::string pixelFormatName;
|
||||
if (dict.find("metadata") != dict.end())
|
||||
|
@ -342,7 +340,7 @@ void SpriteFrameCache::addSpriteFramesWithDictionary(ValueMap& dict, const std::
|
|||
|
||||
if (texture)
|
||||
{
|
||||
addSpriteFramesWithDictionary(dict, texture);
|
||||
addSpriteFramesWithDictionary(dict, texture, plist);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -352,7 +350,7 @@ void SpriteFrameCache::addSpriteFramesWithDictionary(ValueMap& dict, const std::
|
|||
|
||||
void SpriteFrameCache::addSpriteFramesWithFile(const std::string& plist, Texture2D *texture)
|
||||
{
|
||||
if (_loadedFileNames->find(plist) != _loadedFileNames->end())
|
||||
if (_spriteFramesCache.hasPlist(plist))
|
||||
{
|
||||
return; // We already added it
|
||||
}
|
||||
|
@ -360,28 +358,25 @@ void SpriteFrameCache::addSpriteFramesWithFile(const std::string& plist, Texture
|
|||
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(plist);
|
||||
ValueMap dict = FileUtils::getInstance()->getValueMapFromFile(fullPath);
|
||||
|
||||
addSpriteFramesWithDictionary(dict, texture);
|
||||
_loadedFileNames->insert(plist);
|
||||
addSpriteFramesWithDictionary(dict, texture, plist);
|
||||
}
|
||||
|
||||
void SpriteFrameCache::addSpriteFramesWithFileContent(const std::string& plist_content, Texture2D *texture)
|
||||
{
|
||||
ValueMap dict = FileUtils::getInstance()->getValueMapFromData(plist_content.c_str(), static_cast<int>(plist_content.size()));
|
||||
addSpriteFramesWithDictionary(dict, texture);
|
||||
addSpriteFramesWithDictionary(dict, texture, "by#addSpriteFramesWithFileContent()");
|
||||
}
|
||||
|
||||
void SpriteFrameCache::addSpriteFramesWithFile(const std::string& plist, const std::string& textureFileName)
|
||||
{
|
||||
CCASSERT(textureFileName.size()>0, "texture name should not be null");
|
||||
if (_loadedFileNames->find(plist) != _loadedFileNames->end())
|
||||
if (_spriteFramesCache.hasPlist(plist))
|
||||
{
|
||||
return; // We already added it
|
||||
}
|
||||
|
||||
const std::string fullPath = FileUtils::getInstance()->fullPathForFilename(plist);
|
||||
ValueMap dict = FileUtils::getInstance()->getValueMapFromFile(fullPath);
|
||||
addSpriteFramesWithDictionary(dict, textureFileName);
|
||||
_loadedFileNames->insert(plist);
|
||||
addSpriteFramesWithDictionary(dict, textureFileName, plist);
|
||||
}
|
||||
|
||||
void SpriteFrameCache::addSpriteFramesWithFile(const std::string& plist)
|
||||
|
@ -396,7 +391,7 @@ void SpriteFrameCache::addSpriteFramesWithFile(const std::string& plist)
|
|||
return;
|
||||
}
|
||||
|
||||
if (_loadedFileNames->find(plist) == _loadedFileNames->end())
|
||||
if (!_spriteFramesCache.hasPlist(plist))
|
||||
{
|
||||
ValueMap dict = FileUtils::getInstance()->getValueMapFromFile(fullPath);
|
||||
|
||||
|
@ -428,34 +423,25 @@ void SpriteFrameCache::addSpriteFramesWithFile(const std::string& plist)
|
|||
|
||||
CCLOG("cocos2d: SpriteFrameCache: Trying to use file %s as texture", texturePath.c_str());
|
||||
}
|
||||
addSpriteFramesWithDictionary(dict, texturePath);
|
||||
_loadedFileNames->insert(plist);
|
||||
addSpriteFramesWithDictionary(dict, texturePath, plist);
|
||||
}
|
||||
}
|
||||
|
||||
bool SpriteFrameCache::isSpriteFramesWithFileLoaded(const std::string& plist) const
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (_loadedFileNames->find(plist) != _loadedFileNames->end())
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
return _spriteFramesCache.hasPlist(plist);
|
||||
}
|
||||
|
||||
void SpriteFrameCache::addSpriteFrame(SpriteFrame* frame, const std::string& frameName)
|
||||
{
|
||||
CCASSERT(frame, "frame should not be nil");
|
||||
_spriteFrames.insert(frameName, frame);
|
||||
_spriteFramesCache.insertFrame("by#addSpriteFrame()", frameName, frame);
|
||||
}
|
||||
|
||||
void SpriteFrameCache::removeSpriteFrames()
|
||||
{
|
||||
_spriteFrames.clear();
|
||||
_spriteFramesAliases.clear();
|
||||
_loadedFileNames->clear();
|
||||
_spriteFramesCache.clear();
|
||||
}
|
||||
|
||||
void SpriteFrameCache::removeUnusedSpriteFrames()
|
||||
|
@ -463,7 +449,7 @@ void SpriteFrameCache::removeUnusedSpriteFrames()
|
|||
bool removed = false;
|
||||
std::vector<std::string> toRemoveFrames;
|
||||
|
||||
for (auto& iter : _spriteFrames)
|
||||
for (auto& iter : _spriteFramesCache.getSpriteFrames())
|
||||
{
|
||||
SpriteFrame* spriteFrame = iter.second;
|
||||
if( spriteFrame->getReferenceCount() == 1 )
|
||||
|
@ -475,12 +461,10 @@ void SpriteFrameCache::removeUnusedSpriteFrames()
|
|||
}
|
||||
}
|
||||
|
||||
_spriteFrames.erase(toRemoveFrames);
|
||||
|
||||
// FIXME:. Since we don't know the .plist file that originated the frame, we must remove all .plist from the cache
|
||||
|
||||
if( removed )
|
||||
{
|
||||
_loadedFileNames->clear();
|
||||
_spriteFramesCache.eraseFrames(toRemoveFrames);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -497,16 +481,10 @@ void SpriteFrameCache::removeSpriteFrameByName(const std::string& name)
|
|||
|
||||
if (!key.empty())
|
||||
{
|
||||
_spriteFrames.erase(key);
|
||||
_spriteFramesAliases.erase(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
_spriteFrames.erase(name);
|
||||
}
|
||||
|
||||
// FIXME:. Since we don't know the .plist file that originated the frame, we must remove all .plist from the cache
|
||||
_loadedFileNames->clear();
|
||||
_spriteFramesCache.eraseFrame(name);
|
||||
}
|
||||
|
||||
void SpriteFrameCache::removeSpriteFramesFromFile(const std::string& plist)
|
||||
|
@ -521,11 +499,7 @@ void SpriteFrameCache::removeSpriteFramesFromFile(const std::string& plist)
|
|||
removeSpriteFramesFromDictionary(dict);
|
||||
|
||||
// remove it from the cache
|
||||
set<string>::iterator ret = _loadedFileNames->find(plist);
|
||||
if (ret != _loadedFileNames->end())
|
||||
{
|
||||
_loadedFileNames->erase(ret);
|
||||
}
|
||||
_spriteFramesCache.erasePlistIndex(plist);
|
||||
}
|
||||
|
||||
void SpriteFrameCache::removeSpriteFramesFromFileContent(const std::string& plist_content)
|
||||
|
@ -549,35 +523,35 @@ void SpriteFrameCache::removeSpriteFramesFromDictionary(ValueMap& dictionary)
|
|||
|
||||
for (const auto& iter : framesDict)
|
||||
{
|
||||
if (_spriteFrames.at(iter.first))
|
||||
if (_spriteFramesCache.at(iter.first))
|
||||
{
|
||||
keysToRemove.push_back(iter.first);
|
||||
}
|
||||
}
|
||||
|
||||
_spriteFrames.erase(keysToRemove);
|
||||
_spriteFramesCache.eraseFrames(keysToRemove);
|
||||
}
|
||||
|
||||
void SpriteFrameCache::removeSpriteFramesFromTexture(Texture2D* texture)
|
||||
{
|
||||
std::vector<std::string> keysToRemove;
|
||||
|
||||
for (auto& iter : _spriteFrames)
|
||||
for (auto& iter : _spriteFramesCache.getSpriteFrames())
|
||||
{
|
||||
std::string key = iter.first;
|
||||
SpriteFrame* frame = _spriteFrames.at(key);
|
||||
SpriteFrame* frame = _spriteFramesCache.at(key);
|
||||
if (frame && (frame->getTexture() == texture))
|
||||
{
|
||||
keysToRemove.push_back(key);
|
||||
}
|
||||
}
|
||||
|
||||
_spriteFrames.erase(keysToRemove);
|
||||
_spriteFramesCache.eraseFrames(keysToRemove);
|
||||
}
|
||||
|
||||
SpriteFrame* SpriteFrameCache::getSpriteFrameByName(const std::string& name)
|
||||
{
|
||||
SpriteFrame* frame = _spriteFrames.at(name);
|
||||
SpriteFrame* frame = _spriteFramesCache.at(name);
|
||||
if (!frame)
|
||||
{
|
||||
// try alias dictionary
|
||||
|
@ -586,7 +560,7 @@ SpriteFrame* SpriteFrameCache::getSpriteFrameByName(const std::string& name)
|
|||
std::string key = _spriteFramesAliases[name].asString();
|
||||
if (!key.empty())
|
||||
{
|
||||
frame = _spriteFrames.at(key);
|
||||
frame = _spriteFramesCache.at(key);
|
||||
if (!frame)
|
||||
{
|
||||
CCLOG("cocos2d: SpriteFrameCache: Frame aliases '%s' isn't found", key.c_str());
|
||||
|
@ -601,7 +575,7 @@ SpriteFrame* SpriteFrameCache::getSpriteFrameByName(const std::string& name)
|
|||
return frame;
|
||||
}
|
||||
|
||||
void SpriteFrameCache::reloadSpriteFramesWithDictionary(ValueMap& dictionary, Texture2D *texture)
|
||||
void SpriteFrameCache::reloadSpriteFramesWithDictionary(ValueMap& dictionary, Texture2D *texture, const std::string &plist)
|
||||
{
|
||||
ValueMap& framesDict = dictionary["frames"].asValueMap();
|
||||
int format = 0;
|
||||
|
@ -621,11 +595,7 @@ void SpriteFrameCache::reloadSpriteFramesWithDictionary(ValueMap& dictionary, Te
|
|||
ValueMap& frameDict = iter.second.asValueMap();
|
||||
std::string spriteFrameName = iter.first;
|
||||
|
||||
auto it = _spriteFrames.find(spriteFrameName);
|
||||
if (it != _spriteFrames.end())
|
||||
{
|
||||
_spriteFrames.erase(it);
|
||||
}
|
||||
_spriteFramesCache.eraseFrame(spriteFrameName);
|
||||
|
||||
SpriteFrame* spriteFrame = nullptr;
|
||||
|
||||
|
@ -708,7 +678,7 @@ void SpriteFrameCache::reloadSpriteFramesWithDictionary(ValueMap& dictionary, Te
|
|||
}
|
||||
|
||||
// add sprite frame
|
||||
_spriteFrames.insert(spriteFrameName, spriteFrame);
|
||||
_spriteFramesCache.insertFrame(plist, spriteFrameName, spriteFrame);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -716,9 +686,8 @@ bool SpriteFrameCache::reloadTexture(const std::string& plist)
|
|||
{
|
||||
CCASSERT(plist.size()>0, "plist filename should not be nullptr");
|
||||
|
||||
auto it = _loadedFileNames->find(plist);
|
||||
if (it != _loadedFileNames->end()) {
|
||||
_loadedFileNames->erase(it);
|
||||
if (_spriteFramesCache.hasPlist(plist)) {
|
||||
_spriteFramesCache.erasePlistIndex(plist);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -762,8 +731,7 @@ bool SpriteFrameCache::reloadTexture(const std::string& plist)
|
|||
|
||||
if (texture)
|
||||
{
|
||||
reloadSpriteFramesWithDictionary(dict, texture);
|
||||
_loadedFileNames->insert(plist);
|
||||
reloadSpriteFramesWithDictionary(dict, texture, plist);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -772,4 +740,85 @@ bool SpriteFrameCache::reloadTexture(const std::string& plist)
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
void SpriteFrameCache::PlistFramesCache::insertFrame(const std::string &plist, const std::string &frame, SpriteFrame *spriteFrame)
|
||||
{
|
||||
_spriteFrames.insert(frame, spriteFrame); //add SpriteFrame
|
||||
|
||||
_indexPlist2Frames[plist].insert(frame); //insert index plist->[frameName]
|
||||
_indexFrame2plist[frame] = plist; //insert index frameName->plist
|
||||
}
|
||||
|
||||
bool SpriteFrameCache::PlistFramesCache::isPlistUsed(const std::string &plist) const
|
||||
{
|
||||
//plist loaded && not empty
|
||||
auto it = _indexPlist2Frames.find(plist);
|
||||
return it != _indexPlist2Frames.end() && !it->second.empty();
|
||||
}
|
||||
|
||||
bool SpriteFrameCache::PlistFramesCache::eraseFrame(const std::string &frame)
|
||||
{
|
||||
_spriteFrames.erase(frame); //drop SpriteFrame
|
||||
auto itFrame = _indexFrame2plist.find(frame);
|
||||
if (itFrame != _indexFrame2plist.end())
|
||||
{
|
||||
_indexPlist2Frames[itFrame->second].erase(frame); //update index plist->[frameNames]
|
||||
_indexFrame2plist.erase(itFrame); //update index frame->plist
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SpriteFrameCache::PlistFramesCache::eraseFrames(const std::vector<std::string> &frames)
|
||||
{
|
||||
auto ret = false;
|
||||
for (const auto & frame : frames)
|
||||
{
|
||||
ret |= eraseFrame(frame);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool SpriteFrameCache::PlistFramesCache::erasePlistIndex(const std::string &plist)
|
||||
{
|
||||
auto it = _indexPlist2Frames.find(plist);
|
||||
if (it == _indexPlist2Frames.end()) return false;
|
||||
|
||||
auto &frames = it->second;
|
||||
for (auto f : frames)
|
||||
{
|
||||
// !!do not!! call `_spriteFrames.erase(f);` to erase SpriteFrame
|
||||
// only erase index here
|
||||
_indexFrame2plist.erase(f); //erase plist frame frameName->plist
|
||||
}
|
||||
_indexPlist2Frames.erase(plist); //update index plist->[frameNames]
|
||||
return true;
|
||||
}
|
||||
|
||||
void SpriteFrameCache::PlistFramesCache::clear()
|
||||
{
|
||||
_indexPlist2Frames.clear();
|
||||
_indexFrame2plist.clear();
|
||||
_spriteFrames.clear();
|
||||
}
|
||||
|
||||
bool SpriteFrameCache::PlistFramesCache::hasFrame(const std::string &frame) const
|
||||
{
|
||||
return _indexFrame2plist.find(frame) != _indexFrame2plist.end();
|
||||
}
|
||||
|
||||
bool SpriteFrameCache::PlistFramesCache::hasPlist(const std::string &plist) const
|
||||
{
|
||||
return _indexPlist2Frames.find(plist) != _indexPlist2Frames.end();
|
||||
}
|
||||
|
||||
SpriteFrame * SpriteFrameCache::PlistFramesCache::at(const std::string &frame)
|
||||
{
|
||||
return _spriteFrames.at(frame);
|
||||
}
|
||||
Map<std::string, SpriteFrame*>& SpriteFrameCache::PlistFramesCache::getSpriteFrames()
|
||||
{
|
||||
return _spriteFrames;
|
||||
}
|
||||
|
||||
NS_CC_END
|
||||
|
|
|
@ -32,6 +32,7 @@ THE SOFTWARE.
|
|||
#define __SPRITE_CCSPRITE_FRAME_CACHE_H__
|
||||
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include "2d/CCSpriteFrame.h"
|
||||
#include "base/CCRef.h"
|
||||
|
@ -87,6 +88,47 @@ class PolygonInfo;
|
|||
*/
|
||||
class CC_DLL SpriteFrameCache : public Ref
|
||||
{
|
||||
protected:
|
||||
/**
|
||||
* used to wrap plist & frame names & SpriteFrames
|
||||
*/
|
||||
class PlistFramesCache {
|
||||
public:
|
||||
PlistFramesCache() { }
|
||||
void init() {
|
||||
_spriteFrames.reserve(20); clear();
|
||||
}
|
||||
/** Record SpriteFrame with plist and frame name, add frame name
|
||||
* and plist to index
|
||||
*/
|
||||
void insertFrame(const std::string &plist, const std::string &frame, SpriteFrame *frameObj);
|
||||
/** Delete frame from cache, rebuild index
|
||||
*/
|
||||
bool eraseFrame(const std::string &frame);
|
||||
/** Delete a list of frames from cache, rebuild index
|
||||
*/
|
||||
bool eraseFrames(const std::vector<std::string> &frame);
|
||||
/** Delete frame from index and SpriteFrame is kept.
|
||||
*/
|
||||
bool erasePlistIndex(const std::string &frame);
|
||||
/** Clear index and all SpriteFrames.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
inline bool hasFrame(const std::string &frame) const;
|
||||
inline bool hasPlist(const std::string &plist) const;
|
||||
|
||||
inline SpriteFrame *at(const std::string &frame);
|
||||
inline Map<std::string, SpriteFrame*>& getSpriteFrames();
|
||||
|
||||
inline bool isPlistUsed(const std::string &plist) const;
|
||||
|
||||
private:
|
||||
Map<std::string, SpriteFrame*> _spriteFrames;
|
||||
std::unordered_map<std::string, std::set<std::string>> _indexPlist2Frames;
|
||||
std::unordered_map<std::string, std::string> _indexFrame2plist;
|
||||
};
|
||||
|
||||
public:
|
||||
/** Returns the shared instance of the Sprite Frame cache.
|
||||
*
|
||||
|
@ -246,11 +288,11 @@ protected:
|
|||
|
||||
/*Adds multiple Sprite Frames with a dictionary. The texture will be associated with the created sprite frames.
|
||||
*/
|
||||
void addSpriteFramesWithDictionary(ValueMap& dictionary, Texture2D *texture);
|
||||
void addSpriteFramesWithDictionary(ValueMap& dictionary, Texture2D *texture, const std::string &plist);
|
||||
|
||||
/*Adds multiple Sprite Frames with a dictionary. The texture will be associated with the created sprite frames.
|
||||
*/
|
||||
void addSpriteFramesWithDictionary(ValueMap& dictionary, const std::string &texturePath);
|
||||
void addSpriteFramesWithDictionary(ValueMap& dictionary, const std::string &texturePath, const std::string &plist);
|
||||
|
||||
/** Removes multiple Sprite Frames from Dictionary.
|
||||
* @since v0.99.5
|
||||
|
@ -268,11 +310,10 @@ protected:
|
|||
const std::vector<int> &triangleIndices,
|
||||
PolygonInfo &polygonInfo);
|
||||
|
||||
void reloadSpriteFramesWithDictionary(ValueMap& dictionary, Texture2D *texture);
|
||||
void reloadSpriteFramesWithDictionary(ValueMap& dictionary, Texture2D *texture, const std::string &plist);
|
||||
|
||||
Map<std::string, SpriteFrame*> _spriteFrames;
|
||||
ValueMap _spriteFramesAliases;
|
||||
std::set<std::string>* _loadedFileNames;
|
||||
PlistFramesCache _spriteFramesCache;
|
||||
};
|
||||
|
||||
// end of _2d group
|
||||
|
|
Loading…
Reference in New Issue