Updated script templates to version 3 + added script template writer class
This commit is contained in:
parent
f82b3a20a9
commit
97ef20d0d2
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -11,7 +11,7 @@ CAnimSet::~CAnimSet()
|
|||
|
||||
EResType CAnimSet::Type()
|
||||
{
|
||||
return eCharacter;
|
||||
return eAnimSet;
|
||||
}
|
||||
|
||||
u32 CAnimSet::getNodeCount()
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -3,474 +3,408 @@
|
|||
#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();
|
||||
tinyxml2::XMLElement *pChild = pElem->FirstChildElement();
|
||||
|
||||
// Load multi-property struct
|
||||
if (strcmp(pElemName, "struct") == 0)
|
||||
while (pChild)
|
||||
{
|
||||
CStructTemplate *pStruct = LoadStructTemplate(pElem, TemplateName);
|
||||
CPropertyTemplate *pProp = LoadPropertyTemplate(pChild, templateName);
|
||||
|
||||
if (pStruct)
|
||||
pStruct->mIsSingleProperty = false;
|
||||
if (pProp)
|
||||
pTemp->mProperties.push_back(pProp);
|
||||
|
||||
return pStruct;
|
||||
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);
|
||||
}
|
||||
|
||||
// Regular property
|
||||
else
|
||||
pProp = new CPropertyTemplate(type, name, ID);
|
||||
|
||||
return pProp;
|
||||
}
|
||||
|
||||
else if (strcmp(pElemName, "property") == 0)
|
||||
// Load Struct
|
||||
else if (strcmp(pElem->Name(), "struct") == 0)
|
||||
{
|
||||
// Get name, type, and ID
|
||||
std::string Name;
|
||||
EPropertyType Type;
|
||||
u32 ID;
|
||||
GetPropertyInfo(pElem, Name, Type, ID);
|
||||
CStructTemplate *pStruct = new CStructTemplate();
|
||||
|
||||
// Error check
|
||||
if (Type == eInvalidProperty)
|
||||
pStruct->mPropID = ID;
|
||||
|
||||
// Read children properties
|
||||
// Priority: [Embedded] -> [Template] -> [Master]
|
||||
|
||||
// Embedded
|
||||
if (!pElem->NoChildren())
|
||||
LoadStructProperties(pElem, pStruct, templateName);
|
||||
|
||||
// Template
|
||||
else if (kpTemplateStr)
|
||||
{
|
||||
const char *pType = pElem->Attribute("type");
|
||||
std::string tempPath = mMasterDir + kpTemplateStr;
|
||||
|
||||
if (pType)
|
||||
Log::Error("Invalid property type in " + TemplateName + " template: " + pType);
|
||||
else
|
||||
Log::Error("Property " + Name + " in " + TemplateName + " template has no type");
|
||||
}
|
||||
tinyxml2::XMLDocument structXML;
|
||||
structXML.LoadFile(tempPath.c_str());
|
||||
|
||||
// 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, ","));
|
||||
if (structXML.Error())
|
||||
Log::Error("Couldn't open struct XML: " + mMasterDir + kpTemplateStr);
|
||||
|
||||
else
|
||||
{
|
||||
CFileTemplate *pSrc = (CFileTemplate*) mpMaster->GetProperty(ID);
|
||||
tinyxml2::XMLElement *pRoot = structXML.FirstChildElement("struct");
|
||||
pStruct->mSourceFile = kpTemplateStr;
|
||||
|
||||
if (pSrc)
|
||||
pFile = new CFileTemplate(Name, ID, pSrc->Extensions());
|
||||
if (pRoot->Attribute("type"))
|
||||
pStruct->mIsSingleProperty = (strcmp(pRoot->Attribute("type"), "single") == 0);
|
||||
|
||||
if (pRoot->Attribute("name"))
|
||||
pStruct->mPropName = pRoot->Attribute("name");
|
||||
|
||||
LoadStructProperties(pRoot, pStruct, templateName);
|
||||
}
|
||||
|
||||
// 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
|
||||
// Master
|
||||
else if (pSource)
|
||||
{
|
||||
CPropertyTemplate *pProperty = new CPropertyTemplate(Type, Name, ID);
|
||||
return pProperty;
|
||||
CStructTemplate *pSourceStruct = static_cast<CStructTemplate*>(pSource);
|
||||
|
||||
for (u32 iProp = 0; iProp < pSourceStruct->Count(); iProp++)
|
||||
pStruct->mProperties.push_back(pSourceStruct->PropertyByIndex(iProp));
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CStructTemplate* CTemplateLoader::LoadStructTemplate(tinyxml2::XMLElement *pElem, const std::string& TemplateName)
|
||||
// ************ SCRIPT OBJECT ************
|
||||
CScriptTemplate* CTemplateLoader::LoadScriptTemplate(tinyxml2::XMLDocument *pDoc, const std::string& templateName, u32 objectID)
|
||||
{
|
||||
CStructTemplate *pStruct = new CStructTemplate();
|
||||
CScriptTemplate *pScript = new CScriptTemplate(mpMaster);
|
||||
pScript->mObjectID = objectID;
|
||||
|
||||
// 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");
|
||||
tinyxml2::XMLElement *pRoot = pDoc->FirstChildElement("ScriptTemplate");
|
||||
|
||||
// Get source template from the master property list, if it exists
|
||||
CStructTemplate *pSrc = (CStructTemplate*) mpMaster->GetProperty(pStruct->mPropID);
|
||||
// Name
|
||||
tinyxml2::XMLElement *pNameElem = pRoot->FirstChildElement("name");
|
||||
|
||||
// "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);
|
||||
if (pNameElem)
|
||||
pScript->mTemplateName = pNameElem->GetText();
|
||||
|
||||
// Read struct children. Priority is [Embedded -> Template -> Master].
|
||||
// Embedded
|
||||
if (!pElem->NoChildren())
|
||||
// Properties
|
||||
tinyxml2::XMLElement *pPropsElem = pRoot->FirstChildElement("properties");
|
||||
|
||||
while (pPropsElem)
|
||||
{
|
||||
// Get count
|
||||
const char *pCount = pElem->Attribute("count");
|
||||
CScriptTemplate::SPropertySet set;
|
||||
|
||||
if (pCount)
|
||||
pStruct->mPropertyCount = std::stoul(pCount);
|
||||
|
||||
// Parse sub-elements
|
||||
tinyxml2::XMLElement *pChild = pElem->FirstChildElement();
|
||||
|
||||
while (pChild)
|
||||
{
|
||||
CPropertyTemplate *pProp = LoadPropertyTemplate(pChild, TemplateName);
|
||||
|
||||
if (pProp)
|
||||
pStruct->mProperties.push_back(pProp);
|
||||
|
||||
pChild = pChild->NextSiblingElement();
|
||||
}
|
||||
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");
|
||||
}
|
||||
|
||||
// Template
|
||||
else if (pTemp)
|
||||
// Editor Parameters
|
||||
tinyxml2::XMLElement *pEditor = pRoot->FirstChildElement("editor");
|
||||
|
||||
if (pEditor)
|
||||
{
|
||||
// Get handle for XML
|
||||
std::string TempPath = mMasterDir + pTemp;
|
||||
// Editor Properties
|
||||
tinyxml2::XMLElement *pEdProperties = pEditor->FirstChildElement("properties");
|
||||
tinyxml2::XMLElement *pEdProp = pEdProperties->FirstChildElement("property");
|
||||
|
||||
tinyxml2::XMLDocument TempXML;
|
||||
TempXML.LoadFile(TempPath.c_str());
|
||||
|
||||
if (TempXML.Error())
|
||||
Log::Error("Couldn't open struct template: " + TempPath);
|
||||
|
||||
else
|
||||
while (pEdProp)
|
||||
{
|
||||
tinyxml2::XMLElement *pVersionElem = TempXML.FirstChildElement()->FirstChildElement("version");
|
||||
tinyxml2::XMLElement *pPropertiesElem = TempXML.FirstChildElement()->FirstChildElement("properties");
|
||||
const char *kpName = pEdProp->Attribute("name");
|
||||
const char *kpID = pEdProp->Attribute("ID");
|
||||
|
||||
if (!pVersionElem) Log::Error("Struct template has no version element: " + TempPath);
|
||||
if (!pPropertiesElem) Log::Error("Struct template has no properties element: " + TempPath);
|
||||
|
||||
if (pVersionElem && pPropertiesElem)
|
||||
if (kpName && kpID)
|
||||
{
|
||||
// Get version number
|
||||
u32 VersionNumber = std::stoul(pVersionElem->GetText());
|
||||
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;
|
||||
}
|
||||
|
||||
// Get property count
|
||||
const char *pCount = pPropertiesElem->Attribute("count");
|
||||
pEdProp = pEdProp->NextSiblingElement("property");
|
||||
}
|
||||
|
||||
if (pCount)
|
||||
pStruct->mPropertyCount = std::stoul(pCount);
|
||||
// Editor Assets
|
||||
tinyxml2::XMLElement *pEdAssets = pEditor->FirstChildElement("assets");
|
||||
tinyxml2::XMLElement *pAsset = pEdAssets->FirstChildElement();
|
||||
|
||||
// Parse properties
|
||||
tinyxml2::XMLElement *pPropElem = pPropertiesElem->FirstChildElement();
|
||||
while (pAsset)
|
||||
{
|
||||
const char *kpSource = pAsset->Attribute("source");
|
||||
const char *kpID = pAsset->GetText();
|
||||
|
||||
while (pPropElem)
|
||||
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
|
||||
{
|
||||
if (!pPropElem) break;
|
||||
pAsset = pAsset->NextSiblingElement();
|
||||
continue;
|
||||
}
|
||||
|
||||
CPropertyTemplate *pProp = LoadPropertyTemplate(pPropElem, TemplateName);
|
||||
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;
|
||||
}
|
||||
|
||||
if (pProp)
|
||||
pStruct->mProperties.push_back(pProp);
|
||||
const char *kpForce = pAsset->Attribute("force");
|
||||
if (kpForce)
|
||||
asset.ForceNodeIndex = StringUtil::ToInt32(kpForce);
|
||||
else
|
||||
asset.ForceNodeIndex = -1;
|
||||
|
||||
pPropElem = pPropElem->NextSiblingElement();
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Master
|
||||
else if (pSrc)
|
||||
{
|
||||
pStruct->mPropertyCount = pSrc->TemplateCount();
|
||||
|
||||
for (u32 p = 0; p < pSrc->Count(); p++)
|
||||
pStruct->mProperties.push_back(pSrc->PropertyByIndex(p));
|
||||
}
|
||||
|
||||
// If it's none of these things, then it probably has no children because it's a property list entry
|
||||
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;
|
||||
}
|
||||
|
||||
// ************ SCRIPT OBJECT ************
|
||||
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();
|
||||
|
||||
// Properties?
|
||||
tinyxml2::XMLElement *pProperties = pBaseElement->FirstChildElement("properties");
|
||||
if (pProperties)
|
||||
{
|
||||
pScript->mpBaseStruct = LoadStructTemplate(pBaseElement->FirstChildElement("properties"), TemplateName);
|
||||
pScript->mpBaseStruct->SetName(pScript->mTemplateName);
|
||||
}
|
||||
|
||||
// Attribs?
|
||||
tinyxml2::XMLElement *pAttributes = pBaseElement->FirstChildElement("attributes");
|
||||
if (pAttributes) LoadScriptAttribs(pAttributes, pScript);
|
||||
|
||||
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");
|
||||
tinyxml2::XMLElement *pObj = pElem->FirstChildElement("object");
|
||||
|
||||
while (pCat)
|
||||
while (pObj)
|
||||
{
|
||||
CTemplateCategory Cat(pCat->Attribute("name"));
|
||||
tinyxml2::XMLElement *pObj = pCat->FirstChildElement("object");
|
||||
// ID can either be a hex number or an ASCII fourCC
|
||||
std::string strID = pObj->Attribute("ID");
|
||||
u32 ID;
|
||||
|
||||
while (pObj)
|
||||
if (StringUtil::IsHexString(strID, true))
|
||||
ID = StringUtil::ToInt32(strID);
|
||||
else
|
||||
ID = CFourCC(strID).ToLong();
|
||||
|
||||
// Load up the object
|
||||
std::string templateName = pObj->Attribute("template");
|
||||
std::string templatePath = mMasterDir + templateName;
|
||||
|
||||
tinyxml2::XMLDocument scriptXML;
|
||||
scriptXML.LoadFile(templatePath.c_str());
|
||||
|
||||
if (scriptXML.Error())
|
||||
Log::Error("Couldn't open script template: " + templatePath);
|
||||
|
||||
else
|
||||
{
|
||||
// ID can either be a hex number or an ASCII fourCC
|
||||
std::string StrID = pObj->Attribute("ID");
|
||||
u32 ID;
|
||||
CScriptTemplate *pTemp = LoadScriptTemplate(&scriptXML, templateName, ID);
|
||||
|
||||
if (StringUtil::IsHexString(StrID, true))
|
||||
ID = std::stoul(StrID, 0, 16);
|
||||
else
|
||||
ID = CFourCC(StrID).ToLong();
|
||||
|
||||
// Load up the object
|
||||
std::string TemplateName = pObj->Attribute("template");
|
||||
std::string TemplatePath = mMasterDir + TemplateName;
|
||||
|
||||
tinyxml2::XMLDocument ObjectXML;
|
||||
ObjectXML.LoadFile(TemplatePath.c_str());
|
||||
|
||||
if (ObjectXML.Error())
|
||||
Log::Error("Couldn't open script template: " + TemplatePath);
|
||||
|
||||
else
|
||||
if (pTemp)
|
||||
{
|
||||
CScriptTemplate *pTemp = LoadScriptTemplate(&ObjectXML, TemplateName, ID);
|
||||
|
||||
if (pTemp)
|
||||
{
|
||||
mpMaster->mTemplates[ID] = pTemp;
|
||||
Cat.AddTemplate(pTemp);
|
||||
}
|
||||
pTemp->mSourceFile = templateName;
|
||||
mpMaster->mTemplates[ID] = pTemp;
|
||||
}
|
||||
|
||||
pObj = pObj->NextSiblingElement("object");
|
||||
}
|
||||
|
||||
Cat.Sort();
|
||||
mpMaster->mCategories.push_back(Cat);
|
||||
pCat = pCat->NextSiblingElement("category");
|
||||
pObj = pObj->NextSiblingElement("object");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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())
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 ************
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 mTemplateName;
|
||||
// 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("");
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
* 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
|
||||
|
|
|
@ -16,6 +16,7 @@ enum EPropertyType
|
|||
eEnumProperty,
|
||||
eFileProperty,
|
||||
eStructProperty,
|
||||
eArrayProperty,
|
||||
eUnknownProperty,
|
||||
eInvalidProperty
|
||||
};
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef EVOLUMESHAPE
|
||||
#define EVOLUMESHAPE
|
||||
|
||||
enum EVolumeShape
|
||||
{
|
||||
eNoShape,
|
||||
eAxisAlignedBoxShape,
|
||||
eBoxShape,
|
||||
eEllipsoidShape,
|
||||
eCylinderShape,
|
||||
eCylinderLargeShape,
|
||||
eConditionalShape,
|
||||
eInvalidShape
|
||||
};
|
||||
|
||||
#endif // EVOLUMESHAPE
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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") );
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue