Fixed property name generator/template edit dialog to work with new property system

This commit is contained in:
Aruki 2018-10-09 23:15:15 -06:00
parent 803ea5788b
commit 22ab73883c
27 changed files with 394 additions and 212 deletions

View File

@ -11,9 +11,11 @@ using namespace std::experimental::filesystem::v1;
namespace FileUtil
{
#define ToPath(Path) u8path(Path)
bool Exists(const TString &rkFilePath)
{
return exists(*rkFilePath);
return exists(ToPath(*rkFilePath));
}
bool IsRoot(const TString& rkPath)
@ -26,22 +28,22 @@ bool IsRoot(const TString& rkPath)
bool IsFile(const TString& rkFilePath)
{
return is_regular_file(*rkFilePath);
return is_regular_file(ToPath(*rkFilePath));
}
bool IsDirectory(const TString& rkDirPath)
{
return is_directory(*rkDirPath);
return is_directory(ToPath(*rkDirPath));
}
bool IsAbsolute(const TString& rkDirPath)
{
return path(*rkDirPath).is_absolute();
return ToPath(*rkDirPath).is_absolute();
}
bool IsRelative(const TString& rkDirPath)
{
return path(*rkDirPath).is_relative();
return ToPath(*rkDirPath).is_relative();
}
bool IsEmpty(const TString& rkDirPath)
@ -52,7 +54,7 @@ bool IsEmpty(const TString& rkDirPath)
return false;
}
return is_empty(*rkDirPath);
return is_empty(ToPath(*rkDirPath));
}
bool MakeDirectory(const TString& rkNewDir)
@ -63,7 +65,7 @@ bool MakeDirectory(const TString& rkNewDir)
return false;
}
return create_directories(*rkNewDir);
return create_directories(ToPath(*rkNewDir));
}
bool CopyFile(const TString& rkOrigPath, const TString& rkNewPath)
@ -77,7 +79,7 @@ bool CopyFile(const TString& rkOrigPath, const TString& rkNewPath)
MakeDirectory(rkNewPath.GetFileDirectory());
std::error_code Error;
// call std::filesystem::copy, not std::copy
std::experimental::filesystem::copy(*rkOrigPath, *rkNewPath, Error);
std::experimental::filesystem::copy(ToPath(*rkOrigPath), ToPath(*rkNewPath), Error);
return (Error.value() == 0);
}
@ -92,7 +94,7 @@ bool CopyDirectory(const TString& rkOrigPath, const TString& rkNewPath)
MakeDirectory(rkNewPath.GetFileDirectory());
std::error_code Error;
// call std::filesystem::copy, not std::copy
std::experimental::filesystem::copy(*rkOrigPath, *rkNewPath, Error);
std::experimental::filesystem::copy(ToPath(*rkOrigPath), ToPath(*rkNewPath), Error);
return (Error.value() == 0);
}
@ -110,8 +112,9 @@ bool MoveFile(const TString& rkOldPath, const TString& rkNewPath)
return false;
}
int Result = rename(*rkOldPath, *rkNewPath);
return (Result == 0);
std::error_code Error;
rename(ToPath(*rkOldPath), ToPath(*rkNewPath), Error);
return Error.value() == 0;
}
bool MoveDirectory(const TString& rkOldPath, const TString& rkNewPath)
@ -128,14 +131,15 @@ bool MoveDirectory(const TString& rkOldPath, const TString& rkNewPath)
return false;
}
int Result = rename(*rkOldPath, *rkNewPath);
return (Result == 0);
std::error_code Error;
rename(ToPath(*rkOldPath), ToPath(*rkNewPath), Error);
return Error.value() == 0;
}
bool DeleteFile(const TString& rkFilePath)
{
if (!IsFile(rkFilePath)) return false;
return remove(*rkFilePath) == 1;
return remove(ToPath(*rkFilePath)) == 1;
}
bool DeleteDirectory(const TString& rkDirPath, bool FailIfNotEmpty)
@ -159,7 +163,7 @@ bool DeleteDirectory(const TString& rkDirPath, bool FailIfNotEmpty)
// Delete directory
std::error_code Error;
remove_all(*rkDirPath, Error);
remove_all(ToPath(*rkDirPath), Error);
return (Error.value() == 0);
}
@ -200,12 +204,12 @@ bool ClearDirectory(const TString& rkDirPath)
u64 FileSize(const TString &rkFilePath)
{
return (u64) (Exists(rkFilePath) ? file_size(*rkFilePath) : -1);
return (u64) (Exists(rkFilePath) ? file_size(ToPath(*rkFilePath)) : -1);
}
u64 LastModifiedTime(const TString& rkFilePath)
{
return (u64) last_write_time(*rkFilePath).time_since_epoch().count();
return (u64) last_write_time(ToPath(*rkFilePath)).time_since_epoch().count();
}
TString WorkingDirectory()
@ -215,7 +219,7 @@ TString WorkingDirectory()
TString MakeAbsolute(TString Path)
{
if (!path(*Path).has_root_name())
if (!ToPath(*Path).has_root_name())
Path = WorkingDirectory() + "/" + Path;
TStringList Components = Path.Split("/\\");
@ -481,7 +485,7 @@ void GetDirectoryContents(TString DirPath, TStringList& rOut, bool Recursive /*=
if (Recursive)
{
for (recursive_directory_iterator It(*DirPath); It != recursive_directory_iterator(); ++It)
for (recursive_directory_iterator It(ToPath(*DirPath)); It != recursive_directory_iterator(); ++It)
{
AddFileLambda(It->path().string());
}
@ -489,7 +493,7 @@ void GetDirectoryContents(TString DirPath, TStringList& rOut, bool Recursive /*=
else
{
for (directory_iterator It(*DirPath); It != directory_iterator(); ++It)
for (directory_iterator It(ToPath(*DirPath)); It != directory_iterator(); ++It)
{
AddFileLambda(It->path().string());
}
@ -499,7 +503,7 @@ void GetDirectoryContents(TString DirPath, TStringList& rOut, bool Recursive /*=
TString FindFileExtension(const TString& rkDir, const TString& rkName)
{
for (directory_iterator It(*rkDir); It != directory_iterator(); ++It)
for (directory_iterator It(ToPath(*rkDir)); It != directory_iterator(); ++It)
{
TString Name = It->path().filename().string();
if (Name.GetFileName(false) == rkName) return Name.GetFileExtension();

View File

@ -20,7 +20,7 @@ public:
: IArchive()
, mOwnsStream(true)
{
mArchiveFlags = AF_Binary | AF_Reader;
mArchiveFlags = AF_Binary | AF_Reader | AF_NoSkipping;
mpStream = new CFileInStream(rkFilename, IOUtil::eBigEndian);
if (mpStream->IsValid())
@ -35,7 +35,7 @@ public:
, mMagicValid(true)
, mOwnsStream(false)
{
mArchiveFlags = AF_Binary | AF_Reader;
mArchiveFlags = AF_Binary | AF_Reader | AF_NoSkipping;
ASSERT(pStream->IsValid());
mpStream = pStream;
@ -47,7 +47,7 @@ public:
, mMagicValid(true)
, mOwnsStream(true)
{
mArchiveFlags = AF_Binary | AF_Reader;
mArchiveFlags = AF_Binary | AF_Reader | AF_NoSkipping;
mpStream = new CMemoryInStream(pData, DataSize, Endian);
SetVersion(rkVersion);
}

View File

@ -20,7 +20,7 @@ public:
, mMagic(Magic)
, mOwnsStream(true)
{
mArchiveFlags = AF_Binary | AF_Writer;
mArchiveFlags = AF_Binary | AF_Writer | AF_NoSkipping;
mpStream = new CFileOutStream(rkFilename, IOUtil::eBigEndian);
if (mpStream->IsValid())
@ -36,7 +36,7 @@ public:
, mOwnsStream(false)
{
ASSERT(pStream->IsValid());
mArchiveFlags = AF_Binary | AF_Writer;
mArchiveFlags = AF_Binary | AF_Writer | AF_NoSkipping;
mpStream = pStream;
SetVersion(skCurrentArchiveVersion, FileVersion, Game);
}
@ -46,7 +46,7 @@ public:
, mOwnsStream(false)
{
ASSERT(pStream->IsValid());
mArchiveFlags = AF_Binary | AF_Writer;
mArchiveFlags = AF_Binary | AF_Writer | AF_NoSkipping;
mpStream = pStream;
SetVersion(rkVersion);
}

View File

@ -17,12 +17,6 @@ CResTypeInfo::CResTypeInfo(EResType Type, const TString& rkTypeName, const TStri
smTypeMap[Type] = this;
}
CResTypeInfo::~CResTypeInfo()
{
// shouldn't happen - we want to just create these at launch and keep them around forever
ASSERT(false);
}
bool CResTypeInfo::IsInGame(EGame Game) const
{
for (u32 iGame = 0; iGame < mCookedExtensions.size(); iGame++)

View File

@ -28,7 +28,7 @@ class CResTypeInfo
// Private Methods
CResTypeInfo(EResType Type, const TString& rkTypeName, const TString& rkRetroExtension);
~CResTypeInfo();
~CResTypeInfo() {}
// Public Methods
public:

View File

@ -55,6 +55,7 @@ void CGameTemplate::Load(const TString& kFilePath)
void CGameTemplate::Save()
{
Log::Write("Saving game template: " + mSourceFile);
CXMLWriter Writer(mSourceFile, "Game", 0, mGame);
ASSERT(Writer.IsValid());
Serialize(Writer);
@ -108,6 +109,7 @@ void CGameTemplate::SaveGameTemplates(bool ForceAll /*= false*/)
const TString kOutPath = kGameDir + Path.Path;
FileUtil::MakeDirectory( kOutPath.GetFileDirectory() );
Log::Write("Saving property template: " + kOutPath);
CXMLWriter Writer(kOutPath, "PropertyTemplate", 0, Game());
ASSERT(Writer.IsValid());

View File

@ -96,8 +96,9 @@ void CScriptTemplate::Serialize(IArchive& Arc)
void CScriptTemplate::Save(bool Force)
{
if (mDirty || Force)
if (IsDirty() || Force)
{
Log::Write("Saving script template: " + mSourceFile);
CXMLWriter Writer(mSourceFile, "ScriptObject", 0, mpGame->Game());
ASSERT(Writer.IsValid());
Serialize(Writer);

View File

@ -1,4 +1,5 @@
#include "NGameList.h"
#include <Common/Log.h>
namespace NGameList
{
@ -85,6 +86,7 @@ inline void SerializeGameList(IArchive& Arc)
void LoadGameList()
{
ASSERT(!gLoadedGameList);
Log::Write("Loading game list");
CXMLReader Reader(gkGameListPath);
ASSERT(Reader.IsValid());
@ -97,6 +99,7 @@ void LoadGameList()
void SaveGameList()
{
ASSERT(gLoadedGameList);
Log::Write("Saving game list");
CXMLWriter Writer(gkGameListPath, "GameList");
ASSERT(Writer.IsValid());

View File

@ -132,10 +132,16 @@ SNameKey CreateKey(IProperty* pProperty)
return Key;
}
SNameKey CreateKey(u32 ID, const char* pkTypeName)
{
return SNameKey( CCRC32::StaticHashString(pkTypeName), ID );
}
/** Loads property names into memory */
void LoadMap()
{
ASSERT( !gMapIsLoaded );
Log::Write("Loading property map");
if ( gkUseLegacyMapForNameLookups )
{
@ -165,6 +171,7 @@ inline void ConditionalLoadMap()
void SaveMap(bool Force /*= false*/)
{
ASSERT( gMapIsLoaded );
Log::Write("Saving property map");
if( gMapIsDirty || Force )
{
@ -210,21 +217,67 @@ const char* GetPropertyName(u32 ID, const char* pkTypeName)
// Does not support legacy map
ConditionalLoadMap();
SNameKey Key( CCRC32::StaticHashString(pkTypeName), ID );
SNameKey Key = CreateKey(ID, pkTypeName);
auto MapFind = gNameMap.find(Key);
return MapFind == gNameMap.end() ? "Unknown" : *MapFind->second.Name;
}
/** Returns whether the specified name is in the map. */
bool IsValidPropertyName(u32 ID, const char* pkTypeName)
{
SNameKey Key = CreateKey(ID, pkTypeName);
auto MapFind = gNameMap.find(Key);
return MapFind != gNameMap.end();
}
/** Retrieves a list of all properties that match the requested property ID. */
void RetrievePropertiesWithID(u32 ID, const char* pkTypeName, std::list<IProperty*>& OutList)
{
SNameKey Key = CreateKey(ID, pkTypeName);
auto MapFind = gNameMap.find(Key);
if (MapFind != gNameMap.end())
{
SNameValue& Value = MapFind->second;
OutList = Value.PropertyList;
}
}
/** Retrieves a list of all XML templates that contain a given property ID. */
void RetrieveXMLsWithProperty(u32 ID, const char* pkTypeName, std::set<TString>& OutSet)
{
SNameKey Key = CreateKey(ID, pkTypeName);
auto MapFind = gNameMap.find(Key);
if (MapFind != gNameMap.end())
{
SNameValue& NameValue = MapFind->second;
for (auto ListIter = NameValue.PropertyList.begin(); ListIter != NameValue.PropertyList.end(); ListIter++)
{
IProperty* pProperty = *ListIter;
OutSet.insert( pProperty->GetTemplateFileName() );
}
}
}
/** Updates the name of a given property in the map */
void SetPropertyName(IProperty* pProperty, const char* pkNewName)
void SetPropertyName(u32 ID, const char* pkTypeName, const char* pkNewName)
{
if( gkUseLegacyMapForUpdates )
{
gLegacyNameMap[pProperty->ID()] = pkNewName;
auto Iter = gLegacyNameMap.find(ID);
if (Iter == gLegacyNameMap.end() || Iter->second != pkNewName)
{
Iter->second = pkNewName;
gMapIsDirty = true;
}
}
else
{
SNameKey Key = CreateKey(pProperty);
SNameKey Key = CreateKey(ID, pkTypeName);
auto MapFind = gNameMap.find(Key);
if (MapFind != gNameMap.end())
@ -235,6 +288,7 @@ void SetPropertyName(IProperty* pProperty, const char* pkNewName)
{
TString OldName = Value.Name;
Value.Name = pkNewName;
gMapIsDirty = true;
// Update all properties with this ID with the new name
for (auto Iter = Value.PropertyList.begin(); Iter != Value.PropertyList.end(); Iter++)
@ -250,8 +304,6 @@ void SetPropertyName(IProperty* pProperty, const char* pkNewName)
}
}
}
gMapIsDirty = true;
}
/** Registers a property in the name map. Should be called on all properties that use the map */

View File

@ -22,8 +22,17 @@ const char* GetPropertyName(IProperty* pProperty);
*/
const char* GetPropertyName(u32 ID, const char* pkTypeName);
/** Returns whether the specified name is in the map. */
bool IsValidPropertyName(u32 ID, const char* pkTypeName);
/** Retrieves a list of all properties that match the requested property ID. */
void RetrievePropertiesWithID(u32 ID, const char* pkTypeName, std::list<IProperty*>& OutList);
/** Retrieves a list of all XML templates that contain a given property ID. */
void RetrieveXMLsWithProperty(u32 ID, const char* pkTypeName, std::set<TString>& OutSet);
/** Updates the name of a given property in the map */
void SetPropertyName(IProperty* pProperty, const char* pkNewName);
void SetPropertyName(u32 ID, const char* pkTypeName, const char* pkNewName);
/** Registers a property in the name map. Should be called on all properties that use the map */
void RegisterProperty(IProperty* pProperty);

View File

@ -2,6 +2,7 @@
#include "IUIRelay.h"
#include "Core/Resource/Factory/CTemplateLoader.h"
#include "Core/Resource/Script/CGameTemplate.h"
#include "Core/Resource/Script/NPropertyMap.h"
#include <Common/Hash/CCRC32.h>
/** Default constructor */
@ -146,17 +147,16 @@ void CPropertyNameGenerator::Generate(const SPropertyNameGenerationParameters& r
for (int TypeIdx = 0; TypeIdx < rkParams.TypeNames.size(); TypeIdx++)
{
CCRC32 FullHash = BaseHash;
FullHash.Hash( *rkParams.TypeNames[TypeIdx] );
const char* pkTypeName = *rkParams.TypeNames[TypeIdx];
FullHash.Hash( pkTypeName );
u32 PropertyID = FullHash.Digest();
//@FIXME
#if 0
// Check if this hash is a property ID - it's valid if there are any XMLs using this ID
SGeneratedPropertyName PropertyName;
CGameTemplate::XMLsUsingID(PropertyID, PropertyName.XmlList);
if (PropertyName.XmlList.size() > 0)
// Check if this hash is a property ID
if (NPropertyMap::IsValidPropertyName(PropertyID, pkTypeName))
{
SGeneratedPropertyName PropertyName;
NPropertyMap::RetrieveXMLsWithProperty(PropertyID, pkTypeName, PropertyName.XmlList);
// Generate a string with the complete name. (We wait to do this until now to avoid needless string allocation)
PropertyName.Name = rkParams.Prefix;
@ -195,16 +195,15 @@ void CPropertyNameGenerator::Generate(const SPropertyNameGenerationParameters& r
{
TString DelimitedXmlList;
for (int XmlIdx = 0; XmlIdx < PropertyName.XmlList.size(); XmlIdx++)
for (auto Iter = PropertyName.XmlList.begin(); Iter != PropertyName.XmlList.end(); Iter++)
{
DelimitedXmlList += PropertyName.XmlList[XmlIdx] + "\n";
DelimitedXmlList += *Iter + "\n";
}
TString LogMsg = TString::Format("%s [%s] : 0x%08X\n", *PropertyName.Name, *PropertyName.Type, PropertyName.ID) + DelimitedXmlList;
Log::Write(LogMsg);
}
}
#endif
}
// Every 250 tests, check with the progress notifier. Update the progress

View File

@ -32,7 +32,7 @@ struct SGeneratedPropertyName
TString Name;
TString Type;
u32 ID;
std::vector<TString> XmlList;
std::set<TString> XmlList;
};
/** Generates property names and validates them against know property IDs. */

View File

@ -275,15 +275,35 @@ IProperty* IProperty::ChildByIDString(const TIDString& rkIdString)
TString IProperty::GetTemplateFileName()
{
if (mpScriptTemplate)
// We want to return the path to the XML file that this property originally belongs to.
// So, for example, if this is a property of a script template, we want to return that script template.
// However, if this property was copied from a property archetype... If we are a direct instance of an
// archetype property (for instance a DamageInfo struct instance), then we want to return the template
// that contains the instance. However, if we are a sub-property of an archetype, then we want to return
// the path to that archetype instead. Hopefully that makes sense!
IProperty* pTemplateRoot = this;
// If our archetype has a parent, then our archetype is a sub-property of the main archetype, and we
// need to go deeper to find the original source XML file.
//
// If our archetype doesn't have a parent, then we are an instance of the main archetype, and we stop here.
while (pTemplateRoot->Archetype() && pTemplateRoot->Archetype()->Parent())
{
return mpScriptTemplate->SourceFile();
pTemplateRoot = pTemplateRoot->Archetype();
}
pTemplateRoot = pTemplateRoot->RootParent();
// Now that we have the base property of our template, we can return the file path.
static const u32 kChopAmount = strlen("../templates/");
if (pTemplateRoot->ScriptTemplate())
{
return pTemplateRoot->ScriptTemplate()->SourceFile().ChopFront(kChopAmount);
}
else
{
CGameTemplate* pGameTemplate = NGameList::GetGameTemplate(Game());
IProperty* pTemplateRoot = (IsArchetype() ? RootParent() : mpArchetype);
return pGameTemplate->GetPropertyArchetypeFilePath( pTemplateRoot->Name() );
return pGameTemplate->GetPropertyArchetypeFilePath( pTemplateRoot->Name() ).ChopFront(kChopAmount);
}
}
@ -304,27 +324,36 @@ bool IProperty::ShouldCook(void* pPropertyData) const
void IProperty::SetName(const TString& rkNewName)
{
mName = rkNewName;
mFlags.ClearFlag(EPropertyFlag::HasCachedNameCheck);
// in Echoes and on, since property names are referenced by ID, renaming a property
// doesn't directly affect the serialized data, so it doesn't need to be flagged dirty
if (mGame <= EGame::Prime)
if (mName != rkNewName)
{
MarkDirty();
mName = rkNewName;
mFlags.ClearFlag(EPropertyFlag::HasCachedNameCheck);
// in Echoes and on, since property names are referenced by ID, renaming a property
// doesn't directly affect the serialized data, so it doesn't need to be flagged dirty
if (mGame <= EGame::Prime)
{
MarkDirty();
}
}
}
void IProperty::SetDescription(const TString& rkNewDescription)
{
mDescription = rkNewDescription;
MarkDirty();
if (mDescription != rkNewDescription)
{
mDescription = rkNewDescription;
MarkDirty();
}
}
void IProperty::SetSuffix(const TString& rkNewSuffix)
{
mSuffix = rkNewSuffix;
MarkDirty();
if (mSuffix != rkNewSuffix)
{
mSuffix = rkNewSuffix;
MarkDirty();
}
}
void IProperty::MarkDirty()

View File

@ -211,6 +211,7 @@ public:
inline IProperty* Parent() const;
inline IProperty* RootParent();
inline IProperty* Archetype() const;
inline IProperty* RootArchetype();
inline CScriptTemplate* ScriptTemplate() const;
inline TString Name() const;
inline TString Description() const;
@ -286,6 +287,20 @@ inline IProperty* IProperty::Archetype() const
return mpArchetype;
}
inline IProperty* IProperty::RootArchetype()
{
IProperty* pArchetype = Archetype();
IProperty* pOut = this;
while (pArchetype)
{
pOut = pArchetype;
pArchetype = pArchetype->Archetype();
}
return pOut;
}
inline CScriptTemplate* IProperty::ScriptTemplate() const
{
return mpScriptTemplate;

View File

@ -225,13 +225,11 @@ void CGeneratePropertyNamesDialog::ApplyChanges()
{
QTreeWidgetItem* pItem = mCheckedItems[ItemIdx];
u32 ID = TO_TSTRING( pItem->text(2) ).ToInt32();
TString Type = TO_TSTRING( pItem->text(1) );
TString NewName = TO_TSTRING( pItem->text(0) );
//FIXME
#if 0
QString NewName = pItem->text(0);
NPropertyMap::SetPropertyName(::RenameProperty( ID, TO_TSTRING(NewName) );
pItem->setText(3, NewName);
#endif
NPropertyMap::SetPropertyName( ID, *Type, *NewName );
pItem->setText( 3, TO_QSTRING(NewName) );
}
NPropertyMap::SaveMap();
@ -270,9 +268,9 @@ void CGeneratePropertyNamesDialog::CheckForNewResults()
pItem->setCheckState(0, Qt::Unchecked);
// Add children items
for (int XmlIdx = 0; XmlIdx < rkName.XmlList.size(); XmlIdx++)
for (auto Iter = rkName.XmlList.begin(); Iter != rkName.XmlList.end(); Iter++)
{
QString XmlName = TO_QSTRING( rkName.XmlList[XmlIdx] );
QString XmlName = TO_QSTRING( *Iter );
ColumnText.clear();
ColumnText << XmlName;

View File

@ -36,14 +36,11 @@ CTemplateEditDialog::CTemplateEditDialog(IProperty *pProperty, QWidget *pParent)
{
NGameList::LoadAllGameTemplates();
//@FIXME
#if 0
std::vector<TString> TemplateList;
CGameTemplate::XMLsUsingID(pProperty->ID(), TemplateList);
std::set<TString> Templates;
NPropertyMap::RetrieveXMLsWithProperty( pProperty->ID(), pProperty->HashableTypeName(), Templates );
for (u32 iTemp = 0; iTemp < TemplateList.size(); iTemp++)
mpUI->TemplatesListWidget->addItem(TO_QSTRING(TemplateList[iTemp]));
#endif
for (auto Iter = Templates.begin(); Iter != Templates.end(); Iter++)
mpUI->TemplatesListWidget->addItem(TO_QSTRING(*Iter));
mpUI->ValidityLabel->SetValidityText("Hash match! Property name is likely correct.", "Hash mismatch! Property name is likely wrong.");
connect(mpUI->NameLineEdit, SIGNAL( SoftValidityChanged(bool) ), mpUI->ValidityLabel, SLOT( SetValid(bool) ) );
@ -94,7 +91,7 @@ void CTemplateEditDialog::ApplyChanges()
// Rename properties
if (RenameAll && (mGame >= EGame::EchoesDemo || mpProperty->Archetype() != nullptr))
{
NPropertyMap::SetPropertyName(mpProperty, *NewName);
NPropertyMap::SetPropertyName(mpProperty->ID(), mpProperty->HashableTypeName(), *NewName);
}
}
@ -102,10 +99,8 @@ void CTemplateEditDialog::ApplyChanges()
UpdateDescription(NewDescription);
// Resave templates
NGameList::SaveTemplates();
NPropertyMap::SaveMap();
CGameTemplate* pGameTemplate = NGameList::GetGameTemplate( mpProperty->Game() );
pGameTemplate->SaveGameTemplates();
close();
}
@ -115,23 +110,19 @@ void CTemplateEditDialog::UpdateDescription(const TString& rkNewDesc)
mpProperty->SetDescription(rkNewDesc);
// Update all copies of this property in memory with the new description
//@FIXME
#if 0
TString SourceFile = mpProperty->GetTemplateFileName();
if (!SourceFile.IsEmpty())
{
const std::vector<IProperty*>* pkTemplates = CGameTemplate::TemplatesWithMatchingID(mpProperty);
std::list<IProperty*> Templates;
NPropertyMap::RetrievePropertiesWithID(mpProperty->ID(), mpProperty->HashableTypeName(), Templates);
if (pkTemplates)
for (auto Iter = Templates.begin(); Iter != Templates.end(); Iter++)
{
for (u32 TemplateIdx = 0; TemplateIdx < pkTemplates->size(); TemplateIdx++)
{
IProperty* pProp = pkTemplates->at(TemplateIdx);
IProperty* pProperty = *Iter;
if (pProp->GetTemplateFileName() == SourceFile && pProp->Description() == mOriginalDescription)
pProp->SetDescription(rkNewDesc);
}
if (pProperty->GetTemplateFileName() == SourceFile && pProperty->Description() == mOriginalDescription)
pProperty->SetDescription(rkNewDesc);
}
}
@ -140,73 +131,60 @@ void CTemplateEditDialog::UpdateDescription(const TString& rkNewDesc)
{
pProperty->SetDescription(rkNewDesc);
}
#endif
}
void CTemplateEditDialog::FindEquivalentProperties(IProperty *pTemp)
void CTemplateEditDialog::FindEquivalentProperties(IProperty* pProperty)
{
//FIXME
/*
// This function creates a list of properties in other games that are equivalent to this one.
// In this case "equivalent" means same template file and same ID string.
// Since MP1 doesn't have property IDs, we don't apply this to MP1.
if (mGame <= EGame::Prime) return;
// Find the equivalent version of this property in other games.
CScriptTemplate *pScript = pTemp->ScriptTemplate();
TString Source = pTemp->FindStructSource();
// Determine struct-relative ID string
TIDString IDString;
if (Source.IsEmpty())
IDString = pTemp->IDString(true);
else
// Find the lowest-level archetype and retrieve the ID string relative to that archetype's XML file.
while (pProperty->Archetype())
{
IDString = pTemp->IDString(false);
CStructTemplate *pParent = pTemp->Parent();
while (pParent)
{
if (!pParent->SourceFile().IsEmpty()) break;
IDString.Prepend(pParent->IDString(false) + ":");
pParent = pParent->Parent();
}
pProperty = pProperty->Archetype();
}
TString Name = pProperty->Name();
TIDString IDString = pProperty->IDString(true);
CScriptTemplate* pScript = pProperty->ScriptTemplate();
QList<CGameTemplate*> GameList = QList<CGameTemplate*>::fromStdList(CGameTemplate::GameList());
if (Source.IsEmpty())
// Now iterate over all games, check for an equivalent property in an equivalent XML file.
for (int GameIdx = 0; GameIdx < (int) EGame::Max; GameIdx++)
{
u32 ObjectID = pScript->ObjectID();
EGame Game = (EGame) GameIdx;
if (Game <= EGame::Prime || Game == mGame) continue;
foreach (CGameTemplate *pGame, GameList)
CGameTemplate* pGame = NGameList::GetGameTemplate(Game);
// Check for equivalent properties in a script template
CStructProperty* pStruct = nullptr;
if (pScript)
{
if (pGame == pTemp->GameTemplate() || pGame->Game() <= EGame::Prime) continue;
CScriptTemplate *pNewScript = pGame->TemplateByID(ObjectID);
u32 ObjectID = pScript->ObjectID();
CScriptTemplate* pEquivalentScript = pGame->TemplateByID(ObjectID);
if (pNewScript)
if (pEquivalentScript)
{
IPropertyTemplate *pNewTemp = pNewScript->BaseStruct()->PropertyByIDString(IDString);
pStruct = pEquivalentScript->Properties();
}
}
// Check for equivalent properties in a property template
else
{
pStruct = TPropCast<CStructProperty>( pGame->FindPropertyArchetype(Name) );
}
if (pNewTemp)
mEquivalentProperties << pNewTemp;
// If we have a struct, check if thestruct contains an equivalent property.
if (pStruct)
{
IProperty* pEquivalentProperty = pStruct->ChildByIDString( IDString );
if (pEquivalentProperty)
{
mEquivalentProperties << pEquivalentProperty;
}
}
}
else
{
foreach (CGameTemplate *pGame, GameList)
{
if (pGame == pTemp->GameTemplate() || pGame->Game() <= EGame::Prime) continue;
CStructTemplate *pStruct = pGame->StructAtSource(Source);
if (pStruct)
{
IPropertyTemplate *pNewTemp = pStruct->PropertyByIDString(IDString);
if (pNewTemp)
mEquivalentProperties << pNewTemp;
}
}
}*/
}

View File

@ -35,7 +35,7 @@ public slots:
protected:
void UpdateDescription(const TString& rkNewDesc);
void FindEquivalentProperties(IProperty *pTemp);
void FindEquivalentProperties(IProperty *pProperty);
};
#endif // CTEMPLATEEDITDIALOG_H

View File

@ -23,58 +23,78 @@ void QtLogRedirect(QtMsgType Type, const QMessageLogContext& /*rkContext*/, cons
}
}
int main(int argc, char *argv[])
class CMain
{
// Create application
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
CEditorApplication App(argc, argv);
App.setApplicationName( APP_NAME );
App.setApplicationVersion( APP_VERSION );
App.setOrganizationName("Aruki");
App.setWindowIcon(QIcon(":/icons/AppIcon.ico"));
// Create UI relay
CUIRelay UIRelay(&App);
gpUIRelay = &UIRelay;
// Set up dark theme
qApp->setStyle(QStyleFactory::create("Fusion"));
QPalette DarkPalette;
DarkPalette.setColor(QPalette::Window, QColor(53,53,53));
DarkPalette.setColor(QPalette::WindowText, Qt::white);
DarkPalette.setColor(QPalette::Base, QColor(25,25,25));
DarkPalette.setColor(QPalette::AlternateBase, QColor(35,35,35));
DarkPalette.setColor(QPalette::ToolTipBase, Qt::white);
DarkPalette.setColor(QPalette::ToolTipText, Qt::white);
DarkPalette.setColor(QPalette::Text, Qt::white);
DarkPalette.setColor(QPalette::Button, QColor(53,53,53));
DarkPalette.setColor(QPalette::ButtonText, Qt::white);
DarkPalette.setColor(QPalette::BrightText, Qt::red);
DarkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
DarkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
DarkPalette.setColor(QPalette::HighlightedText, Qt::white);
qApp->setPalette(DarkPalette);
// Init log
bool Initialized = Log::InitLog("primeworldeditor.log");
if (!Initialized) QMessageBox::warning(0, "Error", "Couldn't open log file. Logging will not work for this session.");
qInstallMessageHandler(QtLogRedirect);
// Create editor resource store
gpEditorStore = new CResourceStore("../resources/");
if (!gpEditorStore->AreAllEntriesValid())
public:
/** Main function */
int Main(int argc, char *argv[])
{
Log::Write("Editor store has invalid entries. Rebuilding database...");
gpEditorStore->RebuildFromDirectory();
gpEditorStore->ConditionalSaveStore();
// Create application
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
CEditorApplication App(argc, argv);
App.setApplicationName( APP_NAME );
App.setApplicationVersion( APP_VERSION );
App.setOrganizationName("Aruki");
App.setWindowIcon(QIcon(":/icons/AppIcon.ico"));
// Create UI relay
CUIRelay UIRelay(&App);
gpUIRelay = &UIRelay;
// Set up dark theme
qApp->setStyle(QStyleFactory::create("Fusion"));
QPalette DarkPalette;
DarkPalette.setColor(QPalette::Window, QColor(53,53,53));
DarkPalette.setColor(QPalette::WindowText, Qt::white);
DarkPalette.setColor(QPalette::Base, QColor(25,25,25));
DarkPalette.setColor(QPalette::AlternateBase, QColor(35,35,35));
DarkPalette.setColor(QPalette::ToolTipBase, Qt::white);
DarkPalette.setColor(QPalette::ToolTipText, Qt::white);
DarkPalette.setColor(QPalette::Text, Qt::white);
DarkPalette.setColor(QPalette::Button, QColor(53,53,53));
DarkPalette.setColor(QPalette::ButtonText, Qt::white);
DarkPalette.setColor(QPalette::BrightText, Qt::red);
DarkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
DarkPalette.setColor(QPalette::Highlight, QColor(42, 130, 218));
DarkPalette.setColor(QPalette::HighlightedText, Qt::white);
qApp->setPalette(DarkPalette);
// Init log
bool Initialized = Log::InitLog("primeworldeditor.log");
if (!Initialized) QMessageBox::warning(0, "Error", "Couldn't open log file. Logging will not work for this session.");
qInstallMessageHandler(QtLogRedirect);
// Create editor resource store
gpEditorStore = new CResourceStore("../resources/");
if (!gpEditorStore->AreAllEntriesValid())
{
Log::Write("Editor store has invalid entries. Rebuilding database...");
gpEditorStore->RebuildFromDirectory();
gpEditorStore->ConditionalSaveStore();
}
for (int i = 0; i < (int) EGame::Max; i++)
{
CGameTemplate* pGame = NGameList::GetGameTemplate( (EGame) i );
if (pGame) pGame->Save();
}
return 0;
// Execute application
App.InitEditor();
return App.exec();
}
// Execute application
App.InitEditor();
int ReturnValue = App.exec();
/** Clean up any resources at the end of application execution */
~CMain()
{
NGameList::Shutdown();
}
};
// Clean up
NGameList::Shutdown();
return ReturnValue;
int main(int argc, char *argv[])
{
CMain Main;
return Main.Main(argc, argv);
}

View File

@ -659,6 +659,10 @@
<Key>ActorMultiKeyframeStruct</Key>
<Value Path="Structs/ActorMultiKeyframeStruct.xml"/>
</Element>
<Element>
<Key>ActivationTime</Key>
<Value Path="Structs/ActivationTime.xml"/>
</Element>
<Element>
<Key>ActorParameters</Key>
<Value Path="Structs/ActorParameters.xml"/>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<PropertyTemplate ArchiveVer="4" Game="DKCReturns">
<PropertyArchetype Type="Struct">
<Name>ActivationTime</Name>
<Atomic>true</Atomic>
<SubProperties>
<Element Type="Float" ID="0x0">
<Name>Time</Name>
<DefaultValue>0.0</DefaultValue>
</Element>
<Element Type="Int" ID="0x1">
<Name>Unknown 1</Name>
<DefaultValue>0</DefaultValue>
</Element>
<Element Type="Int" ID="0x2">
<Name>Unknown 2</Name>
<DefaultValue>0</DefaultValue>
</Element>
<Element Type="Int" ID="0x3">
<Name>Unknown 3</Name>
<DefaultValue>0</DefaultValue>
</Element>
</SubProperties>
</PropertyArchetype>
</PropertyTemplate>

View File

@ -10,10 +10,7 @@
</Element>
<Element Type="Array" ID="0x1">
<Name>Activation Times</Name>
<ItemArchetype Type="Float" ID="0x0">
<Name></Name>
<DefaultValue>0.0</DefaultValue>
</ItemArchetype>
<ItemArchetype Type="Struct" Archetype="ActivationTime"/>
</Element>
</SubProperties>
</PropertyArchetype>

View File

@ -839,6 +839,10 @@
<Key>Abilities</Key>
<Value Path="Structs/Abilities.xml"/>
</Element>
<Element>
<Key>ActivationTime</Key>
<Value Path="Structs/ActivationTime.xml"/>
</Element>
<Element>
<Key>ActorParameters</Key>
<Value Path="Structs/ActorParameters.xml"/>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<PropertyTemplate ArchiveVer="4" Game="Corruption">
<PropertyArchetype Type="Struct">
<Name>ActivationTime</Name>
<Atomic>true</Atomic>
<SubProperties>
<Element Type="Float" ID="0x0">
<Name>Time</Name>
<DefaultValue>0.0</DefaultValue>
</Element>
<Element Type="Int" ID="0x1">
<Name>Unknown 1</Name>
<DefaultValue>0</DefaultValue>
</Element>
<Element Type="Int" ID="0x2">
<Name>Unknown 2</Name>
<DefaultValue>0</DefaultValue>
</Element>
<Element Type="Int" ID="0x3">
<Name>Unknown 3</Name>
<DefaultValue>0</DefaultValue>
</Element>
</SubProperties>
</PropertyArchetype>
</PropertyTemplate>

View File

@ -10,10 +10,7 @@
</Element>
<Element Type="Array" ID="0x1">
<Name>Activation Times</Name>
<ItemArchetype Type="Float" ID="0x0">
<Name></Name>
<DefaultValue>0.0</DefaultValue>
</ItemArchetype>
<ItemArchetype Type="Struct" Archetype="ActivationTime"/>
</Element>
</SubProperties>
</PropertyArchetype>

View File

@ -623,6 +623,10 @@
<Key>Abilities</Key>
<Value Path="Structs/Abilities.xml"/>
</Element>
<Element>
<Key>ActivationTime</Key>
<Value Path="Structs/ActivationTime.xml"/>
</Element>
<Element>
<Key>ActorParameters</Key>
<Value Path="Structs/ActorParameters.xml"/>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<PropertyTemplate ArchiveVer="4" Game="CorruptionProto">
<PropertyArchetype Type="Struct">
<Name>ActivationTime</Name>
<Atomic>true</Atomic>
<SubProperties>
<Element Type="Float" ID="0x0">
<Name>Time</Name>
<DefaultValue>0.0</DefaultValue>
</Element>
<Element Type="Int" ID="0x1">
<Name>Unknown 1</Name>
<DefaultValue>0</DefaultValue>
</Element>
<Element Type="Int" ID="0x2">
<Name>Unknown 2</Name>
<DefaultValue>0</DefaultValue>
</Element>
<Element Type="Int" ID="0x3">
<Name>Unknown 3</Name>
<DefaultValue>0</DefaultValue>
</Element>
</SubProperties>
</PropertyArchetype>
</PropertyTemplate>

View File

@ -10,10 +10,7 @@
</Element>
<Element Type="Array" ID="0x1">
<Name>Activation Times</Name>
<ItemArchetype Type="Float" ID="0x0">
<Name></Name>
<DefaultValue>0.0</DefaultValue>
</ItemArchetype>
<ItemArchetype Type="Struct" Archetype="ActivationTime"/>
</Element>
</SubProperties>
</PropertyArchetype>