Merge pull request #967 from Akz-/emi-fix-savecrash

EMI: Free materials as soon as they are no longer in use by any costumes
This commit is contained in:
Joel Teichroeb 2014-07-22 14:46:05 -07:00
commit 96946a4802
4 changed files with 28 additions and 27 deletions

View File

@ -125,11 +125,6 @@ Actor::~Actor() {
if (_cleanBuffer) {
g_driver->delBuffer(_cleanBuffer);
}
Common::List<Material *>::iterator it = _materials.begin();
for (; it != _materials.end(); ++it) {
delete (*it);
}
}
void Actor::saveState(SaveGame *savedState) const {
@ -258,9 +253,12 @@ void Actor::saveState(SaveGame *savedState) const {
_lastWearChore.saveState(savedState);
Common::List<Material *>::const_iterator it = _materials.begin();
Common::List<MaterialPtr>::const_iterator it = _materials.begin();
for (; it != _materials.end(); ++it) {
savedState->writeLESint32((*it)->getActiveTexture());
if (*it) {
warning((*it)->getFilename().c_str());
savedState->writeLESint32((*it)->getActiveTexture());
}
}
savedState->writeLESint32(_lookAtActor);
@ -274,9 +272,6 @@ bool Actor::restoreState(SaveGame *savedState) {
delete *i;
}
_costumeStack.clear();
for (Common::List<Material *>::const_iterator i = _materials.begin(); i != _materials.end(); ++i) {
delete *i;
}
_materials.clear();
// load actor name
@ -440,9 +435,11 @@ bool Actor::restoreState(SaveGame *savedState) {
_lastWearChore.restoreState(savedState, this);
if (savedState->saveMinorVersion() >= 13) {
Common::List<Material *>::const_iterator it = _materials.begin();
Common::List<MaterialPtr>::const_iterator it = _materials.begin();
for (; it != _materials.end(); ++it) {
(*it)->setActiveTexture(savedState->readLESint32());
if (*it) {
(*it)->setActiveTexture(savedState->readLESint32());
}
}
}
@ -2411,22 +2408,28 @@ void Actor::restoreCleanBuffer() {
}
}
Material *Actor::findMaterial(const Common::String &name) {
MaterialPtr Actor::findMaterial(const Common::String &name) {
Common::String fixedName = g_resourceloader->fixFilename(name, false);
Common::List<Material *>::iterator it = _materials.begin();
Common::List<MaterialPtr>::iterator it = _materials.begin();
for (; it != _materials.end(); ++it) {
if ((*it)->getFilename() == fixedName) {
return *it;
if (*it) {
if ((*it)->getFilename() == fixedName) {
return *it;
}
} else {
it = _materials.erase(it);
}
}
return nullptr;
}
Material *Actor::loadMaterial(const Common::String &name, bool clamp) {
Material *mat = findMaterial(name);
MaterialPtr Actor::loadMaterial(const Common::String &name, bool clamp) {
MaterialPtr mat = findMaterial(name);
if (!mat) {
mat = g_resourceloader->loadMaterial(name.c_str(), nullptr, clamp);
// Note: We store a weak reference.
_materials.push_back(mat);
mat->dereference();
}
return mat;
}

View File

@ -555,8 +555,8 @@ public:
LightMode getLightMode() const { return _lightMode; }
void setLightMode(LightMode lightMode) { _lightMode = lightMode; }
Material *loadMaterial(const Common::String &name, bool clamp);
Material *findMaterial(const Common::String &name);
ObjectPtr<Material> loadMaterial(const Common::String &name, bool clamp);
ObjectPtr<Material> findMaterial(const Common::String &name);
private:
void costumeMarkerCallback(int marker);
@ -713,7 +713,7 @@ private:
LightMode _lightMode;
Common::List<Material *> _materials;
Common::List<ObjectPtr<Material> > _materials;
};
} // end of namespace Grim

View File

@ -283,12 +283,10 @@ Material *EMICostume::findMaterial(const Common::String &name) {
}
Material *EMICostume::loadMaterial(const Common::String &name, bool clamp) {
Material *mat = _owner->loadMaterial(name, clamp);
MaterialPtr mat = _owner->loadMaterial(name, clamp);
if (mat) {
// We keep track of the list of materials per costume, so we
// can load older savegames from a time when materials were managed
// by EMICostume instead of Actor. Once support for older saves is
// dropped, this list can be removed.
// Save a reference to the material, so it will not be freed during the
// lifetime of this costume.
if (Common::find(_materials.begin(), _materials.end(), mat) == _materials.end())
_materials.push_back(mat);
}

View File

@ -63,7 +63,7 @@ public:
EMISkelComponent *_emiSkel;
private:
bool _isWearChoreActive;
Common::List<Material *> _materials;
Common::List<ObjectPtr<Material> > _materials;
static bool compareChores(const Chore *c1, const Chore *c2);
Component *loadEMIComponent(Component *parent, int parentID, const char *name, Component *prevComponent);
void setWearChore(EMIChore *chore);