Blame |
Last modification |
View Log
| RSS feed
#include "ResourceManager.h"
#include "XMLParser.h"
#include "SoundManager.h"
#include "DDImage.h"
#include "D3DInterface.h"
#include "ImageFont.h"
#include "SysFont.h"
#include "../ImageLib/ImageLib.h"
//#define SEXY_PERF_ENABLED
#include "PerfTimer.h"
using namespace Sexy;
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ResourceManager::ImageRes::DeleteResource()
{
mImage.Release();
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ResourceManager::SoundRes::DeleteResource()
{
if (mSoundId >= 0)
gSexyAppBase->mSoundManager->ReleaseSound(mSoundId);
mSoundId = -1;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ResourceManager::FontRes::DeleteResource()
{
delete mFont;
mFont = NULL;
delete mImage;
mImage = NULL;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
ResourceManager::ResourceManager(SexyAppBase *theApp)
{
mApp = theApp;
mHasFailed = false;
mXMLParser = NULL;
mAllowMissingProgramResources = false;
mAllowAlreadyDefinedResources = false;
mCurResGroupList = NULL;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
ResourceManager::~ResourceManager()
{
DeleteMap(mImageMap);
DeleteMap(mSoundMap);
DeleteMap(mFontMap);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::IsGroupLoaded(const std::string &theGroup)
{
return mLoadedGroups.find(theGroup)!=mLoadedGroups.end();
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ResourceManager::DeleteMap(ResMap &theMap)
{
for (ResMap::iterator anItr = theMap.begin(); anItr != theMap.end(); ++anItr)
{
anItr->second->DeleteResource();
delete anItr->second;
}
theMap.clear();
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ResourceManager::DeleteResources(ResMap &theMap, const std::string &theGroup)
{
for (ResMap::iterator anItr = theMap.begin(); anItr != theMap.end(); ++anItr)
{
if (theGroup.empty() || anItr->second->mResGroup==theGroup)
anItr->second->DeleteResource();
}
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ResourceManager::DeleteResources(const std::string &theGroup)
{
DeleteResources(mImageMap,theGroup);
DeleteResources(mSoundMap,theGroup);
DeleteResources(mFontMap,theGroup);
mLoadedGroups.erase(theGroup);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ResourceManager::DeleteExtraImageBuffers(const std::string &theGroup)
{
for (ResMap::iterator anItr = mImageMap.begin(); anItr != mImageMap.end(); ++anItr)
{
if (theGroup.empty() || anItr->second->mResGroup==theGroup)
{
ImageRes *aRes = (ImageRes*)anItr->second;
MemoryImage *anImage = (MemoryImage*)aRes->mImage;
if (anImage != NULL)
anImage->DeleteExtraBuffers();
}
}
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
std::string ResourceManager::GetErrorText()
{
return mError;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::HadError()
{
return mHasFailed;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::Fail(const std::string& theErrorText)
{
if (!mHasFailed)
{
mHasFailed = true;
if (mXMLParser==NULL)
{
mError = theErrorText;
return false;
}
int aLineNum = mXMLParser->GetCurrentLineNum();
char aLineNumStr[16];
sprintf(aLineNumStr, "%d", aLineNum);
mError = theErrorText;
if (aLineNum > 0)
mError += std::string(" on Line ") + aLineNumStr;
if (mXMLParser->GetFileName().length() > 0)
mError += " in File '" + mXMLParser->GetFileName() + "'";
}
return false;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::ParseCommonResource(XMLElement &theElement, BaseRes *theRes, ResMap &theMap)
{
mHadAlreadyDefinedError = false;
const SexyString &aPath = theElement.mAttributes[_S("path")];
if (aPath.empty())
return Fail("No path specified.");
theRes->mXMLAttributes = theElement.mAttributes;
theRes->mFromProgram = false;
if (aPath[0]==_S('!'))
{
theRes->mPath = SexyStringToStringFast(aPath);
if (aPath==_S("!program"))
theRes->mFromProgram = true;
}
else
theRes->mPath = mDefaultPath + SexyStringToStringFast(aPath);
std::string anId;
XMLParamMap::iterator anItr = theElement.mAttributes.find(_S("id"));
if (anItr == theElement.mAttributes.end())
anId = mDefaultIdPrefix + GetFileName(theRes->mPath,true);
else
anId = mDefaultIdPrefix + SexyStringToStringFast(anItr->second);
theRes->mResGroup = mCurResGroup;
theRes->mId = anId;
std::pair<ResMap::iterator,bool> aRet = theMap.insert(ResMap::value_type(anId,theRes));
if (!aRet.second)
{
mHadAlreadyDefinedError = true;
return Fail("Resource already defined.");
}
mCurResGroupList->push_back(theRes);
return true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::ParseSoundResource(XMLElement &theElement)
{
SoundRes *aRes = new SoundRes;
aRes->mSoundId = -1;
aRes->mVolume = -1;
aRes->mPanning = 0;
if (!ParseCommonResource(theElement, aRes, mSoundMap))
{
if (mHadAlreadyDefinedError && mAllowAlreadyDefinedResources)
{
mError = "";
mHasFailed = false;
SoundRes *oldRes = aRes;
aRes = (SoundRes*)mSoundMap[oldRes->mId];
aRes->mPath = oldRes->mPath;
aRes->mXMLAttributes = oldRes->mXMLAttributes;
delete oldRes;
}
else
{
delete aRes;
return false;
}
}
XMLParamMap::iterator anItr;
anItr = theElement.mAttributes.find(_S("volume"));
if (anItr != theElement.mAttributes.end())
sexysscanf(anItr->second.c_str(),_S("%lf"),&aRes->mVolume);
anItr = theElement.mAttributes.find(_S("pan"));
if (anItr != theElement.mAttributes.end())
sexysscanf(anItr->second.c_str(),_S("%d"),&aRes->mPanning);
return true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static void ReadIntVector(const SexyString &theVal, std::vector<int> &theVector)
{
theVector.clear();
std::string::size_type aPos = 0;
while (true)
{
theVector.push_back(sexyatoi(theVal.c_str()+aPos));
aPos = theVal.find_first_of(_S(','),aPos);
if (aPos==std::string::npos)
break;
aPos++;
}
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::ParseImageResource(XMLElement &theElement)
{
ImageRes *aRes = new ImageRes;
if (!ParseCommonResource(theElement, aRes, mImageMap))
{
if (mHadAlreadyDefinedError && mAllowAlreadyDefinedResources)
{
mError = "";
mHasFailed = false;
ImageRes *oldRes = aRes;
aRes = (ImageRes*)mImageMap[oldRes->mId];
aRes->mPath = oldRes->mPath;
aRes->mXMLAttributes = oldRes->mXMLAttributes;
delete oldRes;
}
else
{
delete aRes;
return false;
}
}
aRes->mPalletize = theElement.mAttributes.find(_S("nopal")) == theElement.mAttributes.end();
aRes->mA4R4G4B4 = theElement.mAttributes.find(_S("a4r4g4b4")) != theElement.mAttributes.end();
aRes->mDDSurface = theElement.mAttributes.find(_S("ddsurface")) != theElement.mAttributes.end();
aRes->mPurgeBits = (theElement.mAttributes.find(_S("nobits")) != theElement.mAttributes.end()) ||
((mApp->Is3DAccelerated()) && (theElement.mAttributes.find(_S("nobits3d")) != theElement.mAttributes.end())) ||
((!mApp->Is3DAccelerated()) && (theElement.mAttributes.find(_S("nobits2d")) != theElement.mAttributes.end()));
aRes->mA8R8G8B8 = theElement.mAttributes.find(_S("a8r8g8b8")) != theElement.mAttributes.end();
aRes->mMinimizeSubdivisions = theElement.mAttributes.find(_S("minsubdivide")) != theElement.mAttributes.end();
aRes->mAutoFindAlpha = theElement.mAttributes.find(_S("noalpha")) == theElement.mAttributes.end();
XMLParamMap::iterator anItr;
anItr = theElement.mAttributes.find(_S("alphaimage"));
if (anItr != theElement.mAttributes.end())
aRes->mAlphaImage = mDefaultPath + SexyStringToStringFast(anItr->second);
aRes->mAlphaColor = 0xFFFFFF;
anItr = theElement.mAttributes.find(_S("alphacolor"));
if (anItr != theElement.mAttributes.end())
sexysscanf(anItr->second.c_str(),_S("%x"),&aRes->mAlphaColor);
anItr = theElement.mAttributes.find(_S("variant"));
if (anItr != theElement.mAttributes.end())
aRes->mVariant = SexyStringToStringFast(anItr->second);
anItr = theElement.mAttributes.find(_S("alphagrid"));
if (anItr != theElement.mAttributes.end())
aRes->mAlphaGridImage = mDefaultPath + SexyStringToStringFast(anItr->second);
anItr = theElement.mAttributes.find(_S("rows"));
if (anItr != theElement.mAttributes.end())
aRes->mRows = sexyatoi(anItr->second.c_str());
else
aRes->mRows = 1;
anItr = theElement.mAttributes.find(_S("cols"));
if (anItr != theElement.mAttributes.end())
aRes->mCols = sexyatoi(anItr->second.c_str());
else
aRes->mCols = 1;
anItr = theElement.mAttributes.find(_S("anim"));
AnimType anAnimType = AnimType_None;
if (anItr != theElement.mAttributes.end())
{
const SexyChar *aType = anItr->second.c_str();
if (sexystricmp(aType,_S("none"))==0) anAnimType = AnimType_None;
else if (sexystricmp(aType,_S("once"))==0) anAnimType = AnimType_Once;
else if (sexystricmp(aType,_S("loop"))==0) anAnimType = AnimType_Loop;
else if (sexystricmp(aType,_S("pingpong"))==0) anAnimType = AnimType_PingPong;
else
{
Fail("Invalid animation type.");
return false;
}
}
aRes->mAnimInfo.mAnimType = anAnimType;
if (anAnimType != AnimType_None)
{
int aNumCels = max(aRes->mRows,aRes->mCols);
int aBeginDelay = 0, anEndDelay = 0;
anItr = theElement.mAttributes.find(_S("framedelay"));
if (anItr != theElement.mAttributes.end())
aRes->mAnimInfo.mFrameDelay = sexyatoi(anItr->second.c_str());
anItr = theElement.mAttributes.find(_S("begindelay"));
if (anItr != theElement.mAttributes.end())
aBeginDelay = sexyatoi(anItr->second.c_str());
anItr = theElement.mAttributes.find(_S("enddelay"));
if (anItr != theElement.mAttributes.end())
anEndDelay = sexyatoi(anItr->second.c_str());
anItr = theElement.mAttributes.find(_S("perframedelay"));
if (anItr != theElement.mAttributes.end())
ReadIntVector(anItr->second,aRes->mAnimInfo.mPerFrameDelay);
anItr = theElement.mAttributes.find(_S("framemap"));
if (anItr != theElement.mAttributes.end())
ReadIntVector(anItr->second,aRes->mAnimInfo.mFrameMap);
aRes->mAnimInfo.Compute(aNumCels,aBeginDelay,anEndDelay);
}
return true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::ParseFontResource(XMLElement &theElement)
{
FontRes *aRes = new FontRes;
aRes->mFont = NULL;
aRes->mImage = NULL;
if (!ParseCommonResource(theElement, aRes, mFontMap))
{
if (mHadAlreadyDefinedError && mAllowAlreadyDefinedResources)
{
mError = "";
mHasFailed = false;
FontRes *oldRes = aRes;
aRes = (FontRes*)mFontMap[oldRes->mId];
aRes->mPath = oldRes->mPath;
aRes->mXMLAttributes = oldRes->mXMLAttributes;
delete oldRes;
}
else
{
delete aRes;
return false;
}
}
XMLParamMap::iterator anItr;
anItr = theElement.mAttributes.find(_S("image"));
if (anItr != theElement.mAttributes.end())
aRes->mImagePath = SexyStringToStringFast(anItr->second);
anItr = theElement.mAttributes.find(_S("tags"));
if (anItr != theElement.mAttributes.end())
aRes->mTags = SexyStringToStringFast(anItr->second);
if (strncmp(aRes->mPath.c_str(),"!sys:",5)==0)
{
aRes->mSysFont = true;
aRes->mPath = aRes->mPath.substr(5);
anItr = theElement.mAttributes.find(_S("size"));
if (anItr==theElement.mAttributes.end())
return Fail("SysFont needs point size");
aRes->mSize = sexyatoi(anItr->second.c_str());
if (aRes->mSize<=0)
return Fail("SysFont needs point size");
aRes->mBold = theElement.mAttributes.find(_S("bold"))!=theElement.mAttributes.end();
aRes->mItalic = theElement.mAttributes.find(_S("italic"))!=theElement.mAttributes.end();
aRes->mShadow = theElement.mAttributes.find(_S("shadow"))!=theElement.mAttributes.end();
aRes->mUnderline = theElement.mAttributes.find(_S("underline"))!=theElement.mAttributes.end();
}
else
aRes->mSysFont = false;
return true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::ParseSetDefaults(XMLElement &theElement)
{
XMLParamMap::iterator anItr;
anItr = theElement.mAttributes.find(_S("path"));
if (anItr != theElement.mAttributes.end())
mDefaultPath = RemoveTrailingSlash(SexyStringToStringFast(anItr->second)) + '/';
anItr = theElement.mAttributes.find(_S("idprefix"));
if (anItr != theElement.mAttributes.end())
mDefaultIdPrefix = RemoveTrailingSlash(SexyStringToStringFast(anItr->second));
return true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::ParseResources()
{
for (;;)
{
XMLElement aXMLElement;
if (!mXMLParser->NextElement(&aXMLElement))
return false;
if (aXMLElement.mType == XMLElement::TYPE_START)
{
if (aXMLElement.mValue == _S("Image"))
{
if (!ParseImageResource(aXMLElement))
return false;
if (!mXMLParser->NextElement(&aXMLElement))
return false;
if (aXMLElement.mType != XMLElement::TYPE_END)
return Fail("Unexpected element found.");
}
else if (aXMLElement.mValue == _S("Sound"))
{
if (!ParseSoundResource(aXMLElement))
return false;
if (!mXMLParser->NextElement(&aXMLElement))
return false;
if (aXMLElement.mType != XMLElement::TYPE_END)
return Fail("Unexpected element found.");
}
else if (aXMLElement.mValue == _S("Font"))
{
if (!ParseFontResource(aXMLElement))
return false;
if (!mXMLParser->NextElement(&aXMLElement))
return false;
if (aXMLElement.mType != XMLElement::TYPE_END)
return Fail("Unexpected element found.");
}
else if (aXMLElement.mValue == _S("SetDefaults"))
{
if (!ParseSetDefaults(aXMLElement))
return false;
if (!mXMLParser->NextElement(&aXMLElement))
return false;
if (aXMLElement.mType != XMLElement::TYPE_END)
return Fail("Unexpected element found.");
}
else
{
Fail("Invalid Section '" + SexyStringToStringFast(aXMLElement.mValue) + "'");
return false;
}
}
else if (aXMLElement.mType == XMLElement::TYPE_ELEMENT)
{
Fail("Element Not Expected '" + SexyStringToStringFast(aXMLElement.mValue) + "'");
return false;
}
else if (aXMLElement.mType == XMLElement::TYPE_END)
{
return true;
}
}
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::DoParseResources()
{
if (!mXMLParser->HasFailed())
{
for (;;)
{
XMLElement aXMLElement;
if (!mXMLParser->NextElement(&aXMLElement))
break;
if (aXMLElement.mType == XMLElement::TYPE_START)
{
if (aXMLElement.mValue == _S("Resources"))
{
mCurResGroup = SexyStringToStringFast(aXMLElement.mAttributes[_S("id")]);
mCurResGroupList = &mResGroupMap[mCurResGroup];
if (mCurResGroup.empty())
{
Fail("No id specified.");
break;
}
if (!ParseResources())
break;
}
else
{
Fail("Invalid Section '" + SexyStringToStringFast(aXMLElement.mValue) + "'");
break;
}
}
else if (aXMLElement.mType == XMLElement::TYPE_ELEMENT)
{
Fail("Element Not Expected '" + SexyStringToStringFast(aXMLElement.mValue) + "'");
break;
}
}
}
if (mXMLParser->HasFailed())
Fail(SexyStringToStringFast(mXMLParser->GetErrorText()));
delete mXMLParser;
mXMLParser = NULL;
return !mHasFailed;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::ParseResourcesFile(const std::string& theFilename)
{
mXMLParser = new XMLParser();
if (!mXMLParser->OpenFile(theFilename))
Fail("Resource file not found: " + theFilename);
XMLElement aXMLElement;
while (!mXMLParser->HasFailed())
{
if (!mXMLParser->NextElement(&aXMLElement))
Fail(SexyStringToStringFast(mXMLParser->GetErrorText()));
if (aXMLElement.mType == XMLElement::TYPE_START)
{
if (aXMLElement.mValue != _S("ResourceManifest"))
break;
else
return DoParseResources();
}
}
Fail("Expecting ResourceManifest tag");
return DoParseResources();
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::ReparseResourcesFile(const std::string& theFilename)
{
bool oldDefined = mAllowAlreadyDefinedResources;
mAllowAlreadyDefinedResources = true;
bool aResult = ParseResourcesFile(theFilename);
mAllowAlreadyDefinedResources = oldDefined;
return aResult;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::LoadAlphaGridImage(ImageRes *theRes, DDImage *theImage)
{
ImageLib::Image* anAlphaImage = ImageLib::GetImage(theRes->mAlphaGridImage,true);
if (anAlphaImage==NULL)
return Fail(StrFormat("Failed to load image: %s",theRes->mAlphaGridImage.c_str()));
std::auto_ptr<ImageLib::Image> aDelAlphaImage(anAlphaImage);
int aNumRows = theRes->mRows;
int aNumCols = theRes->mCols;
int aCelWidth = theImage->mWidth/aNumCols;
int aCelHeight = theImage->mHeight/aNumRows;
if (anAlphaImage->mWidth!=aCelWidth || anAlphaImage->mHeight!=aCelHeight)
return Fail(StrFormat("GridAlphaImage size mismatch between %s and %s",theRes->mPath.c_str(),theRes->mAlphaGridImage.c_str()));
unsigned long *aMasterRowPtr = theImage->mBits;
for (int i=0; i < aNumRows; i++)
{
unsigned long *aMasterColPtr = aMasterRowPtr;
for (int j=0; j < aNumCols; j++)
{
unsigned long* aRowPtr = aMasterColPtr;
unsigned long* anAlphaBits = anAlphaImage->mBits;
for (int y=0; y<aCelHeight; y++)
{
unsigned long *aDestPtr = aRowPtr;
for (int x=0; x<aCelWidth; x++)
{
*aDestPtr = (*aDestPtr & 0x00FFFFFF) | ((*anAlphaBits & 0xFF) << 24);
++anAlphaBits;
++aDestPtr;
}
aRowPtr += theImage->mWidth;
}
aMasterColPtr += aCelWidth;
}
aMasterRowPtr += aCelHeight*theImage->mWidth;
}
theImage->BitsChanged();
return true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::LoadAlphaImage(ImageRes *theRes, DDImage *theImage)
{
SEXY_PERF_BEGIN("ResourceManager::GetImage");
ImageLib::Image* anAlphaImage = ImageLib::GetImage(theRes->mAlphaImage,true);
SEXY_PERF_END("ResourceManager::GetImage");
if (anAlphaImage==NULL)
return Fail(StrFormat("Failed to load image: %s",theRes->mAlphaImage.c_str()));
std::auto_ptr<ImageLib::Image> aDelAlphaImage(anAlphaImage);
if (anAlphaImage->mWidth!=theImage->mWidth || anAlphaImage->mHeight!=theImage->mHeight)
return Fail(StrFormat("AlphaImage size mismatch between %s and %s",theRes->mPath.c_str(),theRes->mAlphaImage.c_str()));
unsigned long* aBits1 = theImage->mBits;
unsigned long* aBits2 = anAlphaImage->mBits;
int aSize = theImage->mWidth*theImage->mHeight;
for (int i = 0; i < aSize; i++)
{
*aBits1 = (*aBits1 & 0x00FFFFFF) | ((*aBits2 & 0xFF) << 24);
++aBits1;
++aBits2;
}
theImage->BitsChanged();
return true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::DoLoadImage(ImageRes *theRes)
{
bool lookForAlpha = theRes->mAlphaImage.empty() && theRes->mAlphaGridImage.empty() && theRes->mAutoFindAlpha;
SEXY_PERF_BEGIN("ResourceManager:GetImage");
//ImageLib::Image *anImage = ImageLib::GetImage(theRes->mPath, lookForAlpha);
//SEXY_PERF_END("ResourceManager:GetImage");
bool isNew;
ImageLib::gAlphaComposeColor = theRes->mAlphaColor;
SharedImageRef aSharedImageRef = gSexyAppBase->GetSharedImage(theRes->mPath, theRes->mVariant, &isNew);
ImageLib::gAlphaComposeColor = 0xFFFFFF;
DDImage* aDDImage = (DDImage*) aSharedImageRef;
if (aDDImage == NULL)
return Fail(StrFormat("Failed to load image: %s",theRes->mPath.c_str()));
if (isNew)
{
if (!theRes->mAlphaImage.empty())
{
if (!LoadAlphaImage(theRes, aSharedImageRef))
return false;
}
if (!theRes->mAlphaGridImage.empty())
{
if (!LoadAlphaGridImage(theRes, aSharedImageRef))
return false;
}
}
aDDImage->CommitBits();
theRes->mImage = aSharedImageRef;
aDDImage->mPurgeBits = theRes->mPurgeBits;
if (theRes->mDDSurface)
{
SEXY_PERF_BEGIN("ResourceManager:DDSurface");
aDDImage->CommitBits();
if (!aDDImage->mHasAlpha)
{
aDDImage->mWantDDSurface = true;
aDDImage->mPurgeBits = true;
}
SEXY_PERF_END("ResourceManager:DDSurface");
}
if (theRes->mPalletize)
{
SEXY_PERF_BEGIN("ResourceManager:Palletize");
if (aDDImage->mSurface==NULL)
aDDImage->Palletize();
else
aDDImage->mWantPal = true;
SEXY_PERF_END("ResourceManager:Palletize");
}
if (theRes->mA4R4G4B4)
aDDImage->mD3DFlags |= D3DImageFlag_UseA4R4G4B4;
if (theRes->mA8R8G8B8)
aDDImage->mD3DFlags |= D3DImageFlag_UseA8R8G8B8;
if (theRes->mMinimizeSubdivisions)
aDDImage->mD3DFlags |= D3DImageFlag_MinimizeNumSubdivisions;
if (theRes->mAnimInfo.mAnimType != AnimType_None)
aDDImage->mAnimInfo = new AnimInfo(theRes->mAnimInfo);
aDDImage->mNumRows = theRes->mRows;
aDDImage->mNumCols = theRes->mCols;
if (aDDImage->mPurgeBits)
aDDImage->PurgeBits();
ResourceLoadedHook(theRes);
return true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ResourceManager::DeleteImage(const std::string &theName)
{
ReplaceImage(theName,NULL);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SharedImageRef ResourceManager::LoadImage(const std::string &theName)
{
ResMap::iterator anItr = mImageMap.find(theName);
if (anItr == mImageMap.end())
return NULL;
ImageRes *aRes = (ImageRes*)anItr->second;
if ((DDImage*) aRes->mImage != NULL)
return aRes->mImage;
if (aRes->mFromProgram)
return NULL;
if (!DoLoadImage(aRes))
return NULL;
return aRes->mImage;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::DoLoadSound(SoundRes* theRes)
{
SoundRes *aRes = theRes;
SEXY_PERF_BEGIN("ResourceManager:LoadSound");
int aSoundId = mApp->mSoundManager->GetFreeSoundId();
if (aSoundId<0)
return Fail("Out of free sound ids");
if(!mApp->mSoundManager->LoadSound(aSoundId, aRes->mPath))
return Fail(StrFormat("Failed to load sound: %s",aRes->mPath.c_str()));
SEXY_PERF_END("ResourceManager:LoadSound");
if (aRes->mVolume >= 0)
mApp->mSoundManager->SetBaseVolume(aSoundId, aRes->mVolume);
if (aRes->mPanning != 0)
mApp->mSoundManager->SetBasePan(aSoundId, aRes->mPanning);
aRes->mSoundId = aSoundId;
ResourceLoadedHook(theRes);
return true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::DoLoadFont(FontRes* theRes)
{
Font *aFont = NULL;
SEXY_PERF_BEGIN("ResourceManager:DoLoadFont");
if (theRes->mSysFont)
{
bool bold = theRes->mBold, simulateBold = false;
if (Sexy::CheckFor98Mill())
{
simulateBold = bold;
bold = false;
}
aFont = new SysFont(theRes->mPath,theRes->mSize,bold,theRes->mItalic,theRes->mUnderline);
SysFont* aSysFont = (SysFont*)aFont;
aSysFont->mDrawShadow = theRes->mShadow;
aSysFont->mSimulateBold = simulateBold;
}
else if (theRes->mImagePath.empty())
{
if (strncmp(theRes->mPath.c_str(),"!ref:",5)==0)
{
std::string aRefName = theRes->mPath.substr(5);
Font *aRefFont = GetFont(aRefName);
if (aRefFont==NULL)
return Fail("Ref font not found: " + aRefName);
aFont = aRefFont->Duplicate();
}
else
aFont = new ImageFont(mApp, theRes->mPath);
}
else
{
Image *anImage = mApp->GetImage(theRes->mImagePath);
if (anImage==NULL)
return Fail(StrFormat("Failed to load image: %s",theRes->mImagePath.c_str()));
theRes->mImage = anImage;
aFont = new ImageFont(anImage, theRes->mPath);
}
ImageFont *anImageFont = dynamic_cast<ImageFont*>(aFont);
if (anImageFont!=NULL)
{
if (anImageFont->mFontData==NULL || !anImageFont->mFontData->mInitialized)
{
delete aFont;
return Fail(StrFormat("Failed to load font: %s",theRes->mPath.c_str()));
}
if (!theRes->mTags.empty())
{
char aBuf[1024];
strcpy(aBuf,theRes->mTags.c_str());
const char *aPtr = strtok(aBuf,", \r\n\t");
while (aPtr != NULL)
{
anImageFont->AddTag(aPtr);
aPtr = strtok(NULL,", \r\n\t");
}
anImageFont->Prepare();
}
}
theRes->mFont = aFont;
SEXY_PERF_END("ResourceManager:DoLoadFont");
ResourceLoadedHook(theRes);
return true;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Font* ResourceManager::LoadFont(const std::string &theName)
{
ResMap::iterator anItr = mFontMap.find(theName);
if (anItr == mFontMap.end())
return NULL;
FontRes *aRes = (FontRes*)anItr->second;
if (aRes->mFont != NULL)
return aRes->mFont;
if (aRes->mFromProgram)
return NULL;
if (!DoLoadFont(aRes))
return NULL;
return aRes->mFont;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ResourceManager::DeleteFont(const std::string &theName)
{
ReplaceFont(theName,NULL);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::LoadNextResource()
{
if (HadError())
return false;
if (mCurResGroupList==NULL)
return false;
while (mCurResGroupListItr!=mCurResGroupList->end())
{
BaseRes *aRes = *mCurResGroupListItr++;
if (aRes->mFromProgram)
continue;
switch (aRes->mType)
{
case ResType_Image:
{
ImageRes *anImageRes = (ImageRes*)aRes;
if ((DDImage*)anImageRes->mImage!=NULL)
continue;
return DoLoadImage(anImageRes);
}
case ResType_Sound:
{
SoundRes *aSoundRes = (SoundRes*)aRes;
if (aSoundRes->mSoundId!=-1)
continue;
return DoLoadSound(aSoundRes);
}
case ResType_Font:
{
FontRes *aFontRes = (FontRes*)aRes;
if (aFontRes->mFont!=NULL)
continue;
return DoLoadFont(aFontRes);
}
}
}
return false;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ResourceManager::ResourceLoadedHook(BaseRes *theRes)
{
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ResourceManager::StartLoadResources(const std::string &theGroup)
{
mError = "";
mHasFailed = false;
mCurResGroup = theGroup;
mCurResGroupList = &mResGroupMap[theGroup];
mCurResGroupListItr = mCurResGroupList->begin();
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void ResourceManager::DumpCurResGroup(std::string& theDestStr)
{
const ResList* rl = &mResGroupMap.find(mCurResGroup)->second;
ResList::const_iterator it = rl->begin();
theDestStr = StrFormat("About to dump %d elements from current res group name %s\r\n", rl->size(), mCurResGroup.c_str());
ResList::const_iterator rl_end = rl->end();
while (it != rl_end)
{
BaseRes* br = *it++;
std::string prefix = StrFormat("%s: %s\r\n", br->mId.c_str(), br->mPath.c_str());
theDestStr += prefix;
if (br->mFromProgram)
theDestStr += std::string(" res is from program\r\n");
else if (br->mType == ResType_Image)
theDestStr += std::string(" res is an image\r\n");
else if (br->mType == ResType_Sound)
theDestStr += std::string(" res is a sound\r\n");
else if (br->mType == ResType_Font)
theDestStr += std::string(" res is a font\r\n");
if (it == mCurResGroupListItr)
theDestStr += std::string("iterator has reached mCurResGroupItr\r\n");
}
theDestStr += std::string("Done dumping resources\r\n");
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::LoadResources(const std::string &theGroup)
{
mError = "";
mHasFailed = false;
StartLoadResources(theGroup);
while (LoadNextResource())
{
}
if (!HadError())
{
mLoadedGroups.insert(theGroup);
return true;
}
else
return false;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int ResourceManager::GetNumResources(const std::string &theGroup, ResMap &theMap)
{
if (theGroup.empty())
return theMap.size();
int aCount = 0;
for (ResMap::iterator anItr = theMap.begin(); anItr != theMap.end(); ++anItr)
{
BaseRes *aRes = anItr->second;
if (aRes->mResGroup==theGroup && !aRes->mFromProgram)
++aCount;
}
return aCount;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int ResourceManager::GetNumImages(const std::string &theGroup)
{
return GetNumResources(theGroup, mImageMap);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int ResourceManager::GetNumSounds(const std::string &theGroup)
{
return GetNumResources(theGroup,mSoundMap);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int ResourceManager::GetNumFonts(const std::string &theGroup)
{
return GetNumResources(theGroup, mFontMap);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int ResourceManager::GetNumResources(const std::string &theGroup)
{
return GetNumImages(theGroup) + GetNumSounds(theGroup) + GetNumFonts(theGroup);
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SharedImageRef ResourceManager::GetImage(const std::string &theId)
{
ResMap::iterator anItr = mImageMap.find(theId);
if (anItr != mImageMap.end())
return ((ImageRes*)anItr->second)->mImage;
else
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int ResourceManager::GetSound(const std::string &theId)
{
ResMap::iterator anItr = mSoundMap.find(theId);
if (anItr != mSoundMap.end())
return ((SoundRes*)anItr->second)->mSoundId;
else
return -1;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Font* ResourceManager::GetFont(const std::string &theId)
{
ResMap::iterator anItr = mFontMap.find(theId);
if (anItr != mFontMap.end())
return ((FontRes*)anItr->second)->mFont;
else
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
SharedImageRef ResourceManager::GetImageThrow(const std::string &theId)
{
ResMap::iterator anItr = mImageMap.find(theId);
if (anItr != mImageMap.end())
{
ImageRes *aRes = (ImageRes*)anItr->second;
if ((MemoryImage*) aRes->mImage != NULL)
return aRes->mImage;
if (mAllowMissingProgramResources && aRes->mFromProgram)
return NULL;
}
Fail(StrFormat("Image resource not found: %s",theId.c_str()));
throw ResourceManagerException(GetErrorText());
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int ResourceManager::GetSoundThrow(const std::string &theId)
{
ResMap::iterator anItr = mSoundMap.find(theId);
if (anItr != mSoundMap.end())
{
SoundRes *aRes = (SoundRes*)anItr->second;
if (aRes->mSoundId!=-1)
return aRes->mSoundId;
if (mAllowMissingProgramResources && aRes->mFromProgram)
return -1;
}
Fail(StrFormat("Sound resource not found: %s",theId.c_str()));
throw ResourceManagerException(GetErrorText());
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
Font* ResourceManager::GetFontThrow(const std::string &theId)
{
ResMap::iterator anItr = mFontMap.find(theId);
if (anItr != mFontMap.end())
{
FontRes *aRes = (FontRes*)anItr->second;
if (aRes->mFont!=NULL)
return aRes->mFont;
if (mAllowMissingProgramResources && aRes->mFromProgram)
return NULL;
}
Fail(StrFormat("Font resource not found: %s",theId.c_str()));
throw ResourceManagerException(GetErrorText());
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
void ResourceManager::SetAllowMissingProgramImages(bool allow)
{
mAllowMissingProgramResources = allow;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::ReplaceImage(const std::string &theId, Image *theImage)
{
ResMap::iterator anItr = mImageMap.find(theId);
if (anItr != mImageMap.end())
{
anItr->second->DeleteResource();
((ImageRes*)anItr->second)->mImage = (MemoryImage*) theImage;
((ImageRes*)anItr->second)->mImage.mOwnsUnshared = true;
return true;
}
else
return false;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::ReplaceSound(const std::string &theId, int theSound)
{
ResMap::iterator anItr = mSoundMap.find(theId);
if (anItr != mSoundMap.end())
{
anItr->second->DeleteResource();
((SoundRes*)anItr->second)->mSoundId = theSound;
return true;
}
else
return false;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
bool ResourceManager::ReplaceFont(const std::string &theId, Font *theFont)
{
ResMap::iterator anItr = mFontMap.find(theId);
if (anItr != mFontMap.end())
{
anItr->second->DeleteResource();
((FontRes*)anItr->second)->mFont = theFont;
return true;
}
else
return false;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
const XMLParamMap& ResourceManager::GetImageAttributes(const std::string &theId)
{
static XMLParamMap aStrMap;
ResMap::iterator anItr = mImageMap.find(theId);
if (anItr != mImageMap.end())
return anItr->second->mXMLAttributes;
else
return aStrMap;
}