From d1e27e533f4ee892f8aaebc006b1d76a1a3b23d9 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 5 Feb 2008 05:29:31 +0000 Subject: [PATCH] - 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) --- docs/rh-log.txt | 10 +- src/decallib.cpp | 14 +-- src/g_shared/sbarinfo.cpp | 203 +++++++++++++++----------------------- src/g_shared/sbarinfo.h | 1 - src/m_misc.cpp | 38 ++++++- src/m_random.cpp | 14 +-- src/tarray.h | 19 +++- src/v_draw.cpp | 114 +++++++++++++-------- src/v_video.h | 2 + 9 files changed, 220 insertions(+), 195 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index fc6d6d83e..99b4718f5 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -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. diff --git a/src/decallib.cpp b/src/decallib.cpp index 40bca2be2..e157cf2ba 100644 --- a/src/decallib.cpp +++ b/src/decallib.cpp @@ -101,19 +101,7 @@ struct FDecalAnimator FName Name; }; -class FDecalAnimatorArray : public TArray -{ -public: - ~FDecalAnimatorArray() - { - for (unsigned int i = 0; i < Size(); ++i) - { - delete (*this)[i]; - } - } -}; - -FDecalAnimatorArray Animators; +TDeletingArray Animators; struct DDecalThinker : public DThinker { diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index 44d93fb03..e0a398730 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -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: diff --git a/src/g_shared/sbarinfo.h b/src/g_shared/sbarinfo.h index 399a62dbb..8caab3a1e 100644 --- a/src/g_shared/sbarinfo.h +++ b/src/g_shared/sbarinfo.h @@ -37,7 +37,6 @@ struct SBarInfoCommand EColorRange translation; EColorRange translation2; EColorRange translation3; - FBarTexture *bar; SBarInfoBlock subBlock; //for type SBarInfo_CMD_GAMEMODE }; diff --git a/src/m_misc.cpp b/src/m_misc.cpp index ef6e9fd30..d9d9a9034 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #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; diff --git a/src/m_random.cpp b/src/m_random.cpp index 7583faabd..3fd1bde64 100644 --- a/src/m_random.cpp +++ b/src/m_random.cpp @@ -256,19 +256,7 @@ void FRandom::StaticReadRNGState (PNGHandle *png) // This is for use by DECORATE. extern FRandom pr_exrandom; -class NewRNGList : public TArray -{ -public: - ~NewRNGList() - { - for(unsigned i=0;i NewRNGs; FRandom *FRandom::StaticFindRNG (const char *name) { diff --git a/src/tarray.h b/src/tarray.h index a66369f62..e0d5bbcf7 100644 --- a/src/tarray.h +++ b/src/tarray.h @@ -286,6 +286,21 @@ private: } }; +// TDeletingArray ----------------------------------------------------------- +// An array that deletes its elements when it gets deleted. +template +class TDeletingArray : public TArray +{ +public: + ~TDeletingArray () + { + 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. // //======================================================================= diff --git a/src/v_draw.cpp b/src/v_draw.cpp index eabaaafd3..f063b8994 100644 --- a/src/v_draw.cpp +++ b/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); diff --git a/src/v_video.h b/src/v_video.h index c1445c85c..3eaff3830 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -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, ...);