- Added rotation 90° angles only) and mirroring to the Multipatch texture

composition code.
- Fixed: The game crashed when a level was ended while a player was morphed
  by a powerup. 

SVN r912 (trunk)
This commit is contained in:
Christoph Oelckers 2008-04-14 18:51:05 +00:00
parent b54b9bad7a
commit adc9f090ef
14 changed files with 218 additions and 121 deletions

View file

@ -1,4 +1,8 @@
April 14, 2008 (Changes by Graf Zahl) April 14, 2008 (Changes by Graf Zahl)
- Added rotation 90° angles only) and mirroring to the Multipatch texture
composition code.
- Fixed: The game crashed when a level was ended while a player was morphed
by a powerup.
- Fixed: A_VileAttack positioned the fire on the wrong side of the target. - Fixed: A_VileAttack positioned the fire on the wrong side of the target.
- Reorganized the HackHack code so that the image creation was moved into - Reorganized the HackHack code so that the image creation was moved into
MakeTexture. This was necessary because Unload deleted the pixel data MakeTexture. This was necessary because Unload deleted the pixel data
@ -19,7 +23,7 @@ April 14, 2008 (Changes by Graf Zahl)
- Fixed: A few calls to P_SpawnPlayerMissile passed 0 as angle - Fixed: A few calls to P_SpawnPlayerMissile passed 0 as angle
April 13, 2008 (Changes by Graf Zahl) April 13, 2008 (Changes by Graf Zahl)
- Fixed a few bufs in the parser for composite textures. - Fixed a few bugs in the parser for composite textures.
- Changed: When loading Zips all patches in the patches/ directory should - Changed: When loading Zips all patches in the patches/ directory should
be loaded, not only those used by a texture in TEXTUREx. be loaded, not only those used by a texture in TEXTUREx.
- Disabled timidity_mastervolume for the internal Timidity again because - Disabled timidity_mastervolume for the internal Timidity again because

View file

@ -211,7 +211,7 @@ private:
void Unload (); void Unload ();
~FDoomStatusBarTexture (); ~FDoomStatusBarTexture ();
void SetPlayerRemap(FRemapTable *remap); void SetPlayerRemap(FRemapTable *remap);
int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y); int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
FTextureFormat GetFormat() FTextureFormat GetFormat()
{ {
@ -1093,10 +1093,11 @@ void DDoomStatusBar::FDoomStatusBarTexture::MakeTexture ()
if (multiplayer) DrawToBar("STFBANY", 143, 1, STBFremap? STBFremap->Remap : NULL); if (multiplayer) DrawToBar("STFBANY", 143, 1, STBFremap? STBFremap->Remap : NULL);
} }
int DDoomStatusBar::FDoomStatusBarTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y) int DDoomStatusBar::FDoomStatusBarTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
{ {
FTexture *tex; FTexture *tex;
// rotate is never used here
BaseTexture->CopyTrueColorPixels(buffer, buf_pitch, buf_height, x, y); BaseTexture->CopyTrueColorPixels(buffer, buf_pitch, buf_height, x, y);
if (!deathmatch) if (!deathmatch)
{ {

View file

@ -163,7 +163,13 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
angle_t angle; angle_t angle;
pmo = player->mo; pmo = player->mo;
if (pmo->tracer == NULL) // [MH]
// Checks pmo as well; the PowerMorph destroyer will
// try to unmorph the player; if the destroyer runs
// because the level or game is ended while morphed,
// by the time it gets executed the morphed player
// pawn instance may have already been destroyed.
if (pmo == NULL || pmo->tracer == NULL)
{ {
return false; return false;
} }

View file

@ -94,7 +94,7 @@ public:
void Unload (); void Unload ();
virtual void SetFrontSkyLayer (); virtual void SetFrontSkyLayer ();
int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y); int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
int GetSourceLump() { return DefinitionLump; } int GetSourceLump() { return DefinitionLump; }
protected: protected:
@ -105,9 +105,8 @@ protected:
struct TexPart struct TexPart
{ {
SWORD OriginX, OriginY; SWORD OriginX, OriginY;
BYTE Mirror:2; BYTE Rotate;
BYTE Rotate:2; bool textureOwned;
BYTE textureOwned:1;
FTexture *Texture; FTexture *Texture;
TexPart(); TexPart();
@ -262,7 +261,7 @@ public:
const BYTE *GetPixels (); const BYTE *GetPixels ();
void Unload (); void Unload ();
FTextureFormat GetFormat (); FTextureFormat GetFormat ();
int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y); int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
bool UseBasePalette(); bool UseBasePalette();
int GetSourceLump() { return SourceLump; } int GetSourceLump() { return SourceLump; }
@ -330,7 +329,7 @@ protected:
void DecompressDXT3 (FWadLump &lump, bool premultiplied, BYTE *tcbuf = NULL); void DecompressDXT3 (FWadLump &lump, bool premultiplied, BYTE *tcbuf = NULL);
void DecompressDXT5 (FWadLump &lump, bool premultiplied, BYTE *tcbuf = NULL); void DecompressDXT5 (FWadLump &lump, bool premultiplied, BYTE *tcbuf = NULL);
int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y); int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
bool UseBasePalette(); bool UseBasePalette();
friend class FTexture; friend class FTexture;
@ -346,7 +345,7 @@ public:
const BYTE *GetPixels (); const BYTE *GetPixels ();
void Unload (); void Unload ();
FTextureFormat GetFormat (); FTextureFormat GetFormat ();
int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y); int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
bool UseBasePalette(); bool UseBasePalette();
int GetSourceLump() { return SourceLump; } int GetSourceLump() { return SourceLump; }
@ -398,7 +397,7 @@ public:
void Unload (); void Unload ();
FTextureFormat GetFormat (); FTextureFormat GetFormat ();
int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y); int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
bool UseBasePalette(); bool UseBasePalette();
int GetSourceLump() { return SourceLump; } int GetSourceLump() { return SourceLump; }
@ -455,7 +454,7 @@ public:
void Unload (); void Unload ();
FTextureFormat GetFormat (); FTextureFormat GetFormat ();
int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y); int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate);
bool UseBasePalette(); bool UseBasePalette();
int GetSourceLump() { return SourceLump; } int GetSourceLump() { return SourceLump; }

View file

@ -794,7 +794,7 @@ public:
// Returns the whole texture, stored in column-major order // Returns the whole texture, stored in column-major order
virtual const BYTE *GetPixels () = 0; virtual const BYTE *GetPixels () = 0;
virtual int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y); virtual int CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate=0);
int CopyTrueColorTranslated(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, FRemapTable *remap); int CopyTrueColorTranslated(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, FRemapTable *remap);
virtual bool UseBasePalette(); virtual bool UseBasePalette();
virtual int GetSourceLump() { return -1; } virtual int GetSourceLump() { return -1; }
@ -824,7 +824,12 @@ public:
virtual void SetFrontSkyLayer(); virtual void SetFrontSkyLayer();
void CopyToBlock (BYTE *dest, int dwidth, int dheight, int x, int y, const BYTE *translation=NULL); void CopyToBlock (BYTE *dest, int dwidth, int dheight, int x, int y, const BYTE *translation=NULL)
{
CopyToBlock(dest, dwidth, dheight, x, y, 0, translation);
}
void CopyToBlock (BYTE *dest, int dwidth, int dheight, int x, int y, int rotate, const BYTE *translation=NULL);
// Returns true if the next call to GetPixels() will return an image different from the // Returns true if the next call to GetPixels() will return an image different from the
// last call to GetPixels(). This should be considered valid only if a call to CheckModified() // last call to GetPixels(). This should be considered valid only if a call to CheckModified()

View file

@ -742,7 +742,7 @@ void FDDSTexture::DecompressDXT5 (FWadLump &lump, bool premultiplied, BYTE *tcbu
// //
//=========================================================================== //===========================================================================
int FDDSTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y) int FDDSTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
{ {
FWadLump lump = Wads.OpenLumpNum (SourceLump); FWadLump lump = Wads.OpenLumpNum (SourceLump);
@ -768,7 +768,7 @@ int FDDSTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
} }
// All formats decompress to RGBA. // All formats decompress to RGBA.
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, TexBuffer, Width, Height, 4, Width*4, CF_RGBA); screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, TexBuffer, Width, Height, 4, Width*4, rotate, CF_RGBA);
delete [] TexBuffer; delete [] TexBuffer;
return -1; return -1;
} }

View file

@ -332,7 +332,7 @@ void FJPEGTexture::MakeTexture ()
// //
//=========================================================================== //===========================================================================
int FJPEGTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y) int FJPEGTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
{ {
PalEntry pe[256]; PalEntry pe[256];
@ -376,18 +376,18 @@ int FJPEGTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_heigh
{ {
case JCS_RGB: case JCS_RGB:
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, buff, cinfo.output_width, cinfo.output_height, screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, buff, cinfo.output_width, cinfo.output_height,
3, cinfo.output_width * cinfo.output_components, CF_RGB); 3, cinfo.output_width * cinfo.output_components, rotate, CF_RGB);
break; break;
case JCS_GRAYSCALE: case JCS_GRAYSCALE:
for(int i=0;i<256;i++) pe[i]=PalEntry(0,i,i,i); // default to a gray map for(int i=0;i<256;i++) pe[i]=PalEntry(0,i,i,i); // default to a gray map
screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, buff, cinfo.output_width, cinfo.output_height, screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, buff, cinfo.output_width, cinfo.output_height,
1, cinfo.output_width, pe); 1, cinfo.output_width, rotate, pe);
break; break;
case JCS_CMYK: case JCS_CMYK:
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, buff, cinfo.output_width, cinfo.output_height, screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, buff, cinfo.output_width, cinfo.output_height,
4, cinfo.output_width * cinfo.output_components, CF_CMYK); 4, cinfo.output_width * cinfo.output_components, rotate, CF_CMYK);
break; break;
default: default:

View file

@ -292,10 +292,65 @@ void FMultiPatchTexture::MakeTexture ()
for (int i = 0; i < NumParts; ++i) for (int i = 0; i < NumParts; ++i)
{ {
Parts[i].Texture->CopyToBlock (Pixels, Width, Height, Parts[i].Texture->CopyToBlock (Pixels, Width, Height,
Parts[i].OriginX, Parts[i].OriginY); Parts[i].OriginX, Parts[i].OriginY, Parts[i].Rotate);
} }
} }
//===========================================================================
//
// FMultipatchTexture::CopyTrueColorPixels
//
// Preserves the palettes of each individual patch
//
//===========================================================================
int FMultiPatchTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
{
int retv = -1;
for(int i=0;i<NumParts;i++)
{
int ret = Parts[i].Texture->CopyTrueColorPixels(buffer, buf_pitch, buf_height,
x+Parts[i].OriginX, y+Parts[i].OriginY, Parts[i].Rotate);
if (ret > retv) retv = ret;
}
return retv;
}
//==========================================================================
//
// FMultiPatchTexture :: GetFormat
//
// only returns 'paletted' if all patches use the base palette.
//
//==========================================================================
FTextureFormat FMultiPatchTexture::GetFormat()
{
if (NumParts == 1) return Parts[0].Texture->GetFormat();
return UseBasePalette() ? TEX_Pal : TEX_RGB;
}
//===========================================================================
//
// FMultipatchTexture::UseBasePalette
//
// returns true if all patches in the texture use the unmodified base
// palette.
//
//===========================================================================
bool FMultiPatchTexture::UseBasePalette()
{
for(int i=0;i<NumParts;i++)
{
if (!Parts[i].Texture->UseBasePalette()) return false;
}
return true;
}
//========================================================================== //==========================================================================
// //
// FMultiPatchTexture :: CheckForHacks // FMultiPatchTexture :: CheckForHacks
@ -423,61 +478,6 @@ void FMultiPatchTexture::CheckForHacks ()
} }
} }
//===========================================================================
//
// FMultipatchTexture::CopyTrueColorPixels
//
// Preserves the palettes of each individual patch
//
//===========================================================================
int FMultiPatchTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y)
{
int retv = -1;
for(int i=0;i<NumParts;i++)
{
int ret = Parts[i].Texture->CopyTrueColorPixels(buffer, buf_pitch, buf_height,
x+Parts[i].OriginX, y+Parts[i].OriginY);
if (ret > retv) retv = ret;
}
return retv;
}
//==========================================================================
//
// FMultiPatchTexture :: GetFormat
//
// only returns 'paletted' if all patches use the base palette.
//
//==========================================================================
FTextureFormat FMultiPatchTexture::GetFormat()
{
if (NumParts == 1) return Parts[0].Texture->GetFormat();
return UseBasePalette() ? TEX_Pal : TEX_RGB;
}
//===========================================================================
//
// FMultipatchTexture::UseBasePalette
//
// returns true if all patches in the texture use the unmodified base
// palette.
//
//===========================================================================
bool FMultiPatchTexture::UseBasePalette()
{
for(int i=0;i<NumParts;i++)
{
if (!Parts[i].Texture->UseBasePalette()) return false;
}
return true;
}
//========================================================================== //==========================================================================
// //
// FMultiPatchTexture :: TexPart :: TexPart // FMultiPatchTexture :: TexPart :: TexPart
@ -487,7 +487,7 @@ bool FMultiPatchTexture::UseBasePalette()
FMultiPatchTexture::TexPart::TexPart() FMultiPatchTexture::TexPart::TexPart()
{ {
OriginX = OriginY = 0; OriginX = OriginY = 0;
Mirror = Rotate = 0; Rotate = 0;
textureOwned = false; textureOwned = false;
Texture = NULL; Texture = NULL;
} }
@ -680,6 +680,7 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
sc.MustGetString(); sc.MustGetString();
int texno = TexMan.CheckForTexture(sc.String, TEX_WallPatch); int texno = TexMan.CheckForTexture(sc.String, TEX_WallPatch);
int Mirror = 0;
if (texno < 0) if (texno < 0)
{ {
@ -705,37 +706,39 @@ void FMultiPatchTexture::ParsePatch(FScanner &sc, TexPart & part)
sc.MustGetNumber(); sc.MustGetNumber();
part.OriginY = sc.Number; part.OriginY = sc.Number;
/* not yet implemented if (sc.CheckString("{"))
if (sc.CheckString("{");
{ {
while (!sc.CheckString("}")) while (!sc.CheckString("}"))
{ {
sc.MustGetString(); sc.MustGetString();
if (sc.Compare("flipx")) if (sc.Compare("flipx"))
{ {
part.Mirror |= 1; Mirror |= 1;
} }
else if (sc.Compare("flipy")) else if (sc.Compare("flipy"))
{ {
part.Mirror |= 2; Mirror |= 2;
} }
else if (sc.Compare("rotate")) else if (sc.Compare("rotate"))
{ {
sc.MustGetNumber(); sc.MustGetNumber();
if (sc.Number != 0 && sc.Number !=90 && sc.Number != 180 && sc.Number != 270) if (sc.Number != 0 && sc.Number !=90 && sc.Number != 180 && sc.Number != -90)
{ {
sc.ScriptError("Rotation must be 0, 90, 180 or 270 degrees"); sc.ScriptError("Rotation must be 0, 90, 180 or -90 degrees");
} }
part.Rotate = sc.Number / 90; part.Rotate = (sc.Number / 90) & 3;
} }
} }
} }
if (part.Mirror & 2) if (Mirror & 2)
{ {
part.Rotate = (part.Rotate + 180) % 360; part.Rotate = (part.Rotate + 2) & 3;
part.Mirror &= 1; Mirror ^= 1;
}
if (Mirror & 1)
{
part.Rotate |= 4;
} }
*/
} }
@ -804,7 +807,7 @@ FMultiPatchTexture::FMultiPatchTexture (FScanner &sc, int usetype)
if (Parts->OriginX == 0 && Parts->OriginY == 0 && if (Parts->OriginX == 0 && Parts->OriginY == 0 &&
Parts->Texture->GetWidth() == Width && Parts->Texture->GetWidth() == Width &&
Parts->Texture->GetHeight() == Height && Parts->Texture->GetHeight() == Height &&
Parts->Mirror == 0 && Parts->Rotate == 0) Parts->Rotate == 0)
{ {
bRedirect = true; bRedirect = true;
} }

View file

@ -418,7 +418,7 @@ void FPCXTexture::MakeTexture()
// //
//=========================================================================== //===========================================================================
int FPCXTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y) int FPCXTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
{ {
PalEntry pe[256]; PalEntry pe[256];
PCXHeader header; PCXHeader header;
@ -472,14 +472,14 @@ int FPCXTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
lump.Seek(sizeof(header), SEEK_SET); lump.Seek(sizeof(header), SEEK_SET);
ReadPCX8bits (Pixels, lump, &header); ReadPCX8bits (Pixels, lump, &header);
} }
screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 1, Width, pe); screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 1, Width, rotate, pe);
} }
else else
{ {
Pixels = new BYTE[Width*Height * 3]; Pixels = new BYTE[Width*Height * 3];
BYTE * row = buffer; BYTE * row = buffer;
ReadPCX24bits (Pixels, lump, &header, 3); ReadPCX24bits (Pixels, lump, &header, 3);
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 3, Width*3, CF_RGB); screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 3, Width*3, rotate, CF_RGB);
} }
delete [] Pixels; delete [] Pixels;
return 0; return 0;

View file

@ -490,7 +490,7 @@ void FPNGTexture::MakeTexture ()
// //
//=========================================================================== //===========================================================================
int FPNGTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y) int FPNGTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
{ {
// Parse pre-IDAT chunks. I skip the CRCs. Is that bad? // Parse pre-IDAT chunks. I skip the CRCs. Is that bad?
PalEntry pe[256]; PalEntry pe[256];
@ -554,20 +554,20 @@ int FPNGTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
{ {
case 0: case 0:
case 3: case 3:
screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 1, Width, pe); screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 1, Width, rotate, pe);
break; break;
case 2: case 2:
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 3, pixwidth, CF_RGB); screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 3, pixwidth, rotate, CF_RGB);
break; break;
case 4: case 4:
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 2, pixwidth, CF_IA); screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 2, pixwidth, rotate, CF_IA);
transpal = -1; transpal = -1;
break; break;
case 6: case 6:
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 4, pixwidth, CF_RGBA); screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, Pixels, Width, Height, 4, pixwidth, rotate, CF_RGBA);
transpal = -1; transpal = -1;
break; break;

View file

@ -270,7 +270,7 @@ void FTexture::FreeSpans (Span **spans) const
M_Free (spans); M_Free (spans);
} }
void FTexture::CopyToBlock (BYTE *dest, int dwidth, int dheight, int xpos, int ypos, const BYTE *translation) void FTexture::CopyToBlock (BYTE *dest, int dwidth, int dheight, int xpos, int ypos, int rotate, const BYTE *translation)
{ {
const BYTE *pixels = GetPixels(); const BYTE *pixels = GetPixels();
int srcwidth = Width; int srcwidth = Width;
@ -278,7 +278,7 @@ void FTexture::CopyToBlock (BYTE *dest, int dwidth, int dheight, int xpos, int y
int step_x = Height; int step_x = Height;
int step_y = 1; int step_y = 1;
if (ClipCopyPixelRect(dwidth, dheight, xpos, ypos, pixels, srcwidth, srcheight, step_x, step_y)) if (ClipCopyPixelRect(dwidth, dheight, xpos, ypos, pixels, srcwidth, srcheight, step_x, step_y, rotate))
{ {
dest += ypos + dheight * xpos; dest += ypos + dheight * xpos;
if (translation == NULL) if (translation == NULL)
@ -288,7 +288,7 @@ void FTexture::CopyToBlock (BYTE *dest, int dwidth, int dheight, int xpos, int y
int pos = x * dheight; int pos = x * dheight;
for (int y = 0; y < srcheight; y++, pos++) for (int y = 0; y < srcheight; y++, pos++)
{ {
// the optimizer is doing a good enough job here so there's no need to make this harder to read. // the optimizer is doing a good enough job here so there's no need to optimize this by hand
BYTE v = pixels[y * step_y + x * step_x]; BYTE v = pixels[y * step_y + x * step_x];
if (v != 0) dest[pos] = v; if (v != 0) dest[pos] = v;
} }
@ -476,13 +476,13 @@ void FTexture::FillBuffer(BYTE *buff, int pitch, int height, FTextureFormat fmt)
// //
//=========================================================================== //===========================================================================
int FTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y) int FTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
{ {
PalEntry *palette = screen->GetPalette(); PalEntry *palette = screen->GetPalette();
palette[0].a=255; // temporarily modify the first color's alpha palette[0].a=255; // temporarily modify the first color's alpha
screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y,
GetPixels(), Width, Height, Height, 1, GetPixels(), Width, Height, Height, 1,
palette); rotate, palette);
palette[0].a=0; palette[0].a=0;
return 0; return 0;
@ -494,7 +494,7 @@ int FTexture::CopyTrueColorTranslated(BYTE *buffer, int buf_pitch, int buf_heigh
palette[0].a=255; // temporarily modify the first color's alpha palette[0].a=255; // temporarily modify the first color's alpha
screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y,
GetPixels(), Width, Height, Height, 1, GetPixels(), Width, Height, Height, 1,
palette); 0, palette);
palette[0].a=0; palette[0].a=0;
return 0; return 0;

View file

@ -384,7 +384,7 @@ void FTGATexture::MakeTexture ()
// //
//=========================================================================== //===========================================================================
int FTGATexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y) int FTGATexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y, int rotate)
{ {
PalEntry pe[256]; PalEntry pe[256];
FWadLump lump = Wads.OpenLumpNum (SourceLump); FWadLump lump = Wads.OpenLumpNum (SourceLump);
@ -469,7 +469,7 @@ int FTGATexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
switch (hdr.img_type & 7) switch (hdr.img_type & 7)
{ {
case 1: // paletted case 1: // paletted
screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, pe); screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, pe);
break; break;
case 2: // RGB case 2: // RGB
@ -477,21 +477,21 @@ int FTGATexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
{ {
case 15: case 15:
case 16: case 16:
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, CF_RGB555); screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_RGB555);
break; break;
case 24: case 24:
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, CF_BGR); screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGR);
break; break;
case 32: case 32:
if ((hdr.img_desc&15)!=8) // 32 bits without a valid alpha channel if ((hdr.img_desc&15)!=8) // 32 bits without a valid alpha channel
{ {
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, CF_BGR); screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGR);
} }
else else
{ {
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, CF_BGRA); screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_BGRA);
transval = -1; transval = -1;
} }
break; break;
@ -506,11 +506,11 @@ int FTGATexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height
{ {
case 8: case 8:
for(int i=0;i<256;i++) pe[i]=PalEntry(0,i,i,i); // gray map for(int i=0;i<256;i++) pe[i]=PalEntry(0,i,i,i); // gray map
screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, pe); screen->CopyPixelData(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, pe);
break; break;
case 16: case 16:
screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, CF_I16); screen->CopyPixelDataRGB(buffer, buf_pitch, buf_height, x, y, ptr, Width, Height, step_x, Pitch, rotate, CF_I16);
break; break;
default: default:

View file

@ -1191,15 +1191,92 @@ static CopyFunc copyfuncs[]={
iCopyColors<cPalEntry> iCopyColors<cPalEntry>
}; };
//=========================================================================== //===========================================================================
// //
// Clips the copy area for CopyPixelData functions // Clips the copy area for CopyPixelData functions
// //
//=========================================================================== //===========================================================================
bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy, bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy,
const BYTE *&patch, int &srcwidth, int &srcheight, int step_x, int step_y) const BYTE *&patch, int &srcwidth, int &srcheight,
int &pstep_x, int &pstep_y, int rotate)
{ {
int pixxoffset;
int pixyoffset;
int step_x;
int step_y;
// First adjust the settings for the intended rotation
switch (rotate)
{
default:
case 0: // normal
pixxoffset = 0;
pixyoffset = 0;
step_x = pstep_x;
step_y = pstep_y;
break;
case 1: // rotate 90° right
pixxoffset = 0;
pixyoffset = srcheight - 1;
step_x = -pstep_y;
step_y = pstep_x;
break;
case 2: // rotate 180°
pixxoffset = srcwidth - 1;
pixyoffset = srcheight - 1;
step_x = -pstep_x;
step_y = -pstep_y;
break;
case 3: // rotate 90° left
pixxoffset = srcwidth - 1;
pixyoffset = 0;
step_x = pstep_y;
step_y = -pstep_x;
break;
case 4: // flip horizontally
pixxoffset = srcwidth - 1;
pixyoffset = 0;
step_x = -pstep_x;
step_y = pstep_y;
break;
case 5: // flip horizontally and rotate 90° right
pixxoffset = srcwidth - 1;
pixyoffset = srcheight - 1;
step_x = -pstep_y;
step_y = -pstep_x;
break;
case 6: // flip vertically
pixxoffset = 0;
pixyoffset = srcheight - 1;
step_x = pstep_x;
step_y = -pstep_y;
break;
case 7: // flip horizontally and rotate 90° left
pixxoffset = 0;
pixyoffset = 0;
step_x = pstep_y;
step_y = pstep_x;
break;
}
if (rotate&1)
{
int v = srcwidth;
srcwidth = srcheight;
srcheight = v;
}
patch += pixxoffset * pstep_x + pixyoffset * pstep_y;
pstep_x = step_x;
pstep_y = step_y;
// clip source rectangle to destination // clip source rectangle to destination
if (originx<0) if (originx<0)
{ {
@ -1229,6 +1306,7 @@ bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy,
return true; return true;
} }
//=========================================================================== //===========================================================================
// //
// True Color texture copy function // True Color texture copy function
@ -1236,9 +1314,9 @@ bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy,
//=========================================================================== //===========================================================================
void DFrameBuffer::CopyPixelDataRGB(BYTE *buffer, int texpitch, int texheight, int originx, int originy, void DFrameBuffer::CopyPixelDataRGB(BYTE *buffer, int texpitch, int texheight, int originx, int originy,
const BYTE *patch, int srcwidth, int srcheight, int step_x, int step_y, const BYTE *patch, int srcwidth, int srcheight, int step_x, int step_y,
int ct) int rotate, int ct)
{ {
if (ClipCopyPixelRect(texpitch/4, texheight, originx, originy, patch, srcwidth, srcheight, step_x, step_y)) if (ClipCopyPixelRect(texpitch/4, texheight, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
{ {
buffer+=4*originx + texpitch*originy; buffer+=4*originx + texpitch*originy;
for (int y=0;y<srcheight;y++) for (int y=0;y<srcheight;y++)
@ -1255,11 +1333,11 @@ void DFrameBuffer::CopyPixelDataRGB(BYTE *buffer, int texpitch, int texheight, i
//=========================================================================== //===========================================================================
void DFrameBuffer::CopyPixelData(BYTE * buffer, int texpitch, int texheight, int originx, int originy, void DFrameBuffer::CopyPixelData(BYTE * buffer, int texpitch, int texheight, int originx, int originy,
const BYTE * patch, int srcwidth, int srcheight, const BYTE * patch, int srcwidth, int srcheight,
int step_x, int step_y, PalEntry * palette) int step_x, int step_y, int rotate, PalEntry * palette)
{ {
int x,y,pos; int x,y,pos;
if (ClipCopyPixelRect(texpitch/4, texheight, originx, originy, patch, srcwidth, srcheight, step_x, step_y)) if (ClipCopyPixelRect(texpitch/4, texheight, originx, originy, patch, srcwidth, srcheight, step_x, step_y, rotate))
{ {
buffer+=4*originx + texpitch*originy; buffer+=4*originx + texpitch*originy;

View file

@ -375,11 +375,11 @@ public:
// texture copy functions // texture copy functions
virtual void CopyPixelDataRGB(BYTE *buffer, int texpitch, int texheight, int originx, int originy, virtual void CopyPixelDataRGB(BYTE *buffer, int texpitch, int texheight, int originx, int originy,
const BYTE *patch, int pix_width, int pix_height, int step_x, int step_y, const BYTE *patch, int pix_width, int pix_height, int step_x, int step_y,
int ct); int rotate, int ct);
virtual void CopyPixelData(BYTE *buffer, int texpitch, int texheight, int originx, int originy, virtual void CopyPixelData(BYTE *buffer, int texpitch, int texheight, int originx, int originy,
const BYTE *patch, int pix_width, int pix_height, const BYTE *patch, int pix_width, int pix_height,
int step_x, int step_y, PalEntry * palette); int step_x, int step_y, int rotate, PalEntry * palette);
// Precaches or unloads a texture // Precaches or unloads a texture
virtual void PrecacheTexture(FTexture *tex, int cache); virtual void PrecacheTexture(FTexture *tex, int cache);
@ -406,7 +406,8 @@ private:
}; };
bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy, bool ClipCopyPixelRect(int texwidth, int texheight, int &originx, int &originy,
const BYTE *&patch, int &srcwidth, int &srcheight, int step_x, int step_y); const BYTE *&patch, int &srcwidth, int &srcheight,
int &step_x, int &step_y, int rotate);
extern FColorMatcher ColorMatcher; extern FColorMatcher ColorMatcher;