WIP script object template serialization
This commit is contained in:
parent
5182f436b8
commit
36926ca28e
|
@ -9,13 +9,13 @@ namespace NBasics
|
|||
|
||||
/** Remove an element from a vector */
|
||||
template<typename T>
|
||||
bool VectorRemoveOne(std::vector<T>& rVector, const T& rkElement)
|
||||
bool VectorRemoveOne(std::vector<T>& Vector, const T& kElement)
|
||||
{
|
||||
for (auto Iter = rVector.begin(); Iter != rVector.end(); Iter++)
|
||||
for (auto Iter = Vector.begin(); Iter != Vector.end(); Iter++)
|
||||
{
|
||||
if (*Iter == rkElement)
|
||||
if (*Iter == kElement)
|
||||
{
|
||||
rVector.erase(Iter);
|
||||
Vector.erase(Iter);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -24,15 +24,15 @@ bool VectorRemoveOne(std::vector<T>& rVector, const T& rkElement)
|
|||
|
||||
/** Remove all occurrences of an element from a vector. Returns the number of elements that were removed. */
|
||||
template<typename T>
|
||||
int VectorRemoveAll(std::vector<T>& rVector, const T& rkElement)
|
||||
int VectorRemoveAll(std::vector<T>& Vector, const T& kElement)
|
||||
{
|
||||
int NumRemoved = 0;
|
||||
|
||||
for (auto Iter = rVector.begin(); Iter != rVector.end(); Iter++)
|
||||
for (auto Iter = Vector.begin(); Iter != Vector.end(); Iter++)
|
||||
{
|
||||
if (*Iter == rkElement)
|
||||
if (*Iter == kElement)
|
||||
{
|
||||
Iter = rVector.erase(Iter);
|
||||
Iter = Vector.erase(Iter);
|
||||
NumRemoved++;
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,34 @@ int VectorRemoveAll(std::vector<T>& rVector, const T& rkElement)
|
|||
return NumRemoved;
|
||||
}
|
||||
|
||||
/** Returns whether the vector contains the given element */
|
||||
template<typename T>
|
||||
bool VectorContains(std::vector<T>& Vector, const T& kElement)
|
||||
{
|
||||
for (auto Iter = Vector.begin(); Iter != Vector.end(); Iter++)
|
||||
{
|
||||
if (*Iter == kElement)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Adds an element to a vector only if it is not already present */
|
||||
template<typename T>
|
||||
bool VectorAddUnique(std::vector<T>& Vector, const T& kElement)
|
||||
{
|
||||
if (!VectorContainsElement(Vector, kElement))
|
||||
{
|
||||
Vector.push_back(kElement);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // NBASICS_H
|
||||
|
|
|
@ -57,22 +57,24 @@
|
|||
/** ESerialHint - Parameter hint flags */
|
||||
enum ESerialHint
|
||||
{
|
||||
SH_HexDisplay = 0x1, // The parameter should be written in hex in text formats
|
||||
SH_Optional = 0x2, // The parameter should not be written to the file if its value matches the default value
|
||||
SH_NeverSave = 0x4, // The parameter should not be saved to files
|
||||
SH_AlwaysSave = 0x8, // The parameter should always be saved regardless of if it matches the default value
|
||||
SH_HexDisplay = 0x1, // The parameter should be written in hex in text formats.
|
||||
SH_Optional = 0x2, // The parameter should not be written to the file if its value matches the default value.
|
||||
SH_NeverSave = 0x4, // The parameter should not be saved to files.
|
||||
SH_AlwaysSave = 0x8, // The parameter should always be saved regardless of if it matches the default value.
|
||||
SH_Attribute = 0x10, // The parameter is an attribute of another parameter. Attributes cannot have children.
|
||||
SH_IgnoreName = 0x20, // The parameter name will not be used to validate file data. May yield incorrect results if used improperly!
|
||||
SH_InheritHints = 0x40, // The parameter will inherit hints from its parent parameter (except for this flag).
|
||||
SH_Proxy = 0x80, // The parameter is a proxy of the parent and will display inline instead of as a child parameter.
|
||||
};
|
||||
|
||||
/** EArchiveFlags */
|
||||
enum EArchiveFlags
|
||||
{
|
||||
AF_Reader = 0x1, // Archive reads data
|
||||
AF_Writer = 0x2, // Archive writes data
|
||||
AF_Text = 0x4, // Archive reads/writes to a text format
|
||||
AF_Binary = 0x8, // Archive reads/writes to a binary format
|
||||
AF_NoSkipping = 0x10, // Properties are never skipped
|
||||
AF_Reader = 0x1, // Archive reads data.
|
||||
AF_Writer = 0x2, // Archive writes data.
|
||||
AF_Text = 0x4, // Archive reads/writes to a text format.
|
||||
AF_Binary = 0x8, // Archive reads/writes to a binary format.
|
||||
AF_NoSkipping = 0x10, // Properties are never skipped.
|
||||
};
|
||||
|
||||
/** Shortcut macro for enable_if */
|
||||
|
@ -128,7 +130,14 @@ inline ParameterMatchesDefault( const TSerialParameter<ValType>& kParameter )
|
|||
}
|
||||
|
||||
template<typename ValType>
|
||||
ENABLE_IF( !SUPPORTS_DEFAULT_VALUES, bool )
|
||||
ENABLE_IF( !SUPPORTS_DEFAULT_VALUES && TIsContainer<ValType>::value, bool )
|
||||
inline ParameterMatchesDefault( const TSerialParameter<ValType>& kParameter )
|
||||
{
|
||||
return kParameter.rValue.size() == 0;
|
||||
}
|
||||
|
||||
template<typename ValType>
|
||||
ENABLE_IF( !SUPPORTS_DEFAULT_VALUES && !TIsContainer<ValType>::value, bool )
|
||||
inline ParameterMatchesDefault( const TSerialParameter<ValType>& )
|
||||
{
|
||||
return false;
|
||||
|
@ -149,7 +158,15 @@ inline InitParameterToDefault( TSerialParameter<ValType>& Param )
|
|||
}
|
||||
|
||||
template<typename ValType>
|
||||
ENABLE_IF( !SUPPORTS_DEFAULT_VALUES, bool )
|
||||
ENABLE_IF( !SUPPORTS_DEFAULT_VALUES && TIsContainer<ValType>::value, bool )
|
||||
inline InitParameterToDefault( TSerialParameter<ValType>& Param )
|
||||
{
|
||||
Param.rValue.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename ValType>
|
||||
ENABLE_IF( !SUPPORTS_DEFAULT_VALUES && !TIsContainer<ValType>::value, bool )
|
||||
inline InitParameterToDefault( TSerialParameter<ValType>& )
|
||||
{
|
||||
return false;
|
||||
|
@ -266,7 +283,6 @@ public:
|
|||
|
||||
virtual ~IArchive() {}
|
||||
|
||||
protected:
|
||||
// Serialize archive version. Always call after opening a file.
|
||||
void SerializeVersion()
|
||||
{
|
||||
|
@ -275,6 +291,25 @@ protected:
|
|||
<< SerialParameter("Game", mGame, SH_Attribute | SH_Optional, eUnknownGame);
|
||||
}
|
||||
|
||||
private:
|
||||
// Attempts to start a new parameter. Return whether the parameter should be serialized.
|
||||
template<typename ValType>
|
||||
bool InternalStartParam(const TSerialParameter<ValType>& Param)
|
||||
{
|
||||
bool IsProxy = (Param.HintFlags & SH_Proxy) != 0;
|
||||
return ShouldSerializeParameter(Param) && (IsProxy || ParamBegin(Param.pkName, Param.HintFlags) );
|
||||
}
|
||||
|
||||
// Ends a parameter.
|
||||
template<typename ValType>
|
||||
void InternalEndParam(const TSerialParameter<ValType>& Param)
|
||||
{
|
||||
if ((Param.HintFlags & SH_Proxy) == 0)
|
||||
{
|
||||
ParamEnd();
|
||||
}
|
||||
}
|
||||
|
||||
// Return whether this parameter should be serialized
|
||||
template<typename ValType>
|
||||
bool ShouldSerializeParameter(const TSerialParameter<ValType>& Param)
|
||||
|
@ -318,7 +353,7 @@ protected:
|
|||
|
||||
// Parameter stack handling
|
||||
template<typename ValType>
|
||||
inline void PushParameter(const TSerialParameter<ValType>& Param)
|
||||
inline void PushParameter(TSerialParameter<ValType>& Param)
|
||||
{
|
||||
#if _DEBUG
|
||||
if (mParmStack.size() > 0)
|
||||
|
@ -328,6 +363,13 @@ protected:
|
|||
}
|
||||
#endif
|
||||
|
||||
// For InheritHints parameters, and for proxy parameters, copy the hint flags from the parent parameter.
|
||||
if (Param.HintFlags & (SH_InheritHints | SH_Proxy))
|
||||
{
|
||||
Param.HintFlags |= mParmStack.back().HintFlags;
|
||||
Param.HintFlags &= ~SH_InheritHints;
|
||||
}
|
||||
|
||||
SParmStackEntry Entry;
|
||||
Entry.TypeID = typeid(ValType).hash_code();
|
||||
Entry.TypeSize = sizeof(ValType);
|
||||
|
@ -357,11 +399,10 @@ public:
|
|||
{
|
||||
PushParameter(rParam);
|
||||
|
||||
if (ShouldSerializeParameter(rParam)
|
||||
&& ParamBegin(rParam.pkName, rParam.HintFlags))
|
||||
if (InternalStartParam(rParam))
|
||||
{
|
||||
SerializePrimitive(rParam.rValue, rParam.HintFlags);
|
||||
ParamEnd();
|
||||
InternalEndParam(rParam);
|
||||
}
|
||||
else if (IsReader())
|
||||
InitParameterToDefault(rParam);
|
||||
|
@ -377,8 +418,7 @@ public:
|
|||
ASSERT( !(mArchiveFlags & AF_Writer) || rParam.rValue != nullptr );
|
||||
PushParameter(rParam);
|
||||
|
||||
if (ShouldSerializeParameter(rParam)
|
||||
&& ParamBegin(rParam.pkName, rParam.HintFlags))
|
||||
if (InternalStartParam(rParam))
|
||||
{
|
||||
// Support for old versions of archives that serialize types on non-abstract polymorphic pointers
|
||||
if (ArchiveVersion() < eArVer_Refactor && IsReader() && std::is_polymorphic_v<ValType>)
|
||||
|
@ -398,7 +438,7 @@ public:
|
|||
else if (IsReader())
|
||||
rParam.rValue = nullptr;
|
||||
|
||||
ParamEnd();
|
||||
InternalEndParam(rParam);
|
||||
}
|
||||
|
||||
PopParameter(rParam);
|
||||
|
@ -412,11 +452,10 @@ public:
|
|||
{
|
||||
PushParameter(rParam);
|
||||
|
||||
if (ShouldSerializeParameter(rParam)
|
||||
&& ParamBegin(rParam.pkName, rParam.HintFlags))
|
||||
if (InternalStartParam(rParam))
|
||||
{
|
||||
Serialize(*this, rParam.rValue);
|
||||
ParamEnd();
|
||||
InternalEndParam(rParam);
|
||||
}
|
||||
else if (IsReader())
|
||||
InitParameterToDefault(rParam);
|
||||
|
@ -432,8 +471,7 @@ public:
|
|||
ASSERT( !IsWriter() || rParam.rValue != nullptr );
|
||||
PushParameter(rParam);
|
||||
|
||||
if (ShouldSerializeParameter(rParam)
|
||||
&& ParamBegin(rParam.pkName))
|
||||
if (InternalStartParam(rParam))
|
||||
{
|
||||
// Support for old versions of archives that serialize types on non-abstract polymorphic pointers
|
||||
if (ArchiveVersion() < eArVer_Refactor && IsReader() && std::is_polymorphic_v<ValType>)
|
||||
|
@ -453,7 +491,7 @@ public:
|
|||
else if (IsReader())
|
||||
rParam.rValue = nullptr;
|
||||
|
||||
ParamEnd();
|
||||
InternalEndParam(rParam);
|
||||
}
|
||||
|
||||
PopParameter(rParam);
|
||||
|
@ -467,11 +505,10 @@ public:
|
|||
{
|
||||
PushParameter(rParam);
|
||||
|
||||
if (ShouldSerializeParameter(rParam) &&
|
||||
ParamBegin(rParam.pkName, rParam.HintFlags))
|
||||
if (InternalStartParam(rParam))
|
||||
{
|
||||
rParam.rValue.Serialize(*this);
|
||||
ParamEnd();
|
||||
InternalEndParam(rParam);
|
||||
}
|
||||
else if (IsReader())
|
||||
InitParameterToDefault(rParam);
|
||||
|
@ -486,8 +523,7 @@ public:
|
|||
{
|
||||
PushParameter(rParam);
|
||||
|
||||
if (ShouldSerializeParameter(rParam) &&
|
||||
ParamBegin(rParam.pkName, rParam.HintFlags))
|
||||
if (InternalStartParam(rParam))
|
||||
{
|
||||
// Support for old versions of archives that serialize types on non-abstract polymorphic pointers
|
||||
if (ArchiveVersion() < eArVer_Refactor && IsReader() && std::is_polymorphic_v<ValType>)
|
||||
|
@ -507,7 +543,7 @@ public:
|
|||
else if (IsReader())
|
||||
rParam.rValue = nullptr;
|
||||
|
||||
ParamEnd();
|
||||
InternalEndParam(rParam);
|
||||
}
|
||||
|
||||
PopParameter(rParam);
|
||||
|
@ -521,8 +557,7 @@ public:
|
|||
{
|
||||
PushParameter(rParam);
|
||||
|
||||
if (ShouldSerializeParameter(rParam) &&
|
||||
ParamBegin(rParam.pkName, rParam.HintFlags))
|
||||
if (InternalStartParam(rParam))
|
||||
{
|
||||
if (PreSerializePointer( (void*&) rParam.rValue, rParam.HintFlags ))
|
||||
{
|
||||
|
@ -560,7 +595,7 @@ public:
|
|||
else if (IsReader())
|
||||
rParam.rValue = nullptr;
|
||||
|
||||
ParamEnd();
|
||||
InternalEndParam(rParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -664,11 +699,36 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/** Function that serializes a value directly */
|
||||
template<typename ValType>
|
||||
ENABLE_IF( IS_SERIAL_TYPE(Primitive), IArchive& )
|
||||
inline SerializeDirect(IArchive& Arc, ValType& Value)
|
||||
{
|
||||
Arc.SerializePrimitive(Value, SH_InheritHints);
|
||||
return Arc;
|
||||
}
|
||||
|
||||
template<typename ValType>
|
||||
ENABLE_IF( IS_SERIAL_TYPE(Global), IArchive& )
|
||||
inline SerializeDirect(IArchive& Arc, ValType& Value)
|
||||
{
|
||||
Serialize(Arc, Value);
|
||||
return Arc;
|
||||
}
|
||||
|
||||
template<typename ValType>
|
||||
ENABLE_IF( IS_SERIAL_TYPE(Member), IArchive& )
|
||||
inline SerializeDirect(IArchive& Arc, ValType& Value)
|
||||
{
|
||||
Value.Serialize(Arc);
|
||||
return Arc;
|
||||
}
|
||||
|
||||
#if WITH_CODEGEN
|
||||
// Default enum serializer; can be overridden
|
||||
#include <codegen/EnumReflection.h>
|
||||
|
||||
template<typename T, typename = typename std::enable_if<std::is_enum<T>::value>::type>
|
||||
template<typename T, typename = typename std::enable_if< std::is_enum<T>::value >::type>
|
||||
inline void Serialize(IArchive& Arc, T& Val)
|
||||
{
|
||||
if (Arc.IsTextFormat())
|
||||
|
@ -709,7 +769,7 @@ inline void Serialize(IArchive& Arc, std::vector<T>& Vector)
|
|||
for (u32 i = 0; i < Size; i++)
|
||||
{
|
||||
// SH_IgnoreName to preserve compatibility with older files that may have differently-named items
|
||||
Arc << SerialParameter("Item", Vector[i], SH_IgnoreName);
|
||||
Arc << SerialParameter("Element", Vector[i], SH_IgnoreName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -742,7 +802,7 @@ inline void Serialize(IArchive& Arc, std::list<T>& List)
|
|||
}
|
||||
|
||||
for (auto Iter = List.begin(); Iter != List.end(); Iter++)
|
||||
Arc << SerialParameter("Item", *Iter, SH_IgnoreName);
|
||||
Arc << SerialParameter("Element", *Iter, SH_IgnoreName);
|
||||
}
|
||||
|
||||
// Overload for TStringList and TWideStringList so they can use the TString/TWideString serialize functions
|
||||
|
@ -770,7 +830,7 @@ inline void Serialize(IArchive& Arc, std::set<T>& Set)
|
|||
for (u32 i = 0; i < Size; i++)
|
||||
{
|
||||
T Val;
|
||||
Arc << SerialParameter("Item", Val, SH_IgnoreName);
|
||||
Arc << SerialParameter("Element", Val, SH_IgnoreName);
|
||||
Set.insert(Val);
|
||||
}
|
||||
}
|
||||
|
@ -780,7 +840,7 @@ inline void Serialize(IArchive& Arc, std::set<T>& Set)
|
|||
for (auto Iter = Set.begin(); Iter != Set.end(); Iter++)
|
||||
{
|
||||
T Val = *Iter;
|
||||
Arc << SerialParameter("Item", Val, SH_IgnoreName);
|
||||
Arc << SerialParameter("Element", Val, SH_IgnoreName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -799,7 +859,7 @@ inline void SerializeMap_Internal(IArchive& Arc, MapType& Map)
|
|||
KeyType Key;
|
||||
ValType Val;
|
||||
|
||||
if (Arc.ParamBegin("Item", SH_IgnoreName))
|
||||
if (Arc.ParamBegin("Element", SH_IgnoreName))
|
||||
{
|
||||
Arc << SerialParameter("Key", Key, SH_IgnoreName)
|
||||
<< SerialParameter("Value", Val, SH_IgnoreName);
|
||||
|
@ -820,7 +880,7 @@ inline void SerializeMap_Internal(IArchive& Arc, MapType& Map)
|
|||
KeyType Key = Iter->first;
|
||||
ValType Val = Iter->second;
|
||||
|
||||
if (Arc.ParamBegin("Item", SH_IgnoreName))
|
||||
if (Arc.ParamBegin("Element", SH_IgnoreName))
|
||||
{
|
||||
Arc << SerialParameter("Key", Key, SH_IgnoreName)
|
||||
<< SerialParameter("Value", Val, SH_IgnoreName);
|
||||
|
@ -843,6 +903,27 @@ inline void Serialize(IArchive& Arc, std::unordered_map<KeyType, ValType>& Map)
|
|||
SerializeMap_Internal<KeyType, ValType, std::unordered_map<KeyType, ValType> >(Arc, Map);
|
||||
}
|
||||
|
||||
// Smart pointer serialize methods
|
||||
template<typename T>
|
||||
void Serialize(IArchive& Arc, std::unique_ptr<T>& Pointer)
|
||||
{
|
||||
T* pRawPtr = Pointer.get();
|
||||
Arc << SerialParameter("RawPointer", pRawPtr, SH_Proxy);
|
||||
|
||||
if (Arc.IsReader())
|
||||
Pointer = std::unique_ptr<T>(pRawPtr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Serialize(IArchive& Arc, std::shared_ptr<T>& Pointer)
|
||||
{
|
||||
T* pRawPtr = Pointer.get();
|
||||
Arc << SerialParameter("RawPointer", pRawPtr, SH_Proxy);
|
||||
|
||||
if (Arc.IsReader())
|
||||
Pointer = std::shared_ptr<T>(pRawPtr);
|
||||
}
|
||||
|
||||
// Remove header-only macros
|
||||
#undef ENABLE_IF
|
||||
#undef SUPPORTS_DEFAULT_VALUES
|
||||
|
|
|
@ -50,7 +50,7 @@ public:
|
|||
void Serialize(IArchive& rArc)
|
||||
{
|
||||
if (rArc.IsReader()) mGame = rArc.Game();
|
||||
rArc << SerialParameter("AcceptedTypes", mAcceptedTypes);
|
||||
rArc << SerialParameter("AcceptedTypes", mAcceptedTypes, SH_Proxy);
|
||||
}
|
||||
|
||||
inline bool Accepts(EResType Type) const
|
||||
|
|
|
@ -375,8 +375,8 @@ IPropertyNew* CTemplateLoader::LoadProperty(XMLElement* pElem, CScriptTemplate*
|
|||
CStructPropertyNew* CTemplateLoader::LoadStructArchetype(const TString& rkTemplateFileName)
|
||||
{
|
||||
// Check whether this struct has already been read
|
||||
auto it = mpMaster->mStructTemplates.find(rkTemplateFileName);
|
||||
CStructPropertyNew* pArchetype = (it == mpMaster->mStructTemplates.end() ? nullptr : it->second);
|
||||
TString StructName = rkTemplateFileName.GetFileName(false);
|
||||
CStructPropertyNew* pArchetype = mpMaster->FindStructArchetype(StructName);
|
||||
|
||||
// If the struct template hasn't been read yet, then we read it and add it to master's list
|
||||
if (!pArchetype)
|
||||
|
@ -432,8 +432,13 @@ CStructPropertyNew* CTemplateLoader::LoadStructArchetype(const TString& rkTempla
|
|||
ASSERT(pSubPropsElem);
|
||||
|
||||
LoadProperties(pSubPropsElem, nullptr, pArchetype, rkTemplateFileName);
|
||||
mpMaster->mStructTemplates[rkTemplateFileName] = pArchetype;
|
||||
pArchetype->PostInitialize();
|
||||
|
||||
mpMaster->mStructTemplates.emplace(
|
||||
std::make_pair(
|
||||
StructName,
|
||||
CMasterTemplate::SPropertyTemplatePath(rkTemplateFileName, pArchetype)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,8 +449,8 @@ CStructPropertyNew* CTemplateLoader::LoadStructArchetype(const TString& rkTempla
|
|||
CEnumProperty* CTemplateLoader::LoadEnumArchetype(const TString& rkTemplateFileName, bool bIsChoice)
|
||||
{
|
||||
// Check whether this struct has already been read
|
||||
auto it = mpMaster->mEnumTemplates.find(rkTemplateFileName);
|
||||
CEnumProperty* pArchetype = (it == mpMaster->mEnumTemplates.end() ? nullptr : it->second);
|
||||
TString EnumName = rkTemplateFileName.GetFileName(false);
|
||||
CEnumProperty* pArchetype = mpMaster->FindEnumArchetype(EnumName);
|
||||
|
||||
// If the enum template hasn't been read yet, then we read it and add it to master's list
|
||||
if (!pArchetype)
|
||||
|
@ -475,8 +480,13 @@ CEnumProperty* CTemplateLoader::LoadEnumArchetype(const TString& rkTemplateFileN
|
|||
ASSERT(pEnumers);
|
||||
|
||||
LoadEnumerators(pEnumers, pArchetype, rkTemplateFileName);
|
||||
mpMaster->mEnumTemplates[rkTemplateFileName] = pArchetype;
|
||||
pArchetype->PostInitialize();
|
||||
|
||||
mpMaster->mEnumTemplates.emplace(
|
||||
std::make_pair(
|
||||
EnumName,
|
||||
CMasterTemplate::SPropertyTemplatePath(rkTemplateFileName, pArchetype)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -487,8 +497,8 @@ CEnumProperty* CTemplateLoader::LoadEnumArchetype(const TString& rkTemplateFileN
|
|||
CFlagsProperty* CTemplateLoader::LoadFlagsArchetype(const TString& rkTemplateFileName)
|
||||
{
|
||||
// Check whether this struct has already been read
|
||||
auto it = mpMaster->mFlagsTemplates.find(rkTemplateFileName);
|
||||
CFlagsProperty* pArchetype = (it == mpMaster->mFlagsTemplates.end() ? nullptr : it->second);
|
||||
TString FlagsName = rkTemplateFileName.GetFileName(false);
|
||||
CFlagsProperty* pArchetype = mpMaster->FindFlagsArchetype(FlagsName);
|
||||
|
||||
// If the enum template hasn't been read yet, then we read it and add it to master's list
|
||||
if (!pArchetype)
|
||||
|
@ -517,8 +527,14 @@ CFlagsProperty* CTemplateLoader::LoadFlagsArchetype(const TString& rkTemplateFil
|
|||
ASSERT(pFlags);
|
||||
|
||||
LoadBitFlags(pFlags, pArchetype, rkTemplateFileName);
|
||||
mpMaster->mFlagsTemplates[rkTemplateFileName] = pArchetype;
|
||||
pArchetype->PostInitialize();
|
||||
|
||||
mpMaster->mFlagsTemplates.emplace(
|
||||
std::make_pair(
|
||||
FlagsName,
|
||||
CMasterTemplate::SPropertyTemplatePath(rkTemplateFileName, pArchetype)
|
||||
));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -937,28 +953,14 @@ void CTemplateLoader::LoadMasterTemplate(XMLDocument *pDoc, CMasterTemplate *pMa
|
|||
mMasterDir = pMaster->mSourceFile.GetFileDirectory();
|
||||
|
||||
XMLElement *pRoot = pDoc->FirstChildElement("MasterTemplate");
|
||||
mpMaster->mVersion = TString(pRoot->Attribute("version")).ToInt32();
|
||||
|
||||
XMLElement *pElem = pRoot->FirstChildElement();
|
||||
|
||||
while (pElem)
|
||||
{
|
||||
TString NodeName = pElem->Name();
|
||||
|
||||
// Versions
|
||||
if (NodeName == "versions")
|
||||
{
|
||||
XMLElement *pVersion = pElem->FirstChildElement("version");
|
||||
|
||||
while (pVersion)
|
||||
{
|
||||
mpMaster->mGameVersions.push_back(pVersion->GetText());
|
||||
pVersion = pVersion->NextSiblingElement("version");
|
||||
}
|
||||
}
|
||||
|
||||
// Objects
|
||||
else if (NodeName == "objects")
|
||||
if (NodeName == "objects")
|
||||
{
|
||||
XMLElement *pObj = pElem->FirstChildElement("object");
|
||||
|
||||
|
@ -984,7 +986,13 @@ void CTemplateLoader::LoadMasterTemplate(XMLDocument *pDoc, CMasterTemplate *pMa
|
|||
CScriptTemplate *pTemp = LoadScriptTemplate(&ScriptXML, TemplateName, ID);
|
||||
|
||||
if (pTemp)
|
||||
mpMaster->mTemplates[ID] = pTemp;
|
||||
{
|
||||
mpMaster->mScriptTemplates.emplace(
|
||||
std::make_pair(
|
||||
ID,
|
||||
CMasterTemplate::SScriptTemplatePath(ID, TemplateName, pTemp)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
pObj = pObj->NextSiblingElement("object");
|
||||
|
@ -1007,7 +1015,7 @@ void CTemplateLoader::LoadMasterTemplate(XMLDocument *pDoc, CMasterTemplate *pMa
|
|||
StateID = CFourCC(StrID).ToLong();
|
||||
|
||||
TString StateName = pState->Attribute("name");
|
||||
mpMaster->mStates[StateID] = SState(StateID, StateName);
|
||||
mpMaster->mStates[StateID] = StateName;
|
||||
pState = pState->NextSiblingElement("state");
|
||||
}
|
||||
}
|
||||
|
@ -1028,7 +1036,7 @@ void CTemplateLoader::LoadMasterTemplate(XMLDocument *pDoc, CMasterTemplate *pMa
|
|||
MessageID = CFourCC(StrID).ToLong();
|
||||
|
||||
TString MessageName = pMessage->Attribute("name");
|
||||
mpMaster->mMessages[MessageID] = SMessage(MessageID, MessageName);
|
||||
mpMaster->mMessages[MessageID] = MessageName;
|
||||
pMessage = pMessage->NextSiblingElement("message");
|
||||
}
|
||||
}
|
||||
|
@ -1229,3 +1237,60 @@ void CTemplateLoader::LoadPropertyList(XMLDocument *pDoc, const TString& ListNam
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTemplateLoader::SaveGameList()
|
||||
{
|
||||
const TString kTemplatesDir = "../templates_new/";
|
||||
FileUtil::MakeDirectory( kTemplatesDir );
|
||||
|
||||
// Write game list
|
||||
{
|
||||
const TString kGameListPath = kTemplatesDir + "GameList.xml";
|
||||
CXMLWriter Writer(kGameListPath, "GameList");
|
||||
TString PropertyListPath = "PropertyNameMap.xml";
|
||||
Writer << SerialParameter("PropertyList", PropertyListPath, 0);
|
||||
|
||||
Writer.ParamBegin("Games", 0);
|
||||
|
||||
for (auto Iter = CMasterTemplate::smMasterMap.begin(); Iter != CMasterTemplate::smMasterMap.end(); Iter++)
|
||||
{
|
||||
struct SGameInfo
|
||||
{
|
||||
EGame Game;
|
||||
TString Name;
|
||||
TString MasterPath;
|
||||
|
||||
void Serialize(IArchive& Arc)
|
||||
{
|
||||
Arc << SerialParameter("ID", Game, SH_Attribute)
|
||||
<< SerialParameter("Name", Name)
|
||||
<< SerialParameter("MasterTemplate", MasterPath);
|
||||
}
|
||||
};
|
||||
|
||||
CMasterTemplate* pMaster = Iter->second;
|
||||
SGameInfo Info;
|
||||
Info.Game = pMaster->Game();
|
||||
Info.Name = pMaster->GameName();
|
||||
Info.MasterPath = pMaster->GetDirectory() + "MasterTemplate.xml";
|
||||
Writer << SerialParameter("Game", Info);
|
||||
}
|
||||
Writer.ParamEnd();
|
||||
}
|
||||
|
||||
// Write master templates
|
||||
{
|
||||
std::list<CMasterTemplate*> MasterList = CMasterTemplate::MasterList();
|
||||
|
||||
for (auto Iter = MasterList.begin(); Iter != MasterList.end(); Iter++)
|
||||
{
|
||||
CMasterTemplate* pMasterTemplate = *Iter;
|
||||
TString MasterFilePath = kTemplatesDir + pMasterTemplate->GetDirectory() + "Game.xml";
|
||||
FileUtil::MakeDirectory( MasterFilePath.GetFileDirectory() );
|
||||
|
||||
CXMLWriter Writer(MasterFilePath, "Game", 0, pMasterTemplate->Game());
|
||||
pMasterTemplate->Serialize(Writer);
|
||||
pMasterTemplate->SaveSubTemplates();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,8 @@ public:
|
|||
static void LoadGameTemplates(EGame Game);
|
||||
static void LoadAllGames();
|
||||
static void LoadPropertyList(tinyxml2::XMLDocument* pDoc, const TString& rkListName);
|
||||
|
||||
static void SaveGameList();
|
||||
};
|
||||
|
||||
#endif // CTEMPLATELOADER_H
|
||||
|
|
|
@ -8,20 +8,56 @@
|
|||
|
||||
struct SState
|
||||
{
|
||||
union {
|
||||
u32 ID;
|
||||
CFourCC ID_4CC;
|
||||
};
|
||||
TString Name;
|
||||
|
||||
SState() {}
|
||||
SState(u32 _ID, const TString& rkName) : ID(_ID), Name(rkName) {}
|
||||
SState()
|
||||
{}
|
||||
|
||||
SState(u32 InID, const TString& kInName)
|
||||
: ID(InID)
|
||||
, Name(kInName)
|
||||
{}
|
||||
|
||||
void Serialize(IArchive& Arc)
|
||||
{
|
||||
if (Arc.Game() <= ePrime)
|
||||
Arc << SerialParameter("ID", ID, SH_Attribute | SH_HexDisplay);
|
||||
else
|
||||
Arc << SerialParameter("ID", ID_4CC, SH_Attribute);
|
||||
|
||||
Arc << SerialParameter("Name", Name, SH_Attribute);
|
||||
}
|
||||
};
|
||||
|
||||
struct SMessage
|
||||
{
|
||||
union {
|
||||
u32 ID;
|
||||
CFourCC ID_4CC;
|
||||
};
|
||||
TString Name;
|
||||
|
||||
SMessage() {}
|
||||
SMessage(u32 _ID, const TString& rkName) : ID(_ID), Name(rkName) {}
|
||||
SMessage()
|
||||
{}
|
||||
|
||||
SMessage(u32 InID, const TString& kInName)
|
||||
: ID(InID)
|
||||
, Name(kInName)
|
||||
{}
|
||||
|
||||
void Serialize(IArchive& Arc)
|
||||
{
|
||||
if (Arc.Game() <= ePrime)
|
||||
Arc << SerialParameter("ID", ID, SH_Attribute | SH_HexDisplay);
|
||||
else
|
||||
Arc << SerialParameter("ID", ID_4CC, SH_Attribute);
|
||||
|
||||
Arc << SerialParameter("Name", Name, SH_Attribute);
|
||||
}
|
||||
};
|
||||
|
||||
class CLink
|
||||
|
|
|
@ -3,34 +3,81 @@
|
|||
#include <Common/Log.h>
|
||||
|
||||
CMasterTemplate::CMasterTemplate()
|
||||
: mVersion(0)
|
||||
, mFullyLoaded(false)
|
||||
: mFullyLoaded(false)
|
||||
{
|
||||
}
|
||||
|
||||
CMasterTemplate::~CMasterTemplate()
|
||||
void CMasterTemplate::Serialize(IArchive& Arc)
|
||||
{
|
||||
for (auto it = mTemplates.begin(); it != mTemplates.end(); it++)
|
||||
delete it->second;
|
||||
Arc << SerialParameter("ScriptObjects", mScriptTemplates)
|
||||
<< SerialParameter("Structs", mStructTemplates)
|
||||
<< SerialParameter("Enums", mEnumTemplates)
|
||||
<< SerialParameter("Flags", mFlagsTemplates)
|
||||
<< SerialParameter("States", mStates)
|
||||
<< SerialParameter("Messages", mMessages);
|
||||
}
|
||||
|
||||
void CMasterTemplate::LoadSubTemplates()
|
||||
{
|
||||
//todo
|
||||
}
|
||||
|
||||
void CMasterTemplate::SaveSubTemplates()
|
||||
{
|
||||
TString GameDir = "../templates_new/" + GetDirectory();
|
||||
|
||||
for (auto Iter = mScriptTemplates.begin(); Iter != mScriptTemplates.end(); Iter++)
|
||||
{
|
||||
SScriptTemplatePath& Path = Iter->second;
|
||||
TString OutPath = GameDir + Path.Path;
|
||||
|
||||
FileUtil::MakeDirectory( OutPath.GetFileDirectory() );
|
||||
CXMLWriter Writer(OutPath, "ScriptObject", 0, Game());
|
||||
Path.pTemplate->Serialize(Writer);
|
||||
}
|
||||
|
||||
for (auto Iter = mStructTemplates.begin(); Iter != mStructTemplates.end(); Iter++)
|
||||
{
|
||||
SPropertyTemplatePath& Path = Iter->second;
|
||||
TString OutPath = GameDir + Path.Path;
|
||||
|
||||
FileUtil::MakeDirectory( OutPath.GetFileDirectory() );
|
||||
CXMLWriter Writer(OutPath, "Struct", 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);
|
||||
}
|
||||
}
|
||||
|
||||
u32 CMasterTemplate::GameVersion(TString VersionName)
|
||||
{
|
||||
VersionName = VersionName.ToLower();
|
||||
|
||||
for (u32 iVer = 0; iVer < mGameVersions.size(); iVer++)
|
||||
if (mGameVersions[iVer].ToLower() == VersionName)
|
||||
return iVer;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
CScriptTemplate* CMasterTemplate::TemplateByID(u32 ObjectID)
|
||||
{
|
||||
auto it = mTemplates.find(ObjectID);
|
||||
auto it = mScriptTemplates.find(ObjectID);
|
||||
|
||||
if (it != mTemplates.end())
|
||||
return it->second;
|
||||
if (it != mScriptTemplates.end())
|
||||
return it->second.pTemplate.get();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -42,16 +89,16 @@ CScriptTemplate* CMasterTemplate::TemplateByID(const CFourCC& ObjectID)
|
|||
|
||||
CScriptTemplate* CMasterTemplate::TemplateByIndex(u32 Index)
|
||||
{
|
||||
auto it = mTemplates.begin();
|
||||
return (std::next(it, Index))->second;
|
||||
auto it = mScriptTemplates.begin();
|
||||
return (std::next(it, Index))->second.pTemplate.get();
|
||||
}
|
||||
|
||||
SState CMasterTemplate::StateByID(u32 StateID)
|
||||
{
|
||||
auto it = mStates.find(StateID);
|
||||
auto Iter = mStates.find(StateID);
|
||||
|
||||
if (it != mStates.end())
|
||||
return it->second;
|
||||
if (Iter != mStates.end())
|
||||
return SState(Iter->first, Iter->second);
|
||||
else
|
||||
return SState(-1, "Invalid");
|
||||
}
|
||||
|
@ -63,16 +110,17 @@ SState CMasterTemplate::StateByID(const CFourCC& State)
|
|||
|
||||
SState CMasterTemplate::StateByIndex(u32 Index)
|
||||
{
|
||||
auto it = mStates.begin();
|
||||
return (std::next(it, Index))->second;
|
||||
auto Iter = mStates.begin();
|
||||
Iter = std::next(Iter, Index);
|
||||
return SState(Iter->first, Iter->second);
|
||||
}
|
||||
|
||||
SMessage CMasterTemplate::MessageByID(u32 MessageID)
|
||||
{
|
||||
auto it = mMessages.find(MessageID);
|
||||
auto Iter = mMessages.find(MessageID);
|
||||
|
||||
if (it != mMessages.end())
|
||||
return it->second;
|
||||
if (Iter != mMessages.end())
|
||||
return SMessage(Iter->first, Iter->second);
|
||||
else
|
||||
return SMessage(-1, "Invalid");
|
||||
}
|
||||
|
@ -84,18 +132,31 @@ SMessage CMasterTemplate::MessageByID(const CFourCC& MessageID)
|
|||
|
||||
SMessage CMasterTemplate::MessageByIndex(u32 Index)
|
||||
{
|
||||
auto it = mMessages.begin();
|
||||
return (std::next(it, Index))->second;
|
||||
auto Iter = mMessages.begin();
|
||||
Iter = std::next(Iter, Index);
|
||||
return SMessage(Iter->first, Iter->second);
|
||||
}
|
||||
|
||||
CStructPropertyNew* CMasterTemplate::StructAtSource(const TString& rkSource)
|
||||
|
||||
CStructPropertyNew* CMasterTemplate::FindStructArchetype(const TString& kStructName) const
|
||||
{
|
||||
auto InfoIt = mStructTemplates.find(rkSource);
|
||||
auto Iter = mStructTemplates.find(kStructName);
|
||||
IPropertyNew* pProperty = (Iter != mStructTemplates.end()) ? Iter->second.pTemplate.get() : nullptr;
|
||||
return TPropCast<CStructPropertyNew>(pProperty);
|
||||
}
|
||||
|
||||
if (InfoIt != mStructTemplates.end())
|
||||
return InfoIt->second;
|
||||
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);
|
||||
}
|
||||
|
||||
else return nullptr;
|
||||
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 ************
|
||||
|
|
|
@ -8,25 +8,113 @@
|
|||
#include <Common/types.h>
|
||||
#include <map>
|
||||
|
||||
/** Serialization aid
|
||||
* Retro switched from using integers to fourCCs to represent IDs in several cases (states/messages, object IDs).
|
||||
* This struct is functionally an integer but it serializes as an int for MP1 and a fourCC for MP2 and on.
|
||||
*/
|
||||
struct SObjId
|
||||
{
|
||||
union {
|
||||
u32 ID;
|
||||
CFourCC ID_4CC;
|
||||
};
|
||||
|
||||
inline SObjId() {}
|
||||
inline SObjId(u32 InID) : ID(InID) {}
|
||||
inline SObjId(CFourCC InID) : ID_4CC(InID) {}
|
||||
|
||||
inline operator u32() const { return ID; }
|
||||
inline operator CFourCC() const { return ID_4CC; }
|
||||
|
||||
void Serialize(IArchive& Arc)
|
||||
{
|
||||
if (Arc.Game() <= ePrime)
|
||||
Arc.SerializePrimitive(ID, SH_HexDisplay);
|
||||
else
|
||||
Arc.SerializePrimitive(ID_4CC, 0);
|
||||
}
|
||||
};
|
||||
|
||||
class CMasterTemplate
|
||||
{
|
||||
friend class CTemplateLoader;
|
||||
friend class CTemplateWriter;
|
||||
|
||||
/** Struct holding a reference to a script object template */
|
||||
struct SScriptTemplatePath
|
||||
{
|
||||
/** Script object ID */
|
||||
SObjId ID;
|
||||
|
||||
/** File path to the template file, relative to the game directory */
|
||||
TString Path;
|
||||
|
||||
/** Template in memory */
|
||||
std::shared_ptr<CScriptTemplate> pTemplate;
|
||||
|
||||
/** Constructor */
|
||||
SScriptTemplatePath()
|
||||
: ID(0)
|
||||
{}
|
||||
|
||||
SScriptTemplatePath(u32 InID, const TString& kInPath, CScriptTemplate* pInTemplate)
|
||||
: ID(InID)
|
||||
, Path(kInPath)
|
||||
, pTemplate( std::shared_ptr<CScriptTemplate>(pInTemplate) )
|
||||
{}
|
||||
|
||||
SScriptTemplatePath(const CFourCC& kInID, const TString& kInPath, CScriptTemplate* pInTemplate)
|
||||
: ID(kInID)
|
||||
, Path(kInPath)
|
||||
, pTemplate( std::shared_ptr<CScriptTemplate>(pInTemplate) )
|
||||
{}
|
||||
|
||||
/** Serializer */
|
||||
void Serialize(IArchive& Arc)
|
||||
{
|
||||
Arc << SerialParameter("ID", ID, SH_Attribute)
|
||||
<< SerialParameter("Path", Path, SH_Attribute);
|
||||
}
|
||||
};
|
||||
|
||||
/** Struct holding a reference to a property template */
|
||||
struct SPropertyTemplatePath
|
||||
{
|
||||
/** File path to the template file, relative to the game directory */
|
||||
TString Path;
|
||||
|
||||
/** Template in memory */
|
||||
std::shared_ptr<IPropertyNew> pTemplate;
|
||||
|
||||
/** Constructor */
|
||||
SPropertyTemplatePath()
|
||||
{}
|
||||
|
||||
SPropertyTemplatePath(const TString& kInPath, IPropertyNew* pInTemplate)
|
||||
: Path(kInPath)
|
||||
, pTemplate( std::shared_ptr<IPropertyNew>(pInTemplate) )
|
||||
{}
|
||||
|
||||
/** Serializer */
|
||||
void Serialize(IArchive& Arc)
|
||||
{
|
||||
Arc << SerialParameter("Path", Path, SH_Attribute);
|
||||
}
|
||||
};
|
||||
|
||||
EGame mGame;
|
||||
TString mGameName;
|
||||
TString mSourceFile;
|
||||
u32 mVersion;
|
||||
bool mFullyLoaded;
|
||||
|
||||
std::vector<TString> mGameVersions;
|
||||
std::map<TString, CStructPropertyNew*> mStructTemplates;
|
||||
std::map<TString, CEnumProperty*> mEnumTemplates;
|
||||
std::map<TString, CFlagsProperty*> mFlagsTemplates;
|
||||
/** Template arrays */
|
||||
std::map<SObjId, SScriptTemplatePath> mScriptTemplates;
|
||||
std::map<TString, SPropertyTemplatePath> mStructTemplates;
|
||||
std::map<TString, SPropertyTemplatePath> mEnumTemplates;
|
||||
std::map<TString, SPropertyTemplatePath> mFlagsTemplates;
|
||||
|
||||
std::map<u32, CScriptTemplate*> mTemplates;
|
||||
std::map<u32, SState> mStates;
|
||||
std::map<u32, SMessage> mMessages;
|
||||
std::map<SObjId, TString> mStates;
|
||||
std::map<SObjId, TString> mMessages;
|
||||
|
||||
struct SPropIDInfo
|
||||
{
|
||||
|
@ -40,7 +128,9 @@ class CMasterTemplate
|
|||
|
||||
public:
|
||||
CMasterTemplate();
|
||||
~CMasterTemplate();
|
||||
void Serialize(IArchive& Arc);
|
||||
void LoadSubTemplates();
|
||||
void SaveSubTemplates();
|
||||
u32 GameVersion(TString VersionName);
|
||||
CScriptTemplate* TemplateByID(u32 ObjectID);
|
||||
CScriptTemplate* TemplateByID(const CFourCC& ObjectID);
|
||||
|
@ -51,13 +141,15 @@ public:
|
|||
SMessage MessageByID(u32 MessageID);
|
||||
SMessage MessageByID(const CFourCC& MessageID);
|
||||
SMessage MessageByIndex(u32 Index);
|
||||
CStructPropertyNew* StructAtSource(const TString& rkSource);
|
||||
|
||||
CStructPropertyNew* FindStructArchetype(const TString& kStructName) const;
|
||||
CEnumProperty* FindEnumArchetype(const TString& kEnumName) const;
|
||||
CFlagsProperty* FindFlagsArchetype(const TString& kFlagsName) const;
|
||||
|
||||
// Inline Accessors
|
||||
inline EGame Game() const { return mGame; }
|
||||
inline TString GameName() const { return mGameName; }
|
||||
inline u32 NumGameVersions() const { return mGameVersions.empty() ? 1 : mGameVersions.size(); }
|
||||
inline u32 NumScriptTemplates() const { return mTemplates.size(); }
|
||||
inline u32 NumScriptTemplates() const { return mScriptTemplates.size(); }
|
||||
inline u32 NumStates() const { return mStates.size(); }
|
||||
inline u32 NumMessages() const { return mMessages.size(); }
|
||||
inline bool IsLoadedSuccessfully() { return mFullyLoaded; }
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
// Old constructor
|
||||
CScriptTemplate::CScriptTemplate(CMasterTemplate *pMaster)
|
||||
: mpMaster(pMaster)
|
||||
, mpProperties(nullptr)
|
||||
|
@ -24,10 +25,58 @@ CScriptTemplate::CScriptTemplate(CMasterTemplate *pMaster)
|
|||
{
|
||||
}
|
||||
|
||||
// New constructor
|
||||
CScriptTemplate::CScriptTemplate(CMasterTemplate* pInMaster, u32 InObjectID, const TString& kInFilePath)
|
||||
: mRotationType(eRotationEnabled)
|
||||
, mScaleType(eScaleEnabled)
|
||||
, mPreviewScale(1.f)
|
||||
, mVolumeShape(eNoShape)
|
||||
, mVolumeScale(1.f)
|
||||
, mSourceFile(kInFilePath)
|
||||
, mObjectID(InObjectID)
|
||||
, mpMaster(pInMaster)
|
||||
, mpNameProperty(nullptr)
|
||||
, mpPositionProperty(nullptr)
|
||||
, mpRotationProperty(nullptr)
|
||||
, mpScaleProperty(nullptr)
|
||||
, mpActiveProperty(nullptr)
|
||||
, mpLightParametersProperty(nullptr)
|
||||
, mVisible(true)
|
||||
{
|
||||
}
|
||||
|
||||
CScriptTemplate::~CScriptTemplate()
|
||||
{
|
||||
}
|
||||
|
||||
void CScriptTemplate::Serialize(IArchive& Arc)
|
||||
{
|
||||
Arc << SerialParameter("Modules", mModules, SH_Optional)
|
||||
<< SerialParameter("Properties", mpProperties);
|
||||
|
||||
if (Arc.ParamBegin("EditorProperties", 0))
|
||||
{
|
||||
Arc << SerialParameter("NameProperty", mNameIDString, SH_Optional)
|
||||
<< SerialParameter("PositionProperty", mPositionIDString, SH_Optional)
|
||||
<< SerialParameter("RotationProperty", mRotationIDString, SH_Optional)
|
||||
<< SerialParameter("ScaleProperty", mScaleIDString, SH_Optional)
|
||||
<< SerialParameter("ActiveProperty", mActiveIDString, SH_Optional)
|
||||
<< SerialParameter("LightParametersProperty", mLightParametersIDString, SH_Optional);
|
||||
|
||||
Arc.ParamEnd();
|
||||
}
|
||||
|
||||
Arc << SerialParameter("Assets", mAssets, SH_Optional)
|
||||
<< SerialParameter("Attachments", mAttachments, SH_Optional)
|
||||
<< SerialParameter("RotationType", mRotationType, SH_Optional, eRotationEnabled)
|
||||
<< SerialParameter("ScaleType", mScaleType, SH_Optional, eScaleEnabled)
|
||||
<< SerialParameter("PreviewScale", mPreviewScale, SH_Optional, 1.0f)
|
||||
<< SerialParameter("VolumeShape", mVolumeShape, SH_Optional, eNoShape)
|
||||
<< SerialParameter("VolumeScale", mVolumeScale, SH_Optional, 1.0f)
|
||||
<< SerialParameter("VolumeConditionProperty", mVolumeConditionIDString, SH_Optional)
|
||||
<< SerialParameter("VolumeConditions", mVolumeConditions, SH_Optional);
|
||||
}
|
||||
|
||||
void CScriptTemplate::PostLoad()
|
||||
{
|
||||
if (!mNameIDString.IsEmpty()) mpNameProperty = TPropCast<CStringProperty>( mpProperties->ChildByIDString(mNameIDString) );
|
||||
|
|
|
@ -26,6 +26,13 @@ struct SAttachment
|
|||
TIDString AttachProperty; // Must point to a CMDL!
|
||||
TString LocatorName;
|
||||
EAttachType AttachType;
|
||||
|
||||
void Serialize(IArchive& Arc)
|
||||
{
|
||||
Arc << SerialParameter("AttachProperty", AttachProperty, SH_Attribute)
|
||||
<< SerialParameter("LocatorName", LocatorName, SH_Attribute)
|
||||
<< SerialParameter("AttachType", AttachType, SH_Attribute);
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -52,41 +59,28 @@ public:
|
|||
private:
|
||||
struct SEditorAsset
|
||||
{
|
||||
enum {
|
||||
enum EAssetType {
|
||||
eModel, eAnimParams, eBillboard, eCollision
|
||||
} AssetType;
|
||||
|
||||
enum {
|
||||
enum EAssetSource {
|
||||
eProperty, eFile
|
||||
} AssetSource;
|
||||
|
||||
TIDString AssetLocation;
|
||||
s32 ForceNodeIndex; // Force animsets to use specific node instead of one from property
|
||||
|
||||
void Serialize(IArchive& Arc)
|
||||
{
|
||||
Arc << SerialParameter("Type", AssetType, SH_Attribute)
|
||||
<< SerialParameter("Source", AssetSource, SH_Attribute)
|
||||
<< SerialParameter("Location", AssetLocation, SH_Attribute)
|
||||
<< SerialParameter("ForceCharacterIndex", ForceNodeIndex, SH_Attribute | SH_Optional, (s32) -1);
|
||||
}
|
||||
};
|
||||
|
||||
CMasterTemplate* mpMaster;
|
||||
std::unique_ptr<CStructPropertyNew> mpProperties;
|
||||
std::list<CScriptObject*> mObjectList;
|
||||
std::vector<TString> mModules;
|
||||
TString mSourceFile;
|
||||
u32 mObjectID;
|
||||
bool mVisible;
|
||||
|
||||
// Editor Properties
|
||||
TIDString mNameIDString;
|
||||
TIDString mPositionIDString;
|
||||
TIDString mRotationIDString;
|
||||
TIDString mScaleIDString;
|
||||
TIDString mActiveIDString;
|
||||
TIDString mLightParametersIDString;
|
||||
|
||||
CStringProperty* mpNameProperty;
|
||||
CVectorProperty* mpPositionProperty;
|
||||
CVectorProperty* mpRotationProperty;
|
||||
CVectorProperty* mpScaleProperty;
|
||||
CBoolProperty* mpActiveProperty;
|
||||
CStructPropertyNew* mpLightParametersProperty;
|
||||
|
||||
std::unique_ptr<CStructPropertyNew> mpProperties;
|
||||
std::vector<SEditorAsset> mAssets;
|
||||
std::vector<SAttachment> mAttachments;
|
||||
|
||||
|
@ -99,15 +93,47 @@ private:
|
|||
float mVolumeScale;
|
||||
TIDString mVolumeConditionIDString;
|
||||
|
||||
TString mSourceFile;
|
||||
u32 mObjectID;
|
||||
|
||||
// Editor Properties
|
||||
TIDString mNameIDString;
|
||||
TIDString mPositionIDString;
|
||||
TIDString mRotationIDString;
|
||||
TIDString mScaleIDString;
|
||||
TIDString mActiveIDString;
|
||||
TIDString mLightParametersIDString;
|
||||
|
||||
CMasterTemplate* mpMaster;
|
||||
std::list<CScriptObject*> mObjectList;
|
||||
|
||||
CStringProperty* mpNameProperty;
|
||||
CVectorProperty* mpPositionProperty;
|
||||
CVectorProperty* mpRotationProperty;
|
||||
CVectorProperty* mpScaleProperty;
|
||||
CBoolProperty* mpActiveProperty;
|
||||
CStructPropertyNew* mpLightParametersProperty;
|
||||
|
||||
struct SVolumeCondition {
|
||||
int Value;
|
||||
u32 Value;
|
||||
EVolumeShape Shape;
|
||||
float Scale;
|
||||
|
||||
void Serialize(IArchive& Arc)
|
||||
{
|
||||
Arc << SerialParameter("Value", Value)
|
||||
<< SerialParameter("Shape", Shape)
|
||||
<< SerialParameter("Scale", Scale, SH_Optional, 1.0f);
|
||||
}
|
||||
};
|
||||
std::vector<SVolumeCondition> mVolumeConditions;
|
||||
bool mVisible;
|
||||
|
||||
public:
|
||||
// Old constructor
|
||||
CScriptTemplate(CMasterTemplate *pMaster);
|
||||
// New constructor
|
||||
CScriptTemplate(CMasterTemplate* pMaster, u32 ObjectID, const TString& kFilePath);
|
||||
~CScriptTemplate();
|
||||
void Serialize(IArchive& rArc);
|
||||
void PostLoad();
|
||||
|
|
|
@ -93,14 +93,14 @@ void* IPropertyNew::GetChildDataPointer(void* pPropertyData) const
|
|||
|
||||
void IPropertyNew::Serialize(IArchive& rArc)
|
||||
{
|
||||
if (rArc.Game() <= ePrime)
|
||||
if (rArc.Game() <= ePrime && !IsArchetype())
|
||||
{
|
||||
rArc << SerialParameter("Name", mName);
|
||||
}
|
||||
|
||||
rArc << SerialParameter("ID", mID, SH_HexDisplay | SH_Optional, (u32) 0xFFFFFFFF)
|
||||
rArc << SerialParameter("ID", mID, SH_HexDisplay | SH_Attribute | SH_Optional, (u32) 0xFFFFFFFF)
|
||||
<< SerialParameter("Description", mDescription, SH_Optional)
|
||||
<< SerialParameter("CookPref", mCookPreference, SH_Optional, ECookPreferenceNew::Default)
|
||||
<< SerialParameter("CookPreference", mCookPreference, SH_Optional, ECookPreferenceNew::Default)
|
||||
<< SerialParameter("MinVersion", mMinVersion, SH_Optional, 0.f)
|
||||
<< SerialParameter("MaxVersion", mMaxVersion, SH_Optional, FLT_MAX);
|
||||
|
||||
|
|
|
@ -376,7 +376,7 @@ protected:
|
|||
public:
|
||||
virtual void Serialize(IArchive& rArc)
|
||||
{
|
||||
IPropertyNew::Serialize(rArc);
|
||||
TTypedPropertyNew::Serialize(rArc);
|
||||
|
||||
// Determine if default value should be serialized as optional.
|
||||
// All MP1 properties should be optional. For MP2 and on, we set optional
|
||||
|
@ -436,14 +436,14 @@ protected:
|
|||
public:
|
||||
virtual void Serialize(IArchive& rArc)
|
||||
{
|
||||
TTypedPropertyNew::Serialize(rArc);
|
||||
TSerializeableTypedProperty::Serialize(rArc);
|
||||
rArc << SerialParameter("Min", mMinValue, SH_Optional, (PropType) -1)
|
||||
<< SerialParameter("Max", mMaxValue, SH_Optional, (PropType) -1);
|
||||
}
|
||||
|
||||
virtual void InitFromArchetype(IPropertyNew* pOther)
|
||||
{
|
||||
TTypedPropertyNew::InitFromArchetype(pOther);
|
||||
TSerializeableTypedProperty::InitFromArchetype(pOther);
|
||||
TNumericalPropertyNew* pCastOther = static_cast<TNumericalPropertyNew*>(pOther);
|
||||
mMinValue = pCastOther->mMinValue;
|
||||
mMaxValue = pCastOther->mMaxValue;
|
||||
|
@ -451,7 +451,7 @@ public:
|
|||
|
||||
virtual void PropertyValueChanged(void* pPropertyData)
|
||||
{
|
||||
IPropertyNew::PropertyValueChanged(pPropertyData);
|
||||
TSerializeableTypedProperty::PropertyValueChanged(pPropertyData);
|
||||
|
||||
if (mMinValue >= 0 && mMaxValue >= 0)
|
||||
{
|
||||
|
|
|
@ -122,16 +122,17 @@ typedef TEnumPropertyBase<EPropertyTypeNew::Enum> CEnumProperty;
|
|||
template<>
|
||||
inline CEnumProperty* TPropCast(IPropertyNew* pProperty)
|
||||
{
|
||||
if (pProperty)
|
||||
{
|
||||
EPropertyTypeNew InType = pProperty->Type();
|
||||
|
||||
if (InType == EPropertyTypeNew::Enum || InType == EPropertyTypeNew::Choice)
|
||||
{
|
||||
return static_cast<CEnumProperty*>(pProperty);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<>
|
||||
|
|
|
@ -128,23 +128,37 @@ void CTemplateEditDialog::ApplyChanges()
|
|||
// ************ PROTECTED ************
|
||||
void CTemplateEditDialog::AddTemplate(IPropertyNew* pProp)
|
||||
{
|
||||
TString Source = pProp->GetTemplateFileName();
|
||||
IPropertyNew* pArchetype = pProp->Archetype();
|
||||
|
||||
if (!Source.IsEmpty())
|
||||
if (pArchetype)
|
||||
{
|
||||
CStructPropertyNew* pStruct = CMasterTemplate::MasterForGame(pProp->Game())->StructAtSource(Source);
|
||||
pArchetype = pArchetype->RootParent();
|
||||
|
||||
switch (pArchetype->Type())
|
||||
{
|
||||
|
||||
case EPropertyTypeNew::Struct:
|
||||
{
|
||||
CStructPropertyNew* pStruct = TPropCast<CStructPropertyNew>(pArchetype);
|
||||
if (!mStructTemplatesToResave.contains(pStruct))
|
||||
{
|
||||
mStructTemplatesToResave << pStruct;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
Log::Warning("Couldn't resave unsupported property archetype: " + TString( EnumValueName(pArchetype->Type()) ));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
CScriptTemplate *pScript = pProp->ScriptTemplate();
|
||||
|
||||
if (pScript)
|
||||
if (pScript && !mScriptTemplatesToResave.contains(pScript))
|
||||
{
|
||||
if (!mScriptTemplatesToResave.contains(pScript))
|
||||
mScriptTemplatesToResave << pScript;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue