Fixed a few last things to get script template serialization working 100%. Fixed some bugs that caused the serializer to crash on loading old projects and prevented dependency trees from serializing correctly.
This commit is contained in:
parent
e2a57b7d49
commit
33e915a638
|
@ -102,6 +102,7 @@ SOURCES += \
|
||||||
Hash/CCRC32.cpp
|
Hash/CCRC32.cpp
|
||||||
|
|
||||||
# Codegen
|
# Codegen
|
||||||
|
CODEGEN_DIR = $$EXTERNALS_DIR/CodeGen
|
||||||
CODEGEN_OUT_PATH = $$BUILD_DIR/Common/codegen_build/auto_codegen.cpp
|
CODEGEN_OUT_PATH = $$BUILD_DIR/Common/codegen_build/auto_codegen.cpp
|
||||||
CODEGEN_SRC_PATH = $$PWD
|
CODEGEN_SRC_PATH = $$PWD
|
||||||
include($$EXTERNALS_DIR/CodeGen/codegen.pri)
|
include($$EXTERNALS_DIR/CodeGen/codegen.pri)
|
||||||
|
|
|
@ -67,19 +67,12 @@ void Serialize(IArchive& rArc, EGame& rGame)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ERegion
|
// ERegion
|
||||||
static const TString gskRegionNames[] = { "NTSC", "PAL", "JPN", "UnknownRegion" };
|
const char* GetRegionName(ERegion Region)
|
||||||
static const u32 gskNumRegions = sizeof(gskRegionNames) / sizeof(gskRegionNames[0]);
|
|
||||||
|
|
||||||
TString GetRegionName(ERegion Region)
|
|
||||||
{
|
{
|
||||||
return gskRegionNames[(int) Region];
|
return TEnumReflection<ERegion>::ConvertValueToString(Region);
|
||||||
}
|
}
|
||||||
|
|
||||||
ERegion GetRegionForName(const TString& rkName)
|
ERegion GetRegionForName(const char* pkName)
|
||||||
{
|
{
|
||||||
for (u32 iReg = 0; iReg < gskNumRegions; iReg++)
|
return TEnumReflection<ERegion>::ConvertStringToValue(pkName);
|
||||||
if (gskRegionNames[iReg] == rkName)
|
|
||||||
return (ERegion) iReg;
|
|
||||||
|
|
||||||
return eRegion_Unknown;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,8 @@
|
||||||
class CFourCC;
|
class CFourCC;
|
||||||
class IArchive;
|
class IArchive;
|
||||||
|
|
||||||
// Note: The reason why the EGame value isn't just the fourCC game ID is because a lot of code does inequality
|
// Note: A lot of code does inequality comparisons on EGame, ie. "if (Game <= eEchoes)", which means that the
|
||||||
// comparisons on EGame for version checking ie. "if (Game <= eEchoes)", which means the enum values need to be
|
// enum values need to be in chronological order. It'd be more convenient if the values were fourCCs, but we can't do that.
|
||||||
// in chronological order.
|
|
||||||
enum EGame
|
enum EGame
|
||||||
{
|
{
|
||||||
ePrimeDemo,
|
ePrimeDemo,
|
||||||
|
@ -29,14 +28,14 @@ TString GetGameShortName(EGame Game);
|
||||||
void Serialize(IArchive& rArc, EGame& rGame);
|
void Serialize(IArchive& rArc, EGame& rGame);
|
||||||
|
|
||||||
// ERegion
|
// ERegion
|
||||||
enum ERegion
|
enum class ERegion
|
||||||
{
|
{
|
||||||
eRegion_NTSC,
|
NTSC,
|
||||||
eRegion_PAL,
|
PAL,
|
||||||
eRegion_JPN,
|
JPN,
|
||||||
eRegion_Unknown = -1
|
Unknown = -1
|
||||||
};
|
};
|
||||||
TString GetRegionName(ERegion Region);
|
const char* GetRegionName(ERegion Region);
|
||||||
ERegion GetRegionForName(const TString& rkName);
|
ERegion GetRegionForName(const char* pkName);
|
||||||
|
|
||||||
#endif // EGAME_H
|
#endif // EGAME_H
|
||||||
|
|
|
@ -93,9 +93,23 @@ public:
|
||||||
virtual void ParamEnd()
|
virtual void ParamEnd()
|
||||||
{
|
{
|
||||||
if (mpAttributeName)
|
if (mpAttributeName)
|
||||||
|
{
|
||||||
mpAttributeName = nullptr;
|
mpAttributeName = nullptr;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
mpCurElem = mpCurElem->Parent()->ToElement();
|
{
|
||||||
|
// If we didn't save any sub parameters, remove the element.
|
||||||
|
tinyxml2::XMLElement* pParent = mpCurElem->Parent()->ToElement();
|
||||||
|
|
||||||
|
if ( mpCurElem->FirstAttribute() == nullptr
|
||||||
|
&& mpCurElem->FirstChild() == nullptr
|
||||||
|
&& mpCurElem->GetText() == nullptr )
|
||||||
|
{
|
||||||
|
pParent->DeleteChild(mpCurElem);
|
||||||
|
}
|
||||||
|
|
||||||
|
mpCurElem = pParent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -189,19 +189,55 @@ struct SerialType
|
||||||
{
|
{
|
||||||
enum { Primitive, Member, Global, None };
|
enum { Primitive, Member, Global, None };
|
||||||
|
|
||||||
// Check for ArcType::SerializePrimitive(ValType&) method
|
/** Check for ArcType::SerializePrimitive(ValType&) method */
|
||||||
template<typename ValType, typename ArcType> static long long& Check(FunctionExists<void (ArcType::*)(ValType&, u32), &ArcType::SerializePrimitive>*);
|
template<typename V, typename A>
|
||||||
// Check for ValType::Serialize(ArcType&)
|
static constexpr auto HasPrimitiveSerialize(int) -> decltype(
|
||||||
template<typename ValType, typename ArcType> static long& Check(FunctionExists<void (ValType::*)(ArcType&), &ValType::Serialize>*);
|
std::declval<A>().SerializePrimitive( std::declval<V&>(), u32() ), bool()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename V, typename A>
|
||||||
|
static constexpr bool HasPrimitiveSerialize(...)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check for ValType::Serialize(ArcType&) */
|
||||||
|
template<typename V, typename A>
|
||||||
|
static constexpr auto HasMemberSerialize(int) -> decltype(
|
||||||
|
std::declval<V>().Serialize( std::declval<A&>() ), bool()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename V, typename A>
|
||||||
|
static constexpr bool HasMemberSerialize(...)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Check for global Serialize(ArcType&,ValType&) function
|
// Check for global Serialize(ArcType&,ValType&) function
|
||||||
template<typename ValType, typename ArcType> static short& Check(FunctionExists<void (*)(ArcType&, ValType&), &Serialize>*);
|
template<typename V, typename A>
|
||||||
// Fallback - no valid Serialize method exists
|
static constexpr auto HasGlobalSerialize(int) -> decltype(
|
||||||
template<typename ValType, typename ArcType> static char& Check(...);
|
Serialize( std::declval<A&>(), std::declval<V&>() ), bool()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename V, typename A>
|
||||||
|
static constexpr bool HasGlobalSerialize(...)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Set Type enum to correspond to whichever function exists
|
// Set Type enum to correspond to whichever function exists
|
||||||
static const int Type = (sizeof(Check<ValueType, ArchiveType>(0)) == sizeof(long long) ? Primitive :
|
static const int Type = (HasPrimitiveSerialize<ValueType, ArchiveType>(0) ? Primitive :
|
||||||
sizeof(Check<ValueType, ArchiveType>(0)) == sizeof(long) ? Member :
|
HasMemberSerialize<ValueType, ArchiveType>(0) ? Member :
|
||||||
sizeof(Check<ValueType, ArchiveType>(0)) == sizeof(short) ? Global :
|
HasGlobalSerialize<ValueType, ArchiveType>(0) ? Global :
|
||||||
None);
|
None);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -216,21 +252,40 @@ struct ArchiveConstructorType
|
||||||
|
|
||||||
enum { Basic, Advanced, None };
|
enum { Basic, Advanced, None };
|
||||||
|
|
||||||
// Check for ValueType::ArchiveConstructor(ObjectType, const IArchive&)
|
/** Check for ValType::ArchiveConstructor(ObjectType) */
|
||||||
template<typename ValueType, typename ObjectType> static long& Check(FunctionExists<ValueType* (*)(ObjectType, const ArchiveType&), &ValueType::ArchiveConstructor>*);
|
template<typename V, typename O>
|
||||||
// Check for ValueType::ArchiveConstructor(ObjectType)
|
static constexpr auto HasBasicArchiveConstructor(int) -> decltype(
|
||||||
template<typename ValueType, typename ObjectType> static short& Check(FunctionExists<ValueType* (*)(ObjectType), &ValueType::ArchiveConstructor>*);
|
std::declval<V>().ArchiveConstructor( std::declval<O>()), bool()
|
||||||
// Fallback - no valid ArchiveConstructor method exists
|
)
|
||||||
template<typename ValueType, typename ObjectType> static char& Check(...);
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename V, typename O>
|
||||||
|
static constexpr bool HasBasicArchiveConstructor(...)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Check for ValType::ArchiveConstructor(ObjectType, IArchive&) */
|
||||||
|
template<typename V, typename A, typename O>
|
||||||
|
static constexpr auto HasAdvancedArchiveConstructor(int) -> decltype(
|
||||||
|
std::declval<V>().ArchiveConstructor( std::declval<O>(), std::declval<A&>() ), bool()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename V, typename A, typename O>
|
||||||
|
static constexpr bool HasAdvancedArchiveConstructor(...)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Set Type enum to correspond to whichever function exists
|
// Set Type enum to correspond to whichever function exists
|
||||||
static const int Type = (sizeof(Check<ValType, ObjType>(0)) == sizeof(long) ? Advanced :
|
static const int Type = (HasAdvancedArchiveConstructor<ValType, ArchiveType, ObjType>(0) ? Advanced :
|
||||||
sizeof(Check<ValType, ObjType>(0)) == sizeof(short) ? Basic :
|
HasBasicArchiveConstructor<ValType, ObjType>(0) ? Basic :
|
||||||
None);
|
None);
|
||||||
|
|
||||||
// If you fail here, you are missing an ArchiveConstructor() function, or you do have one but it is malformed.
|
|
||||||
// Check the comments at the top of this source file for details on serialization requirements for abstract objects.
|
|
||||||
static_assert(Type != None, "Abstract objects being serialized must have virtual Type() and static ArchiveConstructor() functions.");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Helper that turns functions on or off depending on their serialize type */
|
/** Helper that turns functions on or off depending on their serialize type */
|
||||||
|
@ -240,7 +295,7 @@ struct ArchiveConstructorType
|
||||||
#define IS_ARCHIVE_CONSTRUCTOR_TYPE(CType) (ArchiveConstructorType<ValType, IArchive>::Type == ArchiveConstructorType<ValType, IArchive>::##CType)
|
#define IS_ARCHIVE_CONSTRUCTOR_TYPE(CType) (ArchiveConstructorType<ValType, IArchive>::Type == ArchiveConstructorType<ValType, IArchive>::##CType)
|
||||||
|
|
||||||
/** Helper that turns functions on or off depending on if the parameter type is abstract */
|
/** Helper that turns functions on or off depending on if the parameter type is abstract */
|
||||||
#define IS_ABSTRACT std::is_abstract<ValType>::value
|
#define IS_ABSTRACT ( std::is_abstract_v<ValType> || (std::is_polymorphic_v<ValType> && ArchiveConstructorType<ValType, IArchive>::Type != ArchiveConstructorType<ValType, IArchive>::None) )
|
||||||
|
|
||||||
/** IArchive - Main serializer archive interface */
|
/** IArchive - Main serializer archive interface */
|
||||||
class IArchive
|
class IArchive
|
||||||
|
@ -269,6 +324,7 @@ public:
|
||||||
eArVer_Initial,
|
eArVer_Initial,
|
||||||
eArVer_32BitBinarySize,
|
eArVer_32BitBinarySize,
|
||||||
eArVer_Refactor,
|
eArVer_Refactor,
|
||||||
|
eArVer_MapAttributes,
|
||||||
// Insert new versions before this line
|
// Insert new versions before this line
|
||||||
eArVer_Max
|
eArVer_Max
|
||||||
};
|
};
|
||||||
|
@ -342,7 +398,7 @@ private:
|
||||||
{
|
{
|
||||||
// Variant for basic static constructor
|
// Variant for basic static constructor
|
||||||
ASSERT( IsReader() );
|
ASSERT( IsReader() );
|
||||||
return ValType::ArchiveConstructor(Type);
|
return (ValType*) ValType::ArchiveConstructor(Type);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ValType, typename ObjType = ABSTRACT_TYPE>
|
template<typename ValType, typename ObjType = ABSTRACT_TYPE>
|
||||||
|
@ -351,7 +407,16 @@ private:
|
||||||
{
|
{
|
||||||
// Variant for advanced static constructor
|
// Variant for advanced static constructor
|
||||||
ASSERT( IsReader() );
|
ASSERT( IsReader() );
|
||||||
return ValType::ArchiveConstructor(Type, *this);
|
return (ValType*) ValType::ArchiveConstructor(Type, *this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ValType, typename ObjType = ABSTRACT_TYPE>
|
||||||
|
ENABLE_IF( IS_ARCHIVE_CONSTRUCTOR_TYPE(None), ValType* )
|
||||||
|
InstantiateAbstractObject(const TSerialParameter<ValType*>& Param, ObjType Type)
|
||||||
|
{
|
||||||
|
// If you fail here, you are missing an ArchiveConstructor() function, or you do have one but it is malformed.
|
||||||
|
// Check the comments at the top of this source file for details on serialization requirements for abstract objects.
|
||||||
|
static_assert(false, "Abstract objects being serialized must have virtual Type() and static ArchiveConstructor() functions.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parameter stack handling
|
// Parameter stack handling
|
||||||
|
@ -579,7 +644,7 @@ public:
|
||||||
|
|
||||||
if (IsReader() && rParam.rValue == nullptr)
|
if (IsReader() && rParam.rValue == nullptr)
|
||||||
{
|
{
|
||||||
rParam.rValue = InstantiateAbstractObject(rParam, Type);
|
rParam.rValue = (ValType*) InstantiateAbstractObject(rParam, Type);
|
||||||
}
|
}
|
||||||
else if (rParam.rValue != nullptr)
|
else if (rParam.rValue != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -658,6 +723,7 @@ public:
|
||||||
inline bool IsWriter() const { return (mArchiveFlags & AF_Writer) != 0; }
|
inline bool IsWriter() const { return (mArchiveFlags & AF_Writer) != 0; }
|
||||||
inline bool IsTextFormat() const { return (mArchiveFlags & AF_Text) != 0; }
|
inline bool IsTextFormat() const { return (mArchiveFlags & AF_Text) != 0; }
|
||||||
inline bool IsBinaryFormat() const { return (mArchiveFlags & AF_Binary) != 0; }
|
inline bool IsBinaryFormat() const { return (mArchiveFlags & AF_Binary) != 0; }
|
||||||
|
inline bool CanSkipParameters() const { return (mArchiveFlags & AF_NoSkipping) == 0; }
|
||||||
|
|
||||||
inline u16 ArchiveVersion() const { return mArchiveVersion; }
|
inline u16 ArchiveVersion() const { return mArchiveVersion; }
|
||||||
inline u16 FileVersion() const { return mFileVersion; }
|
inline u16 FileVersion() const { return mFileVersion; }
|
||||||
|
@ -837,7 +903,7 @@ inline void SerializeMap_Internal(IArchive& Arc, MapType& Map)
|
||||||
u32 Hints = SH_IgnoreName | SH_InheritHints;
|
u32 Hints = SH_IgnoreName | SH_InheritHints;
|
||||||
|
|
||||||
// Serialize the key/value as attributes if they are both primitive types.
|
// Serialize the key/value as attributes if they are both primitive types.
|
||||||
if (TIsPrimitive<KeyType>::value && TIsPrimitive<ValType>::value)
|
if (Arc.ArchiveVersion() >= IArchive::eArVer_MapAttributes && TIsPrimitive<KeyType>::value && TIsPrimitive<ValType>::value)
|
||||||
{
|
{
|
||||||
Hints |= SH_Attribute;
|
Hints |= SH_Attribute;
|
||||||
}
|
}
|
||||||
|
|
|
@ -366,9 +366,12 @@ SOURCES += \
|
||||||
GameProject\COpeningBanner.cpp \
|
GameProject\COpeningBanner.cpp \
|
||||||
IProgressNotifier.cpp \
|
IProgressNotifier.cpp \
|
||||||
Resource/Script/CPropertyNameGenerator.cpp \
|
Resource/Script/CPropertyNameGenerator.cpp \
|
||||||
Resource/Script/IPropertyNew.cpp
|
Resource/Script/IPropertyNew.cpp \
|
||||||
|
Resource/Script/Property/CStructProperty.cpp \
|
||||||
|
Resource/Script/Property/CFlagsProperty.cpp
|
||||||
|
|
||||||
# Codegen
|
# Codegen
|
||||||
|
CODEGEN_DIR = $$EXTERNALS_DIR/CodeGen
|
||||||
CODEGEN_OUT_PATH = $$BUILD_DIR/Core/codegen_build/auto_codegen.cpp
|
CODEGEN_OUT_PATH = $$BUILD_DIR/Core/codegen_build/auto_codegen.cpp
|
||||||
CODEGEN_SRC_PATH = $$PWD
|
CODEGEN_SRC_PATH = $$PWD
|
||||||
include($$EXTERNALS_DIR/CodeGen/codegen.pri)
|
include($$EXTERNALS_DIR/CodeGen/codegen.pri)
|
||||||
|
|
|
@ -30,7 +30,7 @@ CGameExporter::CGameExporter(EDiscType DiscType, EGame Game, bool FrontEnd, EReg
|
||||||
, mpProgress(nullptr)
|
, mpProgress(nullptr)
|
||||||
{
|
{
|
||||||
ASSERT(mGame != eUnknownGame);
|
ASSERT(mGame != eUnknownGame);
|
||||||
ASSERT(mRegion != eRegion_Unknown);
|
ASSERT(mRegion != ERegion::Unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if PUBLIC_RELEASE
|
#if PUBLIC_RELEASE
|
||||||
|
|
|
@ -46,7 +46,7 @@ class CGameProject
|
||||||
CGameProject()
|
CGameProject()
|
||||||
: mProjectName("Unnamed Project")
|
: mProjectName("Unnamed Project")
|
||||||
, mGame(eUnknownGame)
|
, mGame(eUnknownGame)
|
||||||
, mRegion(eRegion_Unknown)
|
, mRegion(ERegion::Unknown)
|
||||||
, mGameID("000000")
|
, mGameID("000000")
|
||||||
, mBuildVersion(0.f)
|
, mBuildVersion(0.f)
|
||||||
, mpResourceStore(nullptr)
|
, mpResourceStore(nullptr)
|
||||||
|
|
|
@ -376,7 +376,13 @@ CStructPropertyNew* CTemplateLoader::LoadStructArchetype(const TString& rkTempla
|
||||||
{
|
{
|
||||||
// Check whether this struct has already been read
|
// Check whether this struct has already been read
|
||||||
TString StructName = rkTemplateFileName.GetFileName(false);
|
TString StructName = rkTemplateFileName.GetFileName(false);
|
||||||
CStructPropertyNew* pArchetype = mpMaster->FindStructArchetype(StructName);
|
CStructPropertyNew* pArchetype = static_cast<CStructPropertyNew*>( mpMaster->FindPropertyArchetype(StructName) );
|
||||||
|
|
||||||
|
// Names cannot be shared between multiple property archetypes
|
||||||
|
if (pArchetype != nullptr)
|
||||||
|
{
|
||||||
|
ASSERT(pArchetype->Type() == EPropertyTypeNew::Struct);
|
||||||
|
}
|
||||||
|
|
||||||
// If the struct template hasn't been read yet, then we read it and add it to master's list
|
// If the struct template hasn't been read yet, then we read it and add it to master's list
|
||||||
if (!pArchetype)
|
if (!pArchetype)
|
||||||
|
@ -434,7 +440,7 @@ CStructPropertyNew* CTemplateLoader::LoadStructArchetype(const TString& rkTempla
|
||||||
LoadProperties(pSubPropsElem, nullptr, pArchetype, rkTemplateFileName);
|
LoadProperties(pSubPropsElem, nullptr, pArchetype, rkTemplateFileName);
|
||||||
pArchetype->PostInitialize();
|
pArchetype->PostInitialize();
|
||||||
|
|
||||||
mpMaster->mStructTemplates.emplace(
|
mpMaster->mPropertyTemplates.emplace(
|
||||||
std::make_pair(
|
std::make_pair(
|
||||||
StructName,
|
StructName,
|
||||||
CMasterTemplate::SPropertyTemplatePath(rkTemplateFileName, pArchetype)
|
CMasterTemplate::SPropertyTemplatePath(rkTemplateFileName, pArchetype)
|
||||||
|
@ -450,7 +456,13 @@ CEnumProperty* CTemplateLoader::LoadEnumArchetype(const TString& rkTemplateFileN
|
||||||
{
|
{
|
||||||
// Check whether this struct has already been read
|
// Check whether this struct has already been read
|
||||||
TString EnumName = rkTemplateFileName.GetFileName(false);
|
TString EnumName = rkTemplateFileName.GetFileName(false);
|
||||||
CEnumProperty* pArchetype = mpMaster->FindEnumArchetype(EnumName);
|
CEnumProperty* pArchetype = static_cast<CEnumProperty*>( mpMaster->FindPropertyArchetype(EnumName) );
|
||||||
|
|
||||||
|
// Names cannot be shared between multiple property archetypes
|
||||||
|
if (pArchetype != nullptr)
|
||||||
|
{
|
||||||
|
ASSERT(pArchetype->Type() == EPropertyTypeNew::Enum || pArchetype->Type() == EPropertyTypeNew::Choice);
|
||||||
|
}
|
||||||
|
|
||||||
// If the enum template hasn't been read yet, then we read it and add it to master's list
|
// If the enum template hasn't been read yet, then we read it and add it to master's list
|
||||||
if (!pArchetype)
|
if (!pArchetype)
|
||||||
|
@ -470,6 +482,7 @@ CEnumProperty* CTemplateLoader::LoadEnumArchetype(const TString& rkTemplateFileN
|
||||||
);
|
);
|
||||||
ASSERT(pArchetype != nullptr);
|
ASSERT(pArchetype != nullptr);
|
||||||
|
|
||||||
|
pArchetype->mName = rkTemplateFileName.GetFileName(false);
|
||||||
pArchetype->mFlags |= EPropertyFlag::IsArchetype;
|
pArchetype->mFlags |= EPropertyFlag::IsArchetype;
|
||||||
pArchetype->mSourceFile = rkTemplateFileName;
|
pArchetype->mSourceFile = rkTemplateFileName;
|
||||||
|
|
||||||
|
@ -482,7 +495,7 @@ CEnumProperty* CTemplateLoader::LoadEnumArchetype(const TString& rkTemplateFileN
|
||||||
LoadEnumerators(pEnumers, pArchetype, rkTemplateFileName);
|
LoadEnumerators(pEnumers, pArchetype, rkTemplateFileName);
|
||||||
pArchetype->PostInitialize();
|
pArchetype->PostInitialize();
|
||||||
|
|
||||||
mpMaster->mEnumTemplates.emplace(
|
mpMaster->mPropertyTemplates.emplace(
|
||||||
std::make_pair(
|
std::make_pair(
|
||||||
EnumName,
|
EnumName,
|
||||||
CMasterTemplate::SPropertyTemplatePath(rkTemplateFileName, pArchetype)
|
CMasterTemplate::SPropertyTemplatePath(rkTemplateFileName, pArchetype)
|
||||||
|
@ -498,7 +511,13 @@ CFlagsProperty* CTemplateLoader::LoadFlagsArchetype(const TString& rkTemplateFil
|
||||||
{
|
{
|
||||||
// Check whether this struct has already been read
|
// Check whether this struct has already been read
|
||||||
TString FlagsName = rkTemplateFileName.GetFileName(false);
|
TString FlagsName = rkTemplateFileName.GetFileName(false);
|
||||||
CFlagsProperty* pArchetype = mpMaster->FindFlagsArchetype(FlagsName);
|
CFlagsProperty* pArchetype = static_cast<CFlagsProperty*>( mpMaster->FindPropertyArchetype(FlagsName) );
|
||||||
|
|
||||||
|
// Names cannot be shared between multiple property archetypes
|
||||||
|
if (pArchetype != nullptr)
|
||||||
|
{
|
||||||
|
ASSERT(pArchetype->Type() == EPropertyTypeNew::Flags);
|
||||||
|
}
|
||||||
|
|
||||||
// If the enum template hasn't been read yet, then we read it and add it to master's list
|
// If the enum template hasn't been read yet, then we read it and add it to master's list
|
||||||
if (!pArchetype)
|
if (!pArchetype)
|
||||||
|
@ -517,6 +536,7 @@ CFlagsProperty* CTemplateLoader::LoadFlagsArchetype(const TString& rkTemplateFil
|
||||||
);
|
);
|
||||||
ASSERT(pArchetype != nullptr);
|
ASSERT(pArchetype != nullptr);
|
||||||
|
|
||||||
|
pArchetype->mName = rkTemplateFileName.GetFileName(false);
|
||||||
pArchetype->mFlags |= EPropertyFlag::IsArchetype;
|
pArchetype->mFlags |= EPropertyFlag::IsArchetype;
|
||||||
pArchetype->mSourceFile = rkTemplateFileName;
|
pArchetype->mSourceFile = rkTemplateFileName;
|
||||||
|
|
||||||
|
@ -529,7 +549,7 @@ CFlagsProperty* CTemplateLoader::LoadFlagsArchetype(const TString& rkTemplateFil
|
||||||
LoadBitFlags(pFlags, pArchetype, rkTemplateFileName);
|
LoadBitFlags(pFlags, pArchetype, rkTemplateFileName);
|
||||||
pArchetype->PostInitialize();
|
pArchetype->PostInitialize();
|
||||||
|
|
||||||
mpMaster->mFlagsTemplates.emplace(
|
mpMaster->mPropertyTemplates.emplace(
|
||||||
std::make_pair(
|
std::make_pair(
|
||||||
FlagsName,
|
FlagsName,
|
||||||
CMasterTemplate::SPropertyTemplatePath(rkTemplateFileName, pArchetype)
|
CMasterTemplate::SPropertyTemplatePath(rkTemplateFileName, pArchetype)
|
||||||
|
@ -1119,8 +1139,69 @@ TString CTemplateLoader::ErrorName(XMLError Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ PUBLIC ************
|
// ************ PUBLIC ************
|
||||||
|
#define USE_NEW_TEMPLATES 0
|
||||||
|
|
||||||
void CTemplateLoader::LoadGameList()
|
void CTemplateLoader::LoadGameList()
|
||||||
{
|
{
|
||||||
|
#if USE_NEW_TEMPLATES
|
||||||
|
const TString kTemplatesDir = "../templates_new/";
|
||||||
|
|
||||||
|
// Read game list
|
||||||
|
{
|
||||||
|
const TString kGameListPath = kTemplatesDir + "GameList.xml";
|
||||||
|
CXMLReader Reader(kGameListPath);
|
||||||
|
ASSERT(Reader.IsValid());
|
||||||
|
|
||||||
|
if (Reader.ParamBegin("Games", 0))
|
||||||
|
{
|
||||||
|
u32 NumGames;
|
||||||
|
Reader.SerializeArraySize(NumGames);
|
||||||
|
|
||||||
|
for (u32 GameIdx = 0; GameIdx < NumGames; GameIdx++)
|
||||||
|
{
|
||||||
|
if (Reader.ParamBegin("Game", 0))
|
||||||
|
{
|
||||||
|
EGame Game;
|
||||||
|
TString Name, MasterPath;
|
||||||
|
|
||||||
|
Reader << SerialParameter("ID", Game, SH_Attribute)
|
||||||
|
<< SerialParameter("Name", Name)
|
||||||
|
<< SerialParameter("MasterTemplate", MasterPath);
|
||||||
|
|
||||||
|
CMasterTemplate* pMaster = new CMasterTemplate();
|
||||||
|
pMaster->mGame = Game;
|
||||||
|
pMaster->mGameName = Name;
|
||||||
|
pMaster->mSourceFile = MasterPath;
|
||||||
|
CMasterTemplate::smMasterMap[Game] = pMaster;
|
||||||
|
Reader.ParamEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reader.ParamEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Read property list
|
||||||
|
const TString kPropertyMapPath = kTemplatesDir + "PropertyMap.xml";
|
||||||
|
CXMLReader Reader(kPropertyMapPath);
|
||||||
|
ASSERT(Reader.IsValid());
|
||||||
|
Reader << SerialParameter("PropertyMap", CMasterTemplate::smPropertyNames, SH_HexDisplay);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// Read master templates
|
||||||
|
std::list<CMasterTemplate*> MasterList = CMasterTemplate::MasterList();
|
||||||
|
|
||||||
|
for (auto Iter = MasterList.begin(); Iter != MasterList.end(); Iter++)
|
||||||
|
{
|
||||||
|
CMasterTemplate* pMaster = *Iter;
|
||||||
|
const TString kMasterPath = kTemplatesDir + pMaster->GetDirectory() + "Game.xml";
|
||||||
|
|
||||||
|
CXMLReader Reader(kMasterPath);
|
||||||
|
ASSERT(Reader.IsValid());
|
||||||
|
pMaster->Serialize(Reader);
|
||||||
|
pMaster->LoadSubTemplates();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
Log::Write("Loading game list");
|
Log::Write("Loading game list");
|
||||||
|
|
||||||
// Load Game List XML
|
// Load Game List XML
|
||||||
|
@ -1164,6 +1245,7 @@ void CTemplateLoader::LoadGameList()
|
||||||
|
|
||||||
pElem = pElem->NextSiblingElement();
|
pElem = pElem->NextSiblingElement();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTemplateLoader::LoadGameTemplates(EGame Game)
|
void CTemplateLoader::LoadGameTemplates(EGame Game)
|
||||||
|
@ -1247,10 +1329,10 @@ void CTemplateLoader::SaveGameList()
|
||||||
{
|
{
|
||||||
const TString kGameListPath = kTemplatesDir + "GameList.xml";
|
const TString kGameListPath = kTemplatesDir + "GameList.xml";
|
||||||
CXMLWriter Writer(kGameListPath, "GameList");
|
CXMLWriter Writer(kGameListPath, "GameList");
|
||||||
TString PropertyListPath = "PropertyNameMap.xml";
|
|
||||||
Writer << SerialParameter("PropertyList", PropertyListPath, 0);
|
|
||||||
|
|
||||||
|
u32 NumGames = CMasterTemplate::smMasterMap.size();
|
||||||
Writer.ParamBegin("Games", 0);
|
Writer.ParamBegin("Games", 0);
|
||||||
|
Writer.SerializeArraySize(NumGames);
|
||||||
|
|
||||||
for (auto Iter = CMasterTemplate::smMasterMap.begin(); Iter != CMasterTemplate::smMasterMap.end(); Iter++)
|
for (auto Iter = CMasterTemplate::smMasterMap.begin(); Iter != CMasterTemplate::smMasterMap.end(); Iter++)
|
||||||
{
|
{
|
||||||
|
@ -1272,7 +1354,7 @@ void CTemplateLoader::SaveGameList()
|
||||||
SGameInfo Info;
|
SGameInfo Info;
|
||||||
Info.Game = pMaster->Game();
|
Info.Game = pMaster->Game();
|
||||||
Info.Name = pMaster->GameName();
|
Info.Name = pMaster->GameName();
|
||||||
Info.MasterPath = pMaster->GetDirectory() + "MasterTemplate.xml";
|
Info.MasterPath = pMaster->GetDirectory() + "Game.xml";
|
||||||
Writer << SerialParameter("Game", Info);
|
Writer << SerialParameter("Game", Info);
|
||||||
}
|
}
|
||||||
Writer.ParamEnd();
|
Writer.ParamEnd();
|
||||||
|
|
|
@ -10,9 +10,7 @@ CMasterTemplate::CMasterTemplate()
|
||||||
void CMasterTemplate::Serialize(IArchive& Arc)
|
void CMasterTemplate::Serialize(IArchive& Arc)
|
||||||
{
|
{
|
||||||
Arc << SerialParameter("ScriptObjects", mScriptTemplates)
|
Arc << SerialParameter("ScriptObjects", mScriptTemplates)
|
||||||
<< SerialParameter("Structs", mStructTemplates)
|
<< SerialParameter("PropertyArchetypes", mPropertyTemplates)
|
||||||
<< SerialParameter("Enums", mEnumTemplates)
|
|
||||||
<< SerialParameter("Flags", mFlagsTemplates)
|
|
||||||
<< SerialParameter("States", mStates)
|
<< SerialParameter("States", mStates)
|
||||||
<< SerialParameter("Messages", mMessages);
|
<< SerialParameter("Messages", mMessages);
|
||||||
}
|
}
|
||||||
|
@ -36,33 +34,13 @@ void CMasterTemplate::SaveSubTemplates()
|
||||||
Path.pTemplate->Serialize(Writer);
|
Path.pTemplate->Serialize(Writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto Iter = mStructTemplates.begin(); Iter != mStructTemplates.end(); Iter++)
|
for (auto Iter = mPropertyTemplates.begin(); Iter != mPropertyTemplates.end(); Iter++)
|
||||||
{
|
{
|
||||||
SPropertyTemplatePath& Path = Iter->second;
|
SPropertyTemplatePath& Path = Iter->second;
|
||||||
TString OutPath = GameDir + Path.Path;
|
TString OutPath = GameDir + Path.Path;
|
||||||
|
|
||||||
FileUtil::MakeDirectory( OutPath.GetFileDirectory() );
|
FileUtil::MakeDirectory( OutPath.GetFileDirectory() );
|
||||||
CXMLWriter Writer(OutPath, "Struct", 0, Game());
|
CXMLWriter Writer(OutPath, "PropertyArchetype", 0, Game());
|
||||||
Path.pTemplate->Serialize(Writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto Iter = mEnumTemplates.begin(); Iter != mEnumTemplates.end(); Iter++)
|
|
||||||
{
|
|
||||||
SPropertyTemplatePath& Path = Iter->second;
|
|
||||||
TString OutPath = GameDir + Path.Path;
|
|
||||||
|
|
||||||
FileUtil::MakeDirectory( OutPath.GetFileDirectory() );
|
|
||||||
CXMLWriter Writer(OutPath, "Enum", 0, Game());
|
|
||||||
Path.pTemplate->Serialize(Writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto Iter = mFlagsTemplates.begin(); Iter != mFlagsTemplates.end(); Iter++)
|
|
||||||
{
|
|
||||||
SPropertyTemplatePath& Path = Iter->second;
|
|
||||||
TString OutPath = GameDir + Path.Path;
|
|
||||||
|
|
||||||
FileUtil::MakeDirectory( OutPath.GetFileDirectory() );
|
|
||||||
CXMLWriter Writer(OutPath, "Flags", 0, Game());
|
|
||||||
Path.pTemplate->Serialize(Writer);
|
Path.pTemplate->Serialize(Writer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,26 +115,10 @@ SMessage CMasterTemplate::MessageByIndex(u32 Index)
|
||||||
return SMessage(Iter->first, Iter->second);
|
return SMessage(Iter->first, Iter->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IPropertyNew* CMasterTemplate::FindPropertyArchetype(const TString& kTypeName) const
|
||||||
CStructPropertyNew* CMasterTemplate::FindStructArchetype(const TString& kStructName) const
|
|
||||||
{
|
{
|
||||||
auto Iter = mStructTemplates.find(kStructName);
|
auto Iter = mPropertyTemplates.find(kTypeName);
|
||||||
IPropertyNew* pProperty = (Iter != mStructTemplates.end()) ? Iter->second.pTemplate.get() : nullptr;
|
return (Iter != mPropertyTemplates.end()) ? Iter->second.pTemplate.get() : nullptr;
|
||||||
return TPropCast<CStructPropertyNew>(pProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
CEnumProperty* CMasterTemplate::FindEnumArchetype(const TString& kEnumName) const
|
|
||||||
{
|
|
||||||
auto Iter = mEnumTemplates.find(kEnumName);
|
|
||||||
IPropertyNew* pProperty = (Iter != mEnumTemplates.end()) ? Iter->second.pTemplate.get() : nullptr;
|
|
||||||
return TPropCast<CEnumProperty>(pProperty);
|
|
||||||
}
|
|
||||||
|
|
||||||
CFlagsProperty* CMasterTemplate::FindFlagsArchetype(const TString& kFlagsName) const
|
|
||||||
{
|
|
||||||
auto Iter = mFlagsTemplates.find(kFlagsName);
|
|
||||||
IPropertyNew* pProperty = (Iter != mFlagsTemplates.end()) ? Iter->second.pTemplate.get() : nullptr;
|
|
||||||
return TPropCast<CFlagsProperty>(pProperty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ STATIC ************
|
// ************ STATIC ************
|
||||||
|
|
|
@ -109,9 +109,7 @@ class CMasterTemplate
|
||||||
|
|
||||||
/** Template arrays */
|
/** Template arrays */
|
||||||
std::map<SObjId, SScriptTemplatePath> mScriptTemplates;
|
std::map<SObjId, SScriptTemplatePath> mScriptTemplates;
|
||||||
std::map<TString, SPropertyTemplatePath> mStructTemplates;
|
std::map<TString, SPropertyTemplatePath> mPropertyTemplates;
|
||||||
std::map<TString, SPropertyTemplatePath> mEnumTemplates;
|
|
||||||
std::map<TString, SPropertyTemplatePath> mFlagsTemplates;
|
|
||||||
|
|
||||||
std::map<SObjId, TString> mStates;
|
std::map<SObjId, TString> mStates;
|
||||||
std::map<SObjId, TString> mMessages;
|
std::map<SObjId, TString> mMessages;
|
||||||
|
@ -141,10 +139,7 @@ public:
|
||||||
SMessage MessageByID(u32 MessageID);
|
SMessage MessageByID(u32 MessageID);
|
||||||
SMessage MessageByID(const CFourCC& MessageID);
|
SMessage MessageByID(const CFourCC& MessageID);
|
||||||
SMessage MessageByIndex(u32 Index);
|
SMessage MessageByIndex(u32 Index);
|
||||||
|
IPropertyNew* FindPropertyArchetype(const TString& kTypeName) const;
|
||||||
CStructPropertyNew* FindStructArchetype(const TString& kStructName) const;
|
|
||||||
CEnumProperty* FindEnumArchetype(const TString& kEnumName) const;
|
|
||||||
CFlagsProperty* FindFlagsArchetype(const TString& kFlagsName) const;
|
|
||||||
|
|
||||||
// Inline Accessors
|
// Inline Accessors
|
||||||
inline EGame Game() const { return mGame; }
|
inline EGame Game() const { return mGame; }
|
||||||
|
|
|
@ -93,16 +93,41 @@ void* IPropertyNew::GetChildDataPointer(void* pPropertyData) const
|
||||||
|
|
||||||
void IPropertyNew::Serialize(IArchive& rArc)
|
void IPropertyNew::Serialize(IArchive& rArc)
|
||||||
{
|
{
|
||||||
if (rArc.Game() <= ePrime && !IsArchetype())
|
// Always serialize ID first! ID is always required (except for root properties, which have an ID of 0xFFFFFFFF)
|
||||||
|
// because they are needed to look up the correct property to apply parameter overrides to.
|
||||||
|
rArc << SerialParameter("ID", mID, SH_HexDisplay | SH_Attribute | SH_Optional, (u32) 0xFFFFFFFF);
|
||||||
|
|
||||||
|
// Now we can serialize the archetype reference and initialize if needed
|
||||||
|
if ( ((mpArchetype && mpArchetype->IsRootParent()) || rArc.IsReader()) && rArc.CanSkipParameters() )
|
||||||
{
|
{
|
||||||
rArc << SerialParameter("Name", mName);
|
TString ArchetypeName = (mpArchetype ? mpArchetype->Name() : "");
|
||||||
|
rArc << SerialParameter("Archetype", ArchetypeName, SH_Attribute);
|
||||||
|
|
||||||
|
if (rArc.IsReader() && !ArchetypeName.IsEmpty())
|
||||||
|
{
|
||||||
|
CMasterTemplate* pMaster = CMasterTemplate::MasterForGame( Game() );
|
||||||
|
IPropertyNew* pArchetype = pMaster->FindPropertyArchetype(ArchetypeName);
|
||||||
|
|
||||||
|
// The archetype must exist, or else the template file is malformed.
|
||||||
|
//@TODO: I think this will actually always fail right now, because property archetype loading has not been implemented yet
|
||||||
|
ASSERT(pArchetype != nullptr);
|
||||||
|
|
||||||
|
InitFromArchetype(pArchetype);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rArc << SerialParameter("ID", mID, SH_HexDisplay | SH_Attribute | SH_Optional, (u32) 0xFFFFFFFF)
|
// In MP1, the game data does not use property IDs, so we serialize the name directly.
|
||||||
<< SerialParameter("Description", mDescription, SH_Optional)
|
// In MP2 and on, property names are looked up based on the property ID via the property name map.
|
||||||
<< SerialParameter("CookPreference", mCookPreference, SH_Optional, ECookPreferenceNew::Default)
|
if (rArc.Game() <= ePrime && !IsArchetype())
|
||||||
<< SerialParameter("MinVersion", mMinVersion, SH_Optional, 0.f)
|
{
|
||||||
<< SerialParameter("MaxVersion", mMaxVersion, SH_Optional, FLT_MAX);
|
rArc << SerialParameter("Name", mName, mpArchetype ? SH_Optional : 0, mpArchetype ? mpArchetype->mName : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
rArc << SerialParameter("Description", mDescription, SH_Optional, mpArchetype ? mpArchetype->mDescription : "")
|
||||||
|
<< SerialParameter("CookPreference", mCookPreference, SH_Optional, mpArchetype ? mpArchetype->mCookPreference : ECookPreferenceNew::Default)
|
||||||
|
<< SerialParameter("MinVersion", mMinVersion, SH_Optional, mpArchetype ? mpArchetype->mMinVersion : 0.f)
|
||||||
|
<< SerialParameter("MaxVersion", mMaxVersion, SH_Optional, mpArchetype ? mpArchetype->mMaxVersion : FLT_MAX)
|
||||||
|
<< SerialParameter("Suffix", mSuffix, SH_Optional, mpArchetype ? mpArchetype->mSuffix : "");
|
||||||
|
|
||||||
// Children don't get serialized for most property types
|
// Children don't get serialized for most property types
|
||||||
}
|
}
|
||||||
|
@ -129,6 +154,17 @@ void IPropertyNew::InitFromArchetype(IPropertyNew* pOther)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IPropertyNew::ShouldSerialize() const
|
||||||
|
{
|
||||||
|
return mpArchetype == nullptr ||
|
||||||
|
mName != mpArchetype->mName ||
|
||||||
|
mDescription != mpArchetype->mDescription ||
|
||||||
|
mSuffix != mpArchetype->mSuffix ||
|
||||||
|
mCookPreference != mpArchetype->mCookPreference ||
|
||||||
|
mMinVersion != mpArchetype->mMinVersion ||
|
||||||
|
mMaxVersion != mpArchetype->mMaxVersion;
|
||||||
|
}
|
||||||
|
|
||||||
TString IPropertyNew::GetTemplateFileName()
|
TString IPropertyNew::GetTemplateFileName()
|
||||||
{
|
{
|
||||||
if (mpScriptTemplate)
|
if (mpScriptTemplate)
|
||||||
|
|
|
@ -184,6 +184,7 @@ public:
|
||||||
virtual void* GetChildDataPointer(void* pPropertyData) const;
|
virtual void* GetChildDataPointer(void* pPropertyData) const;
|
||||||
virtual void Serialize(IArchive& rArc);
|
virtual void Serialize(IArchive& rArc);
|
||||||
virtual void InitFromArchetype(IPropertyNew* pOther);
|
virtual void InitFromArchetype(IPropertyNew* pOther);
|
||||||
|
virtual bool ShouldSerialize() const;
|
||||||
virtual TString GetTemplateFileName();
|
virtual TString GetTemplateFileName();
|
||||||
|
|
||||||
/** Utility methods */
|
/** Utility methods */
|
||||||
|
@ -215,6 +216,7 @@ public:
|
||||||
inline bool IsArchetype() const { return mFlags.HasFlag(EPropertyFlag::IsArchetype); }
|
inline bool IsArchetype() const { return mFlags.HasFlag(EPropertyFlag::IsArchetype); }
|
||||||
inline bool IsArrayArchetype() const { return mFlags.HasFlag(EPropertyFlag::IsArrayArchetype); }
|
inline bool IsArrayArchetype() const { return mFlags.HasFlag(EPropertyFlag::IsArrayArchetype); }
|
||||||
inline bool IsAtomic() const { return mFlags.HasFlag(EPropertyFlag::IsAtomic); }
|
inline bool IsAtomic() const { return mFlags.HasFlag(EPropertyFlag::IsAtomic); }
|
||||||
|
inline bool IsRootParent() const { return mpParent == nullptr; }
|
||||||
|
|
||||||
/** Create */
|
/** Create */
|
||||||
static IPropertyNew* Create(EPropertyTypeNew Type,
|
static IPropertyNew* Create(EPropertyTypeNew Type,
|
||||||
|
@ -362,6 +364,11 @@ public:
|
||||||
return *ValuePtr(pData);
|
return *ValuePtr(pData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const PropType& DefaultValue() const
|
||||||
|
{
|
||||||
|
return mDefaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
inline static EPropertyTypeNew StaticType() { return PropEnum; }
|
inline static EPropertyTypeNew StaticType() { return PropEnum; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -377,13 +384,14 @@ public:
|
||||||
virtual void Serialize(IArchive& rArc)
|
virtual void Serialize(IArchive& rArc)
|
||||||
{
|
{
|
||||||
TTypedPropertyNew::Serialize(rArc);
|
TTypedPropertyNew::Serialize(rArc);
|
||||||
|
TSerializeableTypedProperty* pArchetype = static_cast<TSerializeableTypedProperty*>(mpArchetype);
|
||||||
|
|
||||||
// Determine if default value should be serialized as optional.
|
// Determine if default value should be serialized as optional.
|
||||||
// All MP1 properties should be optional. For MP2 and on, we set optional
|
// All MP1 properties should be optional. For MP2 and on, we set optional
|
||||||
// on property types that don't have default values in the game executable.
|
// on property types that don't have default values in the game executable.
|
||||||
bool MakeOptional = false;
|
bool MakeOptional = false;
|
||||||
|
|
||||||
if (Game() <= ePrime)
|
if (Game() <= ePrime || pArchetype != nullptr)
|
||||||
{
|
{
|
||||||
MakeOptional = true;
|
MakeOptional = true;
|
||||||
}
|
}
|
||||||
|
@ -405,11 +413,19 @@ public:
|
||||||
|
|
||||||
// Branch here to avoid constructing a default value if we don't need to.
|
// Branch here to avoid constructing a default value if we don't need to.
|
||||||
if (MakeOptional)
|
if (MakeOptional)
|
||||||
rArc << SerialParameter("DefaultValue", mDefaultValue, SH_Optional, GetSerializationDefaultValue());
|
rArc << SerialParameter("DefaultValue", mDefaultValue, SH_Optional, pArchetype ? pArchetype->mDefaultValue : GetSerializationDefaultValue());
|
||||||
else
|
else
|
||||||
rArc << SerialParameter("DefaultValue", mDefaultValue);
|
rArc << SerialParameter("DefaultValue", mDefaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool ShouldSerialize() const
|
||||||
|
{
|
||||||
|
TTypedPropertyNew* pArchetype = static_cast<TTypedPropertyNew*>(mpArchetype);
|
||||||
|
|
||||||
|
return TTypedPropertyNew::ShouldSerialize() ||
|
||||||
|
!(mDefaultValue == pArchetype->DefaultValue());
|
||||||
|
}
|
||||||
|
|
||||||
/** Return default value for serialization - can be customized per type */
|
/** Return default value for serialization - can be customized per type */
|
||||||
virtual PropType GetSerializationDefaultValue()
|
virtual PropType GetSerializationDefaultValue()
|
||||||
{
|
{
|
||||||
|
@ -437,8 +453,18 @@ public:
|
||||||
virtual void Serialize(IArchive& rArc)
|
virtual void Serialize(IArchive& rArc)
|
||||||
{
|
{
|
||||||
TSerializeableTypedProperty::Serialize(rArc);
|
TSerializeableTypedProperty::Serialize(rArc);
|
||||||
rArc << SerialParameter("Min", mMinValue, SH_Optional, (PropType) -1)
|
TNumericalPropertyNew* pArchetype = static_cast<TNumericalPropertyNew*>(mpArchetype);
|
||||||
<< SerialParameter("Max", mMaxValue, SH_Optional, (PropType) -1);
|
|
||||||
|
rArc << SerialParameter("Min", mMinValue, SH_Optional, pArchetype ? pArchetype->mMinValue : (PropType) -1)
|
||||||
|
<< SerialParameter("Max", mMaxValue, SH_Optional, pArchetype ? pArchetype->mMaxValue : (PropType) -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool ShouldSerialize() const
|
||||||
|
{
|
||||||
|
TNumericalPropertyNew* pArchetype = static_cast<TNumericalPropertyNew*>(mpArchetype);
|
||||||
|
return TSerializeableTypedProperty::ShouldSerialize() ||
|
||||||
|
mMinValue != pArchetype->mMinValue ||
|
||||||
|
mMaxValue != pArchetype->mMaxValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void InitFromArchetype(IPropertyNew* pOther)
|
virtual void InitFromArchetype(IPropertyNew* pOther)
|
||||||
|
|
|
@ -22,7 +22,15 @@ public:
|
||||||
virtual void Serialize(IArchive& rArc)
|
virtual void Serialize(IArchive& rArc)
|
||||||
{
|
{
|
||||||
TSerializeableTypedProperty::Serialize(rArc);
|
TSerializeableTypedProperty::Serialize(rArc);
|
||||||
rArc << SerialParameter("TypeFilter", mTypeFilter);
|
CAssetProperty* pArchetype = static_cast<CAssetProperty*>(mpArchetype);
|
||||||
|
rArc << SerialParameter("TypeFilter", mTypeFilter, pArchetype ? SH_Optional : 0, pArchetype ? pArchetype->mTypeFilter : CResTypeFilter());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool ShouldSerialize() const
|
||||||
|
{
|
||||||
|
CAssetProperty* pArchetype = static_cast<CAssetProperty*>(mpArchetype);
|
||||||
|
return TSerializeableTypedProperty::ShouldSerialize() ||
|
||||||
|
mTypeFilter != pArchetype->mTypeFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void InitFromArchetype(IPropertyNew* pOther)
|
virtual void InitFromArchetype(IPropertyNew* pOther)
|
||||||
|
|
|
@ -34,8 +34,8 @@ class TEnumPropertyBase : public TSerializeableTypedProperty<s32, TypeEnum>
|
||||||
|
|
||||||
void Serialize(IArchive& rArc)
|
void Serialize(IArchive& rArc)
|
||||||
{
|
{
|
||||||
rArc << SerialParameter("Name", Name)
|
rArc << SerialParameter("Name", Name, SH_Attribute)
|
||||||
<< SerialParameter("ID", ID, SH_HexDisplay);
|
<< SerialParameter("ID", ID, SH_Attribute | SH_HexDisplay);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
std::vector<SEnumValue> mValues;
|
std::vector<SEnumValue> mValues;
|
||||||
|
@ -57,8 +57,14 @@ public:
|
||||||
// Skip TSerializeableTypedProperty, serialize default value ourselves so we can set SH_HexDisplay
|
// Skip TSerializeableTypedProperty, serialize default value ourselves so we can set SH_HexDisplay
|
||||||
TTypedPropertyNew::Serialize(rArc);
|
TTypedPropertyNew::Serialize(rArc);
|
||||||
|
|
||||||
rArc << SerialParameter("DefaultValue", mDefaultValue, SH_HexDisplay | (Game() <= ePrime ? SH_Optional : 0))
|
TEnumPropertyBase* pArchetype = static_cast<TEnumPropertyBase*>(mpArchetype);
|
||||||
<< SerialParameter("Values", mValues);
|
u32 DefaultValueFlags = SH_HexDisplay | (pArchetype || Game() <= ePrime ? SH_Optional : 0);
|
||||||
|
rArc << SerialParameter("DefaultValue", mDefaultValue, DefaultValueFlags, pArchetype ? pArchetype->mDefaultValue : 0);
|
||||||
|
|
||||||
|
if (!pArchetype || !rArc.CanSkipParameters() || mValues != pArchetype->mValues)
|
||||||
|
{
|
||||||
|
rArc << SerialParameter("Values", mValues);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include "CFlagsProperty.h"
|
||||||
|
#include "Core/Resource/Script/CMasterTemplate.h"
|
||||||
|
|
||||||
|
void CFlagsProperty::Serialize(IArchive& rArc)
|
||||||
|
{
|
||||||
|
TSerializeableTypedProperty::Serialize(rArc);
|
||||||
|
|
||||||
|
CFlagsProperty* pArchetype = static_cast<CFlagsProperty*>(mpArchetype);
|
||||||
|
|
||||||
|
if (!pArchetype || !rArc.CanSkipParameters() || mBitFlags != pArchetype->mBitFlags)
|
||||||
|
{
|
||||||
|
rArc << SerialParameter("Flags", mBitFlags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFlagsProperty::PostInitialize()
|
||||||
|
{
|
||||||
|
TSerializeableTypedProperty::PostInitialize();
|
||||||
|
|
||||||
|
// Create AllFlags mask
|
||||||
|
mAllFlags = 0;
|
||||||
|
|
||||||
|
for (int FlagIdx = 0; FlagIdx < mBitFlags.size(); FlagIdx++)
|
||||||
|
mAllFlags |= mBitFlags[FlagIdx].Mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFlagsProperty::SerializeValue(void* pData, IArchive& rArc) const
|
||||||
|
{
|
||||||
|
rArc.SerializePrimitive( (u32&) ValueRef(pData), SH_HexDisplay );
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFlagsProperty::InitFromArchetype(IPropertyNew* pOther)
|
||||||
|
{
|
||||||
|
TSerializeableTypedProperty::InitFromArchetype(pOther);
|
||||||
|
CFlagsProperty* pOtherFlags = static_cast<CFlagsProperty*>(pOther);
|
||||||
|
mBitFlags = pOtherFlags->mBitFlags;
|
||||||
|
mAllFlags = pOtherFlags->mAllFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
TString CFlagsProperty::GetTemplateFileName()
|
||||||
|
{
|
||||||
|
ASSERT(IsArchetype() || mpArchetype);
|
||||||
|
return IsArchetype() ? mSourceFile : mpArchetype->GetTemplateFileName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether there are any unrecognized bits toggled on in the property value.
|
||||||
|
* Returns the mask of any invalid bits. If all bits are valid, returns 0.
|
||||||
|
*/
|
||||||
|
u32 CFlagsProperty::HasValidValue(void* pPropertyData)
|
||||||
|
{
|
||||||
|
return ValueRef(pPropertyData) & ~mAllFlags;
|
||||||
|
}
|
|
@ -28,8 +28,8 @@ class CFlagsProperty : public TSerializeableTypedProperty<u32, EPropertyTypeNew:
|
||||||
|
|
||||||
void Serialize(IArchive& rArc)
|
void Serialize(IArchive& rArc)
|
||||||
{
|
{
|
||||||
rArc << SerialParameter("Name", Name)
|
rArc << SerialParameter("Name", Name, SH_Attribute)
|
||||||
<< SerialParameter("Mask", Mask, SH_HexDisplay);
|
<< SerialParameter("Mask", Mask, SH_Attribute | SH_HexDisplay);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
std::vector<SBitFlag> mBitFlags;
|
std::vector<SBitFlag> mBitFlags;
|
||||||
|
@ -61,50 +61,17 @@ public:
|
||||||
return mBitFlags[Idx].Mask;
|
return mBitFlags[Idx].Mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void Serialize(IArchive& rArc)
|
virtual void Serialize(IArchive& rArc);
|
||||||
{
|
virtual void PostInitialize();
|
||||||
TSerializeableTypedProperty::Serialize(rArc);
|
virtual void SerializeValue(void* pData, IArchive& rArc) const;
|
||||||
rArc << SerialParameter("Flags", mBitFlags);
|
virtual void InitFromArchetype(IPropertyNew* pOther);
|
||||||
}
|
virtual TString GetTemplateFileName();
|
||||||
|
|
||||||
virtual void PostInitialize()
|
|
||||||
{
|
|
||||||
TTypedPropertyNew::PostInitialize();
|
|
||||||
|
|
||||||
// Create AllFlags mask
|
|
||||||
mAllFlags = 0;
|
|
||||||
|
|
||||||
for (int FlagIdx = 0; FlagIdx < mBitFlags.size(); FlagIdx++)
|
|
||||||
mAllFlags |= mBitFlags[FlagIdx].Mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void SerializeValue(void* pData, IArchive& rArc) const
|
|
||||||
{
|
|
||||||
rArc.SerializePrimitive( (u32&) ValueRef(pData), SH_HexDisplay );
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void InitFromArchetype(IPropertyNew* pOther)
|
|
||||||
{
|
|
||||||
TTypedPropertyNew::InitFromArchetype(pOther);
|
|
||||||
CFlagsProperty* pOtherFlags = static_cast<CFlagsProperty*>(pOther);
|
|
||||||
mBitFlags = pOtherFlags->mBitFlags;
|
|
||||||
mAllFlags = pOtherFlags->mAllFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual TString GetTemplateFileName()
|
|
||||||
{
|
|
||||||
ASSERT(IsArchetype() || mpArchetype);
|
|
||||||
return IsArchetype() ? mSourceFile : mpArchetype->GetTemplateFileName();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether there are any unrecognized bits toggled on in the property value.
|
* Checks whether there are any unrecognized bits toggled on in the property value.
|
||||||
* Returns the mask of any invalid bits. If all bits are valid, returns 0.
|
* Returns the mask of any invalid bits. If all bits are valid, returns 0.
|
||||||
*/
|
*/
|
||||||
u32 HasValidValue(void* pPropertyData)
|
u32 HasValidValue(void* pPropertyData);
|
||||||
{
|
|
||||||
return ValueRef(pPropertyData) & ~mAllFlags;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CFLAGSPROPERTY_H
|
#endif // CFLAGSPROPERTY_H
|
||||||
|
|
|
@ -0,0 +1,175 @@
|
||||||
|
#include "CStructProperty.h"
|
||||||
|
#include "Core/Resource/Script/CMasterTemplate.h"
|
||||||
|
|
||||||
|
EPropertyTypeNew CStructPropertyNew::Type() const
|
||||||
|
{
|
||||||
|
return EPropertyTypeNew::Struct;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 CStructPropertyNew::DataSize() const
|
||||||
|
{
|
||||||
|
if (!mChildren.empty())
|
||||||
|
{
|
||||||
|
IPropertyNew* pLastChild = mChildren.back();
|
||||||
|
return (pLastChild->Offset() - Offset()) + pLastChild->DataSize();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 CStructPropertyNew::DataAlignment() const
|
||||||
|
{
|
||||||
|
// TODO. Should be aligned with the first child, but this function is called before children are loaded.
|
||||||
|
// So for now just use 8 to ensure correct alignment for all child types, but this is wasteful...
|
||||||
|
// It's also problematic for casting property data to a struct
|
||||||
|
return 8;
|
||||||
|
|
||||||
|
//return (mChildren.empty() ? 1 : mChildren[0]->DataAlignment());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStructPropertyNew::Construct(void* pData) const
|
||||||
|
{
|
||||||
|
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||||
|
{
|
||||||
|
mChildren[ChildIdx]->Construct(pData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStructPropertyNew::Destruct(void* pData) const
|
||||||
|
{
|
||||||
|
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||||
|
{
|
||||||
|
mChildren[ChildIdx]->Destruct(pData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CStructPropertyNew::MatchesDefault(void* pData) const
|
||||||
|
{
|
||||||
|
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||||
|
{
|
||||||
|
if (!mChildren[ChildIdx]->MatchesDefault(pData))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStructPropertyNew::RevertToDefault(void* pData) const
|
||||||
|
{
|
||||||
|
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||||
|
{
|
||||||
|
mChildren[ChildIdx]->RevertToDefault(pData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* CStructPropertyNew::HashableTypeName() const
|
||||||
|
{
|
||||||
|
if (IsArchetype() || !mpArchetype)
|
||||||
|
return *mName;
|
||||||
|
else
|
||||||
|
return mpArchetype->HashableTypeName();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStructPropertyNew::Serialize(IArchive& rArc)
|
||||||
|
{
|
||||||
|
IPropertyNew::Serialize(rArc);
|
||||||
|
|
||||||
|
// Serialize archetype
|
||||||
|
if (mpArchetype)
|
||||||
|
{
|
||||||
|
CStructPropertyNew* pArchetype = static_cast<CStructPropertyNew*>(mpArchetype);
|
||||||
|
ASSERT(pArchetype != nullptr);
|
||||||
|
|
||||||
|
if (rArc.IsReader())
|
||||||
|
{
|
||||||
|
// We've initialized from the archetypes, now serialize parameter overrides
|
||||||
|
if (rArc.ParamBegin("SubProperties", 0))
|
||||||
|
{
|
||||||
|
u32 NumChildOverrides;
|
||||||
|
rArc.SerializeArraySize(NumChildOverrides);
|
||||||
|
|
||||||
|
for (u32 ChildIdx = 0; ChildIdx < NumChildOverrides; ChildIdx++)
|
||||||
|
{
|
||||||
|
if (rArc.ParamBegin("Element", SH_IgnoreName))
|
||||||
|
{
|
||||||
|
// Serialize type and ID, then look up the matching property and serialize it.
|
||||||
|
// We don't really need the type, but it's a good sanity check, and it's also helpful
|
||||||
|
// to guarantee that parameters are read in order, as some serializers are order-dependent.
|
||||||
|
EPropertyTypeNew ChildType;
|
||||||
|
u32 ChildID;
|
||||||
|
|
||||||
|
rArc << SerialParameter("Type", ChildType, SH_Attribute)
|
||||||
|
<< SerialParameter("ID", ChildID, SH_Attribute);
|
||||||
|
|
||||||
|
IPropertyNew* pChild = ChildByID(ChildID);
|
||||||
|
ASSERT(pChild != nullptr && pChild->Type() == ChildType);
|
||||||
|
pChild->Serialize(rArc);
|
||||||
|
|
||||||
|
rArc.ParamEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rArc.ParamEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Check if any properties need to override parameters from their archetype.
|
||||||
|
std::vector<IPropertyNew*> PropertiesToSerialize;
|
||||||
|
|
||||||
|
for (u32 ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||||
|
{
|
||||||
|
if (mChildren[ChildIdx]->ShouldSerialize())
|
||||||
|
{
|
||||||
|
PropertiesToSerialize.push_back(mChildren[ChildIdx]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 NumChildOverrides = PropertiesToSerialize.size();
|
||||||
|
|
||||||
|
if (NumChildOverrides > 0)
|
||||||
|
{
|
||||||
|
rArc << SerialParameter("SubProperties", PropertiesToSerialize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rArc << SerialParameter("SubProperties", mChildren);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CStructPropertyNew::SerializeValue(void* pData, IArchive& Arc) const
|
||||||
|
{
|
||||||
|
for (u32 ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||||
|
{
|
||||||
|
if (Arc.ParamBegin("Property", 0))
|
||||||
|
{
|
||||||
|
mChildren[ChildIdx]->SerializeValue(pData, Arc);
|
||||||
|
Arc.ParamEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CStructPropertyNew::ShouldSerialize() const
|
||||||
|
{
|
||||||
|
if (IPropertyNew::ShouldSerialize())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (u32 ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||||
|
{
|
||||||
|
if (mChildren[ChildIdx]->ShouldSerialize())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
TString CStructPropertyNew::GetTemplateFileName()
|
||||||
|
{
|
||||||
|
ASSERT(IsArchetype() || mpArchetype);
|
||||||
|
return IsArchetype() ? mTemplateFileName : mpArchetype->GetTemplateFileName();
|
||||||
|
}
|
|
@ -16,100 +16,18 @@ protected:
|
||||||
TString mTemplateFileName;
|
TString mTemplateFileName;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual EPropertyTypeNew Type() const
|
virtual EPropertyTypeNew Type() const;
|
||||||
{
|
virtual u32 DataSize() const;
|
||||||
return EPropertyTypeNew::Struct;
|
virtual u32 DataAlignment() const;
|
||||||
}
|
virtual void Construct(void* pData) const;
|
||||||
|
virtual void Destruct(void* pData) const;
|
||||||
virtual u32 DataSize() const
|
virtual bool MatchesDefault(void* pData) const;
|
||||||
{
|
virtual void RevertToDefault(void* pData) const;
|
||||||
if (!mChildren.empty())
|
virtual const char* HashableTypeName() const;
|
||||||
{
|
virtual void Serialize(IArchive& rArc);
|
||||||
IPropertyNew* pLastChild = mChildren.back();
|
virtual void SerializeValue(void* pData, IArchive& Arc) const;
|
||||||
return (pLastChild->Offset() - Offset()) + pLastChild->DataSize();
|
virtual bool ShouldSerialize() const;
|
||||||
}
|
virtual TString GetTemplateFileName();
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual u32 DataAlignment() const
|
|
||||||
{
|
|
||||||
// TODO. Should be aligned with the first child, but this function is called before children are loaded.
|
|
||||||
// So for now just use 8 to ensure correct alignment for all child types, but this is wasteful...
|
|
||||||
return 8;
|
|
||||||
|
|
||||||
//return (mChildren.empty() ? 1 : mChildren[0]->DataAlignment());
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Construct(void* pData) const
|
|
||||||
{
|
|
||||||
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
|
||||||
{
|
|
||||||
mChildren[ChildIdx]->Construct(pData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Destruct(void* pData) const
|
|
||||||
{
|
|
||||||
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
|
||||||
{
|
|
||||||
mChildren[ChildIdx]->Destruct(pData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool MatchesDefault(void* pData) const
|
|
||||||
{
|
|
||||||
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
|
||||||
{
|
|
||||||
if (!mChildren[ChildIdx]->MatchesDefault(pData))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void RevertToDefault(void* pData) const
|
|
||||||
{
|
|
||||||
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
|
||||||
{
|
|
||||||
mChildren[ChildIdx]->RevertToDefault(pData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual const char* HashableTypeName() const
|
|
||||||
{
|
|
||||||
if (IsArchetype() || !mpArchetype)
|
|
||||||
return *mName;
|
|
||||||
else
|
|
||||||
return mpArchetype->HashableTypeName();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Serialize(IArchive& rArc)
|
|
||||||
{
|
|
||||||
IPropertyNew::Serialize(rArc);
|
|
||||||
rArc << SerialParameter("SubProperties", mChildren);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
|
||||||
{
|
|
||||||
for (u32 ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
|
||||||
{
|
|
||||||
if (Arc.ParamBegin("Property", 0))
|
|
||||||
{
|
|
||||||
mChildren[ChildIdx]->SerializeValue(pData, Arc);
|
|
||||||
Arc.ParamEnd();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual TString GetTemplateFileName()
|
|
||||||
{
|
|
||||||
ASSERT(IsArchetype() || mpArchetype);
|
|
||||||
return IsArchetype() ? mTemplateFileName : mpArchetype->GetTemplateFileName();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static EPropertyTypeNew StaticType() { return EPropertyTypeNew::Struct; }
|
inline static EPropertyTypeNew StaticType() { return EPropertyTypeNew::Struct; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,7 +25,7 @@ CExportGameDialog::CExportGameDialog(const QString& rkIsoPath, const QString& rk
|
||||||
, mpExporter(nullptr)
|
, mpExporter(nullptr)
|
||||||
, mDiscType(eDT_Normal)
|
, mDiscType(eDT_Normal)
|
||||||
, mGame(eUnknownGame)
|
, mGame(eUnknownGame)
|
||||||
, mRegion(eRegion_Unknown)
|
, mRegion(ERegion::Unknown)
|
||||||
, mBuildVer(0.f)
|
, mBuildVer(0.f)
|
||||||
, mWiiFrontend(false)
|
, mWiiFrontend(false)
|
||||||
, mExportSuccess(false)
|
, mExportSuccess(false)
|
||||||
|
@ -85,8 +85,7 @@ void CExportGameDialog::InitUI(QString ExportDir)
|
||||||
mpUI->GameTitleLineEdit->setText( TO_QSTRING(mGameTitle) );
|
mpUI->GameTitleLineEdit->setText( TO_QSTRING(mGameTitle) );
|
||||||
mpUI->GameIdLineEdit->setText( TO_QSTRING(mGameID) );
|
mpUI->GameIdLineEdit->setText( TO_QSTRING(mGameID) );
|
||||||
mpUI->BuildVersionLineEdit->setText( QString("%1 (%2)").arg(mBuildVer).arg( TO_QSTRING(GameInfo.GetBuildName(mBuildVer, mRegion)) ));
|
mpUI->BuildVersionLineEdit->setText( QString("%1 (%2)").arg(mBuildVer).arg( TO_QSTRING(GameInfo.GetBuildName(mBuildVer, mRegion)) ));
|
||||||
mpUI->RegionLineEdit->setText( mRegion == eRegion_NTSC ? "NTSC" :
|
mpUI->RegionLineEdit->setText( GetRegionName(mRegion) );
|
||||||
mRegion == eRegion_PAL ? "PAL" : "JPN" );
|
|
||||||
|
|
||||||
// Disc tree widget
|
// Disc tree widget
|
||||||
nod::IPartition *pPartition = mpDisc->getDataPartition();
|
nod::IPartition *pPartition = mpDisc->getDataPartition();
|
||||||
|
@ -126,15 +125,15 @@ bool CExportGameDialog::ValidateGame()
|
||||||
switch (mGameID[3])
|
switch (mGameID[3])
|
||||||
{
|
{
|
||||||
case 'E':
|
case 'E':
|
||||||
mRegion = eRegion_NTSC;
|
mRegion = ERegion::NTSC;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
mRegion = eRegion_PAL;
|
mRegion = ERegion::PAL;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'J':
|
case 'J':
|
||||||
mRegion = eRegion_JPN;
|
mRegion = ERegion::JPN;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -306,6 +306,7 @@ FORMS += \
|
||||||
CGeneratePropertyNamesDialog.ui
|
CGeneratePropertyNamesDialog.ui
|
||||||
|
|
||||||
# Codegen
|
# Codegen
|
||||||
|
CODEGEN_DIR = $$EXTERNALS_DIR/CodeGen
|
||||||
CODEGEN_OUT_PATH = $$BUILD_DIR/Editor/codegen_build/auto_codegen.cpp
|
CODEGEN_OUT_PATH = $$BUILD_DIR/Editor/codegen_build/auto_codegen.cpp
|
||||||
CODEGEN_SRC_PATH = $$PWD
|
CODEGEN_SRC_PATH = $$PWD
|
||||||
include($$EXTERNALS_DIR/CodeGen/codegen.pri)
|
include($$EXTERNALS_DIR/CodeGen/codegen.pri)
|
||||||
|
|
|
@ -80,6 +80,7 @@ SOURCES += \
|
||||||
MathUtil.cpp
|
MathUtil.cpp
|
||||||
|
|
||||||
# Codegen
|
# Codegen
|
||||||
|
CODEGEN_DIR = $$EXTERNALS_DIR/CodeGen
|
||||||
CODEGEN_OUT_PATH = $$BUILD_DIR/Common/codegen_build/auto_codegen.cpp
|
CODEGEN_OUT_PATH = $$BUILD_DIR/Common/codegen_build/auto_codegen.cpp
|
||||||
CODEGEN_SRC_PATH = $$PWD
|
CODEGEN_SRC_PATH = $$PWD
|
||||||
include($$EXTERNALS_DIR/CodeGen/codegen.pri)
|
include($$EXTERNALS_DIR/CodeGen/codegen.pri)
|
||||||
|
|
Loading…
Reference in New Issue