Add Lua HUD drawlists

Buffers draw calls between tics to ensure hooks
run at the originally intended rate.
This commit is contained in:
Eidolon 2022-04-30 01:50:12 -05:00
parent 56261d3e1e
commit 82310e0ae2
14 changed files with 931 additions and 28 deletions

View file

@ -96,4 +96,5 @@ lua_taglib.c
lua_polyobjlib.c lua_polyobjlib.c
lua_blockmaplib.c lua_blockmaplib.c
lua_hudlib.c lua_hudlib.c
lua_hudlib_drawlist.c
lua_inputlib.c lua_inputlib.c

View file

@ -826,6 +826,8 @@ void D_SRB2Loop(void)
doDisplay = true; doDisplay = true;
} }
renderisnewtic = true;
} }
if (interp) if (interp)

View file

@ -227,6 +227,8 @@ static tic_t cutscene_lasttextwrite = 0;
// STJR Intro // STJR Intro
char stjrintro[9] = "STJRI000"; char stjrintro[9] = "STJRI000";
static huddrawlist_h luahuddrawlist_title;
// //
// This alters the text string cutscene_disptext. // This alters the text string cutscene_disptext.
// Use the typical string drawing functions to display it. // Use the typical string drawing functions to display it.
@ -2278,6 +2280,9 @@ void F_InitMenuPresValues(void)
M_SetMenuCurBackground((gamestate == GS_TIMEATTACK) ? "RECATTBG" : "TITLESKY"); M_SetMenuCurBackground((gamestate == GS_TIMEATTACK) ? "RECATTBG" : "TITLESKY");
M_SetMenuCurFadeValue(16); M_SetMenuCurFadeValue(16);
M_SetMenuCurTitlePics(); M_SetMenuCurTitlePics();
LUA_HUD_DestroyDrawList(luahuddrawlist_title);
luahuddrawlist_title = LUA_HUD_CreateDrawList();
} }
// //
@ -3397,7 +3402,12 @@ void F_TitleScreenDrawer(void)
} }
luahook: luahook:
LUA_HUDHOOK(title); if (renderisnewtic)
{
LUA_HUD_ClearDrawList(luahuddrawlist_title);
LUA_HUDHOOK(title, luahuddrawlist_title);
}
LUA_HUD_DrawList(luahuddrawlist_title);
} }
// separate animation timer for backgrounds, since we also count // separate animation timer for backgrounds, since we also count

View file

@ -48,6 +48,7 @@
#endif #endif
#include "lua_hud.h" #include "lua_hud.h"
#include "lua_hudlib_drawlist.h"
#include "lua_hook.h" #include "lua_hook.h"
// coords are scaled // coords are scaled
@ -166,6 +167,8 @@ static tic_t cechotimer = 0;
static tic_t cechoduration = 5*TICRATE; static tic_t cechoduration = 5*TICRATE;
static INT32 cechoflags = 0; static INT32 cechoflags = 0;
static huddrawlist_h luahuddrawlist_scores;
//====================================================================== //======================================================================
// HEADS UP INIT // HEADS UP INIT
//====================================================================== //======================================================================
@ -334,6 +337,8 @@ void HU_Init(void)
// set shift translation table // set shift translation table
shiftxform = english_shiftxform; shiftxform = english_shiftxform;
luahuddrawlist_scores = LUA_HUD_CreateDrawList();
} }
static inline void HU_Stop(void) static inline void HU_Stop(void)
@ -1989,7 +1994,13 @@ void HU_Drawer(void)
} }
else else
HU_DrawCoopOverlay(); HU_DrawCoopOverlay();
LUA_HUDHOOK(scores);
if (renderisnewtic)
{
LUA_HUD_ClearDrawList(luahuddrawlist_scores);
LUA_HUDHOOK(scores, luahuddrawlist_scores);
}
LUA_HUD_DrawList(luahuddrawlist_scores);
} }
if (gamestate != GS_LEVEL) if (gamestate != GS_LEVEL)

View file

@ -14,6 +14,7 @@
#include "d_player.h" #include "d_player.h"
#include "s_sound.h" #include "s_sound.h"
#include "d_event.h" #include "d_event.h"
#include "lua_hudlib_drawlist.h"
/* /*
Do you know what an 'X Macro' is? Such a macro is called over each element of Do you know what an 'X Macro' is? Such a macro is called over each element of
@ -110,12 +111,12 @@ ENUM (STRING_HOOK);
/* dead simple, LUA_HOOK(GameQuit) */ /* dead simple, LUA_HOOK(GameQuit) */
#define LUA_HOOK(type) LUA_HookVoid(HOOK(type)) #define LUA_HOOK(type) LUA_HookVoid(HOOK(type))
#define LUA_HUDHOOK(type) LUA_HookHUD(HUD_HOOK(type)) #define LUA_HUDHOOK(type,drawlist) LUA_HookHUD(HUD_HOOK(type),(drawlist))
extern boolean hook_cmd_running; extern boolean hook_cmd_running;
void LUA_HookVoid(int hook); void LUA_HookVoid(int hook);
void LUA_HookHUD(int hook); void LUA_HookHUD(int hook, huddrawlist_h drawlist);
int LUA_HookMobj(mobj_t *, int hook); int LUA_HookMobj(mobj_t *, int hook);
int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook); int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook);

View file

@ -641,7 +641,7 @@ int LUA_HookKey(event_t *event, int hook_type)
return hook.status; return hook.status;
} }
void LUA_HookHUD(int hook_type) void LUA_HookHUD(int hook_type, huddrawlist_h list)
{ {
const hook_t * map = &hudHookIds[hook_type]; const hook_t * map = &hudHookIds[hook_type];
Hook_State hook; Hook_State hook;
@ -650,12 +650,15 @@ void LUA_HookHUD(int hook_type)
start_hook_stack(); start_hook_stack();
begin_hook_values(&hook); begin_hook_values(&hook);
LUA_SetHudHook(hook_type); LUA_SetHudHook(hook_type, list);
hud_running = true; // local hook hud_running = true; // local hook
init_hook_call(&hook, 0, res_none); init_hook_call(&hook, 0, res_none);
call_mapped(&hook, map); call_mapped(&hook, map);
hud_running = false; hud_running = false;
lua_pushnil(gL);
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
} }
} }

View file

@ -10,6 +10,11 @@
/// \file lua_hud.h /// \file lua_hud.h
/// \brief HUD enable/disable flags for Lua scripting /// \brief HUD enable/disable flags for Lua scripting
#ifndef __LUA_HUD_H__
#define __LUA_HUD_H__
#include "lua_hudlib_drawlist.h"
enum hud { enum hud {
hud_stagetitle = 0, hud_stagetitle = 0,
hud_textspectator, hud_textspectator,
@ -47,4 +52,6 @@ extern boolean hud_running;
boolean LUA_HudEnabled(enum hud option); boolean LUA_HudEnabled(enum hud option);
void LUA_SetHudHook(int hook); void LUA_SetHudHook(int hook, huddrawlist_h list);
#endif // __LUA_HUD_H__

View file

@ -645,7 +645,8 @@ static int libd_draw(lua_State *L)
{ {
INT32 x, y, flags; INT32 x, y, flags;
patch_t *patch; patch_t *patch;
const UINT8 *colormap = NULL; UINT8 *colormap = NULL;
huddrawlist_h list;
HUDONLY HUDONLY
x = luaL_checkinteger(L, 1); x = luaL_checkinteger(L, 1);
@ -659,6 +660,13 @@ static int libd_draw(lua_State *L)
flags &= ~V_PARAMMASK; // Don't let crashes happen. flags &= ~V_PARAMMASK; // Don't let crashes happen.
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_AddDraw(list, x, y, patch, flags, colormap);
else
V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, flags, patch, colormap); V_DrawFixedPatch(x<<FRACBITS, y<<FRACBITS, FRACUNIT, flags, patch, colormap);
return 0; return 0;
} }
@ -668,7 +676,8 @@ static int libd_drawScaled(lua_State *L)
fixed_t x, y, scale; fixed_t x, y, scale;
INT32 flags; INT32 flags;
patch_t *patch; patch_t *patch;
const UINT8 *colormap = NULL; UINT8 *colormap = NULL;
huddrawlist_h list;
HUDONLY HUDONLY
x = luaL_checkinteger(L, 1); x = luaL_checkinteger(L, 1);
@ -685,6 +694,13 @@ static int libd_drawScaled(lua_State *L)
flags &= ~V_PARAMMASK; // Don't let crashes happen. flags &= ~V_PARAMMASK; // Don't let crashes happen.
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_AddDrawScaled(list, x, y, scale, patch, flags, colormap);
else
V_DrawFixedPatch(x, y, scale, flags, patch, colormap); V_DrawFixedPatch(x, y, scale, flags, patch, colormap);
return 0; return 0;
} }
@ -694,7 +710,8 @@ static int libd_drawStretched(lua_State *L)
fixed_t x, y, hscale, vscale; fixed_t x, y, hscale, vscale;
INT32 flags; INT32 flags;
patch_t *patch; patch_t *patch;
const UINT8 *colormap = NULL; UINT8 *colormap = NULL;
huddrawlist_h list;
HUDONLY HUDONLY
x = luaL_checkinteger(L, 1); x = luaL_checkinteger(L, 1);
@ -712,6 +729,13 @@ static int libd_drawStretched(lua_State *L)
flags &= ~V_PARAMMASK; // Don't let crashes happen. flags &= ~V_PARAMMASK; // Don't let crashes happen.
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_AddDrawStretched(list, x, y, hscale, vscale, patch, flags, colormap);
else
V_DrawStretchyFixedPatch(x, y, hscale, vscale, flags, patch, colormap); V_DrawStretchyFixedPatch(x, y, hscale, vscale, flags, patch, colormap);
return 0; return 0;
} }
@ -721,7 +745,8 @@ static int libd_drawCropped(lua_State *L)
fixed_t x, y, hscale, vscale, sx, sy, w, h; fixed_t x, y, hscale, vscale, sx, sy, w, h;
INT32 flags; INT32 flags;
patch_t *patch; patch_t *patch;
const UINT8 *colormap = NULL; UINT8 *colormap = NULL;
huddrawlist_h list;
HUDONLY HUDONLY
x = luaL_checkinteger(L, 1); x = luaL_checkinteger(L, 1);
@ -751,6 +776,13 @@ static int libd_drawCropped(lua_State *L)
flags &= ~V_PARAMMASK; // Don't let crashes happen. flags &= ~V_PARAMMASK; // Don't let crashes happen.
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_AddDrawCropped(list, x, y, hscale, vscale, patch, flags, colormap, sx, sy, w, h);
else
V_DrawCroppedPatch(x, y, hscale, vscale, flags, patch, colormap, sx, sy, w, h); V_DrawCroppedPatch(x, y, hscale, vscale, flags, patch, colormap, sx, sy, w, h);
return 0; return 0;
} }
@ -758,6 +790,8 @@ static int libd_drawCropped(lua_State *L)
static int libd_drawNum(lua_State *L) static int libd_drawNum(lua_State *L)
{ {
INT32 x, y, flags, num; INT32 x, y, flags, num;
huddrawlist_h list;
HUDONLY HUDONLY
x = luaL_checkinteger(L, 1); x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2); y = luaL_checkinteger(L, 2);
@ -765,6 +799,13 @@ static int libd_drawNum(lua_State *L)
flags = luaL_optinteger(L, 4, 0); flags = luaL_optinteger(L, 4, 0);
flags &= ~V_PARAMMASK; // Don't let crashes happen. flags &= ~V_PARAMMASK; // Don't let crashes happen.
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_AddDrawNum(list, x, y, num, flags);
else
V_DrawTallNum(x, y, flags, num); V_DrawTallNum(x, y, flags, num);
return 0; return 0;
} }
@ -772,6 +813,8 @@ static int libd_drawNum(lua_State *L)
static int libd_drawPaddedNum(lua_State *L) static int libd_drawPaddedNum(lua_State *L)
{ {
INT32 x, y, flags, num, digits; INT32 x, y, flags, num, digits;
huddrawlist_h list;
HUDONLY HUDONLY
x = luaL_checkinteger(L, 1); x = luaL_checkinteger(L, 1);
y = luaL_checkinteger(L, 2); y = luaL_checkinteger(L, 2);
@ -780,12 +823,20 @@ static int libd_drawPaddedNum(lua_State *L)
flags = luaL_optinteger(L, 5, 0); flags = luaL_optinteger(L, 5, 0);
flags &= ~V_PARAMMASK; // Don't let crashes happen. flags &= ~V_PARAMMASK; // Don't let crashes happen.
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_AddDrawPaddedNum(list, x, y, num, digits, flags);
else
V_DrawPaddedTallNum(x, y, flags, num, digits); V_DrawPaddedTallNum(x, y, flags, num, digits);
return 0; return 0;
} }
static int libd_drawFill(lua_State *L) static int libd_drawFill(lua_State *L)
{ {
huddrawlist_h list;
INT32 x = luaL_optinteger(L, 1, 0); INT32 x = luaL_optinteger(L, 1, 0);
INT32 y = luaL_optinteger(L, 2, 0); INT32 y = luaL_optinteger(L, 2, 0);
INT32 w = luaL_optinteger(L, 3, BASEVIDWIDTH); INT32 w = luaL_optinteger(L, 3, BASEVIDWIDTH);
@ -793,12 +844,21 @@ static int libd_drawFill(lua_State *L)
INT32 c = luaL_optinteger(L, 5, 31); INT32 c = luaL_optinteger(L, 5, 31);
HUDONLY 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_AddDrawFill(list, x, y, w, h, c);
else
V_DrawFill(x, y, w, h, c); V_DrawFill(x, y, w, h, c);
return 0; return 0;
} }
static int libd_drawString(lua_State *L) static int libd_drawString(lua_State *L)
{ {
huddrawlist_h list;
fixed_t x = luaL_checkinteger(L, 1); fixed_t x = luaL_checkinteger(L, 1);
fixed_t y = luaL_checkinteger(L, 2); fixed_t y = luaL_checkinteger(L, 2);
const char *str = luaL_checkstring(L, 3); const char *str = luaL_checkstring(L, 3);
@ -808,6 +868,15 @@ static int libd_drawString(lua_State *L)
flags &= ~V_PARAMMASK; // Don't let crashes happen. flags &= ~V_PARAMMASK; // Don't let crashes happen.
HUDONLY HUDONLY
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
list = (huddrawlist_h) lua_touserdata(L, -1);
lua_pop(L, 1);
// okay, sorry, this is kind of ugly
if (LUA_HUD_IsDrawListValid(list))
LUA_HUD_AddDrawString(list, x, y, str, flags, align);
else
switch(align) switch(align)
{ {
// hu_font // hu_font
@ -899,6 +968,7 @@ static int libd_drawNameTag(lua_State *L)
UINT16 outlinecolor; UINT16 outlinecolor;
UINT8 *basecolormap = NULL; UINT8 *basecolormap = NULL;
UINT8 *outlinecolormap = NULL; UINT8 *outlinecolormap = NULL;
huddrawlist_h list;
HUDONLY HUDONLY
@ -914,6 +984,14 @@ static int libd_drawNameTag(lua_State *L)
outlinecolormap = R_GetTranslationColormap(TC_DEFAULT, outlinecolor, GTC_CACHE); outlinecolormap = R_GetTranslationColormap(TC_DEFAULT, outlinecolor, GTC_CACHE);
flags &= ~V_PARAMMASK; // Don't let crashes happen. flags &= ~V_PARAMMASK; // Don't let crashes happen.
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_AddDrawNameTag(list, x, y, str, flags, basecolor, outlinecolor, basecolormap, outlinecolormap);
else
V_DrawNameTag(x, y, flags, FRACUNIT, basecolormap, outlinecolormap, str); V_DrawNameTag(x, y, flags, FRACUNIT, basecolormap, outlinecolormap, str);
return 0; return 0;
} }
@ -929,6 +1007,7 @@ static int libd_drawScaledNameTag(lua_State *L)
UINT16 outlinecolor; UINT16 outlinecolor;
UINT8 *basecolormap = NULL; UINT8 *basecolormap = NULL;
UINT8 *outlinecolormap = NULL; UINT8 *outlinecolormap = NULL;
huddrawlist_h list;
HUDONLY HUDONLY
@ -947,6 +1026,14 @@ static int libd_drawScaledNameTag(lua_State *L)
outlinecolormap = R_GetTranslationColormap(TC_DEFAULT, outlinecolor, GTC_CACHE); outlinecolormap = R_GetTranslationColormap(TC_DEFAULT, outlinecolor, GTC_CACHE);
flags &= ~V_PARAMMASK; // Don't let crashes happen. flags &= ~V_PARAMMASK; // Don't let crashes happen.
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_AddDrawScaledNameTag(list, x, y, str, flags, scale, basecolor, outlinecolor, basecolormap, outlinecolormap);
else
V_DrawNameTag(FixedInt(x), FixedInt(y), flags, scale, basecolormap, outlinecolormap, str); V_DrawNameTag(FixedInt(x), FixedInt(y), flags, scale, basecolormap, outlinecolormap, str);
return 0; return 0;
} }
@ -957,6 +1044,7 @@ static int libd_drawLevelTitle(lua_State *L)
INT32 y; INT32 y;
const char *str; const char *str;
INT32 flags; INT32 flags;
huddrawlist_h list;
HUDONLY HUDONLY
@ -967,6 +1055,13 @@ static int libd_drawLevelTitle(lua_State *L)
flags &= ~V_PARAMMASK; // Don't let crashes happen. flags &= ~V_PARAMMASK; // Don't let crashes happen.
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_AddDrawLevelTitle(list, x, y, str, flags);
else
V_DrawLevelTitle(x, y, flags, str); V_DrawLevelTitle(x, y, flags, str);
return 0; return 0;
} }
@ -1060,6 +1155,7 @@ static int libd_getStringColormap(lua_State *L)
static int libd_fadeScreen(lua_State *L) static int libd_fadeScreen(lua_State *L)
{ {
huddrawlist_h list;
UINT16 color = luaL_checkinteger(L, 1); UINT16 color = luaL_checkinteger(L, 1);
UINT8 strength = luaL_checkinteger(L, 2); UINT8 strength = luaL_checkinteger(L, 2);
const UINT8 maxstrength = ((color & 0xFF00) ? 32 : 10); const UINT8 maxstrength = ((color & 0xFF00) ? 32 : 10);
@ -1072,13 +1168,24 @@ static int libd_fadeScreen(lua_State *L)
if (strength > maxstrength) if (strength > maxstrength)
return luaL_error(L, "%s fade strength %d out of range (0 - %d)", ((color & 0xFF00) ? "COLORMAP" : "TRANSMAP"), strength, maxstrength); return luaL_error(L, "%s fade strength %d out of range (0 - %d)", ((color & 0xFF00) ? "COLORMAP" : "TRANSMAP"), strength, maxstrength);
lua_getfield(L, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
list = (huddrawlist_h) lua_touserdata(L, -1);
lua_pop(L, 1);
if (strength == maxstrength) // Allow as a shortcut for drawfill... if (strength == maxstrength) // Allow as a shortcut for drawfill...
{ {
if (LUA_HUD_IsDrawListValid(list))
LUA_HUD_AddDrawFill(list, 0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, ((color & 0xFF00) ? 31 : color));
else
V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, ((color & 0xFF00) ? 31 : color)); V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, ((color & 0xFF00) ? 31 : color));
return 0; return 0;
} }
if (LUA_HUD_IsDrawListValid(list))
LUA_HUD_AddFadeScreen(list, color, strength);
else
V_DrawFadeScreen(color, strength); V_DrawFadeScreen(color, strength);
return 0; return 0;
} }
@ -1365,10 +1472,13 @@ boolean LUA_HudEnabled(enum hud option)
return false; return false;
} }
void LUA_SetHudHook(int hook) void LUA_SetHudHook(int hook, huddrawlist_h list)
{ {
lua_getref(gL, lib_draw_ref); lua_getref(gL, lib_draw_ref);
lua_pushlightuserdata(gL, list);
lua_setfield(gL, LUA_REGISTRYINDEX, "HUD_DRAW_LIST");
switch (hook) switch (hook)
{ {
case HUD_HOOK(game): { case HUD_HOOK(game): {

572
src/lua_hudlib_drawlist.c Normal file
View file

@ -0,0 +1,572 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2014-2016 by John "JTE" Muniz.
// Copyright (C) 2014-2022 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file lua_hudlib_drawlist.c
/// \brief a data structure for managing cached drawlists for the Lua hud lib
#include "lua_hudlib_drawlist.h"
#include <string.h>
#include "v_video.h"
#include "z_zone.h"
enum drawitem_e {
DI_Draw = 0,
DI_DrawScaled,
DI_DrawStretched,
DI_DrawCropped,
DI_DrawNum,
DI_DrawPaddedNum,
DI_DrawFill,
DI_DrawString,
DI_DrawNameTag,
DI_DrawScaledNameTag,
DI_DrawLevelTitle,
DI_FadeScreen,
DI_MAX,
};
// A single draw item with all possible arguments needed for a draw call.
typedef struct drawitem_s {
enum drawitem_e type;
fixed_t x;
fixed_t y;
fixed_t w;
fixed_t h;
INT32 c;
fixed_t scale;
fixed_t hscale;
fixed_t vscale;
patch_t *patch;
INT32 flags;
UINT16 basecolor;
UINT16 outlinecolor;
UINT8 *colormap;
UINT8 *basecolormap;
UINT8 *outlinecolormap;
fixed_t sx;
fixed_t sy;
INT32 num;
INT32 digits;
const char *str;
UINT16 color;
UINT8 strength;
INT32 align;
} drawitem_t;
// The internal structure of a drawlist.
struct huddrawlist_s {
drawitem_t *items;
size_t items_capacity;
size_t items_len;
char *strbuf;
size_t strbuf_capacity;
size_t strbuf_len;
};
// alignment types for v.drawString
enum align {
align_left = 0,
align_center,
align_right,
align_fixed,
align_fixedcenter,
align_fixedright,
align_small,
align_smallfixed,
align_smallfixedcenter,
align_smallfixedright,
align_smallcenter,
align_smallright,
align_smallthin,
align_smallthincenter,
align_smallthinright,
align_smallthinfixed,
align_smallthinfixedcenter,
align_smallthinfixedright,
align_thin,
align_thinfixed,
align_thinfixedcenter,
align_thinfixedright,
align_thincenter,
align_thinright
};
huddrawlist_h LUA_HUD_CreateDrawList(void)
{
huddrawlist_h drawlist;
drawlist = (huddrawlist_h) Z_CallocAlign(sizeof(struct huddrawlist_s), PU_STATIC, NULL, 64);
drawlist->items = NULL;
drawlist->items_capacity = 0;
drawlist->items_len = 0;
drawlist->strbuf = NULL;
drawlist->strbuf_capacity = 0;
drawlist->strbuf_len = 0;
return drawlist;
}
void LUA_HUD_ClearDrawList(huddrawlist_h list)
{
// rather than deallocate, we'll just save the existing allocation and empty
// it out for reuse
// this memset probably isn't necessary
if (list->items)
{
memset(list->items, 0, sizeof(drawitem_t) * list->items_capacity);
}
list->items_len = 0;
if (list->strbuf)
{
list->strbuf[0] = 0;
}
list->strbuf_len = 0;
}
void LUA_HUD_DestroyDrawList(huddrawlist_h list)
{
if (list == NULL) return;
if (list->items)
{
Z_Free(list->items);
}
Z_Free(list);
}
boolean LUA_HUD_IsDrawListValid(huddrawlist_h list)
{
if (!list) return false;
// that's all we can really do to check the validity of the handle right now
return true;
}
static size_t AllocateDrawItem(huddrawlist_h list)
{
if (!list) I_Error("can't allocate draw item: invalid list");
if (list->items_capacity <= list->items_len + 1)
{
if (list->items_capacity == 0) list->items_capacity = 128;
else list->items_capacity *= 2;
list->items = (drawitem_t *) Z_ReallocAlign(list->items, sizeof(struct drawitem_s) * list->items_capacity, PU_STATIC, NULL, 64);
}
return list->items_len++;
}
// copy string to list's internal string buffer
// lua can deallocate the string before we get to use it, so it's important to
// keep our own copy
static const char *CopyString(huddrawlist_h list, const char* str)
{
size_t lenstr;
if (!list) I_Error("can't allocate string; invalid list");
lenstr = strlen(str);
if (list->strbuf_capacity <= list->strbuf_len + lenstr + 1)
{
if (list->strbuf_capacity == 0) list->strbuf_capacity = 256;
else list->strbuf_capacity *= 2;
list->strbuf = (char*) Z_ReallocAlign(list->strbuf, sizeof(char) * list->strbuf_capacity, PU_STATIC, NULL, 8);
}
const char *result = (const char *) &list->strbuf[list->strbuf_len];
strncpy(&list->strbuf[list->strbuf_len], str, lenstr + 1);
list->strbuf_len += lenstr + 1;
return result;
}
void LUA_HUD_AddDraw(
huddrawlist_h list,
INT32 x,
INT32 y,
patch_t *patch,
INT32 flags,
UINT8 *colormap
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_Draw;
item->x = x;
item->y = y;
item->patch = patch;
item->flags = flags;
item->colormap = colormap;
}
void LUA_HUD_AddDrawScaled(
huddrawlist_h list,
fixed_t x,
fixed_t y,
fixed_t scale,
patch_t *patch,
INT32 flags,
UINT8 *colormap
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawScaled;
item->x = x;
item->y = y;
item->scale = scale;
item->patch = patch;
item->flags = flags;
item->colormap = colormap;
}
void LUA_HUD_AddDrawStretched(
huddrawlist_h list,
fixed_t x,
fixed_t y,
fixed_t hscale,
fixed_t vscale,
patch_t *patch,
INT32 flags,
UINT8 *colormap
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawStretched;
item->x = x;
item->y = y;
item->hscale = hscale;
item->vscale = vscale;
item->patch = patch;
item->flags = flags;
item->colormap = colormap;
}
void LUA_HUD_AddDrawCropped(
huddrawlist_h list,
fixed_t x,
fixed_t y,
fixed_t hscale,
fixed_t vscale,
patch_t *patch,
INT32 flags,
UINT8 *colormap,
fixed_t sx,
fixed_t sy,
fixed_t w,
fixed_t h
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawCropped;
item->x = x;
item->y = y;
item->hscale = hscale;
item->vscale = vscale;
item->patch = patch;
item->flags = flags;
item->colormap = colormap;
item->sx = sx;
item->sy = sy;
item->w = w;
item->h = h;
}
void LUA_HUD_AddDrawNum(
huddrawlist_h list,
INT32 x,
INT32 y,
INT32 num,
INT32 flags
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawNum;
item->x = x;
item->y = y;
item->num = num;
item->flags = flags;
}
void LUA_HUD_AddDrawPaddedNum(
huddrawlist_h list,
INT32 x,
INT32 y,
INT32 num,
INT32 digits,
INT32 flags
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawPaddedNum;
item->x = x;
item->y = y;
item->num = num;
item->digits = digits;
item->flags = flags;
}
void LUA_HUD_AddDrawFill(
huddrawlist_h list,
INT32 x,
INT32 y,
INT32 w,
INT32 h,
INT32 c
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawFill;
item->x = x;
item->y = y;
item->w = w;
item->h = h;
item->c = c;
}
void LUA_HUD_AddDrawString(
huddrawlist_h list,
fixed_t x,
fixed_t y,
const char *str,
INT32 flags,
INT32 align
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawString;
item->x = x;
item->y = y;
item->str = CopyString(list, str);
item->flags = flags;
item->align = align;
}
void LUA_HUD_AddDrawNameTag(
huddrawlist_h list,
INT32 x,
INT32 y,
const char *str,
INT32 flags,
UINT16 basecolor,
UINT16 outlinecolor,
UINT8 *basecolormap,
UINT8 *outlinecolormap
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawNameTag;
item->x = x;
item->y = y;
item->str = CopyString(list, str);
item->flags = flags;
item->basecolor = basecolor;
item->outlinecolor = outlinecolor;
item->basecolormap = basecolormap;
item->outlinecolormap = outlinecolormap;
}
void LUA_HUD_AddDrawScaledNameTag(
huddrawlist_h list,
fixed_t x,
fixed_t y,
const char *str,
INT32 flags,
fixed_t scale,
UINT16 basecolor,
UINT16 outlinecolor,
UINT8 *basecolormap,
UINT8 *outlinecolormap
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawScaledNameTag;
item->x = x;
item->y = y;
item->str = CopyString(list, str);
item->flags = flags;
item->scale = scale;
item->basecolor = basecolor;
item->outlinecolor = outlinecolor;
item->basecolormap = basecolormap;
item->outlinecolormap = outlinecolormap;
}
void LUA_HUD_AddDrawLevelTitle(
huddrawlist_h list,
INT32 x,
INT32 y,
const char *str,
INT32 flags
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_DrawLevelTitle;
item->x = x;
item->y = y;
item->str = CopyString(list, str);
item->flags = flags;
}
void LUA_HUD_AddFadeScreen(
huddrawlist_h list,
UINT16 color,
UINT8 strength
)
{
size_t i = AllocateDrawItem(list);
drawitem_t *item = &list->items[i];
item->type = DI_FadeScreen;
item->color = color;
item->strength = strength;
}
void LUA_HUD_DrawList(huddrawlist_h list)
{
size_t i;
if (!list) I_Error("HUD drawlist invalid");
if (list->items_len <= 0) return;
if (!list->items) I_Error("HUD drawlist->items invalid");
for (i = 0; i < list->items_len; i++)
{
drawitem_t *item = &list->items[i];
switch (item->type)
{
case DI_Draw:
V_DrawFixedPatch(item->x<<FRACBITS, item->y<<FRACBITS, FRACUNIT, item->flags, item->patch, item->colormap);
break;
case DI_DrawScaled:
V_DrawFixedPatch(item->x, item->y, item->scale, item->flags, item->patch, item->colormap);
break;
case DI_DrawStretched:
V_DrawStretchyFixedPatch(item->x, item->y, item->hscale, item->vscale, item->flags, item->patch, item->colormap);
break;
case DI_DrawCropped:
V_DrawCroppedPatch(item->x, item->y, item->hscale, item->vscale, item->flags, item->patch, item->colormap, item->sx, item->sy, item->w, item->h);
break;
case DI_DrawNum:
V_DrawTallNum(item->x, item->y, item->flags, item->num);
break;
case DI_DrawPaddedNum:
V_DrawPaddedTallNum(item->x, item->y, item->flags, item->num, item->digits);
break;
case DI_DrawFill:
V_DrawFill(item->x, item->y, item->w, item->h, item->c);
break;
case DI_DrawString:
switch(item->align)
{
// hu_font
case align_left:
V_DrawString(item->x, item->y, item->flags, item->str);
break;
case align_center:
V_DrawCenteredString(item->x, item->y, item->flags, item->str);
break;
case align_right:
V_DrawRightAlignedString(item->x, item->y, item->flags, item->str);
break;
case align_fixed:
V_DrawStringAtFixed(item->x, item->y, item->flags, item->str);
break;
case align_fixedcenter:
V_DrawCenteredStringAtFixed(item->x, item->y, item->flags, item->str);
break;
case align_fixedright:
V_DrawRightAlignedStringAtFixed(item->x, item->y, item->flags, item->str);
break;
// hu_font, 0.5x scale
case align_small:
V_DrawSmallString(item->x, item->y, item->flags, item->str);
break;
case align_smallfixed:
V_DrawSmallStringAtFixed(item->x, item->y, item->flags, item->str);
break;
case align_smallfixedcenter:
V_DrawCenteredSmallStringAtFixed(item->x, item->y, item->flags, item->str);
break;
case align_smallfixedright:
V_DrawRightAlignedSmallStringAtFixed(item->x, item->y, item->flags, item->str);
break;
case align_smallcenter:
V_DrawCenteredSmallString(item->x, item->y, item->flags, item->str);
break;
case align_smallright:
V_DrawRightAlignedSmallString(item->x, item->y, item->flags, item->str);
break;
case align_smallthin:
V_DrawSmallThinString(item->x, item->y, item->flags, item->str);
break;
case align_smallthincenter:
V_DrawCenteredSmallThinString(item->x, item->y, item->flags, item->str);
break;
case align_smallthinright:
V_DrawRightAlignedSmallThinString(item->x, item->y, item->flags, item->str);
break;
case align_smallthinfixed:
V_DrawSmallThinStringAtFixed(item->x, item->y, item->flags, item->str);
break;
case align_smallthinfixedcenter:
V_DrawCenteredSmallThinStringAtFixed(item->x, item->y, item->flags, item->str);
break;
case align_smallthinfixedright:
V_DrawRightAlignedSmallThinStringAtFixed(item->x, item->y, item->flags, item->str);
break;
// tny_font
case align_thin:
V_DrawThinString(item->x, item->y, item->flags, item->str);
break;
case align_thincenter:
V_DrawCenteredThinString(item->x, item->y, item->flags, item->str);
break;
case align_thinright:
V_DrawRightAlignedThinString(item->x, item->y, item->flags, item->str);
break;
case align_thinfixed:
V_DrawThinStringAtFixed(item->x, item->y, item->flags, item->str);
break;
case align_thinfixedcenter:
V_DrawCenteredThinStringAtFixed(item->x, item->y, item->flags, item->str);
break;
case align_thinfixedright:
V_DrawRightAlignedThinStringAtFixed(item->x, item->y, item->flags, item->str);
break;
}
break;
case DI_DrawNameTag:
V_DrawNameTag(item->x, item->y, item->flags, FRACUNIT, item->basecolormap, item->outlinecolormap, item->str);
break;
case DI_DrawScaledNameTag:
V_DrawNameTag(FixedInt(item->x), FixedInt(item->y), item->flags, item->scale, item->basecolormap, item->outlinecolormap, item->str);
break;
case DI_DrawLevelTitle:
V_DrawLevelTitle(item->x, item->y, item->flags, item->str);
break;
case DI_FadeScreen:
V_DrawFadeScreen(item->color, item->strength);
break;
default:
I_Error("can't draw draw list item: invalid draw list item type");
continue;
}
}
}

152
src/lua_hudlib_drawlist.h Normal file
View file

@ -0,0 +1,152 @@
// SONIC ROBO BLAST 2
//-----------------------------------------------------------------------------
// Copyright (C) 2022-2022 by Sonic Team Junior.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
/// \file lua_hudlib_drawlist.h
/// \brief a data structure for managing cached drawlists for the Lua hud lib
// The idea behinds this module is to cache drawcall information into an ordered
// list to repeat the same draw operations in later frames. It's used to ensure
// that the HUD hooks from Lua are called at precisely 35hz to avoid problems
// with variable framerates in existing Lua addons.
#ifndef __LUA_HUDLIB_DRAWLIST__
#define __LUA_HUDLIB_DRAWLIST__
#include "doomtype.h"
#include "r_defs.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct huddrawlist_s *huddrawlist_h;
// Create a new drawlist. Returns a handle to it.
huddrawlist_h LUA_HUD_CreateDrawList(void);
// Clears the draw list.
void LUA_HUD_ClearDrawList(huddrawlist_h list);
// Destroys the drawlist, invalidating the given handle
void LUA_HUD_DestroyDrawList(huddrawlist_h list);
boolean LUA_HUD_IsDrawListValid(huddrawlist_h list);
void LUA_HUD_AddDraw(
huddrawlist_h list,
INT32 x,
INT32 y,
patch_t *patch,
INT32 flags,
UINT8 *colormap
);
void LUA_HUD_AddDrawScaled(
huddrawlist_h list,
fixed_t x,
fixed_t y,
fixed_t scale,
patch_t *patch,
INT32 flags,
UINT8 *colormap
);
void LUA_HUD_AddDrawStretched(
huddrawlist_h list,
fixed_t x,
fixed_t y,
fixed_t hscale,
fixed_t vscale,
patch_t *patch,
INT32 flags,
UINT8 *colormap
);
void LUA_HUD_AddDrawCropped(
huddrawlist_h list,
fixed_t x,
fixed_t y,
fixed_t hscale,
fixed_t vscale,
patch_t *patch,
INT32 flags,
UINT8 *colormap,
fixed_t sx,
fixed_t sy,
fixed_t w,
fixed_t h
);
void LUA_HUD_AddDrawNum(
huddrawlist_h list,
INT32 x,
INT32 y,
INT32 num,
INT32 flags
);
void LUA_HUD_AddDrawPaddedNum(
huddrawlist_h list,
INT32 x,
INT32 y,
INT32 num,
INT32 digits,
INT32 flags
);
void LUA_HUD_AddDrawFill(
huddrawlist_h list,
INT32 x,
INT32 y,
INT32 w,
INT32 h,
INT32 c
);
void LUA_HUD_AddDrawString(
huddrawlist_h list,
fixed_t x,
fixed_t y,
const char *str,
INT32 flags,
INT32 align
);
void LUA_HUD_AddDrawNameTag(
huddrawlist_h list,
INT32 x,
INT32 y,
const char *str,
INT32 flags,
UINT16 basecolor,
UINT16 outlinecolor,
UINT8 *basecolormap,
UINT8 *outlinecolormap
);
void LUA_HUD_AddDrawScaledNameTag(
huddrawlist_h list,
fixed_t x,
fixed_t y,
const char *str,
INT32 flags,
fixed_t scale,
UINT16 basecolor,
UINT16 outlinecolor,
UINT8 *basecolormap,
UINT8 *outlinecolormap
);
void LUA_HUD_AddDrawLevelTitle(
huddrawlist_h list,
INT32 x,
INT32 y,
const char *str,
INT32 flags
);
void LUA_HUD_AddFadeScreen(
huddrawlist_h list,
UINT16 color,
UINT8 strength
);
// Draws the given draw list
void LUA_HUD_DrawList(huddrawlist_h list);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // __LUA_HUDLIB_DRAWLIST__

View file

@ -78,6 +78,7 @@ mobj_t *r_viewmobj;
fixed_t rendertimefrac; fixed_t rendertimefrac;
fixed_t renderdeltatics; fixed_t renderdeltatics;
boolean renderisnewtic;
// //
// precalculated math tables // precalculated math tables

View file

@ -38,7 +38,9 @@ extern size_t validcount, linecount, loopcount, framecount;
// The fraction of a tic being drawn (for interpolation between two tics) // The fraction of a tic being drawn (for interpolation between two tics)
extern fixed_t rendertimefrac; extern fixed_t rendertimefrac;
// Evaluated delta tics for this frame (how many tics since the last frame) // Evaluated delta tics for this frame (how many tics since the last frame)
extern fixed_t renderdeltatics;; extern fixed_t renderdeltatics;
// The current render is a new logical tic
extern boolean renderisnewtic;
// //
// Lighting LUT. // Lighting LUT.

View file

@ -43,6 +43,7 @@
#endif #endif
#include "lua_hud.h" #include "lua_hud.h"
#include "lua_hudlib_drawlist.h"
#include "lua_hook.h" #include "lua_hook.h"
#include "r_fps.h" #include "r_fps.h"
@ -163,6 +164,9 @@ hudinfo_t hudinfo[NUMHUDITEMS] =
{ 288, 176, V_SNAPTORIGHT|V_SNAPTOBOTTOM}, // HUD_POWERUPS { 288, 176, V_SNAPTORIGHT|V_SNAPTOBOTTOM}, // HUD_POWERUPS
}; };
static huddrawlist_h luahuddrawlist_game;
static huddrawlist_h luahuddrawlist_titlecard;
// //
// STATUS BAR CODE // STATUS BAR CODE
// //
@ -422,6 +426,9 @@ void ST_Init(void)
return; return;
ST_LoadGraphics(); ST_LoadGraphics();
luahuddrawlist_game = LUA_HUD_CreateDrawList();
luahuddrawlist_titlecard = LUA_HUD_CreateDrawList();
} }
// change the status bar too, when pressing F12 while viewing a demo. // change the status bar too, when pressing F12 while viewing a demo.
@ -1404,7 +1411,12 @@ void ST_drawTitleCard(void)
lt_lasttic = lt_ticker; lt_lasttic = lt_ticker;
luahook: luahook:
LUA_HUDHOOK(titlecard); if (renderisnewtic)
{
LUA_HUD_ClearDrawList(luahuddrawlist_titlecard);
LUA_HUDHOOK(titlecard, luahuddrawlist_titlecard);
}
LUA_HUD_DrawList(luahuddrawlist_titlecard);
} }
// //
@ -2744,7 +2756,14 @@ static void ST_overlayDrawer(void)
ST_drawPowerupHUD(); // same as it ever was... ST_drawPowerupHUD(); // same as it ever was...
if (!(netgame || multiplayer) || !hu_showscores) if (!(netgame || multiplayer) || !hu_showscores)
LUA_HUDHOOK(game); {
if (renderisnewtic)
{
LUA_HUD_ClearDrawList(luahuddrawlist_game);
LUA_HUDHOOK(game, luahuddrawlist_game);
}
LUA_HUD_DrawList(luahuddrawlist_game);
}
// draw level title Tails // draw level title Tails
if (stagetitle && (!WipeInAction) && (!WipeStageTitle)) if (stagetitle && (!WipeInAction) && (!WipeStageTitle))

View file

@ -38,6 +38,7 @@
#include "lua_hook.h" // IntermissionThinker hook #include "lua_hook.h" // IntermissionThinker hook
#include "lua_hud.h" #include "lua_hud.h"
#include "lua_hudlib_drawlist.h"
#ifdef HWRENDER #ifdef HWRENDER
#include "hardware/hw_main.h" #include "hardware/hw_main.h"
@ -165,6 +166,8 @@ static INT32 endtic = -1;
intertype_t intertype = int_none; intertype_t intertype = int_none;
intertype_t intermissiontypes[NUMGAMETYPES]; intertype_t intermissiontypes[NUMGAMETYPES];
static huddrawlist_h luahuddrawlist_intermission;
static void Y_RescaleScreenBuffer(void); static void Y_RescaleScreenBuffer(void);
static void Y_AwardCoopBonuses(void); static void Y_AwardCoopBonuses(void);
static void Y_AwardSpecialStageBonus(void); static void Y_AwardSpecialStageBonus(void);
@ -433,7 +436,13 @@ void Y_IntermissionDrawer(void)
else if (bgtile) else if (bgtile)
V_DrawPatchFill(bgtile); V_DrawPatchFill(bgtile);
LUA_HUDHOOK(intermission); if (renderisnewtic)
{
LUA_HUD_ClearDrawList(luahuddrawlist_intermission);
LUA_HUDHOOK(intermission, luahuddrawlist_intermission);
}
LUA_HUD_DrawList(luahuddrawlist_intermission);
if (!LUA_HudEnabled(hud_intermissiontally)) if (!LUA_HudEnabled(hud_intermissiontally))
goto skiptallydrawer; goto skiptallydrawer;
@ -1591,6 +1600,9 @@ void Y_StartIntermission(void)
default: default:
break; break;
} }
LUA_HUD_DestroyDrawList(luahuddrawlist_intermission);
luahuddrawlist_intermission = LUA_HUD_CreateDrawList();
} }
// //