Updated script templates to version 3 + added script template writer class

This commit is contained in:
parax0 2015-09-17 23:53:53 -06:00
parent f82b3a20a9
commit 97ef20d0d2
29 changed files with 1914 additions and 1287 deletions

View File

@ -237,7 +237,7 @@ CUniqueID CUniqueID::FromString(std::string String)
CUniqueID ID;
ID.mLength = e32Bit;
u32 LongID = StringUtil::StrToRes32(Name);
u32 LongID = StringUtil::ToInt32(Name);
if (SystemEndianness == LittleEndian)
memcpy(ID.mID, &LongID, 4);
@ -252,7 +252,7 @@ CUniqueID CUniqueID::FromString(std::string String)
CUniqueID ID;
ID.mLength = e64Bit;
u64 LongID = StringUtil::StrToRes64(Name);
u64 LongID = StringUtil::ToInt64(Name);
if (SystemEndianness == LittleEndian)
memcpy(ID.mID, &LongID, 8);
@ -266,7 +266,7 @@ CUniqueID CUniqueID::FromString(std::string String)
{
CUniqueID ID;
ID.mLength = e128Bit;
StringUtil::StrToRes128(Name, (char*) ID.mID);
StringUtil::ToInt128(Name, (char*) ID.mID);
return ID;
}
}

View File

@ -39,22 +39,6 @@ namespace StringUtil
return path.substr(endname + 1, path.size() - endname);
}
// Not convinced stringstream is the best way to do string conversions of asset IDs - don't know of a better way tho
std::string ResToStr(unsigned long assetID)
{
std::stringstream sstream;
sstream << std::hex << std::setw(8) << std::setfill('0') << assetID << std::dec;
return sstream.str();
}
std::string ResToStr(unsigned long long assetID)
{
std::stringstream sstream;
sstream << std::hex << std::setw(16) << std::setfill('0') << assetID << std::dec;
return sstream.str();
}
std::string ToUpper(std::string str)
{
for (unsigned int i = 0; i < str.length(); i++)
@ -77,22 +61,25 @@ namespace StringUtil
return str;
}
std::string ToHexString(unsigned char num, bool addPrefix, int width)
std::string ToHexString(unsigned char num, bool addPrefix, bool uppercase, int width)
{
return ToHexString((unsigned long) num, addPrefix, width);
return ToHexString((unsigned long) num, addPrefix, uppercase, width);
}
std::string ToHexString(unsigned short num, bool addPrefix, int width)
std::string ToHexString(unsigned short num, bool addPrefix, bool uppercase, int width)
{
return ToHexString((unsigned long) num, addPrefix, width);
return ToHexString((unsigned long) num, addPrefix, uppercase, width);
}
std::string ToHexString(unsigned long num, bool addPrefix, int width)
std::string ToHexString(unsigned long num, bool addPrefix, bool uppercase, int width)
{
std::stringstream str;
if (addPrefix) str << "0x";
str << std::hex << std::setw(width) << std::setfill('0') << num;
return str.str();
std::stringstream stream;
stream << std::hex << std::setw(width) << std::setfill('0') << num;
std::string str = stream.str();
if (uppercase) str = ToUpper(str);
if (addPrefix) str = std::string("0x") + str;
return str;
}
long Hash32(std::string str)
@ -119,15 +106,15 @@ namespace StringUtil
return hash;
}
long StrToRes32(std::string str) {
long ToInt32(std::string str) {
return std::stoul(str, nullptr, 16);
}
long long StrToRes64(std::string str) {
long long ToInt64(std::string str) {
return std::stoull(str, nullptr, 16);
}
void StrToRes128(std::string str, char *out) {
void ToInt128(std::string str, char *out) {
long long Part1 = std::stoull(str.substr(0, 16), nullptr, 16);
long long Part2 = std::stoull(str.substr(16, 16), nullptr, 16);
@ -141,14 +128,18 @@ namespace StringUtil
memcpy(out + 8, &Part2, 8);
}
long GetResID32(std::string str)
std::string ToString(unsigned long v)
{
long resID;
if (IsHexString(str, false, 8))
resID = StrToRes32(str);
else
resID = Hash32(GetFileName(str));
return resID;
std::stringstream sstream;
sstream << std::hex << std::setw(8) << std::setfill('0') << v << std::dec;
return sstream.str();
}
std::string ToString(unsigned long long v)
{
std::stringstream sstream;
sstream << std::hex << std::setw(16) << std::setfill('0') << v << std::dec;
return sstream.str();
}
bool IsHexString(std::string str, bool requirePrefix, long width)

View File

@ -12,19 +12,18 @@ namespace StringUtil
std::string GetFileNameWithExtension(std::string path);
std::string GetPathWithoutExtension(std::string path);
std::string GetExtension(std::string path);
std::string ResToStr(unsigned long ID);
std::string ResToStr(unsigned long long ID);
std::string ToUpper(std::string str);
std::string ToLower(std::string str);
std::string ToHexString(unsigned char num, bool addPrefix = true, int width = 0);
std::string ToHexString(unsigned short num, bool addPrefix = true, int width = 0);
std::string ToHexString(unsigned long num, bool addPrefix = true, int width = 0);
std::string ToHexString(unsigned char num, bool addPrefix = true, bool uppercase = false, int width = 0);
std::string ToHexString(unsigned short num, bool addPrefix = true, bool uppercase = false, int width = 0);
std::string ToHexString(unsigned long num, bool addPrefix = true, bool uppercase = false, int width = 0);
long Hash32(std::string str);
long long Hash64(std::string str);
long StrToRes32(std::string str);
long long StrToRes64(std::string str);
void StrToRes128(std::string str, char *out);
long GetResID32(std::string str);
long ToInt32(std::string str);
long long ToInt64(std::string str);
void ToInt128(std::string str, char *out);
std::string ToString(unsigned long ID);
std::string ToString(unsigned long long ID);
bool IsHexString(std::string str, bool requirePrefix = false, long width = -1);
std::string AppendSlash(std::string str);
CStringList Tokenize(const std::string& str, const char *pTokens);

View File

@ -116,11 +116,11 @@ CResource* CResCache::GetResource(CUniqueID ResID, CFourCC type)
// Load from folder
else
{
Source = mResSource.Path + StringUtil::ResToStr(ResID.ToLong()) + "." + type.ToString();
Source = mResSource.Path + StringUtil::ToString(ResID.ToLong()) + "." + type.ToString();
CFileInStream file(Source, IOUtil::BigEndian);
if (!file.IsValid())
{
Source = mResSource.Path + StringUtil::ResToStr(ResID.ToLongLong()) + "." + type.ToString();
Source = mResSource.Path + StringUtil::ToString(ResID.ToLongLong()) + "." + type.ToString();
file.Open(Source, IOUtil::BigEndian);
if (!file.IsValid())
{

View File

@ -144,7 +144,11 @@ SOURCES += \
UI/CSceneViewport.cpp \
UI/undo/CRotateNodeCommand.cpp \
UI/undo/CScaleNodeCommand.cpp \
UI/CModelEditorViewport.cpp
UI/CModelEditorViewport.cpp \
Resource/cooker/CTemplateWriter.cpp \
Resource/cooker/CWorldCooker.cpp \
Resource/script/CPropertyTemplate.cpp \
Resource/script/CProperty.cpp
HEADERS += \
Common/AnimUtil.h \
@ -306,7 +310,11 @@ HEADERS += \
UI/CSceneViewport.h \
UI/undo/CRotateNodeCommand.h \
UI/undo/CScaleNodeCommand.h \
UI/CModelEditorViewport.h
UI/CModelEditorViewport.h \
Resource/cooker/CTemplateWriter.h \
Resource/cooker/CWorldCooker.h \
Resource/script/CPropertyTemplate.h \
Resource/script/EVolumeShape.h
FORMS += \
UI/CWorldEditorWindow.ui \
@ -374,3 +382,7 @@ else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../Libraries/assimp/
INCLUDEPATH += $$PWD/../../Libraries/assimp/include
DEPENDPATH += $$PWD/../../Libraries/assimp/include
CONFIG(release, debug|release): LIBS += -LE:/C++/Libraries/boost_1_56_0/lib32-msvc-12.0 -llibboost_filesystem-vc120-mt-1_56
CONFIG(debug, debug|release): LIBS += -LE:/C++/Libraries/boost_1_56_0/lib32-msvc-12.0 -llibboost_filesystem-vc120-mt-gd-1_56
INCLUDEPATH += E:/C++/Libraries/boost_1_56_0

View File

@ -11,7 +11,7 @@ CAnimSet::~CAnimSet()
EResType CAnimSet::Type()
{
return eCharacter;
return eAnimSet;
}
u32 CAnimSet::getNodeCount()

View File

@ -0,0 +1,451 @@
#include "CTemplateWriter.h"
#include "../cooker/CWorldCooker.h"
#include <tinyxml2.h>
#include <boost/filesystem.hpp>
using namespace tinyxml2;
CTemplateWriter::CTemplateWriter()
{
}
void CTemplateWriter::SaveAllTemplates()
{
// Create directory
std::list<CMasterTemplate*> masterList = CMasterTemplate::GetMasterList();
std::string out = "../templates/";
boost::filesystem::create_directory(out);
// Resave master templates
for (auto it = masterList.begin(); it != masterList.end(); it++)
SaveGameTemplates(*it, out);
// Resave game list
XMLDocument gameList;
XMLDeclaration *pDecl = gameList.NewDeclaration();
gameList.LinkEndChild(pDecl);
XMLElement *pBase = gameList.NewElement("GameList");
pBase->SetAttribute("version", 3);
gameList.LinkEndChild(pBase);
for (auto it = masterList.begin(); it != masterList.end(); it++)
{
CMasterTemplate *pMaster = *it;
XMLElement *pGame = gameList.NewElement("game");
XMLElement *pGameName = gameList.NewElement("name");
pGameName->SetText(pMaster->mGameName.c_str());
XMLElement *pWorldVersion = gameList.NewElement("mlvl");
u32 versionNumber = CWorldCooker::GetMLVLVersion(pMaster->GetGame());
pWorldVersion->SetText(StringUtil::ToHexString(versionNumber, true, true, 2).c_str());
XMLElement *pTempPath = gameList.NewElement("master");
pTempPath->SetText(pMaster->mSourceFile.c_str());
pGame->LinkEndChild(pGameName);
pGame->LinkEndChild(pWorldVersion);
pGame->LinkEndChild(pTempPath);
pBase->LinkEndChild(pGame);
}
gameList.SaveFile((out + "GameList.xml").c_str());
}
void CTemplateWriter::SaveGameTemplates(CMasterTemplate *pMaster, const std::string& dir)
{
// Create directory
std::string outFile = dir + pMaster->mSourceFile;
std::string outDir = StringUtil::GetFileDirectory(outFile);
boost::filesystem::create_directory(outDir);
// Resave script templates
for (auto it = pMaster->mTemplates.begin(); it != pMaster->mTemplates.end(); it++)
SaveScriptTemplate(it->second, outDir);
// Resave master template
XMLDocument master;
XMLDeclaration *pDecl = master.NewDeclaration();
master.LinkEndChild(pDecl);
XMLElement *pBase = master.NewElement("MasterTemplate");
pBase->SetAttribute("version", 3);
master.LinkEndChild(pBase);
// Write property list
if (!pMaster->mPropertyList.empty())
{
SavePropertyList(pMaster, outDir);
XMLElement *pPropList = master.NewElement("properties");
pPropList->SetText("Properties.xml");
pBase->LinkEndChild(pPropList);
}
// Write script objects
XMLElement *pObjects = master.NewElement("objects");
pBase->LinkEndChild(pObjects);
for (auto it = pMaster->mTemplates.begin(); it != pMaster->mTemplates.end(); it++)
{
std::string objID;
u32 intID = (it->second)->ObjectID();
if (intID <= 0xFF) objID = StringUtil::ToHexString(intID, true, true, 2);
else objID = CFourCC(intID).ToString();
XMLElement *pObj = master.NewElement("object");
pObj->SetAttribute("ID", objID.c_str());
pObj->SetAttribute("template", (it->second)->mSourceFile.c_str());
pObjects->LinkEndChild(pObj);
}
// Write script states/messages
std::map<u32, std::string> *pMaps[2] = { &pMaster->mStates, &pMaster->mMessages };
std::string types[2] = { "state", "message" };
for (u32 iScr = 0; iScr < 2; iScr++)
{
XMLElement *pElem = master.NewElement((types[iScr] + "s").c_str());
pBase->LinkEndChild(pElem);
for (auto it = pMaps[iScr]->begin(); it != pMaps[iScr]->end(); it++)
{
std::string ID;
if (it->first <= 0xFF) ID = StringUtil::ToHexString(it->first, true, true, 2);
else ID = CFourCC(it->first).ToString();
XMLElement *pSubElem = master.NewElement(types[iScr].c_str());
pSubElem->SetAttribute("ID", ID.c_str());
pSubElem->SetAttribute("name", (it->second).c_str());
pElem->LinkEndChild(pSubElem);
}
}
// Save file
master.SaveFile(outFile.c_str());
}
void CTemplateWriter::SavePropertyList(CMasterTemplate *pMaster, const std::string& dir)
{
// Create XML
XMLDocument list;
XMLDeclaration *pDecl = list.NewDeclaration();
list.LinkEndChild(pDecl);
XMLElement *pBase = list.NewElement("Properties");
pBase->SetAttribute("version", 3);
list.LinkEndChild(pBase);
// Write properties
for (auto it = pMaster->mPropertyList.begin(); it != pMaster->mPropertyList.end(); it++)
{
CPropertyTemplate *pTemp = it->second;
if (pTemp->Type() == eStructProperty)
{
CStructTemplate *pStructTemp = static_cast<CStructTemplate*>(pTemp);
XMLElement *pElem = list.NewElement("struct");
pElem->SetAttribute("ID", StringUtil::ToHexString(pTemp->PropertyID(), true, true, 8).c_str());
pElem->SetAttribute("name", pTemp->Name().c_str());
if (!pStructTemp->mSourceFile.empty())
{
SaveStructTemplate(pStructTemp, pMaster, dir);
pElem->SetAttribute("template", pStructTemp->mSourceFile.c_str());
}
pBase->LinkEndChild(pElem);
}
else
{
XMLElement *pElem = list.NewElement("property");
pElem->SetAttribute("ID", StringUtil::ToHexString(pTemp->PropertyID(), true, true, 8).c_str());
pElem->SetAttribute("name", pTemp->Name().c_str());
pElem->SetAttribute("type", PropEnumToPropString(pTemp->Type()).c_str());
if (pTemp->Type() == eFileProperty)
{
// Construct extension list string
CFileTemplate *pFileProp = static_cast<CFileTemplate*>(pTemp);
const CStringList& extensions = pFileProp->Extensions();
std::string strList = "";
for (auto it = extensions.begin(); it != extensions.end();)
{
strList += *it;
it++;
if (it != extensions.end()) strList += ",";
}
pElem->SetAttribute("ext", strList.c_str());
}
pBase->LinkEndChild(pElem);
}
}
list.SaveFile((dir + "Properties.xml").c_str());
}
void CTemplateWriter::SaveScriptTemplate(CScriptTemplate *pTemp, const std::string& dir)
{
// Create directory
std::string outFile = dir + pTemp->mSourceFile;
std::string outDir = StringUtil::GetFileDirectory(outFile);
boost::filesystem::create_directory(outDir);
// Create new document
XMLDocument scriptXML;
XMLDeclaration *pDecl = scriptXML.NewDeclaration();
scriptXML.LinkEndChild(pDecl);
// Base element
XMLElement *pBase = scriptXML.NewElement("ScriptTemplate");
pBase->SetAttribute("version", 3.0f);
scriptXML.LinkEndChild(pBase);
// Write object name
XMLElement *pName = scriptXML.NewElement("name");
pName->SetText(pTemp->TemplateName().c_str());
pBase->LinkEndChild(pName);
// Write properties
for (auto it = pTemp->mPropertySets.begin(); it != pTemp->mPropertySets.end(); it++)
{
XMLElement *pProperties = scriptXML.NewElement("properties");
pProperties->SetAttribute("version", it->SetName.c_str());
SaveProperties(&scriptXML, pProperties, it->pBaseStruct, pTemp->MasterTemplate(), dir);
pBase->LinkEndChild(pProperties);
}
// Write editor properties
XMLElement *pEditor = scriptXML.NewElement("editor");
pBase->LinkEndChild(pEditor);
// Editor Properties
XMLElement *pEditorProperties = scriptXML.NewElement("properties");
pEditor->LinkEndChild(pEditorProperties);
std::string 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]->empty())
{
XMLElement *pProperty = scriptXML.NewElement("property");
pProperty->SetAttribute("name", propNames[iProp].c_str());
pProperty->SetAttribute("ID", pPropStrings[iProp]->c_str());
pEditorProperties->LinkEndChild(pProperty);
}
}
// Editor Assets
XMLElement *pAssets = scriptXML.NewElement("assets");
pEditor->LinkEndChild(pAssets);
for (auto it = pTemp->mAssets.begin(); it != pTemp->mAssets.end(); it++)
{
std::string type = (it->AssetType == CScriptTemplate::SEditorAsset::eAnimParams ? "animparams" : "model");
std::string source = (it->AssetSource == CScriptTemplate::SEditorAsset::eFile ? "file" : "property");
s32 force = -1;
if (it->AssetSource == CScriptTemplate::SEditorAsset::eAnimParams) force = it->ForceNodeIndex;
XMLElement *pAsset = scriptXML.NewElement(type.c_str());
pAsset->SetAttribute("source", source.c_str());
if (force >= 0) pAsset->SetAttribute("force", std::to_string(force).c_str());
pAsset->SetText(it->AssetLocation.c_str());
pAssets->LinkEndChild(pAsset);
}
// 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) -> std::string
{
switch (shape)
{
case eBoxShape: return "Box";
case eAxisAlignedBoxShape: return "AxisAlignedBox";
case eEllipsoidShape: return "Ellipsoid";
case eCylinderShape: return "Cylinder";
case eCylinderLargeShape: return "CylinderLarge";
case eConditionalShape: return "Conditional";
default: return "INVALID";
}
};
pVolume->SetAttribute("shape", GetVolumeString(pTemp->mVolumeShape).c_str());
if (pTemp->mVolumeShape == eConditionalShape)
{
pVolume->SetAttribute("propertyID", pTemp->mVolumeConditionIDString.c_str());
// Find conditional test property
CPropertyTemplate *pProp;
for (auto it = pTemp->mPropertySets.begin(); it != pTemp->mPropertySets.end(); it++)
{
pProp = it->pBaseStruct->PropertyByIDString(pTemp->mVolumeConditionIDString);
if (pProp) break;
}
// Write conditions
for (auto it = pTemp->mVolumeConditions.begin(); it != pTemp->mVolumeConditions.end(); it++)
{
// Value should be an integer, or a boolean condition?
std::string strVal;
if (pProp->Type() == eBoolProperty)
strVal = (it->Value == 1 ? "true" : "false");
else
strVal = StringUtil::ToHexString((u32) it->Value, true, true, (it->Value > 0xFF ? 8 : 2));
XMLElement *pCondition = scriptXML.NewElement("condition");
pCondition->SetAttribute("value", strVal.c_str());
pCondition->SetAttribute("shape", GetVolumeString(it->Shape).c_str());
pVolume->LinkEndChild(pCondition);
}
}
}
// Write to file
scriptXML.SaveFile(outFile.c_str());
}
void CTemplateWriter::SaveStructTemplate(CStructTemplate *pTemp, CMasterTemplate *pMaster, const std::string& dir)
{
// Create directory
std::string outFile = dir + pTemp->mSourceFile;
std::string outDir = StringUtil::GetFileDirectory(outFile);
std::string name = StringUtil::GetFileName(pTemp->mSourceFile);
boost::filesystem::create_directory(outDir);
// Create new document and write struct properties to it
XMLDocument structXML;
XMLDeclaration *pDecl = structXML.NewDeclaration();
structXML.LinkEndChild(pDecl);
XMLElement *pBase = structXML.NewElement("struct");
pBase->SetAttribute("name", name.c_str());
pBase->SetAttribute("type", (pTemp->IsSingleProperty() ? "single" : "multi"));
SaveProperties(&structXML, pBase, pTemp, pMaster, dir);
structXML.LinkEndChild(pBase);
structXML.SaveFile(outFile.c_str());
}
void CTemplateWriter::SaveProperties(XMLDocument *pDoc, XMLElement *pParent, CStructTemplate *pTemp, CMasterTemplate *pMaster, const std::string& dir)
{
for (u32 iProp = 0; iProp < pTemp->Count(); iProp++)
{
CPropertyTemplate *pProp = pTemp->PropertyByIndex(iProp);
u32 propID = (pProp->PropertyID() == 0xFFFFFFFF ? iProp : pProp->PropertyID());
std::string strID = StringUtil::ToHexString(propID, true, true, (propID > 0xFF ? 8 : 2));
if (pProp->Type() == eStructProperty)
{
CStructTemplate *pStructTemp = static_cast<CStructTemplate*>(pProp);
bool isExternal = (!pStructTemp->mSourceFile.empty());
XMLElement *pElem = pDoc->NewElement("struct");
pElem->SetAttribute("ID", strID.c_str());
if ((!pMaster->HasPropertyList()) || (pProp->PropertyID() == -1) || pTemp->IsSingleProperty())
{
pElem->SetAttribute("name", pProp->Name().c_str());
}
if (!isExternal) {
std::string type = pStructTemp->IsSingleProperty() ? "single" : "multi";
pElem->SetAttribute("type", type.c_str());
}
// Only save properties if this is a multi struct, or if there is no master property list
if (!pMaster->HasPropertyList() || !pStructTemp->IsSingleProperty())
{
// Embed struct or save to external XML?
if (!pStructTemp->mSourceFile.empty())
{
SaveStructTemplate(pStructTemp, pMaster, dir);
pElem->SetAttribute("template", pStructTemp->mSourceFile.c_str());
}
else
{
SaveProperties(pDoc, pElem, pStructTemp, pMaster, dir);
}
}
pParent->LinkEndChild(pElem);
}
else
{
XMLElement *pElem = pDoc->NewElement("property");
pElem->SetAttribute("ID", strID.c_str());
if ((!pMaster->HasPropertyList()) || (pProp->PropertyID() == -1) || pTemp->IsSingleProperty())
{
pElem->SetAttribute("name", pProp->Name().c_str());
pElem->SetAttribute("type", PropEnumToPropString(pProp->Type()).c_str());
if (pProp->Type() == eFileProperty)
{
// Construct extension list string
CFileTemplate *pFileProp = static_cast<CFileTemplate*>(pProp);
const CStringList& extensions = pFileProp->Extensions();
std::string strList = "";
for (auto it = extensions.begin(); it != extensions.end();)
{
strList += *it;
it++;
if (it != extensions.end()) strList += ",";
}
pElem->SetAttribute("ext", strList.c_str());
}
}
pParent->LinkEndChild(pElem);
}
}
}

View File

@ -0,0 +1,21 @@
#ifndef CTEMPLATEWRITER_H
#define CTEMPLATEWRITER_H
#include "../script/CMasterTemplate.h"
#include "../script/CScriptTemplate.h"
class CTemplateWriter
{
CTemplateWriter();
public:
static void SaveAllTemplates();
static void SaveGameTemplates(CMasterTemplate *pMaster, const std::string& dir);
static void SavePropertyList(CMasterTemplate *pMaster, const std::string& dir);
static void SaveScriptTemplate(CScriptTemplate *pTemp, const std::string& dir);
static void SaveStructTemplate(CStructTemplate *pTemp, CMasterTemplate *pMaster, const std::string& dir);
static void SaveProperties(tinyxml2::XMLDocument *pDoc, tinyxml2::XMLElement *pParent, CStructTemplate *pTemp, CMasterTemplate *pMaster, const std::string& dir);
// todo: save enum templates
};
#endif // CTEMPLATEWRITER_H

View File

@ -0,0 +1,19 @@
#include "CWorldCooker.h"
CWorldCooker::CWorldCooker()
{
}
u32 CWorldCooker::GetMLVLVersion(EGame version)
{
switch (version)
{
case ePrimeDemo: return 0xD;
case ePrime: return 0x11;
case eEchoesDemo: return 0x14;
case eEchoes: return 0x17;
case eCorruption: return 0x19;
case eReturns: return 0x1B;
default: return 0;
}
}

View File

@ -0,0 +1,14 @@
#ifndef CWORLDCOOKER_H
#define CWORLDCOOKER_H
#include <Common/types.h>
#include "../EFormatVersion.h"
class CWorldCooker
{
CWorldCooker();
public:
static u32 GetMLVLVersion(EGame version);
};
#endif // CWORLDCOOKER_H

View File

@ -10,78 +10,78 @@ CScriptLoader::CScriptLoader()
mpObj = nullptr;
}
CPropertyStruct* CScriptLoader::LoadStructMP1(CInputStream& SCLY, CStructTemplate *tmp)
CPropertyStruct* CScriptLoader::LoadStructMP1(CInputStream& SCLY, CStructTemplate *pTemp)
{
u32 StructStart = SCLY.Tell();
CPropertyStruct *PropStruct = new CPropertyStruct();
PropStruct->tmp = tmp;
u32 structStart = SCLY.Tell();
CPropertyStruct *propStruct = new CPropertyStruct();
propStruct->mpTemplate = pTemp;
// Verify property count
s32 TemplatePropCount = tmp->TemplateCount();
if (TemplatePropCount >= 0)
u32 propCount = pTemp->Count();
if (!pTemp->IsSingleProperty())
{
u32 FilePropCount = SCLY.ReadLong();
if (TemplatePropCount != FilePropCount)
Log::FileWarning(SCLY.GetSourceString(), StructStart, "Struct \"" + tmp->Name() + "\" template prop count doesn't match file");
u32 filePropCount = SCLY.ReadLong();
if (propCount != filePropCount)
Log::FileWarning(SCLY.GetSourceString(), structStart, "Struct \"" + pTemp->Name() + "\" template prop count doesn't match file");
}
// Parse properties
u32 PropCount = tmp->Count();
PropStruct->Reserve(PropCount);
propStruct->Reserve(propCount);
for (u32 p = 0; p < PropCount; p++)
for (u32 iProp = 0; iProp < propCount; iProp++)
{
CPropertyBase *prop = nullptr;
CPropertyTemplate *proptmp = tmp->PropertyByIndex(p);
EPropertyType type = proptmp->Type();
CPropertyBase *pProp = nullptr;
CPropertyTemplate *pPropTmp = pTemp->PropertyByIndex(iProp);
EPropertyType type = pPropTmp->Type();
switch (type)
{
case eBoolProperty: {
bool v = (SCLY.ReadByte() == 1);
prop = new CBoolProperty(v);
pProp = new CBoolProperty(v);
break;
}
case eByteProperty: {
char v = SCLY.ReadByte();
prop = new CByteProperty(v);
pProp = new CByteProperty(v);
break;
}
case eShortProperty: {
short v = SCLY.ReadShort();
prop = new CShortProperty(v);
pProp = new CShortProperty(v);
break;
}
case eLongProperty: {
long v = SCLY.ReadLong();
prop = new CLongProperty(v);
pProp = new CLongProperty(v);
break;
}
case eFloatProperty: {
float v = SCLY.ReadFloat();
prop = new CFloatProperty(v);
pProp = new CFloatProperty(v);
break;
}
case eStringProperty: {
std::string v = SCLY.ReadString();
prop = new CStringProperty(v);
pProp = new CStringProperty(v);
break;
}
case eVector3Property: {
CVector3f v(SCLY);
prop = new CVector3Property(v);
pProp = new CVector3Property(v);
break;
}
case eColorProperty: {
CVector4f color(SCLY);
CColor v(color.x, color.y, color.z, color.w);
prop = new CColorProperty(v);
pProp = new CColorProperty(v);
break;
}
case eFileProperty: {
u32 ResID = SCLY.ReadLong();
const CStringList& Extensions = static_cast<CFileTemplate*>(proptmp)->Extensions();
const CStringList& Extensions = static_cast<CFileTemplate*>(pPropTmp)->Extensions();
CResource *pRes = nullptr;
@ -94,65 +94,75 @@ CPropertyStruct* CScriptLoader::LoadStructMP1(CInputStream& SCLY, CStructTemplat
if (pRes) break;
}
prop = new CFileProperty(pRes);
pProp = new CFileProperty(pRes);
break;
}
case eStructProperty: {
CStructTemplate *StructTmp = tmp->StructByIndex(p);
prop = LoadStructMP1(SCLY, StructTmp);
CStructTemplate *StructTmp = pTemp->StructByIndex(iProp);
pProp = LoadStructMP1(SCLY, StructTmp);
break;
}
default:
pProp = new CUnknownProperty();
break;
}
if (prop)
if (pProp)
{
prop->tmp = proptmp;
PropStruct->Properties.push_back(prop);
pProp->mpTemplate = pPropTmp;
propStruct->mProperties.push_back(pProp);
}
}
return PropStruct;
return propStruct;
}
CScriptObject* CScriptLoader::LoadObjectMP1(CInputStream& SCLY)
{
u32 ObjStart = SCLY.Tell();
u32 objStart = SCLY.Tell();
u8 type = SCLY.ReadByte();
u32 size = SCLY.ReadLong();
u32 end = SCLY.Tell() + size;
CScriptTemplate *tmp = mpMaster->TemplateByID((u32) type);
if (!tmp)
CScriptTemplate *pTemp = mpMaster->TemplateByID((u32) type);
if (!pTemp)
{
// No valid template for this object; can't load
Log::FileError(SCLY.GetSourceString(), ObjStart, "Invalid object ID encountered - " + StringUtil::ToHexString(type));
Log::FileError(SCLY.GetSourceString(), objStart, "Invalid object ID encountered: " + StringUtil::ToHexString(type));
SCLY.Seek(end, SEEK_SET);
return nullptr;
}
mpObj = new CScriptObject(mpArea, mpLayer, tmp);
mpObj = new CScriptObject(mpArea, mpLayer, pTemp);
mpObj->mInstanceID = SCLY.ReadLong();
// Load connections
u32 numConnections = SCLY.ReadLong();
mpObj->mOutConnections.reserve(numConnections);
u32 numLinks = SCLY.ReadLong();
mpObj->mOutConnections.reserve(numLinks);
for (u32 c = 0; c < numConnections; c++)
for (u32 iLink = 0; iLink < numLinks; iLink++)
{
SLink con;
con.State = SCLY.ReadLong();
con.Message = SCLY.ReadLong();
con.ObjectID = SCLY.ReadLong();
mpObj->mOutConnections.push_back(con);
SLink link;
link.State = SCLY.ReadLong();
link.Message = SCLY.ReadLong();
link.ObjectID = SCLY.ReadLong();
mpObj->mOutConnections.push_back(link);
}
// Load object...
CStructTemplate *base = tmp->BaseStruct();
mpObj->mpProperties = LoadStructMP1(SCLY, base);
SetupAttribs();
u32 count = SCLY.PeekLong();
CStructTemplate *pBase = pTemp->BaseStructByCount(count);
if (!pBase) {
Log::Error(pTemp->TemplateName() + " template doesn't match file property count (" + StringUtil::ToString(count) + ")");
pBase = pTemp->BaseStructByIndex(0);
}
mpObj->mpProperties = LoadStructMP1(SCLY, pBase);
// Cleanup and return
SCLY.Seek(end, SEEK_SET);
mpObj->EvaluateProperties();
return mpObj;
}
@ -184,41 +194,41 @@ void CScriptLoader::LoadStructMP2(CInputStream& SCLY, CPropertyStruct *pStruct,
// Verify property count
if (!pTemp->IsSingleProperty())
{
u16 NumProperties = SCLY.ReadShort();
if ((pTemp->TemplateCount() >= 0) && (NumProperties != pTemp->TemplateCount()))
u16 numProperties = SCLY.ReadShort();
if (numProperties != pTemp->Count())
Log::FileWarning(SCLY.GetSourceString(), SCLY.Tell() - 2, "Struct \"" + pTemp->Name() + "\" template property count doesn't match file");
}
// Parse properties
u32 PropCount = pTemp->Count();
pStruct->Reserve(PropCount);
u32 propCount = pTemp->Count();
pStruct->Reserve(propCount);
for (u32 p = 0; p < PropCount; p++)
for (u32 iProp = 0; iProp < propCount; iProp++)
{
CPropertyBase *pProp;
CPropertyTemplate *pPropTemp;
u32 PropertyStart = SCLY.Tell();
u32 PropertyID = -1;
u32 propertyStart = SCLY.Tell();
u32 propertyID = -1;
u16 PropertyLength = 0;
u32 NextProperty = 0;
if (pTemp->IsSingleProperty())
{
pProp = pStruct->PropertyByIndex(p);
pPropTemp = pTemp->PropertyByIndex(p);
pProp = pStruct->PropertyByIndex(iProp);
pPropTemp = pTemp->PropertyByIndex(iProp);
}
else
{
PropertyID = SCLY.ReadLong();
propertyID = SCLY.ReadLong();
PropertyLength = SCLY.ReadShort();
NextProperty = SCLY.Tell() + PropertyLength;
pProp = pStruct->PropertyByID(PropertyID);
pPropTemp = pTemp->PropertyByID(PropertyID);
pProp = pStruct->PropertyByID(propertyID);
pPropTemp = pTemp->PropertyByID(propertyID);
}
if (!pPropTemp)
Log::FileError(SCLY.GetSourceString(), PropertyStart, "Can't find template for property " + StringUtil::ToHexString(PropertyID) + " - skipping");
Log::FileError(SCLY.GetSourceString(), propertyStart, "Can't find template for property " + StringUtil::ToHexString(propertyID) + " - skipping");
else
{
@ -312,7 +322,7 @@ void CScriptLoader::LoadStructMP2(CInputStream& SCLY, CPropertyStruct *pStruct,
if (it != Extensions.begin()) ExtList += "/";
ExtList += *it;
}
Log::FileWarning(SCLY.GetSourceString(), "Incorrect resource type? " + ExtList + " " + StringUtil::ToHexString(PropertyID));
Log::FileWarning(SCLY.GetSourceString(), "Incorrect resource type? " + ExtList + " " + StringUtil::ToHexString(propertyID));
}
pFileCast->Set(pRes);
@ -333,6 +343,14 @@ void CScriptLoader::LoadStructMP2(CInputStream& SCLY, CPropertyStruct *pStruct,
break;
}
case eArrayProperty: {
CArrayProperty *pArrayCast = static_cast<CArrayProperty*>(pProp);
std::vector<u8> buf(PropertyLength);
SCLY.ReadBytes(buf.data(), buf.size());
pArrayCast->Set(buf);
break;
}
}
}
@ -357,7 +375,7 @@ CScriptObject* CScriptLoader::LoadObjectMP2(CInputStream& SCLY)
return nullptr;
}
mpObj = CScriptObject::CopyFromTemplate(pTemplate, mpArea, mpLayer);
mpObj = new CScriptObject(mpArea, mpLayer, pTemplate);
mpObj->mpTemplate = pTemplate;
mpObj->mInstanceID = SCLY.ReadLong();
@ -375,12 +393,16 @@ CScriptObject* CScriptLoader::LoadObjectMP2(CInputStream& SCLY)
}
// Load object
CStructTemplate *pBase = pTemplate->BaseStruct();
SCLY.Seek(0x6, SEEK_CUR); // Skip base struct ID + size
LoadStructMP2(SCLY, mpObj->mpProperties, pBase);
SetupAttribs();
u16 numProps = SCLY.PeekShort();
mpObj->CopyFromTemplate(pTemplate, (u32) numProps);
CStructTemplate *pBase = pTemplate->BaseStructByCount(numProps);
LoadStructMP2(SCLY, mpObj->mpProperties, pBase);
// Cleanup and return
SCLY.Seek(ObjEnd, SEEK_SET);
mpObj->EvaluateProperties();
return mpObj;
}
@ -416,32 +438,6 @@ CScriptLayer* CScriptLoader::LoadLayerMP2(CInputStream& SCLY)
return mpLayer;
}
void CScriptLoader::SetupAttribs()
{
// Add template attributes
u32 numAttribs = mpObj->mpTemplate->AttribCount();
for (u32 a = 0; a < numAttribs; a++)
{
CAttribTemplate *AttribTmp = mpObj->mpTemplate->Attrib(a);
CPropertyBase *prop = mpObj->PropertyByName( AttribTmp->Target() );
// Check for static resource
CResource *res = nullptr;
std::string ResStr = AttribTmp->Resource();
if (!ResStr.empty())
res = gResCache.GetResource(ResStr);
mpObj->mAttribs.emplace_back(CScriptObject::SAttrib(AttribTmp->Type(), res, AttribTmp->Settings(), prop) );
mpObj->mAttribFlags |= AttribTmp->Type();
}
// Initial attribute evaluation
mpObj->EvaluateInstanceName();
mpObj->EvalutateXForm();
mpObj->EvaluateTevColor();
mpObj->EvaluateDisplayModel();
}
CScriptLayer* CScriptLoader::LoadLayer(CInputStream &SCLY, CGameArea *pArea, EGame version)
{
if (!SCLY.IsValid()) return nullptr;

View File

@ -3,475 +3,409 @@
#include "../script/EAttribType.h"
#include <Core/Log.h>
// ************ PROPERTY ************
CPropertyTemplate* CTemplateLoader::LoadPropertyTemplate(tinyxml2::XMLElement *pElem, const std::string& TemplateName)
void CTemplateLoader::LoadStructProperties(tinyxml2::XMLElement *pElem, CStructTemplate *pTemp, const std::string& templateName)
{
const char *pElemName = pElem->Name();
// Load multi-property struct
if (strcmp(pElemName, "struct") == 0)
{
CStructTemplate *pStruct = LoadStructTemplate(pElem, TemplateName);
if (pStruct)
pStruct->mIsSingleProperty = false;
return pStruct;
}
else if (strcmp(pElemName, "property") == 0)
{
// Get name, type, and ID
std::string Name;
EPropertyType Type;
u32 ID;
GetPropertyInfo(pElem, Name, Type, ID);
// Error check
if (Type == eInvalidProperty)
{
const char *pType = pElem->Attribute("type");
if (pType)
Log::Error("Invalid property type in " + TemplateName + " template: " + pType);
else
Log::Error("Property " + Name + " in " + TemplateName + " template has no type");
}
// Load single-property struct
if (Type == eStructProperty)
{
CStructTemplate *pStruct = LoadStructTemplate(pElem, TemplateName);
pStruct->mIsSingleProperty = true;
return pStruct;
}
// Load file property
else if (Type == eFileProperty)
{
// Fetch file extension
CFileTemplate *pFile = nullptr;
const char *pExt = pElem->Attribute("ext");
if (pExt)
pFile = new CFileTemplate(Name, ID, StringUtil::Tokenize(pExt, ","));
else
{
CFileTemplate *pSrc = (CFileTemplate*) mpMaster->GetProperty(ID);
if (pSrc)
pFile = new CFileTemplate(Name, ID, pSrc->Extensions());
}
// Check if extensions are valid
if (!pFile)
{
Log::Error("File property " + Name + " in " + TemplateName + " template has no extension");
return nullptr;
}
else
return pFile;
}
// Load regular property
else
{
CPropertyTemplate *pProperty = new CPropertyTemplate(Type, Name, ID);
return pProperty;
}
}
return nullptr;
}
CStructTemplate* CTemplateLoader::LoadStructTemplate(tinyxml2::XMLElement *pElem, const std::string& TemplateName)
{
CStructTemplate *pStruct = new CStructTemplate();
// Get name, type, and ID
GetPropertyInfo(pElem, pStruct->mPropName, pStruct->mPropType, pStruct->mPropID);
const char *pTemp = pElem->Attribute("template");
if (!pTemp) pTemp = pElem->Attribute("target");
// Get source template from the master property list, if it exists
CStructTemplate *pSrc = (CStructTemplate*) mpMaster->GetProperty(pStruct->mPropID);
// "IsSingleProperty" means, does the struct contain multiple properties, each with separate IDs
// or does the entire struct as a whole count as just one property?
if (pSrc)
pStruct->mIsSingleProperty = pSrc->IsSingleProperty();
else
pStruct->mIsSingleProperty = (strcmp(pElem->Name(), "property") == 0);
// Read struct children. Priority is [Embedded -> Template -> Master].
// Embedded
if (!pElem->NoChildren())
{
// Get count
const char *pCount = pElem->Attribute("count");
if (pCount)
pStruct->mPropertyCount = std::stoul(pCount);
// Parse sub-elements
tinyxml2::XMLElement *pChild = pElem->FirstChildElement();
while (pChild)
{
CPropertyTemplate *pProp = LoadPropertyTemplate(pChild, TemplateName);
CPropertyTemplate *pProp = LoadPropertyTemplate(pChild, templateName);
if (pProp)
pStruct->mProperties.push_back(pProp);
pTemp->mProperties.push_back(pProp);
pChild = pChild->NextSiblingElement();
}
}
CPropertyTemplate* CTemplateLoader::LoadPropertyTemplate(tinyxml2::XMLElement *pElem, const std::string& templateName)
{
const char *kpIDStr = pElem->Attribute("ID");
const char *kpNameStr = pElem->Attribute("name");
const char *kpTypeStr = pElem->Attribute("type");
const char *kpExtensionsStr = pElem->Attribute("ext");
const char *kpTemplateStr = pElem->Attribute("template");
// Get ID + name, find source template if it exists
u32 ID = StringUtil::ToInt32(kpIDStr);
CPropertyTemplate *pSource = nullptr;
std::string name;
if (mpMaster->HasPropertyList())
pSource = mpMaster->GetProperty(ID);
if (kpNameStr)
name = kpNameStr;
else if (pSource)
name = pSource->Name();
else
name = StringUtil::ToHexString(ID);
// Load Property
if (strcmp(pElem->Name(), "property") == 0)
{
CPropertyTemplate *pProp;
EPropertyType type = eInvalidProperty;
// Type
if (kpTypeStr)
type = PropStringToPropEnum(kpTypeStr);
else if (pSource)
type = pSource->Type();
// File property
if (type == eFileProperty)
{
CStringList extensions;
if (kpExtensionsStr)
extensions = StringUtil::Tokenize(kpExtensionsStr, ",");
else if (pSource)
extensions = static_cast<CFileTemplate*>(pSource)->Extensions();
pProp = new CFileTemplate(name, ID, extensions);
}
// Template
else if (pTemp)
// Regular property
else
pProp = new CPropertyTemplate(type, name, ID);
return pProp;
}
// Load Struct
else if (strcmp(pElem->Name(), "struct") == 0)
{
// Get handle for XML
std::string TempPath = mMasterDir + pTemp;
CStructTemplate *pStruct = new CStructTemplate();
tinyxml2::XMLDocument TempXML;
TempXML.LoadFile(TempPath.c_str());
pStruct->mPropID = ID;
if (TempXML.Error())
Log::Error("Couldn't open struct template: " + TempPath);
// Read children properties
// Priority: [Embedded] -> [Template] -> [Master]
// Embedded
if (!pElem->NoChildren())
LoadStructProperties(pElem, pStruct, templateName);
// Template
else if (kpTemplateStr)
{
std::string tempPath = mMasterDir + kpTemplateStr;
tinyxml2::XMLDocument structXML;
structXML.LoadFile(tempPath.c_str());
if (structXML.Error())
Log::Error("Couldn't open struct XML: " + mMasterDir + kpTemplateStr);
else
{
tinyxml2::XMLElement *pVersionElem = TempXML.FirstChildElement()->FirstChildElement("version");
tinyxml2::XMLElement *pPropertiesElem = TempXML.FirstChildElement()->FirstChildElement("properties");
tinyxml2::XMLElement *pRoot = structXML.FirstChildElement("struct");
pStruct->mSourceFile = kpTemplateStr;
if (!pVersionElem) Log::Error("Struct template has no version element: " + TempPath);
if (!pPropertiesElem) Log::Error("Struct template has no properties element: " + TempPath);
if (pRoot->Attribute("type"))
pStruct->mIsSingleProperty = (strcmp(pRoot->Attribute("type"), "single") == 0);
if (pVersionElem && pPropertiesElem)
{
// Get version number
u32 VersionNumber = std::stoul(pVersionElem->GetText());
if (pRoot->Attribute("name"))
pStruct->mPropName = pRoot->Attribute("name");
// Get property count
const char *pCount = pPropertiesElem->Attribute("count");
if (pCount)
pStruct->mPropertyCount = std::stoul(pCount);
// Parse properties
tinyxml2::XMLElement *pPropElem = pPropertiesElem->FirstChildElement();
while (pPropElem)
{
if (!pPropElem) break;
CPropertyTemplate *pProp = LoadPropertyTemplate(pPropElem, TemplateName);
if (pProp)
pStruct->mProperties.push_back(pProp);
pPropElem = pPropElem->NextSiblingElement();
}
}
LoadStructProperties(pRoot, pStruct, templateName);
}
}
// Master
else if (pSrc)
else if (pSource)
{
pStruct->mPropertyCount = pSrc->TemplateCount();
CStructTemplate *pSourceStruct = static_cast<CStructTemplate*>(pSource);
for (u32 p = 0; p < pSrc->Count(); p++)
pStruct->mProperties.push_back(pSrc->PropertyByIndex(p));
for (u32 iProp = 0; iProp < pSourceStruct->Count(); iProp++)
pStruct->mProperties.push_back(pSourceStruct->PropertyByIndex(iProp));
}
// If it's none of these things, then it probably has no children because it's a property list entry
// If it's none of these, then it probably has no children because it's a property list entry.
// Single property?
if (kpTypeStr)
pStruct->mIsSingleProperty = (strcmp(kpTypeStr, "single") == 0);
else if (pSource)
pStruct->mIsSingleProperty = static_cast<CStructTemplate*>(pSource)->IsSingleProperty();
// Name
if (!name.empty())
pStruct->mPropName = name;
return pStruct;
}
void CTemplateLoader::GetPropertyInfo(tinyxml2::XMLElement *pElem, std::string& Name, EPropertyType& Type, u32& ID)
{
const char *pNameStr = pElem->Attribute("name");
const char *pTypeStr = pElem->Attribute("type");
const char *pIDStr = pElem->Attribute("ID");
bool IsBaseStruct = (strcmp(pElem->Name(), "properties") == 0);
// Fetch source template, if available
CPropertyTemplate *pSrcTmp;
if (pIDStr)
{
ID = std::stoul(pIDStr, 0, 16);
pSrcTmp = mpMaster->GetProperty(ID);
}
else
{
ID = 0xFFFFFFFF;
pSrcTmp = nullptr;
}
// Get name
if (pNameStr)
Name = pNameStr;
else if (pSrcTmp)
Name = pSrcTmp->Name();
else if (IsBaseStruct)
Name = "Base";
else
Name = "";
// Get type
if (strcmp(pElem->Name(), "struct") == 0)
Type = eStructProperty;
else if (IsBaseStruct)
Type = eStructProperty;
else if (pTypeStr)
Type = PropStringToPropEnum(pTypeStr);
else if (pSrcTmp)
Type = pSrcTmp->Type();
else
Type = eInvalidProperty;
return nullptr;
}
// ************ SCRIPT OBJECT ************
CScriptTemplate* CTemplateLoader::LoadScriptTemplate(tinyxml2::XMLDocument *pDoc, const std::string& TemplateName, u32 ObjectID)
CScriptTemplate* CTemplateLoader::LoadScriptTemplate(tinyxml2::XMLDocument *pDoc, const std::string& templateName, u32 objectID)
{
tinyxml2::XMLElement *pBaseElement = pDoc->FirstChildElement();
CScriptTemplate *pScript = new CScriptTemplate(mpMaster);
pScript->mObjectID = ObjectID;
pScript->mTemplateName = pBaseElement->Name();
pScript->mObjectID = objectID;
// Properties?
tinyxml2::XMLElement *pProperties = pBaseElement->FirstChildElement("properties");
if (pProperties)
tinyxml2::XMLElement *pRoot = pDoc->FirstChildElement("ScriptTemplate");
// Name
tinyxml2::XMLElement *pNameElem = pRoot->FirstChildElement("name");
if (pNameElem)
pScript->mTemplateName = pNameElem->GetText();
// Properties
tinyxml2::XMLElement *pPropsElem = pRoot->FirstChildElement("properties");
while (pPropsElem)
{
pScript->mpBaseStruct = LoadStructTemplate(pBaseElement->FirstChildElement("properties"), TemplateName);
pScript->mpBaseStruct->SetName(pScript->mTemplateName);
CScriptTemplate::SPropertySet set;
const char *kpVersion = pPropsElem->Attribute("version");
set.SetName = (kpVersion ? kpVersion : "");
set.pBaseStruct = new CStructTemplate();
set.pBaseStruct->mIsSingleProperty = false;
set.pBaseStruct->mPropID = -1;
set.pBaseStruct->mPropName = pScript->mTemplateName;
LoadStructProperties(pPropsElem, set.pBaseStruct, pScript->mTemplateName);
pScript->mPropertySets.push_back(set);
pPropsElem = pPropsElem->NextSiblingElement("properties");
}
// Attribs?
tinyxml2::XMLElement *pAttributes = pBaseElement->FirstChildElement("attributes");
if (pAttributes) LoadScriptAttribs(pAttributes, pScript);
// Editor Parameters
tinyxml2::XMLElement *pEditor = pRoot->FirstChildElement("editor");
if (pEditor)
{
// Editor Properties
tinyxml2::XMLElement *pEdProperties = pEditor->FirstChildElement("properties");
tinyxml2::XMLElement *pEdProp = pEdProperties->FirstChildElement("property");
while (pEdProp)
{
const char *kpName = pEdProp->Attribute("name");
const char *kpID = pEdProp->Attribute("ID");
if (kpName && kpID)
{
if (strcmp(kpName, "InstanceName") == 0)
pScript->mNameIDString = kpID;
else if (strcmp(kpName, "Position") == 0)
pScript->mPositionIDString = kpID;
else if (strcmp(kpName, "Rotation") == 0)
pScript->mRotationIDString = kpID;
else if (strcmp(kpName, "Scale") == 0)
pScript->mScaleIDString = kpID;
else if (strcmp(kpName, "Active") == 0)
pScript->mActiveIDString = kpID;
else if (strcmp(kpName, "LightParameters") == 0)
pScript->mLightParametersIDString = kpID;
}
pEdProp = pEdProp->NextSiblingElement("property");
}
// Editor Assets
tinyxml2::XMLElement *pEdAssets = pEditor->FirstChildElement("assets");
tinyxml2::XMLElement *pAsset = pEdAssets->FirstChildElement();
while (pAsset)
{
const char *kpSource = pAsset->Attribute("source");
const char *kpID = pAsset->GetText();
if (kpSource && kpID)
{
CScriptTemplate::SEditorAsset asset;
if (strcmp(pAsset->Name(), "animparams") == 0)
asset.AssetType = CScriptTemplate::SEditorAsset::eAnimParams;
else if (strcmp(pAsset->Name(), "model") == 0)
asset.AssetType = CScriptTemplate::SEditorAsset::eModel;
else
{
pAsset = pAsset->NextSiblingElement();
continue;
}
if (strcmp(kpSource, "property") == 0)
asset.AssetSource = CScriptTemplate::SEditorAsset::eProperty;
else if (strcmp(kpSource, "file") == 0)
asset.AssetSource = CScriptTemplate::SEditorAsset::eFile;
else
{
pAsset = pAsset->NextSiblingElement();
continue;
}
const char *kpForce = pAsset->Attribute("force");
if (kpForce)
asset.ForceNodeIndex = StringUtil::ToInt32(kpForce);
else
asset.ForceNodeIndex = -1;
asset.AssetLocation = kpID;
pScript->mAssets.push_back(asset);
}
pAsset = pAsset->NextSiblingElement();
}
// Rotation
tinyxml2::XMLElement *pRotType = pEditor->FirstChildElement("rotation_type");
if (pRotType)
{
const char *kpType = pRotType->GetText();
if (kpType)
{
if (strcmp(kpType, "disabled") == 0) pScript->mRotationType = CScriptTemplate::eRotationDisabled;
else pScript->mRotationType = CScriptTemplate::eRotationEnabled;
}
}
// Scale
tinyxml2::XMLElement *pScaleType = pEditor->FirstChildElement("scale_type");
if (pScaleType)
{
const char *kpType = pScaleType->GetText();
if (kpType)
{
if (strcmp(kpType, "disabled") == 0) pScript->mScaleType = CScriptTemplate::eScaleDisabled;
else if (strcmp(kpType, "volume") == 0) pScript->mScaleType = CScriptTemplate::eScaleVolume;
else pScript->mScaleType = CScriptTemplate::eScaleEnabled;
}
}
// Preview Volume
if (pScript->mScaleType == CScriptTemplate::eScaleVolume)
{
tinyxml2::XMLElement *pVolume = pEditor->FirstChildElement("preview_volume");
// Lambda to avoid duplicating volume shape code
auto GetVolumeType = [](const char *kpType) -> EVolumeShape {
if (strcmp(kpType, "none") == 0) return eNoShape;
if (strcmp(kpType, "Box") == 0) return eBoxShape;
if (strcmp(kpType, "AxisAlignedBox") == 0) return eAxisAlignedBoxShape;
if (strcmp(kpType, "Ellipsoid") == 0) return eEllipsoidShape;
if (strcmp(kpType, "Cylinder") == 0) return eCylinderShape;
if (strcmp(kpType, "CylinderLarge") == 0) return eCylinderLargeShape;
if (strcmp(kpType, "Conditional") == 0) return eConditionalShape;
return eInvalidShape;
};
const char *kpShape = pVolume->Attribute("shape");
if (kpShape)
pScript->mVolumeShape = GetVolumeType(kpShape);
// Conditional
if (pScript->mVolumeShape == eConditionalShape)
{
const char *kpID = pVolume->Attribute("propertyID");
if (kpID)
{
pScript->mVolumeConditionIDString = kpID;
tinyxml2::XMLElement *pCondition = pVolume->FirstChildElement("condition");
while (pCondition)
{
const char *kpConditionValue = pCondition->Attribute("value");
const char *kpConditionShape = pCondition->Attribute("shape");
if (kpConditionValue && kpConditionShape)
{
CScriptTemplate::SVolumeCondition condition;
condition.Shape = GetVolumeType(kpConditionShape);
if (strcmp(kpConditionValue, "true") == 0)
condition.Value = 1;
else if (strcmp(kpConditionValue, "false") == 0)
condition.Value = 0;
else
condition.Value = StringUtil::ToInt32(kpConditionValue);
pScript->mVolumeConditions.push_back(condition);
}
pCondition = pCondition->NextSiblingElement("condition");
}
}
}
}
}
return pScript;
}
void CTemplateLoader::LoadScriptAttribs(tinyxml2::XMLElement *pElem, CScriptTemplate *pScript)
{
// Parsing attribs
tinyxml2::XMLElement *pAttrib = pElem->FirstChildElement("attrib");
while (pAttrib)
{
CAttribTemplate Attrib;
Attrib.ExtraSettings = -1;
const char *pType = pAttrib->Attribute("type");
if (!pType)
Log::Error("An attrib in " + pScript->TemplateName() + " template has no type set");
else
{
// Initialize attrib template values
Attrib.AttribType = AttribStringToAttribEnum(pType);
if (Attrib.AttribType == eInvalidAttrib)
Log::Error("An attrib in " + pScript->TemplateName() + " template has an invalid type: " + pType);
else
{
bool NoError = ParseAttribExtra(pAttrib, Attrib, pScript->TemplateName());
if (NoError)
{
Attrib.AttribTarget = pAttrib->Attribute("target");
CPropertyTemplate *pTargetProp = nullptr;
if (Attrib.ResFile.empty())
{
pTargetProp = pScript->mpBaseStruct->PropertyByName(Attrib.AttribTarget); // Ensure target is valid if it points to a property
if (!pTargetProp)
Log::Error("An attrib in " + pScript->TemplateName() + " template of type " + pType + " has an invalid target: " + Attrib.AttribTarget);
}
if ((pTargetProp) || (!Attrib.ResFile.empty()))
pScript->mAttribs.push_back(Attrib);
}
}
}
pAttrib = pAttrib->NextSiblingElement("attrib");
}
}
bool CTemplateLoader::ParseAttribExtra(tinyxml2::XMLElement *pElem, CAttribTemplate& Attrib, const std::string& TemplateName)
{
// This function is for parsing extra tags that some attribs have, such as "source" for models or "forcenode" for animsets
// AnimSet
if (Attrib.Type() == eAnimSetAttrib)
{
// Check res source
const char *pSource = pElem->Attribute("source");
if ((pSource) && (strcmp(pSource, "file") == 0))
{
const char *pFileName = pElem->Attribute("target");
if (pFileName)
Attrib.ResFile = std::string("../resources/") + pFileName;
else
{
Log::Error("An attrib in " + TemplateName + " template of type animset has an invalid target: \"" + pFileName + "\"");
return false;
}
}
// Check forcenode
const char *pForceNode = pElem->Attribute("forcenode");
if (pForceNode)
{
if (!StringUtil::IsHexString(pForceNode))
{
Log::Error("An animset attrib in " + TemplateName + " has an invalid \"forcenode\" setting: \"" + pForceNode + "\"");
return false;
}
else
Attrib.ExtraSettings = std::stoul(pForceNode);
}
}
// Model
if (Attrib.Type() == eModelAttrib)
{
// Check res source
const char *pSource = pElem->Attribute("source");
if ((pSource) && (strcmp(pSource, "file") == 0))
{
const char *pFileName = pElem->Attribute("target");
if (pFileName)
Attrib.ResFile = std::string("../resources/") + pFileName;
else
{
Log::Error("An attrib in " + TemplateName + " template of type model has an invalid target: \"" + pFileName + "\"");
return false;
}
}
}
// Volume
if (Attrib.Type() == eVolumeAttrib)
{
const char *pShape = pElem->Attribute("shape");
if (pShape)
{
if (strcmp(pShape, "Box") == 0)
Attrib.ExtraSettings = 0;
else if (strcmp(pShape, "OrientedBox") == 0)
Attrib.ExtraSettings = 1;
else if (strcmp(pShape, "Sphere") == 0)
Attrib.ExtraSettings = 2;
else
{
Log::Error("Volume attrib in " + TemplateName + " template has an invalid shape: " + pShape);
return false;
}
}
else
{
Log::Error("Volume attrib in " + TemplateName + " template has no shape attribute");
return false;
}
}
return true;
}
// ************ MASTER ************
void CTemplateLoader::LoadMasterTemplate(tinyxml2::XMLDocument *pDoc)
{
tinyxml2::XMLNode *pNode = pDoc->FirstChild()->NextSibling()->FirstChild();
tinyxml2::XMLElement *pRoot = pDoc->FirstChildElement("MasterTemplate");
mpMaster->mVersion = StringUtil::ToInt32(pRoot->Attribute("version"));
while (pNode)
tinyxml2::XMLElement *pElem = pRoot->FirstChildElement();
while (pElem)
{
tinyxml2::XMLElement *pElem = pNode->ToElement();
// Version
if (strcmp(pElem->Name(), "version") == 0)
{
u32 Version = std::stoul(pElem->GetText());
mpMaster->mVersion = Version;
}
// Properties
else if (strcmp(pElem->Name(), "properties") == 0)
if (strcmp(pElem->Name(), "properties") == 0)
{
std::string PropListPath = mMasterDir + pElem->GetText();
std::string propListPath = mMasterDir + pElem->GetText();
tinyxml2::XMLDocument PropListXML;
PropListXML.LoadFile(PropListPath.c_str());
tinyxml2::XMLDocument propListXML;
propListXML.LoadFile(propListPath.c_str());
if (PropListXML.Error())
Log::Error("Couldn't open property list: " + PropListPath);
if (propListXML.Error())
Log::Error("Couldn't open property list: " + propListPath);
else
LoadPropertyList(&PropListXML, PropListPath);
LoadPropertyList(&propListXML, propListPath);
}
// Objects
else if (strcmp(pElem->Name(), "objects") == 0)
{
// Iterate categories
tinyxml2::XMLElement *pCat = pElem->FirstChildElement("category");
while (pCat)
{
CTemplateCategory Cat(pCat->Attribute("name"));
tinyxml2::XMLElement *pObj = pCat->FirstChildElement("object");
tinyxml2::XMLElement *pObj = pElem->FirstChildElement("object");
while (pObj)
{
// ID can either be a hex number or an ASCII fourCC
std::string StrID = pObj->Attribute("ID");
std::string strID = pObj->Attribute("ID");
u32 ID;
if (StringUtil::IsHexString(StrID, true))
ID = std::stoul(StrID, 0, 16);
if (StringUtil::IsHexString(strID, true))
ID = StringUtil::ToInt32(strID);
else
ID = CFourCC(StrID).ToLong();
ID = CFourCC(strID).ToLong();
// Load up the object
std::string TemplateName = pObj->Attribute("template");
std::string TemplatePath = mMasterDir + TemplateName;
std::string templateName = pObj->Attribute("template");
std::string templatePath = mMasterDir + templateName;
tinyxml2::XMLDocument ObjectXML;
ObjectXML.LoadFile(TemplatePath.c_str());
tinyxml2::XMLDocument scriptXML;
scriptXML.LoadFile(templatePath.c_str());
if (ObjectXML.Error())
Log::Error("Couldn't open script template: " + TemplatePath);
if (scriptXML.Error())
Log::Error("Couldn't open script template: " + templatePath);
else
{
CScriptTemplate *pTemp = LoadScriptTemplate(&ObjectXML, TemplateName, ID);
CScriptTemplate *pTemp = LoadScriptTemplate(&scriptXML, templateName, ID);
if (pTemp)
{
pTemp->mSourceFile = templateName;
mpMaster->mTemplates[ID] = pTemp;
Cat.AddTemplate(pTemp);
}
}
pObj = pObj->NextSiblingElement("object");
}
Cat.Sort();
mpMaster->mCategories.push_back(Cat);
pCat = pCat->NextSiblingElement("category");
}
}
// States
@ -481,16 +415,16 @@ void CTemplateLoader::LoadMasterTemplate(tinyxml2::XMLDocument *pDoc)
while (pState)
{
std::string StrID = pState->Attribute("ID");
u32 StateID;
std::string strID = pState->Attribute("ID");
u32 stateID;
if (StringUtil::IsHexString(StrID, true))
StateID = std::stoul(StrID, 0, 16);
if (StringUtil::IsHexString(strID, true))
stateID = StringUtil::ToInt32(strID);
else
StateID = CFourCC(StrID).ToLong();
stateID = CFourCC(strID).ToLong();
std::string StateName = pState->Attribute("name");
mpMaster->mStates[StateID] = StateName;
std::string stateName = pState->Attribute("name");
mpMaster->mStates[stateID] = stateName;
pState = pState->NextSiblingElement("state");
}
}
@ -502,37 +436,39 @@ void CTemplateLoader::LoadMasterTemplate(tinyxml2::XMLDocument *pDoc)
while (pMessage)
{
std::string StrID = pMessage->Attribute("ID");
u32 MessageID;
std::string strID = pMessage->Attribute("ID");
u32 messageID;
if (StringUtil::IsHexString(StrID, true))
MessageID = std::stoul(StrID, 0, 16);
if (StringUtil::IsHexString(strID, true))
messageID = StringUtil::ToInt32(strID);
else
MessageID = CFourCC(StrID).ToLong();
messageID = CFourCC(strID).ToLong();
std::string MessageName = pMessage->Attribute("name");
mpMaster->mMessages[MessageID] = MessageName;
std::string messageName = pMessage->Attribute("name");
mpMaster->mMessages[messageID] = messageName;
pMessage = pMessage->NextSiblingElement("message");
}
}
pNode = pNode->NextSibling();
pElem = pElem->NextSiblingElement();
}
}
void CTemplateLoader::LoadPropertyList(tinyxml2::XMLDocument *pDoc, const std::string& ListName)
void CTemplateLoader::LoadPropertyList(tinyxml2::XMLDocument *pDoc, const std::string& listName)
{
tinyxml2::XMLElement *pElem = pDoc->FirstChildElement()->FirstChildElement();
while (pElem)
{
CPropertyTemplate *pProp = LoadPropertyTemplate(pElem, ListName);
CPropertyTemplate *pProp = LoadPropertyTemplate(pElem, listName);
if (pProp)
mpMaster->mPropertyList[pProp->PropertyID()] = pProp;
pElem = pElem->NextSiblingElement();
}
mpMaster->mHasPropList = true;
}
CMasterTemplate* CTemplateLoader::LoadGame(tinyxml2::XMLNode *pNode)
@ -561,9 +497,15 @@ CMasterTemplate* CTemplateLoader::LoadGame(tinyxml2::XMLNode *pNode)
MasterXML.LoadFile(MasterPath.c_str());
if (MasterXML.Error())
{
Log::Error("Couldn't open master template at " + MasterPath + " - error " + std::to_string(MasterXML.ErrorID()));
}
else
{
LoadMasterTemplate(&MasterXML);
mpMaster->mSourceFile = pGameElem->GetText();
}
}
pGameElem = pGameElem->NextSiblingElement();
}
@ -575,17 +517,17 @@ CMasterTemplate* CTemplateLoader::LoadGame(tinyxml2::XMLNode *pNode)
// ************ PUBLIC ************
void CTemplateLoader::LoadGameList()
{
static const std::string TemplatesDir = "../templates/";
static const std::string GameListPath = TemplatesDir + "GameList.xml";
static const std::string skTemplatesDir = "../templates/";
static const std::string skGameListPath = skTemplatesDir + "GameList.xml";
Log::Write("Loading game list");
// Load Game List XML
tinyxml2::XMLDocument GameListXML;
GameListXML.LoadFile(GameListPath.c_str());
GameListXML.LoadFile(skGameListPath.c_str());
if (GameListXML.Error())
{
Log::Error("Couldn't open game list at " + GameListPath + " - error " + std::to_string(GameListXML.ErrorID()));
Log::Error("Couldn't open game list at " + skGameListPath + " - error " + std::to_string(GameListXML.ErrorID()));
return;
}
@ -606,7 +548,7 @@ void CTemplateLoader::LoadGameList()
// Games
else if (strcmp(pElement->Name(), "game") == 0)
{
CTemplateLoader Loader(TemplatesDir);
CTemplateLoader Loader(skTemplatesDir);
CMasterTemplate *pMaster = Loader.LoadGame(pNode);
if (!pMaster->IsLoadedSuccessfully())

View File

@ -12,21 +12,18 @@ class CTemplateLoader
std::string mMasterDir;
// Constructor
CTemplateLoader(const std::string& TemplatesDir) : mTemplatesDir(TemplatesDir) {}
CTemplateLoader(const std::string& templatesDir) : mTemplatesDir(templatesDir) {}
// Load Property
CPropertyTemplate* LoadPropertyTemplate(tinyxml2::XMLElement *pElem, const std::string& TemplateName);
CStructTemplate* LoadStructTemplate(tinyxml2::XMLElement *pElem, const std::string& TemplateName);
void GetPropertyInfo(tinyxml2::XMLElement *pElem, std::string& Name, EPropertyType& Type, u32& ID);
void LoadStructProperties(tinyxml2::XMLElement *pElem, CStructTemplate *pTemp, const std::string& templateName);
CPropertyTemplate* LoadPropertyTemplate(tinyxml2::XMLElement *pElem, const std::string& templateName);
// Load Script Object
CScriptTemplate* LoadScriptTemplate(tinyxml2::XMLDocument *pDoc, const std::string& TemplateName, u32 ObjectID);
void LoadScriptAttribs(tinyxml2::XMLElement *pElem, CScriptTemplate *pScript);
bool ParseAttribExtra(tinyxml2::XMLElement *pElem, CAttribTemplate& Attrib, const std::string& TemplateName);
CScriptTemplate* LoadScriptTemplate(tinyxml2::XMLDocument *pDoc, const std::string& templateName, u32 objectID);
// Load Master
void LoadMasterTemplate(tinyxml2::XMLDocument *pDoc);
void LoadPropertyList(tinyxml2::XMLDocument *pDoc, const std::string& ListName);
void LoadPropertyList(tinyxml2::XMLDocument *pDoc, const std::string& listName);
CMasterTemplate* LoadGame(tinyxml2::XMLNode *pNode);
public:

View File

@ -6,6 +6,7 @@ CMasterTemplate::CMasterTemplate()
{
mVersion = 0;
mFullyLoaded = false;
mHasPropList = false;
}
CMasterTemplate::~CMasterTemplate()
@ -92,15 +93,17 @@ CPropertyTemplate* CMasterTemplate::GetProperty(u32 PropertyID)
return nullptr;
}
bool CMasterTemplate::HasPropertyList()
{
return mHasPropList;
}
bool CMasterTemplate::IsLoadedSuccessfully()
{
return mFullyLoaded;
}
// ************ STATIC ************
std::unordered_map<EGame, CMasterTemplate*> CMasterTemplate::smMasterMap;
u32 CMasterTemplate::smGameListVersion;
CMasterTemplate* CMasterTemplate::GetMasterForGame(EGame Game)
{
auto it = smMasterMap.find(Game);
@ -110,3 +113,16 @@ CMasterTemplate* CMasterTemplate::GetMasterForGame(EGame Game)
else
return nullptr;
}
std::list<CMasterTemplate*> CMasterTemplate::GetMasterList()
{
std::list<CMasterTemplate*> list;
for (auto it = smMasterMap.begin(); it != smMasterMap.end(); it++)
list.push_back(it->second);
return list;
}
std::map<EGame, CMasterTemplate*> CMasterTemplate::smMasterMap;
u32 CMasterTemplate::smGameListVersion;

View File

@ -5,27 +5,29 @@
#include "CTemplateCategory.h"
#include "../EFormatVersion.h"
#include <Common/types.h>
#include <unordered_map>
#include <map>
#include <tinyxml2.h>
class CMasterTemplate
{
friend class CTemplateLoader;
friend class CTemplateWriter;
EGame mGame;
std::string mGameName;
std::string mSourceFile;
u32 mVersion;
bool mFullyLoaded;
std::unordered_map<u32, CScriptTemplate*> mTemplates;
std::unordered_map<u32, std::string> mStates;
std::unordered_map<u32, std::string> mMessages;
std::map<u32, CScriptTemplate*> mTemplates;
std::map<u32, std::string> mStates;
std::map<u32, std::string> mMessages;
std::vector<CTemplateCategory> mCategories;
bool mHasPropList;
std::unordered_map<u32, CPropertyTemplate*> mPropertyList;
std::map<u32, CPropertyTemplate*> mPropertyList;
static std::unordered_map<EGame, CMasterTemplate*> smMasterMap;
static std::map<EGame, CMasterTemplate*> smMasterMap;
static u32 smGameListVersion;
public:
@ -45,9 +47,11 @@ public:
std::string MessageByID(const CFourCC& MessageID);
std::string MessageByIndex(u32 Index);
CPropertyTemplate* GetProperty(u32 PropertyID);
bool HasPropertyList();
bool IsLoadedSuccessfully();
static CMasterTemplate* GetMasterForGame(EGame Game);
static std::list<CMasterTemplate*> GetMasterList();
};
// ************ INLINE ************

View File

@ -0,0 +1,121 @@
#include "CProperty.h"
// ************ CPropertyStruct ************
CPropertyStruct::~CPropertyStruct()
{
for (auto it = mProperties.begin(); it != mProperties.end(); it++)
delete *it;
}
CPropertyBase* CPropertyStruct::PropertyByIndex(u32 index)
{
return mProperties[index];
}
CPropertyBase* CPropertyStruct::PropertyByID(u32 ID)
{
for (auto it = mProperties.begin(); it != mProperties.end(); it++)
{
if ((*it)->ID() == ID)
return *it;
}
return nullptr;
}
CPropertyBase* CPropertyStruct::PropertyByIDString(const TIDString& str)
{
// Resolve namespace
std::string::size_type nsStart = str.find_first_of(":");
std::string::size_type propStart = nsStart + 1;
// String has namespace; the requested property is within a struct
if (nsStart != std::string::npos)
{
std::string strStructID = str.substr(0, nsStart);
if (!StringUtil::IsHexString(strStructID)) return nullptr;
u32 structID = StringUtil::ToInt32(strStructID);
std::string propName = str.substr(propStart, str.length() - propStart);
CPropertyStruct *pStruct = StructByID(structID);
if (!pStruct) return nullptr;
else return pStruct->PropertyByIDString(propName);
}
// No namespace; fetch the property from this struct
else
{
if (StringUtil::IsHexString(str))
return PropertyByID(StringUtil::ToInt32(str));
else
return nullptr;
}
}
CPropertyStruct* CPropertyStruct::StructByIndex(u32 index)
{
CPropertyBase *pProp = PropertyByIndex(index);
if (pProp->Type() == eStructProperty)
return static_cast<CPropertyStruct*>(pProp);
else
return nullptr;
}
CPropertyStruct* CPropertyStruct::StructByID(u32 ID)
{
CPropertyBase *pProp = PropertyByID(ID);
if (pProp->Type() == eStructProperty)
return static_cast<CPropertyStruct*>(pProp);
else
return nullptr;
}
CPropertyStruct* CPropertyStruct::StructByIDString(const TIDString& str)
{
CPropertyBase *pProp = PropertyByIDString(str);
if (pProp->Type() == eStructProperty)
return static_cast<CPropertyStruct*>(pProp);
else
return nullptr;
}
// ************ STATIC ************
CPropertyStruct* CPropertyStruct::CopyFromTemplate(CStructTemplate *pTemp)
{
CPropertyStruct *pStruct = new CPropertyStruct();
pStruct->mpTemplate = pTemp;
pStruct->Reserve(pTemp->Count());
for (u32 iProp = 0; iProp < pTemp->Count(); iProp++)
{
CPropertyTemplate *pPropTemp = pTemp->PropertyByIndex(iProp);
CPropertyBase *pProp = nullptr;
switch (pPropTemp->Type())
{
case eBoolProperty: pProp = new CBoolProperty(false); break;
case eByteProperty: pProp = new CByteProperty(0); break;
case eShortProperty: pProp = new CShortProperty(0); break;
case eLongProperty: pProp = new CLongProperty(0); break;
case eFloatProperty: pProp = new CFloatProperty(0.f); break;
case eStringProperty: pProp = new CStringProperty(""); break;
case eVector3Property: pProp = new CVector3Property(CVector3f::skZero); break;
case eColorProperty: pProp = new CColorProperty(CColor::skBlack); break;
case eFileProperty: pProp = new CFileProperty(); break;
case eArrayProperty: pProp = new CArrayProperty(); break;
case eUnknownProperty: pProp = new CUnknownProperty(); break;
case eStructProperty: pProp = CPropertyStruct::CopyFromTemplate(static_cast<CStructTemplate*>(pPropTemp)); break;
}
if (pProp)
{
pProp->SetTemplate(pPropTemp);
pStruct->mProperties.push_back(pProp);
}
}
return pStruct;
}

View File

@ -7,7 +7,7 @@
* It's a bit hard to read, should be reorganized at some point
*/
#include "../CResource.h"
#include "CScriptTemplate.h"
#include "CPropertyTemplate.h"
#include "EPropertyType.h"
#include <Common/CColor.h>
#include <Common/CVector3f.h>
@ -15,6 +15,10 @@
#include <string>
#include <list>
class CScriptTemplate;
typedef std::string TIDString;
/*
* CPropertyBase is the base class, containing just some virtual function definitions
* Virtual destructor is mainly there to make cleanup easy; don't need to cast to delete
@ -23,14 +27,14 @@ class CPropertyBase
{
friend class CScriptLoader;
protected:
CPropertyTemplate *tmp;
CPropertyTemplate *mpTemplate;
public:
virtual ~CPropertyBase() {}
virtual EPropertyType Type() = 0;
CPropertyTemplate *Template() { return tmp; }
void SetTemplate(CPropertyTemplate *_tmp) { tmp = _tmp; }
std::string Name() { return tmp->Name(); }
u32 ID() { return tmp->PropertyID(); }
inline virtual EPropertyType Type() = 0;
inline CPropertyTemplate *Template() { return mpTemplate; }
inline void SetTemplate(CPropertyTemplate *_tmp) { mpTemplate = _tmp; }
inline std::string Name() { return mpTemplate->Name(); }
inline u32 ID() { return mpTemplate->PropertyID(); }
};
/*
@ -41,14 +45,14 @@ template <typename t, EPropertyType type>
class __CProperty : public CPropertyBase
{
friend class CScriptLoader;
t Value;
t mValue;
public:
__CProperty() {}
__CProperty(t v) { Set(v); }
~__CProperty() {}
EPropertyType Type() { return type; }
t Get() { return Value; }
void Set(t v) { Value = v; }
inline EPropertyType Type() { return type; }
inline t Get() { return mValue; }
inline void Set(t v) { mValue = v; }
};
typedef __CProperty<bool, eBoolProperty> CBoolProperty;
typedef __CProperty<char, eByteProperty> CByteProperty;
@ -59,6 +63,7 @@ typedef __CProperty<std::string, eStringProperty> CStringProperty;
typedef __CProperty<CVector3f, eVector3Property> CVector3Property;
typedef __CProperty<CColor, eColorProperty> CColorProperty;
typedef __CProperty<CResource*, eFileProperty> CFileProperty;
typedef __CProperty<std::vector<u8>, eArrayProperty> CArrayProperty;
typedef __CProperty<std::vector<u8>, eUnknownProperty> CUnknownProperty;
/*
@ -67,28 +72,28 @@ typedef __CProperty<std::vector<u8>, eUnknownProperty> CUnknownProperty;
template <>
class __CProperty<CResource*, eFileProperty> : public CPropertyBase
{
CResource *Value;
CResource *mValue;
CToken mToken;
public:
__CProperty<CResource*, eFileProperty>() {
Value = nullptr;
mValue = nullptr;
}
__CProperty<CResource*, eFileProperty>(CResource* v) {
Value = v;
mValue = v;
mToken = CToken(v);
}
~__CProperty<CResource*, eFileProperty>() {}
EPropertyType Type() { return eFileProperty; }
CResource* Get() { return Value; }
void Set(CResource *v)
inline EPropertyType Type() { return eFileProperty; }
inline CResource* Get() { return mValue; }
inline void Set(CResource *v)
{
if (Value != v)
if (mValue != v)
{
Value = v;
mValue = v;
mToken = CToken(v);
}
}
@ -104,128 +109,27 @@ public:
class CPropertyStruct : public CPropertyBase
{
friend class CScriptLoader;
std::vector<CPropertyBase*> Properties;
std::vector<CPropertyBase*> mProperties;
public:
// Destructor simply iterates through the list and deletes them. Nothing complicated.
~CPropertyStruct()
{
for (auto it = Properties.begin(); it != Properties.end(); it++)
delete *it;
}
~CPropertyStruct();
// Inline
EPropertyType Type() { return eStructProperty; }
u32 Count() { return Properties.size(); }
void Reserve(u32 amount) { Properties.reserve(amount); }
CPropertyBase* PropertyByIndex(u32 index) { return Properties[index]; }
CPropertyBase* PropertyByName(std::string name)
{
// Resolve namespace
std::string::size_type NsStart = name.find_first_of("::");
std::string::size_type PropStart = NsStart + 2;
inline u32 Count() { return mProperties.size(); }
inline void Reserve(u32 amount) { mProperties.reserve(amount); }
inline CPropertyBase* operator[](u32 index) { return mProperties[index]; }
// Namespace; the requested property is within a struct
if (NsStart != std::string::npos)
{
std::string StructName = name.substr(0, NsStart);
std::string PropName = name.substr(PropStart, name.length() - PropStart);
// Functions
CPropertyBase* PropertyByIndex(u32 index);
CPropertyBase* PropertyByID(u32 ID);
CPropertyBase* PropertyByIDString(const TIDString& str);
CPropertyStruct* StructByIndex(u32 index);
CPropertyStruct* StructByID(u32 ID);
CPropertyStruct* StructByIDString(const TIDString& str);
CPropertyStruct *Struct = StructByName(StructName);
if (!Struct) return nullptr;
else return Struct->PropertyByName(PropName);
}
// No namespace; fetch the property from this struct
else
{
// ID string lookup
if (StringUtil::IsHexString(name))
return PropertyByID(std::stoul(name, 0, 16));
// Name lookup
else
{
for (auto it = Properties.begin(); it != Properties.end(); it++)
{
if ((*it)->Name() == name)
return *it;
}
return nullptr;
}
}
}
CPropertyBase* PropertyByID(u32 ID)
{
for (auto it = Properties.begin(); it != Properties.end(); it++)
{
if ((*it)->ID() == ID)
return *it;
}
return nullptr;
}
CPropertyStruct* StructByIndex(u32 index)
{
CPropertyBase *prop = PropertyByIndex(index);
if (prop->Type() == eStructProperty)
return static_cast<CPropertyStruct*>(prop);
else
return nullptr;
}
CPropertyStruct* StructByName(std::string name)
{
CPropertyBase *prop = PropertyByName(name);
if (prop->Type() == eStructProperty)
return static_cast<CPropertyStruct*>(prop);
else
return nullptr;
}
CPropertyStruct* StructByID(u32 ID)
{
CPropertyBase *prop = PropertyByID(ID);
if (prop->Type() == eStructProperty)
return static_cast<CPropertyStruct*>(prop);
else
return nullptr;
}
inline CPropertyBase* operator[](u32 index) { return Properties[index]; }
static CPropertyStruct* CopyFromTemplate(CStructTemplate *pTemp)
{
CPropertyStruct *pStruct = new CPropertyStruct();
pStruct->tmp = pTemp;
pStruct->Reserve(pTemp->Count());
for (u32 iProp = 0; iProp < pTemp->Count(); iProp++)
{
CPropertyTemplate *pPropTemp = pTemp->PropertyByIndex(iProp);
CPropertyBase *pProp = nullptr;
switch (pPropTemp->Type())
{
case eBoolProperty: pProp = new CBoolProperty(false); break;
case eByteProperty: pProp = new CByteProperty(0); break;
case eShortProperty: pProp = new CShortProperty(0); break;
case eLongProperty: pProp = new CLongProperty(0); break;
case eFloatProperty: pProp = new CFloatProperty(0.f); break;
case eStringProperty: pProp = new CStringProperty(""); break;
case eVector3Property: pProp = new CVector3Property(CVector3f::skZero); break;
case eColorProperty: pProp = new CColorProperty(CColor::skBlack); break;
case eFileProperty: pProp = new CFileProperty(); break;
case eUnknownProperty: pProp = new CUnknownProperty(); break;
case eStructProperty: pProp = CPropertyStruct::CopyFromTemplate(static_cast<CStructTemplate*>(pPropTemp)); break;
}
if (pProp)
{
pProp->SetTemplate(pPropTemp);
pStruct->Properties.push_back(pProp);
}
}
return pStruct;
}
// Static
static CPropertyStruct* CopyFromTemplate(CStructTemplate *pTemp);
};
#endif // CPROPERTY

View File

@ -0,0 +1,169 @@
#include "CPropertyTemplate.h"
#include <iostream>
EPropertyType PropStringToPropEnum(std::string prop)
{
if (prop == "bool") return eBoolProperty;
if (prop == "byte") return eByteProperty;
if (prop == "short") return eShortProperty;
if (prop == "long") return eLongProperty;
if (prop == "float") return eFloatProperty;
if (prop == "string") return eStringProperty;
if (prop == "color") return eColorProperty;
if (prop == "vector3f") return eVector3Property;
if (prop == "file") return eFileProperty;
if (prop == "struct") return eStructProperty;
if (prop == "array") return eArrayProperty;
if (prop == "unknown") return eUnknownProperty;
return eInvalidProperty;
}
std::string PropEnumToPropString(EPropertyType prop)
{
switch (prop)
{
case eBoolProperty: return "bool";
case eByteProperty: return "byte";
case eShortProperty: return "short";
case eLongProperty: return "long";
case eFloatProperty: return "float";
case eStringProperty: return "string";
case eColorProperty: return "color";
case eVector3Property: return "vector3f";
case eFileProperty: return "file";
case eStructProperty: return "struct";
case eArrayProperty: return "array";
case eUnknownProperty: return "unknown";
case eInvalidProperty:
default:
return "invalid";
}
}
/*******************
* CStructTemplate *
*******************/
CStructTemplate::CStructTemplate() : CPropertyTemplate(-1)
{
mIsSingleProperty = false;
mPropType = eStructProperty;
}
CStructTemplate::~CStructTemplate()
{
for (auto it = mProperties.begin(); it != mProperties.end(); it++)
delete *it;
}
// ************ GETTERS ************
EPropertyType CStructTemplate::Type() const
{
return eStructProperty;
}
bool CStructTemplate::IsSingleProperty() const
{
return mIsSingleProperty;
}
u32 CStructTemplate::Count() const
{
return mProperties.size();
}
CPropertyTemplate* CStructTemplate::PropertyByIndex(u32 index)
{
if (mProperties.size() > index)
return mProperties[index];
else
return nullptr;
}
CPropertyTemplate* CStructTemplate::PropertyByID(u32 ID)
{
for (auto it = mProperties.begin(); it != mProperties.end(); it++)
{
if ((*it)->PropertyID() == ID)
return *it;
}
return nullptr;
}
CPropertyTemplate* CStructTemplate::PropertyByIDString(const std::string& str)
{
// Resolve namespace
std::string::size_type nsStart = str.find_first_of("::");
std::string::size_type propStart = nsStart + 2;
// String has namespace; the requested property is within a struct
if (nsStart != std::string::npos)
{
std::string strStructID = str.substr(0, nsStart);
if (!StringUtil::IsHexString(strStructID)) return nullptr;
u32 structID = StringUtil::ToInt32(strStructID);
std::string propName = str.substr(propStart, str.length() - propStart);
CStructTemplate *pStruct = StructByID(structID);
if (!pStruct) return nullptr;
else return pStruct->PropertyByIDString(propName);
}
// No namespace; fetch the property from this struct
else
{
// ID string lookup
if (StringUtil::IsHexString(str))
return PropertyByID(std::stoul(str, 0, 16));
else
return nullptr;
}
}
CStructTemplate* CStructTemplate::StructByIndex(u32 index)
{
CPropertyTemplate *pProp = PropertyByIndex(index);
if (pProp->Type() == eStructProperty)
return static_cast<CStructTemplate*>(pProp);
else
return nullptr;
}
CStructTemplate* CStructTemplate::StructByID(u32 ID)
{
CPropertyTemplate *pProp = PropertyByID(ID);
if (pProp && pProp->Type() == eStructProperty)
return static_cast<CStructTemplate*>(pProp);
else
return nullptr;
}
CStructTemplate* CStructTemplate::StructByIDString(const std::string& str)
{
CPropertyTemplate *pProp = PropertyByIDString(str);
if (pProp && pProp->Type() == eStructProperty)
return static_cast<CStructTemplate*>(pProp);
else
return nullptr;
}
// ************ DEBUG ************
void CStructTemplate::DebugPrintProperties(std::string base)
{
base = base + Name() + "::";
for (auto it = mProperties.begin(); it != mProperties.end(); it++)
{
CPropertyTemplate *tmp = *it;
if (tmp->Type() == eStructProperty)
{
CStructTemplate *tmp2 = static_cast<CStructTemplate*>(tmp);
tmp2->DebugPrintProperties(base);
}
else
std::cout << base << tmp->Name() << "\n";
}
}

View File

@ -0,0 +1,72 @@
#ifndef CPROPERTYTEMPLATE
#define CPROPERTYTEMPLATE
#include "EPropertyType.h"
#include <Common/StringUtil.h>
#include <Common/types.h>
#include <string>
#include <vector>
class CPropertyTemplate
{
friend class CTemplateLoader;
friend class CTemplateWriter;
protected:
EPropertyType mPropType;
std::string mPropName;
u32 mPropID;
public:
CPropertyTemplate(u32 ID) { mPropID = ID; }
CPropertyTemplate(EPropertyType type, std::string name, u32 ID) : mPropType(type), mPropName(name), mPropID(ID) {}
virtual EPropertyType Type() const { return mPropType; }
inline std::string Name() const { return mPropName; }
inline u32 PropertyID() const { return mPropID; }
inline void SetName(const std::string& Name) { mPropName = Name; }
};
class CFileTemplate : public CPropertyTemplate
{
friend class CTemplateLoader;
friend class CTemplateWriter;
CStringList mAcceptedExtensions;
public:
CFileTemplate(u32 ID) : CPropertyTemplate(ID) { mPropType = eFileProperty; }
CFileTemplate(std::string name, u32 ID, const CStringList& extensions)
: CPropertyTemplate(ID) {
mPropType = eFileProperty; mPropName = name; mAcceptedExtensions = extensions;
}
EPropertyType Type() const { return eFileProperty; }
const CStringList& Extensions() const { return mAcceptedExtensions; }
};
class CStructTemplate : public CPropertyTemplate
{
friend class CTemplateLoader;
friend class CTemplateWriter;
bool mIsSingleProperty;
std::vector<CPropertyTemplate*> mProperties;
std::string mSourceFile;
public:
CStructTemplate();
~CStructTemplate();
EPropertyType Type() const;
bool IsSingleProperty() const;
u32 Count() const;
CPropertyTemplate* PropertyByIndex(u32 index);
CPropertyTemplate* PropertyByID(u32 ID);
CPropertyTemplate* PropertyByIDString(const std::string& str);
CStructTemplate* StructByIndex(u32 index);
CStructTemplate* StructByID(u32 ID);
CStructTemplate* StructByIDString(const std::string& str);
void DebugPrintProperties(std::string base);
};
#endif // CPROPERTYTEMPLATE

View File

@ -4,11 +4,10 @@
CScriptObject::CScriptObject(CGameArea *pArea, CScriptLayer *pLayer, CScriptTemplate *pTemplate)
{
mpTemplate = pTemplate;
mpArea = pArea;
mpLayer = pLayer;
mpTemplate = pTemplate;
mpProperties = nullptr;
mAttribFlags = 0;
mpTemplate->AddObject(this);
}
@ -19,186 +18,72 @@ CScriptObject::~CScriptObject()
}
// ************ DATA MANIPULATION ************
void CScriptObject::EvalutateXForm()
void CScriptObject::CopyFromTemplate(CScriptTemplate *pTemp, u32 propCount)
{
// Reset XForm values to defaults
mPosition = CVector3f(0);
mRotation = CVector3f(0);
mScale = CVector3f(1);
mVolumeSize = CVector3f(0);
mVolumeShape = -1;
// Look for PRS attribs
for (u32 a = 0; a < mAttribs.size(); a++)
{
if ((mAttribs[a].Type == ePositionAttrib) ||
(mAttribs[a].Type == eRotationAttrib) ||
(mAttribs[a].Type == eScaleAttrib) ||
(mAttribs[a].Type == eVolumeAttrib))
{
CVector3Property *attrib = static_cast<CVector3Property*>(mAttribs[a].Prop);
if (mAttribs[a].Type == ePositionAttrib)
mPosition = attrib->Get();
else if (mAttribs[a].Type == eRotationAttrib)
mRotation = attrib->Get();
else if (mAttribs[a].Type == eScaleAttrib)
mScale = attrib->Get();
else if (mAttribs[a].Type == eVolumeAttrib) {
mVolumeSize = attrib->Get();
mVolumeShape = mAttribs[a].Settings;
}
}
}
CStructTemplate *pBaseStruct = pTemp->BaseStructByCount(propCount);
delete mpProperties;
mpProperties = CPropertyStruct::CopyFromTemplate(pBaseStruct);
}
void CScriptObject::EvaluateInstanceName()
void CScriptObject::EvaluateProperties()
{
// Reset instance name to default
mInstanceName = mpTemplate->TemplateName();
// Simply look for an instance name - set if we find it
for (u32 a = 0; a < mAttribs.size(); a++)
{
if (mAttribs[a].Type == eNameAttrib)
{
CStringProperty *str = static_cast<CStringProperty*>(mAttribs[a].Prop);
mInstanceName = str->Get();
return;
}
}
}
void CScriptObject::EvaluateTevColor()
{
// Evaluate the TEV color initializer - this is used for beam troopers
mTevColor = CColor::skWhite; // Initialize to white in case there's no vulnerability attrib
for (u32 a = 0; a < mAttribs.size(); a++)
{
if (mAttribs[a].Type == eVulnerabilityAttrib)
{
CPropertyStruct* vuln = static_cast<CPropertyStruct*>(mAttribs[a].Prop);
u32 Power = static_cast<CLongProperty*>(vuln->PropertyByIndex(0))->Get();
u32 Ice = static_cast<CLongProperty*>(vuln->PropertyByIndex(1))->Get();
u32 Wave = static_cast<CLongProperty*>(vuln->PropertyByIndex(2))->Get();
u32 Plasma = static_cast<CLongProperty*>(vuln->PropertyByIndex(3))->Get();
if (Plasma != 2) mTevColor = CColor::skRed;
else if (Ice != 2) mTevColor = CColor::skWhite;
else if (Power != 2) mTevColor = CColor::skYellow;
else if (Wave != 2) mTevColor = CColor::skPurple;
else mTevColor = CColor::skWhite;
break;
}
}
mpInstanceName = mpTemplate->FindInstanceName(mpProperties);
mpPosition = mpTemplate->FindPosition(mpProperties);
mpRotation = mpTemplate->FindRotation(mpProperties);
mpScale = mpTemplate->FindScale(mpProperties);
mpActive = mpTemplate->FindActive(mpProperties);
mpLightParameters = mpTemplate->FindLightParameters(mpProperties);
mVolumeShape = mpTemplate->VolumeShape(this);
EvaluateDisplayModel();
}
void CScriptObject::EvaluateDisplayModel()
{
// Look for animset or model
for (u32 a = 0; a < mAttribs.size(); a++)
{
// Evaluate AnimSet attrib
if (mAttribs[a].Type == eAnimSetAttrib)
{
// Get the AnimationParameters struct so we can fetch relevant values from it...
SAttrib *Attrib = &mAttribs[a];
CPropertyStruct *AnimParams = static_cast<CPropertyStruct*>(Attrib->Prop);
EGame game = mpTemplate->MasterTemplate()->GetGame();
CResource *ANCS;
if (Attrib->Res)
ANCS = Attrib->Res;
else if (game <= eCorruption)
ANCS = static_cast<CFileProperty*>( (*AnimParams)[0] )->Get();
else
ANCS = static_cast<CFileProperty*>( (*AnimParams)[1] )->Get();
if ((ANCS) && (ANCS->Type() == eCharacter))
{
// Get animset + node index and return the relevant model
CAnimSet *set = static_cast<CAnimSet*>(ANCS);
u32 node;
if (mpTemplate->MasterTemplate()->GetGame() >= eCorruptionProto)
node = 0;
else if (Attrib->Settings == -1)
node = static_cast<CLongProperty*>( (*AnimParams)[1] )->Get();
else
node = Attrib->Settings;
CModel *model = set->getNodeModel(node);
if (model && (model->Type() == eModel))
{
mpDisplayModel = model;
return;
}
}
}
// Evaluate Model attrib
else if (mAttribs[a].Type == eModelAttrib)
{
SAttrib *Attrib = &mAttribs[a];
CResource *CMDL;
if (Attrib->Res)
CMDL = Attrib->Res;
else
CMDL = static_cast<CFileProperty*>(Attrib->Prop)->Get();
if (CMDL && (CMDL->Type() == eModel))
{
mpDisplayModel = static_cast<CModel*>(CMDL);
return;
}
}
}
// No valid display asset
mpDisplayModel = nullptr;
return;
mpDisplayModel = mpTemplate->FindDisplayModel(mpProperties);
mModelToken = CToken(mpDisplayModel);
}
// ************ GETTERS ************
CPropertyBase* CScriptObject::PropertyByIndex(u32 index)
CPropertyBase* CScriptObject::PropertyByIndex(u32 index) const
{
return mpProperties->PropertyByIndex(index);
}
CPropertyBase* CScriptObject::PropertyByName(std::string name)
CPropertyBase* CScriptObject::PropertyByIDString(std::string str) const
{
return mpProperties->PropertyByName(name);
return mpProperties->PropertyByIDString(str);
}
CScriptTemplate* CScriptObject::Template()
CScriptTemplate* CScriptObject::Template() const
{
return mpTemplate;
}
CMasterTemplate* CScriptObject::MasterTemplate()
CMasterTemplate* CScriptObject::MasterTemplate() const
{
return mpTemplate->MasterTemplate();
}
CGameArea* CScriptObject::Area()
CGameArea* CScriptObject::Area() const
{
return mpArea;
}
CScriptLayer* CScriptObject::Layer()
CScriptLayer* CScriptObject::Layer() const
{
return mpLayer;
}
CPropertyStruct* CScriptObject::Properties()
CPropertyStruct* CScriptObject::Properties() const
{
return mpProperties;
}
u32 CScriptObject::NumProperties() const
{
return mpProperties->Count();
}
u32 CScriptObject::ObjectTypeID() const
{
return mpTemplate->ObjectID();
@ -229,40 +114,74 @@ const SLink& CScriptObject::OutLink(u32 index) const
return mOutConnections[index];
}
// Attribs
CVector3f CScriptObject::GetPosition() const
std::string CScriptObject::InstanceName() const
{
return mPosition;
if (mpInstanceName)
return mpInstanceName->Get();
else
return "";
}
CVector3f CScriptObject::GetRotation() const
CVector3f CScriptObject::Position() const
{
return mRotation;
if (mpPosition)
return mpPosition->Get();
else
return CVector3f::skZero;
}
CVector3f CScriptObject::GetScale() const
CVector3f CScriptObject::Rotation() const
{
return mScale;
if (mpRotation)
return mpRotation->Get();
else
return CVector3f::skZero;
}
CVector3f CScriptObject::GetVolume() const
CVector3f CScriptObject::Scale() const
{
return mVolumeSize;
if (mpScale)
return mpScale->Get();
else
return CVector3f::skOne;
}
u32 CScriptObject::GetVolumeShape() const
bool CScriptObject::IsActive() const
{
return mVolumeShape;
if (mpActive)
return mpActive->Get();
else
return true;
}
std::string CScriptObject::GetInstanceName() const
void CScriptObject::SetPosition(const CVector3f& newPos)
{
return mInstanceName;
if (mpPosition) mpPosition->Set(newPos);
}
CColor CScriptObject::GetTevColor() const
void CScriptObject::SetRotation(const CVector3f& newRot)
{
return mTevColor;
if (mpRotation) mpRotation->Set(newRot);
}
void CScriptObject::SetScale(const CVector3f& newScale)
{
if (mpScale) mpScale->Set(newScale);
}
void CScriptObject::SetName(const std::string& newName)
{
if (mpInstanceName) mpInstanceName->Set(newName);
}
void CScriptObject::SetActive(bool isActive)
{
if (mpActive) mpActive->Set(isActive);
}
CPropertyStruct* CScriptObject::LightParameters() const
{
return mpLightParameters;
}
CModel* CScriptObject::GetDisplayModel() const
@ -270,18 +189,7 @@ CModel* CScriptObject::GetDisplayModel() const
return mpDisplayModel;
}
int CScriptObject::GetAttribFlags() const
EVolumeShape CScriptObject::VolumeShape() const
{
return mAttribFlags;
}
// ************ STATIC ************
CScriptObject* CScriptObject::CopyFromTemplate(CScriptTemplate *pTemp, CGameArea *pArea, CScriptLayer *pLayer)
{
CScriptObject *pObj = new CScriptObject(pArea, pLayer, pTemp);
CStructTemplate *pBaseStruct = pTemp->BaseStruct();
pObj->mpProperties = CPropertyStruct::CopyFromTemplate(pBaseStruct);
return pObj;
return mVolumeShape;
}

View File

@ -3,6 +3,7 @@
#include "SConnection.h"
#include "CProperty.h"
#include "CPropertyTemplate.h"
#include "CScriptTemplate.h"
#include "EAttribType.h"
#include "../model/CModel.h"
@ -24,48 +25,32 @@ class CScriptObject
std::vector<SLink> mInConnections;
CPropertyStruct *mpProperties;
CVector3f mPosition, mRotation, mScale;
CVector3f mVolumeSize;
u32 mVolumeShape;
std::string mInstanceName;
CColor mTevColor;
CModel* mpDisplayModel;
struct SAttrib
{
EAttribType Type;
u32 Settings;
CResource *Res;
CToken ResToken;
CPropertyBase *Prop;
// Convenience constructor
SAttrib(EAttribType type, CResource *res, u32 settings, CPropertyBase *prop) {
Type = type;
Res = res;
ResToken = CToken(res);
Settings = settings;
Prop = prop;
}
};
std::vector<SAttrib> mAttribs;
int mAttribFlags; // int container for EAttribType flags
CStringProperty *mpInstanceName;
CVector3Property *mpPosition;
CVector3Property *mpRotation;
CVector3Property *mpScale;
CBoolProperty *mpActive;
CPropertyStruct *mpLightParameters;
CModel *mpDisplayModel;
CToken mModelToken;
EVolumeShape mVolumeShape;
public:
CScriptObject(CGameArea *pArea, CScriptLayer *pLayer, CScriptTemplate *pTemplate);
~CScriptObject();
void CopyFromTemplate(CScriptTemplate *pTemp, u32 propCount);
void EvaluateProperties();
void EvaluateDisplayModel();
void EvaluateInstanceName();
void EvaluateTevColor();
void EvalutateXForm();
CScriptTemplate* Template();
CMasterTemplate* MasterTemplate();
CGameArea* Area();
CScriptLayer* Layer();
CPropertyStruct* Properties();
CScriptTemplate* Template() const;
CMasterTemplate* MasterTemplate() const;
CGameArea* Area() const;
CScriptLayer* Layer() const;
CPropertyStruct* Properties() const;
u32 NumProperties() const;
CPropertyBase* PropertyByIndex(u32 index) const;
CPropertyBase* PropertyByIDString(std::string str) const;
u32 ObjectTypeID() const;
u32 InstanceID() const;
u32 NumInLinks() const;
@ -73,21 +58,19 @@ public:
const SLink& InLink(u32 index) const;
const SLink& OutLink(u32 index) const;
CPropertyBase* PropertyByIndex(u32 index);
CPropertyBase* PropertyByName(std::string name);
CVector3f GetPosition() const;
CVector3f GetRotation() const;
CVector3f GetScale() const;
CVector3f GetVolume() const;
u32 GetVolumeShape() const;
std::string GetInstanceName() const;
CColor GetTevColor() const;
CVector3f Position() const;
CVector3f Rotation() const;
CVector3f Scale() const;
std::string InstanceName() const;
bool IsActive() const;
void SetPosition(const CVector3f& newPos);
void SetRotation(const CVector3f& newRot);
void SetScale(const CVector3f& newScale);
void SetName(const std::string& newName);
void SetActive(bool isActive);
CPropertyStruct* LightParameters() const;
CModel* GetDisplayModel() const;
int GetAttribFlags() const;
// Static
static CScriptObject* CopyFromTemplate(CScriptTemplate *pTemp, CGameArea *pArea, CScriptLayer *pLayer);
EVolumeShape VolumeShape() const;
};
#endif // CSCRIPTOBJECT_H

View File

@ -5,230 +5,19 @@
#include <string>
#include <Core/Log.h>
#include <Core/CResCache.h>
#include <Resource/CAnimSet.h>
EPropertyType PropStringToPropEnum(std::string prop)
{
if (prop == "bool") return eBoolProperty;
if (prop == "byte") return eByteProperty;
if (prop == "short") return eShortProperty;
if (prop == "long") return eLongProperty;
if (prop == "float") return eFloatProperty;
if (prop == "string") return eStringProperty;
if (prop == "color") return eColorProperty;
if (prop == "vector3f") return eVector3Property;
if (prop == "file") return eFileProperty;
if (prop == "struct") return eStructProperty;
if (prop == "unknown") return eUnknownProperty;
return eInvalidProperty;
}
std::string PropEnumToPropString(EPropertyType prop)
{
switch (prop)
{
case eBoolProperty: return "bool";
case eByteProperty: return "byte";
case eShortProperty: return "short";
case eLongProperty: return "long";
case eFloatProperty: return "float";
case eStringProperty: return "string";
case eColorProperty: return "color";
case eVector3Property: return "vector3f";
case eFileProperty: return "file";
case eStructProperty: return "struct";
case eUnknownProperty: return "unknown";
case eInvalidProperty:
default:
return "invalid";
}
}
EAttribType AttribStringToAttribEnum(const std::string& Attrib)
{
if (Attrib == "name") return eNameAttrib;
if (Attrib == "position") return ePositionAttrib;
if (Attrib == "rotation") return eRotationAttrib;
if (Attrib == "scale") return eScaleAttrib;
if (Attrib == "model") return eModelAttrib;
if (Attrib == "animset") return eAnimSetAttrib;
if (Attrib == "volume") return eVolumeAttrib;
if (Attrib == "vulnerability") return eVulnerabilityAttrib;
return eInvalidAttrib;
}
std::string AttribEnumToAttribString(EAttribType Attrib)
{
switch (Attrib)
{
case eNameAttrib: return "name";
case ePositionAttrib: return "position";
case eRotationAttrib: return "rotation";
case eScaleAttrib: return "scale";
case eModelAttrib: return "model";
case eAnimSetAttrib: return "animset";
case eVolumeAttrib: return "volume";
case eVulnerabilityAttrib: return "vulnerability";
case eInvalidAttrib:
default:
return "invalid";
}
}
/*******************
* CStructTemplate *
*******************/
CStructTemplate::CStructTemplate() : CPropertyTemplate(-1)
{
mIsSingleProperty = false;
mPropertyCount = -1;
mPropType = eStructProperty;
}
CStructTemplate::~CStructTemplate()
{
for (auto it = mProperties.begin(); it != mProperties.end(); it++)
delete *it;
}
// ************ GETTERS ************
EPropertyType CStructTemplate::Type() const
{
return eStructProperty;
}
bool CStructTemplate::IsSingleProperty() const
{
return mIsSingleProperty;
}
s32 CStructTemplate::TemplateCount() const
{
return mPropertyCount;
}
u32 CStructTemplate::Count() const
{
return mProperties.size();
}
CPropertyTemplate* CStructTemplate::PropertyByIndex(u32 index)
{
if (mProperties.size() > index)
return mProperties[index];
else
return nullptr;
}
CPropertyTemplate* CStructTemplate::PropertyByName(std::string name)
{
// Resolve namespace
std::string::size_type NsStart = name.find_first_of("::");
std::string::size_type PropStart = NsStart + 2;
// Namespace; the requested property is within a struct
if (NsStart != std::string::npos)
{
std::string StructName = name.substr(0, NsStart);
std::string PropName = name.substr(PropStart, name.length() - PropStart);
CStructTemplate *tmp = StructByName(StructName);
if (!tmp) return nullptr;
else return tmp->PropertyByName(PropName);
}
// No namespace; fetch the property from this struct
else
{
// ID string lookup
if (StringUtil::IsHexString(name))
return PropertyByID(std::stoul(name, 0, 16));
// Name lookup
else
{
for (auto it = mProperties.begin(); it != mProperties.end(); it++)
{
if ((*it)->Name() == name)
return *it;
}
return nullptr;
}
}
}
CPropertyTemplate* CStructTemplate::PropertyByID(u32 ID)
{
for (auto it = mProperties.begin(); it != mProperties.end(); it++)
{
if ((*it)->PropertyID() == ID)
return *it;
}
return nullptr;
}
CStructTemplate* CStructTemplate::StructByIndex(u32 index)
{
CPropertyTemplate *prop = PropertyByIndex(index);
if (prop->Type() == eStructProperty)
return static_cast<CStructTemplate*>(prop);
else
return nullptr;
}
CStructTemplate* CStructTemplate::StructByName(std::string name)
{
CPropertyTemplate *prop = PropertyByName(name);
if (prop && prop->Type() == eStructProperty)
return static_cast<CStructTemplate*>(prop);
else
return nullptr;
}
CStructTemplate* CStructTemplate::StructByID(u32 ID)
{
CPropertyTemplate *prop = PropertyByID(ID);
if (prop && prop->Type() == eStructProperty)
return static_cast<CStructTemplate*>(prop);
else
return nullptr;
}
// ************ DEBUG ************
void CStructTemplate::DebugPrintProperties(std::string base)
{
base = base + Name() + "::";
for (auto it = mProperties.begin(); it != mProperties.end(); it++)
{
CPropertyTemplate *tmp = *it;
if (tmp->Type() == eStructProperty)
{
CStructTemplate *tmp2 = static_cast<CStructTemplate*>(tmp);
tmp2->DebugPrintProperties(base);
}
else
std::cout << base << tmp->Name() << "\n";
}
}
/*******************
* CScriptTemplate *
*******************/
CScriptTemplate::CScriptTemplate(CMasterTemplate *pMaster)
{
mpBaseStruct = nullptr;
mpMaster = pMaster;
mVisible = true;
mVolumeShape = eNoShape;
}
CScriptTemplate::~CScriptTemplate()
{
if (mpBaseStruct)
delete mpBaseStruct;
for (u32 iSet = 0; iSet < mPropertySets.size(); iSet++)
delete mPropertySets[iSet].pBaseStruct;
}
CMasterTemplate* CScriptTemplate::MasterTemplate()
@ -236,27 +25,51 @@ CMasterTemplate* CScriptTemplate::MasterTemplate()
return mpMaster;
}
std::string CScriptTemplate::TemplateName() const
std::string CScriptTemplate::TemplateName(s32 propCount) const
{
// Return original name if there is only one property set
// or if caller doesn't want to distinguish between sets
if ((NumPropertySets() == 1) || (propCount == -1))
return mTemplateName;
// Otherwise we return the template name with the set name appended
for (auto it = mPropertySets.begin(); it != mPropertySets.end(); it++)
if (it->pBaseStruct->Count() == propCount)
return mTemplateName + " (" + it->SetName + ")";
return mTemplateName + " (Invalid)";
}
CStructTemplate* CScriptTemplate::BaseStruct()
std::string CScriptTemplate::PropertySetNameByCount(s32 propCount) const
{
return mpBaseStruct;
for (auto it = mPropertySets.begin(); it != mPropertySets.end(); it++)
if (it->pBaseStruct->Count() == propCount)
return it->SetName;
return "";
}
u32 CScriptTemplate::AttribCount() const
std::string CScriptTemplate::PropertySetNameByIndex(u32 index) const
{
return mAttribs.size();
}
CAttribTemplate* CScriptTemplate::Attrib(u32 index)
{
if (mAttribs.size() > index)
return &mAttribs[index];
if (index < NumPropertySets())
return mPropertySets[index].SetName;
else
return nullptr;
return "";
}
u32 CScriptTemplate::NumPropertySets() const
{
return mPropertySets.size();
}
CScriptTemplate::ERotationType CScriptTemplate::RotationType() const
{
return mRotationType;
}
CScriptTemplate::EScaleType CScriptTemplate::ScaleType() const
{
return mScaleType;
}
u32 CScriptTemplate::ObjectID() const
@ -264,6 +77,206 @@ u32 CScriptTemplate::ObjectID() const
return mObjectID;
}
void CScriptTemplate::SetVisible(bool visible)
{
mVisible = visible;
}
bool CScriptTemplate::IsVisible() const
{
return mVisible;
}
void CScriptTemplate::DebugPrintProperties(int propCount)
{
CStructTemplate *pTemp = BaseStructByCount(propCount);
if (pTemp) pTemp->DebugPrintProperties("");
}
// ************ PROPERTY FETCHING ************
template<typename t, EPropertyType propType>
t TFetchProperty(CPropertyStruct *pProperties, const TIDString& ID)
{
if (ID.empty()) return nullptr;
CPropertyBase *pProp = pProperties->PropertyByIDString(ID);
if (pProp && (pProp->Type() == propType))
return static_cast<t>(pProp);
else
return nullptr;
}
CStructTemplate* CScriptTemplate::BaseStructByCount(s32 propCount)
{
for (u32 iSet = 0; iSet < mPropertySets.size(); iSet++)
if (mPropertySets[iSet].pBaseStruct->Count() == propCount)
return mPropertySets[iSet].pBaseStruct;
return nullptr;
}
CStructTemplate* CScriptTemplate::BaseStructByIndex(u32 index)
{
if (index < NumPropertySets())
return mPropertySets[index].pBaseStruct;
else
return nullptr;
}
EVolumeShape CScriptTemplate::VolumeShape(CScriptObject *pObj)
{
if (pObj->Template() != this)
{
Log::Error(pObj->Template()->TemplateName() + " instance somehow called VolumeShape() on " + TemplateName() + " template");
return eInvalidShape;
}
if (mVolumeShape == eConditionalShape)
{
CPropertyBase *pProp = pObj->Properties()->PropertyByIDString(mVolumeConditionIDString);
// Get value of the condition test property (only boolean, integral, and enum types supported)
int v;
switch (pProp->Type())
{
case eBoolProperty:
v = (static_cast<CBoolProperty*>(pProp)->Get() ? 1 : 0);
break;
case eByteProperty:
v = (int) static_cast<CByteProperty*>(pProp)->Get();
break;
case eShortProperty:
v = (int) static_cast<CShortProperty*>(pProp)->Get();
break;
case eLongProperty:
case eEnumProperty:
v = (int) static_cast<CLongProperty*>(pProp)->Get();
break;
}
// Test and check whether any of the conditions are true
for (auto it = mVolumeConditions.begin(); it != mVolumeConditions.end(); it++)
{
if (it->Value == v)
return it->Shape;
}
Log::Error(TemplateName() + " instance " + StringUtil::ToHexString(pObj->InstanceID(), true, true, 8) + " has unexpected volume shape value of " + StringUtil::ToHexString((u32) v, true, true));
return eInvalidShape;
}
else return mVolumeShape;
}
CStringProperty* CScriptTemplate::FindInstanceName(CPropertyStruct *pProperties)
{
return TFetchProperty<CStringProperty*, eStringProperty>(pProperties, mNameIDString);
}
CVector3Property* CScriptTemplate::FindPosition(CPropertyStruct *pProperties)
{
return TFetchProperty<CVector3Property*, eVector3Property>(pProperties, mPositionIDString);
}
CVector3Property* CScriptTemplate::FindRotation(CPropertyStruct *pProperties)
{
return TFetchProperty<CVector3Property*, eVector3Property>(pProperties, mRotationIDString);
}
CVector3Property* CScriptTemplate::FindScale(CPropertyStruct *pProperties)
{
return TFetchProperty<CVector3Property*, eVector3Property>(pProperties, mScaleIDString);
}
CBoolProperty* CScriptTemplate::FindActive(CPropertyStruct *pProperties)
{
return TFetchProperty<CBoolProperty*, eBoolProperty>(pProperties, mActiveIDString);
}
CPropertyStruct* CScriptTemplate::FindLightParameters(CPropertyStruct *pProperties)
{
return TFetchProperty<CPropertyStruct*, eStructProperty>(pProperties, mLightParametersIDString);
}
CModel* CScriptTemplate::FindDisplayModel(CPropertyStruct *pProperties)
{
for (auto it = mAssets.begin(); it != mAssets.end(); it++)
{
CResource *pRes = nullptr;
int animSetIndex = -1;
// File
if (it->AssetSource == SEditorAsset::eFile)
{
std::string path = "../resources/" + it->AssetLocation;
pRes = gResCache.GetResource(path);
}
// Property
else
{
CPropertyBase *pProp = pProperties->PropertyByIDString(it->AssetLocation);
if (pProp->Type() == eFileProperty)
{
CFileProperty *pFile = static_cast<CFileProperty*>(pProp);
pRes = pFile->Get();
}
else if (pProp->Type() == eStructProperty)
{
CPropertyStruct *pStruct = static_cast<CPropertyStruct*>(pProp);
// Slightly hacky code to fetch the correct parameters for each game
EGame game = mpMaster->GetGame();
if (game <= eCorruption)
pRes = static_cast<CFileProperty*>(pStruct->PropertyByIndex(0))->Get();
else
pRes = static_cast<CFileProperty*>(pStruct->PropertyByIndex(1))->Get();
if (it->ForceNodeIndex >= 0)
animSetIndex = it->ForceNodeIndex;
else if (game >= eCorruptionProto)
animSetIndex = 0;
else
animSetIndex = static_cast<CLongProperty*>(pStruct->PropertyByIndex(1))->Get();
}
}
// Verify resource exists + is correct type
if (pRes)
{
if ((it->AssetType == SEditorAsset::eModel) && (pRes->Type() == eModel))
return static_cast<CModel*>(pRes);
if ((it->AssetType == SEditorAsset::eAnimParams) && ((pRes->Type() == eAnimSet)))
{
CAnimSet *pSet = static_cast<CAnimSet*>(pRes);
if (animSetIndex < pSet->getNodeCount())
{
CModel *pModel = pSet->getNodeModel(animSetIndex);
if (pModel && (pModel->Type() == eModel))
return pModel;
}
}
}
}
return nullptr;
}
bool CScriptTemplate::HasPosition()
{
return (!mPositionIDString.empty());
}
// ************ OBJECT TRACKING ************
u32 CScriptTemplate::NumObjects() const
{
return mObjectList.size();
@ -298,19 +311,3 @@ void CScriptTemplate::SortObjects()
return (pA->InstanceID() < pB->InstanceID());
});
}
void CScriptTemplate::SetVisible(bool Visible)
{
mVisible = Visible;
}
bool CScriptTemplate::IsVisible()
{
return mVisible;
}
// Debug function
void CScriptTemplate::DebugPrintProperties()
{
mpBaseStruct->DebugPrintProperties("");
}

View File

@ -1,141 +1,128 @@
#ifndef CSCRIPTTEMPLATE_H
#define CSCRIPTTEMPLATE_H
#include "CPropertyTemplate.h"
#include "CProperty.h"
#include "EPropertyType.h"
#include "EVolumeShape.h"
#include "EAttribType.h"
#include <Common/CFourCC.h>
#include <Common/types.h>
#include <list>
#include <vector>
#include <tinyxml2.h>
#include <Resource/CResource.h>
#include <Resource/model/CModel.h>
class CMasterTemplate;
class CScriptObject;
/**
* CPropertyTemplate and CStructTemplate each define the layout of a single property/struct.
* The reason they're classes instead of structs is so their internal values can't be externally modified.
* CFileTemplate is a very simple subclass with one extra value - a file extension fourCC
*/
class CPropertyTemplate
{
friend class CTemplateLoader;
typedef std::string TIDString;
protected:
EPropertyType mPropType;
std::string mPropName;
u32 mPropID;
public:
CPropertyTemplate(u32 ID) { mPropID = ID; }
CPropertyTemplate(EPropertyType type, std::string name, u32 ID) : mPropType(type), mPropName(name), mPropID(ID) {}
virtual EPropertyType Type() const { return mPropType; }
inline std::string Name() const { return mPropName; }
inline u32 PropertyID() const { return mPropID; }
inline void SetName(const std::string& Name) { mPropName = Name; }
};
class CFileTemplate : public CPropertyTemplate
{
friend class CTemplateLoader;
CStringList mAcceptedExtensions;
public:
CFileTemplate(u32 ID) : CPropertyTemplate(ID) { mPropType = eFileProperty; }
CFileTemplate(std::string name, u32 ID, const CStringList& extensions)
: CPropertyTemplate(ID) {
mPropType = eFileProperty; mPropName = name; mAcceptedExtensions = extensions;
}
EPropertyType Type() const { return eFileProperty; }
const CStringList& Extensions() const { return mAcceptedExtensions; }
};
class CStructTemplate : public CPropertyTemplate
{
friend class CTemplateLoader;
bool mIsSingleProperty;
s32 mPropertyCount;
std::vector<CPropertyTemplate*> mProperties;
public:
CStructTemplate();
~CStructTemplate();
EPropertyType Type() const;
bool IsSingleProperty() const;
s32 TemplateCount() const;
u32 Count() const;
CPropertyTemplate* PropertyByIndex(u32 index);
CPropertyTemplate* PropertyByName(std::string name);
CPropertyTemplate* PropertyByID(u32 ID);
CStructTemplate* StructByIndex(u32 index);
CStructTemplate* StructByName(std::string name);
CStructTemplate* StructByID(u32 ID);
void DebugPrintProperties(std::string base);
};
/**
* CAttribTemplate defines editor attributes.
* They enable PWE to access and use object properties for use in the world editor.
*/
class CAttribTemplate
{
friend class CTemplateLoader;
EAttribType AttribType;
std::string AttribTarget;
std::string ResFile;
u32 ExtraSettings;
public:
CAttribTemplate() {}
EAttribType Type() const { return AttribType; }
std::string Target() const { return AttribTarget; }
std::string Resource() const { return ResFile; }
u32 Settings() const { return ExtraSettings; }
};
/**
/*
* CScriptTemplate is a class that encases the data contained in one of the XML templates.
* It essentially sets the layout of any given script object.
*
* It contains any data that applies globally to every instance of the object, such as
* property names, editor attribute properties, etc.
*/
class CScriptObject;
class CScriptTemplate
{
friend class CTemplateLoader;
friend class CTemplateWriter;
public:
enum ERotationType {
eRotationEnabled, eRotationDisabled
};
enum EScaleType {
eScaleEnabled, eScaleDisabled, eScaleVolume
};
private:
struct SPropertySet {
std::string SetName;
CStructTemplate *pBaseStruct;
};
struct SEditorAsset
{
enum {
eModel, eAnimParams
} AssetType;
enum {
eProperty, eFile
} AssetSource;
TIDString AssetLocation;
s32 ForceNodeIndex; // Force animsets to use specific node instead of one from property
};
CMasterTemplate *mpMaster;
CStructTemplate *mpBaseStruct;
std::vector<SPropertySet> mPropertySets;
std::list<CScriptObject*> mObjectList;
ERotationType mRotationType;
EScaleType mScaleType;
std::string mTemplateName;
std::vector<CAttribTemplate> mAttribs;
std::string mSourceFile;
u32 mObjectID;
bool mVisible;
// Editor Properties
TIDString mNameIDString;
TIDString mPositionIDString;
TIDString mRotationIDString;
TIDString mScaleIDString;
TIDString mActiveIDString;
TIDString mLightParametersIDString;
std::vector<SEditorAsset> mAssets;
// Preview Volume
EVolumeShape mVolumeShape;
TIDString mVolumeConditionIDString;
struct SVolumeCondition {
int Value;
EVolumeShape Shape;
};
std::vector<SVolumeCondition> mVolumeConditions;
public:
CScriptTemplate(CMasterTemplate *pMaster);
~CScriptTemplate();
CMasterTemplate* MasterTemplate();
std::string TemplateName() const;
CStructTemplate* BaseStruct();
u32 AttribCount() const;
CAttribTemplate* Attrib(u32 index);
std::string TemplateName(s32 propCount = -1) const;
std::string PropertySetNameByCount(s32 propCount) const;
std::string PropertySetNameByIndex(u32 index) const;
u32 NumPropertySets() const;
ERotationType RotationType() const;
EScaleType ScaleType() const;
u32 ObjectID() const;
void SetVisible(bool visible);
bool IsVisible() const;
void DebugPrintProperties(int propCount = -1);
// Property Fetching
CStructTemplate* BaseStructByCount(s32 propCount);
CStructTemplate* BaseStructByIndex(u32 index);
EVolumeShape VolumeShape(CScriptObject *pObj);
CStringProperty* FindInstanceName(CPropertyStruct *pProperties);
CVector3Property* FindPosition(CPropertyStruct *pProperties);
CVector3Property* FindRotation(CPropertyStruct *pProperties);
CVector3Property* FindScale(CPropertyStruct *pProperties);
CBoolProperty* FindActive(CPropertyStruct *pProperties);
CPropertyStruct* FindLightParameters(CPropertyStruct *pProperties);
CModel* FindDisplayModel(CPropertyStruct *pProperties);
bool HasPosition();
// Object Tracking
u32 NumObjects() const;
const std::list<CScriptObject*>& ObjectList() const;
void AddObject(CScriptObject *pObject);
void RemoveObject(CScriptObject *pObject);
void SortObjects();
void SetVisible(bool Visible);
bool IsVisible();
void DebugPrintProperties();
};
#endif // CSCRIPTTEMPLATE_H

View File

@ -16,6 +16,7 @@ enum EPropertyType
eEnumProperty,
eFileProperty,
eStructProperty,
eArrayProperty,
eUnknownProperty,
eInvalidProperty
};

View File

@ -0,0 +1,17 @@
#ifndef EVOLUMESHAPE
#define EVOLUMESHAPE
enum EVolumeShape
{
eNoShape,
eAxisAlignedBoxShape,
eBoxShape,
eEllipsoidShape,
eCylinderShape,
eCylinderLargeShape,
eConditionalShape,
eInvalidShape
};
#endif // EVOLUMESHAPE

View File

@ -19,33 +19,44 @@ CScriptNode::CScriptNode(CSceneManager *pScene, CSceneNode *pParent, CScriptObje
if (mpInstance)
{
CScriptTemplate *pTemp = mpInstance->Template();
mpActiveModel = mpInstance->GetDisplayModel();
mPosition = mpInstance->GetPosition();
mRotation = CQuaternion::FromEuler(mpInstance->GetRotation());
mScale = mpInstance->GetScale();
SetName("[" + mpInstance->Template()->TemplateName() + "] " + mpInstance->GetInstanceName());
mPosition = mpInstance->Position();
mRotation = CQuaternion::FromEuler(mpInstance->Rotation());
SetName("[" + pTemp->TemplateName(mpInstance->NumProperties()) + "] " + mpInstance->InstanceName());
if (pTemp->ScaleType() == CScriptTemplate::eScaleEnabled)
mScale = mpInstance->Scale();
MarkTransformChanged();
mHasValidPosition = ((mpInstance->GetAttribFlags() & ePositionAttrib) != 0);
mHasVolumePreview = ((mpInstance->GetAttribFlags() & eVolumeAttrib) != 0);
mHasValidPosition = pTemp->HasPosition();
mHasVolumePreview = (pTemp->ScaleType() == CScriptTemplate::eScaleVolume);
// Create volume preview node
if (mHasVolumePreview)
{
u32 VolumeShape = mpInstance->GetVolumeShape();
EVolumeShape shape = mpInstance->VolumeShape();
CModel *pVolumeModel = nullptr;
if ((VolumeShape == 0) || (VolumeShape == 1)) // Box/OrientedBox
if ((shape == eAxisAlignedBoxShape) || (shape == eBoxShape))
pVolumeModel = (CModel*) gResCache.GetResource("../resources/VolumeBox.cmdl");
else if (VolumeShape == 2) // Sphere
else if (shape == eEllipsoidShape)
pVolumeModel = (CModel*) gResCache.GetResource("../resources/VolumeSphere.cmdl");
else if (shape == eCylinderShape)
pVolumeModel = (CModel*) gResCache.GetResource("../resources/VolumeCylinder.cmdl");
else if (shape == eCylinderLargeShape)
pVolumeModel = (CModel*) gResCache.GetResource("../resources/VolumeCylinderLarge.cmdl");
if (pVolumeModel)
{
mpVolumePreviewNode = new CModelNode(pScene, this, pVolumeModel);
mpVolumePreviewNode->SetInheritance(true, (VolumeShape == 1), false);
mpVolumePreviewNode->Scale(mpInstance->GetVolume());
mpVolumePreviewNode->SetInheritance(true, (shape != eAxisAlignedBoxShape), false);
mpVolumePreviewNode->Scale(mpInstance->Scale());
mpVolumePreviewNode->ForceAlphaEnabled(true);
}
}
@ -70,7 +81,7 @@ ENodeType CScriptNode::NodeType()
std::string CScriptNode::PrefixedName() const
{
return "[" + mpInstance->Template()->TemplateName() + "] " + mpInstance->GetInstanceName();
return "[" + mpInstance->Template()->TemplateName() + "] " + mpInstance->InstanceName();
}
void CScriptNode::AddToRenderer(CRenderer *pRenderer)
@ -137,9 +148,6 @@ void CScriptNode::Draw(ERenderOptions Options)
return;
}
// Set tev color (used rarely)
CGraphics::sPixelBlock.TevColor = mpInstance->GetTevColor().ToVector4f();
mpActiveModel->Draw(Options, 0);
}
@ -156,8 +164,6 @@ void CScriptNode::DrawAsset(ERenderOptions Options, u32 Asset)
LoadModelMatrix();
LoadLights();
CGraphics::sPixelBlock.TevColor = mpInstance->GetTevColor().ToVector4f();
mpActiveModel->DrawSurface(Options, Asset, 0);
}

View File

@ -113,9 +113,9 @@ void CStartWindow::FillAreaUI()
u64 MREA = mpWorld->GetAreaResourceID(mSelectedAreaIndex);
std::string MREAStr;
if (MREA & 0xFFFFFFFF00000000)
MREAStr = StringUtil::ResToStr(MREA);
MREAStr = StringUtil::ToString(MREA);
else
MREAStr = StringUtil::ResToStr( (u32) MREA );
MREAStr = StringUtil::ToString( (u32) MREA );
ui->AreaMREALineEdit->setText(QString::fromStdString(MREAStr) + QString(".MREA") );

View File

@ -55,7 +55,7 @@ QVariant CLinkModel::data(const QModelIndex &index, int role) const
if (pTargetObj) {
QString ObjType = QString("[%1] ").arg(QString::fromStdString(pTargetObj->Template()->TemplateName()));
return ObjType + QString::fromStdString(pTargetObj->GetInstanceName());
return ObjType + QString::fromStdString(pTargetObj->InstanceName());
}
else {
QString strID = QString::number(link.ObjectID, 16);

View File

@ -235,7 +235,7 @@ QVariant CTypesInstanceModel::data(const QModelIndex &index, int role) const
CScriptObject *pObj = static_cast<CScriptObject*>(index.internalPointer());
if (index.column() == 0)
return QString::fromStdString(pObj->GetInstanceName());
return QString::fromStdString(pObj->InstanceName());
else if (index.column() == 1)
{