mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 13:01:47 +00:00
- 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:
parent
9a785239f2
commit
d1e27e533f
9 changed files with 220 additions and 195 deletions
|
@ -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
|
||||
- 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:
|
||||
* Fixed: drawmugshot now adjust to the player's max health like it should.
|
||||
* drawgem can now accept negative paddings.
|
||||
|
|
|
@ -101,19 +101,7 @@ struct FDecalAnimator
|
|||
FName Name;
|
||||
};
|
||||
|
||||
class FDecalAnimatorArray : public TArray<FDecalAnimator *>
|
||||
{
|
||||
public:
|
||||
~FDecalAnimatorArray()
|
||||
{
|
||||
for (unsigned int i = 0; i < Size(); ++i)
|
||||
{
|
||||
delete (*this)[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
FDecalAnimatorArray Animators;
|
||||
TDeletingArray<FDecalAnimator *> Animators;
|
||||
|
||||
struct DDecalThinker : public DThinker
|
||||
{
|
||||
|
|
|
@ -1074,105 +1074,6 @@ enum
|
|||
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
|
||||
class FBarShader : public FTexture
|
||||
{
|
||||
|
@ -1273,16 +1174,10 @@ SBarInfoCommand::SBarInfoCommand() //sets the default values for more predicable
|
|||
translation2 = CR_UNTRANSLATED;
|
||||
translation3 = CR_UNTRANSLATED;
|
||||
font = V_GetFont("CONFONT");
|
||||
bar = NULL;
|
||||
}
|
||||
|
||||
SBarInfoCommand::~SBarInfoCommand()
|
||||
{
|
||||
if (bar != NULL)
|
||||
{
|
||||
delete bar;
|
||||
}
|
||||
subBlock.commands.Clear();
|
||||
}
|
||||
|
||||
SBarInfoBlock::SBarInfoBlock()
|
||||
|
@ -1769,15 +1664,16 @@ private:
|
|||
}
|
||||
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 reverse = !!((cmd.special2 & DRAWBAR_REVERSE));
|
||||
int value = 0;
|
||||
fixed_t value = 0;
|
||||
int max = 0;
|
||||
if(cmd.flags == DRAWNUMBER_HEALTH)
|
||||
{
|
||||
value = health;
|
||||
if(cmd.value < 0) //health shouldn't display negatives
|
||||
if(value < 0) //health shouldn't display negatives
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
|
@ -1793,7 +1689,7 @@ private:
|
|||
max = 0;
|
||||
}
|
||||
}
|
||||
else //default to the classes health
|
||||
else //default to the class's health
|
||||
{
|
||||
max = CPlayer->mo->GetDefault()->health;
|
||||
}
|
||||
|
@ -1888,26 +1784,91 @@ private:
|
|||
value = 0;
|
||||
}
|
||||
}
|
||||
if(max != 0 || value < 0)
|
||||
if(max != 0 && value > 0)
|
||||
{
|
||||
value = (value*100)/max;
|
||||
if(value > 100)
|
||||
value = 100;
|
||||
value = (value << FRACBITS) / max;
|
||||
if(value > FRACUNIT)
|
||||
value = FRACUNIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = 0;
|
||||
}
|
||||
if(cmd.bar != NULL)
|
||||
delete cmd.bar;
|
||||
if (Images[cmd.sprite] != NULL)
|
||||
assert(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)
|
||||
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);
|
||||
screen->VirtualToRealCoordsInt(x, y, w, h, 320, 200, true);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
case SBARINFO_DRAWGEM:
|
||||
|
|
|
@ -37,7 +37,6 @@ struct SBarInfoCommand
|
|||
EColorRange translation;
|
||||
EColorRange translation2;
|
||||
EColorRange translation3;
|
||||
FBarTexture *bar;
|
||||
SBarInfoBlock subBlock; //for type SBarInfo_CMD_GAMEMODE
|
||||
};
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "version.h"
|
||||
|
@ -595,7 +596,42 @@ static bool FindFreeName (FString &fullname, const char *extension)
|
|||
|
||||
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()))
|
||||
{
|
||||
fullname = lbmname;
|
||||
|
|
|
@ -256,19 +256,7 @@ void FRandom::StaticReadRNGState (PNGHandle *png)
|
|||
// This is for use by DECORATE.
|
||||
extern FRandom pr_exrandom;
|
||||
|
||||
class NewRNGList : public TArray<FRandom*>
|
||||
{
|
||||
public:
|
||||
~NewRNGList()
|
||||
{
|
||||
for(unsigned i=0;i<Size();i++)
|
||||
{
|
||||
delete (*this)[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static NewRNGList NewRNGs;
|
||||
static TDeletingArray<FRandom *> NewRNGs;
|
||||
|
||||
FRandom *FRandom::StaticFindRNG (const char *name)
|
||||
{
|
||||
|
|
19
src/tarray.h
19
src/tarray.h
|
@ -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 -----------------------------------------------------------
|
||||
// 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
|
||||
|
@ -788,8 +803,8 @@ public:
|
|||
// NextPair
|
||||
//
|
||||
// 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
|
||||
// respective parts of the next pair in the table.
|
||||
// returns true, and pair is filled with a pointer to the pair in the
|
||||
// table.
|
||||
//
|
||||
//=======================================================================
|
||||
|
||||
|
|
114
src/v_draw.cpp
114
src/v_draw.cpp
|
@ -531,6 +531,8 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
|
|||
break;
|
||||
|
||||
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);
|
||||
break;
|
||||
|
||||
|
@ -542,51 +544,15 @@ bool DCanvas::ParseDrawTextureTags (FTexture *img, int x, int y, DWORD tag, va_l
|
|||
}
|
||||
va_end (tags);
|
||||
|
||||
if (parms->uclip >= parms->dclip || parms->lclip >= parms->rclip)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parms->virtWidth != Width || parms->virtHeight != Height)
|
||||
{
|
||||
int myratio = CheckRatio (Width, Height);
|
||||
int right = parms->x + parms->destwidth;
|
||||
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;
|
||||
}
|
||||
VirtualToRealCoords(parms->x, parms->y, parms->destwidth, parms->destheight,
|
||||
parms->virtWidth, parms->virtHeight, virtBottom, !parms->keepratio);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int myratio = CheckRatio (Width, Height);
|
||||
|
|
|
@ -200,6 +200,8 @@ public:
|
|||
// 2D Texture drawing
|
||||
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 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
|
||||
void STACK_ARGS DrawText (int normalcolor, int x, int y, const char *string, ...);
|
||||
|
|
Loading…
Reference in a new issue