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