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
This commit is contained in:
toaster 2025-05-31 01:12:18 +01:00
parent 09e23e6e18
commit e4907227fc
9 changed files with 92 additions and 47 deletions

View file

@ -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;

View file

@ -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)

View file

@ -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

View file

@ -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;
}

View file

@ -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,

View file

@ -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)

View file

@ -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();

View file

@ -1076,7 +1076,7 @@ void P_Ticker(boolean run)
}
}
if (g_fast_forward == 0)
if (g_fast_forward == 0 || demo.simplerewind)
{
timeinmap++;
}

View file

@ -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);