- Screen Job refactoring WIP.

Framework to let them handle proper input events.
Not used yet.
This commit is contained in:
Christoph Oelckers 2021-04-16 00:50:13 +02:00
parent 7e9b8059cf
commit dbd3e1de44
10 changed files with 112 additions and 35 deletions

View file

@ -76,12 +76,15 @@ void D_ProcessEvents (void)
continue;
if (ev->type == EV_DeviceChange)
UpdateJoystickMenu(I_UpdateDeviceList());
if (gamestate == GS_INTRO)
continue;
if (C_Responder (ev))
continue; // console ate the event
if (M_Responder (ev))
continue; // menu ate the event
if (gamestate != GS_INTRO) // GS_INTRO blocks the UI.
{
if (C_Responder(ev))
continue; // console ate the event
if (M_Responder(ev))
continue; // menu ate the event
}
G_Responder (ev);
}
}

View file

@ -44,6 +44,7 @@
#include "mmulti.h"
#include "gstrings.h"
#include "gamecontrol.h"
#include "screenjob.h"
#include "mapinfo.h"
CVAR(Bool, sv_cheats, true, CVAR_ARCHIVE|CVAR_SERVERINFO)
@ -239,6 +240,17 @@ void changeMap(int player, uint8_t** stream, bool skip)
//
//---------------------------------------------------------------------------
void endScreenJob(int player, uint8_t** stream, bool skip)
{
if (!skip) EndScreenJob();
}
//---------------------------------------------------------------------------
//
//
//
//---------------------------------------------------------------------------
void ChangeLevel(MapRecord* map, int skill)
{
Net_WriteByte(DEM_CHANGEMAP);

View file

@ -8,3 +8,4 @@ EXTERN_CVAR(Bool, sv_cheats)
void genericCheat(int player, uint8_t** stream, bool skip);
void changeMap(int player, uint8_t** stream, bool skip);
void endScreenJob(int player, uint8_t** stream, bool skip);

View file

@ -43,6 +43,7 @@
#include "gamecontrol.h"
#include "uiinput.h"
#include "automap.h"
#include "screenjob.h"
//==========================================================================
//
@ -53,6 +54,11 @@
bool G_Responder (event_t *ev)
{
if (gamestate == GS_INTRO || gamestate == GS_INTERMISSION)
{
return ScreenJobResponder(ev);
}
if (CT_Responder(ev))
return true; // chat ate the event
if (Cheat_Responder(ev))

View file

@ -1674,6 +1674,7 @@ bool D_CheckNetGame (void)
Net_SetCommandHandler(DEM_GENERICCHEAT, genericCheat);
Net_SetCommandHandler(DEM_CHANGEMAP, changeMap);
Net_SetCommandHandler(DEM_ENDSCREENJOB, endScreenJob);
for (i = 0; i < MAXNETNODES; i++)
{

View file

@ -89,6 +89,7 @@ enum EDemoCommand
DEM_GENERICCHEAT,
DEM_GIVE,
DEM_CHANGEMAP,
DEM_ENDSCREENJOB,
DEM_MAX
};

View file

@ -976,29 +976,6 @@ 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();
C_RunDelayedCommands();
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 updatePauseStatus()
{
// This must go through the network in multiplayer games.

View file

@ -328,9 +328,10 @@ static void GameTicker()
case GS_MENUSCREEN:
case GS_FULLCONSOLE:
break;
case GS_INTERMISSION:
case GS_INTRO:
// These elements do not tick at game rate.
ScreenJobTick();
break;
}
@ -370,7 +371,7 @@ void Display()
case GS_INTRO:
case GS_INTERMISSION:
// screen jobs are not bound by the game ticker so they need to be ticked in the display loop.
RunScreenJobFrame();
ScreenJobDraw();
break;
case GS_LEVEL:

View file

@ -193,7 +193,7 @@ public:
screenfade = 1.f;
}
job.job->SetClock(clock);
int state = job.job->Frame(clock, skiprequest);
int state = job.job->Frame(clock, skiprequest, 0);
clock = job.job->GetClock();
if (clock == 0) clock = 1;
return state;
@ -225,6 +225,36 @@ public:
return 1;
}
bool OnEvent(event_t* ev)
{
if (jobs[index].job->state == DScreenJob::stopping) return false;
return jobs[index].job->OnEvent(ev);
}
void OnFinished()
{
if (completion) completion(false);
completion = nullptr; // only finish once.
}
void OnTick()
{
if (index >= jobs.Size())
{
//DeleteJobs();
//twod->SetScreenFade(1);
//twod->ClearScreen(); // This must not leave the 2d buffer empty.
//if (gamestate == GS_INTRO) OnFinished();
//else Net_WriteByte(DEM_ENDSCREENJOB); // intermissions must be terminated synchronously.
}
else
{
if (jobs[index].job->state == DScreenJob::stopping) return;
jobs[index].job->ticks++;
jobs[index].job->OnTick();
}
}
bool RunFrame()
{
if (index >= jobs.Size())
@ -300,7 +330,25 @@ void DeleteScreenJob()
twod->SetScreenFade(1);
}
void RunScreenJobFrame()
void EndScreenJob()
{
if (runner) runner->OnFinished();
DeleteScreenJob();
}
bool ScreenJobResponder(event_t* ev)
{
if (runner) return runner->OnEvent(ev);
return false;
}
void ScreenJobTick()
{
if (runner) runner->OnTick();
}
void ScreenJobDraw()
{
// we cannot recover from this because we have no completion callback to call.
if (!runner)

View file

@ -2,6 +2,7 @@
#include <functional>
#include "dobject.h"
#include "v_2ddrawer.h"
#include "d_eventbase.h"
using CompletionFunc = std::function<void(bool)>;
struct JobDesc;
@ -16,8 +17,19 @@ class DScreenJob : public DObject
int fadestate = fadein;
friend class ScreenJobRunner;
protected:
int ticks = 0;
int state = running;
public:
enum
{
running = 1, // normal operation
skipped = 2, // finished by user skipping
finished = 3, // finished by completing its sequence
stopping = 4, // running ending animations / fadeout, etc. Will not accept more input.
stopped = 5, // we're done here.
};
enum
{
visible = 0,
@ -42,7 +54,19 @@ public:
return now;
}
virtual int Frame(uint64_t clock, bool skiprequest) { return 0; }
virtual bool OnEvent(event_t* evt) { return false; }
virtual void OnTick() { }
virtual int Frame(uint64_t clock, bool skiprequest) { return 1; }
virtual void Draw(double smoothratio) {}
int Frame(uint64_t clock, bool skiprequest, double smoothratio)
{
Draw(smoothratio);
if (state == skipped) return -1;
if (state == finished) return 0;
return Frame(clock, skiprequest);
}
int GetFadeState() const { return fadestate; }
};
@ -105,8 +129,11 @@ struct JobDesc
void RunScreenJob(JobDesc *jobs, int count, CompletionFunc completion, bool clearbefore = true, bool blockingui = false);
void EndScreenJob();
void DeleteScreenJob();
void RunScreenJobFrame();
bool ScreenJobResponder(event_t* ev);
void ScreenJobTick();
void ScreenJobDraw();
struct AnimSound
{