- Got rid of most TexMan.AddPatch calls because they are no longer needed.

- Got rid of R_InitPatches because the new texture init code needs to preload
  everything to work correctly.
- Rewrote texture manager initialization to order textures primarily by WAD 
  rather than by type. This way later textures will always override earlier 
  ones. The only exception is that TEX_MiscPatch are only used as a fallback
  if nothing else can be found.
- Optimized the tryany case of FTextureManager::CheckForTexture. It is not
  necessary to scan the hash chain twice. The required information can be
  retrieved during the first pass as easily and even offers a little more
  control.
- Made FFont destructor virtual.
- Added 'Ice' translation to DECORATE.

(Caution: Not fully tested yet!)

SVN r715 (trunk)
This commit is contained in:
Christoph Oelckers 2008-01-26 23:20:34 +00:00
parent 58816f5d09
commit 1b28557341
20 changed files with 1517 additions and 1451 deletions

View file

@ -1,4 +1,17 @@
January 26, 2008 (Changes by Graf Zahl)
- Got rid of most TexMan.AddPatch calls because they are no longer needed.
- Got rid of R_InitPatches because the new texture init code needs to preload
everything to work correctly.
- Rewrote texture manager initialization to order textures primarily by WAD
rather than by type. This way later textures will always override earlier
ones. The only exception is that TEX_MiscPatch are only used as a fallback
if nothing else can be found.
- Optimized the tryany case of FTextureManager::CheckForTexture. It is not
necessary to scan the hash chain twice. The required information can be
retrieved during the first pass as easily and even offers a little more
control.
- Made FFont destructor virtual.
- Added 'Ice' translation to DECORATE.
- Added Karate Chris's patch for teamplay MAPINFO option.
- Added Karate Chris's patch for custom damage color per player class.
- Added Karate Chris's patch for respawnlimit skill property.

View file

@ -1234,7 +1234,6 @@ void F_Drawer (void)
break;
case END_Pic:
picname = EndSequences[FinaleSequence].PicName;
TexMan.AddPatch (picname); // make sure it exists!
break;
case END_Bunny:
case END_BuyStrife:

View file

@ -1043,7 +1043,7 @@ private:
FDoomStatusBar::FDoomStatusBarTexture::FDoomStatusBarTexture ()
{
BaseTexture = TexMan[TexMan.AddPatch("STBAR")];
BaseTexture = TexMan["STBAR"];
if (BaseTexture==NULL)
{
I_Error("Fatal error: STBAR not found");

View file

@ -1157,7 +1157,6 @@ static void ParseEpisodeInfo (FScanner &sc)
bool picisgfx = false; // Shut up, GCC!!!!
bool remove = false;
char key = 0;
bool addedgfx = false;
bool noskill = false;
// Get map name
@ -1264,15 +1263,6 @@ static void ParseEpisodeInfo (FScanner &sc)
EpisodeMenu[i].fulltext = !picisgfx;
EpisodeNoSkill[i] = noskill;
strncpy (EpisodeMaps[i], map, 8);
if (picisgfx)
{
if (TexMan.CheckForTexture (pic, FTexture::TEX_MiscPatch, 0) == -1)
{
TexMan.AddPatch (pic);
addedgfx = true;
}
}
}
}

View file

@ -893,17 +893,17 @@ void HUD_InitHud()
{
case GAME_Heretic:
case GAME_Hexen:
healthpic=TexMan[TexMan.AddPatch("ARTIPTN2", ns_sprites)];
healthpic = TexMan.FindTexture("ARTIPTN2");
HudFont=FFont::FindFont("HUDFONT_RAVEN");
break;
case GAME_Strife:
healthpic=TexMan[TexMan.AddPatch("I_MDKT")];
healthpic = TexMan.FindTexture("I_MDKT");
HudFont=BigFont; // Strife doesn't have anything nice so use the standard font
break;
default:
healthpic=TexMan[TexMan.AddPatch("MEDIA0", ns_sprites)];
healthpic = TexMan.FindTexture("MEDIA0");
HudFont=FFont::FindFont("HUDFONT_DOOM");
break;
}
@ -913,12 +913,12 @@ void HUD_InitHud()
if (HudFont == NULL) HudFont = BigFont;
if (IndexFont == NULL) IndexFont = ConFont; // Emergency fallback
invgems[0] = TexMan[TexMan.AddPatch("INVGEML1")];
invgems[1] = TexMan[TexMan.AddPatch("INVGEML2")];
invgems[2] = TexMan[TexMan.AddPatch("INVGEMR1")];
invgems[3] = TexMan[TexMan.AddPatch("INVGEMR2")];
invgems[0] = TexMan.FindTexture("INVGEML1");
invgems[1] = TexMan.FindTexture("INVGEML2");
invgems[2] = TexMan.FindTexture("INVGEMR1");
invgems[3] = TexMan.FindTexture("INVGEMR2");
fragpic = TexMan[TexMan.AddPatch("HU_FRAGS")]; // Sadly, I don't have anything usable for this. :(
fragpic = TexMan.FindTexture("HU_FRAGS"); // Sadly, I don't have anything usable for this. :(
KeyTypes.Clear();
UnassignedKeyTypes.Clear();
@ -934,9 +934,8 @@ void HUD_InitHud()
if (sc.Compare("Health"))
{
sc.MustGetString();
int tex = TexMan.AddPatch(sc.String);
if (tex<=0) tex = TexMan.AddPatch(sc.String, ns_sprites);
if (tex>0) healthpic = TexMan[tex];
int tex = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch);
if (tex > 0) healthpic = TexMan[tex];
}
else
{
@ -955,8 +954,7 @@ void HUD_InitHud()
if (!sc.Compare("0") && !sc.Compare("NULL") && !sc.Compare(""))
{
tex = TexMan.AddPatch(sc.String);
if (tex<=0) tex = TexMan.AddPatch(sc.String, ns_sprites);
tex = TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch);
}
else tex=-1;

View file

@ -114,7 +114,7 @@ CUSTOM_CVAR (Int, crosshair, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
strcpy (name, "XHAIRS1");
}
}
CrosshairImage = TexMan[TexMan.AddPatch (name)];
CrosshairImage = TexMan[name];
}
CVAR (Color, crosshaircolor, 0xff0000, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);

View file

@ -1466,10 +1466,9 @@ void M_DrawReadThis ()
{
tex = TexMan[gameinfo.info.infoPage[InfoType-1]];
// Did the mapper choose a custom help page via MAPINFO?
if((level.f1 != NULL) && (strcmp(level.f1, "") != 0)) {
if(TexMan.CheckForTexture(level.f1,0,0) == -1)
TexMan.AddPatch(level.f1); // Needs to be marked as a patch.
tex = TexMan[level.f1];
if((level.f1 != NULL) && (strlen(level.f1) > 0))
{
tex = TexMan.FindTexture(level.f1);
}
if (InfoType > 1)

View file

@ -275,7 +275,7 @@ static FStrifeDialogueNode *ReadRetailNode (FWadLump *lump, DWORD &prevSpeakerTy
// The speaker's portrait, if any.
speech.Backdrop[8] = 0;
node->Backdrop = TexMan.AddPatch (speech.Backdrop);
node->Backdrop = TexMan.CheckForTexture (speech.Backdrop, FTexture::TEX_MiscPatch);
// The speaker's voice for this node, if any.
speech.Sound[8] = 0;

View file

@ -60,7 +60,6 @@ static int R_CountGroup (const char *start, const char *end);
static int R_CountTexturesX ();
static int R_CountLumpTextures (int lumpnum);
extern void R_InitBuildTiles();
extern void R_DeinitBuildTiles();
extern int R_CountBuildTiles();
@ -80,539 +79,6 @@ BYTE** warpedflats;
int* flatwarpedwhen;
FTextureManager TexMan;
FTextureManager::FTextureManager ()
{
memset (HashFirst, -1, sizeof(HashFirst));
// Texture 0 is a dummy texture used to indicate "no texture"
AddTexture (new FDummyTexture);
}
FTextureManager::~FTextureManager ()
{
for (unsigned int i = 0; i < Textures.Size(); ++i)
{
delete Textures[i].Texture;
}
}
int FTextureManager::CheckForTexture (const char *name, int usetype, BITFIELD flags)
{
int i;
if (name == NULL || name[0] == '\0')
{
return -1;
}
// [RH] Doom counted anything beginning with '-' as "no texture".
// Hopefully nobody made use of that and had textures like "-EMPTY",
// because -NOFLAT- is a valid graphic for ZDoom.
if (name[0] == '-' && name[1] == '\0')
{
return 0;
}
i = HashFirst[MakeKey (name) % HASH_SIZE];
while (i != HASH_END)
{
const FTexture *tex = Textures[i].Texture;
if (stricmp (tex->Name, name) == 0)
{
// The name matches, so check the texture type
if (usetype == FTexture::TEX_Any)
{
// All NULL textures should actually return 0
return tex->UseType==FTexture::TEX_Null? 0 : i;
}
else if ((flags & TEXMAN_Overridable) && tex->UseType == FTexture::TEX_Override)
{
return i;
}
else if (tex->UseType == usetype)
{
return i;
}
}
i = Textures[i].HashNext;
}
if ((flags & TEXMAN_TryAny) && usetype != FTexture::TEX_Any)
{
return CheckForTexture (name, FTexture::TEX_Any, flags & ~TEXMAN_TryAny);
}
return -1;
}
int FTextureManager::ListTextures (const char *name, TArray<int> &list)
{
int i;
if (name == NULL || name[0] == '\0')
{
return 0;
}
// [RH] Doom counted anything beginning with '-' as "no texture".
// Hopefully nobody made use of that and had textures like "-EMPTY",
// because -NOFLAT- is a valid graphic for ZDoom.
if (name[0] == '-' && name[1] == '\0')
{
return 0;
}
i = HashFirst[MakeKey (name) % HASH_SIZE];
while (i != HASH_END)
{
const FTexture *tex = Textures[i].Texture;
if (stricmp (tex->Name, name) == 0)
{
// NULL textures must be ignored.
if (tex->UseType!=FTexture::TEX_Null)
{
unsigned int j;
for(j = 0; j < list.Size(); j++)
{
// Check for overriding definitions from newer WADs
if (Textures[list[j]].Texture->UseType == tex->UseType) break;
}
if (j==list.Size()) list.Push(i);
}
}
i = Textures[i].HashNext;
}
return list.Size();
}
int FTextureManager::GetTexture (const char *name, int usetype, BITFIELD flags)
{
int i;
if (name == NULL || name[0] == 0)
{
return 0;
}
else
{
i = CheckForTexture (name, usetype, flags | TEXMAN_TryAny);
}
if (i == -1)
{
// Use a default texture instead of aborting like Doom did
Printf ("Unknown texture: \"%s\"\n", name);
i = DefaultTexture;
}
return i;
}
void FTextureManager::WriteTexture (FArchive &arc, int picnum)
{
FTexture *pic;
if ((size_t)picnum >= Textures.Size())
{
pic = Textures[0].Texture;
}
else
{
pic = Textures[picnum].Texture;
}
arc.WriteCount (pic->UseType);
arc.WriteName (pic->Name);
}
int FTextureManager::ReadTexture (FArchive &arc)
{
int usetype;
const char *name;
usetype = arc.ReadCount ();
name = arc.ReadName ();
return GetTexture (name, usetype);
}
void FTextureManager::UnloadAll ()
{
for (unsigned int i = 0; i < Textures.Size(); ++i)
{
Textures[i].Texture->Unload ();
}
}
int FTextureManager::AddTexture (FTexture *texture)
{
// Later textures take precedence over earlier ones
size_t bucket = MakeKey (texture->Name) % HASH_SIZE;
TextureHash hasher = { texture, HashFirst[bucket] };
WORD trans = Textures.Push (hasher);
Translation.Push (trans);
HashFirst[bucket] = trans;
return trans;
}
// Calls FTexture::CreateTexture and adds the texture to the manager.
int FTextureManager::CreateTexture (int lumpnum, int usetype)
{
if (lumpnum != -1)
{
FTexture *out = FTexture::CreateTexture(lumpnum, usetype);
if (out != NULL) return AddTexture (out);
else
{
Printf (TEXTCOLOR_ORANGE "Invalid data encountered for texture %s\n", Wads.GetLumpFullName(lumpnum));
return -1;
}
}
return -1;
}
void FTextureManager::ReplaceTexture (int picnum, FTexture *newtexture, bool free)
{
if ((size_t)picnum >= Textures.Size())
return;
FTexture *oldtexture = Textures[picnum].Texture;
strcpy (newtexture->Name, oldtexture->Name);
newtexture->UseType = oldtexture->UseType;
Textures[picnum].Texture = newtexture;
if (free)
{
delete oldtexture;
}
}
int FTextureManager::AddPatch (const char *patchname, int namespc, bool tryany)
{
if (patchname == NULL)
{
return -1;
}
int lumpnum = CheckForTexture (patchname, FTexture::TEX_MiscPatch, tryany);
if (lumpnum >= 0)
{
return lumpnum;
}
lumpnum = Wads.CheckNumForName (patchname, namespc==ns_global? ns_graphics:namespc);
if (lumpnum < 0)
{
return -1;
}
return CreateTexture (lumpnum, FTexture::TEX_MiscPatch);
}
void FTextureManager::AddGroup(const char * startlump, const char * endlump, int ns, int usetype)
{
int firsttx = Wads.CheckNumForName (startlump);
int lasttx = Wads.CheckNumForName (endlump);
char name[9];
if (firsttx == -1 || lasttx == -1)
{
return;
}
name[8] = 0;
// Go from first to last so that ANIMDEFS work as expected. However,
// to avoid duplicates (and to keep earlier entries from overriding
// later ones), the texture is only inserted if it is the one returned
// by doing a check by name in the list of wads.
for (firsttx += 1; firsttx < lasttx; ++firsttx)
{
Wads.GetLumpName (name, firsttx);
if (Wads.CheckNumForName (name, ns) == firsttx)
{
CreateTexture (firsttx, usetype);
}
StartScreen->Progress();
}
}
//==========================================================================
//
// Adds all hires texture definitions.
//
//==========================================================================
void FTextureManager::AddHiresTextures ()
{
int firsttx = Wads.CheckNumForName ("HI_START");
int lasttx = Wads.CheckNumForName ("HI_END");
char name[9];
TArray<int> tlist;
if (firsttx == -1 || lasttx == -1)
{
return;
}
name[8] = 0;
for (firsttx += 1; firsttx < lasttx; ++firsttx)
{
tlist.Clear();
Wads.GetLumpName (name, firsttx);
if (Wads.CheckNumForName (name, ns_hires) == firsttx)
{
int amount = ListTextures(name, tlist);
if (amount == 0)
{
int oldtex = AddPatch(name);
if (oldtex >= 0) tlist.Push(oldtex);
}
if (tlist.Size() == 0)
{
// A texture with this name does not yet exist
FTexture * newtex = FTexture::CreateTexture (firsttx, FTexture::TEX_Any);
newtex->UseType=FTexture::TEX_Override;
AddTexture(newtex);
}
else
{
for(unsigned int i = 0; i < tlist.Size(); i++)
{
FTexture * newtex = FTexture::CreateTexture (firsttx, FTexture::TEX_Any);
if (newtex != NULL)
{
int oldtexno = tlist[i];
FTexture * oldtex = Textures[oldtexno].Texture;
// Replace the entire texture and adjust the scaling and offset factors.
newtex->bWorldPanning = true;
newtex->SetScaledSize(oldtex->GetScaledWidth(), oldtex->GetScaledHeight());
newtex->LeftOffset = FixedMul(oldtex->GetScaledLeftOffset(), newtex->xScale);
newtex->TopOffset = FixedMul(oldtex->GetScaledTopOffset(), newtex->yScale);
ReplaceTexture(oldtexno, newtex, true);
}
}
}
StartScreen->Progress();
}
}
}
//==========================================================================
//
// Loads the HIRESTEX lumps
//
//==========================================================================
void FTextureManager::LoadHiresTex()
{
int remapLump, lastLump;
char src[9];
bool is32bit;
int width, height;
int type, mode;
TArray<int> tlist;
lastLump = 0;
src[8] = '\0';
while ((remapLump = Wads.FindLump("HIRESTEX", &lastLump)) != -1)
{
FScanner sc(remapLump, "HIRESTEX");
while (sc.GetString())
{
if (sc.Compare("remap")) // remap an existing texture
{
sc.MustGetString();
// allow selection by type
if (sc.Compare("wall")) type=FTexture::TEX_Wall, mode=FTextureManager::TEXMAN_Overridable;
else if (sc.Compare("flat")) type=FTexture::TEX_Flat, mode=FTextureManager::TEXMAN_Overridable;
else if (sc.Compare("sprite")) type=FTexture::TEX_Sprite, mode=0;
else type = FTexture::TEX_Any, mode = 0;
sc.String[8]=0;
tlist.Clear();
int amount = ListTextures(sc.String, tlist);
if (amount == 0)
{
int oldtex = AddPatch(sc.String);
if (oldtex >= 0) tlist.Push(oldtex);
}
FName texname = sc.String;
sc.MustGetString();
int lumpnum = Wads.CheckNumForFullName(sc.String);
if (lumpnum < 0) lumpnum = Wads.CheckNumForName(sc.String, ns_graphics);
if (tlist.Size() == 0)
{
Printf("Attempting to remap non-existent texture %s to %s\n",
texname.GetChars(), sc.String);
}
else
{
for(unsigned int i = 0; i < tlist.Size(); i++)
{
FTexture * oldtex = Textures[tlist[i]].Texture;
int sl;
// only replace matching types. For sprites also replace any MiscPatches
// based on the same lump. These can be created for icons.
if (oldtex->UseType == type || type == FTexture::TEX_Any ||
(mode == TEXMAN_Overridable && oldtex->UseType == FTexture::TEX_Override) ||
(type == FTexture::TEX_Sprite && oldtex->UseType == FTexture::TEX_MiscPatch &&
(sl=oldtex->GetSourceLump()) >= 0 && Wads.GetLumpNamespace(sl) == ns_sprites)
)
{
FTexture * newtex = FTexture::CreateTexture (lumpnum, FTexture::TEX_Any);
if (newtex != NULL)
{
// Replace the entire texture and adjust the scaling and offset factors.
newtex->bWorldPanning = true;
newtex->SetScaledSize(oldtex->GetScaledWidth(), oldtex->GetScaledHeight());
newtex->LeftOffset = FixedMul(oldtex->GetScaledLeftOffset(), newtex->xScale);
newtex->TopOffset = FixedMul(oldtex->GetScaledTopOffset(), newtex->yScale);
ReplaceTexture(tlist[i], newtex, true);
}
}
}
}
}
else if (sc.Compare("define")) // define a new "fake" texture
{
sc.GetString();
memcpy(src, sc.String, 8);
int lumpnum = Wads.CheckNumForFullName(sc.String);
if (lumpnum < 0) lumpnum = Wads.CheckNumForName(sc.String, ns_graphics);
sc.GetString();
is32bit = !!sc.Compare("force32bit");
if (!is32bit) sc.UnGet();
sc.GetNumber();
width = sc.Number;
sc.GetNumber();
height = sc.Number;
if (lumpnum>=0)
{
FTexture *newtex = FTexture::CreateTexture(lumpnum, FTexture::TEX_Override);
if (newtex != NULL)
{
// Replace the entire texture and adjust the scaling and offset factors.
newtex->bWorldPanning = true;
newtex->SetScaledSize(width, height);
memcpy(newtex->Name, src, sizeof(newtex->Name));
int oldtex = TexMan.CheckForTexture(src, FTexture::TEX_Override);
if (oldtex>=0) TexMan.ReplaceTexture(oldtex, newtex, true);
else TexMan.AddTexture(newtex);
}
}
//else Printf("Unable to define hires texture '%s'\n", tex->Name);
}
}
}
}
void FTextureManager::AddPatches (int lumpnum)
{
FWadLump *file = Wads.ReopenLumpNum (lumpnum);
DWORD numpatches, i;
char name[9];
*file >> numpatches;
name[8] = 0;
for (i = 0; i < numpatches; ++i)
{
file->Read (name, 8);
if (CheckForTexture (name, FTexture::TEX_WallPatch, false) == -1)
{
CreateTexture (Wads.CheckNumForName (name, ns_patches), FTexture::TEX_WallPatch);
}
StartScreen->Progress();
}
delete file;
}
//
// R_InitTextures
// Initializes the texture list with the textures from the world map.
//
void R_InitTextures (void)
{
int lastlump = 0, lump;
int texlump1 = -1, texlump2 = -1, texlump1a, texlump2a;
int i;
int pfile = -1;
// For each PNAMES lump, load the TEXTURE1 and/or TEXTURE2 lumps from the same wad.
while ((lump = Wads.FindLump ("PNAMES", &lastlump)) != -1)
{
pfile = Wads.GetLumpFile (lump);
TexMan.AddPatches (lump);
texlump1 = Wads.CheckNumForName ("TEXTURE1", ns_global, pfile);
texlump2 = Wads.CheckNumForName ("TEXTURE2", ns_global, pfile);
TexMan.AddTexturesLumps (texlump1, texlump2, lump);
}
// If the final TEXTURE1 and/or TEXTURE2 lumps are in a wad without a PNAMES lump,
// they have not been loaded yet, so load them now.
texlump1a = Wads.CheckNumForName ("TEXTURE1");
texlump2a = Wads.CheckNumForName ("TEXTURE2");
if (texlump1a != -1 && (texlump1a == texlump1 || Wads.GetLumpFile (texlump1a) <= pfile))
{
texlump1a = -1;
}
if (texlump2a != -1 && (texlump2a == texlump2 || Wads.GetLumpFile (texlump2a) <= pfile))
{
texlump2a = -1;
}
TexMan.AddTexturesLumps (texlump1a, texlump2a, Wads.GetNumForName ("PNAMES"));
// The Hexen scripts use BLANK as a blank texture, even though it's really not.
// I guess the Doom renderer must have clipped away the line at the bottom of
// the texture so it wasn't visible. I'll just map it to 0, so it really is blank.
if (gameinfo.gametype == GAME_Hexen &&
0 <= (i = TexMan.CheckForTexture ("BLANK", FTexture::TEX_Wall, false)))
{
TexMan.SetTranslation (i, 0);
}
// Hexen parallax skies use color 0 to indicate transparency on the front
// layer, so we must not remap color 0 on these textures. Unfortunately,
// the only way to identify these textures is to check the MAPINFO.
for (unsigned int i = 0; i < wadlevelinfos.Size(); ++i)
{
if (wadlevelinfos[i].flags & LEVEL_DOUBLESKY)
{
int picnum = TexMan.CheckForTexture (wadlevelinfos[i].skypic1, FTexture::TEX_Wall, false);
if (picnum > 0)
{
TexMan[picnum]->SetFrontSkyLayer ();
}
}
}
}
static struct FakeCmap {
char name[8];
PalEntry blend;
@ -795,16 +261,8 @@ void R_InitData ()
{
FTexture::InitGrayMap();
StartScreen->Progress();
TexMan.AddGroup("S_START", "S_END", ns_sprites, FTexture::TEX_Sprite);
R_InitPatches (); // Initializes "special" textures that have no external references
StartScreen->Progress();
R_InitTextures ();
TexMan.AddGroup("F_START", "F_END", ns_flats, FTexture::TEX_Flat);
R_InitBuildTiles ();
TexMan.AddGroup("TX_START", "TX_END", ns_newtextures, FTexture::TEX_Override);
TexMan.AddHiresTextures ();
TexMan.LoadHiresTex ();
TexMan.DefaultTexture = TexMan.CheckForTexture ("-NOFLAT-", FTexture::TEX_Override, 0);
TexMan.Init();
V_InitFonts();
StartScreen->Progress();
R_InitColormaps ();
@ -1049,215 +507,6 @@ const BYTE *R_GetColumn (FTexture *tex, int col)
return tex->GetColumn (col, NULL);
}
// Add all the miscellaneous 2D patches that are used to the texture manager
// Unfortunately, the wad format does not provide an elegant way to express
// which lumps are patches unless they are used in a wall texture, so I have
// to list them all here.
static void R_InitPatches ()
{
static const char patches[][9] =
{
"CONBACK",
"ADVISOR",
"BOSSBACK",
"PFUB1",
"PFUB2",
"END0",
"END1",
"END2",
"END3",
"END4",
"END5",
"END6",
"FINALE1",
"FINALE2",
"FINALE3",
"CHESSALL",
"CHESSC",
"CHESSM",
"FITEFACE",
"CLERFACE",
"MAGEFACE",
"M_NGAME",
"M_OPTION",
"M_RDTHIS",
"M_QUITG",
"M_JKILL",
"M_ROUGH",
"M_HURT",
"M_ULTRA",
"M_NMARE",
"M_LOADG",
"M_LSLEFT",
"M_LSCNTR",
"M_LSRGHT",
"M_FSLOT",
"M_SAVEG",
"M_DOOM",
"M_HTIC",
"M_STRIFE",
"M_NEWG",
"M_NGAME",
"M_SKILL",
"M_EPISOD",
"M_EPI1",
"M_EPI2",
"M_EPI3",
"M_EPI4",
"INTERPIC",
"WIOSTK",
"WIOSTI",
"WIF",
"WIMSTT",
"WIOSTS",
"WIOSTF",
"WITIME",
"WIPAR",
"WIMSTAR",
"WIMINUS",
"WIPCNT",
"WICOLON",
"WISUCKS",
"WIFRGS",
"WISCRT2",
"WIENTER",
"WIKILRS",
"WIVCTMS",
"IN_YAH",
"IN_X",
"FONTB13",
"FONTB05",
"FONTB26",
"FONTB15",
"FACEA0",
"FACEB0",
"STFDEAD0",
"STBANY",
"M_PAUSE",
"PAUSED",
"M_SKULL1",
"M_SKULL2",
"M_SLCTR1",
"M_SLCTR2",
"M_CURS1",
"M_CURS2",
"M_CURS3",
"M_CURS4",
"M_CURS5",
"M_CURS6",
"M_CURS7",
"M_CURS8",
"BRDR_TL",
"BRDR_T",
"BRDR_TR",
"BRDR_L",
"BRDR_R",
"BRDR_BL",
"BRDR_B",
"BRDR_BR",
"BORDTL",
"BORDT",
"BORDTR",
"BORDL",
"BORDR",
"BORDBL",
"BORDB",
"BORDBR",
"TITLE",
"CREDIT",
"ORDER",
"HELP",
"HELP1",
"HELP2",
"HELP3",
"HELP0",
"TITLEPIC",
"ENDPIC",
"STTPRCNT",
"STARMS",
"VICTORY2",
"STFBANY",
"STPBANY",
"RGELOGO",
"VELLOGO",
"FINAL1",
"FINAL2",
"E2END"
};
static const char spinners[][9] =
{
"SPINBK%d",
"SPFLY%d",
"SPSHLD%d",
"SPBOOT%d",
"SPMINO%d"
};
static const char classChars[3] = { 'F', 'C', 'M' };
int i, j;
char name[9];
for (i = countof(patches); i >= 0; --i)
{
TexMan.AddPatch (patches[i]);
}
// Some digits
for (i = 9; i >= 0; --i)
{
sprintf (name, "WINUM%d", i);
TexMan.AddPatch (name);
sprintf (name, "FONTB%d", i + 16);
TexMan.AddPatch (name);
sprintf (name, "AMMNUM%d", i);
TexMan.AddPatch (name);
}
// Spinning power up icons for Heretic and Hexen
for (j = countof(spinners)-1; j >= 0; --j)
{
for (i = 0; i <= 15; ++i)
{
sprintf (name, spinners[j], i);
TexMan.AddPatch (name);
}
}
// Player class animations for the Hexen new game menu
for (i = 2; i >= 0; --i)
{
sprintf (name, "M_%cBOX", classChars[i]);
TexMan.AddPatch (name);
for (j = 4; j >= 1; --j)
{
sprintf (name, "M_%cWALK%d", classChars[i], j);
TexMan.AddPatch (name);
}
}
// The spinning skull in Heretic's top-level menu
for (i = 0; i <= 17; ++i)
{
sprintf (name, "M_SKL%.2d", i);
TexMan.AddPatch (name);
}
// Strife story panels
for (i = 0; i <= 7; ++i)
{
sprintf (name, "PANEL%d", i);
TexMan.AddPatch (name);
}
for (i = 2; i <= 6; ++i)
{
for (j = 3 + (i < 5); j > 0; --j)
{
sprintf (name, "SS%dF%d", i, j);
TexMan.AddPatch (name);
}
}
}
#ifdef _DEBUG
// Prints the spans generated for a texture. Only needed for debugging.

View file

@ -764,6 +764,11 @@ public:
int texnum = GetTexture (texname, FTexture::TEX_MiscPatch);
return Textures[texnum].Texture;
}
FTexture *FindTexture(const char *texname, int usetype = FTexture::TEX_MiscPatch, BITFIELD flags = TEXMAN_TryAny)
{
int texnum = GetTexture (texname, usetype, flags);
return Textures[texnum].Texture;
}
// Get texture with translation
FTexture *operator() (int texnum)
@ -804,16 +809,20 @@ public:
void AddTexturesLump (const void *lumpdata, int lumpsize, int patcheslump, int firstdup=0, bool texture1=false);
void AddTexturesLumps (int lump1, int lump2, int patcheslump);
void AddGroup(const char * startlump, const char * endlump, int ns, int usetype);
void AddGroup(int wadnum, const char * startlump, const char * endlump, int ns, int usetype);
void AddPatches (int lumpnum);
void AddTiles (void *tileFile);
void AddHiresTextures ();
void LoadHiresTex();
void AddHiresTextures (int wadnum);
void LoadHiresTex(int wadnum);
int CreateTexture (int lumpnum, int usetype=FTexture::TEX_Any); // Also calls AddTexture
int AddTexture (FTexture *texture);
int AddPatch (const char *patchname, int namespc=0, bool tryany = false);
void LoadTextureX(int wadnum);
void AddTexturesForWad(int wadnum);
void Init();
// Replaces one texture with another. The new texture will be assigned
// the same name, slot, and use type as the texture it is replacing.
// The old texture will no longer be managed. Set free true if you want

View file

@ -61,6 +61,7 @@ void FTexture::InitGrayMap()
}
}
// Examines the lump contents to decide what type of texture to create,
// and creates the texture.
FTexture * FTexture::CreateTexture (int lumpnum, int usetype)

View file

@ -0,0 +1,782 @@
/*
** texturemanager.cpp
** The texture manager class
**
**---------------------------------------------------------------------------
** Copyright 2004-2008 Randy Heit
** Copyright 2006-2008 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
**
*/
#include "doomtype.h"
#include "w_wad.h"
#include "r_data.h"
#include "templates.h"
#include "i_system.h"
#include "r_translate.h"
#include "c_dispatch.h"
#include "v_text.h"
#include "sc_man.h"
#include "gi.h"
#include "st_start.h"
extern void R_InitBuildTiles();
FTextureManager TexMan;
//==========================================================================
//
// FTextureManager :: FTextureManager
//
//==========================================================================
FTextureManager::FTextureManager ()
{
memset (HashFirst, -1, sizeof(HashFirst));
// Texture 0 is a dummy texture used to indicate "no texture"
AddTexture (new FDummyTexture);
}
//==========================================================================
//
// FTextureManager :: ~FTextureManager
//
//==========================================================================
FTextureManager::~FTextureManager ()
{
for (unsigned int i = 0; i < Textures.Size(); ++i)
{
delete Textures[i].Texture;
}
}
//==========================================================================
//
// FTextureManager :: CheckForTexture
//
//==========================================================================
int FTextureManager::CheckForTexture (const char *name, int usetype, BITFIELD flags)
{
int i;
int firstfound = -1;
int firsttype = FTexture::TEX_Null;
if (name == NULL || name[0] == '\0')
{
return -1;
}
// [RH] Doom counted anything beginning with '-' as "no texture".
// Hopefully nobody made use of that and had textures like "-EMPTY",
// because -NOFLAT- is a valid graphic for ZDoom.
if (name[0] == '-' && name[1] == '\0')
{
return 0;
}
i = HashFirst[MakeKey (name) % HASH_SIZE];
while (i != HASH_END)
{
const FTexture *tex = Textures[i].Texture;
if (stricmp (tex->Name, name) == 0)
{
// The name matches, so check the texture type
if (usetype == FTexture::TEX_Any)
{
// All NULL textures should actually return 0
return tex->UseType==FTexture::TEX_Null? 0 : i;
}
else if ((flags & TEXMAN_Overridable) && tex->UseType == FTexture::TEX_Override)
{
return i;
}
else if (tex->UseType == usetype)
{
return i;
}
else
{
if (firsttype == FTexture::TEX_Null ||
(firsttype == FTexture::TEX_MiscPatch && tex->UseType != FTexture::TEX_Null)
)
{
firstfound = i;
firsttype = tex->UseType;
}
}
}
i = Textures[i].HashNext;
}
if ((flags & TEXMAN_TryAny) && usetype != FTexture::TEX_Any)
{
return firstfound;
}
return -1;
}
//==========================================================================
//
// FTextureManager :: ListTextures
//
//==========================================================================
int FTextureManager::ListTextures (const char *name, TArray<int> &list)
{
int i;
if (name == NULL || name[0] == '\0')
{
return 0;
}
// [RH] Doom counted anything beginning with '-' as "no texture".
// Hopefully nobody made use of that and had textures like "-EMPTY",
// because -NOFLAT- is a valid graphic for ZDoom.
if (name[0] == '-' && name[1] == '\0')
{
return 0;
}
i = HashFirst[MakeKey (name) % HASH_SIZE];
while (i != HASH_END)
{
const FTexture *tex = Textures[i].Texture;
if (stricmp (tex->Name, name) == 0)
{
// NULL textures must be ignored.
if (tex->UseType!=FTexture::TEX_Null)
{
unsigned int j;
for(j = 0; j < list.Size(); j++)
{
// Check for overriding definitions from newer WADs
if (Textures[list[j]].Texture->UseType == tex->UseType) break;
}
if (j==list.Size()) list.Push(i);
}
}
i = Textures[i].HashNext;
}
return list.Size();
}
//==========================================================================
//
// FTextureManager :: GetTextures
//
//==========================================================================
int FTextureManager::GetTexture (const char *name, int usetype, BITFIELD flags)
{
int i;
if (name == NULL || name[0] == 0)
{
return 0;
}
else
{
i = CheckForTexture (name, usetype, flags | TEXMAN_TryAny);
}
if (i == -1)
{
// Use a default texture instead of aborting like Doom did
Printf ("Unknown texture: \"%s\"\n", name);
i = DefaultTexture;
}
return i;
}
//==========================================================================
//
// FTextureManager :: WriteTexture
//
//==========================================================================
void FTextureManager::WriteTexture (FArchive &arc, int picnum)
{
FTexture *pic;
if ((size_t)picnum >= Textures.Size())
{
pic = Textures[0].Texture;
}
else
{
pic = Textures[picnum].Texture;
}
arc.WriteCount (pic->UseType);
arc.WriteName (pic->Name);
}
//==========================================================================
//
// FTextureManager :: ReadTexture
//
//==========================================================================
int FTextureManager::ReadTexture (FArchive &arc)
{
int usetype;
const char *name;
usetype = arc.ReadCount ();
name = arc.ReadName ();
return GetTexture (name, usetype);
}
//==========================================================================
//
// FTextureManager :: UnloadAll
//
//==========================================================================
void FTextureManager::UnloadAll ()
{
for (unsigned int i = 0; i < Textures.Size(); ++i)
{
Textures[i].Texture->Unload ();
}
}
//==========================================================================
//
// FTextureManager :: AddTexture
//
//==========================================================================
int FTextureManager::AddTexture (FTexture *texture)
{
// Later textures take precedence over earlier ones
size_t bucket = MakeKey (texture->Name) % HASH_SIZE;
TextureHash hasher = { texture, HashFirst[bucket] };
WORD trans = Textures.Push (hasher);
Translation.Push (trans);
HashFirst[bucket] = trans;
return trans;
}
//==========================================================================
//
// FTextureManager :: CreateTexture
//
// Calls FTexture::CreateTexture and adds the texture to the manager.
//
//==========================================================================
int FTextureManager::CreateTexture (int lumpnum, int usetype)
{
if (lumpnum != -1)
{
FTexture *out = FTexture::CreateTexture(lumpnum, usetype);
if (out != NULL) return AddTexture (out);
else
{
Printf (TEXTCOLOR_ORANGE "Invalid data encountered for texture %s\n", Wads.GetLumpFullName(lumpnum));
return -1;
}
}
return -1;
}
//==========================================================================
//
// FTextureManager :: ReplaceTexture
//
//==========================================================================
void FTextureManager::ReplaceTexture (int picnum, FTexture *newtexture, bool free)
{
if ((size_t)picnum >= Textures.Size())
return;
FTexture *oldtexture = Textures[picnum].Texture;
strcpy (newtexture->Name, oldtexture->Name);
newtexture->UseType = oldtexture->UseType;
Textures[picnum].Texture = newtexture;
if (free)
{
delete oldtexture;
}
}
//==========================================================================
//
// FTextureManager :: AddPatch
//
//==========================================================================
int FTextureManager::AddPatch (const char *patchname, int namespc, bool tryany)
{
if (patchname == NULL)
{
return -1;
}
int lumpnum = CheckForTexture (patchname, FTexture::TEX_MiscPatch, tryany);
if (lumpnum >= 0)
{
return lumpnum;
}
lumpnum = Wads.CheckNumForName (patchname, namespc==ns_global? ns_graphics:namespc);
if (lumpnum < 0)
{
return -1;
}
return CreateTexture (lumpnum, FTexture::TEX_MiscPatch);
}
//==========================================================================
//
// FTextureManager :: AddGroup
//
//==========================================================================
void FTextureManager::AddGroup(int wadnum, const char * startlump, const char * endlump, int ns, int usetype)
{
int firsttx = Wads.CheckNumForName (startlump);
int lasttx = Wads.CheckNumForName (endlump);
char name[9];
if (firsttx == -1 || lasttx == -1)
{
return;
}
name[8] = 0;
// Go from first to last so that ANIMDEFS work as expected. However,
// to avoid duplicates (and to keep earlier entries from overriding
// later ones), the texture is only inserted if it is the one returned
// by doing a check by name in the list of wads.
for (firsttx += 1; firsttx < lasttx; ++firsttx)
{
if (Wads.GetLumpFile(firsttx) == wadnum)
{
Wads.GetLumpName (name, firsttx);
if (Wads.CheckNumForName (name, ns) == firsttx)
{
CreateTexture (firsttx, usetype);
}
StartScreen->Progress();
}
}
}
//==========================================================================
//
// Adds all hires texture definitions.
//
//==========================================================================
void FTextureManager::AddHiresTextures (int wadnum)
{
int firsttx = Wads.CheckNumForName ("HI_START");
int lasttx = Wads.CheckNumForName ("HI_END");
char name[9];
TArray<int> tlist;
if (firsttx == -1 || lasttx == -1)
{
return;
}
name[8] = 0;
for (firsttx += 1; firsttx < lasttx; ++firsttx)
{
if (Wads.GetLumpFile(firsttx) == wadnum)
{
tlist.Clear();
Wads.GetLumpName (name, firsttx);
if (Wads.CheckNumForName (name, ns_hires) == firsttx)
{
int amount = ListTextures(name, tlist);
if (amount == 0)
{
int oldtex = AddPatch(name);
if (oldtex >= 0) tlist.Push(oldtex);
}
if (tlist.Size() == 0)
{
// A texture with this name does not yet exist
FTexture * newtex = FTexture::CreateTexture (firsttx, FTexture::TEX_Any);
newtex->UseType=FTexture::TEX_Override;
AddTexture(newtex);
}
else
{
for(unsigned int i = 0; i < tlist.Size(); i++)
{
FTexture * newtex = FTexture::CreateTexture (firsttx, FTexture::TEX_Any);
if (newtex != NULL)
{
int oldtexno = tlist[i];
FTexture * oldtex = Textures[oldtexno].Texture;
// Replace the entire texture and adjust the scaling and offset factors.
newtex->bWorldPanning = true;
newtex->SetScaledSize(oldtex->GetScaledWidth(), oldtex->GetScaledHeight());
newtex->LeftOffset = FixedMul(oldtex->GetScaledLeftOffset(), newtex->xScale);
newtex->TopOffset = FixedMul(oldtex->GetScaledTopOffset(), newtex->yScale);
ReplaceTexture(oldtexno, newtex, true);
}
}
}
StartScreen->Progress();
}
}
}
}
//==========================================================================
//
// Loads the HIRESTEX lumps
//
//==========================================================================
void FTextureManager::LoadHiresTex(int wadnum)
{
int remapLump, lastLump;
char src[9];
bool is32bit;
int width, height;
int type, mode;
TArray<int> tlist;
lastLump = 0;
src[8] = '\0';
while ((remapLump = Wads.FindLump("HIRESTEX", &lastLump)) != -1)
{
if (Wads.GetLumpFile(remapLump) == wadnum)
{
FScanner sc(remapLump, "HIRESTEX");
while (sc.GetString())
{
if (sc.Compare("remap")) // remap an existing texture
{
sc.MustGetString();
// allow selection by type
if (sc.Compare("wall")) type=FTexture::TEX_Wall, mode=FTextureManager::TEXMAN_Overridable;
else if (sc.Compare("flat")) type=FTexture::TEX_Flat, mode=FTextureManager::TEXMAN_Overridable;
else if (sc.Compare("sprite")) type=FTexture::TEX_Sprite, mode=0;
else type = FTexture::TEX_Any, mode = 0;
sc.String[8]=0;
tlist.Clear();
int amount = ListTextures(sc.String, tlist);
if (amount == 0)
{
int oldtex = AddPatch(sc.String);
if (oldtex >= 0) tlist.Push(oldtex);
}
FName texname = sc.String;
sc.MustGetString();
int lumpnum = Wads.CheckNumForFullName(sc.String);
if (lumpnum < 0) lumpnum = Wads.CheckNumForName(sc.String, ns_graphics);
if (tlist.Size() == 0)
{
Printf("Attempting to remap non-existent texture %s to %s\n",
texname.GetChars(), sc.String);
}
else
{
for(unsigned int i = 0; i < tlist.Size(); i++)
{
FTexture * oldtex = Textures[tlist[i]].Texture;
int sl;
// only replace matching types. For sprites also replace any MiscPatches
// based on the same lump. These can be created for icons.
if (oldtex->UseType == type || type == FTexture::TEX_Any ||
(mode == TEXMAN_Overridable && oldtex->UseType == FTexture::TEX_Override) ||
(type == FTexture::TEX_Sprite && oldtex->UseType == FTexture::TEX_MiscPatch &&
(sl=oldtex->GetSourceLump()) >= 0 && Wads.GetLumpNamespace(sl) == ns_sprites)
)
{
FTexture * newtex = FTexture::CreateTexture (lumpnum, FTexture::TEX_Any);
if (newtex != NULL)
{
// Replace the entire texture and adjust the scaling and offset factors.
newtex->bWorldPanning = true;
newtex->SetScaledSize(oldtex->GetScaledWidth(), oldtex->GetScaledHeight());
newtex->LeftOffset = FixedMul(oldtex->GetScaledLeftOffset(), newtex->xScale);
newtex->TopOffset = FixedMul(oldtex->GetScaledTopOffset(), newtex->yScale);
ReplaceTexture(tlist[i], newtex, true);
}
}
}
}
}
else if (sc.Compare("define")) // define a new "fake" texture
{
sc.GetString();
memcpy(src, sc.String, 8);
int lumpnum = Wads.CheckNumForFullName(sc.String);
if (lumpnum < 0) lumpnum = Wads.CheckNumForName(sc.String, ns_graphics);
sc.GetString();
is32bit = !!sc.Compare("force32bit");
if (!is32bit) sc.UnGet();
sc.GetNumber();
width = sc.Number;
sc.GetNumber();
height = sc.Number;
if (lumpnum>=0)
{
FTexture *newtex = FTexture::CreateTexture(lumpnum, FTexture::TEX_Override);
if (newtex != NULL)
{
// Replace the entire texture and adjust the scaling and offset factors.
newtex->bWorldPanning = true;
newtex->SetScaledSize(width, height);
memcpy(newtex->Name, src, sizeof(newtex->Name));
int oldtex = TexMan.CheckForTexture(src, FTexture::TEX_Override);
if (oldtex>=0) TexMan.ReplaceTexture(oldtex, newtex, true);
else TexMan.AddTexture(newtex);
}
}
//else Printf("Unable to define hires texture '%s'\n", tex->Name);
}
}
}
}
}
//==========================================================================
//
// FTextureManager :: AddPatches
//
//==========================================================================
void FTextureManager::AddPatches (int lumpnum)
{
FWadLump *file = Wads.ReopenLumpNum (lumpnum);
DWORD numpatches, i;
char name[9];
*file >> numpatches;
name[8] = 0;
for (i = 0; i < numpatches; ++i)
{
file->Read (name, 8);
if (CheckForTexture (name, FTexture::TEX_WallPatch, false) == -1)
{
CreateTexture (Wads.CheckNumForName (name, ns_patches), FTexture::TEX_WallPatch);
}
StartScreen->Progress();
}
delete file;
}
//==========================================================================
//
// R_InitTextures
// Initializes the texture list with the textures from the world map.
//
//==========================================================================
void FTextureManager::LoadTextureX(int wadnum)
{
// Use the most recent PNAMES for this WAD.
// Multiple PNAMES in a WAD will be ignored.
int pnames = Wads.CheckNumForName("PNAMES", ns_global, wadnum, false);
if (pnames < 0)
{
// should never happen except for zdoom.pk3
return;
}
// Only add the patches if the PNAMES come from the current file
// Otherwise they have already been processed.
if (Wads.GetLumpFile(pnames) == wadnum) TexMan.AddPatches (pnames);
int texlump1 = Wads.CheckNumForName ("TEXTURE1", ns_global, wadnum);
int texlump2 = Wads.CheckNumForName ("TEXTURE2", ns_global, wadnum);
TexMan.AddTexturesLumps (texlump1, texlump2, pnames);
}
//==========================================================================
//
// FTextureManager :: AddTexturesForWad
//
//==========================================================================
void FTextureManager::AddTexturesForWad(int wadnum)
{
int lumpcount = Wads.GetNumLumps();
// First step: Load sprites
AddGroup(wadnum, "S_START", "S_END", ns_sprites, FTexture::TEX_Sprite);
// Second step: TEXTUREx lumps
LoadTextureX(wadnum);
// Third step: Flats
AddGroup(wadnum, "F_START", "F_END", ns_flats, FTexture::TEX_Flat);
// Fourth step: Textures (TX_)
AddGroup(wadnum, "TX_START", "TX_END", ns_newtextures, FTexture::TEX_Override);
// Sixth step: Try to find any lump in the WAD that may be a texture and load as a TEX_MiscPatch
for (int i = 0; i < lumpcount; i++)
{
int file = Wads.GetLumpFile(i);
if (file > wadnum) break; // lumps in the global namespace are ordered by WAD
if (file < wadnum) continue;
char name[9];
Wads.GetLumpName(name, i);
name[8]=0;
// Ignore anything not in the global namespace
int ns = Wads.GetLumpNamespace(i);
if (ns == ns_global)
{
// In Zips all graphics must be in a separate namespace.
if (Wads.GetLumpFlags(i) & LUMPF_ZIPFILE) continue;
// Ignore lumps with empty names.
if (Wads.CheckLumpName(i, "")) continue;
// Ignore anything belonging to a map
if (Wads.CheckLumpName(i, "THINGS")) continue;
if (Wads.CheckLumpName(i, "LINEDEFS")) continue;
if (Wads.CheckLumpName(i, "SIDEDEFS")) continue;
if (Wads.CheckLumpName(i, "VERTEXES")) continue;
if (Wads.CheckLumpName(i, "SEGS")) continue;
if (Wads.CheckLumpName(i, "SSECTORS")) continue;
if (Wads.CheckLumpName(i, "NODES")) continue;
if (Wads.CheckLumpName(i, "SECTORS")) continue;
if (Wads.CheckLumpName(i, "REJECT")) continue;
if (Wads.CheckLumpName(i, "BLOCKMAP")) continue;
if (Wads.CheckLumpName(i, "BEHAVIOR")) continue;
// Don't bother looking this lump if something later overrides it.
if (Wads.CheckNumForName(name, ns_graphics) != i) continue;
// skip this if it has already been added as a wall patch.
if (CheckForTexture(name, FTexture::TEX_WallPatch, 0) >= 0) continue;
}
else if (ns == ns_graphics)
{
// Don't bother looking this lump if something later overrides it.
if (Wads.CheckNumForName(name, ns_graphics) != i) continue;
}
else continue;
// Try to create a texture from this lump and add it.
// Unfortunately we have to look at everything that comes through here...
FTexture *out = FTexture::CreateTexture(i, FTexture::TEX_MiscPatch);
if (out != NULL)
{
AddTexture (out);
}
}
// Seventh step: Check for hires replacements.
AddHiresTextures(wadnum);
LoadHiresTex(wadnum);
}
//==========================================================================
//
// FTextureManager :: Init
//
//==========================================================================
void FTextureManager::Init()
{
int i;
int wadcnt = Wads.GetNumWads();
for(int i = 0; i< wadcnt; i++)
{
AddTexturesForWad(i);
}
R_InitBuildTiles ();
DefaultTexture = CheckForTexture ("-NOFLAT-", FTexture::TEX_Override, 0);
// The Hexen scripts use BLANK as a blank texture, even though it's really not.
// I guess the Doom renderer must have clipped away the line at the bottom of
// the texture so it wasn't visible. I'll just map it to 0, so it really is blank.
if (gameinfo.gametype == GAME_Hexen &&
0 <= (i = CheckForTexture ("BLANK", FTexture::TEX_Wall, false)))
{
SetTranslation (i, 0);
}
// Hexen parallax skies use color 0 to indicate transparency on the front
// layer, so we must not remap color 0 on these textures. Unfortunately,
// the only way to identify these textures is to check the MAPINFO.
for (unsigned int i = 0; i < wadlevelinfos.Size(); ++i)
{
if (wadlevelinfos[i].flags & LEVEL_DOUBLESKY)
{
int picnum = CheckForTexture (wadlevelinfos[i].skypic1, FTexture::TEX_Wall, false);
if (picnum > 0)
{
Textures[picnum].Texture->SetFrontSkyLayer ();
}
}
}
}

View file

@ -1382,6 +1382,10 @@ static void ActorTranslation (FScanner &sc, AActor *defaults, Baggage &bag)
}
defaults->Translation = TRANSLATION(TRANSLATION_Standard, sc.Number);
}
else if (sc.CheckString("Ice"))
{
defaults->Translation = TRANSLATION(TRANSLATION_Standard, 7);
}
else
{
CurrentTranslation.MakeIdentity();

View file

@ -60,13 +60,7 @@ void FImageCollection::Init (const char **patchNames, int numPatches, int namesp
for (int i = 0; i < numPatches; ++i)
{
int picnum = TexMan.AddPatch (patchNames[i], namespc, true);
if (picnum == -1 && namespc != ns_sprites)
{
picnum = TexMan.AddPatch (patchNames[i], ns_sprites);
}
ImageMap[i] = picnum;
ImageMap[i] = TexMan.CheckForTexture(patchNames[i], namespc, true);
}
}

View file

@ -243,10 +243,6 @@ FFont *V_GetFont(const char *name)
if (font == NULL)
{
int picnum = TexMan.CheckForTexture (name, FTexture::TEX_Any);
if (picnum <= 0)
{
picnum = TexMan.AddPatch (name);
}
if (picnum > 0)
{
font = new FSinglePicFont (name);
@ -334,7 +330,7 @@ FFont::FFont (const char *name, const char *nametemplate, int first, int count,
charlumps[i] = lump;
if (lump >= 0)
{
FTexture *pic = TexMan[TexMan.AddPatch (buffer)];
FTexture *pic = TexMan[buffer];
if (pic != NULL)
{
int height = pic->GetScaledHeight();
@ -1482,7 +1478,7 @@ FSpecialFont::FSpecialFont (const char *name, int first, int count, int *lumplis
{
Wads.GetLumpName(buffer, lump);
buffer[8]=0;
FTexture *pic = TexMan[TexMan.AddPatch (buffer)];
FTexture *pic = TexMan[buffer];
if (pic != NULL)
{
int height = pic->GetScaledHeight();

View file

@ -83,7 +83,7 @@ class FFont
{
public:
FFont (const char *fontname, const char *nametemplate, int first, int count, int base);
~FFont ();
virtual ~FFont ();
virtual FTexture *GetChar (int code, int *const width) const;
virtual int GetCharWidth (int code) const;

View file

@ -94,15 +94,6 @@ struct FWadCollection::LumpRecord
int compressedsize;
};
enum
{
LUMPF_BLOODCRYPT = 1, // Lump uses Blood-style encryption
LUMPF_COMPRESSED = 2, // Zip-compressed
LUMPF_ZIPFILE = 4, // Inside a Zip file - used to enforce use of special directories insize Zips
LUMPF_NEEDFILESTART = 8, // Still need to process local file header to find file start inside a zip
LUMPF_EXTERNAL = 16, // Lump is from an external file that won't be kept open permanently
};
class FWadCollection::WadFileRecord : public FileReader
{
public:
@ -806,6 +797,17 @@ int FWadCollection::GetNumLumps () const
return NumLumps;
}
//==========================================================================
//
// GetNumFiles
//
//==========================================================================
int FWadCollection::GetNumWads () const
{
return Wads.Size();
}
//==========================================================================
//
// W_CheckNumForName
@ -857,7 +859,7 @@ int FWadCollection::CheckNumForName (const char *name, int space)
return i != NULL_INDEX ? i : -1;
}
int FWadCollection::CheckNumForName (const char *name, int space, int wadnum)
int FWadCollection::CheckNumForName (const char *name, int space, int wadnum, bool exact)
{
char uname[8];
WORD i;
@ -870,10 +872,12 @@ int FWadCollection::CheckNumForName (const char *name, int space, int wadnum)
uppercopy (uname, name);
i = FirstLumpIndex[LumpNameHash (uname) % NumLumps];
// If exact is true if will only find lumps in the same WAD, otherwise
// also those in earlier WADs.
while (i != NULL_INDEX &&
(*(QWORD *)&LumpInfo[i].name != *(QWORD *)&uname ||
LumpInfo[i].namespc != space ||
LumpInfo[i].wadnum != wadnum))
(exact? (LumpInfo[i].wadnum != wadnum) : (LumpInfo[i].wadnum > wadnum)) ))
{
i = NextLumpIndex[i];
}
@ -1012,6 +1016,22 @@ int FWadCollection::GetLumpOffset (int lump)
return LumpInfo[lump].position;
}
//==========================================================================
//
// GetLumpOffset
//
//==========================================================================
int FWadCollection::GetLumpFlags (int lump)
{
if ((size_t)lump >= NumLumps)
{
return 0;
}
return LumpInfo[lump].flags;
}
//==========================================================================
//
// W_LumpNameHash

View file

@ -62,6 +62,16 @@ struct wadlump_t
char Name[8];
};
enum
{
LUMPF_BLOODCRYPT = 1, // Lump uses Blood-style encryption
LUMPF_COMPRESSED = 2, // Zip-compressed
LUMPF_ZIPFILE = 4, // Inside a Zip file - used to enforce use of special directories insize Zips
LUMPF_NEEDFILESTART = 8, // Still need to process local file header to find file start inside a zip
LUMPF_EXTERNAL = 16, // Lump is from an external file that won't be kept open permanently
};
// [RH] Namespaces from BOOM.
typedef enum {
ns_global = 0,
@ -161,7 +171,7 @@ public:
const char *GetWadFullName (int wadnum) const;
int CheckNumForName (const char *name, int namespc);
int CheckNumForName (const char *name, int namespc, int wadfile);
int CheckNumForName (const char *name, int namespc, int wadfile, bool exact = true);
int GetNumForName (const char *name, int namespc);
inline int CheckNumForName (const BYTE *name) { return CheckNumForName ((const char *)name, ns_global); }
@ -193,6 +203,7 @@ public:
int LumpLength (int lump) const;
int GetLumpOffset (int lump); // [RH] Returns offset of lump in the wadfile
int GetLumpFlags (int lump); // Return the flags for this lump
void GetLumpName (char *to, int lump) const; // [RH] Copies the lump name to to using uppercopy
const char *GetLumpFullName (int lump) const; // [RH] Returns the lump's full name
int GetLumpFile (int lump) const; // [RH] Returns wadnum for a specified lump
@ -203,6 +214,7 @@ public:
bool IsEncryptedFile(int lump) const;
int GetNumLumps () const;
int GetNumWads () const;
int AddExternalFile(const char *filename);

View file

@ -391,9 +391,7 @@ void WI_LoadBackground(bool isenterpic)
// a name with a starting '$' indicates an intermission script
if (*lumpname!='$')
{
// The background picture can also be a flat so just using AddPatch doesn't work
texture = TexMan.CheckForTexture(lumpname, FTexture::TEX_MiscPatch, FTextureManager::TEXMAN_TryAny);
if (texture == -1) texture = TexMan.AddPatch(lumpname);
}
else
{
@ -410,19 +408,17 @@ void WI_LoadBackground(bool isenterpic)
case 0: // Background
sc.MustGetString();
texture=TexMan.CheckForTexture(sc.String, FTexture::TEX_MiscPatch,FTextureManager::TEXMAN_TryAny);
if (texture == -1) texture = TexMan.AddPatch(sc.String);
break;
case 1: // Splat
sc.MustGetString();
splat=TexMan[TexMan.AddPatch(sc.String)];
splat=TexMan[sc.String];
break;
case 2: // Pointers
while (sc.GetString() && !sc.Crossed)
{
int v = TexMan.AddPatch(sc.String);
yah.Push(TexMan[v]);
yah.Push(TexMan[sc.String]);
}
if (sc.Crossed) sc.UnGet();
break;
@ -517,7 +513,7 @@ void WI_LoadBackground(bool isenterpic)
if (!sc.CheckString("{"))
{
sc.MustGetString();
an.p[an.nanims++] = TexMan[TexMan.AddPatch(sc.String)];
an.p[an.nanims++] = TexMan[sc.String];
}
else
{
@ -525,7 +521,7 @@ void WI_LoadBackground(bool isenterpic)
{
sc.MustGetString();
if (an.nanims<MAX_ANIMATION_FRAMES)
an.p[an.nanims++] = TexMan[TexMan.AddPatch(sc.String)];
an.p[an.nanims++] = TexMan[sc.String];
}
}
an.ctr = -1;
@ -539,7 +535,7 @@ void WI_LoadBackground(bool isenterpic)
sc.MustGetNumber();
an.loc.y = sc.Number;
sc.MustGetString();
an.p[0] = TexMan[TexMan.AddPatch(sc.String)];
an.p[0] = TexMan[sc.String];
anims.Push(an);
break;
@ -765,7 +761,7 @@ void WI_drawLF ()
{
int y = WI_TITLEY;
FTexture * tex = wbs->lname0[0]? TexMan[TexMan.AddPatch(wbs->lname0)] : NULL;
FTexture * tex = wbs->lname0[0]? TexMan[wbs->lname0] : NULL;
// draw <LevelName>
if (tex)
@ -827,7 +823,7 @@ void WI_drawEL ()
}
// draw <LevelName>
FTexture * tex = wbs->lname1[0]? TexMan[TexMan.AddPatch(wbs->lname1)] : NULL;
FTexture * tex = wbs->lname1[0]? TexMan[wbs->lname1] : NULL;
if (tex)
{
screen->DrawTexture(tex, (SCREENWIDTH - tex->GetWidth() * CleanXfac) / 2, y * CleanYfac, DTA_CleanNoMove, true, TAG_DONE);

File diff suppressed because it is too large Load diff