mirror of
https://github.com/DrBeef/Raze.git
synced 2025-01-19 07:31:03 +00:00
- big texture system refactor.
Finally that quickly slapped together BuildTiles class is gone and replaced with something that better integrates with the underlying texture manager
This commit is contained in:
parent
9a1a90a730
commit
20edd800f9
63 changed files with 1583 additions and 2101 deletions
|
@ -1220,9 +1220,9 @@ set (PCH_SOURCES
|
|||
common/scripting/backend/vmbuilder.cpp
|
||||
common/scripting/backend/codegen.cpp
|
||||
|
||||
|
||||
|
||||
core/textures/buildtiles.cpp
|
||||
core/textures/tiletexture.cpp
|
||||
core/textures/texinfo.cpp
|
||||
core/textures/tilesetbuilder.cpp
|
||||
core/textures/skytexture.cpp
|
||||
core/textures/hightile.cpp
|
||||
core/music/s_advsound.cpp
|
||||
|
|
|
@ -17,7 +17,6 @@ static_assert('\xff' == 255, "Char must be unsigned!");
|
|||
|
||||
#include "printf.h"
|
||||
#include "palette.h"
|
||||
#include "buildtiles.h"
|
||||
#include "c_cvars.h"
|
||||
#include "cmdlib.h"
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "gamefuncs.h"
|
||||
#include "coreactor.h"
|
||||
#include "texturemanager.h"
|
||||
#include "buildtiles.h"
|
||||
|
||||
enum { MAXCLIPDIST = 1024 };
|
||||
|
||||
|
|
|
@ -186,6 +186,7 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset
|
|||
// The name matches, so check the texture type
|
||||
if (usetype == ETextureType::Any)
|
||||
{
|
||||
if (flags & TEXMAN_ReturnAll) return FTextureID(i); // user asked to skip all checks, including null textures.
|
||||
// All NULL textures should actually return 0
|
||||
if (texUseType == ETextureType::FirstDefined && !(flags & TEXMAN_ReturnFirst)) return 0;
|
||||
if (texUseType == ETextureType::SkinGraphic && !(flags & TEXMAN_AllowSkins)) return 0;
|
||||
|
@ -229,6 +230,7 @@ FTextureID FTextureManager::CheckForTexture (const char *name, ETextureType uset
|
|||
// Never return the index of NULL textures.
|
||||
if (firstfound != -1)
|
||||
{
|
||||
if (flags & TEXMAN_ReturnAll) return FTextureID(i); // user asked to skip all checks, including null textures.
|
||||
if (firsttype == ETextureType::Null) return FTextureID(0);
|
||||
if (firsttype == ETextureType::FirstDefined && !(flags & TEXMAN_ReturnFirst)) return FTextureID(0);
|
||||
return FTextureID(firstfound);
|
||||
|
@ -1601,14 +1603,10 @@ void FTextureManager::SetTranslation(FTextureID fromtexnum, FTextureID totexnum)
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void FTextureManager::AddAlias(const char* name, FGameTexture* tex)
|
||||
void FTextureManager::AddAlias(const char* name, int texindex)
|
||||
{
|
||||
FTextureID id = tex->GetID();
|
||||
if (tex != Textures[id.GetIndex()].Texture)// || !tex->isValid())
|
||||
{
|
||||
return; // Whatever got passed in here was not valid, so ignore the alias.
|
||||
}
|
||||
aliases.Insert(name, id.GetIndex());
|
||||
if (texindex < 0 || texindex >= NumTextures()) return; // Whatever got passed in here was not valid, so ignore the alias.
|
||||
aliases.Insert(name, texindex);
|
||||
}
|
||||
|
||||
void FTextureManager::Listaliases()
|
||||
|
|
|
@ -100,6 +100,7 @@ public:
|
|||
TEXMAN_Localize = 64,
|
||||
TEXMAN_ForceLookup = 128,
|
||||
TEXMAN_NoAlias = 256,
|
||||
TEXMAN_ReturnAll = 512,
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -155,7 +156,11 @@ public:
|
|||
tmanips.Remove(cname);
|
||||
}
|
||||
|
||||
void AddAlias(const char* name, FGameTexture* tex);
|
||||
void AddAlias(const char* name, int texindex);
|
||||
void AddAlias(const char* name, FTextureID texindex)
|
||||
{
|
||||
AddAlias(name, texindex.GetIndex());
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -45,6 +45,8 @@
|
|||
#include "types.h"
|
||||
#include "filesystem.h"
|
||||
#include "texturemanager.h"
|
||||
#include "texinfo.h"
|
||||
#include "buildtiles.h"
|
||||
|
||||
extern void LoadActors ();
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "raze_sound.h"
|
||||
#include "vm.h"
|
||||
#include "texturemanager.h"
|
||||
#include "buildtiles.h"
|
||||
|
||||
// Doubly linked ring list of Actors
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -46,6 +46,9 @@
|
|||
#include "i_system.h"
|
||||
#include "gamecontrol.h"
|
||||
#include "coreactor.h"
|
||||
#include "texinfo.h"
|
||||
|
||||
#include "buildtiles.h"
|
||||
|
||||
extern TArray<ClusterDef> clusters;
|
||||
extern TArray<VolumeRecord> volumes;
|
||||
|
@ -500,18 +503,18 @@ void FMapInfoParser::ParseTextureFlags()
|
|||
do
|
||||
{
|
||||
sc.MustGetString();
|
||||
int tile = tileForName(sc.String);
|
||||
// this must also get null textures and ones not yet loaded.
|
||||
auto tex = TexMan.CheckForTexture(sc.String, ETextureType::Any, FTextureManager::TEXMAN_ReturnAll | FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ForceLookup);
|
||||
|
||||
if (tile == -1)
|
||||
if (!tex.isValid())
|
||||
{
|
||||
sc.ScriptMessage("textureflags:Unknown texture name '%s'", sc.String);
|
||||
}
|
||||
else
|
||||
{
|
||||
TileFiles.tiledata[tile].tileflags |= num;
|
||||
texExtInfo[tex.GetIndex()].flags |= num;
|
||||
}
|
||||
|
||||
// tileflags |= sc.Number;
|
||||
} while (sc.CheckString(","));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,6 +82,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "findfile.h"
|
||||
#include "version.h"
|
||||
#include "hw_material.h"
|
||||
#include "tiletexture.h"
|
||||
#include "tilesetbuilder.h"
|
||||
|
||||
#include "buildtiles.h"
|
||||
|
||||
void LoadHexFont(const char* filename);
|
||||
|
||||
|
@ -629,7 +633,6 @@ int GameMain()
|
|||
voxClear();
|
||||
ClearPalManager();
|
||||
TexMan.DeleteAll();
|
||||
TileFiles.CloseAll(); // delete the texture data before shutting down graphics.
|
||||
I_ShutdownGraphics();
|
||||
if (gi)
|
||||
{
|
||||
|
@ -950,22 +953,32 @@ void GetGames()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static void InitTextures()
|
||||
static void InitTextures(TArray<GrpEntry>& usedgroups)
|
||||
{
|
||||
voxInit();
|
||||
|
||||
TexMan.usefullnames = true;
|
||||
TexMan.Init();
|
||||
TexMan.AddTextures([]() {}, [](BuildInfo&) {});
|
||||
StartWindow->Progress();
|
||||
|
||||
TileFiles.Init();
|
||||
TileFiles.LoadArtSet("tiles%03d.art"); // it's the same for all games.
|
||||
voxInit();
|
||||
gi->LoadGameTextures(); // loads game-side data that must be present before processing the .def files.
|
||||
LoadDefinitions();
|
||||
TArray<FString> addArt;
|
||||
for (auto& grp : usedgroups)
|
||||
{
|
||||
for (auto& art : grp.FileInfo.loadart)
|
||||
{
|
||||
addArt.Push(art);
|
||||
}
|
||||
}
|
||||
if (userConfig.AddArt) for (auto& art : *userConfig.AddArt)
|
||||
{
|
||||
addArt.Push(art);
|
||||
}
|
||||
InitArtFiles(addArt);
|
||||
|
||||
ConstructTileset();
|
||||
InitFont(); // InitFonts may only be called once all texture data has been initialized.
|
||||
gi->SetupSpecialTextures(); // For installing dynamic or deleted textures in the texture manager. This must be done after parsing .def and before setting the aliases.
|
||||
TileFiles.SetAliases();
|
||||
//TileFiles.SetAliases();
|
||||
|
||||
lookups.postLoadTables();
|
||||
highTileSetup();
|
||||
|
@ -1074,20 +1087,6 @@ int RunGame()
|
|||
StartWindow = FStartupScreen::CreateInstance(8, true);
|
||||
StartWindow->Progress();
|
||||
|
||||
TArray<FString> addArt;
|
||||
for (auto& grp : usedgroups)
|
||||
{
|
||||
for (auto& art : grp.FileInfo.loadart)
|
||||
{
|
||||
addArt.Push(art);
|
||||
}
|
||||
}
|
||||
if (userConfig.AddArt) for (auto& art : *userConfig.AddArt)
|
||||
{
|
||||
addArt.Push(art);
|
||||
}
|
||||
TileFiles.AddArt(addArt);
|
||||
|
||||
inputState.ClearAllInput();
|
||||
|
||||
if (!GameConfig->IsInitialized())
|
||||
|
@ -1108,7 +1107,7 @@ int RunGame()
|
|||
gi->loadPalette();
|
||||
BuildFogTable();
|
||||
StartWindow->Progress();
|
||||
InitTextures();
|
||||
InitTextures(usedgroups);
|
||||
|
||||
StartWindow->Progress();
|
||||
I_InitSound();
|
||||
|
@ -1419,61 +1418,6 @@ void DrawCrosshair(int deftile, int health, double xdelta, double ydelta, double
|
|||
ST_DrawCrosshair(health, xpos, ypos, 1, angle);
|
||||
}
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void LoadDefinitions()
|
||||
{
|
||||
const char* defsfile = G_DefFile();
|
||||
FString razedefsfile = defsfile;
|
||||
razedefsfile.Substitute(".def", "-raze.def");
|
||||
|
||||
loaddefinitionsfile("engine/engine.def", true, true); // Internal stuff that is required.
|
||||
|
||||
// check what we have.
|
||||
// user .defs override the default ones and are not cumulative.
|
||||
// if we fine even one Raze-specific file, all of those will be loaded cumulatively.
|
||||
// otherwise the default rules inherited from older ports apply.
|
||||
if (userConfig.UserDef.IsNotEmpty())
|
||||
{
|
||||
loaddefinitionsfile(userConfig.UserDef, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fileSystem.FileExists(razedefsfile))
|
||||
{
|
||||
loaddefinitionsfile(razedefsfile, true);
|
||||
}
|
||||
else if (fileSystem.FileExists(defsfile))
|
||||
{
|
||||
loaddefinitionsfile(defsfile, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (userConfig.AddDefs)
|
||||
{
|
||||
for (auto& m : *userConfig.AddDefs)
|
||||
{
|
||||
loaddefinitionsfile(m, false);
|
||||
}
|
||||
userConfig.AddDefs.reset();
|
||||
}
|
||||
|
||||
if (GameStartupInfo.def.IsNotEmpty())
|
||||
{
|
||||
loaddefinitionsfile(GameStartupInfo.def); // Stuff from gameinfo.
|
||||
}
|
||||
|
||||
// load the widescreen replacements last. This ensures that mods still get the correct CRCs for their own tile replacements.
|
||||
if (fileSystem.FindFile("engine/widescreen.def") >= 0 && !Args->CheckParm("-nowidescreen"))
|
||||
{
|
||||
loaddefinitionsfile("engine/widescreen.def");
|
||||
}
|
||||
fileSystem.InitHashChains(); // make sure that any resources that got added can be found again.
|
||||
}
|
||||
|
||||
bool M_Active()
|
||||
{
|
||||
|
|
|
@ -146,9 +146,6 @@ struct GrpEntry
|
|||
GrpInfo FileInfo;
|
||||
};
|
||||
extern int g_gameType;
|
||||
const char* G_DefaultDefFile(void);
|
||||
const char* G_DefFile(void);
|
||||
void LoadDefinitions();
|
||||
|
||||
// game check shortcuts
|
||||
inline bool isNam()
|
||||
|
|
|
@ -27,6 +27,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "interpolate.h"
|
||||
#include "texturemanager.h"
|
||||
#include "hw_voxels.h"
|
||||
#include "texinfo.h"
|
||||
#include "buildtiles.h"
|
||||
|
||||
IntRect viewport3d;
|
||||
constexpr double MAXCLIPDISTF = 64;
|
||||
|
@ -205,7 +207,7 @@ void GetWallSpritePosition(const spritetypebase* spr, const DVector2& pos, DVect
|
|||
auto tex = TexMan.GetGameTexture(spr->spritetexture());
|
||||
|
||||
double width, xoffset;
|
||||
TileOffs* tofs;
|
||||
const TileOffs* tofs;
|
||||
if (render && hw_hightile && (tofs = GetHiresOffset(spr->spritetexture())))
|
||||
{
|
||||
width = tofs->xsize;
|
||||
|
@ -245,7 +247,7 @@ void TGetFlatSpritePosition(const spritetypebase* spr, const DVector2& pos, DVec
|
|||
int xo = heinum ? 0 : spr->xoffset;
|
||||
int yo = heinum ? 0 : spr->yoffset;
|
||||
|
||||
TileOffs* tofs;
|
||||
const TileOffs* tofs;
|
||||
if (render && hw_hightile && (tofs = GetHiresOffset(spr->spritetexture())))
|
||||
{
|
||||
width = tofs->xsize * xrepeat;
|
||||
|
|
|
@ -205,8 +205,6 @@ inline void dragpoint(walltype* startwall, const DVector2& pos)
|
|||
|
||||
extern double cameradist, cameraclock;
|
||||
|
||||
void loaddefinitionsfile(const char* fn, bool cumulative = false, bool maingrp = false);
|
||||
|
||||
bool calcChaseCamPos(DVector3& ppos, DCoreActor* pspr, sectortype** psectnum, const DRotator& angles, double const interpfrac, double const backamp);
|
||||
int getslopeval(sectortype* sect, const DVector3& pos, double bazez);
|
||||
bool cansee(const DVector3& start, sectortype* sect1, const DVector3& end, sectortype* sect2);
|
||||
|
|
|
@ -46,6 +46,10 @@
|
|||
#include "v_font.h"
|
||||
#include "gamestruct.h"
|
||||
#include "gamefuncs.h"
|
||||
#include "texinfo.h"
|
||||
|
||||
#include "buildtiles.h"
|
||||
|
||||
|
||||
F2DDrawer twodpsp;
|
||||
|
||||
|
@ -56,9 +60,7 @@ void hud_drawsprite(double sx, double sy, double sz, double a, int picnum, int d
|
|||
alpha *= (dastat & RS_TRANS1)? glblend[0].def[!!(dastat & RS_TRANS2)].alpha : 1.;
|
||||
int palid = TRANSLATION(Translation_Remap + curbasepal, dapalnum);
|
||||
|
||||
tileUpdatePicnum(&picnum);
|
||||
|
||||
auto tex = tileGetTexture(picnum);
|
||||
auto tex = tileGetTexture(picnum, true);
|
||||
|
||||
DrawTexture(&twodpsp, tex, sx, sy,
|
||||
DTA_ScaleX, sz, DTA_ScaleY, sz,
|
||||
|
|
|
@ -49,6 +49,7 @@ struct ReservedSpace
|
|||
|
||||
enum EMenuSounds : int;
|
||||
struct MapRecord;
|
||||
struct TilesetBuildInfo;
|
||||
|
||||
extern cycle_t drawtime, actortime, thinktime, gameupdatetime;
|
||||
|
||||
|
@ -71,8 +72,8 @@ struct GameInterface
|
|||
virtual ~GameInterface() {}
|
||||
virtual bool GenerateSavePic() { return false; }
|
||||
virtual void app_init() = 0;
|
||||
virtual void LoadGameTextures() {}
|
||||
virtual void SetupSpecialTextures() {}
|
||||
virtual void LoadTextureInfo(TilesetBuildInfo& info) {}
|
||||
virtual void SetupSpecialTextures(TilesetBuildInfo&) {}
|
||||
virtual void loadPalette();
|
||||
virtual void clearlocalinputstate() {}
|
||||
virtual void UpdateScreenSize() {}
|
||||
|
|
|
@ -89,6 +89,7 @@
|
|||
#include "gamehud.h"
|
||||
#include "wipe.h"
|
||||
#include "i_interface.h"
|
||||
#include "texinfo.h"
|
||||
#include "texturemanager.h"
|
||||
|
||||
CVAR(Bool, vid_activeinbackground, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "render.h"
|
||||
#include "hw_sections.h"
|
||||
#include "interpolate.h"
|
||||
#include "tiletexture.h"
|
||||
#include "games/blood/src/mapstructs.h"
|
||||
|
||||
extern BitArray clipsectormap;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "texturemanager.h"
|
||||
#include "hw_voxels.h"
|
||||
#include "gamefuncs.h"
|
||||
#include "tiletexture.h"
|
||||
|
||||
#include "build.h"
|
||||
|
||||
|
|
|
@ -45,6 +45,9 @@
|
|||
#include "mapinfo.h"
|
||||
#include "models/modeldata.h"
|
||||
#include "gamefuncs.h"
|
||||
#include "texinfo.h"
|
||||
|
||||
#include "buildtiles.h"
|
||||
|
||||
BEGIN_BLD_NS
|
||||
extern short voxelIndex[MAXTILES];
|
||||
|
|
|
@ -34,9 +34,10 @@
|
|||
*/
|
||||
|
||||
#include "psky.h"
|
||||
#include "buildtiles.h"
|
||||
#include "gamefuncs.h"
|
||||
#include "tarray.h"
|
||||
#include "texinfo.h"
|
||||
#include "buildtiles.h"
|
||||
|
||||
|
||||
static TArray<SkyDefinition> skies;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "build.h"
|
||||
#include "voxels.h"
|
||||
#include "hw_voxels.h"
|
||||
#include "tiletexture.h"
|
||||
#include "gamecontrol.h"
|
||||
|
||||
int16_t tiletovox[MAXTILES];
|
||||
|
|
|
@ -43,6 +43,9 @@
|
|||
#include "automap.h"
|
||||
#include "hw_voxels.h"
|
||||
#include "coreactor.h"
|
||||
#include "tiletexture.h"
|
||||
|
||||
#include "buildtiles.h"
|
||||
|
||||
EXTERN_CVAR(Float, r_visibility)
|
||||
CVAR(Bool, gl_no_skyclear, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
@ -275,23 +278,26 @@ void HWDrawInfo::DispatchSprites()
|
|||
for (unsigned i = 0; i < tsprites.Size(); i++)
|
||||
{
|
||||
auto tspr = tsprites.get(i);
|
||||
int tilenum = tspr->picnum;
|
||||
auto actor = tspr->ownerActor;
|
||||
auto texid = tspr->spritetexture();
|
||||
|
||||
if (actor == nullptr || tspr->scale.X == 0 || tspr->scale.Y == 0 || (unsigned)tilenum >= MAXTILES)
|
||||
if (actor == nullptr || tspr->scale.X == 0 || tspr->scale.Y == 0)
|
||||
continue;
|
||||
|
||||
actor->spr.cstat2 |= CSTAT2_SPRITE_MAPPED;
|
||||
|
||||
if ((tspr->cstat & CSTAT_SPRITE_ALIGNMENT_MASK) != CSTAT_SPRITE_ALIGNMENT_SLAB && !(tspr->cstat2 & CSTAT2_SPRITE_NOANIMATE))
|
||||
tileUpdatePicnum(&tilenum, false, (actor->GetIndex() & 16383));
|
||||
{
|
||||
tileUpdatePicnum(texid, (actor->GetIndex() & 16383));
|
||||
}
|
||||
if (tspr->cstat2 & CSTAT2_SPRITE_FULLBRIGHT)
|
||||
tspr->shade = -127;
|
||||
tspr->picnum = tilenum;
|
||||
tspr->picnum = legacyTileNum(texid);
|
||||
int tilenum = tspr->picnum;
|
||||
|
||||
if (!(actor->sprext.renderflags & SPREXT_NOTMD))
|
||||
{
|
||||
auto pt = modelManager.GetModel(tilenum, tspr->pal);
|
||||
auto pt = modelManager.GetModel(tspr->picnum, tspr->pal);
|
||||
if (hw_models && pt && pt->modelid >= 0 && pt->framenum >= 0)
|
||||
{
|
||||
//HWSprite hwsprite;
|
||||
|
@ -315,6 +321,7 @@ void HWDrawInfo::DispatchSprites()
|
|||
}
|
||||
}
|
||||
}
|
||||
if (!texid.isValid()) return; // due to CSTAT_SPRITE_ALIGNMENT_SLAB this can only be checked here
|
||||
|
||||
if (actor->sprext.renderflags & SPREXT_AWAY1)
|
||||
{
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "sectorgeometry.h"
|
||||
#include "hw_sections.h"
|
||||
#include "texturemanager.h"
|
||||
#include "buildtiles.h"
|
||||
|
||||
#ifdef _DEBUG
|
||||
CVAR(Int, gl_breaksec, -1, 0)
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#include "cmdlib.h"
|
||||
#include "psky.h"
|
||||
|
||||
#include "buildtiles.h"
|
||||
|
||||
CVAR(Bool,gl_noskyboxes, false, 0)
|
||||
FGameTexture* GetSkyTexture(int basetile, int lognumtiles, const int16_t* tilemap, int remap);
|
||||
FGameTexture* SkyboxReplacement(FTextureID picnum, int palnum);
|
||||
|
@ -45,7 +47,7 @@ void initSkyInfo(HWDrawInfo *di, HWSkyInfo* sky, sectortype* sector, int plane)
|
|||
{
|
||||
int picnum = plane == plane_ceiling ? sector->ceilingpicnum : sector->floorpicnum;
|
||||
auto tex = tileGetTexture(picnum);
|
||||
tileUpdatePicnum(&picnum);
|
||||
//tileUpdatePicnum(&picnum); // for now we can make do without this.
|
||||
int palette = plane == plane_ceiling ? sector->ceilingpal : sector->floorpal;
|
||||
|
||||
FGameTexture* skytex = SkyboxReplacement(tex->GetID(), palette);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "vectors.h"
|
||||
#include "texturemanager.h"
|
||||
#include "basics.h"
|
||||
#include "texinfo.h"
|
||||
|
||||
//#include "hw_models.h"
|
||||
#include "hw_drawstructs.h"
|
||||
|
@ -45,6 +46,7 @@
|
|||
#include "hw_models.h"
|
||||
#include "hw_viewpointbuffer.h"
|
||||
#include "hw_voxels.h"
|
||||
#include "buildtiles.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -345,7 +347,7 @@ void HWSprite::Process(HWDrawInfo* di, tspritetype* spr, sectortype* sector, int
|
|||
int flags = spr->cstat;
|
||||
|
||||
int xsize, ysize, tilexoff, tileyoff;
|
||||
TileOffs* tofs;
|
||||
const TileOffs* tofs;
|
||||
|
||||
if (hw_hightile && (tofs = GetHiresOffset(spr->spritetexture())))
|
||||
{
|
||||
|
|
|
@ -33,8 +33,10 @@
|
|||
#include "hw_skydome.h"
|
||||
#include "hw_drawstructs.h"
|
||||
#include "hw_vertexmap.h"
|
||||
#include "buildtiles.h"
|
||||
#include "gamefuncs.h"
|
||||
#include "cmdlib.h"
|
||||
#include "texinfo.h"
|
||||
|
||||
#include "v_video.h"
|
||||
#include "flatvertices.h"
|
||||
|
@ -1163,7 +1165,7 @@ void HWWall::ProcessWallSprite(HWDrawInfo* di, tspritetype* spr, sectortype* sec
|
|||
|
||||
SetSpriteTranslucency(Sprite, alpha, RenderStyle);
|
||||
|
||||
TileOffs* tofs;
|
||||
const TileOffs* tofs;
|
||||
int height, topofs;
|
||||
if (hw_hightile && (tofs = GetHiresOffset(spr->spritetexture())))
|
||||
{
|
||||
|
|
|
@ -63,8 +63,12 @@
|
|||
#include "ns.h"
|
||||
#include "serialize_obj.h"
|
||||
#include "games/blood/src/mapstructs.h"
|
||||
#include "texinfo.h"
|
||||
#include <zlib.h>
|
||||
|
||||
#include "buildtiles.h"
|
||||
|
||||
|
||||
|
||||
void WriteSavePic(FileWriter* file, int width, int height);
|
||||
bool WriteZip(const char* filename, TArray<FString>& filenames, TArray<FCompressedBuffer>& content);
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#include "sectorgeometry.h"
|
||||
#include "build.h"
|
||||
#include "buildtiles.h"
|
||||
#include "gamefuncs.h"
|
||||
#include "texturemanager.h"
|
||||
#include "earcut.hpp"
|
||||
|
|
|
@ -1,820 +0,0 @@
|
|||
/*
|
||||
** buildtexture.cpp
|
||||
** Handling Build textures
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2019 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 "files.h"
|
||||
#include "zstring.h"
|
||||
#include "buildtiles.h"
|
||||
#include "image.h"
|
||||
|
||||
#include "palette.h"
|
||||
#include "m_crc32.h"
|
||||
#include "build.h"
|
||||
#include "gamecontrol.h"
|
||||
#include "gamefuncs.h"
|
||||
#include "palettecontainer.h"
|
||||
#include "texturemanager.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "sc_man.h"
|
||||
#include "gamestruct.h"
|
||||
#include "hw_voxels.h"
|
||||
#include "models/modeldata.h"
|
||||
|
||||
#include "hw_renderstate.h"
|
||||
|
||||
enum
|
||||
{
|
||||
MAXARTFILES_BASE = 200,
|
||||
MAXARTFILES_TOTAL = 220
|
||||
};
|
||||
|
||||
|
||||
BuildTiles TileFiles;
|
||||
|
||||
int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor, bool indexed = false);
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
picanm_t tileConvertAnimFormat(int32_t const picanimraw, int* lo, int* to)
|
||||
{
|
||||
// Unpack a 4 byte packed anim descriptor into something more accessible
|
||||
picanm_t anm;
|
||||
anm.num = picanimraw & 63;
|
||||
*lo = (int8_t)((picanimraw >> 8) & 255);
|
||||
*to = (int8_t)((picanimraw >> 16) & 255);
|
||||
anm.sf = ((picanimraw >> 24) & 15) | (picanimraw & 192);
|
||||
anm.extra = (picanimraw >> 28) & 15;
|
||||
return anm;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Base class for Build tile textures
|
||||
// This needs a few subclasses for different use cases.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FTileTexture::CopyPixels(FBitmap* bmp, int conversion)
|
||||
{
|
||||
TArray<uint8_t> buffer;
|
||||
auto ppix = GetRawData();
|
||||
if (ppix)
|
||||
{
|
||||
bmp->CopyPixelData(0, 0, ppix, Width, Height, Height, 1, 0, GPalette.BaseColors);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
TArray<uint8_t> FTileTexture::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
TArray<uint8_t> buffer(Width * Height, true);
|
||||
auto p = GetRawData();
|
||||
if (p) memcpy(buffer.Data(), p, buffer.Size());
|
||||
else memset(buffer.Data(), 0, buffer.Size());
|
||||
return buffer;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// raw pixel cache. This is for accessing pixel data in the game code,
|
||||
// not for rendering.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
struct RawCacheNode
|
||||
{
|
||||
TArray<uint8_t> data;
|
||||
uint64_t lastUseTime;
|
||||
|
||||
RawCacheNode() = default;
|
||||
RawCacheNode(RawCacheNode& other) = default;
|
||||
RawCacheNode& operator=(RawCacheNode& other) = default;
|
||||
|
||||
RawCacheNode(RawCacheNode&& other) noexcept
|
||||
{
|
||||
data = std::move(other.data);
|
||||
lastUseTime = other.lastUseTime;
|
||||
}
|
||||
|
||||
RawCacheNode& operator=(RawCacheNode&& other) noexcept
|
||||
{
|
||||
data = std::move(other.data);
|
||||
lastUseTime = other.lastUseTime;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
static TMap<int, RawCacheNode> CacheNodes;
|
||||
|
||||
const uint8_t* GetRawPixels(FTextureID texid)
|
||||
{
|
||||
if (!texid.isValid()) return nullptr;
|
||||
auto gtex = TexMan.GetGameTexture(texid);
|
||||
auto tex = dynamic_cast<FImageTexture*>(gtex->GetTexture());
|
||||
|
||||
if (!tex || !tex->GetImage()) return nullptr;
|
||||
auto img = tex->GetImage();
|
||||
auto timg = dynamic_cast<FTileTexture*>(img);
|
||||
if (!timg || !timg->GetRawData())
|
||||
{
|
||||
auto cache = CacheNodes.CheckKey(texid.GetIndex());
|
||||
if (cache)
|
||||
{
|
||||
cache->lastUseTime = I_nsTime();
|
||||
return cache->data.Data();
|
||||
}
|
||||
RawCacheNode newnode;
|
||||
newnode.data = img->GetPalettedPixels(0);
|
||||
newnode.lastUseTime = I_nsTime();
|
||||
auto retval =newnode.data.Data();
|
||||
CacheNodes.Insert(texid.GetIndex(), std::move(newnode));
|
||||
return retval;
|
||||
}
|
||||
else
|
||||
{
|
||||
return timg->GetRawData();
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//To use this the texture must have been made writable during texture init.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
uint8_t* GetWritablePixels(FTextureID texid)
|
||||
{
|
||||
if (!texid.isValid()) return nullptr;
|
||||
auto gtex = TexMan.GetGameTexture(texid);
|
||||
auto tex = dynamic_cast<FImageTexture*>(gtex->GetTexture());
|
||||
|
||||
if (!tex || !tex->GetImage()) return nullptr;
|
||||
auto timg = dynamic_cast<FWritableTile*>(tex->GetImage());
|
||||
if (!timg) return nullptr;
|
||||
gtex->CleanHardwareData(); // we can safely assume that this only gets called when the texture is about to be changed.
|
||||
return timg->GetRawData();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FGameTexture* GetTileTexture(const char* name, const TArray<uint8_t>& backingstore, uint32_t offset, int width, int height)
|
||||
{
|
||||
auto tex = new FArtTile(backingstore, offset, width, height);
|
||||
auto p = &backingstore[offset];
|
||||
auto siz = width * height;
|
||||
for (int i = 0; i < siz; i++, p++)
|
||||
{
|
||||
// move transparent color to index 0 to get in line with the rest of the texture management.
|
||||
if (*p == 0) *p = 255;
|
||||
else if (*p == 255) *p = 0;
|
||||
}
|
||||
|
||||
if (tex)
|
||||
{
|
||||
return MakeGameTexture(new FImageTexture(tex), name, ETextureType::Any);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void BuildTiles::Init()
|
||||
{
|
||||
Placeholder = TexMan.GameByIndex(0);
|
||||
tiledata.Resize(MAXTILES);
|
||||
memset(tiledata.Data(), 0, sizeof(tiledata[0]) * MAXTILES);
|
||||
for (auto& tile : tiledata)
|
||||
{
|
||||
tile.texture = Placeholder;
|
||||
tile.alphaThreshold = 0.5;
|
||||
}
|
||||
|
||||
}
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void BuildTiles::AddTile(int tilenum, FGameTexture* tex)
|
||||
{
|
||||
if (!tex->GetID().isValid())
|
||||
TexMan.AddGameTexture(tex);
|
||||
tiledata[tilenum].texture = tex;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// AddTiles
|
||||
//
|
||||
// Adds all the tiles in an artfile to the texture manager.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void BuildTiles::AddTiles (int firsttile, TArray<uint8_t>& RawData, const char *mapname)
|
||||
{
|
||||
|
||||
const uint8_t *tiles = RawData.Data();
|
||||
// int numtiles = LittleLong(((uint32_t *)tiles)[1]); // This value is not reliable
|
||||
int tilestart = LittleLong(((int *)tiles)[2]);
|
||||
int tileend = LittleLong(((int *)tiles)[3]);
|
||||
const uint16_t *tilesizx = &((const uint16_t *)tiles)[8];
|
||||
const uint16_t *tilesizy = &tilesizx[tileend - tilestart + 1];
|
||||
const uint32_t *picanm = (const uint32_t *)&tilesizy[tileend - tilestart + 1];
|
||||
const uint8_t *tiledata = (const uint8_t *)&picanm[tileend - tilestart + 1];
|
||||
|
||||
if (firsttile != -1)
|
||||
{
|
||||
tileend = tileend - tilestart + firsttile;
|
||||
tilestart = firsttile;
|
||||
}
|
||||
|
||||
for (int i = tilestart; i <= tileend; ++i)
|
||||
{
|
||||
int pic = i - tilestart;
|
||||
int width = LittleShort(tilesizx[pic]);
|
||||
int height = LittleShort(tilesizy[pic]);
|
||||
uint32_t anm = LittleLong(picanm[pic]);
|
||||
int size = width*height;
|
||||
|
||||
if (width <= 0 || height <= 0) continue;
|
||||
|
||||
FString texname;
|
||||
if (mapname) texname.Format("maptile_%s_%05d", mapname, i);
|
||||
else texname.Format("#%05d", i);
|
||||
auto tex = GetTileTexture(texname, RawData, uint32_t(tiledata - tiles), width, height);
|
||||
AddTile(i, tex);
|
||||
int leftoffset, topoffset;
|
||||
this->tiledata[i].picanm = tileConvertAnimFormat(anm, &leftoffset, &topoffset);
|
||||
tex->SetOffsets(leftoffset, topoffset);
|
||||
|
||||
tiledata += size;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// CountTiles
|
||||
//
|
||||
// Returns the number of tiles provided by an artfile
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
int CountTiles (const char *fn, const uint8_t *RawData)
|
||||
{
|
||||
int version = LittleLong(*(uint32_t *)RawData);
|
||||
if (version != 1)
|
||||
{
|
||||
Printf("%s: Invalid art file version. Must be 1, got %d\n", fn, version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tilestart = LittleLong(((uint32_t *)RawData)[2]);
|
||||
int tileend = LittleLong(((uint32_t *)RawData)[3]);
|
||||
|
||||
if ((unsigned)tilestart >= MAXUSERTILES || (unsigned)tileend >= MAXUSERTILES)
|
||||
{
|
||||
Printf("%s: Invalid tilestart or tileend\n", fn);
|
||||
return 0;
|
||||
}
|
||||
if (tileend < tilestart)
|
||||
{
|
||||
Printf("%s: tileend < tilestart\n", fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return tileend >= tilestart ? tileend - tilestart + 1 : 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// MakeCanvas
|
||||
//
|
||||
// Turns texture into a canvas (i.e. camera texture)
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void BuildTiles::MakeCanvas(int tilenum, int width, int height)
|
||||
{
|
||||
auto canvas = ValidateCustomTile(tilenum, ReplacementType::Canvas);
|
||||
canvas->SetSize(width*4, height*4);
|
||||
canvas->SetDisplaySize((float)width, (float)height);
|
||||
canvas->GetTexture()->SetSize(width * 4, height * 4);
|
||||
static_cast<FCanvasTexture*>(canvas->GetTexture())->aspectRatio = (float)width / height;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// LoadArtFile
|
||||
//
|
||||
// Returns the number of tiles found.
|
||||
//
|
||||
// let's load everything into memory on startup.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
int BuildTiles::LoadArtFile(const char *fn, const char *mapname, int firsttile)
|
||||
{
|
||||
unsigned old = FindFile(fn);
|
||||
if (old >= ArtFiles.Size()) // Do not process if already loaded.
|
||||
{
|
||||
FileReader fr = fileSystem.OpenFileReader(fn);
|
||||
if (fr.isOpen())
|
||||
{
|
||||
auto artdata = fr.Read();
|
||||
const uint8_t *artptr = artdata.Data();
|
||||
if (artdata.Size() > 16)
|
||||
{
|
||||
if (memcmp(artptr, "BUILDART", 8) == 0)
|
||||
{
|
||||
artdata.Delete(0, 8);
|
||||
}
|
||||
// Only load the data if the header is present
|
||||
if (CountTiles(fn, artptr) > 0)
|
||||
{
|
||||
auto file = new BuildArtFile;
|
||||
ArtFiles.Push(file);
|
||||
file->filename = fn;
|
||||
file->RawData = std::move(artdata);
|
||||
AddTiles(firsttile, file->RawData, mapname);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Printf("%s: file not found\n", fn);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void BuildTiles::LoadArtSet(const char* filename)
|
||||
{
|
||||
for (int index = 0; index < MAXARTFILES_BASE; index++)
|
||||
{
|
||||
FStringf fn(filename, index);
|
||||
LoadArtFile(fn, nullptr);
|
||||
}
|
||||
for (auto& addart : addedArt)
|
||||
{
|
||||
LoadArtFile(addart, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void BuildTiles::SetAliases()
|
||||
{
|
||||
TMap<FName, int>::Iterator it(nametoindex);
|
||||
TMap<FName, int>::Pair* pair;
|
||||
while (it.NextPair(pair))
|
||||
TexMan.AddAlias(pair->Key.GetChars(), tileGetTexture(pair->Value));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Checks if a custom tile has alredy been added to the list.
|
||||
// For each tile index there may only be one replacement and its
|
||||
// type may never change!
|
||||
//
|
||||
// All these uses will need some review further down the line so that the texture manager's content is immutable.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FGameTexture* BuildTiles::ValidateCustomTile(int tilenum, ReplacementType type)
|
||||
{
|
||||
if (locked) I_FatalError("Modifying tiles after startup is not allowed.");
|
||||
if (tilenum < 0 || tilenum >= MAXTILES) return nullptr;
|
||||
auto &td = tiledata[tilenum];
|
||||
auto tile = td.texture;
|
||||
auto reptype = td.replacement;
|
||||
if (reptype == type) return tile; // already created
|
||||
if (reptype > ReplacementType::Art) return nullptr; // different custom type - cannot replace again.
|
||||
FTexture* replacement = nullptr;
|
||||
td.replacement = type;
|
||||
if (type == ReplacementType::Writable)
|
||||
{
|
||||
// Creates an empty writable tile.
|
||||
// Current use cases are:
|
||||
// Blood's 'lens' effect (apparently MP only) - combination of a camera texture with a distortion map - should be made a shader effect to be applied to the camera texture.
|
||||
replacement = new FImageTexture(new FWritableTile);
|
||||
}
|
||||
else if (type == ReplacementType::Restorable)
|
||||
{
|
||||
// This is for modifying an existing tile.
|
||||
// It only gets used for a few specific effects:
|
||||
// A) the fire in Blood.
|
||||
// B) the pin display in Redneck Rampage's bowling lanes.
|
||||
// C) Exhumed's menu plus one special effect tile.
|
||||
if (tile->GetTexelWidth() == 0 || tile->GetTexelHeight() == 0) return nullptr; // The base must have a size for this to work.
|
||||
replacement = new FImageTexture(new FRestorableTile(tile->GetTexture()->GetImage()));
|
||||
}
|
||||
else if (type == ReplacementType::Canvas)
|
||||
{
|
||||
replacement = new FCanvasTexture(1, 1);
|
||||
}
|
||||
else return nullptr;
|
||||
auto rep = MakeGameTexture(replacement, tile->GetName(), ETextureType::Override);
|
||||
AddTile(tilenum, rep);
|
||||
return rep;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Creates a tile for displaying custom content
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
uint8_t* BuildTiles::tileCreate(int tilenum, int width, int height)
|
||||
{
|
||||
if (width <= 0 || height <= 0) return nullptr;
|
||||
auto tex = ValidateCustomTile(tilenum, ReplacementType::Writable);
|
||||
if (tex == nullptr) return nullptr;
|
||||
auto wtex = static_cast<FWritableTile*>(tex->GetTexture()->GetImage());
|
||||
if (!wtex->ResizeImage(width, height)) return nullptr;
|
||||
tex->SetSize(width, height);
|
||||
return wtex->GetRawData();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Makes a tile writable - only used for a handful of special cases
|
||||
// (todo: Investigate how to get rid of this)
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
uint8_t* BuildTiles::tileMakeWritable(int num)
|
||||
{
|
||||
auto tex = ValidateCustomTile(num, ReplacementType::Restorable);
|
||||
auto wtex = static_cast<FWritableTile*>(tex->GetTexture()->GetImage());
|
||||
return wtex ? wtex->GetRawData() : nullptr;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Returns checksum for a given tile
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int32_t tileGetCRC32(int tileNum)
|
||||
{
|
||||
if ((unsigned)tileNum >= (unsigned)MAXTILES) return 0;
|
||||
auto tile = dynamic_cast<FArtTile*>(TileFiles.tiledata[tileNum].texture->GetTexture()->GetImage()); // only consider original ART tiles.
|
||||
if (!tile) return 0;
|
||||
auto pixels = tile->GetRawData();
|
||||
if (!pixels) return 0;
|
||||
|
||||
auto size = tile->GetWidth() * tile->GetHeight();
|
||||
if (size == 0) return 0;
|
||||
|
||||
// Temporarily revert the data to its original form with 255 being transparent. Otherwise the CRC won't match.
|
||||
auto p = pixels;
|
||||
for (int i = 0; i < size; i++, p++)
|
||||
{
|
||||
// move transparent color to index 0 to get in line with the rest of the texture management.
|
||||
if (*p == 0) *p = 255;
|
||||
else if (*p == 255) *p = 0;
|
||||
}
|
||||
|
||||
auto crc = crc32(0, (const Bytef*)pixels, size);
|
||||
|
||||
// ... and back again.
|
||||
p = pixels;
|
||||
for (int i = 0; i < size; i++, p++)
|
||||
{
|
||||
// move transparent color to index 0 to get in line with the rest of the texture management.
|
||||
if (*p == 0) *p = 255;
|
||||
else if (*p == 255) *p = 0;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
|
||||
CCMD(tilecrc)
|
||||
{
|
||||
if (argv.argc() > 1)
|
||||
{
|
||||
int tile = atoi(argv[1]);
|
||||
Printf("%d\n", tileGetCRC32(tile));
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Import a tile from an external image.
|
||||
// This has been signifcantly altered so it may not cover everything yet.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int tileImportFromTexture(const char* fn, int tilenum, int alphacut, int istexture)
|
||||
{
|
||||
FTextureID texid = TexMan.CheckForTexture(fn, ETextureType::Any, FTextureManager::TEXMAN_ForceLookup);
|
||||
if (!texid.isValid()) return -1;
|
||||
auto tex = TexMan.GetGameTexture(texid);
|
||||
|
||||
int32_t xsiz = tex->GetTexelWidth(), ysiz = tex->GetTexelHeight();
|
||||
|
||||
if (xsiz <= 0 || ysiz <= 0)
|
||||
return -2;
|
||||
|
||||
// create a new game texture here - we want to give it a different name!
|
||||
tex = MakeGameTexture(tex->GetTexture(), FStringf("#%05d", tilenum), ETextureType::Override);
|
||||
TileFiles.AddTile(tilenum, tex);
|
||||
if (istexture)
|
||||
tileSetHightileReplacement(tilenum, 0, fn, (float)(255 - alphacut) * (1.f / 255.f), 1.0f, 1.0f, 1.0, 1.0);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Copies a tile into another and optionally translates its palette.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void tileCopy(int tile, int source, int pal, int xoffset, int yoffset, int flags)
|
||||
{
|
||||
picanm_t* picanm = nullptr;
|
||||
picanm_t* sourceanm = nullptr;
|
||||
int srcxo, srcyo;
|
||||
FGameTexture* tex;
|
||||
|
||||
if (pal == -1 && tile == source)
|
||||
{
|
||||
// Only modify the picanm info.
|
||||
tex = tileGetTexture(tile);
|
||||
if (!tex) return;
|
||||
picanm = &TileFiles.tiledata[tile].picanm;
|
||||
sourceanm = picanm;
|
||||
srcxo = tex->GetTexelLeftOffset(0);
|
||||
srcyo = tex->GetTexelTopOffset(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (source == -1) source = tile;
|
||||
tex = tileGetTexture(source);
|
||||
if (!tex) return;
|
||||
sourceanm = &TileFiles.tiledata[source].picanm;
|
||||
srcxo = tex->GetTexelLeftOffset(0);
|
||||
srcyo = tex->GetTexelTopOffset(0);
|
||||
|
||||
TArray<uint8_t> buffer = tex->GetTexture()->Get8BitPixels(false);
|
||||
|
||||
if (pal != -1)
|
||||
{
|
||||
auto remap = lookups.getTable(pal);
|
||||
for (auto& pixel : buffer)
|
||||
{
|
||||
pixel = remap[pixel];
|
||||
}
|
||||
}
|
||||
tex = MakeGameTexture(new FImageTexture(new FLooseTile(buffer, tex->GetTexelWidth(), tex->GetTexelHeight())), FStringf("#%05d", tile), ETextureType::Any);
|
||||
picanm = &TileFiles.tiledata[tile].picanm;
|
||||
TileFiles.AddTile(tile, tex);
|
||||
}
|
||||
|
||||
if (xoffset != -1024) srcxo = clamp(xoffset, -128, 127);
|
||||
if (yoffset != -1024) srcyo = clamp(yoffset, -128, 127);
|
||||
tex->SetOffsets(srcxo, srcyo);
|
||||
picanm->sf = (picanm->sf & ~PICANM_MISC_MASK) | (sourceanm->sf & PICANM_MISC_MASK) | flags;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
FImageSource* CreateEmptyTexture();
|
||||
|
||||
void tileDelete(int tile)
|
||||
{
|
||||
if (TileFiles.locked)
|
||||
I_FatalError("Modifying tiles after startup is not allowed.");
|
||||
|
||||
// explicitly deleted textures must be unique null textures
|
||||
auto nulltex = MakeGameTexture(new FImageTexture(CreateEmptyTexture()), FStringf("#%05d", tile), ETextureType::Null);
|
||||
TileFiles.AddTile(tile, nulltex);
|
||||
TileFiles.tiledata[tile].replacement = ReplacementType::Art; // whatever this was, now it isn't anymore.
|
||||
tiletovox[tile] = -1; // clear the link but don't clear the voxel. It may be in use for another tile.
|
||||
modelManager.UndefineTile(tile);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void tileSetDummy(int tile, int width, int height)
|
||||
{
|
||||
if (width == 0 || height == 0)
|
||||
{
|
||||
tileDelete(tile);
|
||||
}
|
||||
else if (width > 0 && height > 0)
|
||||
{
|
||||
FStringf texname("#%05d", tile);
|
||||
auto dtile = MakeGameTexture(new FImageTexture(new FDummyTile(width, height)), texname, ETextureType::Any);
|
||||
TileFiles.AddTile(tile, dtile);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void BuildTiles::CloseAll()
|
||||
{
|
||||
ArtFiles.DeleteAndClear();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Retrieve animation offset
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int tileAnimateOfs(int tilenum, int randomize)
|
||||
{
|
||||
int framecount = picanm[tilenum].num;
|
||||
if (framecount > 0)
|
||||
{
|
||||
int frametime = !isBlood() ? I_GetBuildTime() : PlayClock;
|
||||
|
||||
if (isBlood() && randomize)
|
||||
{
|
||||
frametime += Bcrc32(&randomize, 2, 0);
|
||||
}
|
||||
|
||||
int curframe = (frametime & 0x7fffffff) >> (picanm[tilenum].speed());
|
||||
|
||||
switch (picanm[tilenum].type())
|
||||
{
|
||||
case PICANM_ANIMTYPE_FWD:
|
||||
return curframe % (framecount + 1);
|
||||
case PICANM_ANIMTYPE_BACK:
|
||||
return -(curframe % (framecount + 1));
|
||||
case PICANM_ANIMTYPE_OSC:
|
||||
curframe = curframe % (framecount << 1);
|
||||
if (curframe >= framecount) return (framecount << 1) - curframe;
|
||||
else return curframe;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Picks a texture for rendering for a given tilenum/palette combination
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void tileUpdateAnimations()
|
||||
{
|
||||
for (int i = 0; i < MAXTILES; i++)
|
||||
{
|
||||
if (TileFiles.tiledata[i].picanm.type())
|
||||
{
|
||||
int j = i + tileAnimateOfs(i);
|
||||
|
||||
auto id1 = TileFiles.tiledata[i].texture->GetID();
|
||||
auto id2 = TileFiles.tiledata[j].texture->GetID();
|
||||
TexMan.SetTranslation(id1, id2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// validates the texture for rendering to a given tilenum
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
FCanvasTexture* tileGetCanvas(int tilenum)
|
||||
{
|
||||
auto tex = tileGetTexture(tilenum);
|
||||
if (!tex || !tex->isHardwareCanvas()) return nullptr;
|
||||
auto canvas = static_cast<FCanvasTexture*>(tex->GetTexture());
|
||||
if (!canvas) return nullptr;
|
||||
int xsiz = tex->GetTexelWidth(), ysiz = tex->GetTexelHeight();
|
||||
if (xsiz <= 0 || ysiz <= 0)
|
||||
return nullptr;
|
||||
return canvas;
|
||||
}
|
||||
|
||||
PicAnm picanm;
|
||||
|
||||
|
||||
// wrappers that allow partial migration to a textureID-based setup.
|
||||
const FTextureID walltype::walltexture() const
|
||||
{
|
||||
return tileGetTextureID(wallpicnum);
|
||||
}
|
||||
const FTextureID walltype::overtexture() const
|
||||
{
|
||||
return tileGetTextureID(overpicnum);
|
||||
}
|
||||
|
||||
const FTextureID sectortype::ceilingtexture() const
|
||||
{
|
||||
return tileGetTextureID(ceilingpicnum);
|
||||
}
|
||||
|
||||
const FTextureID sectortype::floortexture() const
|
||||
{
|
||||
return tileGetTextureID(floorpicnum);
|
||||
}
|
||||
|
||||
const FTextureID spritetypebase::spritetexture() const
|
||||
{
|
||||
return tileGetTextureID(picnum);
|
||||
}
|
||||
|
||||
void sectortype::setfloortexture(FTextureID tex)
|
||||
{
|
||||
auto p = TileFiles.textotile.CheckKey(tex.GetIndex());
|
||||
if (p) floorpicnum = *p;
|
||||
}
|
||||
|
||||
void sectortype::setceilingtexture(FTextureID tex)
|
||||
{
|
||||
auto p = TileFiles.textotile.CheckKey(tex.GetIndex());
|
||||
if (p) ceilingpicnum = *p;
|
||||
}
|
||||
|
||||
void walltype::setwalltexture(FTextureID tex)
|
||||
{
|
||||
auto p = TileFiles.textotile.CheckKey(tex.GetIndex());
|
||||
if (p) wallpicnum = *p;
|
||||
}
|
||||
|
||||
void walltype::setovertexture(FTextureID tex)
|
||||
{
|
||||
auto p = TileFiles.textotile.CheckKey(tex.GetIndex());
|
||||
if (p) overpicnum = *p;
|
||||
else overpicnum = -1; // unlike the others this one can be invalid.
|
||||
}
|
||||
|
||||
TileOffs* GetHiresOffset(FTextureID tex)
|
||||
{
|
||||
// fixme: This must return nullptr if the tile has no replacement.
|
||||
auto p = TileFiles.textotile.CheckKey(tex.GetIndex());
|
||||
if (p && TileFiles.tiledata[*p].hiofs.xsize != 0) return &TileFiles.tiledata[*p].hiofs;
|
||||
else return nullptr;
|
||||
}
|
|
@ -6,432 +6,102 @@
|
|||
#include "i_time.h"
|
||||
#include "intvec.h"
|
||||
#include "name.h"
|
||||
#include "tiletexture.h"
|
||||
#include "maptypes.h"
|
||||
#include "texinfo.h"
|
||||
#include "texturemanager.h"
|
||||
|
||||
enum AnimFlags
|
||||
// all that's left here is the wrappers that need to go away.
|
||||
|
||||
|
||||
// wrappers that allow partial migration to a textureID-based setup.
|
||||
inline const FTextureID walltype::walltexture() const
|
||||
{
|
||||
PICANM_ANIMTYPE_NONE = 0,
|
||||
PICANM_ANIMTYPE_OSC = (1 << 6),
|
||||
PICANM_ANIMTYPE_FWD = (2 << 6),
|
||||
PICANM_ANIMTYPE_BACK = (3 << 6),
|
||||
|
||||
PICANM_ANIMTYPE_SHIFT = 6,
|
||||
PICANM_ANIMTYPE_MASK = (3 << 6), // must be 192
|
||||
PICANM_MISC_MASK = (3 << 4),
|
||||
PICANM_TEXHITSCAN_BIT = (2 << 4),
|
||||
PICANM_NOFULLBRIGHT_BIT = (1 << 4),
|
||||
PICANM_ANIMSPEED_MASK = 15, // must be 15
|
||||
};
|
||||
|
||||
enum
|
||||
return tileGetTextureID(wallpicnum);
|
||||
}
|
||||
inline const FTextureID walltype::overtexture() const
|
||||
{
|
||||
MAXTILES = 30720,
|
||||
MAXUSERTILES = (MAXTILES-16) // reserve 16 tiles at the end
|
||||
return tileGetTextureID(overpicnum);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
enum ETexType
|
||||
inline const FTextureID sectortype::ceilingtexture() const
|
||||
{
|
||||
TT_INDEXED,
|
||||
TT_TRUECOLOR,
|
||||
};
|
||||
return tileGetTextureID(ceilingpicnum);
|
||||
}
|
||||
|
||||
|
||||
enum class ReplacementType : int
|
||||
inline const FTextureID sectortype::floortexture() const
|
||||
{
|
||||
Art,
|
||||
Writable,
|
||||
Restorable,
|
||||
Canvas
|
||||
};
|
||||
return tileGetTextureID(floorpicnum);
|
||||
}
|
||||
|
||||
|
||||
// NOTE: If the layout of this struct is changed, loadpics() must be modified
|
||||
// accordingly.
|
||||
struct picanm_t
|
||||
inline const FTextureID spritetypebase::spritetexture() const
|
||||
{
|
||||
uint16_t num; // animate number
|
||||
uint8_t sf; // anim. speed and flags
|
||||
uint8_t extra;
|
||||
return tileGetTextureID(picnum);
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
extra = sf = 0;
|
||||
num = 0;
|
||||
}
|
||||
|
||||
int speed()
|
||||
{
|
||||
return sf & PICANM_ANIMSPEED_MASK;
|
||||
}
|
||||
|
||||
int type()
|
||||
{
|
||||
return sf & PICANM_ANIMTYPE_MASK;
|
||||
}
|
||||
|
||||
};
|
||||
picanm_t tileConvertAnimFormat(int32_t const picanmdisk, int* lo, int* to);
|
||||
|
||||
class FTileTexture : public FImageSource
|
||||
inline void sectortype::setfloortexture(FTextureID tex)
|
||||
{
|
||||
public:
|
||||
FTileTexture()
|
||||
{
|
||||
bUseGamePalette = true;
|
||||
bTranslucent = false;
|
||||
}
|
||||
virtual uint8_t* GetRawData() = 0;
|
||||
virtual TArray<uint8_t> CreatePalettedPixels(int conversion);
|
||||
virtual int CopyPixels(FBitmap* bmp, int conversion); // This will always ignore 'luminance'.
|
||||
};
|
||||
floorpicnum = legacyTileNum(tex);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A tile coming from an ART file.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FArtTile : public FTileTexture
|
||||
inline void sectortype::setceilingtexture(FTextureID tex)
|
||||
{
|
||||
const TArray<uint8_t>& RawPixels;
|
||||
const uint32_t Offset;
|
||||
public:
|
||||
FArtTile(const TArray<uint8_t>& backingstore, uint32_t offset, int width, int height)
|
||||
: RawPixels(backingstore), Offset(offset)
|
||||
{
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
uint8_t* GetRawData() override final
|
||||
{
|
||||
return &RawPixels[Offset];
|
||||
}
|
||||
};
|
||||
ceilingpicnum = legacyTileNum(tex);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A tile with its own pixel buffer
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FLooseTile : public FTileTexture
|
||||
inline void walltype::setwalltexture(FTextureID tex)
|
||||
{
|
||||
TArray<uint8_t> RawPixels;
|
||||
public:
|
||||
FLooseTile(TArray<uint8_t>& store, int width, int height)
|
||||
{
|
||||
RawPixels = std::move(store);
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
wallpicnum = legacyTileNum(tex);
|
||||
}
|
||||
|
||||
uint8_t* GetRawData() override
|
||||
{
|
||||
return RawPixels.Data();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A non-existent tile
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FDummyTile : public FTileTexture
|
||||
inline void walltype::setovertexture(FTextureID tex)
|
||||
{
|
||||
public:
|
||||
FDummyTile(int width, int height)
|
||||
{
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
uint8_t* GetRawData() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A tile with a writable surface
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FWritableTile : public FTileTexture
|
||||
{
|
||||
protected:
|
||||
TArray<uint8_t> buffer;
|
||||
|
||||
public:
|
||||
FWritableTile()
|
||||
{
|
||||
//useType = Writable;
|
||||
}
|
||||
|
||||
uint8_t* GetRawData() override
|
||||
{
|
||||
return buffer.Data();
|
||||
}
|
||||
|
||||
bool ResizeImage(int w, int h)
|
||||
{
|
||||
if (w <= 0 || h <= 0)
|
||||
{
|
||||
buffer.Reset();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Width = w;
|
||||
Height = h;
|
||||
buffer.Resize(w * h);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A tile with a writable surface
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FRestorableTile : public FWritableTile
|
||||
{
|
||||
FImageSource* Base;
|
||||
|
||||
public:
|
||||
FRestorableTile(FImageSource* base)
|
||||
{
|
||||
Base = base;
|
||||
|
||||
CopySize(*base);
|
||||
ResizeImage(Width, Height);
|
||||
Reload();
|
||||
}
|
||||
|
||||
void Reload()
|
||||
{
|
||||
buffer = Base->GetPalettedPixels(0);
|
||||
}
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// One ART file.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
struct BuildArtFile
|
||||
{
|
||||
FString filename;
|
||||
TArray<uint8_t> RawData;
|
||||
|
||||
BuildArtFile() = default;
|
||||
BuildArtFile(const BuildArtFile&) = delete;
|
||||
BuildArtFile& operator=(const BuildArtFile&) = delete;
|
||||
BuildArtFile(const BuildArtFile&& other)
|
||||
{
|
||||
filename = std::move(other.filename);
|
||||
RawData = std::move(other.RawData);
|
||||
}
|
||||
|
||||
BuildArtFile& operator=(const BuildArtFile&& other)
|
||||
{
|
||||
filename = std::move(other.filename);
|
||||
RawData = std::move(other.RawData);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// THe tile container
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
struct TileOffs
|
||||
{
|
||||
int xsize, ysize, xoffs, yoffs;
|
||||
};
|
||||
|
||||
struct TileDesc
|
||||
{
|
||||
FGameTexture* texture; // the currently active tile
|
||||
picanm_t picanm; // animation descriptor
|
||||
ReplacementType replacement;
|
||||
float alphaThreshold;
|
||||
int tileflags;
|
||||
|
||||
// Sprite offset hackery for hires replacements. This only gets used for sprites in the 3D view, nothing else.
|
||||
TileOffs hiofs;
|
||||
|
||||
};
|
||||
|
||||
struct TexturePick
|
||||
{
|
||||
FGameTexture* texture; // which texture to use
|
||||
int translation; // which translation table to use
|
||||
int tintFlags; // which shader tinting options to use
|
||||
PalEntry tintColor; // Tint color
|
||||
PalEntry basepalTint; // can the base palette be done with a global tint effect?
|
||||
};
|
||||
|
||||
struct BuildTiles
|
||||
{
|
||||
FGameTexture* Placeholder;
|
||||
TDeletingArray<BuildArtFile*> ArtFiles;
|
||||
TArray<TileDesc> tiledata;
|
||||
TArray<FString> addedArt;
|
||||
TMap<FName, int> nametoindex;
|
||||
TMap<int, int> textotile;
|
||||
bool locked; // if this is true, no more tile modifications are allowed.
|
||||
|
||||
void addName(const char* name, int index)
|
||||
{
|
||||
nametoindex.Insert(name, index);
|
||||
}
|
||||
|
||||
void lock()
|
||||
{
|
||||
locked = true;
|
||||
// Now we can set up the reverse map.
|
||||
for (unsigned i = 0; i < MAXTILES; i++)
|
||||
{
|
||||
if (tiledata[i].texture != Placeholder)
|
||||
{
|
||||
textotile.Insert(tiledata[i].texture->GetID().GetIndex(), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetAliases();
|
||||
if (tex.isValid()) overpicnum = legacyTileNum(tex);
|
||||
else overpicnum = -1; // unlike the others this one can be invalid.
|
||||
}
|
||||
|
||||
|
||||
void Init(); // This cannot be a constructor because it needs the texture manager running.
|
||||
~BuildTiles()
|
||||
{
|
||||
CloseAll();
|
||||
}
|
||||
|
||||
void CloseAll();
|
||||
|
||||
void AddTile(int tilenum, FGameTexture* tex);
|
||||
|
||||
void AddTiles(int firsttile, TArray<uint8_t>& store, const char* mapname);
|
||||
|
||||
void AddFile(BuildArtFile* bfd)
|
||||
{
|
||||
ArtFiles.Push(bfd);
|
||||
}
|
||||
int FindFile(const FString& filename)
|
||||
{
|
||||
return ArtFiles.FindEx([filename](const BuildArtFile* element) { return filename.CompareNoCase(element->filename) == 0; });
|
||||
}
|
||||
int LoadArtFile(const char* file, const char* mapname = nullptr, int firsttile = -1);
|
||||
void LoadArtSet(const char* filename);
|
||||
void AddArt(TArray<FString>& art)
|
||||
{
|
||||
addedArt = std::move(art);
|
||||
}
|
||||
|
||||
void setAnim(int tile, int type, int speed, int frames)
|
||||
{
|
||||
auto& anm = tiledata[tile].picanm;
|
||||
anm.sf &= ~(PICANM_ANIMTYPE_MASK | PICANM_ANIMSPEED_MASK);
|
||||
anm.sf |= clamp(speed, 0, 15) | (type << PICANM_ANIMTYPE_SHIFT);
|
||||
anm.num = frames;
|
||||
}
|
||||
|
||||
FGameTexture* ValidateCustomTile(int tilenum, ReplacementType type);
|
||||
uint8_t* tileMakeWritable(int num);
|
||||
uint8_t* tileCreate(int tilenum, int width, int height);
|
||||
void MakeCanvas(int tilenum, int width, int height);
|
||||
};
|
||||
|
||||
int tileGetCRC32(int tileNum);
|
||||
int tileImportFromTexture(const char* fn, int tilenum, int alphacut, int istexture);
|
||||
void tileCopy(int tile, int tempsource, int temppal, int xoffset, int yoffset, int flags);
|
||||
void tileSetDummy(int tile, int width, int height);
|
||||
void tileDelete(int tile);
|
||||
|
||||
extern BuildTiles TileFiles;
|
||||
|
||||
//[[deprecated]]
|
||||
inline int tileForName(const char* name)
|
||||
{
|
||||
FName nm(name, true);
|
||||
if (nm == NAME_None) return -1;
|
||||
auto nmm = TileFiles.nametoindex.CheckKey(nm);
|
||||
if (!nmm) return -1;
|
||||
return *nmm;
|
||||
auto texid = TexMan.CheckForTexture(name, ETextureType::Any, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ReturnAll);
|
||||
if (!texid.isValid()) return -1;
|
||||
return legacyTileNum(texid);
|
||||
}
|
||||
|
||||
// Some hacks to allow accessing the no longer existing arrays as if they still were arrays to avoid changing hundreds of lines of code.
|
||||
struct PicAnm
|
||||
{
|
||||
picanm_t& operator[](size_t index)
|
||||
//[[deprecated]]
|
||||
const picanm_t& operator[](int index) const
|
||||
{
|
||||
assert(index < MAXTILES);
|
||||
return TileFiles.tiledata[index].picanm;
|
||||
assert((unsigned)index < MAXTILES);
|
||||
return GetExtInfo(tileGetTextureID(index)).picanm;
|
||||
}
|
||||
};
|
||||
extern PicAnm picanm;
|
||||
inline PicAnm picanm;
|
||||
|
||||
//[[deprecated]]
|
||||
inline int tileWidth(int num)
|
||||
{
|
||||
assert((unsigned)num < MAXTILES);
|
||||
if ((unsigned)num >= MAXTILES) return 1;
|
||||
return (int)TileFiles.tiledata[num].texture->GetDisplayWidth();
|
||||
auto texid = tileGetTextureID(num);
|
||||
if (!texid.isValid()) return 1;
|
||||
else return (int)TexMan.GetGameTexture(texid)->GetDisplayWidth();
|
||||
}
|
||||
|
||||
//[[deprecated]]
|
||||
inline int tileHeight(int num)
|
||||
{
|
||||
assert((unsigned)num < MAXTILES);
|
||||
if ((unsigned)num >= MAXTILES) return 1;
|
||||
return (int)TileFiles.tiledata[num].texture->GetDisplayHeight();
|
||||
}
|
||||
|
||||
int tileAnimateOfs(int tilenum, int randomize = -1);
|
||||
|
||||
inline void tileUpdatePicnum(int* const tileptr, bool mayrotate = false, int randomize = -1)
|
||||
{
|
||||
auto& tile = *tileptr;
|
||||
|
||||
if (picanm[tile].type())
|
||||
tile += tileAnimateOfs(tile, randomize);
|
||||
auto texid = tileGetTextureID(num);
|
||||
if (!texid.isValid()) return 1;
|
||||
else return (int)TexMan.GetGameTexture(texid)->GetDisplayHeight();
|
||||
}
|
||||
|
||||
|
||||
//[[deprecated]]
|
||||
inline FGameTexture* tileGetTexture(int tile, bool animate = false)
|
||||
{
|
||||
assert((unsigned)tile < MAXTILES && tile != -1); // -1 is valid for overpicnum as 'no texture'.
|
||||
if (tile < 0 || tile >= MAXTILES) return nullptr;
|
||||
if (animate) tileUpdatePicnum(&tile);
|
||||
return TileFiles.tiledata[tile].texture;
|
||||
auto texid = tileGetTextureID(tile);
|
||||
if (animate) tileUpdatePicnum(texid);
|
||||
return TexMan.GetGameTexture(texid);
|
||||
}
|
||||
|
||||
inline FTextureID tileGetTextureID(int tile)
|
||||
{
|
||||
if (tile < 0 || tile >= MAXTILES) return FNullTextureID();
|
||||
return TileFiles.tiledata[tile].texture->GetID();
|
||||
}
|
||||
|
||||
inline int legacyTileNum(FTextureID tex)
|
||||
{
|
||||
auto p = TileFiles.textotile.CheckKey(tex.GetIndex());
|
||||
return p ? *p : -1;
|
||||
}
|
||||
|
||||
void tileUpdateAnimations();
|
||||
|
||||
const uint8_t* GetRawPixels(FTextureID texid);
|
||||
uint8_t* GetWritablePixels(FTextureID texid);
|
||||
void InvalidateTexture(FTextureID num);
|
||||
TileOffs* GetHiresOffset(FTextureID num);
|
||||
|
||||
class FGameTexture;
|
||||
bool PickTexture(FGameTexture* tex, int paletteid, TexturePick& pick, bool wantindexed = false);
|
||||
FCanvasTexture* tileGetCanvas(int tilenum);
|
||||
|
|
|
@ -51,6 +51,13 @@
|
|||
#include "skyboxtexture.h"
|
||||
#include "gamefuncs.h"
|
||||
|
||||
enum ETexType
|
||||
{
|
||||
TT_INDEXED,
|
||||
TT_TRUECOLOR,
|
||||
};
|
||||
|
||||
|
||||
CVARD(Bool, hw_shadeinterpolate, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG, "enable/disable shade interpolation")
|
||||
|
||||
struct HightileReplacement
|
||||
|
@ -244,26 +251,10 @@ void highTileSetup()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int tileSetHightileReplacement(int picnum, int palnum, const char* filename, float alphacut, float xscale, float yscale, float specpower, float specfactor, bool indexed)
|
||||
int tileSetHightileReplacement(int picnum, int palnum, FTextureID texid, float alphacut, float xscale, float yscale, float specpower, float specfactor, bool indexed)
|
||||
{
|
||||
if ((uint32_t)picnum >= (uint32_t)MAXTILES) return -1;
|
||||
if ((uint32_t)palnum >= (uint32_t)MAXPALOOKUPS) return -1;
|
||||
|
||||
auto tex = tileGetTexture(picnum);
|
||||
if (tex->GetTexelWidth() <= 0 || tex->GetTexelHeight() <= 0)
|
||||
{
|
||||
Printf("Warning: defined hightile replacement for empty tile %d.", picnum);
|
||||
return -1; // cannot add replacements to empty tiles, must create one beforehand
|
||||
}
|
||||
// assumes the texture was already validated.
|
||||
HightileReplacement replace = {};
|
||||
|
||||
FTextureID texid = TexMan.CheckForTexture(filename, ETextureType::Any, FTextureManager::TEXMAN_ForceLookup);
|
||||
if (!texid.isValid())
|
||||
{
|
||||
Printf("%s: Replacement for tile %d does not exist or is invalid\n", filename, picnum);
|
||||
return -1;
|
||||
}
|
||||
|
||||
replace.image = TexMan.GetGameTexture(texid);
|
||||
replace.alphacut = min(alphacut,1.f);
|
||||
replace.scale = { xscale, yscale };
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "printf.h"
|
||||
#include "texturemanager.h"
|
||||
#include "buildtiles.h"
|
||||
#include "texinfo.h"
|
||||
|
||||
FGameTexture* GetSkyTexture(int basetile, int lognumtiles, const int16_t *tilemap, int remap)
|
||||
{
|
||||
|
|
100
source/core/textures/texinfo.cpp
Normal file
100
source/core/textures/texinfo.cpp
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
** texinfo.cpp
|
||||
** Extended texture information / handling
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2019-2022 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 "texturemanager.h"
|
||||
#include "texinfo.h"
|
||||
#include "m_crc32.h"
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Retrieve animation offset
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static int tileAnimateOfs(FTextureID texid, int randomize)
|
||||
{
|
||||
auto ext = GetExtInfo(texid);
|
||||
int framecount = ext.picanm.num;
|
||||
if (framecount > 0)
|
||||
{
|
||||
int frametime = !isBlood() ? I_GetBuildTime() : PlayClock;
|
||||
|
||||
if (isBlood() && randomize)
|
||||
{
|
||||
frametime += Bcrc32(&randomize, 2, 0);
|
||||
}
|
||||
|
||||
int curframe = (frametime & 0x7fffffff) >> (ext.picanm.speed());
|
||||
|
||||
switch (ext.picanm.type())
|
||||
{
|
||||
case PICANM_ANIMTYPE_FWD:
|
||||
return curframe % (framecount + 1);
|
||||
case PICANM_ANIMTYPE_BACK:
|
||||
return -(curframe % (framecount + 1));
|
||||
case PICANM_ANIMTYPE_OSC:
|
||||
curframe = curframe % (framecount << 1);
|
||||
if (curframe >= framecount) return (framecount << 1) - curframe;
|
||||
else return curframe;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tileUpdatePicnum(FTextureID& tileptr, int randomize)
|
||||
{
|
||||
tileptr = FSetTextureID(tileptr.GetIndex() + tileAnimateOfs(tileptr, randomize));
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// update the animation info inside the texture manager.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void tileUpdateAnimations()
|
||||
{
|
||||
for (unsigned i = 0; i < texExtInfo.Size(); i++)
|
||||
{
|
||||
auto& x = texExtInfo[i];
|
||||
if (x.picanm.type())
|
||||
{
|
||||
int j = i + tileAnimateOfs(FSetTextureID(i), false);
|
||||
TexMan.SetTranslation(FSetTextureID(i), FSetTextureID(j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
122
source/core/textures/texinfo.h
Normal file
122
source/core/textures/texinfo.h
Normal file
|
@ -0,0 +1,122 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "gamefuncs.h"
|
||||
#include "tiletexture.h"
|
||||
|
||||
// extended texture info for which there is no room in the texture manager.
|
||||
|
||||
enum AnimFlags
|
||||
{
|
||||
PICANM_ANIMTYPE_NONE = 0,
|
||||
PICANM_ANIMTYPE_OSC = (1 << 6),
|
||||
PICANM_ANIMTYPE_FWD = (2 << 6),
|
||||
PICANM_ANIMTYPE_BACK = (3 << 6),
|
||||
|
||||
PICANM_ANIMTYPE_SHIFT = 6,
|
||||
PICANM_ANIMTYPE_MASK = (3 << 6), // must be 192
|
||||
PICANM_MISC_MASK = (3 << 4),
|
||||
PICANM_TEXHITSCAN_BIT = (2 << 4),
|
||||
PICANM_NOFULLBRIGHT_BIT = (1 << 4),
|
||||
PICANM_ANIMSPEED_MASK = 15, // must be 15
|
||||
};
|
||||
|
||||
|
||||
|
||||
// NOTE: If the layout of this struct is changed, loadpics() must be modified
|
||||
// accordingly.
|
||||
struct picanm_t
|
||||
{
|
||||
uint16_t num; // animate number
|
||||
uint8_t sf; // anim. speed and flags
|
||||
uint8_t extra;
|
||||
|
||||
void Clear()
|
||||
{
|
||||
extra = sf = 0;
|
||||
num = 0;
|
||||
}
|
||||
|
||||
int speed() const
|
||||
{
|
||||
return sf & PICANM_ANIMSPEED_MASK;
|
||||
}
|
||||
|
||||
int type() const
|
||||
{
|
||||
return sf & PICANM_ANIMTYPE_MASK;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
struct TileOffs
|
||||
{
|
||||
int16_t xsize, ysize, xoffs, yoffs;
|
||||
};
|
||||
|
||||
struct TexExtInfo
|
||||
{
|
||||
// TexAnim *texanim // todo: extended texture animation like ZDoom's ANIMDEFS.
|
||||
uint8_t terrain; // Contents depend on the game, e.g. this holds Blood's surfType.
|
||||
uint8_t shadeinfo; // Blood's shade.dat
|
||||
uint16_t voxindex;
|
||||
picanm_t picanm;
|
||||
uint32_t flags; // contents are game dependent.
|
||||
TileOffs hiofs;
|
||||
};
|
||||
|
||||
inline TArray<TexExtInfo> texExtInfo;
|
||||
inline int firstarttile, maxarttile; // we need this for conversion between tile numbers and texture IDs
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// THe tile container
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
struct TexturePick
|
||||
{
|
||||
FGameTexture* texture; // which texture to use
|
||||
int translation; // which translation table to use
|
||||
int tintFlags; // which shader tinting options to use
|
||||
PalEntry tintColor; // Tint color
|
||||
PalEntry basepalTint; // can the base palette be done with a global tint effect?
|
||||
};
|
||||
bool PickTexture(FGameTexture* tex, int paletteid, TexturePick& pick, bool wantindexed = false);
|
||||
|
||||
|
||||
|
||||
void tileUpdatePicnum(FTextureID& tileptr, int randomize = -1);
|
||||
void tileUpdateAnimations();
|
||||
|
||||
|
||||
inline const TexExtInfo& GetExtInfo(FTextureID tex) // this is only for reading, not for modifying!
|
||||
{
|
||||
unsigned index = tex.GetIndex();
|
||||
if (index >= texExtInfo.Size()) index = 0; // index 0 (the null texture) serves as backup if textures get added at runtime.
|
||||
return texExtInfo[index];
|
||||
}
|
||||
|
||||
inline FTextureID tileGetTextureID(int tilenum)
|
||||
{
|
||||
if ((unsigned)tilenum >= MAXTILES) return FNullTextureID();
|
||||
return FSetTextureID(firstarttile + min(tilenum, maxarttile));
|
||||
}
|
||||
|
||||
// Use this only for places where some legacy feature needs a tile index. The only such places are CON and nnext.
|
||||
inline int legacyTileNum(FTextureID id)
|
||||
{
|
||||
int index = id.GetIndex() - firstarttile;
|
||||
if (index < 0 || index > maxarttile) return maxarttile;
|
||||
return index;
|
||||
}
|
||||
|
||||
inline const TileOffs* GetHiresOffset(FTextureID tex)
|
||||
{
|
||||
// fixme: This must return nullptr if the tile has no replacement.
|
||||
auto& x = GetExtInfo(tex);
|
||||
if (x.hiofs.xsize != 0) return &x.hiofs;
|
||||
else return nullptr;
|
||||
}
|
||||
|
315
source/core/textures/tilesetbuilder.cpp
Normal file
315
source/core/textures/tilesetbuilder.cpp
Normal file
|
@ -0,0 +1,315 @@
|
|||
/*
|
||||
** tilesetbuilder.cpp
|
||||
** Constructs the full tile set and adds it to the texture manager.
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2019-2022 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 "image.h"
|
||||
#include "texturemanager.h"
|
||||
#include "m_crc32.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "tiletexture.h"
|
||||
#include "tilesetbuilder.h"
|
||||
#include "gamecontrol.h"
|
||||
#include "startupinfo.h"
|
||||
#include "printf.h"
|
||||
#include "m_argv.h"
|
||||
#include "gamestruct.h"
|
||||
|
||||
const char* G_DefFile(void);
|
||||
void loaddefinitionsfile(TilesetBuildInfo& info, const char* fn, bool cumulative = false, bool maingrp = false);
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Returns checksum for a given tile or texture
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int32_t tileGetCRC32(FImageSource* image)
|
||||
{
|
||||
if (image == nullptr) return 0;
|
||||
auto pixels = image->GetPalettedPixels(0);
|
||||
if (pixels.Size() == 0) return 0;
|
||||
|
||||
// To get proper CRCs as the calling code expects we need to put the translucent index back to 255.
|
||||
for (auto& p : pixels)
|
||||
{
|
||||
if (p == 0) p = 255;
|
||||
else if (p == 255) p = 0;
|
||||
}
|
||||
|
||||
return crc32(0, (const Bytef*)pixels.Data(), pixels.Size());
|
||||
}
|
||||
|
||||
CCMD(tilecrc)
|
||||
{
|
||||
if (argv.argc() > 1)
|
||||
{
|
||||
char* p;
|
||||
int tile = strtol(argv[1], &p, 10);
|
||||
FGameTexture* tex;
|
||||
if (tile >= 0 && tile < MAXTILES && !*p)
|
||||
{
|
||||
// tex = tileGetTexture(tile);
|
||||
}
|
||||
else
|
||||
{
|
||||
tex = TexMan.FindGameTexture(argv[1], ETextureType::Any);
|
||||
}
|
||||
auto img = tex? tex->GetTexture()->GetImage() : nullptr;
|
||||
if (!img) Printf("%s: not a valid texture", argv[1]);
|
||||
else Printf("%d\n", tileGetCRC32(img));
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
static void LoadDefinitions(TilesetBuildInfo& info)
|
||||
{
|
||||
const char* defsfile = G_DefFile();
|
||||
FString razedefsfile = defsfile;
|
||||
razedefsfile.Substitute(".def", "-raze.def");
|
||||
|
||||
loaddefinitionsfile(info, "engine/engine.def", true, true); // Internal stuff that is required.
|
||||
|
||||
// check what we have.
|
||||
// user .defs override the default ones and are not cumulative.
|
||||
// if we fine even one Raze-specific file, all of those will be loaded cumulatively.
|
||||
// otherwise the default rules inherited from older ports apply.
|
||||
if (userConfig.UserDef.IsNotEmpty())
|
||||
{
|
||||
loaddefinitionsfile(info, userConfig.UserDef, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fileSystem.FileExists(razedefsfile))
|
||||
{
|
||||
loaddefinitionsfile(info, razedefsfile, true);
|
||||
}
|
||||
else if (fileSystem.FileExists(defsfile))
|
||||
{
|
||||
loaddefinitionsfile(info, defsfile, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (userConfig.AddDefs)
|
||||
{
|
||||
for (auto& m : *userConfig.AddDefs)
|
||||
{
|
||||
loaddefinitionsfile(info, m, false);
|
||||
}
|
||||
userConfig.AddDefs.reset();
|
||||
}
|
||||
|
||||
if (GameStartupInfo.def.IsNotEmpty())
|
||||
{
|
||||
loaddefinitionsfile(info, GameStartupInfo.def); // Stuff from gameinfo.
|
||||
}
|
||||
|
||||
// load the widescreen replacements last. This ensures that mods still get the correct CRCs for their own tile replacements.
|
||||
if (fileSystem.FindFile("engine/widescreen.def") >= 0 && !Args->CheckParm("-nowidescreen"))
|
||||
{
|
||||
loaddefinitionsfile(info, "engine/widescreen.def");
|
||||
}
|
||||
fileSystem.InitHashChains(); // make sure that any resources that got added can be found again.
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
picanm_t tileConvertAnimFormat(int32_t const picanimraw)
|
||||
{
|
||||
// Unpack a 4 byte packed anim descriptor into something more accessible
|
||||
picanm_t anm;
|
||||
anm.num = picanimraw & 63;
|
||||
anm.sf = ((picanimraw >> 24) & 15) | (picanimraw & 192);
|
||||
anm.extra = (picanimraw >> 28) & 15;
|
||||
return anm;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
FImageSource* createWritableTile(int width, int height);
|
||||
FImageSource* makeTileWritable(FImageSource* img);
|
||||
|
||||
void TilesetBuildInfo::MakeWritable(int tileno)
|
||||
{
|
||||
if (tile[tileno].tileimage != nullptr)
|
||||
{
|
||||
auto newtex = makeTileWritable(tile[tileno].tileimage);
|
||||
tile[tileno].tileimage = newtex;
|
||||
tile[tileno].imported = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void TilesetBuildInfo::CreateWritable(int tileno, int w, int h)
|
||||
{
|
||||
auto newtex = createWritableTile(w, h);
|
||||
tile[tileno].tileimage = newtex;
|
||||
tile[tileno].imported = nullptr;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// MakeCanvas
|
||||
//
|
||||
// Turns texture into a canvas (i.e. camera texture)
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void TilesetBuildInfo::MakeCanvas(int tilenum, int width, int height)
|
||||
{
|
||||
auto ftex = new FCanvasTexture(width * 4, height * 4);
|
||||
ftex->aspectRatio = (float)width / height;
|
||||
auto canvas = MakeGameTexture(ftex, FStringf("#%05d", tilenum), ETextureType::Any);
|
||||
canvas->SetSize(width * 4, height * 4);
|
||||
canvas->SetDisplaySize((float)width, (float)height);
|
||||
canvas->GetTexture()->SetSize(width * 4, height * 4);
|
||||
tile[tilenum].imported = canvas;
|
||||
tile[tilenum].tileimage = nullptr;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void ConstructTileset()
|
||||
{
|
||||
TilesetBuildInfo info;
|
||||
TArray<FImageSource*> images;
|
||||
TArray<unsigned> rawpicanm;
|
||||
GetArtImages(images, rawpicanm);
|
||||
info.tile.Resize(MAXTILES);
|
||||
memset(info.tile.Data(), 0, info.tile.Size() * sizeof(info.tile[0]));
|
||||
// fill up the arrays to the maximum allowed but remember the highest original number.
|
||||
for (unsigned i = 0; i < images.Size(); i++)
|
||||
{
|
||||
info.tile[i].orgimage = info.tile[i].tileimage = images[i];
|
||||
if (images[i])
|
||||
{
|
||||
auto s = images[i]->GetOffsets();
|
||||
info.tile[i].leftOffset = s.first;
|
||||
info.tile[i].topOffset = s.second;
|
||||
}
|
||||
info.tile[i].extinfo.picanm = tileConvertAnimFormat(rawpicanm[i]);
|
||||
}
|
||||
images.Reset();
|
||||
rawpicanm.Reset();
|
||||
for (auto& a : info.tile) a.alphathreshold = 0.5f;
|
||||
gi->LoadTextureInfo(info); // initialize game data that must be done before loading .DEF
|
||||
LoadDefinitions(info);
|
||||
gi->SetupSpecialTextures(info); // initialize game data that needs .DEF being processed.
|
||||
|
||||
// now that everything has been set up, we can add the textures to the texture manager.
|
||||
// To keep things simple everything from .ART files and its replacements will remain in order and
|
||||
// converting between a Build tilenum and a texture ID can done with a single addition.
|
||||
// Even though this requires adding quite a few empty textures to the texture manager, it makes things a lot easier,
|
||||
// because it ensures an unambiguous mapping and allows communicating with features that only work with tile numbers.
|
||||
// as long as no named textures are used.
|
||||
|
||||
auto nulltex = TexMan.GameByIndex(0); // Use the null texture's backing data for all empty placeholders.
|
||||
// Only the outward facing FGameTexture needs to be different
|
||||
|
||||
firstarttile = TexMan.NumTextures();
|
||||
maxarttile = MAXTILES - 1;
|
||||
while (maxarttile >= 0 && info.tile[maxarttile].tileimage == nullptr) maxarttile--;
|
||||
if (maxarttile < 0) return; // should never happen, but who knows - maybe someone will make a game without ART files later... :D
|
||||
maxarttile++; // create a placeholder in the first unused spot. This will later get used for all out of range tile numbers.
|
||||
|
||||
int lastid = firstarttile - 1;
|
||||
for (int i = 0; i <= maxarttile; i++)
|
||||
{
|
||||
FTexture* ftex = nullptr;
|
||||
FGameTexture* gtex;
|
||||
FStringf tname("#%05d", i);
|
||||
if (info.tile[i].tileimage == nullptr)
|
||||
{
|
||||
if (info.tile[i].imported == nullptr)
|
||||
{
|
||||
ftex = nulltex->GetTexture();
|
||||
gtex = MakeGameTexture(ftex, tname, ETextureType::Null);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Canvas textures can be used directly without wrapping them again.
|
||||
gtex = info.tile[i].imported;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (info.tile[i].imported) ftex = info.tile[i].imported->GetTexture();
|
||||
else ftex = new FImageTexture(info.tile[i].tileimage);
|
||||
gtex = MakeGameTexture(ftex, tname, ETextureType::Any);
|
||||
gtex->SetOffsets(info.tile[i].leftOffset, info.tile[i].topOffset);
|
||||
}
|
||||
if (info.tile[i].extinfo.picanm.sf & PICANM_NOFULLBRIGHT_BIT)
|
||||
{
|
||||
gtex->SetDisableFullbright(true);
|
||||
}
|
||||
|
||||
auto id = TexMan.AddGameTexture(gtex, true);
|
||||
if (id.GetIndex() != lastid + 1)
|
||||
{
|
||||
// this should never happen unless the texture manager gets redone in an incompatible fashion.
|
||||
I_FatalError("Unable to assign consecutive texture IDs to tile set.");
|
||||
}
|
||||
lastid = id.GetIndex();
|
||||
}
|
||||
// Now create the extended info. This will leave room for all regular textures as well so that later code can assign info to these, too.
|
||||
// Textures being added afterward will always see the default extinfo, even if they are not covered by this array.
|
||||
texExtInfo.Resize(TexMan.NumTextures());
|
||||
memset(texExtInfo.Data(), 0, sizeof(texExtInfo[0]) * texExtInfo.Size());
|
||||
for (auto& x : texExtInfo) x.voxindex = -1;
|
||||
// now copy all extinfo stuff that got parsed by .DEF or some game specific setup.
|
||||
for (int i = 0; i <= maxarttile; i++)
|
||||
{
|
||||
texExtInfo[i + firstarttile] = info.tile[i].extinfo;
|
||||
}
|
||||
|
||||
for (auto& a : info.aliases)
|
||||
{
|
||||
TexMan.AddAlias(a.first.GetChars(), a.second + firstarttile);
|
||||
}
|
||||
}
|
44
source/core/textures/tilesetbuilder.h
Normal file
44
source/core/textures/tilesetbuilder.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
#pragma once
|
||||
|
||||
#include "texinfo.h"
|
||||
|
||||
struct TileBuildDesc
|
||||
{
|
||||
// persistent data that will be present for the entire run of the game.
|
||||
TexExtInfo extinfo;
|
||||
|
||||
// work data
|
||||
FImageSource* orgimage; // this is the original tile image, not connected to a FTexture yet.
|
||||
FImageSource* tileimage; // this is the current tile image, it may be connected to 'imported'. Used for convenient access.
|
||||
FGameTexture* imported; // imported replacement from the texture manager;
|
||||
|
||||
// info that will be copied into the final texture object
|
||||
float alphathreshold;
|
||||
int leftOffset, topOffset; // overrides for imported textures.
|
||||
};
|
||||
|
||||
struct TilesetBuildInfo
|
||||
{
|
||||
TArray<TileBuildDesc> tile;
|
||||
unsigned maxtileofart;
|
||||
TArray <std::pair<FName, int>> aliases;
|
||||
void addName(const char* name, int index)
|
||||
{
|
||||
aliases.Push(std::make_pair(name, index));
|
||||
}
|
||||
|
||||
void Delete(int tileno)
|
||||
{
|
||||
tile[tileno].tileimage = nullptr;
|
||||
tile[tileno].imported = nullptr;
|
||||
}
|
||||
|
||||
void MakeWritable(int tile);
|
||||
void CreateWritable(int tile, int w, int h);
|
||||
void MakeCanvas(int tilenum, int width, int height);
|
||||
|
||||
};
|
||||
|
||||
void ConstructTileset();
|
||||
int32_t tileGetCRC32(FImageSource* image);
|
||||
|
525
source/core/textures/tiletexture.cpp
Normal file
525
source/core/textures/tiletexture.cpp
Normal file
|
@ -0,0 +1,525 @@
|
|||
/*
|
||||
** tiletexture.cpp
|
||||
** Image sources and file management for Build tile textures
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2019-2022 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 "files.h"
|
||||
#include "i_time.h"
|
||||
#include "zstring.h"
|
||||
#include "tiletexture.h"
|
||||
#include "texturemanager.h"
|
||||
#include "filesystem.h"
|
||||
#include "printf.h"
|
||||
|
||||
|
||||
class FTileTexture : public FImageSource
|
||||
{
|
||||
public:
|
||||
FTileTexture() noexcept
|
||||
{
|
||||
bUseGamePalette = true;
|
||||
bTranslucent = false;
|
||||
}
|
||||
virtual uint8_t* GetRawData() = 0;
|
||||
virtual TArray<uint8_t> CreatePalettedPixels(int conversion);
|
||||
virtual int CopyPixels(FBitmap* bmp, int conversion); // This will always ignore 'luminance'.
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A tile coming from an ART file.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FArtTile : public FTileTexture
|
||||
{
|
||||
const TArray<uint8_t>& RawPixels;
|
||||
const uint32_t Offset;
|
||||
public:
|
||||
FArtTile(const TArray<uint8_t>& backingstore, uint32_t offset, int width, int height) noexcept
|
||||
: RawPixels(backingstore), Offset(offset)
|
||||
{
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
uint8_t* GetRawData() override final
|
||||
{
|
||||
return &RawPixels[Offset];
|
||||
}
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A non-existent tile
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FDummyTile : public FTileTexture
|
||||
{
|
||||
public:
|
||||
FDummyTile(int width, int height)
|
||||
{
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
uint8_t* GetRawData() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A tile with a writable surface
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FWritableTile : public FTileTexture
|
||||
{
|
||||
protected:
|
||||
TArray<uint8_t> buffer;
|
||||
|
||||
public:
|
||||
FWritableTile()
|
||||
{
|
||||
//useType = Writable;
|
||||
}
|
||||
|
||||
uint8_t* GetRawData() override
|
||||
{
|
||||
return buffer.Data();
|
||||
}
|
||||
|
||||
bool ResizeImage(int w, int h)
|
||||
{
|
||||
if (w <= 0 || h <= 0)
|
||||
{
|
||||
buffer.Reset();
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Width = w;
|
||||
Height = h;
|
||||
buffer.Resize(w * h);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Reload() {}
|
||||
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// A tile with a writable surface
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
class FRestorableTile : public FWritableTile
|
||||
{
|
||||
FImageSource* Base;
|
||||
|
||||
public:
|
||||
FRestorableTile(FImageSource* base)
|
||||
{
|
||||
Base = base;
|
||||
|
||||
CopySize(*base);
|
||||
ResizeImage(Width, Height);
|
||||
Reload();
|
||||
}
|
||||
|
||||
void Reload() override
|
||||
{
|
||||
buffer = Base->GetPalettedPixels(0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Base class for Build tile textures
|
||||
// This needs a few subclasses for different use cases.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FTileTexture::CopyPixels(FBitmap* bmp, int conversion)
|
||||
{
|
||||
TArray<uint8_t> buffer;
|
||||
auto ppix = GetRawData();
|
||||
if (ppix)
|
||||
{
|
||||
bmp->CopyPixelData(0, 0, ppix, Width, Height, Height, 1, 0, GPalette.BaseColors);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
TArray<uint8_t> FTileTexture::CreatePalettedPixels(int conversion)
|
||||
{
|
||||
TArray<uint8_t> buffer(Width * Height, true);
|
||||
auto p = GetRawData();
|
||||
if (p) memcpy(buffer.Data(), p, buffer.Size());
|
||||
else memset(buffer.Data(), 0, buffer.Size());
|
||||
return buffer;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// raw pixel cache. This is for accessing pixel data in the game code,
|
||||
// not for rendering.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
struct RawCacheNode
|
||||
{
|
||||
TArray<uint8_t> data;
|
||||
uint64_t lastUseTime;
|
||||
|
||||
RawCacheNode() = default;
|
||||
RawCacheNode(const RawCacheNode& other) = default;
|
||||
RawCacheNode& operator=(const RawCacheNode& other) = default;
|
||||
|
||||
RawCacheNode(RawCacheNode&& other) noexcept
|
||||
{
|
||||
data = std::move(other.data);
|
||||
lastUseTime = other.lastUseTime;
|
||||
}
|
||||
|
||||
RawCacheNode& operator=(RawCacheNode&& other) noexcept
|
||||
{
|
||||
data = std::move(other.data);
|
||||
lastUseTime = other.lastUseTime;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// access raw pixel data for in-game checking. Works for all texture types.
|
||||
//
|
||||
//==========================================================================
|
||||
static TMap<int, RawCacheNode> CacheNodes;
|
||||
|
||||
const uint8_t* GetRawPixels(FTextureID texid)
|
||||
{
|
||||
if (!texid.isValid()) return nullptr;
|
||||
auto gtex = TexMan.GetGameTexture(texid);
|
||||
auto tex = dynamic_cast<FImageTexture*>(gtex->GetTexture());
|
||||
|
||||
if (!tex || !tex->GetImage()) return nullptr;
|
||||
auto img = tex->GetImage();
|
||||
auto timg = dynamic_cast<FTileTexture*>(img);
|
||||
if (!timg || !timg->GetRawData())
|
||||
{
|
||||
auto cache = CacheNodes.CheckKey(texid.GetIndex());
|
||||
if (cache)
|
||||
{
|
||||
cache->lastUseTime = I_nsTime();
|
||||
return cache->data.Data();
|
||||
}
|
||||
RawCacheNode newnode;
|
||||
newnode.data = img->GetPalettedPixels(0);
|
||||
newnode.lastUseTime = I_nsTime();
|
||||
auto retval =newnode.data.Data();
|
||||
CacheNodes.Insert(texid.GetIndex(), std::move(newnode));
|
||||
return retval;
|
||||
}
|
||||
else
|
||||
{
|
||||
return timg->GetRawData();
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//To use this the texture must have been made writable during texture init.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
uint8_t* GetWritablePixels(FTextureID texid, bool reload)
|
||||
{
|
||||
if (!texid.isValid()) return nullptr;
|
||||
auto gtex = TexMan.GetGameTexture(texid);
|
||||
auto tex = dynamic_cast<FImageTexture*>(gtex->GetTexture());
|
||||
|
||||
if (!tex || !tex->GetImage()) return nullptr;
|
||||
auto timg = dynamic_cast<FWritableTile*>(tex->GetImage());
|
||||
if (!timg) return nullptr;
|
||||
|
||||
if (reload)
|
||||
timg->Reload();
|
||||
|
||||
gtex->CleanHardwareData(); // we can safely assume that this only gets called when the texture is about to be changed.
|
||||
return timg->GetRawData();
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static FImageSource* GetTileImage(const TArray<uint8_t>& backingstore, uint32_t offset, int width, int height, TArray<void*> freelist)
|
||||
{
|
||||
FImageSource* tex;
|
||||
|
||||
void* mem = nullptr;
|
||||
if (freelist.Size() > 0) freelist.Pop(mem);
|
||||
// recycle discarded image sources if available. They are all the same type so this is safe.
|
||||
if (mem) tex = new(mem) FArtTile(backingstore, offset, width, height);
|
||||
else tex = new FArtTile(backingstore, offset, width, height);
|
||||
auto p = &backingstore[offset];
|
||||
auto siz = width * height;
|
||||
for (int i = 0; i < siz; i++, p++)
|
||||
{
|
||||
// move transparent color to index 0 to get in line with the rest of the texture management.
|
||||
if (*p == 0) *p = 255;
|
||||
else if (*p == 255) *p = 0;
|
||||
}
|
||||
return tex;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Creates image sources for all valid tiles in one ART file.
|
||||
// In case this overwrites older tiles, these get added to a freelist
|
||||
// and reused later
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
static void GetImagesFromFile(TArray<FImageSource*>& array, TArray<unsigned>& picanmarray, TArray<void*> freelist, TArray<uint8_t>& RawData)
|
||||
{
|
||||
const uint8_t* tiles = RawData.Data();
|
||||
// int numtiles = LittleLong(((uint32_t *)tiles)[1]); // This value is not reliable
|
||||
unsigned tilestart = LittleLong(((unsigned*)tiles)[2]);
|
||||
unsigned tileend = LittleLong(((unsigned*)tiles)[3]);
|
||||
const uint16_t* tilesizx = &((const uint16_t*)tiles)[8];
|
||||
const uint16_t* tilesizy = &tilesizx[tileend - tilestart + 1];
|
||||
const uint32_t* picanm = (const uint32_t*)&tilesizy[tileend - tilestart + 1];
|
||||
const uint8_t* tiledata = (const uint8_t*)&picanm[tileend - tilestart + 1];
|
||||
|
||||
unsigned oldsize = array.Size();
|
||||
if (array.Size() < tileend + 1)
|
||||
array.Resize(tileend + 1);
|
||||
|
||||
// picanm info needs to be stashed aside for later use, except for the offsets which are written into the image object
|
||||
if (picanmarray.Size() < tileend + 1)
|
||||
picanmarray.Resize(tileend + 1);
|
||||
|
||||
// If there's a gap, initialize it.
|
||||
for (unsigned i = oldsize; i < tilestart; i++)
|
||||
{
|
||||
array[i] = nullptr;
|
||||
picanmarray[i] = {};
|
||||
}
|
||||
|
||||
for (unsigned i = tilestart; i <= tileend; ++i)
|
||||
{
|
||||
int pic = i - tilestart;
|
||||
int width = LittleShort(tilesizx[pic]);
|
||||
int height = LittleShort(tilesizy[pic]);
|
||||
uint32_t anm = LittleLong(picanm[pic]);
|
||||
int size = width * height;
|
||||
|
||||
picanmarray[i] = picanm[pic]; // this must also be retained for invalid tiles.
|
||||
if (width <= 0 || height <= 0)
|
||||
{
|
||||
// If an existing tile is discarded, add it to the free list
|
||||
if (array[i] && i < oldsize)
|
||||
{
|
||||
array[i]->~FImageSource(); // really a no-op but let's stay on the safe side.
|
||||
freelist.Push(array[i]);
|
||||
}
|
||||
array[i] = nullptr;
|
||||
continue;
|
||||
}
|
||||
|
||||
FString texname;
|
||||
auto tex = GetTileImage(RawData, uint32_t(tiledata - tiles), width, height, freelist);
|
||||
int leftoffset = (int8_t)((anm >> 8) & 255);
|
||||
int topoffset = (int8_t)((anm >> 16) & 255);
|
||||
tex->SetOffsets(leftoffset, topoffset);
|
||||
tiledata += size;
|
||||
array[i] = tex;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// CountTiles
|
||||
//
|
||||
// Returns the number of tiles provided by an artfile
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
int CountTiles(const char* fn, const uint8_t* RawData)
|
||||
{
|
||||
int version = LittleLong(*(uint32_t*)RawData);
|
||||
if (version != 1)
|
||||
{
|
||||
Printf("%s: Invalid art file version. Must be 1, got %d\n", fn, version);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tilestart = LittleLong(((uint32_t*)RawData)[2]);
|
||||
int tileend = LittleLong(((uint32_t*)RawData)[3]);
|
||||
|
||||
if ((unsigned)tilestart >= MAXUSERTILES || (unsigned)tileend >= MAXUSERTILES)
|
||||
{
|
||||
Printf("%s: Invalid tilestart or tileend\n", fn);
|
||||
return 0;
|
||||
}
|
||||
if (tileend < tilestart)
|
||||
{
|
||||
Printf("%s: tileend < tilestart\n", fn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return tileend >= tilestart ? tileend - tilestart + 1 : 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// LoadArtFile
|
||||
//
|
||||
// Returns the number of tiles found.
|
||||
//
|
||||
// let's load everything into memory on startup.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
static void AddArtFile(const FString& filename)
|
||||
{
|
||||
FileReader fr = fileSystem.OpenFileReader(filename);
|
||||
if (fr.isOpen())
|
||||
{
|
||||
auto artdata = fr.Read();
|
||||
if (artdata.Size() > 16)
|
||||
{
|
||||
if (memcmp(artdata.Data(), "BUILDART", 8) == 0)
|
||||
{
|
||||
artdata.Delete(0, 8);
|
||||
}
|
||||
// Only load the data if the header is present
|
||||
if (CountTiles(filename, artdata.Data()) > 0)
|
||||
{
|
||||
// The texture manager already has a store for Build ART files, so let's use it. :)
|
||||
auto& store = TexMan.GetNewBuildTileData();
|
||||
store = std::move(artdata);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Loads an art set but does not do anything with the tiles yet.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void InitArtFiles(TArray<FString>& addedArt)
|
||||
{
|
||||
const int MAXARTFILES_BASE = 200;
|
||||
|
||||
for (int index = 0; index < MAXARTFILES_BASE; index++)
|
||||
{
|
||||
FStringf fn("tiles%03d.art", index);
|
||||
AddArtFile(fn);
|
||||
}
|
||||
for (auto& addart : addedArt)
|
||||
{
|
||||
AddArtFile(addart);
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Creates image sources for all valid tiles in the ART set.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void GetArtImages(TArray<FImageSource*>& array, TArray<unsigned>& picanm)
|
||||
{
|
||||
TArray<void*> freelist;
|
||||
for (auto& f : TexMan.GetBuildTileDataStore())
|
||||
{
|
||||
GetImagesFromFile(array, picanm, freelist, f);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FImageSource* createDummyTile(int width, int height)
|
||||
{
|
||||
if (width > 0 && height > 0)
|
||||
return new FDummyTile(width, height);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FImageSource* createWritableTile(int width, int height)
|
||||
{
|
||||
if (width > 0 && height > 0)
|
||||
{
|
||||
auto tile = new FWritableTile;
|
||||
tile->ResizeImage(width, height);
|
||||
return tile;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FImageSource* makeTileWritable(FImageSource* img)
|
||||
{
|
||||
return new FRestorableTile(img);
|
||||
}
|
||||
|
18
source/core/textures/tiletexture.h
Normal file
18
source/core/textures/tiletexture.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "image.h"
|
||||
#include "textureid.h"
|
||||
#include "tarray.h"
|
||||
|
||||
const uint8_t* GetRawPixels(FTextureID texid);
|
||||
uint8_t* GetWritablePixels(FTextureID texid, bool reload = false);
|
||||
FImageSource* createDummyTile(int width, int height);
|
||||
void InitArtFiles(TArray<FString>& addart);
|
||||
void GetArtImages(TArray<FImageSource*>& array, TArray<unsigned>& picanm);
|
||||
|
||||
enum
|
||||
{
|
||||
MAXTILES = 30720,
|
||||
MAXUSERTILES = (MAXTILES - 16) // reserve 16 tiles at the end
|
||||
};
|
|
@ -38,6 +38,9 @@
|
|||
#include "gamefuncs.h"
|
||||
#include "raze_sound.h"
|
||||
#include "texturemanager.h"
|
||||
#include "texinfo.h"
|
||||
|
||||
#include "buildtiles.h"
|
||||
|
||||
sectortype* Raze_updatesector(double x, double y, sectortype* sec, double dist)
|
||||
{
|
||||
|
@ -478,7 +481,7 @@ int sector_checktexture(sectortype* sec, int place, int intname)
|
|||
{
|
||||
if (!sec) ThrowAbortException(X_READ_NIL, nullptr);
|
||||
|
||||
auto tex = TexMan.CheckForTexture(FName(ENamedName(intname)).GetChars(), ETextureType::Any);
|
||||
auto tex = TexMan.CheckForTexture(FName(ENamedName(intname)).GetChars(), ETextureType::Any, FTextureManager::TEXMAN_TryAny | FTextureManager::TEXMAN_ReturnAll);
|
||||
return tex == (place == 0 ? sec->ceilingtexture() : sec->floortexture());
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "texturemanager.h"
|
||||
#include "statusbar.h"
|
||||
#include "vm.h"
|
||||
#include "tilesetbuilder.h"
|
||||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
|
@ -74,6 +75,7 @@ IMPLEMENT_POINTERS_END
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
void MarkSprInSect();
|
||||
void tileInitProps();
|
||||
|
||||
size_t DBloodActor::PropagateMark()
|
||||
{
|
||||
|
@ -585,6 +587,9 @@ void GameInterface::loadPalette(void)
|
|||
|
||||
void GameInterface::app_init()
|
||||
{
|
||||
mirrortile = tileGetTextureID(504);
|
||||
tileInitProps();
|
||||
|
||||
GC::AddMarkerFunc(markgcroots);
|
||||
|
||||
InitCheats();
|
||||
|
@ -717,7 +722,11 @@ enum
|
|||
DEFINE_ACTION_FUNCTION(_Blood, OriginalLoadScreen)
|
||||
{
|
||||
static int bLoadScreenCrcMatch = -1;
|
||||
if (bLoadScreenCrcMatch == -1) bLoadScreenCrcMatch = tileGetCRC32(kLoadScreen) == kLoadScreenCRC;
|
||||
if (bLoadScreenCrcMatch == -1)
|
||||
{
|
||||
auto tex = tileGetTexture(kLoadScreen)->GetTexture()->GetImage(); // if this is invalid we have a bigger problem on our hand than the inevitable crash.
|
||||
bLoadScreenCrcMatch = tileGetCRC32(tex) == kLoadScreenCRC;
|
||||
}
|
||||
ACTION_RETURN_INT(bLoadScreenCrcMatch);
|
||||
}
|
||||
|
||||
|
|
|
@ -142,8 +142,8 @@ struct GameInterface : public ::GameInterface
|
|||
void processSprites(tspriteArray& tsprites, const DVector3& view, DAngle viewang, double interpfrac) override;
|
||||
void EnterPortal(DCoreActor* viewer, int type) override;
|
||||
void LeavePortal(DCoreActor* viewer, int type) override;
|
||||
void LoadGameTextures() override;
|
||||
void SetupSpecialTextures() override;
|
||||
void LoadTextureInfo(TilesetBuildInfo& info) override;
|
||||
void SetupSpecialTextures(TilesetBuildInfo&) override;
|
||||
int GetCurrentSkill() override;
|
||||
bool IsQAVInterpTypeValid(const FString& type) override;
|
||||
void AddQAVInterpProps(const int res_id, const FString& interptype, const bool loopable, const TMap<int, TArray<int>>&& ignoredata) override;
|
||||
|
|
|
@ -89,7 +89,10 @@ static void viewBurnTime(int gScale)
|
|||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
int nTile = burnTable[i].nTile;
|
||||
tileUpdatePicnum(&nTile);
|
||||
// This is needed because hud_drawsprite still works with tilenums.
|
||||
FTextureID nID = tileGetTextureID(nTile);
|
||||
tileUpdatePicnum(nID);
|
||||
nTile = legacyTileNum(nID);
|
||||
int nScale = burnTable[i].nScale;
|
||||
if (gScale < 600)
|
||||
{
|
||||
|
|
|
@ -24,6 +24,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
#include "m_fixed.h"
|
||||
#include "filesystem.h"
|
||||
#include "texinfo.h"
|
||||
|
||||
#include "buildtiles.h"
|
||||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
|
|
|
@ -28,6 +28,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "build.h"
|
||||
|
||||
#include "blood.h"
|
||||
#include "hw_voxels.h"
|
||||
#include "tilesetbuilder.h"
|
||||
|
||||
BEGIN_BLD_NS
|
||||
|
||||
|
@ -40,16 +42,20 @@ static int8_t tileShade[kMaxTiles];
|
|||
short voxelIndex[kMaxTiles];
|
||||
|
||||
#define x(a, b) registerName(#a, b);
|
||||
static void SetTileNames()
|
||||
static void SetTileNames(TilesetBuildInfo& info)
|
||||
{
|
||||
auto registerName = [](const char* name, int index)
|
||||
auto registerName = [&](const char* name, int index)
|
||||
{
|
||||
TileFiles.addName(name, index);
|
||||
info.addName(name, index);
|
||||
};
|
||||
#include "namelist.h"
|
||||
// Oh Joy! Plasma Pak changes the tile number of the title screen, but we preferably want mods that use the original one to display it.
|
||||
// Oh Joy! Plasma Pak changes the tile number of the title screen, but we preferably want mods that use the original one to display it, e.g. Cryptic Passage
|
||||
// So let's make this remapping depend on the CRC.
|
||||
if (tileGetCRC32(2518) == 1170870757 && (tileGetCRC32(2046) != 290208654 || tileWidth(2518) == 0)) registerName("titlescreen", 2046);
|
||||
const int OTITLE = 2046, PTITLE = 2518;
|
||||
auto& orgtitle = info.tile[OTITLE];
|
||||
auto& pptile = info.tile[PTITLE];
|
||||
|
||||
if (tileGetCRC32(pptile.tileimage) == 1170870757 && (tileGetCRC32(orgtitle.tileimage) != 290208654 || pptile.tileimage->GetWidth() == 0)) registerName("titlescreen", 2046);
|
||||
else registerName("titlescreen", 2518);
|
||||
}
|
||||
#undef x
|
||||
|
@ -60,7 +66,7 @@ static void SetTileNames()
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void GameInterface::LoadGameTextures()
|
||||
void GameInterface::LoadTextureInfo(TilesetBuildInfo& info)
|
||||
{
|
||||
auto hFile = fileSystem.OpenFileReader("SURFACE.DAT");
|
||||
if (hFile.isOpen())
|
||||
|
@ -86,16 +92,19 @@ void GameInterface::LoadGameTextures()
|
|||
if (voxelIndex[i] >= 0 && voxelIndex[i] < MAXVOXELS)
|
||||
voxreserve.Set(voxelIndex[i]);
|
||||
}
|
||||
SetTileNames();
|
||||
}
|
||||
|
||||
void GameInterface::SetupSpecialTextures()
|
||||
void GameInterface::SetupSpecialTextures(TilesetBuildInfo& info)
|
||||
{
|
||||
SetTileNames(info);
|
||||
// set up all special tiles here, before we fully hook up with the texture manager.
|
||||
tileDelete(504);
|
||||
TileFiles.tileMakeWritable(2342);
|
||||
TileFiles.lock(); // from this point on the tile<->texture associations may not change anymore.
|
||||
mirrortile = tileGetTextureID(504);
|
||||
info.Delete(504);
|
||||
info.MakeWritable(2342);
|
||||
|
||||
}
|
||||
|
||||
void tileInitProps()
|
||||
{
|
||||
for (int i = 0; i < MAXTILES; i++)
|
||||
{
|
||||
auto tex = tileGetTexture(i);
|
||||
|
@ -106,7 +115,6 @@ void GameInterface::SetupSpecialTextures()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
//
|
||||
|
|
|
@ -33,6 +33,8 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
|
|||
#include "dukeactor.h"
|
||||
#include "interpolate.h"
|
||||
|
||||
#include "buildtiles.h"
|
||||
|
||||
BEGIN_DUKE_NS
|
||||
|
||||
static int torchcnt;
|
||||
|
|
|
@ -32,6 +32,8 @@ Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
|
|||
#include "gamefuncs.h"
|
||||
#include "models/modeldata.h"
|
||||
|
||||
#include "buildtiles.h"
|
||||
|
||||
BEGIN_DUKE_NS
|
||||
|
||||
void drawshadows(tspriteArray& tsprites, tspritetype* t, DDukeActor* h)
|
||||
|
|
|
@ -26,7 +26,10 @@ enum
|
|||
GPSPEED = 10,
|
||||
FOF = 13,
|
||||
|
||||
TILE_VIEWSCR = (MAXTILES-5)
|
||||
// hack alert! CYCLER is free for use here as all items of this type get destroyed right on map spawn and this value never gets checked anywhere else.
|
||||
// This avoids overallocation of empty tile slots as a high value slightly below the tile limit would do.
|
||||
// Once we can do texture management without tile numbers this can be done as a regular texture without a valid tile index.
|
||||
TILE_VIEWSCR = CYCLER
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -24,8 +24,7 @@ struct GameInterface : public ::GameInterface
|
|||
const char* Name() override { return "Duke"; }
|
||||
void app_init() override;
|
||||
void loadPalette() override;
|
||||
void LoadGameTextures() override;
|
||||
void SetupSpecialTextures() override;
|
||||
void SetupSpecialTextures(TilesetBuildInfo& info) override;
|
||||
void clearlocalinputstate() override;
|
||||
bool GenerateSavePic() override;
|
||||
void PlayHudSound() override;
|
||||
|
|
|
@ -43,6 +43,7 @@ Modifications for JonoF's port by Jonathon Fowler (jf@jonof.id.au)
|
|||
#include "psky.h"
|
||||
#include "vm.h"
|
||||
#include "thingdef.h"
|
||||
#include "tilesetbuilder.h"
|
||||
|
||||
BEGIN_DUKE_NS
|
||||
|
||||
|
@ -281,11 +282,11 @@ static void setupbackdrop()
|
|||
|
||||
#define x(a, b) registerName(#a, b);
|
||||
#define y(a, b) registerName(#a, b);
|
||||
static void SetTileNames()
|
||||
static void SetTileNames(TilesetBuildInfo& info)
|
||||
{
|
||||
auto registerName = [](const char* name, int index)
|
||||
auto registerName = [&](const char* name, int index)
|
||||
{
|
||||
TileFiles.addName(name, index);
|
||||
info.addName(name, index);
|
||||
};
|
||||
if (!isRR())
|
||||
{
|
||||
|
@ -299,31 +300,29 @@ static void SetTileNames()
|
|||
#undef x
|
||||
#undef y
|
||||
|
||||
void GameInterface::LoadGameTextures()
|
||||
{
|
||||
SetTileNames();
|
||||
}
|
||||
|
||||
void GameInterface::SetupSpecialTextures()
|
||||
void GameInterface::SetupSpecialTextures(TilesetBuildInfo& info)
|
||||
{
|
||||
SetTileNames(info);
|
||||
// set up all special tiles here, before we fully hook up with the texture manager.
|
||||
tileDelete(FOF); // portal marker
|
||||
info.Delete(FOF); // portal marker
|
||||
|
||||
FImageSource* viewscreen;
|
||||
if (!isRR())
|
||||
{
|
||||
tileDelete(560); // the mirror tile.
|
||||
TileFiles.MakeCanvas(TILE_VIEWSCR, tileWidth(502), tileHeight(502));
|
||||
info.Delete(560); // the mirror tile.
|
||||
viewscreen = info.tile[502].tileimage;
|
||||
}
|
||||
else
|
||||
{
|
||||
tileDelete(1089); // the mirror tile.
|
||||
tileDelete(0); // RR uses this as an empty texture
|
||||
TileFiles.tileMakeWritable(2025); // bowling lane pin displays
|
||||
TileFiles.tileMakeWritable(2026);
|
||||
TileFiles.tileMakeWritable(2027);
|
||||
TileFiles.tileMakeWritable(2028);
|
||||
TileFiles.MakeCanvas(TILE_VIEWSCR, tileWidth(1055), tileHeight(1055)); // not used by the game but all the support code is present, meaning maps are free to use it.
|
||||
info.Delete(1089); // the mirror tile.
|
||||
info.Delete(0); // RR uses this as an empty texture
|
||||
info.MakeWritable(2025); // bowling lane pin displays
|
||||
info.MakeWritable(2026);
|
||||
info.MakeWritable(2027);
|
||||
info.MakeWritable(2028);
|
||||
viewscreen = info.tile[1055].tileimage;
|
||||
}
|
||||
TileFiles.lock(); // from this point on the tile<->texture associations may not change anymore.
|
||||
info.MakeCanvas(TILE_VIEWSCR, viewscreen? viewscreen->GetWidth() : 128, viewscreen? viewscreen->GetHeight() : 128);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "types.h"
|
||||
#include "d_net.h"
|
||||
#include "serialize_obj.h"
|
||||
#include "tiletexture.h"
|
||||
|
||||
BEGIN_DUKE_NS
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ source as it is released.
|
|||
#include "global.h"
|
||||
#include "names_d.h"
|
||||
#include "dukeactor.h"
|
||||
#include "buildtiles.h"
|
||||
|
||||
BEGIN_DUKE_NS
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "gamehud.h"
|
||||
#include "global.h"
|
||||
#include "models/modeldata.h"
|
||||
#include "texinfo.h"
|
||||
|
||||
// all inline functions.
|
||||
BEGIN_DUKE_NS
|
||||
|
@ -119,11 +120,9 @@ inline bool inventory(DDukeActor* S)
|
|||
return actorflag(S, SFLAG_INVENTORY);
|
||||
}
|
||||
|
||||
inline int& tileflags(unsigned int tilenum)
|
||||
inline const unsigned& tileflags(unsigned int tilenum)
|
||||
{
|
||||
static int sink = 0;
|
||||
if (tilenum >= MAXTILES) return sink;
|
||||
return TileFiles.tiledata[tilenum].tileflags;
|
||||
return GetExtInfo(tileGetTextureID(tilenum)).flags;
|
||||
}
|
||||
|
||||
inline bool wallswitchcheck(DDukeActor* s)
|
||||
|
|
|
@ -933,5 +933,5 @@ x(DEVELOPERCOMMENTARYON, 5295)
|
|||
x(BOSS5, 5310)
|
||||
x(BOSS5STAYPUT, 5311)
|
||||
x(SERIOUSSAM, 5846)
|
||||
x(VIEWSCR, 30715) // MAXTILES-5
|
||||
x(VIEWSCR, 7) // hijacks CYCLER
|
||||
|
||||
|
|
|
@ -1553,4 +1553,4 @@ x(MAMACLOUD, 8663)
|
|||
x(MAMA, 8705)
|
||||
x(MAMAJIBA, 8890)
|
||||
x(MAMAJIBB, 8895)
|
||||
x(VIEWSCR, 30715) // MAXTILES-5
|
||||
x(VIEWSCR, 7) // hijacks CYCLER
|
||||
|
|
|
@ -77,10 +77,10 @@ void GameInterface::UpdateCameras(double smoothratio)
|
|||
|
||||
if (camsprite->GetOwner() && (p->GetActor()->spr.pos - camsprite->spr.pos).Length() < VIEWSCREEN_ACTIVE_DISTANCE)
|
||||
{
|
||||
auto tex = tileGetTexture(camsprite->spr.picnum);
|
||||
auto tex = TexMan.FindGameTexture("VIEWSCR", ETextureType::Any);
|
||||
if (!tex || !tex->GetTexture()->isCanvas()) return;
|
||||
|
||||
auto canvas = tileGetCanvas(TILE_VIEWSCR);
|
||||
if (!canvas) return;
|
||||
auto canvas = static_cast<FCanvasTexture*>(tex->GetTexture());
|
||||
|
||||
screen->RenderTextureView(canvas, [=](IntRect& rect)
|
||||
{
|
||||
|
|
|
@ -42,7 +42,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "vm.h"
|
||||
#include "razefont.h"
|
||||
|
||||
#include <string>
|
||||
#include "buildtiles.h"
|
||||
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
@ -436,9 +437,7 @@ void uploadCinemaPalettes()
|
|||
|
||||
static int DoStatic(int a, int b)
|
||||
{
|
||||
auto tex = dynamic_cast<FRestorableTile*>(tileGetTexture(kTileLoboLaptop)->GetTexture()->GetImage());
|
||||
if (tex) tex->Reload();
|
||||
auto pixels = GetWritablePixels(tileGetTextureID(kTileLoboLaptop));
|
||||
auto pixels = GetWritablePixels(tileGetTextureID(kTileLoboLaptop), true);
|
||||
|
||||
int y = 160 - a / 2;
|
||||
int left = 81 - b / 2;
|
||||
|
@ -463,10 +462,8 @@ static int DoStatic(int a, int b)
|
|||
|
||||
static int UndoStatic()
|
||||
{
|
||||
auto tex = dynamic_cast<FRestorableTile*>(tileGetTexture(kTileLoboLaptop)->GetTexture()->GetImage());
|
||||
if (tex) tex->Reload();
|
||||
auto texid = tileGetTextureID(kTileLoboLaptop);
|
||||
GetWritablePixels(texid);
|
||||
GetWritablePixels(texid, true);
|
||||
return texid.GetIndex();
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#include "razemenu.h"
|
||||
#include "v_draw.h"
|
||||
#include "interpolate.h"
|
||||
#include "tilesetbuilder.h"
|
||||
#include "psky.h"
|
||||
|
||||
BEGIN_PS_NS
|
||||
|
@ -534,34 +535,29 @@ void LevelFinished()
|
|||
//---------------------------------------------------------------------------
|
||||
|
||||
#define x(a, b) registerName(#a, b);
|
||||
static void SetTileNames()
|
||||
static void SetTileNames(TilesetBuildInfo& info)
|
||||
{
|
||||
auto registerName = [](const char* name, int index)
|
||||
auto registerName = [&](const char* name, int index)
|
||||
{
|
||||
TileFiles.addName(name, index);
|
||||
info.addName(name, index);
|
||||
};
|
||||
#include "namelist.h"
|
||||
}
|
||||
#undef x
|
||||
|
||||
void GameInterface::LoadGameTextures()
|
||||
void GameInterface::SetupSpecialTextures(TilesetBuildInfo& info)
|
||||
{
|
||||
SetTileNames();
|
||||
}
|
||||
|
||||
void GameInterface::SetupSpecialTextures()
|
||||
{
|
||||
TileFiles.tileCreate(kTile4092, kPlasmaWidth, kPlasmaHeight);
|
||||
TileFiles.tileCreate(kTile4093, kPlasmaWidth, kPlasmaHeight);
|
||||
TileFiles.tileCreate(kTileRamsesWorkTile, kSpiritY * 2, kSpiritX * 2);
|
||||
TileFiles.tileMakeWritable(kTileLoboLaptop);
|
||||
SetTileNames(info);
|
||||
info.CreateWritable(kTile4092, kPlasmaWidth, kPlasmaHeight);
|
||||
info.CreateWritable(kTile4093, kPlasmaWidth, kPlasmaHeight);
|
||||
info.CreateWritable(kTileRamsesWorkTile, kSpiritY * 2, kSpiritX * 2);
|
||||
info.MakeWritable(kTileLoboLaptop);
|
||||
for(int i = kTile3603; i < kClockSymbol1 + 145; i++)
|
||||
TileFiles.tileMakeWritable(kTile3603);
|
||||
TileFiles.tileMakeWritable(kEnergy1);
|
||||
TileFiles.tileMakeWritable(kEnergy2);
|
||||
info.MakeWritable(kTile3603);
|
||||
info.MakeWritable(kEnergy1);
|
||||
info.MakeWritable(kEnergy2);
|
||||
for (int i = 0; i < 16; i++)
|
||||
TileFiles.tileMakeWritable(kClockSymbol1);
|
||||
TileFiles.lock();
|
||||
info.MakeWritable(kClockSymbol1);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -209,8 +209,7 @@ struct GameInterface : public ::GameInterface
|
|||
{
|
||||
const char* Name() override { return "Exhumed"; }
|
||||
void app_init() override;
|
||||
void LoadGameTextures() override;
|
||||
void SetupSpecialTextures() override;
|
||||
void SetupSpecialTextures(TilesetBuildInfo& info) override;
|
||||
void clearlocalinputstate() override;
|
||||
void loadPalette() override;
|
||||
bool GenerateSavePic() override;
|
||||
|
|
|
@ -41,6 +41,7 @@ not load" error messages.
|
|||
#include "sounds.h"
|
||||
#include "network.h"
|
||||
#include "precache.h"
|
||||
#include "texinfo.h"
|
||||
|
||||
BEGIN_SW_NS
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
|||
#include "razefont.h"
|
||||
#include "models/modeldata.h"
|
||||
|
||||
#include "buildtiles.h"
|
||||
|
||||
extern DCoreActor* wall_to_sprite_actors[8];
|
||||
|
||||
BEGIN_SW_NS
|
||||
|
|
|
@ -49,6 +49,7 @@ Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
|||
#include "i_interface.h"
|
||||
#include "psky.h"
|
||||
#include "startscreen.h"
|
||||
#include "tilesetbuilder.h"
|
||||
|
||||
|
||||
|
||||
|
@ -209,46 +210,39 @@ int ThemeTrack[6];
|
|||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define x(a, b) registerName(#a, b);
|
||||
static void SetTileNames()
|
||||
static void SetTileNames(TilesetBuildInfo& info)
|
||||
{
|
||||
auto registerName = [](const char* name, int index)
|
||||
auto registerName = [&](const char* name, int index)
|
||||
{
|
||||
TileFiles.addName(name, index);
|
||||
info.addName(name, index);
|
||||
};
|
||||
#include "namelist.h"
|
||||
}
|
||||
#undef x
|
||||
|
||||
void GameInterface::LoadGameTextures()
|
||||
void GameInterface::LoadTextureInfo(TilesetBuildInfo& info)
|
||||
{
|
||||
LoadKVXFromScript("swvoxfil.txt"); // Load voxels from script file
|
||||
SetTileNames();
|
||||
}
|
||||
|
||||
void GameInterface::SetupSpecialTextures()
|
||||
enum
|
||||
{
|
||||
enum
|
||||
{
|
||||
FAF_PLACE_MIRROR_PIC = 341,
|
||||
FAF_MIRROR_PIC = 2356
|
||||
};
|
||||
FAF_PLACE_MIRROR_PIC = 341,
|
||||
FAF_MIRROR_PIC = 2356
|
||||
};
|
||||
|
||||
tileDelete(MIRROR); // mirror
|
||||
void GameInterface::SetupSpecialTextures(TilesetBuildInfo& info)
|
||||
{
|
||||
info.Delete(MIRROR); // mirror
|
||||
for (int i = 0; i < MAXMIRRORS; i++)
|
||||
{
|
||||
tileDelete(i + MIRRORLABEL);
|
||||
TileFiles.MakeCanvas(CAMSPRITE + i, 128, 114);
|
||||
info.Delete(i + MIRRORLABEL);
|
||||
info.MakeCanvas(CAMSPRITE + i, 128, 114);
|
||||
}
|
||||
// make these two unique, they are empty by default.
|
||||
tileDelete(FAF_MIRROR_PIC);
|
||||
tileDelete(FAF_MIRROR_PIC + 1);
|
||||
TileFiles.lock();
|
||||
|
||||
// these are frequently checked markers.
|
||||
FAFPlaceMirrorPic[0] = tileGetTextureID(FAF_PLACE_MIRROR_PIC);
|
||||
FAFPlaceMirrorPic[1] = tileGetTextureID(FAF_PLACE_MIRROR_PIC + 1);
|
||||
FAFMirrorPic[0] = tileGetTextureID(FAF_MIRROR_PIC);
|
||||
FAFMirrorPic[1] = tileGetTextureID(FAF_MIRROR_PIC + 1);
|
||||
info.Delete(FAF_MIRROR_PIC);
|
||||
info.Delete(FAF_MIRROR_PIC + 1);
|
||||
SetTileNames(info);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
|
@ -258,6 +252,12 @@ void GameInterface::SetupSpecialTextures()
|
|||
|
||||
void GameInterface::app_init()
|
||||
{
|
||||
// these are frequently checked markers.
|
||||
FAFPlaceMirrorPic[0] = tileGetTextureID(FAF_PLACE_MIRROR_PIC);
|
||||
FAFPlaceMirrorPic[1] = tileGetTextureID(FAF_PLACE_MIRROR_PIC + 1);
|
||||
FAFMirrorPic[0] = tileGetTextureID(FAF_MIRROR_PIC);
|
||||
FAFMirrorPic[1] = tileGetTextureID(FAF_MIRROR_PIC + 1);
|
||||
|
||||
GC::AddMarkerFunc(markgcroots);
|
||||
|
||||
GameTicRate = TICS_PER_SEC / synctics;
|
||||
|
|
|
@ -1654,8 +1654,8 @@ struct GameInterface : public ::GameInterface
|
|||
{
|
||||
const char* Name() override { return "ShadowWarrior"; }
|
||||
void app_init() override;
|
||||
void LoadGameTextures() override;
|
||||
void SetupSpecialTextures() override;
|
||||
void LoadTextureInfo(TilesetBuildInfo& info) override;
|
||||
void SetupSpecialTextures(TilesetBuildInfo& info) override;
|
||||
void loadPalette() override;
|
||||
void clearlocalinputstate() override;
|
||||
void FreeLevelData() override;
|
||||
|
|
|
@ -397,12 +397,13 @@ void JS_InitMirrors(void)
|
|||
/////////////////////////////////////////////////////
|
||||
void drawroomstotile(const DVector3& pos, DAngle ang, DAngle horiz, sectortype* dacursect, short tilenume, double smoothratio)
|
||||
{
|
||||
auto canvas = tileGetCanvas(tilenume);
|
||||
auto tex = tileGetTexture(tilenume);
|
||||
auto canvas = dynamic_cast<FCanvasTexture*>(tex->GetTexture());
|
||||
if (!canvas) return;
|
||||
|
||||
screen->RenderTextureView(canvas, [=](IntRect& rect)
|
||||
{
|
||||
render_camtex(nullptr, pos, dacursect, DRotator(horiz, ang, nullAngle), tileGetTexture(tilenume), rect, smoothratio);
|
||||
render_camtex(nullptr, pos, dacursect, DRotator(horiz, ang, nullAngle), tex, rect, smoothratio);
|
||||
});
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue