mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-12-15 16:16:14 +00:00
Implemented property name validation system
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
#include "Core/Render/CRenderer.h"
|
||||
#include "Core/OpenGL/GLCommon.h"
|
||||
#include "Core/OpenGL/CShaderGenerator.h"
|
||||
#include <Common/CHashFNV1A.h>
|
||||
#include <Common/Hash/CFNV1A.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <GL/glew.h>
|
||||
@@ -243,7 +243,7 @@ u64 CMaterial::HashParameters()
|
||||
{
|
||||
if (mRecalcHash)
|
||||
{
|
||||
CHashFNV1A Hash(CHashFNV1A::e64Bit);
|
||||
CFNV1A Hash(CFNV1A::e64Bit);
|
||||
|
||||
Hash.HashLong(mVersion);
|
||||
Hash.HashLong(mOptions);
|
||||
|
||||
@@ -58,7 +58,7 @@ CMaterialPass* CMaterialPass::Clone(CMaterial *pParent)
|
||||
return pOut;
|
||||
}
|
||||
|
||||
void CMaterialPass::HashParameters(CHashFNV1A& rHash)
|
||||
void CMaterialPass::HashParameters(CFNV1A& rHash)
|
||||
{
|
||||
if (mEnabled)
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include "ETevEnums.h"
|
||||
#include "Core/Render/FRenderOptions.h"
|
||||
#include <Common/CFourCC.h>
|
||||
#include <Common/CHashFNV1A.h>
|
||||
#include <Common/Hash/CFNV1A.h>
|
||||
|
||||
class CMaterial;
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
CMaterialPass(CMaterial *pParent);
|
||||
~CMaterialPass();
|
||||
CMaterialPass* Clone(CMaterial *pParent);
|
||||
void HashParameters(CHashFNV1A& rHash);
|
||||
void HashParameters(CFNV1A& rHash);
|
||||
void LoadTexture(u32 PassIndex);
|
||||
void SetAnimCurrent(FRenderOptions Options, u32 PassIndex);
|
||||
|
||||
|
||||
@@ -256,6 +256,7 @@ void CTemplateLoader::LoadStructTemplate(const TString& rkTemplateFileName, CStr
|
||||
}
|
||||
}
|
||||
pSource->mSourceFile = rkTemplateFileName;
|
||||
pSource->mTypeName = pSource->mSourceFile.GetFileName(false);
|
||||
|
||||
TString NameAttr = TString(pRootElem->Attribute("name"));
|
||||
if (!NameAttr.IsEmpty())
|
||||
@@ -373,7 +374,13 @@ void CTemplateLoader::LoadEnumerators(XMLElement *pEnumeratorsElem, CEnumTemplat
|
||||
const char *pkName = pChild->Attribute("name");
|
||||
|
||||
if (pkID && pkName)
|
||||
pTemp->mEnumerators.push_back(CEnumTemplate::SEnumerator(pkName, TString(pkID).ToInt32()));
|
||||
{
|
||||
u32 EnumeratorID = TString(pkID).ToInt32();
|
||||
pTemp->mEnumerators.push_back(CEnumTemplate::SEnumerator(pkName, EnumeratorID));
|
||||
|
||||
if (EnumeratorID > 0xFF)
|
||||
pTemp->mUsesHashes = true;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
@@ -28,6 +28,7 @@ enum EPropertyType
|
||||
// functions defined in IPropertyTemplate.cpp
|
||||
EPropertyType PropStringToPropEnum(TString Prop);
|
||||
TString PropEnumToPropString(EPropertyType Prop);
|
||||
const char* HashablePropTypeName(EPropertyType Prop);
|
||||
|
||||
#endif // EPROPERTYTYPE
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "IPropertyTemplate.h"
|
||||
#include "CMasterTemplate.h"
|
||||
#include <Common/Hash/CCRC32.h>
|
||||
#include <iostream>
|
||||
|
||||
// ************ IPropertyTemplate ************
|
||||
@@ -69,6 +70,36 @@ bool IPropertyTemplate::IsFromStructTemplate() const
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IPropertyTemplate::IsNameCorrect() const
|
||||
{
|
||||
// Check whether the property name is correct... i.e., if we hash it, does it match the property ID?
|
||||
// Only valid for Prime 2 and up, since Prime 1 doesn't have real property IDs, so we can't validate names
|
||||
if (Game() >= eEchoesDemo)
|
||||
{
|
||||
// Don't hash for single-property structs
|
||||
if ( (!Parent() || !Parent()->IsSingleProperty()) &&
|
||||
// Don't hash for the three properties in EditorProperties that have fourCC property IDs
|
||||
mID != FOURCC('INAM') &&
|
||||
mID != FOURCC('XFRM') &&
|
||||
mID != FOURCC('ACTV') )
|
||||
{
|
||||
// Only re-hash if we need to. Save the result (output won't change if function is called multiple times)
|
||||
if (!mHasCachedNameCheck)
|
||||
{
|
||||
// The property ID is just a CRC32 of the property name + the type
|
||||
CCRC32 Hash;
|
||||
Hash.Hash(*mName);
|
||||
Hash.Hash(GetTypeNameString());
|
||||
mCachedNameIsCorrect = Hash.Digest() == mID;
|
||||
mHasCachedNameCheck = true;
|
||||
}
|
||||
return mCachedNameIsCorrect;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TString IPropertyTemplate::FindStructSource() const
|
||||
{
|
||||
const CStructTemplate *pkStruct = mpParent;
|
||||
@@ -95,6 +126,7 @@ void CStructTemplate::CopyStructData(const CStructTemplate *pkStruct)
|
||||
mVersionPropertyCounts = pkStruct->mVersionPropertyCounts;
|
||||
mIsSingleProperty = pkStruct->mIsSingleProperty;
|
||||
mSourceFile = pkStruct->mSourceFile;
|
||||
mTypeName = pkStruct->mTypeName;
|
||||
|
||||
mSubProperties.resize(pkStruct->mSubProperties.size());
|
||||
|
||||
@@ -271,6 +303,30 @@ EPropertyType PropStringToPropEnum(TString Prop)
|
||||
return eInvalidProperty;
|
||||
}
|
||||
|
||||
const char* HashablePropTypeName(EPropertyType 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 "bitfield";
|
||||
case eFloatProperty: return "float";
|
||||
case eStringProperty: return "string";
|
||||
case eColorProperty: return "Color";
|
||||
case eVector3Property: return "Vector3f";
|
||||
case eSoundProperty: return "SfxId";
|
||||
case eAssetProperty: return "asset";
|
||||
case eMayaSplineProperty: return "MayaSpline";
|
||||
|
||||
// All other types are either invalid or need a custom reimplementation because they can return multiple strings (like struct)
|
||||
default:
|
||||
ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// ************ DEBUG ************
|
||||
void CStructTemplate::DebugPrintProperties(TString base)
|
||||
{
|
||||
|
||||
@@ -40,6 +40,8 @@ protected:
|
||||
u32 mID;
|
||||
ECookPreference mCookPreference;
|
||||
std::vector<u32> mAllowedVersions;
|
||||
mutable bool mHasCachedNameCheck;
|
||||
mutable bool mCachedNameIsCorrect;
|
||||
|
||||
public:
|
||||
IPropertyTemplate(u32 ID, CScriptTemplate *pScript, CMasterTemplate *pMaster, CStructTemplate *pParent = 0)
|
||||
@@ -49,6 +51,8 @@ public:
|
||||
, mpMasterTemplate(pMaster)
|
||||
, mName("UNSET PROPERTY NAME")
|
||||
, mCookPreference(eNoCookPreference)
|
||||
, mHasCachedNameCheck(false)
|
||||
, mCachedNameIsCorrect(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -59,6 +63,8 @@ public:
|
||||
, mpMasterTemplate(pMaster)
|
||||
, mName(rkName)
|
||||
, mCookPreference(CookPreference)
|
||||
, mHasCachedNameCheck(false)
|
||||
, mCachedNameIsCorrect(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -93,6 +99,7 @@ public:
|
||||
virtual bool HasValidRange() const { return false; }
|
||||
virtual TString RangeToString() const { return ""; }
|
||||
virtual TString Suffix() const { return ""; }
|
||||
virtual const char* GetTypeNameString() const { return HashablePropTypeName(Type()); }
|
||||
|
||||
virtual void SetParam(const TString& rkParamName, const TString& rkValue)
|
||||
{
|
||||
@@ -118,6 +125,7 @@ public:
|
||||
TIDString IDString(bool FullPath) const;
|
||||
bool IsDescendantOf(const CStructTemplate *pStruct) const;
|
||||
bool IsFromStructTemplate() const;
|
||||
bool IsNameCorrect() const;
|
||||
TString FindStructSource() const;
|
||||
CStructTemplate* RootStruct();
|
||||
|
||||
@@ -129,7 +137,7 @@ public:
|
||||
inline CStructTemplate* Parent() const { return mpParent; }
|
||||
inline CScriptTemplate* ScriptTemplate() const { return mpScriptTemplate; }
|
||||
inline CMasterTemplate* MasterTemplate() const { return mpMasterTemplate; }
|
||||
inline void SetName(const TString& rkName) { mName = rkName; }
|
||||
inline void SetName(const TString& rkName) { mName = rkName; mHasCachedNameCheck = false; }
|
||||
inline void SetDescription(const TString& rkDesc) { mDescription = rkDesc; }
|
||||
};
|
||||
|
||||
@@ -302,13 +310,13 @@ public:
|
||||
};
|
||||
|
||||
// Typedefs for all property types that don't need further functionality.
|
||||
typedef TTypedPropertyTemplate<bool, eBoolProperty, CBoolValue, true> TBoolTemplate;
|
||||
typedef TNumericalPropertyTemplate<s8, eByteProperty, CByteValue> TByteTemplate;
|
||||
typedef TNumericalPropertyTemplate<s16, eShortProperty, CShortValue> TShortTemplate;
|
||||
typedef TNumericalPropertyTemplate<s32, eLongProperty, CLongValue> TLongTemplate;
|
||||
typedef TNumericalPropertyTemplate<float, eFloatProperty, CFloatValue> TFloatTemplate;
|
||||
typedef TTypedPropertyTemplate<CVector3f, eVector3Property, CVector3Value, true> TVector3Template;
|
||||
typedef TTypedPropertyTemplate<CColor, eColorProperty, CColorValue, true> TColorTemplate;
|
||||
typedef TTypedPropertyTemplate<bool, eBoolProperty, CBoolValue, true> TBoolTemplate;
|
||||
typedef TNumericalPropertyTemplate<s8, eByteProperty, CByteValue> TByteTemplate;
|
||||
typedef TNumericalPropertyTemplate<s16, eShortProperty, CShortValue> TShortTemplate;
|
||||
typedef TNumericalPropertyTemplate<s32, eLongProperty, CLongValue> TLongTemplate;
|
||||
typedef TNumericalPropertyTemplate<float, eFloatProperty, CFloatValue> TFloatTemplate;
|
||||
typedef TTypedPropertyTemplate<CVector3f, eVector3Property, CVector3Value, true> TVector3Template;
|
||||
typedef TTypedPropertyTemplate<CColor, eColorProperty, CColorValue, true> TColorTemplate;
|
||||
|
||||
// TCharacterTemplate, TSoundTemplate, TStringTemplate, and TMayaSplineTemplate get their own subclasses so they can reimplement a couple functions
|
||||
class TCharacterTemplate : public TTypedPropertyTemplate<CAnimationParameters, eCharacterProperty, CCharacterValue, false>
|
||||
@@ -327,6 +335,13 @@ public:
|
||||
{
|
||||
return new TCharacterProperty(this, pInstance, pParent, CAnimationParameters(Game()));
|
||||
}
|
||||
|
||||
const char* GetTypeNameString() const
|
||||
{
|
||||
return (Game() < eCorruptionProto ? "AnimationParameters" : "CharacterAnimationSet");
|
||||
}
|
||||
|
||||
IMPLEMENT_TEMPLATE_CLONE(TCharacterTemplate)
|
||||
};
|
||||
|
||||
class TSoundTemplate : public TTypedPropertyTemplate<u32, eSoundProperty, CSoundValue, false>
|
||||
@@ -345,6 +360,8 @@ public:
|
||||
{
|
||||
return new TSoundProperty(this, pInstance, pParent, -1);
|
||||
}
|
||||
|
||||
IMPLEMENT_TEMPLATE_CLONE(TSoundTemplate)
|
||||
};
|
||||
|
||||
class TStringTemplate : public TTypedPropertyTemplate<TString, eStringProperty, CStringValue, false>
|
||||
@@ -363,6 +380,8 @@ public:
|
||||
{
|
||||
return new TStringProperty(this, pInstance, pParent);
|
||||
}
|
||||
|
||||
IMPLEMENT_TEMPLATE_CLONE(TStringTemplate)
|
||||
};
|
||||
|
||||
class TMayaSplineTemplate : public TTypedPropertyTemplate<std::vector<u8>, eMayaSplineProperty, CMayaSplineValue, false>
|
||||
@@ -381,6 +400,8 @@ public:
|
||||
{
|
||||
return new TMayaSplineProperty(this, pInstance, pParent);
|
||||
}
|
||||
|
||||
IMPLEMENT_TEMPLATE_CLONE(TMayaSplineTemplate)
|
||||
};
|
||||
|
||||
// CAssetTemplate - Property template for assets. Tracks a list of resource types that
|
||||
@@ -448,15 +469,18 @@ class CEnumTemplate : public TTypedPropertyTemplate<s32, eEnumProperty, CHexLong
|
||||
};
|
||||
std::vector<SEnumerator> mEnumerators;
|
||||
TString mSourceFile;
|
||||
bool mUsesHashes;
|
||||
|
||||
public:
|
||||
CEnumTemplate(u32 ID, CScriptTemplate *pScript, CMasterTemplate *pMaster, CStructTemplate *pParent = 0)
|
||||
: TTypedPropertyTemplate(ID, pScript, pMaster, pParent)
|
||||
, mUsesHashes(false)
|
||||
{
|
||||
}
|
||||
|
||||
CEnumTemplate(u32 ID, const TString& rkName, ECookPreference CookPreference, CScriptTemplate *pScript, CMasterTemplate *pMaster, CStructTemplate *pParent = 0)
|
||||
: TTypedPropertyTemplate(ID, rkName, CookPreference, pScript, pMaster, pParent)
|
||||
, mUsesHashes(false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -480,6 +504,7 @@ public:
|
||||
const CEnumTemplate *pkEnum = static_cast<const CEnumTemplate*>(pkTemp);
|
||||
mEnumerators = pkEnum->mEnumerators;
|
||||
mSourceFile = pkEnum->mSourceFile;
|
||||
mUsesHashes = pkEnum->mUsesHashes;
|
||||
}
|
||||
|
||||
virtual bool Matches(const IPropertyTemplate *pkTemp) const
|
||||
@@ -488,7 +513,13 @@ public:
|
||||
|
||||
return ( (TTypedPropertyTemplate::Matches(pkTemp)) &&
|
||||
(mEnumerators == pkEnum->mEnumerators) &&
|
||||
(mSourceFile == pkEnum->mSourceFile) );
|
||||
(mSourceFile == pkEnum->mSourceFile) &&
|
||||
(mUsesHashes == pkEnum->mUsesHashes) );
|
||||
}
|
||||
|
||||
virtual const char* GetTypeNameString() const
|
||||
{
|
||||
return (mUsesHashes ? "enum" : "choice");
|
||||
}
|
||||
|
||||
inline TString SourceFile() const { return mSourceFile; }
|
||||
@@ -603,6 +634,7 @@ protected:
|
||||
std::vector<u32> mVersionPropertyCounts;
|
||||
bool mIsSingleProperty;
|
||||
TString mSourceFile;
|
||||
TString mTypeName;
|
||||
|
||||
void DetermineVersionPropertyCounts();
|
||||
public:
|
||||
@@ -656,7 +688,8 @@ public:
|
||||
if ( (IPropertyTemplate::Matches(pkTemp)) &&
|
||||
(mVersionPropertyCounts == pkStruct->mVersionPropertyCounts) &&
|
||||
(mIsSingleProperty == pkStruct->mIsSingleProperty) &&
|
||||
(mSourceFile == pkStruct->mSourceFile) )
|
||||
(mSourceFile == pkStruct->mSourceFile) &&
|
||||
(mTypeName == pkStruct->mTypeName) )
|
||||
{
|
||||
return StructDataMatches(pkStruct);
|
||||
}
|
||||
@@ -664,6 +697,12 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* GetTypeNameString() const
|
||||
{
|
||||
// hack - currently templates embedded within another XML can't have a type name
|
||||
return mTypeName.IsEmpty() ? *mName : *mTypeName;
|
||||
}
|
||||
|
||||
bool StructDataMatches(const CStructTemplate *pkStruct) const
|
||||
{
|
||||
if ( (mIsSingleProperty == pkStruct->mIsSingleProperty) &&
|
||||
|
||||
Reference in New Issue
Block a user