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, ...);