cleanup of the timer interface.

* rewrote all uses of timerSetCallback. Most were unnecessary or long obsolete, the sound updates need to run per frame, not per tic and the UI tickers need to be handled in the main loop anyway.
* Use a more precise timer to animate the menu transition.
* uncouple other menu animations from the game timer.
This commit is contained in:
Christoph Oelckers 2020-08-25 19:42:11 +02:00
parent a55da24277
commit 435e13dfa4
17 changed files with 40 additions and 103 deletions

View file

@ -671,11 +671,6 @@ void ParseOptions(void)
} }
void ClockStrobe()
{
//gGameClock++;
}
void ReadAllRFS(); void ReadAllRFS();
static const char* actions[] = { static const char* actions[] = {
@ -752,7 +747,6 @@ void GameInterface::app_init()
Printf("Loading control setup\n"); Printf("Loading control setup\n");
ctrlInit(); ctrlInit();
timerInit(120); timerInit(120);
timerSetCallback(ClockStrobe);
Printf("Initializing network users\n"); Printf("Initializing network users\n");
netInitialize(true); netInitialize(true);

View file

@ -16,6 +16,4 @@ uint64_t timerGetFreqU64(void);
double timerGetHiTicks(void); double timerGetHiTicks(void);
uint32_t timerGetTicks(void); uint32_t timerGetTicks(void);
void (*timerSetCallback(void (*callback)(void)))(void);
#endif // timer_h__ #endif // timer_h__

View file

@ -35,8 +35,6 @@ int timerInit(int const tickspersecond)
return 0; return 0;
} }
TArray<void(*)(void)> callbacks;
void timerUpdateClock(void) void timerUpdateClock(void)
{ {
auto time = steady_clock::now(); auto time = steady_clock::now();
@ -51,21 +49,5 @@ void timerUpdateClock(void)
totalclock += n; totalclock += n;
timerlastsample += n*nanoseconds(1000000000/timerticspersec); timerlastsample += n*nanoseconds(1000000000/timerticspersec);
// This function can get called from deep within processing loops.
// The callbacks in here may not be called recursively, though.
static bool recursion;
if (recursion) return;
recursion = true;
for (; n > 0; n--)
{
for (auto cb : callbacks) cb();
}
recursion = false;
} }
void(*timerSetCallback(void(*callback)(void)))(void)
{
callbacks.Push(callback);
return nullptr;
}

View file

@ -638,8 +638,6 @@ void C_InitConsole (int width, int height, bool ingame)
ConCols = ConWidth / cwidth; ConCols = ConWidth / cwidth;
if (conbuffer == NULL) conbuffer = new FConsoleBuffer; if (conbuffer == NULL) conbuffer = new FConsoleBuffer;
timerSetCallback(C_Ticker);
} }
//========================================================================== //==========================================================================
@ -1011,11 +1009,6 @@ void C_NewModeAdjust ()
int consoletic = 0; int consoletic = 0;
void C_Ticker() void C_Ticker()
{ {
// The engine timer ticks at 120 fps which is 4x too fast for this.
static int delay = 0;
if (++delay < 4) return;
delay = 0;
static int lasttic = 0; static int lasttic = 0;
consoletic++; consoletic++;

View file

@ -855,7 +855,6 @@ int RunGame()
sfx_empty = fileSystem.FindFile("engine/dsempty.lmp"); // this must be done outside the sound code because it's initialized late. sfx_empty = fileSystem.FindFile("engine/dsempty.lmp"); // this must be done outside the sound code because it's initialized late.
I_InitSound(); I_InitSound();
Mus_InitMusic(); Mus_InitMusic();
timerSetCallback(Mus_UpdateMusic);
S_ParseSndInfo(); S_ParseSndInfo();
InitStatistics(); InitStatistics();
LoadScripts(); LoadScripts();
@ -884,6 +883,28 @@ int RunGame()
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void TickSubsystems()
{
// run these on an independent timer until we got something working for the games.
static const uint64_t tickInterval = 1'000'000'000 / 30;
static uint64_t nexttick = 0;
auto nowtick = I_nsTime();
if (nexttick == 0) nexttick = nowtick;
int cnt = 0;
while (nexttick <= nowtick && cnt < 5)
{
nexttick += tickInterval;
C_Ticker();
M_Ticker();
cnt++;
}
// If this took too long the engine was most likely suspended so recalibrate the timer.
// Perfect precision is not needed here.
if (cnt == 5) nexttick = nowtick + tickInterval;
}
void app_loop() void app_loop()
{ {
gamestate = GS_STARTUP; gamestate = GS_STARTUP;
@ -892,6 +913,7 @@ void app_loop()
{ {
try try
{ {
TickSubsystems();
twod->SetSize(screen->GetWidth(), screen->GetHeight()); twod->SetSize(screen->GetWidth(), screen->GetHeight());
twodpsp.SetSize(screen->GetWidth(), screen->GetHeight()); twodpsp.SetSize(screen->GetWidth(), screen->GetHeight());
I_SetFrameTime(); I_SetFrameTime();
@ -910,6 +932,7 @@ void app_loop()
videoNextPage(); videoNextPage();
videoSetBrightness(0); // immediately reset this so that the value doesn't stick around in the backend. videoSetBrightness(0); // immediately reset this so that the value doesn't stick around in the backend.
Mus_UpdateMusic(); // must be at the end.
} }
catch (CRecoverableError& err) catch (CRecoverableError& err)
{ {

View file

@ -273,7 +273,7 @@ void DListMenu::PreDraw()
gi->DrawMenuCaption(origin, GStrings.localize(mDesc->mCaption)); gi->DrawMenuCaption(origin, GStrings.localize(mDesc->mCaption));
} }
} }
void DListMenu::Drawer () void DListMenu::Drawer ()
{ {
PreDraw(); PreDraw();
@ -317,20 +317,7 @@ bool FListMenuItem::Selectable()
void FListMenuItem::DrawSelector(int xofs, int yofs, FGameTexture *tex) void FListMenuItem::DrawSelector(int xofs, int yofs, FGameTexture *tex)
{ {
if (!tex) if (tex)
{
if ((DMenu::MenuTime%8) < 6)
{
DrawText(twod, ConFont, OptionSettings.mFontColorSelection,
(mXpos + xofs - 160) * CleanXfac + screen->GetWidth() / 2,
(mYpos + yofs - 100) * CleanYfac + screen->GetHeight() / 2,
"\xd",
DTA_CellX, 8 * CleanXfac,
DTA_CellY, 8 * CleanYfac,
TAG_DONE);
}
}
else
{ {
DrawTexture (twod, tex, mXpos + xofs, mYpos + yofs, DTA_Clean, true, TAG_DONE); DrawTexture (twod, tex, mXpos + xofs, mYpos + yofs, DTA_Clean, true, TAG_DONE);
} }

View file

@ -84,7 +84,6 @@ CVAR(Int, m_show_backbutton, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
TArray<MenuClassDescriptor*> menuClasses(TArray<MenuClassDescriptor*>::ENoInit(0)); TArray<MenuClassDescriptor*> menuClasses(TArray<MenuClassDescriptor*>::ENoInit(0));
DMenu *CurrentMenu; DMenu *CurrentMenu;
int DMenu::MenuTime;
bool DMenu::InMenu; bool DMenu::InMenu;
FNewGameStartup NewGameStartupInfo; FNewGameStartup NewGameStartupInfo;
@ -112,7 +111,7 @@ bool MenuTransition::StartTransition(DMenu *from, DMenu *to, MenuTransitionType
} }
else else
{ {
start = (int32_t) totalclock; start = I_GetTimeNS() * (120. / 1'000'000'000.);
length = 30; length = 30;
dir = animtype == MA_Advance? 1 : -1; dir = animtype == MA_Advance? 1 : -1;
previous = from; previous = from;
@ -123,10 +122,11 @@ bool MenuTransition::StartTransition(DMenu *from, DMenu *to, MenuTransitionType
bool MenuTransition::Draw() bool MenuTransition::Draw()
{ {
if (totalclock < start + length) double now = I_GetTimeNS() * (120. / 1'000'000'000);
if (now < start + length)
{ {
double factor = 120 * xdim / ydim; double factor = 120 * xdim / ydim;
double phase = ((int32_t) totalclock - start) / double(length) * M_PI + M_PI/2; double phase = (now - start) / double(length) * M_PI + M_PI/2;
previous->origin.X = factor * dir * (sin(phase) - 1.); previous->origin.X = factor * dir * (sin(phase) - 1.);
current->origin.X = factor * dir * (sin(phase) + 1.); current->origin.X = factor * dir * (sin(phase) + 1.);
@ -414,8 +414,6 @@ void M_ActivateMenu(DMenu *menu)
transition.StartTransition(CurrentMenu, menu, MA_Advance); transition.StartTransition(CurrentMenu, menu, MA_Advance);
} }
CurrentMenu = menu; CurrentMenu = menu;
DMenu::MenuTime = -1;
M_Ticker(); // This needs to be called once here to make sure that the menu actually has ticked before it gets drawn for the first time.
} }
//============================================================================= //=============================================================================
@ -865,8 +863,6 @@ bool M_Responder(event_t* ev)
void M_Ticker (void) void M_Ticker (void)
{ {
DMenu::MenuTime++;
if (DMenu::MenuTime & 3) return;
if (CurrentMenu != NULL && menuactive != MENU_Off) if (CurrentMenu != NULL && menuactive != MENU_Off)
{ {
if (transition.previous) transition.previous->Ticker(); if (transition.previous) transition.previous->Ticker();
@ -1013,7 +1009,6 @@ void M_Init (void)
RegisterLoadsaveMenus(); RegisterLoadsaveMenus();
RegisterOptionMenus(); RegisterOptionMenus();
RegisterJoystickMenus(); RegisterJoystickMenus();
timerSetCallback(M_Ticker);
M_ParseMenuDefs(); M_ParseMenuDefs();
UpdateJoystickMenu(nullptr); UpdateJoystickMenu(nullptr);
} }

View file

@ -48,7 +48,7 @@ struct MenuTransition
DMenu* previous; DMenu* previous;
DMenu* current; DMenu* current;
int32_t start; double start;
int32_t length; int32_t length;
int32_t dir; int32_t dir;
@ -319,7 +319,6 @@ public:
BACKBUTTON_TIME = 4*MENU_TICRATE BACKBUTTON_TIME = 4*MENU_TICRATE
}; };
static int MenuTime;
static bool InMenu; static bool InMenu;
DMenu *mParentMenu; DMenu *mParentMenu;

View file

@ -42,6 +42,7 @@
#include "statistics.h" #include "statistics.h"
#include "v_2ddrawer.h" #include "v_2ddrawer.h"
#include "v_video.h" #include "v_video.h"
#include "i_time.h"
#include "engineerrors.h" #include "engineerrors.h"
extern FSaveGameNode *quickSaveSlot; extern FSaveGameNode *quickSaveSlot;
@ -232,7 +233,8 @@ void DMessageBoxMenu::Drawer()
if (messageSelection >= 0) if (messageSelection >= 0)
{ {
if (((DMenu::MenuTime >> 2) % 8) < 6) auto time = I_msTime() / 30;
if (((time >> 2) % 8) < 6)
{ {
DrawText(twod, SmallFont, OptionSettings.mFontColorSelection, DrawText(twod, SmallFont, OptionSettings.mFontColorSelection,
(150 - 160) * CleanXfac + screen->GetWidth() / 2, (150 - 160) * CleanXfac + screen->GetWidth() / 2,

View file

@ -46,6 +46,7 @@
#include "v_draw.h" #include "v_draw.h"
#include "v_2ddrawer.h" #include "v_2ddrawer.h"
#include "v_video.h" #include "v_video.h"
#include "i_time.h"
//============================================================================= //=============================================================================
// //
@ -428,7 +429,8 @@ void DOptionMenu::Drawer ()
int cur_indent = mDesc->mItems[i]->Draw(mDesc, y, indent, isSelected); int cur_indent = mDesc->mItems[i]->Draw(mDesc, y, indent, isSelected);
if (cur_indent >= 0 && isSelected && mDesc->mItems[i]->Selectable()) if (cur_indent >= 0 && isSelected && mDesc->mItems[i]->Selectable())
{ {
if ((((DMenu::MenuTime>>2)%8) < 6) || CurrentMenu != this) auto time = I_msTime() / 30;
if ((((time>>2)%8) < 6) || CurrentMenu != this)
{ {
DrawOptionText(cur_indent + 3 * CleanXfac_1, y, OptionSettings.mFontColorSelection, ""); DrawOptionText(cur_indent + 3 * CleanXfac_1, y, OptionSettings.mFontColorSelection, "");
//M_DrawConText(OptionSettings.mFontColorSelection, cur_indent + 3 * CleanXfac_1, y+fontheight-9*CleanYfac_1, "\xd"); //M_DrawConText(OptionSettings.mFontColorSelection, cur_indent + 3 * CleanXfac_1, y+fontheight-9*CleanYfac_1, "\xd");

View file

@ -129,7 +129,6 @@ short nLocalSpr;
int nNetPlayerCount = 0; int nNetPlayerCount = 0;
short nClockVal; short nClockVal;
short fps;
short nRedTicks; short nRedTicks;
short bInMove; short bInMove;
short nAlarmTicks; short nAlarmTicks;
@ -210,22 +209,6 @@ void ShutDown(void)
//UnInitFX(); //UnInitFX();
} }
void timerhandler()
{
UpdateSounds();
scan_char++;
if (scan_char == kTimerTicks)
{
scan_char = 0;
lastfps = fps;
fps = 0;
}
if (!bInMove) {
C_RunDelayedCommands();
}
}
void HandleAsync() void HandleAsync()
{ {
handleevents(); handleevents();
@ -573,7 +556,6 @@ void InitTimer()
htimer = 1; htimer = 1;
timerInit(kTimerTicks); timerInit(kTimerTicks);
timerSetCallback(timerhandler);
} }
static const char* actions[] = static const char* actions[] =

View file

@ -210,7 +210,6 @@ extern short nClockVal;
extern short bSlipMode; extern short bSlipMode;
extern int bVanilla; extern int bVanilla;
extern short fps;
extern short bInMove; extern short bInMove;
#define POWERSLAVE (g_gameType & GAMEFLAG_POWERSLAVE) #define POWERSLAVE (g_gameType & GAMEFLAG_POWERSLAVE)

View file

@ -258,7 +258,6 @@ void GameLoop()
GameTicker(); GameTicker();
PlayerInterruptKeys(); PlayerInterruptKeys();
CheckKeys2(); CheckKeys2();
fps++;
} }

View file

@ -190,7 +190,6 @@ void InitLevel(int level)
InitPlayerKeys(i); InitPlayerKeys(i);
} }
fps = 0;
lastfps = 0; lastfps = 0;
InitStatus(); InitStatus();
ResetView(); ResetView();

View file

@ -246,6 +246,8 @@ void DrawView(double smoothRatio, bool sceneonly)
fix16_t nAngle; fix16_t nAngle;
fix16_t pan; fix16_t pan;
UpdateSounds();
zbob = Sin(2 * bobangle) >> 3; zbob = Sin(2 * bobangle) >> 3;
int nPlayerSprite = PlayerList[nLocalPlayer].nSprite; int nPlayerSprite = PlayerList[nLocalPlayer].nSprite;

View file

@ -275,25 +275,6 @@ static void SetupGameButtons()
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
static void ticker(void)
{
S_Update();
// we need CONTROL_GetInput in order to pick up joystick button presses
if (gamestate != GS_LEVEL || (paused && !System_WantGuiCapture()))
{
ControlInfo noshareinfo;
CONTROL_GetInput(&noshareinfo);
C_RunDelayedCommands();
}
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
static void loaddefs() static void loaddefs()
{ {
const char* defsfile = G_DefFile(); const char* defsfile = G_DefFile();
@ -370,7 +351,6 @@ static void Startup(void)
S_InitSound(); S_InitSound();
timerInit(TICRATE); timerInit(TICRATE);
timerSetCallback(ticker);
loadcons(); loadcons();
fi.initactorflags(); fi.initactorflags();

View file

@ -372,6 +372,7 @@ bool GameTicker()
drawtime.Reset(); drawtime.Reset();
drawtime.Clock(); drawtime.Clock();
S_Update();
displayrooms(screenpeek, smoothRatio); displayrooms(screenpeek, smoothRatio);
displayrest(smoothRatio); displayrest(smoothRatio);
drawtime.Unclock(); drawtime.Unclock();