Massive overhaul of property system done over the last few months. There is unfinished/broken stuff still, but it compiles now.

This commit is contained in:
Aruki
2018-06-22 15:24:04 -06:00
parent 7099b97529
commit ce3dfdc397
174 changed files with 4570 additions and 2050 deletions

View File

@@ -88,7 +88,7 @@ SMessage CMasterTemplate::MessageByIndex(u32 Index)
return (std::next(it, Index))->second;
}
CStructTemplate* CMasterTemplate::StructAtSource(const TString& rkSource)
CStructPropertyNew* CMasterTemplate::StructAtSource(const TString& rkSource)
{
auto InfoIt = mStructTemplates.find(rkSource);
@@ -149,38 +149,44 @@ TString CMasterTemplate::PropertyName(u32 PropertyID)
return "Unknown";
}
u32 CMasterTemplate::CreatePropertyID(IPropertyTemplate *pTemp)
// Removing these functions for now. I'm not sure of the best way to go about implementing them under the new system yet.
u32 CMasterTemplate::CreatePropertyID(IPropertyNew* pProp)
{
// MP1 properties don't have IDs so we can use this function to create one to track instances of a particular property.
// To ensure the IDs are unique we'll create a hash using two things: the struct source file and the ID string (relative to the struct).
TString IDString = pTemp->IDString(false);
TString Source;
CStructTemplate *pStruct = pTemp->Parent();
//
// Note for properties that have accurate names we can apply a CRC32 to the name to generate a hash equivalent to what the hash would
// have been if this were an MP2/3 property. In an ideal world where every property was named, this would be great. However, we have a
// lot of properties that have generic names like "Unknown", and they should be tracked separately as they are in all likelihood
// different properties. So for this reason, we only want to track sub-instances of one property under one ID.
TString IDString = pProp->Archetype()->IDString(true);
TString TemplateFile = pProp->GetTemplateFileName();
while (pStruct)
{
Source = pStruct->SourceFile();
if (!Source.IsEmpty()) break;
IDString.Prepend(pStruct->IDString(false) + ":");
pStruct = pStruct->Parent();
}
return IDString.Hash32() * Source.Hash32();
CCRC32 Hash;
Hash.Hash(*IDString);
Hash.Hash(*TemplateFile);
return Hash.Digest();
}
void CMasterTemplate::AddProperty(IPropertyTemplate *pTemp, const TString& rkTemplateName /*= ""*/)
void CMasterTemplate::AddProperty(IPropertyNew* pProp, const TString& rkTemplateName /*= ""*/)
{
u32 ID;
if (pTemp->Game() >= eEchoesDemo)
ID = pTemp->PropertyID();
if (pProp->Game() >= eEchoesDemo)
ID = pProp->ID();
// Use a different ID for MP1
else
{
// For MP1 we only really need to track properties that come from struct templates.
if (!pTemp->IsFromStructTemplate()) return;
else ID = CreatePropertyID(pTemp);
IPropertyNew* pArchetype = pProp->Archetype();
if (!pArchetype ||
pArchetype->ScriptTemplate() != nullptr ||
pArchetype->RootParent()->Type() != EPropertyTypeNew::Struct)
return;
ID = CreatePropertyID(pProp);
}
auto it = smIDMap.find(ID);
@@ -189,7 +195,7 @@ void CMasterTemplate::AddProperty(IPropertyTemplate *pTemp, const TString& rkTem
if (it != smIDMap.end())
{
SPropIDInfo& rInfo = it->second;
rInfo.PropertyList.push_back(pTemp);
rInfo.PropertyList.push_back(pProp);
if (!rkTemplateName.IsEmpty())
{
@@ -214,15 +220,15 @@ void CMasterTemplate::AddProperty(IPropertyTemplate *pTemp, const TString& rkTem
{
SPropIDInfo Info;
if (!rkTemplateName.IsEmpty()) Info.XMLList.push_back(rkTemplateName);
Info.PropertyList.push_back(pTemp);
Info.PropertyList.push_back(pProp);
smIDMap[ID] = Info;
}
}
void CMasterTemplate::RenameProperty(IPropertyTemplate *pTemp, const TString& rkNewName)
void CMasterTemplate::RenameProperty(IPropertyNew* pProp, const TString& rkNewName)
{
u32 ID = pTemp->PropertyID();
if (ID <= 0xFF) ID = CreatePropertyID(pTemp);
u32 ID = pProp->ID();
if (ID <= 0xFF) ID = CreatePropertyID(pProp);
RenameProperty(ID, rkNewName);
}
@@ -245,10 +251,10 @@ void CMasterTemplate::RenameProperty(u32 ID, const TString& rkNewName)
{
const SPropIDInfo& rkInfo = InfoIt->second;
for (u32 iTemp = 0; iTemp < rkInfo.PropertyList.size(); iTemp++)
for (u32 PropertyIdx = 0; PropertyIdx < rkInfo.PropertyList.size(); PropertyIdx++)
{
if (Original.IsEmpty() || rkInfo.PropertyList[iTemp]->Name() == Original)
rkInfo.PropertyList[iTemp]->SetName(rkNewName);
if (Original.IsEmpty() || rkInfo.PropertyList[PropertyIdx]->Name() == Original)
rkInfo.PropertyList[PropertyIdx]->SetName(rkNewName);
}
}
}
@@ -264,10 +270,10 @@ void CMasterTemplate::XMLsUsingID(u32 ID, std::vector<TString>& rOutList)
}
}
const std::vector<IPropertyTemplate*>* CMasterTemplate::TemplatesWithMatchingID(IPropertyTemplate *pTemp)
const std::vector<IPropertyNew*>* CMasterTemplate::TemplatesWithMatchingID(IPropertyNew* pProp)
{
u32 ID = pTemp->PropertyID();
if (ID <= 0xFF) ID = CreatePropertyID(pTemp);
u32 ID = pProp->ID();
if (ID <= 0xFF) ID = CreatePropertyID(pProp);
auto InfoIt = smIDMap.find(ID);

View File

@@ -3,6 +3,7 @@
#include "CLink.h"
#include "CScriptTemplate.h"
#include "Core/Resource/Script/Property/Properties.h"
#include <Common/EGame.h>
#include <Common/types.h>
#include <map>
@@ -19,7 +20,9 @@ class CMasterTemplate
bool mFullyLoaded;
std::vector<TString> mGameVersions;
std::map<TString, CStructTemplate*> mStructTemplates;
std::map<TString, CStructPropertyNew*> mStructTemplates;
std::map<TString, CEnumProperty*> mEnumTemplates;
std::map<TString, CFlagsProperty*> mFlagsTemplates;
std::map<u32, CScriptTemplate*> mTemplates;
std::map<u32, SState> mStates;
@@ -28,7 +31,7 @@ class CMasterTemplate
struct SPropIDInfo
{
std::vector<TString> XMLList; // List of script/struct templates that use this ID
std::vector<IPropertyTemplate*> PropertyList; // List of all properties that use this ID
std::vector<IPropertyNew*> PropertyList; // List of all properties that use this ID
};
static std::map<u32, SPropIDInfo> smIDMap;
static std::map<EGame, CMasterTemplate*> smMasterMap;
@@ -48,7 +51,7 @@ public:
SMessage MessageByID(u32 MessageID);
SMessage MessageByID(const CFourCC& MessageID);
SMessage MessageByIndex(u32 Index);
CStructTemplate* StructAtSource(const TString& rkSource);
CStructPropertyNew* StructAtSource(const TString& rkSource);
// Inline Accessors
inline EGame Game() const { return mGame; }
@@ -66,12 +69,12 @@ public:
static TString FindGameName(EGame Game);
static EGame FindGameForName(const TString& rkName);
static TString PropertyName(u32 PropertyID);
static u32 CreatePropertyID(IPropertyTemplate *pTemp);
static void AddProperty(IPropertyTemplate *pTemp, const TString& rkTemplateName = "");
static void RenameProperty(IPropertyTemplate *pTemp, const TString& rkNewName);
static u32 CreatePropertyID(IPropertyNew *pTemp);
static void AddProperty(IPropertyNew *pTemp, const TString& rkTemplateName = "");
static void RenameProperty(IPropertyNew *pTemp, const TString& rkNewName);
static void RenameProperty(u32 ID, const TString& rkNewName);
static void XMLsUsingID(u32 ID, std::vector<TString>& rOutList);
static const std::vector<IPropertyTemplate*>* TemplatesWithMatchingID(IPropertyTemplate *pTemp);
static const std::vector<IPropertyNew*>* TemplatesWithMatchingID(IPropertyNew *pTemp);
};
#endif // CMASTERTEMPLATE_H

View File

@@ -13,19 +13,29 @@ CScriptObject::CScriptObject(u32 InstanceID, CGameArea *pArea, CScriptLayer *pLa
, mIsCheckingNearVisibleActivation(false)
{
mpTemplate->AddObject(this);
mpProperties = (CPropertyStruct*) pTemplate->BaseStruct()->InstantiateProperty(this, nullptr);
mpInstanceName = mpTemplate->FindInstanceName(mpProperties);
mpPosition = mpTemplate->FindPosition(mpProperties);
mpRotation = mpTemplate->FindRotation(mpProperties);
mpScale = mpTemplate->FindScale(mpProperties);
mpActive = mpTemplate->FindActive(mpProperties);
mpLightParameters = mpTemplate->FindLightParameters(mpProperties);
// Init properties
CStructPropertyNew* pProperties = pTemplate->Properties();
u32 PropertiesSize = pProperties->DataSize();
mPropertyData.resize( PropertiesSize );
pProperties->Construct( mPropertyData.data() );
mInstanceName = CStringRef(this, pTemplate->NameProperty());
mPosition = CVectorRef(this, pTemplate->PositionProperty());
mRotation = CVectorRef(this, pTemplate->RotationProperty());
mScale = CVectorRef(this, pTemplate->ScaleProperty());
mActive = CBoolRef(this, pTemplate->ActiveProperty());
mLightParameters = CStructRef(this, pTemplate->LightParametersProperty());
}
CScriptObject::~CScriptObject()
{
if (mpProperties) delete mpProperties;
if (!mPropertyData.empty())
{
mpTemplate->Properties()->Destruct( mPropertyData.data() );
mPropertyData.clear();
}
mpTemplate->RemoveObject(this);
// Note: Incoming links will be deleted by the sender.
@@ -34,6 +44,19 @@ CScriptObject::~CScriptObject()
}
// ************ DATA MANIPULATION ************
void CScriptObject::CopyProperties(CScriptObject* pObject)
{
ASSERT(pObject->Template() == Template());
CSerialVersion Version(0, IArchive::skCurrentArchiveVersion, Template()->Game());
CVectorOutStream DataStream;
CBasicBinaryWriter DataWriter(&DataStream, Version);
Template()->Properties()->SerializeValue( pObject->PropertyData(), DataWriter );
CBasicBinaryReader DataReader(DataStream.Data(), DataStream.Size(), Version);
Template()->Properties()->SerializeValue( PropertyData(), DataReader );
}
void CScriptObject::EvaluateProperties()
{
EvaluateDisplayAsset();
@@ -43,12 +66,12 @@ CScriptObject::~CScriptObject()
void CScriptObject::EvaluateDisplayAsset()
{
mpDisplayAsset = mpTemplate->FindDisplayAsset(mpProperties, mActiveCharIndex, mActiveAnimIndex, mHasInGameModel);
mpDisplayAsset = mpTemplate->FindDisplayAsset(PropertyData(), mActiveCharIndex, mActiveAnimIndex, mHasInGameModel);
}
void CScriptObject::EvaluateCollisionModel()
{
mpCollision = mpTemplate->FindCollision(mpProperties);
mpCollision = mpTemplate->FindCollision(PropertyData());
}
void CScriptObject::EvaluateVolume()
@@ -57,15 +80,15 @@ void CScriptObject::EvaluateVolume()
mVolumeScale = mpTemplate->VolumeScale(this);
}
bool CScriptObject::IsEditorProperty(IProperty *pProp)
bool CScriptObject::IsEditorProperty(IPropertyNew *pProp)
{
return ( (pProp == mpInstanceName) ||
(pProp == mpPosition) ||
(pProp == mpRotation) ||
(pProp == mpScale) ||
(pProp == mpActive) ||
(pProp == mpLightParameters) ||
(pProp->Parent() == mpLightParameters)
return ( (pProp == mInstanceName.Property()) ||
(pProp == mPosition.Property()) ||
(pProp == mRotation.Property()) ||
(pProp == mScale.Property()) ||
(pProp == mActive.Property()) ||
(pProp == mLightParameters.Property()) ||
(pProp->Parent() == mLightParameters.Property())
);
}

View File

@@ -1,12 +1,11 @@
#ifndef CSCRIPTOBJECT_H
#define CSCRIPTOBJECT_H
#include "IProperty.h"
#include "IPropertyTemplate.h"
#include "CScriptTemplate.h"
#include "Core/Resource/Area/CGameArea.h"
#include "Core/Resource/Model/CModel.h"
#include "Core/Resource/CCollisionMeshGroup.h"
#include "Core/Resource/Script/Property/Properties.h"
class CScriptLayer;
class CLink;
@@ -30,14 +29,15 @@ class CScriptObject
u32 mInstanceID;
std::vector<CLink*> mOutLinks;
std::vector<CLink*> mInLinks;
CPropertyStruct *mpProperties;
std::vector<char> mPropertyData;
CStringRef mInstanceName;
CVectorRef mPosition;
CVectorRef mRotation;
CVectorRef mScale;
CBoolRef mActive;
CStructRef mLightParameters;
TStringProperty *mpInstanceName;
TVector3Property *mpPosition;
TVector3Property *mpRotation;
TVector3Property *mpScale;
TBoolProperty *mpActive;
CPropertyStruct *mpLightParameters;
TResPtr<CResource> mpDisplayAsset;
TResPtr<CCollisionMeshGroup> mpCollision;
u32 mActiveCharIndex;
@@ -54,11 +54,12 @@ public:
CScriptObject(u32 InstanceID, CGameArea *pArea, CScriptLayer *pLayer, CScriptTemplate *pTemplate);
~CScriptObject();
void CopyProperties(CScriptObject* pObject);
void EvaluateProperties();
void EvaluateDisplayAsset();
void EvaluateCollisionModel();
void EvaluateVolume();
bool IsEditorProperty(IProperty *pProp);
bool IsEditorProperty(IPropertyNew *pProp);
void SetLayer(CScriptLayer *pLayer, u32 NewLayerIndex = -1);
u32 LayerIndex() const;
bool HasNearVisibleActivation() const;
@@ -73,39 +74,37 @@ public:
CGameArea* Area() const { return mpArea; }
CScriptLayer* Layer() const { return mpLayer; }
u32 Version() const { return mVersion; }
CPropertyStruct* Properties() const { return mpProperties; }
u32 NumProperties() const { return mpProperties->Count(); }
IProperty* PropertyByIndex(u32 Index) const { return mpProperties->PropertyByIndex(Index); }
IProperty* PropertyByIDString(const TIDString& rkStr) const { return mpProperties->PropertyByIDString(rkStr); }
u32 ObjectTypeID() const { return mpTemplate->ObjectID(); }
u32 InstanceID() const { return mInstanceID; }
u32 NumLinks(ELinkType Type) const { return (Type == eIncoming ? mInLinks.size() : mOutLinks.size()); }
CLink* Link(ELinkType Type, u32 Index) const { return (Type == eIncoming ? mInLinks[Index] : mOutLinks[Index]); }
void* PropertyData() const { return (void*) mPropertyData.data(); }
CVector3f Position() const { return mpPosition ? mpPosition->Get() : CVector3f::skZero; }
CVector3f Rotation() const { return mpRotation ? mpRotation->Get() : CVector3f::skZero; }
CVector3f Scale() const { return mpScale ? mpScale->Get() : CVector3f::skOne; }
TString InstanceName() const { return mpInstanceName ? mpInstanceName->Get() : ""; }
bool IsActive() const { return mpActive ? mpActive->Get() : false; }
CVector3f Position() const { return mPosition.IsValid() ? mPosition.Get() : CVector3f::skZero; }
CVector3f Rotation() const { return mRotation.IsValid() ? mRotation.Get() : CVector3f::skZero; }
CVector3f Scale() const { return mScale.IsValid() ? mScale.Get() : CVector3f::skOne; }
TString InstanceName() const { return mInstanceName.IsValid() ? mInstanceName.Get() : ""; }
bool IsActive() const { return mActive.IsValid() ? mActive.Get() : false; }
bool HasInGameModel() const { return mHasInGameModel; }
CPropertyStruct* LightParameters() const { return mpLightParameters; }
CStructRef LightParameters() const { return mLightParameters; }
CResource* DisplayAsset() const { return mpDisplayAsset; }
u32 ActiveCharIndex() const { return mActiveCharIndex; }
u32 ActiveAnimIndex() const { return mActiveAnimIndex; }
CCollisionMeshGroup* Collision() const { return mpCollision; }
EVolumeShape VolumeShape() const { return mVolumeShape; }
float VolumeScale() const { return mVolumeScale; }
void SetPosition(const CVector3f& rkNewPos) { if (mpPosition) mpPosition->Set(rkNewPos); }
void SetRotation(const CVector3f& rkNewRot) { if (mpRotation) mpRotation->Set(rkNewRot); }
void SetScale(const CVector3f& rkNewScale) { if (mpScale) mpScale->Set(rkNewScale); }
void SetName(const TString& rkNewName) { if (mpInstanceName) mpInstanceName->Set(rkNewName); }
void SetActive(bool Active) { if (mpActive) mpActive->Set(Active); }
void SetPosition(const CVector3f& rkNewPos) { mPosition.Set(rkNewPos); }
void SetRotation(const CVector3f& rkNewRot) { mRotation.Set(rkNewRot); }
void SetScale(const CVector3f& rkNewScale) { mScale.Set(rkNewScale); }
void SetName(const TString& rkNewName) { mInstanceName.Set(rkNewName); }
void SetActive(bool Active) { mActive.Set(Active); }
TVector3Property* PositionProperty() const { return mpPosition; }
TVector3Property* RotationProperty() const { return mpRotation; }
TVector3Property* ScaleProperty() const { return mpScale; }
TStringProperty* InstanceNameProperty() const { return mpInstanceName; }
TBoolProperty* ActiveProperty() const { return mpActive; }
bool HasPosition() const { return mPosition.IsValid(); }
bool HasRotation() const { return mRotation.IsValid(); }
bool HasScale() const { return mScale.IsValid(); }
bool HasInstanceName() const { return mInstanceName.IsValid(); }
bool HasActive() const { return mActive.IsValid(); }
bool HasLightParameters() const { return mLightParameters.IsValid(); }
};
#endif // CSCRIPTOBJECT_H

View File

@@ -10,8 +10,14 @@
CScriptTemplate::CScriptTemplate(CMasterTemplate *pMaster)
: mpMaster(pMaster)
, mpBaseStruct(nullptr)
, mpProperties(nullptr)
, mVisible(true)
, mpNameProperty(nullptr)
, mpPositionProperty(nullptr)
, mpRotationProperty(nullptr)
, mpScaleProperty(nullptr)
, mpActiveProperty(nullptr)
, mpLightParametersProperty(nullptr)
, mPreviewScale(1.f)
, mVolumeShape(eNoShape)
, mVolumeScale(1.f)
@@ -20,7 +26,16 @@ CScriptTemplate::CScriptTemplate(CMasterTemplate *pMaster)
CScriptTemplate::~CScriptTemplate()
{
delete mpBaseStruct;
}
void CScriptTemplate::PostLoad()
{
if (!mNameIDString.IsEmpty()) mpNameProperty = TPropCast<CStringProperty>( mpProperties->ChildByIDString(mNameIDString) );
if (!mPositionIDString.IsEmpty()) mpPositionProperty = TPropCast<CVectorProperty>( mpProperties->ChildByIDString(mPositionIDString) );
if (!mRotationIDString.IsEmpty()) mpRotationProperty = TPropCast<CVectorProperty>( mpProperties->ChildByIDString(mRotationIDString) );
if (!mScaleIDString.IsEmpty()) mpScaleProperty = TPropCast<CVectorProperty>( mpProperties->ChildByIDString(mScaleIDString) );
if (!mActiveIDString.IsEmpty()) mpActiveProperty = TPropCast<CBoolProperty>( mpProperties->ChildByIDString(mActiveIDString) );
if (!mLightParametersIDString.IsEmpty()) mpLightParametersProperty = TPropCast<CStructPropertyNew>( mpProperties->ChildByIDString(mLightParametersIDString) );
}
EGame CScriptTemplate::Game() const
@@ -29,14 +44,14 @@ EGame CScriptTemplate::Game() const
}
// ************ PROPERTY FETCHING ************
template<typename PropType, EPropertyType PropEnum>
PropType TFetchProperty(CPropertyStruct *pProperties, const TIDString& rkID)
template<class PropType>
PropType* TFetchProperty(CStructPropertyNew* pProperties, const TIDString& rkID)
{
if (rkID.IsEmpty()) return nullptr;
IProperty *pProp = pProperties->PropertyByIDString(rkID);
IPropertyNew *pProp = pProperties->ChildByIDString(rkID);
if (pProp && (pProp->Type() == PropEnum))
return static_cast<PropType>(pProp);
return static_cast<PropType*>(pProp)->ValuePtr();
else
return nullptr;
}
@@ -80,39 +95,42 @@ s32 CScriptTemplate::CheckVolumeConditions(CScriptObject *pObj, bool LogErrors)
// Private function
if (mVolumeShape == eConditionalShape)
{
IProperty *pProp = pObj->Properties()->PropertyByIDString(mVolumeConditionIDString);
TIDString PropID = mVolumeConditionIDString;
IPropertyNew* pProp = pObj->Template()->Properties()->ChildByIDString( PropID );
// Get value of the condition test property (only boolean, integral, and enum types supported)
void* pData = pObj->PropertyData();
int Val;
switch (pProp->Type())
{
case eBoolProperty:
Val = (static_cast<TBoolProperty*>(pProp)->Get() ? 1 : 0);
case EPropertyTypeNew::Bool:
Val = TPropCast<CBoolProperty>(pProp)->Value(pData) ? 1 : 0;
break;
case eByteProperty:
Val = (int) static_cast<TByteProperty*>(pProp)->Get();
case EPropertyTypeNew::Byte:
Val = (int) TPropCast<CByteProperty>(pProp)->Value(pData);
break;
case eShortProperty:
Val = (int) static_cast<TShortProperty*>(pProp)->Get();
case EPropertyTypeNew::Short:
Val = (int) TPropCast<CShortProperty>(pProp)->Value(pData);
break;
case eLongProperty:
Val = (int) static_cast<TLongProperty*>(pProp)->Get();
case EPropertyTypeNew::Int:
Val = TPropCast<CIntProperty>(pProp)->Value(pData);
break;
case eEnumProperty:
Val = (int) static_cast<TEnumProperty*>(pProp)->Get();
case EPropertyTypeNew::Enum:
case EPropertyTypeNew::Choice:
Val = TPropCast<CEnumProperty>(pProp)->Value(pData);
break;
}
// Test and check whether any of the conditions are true
for (u32 iCon = 0; iCon < mVolumeConditions.size(); iCon++)
for (u32 LinkIdx = 0; LinkIdx < mVolumeConditions.size(); LinkIdx++)
{
if (mVolumeConditions[iCon].Value == Val)
return iCon;
if (mVolumeConditions[LinkIdx].Value == Val)
return LinkIdx;
}
if (LogErrors)
@@ -122,37 +140,7 @@ s32 CScriptTemplate::CheckVolumeConditions(CScriptObject *pObj, bool LogErrors)
return -1;
}
TStringProperty* CScriptTemplate::FindInstanceName(CPropertyStruct *pProperties)
{
return TFetchProperty<TStringProperty*, eStringProperty>(pProperties, mNameIDString);
}
TVector3Property* CScriptTemplate::FindPosition(CPropertyStruct *pProperties)
{
return TFetchProperty<TVector3Property*, eVector3Property>(pProperties, mPositionIDString);
}
TVector3Property* CScriptTemplate::FindRotation(CPropertyStruct *pProperties)
{
return TFetchProperty<TVector3Property*, eVector3Property>(pProperties, mRotationIDString);
}
TVector3Property* CScriptTemplate::FindScale(CPropertyStruct *pProperties)
{
return TFetchProperty<TVector3Property*, eVector3Property>(pProperties, mScaleIDString);
}
TBoolProperty* CScriptTemplate::FindActive(CPropertyStruct *pProperties)
{
return TFetchProperty<TBoolProperty*, eBoolProperty>(pProperties, mActiveIDString);
}
CPropertyStruct* CScriptTemplate::FindLightParameters(CPropertyStruct *pProperties)
{
return TFetchProperty<CPropertyStruct*, eStructProperty>(pProperties, mLightParametersIDString);
}
CResource* CScriptTemplate::FindDisplayAsset(CPropertyStruct *pProperties, u32& rOutCharIndex, u32& rOutAnimIndex, bool& rOutIsInGame)
CResource* CScriptTemplate::FindDisplayAsset(void* pPropertyData, u32& rOutCharIndex, u32& rOutAnimIndex, bool& rOutIsInGame)
{
rOutCharIndex = -1;
rOutAnimIndex = -1;
@@ -170,25 +158,28 @@ CResource* CScriptTemplate::FindDisplayAsset(CPropertyStruct *pProperties, u32&
// Property
else
{
IProperty *pProp = pProperties->PropertyByIDString(it->AssetLocation);
IPropertyNew* pProp = mpProperties->ChildByIDString(it->AssetLocation);
if (it->AssetType == SEditorAsset::eAnimParams && pProp->Type() == eCharacterProperty)
if (it->AssetType == SEditorAsset::eAnimParams && pProp->Type() == EPropertyTypeNew::AnimationSet)
{
TCharacterProperty *pChar = static_cast<TCharacterProperty*>(pProp);
pRes = pChar->Get().AnimSet();
CAnimationSetProperty* pAnimSet = TPropCast<CAnimationSetProperty>(pProp);
CAnimationParameters Params = pAnimSet->Value(pPropertyData);
pRes = Params.AnimSet();
if (pRes)
{
u32 MaxNumChars = static_cast<CAnimSet*>(pRes)->NumCharacters();
rOutCharIndex = (it->ForceNodeIndex >= 0 && it->ForceNodeIndex < (s32) MaxNumChars ? it->ForceNodeIndex : pChar->Get().CharacterIndex());
rOutAnimIndex = pChar->Get().AnimIndex();
rOutCharIndex = (it->ForceNodeIndex >= 0 && it->ForceNodeIndex < (s32) MaxNumChars ? it->ForceNodeIndex : Params.CharacterIndex());
rOutAnimIndex = Params.AnimIndex();
}
}
else
{
TAssetProperty *pAsset = static_cast<TAssetProperty*>(pProp);
CResourceEntry *pEntry = gpResourceStore->FindEntry(pAsset->Get());
ASSERT(pProp->Type() == EPropertyTypeNew::Asset);
CAssetProperty* pAsset = TPropCast<CAssetProperty>(pProp);
CAssetID ID = pAsset->Value(pPropertyData);
CResourceEntry *pEntry = gpResourceStore->FindEntry( ID );
if (pEntry) pRes = pEntry->Load();
}
}
@@ -205,7 +196,7 @@ CResource* CScriptTemplate::FindDisplayAsset(CPropertyStruct *pProperties, u32&
return nullptr;
}
CCollisionMeshGroup* CScriptTemplate::FindCollision(CPropertyStruct *pProperties)
CCollisionMeshGroup* CScriptTemplate::FindCollision(void* pPropertyData)
{
for (auto it = mAssets.begin(); it != mAssets.end(); it++)
{
@@ -219,12 +210,12 @@ CCollisionMeshGroup* CScriptTemplate::FindCollision(CPropertyStruct *pProperties
// Property
else
{
IProperty *pProp = pProperties->PropertyByIDString(it->AssetLocation);
IPropertyNew* pProp = mpProperties->ChildByIDString(it->AssetLocation);
if (pProp->Type() == eAssetProperty)
if (pProp->Type() == EPropertyTypeNew::Asset)
{
TAssetProperty *pAsset = static_cast<TAssetProperty*>(pProp);
pRes = gpResourceStore->LoadResource( pAsset->Get(), eDynamicCollision );
CAssetProperty* pAsset = TPropCast<CAssetProperty>(pProp);
pRes = gpResourceStore->LoadResource( pAsset->Value(pPropertyData), eDynamicCollision );
}
}

View File

@@ -1,8 +1,7 @@
#ifndef CSCRIPTTEMPLATE_H
#define CSCRIPTTEMPLATE_H
#include "IPropertyTemplate.h"
#include "IProperty.h"
#include "Core/Resource/Script/Property/Properties.h"
#include "EPropertyType.h"
#include "EVolumeShape.h"
#include "Core/Resource/Model/CModel.h"
@@ -12,6 +11,7 @@
#include <list>
#include <vector>
class CMasterTemplate;
class CScriptObject;
typedef TString TIDString;
@@ -64,10 +64,9 @@ private:
s32 ForceNodeIndex; // Force animsets to use specific node instead of one from property
};
CMasterTemplate *mpMaster;
CStructTemplate *mpBaseStruct;
CMasterTemplate* mpMaster;
std::unique_ptr<CStructPropertyNew> mpProperties;
std::list<CScriptObject*> mObjectList;
TString mTemplateName;
std::vector<TString> mModules;
TString mSourceFile;
u32 mObjectID;
@@ -80,6 +79,14 @@ private:
TIDString mScaleIDString;
TIDString mActiveIDString;
TIDString mLightParametersIDString;
CStringProperty* mpNameProperty;
CVectorProperty* mpPositionProperty;
CVectorProperty* mpRotationProperty;
CVectorProperty* mpScaleProperty;
CBoolProperty* mpActiveProperty;
CStructPropertyNew* mpLightParametersProperty;
std::vector<SEditorAsset> mAssets;
std::vector<SAttachment> mAttachments;
@@ -102,44 +109,38 @@ private:
public:
CScriptTemplate(CMasterTemplate *pMaster);
~CScriptTemplate();
void PostLoad();
EGame Game() const;
// Property Fetching
EVolumeShape VolumeShape(CScriptObject *pObj);
float VolumeScale(CScriptObject *pObj);
TStringProperty* FindInstanceName(CPropertyStruct *pProperties);
TVector3Property* FindPosition(CPropertyStruct *pProperties);
TVector3Property* FindRotation(CPropertyStruct *pProperties);
TVector3Property* FindScale(CPropertyStruct *pProperties);
TBoolProperty* FindActive(CPropertyStruct *pProperties);
CPropertyStruct* FindLightParameters(CPropertyStruct *pProperties);
CResource* FindDisplayAsset(CPropertyStruct *pProperties, u32& rOutCharIndex, u32& rOutAnimIndex, bool& rOutIsInGame);
CCollisionMeshGroup* FindCollision(CPropertyStruct *pProperties);
CResource* FindDisplayAsset(void* pPropertyData, u32& rOutCharIndex, u32& rOutAnimIndex, bool& rOutIsInGame);
CCollisionMeshGroup* FindCollision(void* pPropertyData);
// Accessors
inline CMasterTemplate* MasterTemplate() const { return mpMaster; }
inline TString Name() const { return mTemplateName; }
inline TString Name() const { return mpProperties->Name(); }
inline ERotationType RotationType() const { return mRotationType; }
inline EScaleType ScaleType() const { return mScaleType; }
inline float PreviewScale() const { return mPreviewScale; }
inline u32 ObjectID() const { return mObjectID; }
inline bool IsVisible() const { return mVisible; }
inline TString SourceFile() const { return mSourceFile; }
inline CStructTemplate* BaseStruct() const { return mpBaseStruct; }
inline CStructPropertyNew* Properties() const { return mpProperties.get(); }
inline u32 NumAttachments() const { return mAttachments.size(); }
const SAttachment& Attachment(u32 Index) const { return mAttachments[Index]; }
const std::vector<TString>& RequiredModules() const { return mModules; }
inline bool HasName() const { return !mNameIDString.IsEmpty(); }
inline bool HasPosition() const { return !mPositionIDString.IsEmpty(); }
inline bool HasRotation() const { return !mRotationIDString.IsEmpty(); }
inline bool HasScale() const { return !mScaleIDString.IsEmpty(); }
inline bool HasActive() const { return !mActiveIDString.IsEmpty(); }
inline CStringProperty* NameProperty() const { return mpNameProperty; }
inline CVectorProperty* PositionProperty() const { return mpPositionProperty; }
inline CVectorProperty* RotationProperty() const { return mpRotationProperty; }
inline CVectorProperty* ScaleProperty() const { return mpScaleProperty; }
inline CBoolProperty* ActiveProperty() const { return mpActiveProperty; }
inline CStructPropertyNew* LightParametersProperty() const { return mpLightParametersProperty; }
inline void SetVisible(bool Visible) { mVisible = Visible; }
inline void DebugPrintProperties() { mpBaseStruct->DebugPrintProperties(""); }
// Object Tracking
u32 NumObjects() const;
const std::list<CScriptObject*>& ObjectList() const;

View File

@@ -1,6 +1,9 @@
#ifndef EPROPERTYTYPE
#define EPROPERTYTYPE
#include "IPropertyNew.h"
#if 0
#include <Common/TString.h>
enum EPropertyType
@@ -24,11 +27,12 @@ enum EPropertyType
eUnknownProperty,
eInvalidProperty
};
#endif
// functions defined in IPropertyTemplate.cpp
EPropertyType PropStringToPropEnum(TString Prop);
TString PropEnumToPropString(EPropertyType Prop);
const char* HashablePropTypeName(EPropertyType Prop);
EPropertyTypeNew PropStringToPropEnum(TString Prop);
TString PropEnumToPropString(EPropertyTypeNew Prop);
const char* HashablePropTypeName(EPropertyTypeNew Prop);
#endif // EPROPERTYTYPE

View File

@@ -1,6 +1,7 @@
#include "IProperty.h"
#include "IPropertyTemplate.h"
#if 0
// ************ IProperty ************
bool IProperty::IsInArray() const
{
@@ -241,3 +242,4 @@ TString CArrayProperty::ElementName() const
{
return static_cast<CArrayTemplate*>(Template())->ElementName();
}
#endif

View File

@@ -1,6 +1,7 @@
#ifndef IPROPERTY
#define IPROPERTY
#if 0
#include "EPropertyType.h"
#include "IPropertyValue.h"
#include "Core/Resource/CResource.h"
@@ -297,6 +298,6 @@ PropertyClass* TPropCast(IProperty *pProp)
{
return (pProp && pProp->Type() == PropertyClass::StaticType() ? static_cast<PropertyClass*>(pProp) : nullptr);
}
#endif
#endif // IPROPERTY

View File

@@ -0,0 +1,364 @@
#include "IPropertyNew.h"
#include "Property/CAssetProperty.h"
#include "Property/CArrayProperty.h"
#include "Property/CEnumProperty.h"
#include "Property/CFlagsProperty.h"
#include "Property/CPointerProperty.h"
#include "Core/Resource/Script/CMasterTemplate.h"
#include "Core/Resource/Script/CScriptTemplate.h"
/** IPropertyNew */
IPropertyNew::IPropertyNew()
: mpParent( nullptr )
, mpPointerParent( nullptr )
, mpArchetype( nullptr )
, mOffset( -1 )
, mID( -1 )
, mCookPreference( ECookPreferenceNew::Default )
, mMinVersion( 0.0f )
, 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;
}
}
u32 IPropertyNew::_GetOffset() const
{
return mOffset;
}
void IPropertyNew::_ClearChildren()
{
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
delete mChildren[ChildIdx];
mChildren.clear();
}
IPropertyNew::~IPropertyNew()
{
// Remove from archetype
if( mpArchetype != nullptr )
{
NBasics::VectorRemoveOne(mpArchetype->mSubInstances, this);
}
// If this is an archetype, all our sub-instances should have destructed first.
if( IsArchetype() )
{
ASSERT(mSubInstances.empty());
}
// Delete children
_ClearChildren();
}
const char* IPropertyNew::HashableTypeName() const
{
return PropEnumToHashableTypeName( Type() );
}
void* IPropertyNew::GetChildDataPointer(void* pPropertyData) const
{
return pPropertyData;
}
#if 0
void IPropertyNew::Serialize(IArchive& rArc)
{
if (rArc.Game() <= ePrime)
{
rArc << SERIAL("Name", mName);
}
rArc << SERIAL_HEX("ID", mID)
<< SERIAL("Description", mDescription)
<< SERIAL("CookPref", mCookPref)
<< SERIAL("MinVersion", mMinVersion)
<< SERIAL("MaxVersion", mMaxVersion);
// Children don't get serialized for most property types
}
#endif
void IPropertyNew::InitFromArchetype(IPropertyNew* pOther)
{
//@todo maybe somehow use Serialize for this instead?
mpArchetype = pOther;
mFlags = pOther->mFlags & ~EPropertyFlag::ArchetypeCopyFlags;
mID = pOther->mID;
mName = pOther->mName;
mDescription = pOther->mDescription;
mSuffix = pOther->mSuffix;
mCookPreference = pOther->mCookPreference;
mMinVersion = pOther->mMinVersion;
mMaxVersion = pOther->mMaxVersion;
// Copy children
_ClearChildren();
for (u32 ChildIdx = 0; ChildIdx < pOther->mChildren.size(); ChildIdx++)
{
CreateCopy( pOther->mChildren[ChildIdx], this );
}
}
TString IPropertyNew::GetTemplateFileName()
{
if (mpScriptTemplate)
{
return mpScriptTemplate->SourceFile();
}
else if (IsArchetype())
{
IPropertyNew* pRootParent = RootParent();
ASSERT(pRootParent != this);
return pRootParent->GetTemplateFileName();
}
else
{
return mpArchetype->GetTemplateFileName();
}
}
void* IPropertyNew::RawValuePtr(void* pData) const
{
// For array archetypes, the caller needs to provide the pointer to the correct array item
if (IsArrayArchetype())
return pData;
void* pBasePtr = (mpPointerParent ? mpPointerParent->GetChildDataPointer(pData) : pData);
return ((char*)pBasePtr + mOffset);
}
IPropertyNew* IPropertyNew::ChildByID(u32 ID) const
{
for (u32 ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
{
if (mChildren[ChildIdx]->mID == ID)
return mChildren[ChildIdx];
}
return nullptr;
}
IPropertyNew* IPropertyNew::ChildByIDString(const TIDString& rkIdString)
{
// String must contain at least one ID!
// some ID strings are formatted with 8 characters and some with 2 (plus the beginning "0x")
ASSERT(rkIdString.Size() >= 4);
u32 IDEndPos = rkIdString.IndexOf(':');
u32 NextChildID = -1;
if (IDEndPos == -1)
NextChildID = rkIdString.ToInt32();
else
NextChildID = rkIdString.SubString(2, IDEndPos - 2).ToInt32();
if (NextChildID == 0xFFFFFFFF)
{
return nullptr;
}
IPropertyNew* pNextChild = ChildByID(NextChildID);
// Check if we need to recurse
if (IDEndPos != -1)
{
return pNextChild->ChildByIDString(rkIdString.ChopFront(IDEndPos + 1));
}
else
{
return pNextChild;
}
}
bool IPropertyNew::ShouldCook(void*pPropertyData) const
{
switch (mCookPreference)
{
case ECookPreferenceNew::Always:
return true;
case ECookPreferenceNew::Never:
return false;
default:
return (Game() < eReturns ? true : !MatchesDefault(pPropertyData));
}
}
void IPropertyNew::SetName(const TString& rkNewName)
{
mName = rkNewName;
mFlags.ClearFlag(EPropertyFlag::HasCachedNameCheck);
}
void IPropertyNew::SetDescription(const TString& rkNewDescription)
{
mDescription = rkNewDescription;
}
void IPropertyNew::SetSuffix(const TString& rkNewSuffix)
{
mSuffix = rkNewSuffix;
}
bool IPropertyNew::HasAccurateName()
{
if (!mFlags.HasFlag(EPropertyFlag::HasCachedNameCheck))
{
CCRC32 Hash;
Hash.Hash(*mName);
Hash.Hash(HashableTypeName());
u32 GeneratedID = Hash.Digest();
if (GeneratedID == mID)
mFlags.SetFlag( EPropertyFlag::HasCorrectPropertyName );
else
mFlags.ClearFlag( EPropertyFlag::HasCorrectPropertyName );
mFlags.SetFlag(EPropertyFlag::HasCachedNameCheck);
}
return mFlags.HasFlag( EPropertyFlag::HasCorrectPropertyName );
}
/** IPropertyNew Accessors */
EGame IPropertyNew::Game() const
{
return mpMasterTemplate->Game();
}
IPropertyNew* IPropertyNew::Create(EPropertyTypeNew Type,
IPropertyNew* pParent,
CMasterTemplate* pMaster,
CScriptTemplate* pScript,
bool CallPostInit /*= true*/)
{
IPropertyNew* pOut = nullptr;
switch (Type)
{
case EPropertyTypeNew::Bool: pOut = new CBoolProperty; break;
case EPropertyTypeNew::Byte: pOut = new CByteProperty; break;
case EPropertyTypeNew::Short: pOut = new CShortProperty; break;
case EPropertyTypeNew::Int: pOut = new CIntProperty; break;
case EPropertyTypeNew::Float: pOut = new CFloatProperty; break;
case EPropertyTypeNew::Choice: pOut = new CChoiceProperty; break;
case EPropertyTypeNew::Enum: pOut = new CEnumProperty; break;
case EPropertyTypeNew::Flags: pOut = new CFlagsProperty; break;
case EPropertyTypeNew::String: pOut = new CStringProperty; break;
case EPropertyTypeNew::Vector: pOut = new CVectorProperty; break;
case EPropertyTypeNew::Color: pOut = new CColorProperty; break;
case EPropertyTypeNew::Asset: pOut = new CAssetProperty; break;
case EPropertyTypeNew::Sound: pOut = new CSoundProperty; break;
case EPropertyTypeNew::Animation: pOut = new CAnimationProperty; break;
case EPropertyTypeNew::AnimationSet: pOut = new CAnimationSetProperty; break;
case EPropertyTypeNew::Sequence: pOut = new CSequenceProperty; break;
case EPropertyTypeNew::Spline: pOut = new CSplineProperty; break;
case EPropertyTypeNew::Guid: pOut = new CGuidProperty; break;
case EPropertyTypeNew::Pointer: pOut = new CPointerProperty; break;
case EPropertyTypeNew::Struct: pOut = new CStructPropertyNew; break;
case EPropertyTypeNew::Array: pOut = new CArrayProperty; 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->mpMasterTemplate = pMaster;
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();
}
return pOut;
}
IPropertyNew* IPropertyNew::CreateCopy(IPropertyNew* pArchetype,
IPropertyNew* pParent,
bool CallPostInit /*= true*/)
{
// Note this is mainly going to be used to create copies from struct/enum/flag archetype properties.
// 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->mpMasterTemplate, pParent->mpScriptTemplate, false);
pOut->InitFromArchetype(pArchetype);
pArchetype->mSubInstances.push_back(pOut);
if (CallPostInit)
{
pOut->PostInitialize();
}
return pOut;
}

View File

@@ -0,0 +1,432 @@
#ifndef IPROPERTYNEW_H
#define IPROPERTYNEW_H
#include "Core/Resource/Animation/CAnimationParameters.h"
#include <Common/Common.h>
#include <Math/CVector3f.h>
#include <Math/MathUtil.h>
#include <memory>
/** Forward declares */
class CMasterTemplate;
class CScriptTemplate;
class CStructPropertyNew;
/** Typedefs */
typedef TString TIDString;
/** Property flags */
enum class EPropertyFlag : u32
{
/** Property is an archetype (a template for other properties to copy from) */
IsArchetype = 0x1,
/** Property is an array archetype (a template for elements of an array property) */
IsArrayArchetype = 0x2,
/** This property and all its children are a single unit and do not have individual property IDs, sizes, etc. */
IsAtomic = 0x4,
/** We have cached whether the property name is correct */
HasCachedNameCheck = 0x40000000,
/** The name of the property is a match for the property ID hash */
HasCorrectPropertyName = 0x80000000,
/** Flags that are left intact when copying from an archetype */
ArchetypeCopyFlags = EPropertyFlag::IsAtomic,
/** Flags that are inheritable from parent */
InheritableFlags = EPropertyFlag::IsArchetype | EPropertyFlag::IsArrayArchetype | EPropertyFlag::IsAtomic,
};
DECLARE_FLAGS_ENUMCLASS(EPropertyFlag, FPropertyFlags)
/** Property type */
enum class EPropertyTypeNew
{
Bool = FOURCC('BOOL'),
Byte = FOURCC('BYTE'),
Short = FOURCC('SHRT'),
Int = FOURCC('INT '),
Float = FOURCC('REAL'),
Choice = FOURCC('CHOI'),
Enum = FOURCC('ENUM'),
Flags = FOURCC('FLAG'),
String = FOURCC('STRG'),
Vector = FOURCC('VECT'),
Color = FOURCC('COLR'),
Asset = FOURCC('ASST'),
Sound = FOURCC('SOND'),
Animation = FOURCC('ANIM'),
AnimationSet = FOURCC('ANMS'),
Sequence = FOURCC('SQNC'),
Spline = FOURCC('SPLN'),
Guid = FOURCC('GUID'),
Pointer = FOURCC('PNTR'),
Struct = FOURCC('STRC'),
Array = FOURCC('ARRY'),
Invalid = FOURCC('INVD')
};
inline void Serialize(IArchive& rArc, EPropertyTypeNew& rType)
{
rArc.SerializePrimitive( (CFourCC&) rType );
}
inline const char* PropEnumToHashableTypeName(EPropertyTypeNew Type)
{
switch (Type)
{
case EPropertyTypeNew::Bool: return "bool";
case EPropertyTypeNew::Int: return "int";
case EPropertyTypeNew::Float: return "float";
case EPropertyTypeNew::Choice: return "choice";
case EPropertyTypeNew::Enum: return "enum";
case EPropertyTypeNew::Flags: return "Flags";
case EPropertyTypeNew::String: return "string";
case EPropertyTypeNew::Vector: return "Vector";
case EPropertyTypeNew::Color: return "Color";
case EPropertyTypeNew::Asset: return "asset";
case EPropertyTypeNew::Sound: return "sound";
case EPropertyTypeNew::Spline: return "spline";
case EPropertyTypeNew::Guid: return "guid";
default: return "";
}
}
/** Enum that describes when/how properties should be cooked out */
enum class ECookPreferenceNew
{
Default,
Always,
Never
};
inline void Serialize(IArchive& rArc, ECookPreferenceNew& rPref)
{
rArc.SerializePrimitive( (u32&) rPref );
}
/** New property class */
class IPropertyNew
{
friend class CTemplateLoader;
friend class CPropertyFactory;
protected:
/** Flags */
FPropertyFlags mFlags;
/** Parent property */
IPropertyNew* mpParent;
/** Pointer parent; if non-null, this parent needs to be dereferenced to access the correct
* memory region that our property data is stored in */
IPropertyNew* mpPointerParent;
/** Archetype property; source property that we copied metadata from */
IPropertyNew* mpArchetype;
/** Sub-instances of archetype properties. For non-archetypes, will be empty. @todo better
* method of storing this? maybe a linked list? */
std::vector<IPropertyNew*> mSubInstances;
/** Child properties; these appear underneath this property on the UI */
std::vector<IPropertyNew*> mChildren;
/** Master template for the game this property belongs to.
* Cannot be derived from mpScriptTemplate because mpScriptTemplate is null sometimes */
CMasterTemplate* mpMasterTemplate;
/** Script template that this property belongs to. Null for struct/enum/flag archetypes. */
CScriptTemplate* mpScriptTemplate;
/** Offset of this property within the property block */
u32 mOffset;
/** Property ID. This ID is used to uniquely identify this property within this struct. */
u32 mID;
/** Property metadata */
TString mName;
TString mDescription;
TString mSuffix;
ECookPreferenceNew mCookPreference;
/** Min/max allowed version number. These numbers correspond to the game's internal build number.
* This is not used yet but in the future it can be used to configure certain properties to only
* show up when certain versions of the game are being edited. The default values allow the
* property to show up in all versions. */
float mMinVersion;
float mMaxVersion;
/** Private constructor - use static methods to instantiate */
IPropertyNew();
void _CalcOffset();
u32 _GetOffset() const;
void _ClearChildren();
/** Called after property is created and fully initialized */
virtual void PostInitialize() {}
public:
virtual ~IPropertyNew();
/** Interface */
virtual EPropertyTypeNew Type() const = 0;
virtual u32 DataSize() const = 0;
virtual u32 DataAlignment() const = 0;
virtual void Construct(void* pData) const = 0;
virtual void Destruct(void* pData) const = 0;
virtual bool MatchesDefault(void* pData) const = 0;
virtual void RevertToDefault(void* pData) const = 0;
virtual void SerializeValue(void* pData, IArchive& Arc) const = 0;
virtual void PropertyValueChanged(void* pPropertyData) {}
virtual bool IsNumericalType() const { return false; }
virtual bool IsPointerType() const { return false; }
virtual TString ValueAsString(void* pData) const { return ""; }
virtual const char* HashableTypeName() const;
virtual void* GetChildDataPointer(void* pPropertyData) const;
#if 0
virtual void Serialize(IArchive& rArc);
#endif
virtual void InitFromArchetype(IPropertyNew* pOther);
virtual TString GetTemplateFileName();
/** Utility methods */
void* RawValuePtr(void* pData) const;
IPropertyNew* ChildByID(u32 ID) const;
IPropertyNew* ChildByIDString(const TIDString& rkIdString);
bool ShouldCook(void* pPropertyData) const;
void SetName(const TString& rkNewName);
void SetDescription(const TString& rkNewDescription);
void SetSuffix(const TString& rkNewSuffix);
bool HasAccurateName();
/** Accessors */
EGame Game() const;
inline ECookPreferenceNew CookPreference() const;
inline u32 NumChildren() const;
inline IPropertyNew* ChildByIndex(u32 ChildIndex) const;
inline IPropertyNew* Parent() const;
inline IPropertyNew* RootParent();
inline IPropertyNew* Archetype() const;
inline CScriptTemplate* ScriptTemplate() const;
inline CMasterTemplate* MasterTemplate() const;
inline TString Name() const;
inline TString Description() const;
inline TString Suffix() const;
inline TIDString IDString(bool FullyQualified) const;
inline u32 ID() const;
inline bool IsArchetype() const { return mFlags.HasFlag(EPropertyFlag::IsArchetype); }
inline bool IsArrayArchetype() const { return mFlags.HasFlag(EPropertyFlag::IsArrayArchetype); }
inline bool IsAtomic() const { return mFlags.HasFlag(EPropertyFlag::IsAtomic); }
/** Create */
static IPropertyNew* Create(EPropertyTypeNew Type,
IPropertyNew* pParent,
CMasterTemplate* pMaster,
CScriptTemplate* pScript,
bool CallPostInit = true);
static IPropertyNew* CreateCopy(IPropertyNew* pArchetype,
IPropertyNew* pParent,
bool CallPostInit = true);
};
inline ECookPreferenceNew IPropertyNew::CookPreference() const
{
return mCookPreference;
}
inline u32 IPropertyNew::NumChildren() const
{
return mChildren.size();
}
inline IPropertyNew* IPropertyNew::ChildByIndex(u32 ChildIndex) const
{
ASSERT(ChildIndex >= 0 && ChildIndex < mChildren.size());
return mChildren[ChildIndex];
}
inline IPropertyNew* IPropertyNew::Parent() const
{
return mpParent;
}
inline IPropertyNew* IPropertyNew::RootParent()
{
IPropertyNew* pParent = Parent();
IPropertyNew* pOut = this;
while (pParent)
{
pOut = pParent;
pParent = pParent->Parent();
}
return pOut;
}
inline IPropertyNew* IPropertyNew::Archetype() const
{
return mpArchetype;
}
inline CScriptTemplate* IPropertyNew::ScriptTemplate() const
{
return mpScriptTemplate;
}
inline CMasterTemplate* IPropertyNew::MasterTemplate() const
{
return mpMasterTemplate;
}
inline TString IPropertyNew::Name() const
{
return mName;
}
inline TString IPropertyNew::Description() const
{
return mDescription;
}
inline TString IPropertyNew::Suffix() const
{
return mSuffix;
}
inline TString IPropertyNew::IDString(bool FullyQualified) const
{
if (FullyQualified && mpParent != nullptr)
return mpParent->IDString(FullyQualified) + ":" + TString::HexString(mID);
else
return TString::HexString(mID);
}
inline u32 IPropertyNew::ID() const
{
return mID;
}
template<typename PropType, EPropertyTypeNew PropEnum>
class TTypedPropertyNew : public IPropertyNew
{
friend class IPropertyNew;
friend class CTemplateLoader;
public:
typedef PropType ValueType;
protected:
PropType mDefaultValue;
TTypedPropertyNew()
: IPropertyNew()
{
memset(&mDefaultValue, 0, sizeof(PropType));
}
public:
virtual EPropertyTypeNew Type() const { return PropEnum; }
virtual u32 DataSize() const { return sizeof(PropType); }
virtual u32 DataAlignment() const { return alignof(PropType); }
virtual void Construct(void* pData) const { new(ValuePtr(pData)) PropType(mDefaultValue); }
virtual void Destruct(void* pData) const { ValueRef(pData).~PropType(); }
virtual bool MatchesDefault(void* pData) const { return ValueRef(pData) == mDefaultValue; }
virtual void RevertToDefault(void* pData) const { ValueRef(pData) = mDefaultValue; }
virtual bool CanHaveDefault() const { return true; }
#if 0
virtual void Serialize(IArchive& rArc)
{
IPropertyNew::Serialize(rArc);
rArc << SERIAL("DefaultValue", mDefaultValue);
}
#endif
virtual void InitFromArchetype(IPropertyNew* pOther)
{
IPropertyNew::InitFromArchetype(pOther);
mDefaultValue = static_cast<TTypedPropertyNew*>(pOther)->mDefaultValue;
}
inline PropType* ValuePtr(void* pData) const
{
return (PropType*) RawValuePtr(pData);
}
inline PropType& ValueRef(void* pData) const
{
return *ValuePtr(pData);
}
inline PropType Value(void* pData) const
{
return *ValuePtr(pData);
}
inline static EPropertyTypeNew StaticType() { return PropEnum; }
};
template<typename PropType, EPropertyTypeNew PropEnum>
class TNumericalPropertyNew : public TTypedPropertyNew<PropType, PropEnum>
{
friend class IPropertyNew;
friend class CTemplateLoader;
protected:
PropType mMinValue;
PropType mMaxValue;
TNumericalPropertyNew()
: TTypedPropertyNew()
, mMinValue( -1 )
, mMaxValue( -1 )
{}
public:
#if 0
virtual void Serialize(IArchive& rArc)
{
TTypedPropertyNew::Serialize(rArc);
rArc << SERIAL("Min", mMin)
<< SERIAL("Max", mMax);
}
#endif
virtual void InitFromArchetype(IPropertyNew* pOther)
{
TTypedPropertyNew::InitFromArchetype(pOther);
TNumericalPropertyNew* pCastOther = static_cast<TNumericalPropertyNew*>(pOther);
mMinValue = pCastOther->mMinValue;
mMaxValue = pCastOther->mMaxValue;
}
virtual void PropertyValueChanged(void* pPropertyData)
{
IPropertyNew::PropertyValueChanged(pPropertyData);
if (mMinValue >= 0 && mMaxValue >= 0)
{
PropType& rValue = ValueRef(pPropertyData);
rValue = Math::Clamp(mMinValue, mMaxValue, rValue);
}
}
};
/** Property casting with dynamic type checking */
template<class PropertyClass>
inline PropertyClass* TPropCast(IPropertyNew* pProperty)
{
if (pProperty && pProperty->Type() == PropertyClass::StaticType())
{
return static_cast<PropertyClass*>(pProperty);
}
else
{
return nullptr;
}
}
#endif // IPROPERTYNEW_H

View File

@@ -3,6 +3,7 @@
#include <Common/Hash/CCRC32.h>
#include <iostream>
#if 0
// ************ IPropertyTemplate ************
EGame IPropertyTemplate::Game() const
{
@@ -250,75 +251,73 @@ void CStructTemplate::DetermineVersionPropertyCounts()
}
}
}
#endif
// ************ GLOBAL FUNCTIONS ************
TString PropEnumToPropString(EPropertyType Prop)
TString PropEnumToPropString(EPropertyTypeNew Prop)
{
switch (Prop)
{
case eBoolProperty: return "bool";
case eByteProperty: return "byte";
case eShortProperty: return "short";
case eLongProperty: return "long";
case eEnumProperty: return "enum";
case eBitfieldProperty: return "bitfield";
case eFloatProperty: return "float";
case eStringProperty: return "string";
case eColorProperty: return "color";
case eVector3Property: return "vector3f";
case eSoundProperty: return "sound";
case eAssetProperty: return "asset";
case eStructProperty: return "struct";
case eArrayProperty: return "array";
case eCharacterProperty: return "character";
case eMayaSplineProperty: return "MayaSpline";
case eUnknownProperty: return "unknown";
case EPropertyTypeNew::Bool: return "bool";
case EPropertyTypeNew::Byte: return "byte";
case EPropertyTypeNew::Short: return "short";
case EPropertyTypeNew::Int: return "long";
case EPropertyTypeNew::Enum: return "enum";
case EPropertyTypeNew::Flags: return "bitfield";
case EPropertyTypeNew::Float: return "float";
case EPropertyTypeNew::String: return "string";
case EPropertyTypeNew::Color: return "color";
case EPropertyTypeNew::Vector: return "vector3f";
case EPropertyTypeNew::Sound: return "sound";
case EPropertyTypeNew::Asset: return "asset";
case EPropertyTypeNew::Struct: return "struct";
case EPropertyTypeNew::Array: return "array";
case EPropertyTypeNew::AnimationSet: return "character";
case EPropertyTypeNew::Spline: return "MayaSpline";
case eInvalidProperty:
default:
return "invalid";
}
}
EPropertyType PropStringToPropEnum(TString Prop)
EPropertyTypeNew PropStringToPropEnum(TString Prop)
{
Prop = Prop.ToLower();
if (Prop == "bool") return eBoolProperty;
if (Prop == "byte") return eByteProperty;
if (Prop == "short") return eShortProperty;
if (Prop == "long") return eLongProperty;
if (Prop == "enum") return eEnumProperty;
if (Prop == "bitfield") return eBitfieldProperty;
if (Prop == "float") return eFloatProperty;
if (Prop == "string") return eStringProperty;
if (Prop == "color") return eColorProperty;
if (Prop == "vector3f") return eVector3Property;
if (Prop == "sound") return eSoundProperty;
if (Prop == "asset") return eAssetProperty;
if (Prop == "struct") return eStructProperty;
if (Prop == "array") return eArrayProperty;
if (Prop == "character") return eCharacterProperty;
if (Prop == "mayaspline") return eMayaSplineProperty;
if (Prop == "unknown") return eUnknownProperty;
return eInvalidProperty;
if (Prop == "bool") return EPropertyTypeNew::Bool;
if (Prop == "byte") return EPropertyTypeNew::Byte;
if (Prop == "short") return EPropertyTypeNew::Short;
if (Prop == "long") return EPropertyTypeNew::Int;
if (Prop == "enum") return EPropertyTypeNew::Enum;
if (Prop == "bitfield") return EPropertyTypeNew::Flags;
if (Prop == "float") return EPropertyTypeNew::Float;
if (Prop == "string") return EPropertyTypeNew::String;
if (Prop == "color") return EPropertyTypeNew::Color;
if (Prop == "vector3f") return EPropertyTypeNew::Vector;
if (Prop == "sound") return EPropertyTypeNew::Sound;
if (Prop == "asset") return EPropertyTypeNew::Asset;
if (Prop == "struct") return EPropertyTypeNew::Struct;
if (Prop == "array") return EPropertyTypeNew::Array;
if (Prop == "character") return EPropertyTypeNew::AnimationSet;
if (Prop == "mayaspline") return EPropertyTypeNew::Spline;
return EPropertyTypeNew::Invalid;
}
const char* HashablePropTypeName(EPropertyType Prop)
const char* HashablePropTypeName(EPropertyTypeNew Prop)
{
// Variants that match Retro's internal type names for generating property IDs. case sensitive
switch (Prop)
{
case eBoolProperty: return "bool";
case eLongProperty: return "int";
case eEnumProperty: return "enum";
case eBitfieldProperty: return "Flags";
case eFloatProperty: return "float";
case eStringProperty: return "string";
case eColorProperty: return "Color";
case eVector3Property: return "Vector";
case eSoundProperty: return "sound";
case eAssetProperty: return "asset";
case eMayaSplineProperty: return "spline";
case EPropertyTypeNew::Bool: return "bool";
case EPropertyTypeNew::Int: return "int";
case EPropertyTypeNew::Enum: return "enum";
case EPropertyTypeNew::Flags: return "Flags";
case EPropertyTypeNew::Float: return "float";
case EPropertyTypeNew::String: return "string";
case EPropertyTypeNew::Color: return "Color";
case EPropertyTypeNew::Vector: return "Vector";
case EPropertyTypeNew::Sound: return "sound";
case EPropertyTypeNew::Asset: return "asset";
case EPropertyTypeNew::Spline: return "spline";
// All other types are either invalid or need a custom reimplementation because they can return multiple strings (like struct)
default:
@@ -327,6 +326,7 @@ const char* HashablePropTypeName(EPropertyType Prop)
}
}
#if 0
// ************ DEBUG ************
void CStructTemplate::DebugPrintProperties(TString base)
{
@@ -343,3 +343,4 @@ void CStructTemplate::DebugPrintProperties(TString base)
Log::Write(base + tmp->Name());
}
}
#endif

View File

@@ -1,6 +1,7 @@
#ifndef IPROPERTYTEMPLATE
#define IPROPERTYTEMPLATE
#if 0
#include "EPropertyType.h"
#include "IProperty.h"
#include "IPropertyValue.h"
@@ -797,6 +798,7 @@ public:
return (CPropertyStruct*) CStructTemplate::InstantiateProperty(pInstance, pArray);
}
};
#endif
#endif // IPROPERTYTEMPLATE

View File

@@ -1,6 +1,7 @@
#ifndef IPROPERTYVALUE_H
#define IPROPERTYVALUE_H
#if 0
#include "EPropertyType.h"
#include <Common/CAssetID.h>
#include <Common/Log.h>
@@ -386,5 +387,6 @@ public:
return new CUnknownValue(mValue);
}
};
#endif
#endif // IPROPERTYVALUE_H

View File

@@ -0,0 +1,27 @@
#ifndef CANIMATIONPROPERTY_H
#define CANIMATIONPROPERTY_H
#include "../IPropertyNew.h"
class CAnimationProperty : public TTypedPropertyNew< int, EPropertyTypeNew::Animation >
{
friend class IPropertyNew;
protected:
CAnimationProperty()
: TTypedPropertyNew()
{}
public:
virtual void SerializeValue(void* pData, IArchive& rArc) const
{
rArc.SerializeHexPrimitive( (u32&) ValueRef(pData) );
}
virtual TString ValueAsString(void* pData) const
{
return TString::HexString( (u32) Value(pData) );
}
};
#endif // CANIMATIONPROPERTY_H

View File

@@ -0,0 +1,22 @@
#ifndef CANIMATIONSETPROPERTY_H
#define CANIMATIONSETPROPERTY_H
#include "../IPropertyNew.h"
class CAnimationSetProperty : public TTypedPropertyNew< CAnimationParameters, EPropertyTypeNew::AnimationSet >
{
friend class IPropertyNew;
protected:
CAnimationSetProperty()
: TTypedPropertyNew()
{}
public:
virtual void SerializeValue(void* pData, IArchive& Arc) const
{
Value(pData).Serialize(Arc);
}
};
#endif // CANIMATIONSETPROPERTY_H

View File

@@ -0,0 +1,176 @@
#ifndef CARRAYPROPERTY_H
#define CARRAYPROPERTY_H
#include "../IPropertyNew.h"
struct SScriptArray
{
int Count;
std::vector<char> Array;
SScriptArray()
: Count(0)
{}
inline bool operator==(const SScriptArray& rkOther) const
{
return( Count == rkOther.Count && Array == rkOther.Array );
}
};
/** You probably shouldn't use this on intrinsic classes; script only */
/** @todo proper support of default values for arrays (this would be used for prefabs) */
class CArrayProperty : public TTypedPropertyNew<int, EPropertyTypeNew::Array>
{
friend class CTemplateLoader;
/** This class inherits from TTypedPropertyNew<int> in order to expose the array
* count value. Outside users can edit this value and we respond by updating the
* allocated space, handling destruction/construction, etc.
*/
IPropertyNew* mpItemArchetype;
/** Internal functions */
SScriptArray& _GetInternalArray(void* pData) const
{
return *( (SScriptArray*) RawValuePtr(pData) );
}
u32 _InternalArrayCount(void* pPropertyData) const
{
std::vector<char>& rArray = _GetInternalArray(pPropertyData).Array;
return rArray.size() / ItemSize();
}
public:
virtual u32 DataSize() const
{
return sizeof(SScriptArray);
}
virtual u32 DataAlignment() const
{
return alignof(SScriptArray);
}
virtual void Construct(void* pData) const
{
new(ValuePtr(pData)) SScriptArray;
}
virtual void Destruct(void* pData) const
{
RevertToDefault(pData);
TTypedPropertyNew::Destruct(pData);
}
virtual bool MatchesDefault(void* pData) const
{
return ArrayCount(pData) == 0;
}
virtual void RevertToDefault(void* pData) const
{
Resize(pData, 0);
ValueRef(pData) = 0;
}
virtual bool CanHaveDefault() const
{
return true;
}
virtual bool IsPointerType() const
{
return true;
}
virtual void* GetChildDataPointer(void* pPropertyData) const
{
return _GetInternalArray(pPropertyData).Array.data();
}
virtual void PropertyValueChanged(void* pPropertyData)
{
SScriptArray& rArray = _GetInternalArray(pPropertyData);
rArray.Count = Math::Max(rArray.Count, 0);
Resize(pPropertyData, rArray.Count);
}
virtual void SerializeValue(void* pData, IArchive& Arc) const
{
u32 Count = ArrayCount(pData);
Arc.SerializePrimitive(Count);
if (Arc.IsReader())
Resize(pData, Count);
for (u32 ItemIdx = 0; ItemIdx < Count; ItemIdx++)
{
if (Arc.ParamBegin("ArrayElement"))
{
void* pItemData = ItemPointer(pData, ItemIdx);
mpArchetype->SerializeValue(pItemData, Arc);
Arc.ParamEnd();
}
}
}
u32 ArrayCount(void* pPropertyData) const
{
return ValueRef(pPropertyData);
}
void Resize(void* pPropertyData, u32 NewCount) const
{
u32 OldCount = _InternalArrayCount(pPropertyData);
if (OldCount != NewCount)
{
SScriptArray& rArray = _GetInternalArray(pPropertyData);
// Handle destruction of old elements
if (OldCount > NewCount)
{
for (u32 ItemIdx = NewCount; ItemIdx < OldCount; ItemIdx++)
{
void* pItemPtr = ItemPointer(pPropertyData, ItemIdx);
mpItemArchetype->Destruct(pItemPtr);
}
}
u32 NewSize = NewCount * ItemSize();
rArray.Array.resize(NewSize);
// Handle construction of new elements
if (NewCount > OldCount)
{
for (u32 ItemIdx = OldCount; ItemIdx < NewCount; ItemIdx++)
{
void* pItemPtr = ItemPointer(pPropertyData, ItemIdx);
mpItemArchetype->Construct(pItemPtr);
}
}
}
}
void* ItemPointer(void* pPropertyData, u32 ItemIndex) const
{
ASSERT(ArrayCount(pPropertyData) > ItemIndex);
std::vector<char>& rArray = _GetInternalArray(pPropertyData).Array;
u32 MyItemSize = ItemSize();
ASSERT(rArray.size() >= (MyItemSize * (ItemIndex+1)));
return rArray.data() + (MyItemSize * ItemIndex);
}
u32 ItemSize() const
{
u32 ItemAlign = mpItemArchetype->DataAlignment();
u32 ItemSize = ALIGN(mpItemArchetype->DataSize(), ItemAlign);
return ItemSize;
}
/** Accessors */
IPropertyNew* ArchetypeProperty() const { return mpArchetype; }
};
#endif // CARRAYPROPERTY_H

View File

@@ -0,0 +1,42 @@
#ifndef CASSETPROPERTY_H
#define CASSETPROPERTY_H
#include "../IPropertyNew.h"
#include "Core/Resource/CResTypeFilter.h"
class CAssetProperty : public TTypedPropertyNew<CAssetID, EPropertyTypeNew::Asset>
{
friend class CTemplateLoader;
CResTypeFilter mTypeFilter;
public:
#if 0
virtual void Serialize(IArchive& rArc)
{
TTypedPropertyNew::Serialize(rArc);
rArc << SERIAL("AcceptedTypes", mTypeFilter);
}
#endif
virtual void SerializeValue(void* pData, IArchive& Arc) const
{
Arc.SerializePrimitive( ValueRef(pData) );
}
virtual TString ValueAsString(void* pData) const
{
return Value(pData).ToString();
}
void SetTypeFilter(const TStringList& rkExtensions)
{
mTypeFilter.SetAcceptedTypes(Game(), rkExtensions);
}
const CResTypeFilter& GetTypeFilter() const
{
return mTypeFilter;
}
};
#endif // CASSETPROPERTY_H

View File

@@ -0,0 +1,27 @@
#ifndef CBOOLPROPERTY_H
#define CBOOLPROPERTY_H
#include "../IPropertyNew.h"
class CBoolProperty : public TTypedPropertyNew< bool, EPropertyTypeNew::Bool >
{
friend class IPropertyNew;
protected:
CBoolProperty()
: TTypedPropertyNew()
{}
public:
virtual void SerializeValue(void* pData, IArchive& Arc) const
{
Arc.SerializePrimitive( ValueRef(pData) );
}
virtual TString ValueAsString(void* pData)
{
return Value(pData) ? "true" : "false";
}
};
#endif // CBOOLPROPERTY_H

View File

@@ -0,0 +1,27 @@
#ifndef CBYTEPROPERTY_H
#define CBYTEPROPERTY_H
#include "../IPropertyNew.h"
class CByteProperty : public TNumericalPropertyNew< char, EPropertyTypeNew::Byte >
{
friend class IPropertyNew;
protected:
CByteProperty()
: TNumericalPropertyNew()
{}
public:
virtual void SerializeValue(void* pData, IArchive& Arc) const
{
Arc.SerializePrimitive( (u8&) ValueRef(pData) );
}
virtual TString ValueAsString(void* pData)
{
return TString::FromInt32( (s32) Value(pData), 0, 10 );
}
};
#endif // CBYTEPROPERTY_H

View File

@@ -0,0 +1,34 @@
#ifndef CCOLORPROPERTY_H
#define CCOLORPROPERTY_H
#include "../IPropertyNew.h"
class CColorProperty : public TTypedPropertyNew< CColor, EPropertyTypeNew::Color >
{
friend class IPropertyNew;
protected:
CColorProperty()
: TTypedPropertyNew()
{}
public:
virtual void PostInitialize()
{
IPropertyNew* pR = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate);
IPropertyNew* pG = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate);
IPropertyNew* pB = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate);
IPropertyNew* pA = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate);
pR->SetName("R");
pG->SetName("G");
pB->SetName("B");
pA->SetName("A");
}
virtual void SerializeValue(void* pData, IArchive& Arc) const
{
Value(pData).Serialize(Arc);
}
};
#endif // CVECTORPROPERTY_H

View File

@@ -0,0 +1,124 @@
#ifndef CENUMPROPERTY_H
#define CENUMPROPERTY_H
#include "../IPropertyNew.h"
/** There are two types of enum properties: in the game data enum and choice.
*
* In the game, the difference is that choice properties are index-based, while
* enum properties are stored as a hash of the name of the enum.
*
* In PWE, however, they are both implemented the same way under the hood.
*/
template<EPropertyTypeNew TypeEnum>
class TEnumPropertyBase : public TTypedPropertyNew<int, TypeEnum>
{
friend class CTemplateLoader;
struct SEnumValue
{
TString Name;
u32 ID;
SEnumValue(const TString& rkInName, u32 InID)
: Name(rkInName), ID(InID) {}
inline bool operator==(const SEnumValue& rkOther) const
{
return( Name == rkOther.Name && ID == rkOther.ID );
}
};
std::vector<SEnumValue> mValues;
/** XML template file that this enum originated from; for archetypes */
TString mSourceFile;
public:
virtual const char* GetHashableTypeName() const
{
if (TypeEnum == EPropertyTypeNew::Enum)
return "enum";
else
return "choice";
}
virtual void SerializeValue(void* pData, IArchive& Arc) const
{
Arc.SerializePrimitive( (u32&) ValueRef(pData) );
}
virtual TString GetTemplateFileName()
{
ASSERT(IsArchetype() || mpArchetype);
return IsArchetype() ? mSourceFile : mpArchetype->GetTemplateFileName();
}
inline u32 NumPossibleValues() const { return mValues.size(); }
u32 ValueIndex(u32 ID) const
{
for (u32 ValueIdx = 0; ValueIdx < mValues.size(); ValueIdx++)
{
if (mValues[ValueIdx].ID == ID)
{
return ValueIdx;
}
}
return -1;
}
u32 ValueID(u32 Index) const
{
ASSERT(Index >= 0 && Index < mValues.size());
return mValues[Index].ID;
}
TString ValueName(u32 Index) const
{
ASSERT(Index >= 0 && Index < mValues.size());
return mValues[Index].Name;
}
bool HasValidValue(void* pPropertyData)
{
int ID = ValueRef(pPropertyData);
u32 Index = ValueIndex(ID);
return Index >= 0 && Index < mValues.size();
}
};
typedef TEnumPropertyBase<EPropertyTypeNew::Choice> CChoiceProperty;
typedef TEnumPropertyBase<EPropertyTypeNew::Enum> CEnumProperty;
// Specialization of TPropCast to allow interchangeable casting, as both types are the same thing
template<>
inline CEnumProperty* TPropCast(IPropertyNew* pProperty)
{
EPropertyTypeNew InType = pProperty->Type();
if (InType == EPropertyTypeNew::Enum || InType == EPropertyTypeNew::Choice)
{
return static_cast<CEnumProperty*>(pProperty);
}
else
{
return nullptr;
}
}
template<>
inline CChoiceProperty* TPropCast(IPropertyNew* pProperty)
{
if (pProperty)
{
EPropertyTypeNew InType = pProperty->Type();
if (InType == EPropertyTypeNew::Enum || InType == EPropertyTypeNew::Choice)
{
return static_cast<CChoiceProperty*>(pProperty);
}
}
return nullptr;
}
#endif // CENUMPROPERTY_H

View File

@@ -0,0 +1,99 @@
#ifndef CFLAGSPROPERTY_H
#define CFLAGSPROPERTY_H
#include "../IPropertyNew.h"
class CFlagsProperty : public TTypedPropertyNew<int, EPropertyTypeNew::Flags>
{
friend class CTemplateLoader;
friend class IPropertyNew;
struct SBitFlag
{
TString Name;
u32 Mask;
SBitFlag(const TString& rkInName, u32 InMask)
: Name(rkInName), Mask(InMask)
{}
bool operator==(const SBitFlag& rkOther) const
{
return( Name == rkOther.Name && Mask == rkOther.Mask );
}
#if 0
void Serialize(IArchive& rArc)
{
rArc << SERIAL("FlagName", Name)
<< SERIAL_HEX("FlagMask", Mask);
}
#endif
};
std::vector<SBitFlag> mBitFlags;
u32 mAllFlags;
/** XML template file that this enum originated from; for archetypes */
TString mSourceFile;
CFlagsProperty()
: TTypedPropertyNew()
, mAllFlags(0)
{}
public:
inline u32 NumFlags() const
{
return mBitFlags.size();
}
inline TString FlagName(u32 Idx) const
{
ASSERT(Idx >= 0 && Idx < mBitFlags.size());
return mBitFlags[Idx].Name;
}
inline u32 FlagMask(u32 Idx) const
{
ASSERT(Idx >= 0 && Idx < mBitFlags.size());
return mBitFlags[Idx].Mask;
}
#if 0
virtual void Serialize(IArchive& rArc)
{
TTypedPropertyNew::Serialize(rArc);
rArc << SERIAL_CONTAINER("Flags", mFlags, "Flag");
// Initialize the "all flags" cache
if (rArc.IsReader())
{
mAllFlags = 0;
for (u32 FlagIdx = 0; FlagIdx < mFlags.size(); FlagIdx++)
mAllFlags |= mFlags[FlagIdx].Mask;
}
}
#endif
virtual void SerializeValue(void* pData, IArchive& rArc) const
{
rArc.SerializeHexPrimitive( (u32&) ValueRef(pData) );
}
virtual TString GetTemplateFileName()
{
ASSERT(IsArchetype() || mpArchetype);
return IsArchetype() ? mSourceFile : mpArchetype->GetTemplateFileName();
}
/**
* Checks whether there are any unrecognized bits toggled on in the property value.
* Returns the mask of any invalid bits. If all bits are valid, returns 0.
*/
u32 HasValidValue(void* pPropertyData)
{
return ValueRef(pPropertyData) & ~mAllFlags;
}
};
#endif // CFLAGSPROPERTY_H

View File

@@ -0,0 +1,27 @@
#ifndef CFLOATPROPERTY_H
#define CFLOATPROPERTY_H
#include "../IPropertyNew.h"
class CFloatProperty : public TNumericalPropertyNew< float, EPropertyTypeNew::Float >
{
friend class IPropertyNew;
protected:
CFloatProperty()
: TNumericalPropertyNew()
{}
public:
virtual void SerializeValue(void* pData, IArchive& Arc) const
{
Arc.SerializePrimitive( (float&) ValueRef(pData) );
}
virtual TString ValueAsString(void* pData)
{
return TString::FromFloat( Value(pData) );
}
};
#endif // CFLOATPROPERTY_H

View File

@@ -0,0 +1,22 @@
#ifndef CGUIDPROPERTY_H
#define CGUIDPROPERTY_H
#include "../IPropertyNew.h"
class CGuidProperty : public TTypedPropertyNew< std::vector<char>, EPropertyTypeNew::Guid >
{
friend class IPropertyNew;
protected:
CGuidProperty()
: TTypedPropertyNew()
{}
public:
virtual void SerializeValue(void* pData, IArchive& Arc) const
{
Arc.SerializeBulkData( ValueRef(pData) );
}
};
#endif // CSPLINEPROPERTY_H

View File

@@ -0,0 +1,27 @@
#ifndef CINTPROPERTY_H
#define CINTPROPERTY_H
#include "../IPropertyNew.h"
class CIntProperty : public TNumericalPropertyNew< int, EPropertyTypeNew::Int >
{
friend class IPropertyNew;
protected:
CIntProperty()
: TNumericalPropertyNew()
{}
public:
virtual void SerializeValue(void* pData, IArchive& Arc) const
{
Arc.SerializePrimitive( (u32&) ValueRef(pData) );
}
virtual TString ValueAsString(void* pData)
{
return TString::FromInt32( Value(pData), 0, 10 );
}
};
#endif // CINTPROPERTY_H

View File

@@ -0,0 +1,27 @@
#ifndef CPOINTERPROPERTY_H
#define CPOINTERPROPERTY_H
#include "../IPropertyNew.h"
class CPointerProperty : public TTypedPropertyNew<void*, EPropertyTypeNew::Pointer>
{
friend class CTemplateLoader;
public:
virtual bool IsPointerType() const
{
return true;
}
virtual void* GetChildDataPointer(void* pPropertyData) const
{
return ValueRef(pPropertyData);
}
virtual void SerializeValue(void* pData, IArchive& rArc) const
{
// pointers are not serializable, this shouldn't happen
ASSERT(false);
}
};
#endif // CPOINTERPROPERTY_H

View File

@@ -0,0 +1,19 @@
#ifndef CSEQUENCEPROPERTY_H
#define CSEQUENCEPROPERTY_H
#include "../IPropertyNew.h"
class CSequenceProperty : public TTypedPropertyNew< int, EPropertyTypeNew::Sequence >
{
friend class IPropertyNew;
protected:
CSequenceProperty()
: TTypedPropertyNew()
{}
virtual void SerializeValue(void* pData, IArchive& rArc) const
{}
};
#endif // CSEQUENCEPROPERTY_H

View File

@@ -0,0 +1,27 @@
#ifndef CSHORTPROPERTY_H
#define CSHORTPROPERTY_H
#include "../IPropertyNew.h"
class CShortProperty : public TNumericalPropertyNew< short, EPropertyTypeNew::Short >
{
friend class IPropertyNew;
protected:
CShortProperty()
: TNumericalPropertyNew()
{}
public:
virtual void SerializeValue(void* pData, IArchive& Arc) const
{
Arc.SerializePrimitive( (u16&) ValueRef(pData) );
}
virtual TString ValueAsString(void* pData)
{
return TString::FromInt32( (s32) Value(pData), 0, 10 );
}
};
#endif // CSHORTPROPERTY_H

View File

@@ -0,0 +1,27 @@
#ifndef CSOUNDPROPERTY_H
#define CSOUNDPROPERTY_H
#include "../IPropertyNew.h"
class CSoundProperty : public TTypedPropertyNew< int, EPropertyTypeNew::Sound >
{
friend class IPropertyNew;
protected:
CSoundProperty()
: TTypedPropertyNew()
{}
public:
virtual void SerializeValue(void* pData, IArchive& Arc) const
{
Arc.SerializePrimitive( (u32&) ValueRef(pData) );
}
virtual TString ValueAsString(void* pData)
{
return TString::FromInt32( Value(pData), 0, 10 );
}
};
#endif // CSOUNDPROPERTY_H

View File

@@ -0,0 +1,22 @@
#ifndef CSPLINEPROPERTY_H
#define CSPLINEPROPERTY_H
#include "../IPropertyNew.h"
class CSplineProperty : public TTypedPropertyNew< std::vector<char>, EPropertyTypeNew::Spline >
{
friend class IPropertyNew;
protected:
CSplineProperty()
: TTypedPropertyNew()
{}
public:
virtual void SerializeValue(void* pData, IArchive& Arc) const
{
Arc.SerializeBulkData( ValueRef(pData) );
}
};
#endif // CSPLINEPROPERTY_H

View File

@@ -0,0 +1,27 @@
#ifndef CSTRINGPROPERTY_H
#define CSTRINGPROPERTY_H
#include "../IPropertyNew.h"
class CStringProperty : public TTypedPropertyNew< TString, EPropertyTypeNew::String >
{
friend class IPropertyNew;
protected:
CStringProperty()
: TTypedPropertyNew()
{}
public:
virtual void SerializeValue(void* pData, IArchive& Arc) const
{
Arc.SerializePrimitive( ValueRef(pData) );
}
virtual TString ValueAsString(void* pData) const
{
return Value(pData);
}
};
#endif // CSTRINGPROPERTY_H

View File

@@ -0,0 +1,146 @@
#ifndef CSTRUCTPROPERTY_H
#define CSTRUCTPROPERTY_H
#include "../IPropertyNew.h"
class CStructPropertyNew : public IPropertyNew
{
friend class CTemplateLoader;
public:
// Must be a valid type for TPropertyRef
typedef void* ValueType;
protected:
/** For archetypes, the filename of the template XML file. */
TString mTemplateFileName;
public:
virtual EPropertyTypeNew Type() const
{
return EPropertyTypeNew::Struct;
}
virtual u32 DataSize() const
{
if (!mChildren.empty())
{
IPropertyNew* pLastChild = mChildren.back();
return _GetOffset() + pLastChild->DataSize();
}
else
{
return 0;
}
}
virtual u32 DataAlignment() const
{
return (mChildren.empty() ? 1 : mChildren[0]->DataAlignment());
}
virtual void Construct(void* pData) const
{
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
{
mChildren[ChildIdx]->Construct(pData);
}
}
virtual void Destruct(void* pData) const
{
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
{
mChildren[ChildIdx]->Destruct(pData);
}
}
virtual bool MatchesDefault(void* pData) const
{
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
{
if (!mChildren[ChildIdx]->MatchesDefault(pData))
{
return false;
}
}
return true;
}
virtual void RevertToDefault(void* pData) const
{
for (int ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
{
mChildren[ChildIdx]->RevertToDefault(pData);
}
}
virtual const char* HashableTypeName() const
{
ASSERT(IsArchetype() || mpArchetype != nullptr);
if (IsArchetype())
return *mName;
else
return *mpArchetype->Name();
}
#if 0
virtual void Serialize(IArchive& rArc)
{
IPropertyNew::Serialize(rArc);
if (rArc.ParamBegin("SubProperties"))
{
u32 NumChildren;
rArc.SerializeContainerSize(NumChildren, "Property");
if (rArc.IsReader())
{
mChildren.resize(NumChildren);
}
for (u32 ChildIdx = 0; ChildIdx < NumChildren; ChildIdx++)
{
if (rArc.ParamBegin("Property"))
{
EPropertyTypeNew Type = (rArc.IsWriter() ? mChildren[ChildIdx]->Type() : EPropertyTypeNew::Invalid);
rArc << SERIAL_AUTO(Type);
if (rArc.IsReader())
{
mChildren[ChildIdx] = Create(Type, this, mpMasterTemplate, mpScriptTemplate);
}
mChildren[ChildIdx]->Serialize(rArc);
rArc.ParamEnd();
}
}
rArc.ParamEnd();
}
}
#endif
virtual void SerializeValue(void* pData, IArchive& Arc) const
{
for (u32 ChildIdx = 0; ChildIdx < mChildren.size(); ChildIdx++)
{
if (Arc.ParamBegin("Property"))
{
mChildren[ChildIdx]->SerializeValue(pData, Arc);
Arc.ParamEnd();
}
}
}
virtual TString GetTemplateFileName()
{
ASSERT(IsArchetype() || mpArchetype);
return IsArchetype() ? mTemplateFileName : mpArchetype->GetTemplateFileName();
}
inline static EPropertyTypeNew StaticType() { return EPropertyTypeNew::Struct; }
};
#endif

View File

@@ -0,0 +1,37 @@
#ifndef CVECTORPROPERTY_H
#define CVECTORPROPERTY_H
#include "../IPropertyNew.h"
class CVectorProperty : public TTypedPropertyNew< CVector3f, EPropertyTypeNew::Vector >
{
friend class IPropertyNew;
protected:
CVectorProperty()
: TTypedPropertyNew()
{}
public:
virtual void PostInitialize()
{
IPropertyNew* pX = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate);
IPropertyNew* pY = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate);
IPropertyNew* pZ = Create(EPropertyTypeNew::Float, this, mpMasterTemplate, mpScriptTemplate);
pX->SetName("X");
pY->SetName("Y");
pZ->SetName("Z");
}
virtual void SerializeValue(void* pData, IArchive& Arc) const
{
ValueRef(pData).Serialize(Arc);
}
virtual TString ValueAsString(void* pData) const
{
return Value(pData).ToString();
}
};
#endif // CVECTORPROPERTY_H

View File

@@ -0,0 +1,27 @@
#ifndef PROPERTIES_H
#define PROPERTIES_H
#include "../IPropertyNew.h"
#include "CAnimationProperty.h"
#include "CAnimationSetProperty.h"
#include "CArrayProperty.h"
#include "CAssetProperty.h"
#include "CBoolProperty.h"
#include "CByteProperty.h"
#include "CColorProperty.h"
#include "CEnumProperty.h"
#include "CFlagsProperty.h"
#include "CFloatProperty.h"
#include "CGuidProperty.h"
#include "CIntProperty.h"
#include "CPointerProperty.h"
#include "CSequenceProperty.h"
#include "CShortProperty.h"
#include "CSoundProperty.h"
#include "CSplineProperty.h"
#include "CStringProperty.h"
#include "CStructProperty.h"
#include "CVectorProperty.h"
#include "TPropertyRef.h"
#endif // PROPERTIES_H

View File

@@ -0,0 +1,113 @@
#ifndef TPROPERTYREF_H
#define TPROPERTYREF_H
#include "CAnimationProperty.h"
#include "CAnimationSetProperty.h"
#include "CArrayProperty.h"
#include "CAssetProperty.h"
#include "CBoolProperty.h"
#include "CByteProperty.h"
#include "CColorProperty.h"
#include "CEnumProperty.h"
#include "CFlagsProperty.h"
#include "CFloatProperty.h"
#include "CGuidProperty.h"
#include "CIntProperty.h"
#include "CPointerProperty.h"
#include "CSequenceProperty.h"
#include "CShortProperty.h"
#include "CSoundProperty.h"
#include "CSplineProperty.h"
#include "CStringProperty.h"
#include "CStructProperty.h"
#include "CVectorProperty.h"
/** TPropertyRef: Embeds a reference to a property on a specific script object */
template<class PropertyClass, typename ValueType = PropertyClass::ValueType>
class TPropertyRef
{
/** Script object containing the property data being referenced */
CScriptObject* mpObject;
/** Property being referenced */
PropertyClass* mpProperty;
public:
TPropertyRef()
: mpObject(nullptr), mpProperty(nullptr)
{}
TPropertyRef(CScriptObject* pInObject, IPropertyNew* pInProperty)
: mpObject(pInObject), mpProperty( TPropCast<PropertyClass>(pInProperty) )
{
}
TPropertyRef(CScriptObject* pInObject, PropertyClass* pInProperty)
: mpObject(pInObject), mpProperty(pInProperty)
{
}
/** Accessors */
inline CScriptObject* Object() const { return mpObject; }
inline PropertyClass* Property() const { return mpProperty; }
inline ValueType Get() const { ASSERT(IsValid()); return *((ValueType*) mpProperty->RawValuePtr( mpObject->PropertyData() )); }
inline void Set(const ValueType& kIn) const { if (IsValid()) *((ValueType*) mpProperty->RawValuePtr( mpObject->PropertyData() )) = kIn; }
inline bool IsValid() const { return mpObject != nullptr && mpProperty != nullptr; }
/** Inline operators */
inline operator ValueType() const
{
return Get();
}
inline bool operator==(IPropertyNew* pProperty) const
{
return mpProperty == pProperty;
}
friend bool operator==(IPropertyNew* pLeft, const TPropertyRef& kRight)
{
return pLeft == kRight.Property();
}
};
/** Convenience typedefs */
typedef TPropertyRef<CBoolProperty> CBoolRef;
typedef TPropertyRef<CByteProperty> CByteRef;
typedef TPropertyRef<CShortProperty> CShortRef;
typedef TPropertyRef<CIntProperty> CIntRef;
typedef TPropertyRef<CFloatProperty> CFloatRef;
typedef TPropertyRef<CFlagsProperty> CFlagsRef;
typedef TPropertyRef<CStringProperty> CStringRef;
typedef TPropertyRef<CVectorProperty> CVectorRef;
typedef TPropertyRef<CColorProperty> CColorRef;
typedef TPropertyRef<CAssetProperty> CAssetRef;
typedef TPropertyRef<CSoundProperty> CSoundRef;
typedef TPropertyRef<CAnimationProperty> CAnimationRef;
typedef TPropertyRef<CAnimationSetProperty> CAnimationSetRef;
typedef TPropertyRef<CSequenceProperty> CSequenceRef;
typedef TPropertyRef<CSplineProperty> CSplineRef;
typedef TPropertyRef<CGuidProperty> CGuidRef;
typedef TPropertyRef<CPointerProperty> CPointerRef;
typedef TPropertyRef<CStructPropertyNew> CStructRef;
typedef TPropertyRef<CArrayProperty> CArrayRef;
/** Special version for enums */
template<typename ValueType>
class TEnumRef : public TPropertyRef<CEnumProperty, ValueType>
{
public:
TEnumRef()
: TPropertyRef()
{}
TEnumRef(CScriptObject* pInObject, IPropertyNew* pInProperty)
: TPropertyRef(pInObject, pInProperty)
{}
TEnumRef(CScriptObject* pInObject, CEnumProperty* pInProperty)
: TPropertyRef(pInObject, pInProperty)
{}
};
#endif // TPROPERTYREF_H

View File

@@ -0,0 +1,39 @@
#ifndef TPROPERTYPROXY_H
#define TPROPERTYPROXY_H
#include <type_traits>
/**
* Lightweight proxy class representing a property instance. Easy to read/modify
* specific properties and efficient to pass around.
*/
template<class PropertyClass>
class TPropertyProxy
{
typedef PropertyClass::ValueType ValueType;
/** Property data buffer */
void* mpDataPtr;
/** Source property */
PropertyClass* mpProperty;
public:
TPropertyProxy()
: mpDataPtr(nullptr)
, mpProperty(nullptr)
{}
TPropertyProxy(void* pDataPtr, PropertyClass* pProperty)
: mpDataPtr(pDataPtr)
, mpProperty(pProperty)
{}
/** Returns whether this proxy points to a valid property instance */
bool IsValid() const
{
return mpDataPtr != nullptr && mpProperty != nullptr;
}
};
#endif // TPROPERTYPROXY_H