Lua HUD interpolation #130
No files matched your search
+64
@@ -52,6 +52,70 @@ Returns the displayplayer's HUD color.
|
||||
|
||||
Returns true if colorization is enabled, false otherwise.
|
||||
|
||||
## v.interpolate(true)
|
||||
|
||||
Enables HUD interpolation. Each call to a drawing function will have its coordinates interpolated
|
||||
by assigning an unique ID to every call.
|
||||
For example, three successive calls to `v.draw` will each have their own ID and interpolation offsets.
|
||||
Pass `true` to enable interpolation, `false` to disable.
|
||||
|
||||
Alternatively, pass a number to enable interpolation with the specified tag.
|
||||
Tags allow HUD items drawn by the same call to a drawing function to be differentiated.
|
||||
Valid tags range from 0-255.
|
||||
For example, when iterating players, use a unique tag for each player to avoid artifacting:
|
||||
```lua
|
||||
for p in players.iterate do
|
||||
-- enable interpolation, using player numbers as the tag
|
||||
-- every draw will have different interp offsets per player
|
||||
v.interpolate(#p)
|
||||
|
||||
-- doesn't matter for unconditional draws like this one...
|
||||
v.draw(...)
|
||||
|
||||
-- but it does matter if there's a condition!
|
||||
-- without tags, this patch would warp between players
|
||||
-- whenever their `someVar` changes
|
||||
if p.someVar then v.draw(...) end
|
||||
end
|
||||
|
||||
-- don't want interpolation anymore? then disable it
|
||||
v.interpolate(false)
|
||||
```
|
||||
NOTE: The default tag for `true` is 0.
|
||||
|
||||
## v.interpLatch(true)
|
||||
|
||||
Enables interpolation offset latching. The next call to a drawing function will have its lerp offsets
|
||||
saved and reused for all following draw calls. Disable with `false` when done.
|
||||
Interpolation cannot easily "snap" between two points; latching can help overcome this by manually
|
||||
setting the lerp offsets.
|
||||
```lua
|
||||
v.interpolate(true)
|
||||
|
||||
-- X coordinate for the HUD item
|
||||
-- every so often, this will wrap around to zero
|
||||
local x = (leveltime*4) % 256
|
||||
|
||||
-- draw an interpolated patch, but... when X rolls back to zero,
|
||||
-- the patch will slide all the way across the screen!
|
||||
v.draw(x, 100, ...)
|
||||
|
||||
-- this is where interpLatch comes into play
|
||||
-- enable latching, then draw an invisible patch,
|
||||
-- moving at the same speed as the visible patch
|
||||
-- the exact coordinates don't matter, it just has to move at the right speed
|
||||
v.interpLatch(true)
|
||||
v.draw(leveltime*4, 0, v.cachePatch("K_TRNULL"))
|
||||
|
||||
-- now we can draw the patch again, and when X becomes zero,
|
||||
-- it'll snap right back without sliding across the screen
|
||||
v.draw(x, 150, ...)
|
||||
|
||||
-- don't forget to turn off latching!
|
||||
v.interpLatch(false)
|
||||
```
|
||||
When using a custom string drawer, enable this mode to avoid interpolation artifacting when the string changes.
|
||||
|
||||
## mobj.spritexscale, mobj.spriteyscale, mobj.spritexoffset, mobj.spriteyoffset, mobj.rollangle, mobj.sloperoll, mobj.rollmodel fields
|
||||
|
||||
Same fields as in SRB2 2.2
|
||||
|
||||
+7
-1
@@ -42,9 +42,15 @@ enum hud {
|
||||
|
||||
extern boolean hud_running;
|
||||
|
||||
extern boolean hud_interpolate; // interpolation enabled
|
||||
extern UINT8 hud_interptag; // current tag
|
||||
extern UINT32 hud_interpcounter; // number of HUD hooks ran
|
||||
extern boolean hud_interpstring; // string mode
|
||||
extern boolean hud_interplatch; // string mode was toggled
|
||||
|
||||
boolean LUA_HudEnabled(enum hud option);
|
||||
|
||||
void LUAh_GameHUD(player_t *stplyr, huddrawlist_h list);
|
||||
void LUAh_GameHUD(huddrawlist_h list);
|
||||
void LUAh_ScoresHUD(huddrawlist_h list);
|
||||
void LUAh_IntermissionHUD(huddrawlist_h list);
|
||||
void LUAh_VoteHUD(huddrawlist_h list);
|
||||
|
||||
+60
-24
@@ -32,6 +32,12 @@
|
||||
#define HUDONLY if (!hud_running) return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!");
|
||||
|
||||
boolean hud_running = false;
|
||||
|
||||
boolean hud_interpolate = false;
|
||||
UINT8 hud_interptag = 0;
|
||||
UINT32 hud_interpcounter = 0;
|
||||
boolean hud_interpstring = false;
|
||||
boolean hud_interplatch = false;
|
||||
static UINT8 hud_enabled[(hud_MAX/8)+1];
|
||||
|
||||
static UINT8 hudAvailable; // hud hooks field
|
||||
@@ -1178,6 +1184,41 @@ static int libd_getDrawInfo(lua_State *L)
|
||||
return 3;
|
||||
}
|
||||
|
||||
static int libd_interpolate(lua_State *L)
|
||||
{
|
||||
HUDONLY
|
||||
|
||||
// do type checking even if interpolation is disabled
|
||||
boolean newinterpolate;
|
||||
UINT8 newtag;
|
||||
|
||||
if (lua_isnumber(L, 1))
|
||||
{
|
||||
newinterpolate = true;
|
||||
newtag = luaL_checkinteger(L, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
newinterpolate = luaL_checkboolean(L, 1);
|
||||
newtag = 0;
|
||||
}
|
||||
|
||||
if (!cv_uncappedhud.value)
|
||||
return 0;
|
||||
|
||||
hud_interpolate = newinterpolate;
|
||||
hud_interptag = newtag;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int libd_interpLatch(lua_State *L)
|
||||
{
|
||||
HUDONLY
|
||||
hud_interpstring = hud_interplatch = luaL_checkboolean(L, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static luaL_Reg lib_draw[] = {
|
||||
{"patchExists", libd_patchExists},
|
||||
{"cachePatch", libd_cachePatch},
|
||||
@@ -1205,6 +1246,8 @@ static luaL_Reg lib_draw[] = {
|
||||
{"getDrawInfo", libd_getDrawInfo},
|
||||
{"getHudColor", libd_getHudColor},
|
||||
{"useColorHud", libd_useColorHud},
|
||||
{"interpolate", libd_interpolate},
|
||||
{"interpLatch", libd_interpLatch},
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -1413,7 +1456,7 @@ boolean LUA_HudEnabled(enum hud option)
|
||||
}
|
||||
|
||||
// Hook for HUD rendering
|
||||
void LUAh_GameHUD(player_t *stplayr, huddrawlist_h list)
|
||||
void LUAh_GameHUD(huddrawlist_h list)
|
||||
{
|
||||
if (!gL || !(hudAvailable & (1<<hudhook_game)))
|
||||
return;
|
||||
@@ -1434,33 +1477,17 @@ void LUAh_GameHUD(player_t *stplayr, huddrawlist_h list)
|
||||
lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
lua_remove(gL, -3); // pop HUD
|
||||
LUA_PushUserdata(gL, stplayr, META_PLAYER);
|
||||
|
||||
if (splitscreen > 2 && stplayr == &players[displayplayers[3]])
|
||||
{
|
||||
LUA_PushUserdata(gL, &camera[3], META_CAMERA);
|
||||
camnum = 4;
|
||||
}
|
||||
else if (splitscreen > 1 && stplayr == &players[displayplayers[2]])
|
||||
{
|
||||
LUA_PushUserdata(gL, &camera[2], META_CAMERA);
|
||||
camnum = 3;
|
||||
}
|
||||
else if (splitscreen && stplayr == &players[displayplayers[1]])
|
||||
{
|
||||
LUA_PushUserdata(gL, &camera[1], META_CAMERA);
|
||||
camnum = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
LUA_PushUserdata(gL, &camera[0], META_CAMERA);
|
||||
camnum = 1;
|
||||
}
|
||||
LUA_PushUserdata(gL, stplyr, META_PLAYER);
|
||||
LUA_PushUserdata(gL, &camera[stplyrnum], META_CAMERA);
|
||||
camnum = stplyrnum + 1;
|
||||
|
||||
hud_interpcounter = 0;
|
||||
lua_pushnil(gL);
|
||||
while (lua_next(gL, -5) != 0) {
|
||||
hud_interpolate = hud_interpstring = hud_interplatch = false;
|
||||
hud_interpcounter++;
|
||||
lua_pushvalue(gL, -5); // graphics library (HUD[1])
|
||||
lua_pushvalue(gL, -5); // stplayr
|
||||
lua_pushvalue(gL, -5); // stplyr
|
||||
lua_pushvalue(gL, -5); // camera
|
||||
LUA_Call(gL, 3, 0, 1);
|
||||
}
|
||||
@@ -1493,7 +1520,10 @@ void LUAh_ScoresHUD(huddrawlist_h list)
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
lua_remove(gL, -3); // pop HUD
|
||||
lua_pushnil(gL);
|
||||
hud_interpcounter = 0;
|
||||
while (lua_next(gL, -3) != 0) {
|
||||
hud_interpolate = hud_interpstring = hud_interplatch = false;
|
||||
hud_interpcounter++;
|
||||
lua_pushvalue(gL, -3); // graphics library (HUD[1])
|
||||
LUA_Call(gL, 1, 0, 1);
|
||||
}
|
||||
@@ -1526,7 +1556,10 @@ void LUAh_IntermissionHUD(huddrawlist_h list)
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
lua_remove(gL, -3); // pop HUD
|
||||
lua_pushnil(gL);
|
||||
hud_interpcounter = 0;
|
||||
while (lua_next(gL, -3) != 0) {
|
||||
hud_interpolate = hud_interpstring = hud_interplatch = false;
|
||||
hud_interpcounter++;
|
||||
lua_pushvalue(gL, -3); // graphics library (HUD[1])
|
||||
LUA_Call(gL, 1, 0, 1);
|
||||
}
|
||||
@@ -1559,7 +1592,10 @@ void LUAh_VoteHUD(huddrawlist_h list)
|
||||
I_Assert(lua_istable(gL, -1));
|
||||
lua_remove(gL, -3); // pop HUD
|
||||
lua_pushnil(gL);
|
||||
hud_interpcounter = 0;
|
||||
while (lua_next(gL, -3) != 0) {
|
||||
hud_interpolate = hud_interpstring = hud_interplatch = false;
|
||||
hud_interpcounter++;
|
||||
lua_pushvalue(gL, -3); // graphics library (HUD[1])
|
||||
LUA_Call(gL, 1, 0, 1);
|
||||
}
|
||||
|
||||
+287
-52
@@ -11,11 +11,16 @@
|
||||
/// \brief a data structure for managing cached drawlists for the Lua hud lib
|
||||
|
||||
#include "lua_hudlib_drawlist.h"
|
||||
#include "lua_hud.h"
|
||||
#include "blua/lstate.h" // shhhhhh
|
||||
#include "lua_libs.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "v_video.h"
|
||||
#include "z_zone.h"
|
||||
#include "r_main.h"
|
||||
#include "r_fps.h"
|
||||
|
||||
enum drawitem_e {
|
||||
DI_Draw = 0,
|
||||
@@ -34,37 +39,45 @@ enum drawitem_e {
|
||||
|
||||
// A single draw item with all possible arguments needed for a draw call.
|
||||
typedef struct drawitem_s {
|
||||
UINT64 id;
|
||||
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;
|
||||
union {
|
||||
INT32 flags;
|
||||
INT32 c;
|
||||
};
|
||||
|
||||
union {
|
||||
fixed_t scale; // drawScaled
|
||||
fixed_t hscale; // drawStretched
|
||||
fixed_t w; // drawFill
|
||||
INT32 align; // drawString
|
||||
INT32 num; // drawNum, drawPaddedNum, drawPingNum
|
||||
UINT16 color; // fadeScreen
|
||||
};
|
||||
union {
|
||||
fixed_t vscale; // drawStretched
|
||||
fixed_t h; // drawFill
|
||||
INT32 digits; // drawPaddedNum
|
||||
UINT8 strength; // fadeScreen
|
||||
};
|
||||
|
||||
// pointers (and size_t's) last, for potentially better packing
|
||||
union {
|
||||
patch_t *patch;
|
||||
size_t stroffset; // offset into strbuf to get str
|
||||
};
|
||||
const UINT8 *colormap;
|
||||
UINT8 *basecolormap;
|
||||
UINT8 *outlinecolormap;
|
||||
fixed_t sx;
|
||||
fixed_t sy;
|
||||
INT32 num;
|
||||
INT32 digits;
|
||||
size_t stroffset; // offset into strbuf to get 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;
|
||||
drawitem_t *olditems;
|
||||
size_t olditems_len;
|
||||
size_t capacity;
|
||||
char *strbuf;
|
||||
size_t strbuf_capacity;
|
||||
size_t strbuf_len;
|
||||
@@ -88,8 +101,10 @@ huddrawlist_h LUA_HUD_CreateDrawList(void)
|
||||
|
||||
drawlist = (huddrawlist_h) Z_Calloc(sizeof(struct huddrawlist_s), PU_STATIC, NULL);
|
||||
drawlist->items = NULL;
|
||||
drawlist->items_capacity = 0;
|
||||
drawlist->items_len = 0;
|
||||
drawlist->olditems = NULL;
|
||||
drawlist->olditems_len = 0;
|
||||
drawlist->capacity = 0;
|
||||
drawlist->strbuf = NULL;
|
||||
drawlist->strbuf_capacity = 0;
|
||||
drawlist->strbuf_len = 0;
|
||||
@@ -99,15 +114,14 @@ huddrawlist_h LUA_HUD_CreateDrawList(void)
|
||||
|
||||
void LUA_HUD_ClearDrawList(huddrawlist_h list)
|
||||
{
|
||||
// swap the old and new lists
|
||||
void *tmp = list->olditems;
|
||||
list->olditems = list->items;
|
||||
list->items = tmp;
|
||||
|
||||
// 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->olditems_len = list->items_len;
|
||||
list->items_len = 0;
|
||||
|
||||
if (list->strbuf)
|
||||
@@ -125,6 +139,10 @@ void LUA_HUD_DestroyDrawList(huddrawlist_h list)
|
||||
{
|
||||
Z_Free(list->items);
|
||||
}
|
||||
if (list->olditems)
|
||||
{
|
||||
Z_Free(list->olditems);
|
||||
}
|
||||
if (list->strbuf)
|
||||
{
|
||||
Z_Free(list->strbuf);
|
||||
@@ -143,11 +161,11 @@ boolean LUA_HUD_IsDrawListValid(huddrawlist_h list)
|
||||
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->capacity <= list->items_len)
|
||||
{
|
||||
if (list->items_capacity == 0) list->items_capacity = 128;
|
||||
else list->items_capacity *= 2;
|
||||
list->items = (drawitem_t *) Z_Realloc(list->items, sizeof(struct drawitem_s) * list->items_capacity, PU_STATIC, NULL);
|
||||
list->capacity = list->capacity == 0 ? 128 : list->capacity * 2;
|
||||
list->items = Z_Realloc(list->items, sizeof(struct drawitem_s) * list->capacity, PU_STATIC, NULL);
|
||||
list->olditems = Z_Realloc(list->olditems, sizeof(struct drawitem_s) * list->capacity, PU_STATIC, NULL);
|
||||
}
|
||||
|
||||
return list->items_len++;
|
||||
@@ -178,6 +196,149 @@ static size_t CopyString(huddrawlist_h list, const char* str)
|
||||
}
|
||||
}
|
||||
|
||||
static void CalcStringCoords(drawitem_t *item, const char *string)
|
||||
{
|
||||
if (!(item->flags & V_NOSCALESTART) && cv_uncappedhud.value)
|
||||
{
|
||||
INT32 dupx = vid.dupx;
|
||||
INT32 dupy = vid.dupy;
|
||||
|
||||
item->flags |= V_NOSCALESTART;
|
||||
|
||||
if (item->flags & V_SCALEPATCHMASK) switch ((item->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;
|
||||
}
|
||||
|
||||
// only use one dup, to avoid stretching (har har)
|
||||
dupx = dupy = (dupx < dupy ? dupx : dupy);
|
||||
|
||||
INT32 x = item->x * dupx;
|
||||
INT32 y = item->y * dupy;
|
||||
|
||||
if (item->flags & V_SPLITSCREEN)
|
||||
y += (BASEVIDHEIGHT * (dupy - 1))/2;
|
||||
|
||||
if (item->flags & V_HORZSCREEN)
|
||||
x += (BASEVIDWIDTH * (dupx - 1))/2;
|
||||
|
||||
if (vid.width != BASEVIDWIDTH * dupx)
|
||||
{
|
||||
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
|
||||
// so center this imaginary screen
|
||||
if ((item->flags & (V_HORZSCREEN|V_SNAPTOLEFT)) == (V_HORZSCREEN|V_SNAPTOLEFT))
|
||||
x += (vid.width/2 - (BASEVIDWIDTH/2 * dupx));
|
||||
else if (item->flags & V_SNAPTORIGHT)
|
||||
x += (vid.width - (BASEVIDWIDTH * dupx));
|
||||
else if (!(item->flags & V_SNAPTOLEFT))
|
||||
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
|
||||
}
|
||||
if (vid.height != BASEVIDHEIGHT * dupy)
|
||||
{
|
||||
// same thing here
|
||||
if ((item->flags & (V_SPLITSCREEN|V_SNAPTOTOP)) == (V_SPLITSCREEN|V_SNAPTOTOP))
|
||||
y += (vid.height/2 - (BASEVIDHEIGHT/2 * dupy));
|
||||
else if (item->flags & V_SNAPTOBOTTOM)
|
||||
y += (vid.height - (BASEVIDHEIGHT * dupy));
|
||||
else if (!(item->flags & V_SNAPTOTOP))
|
||||
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
|
||||
}
|
||||
|
||||
// need to compensate for dup here
|
||||
if (item->type == DI_DrawString)
|
||||
{
|
||||
if (item->align == align_center)
|
||||
x -= (V_StringWidth(string, item->flags) * (dupx - 1))/2;
|
||||
if (item->align == align_right)
|
||||
x -= V_StringWidth(string, item->flags) * (dupx - 1);
|
||||
if (item->align == align_smallright)
|
||||
x -= V_SmallStringWidth(string, item->flags) * (dupx - 1);
|
||||
if (item->align == align_thinright)
|
||||
x -= V_ThinStringWidth(string, item->flags) * (dupx - 1);
|
||||
}
|
||||
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
}
|
||||
}
|
||||
|
||||
static void CalcFillCoords(drawitem_t *item)
|
||||
{
|
||||
if (!(item->flags & V_NOSCALESTART) && cv_uncappedhud.value)
|
||||
{
|
||||
INT32 dupx = vid.dupx;
|
||||
INT32 dupy = vid.dupy;
|
||||
INT32 x = item->x * dupx;
|
||||
INT32 y = item->y * dupy;
|
||||
INT32 c = item->c;
|
||||
|
||||
item->flags |= V_NOSCALESTART;
|
||||
item->w *= dupx;
|
||||
item->h *= dupy;
|
||||
|
||||
// Center it if necessary
|
||||
if (vid.width != BASEVIDWIDTH * dupx)
|
||||
{
|
||||
// dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx,
|
||||
// so center this imaginary screen
|
||||
if (c & V_SNAPTORIGHT)
|
||||
x += (vid.width - (BASEVIDWIDTH * dupx));
|
||||
else if (!(c & V_SNAPTOLEFT))
|
||||
x += (vid.width - (BASEVIDWIDTH * dupx)) / 2;
|
||||
}
|
||||
if (vid.height != BASEVIDHEIGHT * dupy)
|
||||
{
|
||||
// same thing here
|
||||
if (c & V_SNAPTOBOTTOM)
|
||||
y += (vid.height - (BASEVIDHEIGHT * dupy));
|
||||
else if (!(c & V_SNAPTOTOP))
|
||||
y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2;
|
||||
}
|
||||
if (c & V_SPLITSCREEN)
|
||||
y += (BASEVIDHEIGHT * dupy)/2;
|
||||
if (c & V_HORZSCREEN)
|
||||
x += (BASEVIDWIDTH * dupx)/2;
|
||||
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
}
|
||||
}
|
||||
|
||||
#define INTERP_LATCH 1
|
||||
#define INTERP_STRING 2
|
||||
#define INTERP_FLAGMASK 0x3
|
||||
|
||||
static UINT64 GetItemId(void)
|
||||
{
|
||||
if (!hud_interpolate)
|
||||
return 0;
|
||||
|
||||
// leave bits 0 and 1 free for the string mode
|
||||
UINT64 id = ((uintptr_t)gL->savedpc << 32) | (hud_interpcounter << 10) | (hud_interptag << 2);
|
||||
|
||||
if (hud_interplatch)
|
||||
{
|
||||
id |= INTERP_LATCH;
|
||||
hud_interplatch = false;
|
||||
}
|
||||
if (hud_interpstring)
|
||||
id |= INTERP_STRING;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDraw(
|
||||
huddrawlist_h list,
|
||||
INT32 x,
|
||||
@@ -189,9 +350,10 @@ void LUA_HUD_AddDraw(
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->id = GetItemId();
|
||||
item->type = DI_Draw;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->x = x << FRACBITS;
|
||||
item->y = y << FRACBITS;
|
||||
item->patch = patch;
|
||||
item->flags = flags;
|
||||
item->colormap = colormap;
|
||||
@@ -209,6 +371,7 @@ void LUA_HUD_AddDrawScaled(
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->id = GetItemId();
|
||||
item->type = DI_DrawScaled;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
@@ -231,6 +394,7 @@ void LUA_HUD_AddDrawStretched(
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->id = GetItemId();
|
||||
item->type = DI_DrawStretched;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
@@ -251,11 +415,13 @@ void LUA_HUD_AddDrawNum(
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->id = GetItemId();
|
||||
item->type = DI_DrawNum;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->num = num;
|
||||
item->flags = flags;
|
||||
CalcStringCoords(item, NULL);
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawPaddedNum(
|
||||
@@ -269,12 +435,14 @@ void LUA_HUD_AddDrawPaddedNum(
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->id = GetItemId();
|
||||
item->type = DI_DrawPaddedNum;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->num = num;
|
||||
item->digits = digits;
|
||||
item->flags = flags;
|
||||
CalcStringCoords(item, NULL);
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawPingNum(
|
||||
@@ -288,12 +456,14 @@ void LUA_HUD_AddDrawPingNum(
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->id = GetItemId();
|
||||
item->type = DI_DrawPingNum;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->num = num;
|
||||
item->flags = flags;
|
||||
item->colormap = colormap;
|
||||
CalcStringCoords(item, NULL);
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawFill(
|
||||
@@ -307,12 +477,14 @@ void LUA_HUD_AddDrawFill(
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->id = GetItemId();
|
||||
item->type = DI_DrawFill;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->w = w;
|
||||
item->h = h;
|
||||
item->c = c;
|
||||
CalcFillCoords(item);
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawString(
|
||||
@@ -326,12 +498,15 @@ void LUA_HUD_AddDrawString(
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->id = GetItemId();
|
||||
item->type = DI_DrawString;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->stroffset = CopyString(list, str);
|
||||
item->flags = flags;
|
||||
item->align = align;
|
||||
if (item->align != align_fixed)
|
||||
CalcStringCoords(item, str);
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawKartString(
|
||||
@@ -344,11 +519,13 @@ void LUA_HUD_AddDrawKartString(
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->id = GetItemId();
|
||||
item->type = DI_DrawKartString;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->stroffset = CopyString(list, str);
|
||||
item->flags = flags;
|
||||
CalcStringCoords(item, str);
|
||||
}
|
||||
|
||||
void LUA_HUD_AddDrawLevelTitle(
|
||||
@@ -361,11 +538,13 @@ void LUA_HUD_AddDrawLevelTitle(
|
||||
{
|
||||
size_t i = AllocateDrawItem(list);
|
||||
drawitem_t *item = &list->items[i];
|
||||
item->id = GetItemId();
|
||||
item->type = DI_DrawLevelTitle;
|
||||
item->x = x;
|
||||
item->y = y;
|
||||
item->stroffset = CopyString(list, str);
|
||||
item->flags = flags;
|
||||
CalcStringCoords(item, str);
|
||||
}
|
||||
|
||||
void LUA_HUD_AddFadeScreen(
|
||||
@@ -376,6 +555,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;
|
||||
@@ -384,6 +565,11 @@ void LUA_HUD_AddFadeScreen(
|
||||
void LUA_HUD_DrawList(huddrawlist_h list)
|
||||
{
|
||||
size_t i;
|
||||
size_t j = 0;
|
||||
fixed_t frac = R_UsingFrameInterpolation() ? rendertimefrac : FRACUNIT;
|
||||
fixed_t lerpx = 0, lerpy = 0;
|
||||
drawitem_t *latchitem = NULL;
|
||||
drawitem_t *oldlatchitem = NULL;
|
||||
|
||||
if (!list) I_Error("HUD drawlist invalid");
|
||||
if (list->items_len <= 0) return;
|
||||
@@ -392,68 +578,117 @@ void LUA_HUD_DrawList(huddrawlist_h list)
|
||||
for (i = 0; i < list->items_len; i++)
|
||||
{
|
||||
drawitem_t *item = &list->items[i];
|
||||
drawitem_t *olditem = NULL;
|
||||
const char *itemstr = &list->strbuf[item->stroffset];
|
||||
|
||||
if (item->id)
|
||||
{
|
||||
// find the old one too
|
||||
// this is kinda cursed... we need to check every item
|
||||
// but stop when the first-checked item is reached again
|
||||
size_t stop = j;
|
||||
do
|
||||
{
|
||||
if (j == list->olditems_len)
|
||||
{
|
||||
j = 0;
|
||||
continue;
|
||||
}
|
||||
drawitem_t *old = &list->olditems[j++];
|
||||
if ((old->id & ~INTERP_FLAGMASK) == (item->id & ~INTERP_FLAGMASK))
|
||||
{
|
||||
// gotcha!
|
||||
olditem = old;
|
||||
if (item->id & INTERP_LATCH)
|
||||
{
|
||||
lerpx = FixedMul(frac, item->x - olditem->x);
|
||||
lerpy = FixedMul(frac, item->y - olditem->y);
|
||||
latchitem = item;
|
||||
oldlatchitem = olditem;
|
||||
}
|
||||
else if (!(item->id & INTERP_STRING))
|
||||
{
|
||||
lerpx = FixedMul(frac, item->x - olditem->x);
|
||||
lerpy = FixedMul(frac, item->y - olditem->y);
|
||||
latchitem = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (j != stop);
|
||||
}
|
||||
else
|
||||
{
|
||||
lerpx = lerpy = 0;
|
||||
latchitem = NULL;
|
||||
}
|
||||
|
||||
#define LERP(it) (olditem ? olditem->it + FixedMul(frac, item->it - olditem->it) : item->it)
|
||||
|
||||
// half of this could be done when the coordinates are latched... zzzzzz
|
||||
#define LERPS(it) (latchitem ? ((latchitem->it + (item->it - latchitem->it)) - (latchitem->it - oldlatchitem->it)) + lerp##it : (olditem ? olditem->it + lerp##it : item->it))
|
||||
//define LERPS(it) (olditem ? (latchitem ? (latchitem->it + (item->it - latchitem->it)) - (latchitem->it - oldlatchitem->it) : olditem->it) + lerp##it : item->it)
|
||||
|
||||
switch (item->type)
|
||||
{
|
||||
case DI_Draw:
|
||||
V_DrawFixedPatch(item->x<<FRACBITS, item->y<<FRACBITS, FRACUNIT, item->flags, item->patch, item->colormap);
|
||||
V_DrawFixedPatch(LERPS(x), LERPS(y), 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);
|
||||
V_DrawFixedPatch(LERPS(x), LERPS(y), LERP(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);
|
||||
V_DrawStretchyFixedPatch(LERPS(x), LERPS(y), LERP(hscale), LERP(vscale), item->flags, item->patch, item->colormap);
|
||||
break;
|
||||
case DI_DrawNum:
|
||||
V_DrawTallNum(item->x, item->y, item->flags, item->num);
|
||||
V_DrawTallNum(LERPS(x), LERPS(y), item->flags, item->num);
|
||||
break;
|
||||
case DI_DrawPaddedNum:
|
||||
V_DrawPaddedTallNum(item->x, item->y, item->flags, item->num, item->digits);
|
||||
V_DrawPaddedTallNum(LERPS(x), LERPS(y), item->flags, item->num, item->digits);
|
||||
break;
|
||||
case DI_DrawPingNum:
|
||||
V_DrawPingNum(item->x, item->y, item->flags, item->num, item->colormap);
|
||||
V_DrawPingNum(LERPS(x), LERPS(y), item->flags, item->num, item->colormap);
|
||||
break;
|
||||
case DI_DrawFill:
|
||||
V_DrawFill(item->x, item->y, item->w, item->h, item->c);
|
||||
V_DrawFill(LERPS(x), LERPS(y), LERP(w), LERP(h), item->c);
|
||||
break;
|
||||
case DI_DrawString:
|
||||
switch(item->align)
|
||||
{
|
||||
// hu_font
|
||||
case align_left:
|
||||
V_DrawString(item->x, item->y, item->flags, itemstr);
|
||||
V_DrawString(LERPS(x), LERPS(y), item->flags, itemstr);
|
||||
break;
|
||||
case align_center:
|
||||
V_DrawCenteredString(item->x, item->y, item->flags, itemstr);
|
||||
V_DrawCenteredString(LERPS(x), LERPS(y), item->flags, itemstr);
|
||||
break;
|
||||
case align_right:
|
||||
V_DrawRightAlignedString(item->x, item->y, item->flags, itemstr);
|
||||
V_DrawRightAlignedString(LERPS(x), LERPS(y), item->flags, itemstr);
|
||||
break;
|
||||
case align_fixed:
|
||||
V_DrawStringAtFixed(item->x, item->y, item->flags, itemstr);
|
||||
V_DrawStringAtFixed(LERPS(x), LERPS(y), item->flags, itemstr);
|
||||
break;
|
||||
// hu_font, 0.5x scale
|
||||
case align_small:
|
||||
V_DrawSmallString(item->x, item->y, item->flags, itemstr);
|
||||
V_DrawSmallString(LERPS(x), LERPS(y), item->flags, itemstr);
|
||||
break;
|
||||
case align_smallright:
|
||||
V_DrawRightAlignedSmallString(item->x, item->y, item->flags, itemstr);
|
||||
V_DrawRightAlignedSmallString(LERPS(x), LERPS(y), item->flags, itemstr);
|
||||
break;
|
||||
// tny_font
|
||||
case align_thin:
|
||||
V_DrawThinString(item->x, item->y, item->flags, itemstr);
|
||||
V_DrawThinString(LERPS(x), LERPS(y), item->flags, itemstr);
|
||||
break;
|
||||
case align_thinright:
|
||||
V_DrawRightAlignedThinString(item->x, item->y, item->flags, itemstr);
|
||||
V_DrawRightAlignedThinString(LERPS(x), LERPS(y), item->flags, itemstr);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case DI_DrawKartString:
|
||||
V_DrawKartString(item->x, item->y, item->flags, itemstr);
|
||||
V_DrawKartString(LERPS(x), LERPS(y), item->flags, itemstr);
|
||||
break;
|
||||
case DI_DrawLevelTitle:
|
||||
V_DrawLevelTitle(item->x, item->y, item->flags, itemstr);
|
||||
V_DrawLevelTitle(LERPS(x), LERPS(y), item->flags, itemstr);
|
||||
break;
|
||||
case DI_FadeScreen:
|
||||
V_DrawFadeScreen(item->color, item->strength);
|
||||
|
||||
+8
-5
@@ -193,7 +193,7 @@ hudinfo_t hudinfo[NUMHUDITEMS] =
|
||||
{ 240, 160}, // HUD_LAP
|
||||
};
|
||||
|
||||
static huddrawlist_h luahuddrawlist_game;
|
||||
static huddrawlist_h luahuddrawlist_game[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
// variable to stop mayonaka static from flickering
|
||||
consvar_t cv_lessflicker = {"lessflicker", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
||||
@@ -473,7 +473,8 @@ void ST_Init(void)
|
||||
|
||||
ST_LoadGraphics();
|
||||
|
||||
luahuddrawlist_game = LUA_HUD_CreateDrawList();
|
||||
for (int i = 0; i < MAXSPLITSCREENPLAYERS; i++)
|
||||
luahuddrawlist_game[i] = LUA_HUD_CreateDrawList();
|
||||
}
|
||||
|
||||
// change the status bar too, when pressing F12 while viewing a demo.
|
||||
@@ -846,7 +847,7 @@ static void ST_overlayDrawer(void)
|
||||
{
|
||||
if (renderisnewtic)
|
||||
{
|
||||
LUAh_GameHUD(stplyr, luahuddrawlist_game);
|
||||
LUAh_GameHUD(luahuddrawlist_game[stplyrnum]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1024,7 +1025,8 @@ void ST_Drawer(void)
|
||||
{
|
||||
if (renderisnewtic)
|
||||
{
|
||||
LUA_HUD_ClearDrawList(luahuddrawlist_game);
|
||||
for (i = 0; i <= splitscreen; i++)
|
||||
LUA_HUD_ClearDrawList(luahuddrawlist_game[i]);
|
||||
}
|
||||
|
||||
// No deadview!
|
||||
@@ -1035,7 +1037,8 @@ void ST_Drawer(void)
|
||||
ST_overlayDrawer();
|
||||
}
|
||||
|
||||
LUA_HUD_DrawList(luahuddrawlist_game);
|
||||
for (i = 0; i <= 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.
|
||||
|
||||
Reference in new issue
Block a user