diff --git a/src/g_statusbar/shared_sbar.cpp b/src/g_statusbar/shared_sbar.cpp index 06f5bed40..8b6b23170 100644 --- a/src/g_statusbar/shared_sbar.cpp +++ b/src/g_statusbar/shared_sbar.cpp @@ -1135,6 +1135,7 @@ void DBaseStatusBar::CallDraw(EHudState state) GlobalVMStack.Call(func, params, countof(params), nullptr, 0); } else Draw(state); + screen->ClearClipRect(); // make sure the scripts don't leave a valid clipping rect behind. } diff --git a/src/gl/system/gl_framebuffer.cpp b/src/gl/system/gl_framebuffer.cpp index 43c56018a..08afb72ae 100644 --- a/src/gl/system/gl_framebuffer.cpp +++ b/src/gl/system/gl_framebuffer.cpp @@ -361,6 +361,7 @@ FNativePalette *OpenGLFrameBuffer::CreatePalette(FRemapTable *remap) //========================================================================== bool OpenGLFrameBuffer::Begin2D(bool) { + ClearClipRect(); gl_RenderState.mViewMatrix.loadIdentity(); gl_RenderState.mProjectionMatrix.ortho(0, GetWidth(), GetHeight(), 0, -1.0f, 1.0f); gl_RenderState.ApplyMatrices(); @@ -428,7 +429,7 @@ void OpenGLFrameBuffer::Dim(PalEntry) Super::Dim(0); } -void OpenGLFrameBuffer::Dim(PalEntry color, float damount, int x1, int y1, int w, int h) +void OpenGLFrameBuffer::DoDim(PalEntry color, float damount, int x1, int y1, int w, int h) { if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr) GLRenderer->m2DDrawer->AddDim(color, damount, x1, y1, w, h); @@ -451,7 +452,7 @@ void OpenGLFrameBuffer::FlatFill (int left, int top, int right, int bottom, FTex // // //========================================================================== -void OpenGLFrameBuffer::Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color) +void OpenGLFrameBuffer::DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color) { if (GLRenderer != nullptr && GLRenderer->m2DDrawer != nullptr) GLRenderer->m2DDrawer->AddClear(left, top, right, bottom, palcolor, color); diff --git a/src/gl/system/gl_framebuffer.h b/src/gl/system/gl_framebuffer.h index 67d5969e5..72bdb7315 100644 --- a/src/gl/system/gl_framebuffer.h +++ b/src/gl/system/gl_framebuffer.h @@ -63,9 +63,9 @@ public: void DrawTextureParms(FTexture *img, DrawParms &parms); void DrawLine(int x1, int y1, int x2, int y2, int palcolor, uint32_t color); void DrawPixel(int x1, int y1, int palcolor, uint32_t color); - void Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color); + void DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color); void Dim(PalEntry color=0); - void Dim (PalEntry color, float damount, int x1, int y1, int w, int h); + void DoDim (PalEntry color, float damount, int x1, int y1, int w, int h); void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin=false); void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints, diff --git a/src/gl/system/gl_swframebuffer.cpp b/src/gl/system/gl_swframebuffer.cpp index 6ff2e0943..acf5dc40b 100644 --- a/src/gl/system/gl_swframebuffer.cpp +++ b/src/gl/system/gl_swframebuffer.cpp @@ -2410,6 +2410,7 @@ bool OpenGLSWFrameBuffer::OpenGLPal::Update() bool OpenGLSWFrameBuffer::Begin2D(bool copy3d) { + ClearClipRect(); if (!Accel2D) { return false; @@ -2488,7 +2489,7 @@ FNativePalette *OpenGLSWFrameBuffer::CreatePalette(FRemapTable *remap) // //========================================================================== -void OpenGLSWFrameBuffer::Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color) +void OpenGLSWFrameBuffer::DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color) { if (In2D < 2) { @@ -2517,7 +2518,7 @@ void OpenGLSWFrameBuffer::Clear(int left, int top, int right, int bottom, int pa // //========================================================================== -void OpenGLSWFrameBuffer::Dim(PalEntry color, float amount, int x1, int y1, int w, int h) +void OpenGLSWFrameBuffer::DoDim(PalEntry color, float amount, int x1, int y1, int w, int h) { if (amount <= 0) { diff --git a/src/gl/system/gl_swframebuffer.h b/src/gl/system/gl_swframebuffer.h index dc202a05c..03cc5a4e0 100644 --- a/src/gl/system/gl_swframebuffer.h +++ b/src/gl/system/gl_swframebuffer.h @@ -55,8 +55,8 @@ public: FNativeTexture *CreateTexture(FTexture *gametex, bool wrapping) override; FNativePalette *CreatePalette(FRemapTable *remap) override; void DrawTextureParms(FTexture *img, DrawParms &parms) override; - void Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color) override; - void Dim(PalEntry color, float amount, int x1, int y1, int w, int h) override; + void DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color) override; + void DoDim(PalEntry color, float amount, int x1, int y1, int w, int h) override; void FlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin) override; void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor) override; void DrawPixel(int x, int y, int palcolor, uint32_t rgbcolor) override; diff --git a/src/menu/menu.cpp b/src/menu/menu.cpp index 2050c4834..6d82bd680 100644 --- a/src/menu/menu.cpp +++ b/src/menu/menu.cpp @@ -279,6 +279,7 @@ void DMenu::CallDrawer() { VMValue params[] = { (DObject*)this }; GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); + screen->ClearClipRect(); // make sure the scripts don't leave a valid clipping rect behind. } } diff --git a/src/v_draw.cpp b/src/v_draw.cpp index d06628d43..a2caded53 100644 --- a/src/v_draw.cpp +++ b/src/v_draw.cpp @@ -155,6 +155,22 @@ void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms) } } +void DCanvas::SetClipRect(int x, int y, int w, int h) +{ + clipleft = clamp(x, 0, GetWidth()); + clipwidth = clamp(w, 0, GetWidth() - x); + cliptop = clamp(y, 0, GetHeight()); + clipwidth = clamp(w, 0, GetHeight() - y); +} + +void DCanvas::GetClipRect(int *x, int *y, int *w, int *h) +{ + if (x) *x = clipleft; + if (y) *y = cliptop; + if (w) *w = clipwidth; + if (h) *h = clipheight; +} + bool DCanvas::SetTextureParms(DrawParms *parms, FTexture *img, double xx, double yy) const { if (img != NULL) @@ -692,6 +708,15 @@ bool DCanvas::ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t t parms->remap = nullptr; } + // intersect with the canvas's clipping rectangle. + if (clipwidth >= 0 && clipheight >= 0) + { + if (parms->lclip < clipleft) parms->lclip = clipleft; + if (parms->rclip > clipleft + clipwidth) parms->rclip = clipleft + clipwidth; + if (parms->uclip < cliptop) parms->uclip = cliptop; + if (parms->dclip < cliptop + clipheight) parms->uclip = cliptop + clipheight; + } + if (parms->uclip >= parms->dclip || parms->lclip >= parms->rclip) { return false; @@ -800,22 +825,6 @@ DEFINE_ACTION_FUNCTION(_Screen, VirtualToRealCoords) return MIN(numret, 2); } -void DCanvas::VirtualToRealCoordsFixed(fixed_t &x, fixed_t &y, fixed_t &w, fixed_t &h, - int vwidth, int vheight, bool vbottom, bool handleaspect) const -{ - double dx, dy, dw, dh; - - dx = FIXED2DBL(x); - dy = FIXED2DBL(y); - dw = FIXED2DBL(w); - dh = FIXED2DBL(h); - VirtualToRealCoords(dx, dy, dw, dh, vwidth, vheight, vbottom, handleaspect); - x = FLOAT2FIXED(dx); - y = FLOAT2FIXED(dy); - w = FLOAT2FIXED(dw); - h = FLOAT2FIXED(dh); -} - void DCanvas::VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, int vwidth, int vheight, bool vbottom, bool handleaspect) const { @@ -900,7 +909,7 @@ void DCanvas::DrawPixel(int x, int y, int palColor, uint32_t realcolor) // //========================================================================== -void DCanvas::Clear (int left, int top, int right, int bottom, int palcolor, uint32_t color) +void DCanvas::DoClear (int left, int top, int right, int bottom, int palcolor, uint32_t color) { #ifndef NO_SWRENDER if (palcolor < 0 && APART(color) != 255) @@ -914,6 +923,33 @@ void DCanvas::Clear (int left, int top, int right, int bottom, int palcolor, uin #endif } +void DCanvas::Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color) +{ + if (clipwidth >= 0 && clipheight >= 0) + { + int w = right - left; + int h = bottom - top; + if (left < clipleft) + { + w -= (clipleft - left); + left = clipleft; + } + if (w > clipwidth) w = clipwidth; + if (w <= 0) return; + + if (top < cliptop) + { + h -= (cliptop - top); + top = cliptop; + } + if (h > clipheight) w = clipheight; + if (h <= 0) return; + right = left + w; + bottom = top + h; + } + DoClear(left, top, right, bottom, palcolor, color); +} + DEFINE_ACTION_FUNCTION(_Screen, Clear) { PARAM_PROLOGUE; @@ -935,13 +971,49 @@ DEFINE_ACTION_FUNCTION(_Screen, Clear) // //========================================================================== -void DCanvas::Dim(PalEntry color, float damount, int x1, int y1, int w, int h) +void DCanvas::DoDim(PalEntry color, float damount, int x1, int y1, int w, int h) { #ifndef NO_SWRENDER SWCanvas::Dim(this, color, damount, x1, y1, w, h); #endif } +void DCanvas::Dim(PalEntry color, float damount, int x1, int y1, int w, int h) +{ + if (clipwidth >= 0 && clipheight >= 0) + { + if (x1 < clipleft) + { + w -= (clipleft - x1); + x1 = clipleft; + } + if (w > clipwidth) w = clipwidth; + if (w <= 0) return; + + if (y1 < cliptop) + { + h -= (cliptop - y1); + y1 = cliptop; + } + if (h > clipheight) w = clipheight; + if (h <= 0) return; + } + DoDim(color, damount, x1, y1, w, h); +} + +DEFINE_ACTION_FUNCTION(_Screen, Dim) +{ + PARAM_PROLOGUE; + PARAM_INT(color); + PARAM_FLOAT(amount); + PARAM_INT(x1); + PARAM_INT(y1); + PARAM_INT(w); + PARAM_INT(h); + screen->Dim(color, float(amount), x1, y1, w, h); + return 0; +} + //========================================================================== // // DCanvas :: FillSimplePoly diff --git a/src/v_video.cpp b/src/v_video.cpp index a6482a90c..3dea831be 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -204,8 +204,6 @@ void V_MarkRect (int x, int y, int width, int height) { } -DCanvas *DCanvas::CanvasChain = NULL; - //========================================================================== // // DCanvas Constructor @@ -220,10 +218,6 @@ DCanvas::DCanvas (int _width, int _height, bool _bgra) Width = _width; Height = _height; Bgra = _bgra; - - // Add to list of active canvases - Next = CanvasChain; - CanvasChain = this; } //========================================================================== @@ -234,22 +228,6 @@ DCanvas::DCanvas (int _width, int _height, bool _bgra) DCanvas::~DCanvas () { - // Remove from list of active canvases - DCanvas *probe = CanvasChain, **prev; - - prev = &CanvasChain; - probe = CanvasChain; - - while (probe != NULL) - { - if (probe == this) - { - *prev = probe->Next; - break; - } - prev = &probe->Next; - probe = probe->Next; - } } //========================================================================== @@ -336,20 +314,6 @@ void DCanvas::Dim (PalEntry color) Dim (dimmer, amount, 0, 0, Width, Height); } -DEFINE_ACTION_FUNCTION(_Screen, Dim) -{ - PARAM_PROLOGUE; - PARAM_INT(color); - PARAM_FLOAT(amount); - PARAM_INT(x1); - PARAM_INT(y1); - PARAM_INT(w); - PARAM_INT(h); - screen->Dim(color, float(amount), x1, y1, w, h); - return 0; -} - - //========================================================================== // // DCanvas :: GetScreenshotBuffer @@ -1168,6 +1132,7 @@ void DFrameBuffer::SetBlendingRect (int x1, int y1, int x2, int y2) bool DFrameBuffer::Begin2D (bool copy3d) { + ClearClipRect(); return false; } diff --git a/src/v_video.h b/src/v_video.h index 444e80f04..56041a228 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -225,7 +225,8 @@ public: virtual void Dim (PalEntry color = 0); // Dim part of the canvas - virtual void Dim (PalEntry color, float amount, int x1, int y1, int w, int h); + virtual void Dim (PalEntry color, float amount, int x1, int y1, int w, int h) final; + virtual void DoDim(PalEntry color, float amount, int x1, int y1, int w, int h); // Fill an area with a texture virtual void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin=false); @@ -236,7 +237,8 @@ public: const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip); // Set an area to a specified color - virtual void Clear (int left, int top, int right, int bottom, int palcolor, uint32_t color); + virtual void Clear (int left, int top, int right, int bottom, int palcolor, uint32_t color) final; + virtual void DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color); // Draws a line virtual void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor); @@ -259,6 +261,10 @@ public: // Text drawing functions ----------------------------------------------- // 2D Texture drawing + void ClearClipRect() { clipleft = cliptop = 0; clipwidth = clipheight = -1; } + void SetClipRect(int x, int y, int w, int h); + void GetClipRect(int *x, int *y, int *w, int *h); + bool SetTextureParms(DrawParms *parms, FTexture *img, double x, double y) const; void DrawTexture (FTexture *img, double x, double y, int tags, ...); void DrawTexture(FTexture *img, double x, double y, VMVa_List &); @@ -266,7 +272,6 @@ public: void VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom=false, bool handleaspect=true) const; // Code that uses these (i.e. SBARINFO) should probably be evaluated for using doubles all around instead. - void VirtualToRealCoordsFixed(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; #ifdef DrawText @@ -285,6 +290,7 @@ protected: int Pitch; int LockCount; bool Bgra; + int clipleft = 0, cliptop = 0, clipwidth = -1, clipheight = -1; void DrawTextCommon(FFont *font, int normalcolor, double x, double y, const char *string, DrawParms &parms); diff --git a/src/wi_stuff.cpp b/src/wi_stuff.cpp index 9e2fc7ed7..f9a49eb0d 100644 --- a/src/wi_stuff.cpp +++ b/src/wi_stuff.cpp @@ -730,6 +730,7 @@ void WI_Drawer() { VMValue self = WI_Screen; GlobalVMStack.Call(func, &self, 1, nullptr, 0); + screen->ClearClipRect(); // make sure the scripts don't leave a valid clipping rect behind. // The internal handling here is somewhat poor. After being set to 'LeavingIntermission' // the screen is needed for one more draw operation so we cannot delete it right away but only here. diff --git a/src/win32/fb_d3d9.cpp b/src/win32/fb_d3d9.cpp index 3c07b9c14..4fd198a1b 100644 --- a/src/win32/fb_d3d9.cpp +++ b/src/win32/fb_d3d9.cpp @@ -2557,6 +2557,7 @@ bool D3DPal::Update() bool D3DFB::Begin2D(bool copy3d) { + ClearClipRect(); if (!Accel2D) { return false; @@ -2635,11 +2636,11 @@ FNativePalette *D3DFB::CreatePalette(FRemapTable *remap) // //========================================================================== -void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint32_t color) +void D3DFB::DoClear (int left, int top, int right, int bottom, int palcolor, uint32_t color) { if (In2D < 2) { - Super::Clear(left, top, right, bottom, palcolor, color); + //Super::Clear(left, top, right, bottom, palcolor, color); return; } if (!InScene) @@ -2664,7 +2665,7 @@ void D3DFB::Clear (int left, int top, int right, int bottom, int palcolor, uint3 // //========================================================================== -void D3DFB::Dim (PalEntry color, float amount, int x1, int y1, int w, int h) +void D3DFB::DoDim (PalEntry color, float amount, int x1, int y1, int w, int h) { if (amount <= 0) { diff --git a/src/win32/win32swiface.h b/src/win32/win32swiface.h index ecd5a49df..5c0a456e4 100644 --- a/src/win32/win32swiface.h +++ b/src/win32/win32swiface.h @@ -132,8 +132,8 @@ public: FNativeTexture *CreateTexture (FTexture *gametex, bool wrapping); FNativePalette *CreatePalette (FRemapTable *remap); void DrawTextureParms (FTexture *img, DrawParms &parms); - void Clear (int left, int top, int right, int bottom, int palcolor, uint32_t color); - void Dim (PalEntry color, float amount, int x1, int y1, int w, int h); + void DoClear (int left, int top, int right, int bottom, int palcolor, uint32_t color); + void DoDim (PalEntry color, float amount, int x1, int y1, int w, int h); void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin); void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor); void DrawPixel(int x, int y, int palcolor, uint32_t rgbcolor);