Files
o3de/Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsSerialization.cpp
T
Esteban Papp 1f9b284de2 Merge branch 'development' into cmake/SPEC-7179
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>

# Conflicts:
#	Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h
#	Code/Editor/Plugins/EditorCommon/EditorCommon_precompiled.h
#	Code/Editor/Plugins/EditorCommon/stdafx.cpp
#	Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin_precompiled.h
#	Code/Editor/Plugins/PerforcePlugin/PerforcePlugin_precompiled.h
#	Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsTool_precompiled.h
#	Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFramework_precompiled.h
#	Code/Tools/AssetProcessor/native/precompiled.h
#	Code/Tools/Standalone/StandaloneTools_precompiled.h
#	Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer_precompiled.h
#	Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageProcessing_precompiled.h
#	Gems/Atom/RHI/DX12/Code/Source/RHI/Atom_RHI_DX12_precompiled.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/Mac/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/iOS/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Source/Atom_RHI_Metal_precompiled.h
#	Gems/Atom/RHI/Metal/Code/atom_rhi_metal_common_files.cmake
#	Gems/Atom/RHI/Null/Code/Source/Atom_RHI_Null_precompiled.h
#	Gems/Atom/RHI/Null/Code/atom_rhi_null_common_files.cmake
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Android/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Linux/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Mac/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Windows/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Source/Atom_RHI_Vulkan_precompiled.h
#	Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp
#	Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_common_files.cmake
#	Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h
#	Gems/Blast/Code/Source/StdAfx.cpp
#	Gems/Camera/Code/Source/Camera_precompiled.h
#	Gems/EMotionFX/Code/Source/EMotionFX_precompiled.h
#	Gems/FastNoise/Code/Source/FastNoise_precompiled.h
#	Gems/Gestures/Code/Source/Gestures_precompiled.h
#	Gems/GradientSignal/Code/Source/GradientSignal_precompiled.h
#	Gems/GraphCanvas/Code/precompiled.h
#	Gems/ImGui/Code/Source/ImGui_precompiled.h
#	Gems/InAppPurchases/Code/Source/InAppPurchases_precompiled.h
#	Gems/LmbrCentral/Code/Source/LmbrCentral_precompiled.h
#	Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp
#	Gems/LyShine/Code/Editor/UiCanvasEditor_precompiled.h
#	Gems/LyShine/Code/Source/Animation/LyShine_precompiled.h
#	Gems/LyShine/Code/Source/LyShine_precompiled.h
#	Gems/LyShineExamples/Code/Source/LyShineExamples_precompiled.h
#	Gems/Maestro/Code/Source/Cinematics/Maestro_precompiled.h
#	Gems/Maestro/Code/Source/Maestro_precompiled.h
#	Gems/MessagePopup/Code/Source/MessagePopup_precompiled.h
#	Gems/Metastream/Code/Source/Metastream_precompiled.h
#	Gems/Microphone/Code/Source/Microphone_precompiled.h
#	Gems/Multiplayer/Code/Source/Multiplayer_precompiled.h
#	Gems/PhysX/Code/NumericalMethods/Source/NumericalMethods_precompiled.h
#	Gems/PhysX/Code/Source/PhysXUnsupported_precompiled.h
#	Gems/PhysX/Code/Source/PhysX_precompiled.h
#	Gems/PhysX/Code/physx_unsupported_files.cmake
#	Gems/PhysXDebug/Code/Source/PhysXDebugUnsupported_precompiled.h
#	Gems/PhysXDebug/Code/Source/PhysXDebug_precompiled.h
#	Gems/ScriptCanvas/Code/Editor/precompiled.h
#	Gems/ScriptCanvas/Code/Source/precompiled.h
#	Gems/ScriptCanvasDeveloper/Code/Source/precompiled.h
#	Gems/ScriptCanvasPhysics/Code/Source/ScriptCanvasPhysics_precompiled.h
#	Gems/ScriptEvents/Code/Source/precompiled.h
#	Gems/ScriptEvents/Code/Tests/Editor/EditorTests.cpp
#	Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweener_precompiled.h
#	Gems/SliceFavorites/Code/Source/SliceFavorites_precompiled.h
#	Gems/StartingPointCamera/Code/Source/StartingPointCamera_precompiled.h
#	Gems/StartingPointInput/Code/Source/StartingPointInput_precompiled.h
#	Gems/StartingPointMovement/Code/Source/StartingPointMovement_precompiled.h
#	Gems/SurfaceData/Code/Source/SurfaceData_precompiled.h
#	Gems/TextureAtlas/Code/Source/TextureAtlas_precompiled.h
#	Gems/TickBusOrderViewer/Code/Source/TickBusOrderViewer_precompiled.h
#	Gems/Twitch/Code/Source/Twitch_precompiled.h
#	Gems/VirtualGamepad/Code/Source/VirtualGamepad_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBoxUnsupported_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBox_precompiled.h
2021-07-16 15:42:37 -07:00

921 lines
33 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <EditorDefs.h>
#include "ProjectSettingsSerialization.h"
#include "PlatformSettings_common.h"
#include <AzToolsFramework/UI/PropertyEditor/InstanceDataHierarchy.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
// Needed to overwrite ios icons and launchscreens
#include <Util/FileUtil.h>
namespace ProjectSettingsTool
{
using XmlNode = AZ::rapidxml::xml_node<char>;
const char* stringStr = "string";
const char* arrayStr = "array";
const char* trueStr = "true";
const char* noDocumentError = "No json or xml document to use for Project Settings Tool serialization.";
Serializer::Serializer(AzToolsFramework::InstanceDataNode* root)
: m_root(root)
, m_jsonDoc(nullptr)
, m_jsonRoot(nullptr)
, m_idString(AZ::SerializeTypeInfo<AZStd::string>::GetUuid())
, m_idInt(AZ::SerializeTypeInfo<int>::GetUuid())
, m_idBool(AZ::SerializeTypeInfo<bool>::GetUuid())
{}
Serializer::Serializer(AzToolsFramework::InstanceDataNode* root, rapidjson::Document* doc, rapidjson::Value* jsonRoot)
: Serializer(root)
{
SetDocumentRoot(doc);
if (jsonRoot != nullptr)
{
SetJsonRoot(jsonRoot);
}
else
{
SetJsonRoot(doc);
}
}
Serializer::Serializer(AzToolsFramework::InstanceDataNode* root, AZStd::unique_ptr<PlistDictionary> dict)
: Serializer(root)
{
SetDocumentRoot(AZStd::move(dict));
}
void Serializer::SetDocumentRoot(rapidjson::Document* doc)
{
m_jsonDoc = doc;
}
void Serializer::SetJsonRoot(rapidjson::Value* jsonRoot)
{
m_jsonRoot = jsonRoot;
}
void Serializer::SetDocumentRoot(AZStd::unique_ptr<PlistDictionary> dict)
{
m_plistDict = AZStd::move(dict);
}
bool Serializer::UiEqualToSettings() const
{
if (m_jsonRoot != nullptr)
{
return UiEqualToJson(m_jsonRoot);
}
else if (m_plistDict)
{
return UiEqualToPlist(m_root);
}
else
{
AZ_Assert(false, noDocumentError);
return false;
}
}
void Serializer::LoadFromSettings()
{
if (m_jsonRoot != nullptr)
{
LoadFromSettings(m_jsonRoot);
}
else if (m_plistDict)
{
LoadFromSettings(m_root);
}
else
{
AZ_Assert(false, noDocumentError);
}
}
void Serializer::SaveToSettings()
{
if (m_jsonRoot != nullptr)
{
SaveToSettings(m_jsonRoot);
}
else if (m_plistDict)
{
SaveToSettings(m_root);
}
else
{
AZ_Assert(false, noDocumentError);
}
}
bool Serializer::UiEqualToJson(rapidjson::Value* root) const
{
return UiEqualToJson(root, m_root);
}
void Serializer::LoadFromSettings(rapidjson::Value* root)
{
LoadFromSettings(root, m_root);
}
void Serializer::SaveToSettings(rapidjson::Value* root)
{
// This value needs to be an object to add members
if (!root->IsObject())
{
root->SetObject();
}
SaveToSettings(root, m_root);
}
bool Serializer::UiEqualToJson(rapidjson::Value* root, AzToolsFramework::InstanceDataNode* node) const
{
const AZ::SerializeContext::ClassData* baseMeta = node->GetClassMetadata();
if (baseMeta)
{
for (AzToolsFramework::InstanceDataNode& childNode : node->GetChildren())
{
auto childMeta = childNode.GetElementMetadata();
if (childMeta)
{
bool noDocElement = true;
rapidjson::Value::MemberIterator jsonMember;
const char* propertyName = childMeta->m_name;
// If there is a json object try to find the member
if (root != nullptr)
{
jsonMember = root->FindMember(propertyName);
if (jsonMember != root->MemberEnd())
{
noDocElement = false;
}
}
AZ::Uuid type = childMeta->m_typeId;
if (m_idString == type)
{
AZStd::string uiValue;
childNode.Read(uiValue);
if (!uiValue.empty() && !noDocElement)
{
if (jsonMember->value.IsString())
{
if (uiValue != jsonMember->value.GetString())
{
return false;
}
}
else
{
return false;
}
}
else if (uiValue.empty() != noDocElement)
{
return false;
}
}
else if (m_idInt == type)
{
int uiValue;
childNode.Read(uiValue);
if (!noDocElement)
{
if (jsonMember->value.IsInt())
{
if (uiValue != jsonMember->value.GetInt())
{
return false;
}
}
else
{
return false;
}
}
else
{
return false;
}
}
else if (m_idBool == type)
{
bool uiValue;
childNode.Read(uiValue);
if (uiValue)
{
if (!noDocElement)
{
if (jsonMember->value.IsString())
{
AZStd::string expectedJsonValue = trueStr;
if (expectedJsonValue != jsonMember->value.GetString())
{
return false;
}
}
else
{
return false;
}
}
else
{
return false;
}
}
else if (!noDocElement)
{
return false;
}
}
// Should be a class with members instead of base data type
else
{
rapidjson::Value* jsonNode = nullptr;
if (!noDocElement)
{
jsonNode = &jsonMember->value;
}
// Drill into class
if (!UiEqualToJson(jsonNode, &childNode))
{
return false;
}
}
}
}
}
return true;
}
bool Serializer::UiEqualToPlist(AzToolsFramework::InstanceDataNode* node) const
{
const AZ::SerializeContext::ClassData* baseMeta = node->GetClassMetadata();
if (baseMeta)
{
for (AzToolsFramework::InstanceDataNode& childNode : node->GetChildren())
{
auto childMeta = childNode.GetElementMetadata();
if (childMeta)
{
bool noDocElement = true;
const char* propertyName = childMeta->m_name;
XmlNode* plistNode = m_plistDict->GetPropertyValueNode(propertyName);
if (plistNode != nullptr)
{
noDocElement = false;
}
AZ::Uuid type = childMeta->m_typeId;
if (m_idString == type)
{
AZStd::string uiValue;
childNode.Read(uiValue);
if (!uiValue.empty() && !noDocElement)
{
if (AZStd::string(plistNode->name()) == stringStr)
{
if (uiValue != plistNode->value())
{
return false;
}
}
else
{
return false;
}
}
else if (uiValue.empty() != noDocElement)
{
return false;
}
}
else if (m_idBool == type)
{
bool uiValue;
childNode.Read(uiValue);
if (uiValue)
{
if (!noDocElement)
{
if (AZStd::string(plistNode->name()) != trueStr)
{
return false;
}
}
else
{
return false;
}
}
else if (!noDocElement)
{
return false;
}
}
else if (AZStd::string(childNode.GetClassMetadata()->m_name) == "IosOrientations")
{
// Enter even if nullptr to make sure all values should be false
if (plistNode == nullptr || AZStd::string(plistNode->name()) == arrayStr)
{
if (!UiEqualToPlistArray(plistNode, &childNode))
{
return false;
}
}
else
{
return false;
}
}
else
{
if (!UiEqualToPlistImages(&childNode))
{
return false;
}
}
}
}
}
return true;
}
bool Serializer::UiEqualToPlistArray(AZ::rapidxml::xml_node<char>* array, AzToolsFramework::InstanceDataNode* node) const
{
const AZ::SerializeContext::ClassData* baseMeta = node->GetClassMetadata();
if (baseMeta)
{
for (AzToolsFramework::InstanceDataNode& childNode : node->GetChildren())
{
const AZ::SerializeContext::ClassElement* childMeta = childNode.GetElementMetadata();
if (childMeta)
{
AZ::Uuid type = childMeta->m_typeId;
if (m_idBool == type)
{
const char* propertyName = childMeta->m_name;
bool uiValue;
childNode.Read(uiValue);
bool found = false;
if (array != nullptr)
{
for (XmlNode* plistNode = array->first_node(); plistNode != nullptr; plistNode = plistNode->next_sibling())
{
if (AZStd::string(plistNode->value()) == propertyName)
{
if (!uiValue)
{
return false;
}
else
{
found = true;
}
break;
}
}
}
if (uiValue && !found)
{
return false;
}
}
}
}
}
return true;
}
bool Serializer::UiEqualToPlistImages(AzToolsFramework::InstanceDataNode* node) const
{
const AZ::SerializeContext::ClassData* baseMeta = node->GetClassMetadata();
if (baseMeta)
{
for (AzToolsFramework::InstanceDataNode& childNode : node->GetChildren())
{
auto childMeta = childNode.GetElementMetadata();
if (childMeta)
{
AZ::Uuid type = childMeta->m_typeId;
if (m_idString == type)
{
AZStd::string uiValue;
childNode.Read(uiValue);
if (!uiValue.empty())
{
return false;
}
}
}
}
}
return true;
}
void Serializer::LoadFromSettings(rapidjson::Value* root, AzToolsFramework::InstanceDataNode* node)
{
const AZ::SerializeContext::ClassData* baseMeta = node->GetClassMetadata();
if (baseMeta)
{
for (AzToolsFramework::InstanceDataNode& childNode : node->GetChildren())
{
auto childMeta = childNode.GetElementMetadata();
if (childMeta)
{
const char* propertyName = childMeta->m_name;
AZ::Uuid type = childMeta->m_typeId;
if (root != nullptr)
{
rapidjson::Value::MemberIterator jsonMember = root->FindMember(propertyName);
if (jsonMember != root->MemberEnd())
{
rapidjson::Value& jsonNode = jsonMember->value;
if (m_idString == type)
{
if (jsonNode.IsString())
{
AZStd::string jsonValue = jsonNode.GetString();
childNode.Write(jsonValue);
}
}
else if (m_idInt == type)
{
if (jsonNode.IsInt())
{
int jsonValue = jsonNode.GetInt();
childNode.Write(jsonValue);
}
}
else if (m_idBool == type)
{
if (jsonNode.IsString())
{
bool value = false;
AZStd::string jsonValue = jsonNode.GetString();
if (jsonValue == trueStr)
{
value = true;
}
childNode.Write(value);
}
}
// Should be a class with members instead of base data type
else
{
if (jsonNode.IsObject())
{
// Drill into class
LoadFromSettings(&jsonNode, &childNode);
}
}
}
else
{
SetDefaults(childNode, type);
}
}
else
{
SetDefaults(childNode, type);
}
}
}
}
}
void Serializer::SaveToSettings(rapidjson::Value* root, AzToolsFramework::InstanceDataNode* node)
{
const AZ::SerializeContext::ClassData* baseMeta = node->GetClassMetadata();
if (baseMeta)
{
for (AzToolsFramework::InstanceDataNode& childNode : node->GetChildren())
{
auto childMeta = childNode.GetElementMetadata();
if (childMeta)
{
const char* propertyName = childMeta->m_name;
rapidjson::Value::MemberIterator jsonMember = root->FindMember(propertyName);
if (jsonMember == root->MemberEnd())
{
root->AddMember(rapidjson::Value(propertyName, m_jsonDoc->GetAllocator())
, rapidjson::Value(rapidjson::Type::kNullType)
, m_jsonDoc->GetAllocator());
jsonMember = root->FindMember(propertyName);
}
rapidjson::Value& jsonNode = jsonMember->value;
AZ::Uuid type = childMeta->m_typeId;
if (m_idString == type)
{
AZStd::string uiValue;
childNode.Read(uiValue);
if (!uiValue.empty())
{
jsonNode.SetString(uiValue.data(), m_jsonDoc->GetAllocator());
}
else
{
root->RemoveMember(propertyName);
}
}
else if (m_idInt == type)
{
int uiValue;
childNode.Read(uiValue);
jsonNode.SetInt(uiValue);
}
else if (m_idBool == type)
{
bool uiValue;
childNode.Read(uiValue);
if (uiValue)
{
jsonNode.SetString(trueStr, m_jsonDoc->GetAllocator());
}
else
{
root->RemoveMember(propertyName);
}
}
// Should be a class with members instead of base data type
else
{
// This value needs to be an object to add members
if (!jsonNode.IsObject())
{
jsonNode.SetObject();
}
// Drill into class
SaveToSettings(&jsonNode, &childNode);
if (jsonNode.ObjectEmpty())
{
root->RemoveMember(propertyName);
}
}
}
}
}
}
void Serializer::LoadFromSettings(AzToolsFramework::InstanceDataNode* node)
{
const AZ::SerializeContext::ClassData* baseMeta = node->GetClassMetadata();
if (baseMeta)
{
for (AzToolsFramework::InstanceDataNode& childNode : node->GetChildren())
{
const AZ::SerializeContext::ClassElement* childMeta = childNode.GetElementMetadata();
if (childMeta)
{
const char* propertyName = childMeta->m_name;
XmlNode* plistNode = m_plistDict->GetPropertyValueNode(propertyName);
AZ::Uuid type = childMeta->m_typeId;
if (plistNode != nullptr)
{
if (m_idString == type)
{
if (AZStd::string(plistNode->name()) == stringStr)
{
AZStd::string plistValue = plistNode->value();
childNode.Write(plistValue);
}
}
else if (m_idBool == type)
{
if (AZStd::string(plistNode->name()) == trueStr)
{
childNode.Write(true);
}
}
else if (AZStd::string(childNode.GetClassMetadata()->m_name) == "IosOrientations")
{
// Make sure it seems like an array in plist as well
if (AZStd::string(plistNode->name()) == arrayStr)
{
LoadOrientations(plistNode, &childNode);
}
}
else
{
SetClassToDefaults(&childNode);
}
}
else
{
SetDefaults(childNode, type);
}
}
}
}
}
void Serializer::LoadOrientations(XmlNode* array, AzToolsFramework::InstanceDataNode* node)
{
const AZ::SerializeContext::ClassData* baseMeta = node->GetClassMetadata();
if (baseMeta)
{
for (AzToolsFramework::InstanceDataNode& childNode : node->GetChildren())
{
const AZ::SerializeContext::ClassElement* childMeta = childNode.GetElementMetadata();
if (childMeta)
{
const char* propertyName = childMeta->m_name;
bool found = false;
if (array != nullptr)
{
for (XmlNode* plistNode = array->first_node(); plistNode != nullptr; plistNode = plistNode->next_sibling())
{
if (AZStd::string(plistNode->value()) == propertyName)
{
AZ::Uuid type = childMeta->m_typeId;
if (m_idBool == type)
{
if (AZStd::string(plistNode->name()) == stringStr)
{
childNode.Write(true);
found = true;
}
}
else
{
AZ_Assert(false, "Unsupported type \"%s\" found in array.", childMeta->m_editData->m_name)
}
break;
}
}
}
if (!found)
{
childNode.Write(false);
}
}
}
}
}
void Serializer::SetClassToDefaults(AzToolsFramework::InstanceDataNode* node)
{
const AZ::SerializeContext::ClassData* baseMeta = node->GetClassMetadata();
if (baseMeta)
{
for (AzToolsFramework::InstanceDataNode& childNode : node->GetChildren())
{
auto childMeta = childNode.GetElementMetadata();
if (childMeta)
{
AZ::Uuid type = childMeta->m_typeId;
SetDefaults(childNode, type);
}
}
}
}
void Serializer::SetDefaults(AzToolsFramework::InstanceDataNode& node, const AZ::Uuid& type)
{
if (m_idString == type)
{
node.Write(AZStd::string(""));
return;
}
else if (m_idBool == type)
{
node.Write(false);
return;
}
else if (m_idInt == type)
{
node.Write(0);
return;
}
if (AZStd::string(node.GetClassMetadata()->m_name) == "IosOrientations")
{
LoadOrientations(nullptr, &node);
}
else
{
SetClassToDefaults(&node);
}
}
void Serializer::SaveToSettings(AzToolsFramework::InstanceDataNode* node)
{
const AZ::SerializeContext::ClassData* baseMeta = node->GetClassMetadata();
if (baseMeta)
{
for (AzToolsFramework::InstanceDataNode& childNode : node->GetChildren())
{
auto childMeta = childNode.GetElementMetadata();
if (childMeta)
{
const char* propertyName = childMeta->m_name;
AZ::Uuid type = childMeta->m_typeId;
if (m_idString == type)
{
AZStd::string uiValue;
childNode.Read(uiValue);
if (!uiValue.empty())
{
m_plistDict->SetPropertyValue(propertyName, uiValue.data());
}
else
{
m_plistDict->RemoveProperty(propertyName);
}
}
else if (m_idBool == type)
{
bool uiValue;
childNode.Read(uiValue);
if (uiValue)
{
m_plistDict->SetPropertyValueName(propertyName, trueStr);
m_plistDict->SetPropertyValue(propertyName, "");
}
else
{
m_plistDict->RemoveProperty(propertyName);
}
}
else if (AZStd::string(childNode.GetClassMetadata()->m_name) == "IosOrientations")
{
XmlNode* plistNode = m_plistDict->GetPropertyValueNode(propertyName);
if (plistNode == nullptr)
{
plistNode = m_plistDict->SetPropertyValueName(propertyName, arrayStr);
}
// Make sure the plist says this is an array type
if (AZStd::string(plistNode->name()) == arrayStr)
{
if (!SaveOrientations(plistNode, &childNode))
{
m_plistDict->RemoveProperty(propertyName);
}
}
}
//Assume this is a class with image overrides
else
{
OverwriteImages(&childNode);
}
}
}
}
}
bool Serializer::SaveOrientations(XmlNode* array, AzToolsFramework::InstanceDataNode* node)
{
bool anyEnabled = false;
const AZ::SerializeContext::ClassData* baseMeta = node->GetClassMetadata();
if (baseMeta)
{
for (AzToolsFramework::InstanceDataNode& childNode : node->GetChildren())
{
const AZ::SerializeContext::ClassElement* childMeta = childNode.GetElementMetadata();
if (childMeta)
{
AZ::Uuid type = childMeta->m_typeId;
if (m_idBool == type)
{
const char* propertyName = childMeta->m_name;
bool uiValue;
childNode.Read(uiValue);
if (uiValue)
{
anyEnabled = true;
}
bool found = false;
for (XmlNode* plistNode = array->first_node(); plistNode != nullptr; plistNode = plistNode->next_sibling())
{
if (AZStd::string(plistNode->value()) == propertyName)
{
if (!uiValue)
{
array->remove_node(plistNode);
}
else
{
found = true;
}
break;
}
}
if (uiValue && !found)
{
array->append_node(m_plistDict->MakeNode(stringStr, propertyName));
}
}
}
}
}
return anyEnabled;
}
void Serializer::OverwriteImages(AzToolsFramework::InstanceDataNode* node)
{
const AZ::SerializeContext::ClassData* baseMeta = node->GetClassMetadata();
if (baseMeta)
{
for (AzToolsFramework::InstanceDataNode& childNode : node->GetChildren())
{
auto childMeta = childNode.GetElementMetadata();
if (childMeta)
{
AZ::Uuid type = childMeta->m_typeId;
if (m_idString == type)
{
AZStd::string uiValue;
childNode.Read(uiValue);
if (!uiValue.empty())
{
AZ::Edit::ElementData* childEditMeta = childMeta->m_editData;
if (childEditMeta != nullptr)
{
AZ::AttributeId handlerType = childEditMeta->m_elementId;
// Special handling for iOS image overrides, the source images must be overwritten.
if (handlerType == Handlers::ImagePreview)
{
AZ::Edit::Attribute* defaultPathAttr = childEditMeta->FindAttribute(Attributes::DefaultPath);
if (defaultPathAttr != nullptr)
{
AzToolsFramework::PropertyAttributeReader reader(defaultPathAttr->GetContextData(), defaultPathAttr);
AZStd::string defaultPath;
if (reader.Read<AZStd::string>(defaultPath))
{
QString defaultPathQString = defaultPath.data();
CFileUtil::OverwriteFile(defaultPathQString);
CFileUtil::CopyFile(QString(uiValue.data()), defaultPathQString);
// Clear the property so this isn't overwritten again for no reason
childNode.Write(AZStd::string(""));
}
}
else
{
AZ_Assert(false, "Could not find default path for \"%s\". Cannot override image.", childMeta->m_name)
}
}
}
}
}
else
{
AZ_Assert(false, "Unsupported type \"%s\" found in what should be image overrides.", childMeta->m_editData->m_name);
}
}
}
}
}
} // ProjectSettingsTool