1 #ifndef __TEXTURES_H 2 #define __TEXTURES_H 3 4 #include "doomtype.h" 5 6 class FBitmap; 7 struct FRemapTable; 8 struct FCopyInfo; 9 class FScanner; 10 struct PClass; 11 class FArchive; 12 13 // Texture IDs 14 class FTextureManager; 15 class FTerrainTypeArray; 16 17 class FTextureID 18 { 19 friend class FTextureManager; 20 friend FArchive &operator<< (FArchive &arc, FTextureID &tex); 21 friend FTextureID GetHUDIcon(const PClass *cls); 22 friend void R_InitSpriteDefs (); 23 24 public: FTextureID()25 FTextureID() throw() {} isNull()26 bool isNull() const { return texnum == 0; } isValid()27 bool isValid() const { return texnum > 0; } Exists()28 bool Exists() const { return texnum >= 0; } SetInvalid()29 void SetInvalid() { texnum = -1; } SetNull()30 void SetNull() { texnum = 0; } 31 bool operator ==(const FTextureID &other) const { return texnum == other.texnum; } 32 bool operator !=(const FTextureID &other) const { return texnum != other.texnum; } 33 FTextureID operator +(int offset) throw(); GetIndex()34 int GetIndex() const { return texnum; } // Use this only if you absolutely need the index! 35 36 // The switch list needs these to sort the switches by texture index 37 int operator -(FTextureID other) const { return texnum - other.texnum; } 38 bool operator < (FTextureID other) const { return texnum < other.texnum; } 39 bool operator > (FTextureID other) const { return texnum > other.texnum; } 40 41 protected: FTextureID(int num)42 FTextureID(int num) { texnum = num; } 43 private: 44 int texnum; 45 }; 46 47 class FNullTextureID : public FTextureID 48 { 49 public: FNullTextureID()50 FNullTextureID() : FTextureID(0) {} 51 }; 52 53 FArchive &operator<< (FArchive &arc, FTextureID &tex); 54 55 // 56 // Animating textures and planes 57 // 58 // [RH] Expanded to work with a Hexen ANIMDEFS lump 59 // 60 61 struct FAnimDef 62 { 63 FTextureID BasePic; 64 WORD NumFrames; 65 WORD CurFrame; 66 BYTE AnimType; 67 bool bDiscrete; // taken out of AnimType to have better control 68 DWORD SwitchTime; // Time to advance to next frame 69 struct FAnimFrame 70 { 71 DWORD SpeedMin; // Speeds are in ms, not tics 72 DWORD SpeedRange; 73 FTextureID FramePic; 74 } Frames[1]; 75 enum 76 { 77 ANIM_Forward, 78 ANIM_Backward, 79 ANIM_OscillateUp, 80 ANIM_OscillateDown, 81 ANIM_Random 82 }; 83 84 void SetSwitchTime (DWORD mstime); 85 }; 86 87 struct FSwitchDef 88 { 89 FTextureID PreTexture; // texture to switch from 90 FSwitchDef *PairDef; // switch def to use to return to PreTexture 91 WORD NumFrames; // # of animation frames 92 bool QuestPanel; // Special texture for Strife mission 93 int Sound; // sound to play at start of animation. Changed to int to avoiud having to include s_sound here. 94 struct frame // Array of times followed by array of textures 95 { // actual length of each array is <NumFrames> 96 WORD TimeMin; 97 WORD TimeRnd; 98 FTextureID Texture; 99 } frames[1]; 100 }; 101 102 struct FDoorAnimation 103 { 104 FTextureID BaseTexture; 105 FTextureID *TextureFrames; 106 int NumTextureFrames; 107 FName OpenSound; 108 FName CloseSound; 109 }; 110 111 // Patches. 112 // A patch holds one or more columns. 113 // Patches are used for sprites and all masked pictures, and we compose 114 // textures from the TEXTURE1/2 lists of patches. 115 struct patch_t 116 { 117 SWORD width; // bounding box size 118 SWORD height; 119 SWORD leftoffset; // pixels to the left of origin 120 SWORD topoffset; // pixels below the origin 121 DWORD columnofs[]; // only [width] used 122 // the [0] is &columnofs[width] 123 }; 124 125 class FileReader; 126 127 // All FTextures present their data to the world in 8-bit format, but if 128 // the source data is something else, this is it. 129 enum FTextureFormat 130 { 131 TEX_Pal, 132 TEX_Gray, 133 TEX_RGB, // Actually ARGB 134 TEX_DXT1, 135 TEX_DXT2, 136 TEX_DXT3, 137 TEX_DXT4, 138 TEX_DXT5, 139 }; 140 141 class FNativeTexture; 142 143 // Base texture class 144 class FTexture 145 { 146 public: 147 static FTexture *CreateTexture(const char *name, int lumpnum, int usetype); 148 static FTexture *CreateTexture(int lumpnum, int usetype); 149 virtual ~FTexture (); 150 151 SWORD LeftOffset, TopOffset; 152 153 BYTE WidthBits, HeightBits; 154 155 fixed_t xScale; 156 fixed_t yScale; 157 158 int SourceLump; 159 FTextureID id; 160 161 FString Name; 162 BYTE UseType; // This texture's primary purpose 163 164 BYTE bNoDecals:1; // Decals should not stick to texture 165 BYTE bNoRemap0:1; // Do not remap color 0 (used by front layer of parallax skies) 166 BYTE bWorldPanning:1; // Texture is panned in world units rather than texels 167 BYTE bMasked:1; // Texture (might) have holes 168 BYTE bAlphaTexture:1; // Texture is an alpha channel without color information 169 BYTE bHasCanvas:1; // Texture is based off FCanvasTexture 170 BYTE bWarped:2; // This is a warped texture. Used to avoid multiple warps on one texture 171 BYTE bComplex:1; // Will be used to mark extended MultipatchTextures that have to be 172 // fully composited before subjected to any kind of postprocessing instead of 173 // doing it per patch. 174 BYTE bMultiPatch:1; // This is a multipatch texture (we really could use real type info for textures...) 175 BYTE bKeepAround:1; // This texture was used as part of a multi-patch texture. Do not free it. 176 177 WORD Rotations; 178 SWORD SkyOffset; 179 180 enum // UseTypes 181 { 182 TEX_Any, 183 TEX_Wall, 184 TEX_Flat, 185 TEX_Sprite, 186 TEX_WallPatch, 187 TEX_Build, 188 TEX_SkinSprite, 189 TEX_Decal, 190 TEX_MiscPatch, 191 TEX_FontChar, 192 TEX_Override, // For patches between TX_START/TX_END 193 TEX_Autopage, // Automap background - used to enable the use of FAutomapTexture 194 TEX_SkinGraphic, 195 TEX_Null, 196 TEX_FirstDefined, 197 }; 198 199 struct Span 200 { 201 WORD TopOffset; 202 WORD Length; // A length of 0 terminates this column 203 }; 204 205 // Returns a single column of the texture 206 virtual const BYTE *GetColumn (unsigned int column, const Span **spans_out) = 0; 207 208 // Returns the whole texture, stored in column-major order 209 virtual const BYTE *GetPixels () = 0; 210 211 virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate=0, FCopyInfo *inf = NULL); 212 int CopyTrueColorTranslated(FBitmap *bmp, int x, int y, int rotate, FRemapTable *remap, FCopyInfo *inf = NULL); 213 virtual bool UseBasePalette(); GetSourceLump()214 virtual int GetSourceLump() { return SourceLump; } 215 virtual FTexture *GetRedirect(bool wantwarped); 216 virtual FTexture *GetRawTexture(); // for FMultiPatchTexture to override 217 218 virtual void Unload () = 0; 219 220 // Returns the native pixel format for this image 221 virtual FTextureFormat GetFormat(); 222 223 // Returns a native 3D representation of the texture 224 FNativeTexture *GetNative(bool wrapping); 225 226 // Frees the native 3D representation of the texture 227 void KillNative(); 228 229 // Fill the native texture buffer with pixel data for this image 230 virtual void FillBuffer(BYTE *buff, int pitch, int height, FTextureFormat fmt); 231 GetWidth()232 int GetWidth () { return Width; } GetHeight()233 int GetHeight () { return Height; } 234 GetScaledWidth()235 int GetScaledWidth () { int foo = (Width << 17) / xScale; return (foo >> 1) + (foo & 1); } GetScaledHeight()236 int GetScaledHeight () { int foo = (Height << 17) / yScale; return (foo >> 1) + (foo & 1); } GetScaledHeight(fixed_t scale)237 int GetScaledHeight(fixed_t scale) { int foo = (Height << 17) / scale; return (foo >> 1) + (foo & 1); } GetScaledWidthDouble()238 double GetScaledWidthDouble () { return (Width * 65536.) / xScale; } GetScaledHeightDouble()239 double GetScaledHeightDouble () { return (Height * 65536.) / yScale; } 240 GetScaledLeftOffset()241 int GetScaledLeftOffset () { int foo = (LeftOffset << 17) / xScale; return (foo >> 1) + (foo & 1); } GetScaledTopOffset()242 int GetScaledTopOffset () { int foo = (TopOffset << 17) / yScale; return (foo >> 1) + (foo & 1); } GetScaledLeftOffsetDouble()243 double GetScaledLeftOffsetDouble() { return (LeftOffset * 65536.) / xScale; } GetScaledTopOffsetDouble()244 double GetScaledTopOffsetDouble() { return (TopOffset * 65536.) / yScale; } 245 246 virtual void SetFrontSkyLayer(); 247 248 void CopyToBlock (BYTE *dest, int dwidth, int dheight, int x, int y, const BYTE *translation=NULL) 249 { 250 CopyToBlock(dest, dwidth, dheight, x, y, 0, translation); 251 } 252 253 void CopyToBlock (BYTE *dest, int dwidth, int dheight, int x, int y, int rotate, const BYTE *translation=NULL); 254 255 // Returns true if the next call to GetPixels() will return an image different from the 256 // last call to GetPixels(). This should be considered valid only if a call to CheckModified() 257 // is immediately followed by a call to GetPixels(). 258 virtual bool CheckModified (); 259 260 static void InitGrayMap(); 261 CopySize(FTexture * BaseTexture)262 void CopySize(FTexture *BaseTexture) 263 { 264 Width = BaseTexture->GetWidth(); 265 Height = BaseTexture->GetHeight(); 266 TopOffset = BaseTexture->TopOffset; 267 LeftOffset = BaseTexture->LeftOffset; 268 WidthBits = BaseTexture->WidthBits; 269 HeightBits = BaseTexture->HeightBits; 270 xScale = BaseTexture->xScale; 271 yScale = BaseTexture->yScale; 272 WidthMask = (1 << WidthBits) - 1; 273 } 274 275 void SetScaledSize(int fitwidth, int fitheight); 276 277 virtual void HackHack (int newheight); // called by FMultipatchTexture to discover corrupt patches. 278 279 protected: 280 WORD Width, Height, WidthMask; 281 static BYTE GrayMap[256]; 282 FNativeTexture *Native; 283 284 FTexture (const char *name = NULL, int lumpnum = -1); 285 286 Span **CreateSpans (const BYTE *pixels) const; 287 void FreeSpans (Span **spans) const; 288 void CalcBitSize (); CopyInfo(FTexture * other)289 void CopyInfo(FTexture *other) 290 { 291 CopySize(other); 292 bNoDecals = other->bNoDecals; 293 Rotations = other->Rotations; 294 } 295 296 public: 297 static void FlipSquareBlock (BYTE *block, int x, int y); 298 static void FlipSquareBlockRemap (BYTE *block, int x, int y, const BYTE *remap); 299 static void FlipNonSquareBlock (BYTE *blockto, const BYTE *blockfrom, int x, int y, int srcpitch); 300 static void FlipNonSquareBlockRemap (BYTE *blockto, const BYTE *blockfrom, int x, int y, int srcpitch, const BYTE *remap); 301 302 friend class D3DTex; 303 }; 304 305 306 // Texture manager 307 class FTextureManager 308 { 309 public: 310 FTextureManager (); 311 ~FTextureManager (); 312 313 // Get texture without translation 314 FTexture *operator[] (FTextureID texnum) 315 { 316 if ((unsigned)texnum.GetIndex() >= Textures.Size()) return NULL; 317 return Textures[texnum.GetIndex()].Texture; 318 } 319 FTexture *operator[] (const char *texname) 320 { 321 FTextureID texnum = GetTexture (texname, FTexture::TEX_MiscPatch); 322 if (!texnum.Exists()) return NULL; 323 return Textures[texnum.GetIndex()].Texture; 324 } ByIndex(int i)325 FTexture *ByIndex(int i) 326 { 327 if (unsigned(i) >= Textures.Size()) return NULL; 328 return Textures[i].Texture; 329 } 330 FTexture *FindTexture(const char *texname, int usetype = FTexture::TEX_MiscPatch, BITFIELD flags = TEXMAN_TryAny); 331 332 // Get texture with translation operator()333 FTexture *operator() (FTextureID texnum, bool withpalcheck=false) 334 { 335 if ((size_t)texnum.texnum >= Textures.Size()) return NULL; 336 int picnum = Translation[texnum.texnum]; 337 if (withpalcheck) 338 { 339 picnum = PalCheck(picnum).GetIndex(); 340 } 341 return Textures[picnum].Texture; 342 } operator()343 FTexture *operator() (const char *texname) 344 { 345 FTextureID texnum = GetTexture (texname, FTexture::TEX_MiscPatch); 346 if (texnum.texnum == -1) return NULL; 347 return Textures[Translation[texnum.texnum]].Texture; 348 } 349 ByIndexTranslated(int i)350 FTexture *ByIndexTranslated(int i) 351 { 352 if (unsigned(i) >= Textures.Size()) return NULL; 353 return Textures[Translation[i]].Texture; 354 } 355 356 FTextureID PalCheck(FTextureID tex); 357 358 enum 359 { 360 TEXMAN_TryAny = 1, 361 TEXMAN_Overridable = 2, 362 TEXMAN_ReturnFirst = 4, 363 TEXMAN_AllowSkins = 8, 364 TEXMAN_ShortNameOnly = 16, 365 TEXMAN_DontCreate = 32 366 }; 367 368 enum 369 { 370 HIT_Wall = 1, 371 HIT_Flat = 2, 372 HIT_Sky = 4, 373 HIT_Sprite = 8, 374 375 HIT_Columnmode = HIT_Wall|HIT_Sky|HIT_Sprite 376 }; 377 378 FTextureID CheckForTexture (const char *name, int usetype, BITFIELD flags=TEXMAN_TryAny); 379 FTextureID GetTexture (const char *name, int usetype, BITFIELD flags=0); 380 int ListTextures (const char *name, TArray<FTextureID> &list); 381 382 void AddTexturesLump (const void *lumpdata, int lumpsize, int deflumpnum, int patcheslump, int firstdup=0, bool texture1=false); 383 void AddTexturesLumps (int lump1, int lump2, int patcheslump); 384 void AddGroup(int wadnum, int ns, int usetype); 385 void AddPatches (int lumpnum); 386 void AddHiresTextures (int wadnum); 387 void LoadTextureDefs(int wadnum, const char *lumpname); 388 void ParseXTexture(FScanner &sc, int usetype); 389 void SortTexturesByType(int start, int end); 390 bool AreTexturesCompatible (FTextureID picnum1, FTextureID picnum2); 391 392 FTextureID CreateTexture (int lumpnum, int usetype=FTexture::TEX_Any); // Also calls AddTexture 393 FTextureID AddTexture (FTexture *texture); GetDefaultTexture()394 FTextureID GetDefaultTexture() const { return DefaultTexture; } 395 396 void LoadTextureX(int wadnum); 397 void AddTexturesForWad(int wadnum); 398 void Init(); 399 void DeleteAll(); 400 401 // Replaces one texture with another. The new texture will be assigned 402 // the same name, slot, and use type as the texture it is replacing. 403 // The old texture will no longer be managed. Set free true if you want 404 // the old texture to be deleted or set it false if you want it to 405 // be left alone in memory. You will still need to delete it at some 406 // point, because the texture manager no longer knows about it. 407 // This function can be used for such things as warping textures. 408 void ReplaceTexture (FTextureID picnum, FTexture *newtexture, bool free); 409 410 void UnloadAll (); 411 NumTextures()412 int NumTextures () const { return (int)Textures.Size(); } 413 void PrecacheLevel (void); 414 415 void WriteTexture (FArchive &arc, int picnum); 416 int ReadTexture (FArchive &arc); 417 418 void UpdateAnimations (DWORD mstime); 419 int GuesstimateNumTextures (); 420 421 FSwitchDef *FindSwitch (FTextureID texture); 422 FDoorAnimation *FindAnimatedDoor (FTextureID picnum); 423 424 private: 425 426 // texture counting 427 int CountTexturesX (); 428 int CountLumpTextures (int lumpnum); 429 430 // Build tiles 431 void AddTiles (void *tiles); 432 int CountTiles (void *tiles); 433 int CountBuildTiles (); 434 void InitBuildTiles (); 435 436 // Animation stuff 437 FAnimDef *AddAnim (FAnimDef *anim); 438 void FixAnimations (); 439 void InitAnimated (); 440 void InitAnimDefs (); 441 FAnimDef *AddSimpleAnim (FTextureID picnum, int animcount, DWORD speedmin, DWORD speedrange=0); 442 FAnimDef *AddComplexAnim (FTextureID picnum, const TArray<FAnimDef::FAnimFrame> &frames); 443 void ParseAnim (FScanner &sc, int usetype); 444 FAnimDef *ParseRangeAnim (FScanner &sc, FTextureID picnum, int usetype, bool missing); 445 void ParsePicAnim (FScanner &sc, FTextureID picnum, int usetype, bool missing, TArray<FAnimDef::FAnimFrame> &frames); 446 void ParseWarp(FScanner &sc); 447 void ParseCameraTexture(FScanner &sc); 448 FTextureID ParseFramenum (FScanner &sc, FTextureID basepicnum, int usetype, bool allowMissing); 449 void ParseTime (FScanner &sc, DWORD &min, DWORD &max); Texture(FTextureID id)450 FTexture *Texture(FTextureID id) { return Textures[id.GetIndex()].Texture; } 451 void SetTranslation (FTextureID fromtexnum, FTextureID totexnum); 452 void ParseAnimatedDoor(FScanner &sc); 453 454 void InitPalettedVersions(); 455 456 // Switches 457 458 void InitSwitchList (); 459 void ProcessSwitchDef (FScanner &sc); 460 FSwitchDef *ParseSwitchDef (FScanner &sc, bool ignoreBad); 461 void AddSwitchPair (FSwitchDef *def1, FSwitchDef *def2); 462 463 struct TextureHash 464 { 465 FTexture *Texture; 466 int HashNext; 467 }; 468 enum { HASH_END = -1, HASH_SIZE = 1027 }; 469 TArray<TextureHash> Textures; 470 TArray<int> Translation; 471 int HashFirst[HASH_SIZE]; 472 FTextureID DefaultTexture; 473 TArray<int> FirstTextureForFile; 474 TMap<int,int> PalettedVersions; // maps from normal -> paletted version 475 476 TArray<FAnimDef *> mAnimations; 477 TArray<FSwitchDef *> mSwitchDefs; 478 TArray<FDoorAnimation> mAnimatedDoors; 479 TArray<BYTE *> BuildTileFiles; 480 }; 481 482 // A texture that doesn't really exist 483 class FDummyTexture : public FTexture 484 { 485 public: 486 FDummyTexture (); 487 const BYTE *GetColumn (unsigned int column, const Span **spans_out); 488 const BYTE *GetPixels (); 489 void Unload (); 490 void SetSize (int width, int height); 491 }; 492 493 // A texture that returns a wiggly version of another texture. 494 class FWarpTexture : public FTexture 495 { 496 public: 497 FWarpTexture (FTexture *source); 498 ~FWarpTexture (); 499 500 virtual int CopyTrueColorPixels(FBitmap *bmp, int x, int y, int rotate=0, FCopyInfo *inf = NULL); 501 const BYTE *GetColumn (unsigned int column, const Span **spans_out); 502 const BYTE *GetPixels (); 503 void Unload (); 504 bool CheckModified (); 505 GetSpeed()506 float GetSpeed() const { return Speed; } GetSourceLump()507 int GetSourceLump() { return SourcePic->GetSourceLump(); } SetSpeed(float fac)508 void SetSpeed(float fac) { Speed = fac; } 509 FTexture *GetRedirect(bool wantwarped); 510 511 DWORD GenTime; 512 protected: 513 FTexture *SourcePic; 514 BYTE *Pixels; 515 Span **Spans; 516 float Speed; 517 518 virtual void MakeTexture (DWORD time); 519 }; 520 521 // [GRB] Eternity-like warping 522 class FWarp2Texture : public FWarpTexture 523 { 524 public: 525 FWarp2Texture (FTexture *source); 526 527 protected: 528 void MakeTexture (DWORD time); 529 }; 530 531 // A texture that can be drawn to. 532 class DSimpleCanvas; 533 class AActor; 534 class FArchive; 535 536 class FCanvasTexture : public FTexture 537 { 538 public: 539 FCanvasTexture (const char *name, int width, int height); 540 ~FCanvasTexture (); 541 542 const BYTE *GetColumn (unsigned int column, const Span **spans_out); 543 const BYTE *GetPixels (); 544 void Unload (); 545 bool CheckModified (); NeedUpdate()546 void NeedUpdate() { bNeedsUpdate=true; } SetUpdated()547 void SetUpdated() { bNeedsUpdate = false; bDidUpdate = true; bFirstUpdate = false; } GetCanvas()548 DSimpleCanvas *GetCanvas() { return Canvas; } 549 void MakeTexture (); 550 551 protected: 552 553 DSimpleCanvas *Canvas; 554 BYTE *Pixels; 555 Span DummySpans[2]; 556 bool bNeedsUpdate; 557 bool bDidUpdate; 558 bool bPixelsAllocated; 559 public: 560 bool bFirstUpdate; 561 562 563 friend struct FCanvasTextureInfo; 564 }; 565 566 extern FTextureManager TexMan; 567 568 #endif 569 570 571