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();
static const char* actions[] = {
@ -752,7 +747,6 @@ void GameInterface::app_init()
Printf("Loading control setup\n");
ctrlInit();
timerInit(120);
timerSetCallback(ClockStrobe);
Printf("Initializing network users\n");
netInitialize(true);

View file

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

View file

@ -35,8 +35,6 @@ int timerInit(int const tickspersecond)
return 0;
}
TArray<void(*)(void)> callbacks;
void timerUpdateClock(void)
{
auto time = steady_clock::now();
@ -51,21 +49,5 @@ void timerUpdateClock(void)
totalclock += n;
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;
if (conbuffer == NULL) conbuffer = new FConsoleBuffer;
timerSetCallback(C_Ticker);
}
//==========================================================================
@ -1011,11 +1009,6 @@ void C_NewModeAdjust ()
int consoletic = 0;
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;
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.
I_InitSound();
Mus_InitMusic();
timerSetCallback(Mus_UpdateMusic);
S_ParseSndInfo();
InitStatistics();
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()
{
gamestate = GS_STARTUP;
@ -892,6 +913,7 @@ void app_loop()
{
try
{
TickSubsystems();
twod->SetSize(screen->GetWidth(), screen->GetHeight());
twodpsp.SetSize(screen->GetWidth(), screen->GetHeight());
I_SetFrameTime();
@ -910,6 +932,7 @@ void app_loop()
videoNextPage();
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)
{

View file

@ -317,20 +317,7 @@ bool FListMenuItem::Selectable()
void FListMenuItem::DrawSelector(int xofs, int yofs, FGameTexture *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
if (tex)
{
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));
DMenu *CurrentMenu;
int DMenu::MenuTime;
bool DMenu::InMenu;
FNewGameStartup NewGameStartupInfo;
@ -112,7 +111,7 @@ bool MenuTransition::StartTransition(DMenu *from, DMenu *to, MenuTransitionType
}
else
{
start = (int32_t) totalclock;
start = I_GetTimeNS() * (120. / 1'000'000'000.);
length = 30;
dir = animtype == MA_Advance? 1 : -1;
previous = from;
@ -123,10 +122,11 @@ bool MenuTransition::StartTransition(DMenu *from, DMenu *to, MenuTransitionType
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 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.);
current->origin.X = factor * dir * (sin(phase) + 1.);
@ -414,8 +414,6 @@ void M_ActivateMenu(DMenu *menu)
transition.StartTransition(CurrentMenu, menu, MA_Advance);
}
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)
{
DMenu::MenuTime++;
if (DMenu::MenuTime & 3) return;
if (CurrentMenu != NULL && menuactive != MENU_Off)
{
if (transition.previous) transition.previous->Ticker();
@ -1013,7 +1009,6 @@ void M_Init (void)
RegisterLoadsaveMenus();
RegisterOptionMenus();
RegisterJoystickMenus();
timerSetCallback(M_Ticker);
M_ParseMenuDefs();
UpdateJoystickMenu(nullptr);
}

View file

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

View file

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

View file

@ -46,6 +46,7 @@
#include "v_draw.h"
#include "v_2ddrawer.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);
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, "");
//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;
short nClockVal;
short fps;
short nRedTicks;
short bInMove;
short nAlarmTicks;
@ -210,22 +209,6 @@ void ShutDown(void)
//UnInitFX();
}
void timerhandler()
{
UpdateSounds();
scan_char++;
if (scan_char == kTimerTicks)
{
scan_char = 0;
lastfps = fps;
fps = 0;
}
if (!bInMove) {
C_RunDelayedCommands();
}
}
void HandleAsync()
{
handleevents();
@ -573,7 +556,6 @@ void InitTimer()
htimer = 1;
timerInit(kTimerTicks);
timerSetCallback(timerhandler);
}
static const char* actions[] =

View file

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

View file

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

View file

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

View file

@ -246,6 +246,8 @@ void DrawView(double smoothRatio, bool sceneonly)
fix16_t nAngle;
fix16_t pan;
UpdateSounds();
zbob = Sin(2 * bobangle) >> 3;
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()
{
const char* defsfile = G_DefFile();
@ -370,7 +351,6 @@ static void Startup(void)
S_InitSound();
timerInit(TICRATE);
timerSetCallback(ticker);
loadcons();
fi.initactorflags();

View file

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