#pragma once #include #include "tarray.h" #include "textureid.h" #include "textures.h" #include "basics.h" #include "texmanip.h" #include "name.h" class FxAddSub; struct BuildInfo; class FMultipatchTextureBuilder; class FScanner; // Texture manager class FTextureManager { void (*progressFunc)(); friend class FxAddSub; // needs access to do a bounds check on the texture ID. public: FTextureManager (); ~FTextureManager (); private: int ResolveLocalizedTexture(int texnum); int ResolveTextureIndex(int texnum, bool animate, bool localize) { if ((unsigned)texnum >= Textures.Size()) return -1; if (animate) texnum = Translation[texnum]; if (localize && Textures[texnum].HasLocalization) texnum = ResolveLocalizedTexture(texnum); return texnum; } FGameTexture *InternalGetTexture(int texnum, bool animate, bool localize) { texnum = ResolveTextureIndex(texnum, animate, localize); if (texnum == -1) return nullptr; return Textures[texnum].Texture; } public: FTextureID ResolveTextureIndex(FTextureID texid, bool animate, bool localize) { return FSetTextureID(ResolveTextureIndex(texid.GetIndex(), animate, localize)); } // This only gets used in UI code so we do not need PALVERS handling. FGameTexture* GetGameTextureByName(const char *name, bool animate = false, int flags = 0) { FTextureID texnum = GetTextureID(name, ETextureType::MiscPatch, flags); return InternalGetTexture(texnum.GetIndex(), animate, true); } FGameTexture* GetGameTexture(FTextureID texnum, bool animate = false) { return InternalGetTexture(texnum.GetIndex(), animate, true); } FGameTexture* GetPalettedTexture(FTextureID texnum, bool animate = false, bool allowsubstitute = true) { auto texid = ResolveTextureIndex(texnum.GetIndex(), animate, true); if (texid == -1) return nullptr; if (allowsubstitute && Textures[texid].Paletted > 0) texid = Textures[texid].Paletted; return Textures[texid].Texture; } FGameTexture* GameByIndex(int i, bool animate = false) { return InternalGetTexture(i, animate, true); } FGameTexture* FindGameTexture(const char* texname, ETextureType usetype = ETextureType::MiscPatch, BITFIELD flags = TEXMAN_TryAny); bool OkForLocalization(FTextureID texnum, const char *substitute, int locnum); void FlushAll(); FTextureID GetFrontSkyLayer(FTextureID); FTextureID GetRawTexture(FTextureID tex, bool dontlookup = false); void SetRawTexture(FTextureID texid) { int texidx = texid.GetIndex(); if ((unsigned)texidx < Textures.Size()) { Textures[texidx].RawTexture = texidx; } } enum { TEXMAN_TryAny = 1, TEXMAN_Overridable = 2, TEXMAN_ReturnFirst = 4, TEXMAN_AllowSkins = 8, TEXMAN_ShortNameOnly = 16, TEXMAN_DontCreate = 32, TEXMAN_Localize = 64, TEXMAN_ForceLookup = 128, TEXMAN_NoAlias = 256, }; enum { HIT_Wall = 1, HIT_Flat = 2, HIT_Sky = 4, HIT_Sprite = 8, HIT_Columnmode = HIT_Wall|HIT_Sky|HIT_Sprite }; FTextureID CheckForTexture (const char *name, ETextureType usetype, BITFIELD flags=TEXMAN_TryAny); FTextureID GetTextureID (const char *name, ETextureType usetype, BITFIELD flags=0); int ListTextures (const char *name, TArray &list, bool listall = false); void AddGroup(int wadnum, int ns, ETextureType usetype); void AddPatches (int lumpnum); void AddHiresTextures (int wadnum); void LoadTextureDefs(int wadnum, const char *lumpname, FMultipatchTextureBuilder &build); void ParseColorization(FScanner& sc); void ParseTextureDef(int remapLump, FMultipatchTextureBuilder &build); void SortTexturesByType(int start, int end); bool AreTexturesCompatible (FTextureID picnum1, FTextureID picnum2); void AddLocalizedVariants(); FTextureID CreateTexture (int lumpnum, ETextureType usetype=ETextureType::Any); // Also calls AddTexture FTextureID AddGameTexture(FGameTexture* texture, bool addtohash = true); FTextureID GetDefaultTexture() const { return DefaultTexture; } void LoadTextureX(int wadnum, FMultipatchTextureBuilder &build); void AddTexturesForWad(int wadnum, FMultipatchTextureBuilder &build); void Init(); void AddTextures(void (*progressFunc_)(), void (*checkForHacks)(BuildInfo&), void (*customtexturehandler)() = nullptr); void DeleteAll(); void ReplaceTexture (FTextureID picnum, FGameTexture *newtexture, bool free); int NumTextures () const { return (int)Textures.Size(); } int GuesstimateNumTextures (); TextureManipulation* GetTextureManipulation(FName name) { return tmanips.CheckKey(name); } void InsertTextureManipulation(FName cname, TextureManipulation tm) { tmanips.Insert(cname, tm); } void RemoveTextureManipulation(FName cname) { tmanips.Remove(cname); } void AddAlias(const char* name, FGameTexture* tex); private: // texture counting int CountTexturesX (); int CountLumpTextures (int lumpnum); void AdjustSpriteOffsets(); // Build tiles //int CountBuildTiles (); public: TArray& GetNewBuildTileData() { BuildTileData.Reserve(1); return BuildTileData.Last(); } FGameTexture* GameTexture(FTextureID id) { return Textures[id.GetIndex()].Texture; } void SetTranslation(FTextureID fromtexnum, FTextureID totexnum); private: void InitPalettedVersions(); // Switches struct TextureHash { FGameTexture* Texture; int Paletted; // redirection to paletted variant int FrontSkyLayer; // and front sky layer, int RawTexture; int HashNext; bool HasLocalization; }; enum { HASH_END = -1, HASH_SIZE = 1027 }; TArray Textures; TMap LocalizedTextures; int HashFirst[HASH_SIZE]; FTextureID DefaultTexture; TArray FirstTextureForFile; TArray > BuildTileData; TArray Translation; TMap tmanips; TMap aliases; public: short sintable[2048]; // for texture warping enum { SINMASK = 2047 }; FTextureID glPart2; FTextureID glPart; FTextureID mirrorTexture; bool usefullnames; }; extern FTextureManager TexMan;