mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-25 05:21:02 +00:00
- 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.
This commit is contained in:
parent
93ec6eb92e
commit
4e4fd97950
3 changed files with 110 additions and 82 deletions
|
@ -48,6 +48,7 @@
|
||||||
#include "v_palette.h"
|
#include "v_palette.h"
|
||||||
#include "v_video.h"
|
#include "v_video.h"
|
||||||
#include "v_text.h"
|
#include "v_text.h"
|
||||||
|
#include "cmdlib.h"
|
||||||
#include "m_fixed.h"
|
#include "m_fixed.h"
|
||||||
#include "textures/textures.h"
|
#include "textures/textures.h"
|
||||||
#include "r_data/colormaps.h"
|
#include "r_data/colormaps.h"
|
||||||
|
@ -138,7 +139,6 @@ struct strifemaptexture_t
|
||||||
struct FPatchLookup
|
struct FPatchLookup
|
||||||
{
|
{
|
||||||
FString Name;
|
FString Name;
|
||||||
FTexture *Texture;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -166,6 +166,7 @@ public:
|
||||||
int GetSourceLump() { return DefinitionLump; }
|
int GetSourceLump() { return DefinitionLump; }
|
||||||
FTexture *GetRedirect(bool wantwarped);
|
FTexture *GetRedirect(bool wantwarped);
|
||||||
FTexture *GetRawTexture();
|
FTexture *GetRawTexture();
|
||||||
|
void ResolvePatches();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BYTE *Pixels;
|
BYTE *Pixels;
|
||||||
|
@ -185,8 +186,18 @@ protected:
|
||||||
TexPart();
|
TexPart();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TexInit
|
||||||
|
{
|
||||||
|
FString TexName;
|
||||||
|
int UseType = TEX_Null;
|
||||||
|
bool Silent = false;
|
||||||
|
bool HasLine = false;
|
||||||
|
FScriptPosition sc;
|
||||||
|
};
|
||||||
|
|
||||||
int NumParts;
|
int NumParts;
|
||||||
TexPart *Parts;
|
TexPart *Parts;
|
||||||
|
TexInit *Inits;
|
||||||
bool bRedirect:1;
|
bool bRedirect:1;
|
||||||
bool bTranslucentPatches:1;
|
bool bTranslucentPatches:1;
|
||||||
|
|
||||||
|
@ -194,7 +205,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CheckForHacks ();
|
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)
|
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
|
union
|
||||||
{
|
{
|
||||||
|
@ -240,7 +251,8 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl
|
||||||
}
|
}
|
||||||
|
|
||||||
UseType = FTexture::TEX_Wall;
|
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);
|
Width = SAFESHORT(mtexture.d->width);
|
||||||
Height = SAFESHORT(mtexture.d->height);
|
Height = SAFESHORT(mtexture.d->height);
|
||||||
Name = (char *)mtexture.d->name;
|
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].OriginX = LittleShort(mpatch.d->originx);
|
||||||
Parts[i].OriginY = LittleShort(mpatch.d->originy);
|
Parts[i].OriginY = LittleShort(mpatch.d->originy);
|
||||||
Parts[i].Texture = patchlookup[LittleShort(mpatch.d->patch)].Texture;
|
Parts[i].Texture = nullptr;
|
||||||
if (Parts[i].Texture == NULL)
|
Inits[i].TexName = patchlookup[LittleShort(mpatch.d->patch)].Name;
|
||||||
{
|
Inits[i].UseType = TEX_WallPatch;
|
||||||
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;
|
|
||||||
}
|
|
||||||
if (strife)
|
if (strife)
|
||||||
mpatch.s++;
|
mpatch.s++;
|
||||||
else
|
else
|
||||||
|
@ -295,17 +299,6 @@ FMultiPatchTexture::FMultiPatchTexture (const void *texdef, FPatchLookup *patchl
|
||||||
|
|
||||||
CheckForHacks ();
|
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;
|
DefinitionLump = deflumpnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,6 +320,11 @@ FMultiPatchTexture::~FMultiPatchTexture ()
|
||||||
delete[] Parts;
|
delete[] Parts;
|
||||||
Parts = NULL;
|
Parts = NULL;
|
||||||
}
|
}
|
||||||
|
if (Inits != nullptr)
|
||||||
|
{
|
||||||
|
delete[] Inits;
|
||||||
|
Inits = nullptr;
|
||||||
|
}
|
||||||
if (Spans != NULL)
|
if (Spans != NULL)
|
||||||
{
|
{
|
||||||
FreeSpans (Spans);
|
FreeSpans (Spans);
|
||||||
|
@ -863,19 +861,6 @@ void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int d
|
||||||
pnames.Read(pname, 8);
|
pnames.Read(pname, 8);
|
||||||
pname[8] = '\0';
|
pname[8] = '\0';
|
||||||
patchlookup[i].Name = pname;
|
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;
|
FString patchname;
|
||||||
|
int Mirror = 0;
|
||||||
sc.MustGetString();
|
sc.MustGetString();
|
||||||
|
|
||||||
FTextureID texno = TexMan.CheckForTexture(sc.String, usetype);
|
init.TexName = sc.String;
|
||||||
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());
|
|
||||||
}
|
|
||||||
sc.MustGetStringName(",");
|
sc.MustGetStringName(",");
|
||||||
sc.MustGetNumber();
|
sc.MustGetNumber();
|
||||||
part.OriginX = sc.Number;
|
part.OriginX = sc.Number;
|
||||||
|
@ -1207,6 +1170,7 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype)
|
||||||
: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false)
|
: Pixels (0), Spans(0), Parts(0), bRedirect(false), bTranslucentPatches(false)
|
||||||
{
|
{
|
||||||
TArray<TexPart> parts;
|
TArray<TexPart> parts;
|
||||||
|
TArray<TexInit> inits;
|
||||||
bool bSilent = false;
|
bool bSilent = false;
|
||||||
|
|
||||||
bMultiPatch = true;
|
bMultiPatch = true;
|
||||||
|
@ -1267,16 +1231,34 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype)
|
||||||
else if (sc.Compare("Patch"))
|
else if (sc.Compare("Patch"))
|
||||||
{
|
{
|
||||||
TexPart part;
|
TexPart part;
|
||||||
ParsePatch(sc, part, bSilent, TEX_WallPatch);
|
TexInit init;
|
||||||
if (part.Texture != NULL) parts.Push(part);
|
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.Texture = NULL;
|
||||||
part.Translation = NULL;
|
part.Translation = NULL;
|
||||||
}
|
}
|
||||||
else if (sc.Compare("Graphic"))
|
else if (sc.Compare("Graphic"))
|
||||||
{
|
{
|
||||||
TexPart part;
|
TexPart part;
|
||||||
ParsePatch(sc, part, bSilent, TEX_MiscPatch);
|
TexInit init;
|
||||||
if (part.Texture != NULL) parts.Push(part);
|
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.Texture = NULL;
|
||||||
part.Translation = NULL;
|
part.Translation = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1297,21 +1279,10 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype)
|
||||||
NumParts = parts.Size();
|
NumParts = parts.Size();
|
||||||
Parts = new TexPart[NumParts];
|
Parts = new TexPart[NumParts];
|
||||||
memcpy(Parts, &parts[0], NumParts * sizeof(*Parts));
|
memcpy(Parts, &parts[0], NumParts * sizeof(*Parts));
|
||||||
|
Inits = new TexInit[NumParts];
|
||||||
//CalcBitSize ();
|
for (int i = 0; i < NumParts; i++)
|
||||||
|
|
||||||
// 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 &&
|
Inits[i] = inits[i];
|
||||||
Parts->Texture->GetWidth() == Width &&
|
|
||||||
Parts->Texture->GetHeight() == Height &&
|
|
||||||
Parts->Rotate == 0 &&
|
|
||||||
!bComplex)
|
|
||||||
{
|
|
||||||
bRedirect = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
void FTextureManager::ParseXTexture(FScanner &sc, int usetype)
|
||||||
{
|
{
|
||||||
|
|
|
@ -981,6 +981,10 @@ void FTextureManager::Init()
|
||||||
{
|
{
|
||||||
AddTexturesForWad(i);
|
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
|
// Add one marker so that the last WAD is easier to handle and treat
|
||||||
// Build tiles as a completely separate block.
|
// Build tiles as a completely separate block.
|
||||||
|
|
|
@ -209,6 +209,7 @@ public:
|
||||||
int GetScaledTopOffset () { int foo = int((TopOffset * 2) / Scale.Y); return (foo >> 1) + (foo & 1); }
|
int GetScaledTopOffset () { int foo = int((TopOffset * 2) / Scale.Y); return (foo >> 1) + (foo & 1); }
|
||||||
double GetScaledLeftOffsetDouble() { return LeftOffset / Scale.X; }
|
double GetScaledLeftOffsetDouble() { return LeftOffset / Scale.X; }
|
||||||
double GetScaledTopOffsetDouble() { return TopOffset / Scale.Y; }
|
double GetScaledTopOffsetDouble() { return TopOffset / Scale.Y; }
|
||||||
|
virtual void ResolvePatches() {}
|
||||||
|
|
||||||
virtual void SetFrontSkyLayer();
|
virtual void SetFrontSkyLayer();
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue