- Applied a modified version of Karate Chris's screenshot naming patch.

- Sbarinfo optimization: Creating and destroying bar textures every frame is
  a relatively expensive operation. We can skip the custom texture entirely
  and just draw the bars directly to the screen, using the clipping parameters
  for DrawTexture(). This also means bars are no longer limited to the game
  palette, and the bar itself has the same resolution as the screen.


SVN r731 (trunk)
This commit is contained in:
Randy Heit 2008-02-05 05:29:31 +00:00
parent 9a785239f2
commit d1e27e533f
9 changed files with 220 additions and 195 deletions

View file

@ -1,6 +1,14 @@
February 4, 2008
- Applied a modified version of Karate Chris's screenshot naming patch.
- Sbarinfo optimization: Creating and destroying bar textures every frame is
a relatively expensive operation. We can skip the custom texture entirely
and just draw the bars directly to the screen, using the clipping parameters
for DrawTexture(). This also means bars are no longer limited to the game
palette, and the bar itself has the same resolution as the screen.
February 2, 2008 February 2, 2008
- Removed support for numeric flags from sbarinfo's drawmugshot command since - Removed support for numeric flags from sbarinfo's drawmugshot command since
it was declared unrecommended and deprecated. it was previously declared unrecommended and deprecated.
- Added Blzut3's sbarinfo update #10: - Added Blzut3's sbarinfo update #10:
* Fixed: drawmugshot now adjust to the player's max health like it should. * Fixed: drawmugshot now adjust to the player's max health like it should.
* drawgem can now accept negative paddings. * drawgem can now accept negative paddings.

View file

@ -101,19 +101,7 @@ struct FDecalAnimator
FName Name; FName Name;
}; };
class FDecalAnimatorArray : public TArray<FDecalAnimator *> TDeletingArray<FDecalAnimator *> Animators;
{
public:
~FDecalAnimatorArray()
{
for (unsigned int i = 0; i < Size(); ++i)
{
delete (*this)[i];
}
}
};
FDecalAnimatorArray Animators;
struct DDecalThinker : public DThinker struct DDecalThinker : public DThinker
{ {

View file

@ -1074,105 +1074,6 @@ enum
imgINVRTGEM2, imgINVRTGEM2,
}; };
//The next class allows us to draw bars
class FBarTexture : public FTexture
{
public:
~FBarTexture()
{
delete Pixels;
}
void Unload()
{
if(image != NULL)
{
image->Unload ();
}
}
const BYTE *GetColumn(unsigned int column, const Span **spans_out)
{
if (column > (unsigned int) Width)
{
column = Width;
}
image->GetColumn(column, spans_out);
return Pixels + column*Height;
}
const BYTE *GetPixels()
{
return Pixels;
}
FBarTexture(FTexture* bar, FTexture* bg, int value, bool horizontal, bool reverse, int border=0)
{
value = clamp(value, 0, 100);
image = bar;
//width and height are supposed to be the end result, Width and Height are the input image. If that makes sense.
int width = Width = bar->GetWidth();
int height = Height = bar->GetHeight();
if(horizontal)
{
width = (int) (((double) (width-border*2)/100)*value);
}
Pixels = new BYTE[Width*Height];
memset(Pixels, 0, Width*Height); //Prevent garbage when using transparent images
bar->CopyToBlock(Pixels, Width, Height, 0, 0); //draw the bar
int run = bar->GetHeight() - (int) (((double) (height-border*2)/100)*value);
int visible = bar->GetHeight() - run;
if(bg == NULL || bg->GetWidth() != bar->GetWidth() || bg->GetHeight() != bar->GetHeight())
{
BYTE color0 = GPalette.Remap[0];
if(!horizontal)
{
if(!reverse) //remove offset if we are not reversing the direction.
{
visible = 0;
}
for(int i = border;i < Width-border;i++)
{
memset(Pixels + i*Height + visible + border, color0, run-border*2);
}
}
else
{
for(int i = reverse ? border : width+border;(reverse && i < Width - width - border) || (!reverse && i < Width-border);i++)
{
memset(Pixels + i*Height + border, color0, Height-border*2);
}
}
}
else
{
BYTE* PixelData = (BYTE*) bg->GetPixels();
PixelData += border;
if(!horizontal)
{
if(!reverse)
{
visible = 0;
}
for(int i = border;i < Width-border;i++)
{
memcpy(Pixels + i*Height + visible + border, PixelData + i*Height, run-border*2);
}
}
else
{
for(int i = reverse ? border : width+border;(reverse && i < Width - width - border) || (!reverse && i < Width-border);i++)
{
memcpy(Pixels + i*Height + border, PixelData + i*Height, Height-border*2);
}
}
}
}
protected:
BYTE* Pixels;
FTexture* image;
};
//Used for shading //Used for shading
class FBarShader : public FTexture class FBarShader : public FTexture
{ {
@ -1273,16 +1174,10 @@ SBarInfoCommand::SBarInfoCommand() //sets the default values for more predicable
translation2 = CR_UNTRANSLATED; translation2 = CR_UNTRANSLATED;
translation3 = CR_UNTRANSLATED; translation3 = CR_UNTRANSLATED;
font = V_GetFont("CONFONT"); font = V_GetFont("CONFONT");
bar = NULL;
} }
SBarInfoCommand::~SBarInfoCommand() SBarInfoCommand::~SBarInfoCommand()
{ {
if (bar != NULL)
{
delete bar;
}
subBlock.commands.Clear();
} }
SBarInfoBlock::SBarInfoBlock() SBarInfoBlock::SBarInfoBlock()
@ -1769,15 +1664,16 @@ private:
} }
case SBARINFO_DRAWBAR: case SBARINFO_DRAWBAR:
{ {
if(cmd.sprite == -1) break; //don't draw anything. if(cmd.sprite == -1 || Images[cmd.sprite] == NULL)
break; //don't draw anything.
bool horizontal = !!((cmd.special2 & DRAWBAR_HORIZONTAL)); bool horizontal = !!((cmd.special2 & DRAWBAR_HORIZONTAL));
bool reverse = !!((cmd.special2 & DRAWBAR_REVERSE)); bool reverse = !!((cmd.special2 & DRAWBAR_REVERSE));
int value = 0; fixed_t value = 0;
int max = 0; int max = 0;
if(cmd.flags == DRAWNUMBER_HEALTH) if(cmd.flags == DRAWNUMBER_HEALTH)
{ {
value = health; value = health;
if(cmd.value < 0) //health shouldn't display negatives if(value < 0) //health shouldn't display negatives
{ {
value = 0; value = 0;
} }
@ -1793,7 +1689,7 @@ private:
max = 0; max = 0;
} }
} }
else //default to the classes health else //default to the class's health
{ {
max = CPlayer->mo->GetDefault()->health; max = CPlayer->mo->GetDefault()->health;
} }
@ -1888,26 +1784,91 @@ private:
value = 0; value = 0;
} }
} }
if(max != 0 || value < 0) if(max != 0 && value > 0)
{ {
value = (value*100)/max; value = (value << FRACBITS) / max;
if(value > 100) if(value > FRACUNIT)
value = 100; value = FRACUNIT;
} }
else else
{ {
value = 0; value = 0;
} }
if(cmd.bar != NULL) assert(Images[cmd.sprite] != NULL);
delete cmd.bar;
if (Images[cmd.sprite] != NULL) FTexture *fg = Images[cmd.sprite];
FTexture *bg = (cmd.special != -1) ? Images[cmd.special] : NULL;
int x, y, w, h;
int cx, cy, cw, ch, cr, cb;
// Calc real screen coordinates for bar
x = cmd.x + ST_X;
y = cmd.y + ST_Y;
w = fg->GetWidth();
h = fg->GetHeight();
if (Scaled)
{ {
if(cmd.special != -1) screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true);
cmd.bar = new FBarTexture(Images[cmd.sprite], Images[cmd.special], value, horizontal, reverse, cmd.special3);
else
cmd.bar = new FBarTexture(Images[cmd.sprite], NULL, value, horizontal, reverse, cmd.special3);
DrawImage(cmd.bar, cmd.x, cmd.y);
} }
// Draw background
if (bg != NULL && bg->GetWidth() == fg->GetWidth() && bg->GetHeight() == fg->GetHeight())
{
screen->DrawTexture(bg, x, y,
DTA_DestWidth, w,
DTA_DestHeight, h,
TAG_DONE);
}
else
{
screen->Clear(x, y, x + w, y + h, GPalette.BlackIndex, 0);
}
// Calc clipping rect for foreground
cx = cmd.x + ST_X + cmd.special3;
cy = cmd.y + ST_Y + cmd.special3;
cw = fg->GetWidth() - cmd.special3 * 2;
ch = fg->GetHeight() - cmd.special3 * 2;
if (Scaled)
{
screen->VirtualToRealCoordsInt(cx, cy, cw, ch, 320, 200, true);
}
if (horizontal)
{
if (!reverse)
{ // left to right
cr = cx + FixedMul(cw, value);
}
else
{ // right to left
cr = cx + cw;
cx += FixedMul(cw, FRACUNIT - value);
}
cb = cy + ch;
}
else
{
if (!reverse)
{ // bottom to top
cb = cy + ch;
cy += FixedMul(ch, FRACUNIT - value);
}
else
{ // top to bottom
cb = cy + FixedMul(ch, value);
}
cr = cx + cw;
}
// Draw foreground
screen->DrawTexture(fg, x, y,
DTA_DestWidth, w,
DTA_DestHeight, h,
DTA_ClipLeft, cx,
DTA_ClipTop, cy,
DTA_ClipRight, cr,
DTA_ClipBottom, cb,
TAG_DONE);
break; break;
} }
case SBARINFO_DRAWGEM: case SBARINFO_DRAWGEM:

View file

@ -37,7 +37,6 @@ struct SBarInfoCommand
EColorRange translation; EColorRange translation;
EColorRange translation2; EColorRange translation2;
EColorRange translation3; EColorRange translation3;
FBarTexture *bar;
SBarInfoBlock subBlock; //for type SBarInfo_CMD_GAMEMODE SBarInfoBlock subBlock; //for type SBarInfo_CMD_GAMEMODE
}; };

View file

@ -30,6 +30,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <malloc.h> #include <malloc.h>
#include <time.h>
#include "doomtype.h" #include "doomtype.h"
#include "version.h" #include "version.h"
@ -595,7 +596,42 @@ static bool FindFreeName (FString &fullname, const char *extension)
for (i = 0; i <= 9999; i++) for (i = 0; i <= 9999; i++)
{ {
lbmname.Format ("%sDOOM%04d.%s", fullname.GetChars(), i, extension); const char *gamename;
switch (gameinfo.gametype)
{
case GAME_Doom: gamename = "Doom"; break;
case GAME_Heretic: gamename = "Heretic"; break;
case GAME_Hexen: gamename = "Hexen"; break;
case GAME_Strife: gamename = "Strife"; break;
default: break;
}
time_t now;
tm *tm;
time(&now);
tm = localtime(&now);
if (tm == NULL)
{
lbmname.Format ("%sScreenshot_%s_%04d.%s", fullname.GetChars(), gamename, i, extension);
}
else if (i == 0)
{
lbmname.Format ("%sScreenshot_%s_%04d%02d%02d_%02d%02d%02d.%s", fullname.GetChars(), gamename,
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec,
extension);
}
else
{
lbmname.Format ("%sScreenshot_%s_%04d%02d%02d_%02d%02d%02d_%02d.%s", fullname.GetChars(), gamename,
tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
tm->tm_hour, tm->tm_min, tm->tm_sec,
i, extension);
}
if (!FileExists (lbmname.GetChars())) if (!FileExists (lbmname.GetChars()))
{ {
fullname = lbmname; fullname = lbmname;

View file

@ -256,19 +256,7 @@ void FRandom::StaticReadRNGState (PNGHandle *png)
// This is for use by DECORATE. // This is for use by DECORATE.
extern FRandom pr_exrandom; extern FRandom pr_exrandom;
class NewRNGList : public TArray<FRandom*> static TDeletingArray<FRandom *> NewRNGs;
{
public:
~NewRNGList()
{
for(unsigned i=0;i<Size();i++)
{
delete (*this)[i];
}
}
};
static NewRNGList NewRNGs;
FRandom *FRandom::StaticFindRNG (const char *name) FRandom *FRandom::StaticFindRNG (const char *name)
{ {

View file

@ -286,6 +286,21 @@ private:
} }
}; };
// TDeletingArray -----------------------------------------------------------
// An array that deletes its elements when it gets deleted.
template<class T, class TT=T>
class TDeletingArray : public TArray<T, TT>
{
public:
~TDeletingArray<T, TT> ()
{
for (unsigned int i = 0; i < Size(); ++i)
{
delete (*this)[i];
}
}
};
// TAutoGrowArray ----------------------------------------------------------- // TAutoGrowArray -----------------------------------------------------------
// An array with accessors that automatically grow the array as needed. // An array with accessors that automatically grow the array as needed.
// It can still be used as a normal TArray if needed. ACS uses this for // It can still be used as a normal TArray if needed. ACS uses this for
@ -788,8 +803,8 @@ public:
// NextPair // NextPair
// //
// Returns false if there are no more entries in the table. Otherwise, it // Returns false if there are no more entries in the table. Otherwise, it
// returns true, and key and value are filled with pointers to the // returns true, and pair is filled with a pointer to the pair in the
// respective parts of the next pair in the table. // table.
// //
//======================================================================= //=======================================================================

View file

@ -531,6 +531,8 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
break; break;
case DTA_KeepRatio: case DTA_KeepRatio:
// I think this is a terribly misleading name, since it actually turns
// *off* aspect ratio correction.
parms->keepratio = va_arg (tags, INTBOOL); parms->keepratio = va_arg (tags, INTBOOL);
break; break;
@ -542,51 +544,15 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
} }
va_end (tags); va_end (tags);
if (parms->uclip >= parms->dclip || parms->lclip >= parms->rclip)
{
return false;
}
if (parms->virtWidth != Width || parms->virtHeight != Height) if (parms->virtWidth != Width || parms->virtHeight != Height)
{ {
int myratio = CheckRatio (Width, Height); VirtualToRealCoords(parms->x, parms->y, parms->destwidth, parms->destheight,
int right = parms->x + parms->destwidth; parms->virtWidth, parms->virtHeight, virtBottom, !parms->keepratio);
int bottom = parms->y + parms->destheight;
if (myratio != 0 && myratio != 4 && !parms->keepratio)
{ // The target surface is either 16:9 or 16:10, so expand the
// specified virtual size to avoid undesired stretching of the
// image. Does not handle non-4:3 virtual sizes. I'll worry about
// those if somebody expresses a desire to use them.
parms->x = Scale(parms->x - parms->virtWidth*FRACUNIT/2,
Width*960,
parms->virtWidth*BaseRatioSizes[myratio][0])
+ Width*FRACUNIT/2;
parms->destwidth = Scale(right - parms->virtWidth*FRACUNIT/2,
Width*960,
parms->virtWidth*BaseRatioSizes[myratio][0])
+ Width*FRACUNIT/2 - parms->x;
}
else
{
parms->x = Scale (parms->x, Width, parms->virtWidth);
parms->destwidth = Scale (right, Width, parms->virtWidth) - parms->x;
}
if (myratio != 0 && myratio == 4 && !parms->keepratio)
{ // The target surface is 5:4
parms->y = Scale(parms->y - parms->virtHeight*FRACUNIT/2,
Height*600,
parms->virtHeight*BaseRatioSizes[myratio][1])
+ Height*FRACUNIT/2;
parms->destheight = Scale(bottom - parms->virtHeight*FRACUNIT/2,
Height*600,
parms->virtHeight*BaseRatioSizes[myratio][1])
+ Height*FRACUNIT/2 - parms->y;
if (virtBottom)
{
parms->y += (Height - Height * BaseRatioSizes[myratio][3] / 48) << (FRACBITS - 1);
}
}
else
{
parms->y = Scale (parms->y, Height, parms->virtHeight);
parms->destheight = Scale (bottom, Height, parms->virtHeight) - parms->y;
}
} }
if (parms->destwidth <= 0 || parms->destheight <= 0) if (parms->destwidth <= 0 || parms->destheight <= 0)
@ -628,6 +594,68 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
return true; return true;
} }
void DCanvas::VirtualToRealCoords(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h,
int vwidth, int vheight, bool vbottom, bool handleaspect) const
{
int myratio = handleaspect ? CheckRatio (Width, Height) : 0;
int right = x + w;
int bottom = y + h;
if (myratio != 0 && myratio != 4)
{ // The target surface is either 16:9 or 16:10, so expand the
// specified virtual size to avoid undesired stretching of the
// image. Does not handle non-4:3 virtual sizes. I'll worry about
// those if somebody expresses a desire to use them.
x = Scale(x - vwidth*FRACUNIT/2,
Width*960,
vwidth*BaseRatioSizes[myratio][0])
+ Width*FRACUNIT/2;
w = Scale(right - vwidth*FRACUNIT/2,
Width*960,
vwidth*BaseRatioSizes[myratio][0])
+ Width*FRACUNIT/2 - x;
}
else
{
x = Scale (x, Width, vwidth);
w = Scale (right, Width, vwidth) - x;
}
if (myratio == 4)
{ // The target surface is 5:4
y = Scale(y - vheight*FRACUNIT/2,
Height*600,
vheight*BaseRatioSizes[myratio][1])
+ Height*FRACUNIT/2;
h = Scale(bottom - vheight*FRACUNIT/2,
Height*600,
vheight*BaseRatioSizes[myratio][1])
+ Height*FRACUNIT/2 - y;
if (vbottom)
{
y += (Height - Height * BaseRatioSizes[myratio][3] / 48) << (FRACBITS - 1);
}
}
else
{
y = Scale (y, Height, vheight);
h = Scale (bottom, Height, vheight) - y;
}
}
void DCanvas::VirtualToRealCoordsInt(int &x, int &y, int &w, int &h,
int vwidth, int vheight, bool vbottom, bool handleaspect) const
{
x <<= FRACBITS;
y <<= FRACBITS;
w <<= FRACBITS;
h <<= FRACBITS;
VirtualToRealCoords(x, y, w, h, vwidth, vheight, vbottom, handleaspect);
x >>= FRACBITS;
y >>= FRACBITS;
w >>= FRACBITS;
h >>= FRACBITS;
}
void DCanvas::FillBorder (FTexture *img) void DCanvas::FillBorder (FTexture *img)
{ {
int myratio = CheckRatio (Width, Height); int myratio = CheckRatio (Width, Height);

View file

@ -200,6 +200,8 @@ public:
// 2D Texture drawing // 2D Texture drawing
void STACK_ARGS DrawTexture (FTexture *img, int x, int y, int tags, ...); void STACK_ARGS DrawTexture (FTexture *img, int x, int y, int tags, ...);
void FillBorder (FTexture *img); // Fills the border around a 4:3 part of the screen on non-4:3 displays void FillBorder (FTexture *img); // Fills the border around a 4:3 part of the screen on non-4:3 displays
void VirtualToRealCoords(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const;
void VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, int vwidth, int vheight, bool vbottom=false, bool handleaspect=true) const;
// 2D Text drawing // 2D Text drawing
void STACK_ARGS DrawText (int normalcolor, int x, int y, const char *string, ...); void STACK_ARGS DrawText (int normalcolor, int x, int y, const char *string, ...);