Property cleanup

This commit is contained in:
Aruki
2018-09-22 13:36:50 -06:00
parent e68b961a8c
commit 31dac74a64
97 changed files with 287 additions and 3319 deletions

View File

@@ -5,7 +5,7 @@
#include <Core/Resource/Script/Property/CEnumProperty.h>
#include <Core/Resource/Script/Property/CFlagsProperty.h>
void CScriptCooker::WriteProperty(IOutputStream& rOut, IPropertyNew* pProperty, bool InAtomicStruct)
void CScriptCooker::WriteProperty(IOutputStream& rOut, IProperty* pProperty, bool InAtomicStruct)
{
u32 SizeOffset = 0, PropStart = 0;
void* pData = (mpArrayItemData ? mpArrayItemData : mpObject->PropertyData());
@@ -21,118 +21,118 @@ void CScriptCooker::WriteProperty(IOutputStream& rOut, IPropertyNew* pProperty,
switch (pProperty->Type())
{
case EPropertyTypeNew::Bool:
case EPropertyType::Bool:
{
CBoolProperty* pBool = TPropCast<CBoolProperty>(pProperty);
rOut.WriteBool( pBool->Value(pData) );
break;
}
case EPropertyTypeNew::Byte:
case EPropertyType::Byte:
{
CByteProperty* pByte = TPropCast<CByteProperty>(pProperty);
rOut.WriteByte( pByte->Value(pData) );
break;
}
case EPropertyTypeNew::Short:
case EPropertyType::Short:
{
CShortProperty* pShort = TPropCast<CShortProperty>(pProperty);
rOut.WriteShort( pShort->Value(pData) );
break;
}
case EPropertyTypeNew::Int:
case EPropertyType::Int:
{
CIntProperty* pInt = TPropCast<CIntProperty>(pProperty);
rOut.WriteLong( pInt->Value(pData) );
break;
}
case EPropertyTypeNew::Float:
case EPropertyType::Float:
{
CFloatProperty* pFloat = TPropCast<CFloatProperty>(pProperty);
rOut.WriteFloat( pFloat->Value(pData) );
break;
}
case EPropertyTypeNew::Choice:
case EPropertyType::Choice:
{
CChoiceProperty* pChoice = TPropCast<CChoiceProperty>(pProperty);
rOut.WriteLong( pChoice->Value(pData) );
break;
}
case EPropertyTypeNew::Enum:
case EPropertyType::Enum:
{
CEnumProperty* pEnum = TPropCast<CEnumProperty>(pProperty);
rOut.WriteLong( pEnum->Value(pData) );
break;
}
case EPropertyTypeNew::Flags:
case EPropertyType::Flags:
{
CFlagsProperty* pFlags = TPropCast<CFlagsProperty>(pProperty);
rOut.WriteLong( pFlags->Value(pData) );
break;
}
case EPropertyTypeNew::String:
case EPropertyType::String:
{
CStringProperty* pString = TPropCast<CStringProperty>(pProperty);
rOut.WriteString( pString->Value(pData) );
break;
}
case EPropertyTypeNew::Vector:
case EPropertyType::Vector:
{
CVectorProperty* pVector = TPropCast<CVectorProperty>(pProperty);
pVector->ValueRef(pData).Write(rOut);
break;
}
case EPropertyTypeNew::Color:
case EPropertyType::Color:
{
CColorProperty* pColor = TPropCast<CColorProperty>(pProperty);
pColor->ValueRef(pData).Write(rOut);
break;
}
case EPropertyTypeNew::Asset:
case EPropertyType::Asset:
{
CAssetProperty* pAsset = TPropCast<CAssetProperty>(pProperty);
pAsset->ValueRef(pData).Write(rOut);
break;
}
case EPropertyTypeNew::Sound:
case EPropertyType::Sound:
{
CSoundProperty* pSound = TPropCast<CSoundProperty>(pProperty);
rOut.WriteLong( pSound->Value(pData) );
break;
}
case EPropertyTypeNew::Animation:
case EPropertyType::Animation:
{
CAnimationProperty* pAnim = TPropCast<CAnimationProperty>(pProperty);
rOut.WriteLong( pAnim->Value(pData) );
break;
}
case EPropertyTypeNew::AnimationSet:
case EPropertyType::AnimationSet:
{
CAnimationSetProperty* pAnimSet = TPropCast<CAnimationSetProperty>(pProperty);
pAnimSet->ValueRef(pData).Write(rOut);
break;
}
case EPropertyTypeNew::Sequence:
case EPropertyType::Sequence:
{
// TODO
break;
}
case EPropertyTypeNew::Spline:
case EPropertyType::Spline:
{
CSplineProperty* pSpline = TPropCast<CSplineProperty>(pProperty);
std::vector<char>& rBuffer = pSpline->ValueRef(pData);
@@ -163,7 +163,7 @@ void CScriptCooker::WriteProperty(IOutputStream& rOut, IPropertyNew* pProperty,
break;
}
case EPropertyTypeNew::Guid:
case EPropertyType::Guid:
{
CGuidProperty* pGuid = TPropCast<CGuidProperty>(pProperty);
std::vector<char>& rBuffer = pGuid->ValueRef(pData);
@@ -175,14 +175,14 @@ void CScriptCooker::WriteProperty(IOutputStream& rOut, IPropertyNew* pProperty,
break;
}
case EPropertyTypeNew::Struct:
case EPropertyType::Struct:
{
CStructPropertyNew* pStruct = TPropCast<CStructPropertyNew>(pProperty);
std::vector<IPropertyNew*> PropertiesToWrite;
CStructProperty* pStruct = TPropCast<CStructProperty>(pProperty);
std::vector<IProperty*> PropertiesToWrite;
for (u32 ChildIdx = 0; ChildIdx < pStruct->NumChildren(); ChildIdx++)
{
IPropertyNew *pChild = pStruct->ChildByIndex(ChildIdx);
IProperty *pChild = pStruct->ChildByIndex(ChildIdx);
if (pStruct->IsAtomic() || pChild->ShouldCook(pData))
PropertiesToWrite.push_back(pChild);
@@ -202,7 +202,7 @@ void CScriptCooker::WriteProperty(IOutputStream& rOut, IPropertyNew* pProperty,
break;
}
case EPropertyTypeNew::Array:
case EPropertyType::Array:
{
CArrayProperty* pArray = TPropCast<CArrayProperty>(pProperty);
u32 Count = pArray->ArrayCount(pData);

View File

@@ -15,7 +15,7 @@ class CScriptCooker
std::vector<CScriptObject*> mGeneratedObjects;
bool mWriteGeneratedSeparately;
void WriteProperty(IOutputStream& rOut, IPropertyNew* pProperty, bool InAtomicStruct);
void WriteProperty(IOutputStream& rOut, IProperty* pProperty, bool InAtomicStruct);
public:
CScriptCooker(EGame Game, bool WriteGeneratedObjectsSeparately = true)

View File

@@ -1,844 +0,0 @@
#include "CTemplateWriter.h"
#include "CAreaCooker.h"
#include <Common/FileUtil.h>
#include <Core/Resource/Script/IPropertyTemplate.h>
#include <tinyxml2.h>
#if 0
using namespace tinyxml2;
TString CTemplateWriter::smTemplatesDir = "../templates/";
CTemplateWriter::CTemplateWriter()
{
}
void CTemplateWriter::SavePropertyTemplate(IPropertyTemplate *pTemp)
{
// Check for a source file in the template's hierarchy; that indicates it's part of a struct template, not a script template
TString SourceFile = pTemp->FindStructSource();
// Struct
if (!SourceFile.IsEmpty())
{
CMasterTemplate *pMaster = pTemp->MasterTemplate();
auto StructIt = pMaster->mStructTemplates.find(SourceFile);
if (StructIt != pMaster->mStructTemplates.end())
{
CStructTemplate *pStruct = StructIt->second;
CTemplateWriter::SaveStructTemplate(pStruct);
}
}
// Script
else if (pTemp->ScriptTemplate())
CTemplateWriter::SaveScriptTemplate(pTemp->ScriptTemplate());
// Error
else
Log::Error("Couldn't save property template " + pTemp->IDString(true) + "; no struct template source path or script template found");
}
void CTemplateWriter::SaveAllTemplates()
{
// Create directory
std::list<CMasterTemplate*> MasterList = CMasterTemplate::MasterList();
FileUtil::MakeDirectory(smTemplatesDir);
// Resave property list
SavePropertyList();
// Resave master templates
for (auto it = MasterList.begin(); it != MasterList.end(); it++)
SaveGameTemplates(*it);
// Resave game list
XMLDocument GameList;
XMLDeclaration *pDecl = GameList.NewDeclaration();
GameList.LinkEndChild(pDecl);
XMLElement *pBase = GameList.NewElement("GameList");
pBase->SetAttribute("version", 4);
GameList.LinkEndChild(pBase);
XMLElement *pProperties = GameList.NewElement("properties");
pProperties->SetText("Properties.xml");
pBase->LinkEndChild(pProperties);
for (auto it = MasterList.begin(); it != MasterList.end(); it++)
{
CMasterTemplate *pMaster = *it;
XMLElement *pGame = GameList.NewElement("game");
pBase->LinkEndChild(pGame);
XMLElement *pGameName = GameList.NewElement("name");
pGameName->SetText(*pMaster->mGameName);
pGame->LinkEndChild(pGameName);
XMLElement *pAreaVersion = GameList.NewElement("mrea");
u32 VersionNumber = CAreaCooker::GetMREAVersion(pMaster->Game());
pAreaVersion->SetText(*TString::HexString(VersionNumber, 2));
pGame->LinkEndChild(pAreaVersion);
XMLElement *pTempPath = GameList.NewElement("master");
pTempPath->SetText(*pMaster->mSourceFile);
pGame->LinkEndChild(pTempPath);
}
TString GameListName = smTemplatesDir + "GameList.xml";
GameList.SaveFile(*GameListName);
}
void CTemplateWriter::SaveGameTemplates(CMasterTemplate *pMaster)
{
// Create directory
TString OutFile = smTemplatesDir + pMaster->mSourceFile;
TString OutDir = OutFile.GetFileDirectory();
FileUtil::MakeDirectory(OutDir);
// Resave script templates
for (auto it = pMaster->mTemplates.begin(); it != pMaster->mTemplates.end(); it++)
SaveScriptTemplate(it->second);
// Resave struct templates
for (auto it = pMaster->mStructTemplates.begin(); it != pMaster->mStructTemplates.end(); it++)
SaveStructTemplate(it->second);
// Resave master template
XMLDocument Master;
XMLDeclaration *pDecl = Master.NewDeclaration();
Master.LinkEndChild(pDecl);
XMLElement *pBase = Master.NewElement("MasterTemplate");
pBase->SetAttribute("version", 4);
Master.LinkEndChild(pBase);
// Write versions
if (!pMaster->mGameVersions.empty())
{
XMLElement *pVersionsBlock = Master.NewElement("versions");
pBase->LinkEndChild(pVersionsBlock);
for (auto it = pMaster->mGameVersions.begin(); it != pMaster->mGameVersions.end(); it++)
{
XMLElement *pVersion = Master.NewElement("version");
pVersion->SetText(*(*it));
pVersionsBlock->LinkEndChild(pVersion);
}
}
// Write script objects
XMLElement *pObjects = Master.NewElement("objects");
pBase->LinkEndChild(pObjects);
for (auto it = pMaster->mTemplates.begin(); it != pMaster->mTemplates.end(); it++)
{
u32 ObjID = (it->second)->ObjectID();
TString StrID;
if (ObjID <= 0xFF)
StrID = TString::HexString(ObjID, 2);
else
StrID = CFourCC(ObjID).ToString();
XMLElement *pObj = Master.NewElement("object");
pObj->SetAttribute("ID", *StrID);
pObj->SetAttribute("template", *(it->second)->mSourceFile);
pObjects->LinkEndChild(pObj);
}
// Write script states/messages
for (u32 iType = 0; iType < 2; iType++)
{
TString Type = (iType == 0 ? "state" : "message");
XMLElement *pElem = Master.NewElement(*(Type + "s"));
pBase->LinkEndChild(pElem);
u32 Num = (iType == 0 ? pMaster->NumStates() : pMaster->NumMessages());
for (u32 iScr = 0; iScr < Num; iScr++)
{
u32 ID;
TString Name;
if (iType == 0)
{
SState State = pMaster->StateByIndex(iScr);
ID = State.ID;
Name = State.Name;
}
else
{
SMessage Message = pMaster->MessageByIndex(iScr);
ID = Message.ID;
Name = Message.Name;
}
TString StrID;
if (ID <= 0xFF) StrID = TString::HexString(ID, 2);
else StrID = CFourCC(ID).ToString();
XMLElement *pSubElem = Master.NewElement(*Type);
pSubElem->SetAttribute("ID", *StrID);
pSubElem->SetAttribute("name", *Name);
pElem->LinkEndChild(pSubElem);
}
}
// Save file
Master.SaveFile(*OutFile);
}
void CTemplateWriter::SavePropertyList()
{
// Create XML
XMLDocument List;
XMLDeclaration *pDecl = List.NewDeclaration();
List.LinkEndChild(pDecl);
XMLElement *pBase = List.NewElement("Properties");
pBase->SetAttribute("version", 4);
List.LinkEndChild(pBase);
// Write properties
for (auto it = CMasterTemplate::smPropertyNames.begin(); it != CMasterTemplate::smPropertyNames.end(); it++)
{
u32 ID = it->first;
TString Name = it->second;
XMLElement *pElem = List.NewElement("property");
pElem->SetAttribute("ID", *TString::HexString(ID));
pElem->SetAttribute("name", *Name);
pBase->LinkEndChild(pElem);
}
TString OutFile = smTemplatesDir + "Properties.xml";
List.SaveFile(*OutFile);
}
void CTemplateWriter::SaveScriptTemplate(CScriptTemplate *pTemp)
{
CMasterTemplate *pMaster = pTemp->MasterTemplate();
// Create directory
TString OutFile = smTemplatesDir + pMaster->GetDirectory() + pTemp->mSourceFile;
TString OutDir = OutFile.GetFileDirectory();
FileUtil::MakeDirectory(*OutDir);
// Create new document
XMLDocument ScriptXML;
XMLDeclaration *pDecl = ScriptXML.NewDeclaration();
ScriptXML.LinkEndChild(pDecl);
// Base element
XMLElement *pRoot = ScriptXML.NewElement("ScriptTemplate");
pRoot->SetAttribute("version", 4);
ScriptXML.LinkEndChild(pRoot);
// Write object name
XMLElement *pName = ScriptXML.NewElement("name");
pName->SetText(*pTemp->Name());
pRoot->LinkEndChild(pName);
// Write modules
if (!pTemp->mModules.empty())
{
XMLElement *pModules = ScriptXML.NewElement("modules");
pRoot->LinkEndChild(pModules);
for (u32 iMod = 0; iMod < pTemp->mModules.size(); iMod++)
{
XMLElement *pModule = ScriptXML.NewElement("module");
pModule->SetText(*pTemp->mModules[iMod]);
pModules->LinkEndChild(pModule);
}
}
// Write properties
SaveProperties(&ScriptXML, pRoot, pTemp->mpBaseStruct);
// States/Messages [todo]
XMLElement *pStates = ScriptXML.NewElement("states");
pRoot->LinkEndChild(pStates);
XMLElement *pMessages = ScriptXML.NewElement("messages");
pRoot->LinkEndChild(pMessages);
// Write editor properties
XMLElement *pEditor = ScriptXML.NewElement("editor");
pRoot->LinkEndChild(pEditor);
// Editor Properties
XMLElement *pEditorProperties = ScriptXML.NewElement("properties");
pEditor->LinkEndChild(pEditorProperties);
TString PropNames[6] = {
"InstanceName", "Position", "Rotation",
"Scale", "Active", "LightParameters"
};
TIDString *pPropStrings[6] = {
&pTemp->mNameIDString, &pTemp->mPositionIDString, &pTemp->mRotationIDString,
&pTemp->mScaleIDString, &pTemp->mActiveIDString, &pTemp->mLightParametersIDString
};
for (u32 iProp = 0; iProp < 6; iProp++)
{
if (!pPropStrings[iProp]->IsEmpty())
{
XMLElement *pProperty = ScriptXML.NewElement("property");
pProperty->SetAttribute("name", *PropNames[iProp]);
pProperty->SetAttribute("ID", **pPropStrings[iProp]);
pEditorProperties->LinkEndChild(pProperty);
}
}
// Editor Assets
XMLElement *pAssets = ScriptXML.NewElement("assets");
pEditor->LinkEndChild(pAssets);
for (auto it = pTemp->mAssets.begin(); it != pTemp->mAssets.end(); it++)
{
TString Source = (it->AssetSource == CScriptTemplate::SEditorAsset::eFile ? "file" : "property");
TString Type;
switch (it->AssetType)
{
case CScriptTemplate::SEditorAsset::eModel: Type = "model"; break;
case CScriptTemplate::SEditorAsset::eAnimParams: Type = "animparams"; break;
case CScriptTemplate::SEditorAsset::eBillboard: Type = "billboard"; break;
case CScriptTemplate::SEditorAsset::eCollision: Type = "collision"; break;
}
s32 Force = -1;
if (it->AssetType == CScriptTemplate::SEditorAsset::eAnimParams)
Force = it->ForceNodeIndex;
XMLElement *pAsset = ScriptXML.NewElement(*Type);
pAsset->SetAttribute("source", *Source);
if (Force >= 0) pAsset->SetAttribute("force", *TString::FromInt32(Force, 0, 10));
pAsset->SetText(*it->AssetLocation);
pAssets->LinkEndChild(pAsset);
}
// Attachments
if (!pTemp->mAttachments.empty())
{
XMLElement *pAttachments = ScriptXML.NewElement("attachments");
pEditor->LinkEndChild(pAttachments);
for (auto it = pTemp->mAttachments.begin(); it != pTemp->mAttachments.end(); it++)
{
XMLElement *pAttachment = ScriptXML.NewElement("attachment");
pAttachment->SetAttribute("propertyID", *it->AttachProperty);
pAttachment->SetAttribute("locator", *it->LocatorName);
pAttachments->LinkEndChild(pAttachment);
// Sub-properties
if (it->AttachType != eAttach)
{
XMLElement *pAttachType = ScriptXML.NewElement("attach_type");
pAttachType->SetText("follow");
pAttachment->LinkEndChild(pAttachType);
}
}
}
// Preview Scale
if (pTemp->mPreviewScale != 1.f)
{
XMLElement *pPreviewScale = ScriptXML.NewElement("preview_scale");
pPreviewScale->SetText(*TString::FromFloat(pTemp->mPreviewScale));
pEditor->LinkEndChild(pPreviewScale);
}
// Rot/Scale Type
XMLElement *pRotType = ScriptXML.NewElement("rotation_type");
pEditor->LinkEndChild(pRotType);
pRotType->SetText(pTemp->mRotationType == CScriptTemplate::eRotationEnabled ? "enabled" : "disabled");
XMLElement *pScaleType = ScriptXML.NewElement("scale_type");
pEditor->LinkEndChild(pScaleType);
if (pTemp->mScaleType != CScriptTemplate::eScaleVolume)
pScaleType->SetText(pTemp->mScaleType == CScriptTemplate::eScaleEnabled ? "enabled" : "disabled");
else
{
pScaleType->SetText("volume");
// Volume Preview
XMLElement *pVolume = ScriptXML.NewElement("preview_volume");
pEditor->LinkEndChild(pVolume);
// Enum -> String conversion lambda to avoid redundant code
auto GetVolumeString = [](EVolumeShape shape) -> TString
{
switch (shape)
{
case eBoxShape: return "Box";
case eAxisAlignedBoxShape: return "AxisAlignedBox";
case eEllipsoidShape: return "Ellipsoid";
case eCylinderShape: return "Cylinder";
case eConditionalShape: return "Conditional";
default: return "INVALID";
}
};
pVolume->SetAttribute("shape", *GetVolumeString(pTemp->mVolumeShape));
if (pTemp->mVolumeScale != 1.f)
pVolume->SetAttribute("scale", pTemp->mVolumeScale);
if (pTemp->mVolumeShape == eConditionalShape)
{
pVolume->SetAttribute("propertyID", *pTemp->mVolumeConditionIDString);
// Find conditional test property
IPropertyTemplate *pProp = pTemp->mpBaseStruct->PropertyByIDString(pTemp->mVolumeConditionIDString);
// Write conditions
for (auto it = pTemp->mVolumeConditions.begin(); it != pTemp->mVolumeConditions.end(); it++)
{
// Value should be an integer, or a boolean condition
TString StrVal;
if (pProp->Type() == eBoolProperty)
StrVal = (it->Value == 1 ? "true" : "false");
else
StrVal = TString::HexString((u32) it->Value, (it->Value > 0xFF ? 8 : 2));
XMLElement *pCondition = ScriptXML.NewElement("condition");
pCondition->SetAttribute("value", *StrVal);
pCondition->SetAttribute("shape", *GetVolumeString(it->Shape));
if (it->Scale != 1.f) pCondition->SetAttribute("scale", it->Scale);
pVolume->LinkEndChild(pCondition);
}
}
}
// Write to file
ScriptXML.SaveFile(*OutFile);
}
void CTemplateWriter::SaveStructTemplate(CStructTemplate *pTemp)
{
// Create directory
CMasterTemplate *pMaster = pTemp->MasterTemplate();
TString OutFile = smTemplatesDir + pMaster->GetDirectory() + pTemp->mSourceFile;
TString OutDir = OutFile.GetFileDirectory();
TString Name = OutFile.GetFileName(false);
FileUtil::MakeDirectory(OutDir);
// Create new document and write struct properties to it
XMLDocument StructXML;
XMLDeclaration *pDecl = StructXML.NewDeclaration();
StructXML.LinkEndChild(pDecl);
XMLElement *pRoot = StructXML.NewElement("struct");
pRoot->SetAttribute("name", *Name);
pRoot->SetAttribute("type", (pTemp->IsSingleProperty() ? "single" : "multi"));
StructXML.LinkEndChild(pRoot);
SaveProperties(&StructXML, pRoot, pTemp);
StructXML.SaveFile(*OutFile);
}
void CTemplateWriter::SaveEnumTemplate(CEnumTemplate *pTemp)
{
// Create directory
CMasterTemplate *pMaster = pTemp->MasterTemplate();
TString OutFile = smTemplatesDir + pMaster->GetDirectory() + pTemp->mSourceFile;
TString OutDir = OutFile.GetFileDirectory();
TString Name = OutFile.GetFileName(false);
FileUtil::MakeDirectory(OutDir);
// Create new document and write enumerators to it
XMLDocument EnumXML;
XMLDeclaration *pDecl = EnumXML.NewDeclaration();
EnumXML.LinkEndChild(pDecl);
XMLElement *pRoot = EnumXML.NewElement("enum");
pRoot->SetAttribute("name", *Name);
EnumXML.LinkEndChild(pRoot);
SaveEnumerators(&EnumXML, pRoot, pTemp);
EnumXML.SaveFile(*OutFile);
}
void CTemplateWriter::SaveBitfieldTemplate(CBitfieldTemplate *pTemp)
{
// Create directory
CMasterTemplate *pMaster = pTemp->MasterTemplate();
TString OutFile = smTemplatesDir + pMaster->GetDirectory() + pTemp->mSourceFile;
TString OutDir = OutFile.GetFileDirectory();
TString Name = pTemp->mSourceFile.GetFileName(false);
FileUtil::MakeDirectory(OutDir);
// Create new document and write enumerators to it
XMLDocument BitfieldXML;
XMLDeclaration *pDecl = BitfieldXML.NewDeclaration();
BitfieldXML.LinkEndChild(pDecl);
XMLElement *pRoot = BitfieldXML.NewElement("bitfield");
pRoot->SetAttribute("name", *Name);
BitfieldXML.LinkEndChild(pRoot);
SaveBitFlags(&BitfieldXML, pRoot, pTemp);
BitfieldXML.SaveFile(*OutFile);
}
void CTemplateWriter::SaveProperties(XMLDocument *pDoc, XMLElement *pParent, CStructTemplate *pTemp)
{
// Create base element
XMLElement *pPropsBlock = pDoc->NewElement("properties");
pParent->LinkEndChild(pPropsBlock);
for (u32 iProp = 0; iProp < pTemp->Count(); iProp++)
{
// Get ID
IPropertyTemplate *pProp = pTemp->PropertyByIndex(iProp);
u32 ID = pProp->PropertyID();
TString StrID = TString::HexString(ID, (ID > 0xFF ? 8 : 2));
// Create element
XMLElement *pElem;
if (pProp->Type() == eStructProperty)
pElem = pDoc->NewElement("struct");
else if (pProp->Type() == eEnumProperty)
pElem = pDoc->NewElement("enum");
else if (pProp->Type() == eBitfieldProperty)
pElem = pDoc->NewElement("bitfield");
else if (pProp->Type() == eArrayProperty)
pElem = pDoc->NewElement("array");
else
pElem = pDoc->NewElement("property");
pPropsBlock->LinkEndChild(pElem);
// Set common property parameters, starting with ID
pElem->SetAttribute("ID", *StrID);
// Name
TString Name = pProp->Name();
if (pProp->Game() >= eEchoesDemo && ID > 0xFF)
{
TString MasterName = CMasterTemplate::PropertyName(ID);
if (Name != MasterName)
pElem->SetAttribute("name", *Name);
}
else
pElem->SetAttribute("name", *Name);
// Type
if (pProp->Type() == eStructProperty)
{
CStructTemplate *pStruct = static_cast<CStructTemplate*>(pProp);
if (pStruct->mSourceFile.IsEmpty())
pElem->SetAttribute("type", (pStruct->mIsSingleProperty ? "single" : "multi"));
}
else if (TString(pElem->Name()) == "property")
pElem->SetAttribute("type", *PropEnumToPropString(pProp->Type()));
// Versions
CMasterTemplate *pMaster = pProp->MasterTemplate();
u32 NumVersions = pProp->mAllowedVersions.size();
if (NumVersions > 0 && NumVersions != pMaster->mGameVersions.size())
{
XMLElement *pVersions = pDoc->NewElement("versions");
pElem->LinkEndChild(pVersions);
for (u32 iVer = 0; iVer < pMaster->mGameVersions.size(); iVer++)
{
if (pProp->IsInVersion(iVer))
{
XMLElement *pVersion = pDoc->NewElement("version");
pVersion->SetText(*pMaster->mGameVersions[iVer]);
pVersions->LinkEndChild(pVersion);
}
}
}
// Default
if (pProp->CanHaveDefault() && pProp->Game() >= eEchoesDemo)
{
XMLElement *pDefault = pDoc->NewElement("default");
pDefault->SetText(*pProp->DefaultToString());
pElem->LinkEndChild(pDefault);
}
// Description
if (!pProp->Description().IsEmpty())
{
XMLElement *pDesc = pDoc->NewElement("description");
pDesc->SetText(*pProp->Description());
pElem->LinkEndChild(pDesc);
}
// Range
if (pProp->IsNumerical() && pProp->HasValidRange())
{
XMLElement *pRange = pDoc->NewElement("range");
pRange->SetText(*pProp->RangeToString());
pElem->LinkEndChild(pRange);
}
// Suffix
if (pProp->IsNumerical())
{
TString Suffix = pProp->Suffix();
if (!Suffix.IsEmpty())
{
XMLElement *pSuffix = pDoc->NewElement("suffix");
pSuffix->SetText(*Suffix);
pElem->LinkEndChild(pSuffix);
}
}
// Cook Pref
ECookPreference CookPref = pProp->CookPreference();
if (CookPref != eNoCookPreference)
{
XMLElement *pCookPref = pDoc->NewElement("cook_pref");
pCookPref->SetText(CookPref == eAlwaysCook ? "always" : "never");
pElem->LinkEndChild(pCookPref);
}
// Asset-specific parameters
if (pProp->Type() == eAssetProperty)
{
CAssetTemplate *pAsset = static_cast<CAssetTemplate*>(pProp);
const CResTypeFilter& rkFilter = pAsset->TypeFilter();
TString ExtensionsString = rkFilter.ToString();
if (ExtensionsString.IsEmpty()) ExtensionsString = "UNKN";
pElem->SetAttribute("extensions", *ExtensionsString);
}
// Enum-specific parameters
else if (pProp->Type() == eEnumProperty)
{
CEnumTemplate *pEnum = static_cast<CEnumTemplate*>(pProp);
if (pEnum->mSourceFile.IsEmpty())
SaveEnumerators(pDoc, pElem, pEnum);
else
{
SaveEnumTemplate(pEnum);
pElem->SetAttribute("template", *pEnum->mSourceFile);
}
}
// Bitfield-specific parameters
else if (pProp->Type() == eBitfieldProperty)
{
CBitfieldTemplate *pBitfield = static_cast<CBitfieldTemplate*>(pProp);
if (pBitfield->mSourceFile.IsEmpty())
SaveBitFlags(pDoc, pElem, pBitfield);
else
{
SaveBitfieldTemplate(pBitfield);
pElem->SetAttribute("template", *pBitfield->mSourceFile);
}
}
// Struct/array-specific parameters
else if (pProp->Type() == eStructProperty || pProp->Type() == eArrayProperty)
{
// Element Name
if (pProp->Type() == eArrayProperty)
{
CArrayTemplate *pArray = static_cast<CArrayTemplate*>(pProp);
if (!pArray->ElementName().IsEmpty())
{
XMLElement *pElement = pDoc->NewElement("element_name");
pElement->SetText(*static_cast<CArrayTemplate*>(pProp)->ElementName());
pElem->LinkEndChild(pElement);
}
}
// Sub-properties
CStructTemplate *pStruct = static_cast<CStructTemplate*>(pProp);
if (pStruct->mSourceFile.IsEmpty())
SaveProperties(pDoc, pElem, pStruct);
else
{
CStructTemplate *pOriginal = pMaster->StructAtSource(pStruct->mSourceFile);
if (pOriginal)
SavePropertyOverrides(pDoc, pElem, pStruct, pOriginal);
pElem->SetAttribute("template", *pStruct->mSourceFile);
}
}
}
}
void CTemplateWriter::SavePropertyOverrides(XMLDocument *pDoc, XMLElement *pParent, CStructTemplate *pStruct, CStructTemplate *pOriginal)
{
if (!pStruct->StructDataMatches(pOriginal))
{
// Create base element
XMLElement *pPropsBlock = pDoc->NewElement("properties");
pParent->LinkEndChild(pPropsBlock);
for (u32 iProp = 0; iProp < pStruct->Count(); iProp++)
{
IPropertyTemplate *pProp = pStruct->PropertyByIndex(iProp);
IPropertyTemplate *pSource = pOriginal->PropertyByIndex(iProp);
if (!pProp->Matches(pSource))
{
// Create element
XMLElement *pElem;
if (pProp->Type() == eStructProperty)
pElem = pDoc->NewElement("struct");
else if (pProp->Type() == eEnumProperty)
pElem = pDoc->NewElement("enum");
else if (pProp->Type() == eBitfieldProperty)
pElem = pDoc->NewElement("bitfield");
else if (pProp->Type() == eArrayProperty)
pElem = pDoc->NewElement("array");
else
pElem = pDoc->NewElement("property");
pPropsBlock->LinkEndChild(pElem);
// ID
u32 ID = pProp->PropertyID();
pElem->SetAttribute("ID", *TString::HexString(pProp->PropertyID(), (ID > 0xFF ? 8 : 2)));
// Name
if (pProp->Name() != pSource->Name())
pElem->SetAttribute("name", *pProp->Name());
// Default
if (pProp->CanHaveDefault() && !pProp->RawDefaultValue()->Matches(pSource->RawDefaultValue()))
{
XMLElement *pDefault = pDoc->NewElement("default");
pDefault->SetText(*pProp->DefaultToString());
pElem->LinkEndChild(pDefault);
}
// Description
if (pProp->Description() != pSource->Description())
{
XMLElement *pDesc = pDoc->NewElement("description");
pDesc->SetText(*pProp->Description());
pElem->LinkEndChild(pDesc);
}
// Range
if (pProp->IsNumerical())
{
TString Range = pProp->RangeToString();
if (Range != pSource->RangeToString())
{
XMLElement *pRange = pDoc->NewElement("range");
pRange->SetText(*Range);
pElem->LinkEndChild(pRange);
}
}
// Suffix
if (pProp->Suffix() != pSource->Suffix())
{
XMLElement *pSuffix = pDoc->NewElement("suffix");
pSuffix->SetText(*pProp->Suffix());
pElem->LinkEndChild(pSuffix);
}
// Cook Pref
if (pProp->CookPreference() != pSource->CookPreference())
{
XMLElement *pCookPref = pDoc->NewElement("cook_pref");
TString PrefStr;
if (pProp->CookPreference() == eAlwaysCook) PrefStr = "always";
else if (pProp->CookPreference() == eNeverCook) PrefStr = "never";
else PrefStr = "none";
pCookPref->SetText(*PrefStr);
pElem->LinkEndChild(pCookPref);
}
// Asset-specific parameters
if (pProp->Type() == eAssetProperty)
{
CAssetTemplate *pAsset = static_cast<CAssetTemplate*>(pProp);
CAssetTemplate *pSourceAsset = static_cast<CAssetTemplate*>(pSource);
if (pAsset->TypeFilter() != pSourceAsset->TypeFilter())
{
TString ExtensionsString = pAsset->TypeFilter().ToString();
if (ExtensionsString.IsEmpty()) ExtensionsString = "UNKN";
pElem->SetAttribute("extensions", *ExtensionsString);
}
}
// Struct/array-specific parameters
else if (pProp->Type() == eStructProperty || pProp->Type() == eArrayProperty)
{
CStructTemplate *pChildStruct = static_cast<CStructTemplate*>(pProp);
CStructTemplate *pSourceStruct = static_cast<CStructTemplate*>(pSource);
SavePropertyOverrides(pDoc, pElem, pChildStruct, pSourceStruct);
}
}
}
}
}
void CTemplateWriter::SaveEnumerators(XMLDocument *pDoc, XMLElement *pParent, CEnumTemplate *pTemp)
{
XMLElement *pEnumerators = pDoc->NewElement("enumerators");
pParent->LinkEndChild(pEnumerators);
for (u32 iEnum = 0; iEnum < pTemp->NumEnumerators(); iEnum++)
{
XMLElement *pElem = pDoc->NewElement("enumerator");
u32 EnumerID = pTemp->EnumeratorID(iEnum);
pElem->SetAttribute("ID", *TString::HexString(EnumerID, (EnumerID > 0xFF ? 8 : 2)));
pElem->SetAttribute("name", *pTemp->EnumeratorName(iEnum));
pEnumerators->LinkEndChild(pElem);
}
}
void CTemplateWriter::SaveBitFlags(XMLDocument *pDoc, XMLElement *pParent, CBitfieldTemplate *pTemp)
{
XMLElement *pFlags = pDoc->NewElement("flags");
pParent->LinkEndChild(pFlags);
for (u32 iFlag = 0; iFlag < pTemp->NumFlags(); iFlag++)
{
XMLElement *pElem = pDoc->NewElement("flag");
pElem->SetAttribute("mask", *TString::HexString(pTemp->FlagMask(iFlag)));
pElem->SetAttribute("name", *pTemp->FlagName(iFlag));
pFlags->LinkEndChild(pElem);
}
}
#endif

View File

@@ -1,30 +0,0 @@
#ifndef CTEMPLATEWRITER_H
#define CTEMPLATEWRITER_H
#include "Core/Resource/Script/CMasterTemplate.h"
#include "Core/Resource/Script/CScriptTemplate.h"
#include <tinyxml2.h>
#if 0
class CTemplateWriter
{
CTemplateWriter();
static TString smTemplatesDir;
public:
static void SavePropertyTemplate(IPropertyTemplate *pTemp);
static void SaveAllTemplates();
static void SaveGameTemplates(CMasterTemplate *pMaster);
static void SavePropertyList();
static void SaveScriptTemplate(CScriptTemplate *pTemp);
static void SaveStructTemplate(CStructTemplate *pTemp);
static void SaveEnumTemplate(CEnumTemplate *pTemp);
static void SaveBitfieldTemplate(CBitfieldTemplate *pTemp);
static void SaveProperties(tinyxml2::XMLDocument *pDoc, tinyxml2::XMLElement *pParent, CStructTemplate *pTemp);
static void SavePropertyOverrides(tinyxml2::XMLDocument *pDoc, tinyxml2::XMLElement *pParent, CStructTemplate *pStruct, CStructTemplate *pOriginal);
static void SaveEnumerators(tinyxml2::XMLDocument *pDoc, tinyxml2::XMLElement *pParent, CEnumTemplate *pTemp);
static void SaveBitFlags(tinyxml2::XMLDocument *pDoc, tinyxml2::XMLElement *pParent, CBitfieldTemplate *pTemp);
};
#endif
#endif // CTEMPLATEWRITER_H