mirror of
https://github.com/DrBeef/Raze.git
synced 2024-11-25 05:21:28 +00:00
- Backend update from GZDoom
* scriptable CVARs. * GLES update * various ZScript improvements.
This commit is contained in:
parent
565f1ed416
commit
8c99d7b034
31 changed files with 1022 additions and 276 deletions
|
@ -45,6 +45,7 @@
|
|||
#include "findfile.h"
|
||||
#include "i_interface.h"
|
||||
#include "configfile.h"
|
||||
#include "printf.h"
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -447,6 +448,7 @@ const FSoundFontInfo *FSoundFontManager::FindSoundFont(const char *name, int all
|
|||
// an empty name will pick the first one in a compatible format.
|
||||
if (allowed & sfi.type && (name == nullptr || *name == 0 || !sfi.mName.CompareNoCase(name) || !sfi.mNameExt.CompareNoCase(name)))
|
||||
{
|
||||
DPrintf(DMSG_NOTIFY, "Found compatible soundfont %s\n", sfi.mNameExt.GetChars());
|
||||
return &sfi;
|
||||
}
|
||||
}
|
||||
|
@ -455,6 +457,7 @@ const FSoundFontInfo *FSoundFontManager::FindSoundFont(const char *name, int all
|
|||
{
|
||||
if (allowed & sfi.type)
|
||||
{
|
||||
DPrintf(DMSG_NOTIFY, "Unable to find %s soundfont. Falling back to %s\n", name, sfi.mNameExt.GetChars());
|
||||
return &sfi;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
@ -296,6 +302,7 @@ bool FBaseCVar::ToBool (UCVarValue value, ECVarType type)
|
|||
case CVAR_Bool:
|
||||
return value.Bool;
|
||||
|
||||
case CVAR_Color:
|
||||
case CVAR_Int:
|
||||
return !!value.Int;
|
||||
|
||||
|
@ -325,6 +332,7 @@ int FBaseCVar::ToInt (UCVarValue value, ECVarType type)
|
|||
switch (type)
|
||||
{
|
||||
case CVAR_Bool: res = (int)value.Bool; break;
|
||||
case CVAR_Color:
|
||||
case CVAR_Int: res = value.Int; break;
|
||||
#if __GNUC__ <= 2
|
||||
case CVAR_Float: tmp = value.Float; res = (int)tmp; break;
|
||||
|
@ -353,6 +361,7 @@ float FBaseCVar::ToFloat (UCVarValue value, ECVarType type)
|
|||
case CVAR_Bool:
|
||||
return (float)value.Bool;
|
||||
|
||||
case CVAR_Color:
|
||||
case CVAR_Int:
|
||||
return (float)value.Int;
|
||||
|
||||
|
@ -382,6 +391,7 @@ const char *FBaseCVar::ToString (UCVarValue value, ECVarType type)
|
|||
case CVAR_String:
|
||||
return value.String;
|
||||
|
||||
case CVAR_Color:
|
||||
case CVAR_Int:
|
||||
mysnprintf (cstrbuf, countof(cstrbuf), "%i", value.Int);
|
||||
break;
|
||||
|
@ -603,6 +613,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 +1470,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 +1790,305 @@ 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);
|
||||
}
|
||||
|
||||
UCVarValue FZSIntCVar::GenericZSCVarCallback(UCVarValue value, ECVarType type) {
|
||||
int val = ToInt(value, type);
|
||||
|
||||
IFVIRTUALPTRNAME(customCVarHandler, "CustomIntCVar", ModifyValue)
|
||||
{
|
||||
VMValue param[] = { customCVarHandler.Get() , cvarName.GetIndex() , val };
|
||||
VMReturn ret(&val);
|
||||
VMCall(func, param, 3, &ret, 1);
|
||||
}
|
||||
|
||||
UCVarValue v;
|
||||
v.Int = val;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
|
||||
UCVarValue FZSFloatCVar::GenericZSCVarCallback(UCVarValue value, ECVarType type) {
|
||||
float val = ToFloat(value, type);
|
||||
|
||||
IFVIRTUALPTRNAME(customCVarHandler, "CustomFloatCVar", ModifyValue)
|
||||
{
|
||||
VMValue param[] = { customCVarHandler.Get() , cvarName.GetIndex() , (double) val };
|
||||
double v;
|
||||
VMReturn ret(&v);
|
||||
VMCall(func, param, 3, &ret, 1);
|
||||
val = (float) v;
|
||||
}
|
||||
|
||||
UCVarValue v;
|
||||
v.Float = val;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
|
||||
UCVarValue FZSStringCVar::GenericZSCVarCallback(UCVarValue value, ECVarType type) {
|
||||
FString val = ToString(value, type);
|
||||
|
||||
IFVIRTUALPTRNAME(customCVarHandler, "CustomStringCVar", ModifyValue)
|
||||
{
|
||||
VMValue param[] = { customCVarHandler.Get() , cvarName.GetIndex() , &val };
|
||||
VMReturn ret(&val);
|
||||
VMCall(func, param, 3, &ret, 1);
|
||||
}
|
||||
|
||||
char * str = new char[val.Len() + 1];
|
||||
memcpy(str, val.GetChars(), val.Len() * sizeof(char));
|
||||
str[val.Len()] = '\0';
|
||||
|
||||
UCVarValue v;
|
||||
v.String = str;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
|
||||
UCVarValue FZSBoolCVar::GenericZSCVarCallback(UCVarValue value, ECVarType type) {
|
||||
bool val = ToFloat(value, type);
|
||||
|
||||
IFVIRTUALPTRNAME(customCVarHandler, "CustomBoolCVar", ModifyValue)
|
||||
{
|
||||
VMValue param[] = { customCVarHandler.Get() , cvarName.GetIndex() , val };
|
||||
int v;
|
||||
VMReturn ret(&v);
|
||||
VMCall(func, param, 3, &ret, 1);
|
||||
val = v;
|
||||
}
|
||||
|
||||
UCVarValue v;
|
||||
v.Bool = val;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FZSColorCVar
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
UCVarValue FZSColorCVar::GenericZSCVarCallback(UCVarValue value, ECVarType type) {
|
||||
int val = ToInt(value, type);
|
||||
|
||||
IFVIRTUALPTRNAME(customCVarHandler, "CustomColorCVar", ModifyValue)
|
||||
{
|
||||
VMValue param[] = { customCVarHandler.Get() , cvarName.GetIndex() , val };
|
||||
VMReturn ret(&val);
|
||||
VMCall(func, param, 3, &ret, 1);
|
||||
}
|
||||
|
||||
UCVarValue v;
|
||||
v.Int = val;
|
||||
return v;
|
||||
}
|
|
@ -37,6 +37,7 @@
|
|||
#include "tarray.h"
|
||||
#include "autosegs.h"
|
||||
#include "name.h"
|
||||
#include "dobjgc.h"
|
||||
|
||||
class FSerializer; // this needs to go away.
|
||||
/*
|
||||
|
@ -49,29 +50,31 @@ CVARS (console variables)
|
|||
|
||||
enum
|
||||
{
|
||||
CVAR_ARCHIVE = 1, // set to cause it to be saved to config.
|
||||
CVAR_USERINFO = 1 << 1, // added to userinfo when changed.
|
||||
CVAR_SERVERINFO = 1 << 2, // added to serverinfo when changed.
|
||||
CVAR_NOSET = 1 << 3, // don't allow change from console at all,
|
||||
// but can be set from the command line.
|
||||
CVAR_LATCH = 1 << 4, // save changes until server restart.
|
||||
CVAR_UNSETTABLE = 1 << 5, // can unset this var from console.
|
||||
CVAR_DEMOSAVE = 1 << 6, // save the value of this cvar in a demo.
|
||||
CVAR_ISDEFAULT = 1 << 7, // is cvar unchanged since creation?
|
||||
CVAR_AUTO = 1 << 8, // allocated; needs to be freed when destroyed.
|
||||
CVAR_NOINITCALL = 1 << 9, // don't call callback at game start.
|
||||
CVAR_GLOBALCONFIG = 1 << 10, // cvar is saved to global config section.
|
||||
CVAR_VIDEOCONFIG = 1 << 11, // cvar is saved to video config section (not implemented).
|
||||
CVAR_NOSAVE = 1 << 12, // when used with CVAR_SERVERINFO, do not save var to savegame
|
||||
// and config.
|
||||
CVAR_MOD = 1 << 13, // cvar was defined by a mod.
|
||||
CVAR_IGNORE = 1 << 14, // do not send cvar across the network/inaccesible from ACS
|
||||
// (dummy mod cvar).
|
||||
CVAR_CHEAT = 1 << 15, // can be set only when sv_cheats is enabled.
|
||||
CVAR_UNSAFECONTEXT = 1 << 16, // cvar value came from unsafe context.
|
||||
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_ARCHIVE = 1, // set to cause it to be saved to config.
|
||||
CVAR_USERINFO = 1 << 1, // added to userinfo when changed.
|
||||
CVAR_SERVERINFO = 1 << 2, // added to serverinfo when changed.
|
||||
CVAR_NOSET = 1 << 3, // don't allow change from console at all,
|
||||
// but can be set from the command line.
|
||||
CVAR_LATCH = 1 << 4, // save changes until server restart.
|
||||
CVAR_UNSETTABLE = 1 << 5, // can unset this var from console.
|
||||
CVAR_DEMOSAVE = 1 << 6, // save the value of this cvar in a demo.
|
||||
CVAR_ISDEFAULT = 1 << 7, // is cvar unchanged since creation?
|
||||
CVAR_AUTO = 1 << 8, // allocated; needs to be freed when destroyed.
|
||||
CVAR_NOINITCALL = 1 << 9, // don't call callback at game start.
|
||||
CVAR_GLOBALCONFIG = 1 << 10, // cvar is saved to global config section.
|
||||
CVAR_VIDEOCONFIG = 1 << 11, // cvar is saved to video config section (not implemented).
|
||||
CVAR_NOSAVE = 1 << 12, // when used with CVAR_SERVERINFO, do not save var to savegame
|
||||
// and config.
|
||||
CVAR_MOD = 1 << 13, // cvar was defined by a mod.
|
||||
CVAR_IGNORE = 1 << 14, // do not send cvar across the network/inaccesible from ACS
|
||||
// (dummy mod cvar).
|
||||
CVAR_CHEAT = 1 << 15, // can be set only when sv_cheats is enabled.
|
||||
CVAR_UNSAFECONTEXT = 1 << 16, // cvar value came from unsafe context.
|
||||
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
|
||||
CVAR_ZS_CUSTOM_CLONE = 1 << 20, // Clone of a Custom ZScript CVar
|
||||
};
|
||||
|
||||
enum ECVarType
|
||||
|
@ -182,12 +185,20 @@ public:
|
|||
virtual UCVarValue GetFavoriteRepDefault (ECVarType *type) const = 0;
|
||||
virtual void SetGenericRepDefault (UCVarValue value, ECVarType type) = 0;
|
||||
|
||||
virtual UCVarValue GenericZSCVarCallback(UCVarValue value, ECVarType type)
|
||||
{ // not valid for cvars that aren't custom zscript cvars, doesn't modify the actual cvar directly, just transforms the value
|
||||
// FZSStringCVar allocates a buffer for the returned string that must be freed by the caller
|
||||
return 0;
|
||||
}
|
||||
|
||||
FBaseCVar &operator= (const FBaseCVar &var)
|
||||
{ UCVarValue val; ECVarType type; val = var.GetFavoriteRep (&type); SetGenericRep (val, type); return *this; }
|
||||
|
||||
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 +220,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 +293,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 +498,76 @@ 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;
|
||||
UCVarValue GenericZSCVarCallback(UCVarValue value, ECVarType type) 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;
|
||||
UCVarValue GenericZSCVarCallback(UCVarValue value, ECVarType type) 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;
|
||||
UCVarValue GenericZSCVarCallback(UCVarValue value, ECVarType type) 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;
|
||||
UCVarValue GenericZSCVarCallback(UCVarValue value, ECVarType type) 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;
|
||||
UCVarValue GenericZSCVarCallback(UCVarValue value, ECVarType type) override;
|
||||
};
|
||||
|
||||
class FBoolCVarRef
|
||||
{
|
||||
FBoolCVar* ref;
|
||||
|
|
|
@ -29,7 +29,7 @@ CVAR(Bool, vid_fps, false, 0)
|
|||
|
||||
EXTERN_CVAR(Bool, ui_generic)
|
||||
|
||||
CUSTOM_CVAR(String, language, "auto", CVAR_ARCHIVE | CVAR_NOINITCALL /* | CVAR_GLOBALCONFIG*/)
|
||||
CUSTOM_CVAR(String, language, "auto", CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG)
|
||||
{
|
||||
GStrings.UpdateLanguage(self);
|
||||
UpdateGenericUI(ui_generic);
|
||||
|
|
|
@ -167,10 +167,12 @@ xx(Insert)
|
|||
xx(InsertNew)
|
||||
xx(Remove)
|
||||
xx(Get)
|
||||
xx(GetIfExists)
|
||||
xx(GetValue)
|
||||
xx(GetKey)
|
||||
xx(SetValue)
|
||||
xx(CheckKey)
|
||||
xx(CheckValue)
|
||||
xx(Value)
|
||||
xx(Copy)
|
||||
xx(Move)
|
||||
|
@ -185,6 +187,8 @@ xx(Exists)
|
|||
xx(SetInvalid)
|
||||
xx(SetNull)
|
||||
xx(Key)
|
||||
xx(Index)
|
||||
xx(Find)
|
||||
|
||||
// color channels
|
||||
xx(a)
|
||||
|
|
|
@ -531,7 +531,7 @@ void PClass::Derive(PClass *newclass, FName name)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
PClass *PClass::CreateDerivedClass(FName name, unsigned int size, bool *newlycreated)
|
||||
PClass *PClass::CreateDerivedClass(FName name, unsigned int size, bool *newlycreated, int fileno)
|
||||
{
|
||||
assert(size >= Size);
|
||||
PClass *type;
|
||||
|
@ -571,7 +571,7 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size, bool *newlycre
|
|||
type->Size = size;
|
||||
if (size != TentativeClass)
|
||||
{
|
||||
NewClassType(type);
|
||||
NewClassType(type, fileno);
|
||||
if (newlycreated) *newlycreated = true;
|
||||
type->Virtuals = Virtuals;
|
||||
}
|
||||
|
@ -591,13 +591,13 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size, bool *newlycre
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
PField *PClass::AddField(FName name, PType *type, uint32_t flags)
|
||||
PField *PClass::AddField(FName name, PType *type, uint32_t flags, int fileno)
|
||||
{
|
||||
PField *field;
|
||||
if (!(flags & VARF_Meta))
|
||||
{
|
||||
unsigned oldsize = Size;
|
||||
field = VMType->Symbols.AddField(name, type, flags, Size);
|
||||
field = VMType->Symbols.AddField(name, type, flags, Size, nullptr, fileno);
|
||||
|
||||
// Only initialize the defaults if they have already been created.
|
||||
// For ZScript this is not the case, it will first define all fields before
|
||||
|
@ -612,7 +612,7 @@ PField *PClass::AddField(FName name, PType *type, uint32_t flags)
|
|||
{
|
||||
// Same as above, but a different data storage.
|
||||
unsigned oldsize = MetaSize;
|
||||
field = VMType->Symbols.AddField(name, type, flags, MetaSize);
|
||||
field = VMType->Symbols.AddField(name, type, flags, MetaSize, nullptr, fileno);
|
||||
|
||||
if (field != nullptr && !(flags & VARF_Native) && Meta != nullptr)
|
||||
{
|
||||
|
|
|
@ -45,7 +45,7 @@ public:
|
|||
bool ReadAllFields(FSerializer &ar, void *addr) const;
|
||||
int FindVirtualIndex(FName name, PFunction::Variant *variant, PFunction *parentfunc, bool exactReturnType);
|
||||
PSymbol *FindSymbol(FName symname, bool searchparents) const;
|
||||
PField *AddField(FName name, PType *type, uint32_t flags);
|
||||
PField *AddField(FName name, PType *type, uint32_t flags, int fileno = 0);
|
||||
void InitializeDefaults();
|
||||
|
||||
static void StaticInit();
|
||||
|
@ -80,7 +80,7 @@ public:
|
|||
~PClass();
|
||||
void InsertIntoHash(bool native);
|
||||
DObject *CreateNew();
|
||||
PClass *CreateDerivedClass(FName name, unsigned int size, bool *newlycreated = nullptr);
|
||||
PClass *CreateDerivedClass(FName name, unsigned int size, bool *newlycreated = nullptr, int fileno = 0);
|
||||
|
||||
void InitializeActorInfo();
|
||||
void BuildFlatPointers();
|
||||
|
|
|
@ -85,6 +85,8 @@
|
|||
// The main window's title.
|
||||
#ifdef _M_X64
|
||||
#define X64 " 64-bit"
|
||||
#elif _M_ARM64
|
||||
#define X64 " ARM-64"
|
||||
#else
|
||||
#define X64 ""
|
||||
#endif
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
#ifdef _M_X64
|
||||
#define X64 " 64-bit"
|
||||
#elif _M_ARM64
|
||||
#define X64 " ARM-64"
|
||||
#else
|
||||
#define X64 ""
|
||||
#endif
|
||||
|
|
|
@ -196,10 +196,12 @@ static void SetCursorState(bool visible)
|
|||
{
|
||||
if (CursorState)
|
||||
{
|
||||
ShowCursor(1);
|
||||
SetCursor((HCURSOR)(intptr_t)GetClassLongPtr(mainwindow.GetHandle(), GCLP_HCURSOR));
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowCursor(0);
|
||||
SetCursor(NULL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,7 +90,7 @@ bool IsPortable()
|
|||
}
|
||||
|
||||
// A portable INI means that this storage location should also be portable if the file can be written to.
|
||||
FStringf path("%s" GAMENAME "_portable.ini", progdir.GetChars());
|
||||
FStringf path("%s" GAMENAMELOWERCASE "_portable.ini", progdir.GetChars());
|
||||
if (FileExists(path))
|
||||
{
|
||||
file = CreateFile(path.WideString().c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
|
|
|
@ -388,6 +388,7 @@ BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa
|
|||
break;
|
||||
#ifdef HAVE_GLES2
|
||||
case 2:
|
||||
case 3:
|
||||
SendDlgItemMessage( hDlg, IDC_WELCOME_VULKAN4, BM_SETCHECK, BST_CHECKED, 0 );
|
||||
break;
|
||||
#endif
|
||||
|
|
|
@ -234,8 +234,7 @@ void GLBuffer::Resize(size_t newsize)
|
|||
|
||||
void GLBuffer::GPUDropSync()
|
||||
{
|
||||
#if !(USE_GLES2) // Only applicable when running on desktop for now
|
||||
if (gles.useMappedBuffers && glFenceSync && glClientWaitSync)
|
||||
if (gles.glesMode > GLES_MODE_GLES && gles.useMappedBuffers && glFenceSync && glDeleteSync)
|
||||
{
|
||||
if (mGLSync != NULL)
|
||||
{
|
||||
|
@ -244,13 +243,11 @@ void GLBuffer::GPUDropSync()
|
|||
|
||||
mGLSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLBuffer::GPUWaitSync()
|
||||
{
|
||||
#if !(USE_GLES2) // Only applicable when running on desktop for now
|
||||
if (gles.useMappedBuffers && glFenceSync && glClientWaitSync)
|
||||
if (gles.glesMode > GLES_MODE_GLES && gles.useMappedBuffers && glDeleteSync && glClientWaitSync)
|
||||
{
|
||||
GLenum status = glClientWaitSync(mGLSync, GL_SYNC_FLUSH_COMMANDS_BIT, 1000 * 1000 * 50); // Wait for a max of 50ms...
|
||||
|
||||
|
@ -263,7 +260,6 @@ void GLBuffer::GPUWaitSync()
|
|||
|
||||
mGLSync = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -318,7 +314,7 @@ void GLVertexBuffer::Bind(int *offsets)
|
|||
glVertexAttribPointer(i, attrinf.size, attrinf.format, attrinf.normalize, (GLsizei)mStride, (void*)(intptr_t)ofs);
|
||||
else
|
||||
{
|
||||
if (gles.gles3Features)
|
||||
if (gles.glesMode >= GLES_MODE_OGL3)
|
||||
glVertexAttribIPointer(i, attrinf.size, attrinf.format, (GLsizei)mStride, (void*)(intptr_t)ofs);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,44 +130,47 @@ unsigned int FHardwareTexture::CreateTexture(unsigned char * buffer, int w, int
|
|||
|
||||
int sourcetype;
|
||||
|
||||
|
||||
#if USE_GLES2
|
||||
if (glTextureBytes == 1)
|
||||
if (gles.glesMode == GLES_MODE_GLES)
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
sourcetype = GL_ALPHA;
|
||||
texformat = GL_ALPHA;
|
||||
if (glTextureBytes == 1)
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
sourcetype = GL_ALPHA;
|
||||
texformat = GL_ALPHA;
|
||||
}
|
||||
else
|
||||
{
|
||||
sourcetype = GL_BGRA; // These two must be the same
|
||||
texformat = GL_BGRA;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sourcetype = GL_BGRA;
|
||||
texformat = GL_BGRA;
|
||||
if (glTextureBytes == 1) //Use Red channel instread becuase Alpha does not work in OpenGL, swizzle later
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
sourcetype = GL_RED;
|
||||
texformat = GL_RED;
|
||||
}
|
||||
else
|
||||
{
|
||||
sourcetype = GL_BGRA;
|
||||
texformat = GL_RGBA;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (glTextureBytes == 1)
|
||||
{
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
sourcetype = GL_RED;
|
||||
texformat = GL_RED;
|
||||
}
|
||||
else
|
||||
{
|
||||
sourcetype = GL_BGRA;
|
||||
texformat = GL_RGBA;
|
||||
}
|
||||
#endif
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, texformat, rw, rh, 0, sourcetype, GL_UNSIGNED_BYTE, buffer);
|
||||
|
||||
#if !(USE_GLES2)
|
||||
// The shader is using the alpha channel instead of red, this work on GLES but not on GL
|
||||
// So the texture uses GL_RED and this swizzels the red channel into the alpha channel
|
||||
if (glTextureBytes == 1)
|
||||
if (gles.glesMode != GLES_MODE_GLES)
|
||||
{
|
||||
GLint swizzleMask[] = { GL_ZERO, GL_ZERO, GL_ZERO, GL_RED };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
// The shader is using the alpha channel instead of red, this work on GLES but not on GL
|
||||
// So the texture uses GL_RED and this swizzels the red channel into the alpha channel
|
||||
if (glTextureBytes == 1)
|
||||
{
|
||||
GLint swizzleMask[] = { GL_ZERO, GL_ZERO, GL_ZERO, GL_RED };
|
||||
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (deletebuffer && buffer) free(buffer);
|
||||
|
||||
|
|
|
@ -346,7 +346,7 @@ bool FGLRenderState::ApplyShader()
|
|||
activeShader->cur->muLightRange.Set(range);
|
||||
}
|
||||
|
||||
if (gles.gles3Features)
|
||||
if (gles.glesMode >= GLES_MODE_OGL3)
|
||||
{
|
||||
// Upload bone data
|
||||
// NOTE, this is pretty inefficient, it will be reloading the same data over and over in a single frame
|
||||
|
|
|
@ -12,50 +12,16 @@ EXTERN_CVAR(Bool, gl_customshader);
|
|||
void setGlVersion(double glv);
|
||||
|
||||
|
||||
#if USE_GLES2
|
||||
#if USE_GLAD_LOADER
|
||||
|
||||
PFNGLMAPBUFFERRANGEEXTPROC glMapBufferRange = NULL;
|
||||
PFNGLUNMAPBUFFEROESPROC glUnmapBuffer = NULL;
|
||||
PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer = NULL;
|
||||
PFNGLFENCESYNCPROC glFenceSync = NULL;
|
||||
PFNGLCLIENTWAITSYNCPROC glClientWaitSync = NULL;
|
||||
PFNGLDELETESYNCPROC glDeleteSync = NULL;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <dlfcn.h>
|
||||
|
||||
static void* LoadGLES2Proc(const char* name)
|
||||
{
|
||||
static void *glesLib = NULL;
|
||||
|
||||
if(!glesLib)
|
||||
{
|
||||
int flags = RTLD_LOCAL | RTLD_NOW;
|
||||
|
||||
glesLib = dlopen("libGLESv2_CM.so", flags);
|
||||
if(!glesLib)
|
||||
{
|
||||
glesLib = dlopen("libGLESv2.so", flags);
|
||||
}
|
||||
if(!glesLib)
|
||||
{
|
||||
glesLib = dlopen("libGLESv2.so.2", flags);
|
||||
}
|
||||
}
|
||||
|
||||
void * ret = NULL;
|
||||
ret = dlsym(glesLib, name);
|
||||
|
||||
if(!ret)
|
||||
{
|
||||
//LOGI("Failed to load: %s", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
//LOGI("Loaded %s func OK", name);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#elif defined _WIN32
|
||||
#if defined _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
@ -80,9 +46,38 @@ static void* LoadGLES2Proc(const char* name)
|
|||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
static void* LoadGLES2Proc(const char* name)
|
||||
{
|
||||
static void* glesLib = NULL;
|
||||
|
||||
if (!glesLib)
|
||||
{
|
||||
int flags = RTLD_LOCAL | RTLD_NOW;
|
||||
|
||||
glesLib = dlopen("libGLESv2_CM.so", flags);
|
||||
if (!glesLib)
|
||||
{
|
||||
glesLib = dlopen("libGLESv2.so", flags);
|
||||
}
|
||||
if (!glesLib)
|
||||
{
|
||||
glesLib = dlopen("libGLESv2.so.2", flags);
|
||||
}
|
||||
}
|
||||
|
||||
void* ret = NULL;
|
||||
ret = dlsym(glesLib, name);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif // USE_GLES2
|
||||
#endif // USE_GLAD_LOADER
|
||||
|
||||
static TArray<FString> m_Extensions;
|
||||
|
||||
|
@ -126,7 +121,7 @@ namespace OpenGLESRenderer
|
|||
void InitGLES()
|
||||
{
|
||||
|
||||
#if USE_GLES2
|
||||
#if USE_GLAD_LOADER
|
||||
|
||||
if (!gladLoadGLES2Loader(&LoadGLES2Proc))
|
||||
{
|
||||
|
@ -136,6 +131,10 @@ namespace OpenGLESRenderer
|
|||
glMapBufferRange = (PFNGLMAPBUFFERRANGEEXTPROC)LoadGLES2Proc("glMapBufferRange");
|
||||
glUnmapBuffer = (PFNGLUNMAPBUFFEROESPROC)LoadGLES2Proc("glUnmapBuffer");
|
||||
glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC)LoadGLES2Proc("glVertexAttribIPointer");
|
||||
|
||||
glFenceSync = (PFNGLFENCESYNCPROC)LoadGLES2Proc("glFenceSync");
|
||||
glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC)LoadGLES2Proc("glClientWaitSync");
|
||||
glDeleteSync = (PFNGLDELETESYNCPROC)LoadGLES2Proc("glDeleteSync");
|
||||
#else
|
||||
static bool first = true;
|
||||
|
||||
|
@ -161,48 +160,78 @@ namespace OpenGLESRenderer
|
|||
{
|
||||
Printf(" %s\n", m_Extensions[i].GetChars());
|
||||
}
|
||||
const char* glVersionStr = (const char*)glGetString(GL_VERSION);
|
||||
double glVersion = strtod(glVersionStr, NULL);
|
||||
|
||||
Printf("GL Version parsed = %f\n", glVersion);
|
||||
|
||||
gles.flags = RFL_NO_CLIP_PLANES;
|
||||
|
||||
gles.useMappedBuffers = gles_use_mapped_buffer;
|
||||
gles.forceGLSLv100 = gles_force_glsl_v100;
|
||||
gles.maxlights = gles_max_lights_per_surface;
|
||||
gles.numlightvectors = (gles.maxlights * LIGHT_VEC4_NUM);
|
||||
|
||||
gles.modelstring = (char*)glGetString(GL_RENDERER);
|
||||
gles.vendorstring = (char*)glGetString(GL_VENDOR);
|
||||
|
||||
gl_customshader = false;
|
||||
|
||||
gl_customshader = false; // Disable user shaders for GLES renderer
|
||||
|
||||
GLint maxTextureSize[1];
|
||||
glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxTextureSize);
|
||||
|
||||
gles.max_texturesize = maxTextureSize[0];
|
||||
|
||||
Printf("GL_MAX_TEXTURE_SIZE: %d\n", gles.max_texturesize);
|
||||
|
||||
#if USE_GLES2
|
||||
gles.gles3Features = false; // Enales IQM bones
|
||||
gles.shaderVersionString = "100";
|
||||
|
||||
gles.depthStencilAvailable = CheckExtension("GL_OES_packed_depth_stencil");
|
||||
gles.npotAvailable = CheckExtension("GL_OES_texture_npot");
|
||||
gles.depthClampAvailable = CheckExtension("GL_EXT_depth_clamp");
|
||||
gles.anistropicFilterAvailable = CheckExtension("GL_EXT_texture_filter_anisotropic");
|
||||
#else
|
||||
gles.gles3Features = true;
|
||||
gles.shaderVersionString = "330";
|
||||
gles.depthStencilAvailable = true;
|
||||
gles.npotAvailable = true;
|
||||
gles.useMappedBuffers = true;
|
||||
gles.depthClampAvailable = true;
|
||||
gles.anistropicFilterAvailable = true;
|
||||
#endif
|
||||
// Check if running on a GLES device, version string will start with 'OpenGL ES'
|
||||
if (!strncmp(glVersionStr, "OpenGL ES", strlen("OpenGL ES")))
|
||||
{
|
||||
gles.glesMode = GLES_MODE_GLES;
|
||||
}
|
||||
else // Else runnning on Desktop, check OpenGL version is 3 or above
|
||||
{
|
||||
if (glVersion > 3.29)
|
||||
gles.glesMode = GLES_MODE_OGL3; // 3.3 or above
|
||||
else
|
||||
gles.glesMode = GLES_MODE_OGL2; // Below 3.3
|
||||
}
|
||||
|
||||
gles.numlightvectors = (gles.maxlights * LIGHT_VEC4_NUM);
|
||||
|
||||
const char* glversion = (const char*)glGetString(GL_VERSION);
|
||||
setGlVersion( strtod(glversion, NULL));
|
||||
if (gles.glesMode == GLES_MODE_GLES)
|
||||
{
|
||||
Printf("GLES choosing mode: GLES_MODE_GLES\n");
|
||||
|
||||
gles.shaderVersionString = "100";
|
||||
gles.depthStencilAvailable = CheckExtension("GL_OES_packed_depth_stencil");
|
||||
gles.npotAvailable = CheckExtension("GL_OES_texture_npot");
|
||||
gles.depthClampAvailable = CheckExtension("GL_EXT_depth_clamp");
|
||||
gles.anistropicFilterAvailable = CheckExtension("GL_EXT_texture_filter_anisotropic");
|
||||
}
|
||||
else if (gles.glesMode == GLES_MODE_OGL2)
|
||||
{
|
||||
Printf("GLES choosing mode: GLES_MODE_OGL2\n");
|
||||
|
||||
gles.shaderVersionString = "100";
|
||||
gles.depthStencilAvailable = true;
|
||||
gles.npotAvailable = true;
|
||||
gles.useMappedBuffers = true;
|
||||
gles.depthClampAvailable = true;
|
||||
gles.anistropicFilterAvailable = true;
|
||||
}
|
||||
else if (gles.glesMode == GLES_MODE_OGL3)
|
||||
{
|
||||
Printf("GLES choosing mode: GLES_MODE_OGL3\n");
|
||||
|
||||
gles.shaderVersionString = "330";
|
||||
gles.depthStencilAvailable = true;
|
||||
gles.npotAvailable = true;
|
||||
gles.useMappedBuffers = true;
|
||||
gles.depthClampAvailable = true;
|
||||
gles.anistropicFilterAvailable = true;
|
||||
}
|
||||
|
||||
setGlVersion(glVersion);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,32 +23,47 @@
|
|||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define USE_GLES2 0 // For Desktop PC leave as 0, it will use the exisiting OpenGL context creationg code but run with the GLES2 renderer
|
||||
// Set to 1 for when comipling for a real GLES device
|
||||
#define USE_GLAD_LOADER 0 // Set to 1 to use the GLAD loader, otherwise use noramal GZDoom loader for PC
|
||||
|
||||
#if (USE_GLES2)
|
||||
#if (USE_GLAD_LOADER)
|
||||
#include "glad/glad.h"
|
||||
|
||||
// Below are used extensions for GLES
|
||||
typedef void* (APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
|
||||
GLAPI PFNGLMAPBUFFERRANGEEXTPROC glMapBufferRange;
|
||||
// Below are used extensions for GLES
|
||||
typedef void* (APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
|
||||
GLAPI PFNGLMAPBUFFERRANGEEXTPROC glMapBufferRange;
|
||||
|
||||
typedef GLboolean(APIENTRYP PFNGLUNMAPBUFFEROESPROC)(GLenum target);
|
||||
GLAPI PFNGLUNMAPBUFFEROESPROC glUnmapBuffer;
|
||||
typedef GLboolean(APIENTRYP PFNGLUNMAPBUFFEROESPROC)(GLenum target);
|
||||
GLAPI PFNGLUNMAPBUFFEROESPROC glUnmapBuffer;
|
||||
|
||||
typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer);
|
||||
GLAPI PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
|
||||
typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const void* pointer);
|
||||
GLAPI PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
|
||||
|
||||
typedef GLsync(APIENTRYP PFNGLFENCESYNCPROC)(GLenum condition, GLbitfield flags);
|
||||
GLAPI PFNGLFENCESYNCPROC glFenceSync;
|
||||
|
||||
typedef GLenum(APIENTRYP PFNGLCLIENTWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout);
|
||||
GLAPI PFNGLCLIENTWAITSYNCPROC glClientWaitSync;
|
||||
|
||||
typedef void (APIENTRYP PFNGLDELETESYNCPROC)(GLsync sync);
|
||||
GLAPI PFNGLDELETESYNCPROC glDeleteSync;
|
||||
|
||||
#define GL_DEPTH24_STENCIL8 0x88F0
|
||||
#define GL_MAP_PERSISTENT_BIT 0x0040
|
||||
#define GL_MAP_READ_BIT 0x0001
|
||||
#define GL_MAP_WRITE_BIT 0x0002
|
||||
#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
|
||||
#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
|
||||
#define GL_BGRA 0x80E1
|
||||
#define GL_DEPTH_CLAMP 0x864F
|
||||
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
|
||||
#define GL_INT_2_10_10_10_REV 0x8D9F
|
||||
#define GL_RED 0x1903
|
||||
#define GL_TEXTURE_SWIZZLE_RGBA 0x8E46
|
||||
#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
|
||||
#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
|
||||
#define GL_ALREADY_SIGNALED 0x911A
|
||||
#define GL_CONDITION_SATISFIED 0x911C
|
||||
|
||||
#define GL_DEPTH24_STENCIL8 0x88F0
|
||||
#define GL_MAP_PERSISTENT_BIT 0x0040
|
||||
#define GL_MAP_READ_BIT 0x0001
|
||||
#define GL_MAP_WRITE_BIT 0x0002
|
||||
#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020
|
||||
#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008
|
||||
#define GL_BGRA 0x80E1
|
||||
#define GL_DEPTH_CLAMP 0x864F
|
||||
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
|
||||
#define GL_INT_2_10_10_10_REV 0x8D9F
|
||||
#else
|
||||
#include "gl_load/gl_load.h"
|
||||
#endif
|
||||
|
@ -66,6 +81,13 @@ GLAPI PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
|
|||
|
||||
namespace OpenGLESRenderer
|
||||
{
|
||||
enum
|
||||
{
|
||||
GLES_MODE_GLES = 0,
|
||||
GLES_MODE_OGL2 = 1,
|
||||
GLES_MODE_OGL3 = 2,
|
||||
};
|
||||
|
||||
struct RenderContextGLES
|
||||
{
|
||||
unsigned int flags;
|
||||
|
@ -77,7 +99,7 @@ namespace OpenGLESRenderer
|
|||
bool forceGLSLv100;
|
||||
bool depthClampAvailable;
|
||||
bool anistropicFilterAvailable;
|
||||
bool gles3Features;
|
||||
int glesMode;
|
||||
const char* shaderVersionString;
|
||||
int max_texturesize;
|
||||
char* vendorstring;
|
||||
|
|
|
@ -96,6 +96,7 @@ void HWViewpointBuffer::Set2D(FRenderState &di, int width, int height, int pll)
|
|||
matrices.mProjectionMatrix.ortho(0, (float)width, (float)height, 0, -1.0f, 1.0f);
|
||||
matrices.CalcDependencies();
|
||||
|
||||
CheckSize();
|
||||
mBuffer->Map();
|
||||
memcpy(((char*)mBuffer->Memory()) + mUploadIndex * mBlockAlign, &matrices, sizeof(matrices));
|
||||
mBuffer->Unmap();
|
||||
|
@ -125,6 +126,8 @@ void HWViewpointBuffer::Clear()
|
|||
|
||||
if (needNewPipeline)
|
||||
{
|
||||
mLastMappedIndex = UINT_MAX;
|
||||
|
||||
mPipelinePos++;
|
||||
mPipelinePos %= mPipelineNbr;
|
||||
}
|
||||
|
|
|
@ -177,12 +177,9 @@ void FCompileContext::CheckReturn(PPrototype *proto, FScriptPosition &pos)
|
|||
}
|
||||
}
|
||||
|
||||
// [ZZ] I find it really dumb that something called CheckReadOnly returns false for readonly. renamed.
|
||||
bool FCompileContext::CheckWritable(int flags)
|
||||
bool FCompileContext::IsWritable(int flags, int checkFileNo)
|
||||
{
|
||||
if (!(flags & VARF_ReadOnly)) return false;
|
||||
if (!(flags & VARF_InternalAccess)) return true;
|
||||
return fileSystem.GetFileContainer(Lump) != 0;
|
||||
return !(flags & VARF_ReadOnly) || ((flags & VARF_InternalAccess) && fileSystem.GetFileContainer(Lump) == checkFileNo);
|
||||
}
|
||||
|
||||
FxLocalVariableDeclaration *FCompileContext::FindLocalVariable(FName name)
|
||||
|
@ -277,6 +274,14 @@ bool AreCompatiblePointerTypes(PType *dest, PType *source, bool forcompare)
|
|||
{
|
||||
auto fromtype = source->toPointer();
|
||||
auto totype = dest->toPointer();
|
||||
// implicit pointer casts
|
||||
if( fromtype->isClassPointer() && !totype->isClassPointer() ) totype->toClassPointer(fromtype); // just to make sure they're compatible pointer types
|
||||
else if( !fromtype->isClassPointer() && totype->isClassPointer() ) fromtype->toClassPointer(totype); // just to make sure they're compatible pointer types
|
||||
else if( fromtype->PointedType != totype->PointedType )
|
||||
{
|
||||
auto res = fromtype->PointedType->toClass(totype->PointedType);
|
||||
if(!res || res != totype->PointedType) return false;
|
||||
}
|
||||
// null pointers can be assigned to everything, everything can be assigned to void pointers.
|
||||
if (fromtype == nullptr || totype == TypeVoidPtr) return true;
|
||||
// when comparing const-ness does not matter.
|
||||
|
@ -6730,7 +6735,7 @@ FxExpression *FxLocalVariable::Resolve(FCompileContext &ctx)
|
|||
bool FxLocalVariable::RequestAddress(FCompileContext &ctx, bool *writable)
|
||||
{
|
||||
AddressRequested = true;
|
||||
if (writable != nullptr) *writable = !ctx.CheckWritable(Variable->VarFlags);
|
||||
if (writable != nullptr) *writable = ctx.IsWritable(Variable->VarFlags);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -6885,7 +6890,7 @@ FxGlobalVariable::FxGlobalVariable(PField* mem, const FScriptPosition &pos)
|
|||
bool FxGlobalVariable::RequestAddress(FCompileContext &ctx, bool *writable)
|
||||
{
|
||||
AddressRequested = true;
|
||||
if (writable != nullptr) *writable = AddressWritable && !ctx.CheckWritable(membervar->Flags);
|
||||
if (writable != nullptr) *writable = AddressWritable && ctx.IsWritable(membervar->Flags, membervar->mDefFileNo);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -7078,7 +7083,7 @@ FxStackVariable::~FxStackVariable()
|
|||
bool FxStackVariable::RequestAddress(FCompileContext &ctx, bool *writable)
|
||||
{
|
||||
AddressRequested = true;
|
||||
if (writable != nullptr) *writable = AddressWritable && !ctx.CheckWritable(membervar->Flags);
|
||||
if (writable != nullptr) *writable = AddressWritable && ctx.IsWritable(membervar->Flags, membervar->mDefFileNo);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -7180,7 +7185,7 @@ bool FxStructMember::RequestAddress(FCompileContext &ctx, bool *writable)
|
|||
else if (writable != nullptr)
|
||||
{
|
||||
// [ZZ] original check.
|
||||
bool bWritable = (AddressWritable && !ctx.CheckWritable(membervar->Flags) &&
|
||||
bool bWritable = (AddressWritable && ctx.IsWritable(membervar->Flags, membervar->mDefFileNo) &&
|
||||
(!classx->ValueType->isPointer() || !classx->ValueType->toPointer()->IsConst));
|
||||
// [ZZ] implement write barrier between different scopes
|
||||
if (bWritable)
|
||||
|
@ -8508,6 +8513,11 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
|
|||
}
|
||||
else
|
||||
{
|
||||
if (PFunction **Override; ctx.Version >= MakeVersion(4, 11, 0) && (Override = static_cast<PDynArray*>(Self->ValueType)->FnOverrides.CheckKey(MethodName)))
|
||||
{
|
||||
afd_override = *Override;
|
||||
}
|
||||
|
||||
auto elementType = static_cast<PDynArray*>(Self->ValueType)->ElementType;
|
||||
Self->ValueType = static_cast<PDynArray*>(Self->ValueType)->BackingType;
|
||||
bool isDynArrayObj = elementType->isObjectPointer();
|
||||
|
|
|
@ -101,7 +101,7 @@ struct FCompileContext
|
|||
|
||||
void HandleJumps(int token, FxExpression *handler);
|
||||
void CheckReturn(PPrototype *proto, FScriptPosition &pos);
|
||||
bool CheckWritable(int flags);
|
||||
bool IsWritable(int flags, int checkFileNo = 0);
|
||||
FxLocalVariableDeclaration *FindLocalVariable(FName name);
|
||||
};
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ template<typename T>
|
|||
using expand_types_vm =
|
||||
std::conditional_t<std::is_same_v<T, uint8_t> || std::is_same_v<T, uint16_t>, uint32_t , /* expand 8/16-bit to 32-bit */
|
||||
std::conditional_t<std::is_same_v<T, float> , double , /* expand float to double */
|
||||
std::conditional_t<std::is_same_v<T, FString> , const FString & , T>>>; /* change String to String ref */
|
||||
std::conditional_t<std::is_same_v<T, FString> , const FString & , T>>>; /* change String to String ref */
|
||||
|
||||
template<typename M> unsigned int MapCountUsed(M * self)
|
||||
{
|
||||
|
@ -118,13 +118,22 @@ template<typename M> unsigned int MapCountUsed(M * self)
|
|||
template<typename M> expand_types_vm<typename M::ValueType> MapGet(M * self,expand_types_vm<typename M::KeyType> key)
|
||||
{
|
||||
typename M::ValueType * v = self->CheckKey(key);
|
||||
if (v) {
|
||||
return *v;
|
||||
if (v)
|
||||
{
|
||||
if constexpr(std::is_same_v<typename M::ValueType, DObject*>)
|
||||
{
|
||||
return GC::ReadBarrier(*v);
|
||||
}
|
||||
else
|
||||
{
|
||||
return *v;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
typename M::ValueType n {};
|
||||
self->Insert(key,n);
|
||||
self->info->rev++; // invalidate iterators
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
@ -139,6 +148,38 @@ template<typename M> void MapGetString(M * self,expand_types_vm<typename M::KeyT
|
|||
{
|
||||
out = FString();
|
||||
self->Insert(key,out);
|
||||
self->info->rev++; // invalidate iterators
|
||||
}
|
||||
}
|
||||
|
||||
template<typename M> expand_types_vm<typename M::ValueType> MapGetIfExists(M * self,expand_types_vm<typename M::KeyType> key)
|
||||
{
|
||||
typename M::ValueType * v = self->CheckKey(key);
|
||||
if (v) {
|
||||
if constexpr(std::is_same_v<typename M::ValueType, DObject*>)
|
||||
{
|
||||
return GC::ReadBarrier(*v);
|
||||
}
|
||||
else
|
||||
{
|
||||
return *v;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
template<typename M> void MapGetIfExistsString(M * self,expand_types_vm<typename M::KeyType> key, FString &out)
|
||||
{
|
||||
FString * v = self->CheckKey(key);
|
||||
if (v) {
|
||||
out = *v;
|
||||
}
|
||||
else
|
||||
{
|
||||
out = FString();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -147,6 +188,37 @@ template<typename M> int MapCheckKey(M * self, expand_types_vm<typename M::KeyTy
|
|||
return self->CheckKey(key) != nullptr;
|
||||
}
|
||||
|
||||
template<typename M> expand_types_vm<typename M::ValueType> MapCheckValue(M * self,expand_types_vm<typename M::KeyType> key, int &exists)
|
||||
{
|
||||
typename M::ValueType * v = self->CheckKey(key);
|
||||
if ((exists = !!v)) {
|
||||
if constexpr(std::is_same_v<typename M::ValueType, DObject*>)
|
||||
{
|
||||
return GC::ReadBarrier(*v);
|
||||
}
|
||||
else
|
||||
{
|
||||
return *v;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
template<typename M> void MapCheckValueString(M * self,expand_types_vm<typename M::KeyType> key, FString &out, int &exists)
|
||||
{
|
||||
FString * v = self->CheckKey(key);
|
||||
if ((exists = !!v)) {
|
||||
out = *v;
|
||||
}
|
||||
else
|
||||
{
|
||||
out = FString();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
@ -238,7 +310,14 @@ template<typename I> void MapIteratorGetKeyString(I * self, FString &out)
|
|||
|
||||
template<typename I> expand_types_vm<typename I::ValueType> MapIteratorGetValue(I * self)
|
||||
{
|
||||
return self->GetValue();
|
||||
if constexpr(std::is_same_v<typename I::ValueType, DObject*>)
|
||||
{
|
||||
return GC::ReadBarrier(self->GetValue());
|
||||
}
|
||||
else
|
||||
{
|
||||
return self->GetValue();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename I> void MapIteratorGetValueString(I * self, FString &out)
|
||||
|
@ -272,6 +351,25 @@ template<typename I> void MapIteratorSetValue(I * self, expand_types_vm<typename
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
template<int N, typename T, typename U> void SetValType(T & ret,U & val){
|
||||
if constexpr(std::is_same_v<U, DObject*>)
|
||||
{
|
||||
ret[N].SetObject(val);
|
||||
}
|
||||
else if constexpr(std::is_same_v<U, void*>)
|
||||
{
|
||||
ret[N].SetPointer(val);
|
||||
}
|
||||
else if constexpr(std::is_same_v<U, uint32_t>)
|
||||
{
|
||||
ret[N].SetInt(val);
|
||||
}
|
||||
else if constexpr(std::is_same_v<U, double>)
|
||||
{
|
||||
ret[N].SetFloat(val);
|
||||
}
|
||||
}
|
||||
|
||||
#define PARAM_VOIDPOINTER(X) PARAM_POINTER( X , void )
|
||||
#define PARAM_OBJPOINTER(X) PARAM_OBJECT( X , DObject )
|
||||
|
||||
|
@ -345,6 +443,23 @@ template<typename I> void MapIteratorSetValue(I * self, expand_types_vm<typename
|
|||
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||
PARAM_KEY( key ); \
|
||||
ACTION_RETURN_VALUE( MapGet(self, key) ); \
|
||||
} \
|
||||
DEFINE_ACTION_FUNCTION_NATIVE( name, GetIfExists, MapGetIfExists< name >) \
|
||||
{ \
|
||||
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||
PARAM_KEY( key ); \
|
||||
ACTION_RETURN_VALUE( MapGetIfExists(self, key) ); \
|
||||
} \
|
||||
DEFINE_ACTION_FUNCTION_NATIVE( name, CheckValue, MapCheckValue< name >) \
|
||||
{ \
|
||||
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||
PARAM_KEY( key ); \
|
||||
int exists; \
|
||||
expand_types_vm<value_type> out; \
|
||||
out = MapCheckValue(self, key, exists); \
|
||||
if (numret > 1) ret[1].SetInt(exists); \
|
||||
if (numret > 0) SetValType<0>(ret, out); \
|
||||
return numret; \
|
||||
}
|
||||
|
||||
#define DEF_MAP_X_S( name, key_type, PARAM_KEY ) \
|
||||
|
@ -356,6 +471,25 @@ template<typename I> void MapIteratorSetValue(I * self, expand_types_vm<typename
|
|||
FString out; \
|
||||
MapGetString(self, key, out); \
|
||||
ACTION_RETURN_STRING( out ); \
|
||||
} \
|
||||
DEFINE_ACTION_FUNCTION_NATIVE( name, GetIfExists, MapGetIfExistsString< name >) \
|
||||
{ \
|
||||
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||
PARAM_KEY( key ); \
|
||||
FString out; \
|
||||
MapGetIfExistsString(self, key, out); \
|
||||
ACTION_RETURN_STRING( out ); \
|
||||
} \
|
||||
DEFINE_ACTION_FUNCTION_NATIVE( name, CheckValue, MapCheckValueString< name >) \
|
||||
{ \
|
||||
PARAM_SELF_STRUCT_PROLOGUE( name ); \
|
||||
PARAM_KEY( key ); \
|
||||
int exists; \
|
||||
FString out; \
|
||||
MapCheckValueString(self, key, out, exists); \
|
||||
if (numret > 1) ret[1].SetInt(exists); \
|
||||
if (numret > 0) ret[0].SetString(out); \
|
||||
return numret; \
|
||||
}
|
||||
|
||||
#define COMMA ,
|
||||
|
|
|
@ -211,6 +211,7 @@ void FScopeBarrier::AddFlags(int flags1, int flags2, const char* name)
|
|||
// these are for vmexec.h
|
||||
void FScopeBarrier::ValidateNew(PClass* cls, int outerside)
|
||||
{
|
||||
if (cls->VMType == nullptr) ThrowAbortException(X_OTHER,"Cannot instantiate invalid class %s", cls->TypeName.GetChars());
|
||||
int innerside = FScopeBarrier::SideFromObjectFlags(cls->VMType->ScopeFlags);
|
||||
if ((outerside != innerside) && (innerside != FScopeBarrier::Side_PlainData)) // "cannot construct ui class ... from data context"
|
||||
ThrowAbortException(X_OTHER, "Cannot construct %s class %s from %s context", FScopeBarrier::StringFromSide(innerside), cls->TypeName.GetChars(), FScopeBarrier::StringFromSide(outerside));
|
||||
|
|
|
@ -137,7 +137,6 @@ PField::PField()
|
|||
{
|
||||
}
|
||||
|
||||
|
||||
PField::PField(FName name, PType *type, uint32_t flags, size_t offset, int bitvalue)
|
||||
: PSymbol(name), Offset(offset), Type(type), Flags(flags)
|
||||
{
|
||||
|
@ -331,10 +330,12 @@ PSymbol *PSymbolTable::AddSymbol (PSymbol *sym)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
PField *PSymbolTable::AddField(FName name, PType *type, uint32_t flags, unsigned &Size, unsigned *Align)
|
||||
PField *PSymbolTable::AddField(FName name, PType *type, uint32_t flags, unsigned &Size, unsigned *Align, int fileno)
|
||||
{
|
||||
PField *field = Create<PField>(name, type, flags);
|
||||
|
||||
field->mDefFileNo = fileno;
|
||||
|
||||
// The new field is added to the end of this struct, alignment permitting.
|
||||
field->Offset = (Size + (type->Align - 1)) & ~(type->Align - 1);
|
||||
|
||||
|
@ -365,10 +366,12 @@ PField *PSymbolTable::AddField(FName name, PType *type, uint32_t flags, unsigned
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
PField *PSymbolTable::AddNativeField(FName name, PType *type, size_t address, uint32_t flags, int bitvalue)
|
||||
PField *PSymbolTable::AddNativeField(FName name, PType *type, size_t address, uint32_t flags, int bitvalue, int fileno)
|
||||
{
|
||||
PField *field = Create<PField>(name, type, flags | VARF_Native | VARF_Transient, address, bitvalue);
|
||||
|
||||
field->mDefFileNo = fileno;
|
||||
|
||||
if (AddSymbol(field) == nullptr)
|
||||
{ // name is already in use
|
||||
field->Destroy();
|
||||
|
|
|
@ -78,6 +78,7 @@ public:
|
|||
uint32_t Flags;
|
||||
int BitValue;
|
||||
FString DeprecationMessage;
|
||||
int mDefFileNo = 0;
|
||||
protected:
|
||||
PField();
|
||||
};
|
||||
|
@ -212,8 +213,8 @@ struct PSymbolTable
|
|||
// a symbol with the same name is already in the table. This symbol is
|
||||
// not copied and will be freed when the symbol table is destroyed.
|
||||
PSymbol *AddSymbol (PSymbol *sym);
|
||||
PField *AddField(FName name, PType *type, uint32_t flags, unsigned &Size, unsigned *Align = nullptr);
|
||||
PField *AddNativeField(FName name, PType *type, size_t address, uint32_t flags, int bitvalue);
|
||||
PField *AddField(FName name, PType *type, uint32_t flags, unsigned &Size, unsigned *Align = nullptr, int fileno = 0);
|
||||
PField *AddNativeField(FName name, PType *type, size_t address, uint32_t flags, int bitvalue, int fileno = 0);
|
||||
bool ReadFields(FSerializer &ar, void *addr, const char *TypeName) const;
|
||||
void WriteFields(FSerializer &ar, const void *addr, const void *def = nullptr) const;
|
||||
|
||||
|
|
|
@ -1985,12 +1985,114 @@ PStaticArray *NewStaticArray(PType *type)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
enum OverrideFunctionRetType {
|
||||
OFN_RET_VOID,
|
||||
OFN_RET_VAL,
|
||||
OFN_RET_KEY,
|
||||
OFN_RET_BOOL,
|
||||
OFN_RET_VAL_BOOL,
|
||||
OFN_RET_INT,
|
||||
};
|
||||
enum OverrideFunctionArgType {
|
||||
OFN_ARG_VOID,
|
||||
OFN_ARG_KEY,
|
||||
OFN_ARG_VAL,
|
||||
OFN_ARG_KEY_VAL,
|
||||
OFN_ARG_ELEM,
|
||||
OFN_ARG_INT_ELEM,
|
||||
};
|
||||
|
||||
template<OverrideFunctionRetType RetType, OverrideFunctionArgType ArgType , int ExtraFlags = 0, class MT>
|
||||
void CreateOverrideFunction(MT *self, FName name)
|
||||
{
|
||||
auto Fn = Create<PFunction>(self->BackingType, name);
|
||||
auto NativeFn = FindFunction(self->BackingType, name.GetChars());
|
||||
|
||||
assert(NativeFn);
|
||||
assert(NativeFn->VMPointer);
|
||||
|
||||
TArray<PType*> ret;
|
||||
TArray<PType*> args;
|
||||
TArray<uint32_t> argflags;
|
||||
TArray<FName> argnames;
|
||||
|
||||
if constexpr(RetType == OFN_RET_VAL)
|
||||
{
|
||||
ret.Push(self->ValueType);
|
||||
}
|
||||
else if constexpr(RetType == OFN_RET_KEY)
|
||||
{
|
||||
ret.Push(self->KeyType);
|
||||
}
|
||||
else if constexpr(RetType == OFN_RET_BOOL)
|
||||
{
|
||||
ret.Push(TypeBool);
|
||||
}
|
||||
else if constexpr(RetType == OFN_RET_VAL_BOOL)
|
||||
{
|
||||
ret.Push(self->ValueType);
|
||||
ret.Push(TypeBool);
|
||||
}
|
||||
else if constexpr(RetType == OFN_RET_INT)
|
||||
{
|
||||
ret.Push(TypeSInt32);
|
||||
}
|
||||
|
||||
args.Push(NewPointer(self->BackingType));
|
||||
argnames.Push(NAME_self);
|
||||
argflags.Push(VARF_Implicit | VARF_ReadOnly);
|
||||
|
||||
if constexpr(ArgType == OFN_ARG_KEY)
|
||||
{
|
||||
args.Push(self->KeyType);
|
||||
argflags.Push(0);
|
||||
argnames.Push(NAME_Key);
|
||||
}
|
||||
else if constexpr(ArgType == OFN_ARG_VAL)
|
||||
{
|
||||
|
||||
args.Push(self->ValueType);
|
||||
argflags.Push(0);
|
||||
argnames.Push(NAME_Value);
|
||||
}
|
||||
else if constexpr(ArgType == OFN_ARG_KEY_VAL)
|
||||
{
|
||||
args.Push(self->KeyType);
|
||||
args.Push(self->ValueType);
|
||||
argflags.Push(0);
|
||||
argflags.Push(0);
|
||||
argnames.Push(NAME_Key);
|
||||
argnames.Push(NAME_Value);
|
||||
}
|
||||
else if constexpr(ArgType == OFN_ARG_ELEM)
|
||||
{
|
||||
args.Push(self->ElementType);
|
||||
argflags.Push(0);
|
||||
argnames.Push(NAME_Item);
|
||||
}
|
||||
else if constexpr(ArgType == OFN_ARG_INT_ELEM)
|
||||
{
|
||||
args.Push(TypeSInt32);
|
||||
args.Push(self->ElementType);
|
||||
argflags.Push(0);
|
||||
argflags.Push(0);
|
||||
argnames.Push(NAME_Index);
|
||||
argnames.Push(NAME_Item);
|
||||
}
|
||||
|
||||
Fn->AddVariant(NewPrototype(ret, args), argflags, argnames, *NativeFn->VMPointer, VARF_Method | VARF_Native | ExtraFlags, SUF_ACTOR | SUF_OVERLAY | SUF_WEAPON | SUF_ITEM);
|
||||
self->FnOverrides.Insert(name, Fn);
|
||||
}
|
||||
|
||||
PDynArray::PDynArray(PType *etype,PStruct *backing)
|
||||
: ElementType(etype), BackingType(backing)
|
||||
{
|
||||
mDescriptiveName.Format("DynArray<%s>", etype->DescriptiveName());
|
||||
Size = sizeof(FArray);
|
||||
Align = alignof(FArray);
|
||||
CreateOverrideFunction<OFN_RET_INT , OFN_ARG_ELEM , VARF_ReadOnly> (this, NAME_Find);
|
||||
CreateOverrideFunction<OFN_RET_INT , OFN_ARG_ELEM > (this, NAME_Push);
|
||||
CreateOverrideFunction<OFN_RET_VOID , OFN_ARG_INT_ELEM > (this, NAME_Insert);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -2226,89 +2328,19 @@ PDynArray *NewDynArray(PType *type)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
enum OverrideFunctionRetType {
|
||||
OFN_RET_VOID,
|
||||
OFN_RET_VAL,
|
||||
OFN_RET_KEY,
|
||||
OFN_RET_BOOL,
|
||||
};
|
||||
enum OverrideFunctionArgType {
|
||||
OFN_ARG_VOID,
|
||||
OFN_ARG_KEY,
|
||||
OFN_ARG_VAL,
|
||||
OFN_ARG_KEY_VAL,
|
||||
};
|
||||
|
||||
template<class MT, OverrideFunctionRetType RetType, OverrideFunctionArgType ArgType >
|
||||
void CreateOverrideFunction(MT *self, FName name)
|
||||
{
|
||||
auto Fn = Create<PFunction>(self->BackingType, name);
|
||||
auto NativeFn = FindFunction(self->BackingType, name.GetChars());
|
||||
|
||||
assert(NativeFn);
|
||||
assert(NativeFn->VMPointer);
|
||||
|
||||
|
||||
TArray<PType*> ret;
|
||||
TArray<PType*> args;
|
||||
TArray<uint32_t> argflags;
|
||||
TArray<FName> argnames;
|
||||
|
||||
if constexpr(RetType == OFN_RET_VAL)
|
||||
{
|
||||
ret.Push(self->ValueType);
|
||||
}
|
||||
else if constexpr(RetType == OFN_RET_KEY)
|
||||
{
|
||||
ret.Push(self->KeyType);
|
||||
}
|
||||
else if constexpr(RetType == OFN_RET_BOOL)
|
||||
{
|
||||
ret.Push(TypeBool);
|
||||
}
|
||||
|
||||
args.Push(NewPointer(self->BackingType));
|
||||
argnames.Push(NAME_self);
|
||||
argflags.Push(VARF_Implicit | VARF_ReadOnly);
|
||||
|
||||
if constexpr(ArgType == OFN_ARG_KEY)
|
||||
{
|
||||
args.Push(self->KeyType);
|
||||
argflags.Push(0);
|
||||
argnames.Push(NAME_Key);
|
||||
}
|
||||
else if constexpr(ArgType == OFN_ARG_VAL)
|
||||
{
|
||||
|
||||
args.Push(self->ValueType);
|
||||
argflags.Push(0);
|
||||
argnames.Push(NAME_Value);
|
||||
}
|
||||
else if constexpr(ArgType == OFN_ARG_KEY_VAL)
|
||||
{
|
||||
args.Push(self->KeyType);
|
||||
args.Push(self->ValueType);
|
||||
argflags.Push(0);
|
||||
argflags.Push(0);
|
||||
argnames.Push(NAME_Key);
|
||||
argnames.Push(NAME_Value);
|
||||
}
|
||||
|
||||
Fn->AddVariant(NewPrototype(ret, args), argflags, argnames, *NativeFn->VMPointer, VARF_Method | VARF_Native,SUF_ACTOR | SUF_OVERLAY | SUF_WEAPON | SUF_ITEM);
|
||||
self->FnOverrides.Insert(name, Fn);
|
||||
}
|
||||
|
||||
PMap::PMap(PType *keytype, PType *valtype, PStruct *backing, int backing_class)
|
||||
: KeyType(keytype), ValueType(valtype), BackingType(backing), BackingClass((decltype(BackingClass)) backing_class)
|
||||
{
|
||||
mDescriptiveName.Format("Map<%s, %s>", keytype->DescriptiveName(), valtype->DescriptiveName());
|
||||
Size = sizeof(ZSFMap);
|
||||
Align = alignof(ZSFMap);
|
||||
CreateOverrideFunction<PMap, OFN_RET_VAL, OFN_ARG_KEY>(this, NAME_Get);
|
||||
CreateOverrideFunction<PMap, OFN_RET_BOOL, OFN_ARG_KEY>(this, NAME_CheckKey);
|
||||
CreateOverrideFunction<PMap, OFN_RET_VOID, OFN_ARG_KEY_VAL>(this, NAME_Insert);
|
||||
CreateOverrideFunction<PMap, OFN_RET_VOID, OFN_ARG_KEY>(this, NAME_InsertNew);
|
||||
CreateOverrideFunction<PMap, OFN_RET_VOID, OFN_ARG_KEY>(this, NAME_Remove);
|
||||
CreateOverrideFunction< OFN_RET_VAL , OFN_ARG_KEY > (this, NAME_Get);
|
||||
CreateOverrideFunction< OFN_RET_VAL , OFN_ARG_KEY , VARF_ReadOnly> (this, NAME_GetIfExists);
|
||||
CreateOverrideFunction< OFN_RET_BOOL , OFN_ARG_KEY , VARF_ReadOnly> (this, NAME_CheckKey);
|
||||
CreateOverrideFunction< OFN_RET_VAL_BOOL , OFN_ARG_KEY , VARF_ReadOnly> (this, NAME_CheckValue);
|
||||
CreateOverrideFunction< OFN_RET_VOID , OFN_ARG_KEY_VAL > (this, NAME_Insert);
|
||||
CreateOverrideFunction< OFN_RET_VOID , OFN_ARG_KEY > (this, NAME_InsertNew);
|
||||
CreateOverrideFunction< OFN_RET_VOID , OFN_ARG_KEY > (this, NAME_Remove);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -2770,9 +2802,9 @@ PMapIterator::PMapIterator(PType *keytype, PType *valtype, PStruct *backing, int
|
|||
mDescriptiveName.Format("MapIterator<%s, %s>", keytype->DescriptiveName(), valtype->DescriptiveName());
|
||||
Size = sizeof(ZSFMap);
|
||||
Align = alignof(ZSFMap);
|
||||
CreateOverrideFunction<PMapIterator, OFN_RET_KEY, OFN_ARG_VOID>(this, NAME_GetKey);
|
||||
CreateOverrideFunction<PMapIterator, OFN_RET_VAL, OFN_ARG_VOID>(this, NAME_GetValue);
|
||||
CreateOverrideFunction<PMapIterator, OFN_RET_VOID, OFN_ARG_VAL>(this, NAME_SetValue);
|
||||
CreateOverrideFunction<OFN_RET_KEY, OFN_ARG_VOID>(this, NAME_GetKey);
|
||||
CreateOverrideFunction<OFN_RET_VAL, OFN_ARG_VOID>(this, NAME_GetValue);
|
||||
CreateOverrideFunction<OFN_RET_VOID, OFN_ARG_VAL>(this, NAME_SetValue);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -3009,12 +3041,13 @@ PMapIterator *NewMapIterator(PType *keyType, PType *valueType)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
PStruct::PStruct(FName name, PTypeBase *outer, bool isnative)
|
||||
PStruct::PStruct(FName name, PTypeBase *outer, bool isnative, int fileno)
|
||||
: PContainerType(name, outer)
|
||||
{
|
||||
mDescriptiveName.Format("%sStruct<%s>", isnative? "Native" : "", name.GetChars());
|
||||
Size = 0;
|
||||
isNative = isnative;
|
||||
mDefFileNo = fileno;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -3155,7 +3188,7 @@ PField *PStruct::AddField(FName name, PType *type, uint32_t flags)
|
|||
|
||||
PField *PStruct::AddNativeField(FName name, PType *type, size_t address, uint32_t flags, int bitvalue)
|
||||
{
|
||||
return Symbols.AddNativeField(name, type, address, flags, bitvalue);
|
||||
return Symbols.AddNativeField(name, type, address, flags, bitvalue, mDefFileNo);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -3166,14 +3199,14 @@ PField *PStruct::AddNativeField(FName name, PType *type, size_t address, uint32_
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
PStruct *NewStruct(FName name, PTypeBase *outer, bool native)
|
||||
PStruct *NewStruct(FName name, PTypeBase *outer, bool native, int fileno)
|
||||
{
|
||||
size_t bucket;
|
||||
if (outer == nullptr) outer = Namespaces.GlobalNamespace;
|
||||
PType *stype = TypeTable.FindType(NAME_Struct, (intptr_t)outer, name.GetIndex(), &bucket);
|
||||
if (stype == nullptr)
|
||||
{
|
||||
stype = new PStruct(name, outer, native);
|
||||
stype = new PStruct(name, outer, native, fileno);
|
||||
TypeTable.AddType(stype, NAME_Struct, (intptr_t)outer, name.GetIndex(), bucket);
|
||||
}
|
||||
return static_cast<PStruct *>(stype);
|
||||
|
@ -3271,7 +3304,7 @@ PPrototype *NewPrototype(const TArray<PType *> &rettypes, const TArray<PType *>
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
PClassType::PClassType(PClass *cls)
|
||||
PClassType::PClassType(PClass *cls, int fileno)
|
||||
{
|
||||
assert(cls->VMType == nullptr);
|
||||
Descriptor = cls;
|
||||
|
@ -3284,6 +3317,7 @@ PClassType::PClassType(PClass *cls)
|
|||
ScopeFlags = ParentType->ScopeFlags;
|
||||
}
|
||||
cls->VMType = this;
|
||||
mDefFileNo = fileno;
|
||||
mDescriptiveName.Format("Class<%s>", cls->TypeName.GetChars());
|
||||
}
|
||||
|
||||
|
@ -3295,7 +3329,7 @@ PClassType::PClassType(PClass *cls)
|
|||
|
||||
PField *PClassType::AddField(FName name, PType *type, uint32_t flags)
|
||||
{
|
||||
return Descriptor->AddField(name, type, flags);
|
||||
return Descriptor->AddField(name, type, flags, mDefFileNo);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -3306,7 +3340,7 @@ PField *PClassType::AddField(FName name, PType *type, uint32_t flags)
|
|||
|
||||
PField *PClassType::AddNativeField(FName name, PType *type, size_t address, uint32_t flags, int bitvalue)
|
||||
{
|
||||
auto field = Symbols.AddNativeField(name, type, address, flags, bitvalue);
|
||||
auto field = Symbols.AddNativeField(name, type, address, flags, bitvalue, mDefFileNo);
|
||||
if (field != nullptr) Descriptor->Fields.Push(field);
|
||||
return field;
|
||||
}
|
||||
|
@ -3317,13 +3351,13 @@ PField *PClassType::AddNativeField(FName name, PType *type, size_t address, uint
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
PClassType *NewClassType(PClass *cls)
|
||||
PClassType *NewClassType(PClass *cls, int fileno)
|
||||
{
|
||||
size_t bucket;
|
||||
PType *ptype = TypeTable.FindType(NAME_Object, 0, cls->TypeName.GetIndex(), &bucket);
|
||||
if (ptype == nullptr)
|
||||
{
|
||||
ptype = new PClassType(cls);
|
||||
ptype = new PClassType(cls, fileno);
|
||||
TypeTable.AddType(ptype, NAME_Object, 0, cls->TypeName.GetIndex(), bucket);
|
||||
}
|
||||
return static_cast<PClassType *>(ptype);
|
||||
|
|
|
@ -512,6 +512,8 @@ public:
|
|||
PType *ElementType;
|
||||
PStruct *BackingType;
|
||||
|
||||
TMap<FName,PFunction*> FnOverrides;
|
||||
|
||||
bool IsMatch(intptr_t id1, intptr_t id2) const override;
|
||||
void GetTypeIDs(intptr_t &id1, intptr_t &id2) const override;
|
||||
|
||||
|
@ -596,13 +598,14 @@ public:
|
|||
class PStruct : public PContainerType
|
||||
{
|
||||
public:
|
||||
PStruct(FName name, PTypeBase *outer, bool isnative = false);
|
||||
PStruct(FName name, PTypeBase *outer, bool isnative = false, int fileno = 0);
|
||||
|
||||
bool isNative;
|
||||
bool isOrdered = false;
|
||||
// Some internal structs require explicit construction and destruction of fields the VM cannot handle directly so use these two functions for it.
|
||||
VMFunction *mConstructor = nullptr;
|
||||
VMFunction *mDestructor = nullptr;
|
||||
int mDefFileNo;
|
||||
|
||||
PField *AddField(FName name, PType *type, uint32_t flags=0) override;
|
||||
PField *AddNativeField(FName name, PType *type, size_t address, uint32_t flags = 0, int bitvalue = 0) override;
|
||||
|
@ -635,8 +638,9 @@ class PClassType : public PContainerType
|
|||
public:
|
||||
PClass *Descriptor;
|
||||
PClassType *ParentType;
|
||||
int mDefFileNo;
|
||||
|
||||
PClassType(PClass *cls = nullptr);
|
||||
PClassType(PClass *cls = nullptr, int fileno = 0);
|
||||
PField *AddField(FName name, PType *type, uint32_t flags = 0) override;
|
||||
PField *AddNativeField(FName name, PType *type, size_t address, uint32_t flags = 0, int bitvalue = 0) override;
|
||||
};
|
||||
|
@ -657,9 +661,9 @@ PPointer *NewPointer(PType *type, bool isconst = false);
|
|||
PPointer *NewPointer(PClass *type, bool isconst = false);
|
||||
PClassPointer *NewClassPointer(PClass *restrict);
|
||||
PEnum *NewEnum(FName name, PTypeBase *outer);
|
||||
PStruct *NewStruct(FName name, PTypeBase *outer, bool native = false);
|
||||
PStruct *NewStruct(FName name, PTypeBase *outer, bool native = false, int fileno = 0);
|
||||
PPrototype *NewPrototype(const TArray<PType *> &rettypes, const TArray<PType *> &argtypes);
|
||||
PClassType *NewClassType(PClass *cls);
|
||||
PClassType *NewClassType(PClass *cls, int fileno);
|
||||
|
||||
// Built-in types -----------------------------------------------------------
|
||||
|
||||
|
|
|
@ -720,11 +720,11 @@ void ZCCCompiler::CreateStructTypes()
|
|||
}
|
||||
else if (s->strct->Flags & ZCC_Native)
|
||||
{
|
||||
s->strct->Type = NewStruct(s->NodeName(), outer, true);
|
||||
s->strct->Type = NewStruct(s->NodeName(), outer, true, AST.FileNo);
|
||||
}
|
||||
else
|
||||
{
|
||||
s->strct->Type = NewStruct(s->NodeName(), outer);
|
||||
s->strct->Type = NewStruct(s->NodeName(), outer, false, AST.FileNo);
|
||||
}
|
||||
if (s->strct->Flags & ZCC_Version)
|
||||
{
|
||||
|
@ -832,7 +832,7 @@ void ZCCCompiler::CreateClassTypes()
|
|||
{
|
||||
DPrintf(DMSG_SPAMMY, "Registered %s as native with parent %s\n", me->TypeName.GetChars(), parent->TypeName.GetChars());
|
||||
}
|
||||
c->cls->Type = NewClassType(me);
|
||||
c->cls->Type = NewClassType(me, AST.FileNo);
|
||||
me->SourceLumpName = *c->cls->SourceName;
|
||||
}
|
||||
else
|
||||
|
@ -844,14 +844,14 @@ void ZCCCompiler::CreateClassTypes()
|
|||
{
|
||||
Error(c->cls, "Parent class %s of %s not accessible to ZScript version %d.%d.%d", parent->TypeName.GetChars(), c->NodeName().GetChars(), mVersion.major, mVersion.minor, mVersion.revision);
|
||||
}
|
||||
auto newclass = parent->CreateDerivedClass(c->NodeName(), TentativeClass);
|
||||
auto newclass = parent->CreateDerivedClass(c->NodeName(), TentativeClass, nullptr, AST.FileNo);
|
||||
if (newclass == nullptr)
|
||||
{
|
||||
Error(c->cls, "Class name %s already exists", c->NodeName().GetChars());
|
||||
}
|
||||
else
|
||||
{
|
||||
c->cls->Type = NewClassType(newclass);
|
||||
c->cls->Type = NewClassType(newclass, AST.FileNo);
|
||||
DPrintf(DMSG_SPAMMY, "Created class %s with parent %s\n", c->Type()->TypeName.GetChars(), c->ClassType()->ParentClass->TypeName.GetChars());
|
||||
}
|
||||
}
|
||||
|
@ -864,7 +864,7 @@ void ZCCCompiler::CreateClassTypes()
|
|||
if (c->Type() == nullptr)
|
||||
{
|
||||
// create a placeholder so that the compiler can continue looking for errors.
|
||||
c->cls->Type = NewClassType(parent->FindClassTentative(c->NodeName()));
|
||||
c->cls->Type = NewClassType(parent->FindClassTentative(c->NodeName()), AST.FileNo);
|
||||
}
|
||||
|
||||
if (c->cls->Flags & ZCC_Abstract)
|
||||
|
@ -928,7 +928,7 @@ void ZCCCompiler::CreateClassTypes()
|
|||
{
|
||||
Error(c->cls, "Class %s has unknown base class %s", c->NodeName().GetChars(), FName(c->cls->ParentName->Id).GetChars());
|
||||
// create a placeholder so that the compiler can continue looking for errors.
|
||||
c->cls->Type = NewClassType(RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName()));
|
||||
c->cls->Type = NewClassType(RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName()), AST.FileNo);
|
||||
c->cls->Symbol = Create<PSymbolType>(c->NodeName(), c->Type());
|
||||
OutNamespace->Symbols.AddSymbol(c->cls->Symbol);
|
||||
Classes.Push(c);
|
||||
|
@ -944,7 +944,7 @@ void ZCCCompiler::CreateClassTypes()
|
|||
for (auto c : OrigClasses)
|
||||
{
|
||||
Error(c->cls, "Class %s has circular inheritance", FName(c->NodeName()).GetChars());
|
||||
c->cls->Type = NewClassType(RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName()));
|
||||
c->cls->Type = NewClassType(RUNTIME_CLASS(DObject)->FindClassTentative(c->NodeName()), AST.FileNo);
|
||||
c->cls->Symbol = Create<PSymbolType>(c->NodeName(), c->Type());
|
||||
OutNamespace->Symbols.AddSymbol(c->cls->Symbol);
|
||||
Classes.Push(c);
|
||||
|
|
|
@ -407,6 +407,10 @@ PNamespace *ParseOneScript(const int baselump, ZCCParseState &state)
|
|||
int lumpnum = baselump;
|
||||
auto fileno = fileSystem.GetFileContainer(lumpnum);
|
||||
|
||||
FString file = fileSystem.GetFileFullPath(lumpnum);
|
||||
|
||||
state.FileNo = fileno;
|
||||
|
||||
if (TokenMap.CountUsed() == 0)
|
||||
{
|
||||
InitTokenMap();
|
||||
|
|
|
@ -628,6 +628,7 @@ struct ZCC_AST
|
|||
FMemArena SyntaxArena;
|
||||
struct ZCC_TreeNode *TopNode;
|
||||
VersionInfo ParseVersion;
|
||||
int FileNo;
|
||||
};
|
||||
|
||||
struct ZCCParseState : public ZCC_AST
|
||||
|
|
|
@ -852,7 +852,22 @@ DEFINE_ACTION_FUNCTION(_CVar, SetInt)
|
|||
PARAM_INT(val);
|
||||
UCVarValue v;
|
||||
v.Int = val;
|
||||
self->SetGenericRep(v, CVAR_Int);
|
||||
|
||||
if(self->GetFlags() & CVAR_ZS_CUSTOM_CLONE)
|
||||
{
|
||||
auto realCVar = (FBaseCVar*)(self->GetExtraDataPointer());
|
||||
assert(realCVar->GetFlags() & CVAR_ZS_CUSTOM);
|
||||
|
||||
v = realCVar->GenericZSCVarCallback(v, CVAR_Int);
|
||||
self->SetGenericRep(v, realCVar->GetRealType());
|
||||
|
||||
if(realCVar->GetRealType() == CVAR_String) delete[] v.String;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->SetGenericRep(v, CVAR_Int);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -870,7 +885,22 @@ DEFINE_ACTION_FUNCTION(_CVar, SetFloat)
|
|||
PARAM_FLOAT(val);
|
||||
UCVarValue v;
|
||||
v.Float = (float)val;
|
||||
self->SetGenericRep(v, CVAR_Float);
|
||||
|
||||
if(self->GetFlags() & CVAR_ZS_CUSTOM_CLONE)
|
||||
{
|
||||
auto realCVar = (FBaseCVar*)(self->GetExtraDataPointer());
|
||||
assert(realCVar->GetFlags() & CVAR_ZS_CUSTOM);
|
||||
|
||||
v = realCVar->GenericZSCVarCallback(v, CVAR_Float);
|
||||
self->SetGenericRep(v, realCVar->GetRealType());
|
||||
|
||||
if(realCVar->GetRealType() == CVAR_String) delete[] v.String;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->SetGenericRep(v, CVAR_Float);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -889,7 +919,22 @@ DEFINE_ACTION_FUNCTION(_CVar, SetString)
|
|||
PARAM_STRING(val);
|
||||
UCVarValue v;
|
||||
v.String = val.GetChars();
|
||||
self->SetGenericRep(v, CVAR_String);
|
||||
|
||||
if(self->GetFlags() & CVAR_ZS_CUSTOM_CLONE)
|
||||
{
|
||||
auto realCVar = (FBaseCVar*)(self->GetExtraDataPointer());
|
||||
assert(realCVar->GetFlags() & CVAR_ZS_CUSTOM);
|
||||
|
||||
v = realCVar->GenericZSCVarCallback(v, CVAR_String);
|
||||
self->SetGenericRep(v, realCVar->GetRealType());
|
||||
|
||||
if(realCVar->GetRealType() == CVAR_String) delete[] v.String;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->SetGenericRep(v, CVAR_String);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -849,6 +849,7 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret)
|
|||
return 0;
|
||||
}
|
||||
auto p = o->GetClass();
|
||||
if(p->Virtuals.Size() <= 0) ThrowAbortException(X_OTHER,"Attempted to call an invalid virtual function in class %s",p->TypeName.GetChars());
|
||||
assert(C < p->Virtuals.Size());
|
||||
reg.a[a] = p->Virtuals[C];
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue