From 1b2855734174d66eb418c4932f0d61a8f1cb5923 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 26 Jan 2008 23:20:34 +0000 Subject: [PATCH] - 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) --- docs/rh-log.txt | 13 + src/f_finale.cpp | 1 - src/g_doom/doom_sbar.cpp | 2 +- src/g_level.cpp | 10 - src/g_shared/shared_hud.cpp | 24 +- src/g_shared/shared_sbar.cpp | 2 +- src/m_menu.cpp | 7 +- src/p_conversation.cpp | 2 +- src/r_data.cpp | 755 +--------------- src/r_defs.h | 15 +- src/textures/texture.cpp | 1 + src/textures/texturemanager.cpp | 782 ++++++++++++++++ src/thingdef/thingdef_properties.cpp | 4 + src/v_collection.cpp | 8 +- src/v_font.cpp | 8 +- src/v_font.h | 2 +- src/w_wad.cpp | 42 +- src/w_wad.h | 14 +- src/wi_stuff.cpp | 18 +- zdoom.vcproj | 1258 +++++++++++++------------- 20 files changed, 1517 insertions(+), 1451 deletions(-) create mode 100644 src/textures/texturemanager.cpp diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 74d6023c9..16e0d9607 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -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. diff --git a/src/f_finale.cpp b/src/f_finale.cpp index e2d2b4e93..c1ed7aee2 100644 --- a/src/f_finale.cpp +++ b/src/f_finale.cpp @@ -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: diff --git a/src/g_doom/doom_sbar.cpp b/src/g_doom/doom_sbar.cpp index 5334271b7..31538f7b6 100644 --- a/src/g_doom/doom_sbar.cpp +++ b/src/g_doom/doom_sbar.cpp @@ -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"); diff --git a/src/g_level.cpp b/src/g_level.cpp index 6fdd5d100..90ceb73eb 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -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; - } - } } } diff --git a/src/g_shared/shared_hud.cpp b/src/g_shared/shared_hud.cpp index ae113daab..aebe00100 100644 --- a/src/g_shared/shared_hud.cpp +++ b/src/g_shared/shared_hud.cpp @@ -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; diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 52d5299fc..84cb9ee37 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -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); diff --git a/src/m_menu.cpp b/src/m_menu.cpp index 756d3f78f..5ac7209da 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -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) diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index 2211b6044..f07b89d20 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -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; diff --git a/src/r_data.cpp b/src/r_data.cpp index d92dca734..13b50918d 100644 --- a/src/r_data.cpp +++ b/src/r_data.cpp @@ -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 &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 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 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. diff --git a/src/r_defs.h b/src/r_defs.h index 1a3e7bb89..c76620199 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -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 diff --git a/src/textures/texture.cpp b/src/textures/texture.cpp index 35ebbf60b..c162e3acc 100644 --- a/src/textures/texture.cpp +++ b/src/textures/texture.cpp @@ -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) diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp new file mode 100644 index 000000000..09b58a0a9 --- /dev/null +++ b/src/textures/texturemanager.cpp @@ -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 &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 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 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 (); + } + } + } +} \ No newline at end of file diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index ed8c886b3..22e5f0b9d 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -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(); diff --git a/src/v_collection.cpp b/src/v_collection.cpp index 55bac6093..8e330c361 100644 --- a/src/v_collection.cpp +++ b/src/v_collection.cpp @@ -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); } } diff --git a/src/v_font.cpp b/src/v_font.cpp index a6e585042..79433d5fe 100644 --- a/src/v_font.cpp +++ b/src/v_font.cpp @@ -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(); diff --git a/src/v_font.h b/src/v_font.h index 8a383658e..c48561573 100644 --- a/src/v_font.h +++ b/src/v_font.h @@ -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; diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 53e645004..fc4b5d42b 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -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 diff --git a/src/w_wad.h b/src/w_wad.h index cab55d7b3..7cd148343 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -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); diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 50fb1f541..ae247ccb4 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -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.nanimslname0[0]? TexMan[TexMan.AddPatch(wbs->lname0)] : NULL; + FTexture * tex = wbs->lname0[0]? TexMan[wbs->lname0] : NULL; // draw if (tex) @@ -827,7 +823,7 @@ void WI_drawEL () } // draw - 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); diff --git a/zdoom.vcproj b/zdoom.vcproj index b755abc5f..be5d130cf 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - @@ -2729,6 +2721,14 @@ GeneratePreprocessedFile="0" /> + + + @@ -2751,7 +2751,7 @@ /> - - - @@ -3720,6 +3710,16 @@ Outputs=""src/$(InputName).h"" /> + + + @@ -3743,7 +3743,7 @@ /> - - - @@ -4806,6 +4796,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -4830,16 +4830,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -4850,6 +4840,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -4874,16 +4874,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -4894,6 +4884,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -4918,16 +4918,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -4938,6 +4928,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -4962,16 +4962,6 @@ Outputs="$(IntDir)\$(InputName).obj" /> - - - @@ -4982,6 +4972,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + @@ -5069,7 +5069,7 @@ /> - - - @@ -5416,6 +5408,14 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + + + + @@ -5642,14 +5650,6 @@ GeneratePreprocessedFile="0" /> - - - @@ -5671,7 +5671,7 @@ /> + + @@ -9171,14 +9175,6 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> - - - @@ -9188,6 +9184,14 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> + + + @@ -9362,7 +9366,7 @@ />