mirror of
https://github.com/ZDoom/Raze.git
synced 2025-01-31 04:20:42 +00:00
- another backend update from GZDoom.
This commit is contained in:
parent
f599040212
commit
998def2487
4 changed files with 100 additions and 75 deletions
|
@ -54,10 +54,7 @@
|
|||
|
||||
CVAR(Bool, inter_subtitles, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG);
|
||||
|
||||
DObject* runner;
|
||||
PClass* runnerclass;
|
||||
PType* runnerclasstype;
|
||||
CompletionFunc completion;
|
||||
CutsceneState cutscene;
|
||||
static int ticks;
|
||||
|
||||
//=============================================================================
|
||||
|
@ -72,11 +69,11 @@ void Job_Init()
|
|||
if (!done)
|
||||
{
|
||||
done = true;
|
||||
GC::AddMarkerFunc([] { GC::Mark(runner); });
|
||||
GC::AddMarkerFunc([] { GC::Mark(cutscene.runner); });
|
||||
}
|
||||
runnerclass = PClass::FindClass("ScreenJobRunner");
|
||||
if (!runnerclass) I_FatalError("ScreenJobRunner not defined");
|
||||
runnerclasstype = NewPointer(runnerclass);
|
||||
cutscene.runnerclass = PClass::FindClass("ScreenJobRunner");
|
||||
if (!cutscene.runnerclass) I_FatalError("ScreenJobRunner not defined");
|
||||
cutscene.runnerclasstype = NewPointer(cutscene.runnerclass);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
@ -115,7 +112,7 @@ void CallCreateFunction(const char* qname, DObject* runner)
|
|||
{
|
||||
auto func = LookupFunction(qname);
|
||||
if (func->Proto->ArgumentTypes.Size() != 1) I_Error("Bad cutscene function %s. Must receive precisely one argument.", qname);
|
||||
if (func->Proto->ArgumentTypes[0] != runnerclasstype) I_Error("Bad cutscene function %s. Must receive ScreenJobRunner reference.", qname);
|
||||
if (func->Proto->ArgumentTypes[0] != cutscene.runnerclasstype) I_Error("Bad cutscene function %s. Must receive ScreenJobRunner reference.", qname);
|
||||
VMValue val = runner;
|
||||
VMCall(func, &val, 1, nullptr, 0);
|
||||
}
|
||||
|
@ -128,7 +125,7 @@ void CallCreateFunction(const char* qname, DObject* runner)
|
|||
|
||||
DObject* CreateRunner(bool clearbefore)
|
||||
{
|
||||
auto obj = runnerclass->CreateNew();
|
||||
auto obj = cutscene.runnerclass->CreateNew();
|
||||
auto func = LookupFunction("ScreenJobRunner.Init", false);
|
||||
VMValue val[3] = { obj, clearbefore, false };
|
||||
VMCall(func, val, 3, nullptr, 0);
|
||||
|
@ -182,15 +179,15 @@ void CutsceneDef::Create(DObject* runner)
|
|||
|
||||
void DeleteScreenJob()
|
||||
{
|
||||
if (runner) runner->Destroy();
|
||||
runner = nullptr;
|
||||
if (cutscene.runner) cutscene.runner->Destroy();
|
||||
cutscene.runner = nullptr;
|
||||
}
|
||||
|
||||
void EndScreenJob()
|
||||
{
|
||||
DeleteScreenJob();
|
||||
if (completion) completion(false);
|
||||
completion = nullptr;
|
||||
if (cutscene.completion) cutscene.completion(false);
|
||||
cutscene.completion = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -213,12 +210,12 @@ bool ScreenJobResponder(event_t* ev)
|
|||
}
|
||||
}
|
||||
FInputEvent evt = ev;
|
||||
if (runner)
|
||||
if (cutscene.runner)
|
||||
{
|
||||
IFVIRTUALPTRNAME(runner, NAME_ScreenJobRunner, OnEvent)
|
||||
IFVIRTUALPTRNAME(cutscene.runner, NAME_ScreenJobRunner, OnEvent)
|
||||
{
|
||||
int result = 0;
|
||||
VMValue parm[] = { runner, &evt };
|
||||
VMValue parm[] = { cutscene.runner, &evt };
|
||||
VMReturn ret(&result);
|
||||
VMCall(func, parm, 2, &ret, 1);
|
||||
return result;
|
||||
|
@ -236,12 +233,12 @@ bool ScreenJobResponder(event_t* ev)
|
|||
bool ScreenJobTick()
|
||||
{
|
||||
ticks++;
|
||||
if (runner)
|
||||
if (cutscene.runner)
|
||||
{
|
||||
IFVIRTUALPTRNAME(runner, NAME_ScreenJobRunner, OnTick)
|
||||
IFVIRTUALPTRNAME(cutscene.runner, NAME_ScreenJobRunner, OnTick)
|
||||
{
|
||||
int result = 0;
|
||||
VMValue parm[] = { runner };
|
||||
VMValue parm[] = { cutscene.runner };
|
||||
VMReturn ret(&result);
|
||||
VMCall(func, parm, 1, &ret, 1);
|
||||
return result;
|
||||
|
@ -260,12 +257,12 @@ void ScreenJobDraw()
|
|||
{
|
||||
double smoothratio = I_GetTimeFrac();
|
||||
|
||||
if (runner)
|
||||
if (cutscene.runner)
|
||||
{
|
||||
twod->ClearScreen();
|
||||
IFVIRTUALPTRNAME(runner, NAME_ScreenJobRunner, RunFrame)
|
||||
IFVIRTUALPTRNAME(cutscene.runner, NAME_ScreenJobRunner, RunFrame)
|
||||
{
|
||||
VMValue parm[] = { runner, smoothratio };
|
||||
VMValue parm[] = { cutscene.runner, smoothratio };
|
||||
VMCall(func, parm, 2, nullptr, 0);
|
||||
}
|
||||
}
|
||||
|
@ -279,12 +276,12 @@ void ScreenJobDraw()
|
|||
|
||||
bool ScreenJobValidate()
|
||||
{
|
||||
if (runner)
|
||||
if (cutscene.runner)
|
||||
{
|
||||
IFVIRTUALPTRNAME(runner, NAME_ScreenJobRunner, Validate)
|
||||
IFVIRTUALPTRNAME(cutscene.runner, NAME_ScreenJobRunner, Validate)
|
||||
{
|
||||
int res;
|
||||
VMValue parm[] = { runner };
|
||||
VMValue parm[] = { cutscene.runner };
|
||||
VMReturn ret(&res);
|
||||
VMCall(func, parm, 1, &ret, 1);
|
||||
I_ResetFrameTime();
|
||||
|
@ -304,12 +301,12 @@ bool StartCutscene(CutsceneDef& cs, int flags, const CompletionFunc& completion_
|
|||
{
|
||||
if ((cs.function.IsNotEmpty() || cs.video.IsNotEmpty()) && cs.function.CompareNoCase("none") != 0)
|
||||
{
|
||||
completion = completion_;
|
||||
runner = CreateRunner();
|
||||
GC::WriteBarrier(runner);
|
||||
cutscene.completion = completion_;
|
||||
cutscene.runner = CreateRunner();
|
||||
GC::WriteBarrier(cutscene.runner);
|
||||
try
|
||||
{
|
||||
cs.Create(runner);
|
||||
cs.Create(cutscene.runner);
|
||||
if (!ScreenJobValidate())
|
||||
{
|
||||
DeleteScreenJob();
|
||||
|
@ -349,6 +346,26 @@ DEFINE_ACTION_FUNCTION(DScreenJobRunner, setTransition)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// to block wipes on cutscenes that cannot handle it
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
bool CanWipe()
|
||||
{
|
||||
if (cutscene.runner == nullptr) return true;
|
||||
IFVM(ScreenJobRunner, CanWipe)
|
||||
{
|
||||
int can;
|
||||
VMReturn ret(&can);
|
||||
VMValue param = cutscene.runner;
|
||||
VMCall(func, ¶m, 1, &ret, 1);
|
||||
return can;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//
|
||||
|
|
|
@ -43,14 +43,19 @@ bool ScreenJobValidate();
|
|||
struct CutsceneDef;
|
||||
bool StartCutscene(const char* s, int flags, const CompletionFunc& completion);
|
||||
bool StartCutscene(CutsceneDef& cs, int flags, const CompletionFunc& completion_);
|
||||
bool CanWipe();
|
||||
|
||||
VMFunction* LookupFunction(const char* qname, bool validate = true);
|
||||
void CallCreateFunction(const char* qname, DObject* runner);
|
||||
DObject* CreateRunner(bool clearbefore = true);
|
||||
void AddGenericVideo(DObject* runner, const FString& fn, int soundid, int fps);
|
||||
|
||||
struct CutsceneState
|
||||
{
|
||||
DObject* runner;
|
||||
PClass* runnerclass;
|
||||
PType* runnerclasstype;
|
||||
CompletionFunc completion;
|
||||
};
|
||||
|
||||
extern DObject* runner;
|
||||
extern PClass* runnerclass;
|
||||
extern PType* runnerclasstype;
|
||||
extern CompletionFunc completion;
|
||||
extern CutsceneState cutscene;
|
||||
|
|
|
@ -180,29 +180,21 @@ class TObjPtr
|
|||
DObject *o;
|
||||
};
|
||||
public:
|
||||
TObjPtr() = default;
|
||||
TObjPtr(const TObjPtr<T> &q) = default;
|
||||
|
||||
#if 0 // Courtesy of GCC being stupid and not fully recognizing TobjPtr as trivial. GZDoom needs this constructor, but it breaks compilation in Raze, but only with GCC.
|
||||
TObjPtr(T q) noexcept
|
||||
: pp(q)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
T operator=(T q)
|
||||
constexpr TObjPtr<T>& operator=(T q) noexcept
|
||||
{
|
||||
pp = q;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T operator=(std::nullptr_t nul)
|
||||
constexpr TObjPtr<T>& operator=(std::nullptr_t nul) noexcept
|
||||
{
|
||||
o = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// To allow NULL, too.
|
||||
T operator=(const int val)
|
||||
TObjPtr<T>& operator=(const int val) noexcept
|
||||
{
|
||||
assert(val == 0);
|
||||
o = nullptr;
|
||||
|
@ -210,42 +202,42 @@ public:
|
|||
}
|
||||
|
||||
// To allow NULL, too. In Clang NULL is a long.
|
||||
T operator=(const long val)
|
||||
TObjPtr<T>& operator=(const long val) noexcept
|
||||
{
|
||||
assert(val == 0);
|
||||
o = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T Get() noexcept
|
||||
constexpr T Get() noexcept
|
||||
{
|
||||
return GC::ReadBarrier(pp);
|
||||
}
|
||||
|
||||
T ForceGet() noexcept //for situations where the read barrier needs to be skipped.
|
||||
constexpr T ForceGet() noexcept //for situations where the read barrier needs to be skipped.
|
||||
{
|
||||
return pp;
|
||||
}
|
||||
|
||||
operator T() noexcept
|
||||
constexpr operator T() noexcept
|
||||
{
|
||||
return GC::ReadBarrier(pp);
|
||||
}
|
||||
T &operator*() noexcept
|
||||
constexpr T &operator*() noexcept
|
||||
{
|
||||
T q = GC::ReadBarrier(pp);
|
||||
assert(q != NULL);
|
||||
return *q;
|
||||
}
|
||||
T operator->() noexcept
|
||||
constexpr T operator->() noexcept
|
||||
{
|
||||
return GC::ReadBarrier(pp);
|
||||
}
|
||||
bool operator!=(T u) noexcept
|
||||
constexpr bool operator!=(T u) noexcept
|
||||
{
|
||||
return GC::ReadBarrier(o) != u;
|
||||
}
|
||||
bool operator==(T u) noexcept
|
||||
constexpr bool operator==(T u) noexcept
|
||||
{
|
||||
return GC::ReadBarrier(o) == u;
|
||||
}
|
||||
|
@ -257,6 +249,17 @@ public:
|
|||
friend class DObject;
|
||||
};
|
||||
|
||||
// This is only needed because some parts of GCC do not treat a class with any constructor as trivial.
|
||||
// TObjPtr needs to be fully trivial, though - some parts in the engine depend on it.
|
||||
template<class T>
|
||||
constexpr TObjPtr<T> MakeObjPtr(T t) noexcept
|
||||
{
|
||||
// since this exists to replace the constructor we cannot initialize in the declaration as this would require the constructor we want to avoid.
|
||||
TObjPtr<T> tt;
|
||||
tt = t;
|
||||
return tt;
|
||||
}
|
||||
|
||||
// Use barrier_cast instead of static_cast when you need to cast
|
||||
// the contents of a TObjPtr to a related type.
|
||||
template<class T,class U> inline T barrier_cast(TObjPtr<U> &o)
|
||||
|
|
|
@ -77,7 +77,7 @@ static void CallCreateMapFunction(const char* qname, DObject* runner, MapRecord*
|
|||
auto func = LookupFunction(qname);
|
||||
if (func->Proto->ArgumentTypes.Size() == 1) return CallCreateFunction(qname, runner); // accept functions without map parameter as well here.
|
||||
if (func->Proto->ArgumentTypes.Size() != 2) I_Error("Bad map-cutscene function %s. Must receive precisely two arguments.", qname);
|
||||
if (func->Proto->ArgumentTypes[0] != runnerclasstype && func->Proto->ArgumentTypes[1] != maprecordtype)
|
||||
if (func->Proto->ArgumentTypes[0] != cutscene.runnerclasstype && func->Proto->ArgumentTypes[1] != maprecordtype)
|
||||
I_Error("Bad cutscene function %s. Must receive ScreenJobRunner and MapRecord reference.", qname);
|
||||
VMValue val[2] = { runner, map };
|
||||
VMCall(func, val, 2, nullptr, 0);
|
||||
|
@ -96,7 +96,7 @@ void CallCreateSummaryFunction(const char* qname, DObject* runner, MapRecord* ma
|
|||
auto s = func->Proto->ArgumentTypes.Size();
|
||||
auto at = func->Proto->ArgumentTypes.Data();
|
||||
if (s != 3 && s != 4) I_Error("Bad map-cutscene function %s. Must receive precisely three or four arguments.", qname);
|
||||
if (at[0] != runnerclasstype && at[1] != maprecordtype && at[2] != summaryinfotype && (s == 3 || at[3] == maprecordtype))
|
||||
if (at[0] != cutscene.runnerclasstype && at[1] != maprecordtype && at[2] != summaryinfotype && (s == 3 || at[3] == maprecordtype))
|
||||
I_Error("Bad cutscene function %s. Must receive ScreenJobRunner, MapRecord and SummaryInfo reference,", qname);
|
||||
if (info) summaryinfo = *info; // must be copied to a persistent location.
|
||||
else summaryinfo = {};
|
||||
|
@ -158,24 +158,24 @@ void PlayLogos(gameaction_t complete_ga, gameaction_t def_ga, bool stopmusic)
|
|||
|
||||
void ShowScoreboard(int numplayers, const CompletionFunc& completion_)
|
||||
{
|
||||
completion = completion_;
|
||||
runner = CreateRunner();
|
||||
Printf("Created runner at %p\n", runner);
|
||||
GC::WriteBarrier(runner);
|
||||
cutscene.completion = completion_;
|
||||
cutscene.runner = CreateRunner();
|
||||
Printf("Created runner at %p\n", cutscene.runner);
|
||||
GC::WriteBarrier(cutscene.runner);
|
||||
|
||||
const char* qname = globalCutscenes.MPSummaryScreen;
|
||||
auto func = LookupFunction(qname);
|
||||
if (func->Proto->ArgumentTypes.Size() != 2) I_Error("Bad map-cutscene function %s. Must receive precisely two arguments.", qname);
|
||||
if (func->Proto->ArgumentTypes[0] != runnerclasstype && func->Proto->ArgumentTypes[1] != TypeSInt32)
|
||||
if (func->Proto->ArgumentTypes[0] != cutscene.runnerclasstype && func->Proto->ArgumentTypes[1] != TypeSInt32)
|
||||
I_Error("Bad cutscene function %s. Must receive ScreenJobRunner reference and integer.", qname);
|
||||
VMValue val[2] = { runner, numplayers };
|
||||
VMValue val[2] = { cutscene.runner, numplayers };
|
||||
VMCall(func, val, 2, nullptr, 0);
|
||||
if (!ScreenJobValidate())
|
||||
{
|
||||
runner->Destroy();
|
||||
runner = nullptr;
|
||||
if (completion) completion(false);
|
||||
completion = nullptr;
|
||||
cutscene.runner->Destroy();
|
||||
cutscene.runner = nullptr;
|
||||
if (cutscene.completion) cutscene.completion(false);
|
||||
cutscene.completion = nullptr;
|
||||
return;
|
||||
}
|
||||
gameaction = ga_intermission;
|
||||
|
@ -189,7 +189,7 @@ void ShowScoreboard(int numplayers, const CompletionFunc& completion_)
|
|||
|
||||
void ShowIntermission(MapRecord* fromMap, MapRecord* toMap, SummaryInfo* info, CompletionFunc completion_)
|
||||
{
|
||||
if (runner != nullptr)
|
||||
if (cutscene.runner != nullptr)
|
||||
return; // protection against double exits.
|
||||
if (fromMap == toMap)
|
||||
{
|
||||
|
@ -200,17 +200,17 @@ void ShowIntermission(MapRecord* fromMap, MapRecord* toMap, SummaryInfo* info, C
|
|||
bool bossexit = g_bossexit;
|
||||
g_bossexit = false;
|
||||
|
||||
completion = completion_;
|
||||
runner = CreateRunner();
|
||||
GC::WriteBarrier(runner);
|
||||
cutscene.completion = completion_;
|
||||
cutscene.runner = CreateRunner();
|
||||
GC::WriteBarrier(cutscene.runner);
|
||||
|
||||
// retrieve cluster relations for cluster-based cutscenes.
|
||||
// retrieve cluster relations for cluster-based cutscene.
|
||||
ClusterDef* fromcluster = nullptr, *tocluster = nullptr;
|
||||
if (fromMap) fromcluster = FindCluster(fromMap->cluster);
|
||||
if (toMap) tocluster = FindCluster(toMap->cluster);
|
||||
if (fromcluster == tocluster) fromcluster = tocluster = nullptr;
|
||||
|
||||
|
||||
auto runner = cutscene.runner;
|
||||
try
|
||||
{
|
||||
if (fromMap && (!(fromMap->gameflags & LEVEL_BOSSONLYCUTSCENE) || bossexit))
|
||||
|
@ -245,9 +245,9 @@ void ShowIntermission(MapRecord* fromMap, MapRecord* toMap, SummaryInfo* info, C
|
|||
if (!ScreenJobValidate())
|
||||
{
|
||||
runner->Destroy();
|
||||
runner = nullptr;
|
||||
if (completion) completion(false);
|
||||
completion = nullptr;
|
||||
cutscene.runner = nullptr;
|
||||
if (cutscene.completion) cutscene.completion(false);
|
||||
cutscene.completion = nullptr;
|
||||
return;
|
||||
}
|
||||
gameaction = ga_intermission;
|
||||
|
@ -255,7 +255,7 @@ void ShowIntermission(MapRecord* fromMap, MapRecord* toMap, SummaryInfo* info, C
|
|||
catch (...)
|
||||
{
|
||||
if (runner) runner->Destroy();
|
||||
runner = nullptr;
|
||||
cutscene.runner = nullptr;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue