207 lines
5.6 KiB
C++
207 lines
5.6 KiB
C++
#include "CStructProperty.h"
|
|
#include "Core/Resource/Script/CGameTemplate.h"
|
|
|
|
EPropertyType CStructProperty::Type() const
|
|
{
|
|
return EPropertyType::Struct;
|
|
}
|
|
|
|
void CStructProperty::PostInitialize()
|
|
{
|
|
IProperty::PostInitialize();
|
|
|
|
// All structs should have an archetype.
|
|
ASSERT( IsRootParent() || mpArchetype != nullptr );
|
|
}
|
|
|
|
uint32 CStructProperty::DataSize() const
|
|
{
|
|
if (!mChildren.empty())
|
|
{
|
|
IProperty* pLastChild = mChildren.back();
|
|
return (pLastChild->Offset() - Offset()) + pLastChild->DataSize();
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
uint32 CStructProperty::DataAlignment() const
|
|
{
|
|
// Structs are aligned to the first child property.
|
|
return (mChildren.empty() ? 1 : mChildren[0]->DataAlignment());
|
|
}
|
|
|
|
void CStructProperty::Construct(void* pData) const
|
|
{
|
|
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
|
{
|
|
mChildren[ChildIdx]->Construct(pData);
|
|
}
|
|
}
|
|
|
|
void CStructProperty::Destruct(void* pData) const
|
|
{
|
|
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
|
{
|
|
mChildren[ChildIdx]->Destruct(pData);
|
|
}
|
|
}
|
|
|
|
bool CStructProperty::MatchesDefault(void* pData) const
|
|
{
|
|
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
|
{
|
|
if (!mChildren[ChildIdx]->MatchesDefault(pData))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void CStructProperty::RevertToDefault(void* pData) const
|
|
{
|
|
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
|
{
|
|
mChildren[ChildIdx]->RevertToDefault(pData);
|
|
}
|
|
}
|
|
|
|
void CStructProperty::SetDefaultFromData(void* pData)
|
|
{
|
|
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
|
{
|
|
mChildren[ChildIdx]->SetDefaultFromData(pData);
|
|
}
|
|
}
|
|
|
|
const char* CStructProperty::HashableTypeName() const
|
|
{
|
|
return mpArchetype ? mpArchetype->HashableTypeName() : *mName;
|
|
}
|
|
|
|
void CStructProperty::Serialize(IArchive& rArc)
|
|
{
|
|
IProperty::Serialize(rArc);
|
|
|
|
// Serialize atomic flag
|
|
// Only serialize this if we don't have an archetype. Otherwise we just inherit the archetype's atomic flag.
|
|
if (!mpArchetype)
|
|
{
|
|
bool Atomic = IsAtomic();
|
|
rArc << SerialParameter("Atomic", Atomic, SH_Optional, false);
|
|
|
|
if (rArc.IsReader() && Atomic)
|
|
{
|
|
mFlags.SetFlag(EPropertyFlag::IsAtomic);
|
|
}
|
|
}
|
|
|
|
// Serialize archetype
|
|
if (mpArchetype)
|
|
{
|
|
CStructProperty* pArchetype = static_cast<CStructProperty*>(mpArchetype);
|
|
ASSERT(pArchetype != nullptr);
|
|
|
|
if (rArc.IsReader())
|
|
{
|
|
// We've initialized from the archetypes, now serialize parameter overrides
|
|
if (rArc.ParamBegin("SubProperties", 0))
|
|
{
|
|
uint32 NumChildOverrides;
|
|
rArc.SerializeArraySize(NumChildOverrides);
|
|
|
|
for (uint32 ChildIdx = 0; ChildIdx < NumChildOverrides; ChildIdx++)
|
|
{
|
|
if (rArc.ParamBegin("Element", SH_IgnoreName))
|
|
{
|
|
// Serialize type and ID, then look up the matching property and serialize it.
|
|
// We don't really need the type, but it's a good sanity check, and it's also good practice
|
|
// to guarantee that parameters are read in order, as some serializers are order-dependent.
|
|
EPropertyType ChildType;
|
|
uint32 ChildID;
|
|
|
|
rArc << SerialParameter("Type", ChildType, SH_Attribute)
|
|
<< SerialParameter("ID", ChildID, SH_Attribute | SH_HexDisplay );
|
|
|
|
IProperty* pChild = ChildByID(ChildID);
|
|
ASSERT(pChild != nullptr && pChild->Type() == ChildType);
|
|
pChild->Serialize(rArc);
|
|
|
|
rArc.ParamEnd();
|
|
}
|
|
}
|
|
|
|
rArc.ParamEnd();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Check if any properties need to override parameters from their archetype.
|
|
std::vector<IProperty*> PropertiesToSerialize;
|
|
|
|
for (uint32 ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
|
{
|
|
if (mChildren[ChildIdx]->ShouldSerialize())
|
|
{
|
|
PropertiesToSerialize.push_back(mChildren[ChildIdx]);
|
|
}
|
|
}
|
|
|
|
uint32 NumChildOverrides = PropertiesToSerialize.size();
|
|
|
|
if (NumChildOverrides > 0)
|
|
{
|
|
rArc << SerialParameter("SubProperties", PropertiesToSerialize);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
rArc << SerialParameter("SubProperties", mChildren);
|
|
}
|
|
}
|
|
|
|
void CStructProperty::SerializeValue(void* pData, IArchive& Arc) const
|
|
{
|
|
for (uint32 ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
|
{
|
|
if (Arc.ParamBegin("Property", 0))
|
|
{
|
|
mChildren[ChildIdx]->SerializeValue(pData, Arc);
|
|
Arc.ParamEnd();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CStructProperty::InitFromArchetype(IProperty* pOther)
|
|
{
|
|
IProperty::InitFromArchetype(pOther);
|
|
|
|
// Copy children
|
|
_ClearChildren();
|
|
mChildren.reserve( pOther->NumChildren() );
|
|
|
|
for (uint32 ChildIdx = 0; ChildIdx < pOther->NumChildren(); ChildIdx++)
|
|
{
|
|
IProperty* pChild = CreateCopy( pOther->ChildByIndex(ChildIdx) );
|
|
mChildren.push_back( pChild );
|
|
}
|
|
}
|
|
|
|
bool CStructProperty::ShouldSerialize() const
|
|
{
|
|
if (IProperty::ShouldSerialize())
|
|
return true;
|
|
|
|
for (uint32 ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
|
|
{
|
|
if (mChildren[ChildIdx]->ShouldSerialize())
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|