From e4907227fc4f6e51c22ca0cf203be5470ccd4bf4 Mon Sep 17 00:00:00 2001 From: toaster Date: Sat, 31 May 2025 01:12:18 +0100 Subject: [PATCH] New simpler rewind code + re-enable in UI - Built off g_fast_forward to utilise a lot of existing structure - Only does steps of 5 seconds and therefore isn't precise, but that's better than having to rewatch/fastforward through the entire thing - No single frame step back or general in-motion rewind preview, but that was all overkill --- src/d_main.cpp | 2 +- src/g_demo.cpp | 3 +- src/g_demo.h | 8 +++ src/g_game.c | 10 +++- src/k_menu.h | 2 +- src/menus/transient/pause-replay.c | 89 ++++++++++++++++++++---------- src/p_setup.cpp | 21 ++++--- src/p_tick.c | 2 +- src/st_stuff.c | 2 +- 9 files changed, 92 insertions(+), 47 deletions(-) diff --git a/src/d_main.cpp b/src/d_main.cpp index 71f5f74d4..d660cf3a7 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -933,7 +933,7 @@ void D_SRB2Loop(void) realtics = entertic - oldentertics; oldentertics = entertic; - if (demo.playback && gamestate == GS_LEVEL) + if (demo.playback && gamestate == GS_LEVEL && demo.simplerewind == DEMO_REWIND_OFF) { // Nicer place to put this. realtics = realtics * cv_playbackspeed.value; diff --git a/src/g_demo.cpp b/src/g_demo.cpp index 9e6ecf1e2..05a881ace 100644 --- a/src/g_demo.cpp +++ b/src/g_demo.cpp @@ -3364,7 +3364,8 @@ void G_DoPlayDemoEx(const char *defdemoname, lumpnum_t deflumpnum) demo.deferstart = true; - CV_StealthSetValue(&cv_playbackspeed, 1); + if (demo.simplerewind == DEMO_REWIND_OFF) + CV_StealthSetValue(&cv_playbackspeed, 1); } void G_AddGhost(savebuffer_t *buffer, const char *defdemoname) diff --git a/src/g_demo.h b/src/g_demo.h index d2e19617f..4ce05c2a3 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -84,6 +84,7 @@ struct demovars_s { boolean recording, playback, timing; UINT16 version; // Current file format of the demo being played UINT8 attract; // Attract demo can be cancelled by any key + UINT8 simplerewind; boolean loadfiles, ignorefiles; // Demo file loading options boolean quitafterplaying; // quit after playing a demo from cmdline @@ -246,6 +247,13 @@ typedef enum DEMO_ATTRACT_CREDITS } demoAttractMode_t; +typedef enum +{ + DEMO_REWIND_OFF = 0, + DEMO_REWIND_RESUME, + DEMO_REWIND_PAUSE +} demoRewindMode_t; + void G_SyncDemoParty(INT32 rem, INT32 newsplitscreen); #ifdef __cplusplus diff --git a/src/g_game.c b/src/g_game.c index f4e2d3feb..8f05f30ab 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -1247,7 +1247,7 @@ void G_StartTitleCard(void) // The title card has been disabled for this map. // Oh well. - if (!G_IsTitleCardAvailable()) + if (demo.simplerewind || !G_IsTitleCardAvailable()) { WipeStageTitle = false; return; @@ -2144,6 +2144,14 @@ void G_Ticker(boolean run) if (g_fast_forward == 0) { + // Not "rewinding" anymore. + if (demo.simplerewind == DEMO_REWIND_PAUSE) + { + paused = true; + S_PauseAudio(); + } + demo.simplerewind = DEMO_REWIND_OFF; + // Next fast-forward is unlimited. g_fast_forward_clock_stop = INFTICS; } diff --git a/src/k_menu.h b/src/k_menu.h index c9564c484..1a4dc3066 100644 --- a/src/k_menu.h +++ b/src/k_menu.h @@ -593,10 +593,10 @@ extern menu_t PAUSE_PlaybackMenuDef; typedef enum { playback_hide, + playback_restart, playback_rewind, playback_pause, playback_fastforward, - playback_backframe, playback_resume, playback_advanceframe, playback_viewcount, diff --git a/src/menus/transient/pause-replay.c b/src/menus/transient/pause-replay.c index 7a63e65d1..ef5d1eb1e 100644 --- a/src/menus/transient/pause-replay.c +++ b/src/menus/transient/pause-replay.c @@ -39,21 +39,21 @@ menuitem_t PAUSE_PlaybackMenu[] = {IT_CALL | IT_STRING, "Hide Menu", NULL, "M_PHIDE", {.routine = M_SelectableClearMenus}, 0, 0}, {IT_CALL | IT_STRING, "Restart", NULL, "M_PRSTRT", {.routine = M_PlaybackRewind}, 20, 0}, - {IT_CALL | IT_STRING, "Pause", NULL, "M_PPAUSE", {.routine = M_PlaybackPause}, 36, 0}, - {IT_CALL | IT_STRING, "Fast-Forward", NULL, "M_PFFWD", {.routine = M_PlaybackFastForward}, 52, 0}, - {IT_CALL | IT_STRING, "Restart", NULL, "M_PRSTRT", {.routine = M_PlaybackRewind}, 20, 0}, - {IT_CALL | IT_STRING, "Resume", NULL, "M_PRESUM", {.routine = M_PlaybackPause}, 36, 0}, - {IT_CALL | IT_STRING, "Advance Frame", NULL, "M_PFADV", {.routine = M_PlaybackAdvance}, 52, 0}, + {IT_CALL | IT_STRING, "Rewind 5 seconds", NULL, "M_PREW", {.routine = M_PlaybackRewind}, 36, 0}, + {IT_CALL | IT_STRING, "Pause", NULL, "M_PPAUSE", {.routine = M_PlaybackPause}, 52, 0}, + {IT_CALL | IT_STRING, "Fast-Forward", NULL, "M_PFFWD", {.routine = M_PlaybackFastForward}, 68, 0}, + {IT_CALL | IT_STRING, "Resume", NULL, "M_PRESUM", {.routine = M_PlaybackPause}, 52, 0}, + {IT_CALL | IT_STRING, "Advance Frame", NULL, "M_PFADV", {.routine = M_PlaybackAdvance}, 68, 0}, - {IT_ARROWS | IT_STRING, "View Count", NULL, "M_PVIEWS", {.routine = M_PlaybackSetViews}, 72, 0}, - {IT_ARROWS | IT_STRING, "Viewpoint", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 88, 0}, - {IT_ARROWS | IT_STRING, "Viewpoint 2", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 104, 0}, - {IT_ARROWS | IT_STRING, "Viewpoint 3", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 120, 0}, - {IT_ARROWS | IT_STRING, "Viewpoint 4", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 136, 0}, + {IT_ARROWS | IT_STRING, "View Count", NULL, "M_PVIEWS", {.routine = M_PlaybackSetViews}, 88, 0}, + {IT_ARROWS | IT_STRING, "Viewpoint", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 104, 0}, + {IT_ARROWS | IT_STRING, "Viewpoint 2", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 120, 0}, + {IT_ARROWS | IT_STRING, "Viewpoint 3", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 136, 0}, + {IT_ARROWS | IT_STRING, "Viewpoint 4", NULL, "M_PNVIEW", {.routine = M_PlaybackAdjustView}, 152, 0}, - {IT_CALL | IT_STRING, "Toggle Director", NULL, "UN_IC11A", {.routine = M_PlaybackToggleDirector}, 156, 0}, - {IT_CALL | IT_STRING, "Toggle Free Camera", NULL, "M_PVIEWS", {.routine = M_PlaybackToggleFreecam}, 172, 0}, - {IT_CALL | IT_STRING, "Stop Playback", NULL, "M_PEXIT", {.routine = M_PlaybackQuit}, 188, 0}, + {IT_CALL | IT_STRING, "Toggle Director", NULL, "UN_IC11A", {.routine = M_PlaybackToggleDirector}, 172, 0}, + {IT_CALL | IT_STRING, "Toggle Free Camera", NULL, "M_PVIEWS", {.routine = M_PlaybackToggleFreecam}, 188, 0}, + {IT_CALL | IT_STRING, "Stop Playback", NULL, "M_PEXIT", {.routine = M_PlaybackQuit}, 204, 0}, }; menu_t PAUSE_PlaybackMenuDef = { @@ -153,19 +153,19 @@ static void M_PlaybackTick(void) // Toggle items if (paused) { - PAUSE_PlaybackMenu[playback_pause].status = PAUSE_PlaybackMenu[playback_fastforward].status = PAUSE_PlaybackMenu[playback_rewind].status = IT_DISABLED; - PAUSE_PlaybackMenu[playback_resume].status = PAUSE_PlaybackMenu[playback_advanceframe].status = PAUSE_PlaybackMenu[playback_backframe].status = IT_CALL|IT_STRING; + PAUSE_PlaybackMenu[playback_pause].status = PAUSE_PlaybackMenu[playback_fastforward].status = IT_DISABLED; + PAUSE_PlaybackMenu[playback_resume].status = PAUSE_PlaybackMenu[playback_advanceframe].status = IT_CALL|IT_STRING; - if (itemOn >= playback_rewind && itemOn <= playback_fastforward) - itemOn += playback_backframe - playback_rewind; + if (itemOn >= playback_pause && itemOn <= playback_fastforward) + itemOn += playback_resume - playback_pause; } else { - PAUSE_PlaybackMenu[playback_pause].status = PAUSE_PlaybackMenu[playback_fastforward].status = PAUSE_PlaybackMenu[playback_rewind].status = IT_CALL|IT_STRING; - PAUSE_PlaybackMenu[playback_resume].status = PAUSE_PlaybackMenu[playback_advanceframe].status = PAUSE_PlaybackMenu[playback_backframe].status = IT_DISABLED; + PAUSE_PlaybackMenu[playback_pause].status = PAUSE_PlaybackMenu[playback_fastforward].status = IT_CALL|IT_STRING; + PAUSE_PlaybackMenu[playback_resume].status = PAUSE_PlaybackMenu[playback_advanceframe].status = IT_DISABLED; - if (itemOn >= playback_backframe && itemOn <= playback_advanceframe) - itemOn -= playback_backframe - playback_rewind; + if (itemOn >= playback_resume && itemOn <= playback_advanceframe) + itemOn -= playback_resume - playback_pause; } if (modeattacking) @@ -173,10 +173,10 @@ static void M_PlaybackTick(void) for (i = playback_viewcount; i <= playback_director; i++) PAUSE_PlaybackMenu[i].status = IT_DISABLED; - PAUSE_PlaybackMenu[playback_freecam].mvar1 = 72; - PAUSE_PlaybackMenu[playback_quit].mvar1 = 88; + PAUSE_PlaybackMenu[playback_freecam].mvar1 = 88; + PAUSE_PlaybackMenu[playback_quit].mvar1 = 104; - currentMenu->x = BASEVIDWIDTH/2 - 52; + currentMenu->x = BASEVIDWIDTH/2 - 60; } else { @@ -189,11 +189,11 @@ static void M_PlaybackTick(void) for (i = r_splitscreen+1; i < 4; i++) PAUSE_PlaybackMenu[playback_view1+i].status = IT_DISABLED; - PAUSE_PlaybackMenu[playback_freecam].mvar1 = 172; - PAUSE_PlaybackMenu[playback_quit].mvar1 = 188; + PAUSE_PlaybackMenu[playback_freecam].mvar1 = 188; + PAUSE_PlaybackMenu[playback_quit].mvar1 = 204; - //currentMenu->x = BASEVIDWIDTH/2 - 94; - currentMenu->x = BASEVIDWIDTH/2 - 96; + //currentMenu->x = BASEVIDWIDTH/2 - 102; + currentMenu->x = BASEVIDWIDTH/2 - 104; } } @@ -204,9 +204,38 @@ void M_SetPlaybackMenuPointer(void) void M_PlaybackRewind(INT32 choice) { - (void)choice; + const tic_t curleveltime = leveltime; + + if (choice == playback_rewind) + { + demo.simplerewind = (paused ? DEMO_REWIND_PAUSE : DEMO_REWIND_RESUME); + menuactive = false; + } + G_DoPlayDemo(NULL); // Restart the current demo - M_ClearMenus(true); + + if (demo.simplerewind) + { + if (curleveltime > 5*TICRATE) + { + g_fast_forward = curleveltime - (5 * TICRATE); + g_fast_forward_clock_stop = INFTICS; //I_GetTime() + 2 * TICRATE; -- maybe? + } + else + { + if (demo.simplerewind == DEMO_REWIND_PAUSE) + { + paused = true; + S_PauseAudio(); + } + demo.simplerewind = DEMO_REWIND_OFF; + } + menuactive = true; + } + else + { + M_ClearMenus(true); + } } void M_PlaybackPause(INT32 choice) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index d6ceb5c19..8dd1b1e93 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -8474,7 +8474,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) wipegamestate = gamestate; // Don't fade if reloading the gamestate // Encore mode fade to pink to white // This is handled BEFORE sounds are stopped. - else if (encoremode && !prevencoremode && modeattacking == ATTACKING_NONE) + else if (encoremode && !prevencoremode && modeattacking == ATTACKING_NONE && !demo.simplerewind) { if (rendermode != render_none) { @@ -8545,7 +8545,14 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) // Let's fade to white here // But only if we didn't do the encore startup wipe - if (!reloadinggamestate) + if (demo.attract || demo.simplerewind) + { + // Leave the music alone! We're already playing what we want! + // Pull from RNG even though music will never change + // To silence playback has desynced warning + P_Random(PR_MUSICSELECT); + } + else if (!reloadinggamestate) { int wipetype = wipe_level_toblack; @@ -8558,15 +8565,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate) FixedDiv((F_GetWipeLength(wipedefs[wipe_level_toblack])-2)*NEWTICRATERATIO, NEWTICRATE), MUSICRATE)); #endif - if (demo.attract) - { - ; // Leave the music alone! We're already playing what we want! - - // Pull from RNG even though music will never change - // To silence playback has desynced warning - P_Random(PR_MUSICSELECT); - } - else if (K_PodiumSequence()) + if (K_PodiumSequence()) { // mapmusrng is set by local player position in K_ResetCeremony P_LoadLevelMusic(); diff --git a/src/p_tick.c b/src/p_tick.c index 206cdaf4c..bb1013312 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -1076,7 +1076,7 @@ void P_Ticker(boolean run) } } - if (g_fast_forward == 0) + if (g_fast_forward == 0 || demo.simplerewind) { timeinmap++; } diff --git a/src/st_stuff.c b/src/st_stuff.c index fef6481dc..e8196e57e 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -788,7 +788,7 @@ patch_t *ST_getRoundPicture(boolean small) // void ST_runTitleCard(void) { - boolean run = !(paused || P_AutoPause() || g_fast_forward > 0); + boolean run = !(paused || P_AutoPause() || (g_fast_forward > 0 && demo.simplerewind == DEMO_REWIND_OFF)); INT32 auxticker; boolean doroundicon = (ST_getRoundPicture(false) != NULL);