More fixes. Property/serialization changes are finally basically finished now. Serialized property templates now load & display correctly in the editor
This commit is contained in:
parent
33e915a638
commit
2118bbd0cd
|
@ -97,8 +97,13 @@ template<typename T> struct TIsContainer< std::set<T> > : std::true_type {};
|
||||||
template<typename T, typename V> struct TIsContainer< std::map<T,V> > : std::true_type {};
|
template<typename T, typename V> struct TIsContainer< std::map<T,V> > : std::true_type {};
|
||||||
template<typename T, typename V> struct TIsContainer< std::unordered_map<T,V> > : std::true_type {};
|
template<typename T, typename V> struct TIsContainer< std::unordered_map<T,V> > : std::true_type {};
|
||||||
|
|
||||||
|
/** Class that determines if the type is a smart pointer */
|
||||||
|
template<typename> struct TIsSmartPointer : std::false_type {};
|
||||||
|
template<typename T> struct TIsSmartPointer< std::shared_ptr<T> > : std::true_type {};
|
||||||
|
template<typename T> struct TIsSmartPointer< std::unique_ptr<T> > : std::true_type {};
|
||||||
|
|
||||||
/** Helper macro that tells us whether the parameter supports default property values */
|
/** Helper macro that tells us whether the parameter supports default property values */
|
||||||
#define SUPPORTS_DEFAULT_VALUES (!std::is_pointer_v<ValType> && std::is_copy_assignable_v<ValType> && THasEqualTo<ValType>::value && !TIsContainer<ValType>::value)
|
#define SUPPORTS_DEFAULT_VALUES (!std::is_pointer_v<ValType> && std::is_copy_assignable_v<ValType> && THasEqualTo<ValType>::value && !TIsContainer<ValType>::value && !TIsSmartPointer<ValType>::value)
|
||||||
|
|
||||||
/** TSerialParameter - name/value pair for generic serial parameters */
|
/** TSerialParameter - name/value pair for generic serial parameters */
|
||||||
template<typename ValType>
|
template<typename ValType>
|
||||||
|
@ -241,14 +246,26 @@ struct SerialType
|
||||||
None);
|
None);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Helper for determining the type used by a given abstract object class (i.e. the type returned by the Type() function) */
|
|
||||||
#define ABSTRACT_TYPE decltype( std::declval<ValType>().Type() )
|
|
||||||
|
|
||||||
/** For abstract types, determine what kind of ArchiveConstructor the type has */
|
/** For abstract types, determine what kind of ArchiveConstructor the type has */
|
||||||
template<typename ValType, class ArchiveType>
|
template<typename ValType, class ArchiveType>
|
||||||
struct ArchiveConstructorType
|
struct ArchiveConstructorType
|
||||||
{
|
{
|
||||||
typedef ABSTRACT_TYPE ObjType;
|
/** Figure out the type being used to represent the object type.
|
||||||
|
* If there isn't a type function, then it doesn't matter; just substitute int.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
static constexpr auto HasTypeMethod(int) -> decltype( std::declval<T>().Type() )
|
||||||
|
{
|
||||||
|
return std::declval<T>().Type();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static constexpr int HasTypeMethod(...)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
using ObjType = decltype(HasTypeMethod<ValType>(0));
|
||||||
|
|
||||||
enum { Basic, Advanced, None };
|
enum { Basic, Advanced, None };
|
||||||
|
|
||||||
|
@ -340,7 +357,7 @@ public:
|
||||||
mParmStack.reserve(16);
|
mParmStack.reserve(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~IArchive() {}
|
virtual ~IArchive() { ASSERT(mParmStack.empty()); }
|
||||||
|
|
||||||
// Serialize archive version. Always call after opening a file.
|
// Serialize archive version. Always call after opening a file.
|
||||||
void SerializeVersion()
|
void SerializeVersion()
|
||||||
|
|
|
@ -266,7 +266,6 @@ CGameProject* CGameProject::LoadProject(const TString& rkProjPath, IProgressNoti
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CTemplateLoader::LoadGameTemplates(pProj->mGame);
|
|
||||||
pProj->mProjFileLock.Lock(ProjPath);
|
pProj->mProjFileLock.Lock(ProjPath);
|
||||||
pProj->mpGameInfo->LoadGameInfo(pProj->mGame);
|
pProj->mpGameInfo->LoadGameInfo(pProj->mGame);
|
||||||
pProj->mpAudioManager->LoadAssets();
|
pProj->mpAudioManager->LoadAssets();
|
||||||
|
|
|
@ -137,7 +137,7 @@ CStructPropertyNew* CLight::GetProperties() const
|
||||||
if (!pProperties)
|
if (!pProperties)
|
||||||
{
|
{
|
||||||
pProperties = (CStructPropertyNew*) IPropertyNew::CreateIntrinsic(EPropertyTypeNew::Struct,
|
pProperties = (CStructPropertyNew*) IPropertyNew::CreateIntrinsic(EPropertyTypeNew::Struct,
|
||||||
nullptr,
|
ePrime,
|
||||||
0,
|
0,
|
||||||
"Light");
|
"Light");
|
||||||
|
|
||||||
|
|
|
@ -189,14 +189,14 @@ IPropertyNew* CTemplateLoader::LoadProperty(XMLElement* pElem, CScriptTemplate*
|
||||||
// create property as a copy of the archetype
|
// create property as a copy of the archetype
|
||||||
if (pArchetype != nullptr)
|
if (pArchetype != nullptr)
|
||||||
{
|
{
|
||||||
pProp = IPropertyNew::CreateCopy(pArchetype, pParent);
|
pProp = IPropertyNew::CreateCopy(pArchetype);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// no archetype, so do normal create
|
// no archetype, so do normal create
|
||||||
if (!pProp)
|
if (!pProp)
|
||||||
{
|
{
|
||||||
pProp = IPropertyNew::Create(Type, pParent, mGame, pScript, false);
|
pProp = IPropertyNew::Create(Type, mGame);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we need to have a valid property by this point
|
// we need to have a valid property by this point
|
||||||
|
@ -340,7 +340,7 @@ IPropertyNew* CTemplateLoader::LoadProperty(XMLElement* pElem, CScriptTemplate*
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pArray->mpItemArchetype = IPropertyNew::Create(EPropertyTypeNew::Struct, pArray, mGame, pScript, false);
|
pArray->mpItemArchetype = IPropertyNew::Create(EPropertyTypeNew::Struct, mGame);
|
||||||
pStruct = TPropCast<CStructPropertyNew>(pArray->mpItemArchetype);
|
pStruct = TPropCast<CStructPropertyNew>(pArray->mpItemArchetype);
|
||||||
pStruct->mFlags = EPropertyFlag::IsAtomic | EPropertyFlag::IsArrayArchetype;
|
pStruct->mFlags = EPropertyFlag::IsAtomic | EPropertyFlag::IsArrayArchetype;
|
||||||
}
|
}
|
||||||
|
@ -358,17 +358,16 @@ IPropertyNew* CTemplateLoader::LoadProperty(XMLElement* pElem, CScriptTemplate*
|
||||||
{
|
{
|
||||||
LoadProperties(pProperties, pScript, pStruct, rkTemplateName);
|
LoadProperties(pProperties, pScript, pStruct, rkTemplateName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Type == EPropertyTypeNew::Array)
|
|
||||||
{
|
|
||||||
pStruct->PostInitialize();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsNewProperty)
|
if (IsNewProperty)
|
||||||
|
{
|
||||||
CMasterTemplate::AddProperty(pProp, mMasterDir + rkTemplateName);
|
CMasterTemplate::AddProperty(pProp, mMasterDir + rkTemplateName);
|
||||||
|
|
||||||
pProp->PostInitialize();
|
if (pParent)
|
||||||
|
pParent->mChildren.push_back(pProp);
|
||||||
|
}
|
||||||
|
|
||||||
return pProp;
|
return pProp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,11 +392,7 @@ CStructPropertyNew* CTemplateLoader::LoadStructArchetype(const TString& rkTempla
|
||||||
if (!Doc.Error())
|
if (!Doc.Error())
|
||||||
{
|
{
|
||||||
pArchetype = TPropCast<CStructPropertyNew>(
|
pArchetype = TPropCast<CStructPropertyNew>(
|
||||||
IPropertyNew::Create(EPropertyTypeNew::Struct,
|
IPropertyNew::Create(EPropertyTypeNew::Struct, mGame)
|
||||||
nullptr,
|
|
||||||
mGame,
|
|
||||||
nullptr,
|
|
||||||
false)
|
|
||||||
);
|
);
|
||||||
ASSERT(pArchetype != nullptr);
|
ASSERT(pArchetype != nullptr);
|
||||||
|
|
||||||
|
@ -438,7 +433,7 @@ CStructPropertyNew* CTemplateLoader::LoadStructArchetype(const TString& rkTempla
|
||||||
ASSERT(pSubPropsElem);
|
ASSERT(pSubPropsElem);
|
||||||
|
|
||||||
LoadProperties(pSubPropsElem, nullptr, pArchetype, rkTemplateFileName);
|
LoadProperties(pSubPropsElem, nullptr, pArchetype, rkTemplateFileName);
|
||||||
pArchetype->PostInitialize();
|
pArchetype->Initialize(nullptr, nullptr, 0);
|
||||||
|
|
||||||
mpMaster->mPropertyTemplates.emplace(
|
mpMaster->mPropertyTemplates.emplace(
|
||||||
std::make_pair(
|
std::make_pair(
|
||||||
|
@ -474,11 +469,7 @@ CEnumProperty* CTemplateLoader::LoadEnumArchetype(const TString& rkTemplateFileN
|
||||||
{
|
{
|
||||||
// use static_cast so this code works for both enum and choice
|
// use static_cast so this code works for both enum and choice
|
||||||
pArchetype = static_cast<CEnumProperty*>(
|
pArchetype = static_cast<CEnumProperty*>(
|
||||||
IPropertyNew::Create(bIsChoice ? EPropertyTypeNew::Choice : EPropertyTypeNew::Enum,
|
IPropertyNew::Create(bIsChoice ? EPropertyTypeNew::Choice : EPropertyTypeNew::Enum, mGame)
|
||||||
nullptr,
|
|
||||||
mGame,
|
|
||||||
nullptr,
|
|
||||||
false)
|
|
||||||
);
|
);
|
||||||
ASSERT(pArchetype != nullptr);
|
ASSERT(pArchetype != nullptr);
|
||||||
|
|
||||||
|
@ -493,7 +484,7 @@ CEnumProperty* CTemplateLoader::LoadEnumArchetype(const TString& rkTemplateFileN
|
||||||
ASSERT(pEnumers);
|
ASSERT(pEnumers);
|
||||||
|
|
||||||
LoadEnumerators(pEnumers, pArchetype, rkTemplateFileName);
|
LoadEnumerators(pEnumers, pArchetype, rkTemplateFileName);
|
||||||
pArchetype->PostInitialize();
|
pArchetype->Initialize(nullptr, nullptr, 0);
|
||||||
|
|
||||||
mpMaster->mPropertyTemplates.emplace(
|
mpMaster->mPropertyTemplates.emplace(
|
||||||
std::make_pair(
|
std::make_pair(
|
||||||
|
@ -528,11 +519,7 @@ CFlagsProperty* CTemplateLoader::LoadFlagsArchetype(const TString& rkTemplateFil
|
||||||
if (!Doc.Error())
|
if (!Doc.Error())
|
||||||
{
|
{
|
||||||
pArchetype = TPropCast<CFlagsProperty>(
|
pArchetype = TPropCast<CFlagsProperty>(
|
||||||
IPropertyNew::Create(EPropertyTypeNew::Flags,
|
IPropertyNew::Create(EPropertyTypeNew::Flags, mGame)
|
||||||
nullptr,
|
|
||||||
mGame,
|
|
||||||
nullptr,
|
|
||||||
false)
|
|
||||||
);
|
);
|
||||||
ASSERT(pArchetype != nullptr);
|
ASSERT(pArchetype != nullptr);
|
||||||
|
|
||||||
|
@ -547,7 +534,7 @@ CFlagsProperty* CTemplateLoader::LoadFlagsArchetype(const TString& rkTemplateFil
|
||||||
ASSERT(pFlags);
|
ASSERT(pFlags);
|
||||||
|
|
||||||
LoadBitFlags(pFlags, pArchetype, rkTemplateFileName);
|
LoadBitFlags(pFlags, pArchetype, rkTemplateFileName);
|
||||||
pArchetype->PostInitialize();
|
pArchetype->Initialize(nullptr, nullptr, 0);
|
||||||
|
|
||||||
mpMaster->mPropertyTemplates.emplace(
|
mpMaster->mPropertyTemplates.emplace(
|
||||||
std::make_pair(
|
std::make_pair(
|
||||||
|
@ -645,7 +632,7 @@ CScriptTemplate* CTemplateLoader::LoadScriptTemplate(XMLDocument *pDoc, const TS
|
||||||
pScript->mObjectID = ObjectID;
|
pScript->mObjectID = ObjectID;
|
||||||
pScript->mSourceFile = rkTemplateName;
|
pScript->mSourceFile = rkTemplateName;
|
||||||
|
|
||||||
IPropertyNew* pBaseStruct = IPropertyNew::Create(EPropertyTypeNew::Struct, nullptr, mGame, pScript);
|
IPropertyNew* pBaseStruct = IPropertyNew::Create(EPropertyTypeNew::Struct, mGame);
|
||||||
pScript->mpProperties = std::make_unique<CStructPropertyNew>( *TPropCast<CStructPropertyNew>(pBaseStruct) );
|
pScript->mpProperties = std::make_unique<CStructPropertyNew>( *TPropCast<CStructPropertyNew>(pBaseStruct) );
|
||||||
|
|
||||||
XMLElement *pRoot = pDoc->FirstChildElement("ScriptTemplate");
|
XMLElement *pRoot = pDoc->FirstChildElement("ScriptTemplate");
|
||||||
|
@ -1139,7 +1126,7 @@ TString CTemplateLoader::ErrorName(XMLError Error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ PUBLIC ************
|
// ************ PUBLIC ************
|
||||||
#define USE_NEW_TEMPLATES 0
|
#define USE_NEW_TEMPLATES 1
|
||||||
|
|
||||||
void CTemplateLoader::LoadGameList()
|
void CTemplateLoader::LoadGameList()
|
||||||
{
|
{
|
||||||
|
@ -1193,7 +1180,7 @@ void CTemplateLoader::LoadGameList()
|
||||||
for (auto Iter = MasterList.begin(); Iter != MasterList.end(); Iter++)
|
for (auto Iter = MasterList.begin(); Iter != MasterList.end(); Iter++)
|
||||||
{
|
{
|
||||||
CMasterTemplate* pMaster = *Iter;
|
CMasterTemplate* pMaster = *Iter;
|
||||||
const TString kMasterPath = kTemplatesDir + pMaster->GetDirectory() + "Game.xml";
|
const TString kMasterPath = pMaster->GetGameDirectory(true) + "Game.xml";
|
||||||
|
|
||||||
CXMLReader Reader(kMasterPath);
|
CXMLReader Reader(kMasterPath);
|
||||||
ASSERT(Reader.IsValid());
|
ASSERT(Reader.IsValid());
|
||||||
|
@ -1354,7 +1341,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() + "Game.xml";
|
Info.MasterPath = pMaster->GetGameDirectory() + "Game.xml";
|
||||||
Writer << SerialParameter("Game", Info);
|
Writer << SerialParameter("Game", Info);
|
||||||
}
|
}
|
||||||
Writer.ParamEnd();
|
Writer.ParamEnd();
|
||||||
|
@ -1373,7 +1360,7 @@ void CTemplateLoader::SaveGameList()
|
||||||
for (auto Iter = MasterList.begin(); Iter != MasterList.end(); Iter++)
|
for (auto Iter = MasterList.begin(); Iter != MasterList.end(); Iter++)
|
||||||
{
|
{
|
||||||
CMasterTemplate* pMasterTemplate = *Iter;
|
CMasterTemplate* pMasterTemplate = *Iter;
|
||||||
TString MasterFilePath = kTemplatesDir + pMasterTemplate->GetDirectory() + "Game.xml";
|
TString MasterFilePath = pMasterTemplate->GetGameDirectory(true) + "Game.xml";
|
||||||
FileUtil::MakeDirectory( MasterFilePath.GetFileDirectory() );
|
FileUtil::MakeDirectory( MasterFilePath.GetFileDirectory() );
|
||||||
|
|
||||||
CXMLWriter Writer(MasterFilePath, "Game", 0, pMasterTemplate->Game());
|
CXMLWriter Writer(MasterFilePath, "Game", 0, pMasterTemplate->Game());
|
||||||
|
|
|
@ -17,17 +17,52 @@ void CMasterTemplate::Serialize(IArchive& Arc)
|
||||||
|
|
||||||
void CMasterTemplate::LoadSubTemplates()
|
void CMasterTemplate::LoadSubTemplates()
|
||||||
{
|
{
|
||||||
//todo
|
for (auto Iter = mScriptTemplates.begin(); Iter != mScriptTemplates.end(); Iter++)
|
||||||
|
Internal_LoadScriptTemplate( Iter->second );
|
||||||
|
|
||||||
|
for (auto Iter = mPropertyTemplates.begin(); Iter != mPropertyTemplates.end(); Iter++)
|
||||||
|
Internal_LoadPropertyTemplate( Iter->second );
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMasterTemplate::Internal_LoadScriptTemplate(SScriptTemplatePath& Path)
|
||||||
|
{
|
||||||
|
ASSERT(Path.pTemplate == nullptr); // make sure it hasn't been loaded yet
|
||||||
|
|
||||||
|
const TString kGameDir = GetGameDirectory(true);
|
||||||
|
const TString kTemplateFilePath = kGameDir + Path.Path;
|
||||||
|
CXMLReader Reader(kTemplateFilePath);
|
||||||
|
ASSERT(Reader.IsValid());
|
||||||
|
|
||||||
|
Path.pTemplate = std::make_shared<CScriptTemplate>(this, Path.ID.ID, Path.Path);
|
||||||
|
Path.pTemplate->Serialize(Reader);
|
||||||
|
Path.pTemplate->PostLoad();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMasterTemplate::Internal_LoadPropertyTemplate(SPropertyTemplatePath& Path)
|
||||||
|
{
|
||||||
|
if (Path.pTemplate != nullptr) // don't load twice
|
||||||
|
return;
|
||||||
|
|
||||||
|
const TString kGameDir = GetGameDirectory(true);
|
||||||
|
const TString kTemplateFilePath = kGameDir + Path.Path;
|
||||||
|
CXMLReader Reader(kTemplateFilePath);
|
||||||
|
ASSERT(Reader.IsValid());
|
||||||
|
|
||||||
|
Reader << SerialParameter("PropertyArchetype", Path.pTemplate);
|
||||||
|
ASSERT(Path.pTemplate != nullptr);
|
||||||
|
|
||||||
|
Path.pTemplate->SetPropertyFlags( EPropertyFlag::IsArchetype );
|
||||||
|
Path.pTemplate->Initialize(nullptr, nullptr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMasterTemplate::SaveSubTemplates()
|
void CMasterTemplate::SaveSubTemplates()
|
||||||
{
|
{
|
||||||
TString GameDir = "../templates_new/" + GetDirectory();
|
const TString kGameDir = GetGameDirectory(true);
|
||||||
|
|
||||||
for (auto Iter = mScriptTemplates.begin(); Iter != mScriptTemplates.end(); Iter++)
|
for (auto Iter = mScriptTemplates.begin(); Iter != mScriptTemplates.end(); Iter++)
|
||||||
{
|
{
|
||||||
SScriptTemplatePath& Path = Iter->second;
|
SScriptTemplatePath& Path = Iter->second;
|
||||||
TString OutPath = GameDir + Path.Path;
|
TString OutPath = kGameDir + Path.Path;
|
||||||
|
|
||||||
FileUtil::MakeDirectory( OutPath.GetFileDirectory() );
|
FileUtil::MakeDirectory( OutPath.GetFileDirectory() );
|
||||||
CXMLWriter Writer(OutPath, "ScriptObject", 0, Game());
|
CXMLWriter Writer(OutPath, "ScriptObject", 0, Game());
|
||||||
|
@ -37,11 +72,11 @@ void CMasterTemplate::SaveSubTemplates()
|
||||||
for (auto Iter = mPropertyTemplates.begin(); Iter != mPropertyTemplates.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 = kGameDir + Path.Path;
|
||||||
|
|
||||||
FileUtil::MakeDirectory( OutPath.GetFileDirectory() );
|
FileUtil::MakeDirectory( OutPath.GetFileDirectory() );
|
||||||
CXMLWriter Writer(OutPath, "PropertyArchetype", 0, Game());
|
CXMLWriter Writer(OutPath, "PropertyTemplate", 0, Game());
|
||||||
Path.pTemplate->Serialize(Writer);
|
Writer << SerialParameter("PropertyArchetype", Path.pTemplate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,10 +150,34 @@ SMessage CMasterTemplate::MessageByIndex(u32 Index)
|
||||||
return SMessage(Iter->first, Iter->second);
|
return SMessage(Iter->first, Iter->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
IPropertyNew* CMasterTemplate::FindPropertyArchetype(const TString& kTypeName) const
|
IPropertyNew* CMasterTemplate::FindPropertyArchetype(const TString& kTypeName)
|
||||||
{
|
{
|
||||||
auto Iter = mPropertyTemplates.find(kTypeName);
|
auto Iter = mPropertyTemplates.find(kTypeName);
|
||||||
return (Iter != mPropertyTemplates.end()) ? Iter->second.pTemplate.get() : nullptr;
|
|
||||||
|
// Should require Iter to be valid in the future. For now, this is possible for some of the transition template loader code.
|
||||||
|
// ASSERT(Iter != mPropertyTemplates.end()); // Requested archetype property does not exist; missing or malformed template
|
||||||
|
if (Iter == mPropertyTemplates.end())
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the template isn't loaded yet, then load it.
|
||||||
|
// This has to be done here to allow recursion while loading other property archetypes, because some properties may
|
||||||
|
// request archetypes of other properties that haven't been loaded yet during their load.
|
||||||
|
SPropertyTemplatePath& Path = Iter->second;
|
||||||
|
if (!Path.pTemplate)
|
||||||
|
{
|
||||||
|
Internal_LoadPropertyTemplate(Path);
|
||||||
|
ASSERT(Path.pTemplate != nullptr); // Load failed; missing or malformed template
|
||||||
|
}
|
||||||
|
|
||||||
|
return Path.pTemplate.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
TString CMasterTemplate::GetGameDirectory(bool Absolute) const
|
||||||
|
{
|
||||||
|
TString Out = mSourceFile.GetFileDirectory();
|
||||||
|
return Absolute ? "../templates_new/" + Out : Out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ************ STATIC ************
|
// ************ STATIC ************
|
||||||
|
|
|
@ -124,6 +124,9 @@ class CMasterTemplate
|
||||||
static std::map<u32, TString> smPropertyNames;
|
static std::map<u32, TString> smPropertyNames;
|
||||||
static u32 smGameListVersion;
|
static u32 smGameListVersion;
|
||||||
|
|
||||||
|
void Internal_LoadScriptTemplate(SScriptTemplatePath& Path);
|
||||||
|
void Internal_LoadPropertyTemplate(SPropertyTemplatePath& Path);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CMasterTemplate();
|
CMasterTemplate();
|
||||||
void Serialize(IArchive& Arc);
|
void Serialize(IArchive& Arc);
|
||||||
|
@ -139,7 +142,8 @@ 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;
|
IPropertyNew* FindPropertyArchetype(const TString& kTypeName);
|
||||||
|
TString GetGameDirectory(bool Absolute = false) const;
|
||||||
|
|
||||||
// Inline Accessors
|
// Inline Accessors
|
||||||
inline EGame Game() const { return mGame; }
|
inline EGame Game() const { return mGame; }
|
||||||
|
@ -148,7 +152,6 @@ public:
|
||||||
inline u32 NumStates() const { return mStates.size(); }
|
inline u32 NumStates() const { return mStates.size(); }
|
||||||
inline u32 NumMessages() const { return mMessages.size(); }
|
inline u32 NumMessages() const { return mMessages.size(); }
|
||||||
inline bool IsLoadedSuccessfully() { return mFullyLoaded; }
|
inline bool IsLoadedSuccessfully() { return mFullyLoaded; }
|
||||||
inline TString GetDirectory() const { return mSourceFile.GetFileDirectory(); }
|
|
||||||
|
|
||||||
// Static
|
// Static
|
||||||
static CMasterTemplate* MasterForGame(EGame Game);
|
static CMasterTemplate* MasterForGame(EGame Game);
|
||||||
|
|
|
@ -79,6 +79,8 @@ void CScriptTemplate::Serialize(IArchive& Arc)
|
||||||
|
|
||||||
void CScriptTemplate::PostLoad()
|
void CScriptTemplate::PostLoad()
|
||||||
{
|
{
|
||||||
|
mpProperties->Initialize(nullptr, this, 0);
|
||||||
|
|
||||||
if (!mNameIDString.IsEmpty()) mpNameProperty = TPropCast<CStringProperty>( mpProperties->ChildByIDString(mNameIDString) );
|
if (!mNameIDString.IsEmpty()) mpNameProperty = TPropCast<CStringProperty>( mpProperties->ChildByIDString(mNameIDString) );
|
||||||
if (!mPositionIDString.IsEmpty()) mpPositionProperty = TPropCast<CVectorProperty>( mpProperties->ChildByIDString(mPositionIDString) );
|
if (!mPositionIDString.IsEmpty()) mpPositionProperty = TPropCast<CVectorProperty>( mpProperties->ChildByIDString(mPositionIDString) );
|
||||||
if (!mRotationIDString.IsEmpty()) mpRotationProperty = TPropCast<CVectorProperty>( mpProperties->ChildByIDString(mRotationIDString) );
|
if (!mRotationIDString.IsEmpty()) mpRotationProperty = TPropCast<CVectorProperty>( mpProperties->ChildByIDString(mRotationIDString) );
|
||||||
|
|
|
@ -130,6 +130,8 @@ private:
|
||||||
bool mVisible;
|
bool mVisible;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// Default constructor. Don't use. This is only here so the serializer doesn't complain
|
||||||
|
CScriptTemplate() { ASSERT(false); }
|
||||||
// Old constructor
|
// Old constructor
|
||||||
CScriptTemplate(CMasterTemplate *pMaster);
|
CScriptTemplate(CMasterTemplate *pMaster);
|
||||||
// New constructor
|
// New constructor
|
||||||
|
|
|
@ -9,10 +9,12 @@
|
||||||
#include "Core/Resource/Script/CScriptTemplate.h"
|
#include "Core/Resource/Script/CScriptTemplate.h"
|
||||||
|
|
||||||
/** IPropertyNew */
|
/** IPropertyNew */
|
||||||
IPropertyNew::IPropertyNew()
|
IPropertyNew::IPropertyNew(EGame Game)
|
||||||
: mpParent( nullptr )
|
: mpParent( nullptr )
|
||||||
, mpPointerParent( nullptr )
|
, mpPointerParent( nullptr )
|
||||||
, mpArchetype( nullptr )
|
, mpArchetype( nullptr )
|
||||||
|
, mGame( Game )
|
||||||
|
, mpScriptTemplate( nullptr )
|
||||||
, mOffset( -1 )
|
, mOffset( -1 )
|
||||||
, mID( -1 )
|
, mID( -1 )
|
||||||
, mCookPreference( ECookPreferenceNew::Default )
|
, mCookPreference( ECookPreferenceNew::Default )
|
||||||
|
@ -20,41 +22,6 @@ IPropertyNew::IPropertyNew()
|
||||||
, mMaxVersion( FLT_MAX )
|
, mMaxVersion( FLT_MAX )
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void IPropertyNew::_CalcOffset()
|
|
||||||
{
|
|
||||||
// For standard properties, append to the end of the parent.
|
|
||||||
bool IsRootArrayArchetype = (IsArrayArchetype() && TPropCast<CArrayProperty>(mpParent) != nullptr);
|
|
||||||
|
|
||||||
if (mpParent && !IsRootArrayArchetype)
|
|
||||||
{
|
|
||||||
// When we have a parent, our data is usually located inside the parent's property data. So we want to
|
|
||||||
// position ourself at the end of the parent's existing children so we don't overlap any other properties.
|
|
||||||
IPropertyNew* pLastChild = (mpParent->mChildren.empty() ? nullptr : mpParent->mChildren.back());
|
|
||||||
|
|
||||||
if (pLastChild)
|
|
||||||
{
|
|
||||||
mOffset = pLastChild->mOffset + pLastChild->DataSize();
|
|
||||||
}
|
|
||||||
else if (mpParent != mpPointerParent)
|
|
||||||
{
|
|
||||||
mOffset = mpParent->mOffset;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mOffset = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mOffset = ALIGN(mOffset, DataAlignment());
|
|
||||||
}
|
|
||||||
// Array archetypes are accessed differently because they have no way of knowing
|
|
||||||
// which array index is meant to be accessed. So the offset is 0 and the caller
|
|
||||||
// is responsible for passing in a pointer to the correct array item.
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mOffset = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IPropertyNew::_ClearChildren()
|
void IPropertyNew::_ClearChildren()
|
||||||
{
|
{
|
||||||
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||||
|
@ -109,7 +76,6 @@ void IPropertyNew::Serialize(IArchive& rArc)
|
||||||
IPropertyNew* pArchetype = pMaster->FindPropertyArchetype(ArchetypeName);
|
IPropertyNew* pArchetype = pMaster->FindPropertyArchetype(ArchetypeName);
|
||||||
|
|
||||||
// The archetype must exist, or else the template file is malformed.
|
// 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);
|
ASSERT(pArchetype != nullptr);
|
||||||
|
|
||||||
InitFromArchetype(pArchetype);
|
InitFromArchetype(pArchetype);
|
||||||
|
@ -118,7 +84,12 @@ void IPropertyNew::Serialize(IArchive& rArc)
|
||||||
|
|
||||||
// In MP1, the game data does not use property IDs, so we serialize the name directly.
|
// In MP1, the game data does not use property IDs, so we serialize the name directly.
|
||||||
// In MP2 and on, property names are looked up based on the property ID via the property name map.
|
// In MP2 and on, property names are looked up based on the property ID via the property name map.
|
||||||
if (rArc.Game() <= ePrime && !IsArchetype())
|
// Exceptions: Properties that are not in the name map still need to serialize their names.
|
||||||
|
// This includes root-level properties, and properties of atomic structs.
|
||||||
|
//
|
||||||
|
// We can't currently tell if this property is atomic, as the flag hasn't been serialized and the parent
|
||||||
|
// hasn't been set, but atomic sub-properties don't use hash IDs, so we can do a pseudo-check against the ID.
|
||||||
|
if (rArc.Game() <= ePrime || IsRootParent() || mID <= 0xFF)
|
||||||
{
|
{
|
||||||
rArc << SerialParameter("Name", mName, mpArchetype ? SH_Optional : 0, mpArchetype ? mpArchetype->mName : "");
|
rArc << SerialParameter("Name", mName, mpArchetype ? SH_Optional : 0, mpArchetype ? mpArchetype->mName : "");
|
||||||
}
|
}
|
||||||
|
@ -137,7 +108,6 @@ void IPropertyNew::InitFromArchetype(IPropertyNew* pOther)
|
||||||
//@todo maybe somehow use Serialize for this instead?
|
//@todo maybe somehow use Serialize for this instead?
|
||||||
mpArchetype = pOther;
|
mpArchetype = pOther;
|
||||||
mFlags = pOther->mFlags & EPropertyFlag::ArchetypeCopyFlags;
|
mFlags = pOther->mFlags & EPropertyFlag::ArchetypeCopyFlags;
|
||||||
mID = pOther->mID;
|
|
||||||
mName = pOther->mName;
|
mName = pOther->mName;
|
||||||
mDescription = pOther->mDescription;
|
mDescription = pOther->mDescription;
|
||||||
mSuffix = pOther->mSuffix;
|
mSuffix = pOther->mSuffix;
|
||||||
|
@ -145,12 +115,10 @@ void IPropertyNew::InitFromArchetype(IPropertyNew* pOther)
|
||||||
mMinVersion = pOther->mMinVersion;
|
mMinVersion = pOther->mMinVersion;
|
||||||
mMaxVersion = pOther->mMaxVersion;
|
mMaxVersion = pOther->mMaxVersion;
|
||||||
|
|
||||||
// Copy children
|
// Copy ID only if our existing ID is not valid.
|
||||||
_ClearChildren();
|
if (mID == 0xFFFFFFFF)
|
||||||
|
|
||||||
for (u32 ChildIdx = 0; ChildIdx < pOther->mChildren.size(); ChildIdx++)
|
|
||||||
{
|
{
|
||||||
CreateCopy( pOther->mChildren[ChildIdx], this );
|
mID = pOther->mID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,6 +151,62 @@ TString IPropertyNew::GetTemplateFileName()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IPropertyNew::Initialize(IPropertyNew* pInParent, CScriptTemplate* pInTemplate, u32 InOffset)
|
||||||
|
{
|
||||||
|
// Make sure we only get initialized once.
|
||||||
|
ASSERT( (mFlags & EPropertyFlag::IsInitialized) == 0 );
|
||||||
|
mFlags |= EPropertyFlag::IsInitialized;
|
||||||
|
|
||||||
|
mpParent = pInParent;
|
||||||
|
mOffset = InOffset;
|
||||||
|
mpScriptTemplate = pInTemplate;
|
||||||
|
|
||||||
|
// Look up property name if needed.
|
||||||
|
if (Game() >= eEchoesDemo && !IsRootParent() && !IsIntrinsic() && !mpParent->IsAtomic())
|
||||||
|
{
|
||||||
|
mName = CMasterTemplate::PropertyName(mID);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set any fields dependent on the parent...
|
||||||
|
if (mpParent)
|
||||||
|
{
|
||||||
|
mFlags |= mpParent->mFlags & EPropertyFlag::InheritableFlags;
|
||||||
|
|
||||||
|
if (mpParent->IsPointerType())
|
||||||
|
{
|
||||||
|
mpPointerParent = mpParent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mpPointerParent = mpParent->mpPointerParent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow subclasses to handle any initialization tasks
|
||||||
|
PostInitialize();
|
||||||
|
|
||||||
|
// Now, route initialization to any child properties...
|
||||||
|
u32 ChildOffset = mOffset;
|
||||||
|
|
||||||
|
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
||||||
|
{
|
||||||
|
IPropertyNew* pChild = mChildren[ChildIdx];
|
||||||
|
|
||||||
|
// update offset and round up to the child's alignment
|
||||||
|
if (ChildIdx > 0)
|
||||||
|
{
|
||||||
|
ChildOffset += mChildren[ChildIdx-1]->DataSize();
|
||||||
|
}
|
||||||
|
ChildOffset = ALIGN(ChildOffset, pChild->DataAlignment());
|
||||||
|
|
||||||
|
// Don't call Initialize on intrinsic children as they have already been initialized.
|
||||||
|
if (!pChild->IsIntrinsic())
|
||||||
|
{
|
||||||
|
pChild->Initialize(this, pInTemplate, ChildOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void* IPropertyNew::RawValuePtr(void* pData) const
|
void* IPropertyNew::RawValuePtr(void* pData) const
|
||||||
{
|
{
|
||||||
// For array archetypes, the caller needs to provide the pointer to the correct array item
|
// For array archetypes, the caller needs to provide the pointer to the correct array item
|
||||||
|
@ -266,8 +290,27 @@ void IPropertyNew::SetSuffix(const TString& rkNewSuffix)
|
||||||
mSuffix = rkNewSuffix;
|
mSuffix = rkNewSuffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IPropertyNew::SetPropertyFlags(FPropertyFlags FlagsToSet)
|
||||||
|
{
|
||||||
|
mFlags |= FlagsToSet;
|
||||||
|
}
|
||||||
|
|
||||||
bool IPropertyNew::HasAccurateName()
|
bool IPropertyNew::HasAccurateName()
|
||||||
{
|
{
|
||||||
|
// Exceptions for the three hardcoded 4CC property IDs
|
||||||
|
if (mID == FOURCC('XFRM') || mID == FOURCC('INAM') || mID == FOURCC('ACTV'))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Children of atomic properties defer to parents. Intrinsic properties also defer to parents.
|
||||||
|
if ( (mpParent && mpParent->IsAtomic()) || IsIntrinsic() )
|
||||||
|
{
|
||||||
|
if (mpParent)
|
||||||
|
return mpParent->HasAccurateName();
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For everything else, hash the property name and check if it is a match for the property ID
|
||||||
if (!mFlags.HasFlag(EPropertyFlag::HasCachedNameCheck))
|
if (!mFlags.HasFlag(EPropertyFlag::HasCachedNameCheck))
|
||||||
{
|
{
|
||||||
CCRC32 Hash;
|
CCRC32 Hash;
|
||||||
|
@ -293,114 +336,79 @@ EGame IPropertyNew::Game() const
|
||||||
}
|
}
|
||||||
|
|
||||||
IPropertyNew* IPropertyNew::Create(EPropertyTypeNew Type,
|
IPropertyNew* IPropertyNew::Create(EPropertyTypeNew Type,
|
||||||
IPropertyNew* pParent,
|
EGame Game)
|
||||||
EGame Game,
|
|
||||||
CScriptTemplate* pScript,
|
|
||||||
bool CallPostInit /*= true*/)
|
|
||||||
{
|
{
|
||||||
IPropertyNew* pOut = nullptr;
|
IPropertyNew* pOut = nullptr;
|
||||||
|
|
||||||
switch (Type)
|
switch (Type)
|
||||||
{
|
{
|
||||||
case EPropertyTypeNew::Bool: pOut = new CBoolProperty; break;
|
case EPropertyTypeNew::Bool: pOut = new CBoolProperty(Game); break;
|
||||||
case EPropertyTypeNew::Byte: pOut = new CByteProperty; break;
|
case EPropertyTypeNew::Byte: pOut = new CByteProperty(Game); break;
|
||||||
case EPropertyTypeNew::Short: pOut = new CShortProperty; break;
|
case EPropertyTypeNew::Short: pOut = new CShortProperty(Game); break;
|
||||||
case EPropertyTypeNew::Int: pOut = new CIntProperty; break;
|
case EPropertyTypeNew::Int: pOut = new CIntProperty(Game); break;
|
||||||
case EPropertyTypeNew::Float: pOut = new CFloatProperty; break;
|
case EPropertyTypeNew::Float: pOut = new CFloatProperty(Game); break;
|
||||||
case EPropertyTypeNew::Choice: pOut = new CChoiceProperty; break;
|
case EPropertyTypeNew::Choice: pOut = new CChoiceProperty(Game); break;
|
||||||
case EPropertyTypeNew::Enum: pOut = new CEnumProperty; break;
|
case EPropertyTypeNew::Enum: pOut = new CEnumProperty(Game); break;
|
||||||
case EPropertyTypeNew::Flags: pOut = new CFlagsProperty; break;
|
case EPropertyTypeNew::Flags: pOut = new CFlagsProperty(Game); break;
|
||||||
case EPropertyTypeNew::String: pOut = new CStringProperty; break;
|
case EPropertyTypeNew::String: pOut = new CStringProperty(Game); break;
|
||||||
case EPropertyTypeNew::Vector: pOut = new CVectorProperty; break;
|
case EPropertyTypeNew::Vector: pOut = new CVectorProperty(Game); break;
|
||||||
case EPropertyTypeNew::Color: pOut = new CColorProperty; break;
|
case EPropertyTypeNew::Color: pOut = new CColorProperty(Game); break;
|
||||||
case EPropertyTypeNew::Asset: pOut = new CAssetProperty; break;
|
case EPropertyTypeNew::Asset: pOut = new CAssetProperty(Game); break;
|
||||||
case EPropertyTypeNew::Sound: pOut = new CSoundProperty; break;
|
case EPropertyTypeNew::Sound: pOut = new CSoundProperty(Game); break;
|
||||||
case EPropertyTypeNew::Animation: pOut = new CAnimationProperty; break;
|
case EPropertyTypeNew::Animation: pOut = new CAnimationProperty(Game); break;
|
||||||
case EPropertyTypeNew::AnimationSet: pOut = new CAnimationSetProperty; break;
|
case EPropertyTypeNew::AnimationSet: pOut = new CAnimationSetProperty(Game); break;
|
||||||
case EPropertyTypeNew::Sequence: pOut = new CSequenceProperty; break;
|
case EPropertyTypeNew::Sequence: pOut = new CSequenceProperty(Game); break;
|
||||||
case EPropertyTypeNew::Spline: pOut = new CSplineProperty; break;
|
case EPropertyTypeNew::Spline: pOut = new CSplineProperty(Game); break;
|
||||||
case EPropertyTypeNew::Guid: pOut = new CGuidProperty; break;
|
case EPropertyTypeNew::Guid: pOut = new CGuidProperty(Game); break;
|
||||||
case EPropertyTypeNew::Pointer: pOut = new CPointerProperty; break;
|
case EPropertyTypeNew::Pointer: pOut = new CPointerProperty(Game); break;
|
||||||
case EPropertyTypeNew::Struct: pOut = new CStructPropertyNew; break;
|
case EPropertyTypeNew::Struct: pOut = new CStructPropertyNew(Game); break;
|
||||||
case EPropertyTypeNew::Array: pOut = new CArrayProperty; break;
|
case EPropertyTypeNew::Array: pOut = new CArrayProperty(Game); break;
|
||||||
}
|
|
||||||
|
|
||||||
if (!pOut)
|
|
||||||
{
|
|
||||||
// this shouldn't be possible! unhandled type! someone fucked up!
|
|
||||||
ASSERT(false);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set parent and offset
|
|
||||||
pOut->mpParent = pParent;
|
|
||||||
|
|
||||||
if (pParent)
|
|
||||||
{
|
|
||||||
pOut->mFlags = pParent->mFlags & EPropertyFlag::InheritableFlags;
|
|
||||||
|
|
||||||
if (pParent->IsPointerType())
|
|
||||||
{
|
|
||||||
pOut->mpPointerParent = pParent;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pOut->mpPointerParent = pParent->mpPointerParent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set other metadata
|
|
||||||
pOut->mGame = Game;
|
|
||||||
pOut->mpScriptTemplate = pScript;
|
|
||||||
pOut->_CalcOffset();
|
|
||||||
|
|
||||||
// Add to the parent's array. This needs to be done -after- we calculate offset, as adding a child to
|
|
||||||
// the parent property will change the offset that gets calculated.
|
|
||||||
if (pParent)
|
|
||||||
{
|
|
||||||
pParent->mChildren.push_back(pOut);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CallPostInit)
|
|
||||||
{
|
|
||||||
pOut->PostInitialize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this assertion fails, then there is an unhandled type!
|
||||||
|
ASSERT(pOut != nullptr);
|
||||||
return pOut;
|
return pOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPropertyNew* IPropertyNew::CreateCopy(IPropertyNew* pArchetype,
|
IPropertyNew* IPropertyNew::CreateCopy(IPropertyNew* pArchetype)
|
||||||
IPropertyNew* pParent)
|
|
||||||
{
|
{
|
||||||
// Note this is mainly going to be used to create copies from struct/enum/flag archetype properties.
|
IPropertyNew* pOut = Create(pArchetype->Type(), pArchetype->mGame);
|
||||||
// Properties that have archetypes will never be the root property of a script template, and there
|
|
||||||
// is no case where we will be creating archetypes outside this context. As such, pParent should
|
|
||||||
// always be valid.
|
|
||||||
ASSERT(pParent != nullptr);
|
|
||||||
|
|
||||||
IPropertyNew* pOut = Create(pArchetype->Type(), pParent, pParent->mGame, pParent->mpScriptTemplate, false);
|
|
||||||
pOut->InitFromArchetype(pArchetype);
|
pOut->InitFromArchetype(pArchetype);
|
||||||
pArchetype->mSubInstances.push_back(pOut);
|
pArchetype->mSubInstances.push_back(pOut);
|
||||||
return pOut;
|
return pOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IPropertyNew* IPropertyNew::CreateIntrinsic(EPropertyTypeNew Type,
|
||||||
|
EGame Game,
|
||||||
|
u32 Offset,
|
||||||
|
const TString& rkName)
|
||||||
|
{
|
||||||
|
IPropertyNew* pOut = Create(Type, Game);
|
||||||
|
pOut->mFlags |= EPropertyFlag::IsIntrinsic;
|
||||||
|
pOut->SetName(rkName);
|
||||||
|
pOut->Initialize(nullptr, nullptr, Offset);
|
||||||
|
return pOut;
|
||||||
|
}
|
||||||
|
|
||||||
IPropertyNew* IPropertyNew::CreateIntrinsic(EPropertyTypeNew Type,
|
IPropertyNew* IPropertyNew::CreateIntrinsic(EPropertyTypeNew Type,
|
||||||
IPropertyNew* pParent,
|
IPropertyNew* pParent,
|
||||||
u32 Offset,
|
u32 Offset,
|
||||||
const TString& rkName)
|
const TString& rkName)
|
||||||
{
|
{
|
||||||
IPropertyNew* pOut = Create(Type, pParent, pParent ? pParent->mGame : eUnknownGame, nullptr, false);
|
// pParent should always be valid.
|
||||||
pOut->mOffset = Offset;
|
// If you are creating a root property, call the other overload takes an EGame instead of a parent.
|
||||||
|
ASSERT(pParent != nullptr);
|
||||||
|
|
||||||
|
IPropertyNew* pOut = Create(Type, pParent->mGame);
|
||||||
|
pOut->mFlags |= EPropertyFlag::IsIntrinsic;
|
||||||
pOut->SetName(rkName);
|
pOut->SetName(rkName);
|
||||||
pOut->PostInitialize();
|
pOut->Initialize(pParent, nullptr, Offset);
|
||||||
|
pParent->mChildren.push_back(pOut);
|
||||||
return pOut;
|
return pOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
IPropertyNew* IPropertyNew::ArchiveConstructor(EPropertyTypeNew Type,
|
IPropertyNew* IPropertyNew::ArchiveConstructor(EPropertyTypeNew Type,
|
||||||
const IArchive& Arc)
|
const IArchive& Arc)
|
||||||
{
|
{
|
||||||
IPropertyNew* pParent = Arc.FindParentObject<IPropertyNew>();
|
return Create(Type, Arc.Game());
|
||||||
CScriptTemplate* pTemplate = (pParent ? pParent->ScriptTemplate() : Arc.FindParentObject<CScriptTemplate>());
|
|
||||||
EGame Game = Arc.Game();
|
|
||||||
return Create(Type, pParent, Game, pTemplate);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,12 +19,16 @@ typedef TString TIDString;
|
||||||
/** Property flags */
|
/** Property flags */
|
||||||
enum class EPropertyFlag : u32
|
enum class EPropertyFlag : u32
|
||||||
{
|
{
|
||||||
|
/** Property has been fully initialized and has had PostLoad called */
|
||||||
|
IsInitialized = 0x1,
|
||||||
/** Property is an archetype (a template for other properties to copy from) */
|
/** Property is an archetype (a template for other properties to copy from) */
|
||||||
IsArchetype = 0x1,
|
IsArchetype = 0x2,
|
||||||
/** Property is an array archetype (a template for elements of an array property) */
|
/** Property is an array archetype (a template for elements of an array property) */
|
||||||
IsArrayArchetype = 0x2,
|
IsArrayArchetype = 0x4,
|
||||||
/** This property and all its children are a single unit and do not have individual property IDs, sizes, etc. */
|
/** This property and all its children are a single unit and do not have individual property IDs, sizes, etc. */
|
||||||
IsAtomic = 0x4,
|
IsAtomic = 0x8,
|
||||||
|
/** This is a property of a C++ class, not a script object */
|
||||||
|
IsIntrinsic = 0x10,
|
||||||
/** We have cached whether the property name is correct */
|
/** We have cached whether the property name is correct */
|
||||||
HasCachedNameCheck = 0x40000000,
|
HasCachedNameCheck = 0x40000000,
|
||||||
/** The name of the property is a match for the property ID hash */
|
/** The name of the property is a match for the property ID hash */
|
||||||
|
@ -122,8 +126,8 @@ protected:
|
||||||
/** Archetype property; source property that we copied metadata from */
|
/** Archetype property; source property that we copied metadata from */
|
||||||
IPropertyNew* mpArchetype;
|
IPropertyNew* mpArchetype;
|
||||||
|
|
||||||
/** Sub-instances of archetype properties. For non-archetypes, will be empty. @todo better
|
/** Sub-instances of archetype properties. For non-archetypes, will be empty.
|
||||||
* method of storing this? maybe a linked list? */
|
* @todo this really oughta be a linked list */
|
||||||
std::vector<IPropertyNew*> mSubInstances;
|
std::vector<IPropertyNew*> mSubInstances;
|
||||||
|
|
||||||
/** Child properties; these appear underneath this property on the UI */
|
/** Child properties; these appear underneath this property on the UI */
|
||||||
|
@ -155,13 +159,9 @@ protected:
|
||||||
float mMaxVersion;
|
float mMaxVersion;
|
||||||
|
|
||||||
/** Private constructor - use static methods to instantiate */
|
/** Private constructor - use static methods to instantiate */
|
||||||
IPropertyNew();
|
IPropertyNew(EGame Game);
|
||||||
void _CalcOffset();
|
|
||||||
void _ClearChildren();
|
void _ClearChildren();
|
||||||
|
|
||||||
/** Called after property is created and fully initialized */
|
|
||||||
virtual void PostInitialize() {}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual ~IPropertyNew();
|
virtual ~IPropertyNew();
|
||||||
|
|
||||||
|
@ -175,11 +175,11 @@ public:
|
||||||
virtual void RevertToDefault(void* pData) const = 0;
|
virtual void RevertToDefault(void* pData) const = 0;
|
||||||
virtual void SerializeValue(void* pData, IArchive& Arc) const = 0;
|
virtual void SerializeValue(void* pData, IArchive& Arc) const = 0;
|
||||||
|
|
||||||
|
virtual void PostInitialize() {}
|
||||||
virtual void PropertyValueChanged(void* pPropertyData) {}
|
virtual void PropertyValueChanged(void* pPropertyData) {}
|
||||||
virtual bool IsNumericalType() const { return false; }
|
virtual bool IsNumericalType() const { return false; }
|
||||||
virtual bool IsPointerType() const { return false; }
|
virtual bool IsPointerType() const { return false; }
|
||||||
virtual TString ValueAsString(void* pData) const { return ""; }
|
virtual TString ValueAsString(void* pData) const { return ""; }
|
||||||
|
|
||||||
virtual const char* HashableTypeName() const;
|
virtual const char* HashableTypeName() const;
|
||||||
virtual void* GetChildDataPointer(void* pPropertyData) const;
|
virtual void* GetChildDataPointer(void* pPropertyData) const;
|
||||||
virtual void Serialize(IArchive& rArc);
|
virtual void Serialize(IArchive& rArc);
|
||||||
|
@ -188,6 +188,7 @@ public:
|
||||||
virtual TString GetTemplateFileName();
|
virtual TString GetTemplateFileName();
|
||||||
|
|
||||||
/** Utility methods */
|
/** Utility methods */
|
||||||
|
void Initialize(IPropertyNew* pInParent, CScriptTemplate* pInTemplate, u32 InOffset);
|
||||||
void* RawValuePtr(void* pData) const;
|
void* RawValuePtr(void* pData) const;
|
||||||
IPropertyNew* ChildByID(u32 ID) const;
|
IPropertyNew* ChildByID(u32 ID) const;
|
||||||
IPropertyNew* ChildByIDString(const TIDString& rkIdString);
|
IPropertyNew* ChildByIDString(const TIDString& rkIdString);
|
||||||
|
@ -195,6 +196,7 @@ public:
|
||||||
void SetName(const TString& rkNewName);
|
void SetName(const TString& rkNewName);
|
||||||
void SetDescription(const TString& rkNewDescription);
|
void SetDescription(const TString& rkNewDescription);
|
||||||
void SetSuffix(const TString& rkNewSuffix);
|
void SetSuffix(const TString& rkNewSuffix);
|
||||||
|
void SetPropertyFlags(FPropertyFlags FlagsToSet);
|
||||||
bool HasAccurateName();
|
bool HasAccurateName();
|
||||||
|
|
||||||
/** Accessors */
|
/** Accessors */
|
||||||
|
@ -216,17 +218,19 @@ 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 IsIntrinsic() const { return mFlags.HasFlag(EPropertyFlag::IsIntrinsic); }
|
||||||
inline bool IsRootParent() const { return mpParent == nullptr; }
|
inline bool IsRootParent() const { return mpParent == nullptr; }
|
||||||
|
|
||||||
/** Create */
|
/** Create */
|
||||||
static IPropertyNew* Create(EPropertyTypeNew Type,
|
static IPropertyNew* Create(EPropertyTypeNew Type,
|
||||||
IPropertyNew* pParent,
|
EGame Game);
|
||||||
EGame Game,
|
|
||||||
CScriptTemplate* pScript,
|
|
||||||
bool CallPostInit = true);
|
|
||||||
|
|
||||||
static IPropertyNew* CreateCopy(IPropertyNew* pArchetype,
|
static IPropertyNew* CreateCopy(IPropertyNew* pArchetype);
|
||||||
IPropertyNew* pParent);
|
|
||||||
|
static IPropertyNew* CreateIntrinsic(EPropertyTypeNew Type,
|
||||||
|
EGame Game,
|
||||||
|
u32 Offset,
|
||||||
|
const TString& rkName);
|
||||||
|
|
||||||
static IPropertyNew* CreateIntrinsic(EPropertyTypeNew Type,
|
static IPropertyNew* CreateIntrinsic(EPropertyTypeNew Type,
|
||||||
IPropertyNew* pParent,
|
IPropertyNew* pParent,
|
||||||
|
@ -326,8 +330,8 @@ public:
|
||||||
protected:
|
protected:
|
||||||
PropType mDefaultValue;
|
PropType mDefaultValue;
|
||||||
|
|
||||||
TTypedPropertyNew()
|
TTypedPropertyNew(EGame Game)
|
||||||
: IPropertyNew()
|
: IPropertyNew(Game)
|
||||||
{
|
{
|
||||||
memset(&mDefaultValue, 0, sizeof(PropType));
|
memset(&mDefaultValue, 0, sizeof(PropType));
|
||||||
}
|
}
|
||||||
|
@ -369,6 +373,11 @@ public:
|
||||||
return mDefaultValue;
|
return mDefaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void SetDefaultValue(const PropType& kInDefaultValue)
|
||||||
|
{
|
||||||
|
mDefaultValue = kInDefaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
inline static EPropertyTypeNew StaticType() { return PropEnum; }
|
inline static EPropertyTypeNew StaticType() { return PropEnum; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -376,8 +385,8 @@ template<typename PropType, EPropertyTypeNew PropEnum>
|
||||||
class TSerializeableTypedProperty : public TTypedPropertyNew<PropType, PropEnum>
|
class TSerializeableTypedProperty : public TTypedPropertyNew<PropType, PropEnum>
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
TSerializeableTypedProperty()
|
TSerializeableTypedProperty(EGame Game)
|
||||||
: TTypedPropertyNew()
|
: TTypedPropertyNew(Game)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -443,8 +452,8 @@ protected:
|
||||||
PropType mMinValue;
|
PropType mMinValue;
|
||||||
PropType mMaxValue;
|
PropType mMaxValue;
|
||||||
|
|
||||||
TNumericalPropertyNew()
|
TNumericalPropertyNew(EGame Game)
|
||||||
: TSerializeableTypedProperty()
|
: TSerializeableTypedProperty(Game)
|
||||||
, mMinValue( -1 )
|
, mMinValue( -1 )
|
||||||
, mMaxValue( -1 )
|
, mMaxValue( -1 )
|
||||||
{}
|
{}
|
||||||
|
|
|
@ -8,8 +8,8 @@ class CAnimationProperty : public TSerializeableTypedProperty< u32, EPropertyTyp
|
||||||
friend class IPropertyNew;
|
friend class IPropertyNew;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CAnimationProperty()
|
CAnimationProperty(EGame Game)
|
||||||
: TSerializeableTypedProperty()
|
: TSerializeableTypedProperty(Game)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -8,16 +8,13 @@ class CAnimationSetProperty : public TSerializeableTypedProperty< CAnimationPara
|
||||||
friend class IPropertyNew;
|
friend class IPropertyNew;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CAnimationSetProperty()
|
CAnimationSetProperty(EGame Game)
|
||||||
: TSerializeableTypedProperty()
|
: TSerializeableTypedProperty(Game)
|
||||||
{}
|
|
||||||
|
|
||||||
public:
|
|
||||||
virtual void PostInitialize()
|
|
||||||
{
|
{
|
||||||
mDefaultValue.SetGame(Game());
|
mDefaultValue.SetGame(Game);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||||
{
|
{
|
||||||
Value(pData).Serialize(Arc);
|
Value(pData).Serialize(Arc);
|
||||||
|
|
|
@ -45,8 +45,8 @@ class CArrayProperty : public TTypedPropertyNew<u32, EPropertyTypeNew::Array>
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CArrayProperty()
|
CArrayProperty(EGame Game)
|
||||||
: TTypedPropertyNew()
|
: TTypedPropertyNew(Game)
|
||||||
, mpItemArchetype(nullptr)
|
, mpItemArchetype(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -109,6 +109,11 @@ public:
|
||||||
{
|
{
|
||||||
TTypedPropertyNew::Serialize(rArc);
|
TTypedPropertyNew::Serialize(rArc);
|
||||||
rArc << SerialParameter("ItemArchetype", mpItemArchetype);
|
rArc << SerialParameter("ItemArchetype", mpItemArchetype);
|
||||||
|
|
||||||
|
if (rArc.IsReader())
|
||||||
|
{
|
||||||
|
mpItemArchetype->SetPropertyFlags( EPropertyFlag::IsArrayArchetype );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||||
|
@ -134,7 +139,13 @@ public:
|
||||||
{
|
{
|
||||||
TTypedPropertyNew::InitFromArchetype(pOther);
|
TTypedPropertyNew::InitFromArchetype(pOther);
|
||||||
CArrayProperty* pOtherArray = static_cast<CArrayProperty*>(pOther);
|
CArrayProperty* pOtherArray = static_cast<CArrayProperty*>(pOther);
|
||||||
mpItemArchetype = IPropertyNew::CreateCopy(pOtherArray->mpItemArchetype, this);
|
mpItemArchetype = IPropertyNew::CreateCopy(pOtherArray->mpItemArchetype);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void PostInitialize()
|
||||||
|
{
|
||||||
|
TTypedPropertyNew::PostInitialize();
|
||||||
|
mpItemArchetype->Initialize(this, mpScriptTemplate, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ArrayCount(void* pPropertyData) const
|
u32 ArrayCount(void* pPropertyData) const
|
||||||
|
|
|
@ -7,18 +7,18 @@
|
||||||
class CAssetProperty : public TSerializeableTypedProperty<CAssetID, EPropertyTypeNew::Asset>
|
class CAssetProperty : public TSerializeableTypedProperty<CAssetID, EPropertyTypeNew::Asset>
|
||||||
{
|
{
|
||||||
friend class CTemplateLoader;
|
friend class CTemplateLoader;
|
||||||
|
friend class IPropertyNew;
|
||||||
|
|
||||||
CResTypeFilter mTypeFilter;
|
CResTypeFilter mTypeFilter;
|
||||||
|
|
||||||
public:
|
protected:
|
||||||
virtual void PostInitialize()
|
CAssetProperty::CAssetProperty(EGame Game)
|
||||||
{
|
: TSerializeableTypedProperty(Game)
|
||||||
// Init default value to an invalid ID depending on the game
|
|
||||||
if (!mDefaultValue.IsValid())
|
|
||||||
{
|
{
|
||||||
mDefaultValue = CAssetID::InvalidID( mGame );
|
mDefaultValue = CAssetID::InvalidID( mGame );
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
public:
|
||||||
virtual void Serialize(IArchive& rArc)
|
virtual void Serialize(IArchive& rArc)
|
||||||
{
|
{
|
||||||
TSerializeableTypedProperty::Serialize(rArc);
|
TSerializeableTypedProperty::Serialize(rArc);
|
||||||
|
|
|
@ -8,8 +8,8 @@ class CBoolProperty : public TSerializeableTypedProperty< bool, EPropertyTypeNew
|
||||||
friend class IPropertyNew;
|
friend class IPropertyNew;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CBoolProperty()
|
CBoolProperty(EGame Game)
|
||||||
: TSerializeableTypedProperty()
|
: TSerializeableTypedProperty(Game)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -8,8 +8,8 @@ class CByteProperty : public TNumericalPropertyNew< s8, EPropertyTypeNew::Byte >
|
||||||
friend class IPropertyNew;
|
friend class IPropertyNew;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CByteProperty()
|
CByteProperty(EGame Game)
|
||||||
: TNumericalPropertyNew()
|
: TNumericalPropertyNew(Game)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -2,27 +2,25 @@
|
||||||
#define CCOLORPROPERTY_H
|
#define CCOLORPROPERTY_H
|
||||||
|
|
||||||
#include "../IPropertyNew.h"
|
#include "../IPropertyNew.h"
|
||||||
|
#include "CFloatProperty.h"
|
||||||
|
|
||||||
class CColorProperty : public TSerializeableTypedProperty< CColor, EPropertyTypeNew::Color >
|
class CColorProperty : public TSerializeableTypedProperty< CColor, EPropertyTypeNew::Color >
|
||||||
{
|
{
|
||||||
friend class IPropertyNew;
|
friend class IPropertyNew;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CColorProperty()
|
CColorProperty(EGame Game)
|
||||||
: TSerializeableTypedProperty()
|
: TSerializeableTypedProperty(Game)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void PostInitialize()
|
virtual void PostInitialize()
|
||||||
{
|
{
|
||||||
IPropertyNew* pR = Create(EPropertyTypeNew::Float, this, mGame, mpScriptTemplate);
|
CreateIntrinsic(EPropertyTypeNew::Float, this, mOffset + 0, "R");
|
||||||
IPropertyNew* pG = Create(EPropertyTypeNew::Float, this, mGame, mpScriptTemplate);
|
CreateIntrinsic(EPropertyTypeNew::Float, this, mOffset + 4, "G");
|
||||||
IPropertyNew* pB = Create(EPropertyTypeNew::Float, this, mGame, mpScriptTemplate);
|
CreateIntrinsic(EPropertyTypeNew::Float, this, mOffset + 8, "B");
|
||||||
IPropertyNew* pA = Create(EPropertyTypeNew::Float, this, mGame, mpScriptTemplate);
|
CreateIntrinsic(EPropertyTypeNew::Float, this, mOffset + 12, "A");
|
||||||
pR->SetName("R");
|
TPropCast<CFloatProperty>( mChildren.back() )->SetDefaultValue(1.0f);
|
||||||
pG->SetName("G");
|
|
||||||
pB->SetName("B");
|
|
||||||
pA->SetName("A");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||||
|
|
|
@ -14,6 +14,8 @@ template<EPropertyTypeNew TypeEnum>
|
||||||
class TEnumPropertyBase : public TSerializeableTypedProperty<s32, TypeEnum>
|
class TEnumPropertyBase : public TSerializeableTypedProperty<s32, TypeEnum>
|
||||||
{
|
{
|
||||||
friend class CTemplateLoader;
|
friend class CTemplateLoader;
|
||||||
|
friend class IPropertyNew;
|
||||||
|
|
||||||
struct SEnumValue
|
struct SEnumValue
|
||||||
{
|
{
|
||||||
TString Name;
|
TString Name;
|
||||||
|
@ -43,6 +45,12 @@ class TEnumPropertyBase : public TSerializeableTypedProperty<s32, TypeEnum>
|
||||||
/** XML template file that this enum originated from; for archetypes */
|
/** XML template file that this enum originated from; for archetypes */
|
||||||
TString mSourceFile;
|
TString mSourceFile;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/** Constructor */
|
||||||
|
TEnumPropertyBase(EGame Game)
|
||||||
|
: TSerializeableTypedProperty(Game)
|
||||||
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual const char* GetHashableTypeName() const
|
virtual const char* GetHashableTypeName() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,8 +38,8 @@ class CFlagsProperty : public TSerializeableTypedProperty<u32, EPropertyTypeNew:
|
||||||
/** XML template file that this enum originated from; for archetypes */
|
/** XML template file that this enum originated from; for archetypes */
|
||||||
TString mSourceFile;
|
TString mSourceFile;
|
||||||
|
|
||||||
CFlagsProperty()
|
CFlagsProperty(EGame Game)
|
||||||
: TSerializeableTypedProperty()
|
: TSerializeableTypedProperty(Game)
|
||||||
, mAllFlags(0)
|
, mAllFlags(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,8 @@ class CFloatProperty : public TNumericalPropertyNew< float, EPropertyTypeNew::Fl
|
||||||
friend class IPropertyNew;
|
friend class IPropertyNew;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CFloatProperty()
|
CFloatProperty(EGame Game)
|
||||||
: TNumericalPropertyNew()
|
: TNumericalPropertyNew(Game)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -8,8 +8,8 @@ class CGuidProperty : public TTypedPropertyNew< std::vector<char>, EPropertyType
|
||||||
friend class IPropertyNew;
|
friend class IPropertyNew;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CGuidProperty()
|
CGuidProperty(EGame Game)
|
||||||
: TTypedPropertyNew()
|
: TTypedPropertyNew(Game)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -8,8 +8,8 @@ class CIntProperty : public TNumericalPropertyNew< s32, EPropertyTypeNew::Int >
|
||||||
friend class IPropertyNew;
|
friend class IPropertyNew;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CIntProperty()
|
CIntProperty(EGame Game)
|
||||||
: TNumericalPropertyNew()
|
: TNumericalPropertyNew(Game)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -6,6 +6,12 @@
|
||||||
class CPointerProperty : public TTypedPropertyNew<void*, EPropertyTypeNew::Pointer>
|
class CPointerProperty : public TTypedPropertyNew<void*, EPropertyTypeNew::Pointer>
|
||||||
{
|
{
|
||||||
friend class CTemplateLoader;
|
friend class CTemplateLoader;
|
||||||
|
friend class IPropertyNew;
|
||||||
|
|
||||||
|
CPointerProperty(EGame Game)
|
||||||
|
: TTypedPropertyNew(Game)
|
||||||
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool IsPointerType() const
|
virtual bool IsPointerType() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,8 +8,8 @@ class CSequenceProperty : public TTypedPropertyNew< s32, EPropertyTypeNew::Seque
|
||||||
friend class IPropertyNew;
|
friend class IPropertyNew;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CSequenceProperty()
|
CSequenceProperty(EGame Game)
|
||||||
: TTypedPropertyNew()
|
: TTypedPropertyNew(Game)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual void SerializeValue(void* pData, IArchive& rArc) const
|
virtual void SerializeValue(void* pData, IArchive& rArc) const
|
||||||
|
|
|
@ -8,8 +8,8 @@ class CShortProperty : public TNumericalPropertyNew< s16, EPropertyTypeNew::Shor
|
||||||
friend class IPropertyNew;
|
friend class IPropertyNew;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CShortProperty()
|
CShortProperty(EGame Game)
|
||||||
: TNumericalPropertyNew()
|
: TNumericalPropertyNew(Game)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -8,8 +8,8 @@ class CSoundProperty : public TSerializeableTypedProperty< s32, EPropertyTypeNew
|
||||||
friend class IPropertyNew;
|
friend class IPropertyNew;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CSoundProperty()
|
CSoundProperty(EGame Game)
|
||||||
: TSerializeableTypedProperty()
|
: TSerializeableTypedProperty(Game)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -8,8 +8,8 @@ class CSplineProperty : public TTypedPropertyNew< std::vector<char>, EPropertyTy
|
||||||
friend class IPropertyNew;
|
friend class IPropertyNew;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CSplineProperty()
|
CSplineProperty(EGame Game)
|
||||||
: TTypedPropertyNew()
|
: TTypedPropertyNew(Game)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -8,8 +8,8 @@ class CStringProperty : public TSerializeableTypedProperty< TString, EPropertyTy
|
||||||
friend class IPropertyNew;
|
friend class IPropertyNew;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CStringProperty()
|
CStringProperty(EGame Game)
|
||||||
: TSerializeableTypedProperty()
|
: TSerializeableTypedProperty(Game)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -21,12 +21,8 @@ u32 CStructPropertyNew::DataSize() const
|
||||||
|
|
||||||
u32 CStructPropertyNew::DataAlignment() const
|
u32 CStructPropertyNew::DataAlignment() const
|
||||||
{
|
{
|
||||||
// TODO. Should be aligned with the first child, but this function is called before children are loaded.
|
// Structs are aligned to the first child property.
|
||||||
// So for now just use 8 to ensure correct alignment for all child types, but this is wasteful...
|
return (mChildren.empty() ? 1 : mChildren[0]->DataAlignment());
|
||||||
// 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
|
void CStructPropertyNew::Construct(void* pData) const
|
||||||
|
@ -67,16 +63,25 @@ void CStructPropertyNew::RevertToDefault(void* pData) const
|
||||||
|
|
||||||
const char* CStructPropertyNew::HashableTypeName() const
|
const char* CStructPropertyNew::HashableTypeName() const
|
||||||
{
|
{
|
||||||
if (IsArchetype() || !mpArchetype)
|
return mpArchetype ? mpArchetype->HashableTypeName() : *mName;
|
||||||
return *mName;
|
|
||||||
else
|
|
||||||
return mpArchetype->HashableTypeName();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStructPropertyNew::Serialize(IArchive& rArc)
|
void CStructPropertyNew::Serialize(IArchive& rArc)
|
||||||
{
|
{
|
||||||
IPropertyNew::Serialize(rArc);
|
IPropertyNew::Serialize(rArc);
|
||||||
|
|
||||||
|
// Serialize atomic flag
|
||||||
|
bool Atomic = IsAtomic();
|
||||||
|
rArc << SerialParameter("Atomic", Atomic, SH_Optional, false);
|
||||||
|
|
||||||
|
if (rArc.IsReader())
|
||||||
|
{
|
||||||
|
if (Atomic)
|
||||||
|
mFlags.SetFlag(EPropertyFlag::IsAtomic);
|
||||||
|
else
|
||||||
|
mFlags.ClearFlag(EPropertyFlag::IsAtomic);
|
||||||
|
}
|
||||||
|
|
||||||
// Serialize archetype
|
// Serialize archetype
|
||||||
if (mpArchetype)
|
if (mpArchetype)
|
||||||
{
|
{
|
||||||
|
@ -96,13 +101,13 @@ void CStructPropertyNew::Serialize(IArchive& rArc)
|
||||||
if (rArc.ParamBegin("Element", SH_IgnoreName))
|
if (rArc.ParamBegin("Element", SH_IgnoreName))
|
||||||
{
|
{
|
||||||
// Serialize type and ID, then look up the matching property and serialize it.
|
// 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
|
// We don't really need the type, but it's a good sanity check, and it's also good practice
|
||||||
// to guarantee that parameters are read in order, as some serializers are order-dependent.
|
// to guarantee that parameters are read in order, as some serializers are order-dependent.
|
||||||
EPropertyTypeNew ChildType;
|
EPropertyTypeNew ChildType;
|
||||||
u32 ChildID;
|
u32 ChildID;
|
||||||
|
|
||||||
rArc << SerialParameter("Type", ChildType, SH_Attribute)
|
rArc << SerialParameter("Type", ChildType, SH_Attribute)
|
||||||
<< SerialParameter("ID", ChildID, SH_Attribute);
|
<< SerialParameter("ID", ChildID, SH_Attribute | SH_HexDisplay );
|
||||||
|
|
||||||
IPropertyNew* pChild = ChildByID(ChildID);
|
IPropertyNew* pChild = ChildByID(ChildID);
|
||||||
ASSERT(pChild != nullptr && pChild->Type() == ChildType);
|
ASSERT(pChild != nullptr && pChild->Type() == ChildType);
|
||||||
|
@ -154,6 +159,21 @@ void CStructPropertyNew::SerializeValue(void* pData, IArchive& Arc) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CStructPropertyNew::InitFromArchetype(IPropertyNew* pOther)
|
||||||
|
{
|
||||||
|
IPropertyNew::InitFromArchetype(pOther);
|
||||||
|
|
||||||
|
// Copy children
|
||||||
|
_ClearChildren();
|
||||||
|
mChildren.reserve( pOther->NumChildren() );
|
||||||
|
|
||||||
|
for (u32 ChildIdx = 0; ChildIdx < pOther->NumChildren(); ChildIdx++)
|
||||||
|
{
|
||||||
|
IPropertyNew* pChild = CreateCopy( pOther->ChildByIndex(ChildIdx) );
|
||||||
|
mChildren.push_back( pChild );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool CStructPropertyNew::ShouldSerialize() const
|
bool CStructPropertyNew::ShouldSerialize() const
|
||||||
{
|
{
|
||||||
if (IPropertyNew::ShouldSerialize())
|
if (IPropertyNew::ShouldSerialize())
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
class CStructPropertyNew : public IPropertyNew
|
class CStructPropertyNew : public IPropertyNew
|
||||||
{
|
{
|
||||||
friend class CTemplateLoader;
|
friend class CTemplateLoader;
|
||||||
|
friend class IPropertyNew;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Must be a valid type for TPropertyRef
|
// Must be a valid type for TPropertyRef
|
||||||
|
@ -15,6 +16,10 @@ protected:
|
||||||
/** For archetypes, the filename of the template XML file. */
|
/** For archetypes, the filename of the template XML file. */
|
||||||
TString mTemplateFileName;
|
TString mTemplateFileName;
|
||||||
|
|
||||||
|
CStructPropertyNew(EGame Game)
|
||||||
|
: IPropertyNew(Game)
|
||||||
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual EPropertyTypeNew Type() const;
|
virtual EPropertyTypeNew Type() const;
|
||||||
virtual u32 DataSize() const;
|
virtual u32 DataSize() const;
|
||||||
|
@ -26,6 +31,7 @@ public:
|
||||||
virtual const char* HashableTypeName() const;
|
virtual const char* HashableTypeName() const;
|
||||||
virtual void Serialize(IArchive& rArc);
|
virtual void Serialize(IArchive& rArc);
|
||||||
virtual void SerializeValue(void* pData, IArchive& Arc) const;
|
virtual void SerializeValue(void* pData, IArchive& Arc) const;
|
||||||
|
virtual void InitFromArchetype(IPropertyNew* pOther);
|
||||||
virtual bool ShouldSerialize() const;
|
virtual bool ShouldSerialize() const;
|
||||||
virtual TString GetTemplateFileName();
|
virtual TString GetTemplateFileName();
|
||||||
|
|
||||||
|
|
|
@ -8,19 +8,16 @@ class CVectorProperty : public TSerializeableTypedProperty< CVector3f, EProperty
|
||||||
friend class IPropertyNew;
|
friend class IPropertyNew;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CVectorProperty()
|
CVectorProperty(EGame Game)
|
||||||
: TSerializeableTypedProperty()
|
: TSerializeableTypedProperty(Game)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void PostInitialize()
|
virtual void PostInitialize() override
|
||||||
{
|
{
|
||||||
IPropertyNew* pX = Create(EPropertyTypeNew::Float, this, mGame, mpScriptTemplate);
|
CreateIntrinsic(EPropertyTypeNew::Float, this, mOffset + 0, "X");
|
||||||
IPropertyNew* pY = Create(EPropertyTypeNew::Float, this, mGame, mpScriptTemplate);
|
CreateIntrinsic(EPropertyTypeNew::Float, this, mOffset + 4, "Y");
|
||||||
IPropertyNew* pZ = Create(EPropertyTypeNew::Float, this, mGame, mpScriptTemplate);
|
CreateIntrinsic(EPropertyTypeNew::Float, this, mOffset + 8, "Z");
|
||||||
pX->SetName("X");
|
|
||||||
pY->SetName("Y");
|
|
||||||
pZ->SetName("Z");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
virtual void SerializeValue(void* pData, IArchive& Arc) const
|
||||||
|
|
|
@ -235,7 +235,11 @@ void CPropertyView::CreateContextMenu(const QPoint& rkPos)
|
||||||
mpMenuProperty = pProp;
|
mpMenuProperty = pProp;
|
||||||
|
|
||||||
QMenu Menu;
|
QMenu Menu;
|
||||||
|
|
||||||
|
if (!pProp->IsIntrinsic())
|
||||||
|
{
|
||||||
Menu.addAction(mpEditTemplateAction);
|
Menu.addAction(mpEditTemplateAction);
|
||||||
|
}
|
||||||
|
|
||||||
if (mpEditor->CurrentGame() >= eEchoesDemo)
|
if (mpEditor->CurrentGame() >= eEchoesDemo)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue