diff --git a/src/tarray.h b/src/tarray.h index 524c0942e8..1c5faca437 100644 --- a/src/tarray.h +++ b/src/tarray.h @@ -497,6 +497,14 @@ public: Array = nullptr; } } + + void Swap(TArray &other) + { + std::swap(Array, other.Array); + std::swap(Count, other.Count); + std::swap(Most, other.Most); + } + private: T *Array; unsigned int Count; @@ -760,6 +768,7 @@ struct FMap hash_t NumUsed; }; + template class TMapIterator; template class TMapConstIterator; @@ -947,6 +956,14 @@ public: DelKey(key); } + void Swap(MyType &other) + { + std::swap(Nodes, other.Nodes); + std::swap(LastFree, other.LastFree); + std::swap(Size, other.Size); + std::swap(NumUsed, other.NumUsed); + } + protected: struct IPair // This must be the same as Pair above, but with a { // non-const Key. @@ -1518,4 +1535,3 @@ private: T *Array; unsigned int Count; }; - diff --git a/src/textures/formats/multipatchtexture.h b/src/textures/formats/multipatchtexture.h index 3d78008328..8337ffe6c1 100644 --- a/src/textures/formats/multipatchtexture.h +++ b/src/textures/formats/multipatchtexture.h @@ -89,8 +89,30 @@ struct BuildInfo int LeftOffset[2] = {}; int TopOffset[2] = {}; FImageTexture *tex = nullptr; + + void swap(BuildInfo &other) + { + Name.Swap(other.Name); + Parts.Swap(other.Parts); + Inits.Swap(other.Inits); + std::swap(Width, other.Width); + std::swap(Height, other.Height); + std::swap(Scale, other.Scale); + std::swap(bWorldPanning, other.bWorldPanning); + std::swap(DefinitionLump, other.DefinitionLump); + std::swap(bComplex, bComplex); + std::swap(textual, other.textual); + std::swap(bNoDecals, other.bNoDecals); + std::swap(LeftOffset[0], other.LeftOffset[0]); + std::swap(LeftOffset[1], other.LeftOffset[1]); + std::swap(TopOffset[0], other.TopOffset[0]); + std::swap(TopOffset[1], other.TopOffset[1]); + std::swap(tex, other.tex); + } }; + + class FMultipatchTextureBuilder { FTextureManager &TexMan; diff --git a/src/textures/multipatchtexturebuilder.cpp b/src/textures/multipatchtexturebuilder.cpp index 7be8a69e53..4675220f55 100644 --- a/src/textures/multipatchtexturebuilder.cpp +++ b/src/textures/multipatchtexturebuilder.cpp @@ -922,11 +922,21 @@ void FMultipatchTextureBuilder::ResolveAllPatches() } // Now try to resolve the images. We only can do this at the end when all multipatch textures are set up. int i = 0; + + // reverse the list so that the Delete operation in the loop below deletes at the end. + // For normal sized lists this is of no real concern, but Total Chaos has over 250000 textures where this becomes a performance issue. + for (unsigned i = 0; i < BuiltTextures.Size() / 2; i++) + { + // std::swap is VERY inefficient here... + BuiltTextures[i].swap(BuiltTextures[BuiltTextures.Size() - 1 - i]); + } + + while (BuiltTextures.Size() > 0) { bool donesomething = false; - for (unsigned i = 0; i < BuiltTextures.Size(); i++) + for (int i = BuiltTextures.Size()-1; i>= 0; i--) { auto &buildinfo = BuiltTextures[i]; bool hasEmpty = false; @@ -969,7 +979,6 @@ void FMultipatchTextureBuilder::ResolveAllPatches() } BuiltTextures.Delete(i); - i--; donesomething = true; } } diff --git a/src/zstring.h b/src/zstring.h index 67fef4a181..334fbcb1f1 100644 --- a/src/zstring.h +++ b/src/zstring.h @@ -148,6 +148,11 @@ public: char *LockBuffer(); // Obtain write access to the character buffer void UnlockBuffer(); // Allow shared access to the character buffer + void Swap(FString &other) + { + std::swap(Chars, other.Chars); + } + operator const char *() const { return Chars; } const char *GetChars() const { return Chars; }