From e948b8ba48180d7028d9c5c9fe1f8e8e68008e97 Mon Sep 17 00:00:00 2001 From: fickleheart Date: Fri, 5 Apr 2019 02:38:48 -0500 Subject: [PATCH] Begin work on playback menu --- src/d_main.c | 2 +- src/d_netcmd.c | 2 +- src/g_game.c | 47 +++++++++--- src/g_game.h | 2 +- src/m_menu.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 232 insertions(+), 16 deletions(-) diff --git a/src/d_main.c b/src/d_main.c index 16a70519..a86a4f97 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -556,7 +556,7 @@ static void D_Display(void) wipegamestate = gamestate; // draw pause pic - if (paused && cv_showhud.value) + if (paused && cv_showhud.value && !demo.playback) { INT32 py; patch_t *patch; diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 50f0a2e8..21a8e2a3 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -2689,7 +2689,7 @@ static void Got_Pause(UINT8 **cp, INT32 playernum) return; } - if (modeattacking) + if (modeattacking && !demo.playback) return; paused = READUINT8(*cp); diff --git a/src/g_game.c b/src/g_game.c index 5aa28a07..df1c8235 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1949,6 +1949,33 @@ boolean G_Responder(event_t *ev) return true; } + + // Allow pausing + if ( + ev->data1 == gamecontrol[gc_pause][0] + || ev->data1 == gamecontrol[gc_pause][1] + || ev->data1 == KEY_PAUSE + ) + { + paused = !paused; + if (paused) + S_PauseAudio(); + else + S_ResumeAudio(); + + return true; + } + + // Anything else opens the menu if not already open, except for a few keys... + if (!( + // Rankings + ev->data1 == gamecontrol[gc_scores][0] || ev->data1 == gamecontrol[gc_scores][1] + )) + { + M_StartControlPanel(); + + return true; + } } // update keys current state @@ -2171,16 +2198,16 @@ boolean G_CanView(INT32 playernum, UINT8 viewnum, boolean onlyactive) // Return the next player that can be viewed on a view, wraps forward. // An out of range startview is corrected. // -INT32 G_FindView(INT32 startview, UINT8 viewnum, boolean onlyactive) +INT32 G_FindView(INT32 startview, UINT8 viewnum, boolean onlyactive, boolean reverse) { - INT32 i; + INT32 i, dir = reverse ? -1 : 1; startview = min(max(startview, 0), MAXPLAYERS); - for (i = startview; i < MAXPLAYERS; ++i) + for (i = startview; i < MAXPLAYERS && i >= 0; i += dir) { if (G_CanView(i, viewnum, onlyactive)) return i; } - for (i = 0; i < startview; ++i) + for (i = (reverse ? MAXPLAYERS-1 : 0); i != startview; i += dir) { if (G_CanView(i, viewnum, onlyactive)) return i; @@ -2251,12 +2278,14 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) R_ExecuteSetViewSize(); } - /* Check if anyone is available to view. */ - if (( playernum = G_FindView(playernum, viewnum, onlyactive) ) == -1) - return; - /* Focus our target view first so that we don't take its player. */ displayplayerp = (G_GetDisplayplayerPtr(viewnum)); olddisplayplayer = (*displayplayerp); + + /* Check if anyone is available to view. */ + if (( playernum = G_FindView(playernum, viewnum, onlyactive, playernum < olddisplayplayer) ) == -1) + return; + + /* Focus our target view first so that we don't take its player. */ (*displayplayerp) = playernum; if ((*displayplayerp) != olddisplayplayer) { @@ -2271,7 +2300,7 @@ void G_ResetView(UINT8 viewnum, INT32 playernum, boolean onlyactive) displayplayerp = (G_GetDisplayplayerPtr(viewd)); camerap = (P_GetCameraPtr(viewd)); - (*displayplayerp) = G_FindView(0, viewd, onlyactive); + (*displayplayerp) = G_FindView(0, viewd, onlyactive, false); P_ResetCamera(&players[(*displayplayerp)], camerap); } diff --git a/src/g_game.h b/src/g_game.h index c44691e8..42623dfa 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -294,7 +294,7 @@ INT32 *G_GetDisplayplayerPtr(UINT8 viewnum); boolean G_CouldView(INT32 playernum); boolean G_CanView(INT32 playernum, UINT8 viewnum, boolean onlyactive); -INT32 G_FindView(INT32 startview, UINT8 viewnum, boolean onlyactive); +INT32 G_FindView(INT32 startview, UINT8 viewnum, boolean onlyactive, boolean reverse); INT32 G_CountPlayersPotentiallyViewable(boolean active); void G_ResetViews(void); diff --git a/src/m_menu.c b/src/m_menu.c index c841d50e..96e4075d 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -345,6 +345,13 @@ static boolean M_QuitReplayHut(void); static void M_EnterReplayOptions(INT32 choice); static void M_HutStartReplay(INT32 choice); +static void M_DrawPlaybackMenu(void); +static void M_PlaybackPause(INT32 choice); +static void M_PlaybackFastForward(INT32 choice); +static void M_PlaybackAdvance(INT32 choice); +static void M_PlaybackSetViews(INT32 choice); +static void M_PlaybackAdjustView(INT32 choice); + // Drawing functions static void M_DrawGenericMenu(void); static void M_DrawGenericBackgroundMenu(void); @@ -558,6 +565,43 @@ static menuitem_t MISC_ReplayOptionsMenu[] = {IT_CVAR|IT_STRING, NULL, "Sync Check Interval", &cv_netdemosyncquality, 10}, }; +static menuitem_t PlaybackMenu[] = +{ + {IT_CALL | IT_STRING, NULL, "Hide Menu", M_SelectableClearMenus, 0}, + + {IT_CALL | IT_STRING, NULL, "Rewind", M_SelectableClearMenus, 24}, + {IT_CALL | IT_STRING, NULL, "Pause", M_PlaybackPause, 40}, + {IT_CALL | IT_STRING, NULL, "Resume", M_PlaybackPause, 40}, + {IT_CALL | IT_STRING, NULL, "Fast-Foward", M_PlaybackFastForward, 56}, + {IT_CALL | IT_STRING, NULL, "Advance Frame", M_PlaybackAdvance, 56}, + + {IT_ARROWS | IT_STRING, NULL, "View Count", M_PlaybackSetViews, 80}, + {IT_ARROWS | IT_STRING, NULL, "Viewpoint", M_PlaybackAdjustView, 96}, + {IT_ARROWS | IT_STRING, NULL, "Viewpoint 2", M_PlaybackAdjustView, 112}, + {IT_ARROWS | IT_STRING, NULL, "Viewpoint 3", M_PlaybackAdjustView, 128}, + {IT_ARROWS | IT_STRING, NULL, "Viewpoint 4", M_PlaybackAdjustView, 144}, + + + {IT_CALL | IT_STRING, NULL, "More Options...", M_ReplayHut, 168}, + {IT_CALL | IT_STRING, NULL, "Stop Playback", M_ReplayHut, 184}, +}; +typedef enum +{ + playback_hide, + playback_rewind, + playback_pause, + playback_resume, + playback_fastforward, + playback_advanceframe, + playback_viewcount, + playback_view1, + playback_view2, + playback_view3, + playback_view4, + playback_moreoptions, + playback_quit +} playback_e; + // --------------------------------- // Pause Menu Mode Attacking Edition // --------------------------------- @@ -1651,6 +1695,17 @@ menu_t MISC_ReplayStartDef = NULL }; +menu_t PlaybackMenuDef = { + NULL, + sizeof (PlaybackMenu)/sizeof (menuitem_t), + NULL, + PlaybackMenu, + M_DrawPlaybackMenu, + BASEVIDWIDTH/2 - 100, 2, + 0, + NULL +}; + menu_t MAPauseDef = PAUSEMENUSTYLE(MAPauseMenu, 40, 72); menu_t SPauseDef = PAUSEMENUSTYLE(SPauseMenu, 40, 72); menu_t MPauseDef = PAUSEMENUSTYLE(MPauseMenu, 40, 72); @@ -2639,8 +2694,6 @@ boolean M_Responder(event_t *ev) } } } - else if (ev->type == ev_keydown) // Preserve event for other responders - ch = ev->data1; if (ch == -1) return false; @@ -2786,6 +2839,19 @@ boolean M_Responder(event_t *ev) routine = M_ChangeCvar; } + if (currentMenu == &PlaybackMenuDef) + { + // Flip left/right with up/down for the playback menu, since it's a horizontal icon row. + switch (ch) + { + case KEY_LEFTARROW: ch = KEY_UPARROW; break; + case KEY_UPARROW: ch = KEY_RIGHTARROW; break; + case KEY_RIGHTARROW: ch = KEY_DOWNARROW; break; + case KEY_DOWNARROW: ch = KEY_LEFTARROW; break; + default: break; + } + } + // Keys usable within menu switch (ch) { @@ -2944,7 +3010,7 @@ void M_Drawer(void) if (menuactive) { // now that's more readable with a faded background (yeah like Quake...) - if (!WipeInAction) + if (!WipeInAction && currentMenu != &PlaybackMenuDef) // Replay playback has its own background V_DrawFadeScreen(0xFF00, 16); if (currentMenu->drawroutine) @@ -3007,7 +3073,11 @@ void M_StartControlPanel(void) menuactive = true; - if (!Playing()) + if (demo.playback) + { + currentMenu = &PlaybackMenuDef; + } + else if (!Playing()) { // Secret menu! //MainMenu[secrets].status = (M_AnySecretUnlocked()) ? (IT_STRING | IT_CALL) : (IT_DISABLED); @@ -5656,6 +5726,123 @@ static void M_HutStartReplay(INT32 choice) G_DoPlayDemo(demolist[dir_on[menudepthleft]].filepath); } +static void M_DrawPlaybackMenu(void) +{ + INT16 i; + patch_t *icon; + UINT8 *activemap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_GOLD, GTC_MENUCACHE); + + // Toggle items + if (paused) + { + PlaybackMenu[playback_pause].status = PlaybackMenu[playback_fastforward].status = IT_DISABLED; + PlaybackMenu[playback_resume].status = PlaybackMenu[playback_advanceframe].status = IT_CALL|IT_STRING; + } + else + { + PlaybackMenu[playback_pause].status = PlaybackMenu[playback_fastforward].status = IT_CALL|IT_STRING; + PlaybackMenu[playback_resume].status = PlaybackMenu[playback_advanceframe].status = IT_DISABLED; + } + for (i = 0; i <= splitscreen; i++) + PlaybackMenu[playback_view1+i].status = IT_ARROWS|IT_STRING; + for (i = splitscreen+1; i < 4; i++) + PlaybackMenu[playback_view1+i].status = IT_DISABLED; + + // wip + //M_DrawTextBox(currentMenu->x-68, currentMenu->y-7, 15, 15); + //M_DrawCenteredMenu(); + + for (i = 0; i < currentMenu->numitems; i++) + { + UINT8 *inactivemap = NULL; + + if (i >= playback_view1 && i <= playback_view4) + { + if (splitscreen >= i - playback_view1) + { + INT32 ply = *G_GetDisplayplayerPtr(i - playback_view1 + 1); + + icon = facerankprefix[players[ply].skin]; + if (i != itemOn) + inactivemap = R_GetTranslationColormap(players[ply].skin, players[ply].skincolor, GTC_MENUCACHE); + } + else if (currentMenu->menuitems[i].patch && W_GetNumForName(currentMenu->menuitems[i].patch) != LUMPERROR) + icon = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE); + else + icon = W_CachePatchName("PLAYRANK", PU_CACHE); // temp + } + else if (currentMenu->menuitems[i].status == IT_DISABLED) + continue; + else if (currentMenu->menuitems[i].patch && W_GetNumForName(currentMenu->menuitems[i].patch) != LUMPERROR) + icon = W_CachePatchName(currentMenu->menuitems[i].patch, PU_CACHE); + else + icon = W_CachePatchName("PLAYRANK", PU_CACHE); // temp + + if (i == playback_fastforward && cv_playbackspeed.value > 1) + V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, 0, icon, R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_SILVER, GTC_MENUCACHE)); + else + V_DrawMappedPatch(currentMenu->x + currentMenu->menuitems[i].alphaKey, currentMenu->y, 0, icon, (i == itemOn) ? activemap : inactivemap); + + if (i == itemOn) + V_DrawCenteredString(BASEVIDWIDTH/2, currentMenu->y + 18, V_ALLOWLOWERCASE, currentMenu->menuitems[i].text); + } +} + +static void M_PlaybackPause(INT32 choice) +{ + (void)choice; + + paused = !paused; + + if (paused) + { + itemOn = playback_resume; + S_PauseAudio(); + } + else + { + itemOn = playback_pause; + S_ResumeAudio(); + } + + CV_SetValue(&cv_playbackspeed, 1); +} + +static void M_PlaybackFastForward(INT32 choice) +{ + (void)choice; + + CV_SetValue(&cv_playbackspeed, cv_playbackspeed.value == 1 ? 4 : 1); +} + +static void M_PlaybackAdvance(INT32 choice) +{ + (void)choice; + + paused = false; + TryRunTics(1); + paused = true; +} + + +static void M_PlaybackSetViews(INT32 choice) +{ + if (choice > 0) + { + if (splitscreen < 3) + G_AdjustView(splitscreen + 2, 0, true); + } + else if (splitscreen) + { + splitscreen--; + R_ExecuteSetViewSize(); + } +} + +static void M_PlaybackAdjustView(INT32 choice) +{ + G_AdjustView(itemOn - playback_viewcount, (choice > 0) ? 1 : -1, true); +} static void M_PandorasBox(INT32 choice) {