From ea3f3a718ca71dc313dd148987e094390a8af1a1 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Thu, 3 Nov 2022 08:47:44 -0400 Subject: [PATCH 01/14] Add V_VFLIP Ironman can now be shitty --- src/deh_tables.c | 1 + src/hardware/hw_draw.c | 17 ++++++++++++++--- src/v_video.c | 41 +++++++++++++++++++++++++++-------------- src/v_video.h | 9 ++++++--- 4 files changed, 48 insertions(+), 20 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 5dcef079b..eb2143577 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1252,6 +1252,7 @@ struct int_const_s const INT_CONST[] = { {"V_OVERLAY",V_OVERLAY}, {"V_ALLOWLOWERCASE",V_ALLOWLOWERCASE}, {"V_FLIP",V_FLIP}, + {"V_VFLIP",V_VFLIP}, {"V_SNAPTOTOP",V_SNAPTOTOP}, {"V_SNAPTOBOTTOM",V_SNAPTOBOTTOM}, {"V_SNAPTOLEFT",V_SNAPTOLEFT}, diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index ca2881921..008838178 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -188,7 +188,10 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p offsetx = (float)(gpatch->leftoffset) * fscalew; // top offset - offsety = (float)(gpatch->topoffset) * fscaleh; + if (option & V_VFLIP) + offsety = (float)(gpatch->height - gpatch->topoffset) * fscaleh; + else + offsety = (float)(gpatch->topoffset) * fscaleh; cx -= offsetx; cy -= offsety; @@ -249,8 +252,16 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p v[2].s = v[1].s = hwrPatch->max_s; } - v[0].t = v[1].t = 0.0f; - v[2].t = v[3].t = hwrPatch->max_t; + if (option & V_VFLIP) + { + v[0].t = v[1].t = hwrPatch->max_t; + v[2].t = v[3].t = 0.0f; + } + else + { + v[0].t = v[1].t = 0.0f; + v[2].t = v[3].t = hwrPatch->max_t; + } flags = PF_NoDepthTest; diff --git a/src/v_video.c b/src/v_video.c index 8b96fa0b6..50979f8d6 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -627,10 +627,6 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca colfrac = FixedDiv(FRACUNIT, fdup); rowfrac = FixedDiv(FRACUNIT, vdup); - // So it turns out offsets aren't scaled in V_NOSCALESTART unless V_OFFSET is applied ...poo, that's terrible - // For now let's just at least give V_OFFSET the ability to support V_FLIP - // I'll probably make a better fix for 2.2 where I don't have to worry about breaking existing support for stuff - // -- Monster Iestyn 29/10/18 { fixed_t offsetx = 0, offsety = 0; @@ -641,15 +637,17 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca offsetx = FixedMul(patch->leftoffset<topoffset<height - patch->topoffset)<topoffset<= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) break; } + column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[col>>FRACBITS])); while (column->topdelta != 0xff) @@ -717,17 +716,31 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca topdelta += prevdelta; prevdelta = topdelta; source = (const UINT8 *)(column) + 3; + dest = desttop; if (scrn & V_FLIP) - dest = deststart + (destend - desttop); + dest = deststart + (destend - dest); dest += FixedInt(FixedMul(topdelta<>FRACBITS) < column->length; ofs += rowfrac) + if (scrn & V_VFLIP) { - if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) - *dest = patchdrawfunc(dest, source, ofs); - dest += vid.width; + for (ofs = (column->length << FRACBITS)-1; dest < deststop && ofs >= 0; ofs -= rowfrac) + { + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = patchdrawfunc(dest, source, ofs); + dest += vid.width; + } } + else + { + for (ofs = 0; dest < deststop && ofs < (column->length << FRACBITS); ofs += rowfrac) + { + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + *dest = patchdrawfunc(dest, source, ofs); + dest += vid.width; + } + } + column = (const column_t *)((const UINT8 *)column + column->length + 4); } } @@ -786,7 +799,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ y -= FixedMul(patch->topoffset<leftoffset<>FRACBITS) < column->length && (((ofs>>FRACBITS) - sy) + topdelta) < h; ofs += rowfrac) { - if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) *dest = patchdrawfunc(dest, source, ofs); dest += vid.width; } diff --git a/src/v_video.h b/src/v_video.h index 4aad49de2..8dbe029ff 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -85,11 +85,14 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue); #define V_GetColor(color) (pLocalPalette[color&0xFF]) #define V_GetMasterColor(color) (pMasterPalette[color&0xFF]) -// Bottom 8 bits are used for parameter (screen or character) +// Bottom 8 bits are used for parameter (character) #define V_PARAMMASK 0x000000FF -// strings/characters only -#define V_STRINGDANCE 0x00000002 +// Bottom bit is used for screen (patches) +#define V_SCREENMASK 0x0000000F + +#define V_STRINGDANCE 0x00000002 // (strings/characters only) funny undertale +#define V_VFLIP 0x00000010 // (patches only) Vertical flip // flags hacked in scrn (not supported by all functions (see src)) // patch scaling uses bits 9 and 10 From 11608cd1b7f2bf438d6d88c35688b84a69642d9b Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 11 Dec 2022 13:53:51 -0500 Subject: [PATCH 02/14] Clipping rectangle Instead of the absolute insanity that is V_DrawCroppedPatch, which makes you specify the number of pixels to crop off the top/left and then the number of pixels to show after the crop ... you just use V_SetClipRect to create a rectangle for any future draws to be cropped down to, and V_ClearClipRect afterwards to clear it. Currently only supported by V_DrawStretchyFixedPatch. Ideally other drawing functions should also receive clipping rectangle support too. --- src/hardware/hw_draw.c | 6 +- src/k_hud.c | 114 +----------- src/k_hud.h | 2 - src/typedef.h | 1 + src/v_video.c | 381 ++++++++++++++++++++++++++++------------- src/v_video.h | 13 ++ 6 files changed, 286 insertions(+), 231 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 008838178..ff58f05f3 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -207,7 +207,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p INT32 intx, inty; intx = (INT32)cx; inty = (INT32)cy; - K_AdjustXYWithSnap(&intx, &inty, option, dupx, dupy); + V_AdjustXYWithSnap(&intx, &inty, option, dupx, dupy); cx = (float)intx; cy = (float)inty; } @@ -1011,7 +1011,7 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32 intx = (INT32)fx; inty = (INT32)fy; - K_AdjustXYWithSnap(&intx, &inty, color, dupx, dupy); + V_AdjustXYWithSnap(&intx, &inty, color, dupx, dupy); fx = (float)intx; fy = (float)inty; } @@ -1103,7 +1103,7 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) intx = (INT32)fx; inty = (INT32)fy; - K_AdjustXYWithSnap(&intx, &inty, color, dupx, dupy); + V_AdjustXYWithSnap(&intx, &inty, color, dupx, dupy); fx = (float)intx; fy = (float)inty; } diff --git a/src/k_hud.c b/src/k_hud.c index 5da4c25ed..177b4a9b2 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -620,116 +620,6 @@ INT32 ITEM2_X, ITEM2_Y; INT32 LAPS2_X, LAPS2_Y; INT32 POSI2_X, POSI2_Y; -void K_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 dupy) -{ - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx - INT32 screenwidth = vid.width; - INT32 screenheight = vid.height; - INT32 basewidth = BASEVIDWIDTH * dupx; - INT32 baseheight = BASEVIDHEIGHT * dupy; - SINT8 player = -1; - UINT8 i; - - if (options & V_SPLITSCREEN) - { - if (r_splitscreen > 0) - { - screenheight /= 2; - baseheight /= 2; - } - - if (r_splitscreen > 1) - { - screenwidth /= 2; - basewidth /= 2; - } - } - - for (i = 0; i <= r_splitscreen; i++) - { - if (stplyr == &players[displayplayers[i]]) - { - player = i; - break; - } - } - - if (vid.width != (BASEVIDWIDTH * dupx)) - { - if (options & V_SNAPTORIGHT) - *x += (screenwidth - basewidth); - else if (!(options & V_SNAPTOLEFT)) - *x += (screenwidth - basewidth) / 2; - } - - if (vid.height != (BASEVIDHEIGHT * dupy)) - { - if (options & V_SNAPTOBOTTOM) - *y += (screenheight - baseheight); - else if (!(options & V_SNAPTOTOP)) - *y += (screenheight - baseheight) / 2; - } - - if (options & V_SPLITSCREEN) - { - if (r_splitscreen == 1) - { - if (player == 1) - *y += screenheight; - } - else if (r_splitscreen > 1) - { - if (player == 1 || player == 3) - *x += screenwidth; - - if (player == 2 || player == 3) - *y += screenheight; - } - } - - if (options & V_SLIDEIN) - { - const tic_t length = TICRATE/4; - tic_t timer = lt_exitticker; - if (bossinfo.boss == true) - { - if (leveltime <= 3) - timer = 0; - else - timer = leveltime-3; - } - - if (timer < length) - { - boolean slidefromright = false; - - const INT32 offsetAmount = (screenwidth * FRACUNIT/2) / length; - fixed_t offset = (screenwidth * FRACUNIT/2) - (timer * offsetAmount); - - offset += FixedMul(offsetAmount, renderdeltatics); - offset /= FRACUNIT; - - if (r_splitscreen > 1) - { - if (stplyr == &players[displayplayers[1]] || stplyr == &players[displayplayers[3]]) - slidefromright = true; - } - - if (options & V_SNAPTORIGHT) - slidefromright = true; - else if (options & V_SNAPTOLEFT) - slidefromright = false; - - if (slidefromright == true) - { - offset = -offset; - } - - *x -= offset; - } - } -} - // This version of the function was prototyped in Lua by Nev3r ... a HUGE thank you goes out to them! void K_ObjectTracking(trackingResult_t *result, vector3_t *point, boolean reverse) { @@ -1269,6 +1159,8 @@ static void K_drawKartItem(void) V_DrawScaledPatch(fx, fy, V_HUDTRANS|fflags, localbg); + V_SetClipRect((fx + 10) << FRACBITS, (fy + 10) << FRACBITS, 30 << FRACBITS, 30 << FRACBITS, V_HUDTRANS|V_SLIDEIN|fflags); + // Then, the numbers: if (stplyr->itemamount >= numberdisplaymin && !stplyr->itemroulette) { @@ -1288,6 +1180,8 @@ static void K_drawKartItem(void) else V_DrawFixedPatch(fx< 0) + { + screenheight /= 2; + baseheight /= 2; + } + + if (r_splitscreen > 1) + { + screenwidth /= 2; + basewidth /= 2; + } + } + + for (i = 0; i <= r_splitscreen; i++) + { + if (stplyr == &players[displayplayers[i]]) + { + player = i; + break; + } + } + + if (vid.width != (BASEVIDWIDTH * dupx)) + { + if (options & V_SNAPTORIGHT) + *x += (screenwidth - basewidth); + else if (!(options & V_SNAPTOLEFT)) + *x += (screenwidth - basewidth) / 2; + } + + if (vid.height != (BASEVIDHEIGHT * dupy)) + { + if (options & V_SNAPTOBOTTOM) + *y += (screenheight - baseheight); + else if (!(options & V_SNAPTOTOP)) + *y += (screenheight - baseheight) / 2; + } + + if (options & V_SPLITSCREEN) + { + if (r_splitscreen == 1) + { + if (player == 1) + *y += screenheight; + } + else if (r_splitscreen > 1) + { + if (player == 1 || player == 3) + *x += screenwidth; + + if (player == 2 || player == 3) + *y += screenheight; + } + } + + if (options & V_SLIDEIN) + { + const tic_t length = TICRATE/4; + tic_t timer = lt_exitticker; + if (bossinfo.boss == true) + { + if (leveltime <= 3) + timer = 0; + else + timer = leveltime-3; + } + + if (timer < length) + { + boolean slidefromright = false; + + const INT32 offsetAmount = (screenwidth * FRACUNIT/2) / length; + fixed_t offset = (screenwidth * FRACUNIT/2) - (timer * offsetAmount); + + offset += FixedMul(offsetAmount, renderdeltatics); + offset /= FRACUNIT; + + if (r_splitscreen > 1) + { + if (stplyr == &players[displayplayers[1]] || stplyr == &players[displayplayers[3]]) + slidefromright = true; + } + + if (options & V_SNAPTORIGHT) + slidefromright = true; + else if (options & V_SNAPTOLEFT) + slidefromright = false; + + if (slidefromright == true) + { + offset = -offset; + } + + *x -= offset; + } + } +} + +static cliprect_t cliprect; + +cliprect_t *V_GetClipRect(void) +{ + if (cliprect.enabled == false) + { + return NULL; + } + + return &cliprect; +} + +void V_SetClipRect(fixed_t x, fixed_t y, fixed_t w, fixed_t h, INT32 flags) +{ + // Adjust position. + if (!(flags & V_NOSCALESTART)) + { + fixed_t dupx = vid.dupx; + fixed_t dupy = vid.dupy; + + if (flags & V_SCALEPATCHMASK) + { + switch ((flags & V_SCALEPATCHMASK) >> V_SCALEPATCHSHIFT) + { + case 1: // V_NOSCALEPATCH + dupx = dupy = 1; + break; + case 2: // V_SMALLSCALEPATCH + dupx = vid.smalldupx; + dupy = vid.smalldupy; + break; + case 3: // V_MEDSCALEPATCH + dupx = vid.meddupx; + dupy = vid.meddupy; + break; + default: + break; + } + } + + dupx = dupy = (dupx < dupy ? dupx : dupy); + + x = FixedMul(x, dupx); + y = FixedMul(y, dupy); + w = FixedMul(w, dupx); + h = FixedMul(h, dupy); + + if (!(flags & V_SCALEPATCHMASK)) + { + V_AdjustXYWithSnap(&x, &y, flags, dupx, dupy); + } + } + + if (x < 0) + { + w += x; + x = 0; + } + + if (y < 0) + { + h += y; + y = 0; + } + + if (x > vid.width) + { + x = vid.width; + w = 0; + } + + if (y > vid.height) + { + y = vid.height; + h = 0; + } + + cliprect.l = x; + cliprect.t = y; + cliprect.r = x + w; + cliprect.b = y + h; + cliprect.flags = flags; + cliprect.enabled = true; + + /* + V_DrawFill(cliprect.l, cliprect.t, cliprect.r - cliprect.l, cliprect.b - cliprect.t, V_NOSCALESTART); + CONS_Printf("[(%d, %d), (%d, %d)]\n", cliprect.l, cliprect.t, cliprect.r, cliprect.b); + */ +} + +void V_ClearClipRect(void) +{ + cliprect.enabled = false; +} + static UINT8 hudplusalpha[11] = { 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0}; static UINT8 hudminusalpha[11] = { 10, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5}; @@ -562,6 +768,8 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca fixed_t pwidth; // patch width fixed_t offx = 0; // x offset + cliprect_t *const clip = V_GetClipRect(); + if (rendermode == render_none) return; @@ -670,7 +878,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca // Center it if necessary if (!(scrn & V_SCALEPATCHMASK)) { - K_AdjustXYWithSnap(&x, &y, scrn, dupx, dupy); + V_AdjustXYWithSnap(&x, &y, scrn, dupx, dupy); } desttop += (y*vid.width) + x; @@ -692,18 +900,19 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca for (col = 0; (col>>FRACBITS) < patch->width; col += colfrac, ++offx, desttop++) { INT32 topdelta, prevdelta = -1; + if (scrn & V_FLIP) // offx is measured from right edge instead of left { - if (x+pwidth-offx < 0) // don't draw off the left of the screen (WRAP PREVENTION) + if (x+pwidth-offx < (clip ? clip->l : 0)) // don't draw off the left of the screen (WRAP PREVENTION) break; - if (x+pwidth-offx >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) + if (x+pwidth-offx >= (clip ? clip->r : vid.width)) // don't draw off the right of the screen (WRAP PREVENTION) continue; } else { - if (x+offx < 0) // don't draw off the left of the screen (WRAP PREVENTION) + if (x+offx < (clip ? clip->l : 0)) // don't draw off the left of the screen (WRAP PREVENTION) continue; - if (x+offx >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) + if (x+offx >= (clip ? clip->r : vid.width)) // don't draw off the right of the screen (WRAP PREVENTION) break; } @@ -711,6 +920,8 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca while (column->topdelta != 0xff) { + fixed_t offy = 0; + topdelta = column->topdelta; if (topdelta <= prevdelta) topdelta += prevdelta; @@ -720,23 +931,60 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca dest = desttop; if (scrn & V_FLIP) dest = deststart + (destend - dest); - dest += FixedInt(FixedMul(topdelta<length << FRACBITS)-1; dest < deststop && ofs >= 0; ofs -= rowfrac) + for (ofs = (column->length << FRACBITS)-1; dest < deststop && ofs >= 0; ofs -= rowfrac, ++offy) { + if (clip != NULL) + { + const INT32 cy = y + topdelta - offy; + + if (cy < clip->t) // don't draw off the top of the clip rect + { + dest += vid.width; + continue; + } + + if (cy > clip->b) // don't draw off the bottom of the clip rect + { + dest += vid.width; + continue; + } + } + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) *dest = patchdrawfunc(dest, source, ofs); + dest += vid.width; } } else { - for (ofs = 0; dest < deststop && ofs < (column->length << FRACBITS); ofs += rowfrac) + for (ofs = 0; dest < deststop && ofs < (column->length << FRACBITS); ofs += rowfrac, ++offy) { + if (clip != NULL) + { + const INT32 cy = y + topdelta + offy; + + if (cy < clip->t) // don't draw off the top of the clip rect + { + dest += vid.width; + continue; + } + + if (cy > clip->b) // don't draw off the bottom of the clip rect + { + dest += vid.width; + continue; + } + } + if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) *dest = patchdrawfunc(dest, source, ofs); + dest += vid.width; } } @@ -749,115 +997,16 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca // Draws a patch cropped and scaled to arbitrary size. void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t *patch, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) { - UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t); - UINT32 alphalevel, blendmode; - // boolean flip = false; + cliprect_t oldClip = cliprect; - fixed_t col, ofs, colfrac, rowfrac, fdup; - INT32 dupx, dupy; - const column_t *column; - UINT8 *desttop, *dest; - const UINT8 *source, *deststop; + V_SetClipRect(x, y, w, h, scrn); - if (rendermode == render_none) - return; + x -= sx; + y -= sy; -#ifdef HWRENDER - //if (rendermode != render_soft && !con_startup) // Not this again - if (rendermode == render_opengl) - { - HWR_DrawCroppedPatch(patch,x,y,pscale,scrn,sx,sy,w,h); - return; - } -#endif + V_DrawStretchyFixedPatch(x, y, pscale, pscale, scrn, patch, NULL); - patchdrawfunc = standardpdraw; - - if ((blendmode = ((scrn & V_BLENDMASK) >> V_BLENDSHIFT))) - blendmode++; // realign to constants - if ((alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT))) - { - if (alphalevel == 10) // V_HUDTRANSHALF - alphalevel = hudminusalpha[st_translucency]; - else if (alphalevel == 11) // V_HUDTRANS - alphalevel = 10 - st_translucency; - else if (alphalevel == 12) // V_HUDTRANSDOUBLE - alphalevel = hudplusalpha[st_translucency]; - - if (alphalevel >= 10) // Still inelegible to render? - return; - } - if ((v_translevel = R_GetBlendTable(blendmode, alphalevel))) - patchdrawfunc = translucentpdraw; - - // only use one dup, to avoid stretching (har har) - dupx = dupy = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - fdup = FixedMul(dupx<topoffset<leftoffset<>= FRACBITS; - y >>= FRACBITS; - desttop += (y*vid.width) + x; - } - else - { - x = FixedMul(x,dupx<>= FRACBITS; - y >>= FRACBITS; - - // Center it if necessary - // adjustxy - - desttop += (y*vid.width) + x; - } - - for (col = sx<>FRACBITS) < patch->width && ((col>>FRACBITS) - sx) < w; col += colfrac, ++x, desttop++) - { - INT32 topdelta, prevdelta = -1; - if (x < 0) // don't draw off the left of the screen (WRAP PREVENTION) - continue; - if (x >= vid.width) // don't draw off the right of the screen (WRAP PREVENTION) - break; - column = (const column_t *)((const UINT8 *)(patch->columns) + (patch->columnofs[col>>FRACBITS])); - - while (column->topdelta != 0xff) - { - topdelta = column->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)(column) + 3; - dest = desttop; - if (topdelta-sy > 0) - { - dest += FixedInt(FixedMul((topdelta-sy)<>FRACBITS) < column->length && (((ofs>>FRACBITS) - sy) + topdelta) < h; ofs += rowfrac) - { - if (dest >= screens[scrn&V_SCREENMASK]) // don't draw off the top of the screen (CRASH PREVENTION) - *dest = patchdrawfunc(dest, source, ofs); - dest += vid.width; - } - column = (const column_t *)((const UINT8 *)column + column->length + 4); - } - } + cliprect = oldClip; } // @@ -956,7 +1105,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) h *= dupy; // Center it if necessary - K_AdjustXYWithSnap(&x, &y, c, dupx, dupy); + V_AdjustXYWithSnap(&x, &y, c, dupx, dupy); } if (x >= vid.width || y >= vid.height) @@ -1083,7 +1232,7 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) h *= dupy; // Center it if necessary - K_AdjustXYWithSnap(&x, &y, c, dupx, dupy); + V_AdjustXYWithSnap(&x, &y, c, dupx, dupy); } if (x >= vid.width || y >= vid.height) @@ -1170,7 +1319,7 @@ void V_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 c) wh *= dupx; // Center it if necessary - K_AdjustXYWithSnap(&x, &y, c, dupx, dupy); + V_AdjustXYWithSnap(&x, &y, c, dupx, dupy); } if (x >= vid.width || y >= vid.height) diff --git a/src/v_video.h b/src/v_video.h index 8dbe029ff..a88681846 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -171,6 +171,19 @@ void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue); #define V_NOSCALESTART 0x40000000 // don't scale x, y, start coords #define V_SPLITSCREEN 0x80000000 // Add half of screen width or height automatically depending on player number +void V_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 dupy); + +struct cliprect_t +{ + fixed_t l, r, t, b; + INT32 flags; + boolean enabled; +}; + +cliprect_t *V_GetClipRect(void); +void V_SetClipRect(fixed_t x, fixed_t y, fixed_t w, fixed_t h, INT32 flags); +void V_ClearClipRect(void); + // defines for old functions #define V_DrawPatch(x,y,s,p) V_DrawFixedPatch((x)< Date: Sun, 11 Dec 2022 14:02:48 -0500 Subject: [PATCH 03/14] Comment out test case --- src/k_hud.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/k_hud.c b/src/k_hud.c index 177b4a9b2..5804bcc5d 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -1159,7 +1159,7 @@ static void K_drawKartItem(void) V_DrawScaledPatch(fx, fy, V_HUDTRANS|fflags, localbg); - V_SetClipRect((fx + 10) << FRACBITS, (fy + 10) << FRACBITS, 30 << FRACBITS, 30 << FRACBITS, V_HUDTRANS|V_SLIDEIN|fflags); + //V_SetClipRect((fx + 10) << FRACBITS, (fy + 10) << FRACBITS, 30 << FRACBITS, 30 << FRACBITS, V_HUDTRANS|V_SLIDEIN|fflags); // Then, the numbers: if (stplyr->itemamount >= numberdisplaymin && !stplyr->itemroulette) @@ -1180,7 +1180,7 @@ static void K_drawKartItem(void) else V_DrawFixedPatch(fx< Date: Sun, 11 Dec 2022 14:14:12 -0500 Subject: [PATCH 04/14] Clear clipping rectangle before each hook call Prevents Lua from being able to make a mess. --- src/d_main.cpp | 3 +++ src/lua_hooklib.c | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/src/d_main.cpp b/src/d_main.cpp index 1ae89e800..e3a492cf5 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -371,6 +371,9 @@ static bool D_Display(void) if (dedicated) //bail out after wipe logic return false; + // Catch runaway clipping rectangles. + V_ClearClipRect(); + // do buffered drawing switch (gamestate) { diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index f186ccabf..f1439c889 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -27,6 +27,8 @@ #include "d_netcmd.h" // for cv_perfstats #include "i_system.h" // I_GetPreciseTime +#include "v_video.h" // V_ClearClipRect + /* ========================================================================= ABSTRACTION ========================================================================= */ @@ -672,8 +674,13 @@ void LUA_HookHUD(huddrawlist_h list, int hook_type) hud_interpcounter = 0; hud_running = true; // local hook + + // Catch runaway clipping rectangles. + V_ClearClipRect(); + init_hook_call(&hook, 0, res_none); call_mapped_hud(&hook, map); + hud_running = false; } } From 34fc4066d7a7845e76051ff6f9be0a96aaf31eac Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Sun, 11 Dec 2022 16:47:25 -0500 Subject: [PATCH 05/14] Prevent modifying cliprect, wordier vars --- src/v_video.c | 28 ++++++++++++++-------------- src/v_video.h | 4 ++-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index 43f524e68..0583a96fa 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -638,7 +638,7 @@ void V_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 du static cliprect_t cliprect; -cliprect_t *V_GetClipRect(void) +const cliprect_t *V_GetClipRect(void) { if (cliprect.enabled == false) { @@ -713,10 +713,10 @@ void V_SetClipRect(fixed_t x, fixed_t y, fixed_t w, fixed_t h, INT32 flags) h = 0; } - cliprect.l = x; - cliprect.t = y; - cliprect.r = x + w; - cliprect.b = y + h; + cliprect.left = x; + cliprect.top = y; + cliprect.right = x + w; + cliprect.bottom = y + h; cliprect.flags = flags; cliprect.enabled = true; @@ -768,7 +768,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca fixed_t pwidth; // patch width fixed_t offx = 0; // x offset - cliprect_t *const clip = V_GetClipRect(); + const cliprect_t *clip = V_GetClipRect(); if (rendermode == render_none) return; @@ -903,16 +903,16 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca if (scrn & V_FLIP) // offx is measured from right edge instead of left { - if (x+pwidth-offx < (clip ? clip->l : 0)) // don't draw off the left of the screen (WRAP PREVENTION) + if (x+pwidth-offx < (clip ? clip->left : 0)) // don't draw off the left of the screen (WRAP PREVENTION) break; - if (x+pwidth-offx >= (clip ? clip->r : vid.width)) // don't draw off the right of the screen (WRAP PREVENTION) + if (x+pwidth-offx >= (clip ? clip->right : vid.width)) // don't draw off the right of the screen (WRAP PREVENTION) continue; } else { - if (x+offx < (clip ? clip->l : 0)) // don't draw off the left of the screen (WRAP PREVENTION) + if (x+offx < (clip ? clip->left : 0)) // don't draw off the left of the screen (WRAP PREVENTION) continue; - if (x+offx >= (clip ? clip->r : vid.width)) // don't draw off the right of the screen (WRAP PREVENTION) + if (x+offx >= (clip ? clip->right : vid.width)) // don't draw off the right of the screen (WRAP PREVENTION) break; } @@ -942,13 +942,13 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca { const INT32 cy = y + topdelta - offy; - if (cy < clip->t) // don't draw off the top of the clip rect + if (cy < clip->top) // don't draw off the top of the clip rect { dest += vid.width; continue; } - if (cy > clip->b) // don't draw off the bottom of the clip rect + if (cy > clip->bottom) // don't draw off the bottom of the clip rect { dest += vid.width; continue; @@ -969,13 +969,13 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca { const INT32 cy = y + topdelta + offy; - if (cy < clip->t) // don't draw off the top of the clip rect + if (cy < clip->top) // don't draw off the top of the clip rect { dest += vid.width; continue; } - if (cy > clip->b) // don't draw off the bottom of the clip rect + if (cy > clip->bottom) // don't draw off the bottom of the clip rect { dest += vid.width; continue; diff --git a/src/v_video.h b/src/v_video.h index a88681846..1bd2eb822 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -175,12 +175,12 @@ void V_AdjustXYWithSnap(INT32 *x, INT32 *y, UINT32 options, INT32 dupx, INT32 du struct cliprect_t { - fixed_t l, r, t, b; + fixed_t left, right, top, bottom; INT32 flags; boolean enabled; }; -cliprect_t *V_GetClipRect(void); +const cliprect_t *V_GetClipRect(void); void V_SetClipRect(fixed_t x, fixed_t y, fixed_t w, fixed_t h, INT32 flags); void V_ClearClipRect(void); From bdb7d5c6a053c3dc50598e9bacd8839230d2473f Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Dec 2022 17:43:11 -0800 Subject: [PATCH 06/14] Fix off-by-one when clipping rectangle bottom --- src/v_video.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/v_video.c b/src/v_video.c index 0583a96fa..709bf489d 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -948,7 +948,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca continue; } - if (cy > clip->bottom) // don't draw off the bottom of the clip rect + if (cy >= clip->bottom) // don't draw off the bottom of the clip rect { dest += vid.width; continue; @@ -975,7 +975,7 @@ void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vsca continue; } - if (cy > clip->bottom) // don't draw off the bottom of the clip rect + if (cy >= clip->bottom) // don't draw off the bottom of the clip rect { dest += vid.width; continue; From 81978cd7f1a4db9a06d2fd7c404ef0b4c4cc3be1 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 11 Dec 2022 17:44:49 -0800 Subject: [PATCH 07/14] OpenGL: clipping support for HWR_DrawStretchyFixedPatch --- src/hardware/hw_draw.c | 56 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index ff58f05f3..e79860261 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -145,6 +145,11 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p // 0--1 float dupx, dupy, fscalew, fscaleh, fwidth, fheight; + const cliprect_t *clip = V_GetClipRect(); + + float s_min, s_max; + float t_min, t_max; + // make patch ready in hardware cache if (!colormap) HWR_GetPatch(gpatch); @@ -224,6 +229,41 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p fheight = (float)(gpatch->height) * dupy; } + s_min = t_min = 0.0f; + s_max = hwrPatch->max_s; + t_max = hwrPatch->max_t; + + if (clip) + { + if (cx < clip->left) + { + s_min = ((clip->left - cx) / fwidth) * s_max; + cx = clip->left; + } + + if (cy < clip->top) + { + t_min = ((clip->top - cy) / fheight) * t_max; + cy = clip->top; + } + + if ((cx + fwidth) > clip->right) + { + const float n = (clip->right - clip->left); + + s_max = (s_min + ((n / fwidth) * s_max)); + fwidth = n; + } + + if ((cy + fheight) > clip->bottom) + { + const float n = (clip->bottom - clip->top); + + t_max = (t_min + ((n / fheight) * t_max)); + fheight = n; + } + } + // positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1 cx = -1.0f + (cx / (vid.width / 2.0f)); cy = 1.0f - (cy / (vid.height / 2.0f)); @@ -243,24 +283,24 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p if (option & V_FLIP) { - v[0].s = v[3].s = hwrPatch->max_s; - v[2].s = v[1].s = 0.0f; + v[0].s = v[3].s = s_max; + v[2].s = v[1].s = s_min; } else { - v[0].s = v[3].s = 0.0f; - v[2].s = v[1].s = hwrPatch->max_s; + v[0].s = v[3].s = s_min; + v[2].s = v[1].s = s_max; } if (option & V_VFLIP) { - v[0].t = v[1].t = hwrPatch->max_t; - v[2].t = v[3].t = 0.0f; + v[0].t = v[1].t = t_max; + v[2].t = v[3].t = t_min; } else { - v[0].t = v[1].t = 0.0f; - v[2].t = v[3].t = hwrPatch->max_t; + v[0].t = v[1].t = t_min; + v[2].t = v[3].t = t_max; } flags = PF_NoDepthTest; From c797b3bff5d2b93e10535783417464a52cccdbdb Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 17 Dec 2022 18:38:40 -0800 Subject: [PATCH 08/14] opengl: fix bottom and right edge of clip rect --- src/hardware/hw_draw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index e79860261..76cc2e289 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -249,7 +249,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p if ((cx + fwidth) > clip->right) { - const float n = (clip->right - clip->left); + const float n = (clip->right - cx); s_max = (s_min + ((n / fwidth) * s_max)); fwidth = n; @@ -257,7 +257,7 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p if ((cy + fheight) > clip->bottom) { - const float n = (clip->bottom - clip->top); + const float n = (clip->bottom - cy); t_max = (t_min + ((n / fheight) * t_max)); fheight = n; From d4f54fa28e09cdda4310dbe5b317c4f1f1d01591 Mon Sep 17 00:00:00 2001 From: James R Date: Mon, 25 Mar 2024 17:34:53 -0700 Subject: [PATCH 09/14] Legacy GL: fix cliprect in top/left - UV were not adjusted correctly when clipped in the top/left. - Code is more plainly written. --- src/hardware/hw_draw.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 76cc2e289..50655f6aa 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -235,33 +235,39 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p if (clip) { - if (cx < clip->left) + float cx1 = cx; + float cy1 = cy; + float cx2 = cx + fwidth; + float cy2 = cy + fheight; + + if (cx1 < clip->left) { - s_min = ((clip->left - cx) / fwidth) * s_max; - cx = clip->left; + s_min = (clip->left - cx1) / fwidth * hwrPatch->max_s; + cx1 = clip->left; } - if (cy < clip->top) + if (cy1 < clip->top) { - t_min = ((clip->top - cy) / fheight) * t_max; - cy = clip->top; + t_min = (clip->top - cy1) / fheight * hwrPatch->max_t; + cy1 = clip->top; } - if ((cx + fwidth) > clip->right) + if (cx2 > clip->right) { - const float n = (clip->right - cx); - - s_max = (s_min + ((n / fwidth) * s_max)); - fwidth = n; + s_max = s_min + (clip->right - cx1) / fwidth * hwrPatch->max_s; + cx2 = clip->right; } - if ((cy + fheight) > clip->bottom) + if (cy2 > clip->bottom) { - const float n = (clip->bottom - cy); - - t_max = (t_min + ((n / fheight) * t_max)); - fheight = n; + t_max = t_min + (clip->bottom - cy1) / fheight * hwrPatch->max_t; + cy2 = clip->bottom; } + + cx = cx1; + cy = cy1; + fwidth = cx2 - cx1; + fheight = cy2 - cy1; } // positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1 From 3e1e1245cee19bf54b3cc3655ea20f975da97eed Mon Sep 17 00:00:00 2001 From: hayaunderscore Date: Tue, 4 Jun 2024 17:13:35 +0800 Subject: [PATCH 10/14] Expose `V_SetClipRect` and `V_ClearClipRect` to lua Via the `v.setClipRect` and `v.clearClipRect` functions respectively. --- src/lua_hudlib.c | 41 +++++++++++++++++++++++++++++++++++++++ src/lua_hudlib_drawlist.c | 36 ++++++++++++++++++++++++++++++++++ src/lua_hudlib_drawlist.h | 11 +++++++++++ 3 files changed, 88 insertions(+) diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 46d5b8a02..e3cf0db32 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -972,6 +972,45 @@ static int libd_drawKartString(lua_State *L) return 0; } +static int libd_setClipRect(lua_State *L) +{ + fixed_t x = luaL_checkinteger(L, 1); + fixed_t y = luaL_checkinteger(L, 2); + fixed_t w = luaL_checkinteger(L, 3); + fixed_t h = luaL_checkinteger(L, 4); + INT32 flags = luaL_optinteger(L, 5, 0); + huddrawlist_h list; + + flags &= ~V_PARAMMASK; // Don't let crashes happen. + + HUDONLY + lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); + list = (huddrawlist_h) lua_touserdata(L, -1); + lua_pop(L, 1); + + if (LUA_HUD_IsDrawListValid(list)) + LUA_HUD_AddSetClipRect(list, x, y, w, h, flags); + else + V_SetClipRect(x, y, w, h, flags); + return 0; +} + +static int libd_clearClipRect(lua_State *L) +{ + huddrawlist_h list; + + HUDONLY + lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); + list = (huddrawlist_h) lua_touserdata(L, -1); + lua_pop(L, 1); + + if (LUA_HUD_IsDrawListValid(list)) + LUA_HUD_AddClearClipRect(list); + else + V_ClearClipRect(); + return 0; +} + static int libd_titleCardStringWidth(lua_State *L) { const char *str = luaL_checkstring(L, 1); @@ -1263,6 +1302,8 @@ static luaL_Reg lib_draw[] = { {"drawString", libd_drawString}, {"drawTitleCardString", libd_drawTitleCardString}, {"drawKartString", libd_drawKartString}, + {"setClipRect", libd_setClipRect}, + {"clearClipRect", libd_clearClipRect}, // misc {"stringWidth", libd_stringWidth}, {"titleCardStringWidth", libd_titleCardStringWidth}, diff --git a/src/lua_hudlib_drawlist.c b/src/lua_hudlib_drawlist.c index 9a12c7b99..ae62b629b 100644 --- a/src/lua_hudlib_drawlist.c +++ b/src/lua_hudlib_drawlist.c @@ -37,6 +37,8 @@ enum drawitem_e { DI_DrawTitleCardString, DI_DrawTitleCardStringBoss, DI_DrawKartString, + DI_SetClipRect, + DI_ClearClipRect, DI_MAX, }; @@ -555,6 +557,34 @@ void LUA_HUD_AddDrawKartString( // CalcStringCoords(item, str); } +void LUA_HUD_AddSetClipRect( + huddrawlist_h list, + fixed_t x, + fixed_t y, + fixed_t w, + fixed_t h, + INT32 flags +) +{ + size_t i = AllocateDrawItem(list); + drawitem_t *item = &list->items[i]; + item->type = DI_SetClipRect; + item->x = x; + item->y = y; + item->w = w; + item->h = h; + item->flags = flags; +} + +void LUA_HUD_AddClearClipRect( + huddrawlist_h list +) +{ + size_t i = AllocateDrawItem(list); + drawitem_t *item = &list->items[i]; + item->type = DI_ClearClipRect; +} + void LUA_HUD_DrawList(huddrawlist_h list) { size_t i; @@ -692,6 +722,12 @@ void LUA_HUD_DrawList(huddrawlist_h list) case DI_DrawKartString: V_DrawKartString(LERPS(x), LERPS(y), item->flags, itemstr); break; + case DI_SetClipRect: + V_SetClipRect(item->x, item->y, item->w, item->h, item->flags); + break; + case DI_ClearClipRect: + V_ClearClipRect(); + break; default: I_Error("can't draw draw list item: invalid draw list item type"); continue; diff --git a/src/lua_hudlib_drawlist.h b/src/lua_hudlib_drawlist.h index 15249e4f9..1e6bb97d9 100644 --- a/src/lua_hudlib_drawlist.h +++ b/src/lua_hudlib_drawlist.h @@ -120,6 +120,17 @@ void LUA_HUD_AddDrawKartString( const char *str, INT32 flags ); +void LUA_HUD_AddSetClipRect( + huddrawlist_h list, + fixed_t x, + fixed_t y, + fixed_t w, + fixed_t h, + INT32 flags +); +void LUA_HUD_AddClearClipRect( + huddrawlist_h list +); // Draws the given draw list void LUA_HUD_DrawList(huddrawlist_h list); From abc004ddc89d67149ecddee5d3ca98fc9ebaf3c9 Mon Sep 17 00:00:00 2001 From: hayaunderscore Date: Mon, 26 Aug 2024 10:25:09 +0800 Subject: [PATCH 11/14] Move V_ClearClipRect after call_mapped based on toaster's suggestion --- src/lua_hooklib.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index f1439c889..3dca19072 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -675,12 +675,12 @@ void LUA_HookHUD(huddrawlist_h list, int hook_type) hud_running = true; // local hook - // Catch runaway clipping rectangles. - V_ClearClipRect(); - init_hook_call(&hook, 0, res_none); call_mapped_hud(&hook, map); + // Catch runaway clipping rectangles. + V_ClearClipRect(); + hud_running = false; } } From 51aeaa7529a54255d41bedb74091883c86d820b8 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Sat, 22 Feb 2025 02:25:25 +0100 Subject: [PATCH 12/14] Interop late, fix runaway cliprects, cleanup --- src/lua_hudlib_drawlist.c | 11 ++++++++++- src/st_stuff.c | 17 +++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/lua_hudlib_drawlist.c b/src/lua_hudlib_drawlist.c index ae62b629b..c368d5026 100644 --- a/src/lua_hudlib_drawlist.c +++ b/src/lua_hudlib_drawlist.c @@ -203,6 +203,7 @@ static size_t CopyString(huddrawlist_h list, const char* str) } } +/* static void CalcStringCoords(drawitem_t *item, const char *string) { if (!(item->flags & V_NOSCALESTART)) @@ -309,6 +310,7 @@ static void CalcFillCoords(drawitem_t *item) item->y = y; } } +*/ #define INTERP_LATCH 1 #define INTERP_STRING 2 @@ -510,6 +512,8 @@ void LUA_HUD_AddFadeScreen( { size_t i = AllocateDrawItem(list); drawitem_t *item = &list->items[i]; + // nothing to interpolate here + item->id = 0; item->type = DI_FadeScreen; item->color = color; item->strength = strength; @@ -568,6 +572,7 @@ void LUA_HUD_AddSetClipRect( { size_t i = AllocateDrawItem(list); drawitem_t *item = &list->items[i]; + item->id = GetItemId(); item->type = DI_SetClipRect; item->x = x; item->y = y; @@ -582,6 +587,7 @@ void LUA_HUD_AddClearClipRect( { size_t i = AllocateDrawItem(list); drawitem_t *item = &list->items[i]; + item->id = 0; item->type = DI_ClearClipRect; } @@ -723,7 +729,7 @@ void LUA_HUD_DrawList(huddrawlist_h list) V_DrawKartString(LERPS(x), LERPS(y), item->flags, itemstr); break; case DI_SetClipRect: - V_SetClipRect(item->x, item->y, item->w, item->h, item->flags); + V_SetClipRect(LERPS(x), LERPS(y), LERP(w), LERP(h), item->flags); break; case DI_ClearClipRect: V_ClearClipRect(); @@ -733,4 +739,7 @@ void LUA_HUD_DrawList(huddrawlist_h list) continue; } } + + // who are you running from? + V_ClearClipRect(); } diff --git a/src/st_stuff.c b/src/st_stuff.c index 6e5079962..d108a1c9c 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -724,7 +724,7 @@ void ST_preLevelTitleCardDrawer(void) // Draw the status bar overlay, customisable: the user chooses which // kind of information to overlay // -static void ST_overlayDrawer(UINT8 playernum) +static void ST_overlayDrawer(void) { // hu_showscores = auto hide score/time/rings when tab rankings are shown if (!(hu_showscores && (netgame || multiplayer))) @@ -733,9 +733,10 @@ static void ST_overlayDrawer(UINT8 playernum) if (renderisnewtic) { - LUA_HookHUD(luahuddrawlist_game[playernum], HUD_HOOK(game)); + LUA_HUD_ClearDrawList(luahuddrawlist_game[stplyrnum]); + LUA_HookHUD(luahuddrawlist_game[stplyrnum], HUD_HOOK(game)); } - LUA_HUD_DrawList(luahuddrawlist_game[playernum]); + LUA_HUD_DrawList(luahuddrawlist_game[stplyrnum]); } if (!hu_showscores) // hide the following if TAB is held @@ -911,11 +912,6 @@ void ST_Drawer(void) if (st_overlay) { UINT8 i; - if (renderisnewtic) - { - for (i = 0; i <= r_splitscreen; i++) - LUA_HUD_ClearDrawList(luahuddrawlist_game[i]); - } // No deadview! for (i = 0; i <= r_splitscreen; i++) { @@ -923,12 +919,9 @@ void ST_Drawer(void) stplyrnum = i; R_SetViewContext(VIEWCONTEXT_PLAYER1 + i); R_InterpolateView(rendertimefrac); // to assist with object tracking - ST_overlayDrawer(i); + ST_overlayDrawer(); } - for (i = 0; i <= r_splitscreen; i++) - LUA_HUD_DrawList(luahuddrawlist_game[i]); - // draw Midnight Channel's overlay ontop if (mapheaderinfo[gamemap-1]->typeoflevel & TOL_TV) // Very specific Midnight Channel stuff. ST_MayonakaStatic(); From 2e1ba3fa44592da337547ae1c77d9bb293f6dfc6 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Sat, 22 Feb 2025 15:51:02 +0100 Subject: [PATCH 13/14] Fix patches being turned inside-out by cliprect in GL --- src/hardware/hw_draw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index 50655f6aa..15032cbe2 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -266,8 +266,8 @@ void HWR_DrawStretchyFixedPatch(patch_t *gpatch, fixed_t x, fixed_t y, fixed_t p cx = cx1; cy = cy1; - fwidth = cx2 - cx1; - fheight = cy2 - cy1; + fwidth = fmaxf(0.0f, cx2 - cx1); + fheight = fmaxf(0.0f, cy2 - cy1); } // positions of the cx, cy, are between 0 and vid.width/vid.height now, we need them to be between -1 and 1 From 3928a98d727664b8daa1313ff12ba7352ffb30b3 Mon Sep 17 00:00:00 2001 From: GenericHeroGuy Date: Sat, 22 Feb 2025 19:34:53 +0100 Subject: [PATCH 14/14] Properly fix runaway cliprects so they don't interfere with other hooks --- src/lua_hooklib.c | 7 ++++--- src/lua_hud.h | 2 ++ src/lua_hudlib.c | 16 ++++++++++++++++ src/lua_hudlib_drawlist.c | 3 --- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 3dca19072..aebf2185c 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -488,8 +488,12 @@ static int call_mapped_hud(Hook_State *hook, const hook_t *map) { hud_interpolate = hud_interpstring = hud_interplatch = false; hud_interpcounter++; + get_hook(hook, map->ids, k); call_single_hook(hook); + + // Catch runaway clipping rectangles. + LUA_ClearClipRect(); } return map->numHooks; @@ -678,9 +682,6 @@ void LUA_HookHUD(huddrawlist_h list, int hook_type) init_hook_call(&hook, 0, res_none); call_mapped_hud(&hook, map); - // Catch runaway clipping rectangles. - V_ClearClipRect(); - hud_running = false; } } diff --git a/src/lua_hud.h b/src/lua_hud.h index 0c632b1fa..2d4cb664f 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -59,6 +59,8 @@ boolean LUA_HudEnabled(enum hud option); void LUA_SetHudHook(int hook, huddrawlist_h list); +void LUA_ClearClipRect(void); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index e3cf0db32..fb573b592 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -47,6 +47,8 @@ static UINT8 hud_enabled[(hud_MAX/8)+1]; static UINT8 camnum = 1; +static boolean cliprectenabled; + // must match enum hud in lua_hud.h static const char *const hud_disable_options[] = { "stagetitle", @@ -987,6 +989,7 @@ static int libd_setClipRect(lua_State *L) lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); list = (huddrawlist_h) lua_touserdata(L, -1); lua_pop(L, 1); + cliprectenabled = true; if (LUA_HUD_IsDrawListValid(list)) LUA_HUD_AddSetClipRect(list, x, y, w, h, flags); @@ -1003,6 +1006,7 @@ static int libd_clearClipRect(lua_State *L) lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); list = (huddrawlist_h) lua_touserdata(L, -1); lua_pop(L, 1); + cliprectenabled = false; if (LUA_HUD_IsDrawListValid(list)) LUA_HUD_AddClearClipRect(list); @@ -1458,6 +1462,8 @@ void LUA_SetHudHook(int hook, huddrawlist_h list) lua_pushlightuserdata(gL, list); lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST"); + cliprectenabled = false; + switch (hook) { case HUD_HOOK(game): @@ -1476,3 +1482,13 @@ void LUA_SetHudHook(int hook, huddrawlist_h list) break; } } + +void LUA_ClearClipRect(void) +{ + // V_ClearClipRect is not enough: we need to insert a clearClipRect + // into the drawlist to protect both hardcode and other HUD hooks. + // thankfully the below function takes zero Lua arguments :^) + if (cliprectenabled) + libd_clearClipRect(gL); + //cliprectenabled = false; +} diff --git a/src/lua_hudlib_drawlist.c b/src/lua_hudlib_drawlist.c index c368d5026..73edb10cc 100644 --- a/src/lua_hudlib_drawlist.c +++ b/src/lua_hudlib_drawlist.c @@ -739,7 +739,4 @@ void LUA_HUD_DrawList(huddrawlist_h list) continue; } } - - // who are you running from? - V_ClearClipRect(); }