From 6309d90be0f1d2480f2ffba25d9639ece66e9fff Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 11 Dec 2010 12:00:40 +0000 Subject: [PATCH] - moved texture counting code into FTextureManager. - moved all code and data for Build tile management into FTextureManager. - moved texture animation management into FTextureManager. - changed: Animate textures only once per frame, not per view. Otherwise with animations that have sub-frame accuracy camera textures of the same area can show different animation frames if the frame changes falls between the rendering of the different views. SVN r3026 (trunk) --- src/d_main.cpp | 9 +- src/p_setup.cpp | 1 - src/r_data.cpp | 98 ---- src/r_local.h | 6 - src/r_main.cpp | 1 - src/r_main.h | 1 - src/r_sky.cpp | 17 + src/r_sky.h | 1 + src/{r_anim.cpp => textures/animations.cpp} | 521 +++++++++----------- src/textures/buildtexture.cpp | 29 +- src/textures/texturemanager.cpp | 144 +++++- src/textures/textures.h | 80 ++- zdoom.vcproj | 8 +- 13 files changed, 482 insertions(+), 434 deletions(-) rename src/{r_anim.cpp => textures/animations.cpp} (64%) diff --git a/src/d_main.cpp b/src/d_main.cpp index 61400d8a8..fd03a5c4a 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -712,10 +712,12 @@ void D_Display () } else { + unsigned int nowtime = I_FPSTime(); + TexMan.UpdateAnimations(nowtime); + R_UpdateSky(nowtime); switch (gamestate) { case GS_FULLCONSOLE: - R_UpdateAnimations(I_FPSTime()); screen->SetBlendingRect(0,0,0,0); hw2d = screen->Begin2D(false); C_DrawConsole (false); @@ -780,7 +782,6 @@ void D_Display () break; case GS_INTERMISSION: - R_UpdateAnimations(I_FPSTime()); screen->SetBlendingRect(0,0,0,0); hw2d = screen->Begin2D(false); WI_Drawer (); @@ -788,7 +789,6 @@ void D_Display () break; case GS_FINALE: - R_UpdateAnimations(I_FPSTime()); screen->SetBlendingRect(0,0,0,0); hw2d = screen->Begin2D(false); F_Drawer (); @@ -796,7 +796,6 @@ void D_Display () break; case GS_DEMOSCREEN: - R_UpdateAnimations(I_FPSTime()); screen->SetBlendingRect(0,0,0,0); hw2d = screen->Begin2D(false); D_PageDrawer (); @@ -1987,7 +1986,7 @@ void D_DoomMain (void) S_Init (); Printf ("ST_Init: Init startup screen.\n"); - StartScreen = FStartupScreen::CreateInstance (R_GuesstimateNumTextures() + 5); + StartScreen = FStartupScreen::CreateInstance (TexMan.GuesstimateNumTextures() + 5); ParseCompatibility(); diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 549028cdb..9a0c001a0 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -4055,7 +4055,6 @@ void P_Init () atterm (P_Shutdown); P_InitEffects (); // [RH] - R_InitPicAnims (); P_InitSwitchList (); P_InitTerrainTypes (); P_InitKeyMessages (); diff --git a/src/r_data.cpp b/src/r_data.cpp index ee40e29ca..37602007e 100644 --- a/src/r_data.cpp +++ b/src/r_data.cpp @@ -286,103 +286,6 @@ void R_InitData () StartScreen->Progress(); } -//=========================================================================== -// -// R_GuesstimateNumTextures -// -// Returns an estimate of the number of textures R_InitData will have to -// process. Used by D_DoomMain() when it calls ST_Init(). -// -//=========================================================================== - -int R_GuesstimateNumTextures () -{ - int numtex = 0; - - for(int i = Wads.GetNumLumps()-1; i>=0; i--) - { - int space = Wads.GetLumpNamespace(i); - switch(space) - { - case ns_flats: - case ns_sprites: - case ns_newtextures: - case ns_hires: - case ns_patches: - case ns_graphics: - numtex++; - break; - - default: - if (Wads.GetLumpFlags(i) & LUMPF_MAYBEFLAT) numtex++; - - break; - } - } - - numtex += R_CountBuildTiles (); - numtex += R_CountTexturesX (); - return numtex; -} - -//=========================================================================== -// -// R_CountTexturesX -// -// See R_InitTextures() for the logic in deciding what lumps to check. -// -//=========================================================================== - -static int R_CountTexturesX () -{ - int count = 0; - int wadcount = Wads.GetNumWads(); - for (int wadnum = 0; wadnum < wadcount; 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); - - // should never happen except for zdoom.pk3 - if (pnames < 0) continue; - - // Only count the patches if the PNAMES come from the current file - // Otherwise they have already been counted. - if (Wads.GetLumpFile(pnames) == wadnum) - { - count += R_CountLumpTextures (pnames); - } - - int texlump1 = Wads.CheckNumForName ("TEXTURE1", ns_global, wadnum); - int texlump2 = Wads.CheckNumForName ("TEXTURE2", ns_global, wadnum); - - count += R_CountLumpTextures (texlump1) - 1; - count += R_CountLumpTextures (texlump2) - 1; - } - return count; -} - -//=========================================================================== -// -// R_CountLumpTextures -// -// Returns the number of patches in a PNAMES/TEXTURE1/TEXTURE2 lump. -// -//=========================================================================== - -static int R_CountLumpTextures (int lumpnum) -{ - if (lumpnum >= 0) - { - FWadLump file = Wads.OpenLumpNum (lumpnum); - DWORD numtex; - - file >> numtex; - return numtex >= 0 ? numtex : 0; - } - return 0; -} - //=========================================================================== // // R_DeinitData @@ -392,7 +295,6 @@ static int R_CountLumpTextures (int lumpnum) void R_DeinitData () { R_DeinitColormaps (); - R_DeinitBuildTiles(); FCanvasTextureInfo::EmptyList(); // Free openings diff --git a/src/r_local.h b/src/r_local.h index b4508a229..c666b1de4 100644 --- a/src/r_local.h +++ b/src/r_local.h @@ -39,12 +39,6 @@ #include "r_things.h" #include "r_draw.h" -// r_anim.cpp - -void R_InitPicAnims (); -void R_AddSimpleAnim (FTextureID picnum, int animcount, int animtype, DWORD animspeed /* in ms */, DWORD speedrange=0); -void R_UpdateAnimations (DWORD mstime); - bool R_AlignFlat (int linenum, int side, int fc); #endif // __R_LOCAL_H__ diff --git a/src/r_main.cpp b/src/r_main.cpp index fa25f7ca1..88aab962c 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1084,7 +1084,6 @@ void R_SetupFrame (AActor *actor) iview->otic = nowtic; } - R_UpdateAnimations (I_FPSTime()); r_TicFrac = I_GetTimeFrac (&r_FrameTime); if (cl_capfps || r_NoInterpolate) { diff --git a/src/r_main.h b/src/r_main.h index e633404e1..c894a2bcf 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -189,7 +189,6 @@ void R_RenderViewToCanvas (AActor *actor, DCanvas *canvas, int x, int y, int wid void R_ResetViewInterpolation (); // Called by startup code. -int R_GuesstimateNumTextures (); void R_Init (void); void R_ExecuteSetViewSize (void); diff --git a/src/r_sky.cpp b/src/r_sky.cpp index 544c1ded9..e9c319de1 100644 --- a/src/r_sky.cpp +++ b/src/r_sky.cpp @@ -137,3 +137,20 @@ void R_InitSkyMap () sky2cyl = MAX(skytex2->GetWidth(), skytex2->xScale >> (16 - 10)); } + +//========================================================================== +// +// R_UpdateSky +// +// Performs sky scrolling +// +//========================================================================== + +void R_UpdateSky (DWORD mstime) +{ + // Scroll the sky + double ms = (double)mstime * FRACUNIT; + sky1pos = ms * level.skyspeed1; + sky2pos = ms * level.skyspeed2; +} + diff --git a/src/r_sky.h b/src/r_sky.h index 3e836ec3e..f285c4268 100644 --- a/src/r_sky.h +++ b/src/r_sky.h @@ -38,5 +38,6 @@ extern bool skystretch; // Called whenever the sky changes. void R_InitSkyMap (); +void R_UpdateSky (DWORD mstime); #endif //__R_SKY_H__ diff --git a/src/r_anim.cpp b/src/textures/animations.cpp similarity index 64% rename from src/r_anim.cpp rename to src/textures/animations.cpp index cac361866..a4f0efe0c 100644 --- a/src/r_anim.cpp +++ b/src/textures/animations.cpp @@ -49,69 +49,91 @@ // TYPES ------------------------------------------------------------------- -// -// Animating textures and planes -// -// [RH] Expanded to work with a Hexen ANIMDEFS lump -// - -struct FAnimDef -{ - FTextureID BasePic; - WORD NumFrames; - WORD CurFrame; - BYTE AnimType; - DWORD SwitchTime; // Time to advance to next frame - struct FAnimFrame - { - DWORD SpeedMin; // Speeds are in ms, not tics - DWORD SpeedRange; - FTextureID FramePic; - } Frames[1]; - enum - { - ANIM_Forward, - ANIM_Backward, - ANIM_OscillateUp, - ANIM_OscillateDown, - ANIM_DiscreteFrames - }; - - void SetSwitchTime (DWORD mstime); -}; - -// This is an array of pointers to animation definitions. -// When it is destroyed, it deletes any animations it points to as well. -class AnimArray : public TArray -{ -public: - ~AnimArray(); - void AddAnim (FAnimDef *anim); - void FixAnimations (); -}; - // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- -static void R_InitAnimDefs (); -static void R_AddComplexAnim (FTextureID picnum, const TArray &frames); -static void ParseAnim (FScanner &sc, bool istex); -static void ParseRangeAnim (FScanner &sc, FTextureID picnum, int usetype, bool missing); -static void ParsePicAnim (FScanner &sc, FTextureID picnum, int usetype, bool missing, TArray &frames); -static FTextureID ParseFramenum (FScanner &sc, FTextureID basepicnum, int usetype, bool allowMissing); -static void ParseTime (FScanner &sc, DWORD &min, DWORD &max); - // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ -static AnimArray Anims; static FRandom pr_animatepictures ("AnimatePics"); // CODE -------------------------------------------------------------------- //========================================================================== // -// R_InitPicAnims +// FTextureManager :: AddAnim +// +// Adds a new animation to the array. If one with the same basepic as the +// new one already exists, it is replaced. +// +//========================================================================== + +void FTextureManager::AddAnim (FAnimDef *anim) +{ + // Search for existing duplicate. + for (unsigned int i = 0; i < mAnimations.Size(); ++i) + { + if (mAnimations[i]->BasePic == anim->BasePic) + { + // Found one! + free (mAnimations[i]); + mAnimations[i] = anim; + return; + } + } + // Didn't find one, so add it at the end. + mAnimations.Push (anim); +} + +//========================================================================== +// +// FTextureManager :: AddSimpleAnim +// +// Creates an animation with simple characteristics. This is used for +// original Doom (non-ANIMDEFS-style) animations and Build animations. +// +//========================================================================== + +void FTextureManager::AddSimpleAnim (FTextureID picnum, int animcount, int animtype, DWORD speedmin, DWORD speedrange) +{ + if (AreTexturesCompatible(picnum, picnum + (animcount - 1))) + { + FAnimDef *anim = (FAnimDef *)M_Malloc (sizeof(FAnimDef)); + anim->CurFrame = 0; + anim->BasePic = picnum; + anim->NumFrames = animcount; + anim->AnimType = animtype; + anim->SwitchTime = 0; + anim->Frames[0].SpeedMin = speedmin; + anim->Frames[0].SpeedRange = speedrange; + anim->Frames[0].FramePic = anim->BasePic; + AddAnim (anim); + } +} + +//========================================================================== +// +// FTextureManager :: AddComplexAnim +// +// Creates an animation with individually defined frames. +// +//========================================================================== + +void FTextureManager::AddComplexAnim (FTextureID picnum, const TArray &frames) +{ + FAnimDef *anim = (FAnimDef *)M_Malloc (sizeof(FAnimDef) + (frames.Size()-1) * sizeof(frames[0])); + anim->BasePic = picnum; + anim->NumFrames = frames.Size(); + anim->CurFrame = 0; + anim->AnimType = FAnimDef::ANIM_DiscreteFrames; + anim->SwitchTime = 0; + memcpy (&anim->Frames[0], &frames[0], frames.Size() * sizeof(frames[0])); + AddAnim (anim); +} + +//========================================================================== +// +// FTextureManager :: Initanimated // // [description copied from BOOM] // Load the table of animation definitions, checking for existence of @@ -139,9 +161,9 @@ static FRandom pr_animatepictures ("AnimatePics"); CVAR(Bool, debuganimated, false, 0) -void R_InitPicAnims (void) +void FTextureManager::InitAnimated (void) { - const BITFIELD texflags = FTextureManager::TEXMAN_Overridable; + const BITFIELD texflags = TEXMAN_Overridable; // I think better not! This is only for old ANIMATED definition that // don't know about ZDoom's more flexible texture system. // | FTextureManager::TEXMAN_TryAny; @@ -163,17 +185,17 @@ void R_InitPicAnims (void) if (*anim_p /* .istexture */ & 1) { // different episode ? - if (!(pic1 = TexMan.CheckForTexture (anim_p + 10 /* .startname */, FTexture::TEX_Wall, texflags)).Exists() || - !(pic2 = TexMan.CheckForTexture (anim_p + 1 /* .endname */, FTexture::TEX_Wall, texflags)).Exists()) + if (!(pic1 = CheckForTexture (anim_p + 10 /* .startname */, FTexture::TEX_Wall, texflags)).Exists() || + !(pic2 = CheckForTexture (anim_p + 1 /* .endname */, FTexture::TEX_Wall, texflags)).Exists()) continue; // [RH] Bit 1 set means allow decals on walls with this texture - TexMan[pic2]->bNoDecals = TexMan[pic1]->bNoDecals = !(*anim_p & 2); + Texture(pic2)->bNoDecals = Texture(pic1)->bNoDecals = !(*anim_p & 2); } else { - if (!(pic1 = TexMan.CheckForTexture (anim_p + 10 /* .startname */, FTexture::TEX_Flat, texflags)).Exists() || - !(pic2 = TexMan.CheckForTexture (anim_p + 1 /* .startname */, FTexture::TEX_Flat, texflags)).Exists()) + if (!(pic1 = CheckForTexture (anim_p + 10 /* .startname */, FTexture::TEX_Flat, texflags)).Exists() || + !(pic2 = CheckForTexture (anim_p + 1 /* .startname */, FTexture::TEX_Flat, texflags)).Exists()) continue; } if (pic1 == pic2) @@ -183,8 +205,8 @@ void R_InitPicAnims (void) continue; } - FTexture *tex1 = TexMan[pic1]; - FTexture *tex2 = TexMan[pic2]; + FTexture *tex1 = Texture(pic1); + FTexture *tex2 = Texture(pic2); if (tex1->UseType != tex2->UseType) { @@ -213,71 +235,22 @@ void R_InitPicAnims (void) (BYTE(anim_p[21]) << 16) | (BYTE(anim_p[22]) << 24), 1000, 35); - R_AddSimpleAnim (pic1, pic2 - pic1 + 1, animtype, animspeed); + AddSimpleAnim (pic1, pic2 - pic1 + 1, animtype, animspeed); } } - // [RH] Load any ANIMDEFS lumps - R_InitAnimDefs (); - Anims.FixAnimations (); } //========================================================================== // -// R_AddSimpleAnim -// -// Creates an animation with simple characteristics. This is used for -// original Doom (non-ANIMDEFS-style) animations and Build animations. -// -//========================================================================== - -void R_AddSimpleAnim (FTextureID picnum, int animcount, int animtype, DWORD speedmin, DWORD speedrange) -{ - if (TexMan.AreTexturesCompatible(picnum, picnum + (animcount - 1))) - { - FAnimDef *anim = (FAnimDef *)M_Malloc (sizeof(FAnimDef)); - anim->CurFrame = 0; - anim->BasePic = picnum; - anim->NumFrames = animcount; - anim->AnimType = animtype; - anim->SwitchTime = 0; - anim->Frames[0].SpeedMin = speedmin; - anim->Frames[0].SpeedRange = speedrange; - anim->Frames[0].FramePic = anim->BasePic; - Anims.AddAnim (anim); - } -} - -//========================================================================== -// -// R_AddComplexAnim -// -// Creates an animation with individually defined frames. -// -//========================================================================== - -static void R_AddComplexAnim (FTextureID picnum, const TArray &frames) -{ - FAnimDef *anim = (FAnimDef *)M_Malloc (sizeof(FAnimDef) + (frames.Size()-1) * sizeof(frames[0])); - anim->BasePic = picnum; - anim->NumFrames = frames.Size(); - anim->CurFrame = 0; - anim->AnimType = FAnimDef::ANIM_DiscreteFrames; - anim->SwitchTime = 0; - memcpy (&anim->Frames[0], &frames[0], frames.Size() * sizeof(frames[0])); - Anims.AddAnim (anim); -} - -//========================================================================== -// -// R_InitAnimDefs +// FTextureManager :: InitAnimDefs // // This uses a Hexen ANIMDEFS lump to define the animation sequences // //========================================================================== -static void R_InitAnimDefs () +void FTextureManager::InitAnimDefs () { - const BITFIELD texflags = FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny; + const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; int lump, lastlump = 0; while ((lump = Wads.FindLump ("ANIMDEFS", &lastlump)) != -1) @@ -288,11 +261,11 @@ static void R_InitAnimDefs () { if (sc.Compare ("flat")) { - ParseAnim (sc, false); + ParseAnim (sc, FTexture::TEX_Flat); } else if (sc.Compare ("texture")) { - ParseAnim (sc, true); + ParseAnim (sc, FTexture::TEX_Wall); } else if (sc.Compare ("switch")) { @@ -301,105 +274,11 @@ static void R_InitAnimDefs () // [GRB] Added warping type 2 else if (sc.Compare ("warp") || sc.Compare ("warp2")) { - bool isflat = false; - bool type2 = sc.Compare ("warp2"); // [GRB] - sc.MustGetString (); - if (sc.Compare ("flat")) - { - isflat = true; - sc.MustGetString (); - } - else if (sc.Compare ("texture")) - { - isflat = false; - sc.MustGetString (); - } - else - { - sc.ScriptError (NULL); - } - FTextureID picnum = TexMan.CheckForTexture (sc.String, isflat ? FTexture::TEX_Flat : FTexture::TEX_Wall, texflags); - if (picnum.isValid()) - { - FTexture * warper = TexMan[picnum]; - - // don't warp a texture more than once - if (!warper->bWarped) - { - if (type2) // [GRB] - warper = new FWarp2Texture (warper); - else - warper = new FWarpTexture (warper); - TexMan.ReplaceTexture (picnum, warper, false); - } - - if (sc.CheckFloat()) - { - static_cast(warper)->SetSpeed(float(sc.Float)); - } - - // No decals on warping textures, by default. - // Warping information is taken from the last warp - // definition for this texture. - warper->bNoDecals = true; - if (sc.GetString ()) - { - if (sc.Compare ("allowdecals")) - { - warper->bNoDecals = false; - } - else - { - sc.UnGet (); - } - } - } + ParseWarp(sc); } else if (sc.Compare ("cameratexture")) { - int width, height; - int fitwidth, fitheight; - FString picname; - - sc.MustGetString (); - picname = sc.String; - sc.MustGetNumber (); - width = sc.Number; - sc.MustGetNumber (); - height = sc.Number; - FTextureID picnum = TexMan.CheckForTexture (picname, FTexture::TEX_Flat, texflags); - FTexture *viewer = new FCanvasTexture (picname, width, height); - if (picnum.Exists()) - { - FTexture *oldtex = TexMan[picnum]; - fitwidth = oldtex->GetScaledWidth (); - fitheight = oldtex->GetScaledHeight (); - viewer->UseType = oldtex->UseType; - TexMan.ReplaceTexture (picnum, viewer, true); - } - else - { - fitwidth = width; - fitheight = height; - // [GRB] No need for oldtex - viewer->UseType = FTexture::TEX_Wall; - TexMan.AddTexture (viewer); - } - if (sc.GetString()) - { - if (sc.Compare ("fit")) - { - sc.MustGetNumber (); - fitwidth = sc.Number; - sc.MustGetNumber (); - fitheight = sc.Number; - } - else - { - sc.UnGet (); - } - } - viewer->SetScaledSize(fitwidth, fitheight); + ParseCameraTexture(sc); } else if (sc.Compare ("animatedDoor")) { @@ -408,12 +287,11 @@ static void R_InitAnimDefs () else if (sc.Compare("skyoffset")) { sc.MustGetString (); - FTextureID picnum = TexMan.CheckForTexture (sc.String, FTexture::TEX_Wall, texflags); + FTextureID picnum = CheckForTexture (sc.String, FTexture::TEX_Wall, texflags); sc.MustGetNumber(); if (picnum.Exists()) { - FTexture *tex = TexMan[picnum]; - tex->SkyOffset = sc.Number; + Texture(picnum)->SkyOffset = sc.Number; } } else @@ -426,31 +304,28 @@ static void R_InitAnimDefs () //========================================================================== // -// ParseAnim +// FTextureManager :: ParseAnim // // Parse a single animation definition out of an ANIMDEFS lump and // create the corresponding animation structure. // //========================================================================== -static void ParseAnim (FScanner &sc, bool istex) +void FTextureManager::ParseAnim (FScanner &sc, int usetype) { - const BITFIELD texflags = FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny; + const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; TArray frames (32); FTextureID picnum; - int usetype; int defined = 0; bool optional = false, missing = false; - usetype = istex ? FTexture::TEX_Wall : FTexture::TEX_Flat; - sc.MustGetString (); if (sc.Compare ("optional")) { optional = true; sc.MustGetString (); } - picnum = TexMan.CheckForTexture (sc.String, usetype, texflags); + picnum = CheckForTexture (sc.String, usetype, texflags); if (!picnum.Exists()) { @@ -467,7 +342,7 @@ static void ParseAnim (FScanner &sc, bool istex) // no decals on animating textures, by default if (picnum.isValid()) { - TexMan[picnum]->bNoDecals = true; + Texture(picnum)->bNoDecals = true; } while (sc.GetString ()) @@ -476,7 +351,7 @@ static void ParseAnim (FScanner &sc, bool istex) { if (picnum.isValid()) { - TexMan[picnum]->bNoDecals = false; + Texture(picnum)->bNoDecals = false; } continue; } @@ -517,20 +392,20 @@ static void ParseAnim (FScanner &sc, bool istex) { sc.ScriptError ("Animation needs at least 2 frames"); } - R_AddComplexAnim (picnum, frames); + AddComplexAnim (picnum, frames); } } //========================================================================== // -// ParseRangeAnim +// FTextureManager :: ParseRangeAnim // // Parse an animation defined using "range". Not that one range entry is // enough to define a complete animation, unlike "pic". // //========================================================================== -static void ParseRangeAnim (FScanner &sc, FTextureID picnum, int usetype, bool missing) +void FTextureManager::ParseRangeAnim (FScanner &sc, FTextureID picnum, int usetype, bool missing) { int type; FTextureID framenum; @@ -547,7 +422,7 @@ static void ParseRangeAnim (FScanner &sc, FTextureID picnum, int usetype, bool m if (framenum < picnum) { type = FAnimDef::ANIM_Backward; - TexMan[framenum]->bNoDecals = TexMan[picnum]->bNoDecals; + Texture(framenum)->bNoDecals = Texture(picnum)->bNoDecals; swapvalues (framenum, picnum); } if (sc.GetString()) @@ -561,18 +436,18 @@ static void ParseRangeAnim (FScanner &sc, FTextureID picnum, int usetype, bool m sc.UnGet (); } } - R_AddSimpleAnim (picnum, framenum - picnum + 1, type, min, max - min); + AddSimpleAnim (picnum, framenum - picnum + 1, type, min, max - min); } //========================================================================== // -// ParsePicAnim +// FTextureManager :: ParsePicAnim // // Parse a single frame from ANIMDEFS defined using "pic". // //========================================================================== -static void ParsePicAnim (FScanner &sc, FTextureID picnum, int usetype, bool missing, TArray &frames) +void FTextureManager::ParsePicAnim (FScanner &sc, FTextureID picnum, int usetype, bool missing, TArray &frames) { FTextureID framenum; DWORD min, max; @@ -593,16 +468,16 @@ static void ParsePicAnim (FScanner &sc, FTextureID picnum, int usetype, bool mis //========================================================================== // -// ParseFramenum +// FTextureManager :: ParseFramenum // // Reads a frame's texture from ANIMDEFS. It can either be an integral // offset from basepicnum or a specific texture name. // //========================================================================== -static FTextureID ParseFramenum (FScanner &sc, FTextureID basepicnum, int usetype, bool allowMissing) +FTextureID FTextureManager::ParseFramenum (FScanner &sc, FTextureID basepicnum, int usetype, bool allowMissing) { - const BITFIELD texflags = FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny; + const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; FTextureID framenum; sc.MustGetString (); @@ -612,7 +487,7 @@ static FTextureID ParseFramenum (FScanner &sc, FTextureID basepicnum, int usetyp } else { - framenum = TexMan.CheckForTexture (sc.String, usetype, texflags); + framenum = CheckForTexture (sc.String, usetype, texflags); if (!framenum.Exists() && !allowMissing) { sc.ScriptError ("Unknown texture %s", sc.String); @@ -623,13 +498,13 @@ static FTextureID ParseFramenum (FScanner &sc, FTextureID basepicnum, int usetyp //========================================================================== // -// ParseTime +// FTextureManager :: ParseTime // // Reads a tics or rand time definition from ANIMDEFS. // //========================================================================== -static void ParseTime (FScanner &sc, DWORD &min, DWORD &max) +void FTextureManager::ParseTime (FScanner &sc, DWORD &min, DWORD &max) { sc.MustGetString (); if (sc.Compare ("tics")) @@ -652,53 +527,128 @@ static void ParseTime (FScanner &sc, DWORD &min, DWORD &max) //========================================================================== // -// AnimArray :: ~AnimArray +// FTextureManager :: ParseWarp // -// Frees all animations held in this array before freeing the array. +// Parses a warping texture definition // //========================================================================== -AnimArray::~AnimArray() +void FTextureManager::ParseWarp(FScanner &sc) { - for (unsigned i = 0; i < Size(); i++) + const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; + bool isflat = false; + bool type2 = sc.Compare ("warp2"); // [GRB] + sc.MustGetString (); + if (sc.Compare ("flat")) { - if ((*this)[i] != NULL) + isflat = true; + sc.MustGetString (); + } + else if (sc.Compare ("texture")) + { + isflat = false; + sc.MustGetString (); + } + else + { + sc.ScriptError (NULL); + } + FTextureID picnum = CheckForTexture (sc.String, isflat ? FTexture::TEX_Flat : FTexture::TEX_Wall, texflags); + if (picnum.isValid()) + { + FTexture *warper = Texture(picnum); + + // don't warp a texture more than once + if (!warper->bWarped) { - M_Free ((*this)[i]); - (*this)[i] = NULL; + if (type2) warper = new FWarp2Texture (warper); + else warper = new FWarpTexture (warper); + + ReplaceTexture (picnum, warper, false); + } + + if (sc.CheckFloat()) + { + static_cast(warper)->SetSpeed(float(sc.Float)); + } + + // No decals on warping textures, by default. + // Warping information is taken from the last warp + // definition for this texture. + warper->bNoDecals = true; + if (sc.GetString ()) + { + if (sc.Compare ("allowdecals")) + { + warper->bNoDecals = false; + } + else + { + sc.UnGet (); + } } } } //========================================================================== // -// AnimArray :: AddAnim +// ParseCameraTexture // -// Adds a new animation to the array. If one with the same basepic as the -// new one already exists, it is replaced. +// Parses a camera texture definition // //========================================================================== -void AnimArray::AddAnim (FAnimDef *anim) +void FTextureManager::ParseCameraTexture(FScanner &sc) { - // Search for existing duplicate. - for (unsigned int i = 0; i < Anims.Size(); ++i) + const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; + int width, height; + int fitwidth, fitheight; + FString picname; + + sc.MustGetString (); + picname = sc.String; + sc.MustGetNumber (); + width = sc.Number; + sc.MustGetNumber (); + height = sc.Number; + FTextureID picnum = CheckForTexture (picname, FTexture::TEX_Flat, texflags); + FTexture *viewer = new FCanvasTexture (picname, width, height); + if (picnum.Exists()) { - if ((*this)[i]->BasePic == anim->BasePic) + FTexture *oldtex = Texture(picnum); + fitwidth = oldtex->GetScaledWidth (); + fitheight = oldtex->GetScaledHeight (); + viewer->UseType = oldtex->UseType; + ReplaceTexture (picnum, viewer, true); + } + else + { + fitwidth = width; + fitheight = height; + // [GRB] No need for oldtex + viewer->UseType = FTexture::TEX_Wall; + AddTexture (viewer); + } + if (sc.GetString()) + { + if (sc.Compare ("fit")) { - // Found one! - free ((*this)[i]); - (*this)[i] = anim; - return; + sc.MustGetNumber (); + fitwidth = sc.Number; + sc.MustGetNumber (); + fitheight = sc.Number; + } + else + { + sc.UnGet (); } } - // Didn't find one, so add it at the end. - Push (anim); + viewer->SetScaledSize(fitwidth, fitheight); } //========================================================================== // -// AnimArray :: FixAnimations +// FTextureManager :: FixAnimations // // Copy the "front sky" flag from an animated texture to the rest // of the textures in the animation, and make every texture in an @@ -706,21 +656,21 @@ void AnimArray::AddAnim (FAnimDef *anim) // //========================================================================== -void AnimArray::FixAnimations () +void FTextureManager::FixAnimations () { unsigned int i; int j; - for (i = 0; i < Size(); ++i) + for (i = 0; i < mAnimations.Size(); ++i) { - FAnimDef *anim = operator[] (i); + FAnimDef *anim = mAnimations[i]; if (anim->AnimType == FAnimDef::ANIM_DiscreteFrames) { - if (TexMan[anim->BasePic]->bNoRemap0) + if (Texture(anim->BasePic)->bNoRemap0) { for (j = 0; j < anim->NumFrames; ++j) { - TexMan[anim->Frames[j].FramePic]->SetFrontSkyLayer (); + Texture(anim->Frames[j].FramePic)->SetFrontSkyLayer (); } } } @@ -730,11 +680,11 @@ void AnimArray::FixAnimations () bool noremap = false; const char *name; - name = TexMan[anim->BasePic]->Name; - nodecals = TexMan[anim->BasePic]->bNoDecals; + name = Texture(anim->BasePic)->Name; + nodecals = Texture(anim->BasePic)->bNoDecals; for (j = 0; j < anim->NumFrames; ++j) { - FTexture *tex = TexMan[anim->BasePic + j]; + FTexture *tex = Texture(anim->BasePic + j); noremap |= tex->bNoRemap0; tex->bNoDecals = nodecals; } @@ -742,7 +692,7 @@ void AnimArray::FixAnimations () { for (j = 0; j < anim->NumFrames; ++j) { - TexMan[anim->BasePic + j]->SetFrontSkyLayer (); + Texture(anim->BasePic + j)->SetFrontSkyLayer (); } } } @@ -768,19 +718,41 @@ void FAnimDef::SetSwitchTime (DWORD mstime) } } + //========================================================================== // -// R_UpdateAnimations +// FTextureManager :: SetTranslation +// +// Sets animation translation for a texture +// +//========================================================================== + +void FTextureManager::SetTranslation (FTextureID fromtexnum, FTextureID totexnum) +{ + if ((size_t)fromtexnum.texnum < Translation.Size()) + { + if ((size_t)totexnum.texnum >= Textures.Size()) + { + totexnum.texnum = fromtexnum.texnum; + } + Translation[fromtexnum.texnum] = totexnum.texnum; + } +} + + +//========================================================================== +// +// FTextureManager :: UpdateAnimations // // Updates texture translations for each animation and scrolls the skies. // //========================================================================== -void R_UpdateAnimations (DWORD mstime) +void FTextureManager::UpdateAnimations (DWORD mstime) { - for (unsigned int j = 0; j < Anims.Size(); ++j) + for (unsigned int j = 0; j < mAnimations.Size(); ++j) { - FAnimDef *anim = Anims[j]; + FAnimDef *anim = mAnimations[j]; // If this is the first time through R_UpdateAnimations, just // initialize the anim's switch time without actually animating. @@ -832,19 +804,14 @@ void R_UpdateAnimations (DWORD mstime) if (anim->AnimType == FAnimDef::ANIM_DiscreteFrames) { - TexMan.SetTranslation (anim->BasePic, anim->Frames[anim->CurFrame].FramePic); + SetTranslation (anim->BasePic, anim->Frames[anim->CurFrame].FramePic); } else { for (unsigned int i = 0; i < anim->NumFrames; i++) { - TexMan.SetTranslation (anim->BasePic + i, anim->BasePic + (i + anim->CurFrame) % anim->NumFrames); + SetTranslation (anim->BasePic + i, anim->BasePic + (i + anim->CurFrame) % anim->NumFrames); } } } - - // Scroll the sky - double ms = (double)mstime * FRACUNIT; - sky1pos = ms * level.skyspeed1; - sky2pos = ms * level.skyspeed2; } diff --git a/src/textures/buildtexture.cpp b/src/textures/buildtexture.cpp index 5f4172a60..2a3d1809f 100644 --- a/src/textures/buildtexture.cpp +++ b/src/textures/buildtexture.cpp @@ -41,8 +41,6 @@ #include "cmdlib.h" #include "st_start.h" -static TArray BuildTileFiles; - //========================================================================== // // A texture defined in a Build TILESxxx.ART file @@ -158,7 +156,7 @@ const BYTE *FBuildTexture::GetColumn (unsigned int column, const Span **spans_ou // //=========================================================================== -void AddTiles (void *tiles) +void FTextureManager::AddTiles (void *tiles) { // int numtiles = LittleLong(((DWORD *)tiles)[1]); // This value is not reliable int tilestart = LittleLong(((DWORD *)tiles)[2]); @@ -183,7 +181,7 @@ void AddTiles (void *tiles) if (width <= 0 || height <= 0) continue; tex = new FBuildTexture (i, tiledata, width, height, xoffs, yoffs); - texnum = TexMan.AddTexture (tex); + texnum = AddTexture (tex); while (size > 0) { *tiledata = 255 - *tiledata; @@ -207,7 +205,7 @@ void AddTiles (void *tiles) speed = (anm >> 24) & 15; speed = MAX (1, (1 << speed) * 1000 / 120); // Convert from 120 Hz to 1000 Hz. - R_AddSimpleAnim (texnum, picanm[pic] & 63, type, speed); + AddSimpleAnim (texnum, picanm[pic] & 63, type, speed); } // Blood's rotation types: @@ -262,7 +260,7 @@ void AddTiles (void *tiles) // //=========================================================================== -static int CountTiles (void *tiles) +int FTextureManager::CountTiles (void *tiles) { int version = LittleLong(*(DWORD *)tiles); if (version != 1) @@ -285,7 +283,7 @@ static int CountTiles (void *tiles) // //=========================================================================== -int R_CountBuildTiles () +int FTextureManager::CountBuildTiles () { int numartfiles = 0; char artfile[] = "tilesXXX.art"; @@ -373,25 +371,10 @@ int R_CountBuildTiles () // //=========================================================================== -void R_InitBuildTiles () +void FTextureManager::InitBuildTiles () { for (unsigned int i = 0; i < BuildTileFiles.Size(); ++i) { AddTiles (BuildTileFiles[i]); } } - -//=========================================================================== -// -// R_DeinitBuildTiles -// -//=========================================================================== - -void R_DeinitBuildTiles () -{ - for (unsigned int i = 0; i < BuildTileFiles.Size(); ++i) - { - delete[] BuildTileFiles[i]; - } - BuildTileFiles.Clear(); -} diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index e562923db..80690a03b 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -62,8 +62,6 @@ FTextureManager TexMan; FTextureManager::FTextureManager () { memset (HashFirst, -1, sizeof(HashFirst)); - // Texture 0 is a dummy texture used to indicate "no texture" - AddTexture (new FDummyTexture); } @@ -74,11 +72,43 @@ FTextureManager::FTextureManager () //========================================================================== FTextureManager::~FTextureManager () +{ + DeleteAll(); +} + +//========================================================================== +// +// FTextureManager :: DeleteAll +// +//========================================================================== + +void FTextureManager::DeleteAll() { for (unsigned int i = 0; i < Textures.Size(); ++i) { delete Textures[i].Texture; } + Textures.Clear(); + Translation.Clear(); + FirstTextureForFile.Clear(); + memset (HashFirst, -1, sizeof(HashFirst)); + DefaultTexture.SetInvalid(); + + for (unsigned i = 0; i < mAnimations.Size(); i++) + { + if (mAnimations[i] != NULL) + { + M_Free (mAnimations[i]); + mAnimations[i] = NULL; + } + } + mAnimations.Clear(); + + for (unsigned int i = 0; i < BuildTileFiles.Size(); ++i) + { + delete[] BuildTileFiles[i]; + } + BuildTileFiles.Clear(); } //========================================================================== @@ -896,8 +926,14 @@ void FTextureManager::SortTexturesByType(int start, int end) void FTextureManager::Init() { + DeleteAll(); + // Init Build Tile data if it hasn't been done already + if (BuildTileFiles.Size() == 0) CountBuildTiles (); FTexture::InitGrayMap(); + // Texture 0 is a dummy texture used to indicate "no texture" + AddTexture (new FDummyTexture); + int wadcnt = Wads.GetNumWads(); for(int i = 0; i< wadcnt; i++) { @@ -907,7 +943,7 @@ void FTextureManager::Init() // Add one marker so that the last WAD is easier to handle and treat // Build tiles as a completely separate block. FirstTextureForFile.Push(Textures.Size()); - R_InitBuildTiles (); + InitBuildTiles (); FirstTextureForFile.Push(Textures.Size()); DefaultTexture = CheckForTexture ("-NOFLAT-", FTexture::TEX_Override, 0); @@ -938,6 +974,10 @@ void FTextureManager::Init() } } } + + InitAnimated(); + InitAnimDefs(); + FixAnimations(); } //========================================================================== @@ -988,6 +1028,104 @@ int FTextureManager::ReadTexture (FArchive &arc) else return -1; } +//=========================================================================== +// +// R_GuesstimateNumTextures +// +// Returns an estimate of the number of textures R_InitData will have to +// process. Used by D_DoomMain() when it calls ST_Init(). +// +//=========================================================================== + +int FTextureManager::GuesstimateNumTextures () +{ + int numtex = 0; + + for(int i = Wads.GetNumLumps()-1; i>=0; i--) + { + int space = Wads.GetLumpNamespace(i); + switch(space) + { + case ns_flats: + case ns_sprites: + case ns_newtextures: + case ns_hires: + case ns_patches: + case ns_graphics: + numtex++; + break; + + default: + if (Wads.GetLumpFlags(i) & LUMPF_MAYBEFLAT) numtex++; + + break; + } + } + + numtex += CountBuildTiles (); + numtex += CountTexturesX (); + return numtex; +} + +//=========================================================================== +// +// R_CountTexturesX +// +// See R_InitTextures() for the logic in deciding what lumps to check. +// +//=========================================================================== + +int FTextureManager::CountTexturesX () +{ + int count = 0; + int wadcount = Wads.GetNumWads(); + for (int wadnum = 0; wadnum < wadcount; 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); + + // should never happen except for zdoom.pk3 + if (pnames < 0) continue; + + // Only count the patches if the PNAMES come from the current file + // Otherwise they have already been counted. + if (Wads.GetLumpFile(pnames) == wadnum) + { + count += CountLumpTextures (pnames); + } + + int texlump1 = Wads.CheckNumForName ("TEXTURE1", ns_global, wadnum); + int texlump2 = Wads.CheckNumForName ("TEXTURE2", ns_global, wadnum); + + count += CountLumpTextures (texlump1) - 1; + count += CountLumpTextures (texlump2) - 1; + } + return count; +} + +//=========================================================================== +// +// R_CountLumpTextures +// +// Returns the number of patches in a PNAMES/TEXTURE1/TEXTURE2 lump. +// +//=========================================================================== + +int FTextureManager::CountLumpTextures (int lumpnum) +{ + if (lumpnum >= 0) + { + FWadLump file = Wads.OpenLumpNum (lumpnum); + DWORD numtex; + + file >> numtex; + return numtex >= 0 ? numtex : 0; + } + return 0; +} + + //========================================================================== // // operator<< diff --git a/src/textures/textures.h b/src/textures/textures.h index a756a7036..e65aae13b 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -41,8 +41,6 @@ protected: FTextureID(int num) { texnum = num; } private: int texnum; - - friend void AddTiles (void *tiles); }; class FNullTextureID : public FTextureID @@ -53,6 +51,37 @@ public: FArchive &operator<< (FArchive &arc, FTextureID &tex); +// +// Animating textures and planes +// +// [RH] Expanded to work with a Hexen ANIMDEFS lump +// + +struct FAnimDef +{ + FTextureID BasePic; + WORD NumFrames; + WORD CurFrame; + BYTE AnimType; + DWORD SwitchTime; // Time to advance to next frame + struct FAnimFrame + { + DWORD SpeedMin; // Speeds are in ms, not tics + DWORD SpeedRange; + FTextureID FramePic; + } Frames[1]; + enum + { + ANIM_Forward, + ANIM_Backward, + ANIM_OscillateUp, + ANIM_OscillateDown, + ANIM_DiscreteFrames + }; + + void SetSwitchTime (DWORD mstime); +}; + // Patches. // A patch holds one or more columns. @@ -294,18 +323,6 @@ public: return Textures[Translation[i]].Texture; } - void SetTranslation (FTextureID fromtexnum, FTextureID totexnum) - { - if ((size_t)fromtexnum.texnum < Translation.Size()) - { - if ((size_t)totexnum.texnum >= Textures.Size()) - { - totexnum.texnum = fromtexnum.texnum; - } - Translation[fromtexnum.texnum] = totexnum.texnum; - } - } - enum { TEXMAN_TryAny = 1, @@ -322,7 +339,6 @@ public: void AddTexturesLumps (int lump1, int lump2, int patcheslump); void AddGroup(int wadnum, int ns, int usetype); void AddPatches (int lumpnum); - void AddTiles (void *tileFile); void AddHiresTextures (int wadnum); void LoadTextureDefs(int wadnum, const char *lumpname); void ParseXTexture(FScanner &sc, int usetype); @@ -336,6 +352,7 @@ public: void LoadTextureX(int wadnum); void AddTexturesForWad(int wadnum); void Init(); + void DeleteAll(); // Replaces one texture with another. The new texture will be assigned // the same name, slot, and use type as the texture it is replacing. @@ -353,8 +370,38 @@ public: void WriteTexture (FArchive &arc, int picnum); int ReadTexture (FArchive &arc); + void UpdateAnimations (DWORD mstime); + int GuesstimateNumTextures (); private: + + // texture counting + int CountTexturesX (); + int CountLumpTextures (int lumpnum); + + // Build tiles + void AddTiles (void *tiles); + int CountTiles (void *tiles); + int CountBuildTiles (); + void InitBuildTiles (); + + // Animation stuff + void AddAnim (FAnimDef *anim); + void FixAnimations (); + void InitAnimated (); + void InitAnimDefs (); + void AddSimpleAnim (FTextureID picnum, int animcount, int animtype, DWORD speedmin, DWORD speedrange=0); + void AddComplexAnim (FTextureID picnum, const TArray &frames); + void ParseAnim (FScanner &sc, int usetype); + void ParseRangeAnim (FScanner &sc, FTextureID picnum, int usetype, bool missing); + void ParsePicAnim (FScanner &sc, FTextureID picnum, int usetype, bool missing, TArray &frames); + void ParseWarp(FScanner &sc); + void ParseCameraTexture(FScanner &sc); + FTextureID ParseFramenum (FScanner &sc, FTextureID basepicnum, int usetype, bool allowMissing); + void ParseTime (FScanner &sc, DWORD &min, DWORD &max); + FTexture *Texture(FTextureID id) { return Textures[id.GetIndex()].Texture; } + void SetTranslation (FTextureID fromtexnum, FTextureID totexnum); + struct TextureHash { FTexture *Texture; @@ -366,6 +413,9 @@ private: int HashFirst[HASH_SIZE]; FTextureID DefaultTexture; TArray FirstTextureForFile; + + TArray mAnimations; + TArray BuildTileFiles; }; extern FTextureManager TexMan; diff --git a/zdoom.vcproj b/zdoom.vcproj index 834715c60..9acb2c29e 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -2299,10 +2299,6 @@ - - @@ -2423,6 +2419,10 @@ + +