From 3a1228bf9527f11ae4ae358f5e93446aa91170fd Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 30 Mar 2017 12:13:28 +0200 Subject: [PATCH] - exported the clipping rectangle to scripting and added a statusbar scaling wrapper for it. - fixed: BaseStatusBar.Fill did not pass its flags parameter to the native function. --- src/g_statusbar/sbar.h | 1 + src/g_statusbar/shared_sbar.cpp | 77 ++++++++++++++++++- src/v_draw.cpp | 31 ++++++++ wadsrc/static/zscript/base.txt | 4 + wadsrc/static/zscript/statusbar/statusbar.txt | 17 +++- 5 files changed, 126 insertions(+), 4 deletions(-) diff --git a/src/g_statusbar/sbar.h b/src/g_statusbar/sbar.h index 2f3f7b202..fd200c8d8 100644 --- a/src/g_statusbar/sbar.h +++ b/src/g_statusbar/sbar.h @@ -397,6 +397,7 @@ public: void DrawGraphic(FTextureID texture, double x, double y, int flags, double Alpha, double boxwidth, double boxheight, double scaleX, double scaleY); void DrawString(FFont *font, const FString &cstring, double x, double y, int flags, double Alpha, int translation, int spacing, bool monospaced, int shadowX, int shadowY); void Fill(PalEntry color, double x, double y, double w, double h, int flags = 0); + void SetClipRect(double x, double y, double w, double h, int flags = 0); void BeginStatusBar(int resW, int resH, int relTop, bool forceScaled); void BeginHUD(int resW, int resH, double Alpha, bool forceScaled = false); diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index d5330b2b5..160a0d499 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -1910,7 +1910,82 @@ DEFINE_ACTION_FUNCTION(DBaseStatusBar, Fill) PARAM_FLOAT(h); PARAM_INT_DEF(flags); if (!screen->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); - self->Fill(color, x, y, w, h); + self->Fill(color, x, y, w, h, flags); + return 0; +} + +//============================================================================ +// +// draw stuff +// +//============================================================================ + +void DBaseStatusBar::SetClipRect(double x, double y, double w, double h, int flags) +{ + // resolve auto-alignment before making any adjustments to the position values. + if (!(flags & DI_SCREEN_MANUAL_ALIGN)) + { + if (x < 0) flags |= DI_SCREEN_RIGHT; + else flags |= DI_SCREEN_LEFT; + if (y < 0) flags |= DI_SCREEN_BOTTOM; + else flags |= DI_SCREEN_TOP; + } + + x += drawOffset.X; + y += drawOffset.Y; + + if (!fullscreenOffsets) + { + StatusbarToRealCoords(x, y, w, h); + } + else + { + double orgx, orgy; + + switch (flags & DI_SCREEN_HMASK) + { + default: orgx = 0; break; + case DI_SCREEN_HCENTER: orgx = screen->GetWidth() / 2; break; + case DI_SCREEN_RIGHT: orgx = screen->GetWidth(); break; + } + + switch (flags & DI_SCREEN_VMASK) + { + default: orgy = 0; break; + case DI_SCREEN_VCENTER: orgy = screen->GetHeight() / 2; break; + case DI_SCREEN_BOTTOM: orgy = screen->GetHeight(); break; + } + + // move stuff in the top right corner a bit down if the fps counter is on. + if ((flags & (DI_SCREEN_HMASK | DI_SCREEN_VMASK)) == DI_SCREEN_RIGHT_TOP && vid_fps) y += 10; + + DVector2 Scale = GetHUDScale(); + + x *= Scale.X; + y *= Scale.Y; + w *= Scale.X; + h *= Scale.Y; + x += orgx; + y += orgy; + } + int x1 = int(x); + int y1 = int(y); + int ww = int(x + w - x1); // account for scaling to non-integers. Truncating the values separately would fail for cases like + int hh = int(y + h - y1); // y=3.5, height = 5.5 where adding both values gives a larger integer than adding the two integers. + + screen->SetClipRect(x1, y1, ww, hh); +} + + +DEFINE_ACTION_FUNCTION(DBaseStatusBar, SetClipRect) +{ + PARAM_SELF_PROLOGUE(DBaseStatusBar); + PARAM_FLOAT(x); + PARAM_FLOAT(y); + PARAM_FLOAT(w); + PARAM_FLOAT(h); + PARAM_INT_DEF(flags); + self->SetClipRect(x, y, w, h, flags); return 0; } diff --git a/src/v_draw.cpp b/src/v_draw.cpp index 2a1248f90..96d5626c2 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -190,6 +190,24 @@ void DCanvas::SetClipRect(int x, int y, int w, int h) clipwidth = clamp(w, 0, GetHeight() - y); } +DEFINE_ACTION_FUNCTION(_Screen, SetClipRect) +{ + PARAM_PROLOGUE; + PARAM_INT(x); + PARAM_INT(y); + PARAM_INT(w); + PARAM_INT(h); + screen->SetClipRect(x, y, w, h); + return 0; +} + +DEFINE_ACTION_FUNCTION(_Screen, ClearClipRect) +{ + PARAM_PROLOGUE; + screen->ClearClipRect(); + return 0; +} + void DCanvas::GetClipRect(int *x, int *y, int *w, int *h) { if (x) *x = clipleft; @@ -198,6 +216,19 @@ void DCanvas::GetClipRect(int *x, int *y, int *w, int *h) if (h) *h = clipheight; } +DEFINE_ACTION_FUNCTION(_Screen, GetClipRect) +{ + PARAM_PROLOGUE; + int x, y, w, h; + screen->GetClipRect(&x, &y, &w, &h); + if (numret > 0) ret[0].SetInt(x); + if (numret > 1) ret[1].SetInt(x); + if (numret > 2) ret[2].SetInt(x); + if (numret > 3) ret[3].SetInt(x); + return MIN(numret, 4); +} + + bool DCanvas::SetTextureParms(DrawParms *parms, FTexture *img, double xx, double yy) const { if (img != NULL) diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index d92f79b6d..77d6fa26b 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -166,6 +166,10 @@ struct Screen native native static void DrawFrame(int x, int y, int w, int h); native static Vector2, Vector2 VirtualToRealCoords(Vector2 pos, Vector2 size, Vector2 vsize, bool vbottom=false, bool handleaspect=true); native static double GetAspectRatio(); + native static void SetClipRect(int x, int y, int w, int h); + native static void ClearClipRect(); + native static int, int, int, int GetClipRect(); + // This is a leftover of the abandoned Inventory.DrawPowerup method. deprecated("2.5") static ui void DrawHUDTexture(TextureID tex, double x, double y) diff --git a/wadsrc/static/zscript/statusbar/statusbar.txt b/wadsrc/static/zscript/statusbar/statusbar.txt index 238e177bb..0af3442d2 100644 --- a/wadsrc/static/zscript/statusbar/statusbar.txt +++ b/wadsrc/static/zscript/statusbar/statusbar.txt @@ -327,6 +327,12 @@ class BaseStatusBar native ui native static String FormatNumber(int number, int minsize = 0, int maxsize = 0, int format = 0, String prefix = ""); native double, double, double, double StatusbarToRealCoords(double x, double y=0, double w=0, double h=0); native int GetTopOfStatusBar(); + native void SetClipRect(double x, double y, double w, double h, int flags = 0); + + void ClearClipRect() + { + screen.ClearClipRect(); + } //============================================================================ // @@ -984,13 +990,17 @@ class BaseStatusBar native ui double sizeOfImage = (horizontal ? texsize.X - border*2 : texsize.Y - border*2); Clip[(!horizontal) | ((!reverse)<<1)] = sizeOfImage - sizeOfImage *value; + // preserve the active clipping rectangle + int cx, cy, cw, ch; + [cx, cy, cw, ch] = screen.GetClipRect(); + if(border != 0) { for(int i = 0; i < 4; i++) Clip[i] += border; //Draw the whole foreground DrawTexture(ontex, position, flags | DI_ITEM_LEFT_TOP); - // SetClip + SetClipRect(position.X + Clip[0], position.Y + Clip[1], texsize.X - Clip[0] - Clip[2], texsize.Y - Clip[1] - Clip[3], flags); } if (offtex.IsValid() && TexMan.GetScaledSize(offtex) == texsize) DrawTexture(offtex, position, flags | DI_ITEM_LEFT_TOP); @@ -998,10 +1008,11 @@ class BaseStatusBar native ui if (border == 0) { - // SetClip + SetClipRect(position.X + Clip[0], position.Y + Clip[1], texsize.X - Clip[0] - Clip[2], texsize.Y - Clip[1] - Clip[3], flags); DrawTexture(ontex, position, flags | DI_ITEM_LEFT_TOP); } - // UnsetClip + // restore the previous clipping rectangle + screen.SetClipRect(cx, cy, cw, ch); } //============================================================================