mirror of
https://github.com/AxioDL/PrimeWorldEditor.git
synced 2025-12-14 23:56:23 +00:00
Fixed property name generator/template edit dialog to work with new property system
This commit is contained in:
@@ -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());
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user