diff --git a/src/f_finale.c b/src/f_finale.c index e8757c18adcaad692faac6d83542eccd00650a10..401ab45b13813899534074a809cdc92817f90715 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -41,6 +41,7 @@ #include "console.h" #include "lua_hud.h" +#include "lua_hook.h" // Stage of animation: // 0 = text, 1 = art screen @@ -3423,7 +3424,7 @@ void F_TitleScreenDrawer(void) } luahook: - LUAh_TitleHUD(); + LUA_HUDHOOK(title); } // separate animation timer for backgrounds, since we also count diff --git a/src/hu_stuff.c b/src/hu_stuff.c index e0eaf8fb178f1252b60b93e329d2f14d05858e53..be215ff2135e9482b743cee1336809f7be5aaed0 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2104,7 +2104,7 @@ void HU_Drawer(void) } else HU_DrawCoopOverlay(); - LUAh_ScoresHUD(); + LUA_HUDHOOK(scores); } if (gamestate != GS_LEVEL) diff --git a/src/lua_hook.h b/src/lua_hook.h index 1af1697a7b9f937b449fe98777f572dcb342048b..1c01d1d6656622a2d703641747eb9c71865eaa23 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -78,6 +78,13 @@ automatically. X (LinedefExecute),\ X (ShouldJingleContinue),/* should jingle of the given music continue playing */\ +#define HUD_HOOK_LIST(X) \ + X (game),\ + X (scores),/* emblems/multiplayer list */\ + X (title),/* titlescreen */\ + X (titlecard),\ + X (intermission),\ + /* I chose to access the hook enums through a macro as well. This could provide a hint to lookup the macro's definition instead of the enum's definition. @@ -88,22 +95,26 @@ grepped and found in the lists above. #define MOBJ_HOOK(name) mobjhook_ ## name #define HOOK(name) hook_ ## name +#define HUD_HOOK(name) hudhook_ ## name #define STRING_HOOK(name) stringhook_ ## name #define ENUM(X) enum { X ## _LIST (X) X(MAX) } ENUM (MOBJ_HOOK); ENUM (HOOK); +ENUM (HUD_HOOK); ENUM (STRING_HOOK); #undef ENUM /* dead simple, LUA_HOOK(GameQuit) */ #define LUA_HOOK(type) LUA_HookVoid(HOOK(type)) +#define LUA_HUDHOOK(type) LUA_HookHUD(HUD_HOOK(type)) extern boolean hook_cmd_running; void LUA_HookVoid(int hook); +void LUA_HookHUD(int hook); int LUA_HookMobj(mobj_t *, int hook); int LUA_Hook2Mobj(mobj_t *, mobj_t *, int hook); diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 5815f17b327a22472b63af26f10cd055f380dfa8..96cb04543c43bd5740778230325c587bd4342cd3 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -36,6 +36,7 @@ LIST (mobjHookNames, MOBJ_HOOK_LIST); LIST (hookNames, HOOK_LIST); +LIST (hudHookNames, HUD_HOOK_LIST); LIST (stringHookNames, STRING_HOOK_LIST); #undef LIST @@ -51,6 +52,7 @@ typedef struct { } stringhook_t; static hook_t hookIds[HOOK(MAX)]; +static hook_t hudHookIds[HUD_HOOK(MAX)]; static hook_t mobjHookIds[NUMMOBJTYPES][MOBJ_HOOK(MAX)]; // Lua tables are used to lookup string hook ids. @@ -171,6 +173,12 @@ static void add_mobj_hook(lua_State *L, int hook_type) add_hook(&mobjHookIds[mobj_type][hook_type]); } +static void add_hud_hook(lua_State *L, int idx) +{ + add_hook(&hudHookIds[luaL_checkoption(L, + idx, "game", hudHookNames)]); +} + static void add_hook_ref(lua_State *L, int idx) { if (!(nextid & 7)) @@ -213,6 +221,10 @@ static int lib_addHook(lua_State *L) { add_hook(&hookIds[type]); } + else if (strcmp(name, "HUD") == 0) + { + add_hud_hook(L, 3); + } else { return luaL_argerror(L, 1, lua_pushfstring(L, "invalid hook " LUA_QS, name)); @@ -233,6 +245,23 @@ int LUA_HookLib(lua_State *L) return 0; } +/* TODO: remove in next backwards incompatible release */ +#if MODID == 18 +int lib_hudadd(lua_State *L);/* yeah compiler */ +int lib_hudadd(lua_State *L) +{ + if (!lua_lumploading) + return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); + + luaL_checktype(L, 1, LUA_TFUNCTION); + + add_hud_hook(L, 2); + add_hook_ref(L, 1); + + return 0; +} +#endif + typedef struct Hook_State Hook_State; typedef void (*Hook_Callback)(Hook_State *); @@ -610,6 +639,24 @@ int LUA_HookKey(INT32 keycode, int hook_type) return hook.status; } +void LUA_HookHUD(int hook_type) +{ + const hook_t * map = &hudHookIds[hook_type]; + Hook_State hook; + if (map->numHooks > 0) + { + start_hook_stack(); + begin_hook_values(&hook); + + LUA_SetHudHook(hook_type); + + hud_running = true; // local hook + init_hook_call(&hook, 0, res_none); + call_mapped(&hook, map); + hud_running = false; + } +} + /* ========================================================================= SPECIALIZED HOOKS ========================================================================= */ diff --git a/src/lua_hud.h b/src/lua_hud.h index d2f5bceca6f0d56745d2a40c3826ea1e594b9718..c1d2d164b97d6952612e088d80f0bd256a117d4b 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -47,8 +47,4 @@ extern boolean hud_running; boolean LUA_HudEnabled(enum hud option); -void LUAh_GameHUD(player_t *stplyr); -void LUAh_ScoresHUD(void); -void LUAh_TitleHUD(void); -void LUAh_TitleCardHUD(player_t *stplayr); -void LUAh_IntermissionHUD(boolean failedstage); +void LUA_SetHudHook(int hook); diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 9a3e676d5fd6168fd64bfaaa44466a5e85e8949c..b60cdcde09e3857680a982d78478e71739afef82 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -23,18 +23,18 @@ #include "v_video.h" #include "w_wad.h" #include "z_zone.h" +#include "y_inter.h" #include "lua_script.h" #include "lua_libs.h" #include "lua_hud.h" +#include "lua_hook.h" #define HUDONLY if (!hud_running) return luaL_error(L, "HUD rendering code should not be called outside of rendering hooks!"); boolean hud_running = false; static UINT8 hud_enabled[(hud_MAX/8)+1]; -static UINT8 hudAvailable; // hud hooks field - // must match enum hud in lua_hud.h static const char *const hud_disable_options[] = { "stagetitle", @@ -95,21 +95,6 @@ static const char *const patch_opt[] = { "topoffset", NULL}; -enum hudhook { - hudhook_game = 0, - hudhook_scores, - hudhook_intermission, - hudhook_title, - hudhook_titlecard -}; -static const char *const hudhook_opt[] = { - "game", - "scores", - "intermission", - "title", - "titlecard", - NULL}; - // alignment types for v.drawString enum align { align_left = 0, @@ -1152,6 +1137,8 @@ static luaL_Reg lib_draw[] = { {NULL, NULL} }; +static int lib_draw_ref; + // // lib_hud // @@ -1186,28 +1173,7 @@ static int lib_hudenabled(lua_State *L) // add a HUD element for rendering -static int lib_hudadd(lua_State *L) -{ - enum hudhook field; - - luaL_checktype(L, 1, LUA_TFUNCTION); - field = luaL_checkoption(L, 2, "game", hudhook_opt); - - if (!lua_lumploading) - return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); - - lua_getfield(L, LUA_REGISTRYINDEX, "HUD"); - I_Assert(lua_istable(L, -1)); - lua_rawgeti(L, -1, field+2); // HUD[2+] - I_Assert(lua_istable(L, -1)); - lua_remove(L, -2); - - lua_pushvalue(L, 1); - lua_rawseti(L, -2, (int)(lua_objlen(L, -2) + 1)); - - hudAvailable |= 1<<field; - return 0; -} +extern int lib_hudadd(lua_State *L); static luaL_Reg lib_hud[] = { {"enable", lib_hudenable}, @@ -1225,26 +1191,9 @@ int LUA_HudLib(lua_State *L) { memset(hud_enabled, 0xff, (hud_MAX/8)+1); - lua_newtable(L); // HUD registry table - lua_newtable(L); - luaL_register(L, NULL, lib_draw); - lua_rawseti(L, -2, 1); // HUD[1] = lib_draw - - lua_newtable(L); - lua_rawseti(L, -2, 2); // HUD[2] = game rendering functions array - - lua_newtable(L); - lua_rawseti(L, -2, 3); // HUD[3] = scores rendering functions array - - lua_newtable(L); - lua_rawseti(L, -2, 4); // HUD[4] = intermission rendering functions array - - lua_newtable(L); - lua_rawseti(L, -2, 5); // HUD[5] = title rendering functions array - - lua_newtable(L); - lua_rawseti(L, -2, 6); // HUD[6] = title card rendering functions array - lua_setfield(L, LUA_REGISTRYINDEX, "HUD"); + lua_newtable(L); + luaL_register(L, NULL, lib_draw); + lib_draw_ref = luaL_ref(L, LUA_REGISTRYINDEX); luaL_newmetatable(L, META_HUDINFO); lua_pushcfunction(L, hudinfo_get); @@ -1296,160 +1245,29 @@ boolean LUA_HudEnabled(enum hud option) return false; } -// Hook for HUD rendering -void LUAh_GameHUD(player_t *stplayr) +void LUA_SetHudHook(int hook) { - if (!gL || !(hudAvailable & (1<<hudhook_game))) - return; + lua_getref(gL, lib_draw_ref); - hud_running = true; - lua_settop(gL, 0); - - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); - I_Assert(lua_istable(gL, -1)); - lua_rawgeti(gL, -1, 2+hudhook_game); // HUD[2] = rendering funcs - I_Assert(lua_istable(gL, -1)); - - 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 && stplayr == &players[secondarydisplayplayer]) - LUA_PushUserdata(gL, &camera2, META_CAMERA); - else - LUA_PushUserdata(gL, &camera, META_CAMERA); - - lua_pushnil(gL); - while (lua_next(gL, -5) != 0) { - lua_pushvalue(gL, -5); // graphics library (HUD[1]) - lua_pushvalue(gL, -5); // stplayr - lua_pushvalue(gL, -5); // camera - LUA_Call(gL, 3, 0, 1); - } - lua_settop(gL, 0); - hud_running = false; -} - -void LUAh_ScoresHUD(void) -{ - if (!gL || !(hudAvailable & (1<<hudhook_scores))) - return; - - hud_running = true; - lua_settop(gL, 0); - - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); - I_Assert(lua_istable(gL, -1)); - lua_rawgeti(gL, -1, 2+hudhook_scores); // HUD[3] = rendering funcs - I_Assert(lua_istable(gL, -1)); - - lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw - I_Assert(lua_istable(gL, -1)); - lua_remove(gL, -3); // pop HUD - lua_pushnil(gL); - while (lua_next(gL, -3) != 0) { - lua_pushvalue(gL, -3); // graphics library (HUD[1]) - LUA_Call(gL, 1, 0, 1); - } - lua_settop(gL, 0); - hud_running = false; -} - -void LUAh_TitleHUD(void) -{ - if (!gL || !(hudAvailable & (1<<hudhook_title))) - return; - - hud_running = true; - lua_settop(gL, 0); - - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); - I_Assert(lua_istable(gL, -1)); - lua_rawgeti(gL, -1, 2+hudhook_title); // HUD[5] = rendering funcs - I_Assert(lua_istable(gL, -1)); - - lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw - I_Assert(lua_istable(gL, -1)); - lua_remove(gL, -3); // pop HUD - lua_pushnil(gL); - while (lua_next(gL, -3) != 0) { - lua_pushvalue(gL, -3); // graphics library (HUD[1]) - LUA_Call(gL, 1, 0, 1); - } - lua_settop(gL, 0); - hud_running = false; -} - -void LUAh_TitleCardHUD(player_t *stplayr) -{ - if (!gL || !(hudAvailable & (1<<hudhook_titlecard))) - return; - - hud_running = true; - lua_settop(gL, 0); - - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); - I_Assert(lua_istable(gL, -1)); - lua_rawgeti(gL, -1, 2+hudhook_titlecard); // HUD[6] = rendering funcs - I_Assert(lua_istable(gL, -1)); - - 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); - lua_pushinteger(gL, lt_ticker); - lua_pushinteger(gL, (lt_endtime + TICRATE)); - lua_pushnil(gL); - - while (lua_next(gL, -6) != 0) { - lua_pushvalue(gL, -6); // graphics library (HUD[1]) - lua_pushvalue(gL, -6); // stplayr - lua_pushvalue(gL, -6); // lt_ticker - lua_pushvalue(gL, -6); // lt_endtime - LUA_Call(gL, 4, 0, 1); - } - - lua_settop(gL, 0); - hud_running = false; -} - -void LUAh_IntermissionHUD(boolean failedstage) -{ - if (!gL || !(hudAvailable & (1<<hudhook_intermission))) - return; - - hud_running = true; - lua_settop(gL, 0); - - lua_pushcfunction(gL, LUA_GetErrorMessage); - - lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); - I_Assert(lua_istable(gL, -1)); - lua_rawgeti(gL, -1, 2+hudhook_intermission); // HUD[4] = rendering funcs - I_Assert(lua_istable(gL, -1)); - - lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw - I_Assert(lua_istable(gL, -1)); - lua_remove(gL, -3); // pop HUD - - lua_pushboolean(gL, failedstage); // stagefailed - lua_pushnil(gL); - - while (lua_next(gL, -4) != 0) { - lua_pushvalue(gL, -4); // graphics library (HUD[1]) - lua_pushvalue(gL, -4); // stagefailed - LUA_Call(gL, 2, 0, 1); + switch (hook) + { + case HUD_HOOK(game): { + camera_t *cam = (splitscreen && stplyr == + &players[secondarydisplayplayer]) + ? &camera2 : &camera; + + LUA_PushUserdata(gL, stplyr, META_PLAYER); + LUA_PushUserdata(gL, cam, META_CAMERA); + } break; + + case HUD_HOOK(titlecard): + LUA_PushUserdata(gL, stplyr, META_PLAYER); + lua_pushinteger(gL, lt_ticker); + lua_pushinteger(gL, (lt_endtime + TICRATE)); + break; + + case HUD_HOOK(intermission): + lua_pushboolean(gL, intertype == int_spec && + stagefailed); } - lua_settop(gL, 0); - hud_running = false; } diff --git a/src/st_stuff.c b/src/st_stuff.c index af14118e36cb87bb0475982345bba8bd1943306f..784666ad49e1db0492e4fa98d72dbba739893574 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -43,6 +43,7 @@ #endif #include "lua_hud.h" +#include "lua_hook.h" UINT16 objectsdrawn = 0; @@ -1391,7 +1392,7 @@ void ST_drawTitleCard(void) lt_lasttic = lt_ticker; luahook: - LUAh_TitleCardHUD(stplyr); + LUA_HUDHOOK(titlecard); } // @@ -2732,7 +2733,7 @@ static void ST_overlayDrawer(void) ST_drawPowerupHUD(); // same as it ever was... if (!(netgame || multiplayer) || !hu_showscores) - LUAh_GameHUD(stplyr); + LUA_HUDHOOK(game); // draw level title Tails if (stagetitle && (!WipeInAction) && (!WipeStageTitle)) diff --git a/src/y_inter.c b/src/y_inter.c index 6d876d7bdbf1a5d846e74eed2d34a284dfe03d22..b6528e0e6bfd5462a6bdba75cf2c968e1b5a843f 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -430,7 +430,7 @@ void Y_IntermissionDrawer(void) else if (bgtile) V_DrawPatchFill(bgtile); - LUAh_IntermissionHUD(intertype == int_spec && stagefailed); + LUA_HUDHOOK(intermission); if (!LUA_HudEnabled(hud_intermissiontally)) goto skiptallydrawer;