mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 06:42:12 +00:00
Merged https://github.com/ZDoom/gzdoom/pull/1878 (ZScript Custom Cvars)
This commit is contained in:
parent
3039e3e7c8
commit
0a2fc5651c
4 changed files with 382 additions and 3 deletions
|
@ -45,6 +45,14 @@
|
|||
#include "palutil.h"
|
||||
#include "i_interface.h"
|
||||
|
||||
#include "dobject.h"
|
||||
#include "dobjtype.h"
|
||||
#include "dobjgc.h"
|
||||
|
||||
#include "vm.h"
|
||||
|
||||
#include "doomstat.h"
|
||||
|
||||
|
||||
struct FLatchedValue
|
||||
{
|
||||
|
@ -215,13 +223,11 @@ FBaseCVar::~FBaseCVar ()
|
|||
void FBaseCVar::SetCallback(void (*callback)(FBaseCVar&))
|
||||
{
|
||||
m_Callback = callback;
|
||||
m_UseCallback = true;
|
||||
}
|
||||
|
||||
void FBaseCVar::ClearCallback()
|
||||
{
|
||||
m_Callback = nullptr;
|
||||
m_UseCallback = false;
|
||||
}
|
||||
|
||||
void FBaseCVar::SetExtraDataPointer(void *pointer)
|
||||
|
@ -603,6 +609,34 @@ void FBaseCVar::EnableCallbacks ()
|
|||
}
|
||||
}
|
||||
|
||||
void FBaseCVar::InitZSCallbacks ()
|
||||
{
|
||||
CVarMap::Iterator it(cvarMap);
|
||||
CVarMap::Pair *pair;
|
||||
while (it.NextPair(pair))
|
||||
{
|
||||
auto cvar = pair->Value;
|
||||
if (cvar->Flags & CVAR_ZS_CUSTOM)
|
||||
{
|
||||
cvar->InstantiateZSCVar();
|
||||
}
|
||||
}
|
||||
GC::AddMarkerFunc(FBaseCVar::MarkZSCallbacks);
|
||||
}
|
||||
|
||||
void FBaseCVar::MarkZSCallbacks () {
|
||||
CVarMap::Iterator it(cvarMap);
|
||||
CVarMap::Pair *pair;
|
||||
while (it.NextPair(pair))
|
||||
{
|
||||
auto cvar = pair->Value;
|
||||
if (cvar->Flags & CVAR_ZS_CUSTOM)
|
||||
{
|
||||
cvar->MarkZSCVar();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FBaseCVar::DisableCallbacks ()
|
||||
{
|
||||
m_UseCallback = false;
|
||||
|
@ -1432,6 +1466,21 @@ FBaseCVar *C_CreateCVar(const char *var_name, ECVarType var_type, uint32_t flags
|
|||
}
|
||||
}
|
||||
|
||||
FBaseCVar * C_CreateZSCustomCVar(const char *var_name, ECVarType var_type, uint32_t flags, FName className)
|
||||
{
|
||||
assert(FindCVar(var_name, NULL) == NULL);
|
||||
flags |= CVAR_AUTO | CVAR_ZS_CUSTOM;
|
||||
switch (var_type)
|
||||
{
|
||||
case CVAR_Bool: return new FZSBoolCVar(var_name, 0, flags, className);
|
||||
case CVAR_Int: return new FZSIntCVar(var_name, 0, flags, className);
|
||||
case CVAR_Float: return new FZSFloatCVar(var_name, 0, flags, className);
|
||||
case CVAR_String: return new FZSStringCVar(var_name, NULL, flags, className);
|
||||
case CVAR_Color: return new FZSColorCVar(var_name, 0, flags, className);
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void UnlatchCVars (void)
|
||||
{
|
||||
for (const FLatchedValue& var : LatchedValues)
|
||||
|
@ -1737,3 +1786,222 @@ CCMD(listcvarswithoutdescription)
|
|||
{
|
||||
C_ListCVarsWithoutDescription();
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FZSIntCVar
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
|
||||
FZSIntCVar::FZSIntCVar(const char *name, int def, uint32_t flags, FName _className, const char* descr)
|
||||
: FIntCVar(name,def,flags,nullptr,descr) , cvarName(name) , className(_className)
|
||||
{ customCVarHandler = nullptr; }
|
||||
|
||||
void FZSIntCVar::CallCVarCallback(FZSIntCVar &self)
|
||||
{
|
||||
if (!self.customCVarHandler) {
|
||||
I_Error("Handler for CustomIntCVar '%s' of class '%s' was Destroyed", self.cvarName.GetChars(), self.className.GetChars());
|
||||
}
|
||||
IFVIRTUALPTRNAME(self.customCVarHandler, "CustomIntCVar", ModifyValue)
|
||||
{
|
||||
VMValue param[] = { self.customCVarHandler.Get() , self.cvarName.GetIndex() , self.Value };
|
||||
VMReturn ret(&self.Value);
|
||||
VMCall(func, param, 3, &ret, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void FZSIntCVar::InstantiateZSCVar()
|
||||
{
|
||||
static PClass * baseClass = PClass::FindClass("CustomIntCVar");
|
||||
assert(baseClass);
|
||||
PClass * classPtr = PClass::FindClass(className);
|
||||
if (!classPtr || !classPtr->IsDescendantOf(baseClass))
|
||||
{
|
||||
I_Error("Instantiating CVar '%s': Class '%s' %s",cvarName.GetChars(), className.GetChars(), (classPtr ? "is not a descendant of CustomIntCVar" : "does not exist"));
|
||||
}
|
||||
customCVarHandler = classPtr->CreateNew();
|
||||
SetCallback(reinterpret_cast<void (*)(FBaseCVar &)>(CallCVarCallback));
|
||||
}
|
||||
|
||||
void FZSIntCVar::MarkZSCVar()
|
||||
{
|
||||
GC::Mark(customCVarHandler);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FZSFloatCVar
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
|
||||
FZSFloatCVar::FZSFloatCVar(const char *name, float def, uint32_t flags, FName _className, const char* descr)
|
||||
: FFloatCVar(name,def,flags,nullptr,descr) , cvarName(name) , className(_className)
|
||||
{ customCVarHandler = nullptr; }
|
||||
|
||||
void FZSFloatCVar::CallCVarCallback(FZSFloatCVar &self)
|
||||
{
|
||||
if (!self.customCVarHandler) {
|
||||
I_Error("Handler for CustomFloatCVar '%s' of class '%s' was Destroyed", self.cvarName.GetChars(), self.className.GetChars());
|
||||
}
|
||||
IFVIRTUALPTRNAME(self.customCVarHandler, "CustomFloatCVar", ModifyValue)
|
||||
{
|
||||
VMValue param[] = { self.customCVarHandler.Get() , self.cvarName.GetIndex() , (double)self.Value };
|
||||
double v;
|
||||
VMReturn ret(&v);
|
||||
VMCall(func, param, 3, &ret, 1);
|
||||
self.Value = float(v);
|
||||
}
|
||||
}
|
||||
|
||||
void FZSFloatCVar::InstantiateZSCVar()
|
||||
{
|
||||
static PClass * baseClass = PClass::FindClass("CustomFloatCVar");
|
||||
assert(baseClass);
|
||||
PClass * classPtr = PClass::FindClass(className);
|
||||
if (!classPtr || !classPtr->IsDescendantOf(baseClass))
|
||||
{
|
||||
I_Error("Instantiating CVar '%s': Class '%s' %s", cvarName.GetChars(), className.GetChars(), (classPtr ? "is not a descendant of CustomFloatCVar" : "does not exist"));
|
||||
}
|
||||
customCVarHandler = classPtr->CreateNew();
|
||||
SetCallback(reinterpret_cast<void (*)(FBaseCVar &)>(CallCVarCallback));
|
||||
}
|
||||
|
||||
void FZSFloatCVar::MarkZSCVar()
|
||||
{
|
||||
GC::Mark(customCVarHandler);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FZSStringCVar
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
|
||||
FZSStringCVar::FZSStringCVar(const char *name, const char * def, uint32_t flags, FName _className, const char* descr)
|
||||
: FStringCVar(name,def,flags,nullptr,descr) , cvarName(name) , className(_className)
|
||||
{ customCVarHandler = nullptr; }
|
||||
|
||||
void FZSStringCVar::CallCVarCallback(FZSStringCVar &self)
|
||||
{
|
||||
if (!self.customCVarHandler) {
|
||||
I_Error("Handler for CustomStringCVar '%s' of class '%s' was Destroyed", self.cvarName.GetChars(), self.className.GetChars());
|
||||
}
|
||||
IFVIRTUALPTRNAME(self.customCVarHandler, "CustomStringCVar", ModifyValue)
|
||||
{
|
||||
VMValue param[] = { self.customCVarHandler.Get() , self.cvarName.GetIndex() , &self.mValue };
|
||||
VMReturn ret(&self.mValue);
|
||||
VMCall(func, param, 3, &ret, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void FZSStringCVar::InstantiateZSCVar()
|
||||
{
|
||||
static PClass * baseClass = PClass::FindClass("CustomStringCVar");
|
||||
assert(baseClass);
|
||||
PClass * classPtr = PClass::FindClass(className);
|
||||
if (!classPtr || !classPtr->IsDescendantOf(baseClass))
|
||||
{
|
||||
I_Error("Instantiating CVar '%s': Class '%s' %s", cvarName.GetChars(), className.GetChars(), (classPtr ? "is not a descendant of CustomStringCVar" : "does not exist"));
|
||||
}
|
||||
customCVarHandler = classPtr->CreateNew();
|
||||
SetCallback(reinterpret_cast<void (*)(FBaseCVar &)>(CallCVarCallback));
|
||||
}
|
||||
|
||||
void FZSStringCVar::MarkZSCVar()
|
||||
{
|
||||
GC::Mark(customCVarHandler);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FZSBoolCVar
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
|
||||
FZSBoolCVar::FZSBoolCVar(const char *name, bool def, uint32_t flags, FName _className, const char* descr)
|
||||
: FBoolCVar(name,def,flags,nullptr,descr) , cvarName(name) , className(_className)
|
||||
{ customCVarHandler = nullptr; }
|
||||
|
||||
void FZSBoolCVar::CallCVarCallback(FZSBoolCVar &self)
|
||||
{
|
||||
if (!self.customCVarHandler) {
|
||||
I_Error("Handler for CustomBoolCVar '%s' of class '%s' was Destroyed", self.cvarName.GetChars(), self.className.GetChars());
|
||||
}
|
||||
IFVIRTUALPTRNAME(self.customCVarHandler, "CustomBoolCVar", ModifyValue)
|
||||
{
|
||||
VMValue param[] = { self.customCVarHandler.Get() , self.cvarName.GetIndex() , self.Value };
|
||||
int v;
|
||||
VMReturn ret(&v);
|
||||
VMCall(func, param, 3, &ret, 1);
|
||||
self.Value = v;
|
||||
}
|
||||
}
|
||||
|
||||
void FZSBoolCVar::InstantiateZSCVar()
|
||||
{
|
||||
static PClass * baseClass = PClass::FindClass("CustomBoolCVar");
|
||||
assert(baseClass);
|
||||
PClass * classPtr = PClass::FindClass(className);
|
||||
if (!classPtr || !classPtr->IsDescendantOf(baseClass))
|
||||
{
|
||||
I_Error("Instantiating CVar '%s': Class '%s' %s", cvarName.GetChars(), className.GetChars(), (classPtr ? "is not a descendant of CustomBoolCVar" : "does not exist"));
|
||||
}
|
||||
customCVarHandler = classPtr->CreateNew();
|
||||
SetCallback(reinterpret_cast<void (*)(FBaseCVar &)>(CallCVarCallback));
|
||||
}
|
||||
|
||||
void FZSBoolCVar::MarkZSCVar()
|
||||
{
|
||||
GC::Mark(customCVarHandler);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FZSIntCVar
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
|
||||
FZSColorCVar::FZSColorCVar(const char *name, int def, uint32_t flags, FName _className, const char* descr)
|
||||
: FColorCVar(name,def,flags,nullptr,descr) , cvarName(name) , className(_className)
|
||||
{ customCVarHandler = nullptr; }
|
||||
|
||||
void FZSColorCVar::CallCVarCallback(FZSColorCVar &self)
|
||||
{
|
||||
if (!self.customCVarHandler) {
|
||||
I_Error("Handler for CustomColorCVar '%s' of class '%s' was Destroyed", self.cvarName.GetChars(), self.className.GetChars());
|
||||
}
|
||||
IFVIRTUALPTRNAME(self.customCVarHandler, "CustomColorCVar", ModifyValue)
|
||||
{
|
||||
VMValue param[] = { self.customCVarHandler.Get() , self.cvarName.GetIndex() , self.Value };
|
||||
VMReturn ret(&self.Value);
|
||||
VMCall(func, param, 3, &ret, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void FZSColorCVar::InstantiateZSCVar()
|
||||
{
|
||||
static PClass * baseClass = PClass::FindClass("CustomColorCVar");
|
||||
assert(baseClass);
|
||||
PClass * classPtr = PClass::FindClass(className);
|
||||
if (!classPtr || !classPtr->IsDescendantOf(baseClass))
|
||||
{
|
||||
I_Error("Instantiating CVar '%s': Class '%s' %s", cvarName.GetChars(), className.GetChars(), (classPtr ? "is not a descendant of CustomColorCVar" : "does not exist"));
|
||||
}
|
||||
customCVarHandler = classPtr->CreateNew();
|
||||
SetCallback(reinterpret_cast<void (*)(FBaseCVar &)>(CallCVarCallback));
|
||||
}
|
||||
|
||||
void FZSColorCVar::MarkZSCVar()
|
||||
{
|
||||
GC::Mark(customCVarHandler);
|
||||
}
|
|
@ -37,6 +37,7 @@
|
|||
#include "tarray.h"
|
||||
#include "autosegs.h"
|
||||
#include "name.h"
|
||||
#include "dobjgc.h"
|
||||
|
||||
class FSerializer; // this needs to go away.
|
||||
/*
|
||||
|
@ -72,6 +73,7 @@ enum
|
|||
CVAR_VIRTUAL = 1 << 17, // do not invoke the callback recursively so it can be used to
|
||||
// mirror an external variable.
|
||||
CVAR_CONFIG_ONLY = 1 << 18, // do not save var to savegame and do not send it across network.
|
||||
CVAR_ZS_CUSTOM = 1 << 19, // Custom CVar backed by a ZScript class
|
||||
};
|
||||
|
||||
enum ECVarType
|
||||
|
@ -188,6 +190,8 @@ public:
|
|||
static void EnableNoSet (); // enable the honoring of CVAR_NOSET
|
||||
static void EnableCallbacks ();
|
||||
static void DisableCallbacks ();
|
||||
static void InitZSCallbacks ();
|
||||
static void MarkZSCallbacks ();
|
||||
static void ResetColors (); // recalc color cvars' indices after screen change
|
||||
|
||||
static void ListVars (const char *filter, bool plain);
|
||||
|
@ -209,6 +213,10 @@ public:
|
|||
|
||||
protected:
|
||||
virtual void DoSet (UCVarValue value, ECVarType type) = 0;
|
||||
virtual void InstantiateZSCVar()
|
||||
{}
|
||||
virtual void MarkZSCVar()
|
||||
{}
|
||||
|
||||
static bool ToBool (UCVarValue value, ECVarType type);
|
||||
static int ToInt (UCVarValue value, ECVarType type);
|
||||
|
@ -278,6 +286,7 @@ FBaseCVar *GetCVar(int playernum, const char *cvarname);
|
|||
|
||||
// Create a new cvar with the specified name and type
|
||||
FBaseCVar *C_CreateCVar(const char *var_name, ECVarType var_type, uint32_t flags);
|
||||
FBaseCVar *C_CreateZSCustomCVar(const char *var_name, ECVarType var_type, uint32_t flags, FName className);
|
||||
|
||||
// Called from G_InitNew()
|
||||
void UnlatchCVars (void);
|
||||
|
@ -482,6 +491,71 @@ protected:
|
|||
int BitNum;
|
||||
};
|
||||
|
||||
class FZSIntCVar : public FIntCVar
|
||||
{
|
||||
TObjPtr<DObject*> customCVarHandler;
|
||||
FName cvarName;
|
||||
FName className;
|
||||
|
||||
static void CallCVarCallback(FZSIntCVar &);
|
||||
public:
|
||||
FZSIntCVar(const char *name, int def, uint32_t flags, FName className, const char* descr = nullptr);
|
||||
void InstantiateZSCVar() override;
|
||||
void MarkZSCVar() override;
|
||||
};
|
||||
|
||||
class FZSFloatCVar : public FFloatCVar
|
||||
{
|
||||
TObjPtr<DObject*> customCVarHandler;
|
||||
FName cvarName;
|
||||
FName className;
|
||||
|
||||
static void CallCVarCallback(FZSFloatCVar &);
|
||||
public:
|
||||
FZSFloatCVar(const char *name, float def, uint32_t flags, FName className, const char* descr = nullptr);
|
||||
void InstantiateZSCVar() override;
|
||||
void MarkZSCVar() override;
|
||||
};
|
||||
|
||||
class FZSStringCVar : public FStringCVar
|
||||
{
|
||||
TObjPtr<DObject*> customCVarHandler;
|
||||
FName cvarName;
|
||||
FName className;
|
||||
|
||||
static void CallCVarCallback(FZSStringCVar &);
|
||||
public:
|
||||
FZSStringCVar(const char *name, const char * def, uint32_t flags, FName className, const char* descr = nullptr);
|
||||
void InstantiateZSCVar() override;
|
||||
void MarkZSCVar() override;
|
||||
};
|
||||
|
||||
class FZSBoolCVar : public FBoolCVar
|
||||
{
|
||||
TObjPtr<DObject*> customCVarHandler;
|
||||
FName cvarName;
|
||||
FName className;
|
||||
|
||||
static void CallCVarCallback(FZSBoolCVar &);
|
||||
public:
|
||||
FZSBoolCVar(const char *name, bool def, uint32_t flags, FName className, const char* descr = nullptr);
|
||||
void InstantiateZSCVar() override;
|
||||
void MarkZSCVar() override;
|
||||
};
|
||||
|
||||
class FZSColorCVar : public FColorCVar
|
||||
{
|
||||
TObjPtr<DObject*> customCVarHandler;
|
||||
FName cvarName;
|
||||
FName className;
|
||||
|
||||
static void CallCVarCallback(FZSColorCVar &);
|
||||
public:
|
||||
FZSColorCVar(const char *name, int def, uint32_t flags, FName className, const char* descr = nullptr);
|
||||
void InstantiateZSCVar() override;
|
||||
void MarkZSCVar() override;
|
||||
};
|
||||
|
||||
class FBoolCVarRef
|
||||
{
|
||||
FBoolCVar* ref;
|
||||
|
|
|
@ -1593,6 +1593,8 @@ void ParseCVarInfo()
|
|||
ECVarType cvartype = CVAR_Dummy;
|
||||
int cvarflags = CVAR_MOD|CVAR_ARCHIVE;
|
||||
FBaseCVar *cvar;
|
||||
bool customCVar = false;
|
||||
FName customCVarClassName;
|
||||
|
||||
// Check for flag tokens.
|
||||
while (sc.TokenType == TK_Identifier)
|
||||
|
@ -1621,6 +1623,14 @@ void ParseCVarInfo()
|
|||
{
|
||||
cvarflags |= CVAR_CONFIG_ONLY;
|
||||
}
|
||||
else if (stricmp(sc.String, "handlerClass") == 0)
|
||||
{
|
||||
sc.MustGetStringName("(");
|
||||
sc.MustGetString();
|
||||
customCVar = true;
|
||||
customCVarClassName = sc.String;
|
||||
sc.MustGetStringName(")");
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Unknown cvar attribute '%s'", sc.String);
|
||||
|
@ -1703,7 +1713,7 @@ void ParseCVarInfo()
|
|||
}
|
||||
}
|
||||
// Now create the cvar.
|
||||
cvar = C_CreateCVar(cvarname, cvartype, cvarflags);
|
||||
cvar = customCVar ? C_CreateZSCustomCVar(cvarname, cvartype, cvarflags, customCVarClassName) : C_CreateCVar(cvarname, cvartype, cvarflags);
|
||||
if (cvardefault != NULL)
|
||||
{
|
||||
UCVarValue val;
|
||||
|
@ -3261,6 +3271,8 @@ static int D_InitGame(const FIWADInfo* iwad_info, TArray<FString>& allwads, TArr
|
|||
|
||||
R_ParseTrnslate();
|
||||
PClassActor::StaticInit ();
|
||||
FBaseCVar::InitZSCallbacks ();
|
||||
|
||||
Job_Init();
|
||||
|
||||
// [GRB] Initialize player class list
|
||||
|
|
|
@ -688,6 +688,31 @@ struct CVar native
|
|||
native int ResetToDefault();
|
||||
}
|
||||
|
||||
class CustomIntCVar abstract
|
||||
{
|
||||
abstract int ModifyValue(Name CVarName, int val);
|
||||
}
|
||||
|
||||
class CustomFloatCVar abstract
|
||||
{
|
||||
abstract double ModifyValue(Name CVarName, double val);
|
||||
}
|
||||
|
||||
class CustomStringCVar abstract
|
||||
{
|
||||
abstract String ModifyValue(Name CVarName, String val);
|
||||
}
|
||||
|
||||
class CustomBoolCVar abstract
|
||||
{
|
||||
abstract bool ModifyValue(Name CVarName, bool val);
|
||||
}
|
||||
|
||||
class CustomColorCVar abstract
|
||||
{
|
||||
abstract Color ModifyValue(Name CVarName, Color val);
|
||||
}
|
||||
|
||||
struct GIFont version("2.4")
|
||||
{
|
||||
Name fontname;
|
||||
|
|
Loading…
Reference in a new issue