diff --git a/source/common/2d/v_2ddrawer.cpp b/source/common/2d/v_2ddrawer.cpp index d276bd0e3..68d2f8480 100644 --- a/source/common/2d/v_2ddrawer.cpp +++ b/source/common/2d/v_2ddrawer.cpp @@ -39,6 +39,7 @@ #include "v_draw.h" #include "v_video.h" #include "fcolormap.h" +#include "printf.h" static F2DDrawer drawer; F2DDrawer* twod = &drawer; @@ -401,10 +402,6 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms) double xscale = parms.destwidth / parms.texwidth; double yscale = parms.destheight / parms.texheight; - double x = parms.x - parms.left * xscale; - double y = parms.y - parms.top * yscale; - double w = parms.destwidth; - double h = parms.destheight; double u1, v1, u2, v2; PalEntry vertexcolor; @@ -433,38 +430,86 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms) if (parms.flipY) std::swap(v1, v2); - // This is crap. Only kept for backwards compatibility with scripts that may have used it. - // Note that this only works for unflipped full textures. - if (parms.windowleft > 0 || parms.windowright < parms.texwidth) + if (parms.rotateangle == 0) { - double wi = std::min(parms.windowright, parms.texwidth); - x += parms.windowleft * xscale; - w -= (parms.texwidth - wi + parms.windowleft) * xscale; + double x = parms.x - parms.left * xscale; + double y = parms.y - parms.top * yscale; + double w = parms.destwidth; + double h = parms.destheight; - u1 = float(u1 + parms.windowleft / parms.texwidth); - u2 = float(u2 - (parms.texwidth - wi) / parms.texwidth); + + // This is crap. Only kept for backwards compatibility with scripts that may have used it. + // Note that this only works for unflipped and unrotated full textures. + if (parms.windowleft > 0 || parms.windowright < parms.texwidth) + { + double wi = std::min(parms.windowright, parms.texwidth); + x += parms.windowleft * xscale; + w -= (parms.texwidth - wi + parms.windowleft) * xscale; + + u1 = float(u1 + parms.windowleft / parms.texwidth); + u2 = float(u2 - (parms.texwidth - wi) / parms.texwidth); + } + + if (x < (double)parms.lclip || y < (double)parms.uclip || x + w >(double)parms.rclip || y + h >(double)parms.dclip) + { + dg.mScissor[0] = parms.lclip; + dg.mScissor[1] = parms.uclip; + dg.mScissor[2] = parms.rclip; + dg.mScissor[3] = parms.dclip; + dg.mFlags |= DTF_Scissor; + } + else + { + memset(dg.mScissor, 0, sizeof(dg.mScissor)); + } + + dg.mVertCount = 4; + dg.mVertIndex = (int)mVertices.Reserve(4); + TwoDVertex* ptr = &mVertices[dg.mVertIndex]; + ptr->Set(x, y, 0, u1, v1, vertexcolor); ptr++; + ptr->Set(x, y + h, 0, u1, v2, vertexcolor); ptr++; + ptr->Set(x + w, y, 0, u2, v1, vertexcolor); ptr++; + ptr->Set(x + w, y + h, 0, u2, v2, vertexcolor); ptr++; } - - if (x < (double)parms.lclip || y < (double)parms.uclip || x + w >(double)parms.rclip || y + h >(double)parms.dclip) + else { + double radang = parms.rotateangle * (pi::pi() / 180.); + double cosang = cos(radang); + double sinang = sin(radang); + double xd1 = -parms.left; + double yd1 = -parms.top; + double xd2 = xd1 + parms.texwidth; + double yd2 = yd1 + parms.texheight; + + double x1 = parms.x + xscale * (xd1 * cosang + yd1 * sinang); + double y1 = parms.y - yscale * (xd1 * sinang - yd1 * cosang); + + double x2 = parms.x + xscale * (xd1 * cosang + yd2 * sinang); + double y2 = parms.y - yscale * (xd1 * sinang - yd2 * cosang); + + double x3 = parms.x + xscale * (xd2 * cosang + yd1 * sinang); + double y3 = parms.y - yscale * (xd2 * sinang - yd1 * cosang); + + double x4 = parms.x + xscale * (xd2 * cosang + yd2 * sinang); + double y4 = parms.y - yscale * (xd2 * sinang - yd2 * cosang); + + Printf(PRINT_NOTIFY, "%f, %f\n", y2, y4); + dg.mScissor[0] = parms.lclip; dg.mScissor[1] = parms.uclip; dg.mScissor[2] = parms.rclip; dg.mScissor[3] = parms.dclip; dg.mFlags |= DTF_Scissor; - } - else - { - memset(dg.mScissor, 0, sizeof(dg.mScissor)); - } - dg.mVertCount = 4; - dg.mVertIndex = (int)mVertices.Reserve(4); - TwoDVertex *ptr = &mVertices[dg.mVertIndex]; - ptr->Set(x, y, 0, u1, v1, vertexcolor); ptr++; - ptr->Set(x, y + h, 0, u1, v2, vertexcolor); ptr++; - ptr->Set(x + w, y, 0, u2, v1, vertexcolor); ptr++; - ptr->Set(x + w, y + h, 0, u2, v2, vertexcolor); ptr++; + dg.mVertCount = 4; + dg.mVertIndex = (int)mVertices.Reserve(4); + TwoDVertex* ptr = &mVertices[dg.mVertIndex]; + ptr->Set(x1, y1, 0, u1, v1, vertexcolor); ptr++; + ptr->Set(x2, y2, 0, u1, v2, vertexcolor); ptr++; + ptr->Set(x3, y3, 0, u2, v1, vertexcolor); ptr++; + ptr->Set(x4, y4, 0, u2, v2, vertexcolor); ptr++; + + } dg.mIndexIndex = mIndices.Size(); dg.mIndexCount += 6; AddIndices(dg.mVertIndex, 6, 0, 1, 2, 1, 3, 2); diff --git a/source/common/2d/v_draw.cpp b/source/common/2d/v_draw.cpp index d22cd264b..1bde79cea 100644 --- a/source/common/2d/v_draw.cpp +++ b/source/common/2d/v_draw.cpp @@ -636,6 +636,7 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double parms->fsscalemode = -1; parms->patchscalex = parms->patchscaley = 1; parms->viewport = { 0,0,drawer->GetWidth(), drawer->GetHeight() }; + parms->rotateangle = 0; // Parse the tag list for attributes. (For floating point attributes, // consider that the C ABI dictates that all floats be promoted to @@ -1069,6 +1070,12 @@ bool ParseDrawTextureTags(F2DDrawer *drawer, FGameTexture *img, double x, double case DTA_ViewportHeight: parms->viewport.height = ListGetInt(tags); break; + + case DTA_Rotate: + assert(fortext == false); + if (fortext) return false; + parms->rotateangle = ListGetDouble(tags); + break; } tag = ListGetInt(tags); } diff --git a/source/common/2d/v_draw.h b/source/common/2d/v_draw.h index 4a1005137..be4142145 100644 --- a/source/common/2d/v_draw.h +++ b/source/common/2d/v_draw.h @@ -103,6 +103,7 @@ enum DTA_CenterOffsetRel, // Apply texture offsets relative to center, instead of top left. This is standard alignment for Build's 2D content. DTA_TopLeft, // always align to top left. Added to have a boolean condition for this alignment. DTA_Pin, // Pin a non-widescreen image to the left/right edge of the screen. + DTA_Rotate, }; @@ -172,6 +173,7 @@ struct DrawParms double srcx, srcy; double srcwidth, srcheight; double patchscalex, patchscaley; + double rotateangle; IntRect viewport; }; diff --git a/source/core/statusbar.cpp b/source/core/statusbar.cpp index 6aab8a582..7a72e49dc 100644 --- a/source/core/statusbar.cpp +++ b/source/core/statusbar.cpp @@ -405,16 +405,16 @@ void DBaseStatusBar::StatusbarToRealCoords(double &x, double &y, double &w, doub // //============================================================================ -void DBaseStatusBar::DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color, int translation) +void DBaseStatusBar::DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color, int translation, double rotate) { if (!texture.isValid()) return; FGameTexture* tex = TexMan.GetGameTexture(texture, !(flags & DI_DONTANIMATE)); - DrawGraphic(tex, x, y, flags, Alpha, boxwidth, boxheight, scaleX, scaleY, color, translation); + DrawGraphic(tex, x, y, flags, Alpha, boxwidth, boxheight, scaleX, scaleY, color, translation, rotate); } -void DBaseStatusBar::DrawGraphic(FGameTexture* tex, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color, int translation) +void DBaseStatusBar::DrawGraphic(FGameTexture* tex, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color, int translation, double rotate) { double texwidth = tex->GetDisplayWidth() * scaleX; double texheight = tex->GetDisplayHeight() * scaleY; @@ -466,19 +466,29 @@ void DBaseStatusBar::DrawGraphic(FGameTexture* tex, double x, double y, int flag y += drawOffset.Y; double xo = 0, yo = 0; - switch (flags & DI_ITEM_HMASK) + if (flags & DI_ITEM_RELCENTER) { - case DI_ITEM_HCENTER: xo = texwidth / 2; break; - case DI_ITEM_RIGHT: xo = texwidth; break; - case DI_ITEM_HOFFSET: xo = tex->GetDisplayLeftOffset(); break; + xo = tex->GetDisplayWidth() / 2 + tex->GetDisplayLeftOffset(); + yo = tex->GetDisplayHeight() / 2 + tex->GetDisplayTopOffset(); } + else + { + switch (flags & DI_ITEM_HMASK) + { + case DI_ITEM_HCENTER: xo = tex->GetDisplayWidth() / 2; break; + case DI_ITEM_RIGHT: xo = tex->GetDisplayWidth(); break; + case DI_ITEM_HOFFSET: xo = tex->GetDisplayLeftOffset(); break; + } - switch (flags & DI_ITEM_VMASK) - { - case DI_ITEM_VCENTER: yo = texheight / 2; break; - case DI_ITEM_BOTTOM: yo = texheight; break; - case DI_ITEM_VOFFSET: yo = tex->GetDisplayTopOffset(); break; + switch (flags & DI_ITEM_VMASK) + { + case DI_ITEM_VCENTER: yo = tex->GetDisplayHeight() / 2; break; + case DI_ITEM_BOTTOM: yo = tex->GetDisplayHeight(); break; + case DI_ITEM_VOFFSET: yo = tex->GetDisplayTopOffset(); break; + } } + //xo *= scaleX; + //yo *= scaleY; if (!fullscreenOffsets) { @@ -527,6 +537,7 @@ void DBaseStatusBar::DrawGraphic(FGameTexture* tex, double x, double y, int flag DTA_AlphaChannel, !!(flags & DI_ALPHAMAPPED), DTA_FillColor, (flags & DI_ALPHAMAPPED) ? 0 : -1, DTA_FlipX, !!(flags & DI_MIRROR), + DTA_Rotate, rotate, TAG_DONE); } diff --git a/source/core/statusbar.h b/source/core/statusbar.h index 9199cf7e4..4173d507a 100644 --- a/source/core/statusbar.h +++ b/source/core/statusbar.h @@ -177,8 +177,8 @@ public: DVector2 GetHUDScale() const; void NewGame (); - void DrawGraphic(FGameTexture *texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0); - void DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0); + void DrawGraphic(FGameTexture *texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, double rotate = 0); + void DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY, PalEntry color = 0xffffffff, int translation = 0, double rotate = 0); void DrawString(FFont *font, const FString &cstring, double x, double y, int flags, double Alpha, int translation, int spacing, EMonospacing monospacing, int shadowX, int shadowY, double scaleX, double scaleY); void TransformRect(double &x, double &y, double &w, double &h, int flags = 0); void Fill(PalEntry color, double x, double y, double w, double h, int flags = 0); @@ -279,6 +279,7 @@ enum DI_Flags DI_DIMDEPLETED = 0x400, DI_DONTANIMATE = 0x800, // do not animate the texture DI_MIRROR = 0x1000, // flip the texture horizontally, like a mirror + DI_ITEM_RELCENTER = 0x2000, DI_SCREEN_AUTO = 0, // decide based on given offsets. DI_SCREEN_MANUAL_ALIGN = 0x4000, // If this is on, the following flags will have an effect diff --git a/source/games/duke/src/sbar_r.cpp b/source/games/duke/src/sbar_r.cpp index 7abee4eb3..838a96954 100644 --- a/source/games/duke/src/sbar_r.cpp +++ b/source/games/duke/src/sbar_r.cpp @@ -346,8 +346,8 @@ public: } // Todo: These need rotation support which currently does not exist. - DrawGraphic(tileGetTexture(GUTMETER), 257, top + 24, DI_ITEM_BOTTOM, 1, -1, -1, scale, scale, 0xffffffff, 0 /*, p->drunkang * 360. / 2048 */ ); - DrawGraphic(tileGetTexture(GUTMETER), 293, top + 24, DI_ITEM_BOTTOM, 1, -1, -1, scale, scale, 0xffffffff, 0 /*, p->eatang * 360. / 2048 */); + DrawGraphic(tileGetTexture(GUTMETER), 256, top + 15, DI_ITEM_RELCENTER, 1, -1, -1, scale, scale, 0xffffffff, 0, p->drunkang * (-360. / 2048)); + DrawGraphic(tileGetTexture(GUTMETER), 292, top + 15, DI_ITEM_RELCENTER, 1, -1, -1, scale, scale, 0xffffffff, 0, p->eatang * (-360. / 2048)); if (p->drink_amt >= 0 && p->drink_amt <= 30) {