- allow specifying actor classes whose graphics to precache through MAPINFO.

- some reorganization of texture precaching so that the renderer can decide what to do with actors.

Just marking the sprite textures loses too much info if more is needed than just loading the images into memory.
This commit is contained in:
Christoph Oelckers 2016-05-01 22:47:36 +02:00
parent 0d402618a3
commit 65e1589543
10 changed files with 144 additions and 121 deletions

View File

@ -338,6 +338,7 @@ struct level_info_t
TArray<FSoundID> PrecacheSounds;
TArray<FString> PrecacheTextures;
TArray<FName> PrecacheClasses;
level_info_t()
{

View File

@ -1083,6 +1083,18 @@ DEFINE_MAP_OPTION(PrecacheTextures, true)
} while (parse.sc.CheckString(","));
}
DEFINE_MAP_OPTION(PrecacheClasses, true)
{
parse.ParseAssign();
do
{
parse.sc.MustGetString();
//the class list is not initialized here so all we can do is store the class's name.
info->PrecacheClasses.Push(parse.sc.String);
} while (parse.sc.CheckString(","));
}
DEFINE_MAP_OPTION(redirect, true)
{
parse.ParseAssign();

View File

@ -3366,6 +3366,83 @@ void P_GetPolySpots (MapData * map, TArray<FNodeBuilder::FPolyStart> &spots, TAr
}
}
//===========================================================================
//
// P_PrecacheLevel
//
// Preloads all relevant graphics for the level.
//
//===========================================================================
static void P_PrecacheLevel()
{
int i;
BYTE *hitlist;
TMap<PClassActor *, bool> actorhitlist;
int cnt = TexMan.NumTextures();
if (demoplayback)
return;
hitlist = new BYTE[cnt];
memset(hitlist, 0, cnt);
AActor *actor;
TThinkerIterator<AActor> iterator;
while ((actor = iterator.Next()))
{
actorhitlist[actor->GetClass()] = true;
}
for (unsigned i = 0; i < level.info->PrecacheClasses.Size(); i++)
{
// level.info can only store names, no class pointers.
PClassActor *cls = PClass::FindActor(level.info->PrecacheClasses[i]);
if (cls != NULL) actorhitlist[cls] = true;
}
for (i = numsectors - 1; i >= 0; i--)
{
hitlist[sectors[i].GetTexture(sector_t::floor).GetIndex()] |= FTextureManager::HIT_Flat;
hitlist[sectors[i].GetTexture(sector_t::ceiling).GetIndex()] |= FTextureManager::HIT_Flat;
}
for (i = numsides - 1; i >= 0; i--)
{
hitlist[sides[i].GetTexture(side_t::top).GetIndex()] |= FTextureManager::HIT_Wall;
hitlist[sides[i].GetTexture(side_t::mid).GetIndex()] |= FTextureManager::HIT_Wall;
hitlist[sides[i].GetTexture(side_t::bottom).GetIndex()] |= FTextureManager::HIT_Wall;
}
// Sky texture is always present.
// Note that F_SKY1 is the name used to
// indicate a sky floor/ceiling as a flat,
// while the sky texture is stored like
// a wall texture, with an episode dependant
// name.
if (sky1texture.isValid())
{
hitlist[sky1texture.GetIndex()] |= FTextureManager::HIT_Sky;
}
if (sky2texture.isValid())
{
hitlist[sky2texture.GetIndex()] |= FTextureManager::HIT_Sky;
}
for (unsigned i = 0; i < level.info->PrecacheTextures.Size(); i++)
{
FTextureID tex = TexMan.CheckForTexture(level.info->PrecacheTextures[i], FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable | FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ReturnFirst);
if (tex.Exists()) hitlist[tex.GetIndex()] |= FTextureManager::HIT_Wall;
}
Renderer->Precache(hitlist, actorhitlist);
delete[] hitlist;
}
extern polyblock_t **PolyBlockMap;
void P_FreeLevelData ()
@ -4094,7 +4171,7 @@ void P_SetupLevel (const char *lumpname, int position)
// preload graphics and sounds
if (precache)
{
TexMan.PrecacheLevel ();
P_PrecacheLevel ();
S_PrecacheLevel ();
}
times[17].Unclock();

View File

@ -28,7 +28,7 @@ struct FRenderer
virtual bool UsesColormap() const = 0;
// precache one texture
virtual void PrecacheTexture(FTexture *tex, int cache) = 0;
virtual void Precache(BYTE *texhitlist, TMap<PClassActor*, bool> &actorhitlist) = 0;
// render 3D view
virtual void RenderView(player_t *player) = 0;

View File

@ -98,6 +98,55 @@ void FSoftwareRenderer::PrecacheTexture(FTexture *tex, int cache)
}
}
void FSoftwareRenderer::Precache(BYTE *texhitlist, TMap<PClassActor*, bool> &actorhitlist)
{
BYTE *spritelist = new BYTE[sprites.Size()];
TMap<PClassActor*, bool>::Iterator it(actorhitlist);
TMap<PClassActor*, bool>::Pair *pair;
memset(spritelist, 0, sprites.Size());
while (it.NextPair(pair))
{
PClassActor *cls = pair->Key;
for (int i = 0; i < cls->NumOwnedStates; i++)
{
spritelist[cls->OwnedStates[i].sprite] = true;
}
}
// Precache textures (and sprites).
for (int i = (int)(sprites.Size() - 1); i >= 0; i--)
{
if (spritelist[i])
{
int j, k;
for (j = 0; j < sprites[i].numframes; j++)
{
const spriteframe_t *frame = &SpriteFrames[sprites[i].spriteframes + j];
for (k = 0; k < 16; k++)
{
FTextureID pic = frame->Texture[k];
if (pic.isValid())
{
texhitlist[pic.GetIndex()] = FTextureManager::HIT_Sprite;
}
}
}
}
}
delete[] spritelist;
int cnt = TexMan.NumTextures();
for (int i = cnt - 1; i >= 0; i--)
{
PrecacheTexture(TexMan.ByIndex(i), texhitlist[i]);
}
}
//===========================================================================
//
// Render the view

View File

@ -9,7 +9,8 @@ struct FSoftwareRenderer : public FRenderer
virtual bool UsesColormap() const;
// precache one texture
virtual void PrecacheTexture(FTexture *tex, int cache);
void PrecacheTexture(FTexture *tex, int cache);
virtual void Precache(BYTE *texhitlist, TMap<PClassActor*, bool> &actorhitlist);
// render 3D view
virtual void RenderView(player_t *player);

View File

@ -1226,44 +1226,6 @@ int FTextureManager::CountLumpTextures (int lumpnum)
return 0;
}
//===========================================================================
//
// R_PrecacheLevel
//
// Preloads all relevant graphics for the level.
//
//===========================================================================
void FTextureManager::PrecacheLevel (void)
{
BYTE *hitlist;
int cnt = NumTextures();
if (demoplayback)
return;
hitlist = new BYTE[cnt];
memset (hitlist, 0, cnt);
screen->GetHitlist(hitlist);
for (unsigned i = 0; i < level.info->PrecacheTextures.Size(); i++)
{
FTextureID tex = TexMan.CheckForTexture(level.info->PrecacheTextures[i], FTexture::TEX_Wall, FTextureManager::TEXMAN_Overridable|FTextureManager::TEXMAN_TryAny|FTextureManager::TEXMAN_ReturnFirst);
if (tex.Exists()) hitlist[tex.GetIndex()] |= FTextureManager::HIT_Wall;
}
for (int i = cnt - 1; i >= 0; i--)
{
Renderer->PrecacheTexture(ByIndex(i), hitlist[i]);
}
delete[] hitlist;
}
//==========================================================================
//

View File

@ -379,7 +379,6 @@ public:
void UnloadAll ();
int NumTextures () const { return (int)Textures.Size(); }
void PrecacheLevel (void);
void WriteTexture (FArchive &arc, int picnum);
int ReadTexture (FArchive &arc);

View File

@ -1207,83 +1207,6 @@ void DFrameBuffer::WipeCleanup()
wipe_Cleanup();
}
//===========================================================================
//
// Create texture hitlist
//
//===========================================================================
void DFrameBuffer::GetHitlist(BYTE *hitlist)
{
BYTE *spritelist;
int i;
spritelist = new BYTE[sprites.Size()];
// Precache textures (and sprites).
memset (spritelist, 0, sprites.Size());
{
AActor *actor;
TThinkerIterator<AActor> iterator;
while ( (actor = iterator.Next ()) )
spritelist[actor->sprite] = 1;
}
for (i = (int)(sprites.Size () - 1); i >= 0; i--)
{
if (spritelist[i])
{
int j, k;
for (j = 0; j < sprites[i].numframes; j++)
{
const spriteframe_t *frame = &SpriteFrames[sprites[i].spriteframes + j];
for (k = 0; k < 16; k++)
{
FTextureID pic = frame->Texture[k];
if (pic.isValid())
{
hitlist[pic.GetIndex()] = FTextureManager::HIT_Sprite;
}
}
}
}
}
delete[] spritelist;
for (i = numsectors - 1; i >= 0; i--)
{
hitlist[sectors[i].GetTexture(sector_t::floor).GetIndex()] =
hitlist[sectors[i].GetTexture(sector_t::ceiling).GetIndex()] |= FTextureManager::HIT_Flat;
}
for (i = numsides - 1; i >= 0; i--)
{
hitlist[sides[i].GetTexture(side_t::top).GetIndex()] =
hitlist[sides[i].GetTexture(side_t::mid).GetIndex()] =
hitlist[sides[i].GetTexture(side_t::bottom).GetIndex()] |= FTextureManager::HIT_Wall;
}
// Sky texture is always present.
// Note that F_SKY1 is the name used to
// indicate a sky floor/ceiling as a flat,
// while the sky texture is stored like
// a wall texture, with an episode dependant
// name.
if (sky1texture.isValid())
{
hitlist[sky1texture.GetIndex()] |= FTextureManager::HIT_Sky;
}
if (sky2texture.isValid())
{
hitlist[sky2texture.GetIndex()] |= FTextureManager::HIT_Sky;
}
}
//==========================================================================
//
// DFrameBuffer :: GameRestart

View File

@ -395,8 +395,7 @@ public:
virtual FNativePalette *CreatePalette(FRemapTable *remap);
// Precaches or unloads a texture
virtual void GetHitlist(BYTE *hitlist);
// Report a game restart
virtual void GameRestart();