On 26/08/2016 at 09:05, xxxxxxxx wrote:
Hi eldiren,
thanks for writing us.
With reference to your request, I confirm there's no chance to effectively use the GetNext() method once the object has been removed. Infact although the pointed object is still valid, being removed from the document, can't provide a valid pointer to the next material thus returning nullptr if invoked after removal. Even worse if the GetNext() is invoked after the deletion of the object, it will result in calling a method of an object no longer existing in the memory.
To effectively delete materials while looping over the them, it's more comfortable to use a temporary pointer to store the pointer to the material object to be removed, then update the original pointer to point to the next object and proceed in removing and freeing the temporary pointer previously created.
BaseMaterial* pCurrentBaseMat = doc->GetFirstMaterial();
while (pCurrentBaseMat)
{
if (pCurrentBaseMat->GetName() == "RemoveMe")
{
BaseMaterial* pTempBaseMat = pCurrentBaseMat;
pCurrentBaseMat = pCurrentBaseMat->GetNext();
pTempBaseMat->Remove();
BaseMaterial::Free(pTempBaseMat);
}
else
pCurrentBaseMat = pCurrentBaseMat->GetNext();
}
Alternatively you could arrange a different design where a first loop runs over all the materials and store on a list the pointers of the materials to be deleted, and a second where, running over this list, the effective removal and resource deallocation of the marked items takes place.
BaseMaterial* pCurrentBaseMat = doc->GetFirstMaterial();
AtomArray* pRemovableItems = AtomArray::Alloc();
while (pCurrentBaseMat)
{
if (pCurrentBaseMat->GetName() == "RemoveMe")
pRemovableItems->Append((C4DAtom* )pCurrentBaseMat);
pCurrentBaseMat = pCurrentBaseMat->GetNext();
}
for (Int32 i = 0; i < pRemovableItems->GetCount(); i++)
{
BaseMaterial* pTmpBaseMat = (BaseMaterial* )pRemovableItems->GetIndex(i);
pTmpBaseMat->Remove();
BaseMaterial::Free(pTmpBaseMat);
}
Best, Riccardo