From 4e4fd97950c8b844a235c890f176c9233590bb18 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 24 Oct 2016 23:35:18 +0200 Subject: [PATCH 1/3] - fixed: Multipatch textures may not set up their patch references until all textures have been loaded. If done earlier they will not be able to detect overrides of sprites and graphics which are not part of the PATCHES lump. There was some fudging code to work around this problem but it was only partially working. Now these textures only collect the texture name and use type during setup and resolve them after all textures have been created. --- src/textures/multipatchtexture.cpp | 187 ++++++++++++++++------------- src/textures/texturemanager.cpp | 4 + src/textures/textures.h | 1 + 3 files changed, 110 insertions(+), 82 deletions(-) diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index b0db481a89..741f88a31c 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -48,6 +48,7 @@ #include "v_palette.h" #include "v_video.h" #include "v_text.h" +#include "cmdlib.h" #include "m_fixed.h" #include "textures/textures.h" #include "r_data/colormaps.h" @@ -138,7 +139,6 @@ struct strifemaptexture_t struct FPatchLookup { FString Name; - FTexture *Texture; }; @@ -166,6 +166,7 @@ public: int GetSourceLump() { return DefinitionLump; } FTexture *GetRedirect(bool wantwarped); FTexture *GetRawTexture(); + void ResolvePatches(); protected: BYTE *Pixels; @@ -185,8 +186,18 @@ protected: TexPart(); }; + struct TexInit + { + FString TexName; + int UseType = TEX_Null; + bool Silent = false; + bool HasLine = false; + FScriptPosition sc; + }; + int NumParts; TexPart *Parts; + TexInit *Inits; bool bRedirect:1; bool bTranslucentPatches:1; @@ -194,7 +205,7 @@ protected: private: void CheckForHacks (); - void ParsePatch(FScanner &sc, TexPart & part, bool silent, int usetype); + void ParsePatch(FScanner &sc, TexPart & part, TexInit &init); }; //========================================================================== @@ -204,7 +215,7 @@ private: //========================================================================== FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchlookup, int maxpatchnum, bool strife, int deflumpnum) -: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false) +: Pixels (0), Spans(0), Parts(nullptr), Inits(nullptr), bRedirect(false), bTranslucentPatches(false) { union { @@ -240,7 +251,8 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl } UseType = FTexture::TEX_Wall; - Parts = NumParts > 0 ? new TexPart[NumParts] : NULL; + Parts = NumParts > 0 ? new TexPart[NumParts] : nullptr; + Inits = NumParts > 0 ? new TexInit[NumParts] : nullptr; Width = SAFESHORT(mtexture.d->width); Height = SAFESHORT(mtexture.d->height); Name = (char *)mtexture.d->name; @@ -272,17 +284,9 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl } Parts[i].OriginX = LittleShort(mpatch.d->originx); Parts[i].OriginY = LittleShort(mpatch.d->originy); - Parts[i].Texture = patchlookup[LittleShort(mpatch.d->patch)].Texture; - if (Parts[i].Texture == NULL) - { - Printf(TEXTCOLOR_RED "Unknown patch %s in texture %s\n", patchlookup[LittleShort(mpatch.d->patch)].Name.GetChars(), Name.GetChars()); - NumParts--; - i--; - } - else - { - Parts[i].Texture->bKeepAround = true; - } + Parts[i].Texture = nullptr; + Inits[i].TexName = patchlookup[LittleShort(mpatch.d->patch)].Name; + Inits[i].UseType = TEX_WallPatch; if (strife) mpatch.s++; else @@ -295,17 +299,6 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl CheckForHacks (); - // If this texture is just a wrapper around a single patch, we can simply - // forward GetPixels() and GetColumn() calls to that patch. - if (NumParts == 1) - { - if (Parts->OriginX == 0 && Parts->OriginY == 0 && - Parts->Texture->GetWidth() == Width && - Parts->Texture->GetHeight() == Height) - { - bRedirect = true; - } - } DefinitionLump = deflumpnum; } @@ -327,6 +320,11 @@ FMultiPatchTexture::~FMultiPatchTexture () delete[] Parts; Parts = NULL; } + if (Inits != nullptr) + { + delete[] Inits; + Inits = nullptr; + } if (Spans != NULL) { FreeSpans (Spans); @@ -863,19 +861,6 @@ void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int d pnames.Read(pname, 8); pname[8] = '\0'; patchlookup[i].Name = pname; - FTextureID j = CheckForTexture (patchlookup[i].Name, FTexture::TEX_WallPatch); - if (j.isValid()) - { - patchlookup[i].Texture = Textures[j.GetIndex()].Texture; - } - else - { - // Shareware Doom has the same PNAMES lump as the registered - // Doom, so printing warnings for patches that don't really - // exist isn't such a good idea. - //Printf ("Patch %s not found.\n", patchlookup[i].Name); - patchlookup[i].Texture = NULL; - } } } @@ -996,35 +981,13 @@ void FTextureManager::AddTexturesLumps (int lump1, int lump2, int patcheslump) // //========================================================================== -void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, bool silent, int usetype) +void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part, TexInit &init) { FString patchname; + int Mirror = 0; sc.MustGetString(); - FTextureID texno = TexMan.CheckForTexture(sc.String, usetype); - int Mirror = 0; - - if (!texno.isValid()) - { - if (strlen(sc.String) <= 8 && !strpbrk(sc.String, "./")) - { - int lumpnum = Wads.CheckNumForName(sc.String, usetype == TEX_MiscPatch? ns_graphics : ns_patches); - if (lumpnum >= 0) - { - part.Texture = FTexture::CreateTexture(lumpnum, usetype); - TexMan.AddTexture(part.Texture); - } - } - } - else - { - part.Texture = TexMan[texno]; - bComplex |= part.Texture->bComplex; - } - if (part.Texture == NULL) - { - if (!silent) sc.ScriptMessage(TEXTCOLOR_RED "Unknown patch '%s' in texture '%s'\n", sc.String, Name.GetChars()); - } + init.TexName = sc.String; sc.MustGetStringName(","); sc.MustGetNumber(); part.OriginX = sc.Number; @@ -1207,6 +1170,7 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) : Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false) { TArray parts; + TArray inits; bool bSilent = false; bMultiPatch = true; @@ -1267,16 +1231,34 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) else if (sc.Compare("Patch")) { TexPart part; - ParsePatch(sc, part, bSilent, TEX_WallPatch); - if (part.Texture != NULL) parts.Push(part); + TexInit init; + ParsePatch(sc, part, init); + if (init.TexName.IsNotEmpty()) + { + parts.Push(part); + init.UseType = TEX_WallPatch; + init.Silent = bSilent; + init.HasLine = true; + init.sc = sc; + inits.Push(init); + } part.Texture = NULL; part.Translation = NULL; } else if (sc.Compare("Graphic")) { TexPart part; - ParsePatch(sc, part, bSilent, TEX_MiscPatch); - if (part.Texture != NULL) parts.Push(part); + TexInit init; + ParsePatch(sc, part, init); + if (init.TexName.IsNotEmpty()) + { + parts.Push(part); + init.UseType = TEX_MiscPatch; + init.Silent = bSilent; + init.HasLine = true; + init.sc = sc; + inits.Push(init); + } part.Texture = NULL; part.Translation = NULL; } @@ -1297,21 +1279,10 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) NumParts = parts.Size(); Parts = new TexPart[NumParts]; memcpy(Parts, &parts[0], NumParts * sizeof(*Parts)); - - //CalcBitSize (); - - // If this texture is just a wrapper around a single patch, we can simply - // forward GetPixels() and GetColumn() calls to that patch. - if (NumParts == 1) + Inits = new TexInit[NumParts]; + for (int i = 0; i < NumParts; i++) { - if (Parts->OriginX == 0 && Parts->OriginY == 0 && - Parts->Texture->GetWidth() == Width && - Parts->Texture->GetHeight() == Height && - Parts->Rotate == 0 && - !bComplex) - { - bRedirect = true; - } + Inits[i] = inits[i]; } } @@ -1328,6 +1299,58 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) } +void FMultiPatchTexture::ResolvePatches() +{ + if (Inits != nullptr) + { + for (int i = 0; i < NumParts; i++) + { + FTextureID texno = TexMan.CheckForTexture(Inits[i].TexName, Inits[i].UseType); + + if (!texno.isValid()) + { + if (!Inits[i].Silent) + { + if (Inits[i].HasLine) Inits[i].sc.Message(MSG_WARNING, "Unknown patch '%s' in texture '%s'\n", Inits[i].TexName.GetChars(), Name.GetChars()); + else Printf(TEXTCOLOR_YELLOW "Unknown patch '%s' in texture '%s'\n", Inits[i].TexName.GetChars(), Name.GetChars()); + } + } + else + { + Parts[i].Texture = TexMan[texno]; + bComplex |= Parts[i].Texture->bComplex; + Parts[i].Texture->bKeepAround = true; + } + } + for (int i = 0; i < NumParts; i++) + { + if (Parts[i].Texture == nullptr) + { + memcpy(&Parts[i], &Parts[i + 1], NumParts - i - 1); + i--; + NumParts--; + } + } + } + delete[] Inits; + Inits = nullptr; + + // If this texture is just a wrapper around a single patch, we can simply + // forward GetPixels() and GetColumn() calls to that patch. + + if (NumParts == 1) + { + if (Parts->OriginX == 0 && Parts->OriginY == 0 && + Parts->Texture->GetWidth() == Width && + Parts->Texture->GetHeight() == Height && + Parts->Rotate == 0 && + !bComplex) + { + bRedirect = true; + } + } +} + void FTextureManager::ParseXTexture(FScanner &sc, int usetype) { diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 3fb01dc6cf..07ed71a3bb 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -981,6 +981,10 @@ void FTextureManager::Init() { AddTexturesForWad(i); } + for (unsigned i = 0; i < Textures.Size(); i++) + { + Textures[i].Texture->ResolvePatches(); + } // Add one marker so that the last WAD is easier to handle and treat // Build tiles as a completely separate block. diff --git a/src/textures/textures.h b/src/textures/textures.h index ad1d9ba8c2..407500f185 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -209,6 +209,7 @@ public: int GetScaledTopOffset () { int foo = int((TopOffset * 2) / Scale.Y); return (foo >> 1) + (foo & 1); } double GetScaledLeftOffsetDouble() { return LeftOffset / Scale.X; } double GetScaledTopOffsetDouble() { return TopOffset / Scale.Y; } + virtual void ResolvePatches() {} virtual void SetFrontSkyLayer(); From 8368272b4d5848d2f6596d5350164b3902194e94 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 24 Oct 2016 23:40:37 +0200 Subject: [PATCH 2/3] - just to be thorough, added a 'sprite' keyword to define a patch to give priority to the TEX_Sprite namespace. --- src/textures/multipatchtexture.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index 741f88a31c..340376a25b 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -1245,6 +1245,23 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype) part.Texture = NULL; part.Translation = NULL; } + else if (sc.Compare("Sprite")) + { + TexPart part; + TexInit init; + ParsePatch(sc, part, init); + if (init.TexName.IsNotEmpty()) + { + parts.Push(part); + init.UseType = TEX_Sprite; + init.Silent = bSilent; + init.HasLine = true; + init.sc = sc; + inits.Push(init); + } + part.Texture = NULL; + part.Translation = NULL; + } else if (sc.Compare("Graphic")) { TexPart part; From dad89b07830f649af1e26cba15990328e517ddf6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 25 Oct 2016 01:03:44 +0200 Subject: [PATCH 3/3] - fixed: Portals with disconnected parts were not grouped correctly. --- src/portal.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/portal.cpp b/src/portal.cpp index cef79820fe..f1454cdc6c 100644 --- a/src/portal.cpp +++ b/src/portal.cpp @@ -1024,7 +1024,8 @@ void P_CreateLinkedPortals() { if (sectors[i].GetPortalType(j) == PORTS_LINKEDPORTAL && sectors[i].PortalGroup == 0) { - CollectSectors(sectors[i].GetOppositePortalGroup(j), §ors[i]); + auto p = sectors[i].GetPortal(j); + CollectSectors(p->mOrigin->PortalGroup, §ors[i]); } } }