git mv Code\Sandbox\Plugins Code/Editor/Plugins
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ProjectSettingsTool_precompiled.h"
|
||||
#include "ProjectSettingsContainer.h"
|
||||
|
||||
#include <AzCore/JSON/prettywriter.h>
|
||||
#include <AzCore/JSON/stringbuffer.h>
|
||||
#include <AzCore/XML/rapidxml_print.h>
|
||||
|
||||
#include <Util/FileUtil.h>
|
||||
|
||||
namespace ProjectSettingsTool
|
||||
{
|
||||
using namespace AZ;
|
||||
using StringOutcome = Outcome<void, AZStd::string>;
|
||||
using XmlDocument = rapidxml::xml_document<char>;
|
||||
using XmlNode = rapidxml::xml_node<char>;
|
||||
|
||||
const int xmlFlags = rapidxml::parse_doctype_node | rapidxml::parse_declaration_node | rapidxml::parse_no_data_nodes;
|
||||
|
||||
SettingsError::SettingsError(const AZStd::string& error, const AZStd::string& reason)
|
||||
{
|
||||
m_error = error;
|
||||
m_reason = reason;
|
||||
}
|
||||
|
||||
StringOutcome WriteConfigFile(const AZStd::string& fileName, const AZStd::string& fileContents)
|
||||
{
|
||||
using AZ::IO::SystemFile;
|
||||
const char* filePath = fileName.c_str();
|
||||
|
||||
// Attempt to make file writable or check it out in source control
|
||||
if (CFileUtil::OverwriteFile(filePath))
|
||||
{
|
||||
if (!CFileUtil::CreateDirectory(fileName.substr(0, fileName.find_last_of('/')).data()))
|
||||
{
|
||||
return AZ::Failure(AZStd::string::format("Could not create the directory for file \"%s\".", filePath));
|
||||
}
|
||||
|
||||
SystemFile settingsFile;
|
||||
if (!settingsFile.Open(filePath, SystemFile::SF_OPEN_WRITE_ONLY | SystemFile::SF_OPEN_CREATE))
|
||||
{
|
||||
return AZ::Failure(AZStd::string::format("Failed to open settings file %s for write.", filePath));
|
||||
}
|
||||
|
||||
if (settingsFile.Write(fileContents.c_str(), fileContents.size()) != fileContents.size())
|
||||
{
|
||||
return AZ::Failure(AZStd::string::format("Failed to write to file %s.", filePath));
|
||||
}
|
||||
|
||||
|
||||
settingsFile.Close();
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
return AZ::Failure(AZStd::string::format("Could not check out or make file writable: \"%s\".", filePath));
|
||||
}
|
||||
|
||||
StringOutcome ReadConfigFile(const AZStd::string& fileName, AZStd::string& fileContents)
|
||||
{
|
||||
using AZ::IO::SystemFile;
|
||||
const char* filePath = fileName.c_str();
|
||||
|
||||
if (!SystemFile::Exists(filePath))
|
||||
{
|
||||
return AZ::Failure(AZStd::string::format("%s file doesn't exist.", filePath));
|
||||
}
|
||||
|
||||
SystemFile settingsFile;
|
||||
if (!settingsFile.Open(filePath, SystemFile::SF_OPEN_READ_ONLY))
|
||||
{
|
||||
return AZ::Failure(AZStd::string::format("Failed to open settings file %s.", filePath));
|
||||
}
|
||||
|
||||
fileContents = AZStd::string(settingsFile.Length(), '\0');
|
||||
settingsFile.Read(fileContents.size(), fileContents.data());
|
||||
|
||||
settingsFile.Close();
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
|
||||
ProjectSettingsContainer::ProjectSettingsContainer(const AZStd::string& projectJsonFileName, PlistInitVector& plistPaths)
|
||||
: m_projectJson(JsonSettings{ projectJsonFileName, "", AZStd::make_unique<rapidjson::Document>() })
|
||||
{
|
||||
LoadProjectJsonData();
|
||||
|
||||
for (PlatformAndPath& plistInfo : plistPaths)
|
||||
{
|
||||
m_pListsMap.insert(AZStd::pair<PlatformId, PlistSettings>(
|
||||
plistInfo.first,
|
||||
PlistSettings{ plistInfo.second, "", AZStd::make_unique<XmlDocument>() }));
|
||||
|
||||
// We will have to find it then because unique_ptrs are not copy constructible
|
||||
// And a move constructor would copy large strings
|
||||
LoadPlist(m_pListsMap.find(plistInfo.first)->second);
|
||||
}
|
||||
}
|
||||
|
||||
ProjectSettingsContainer::~ProjectSettingsContainer()
|
||||
{
|
||||
}
|
||||
|
||||
ProjectSettingsContainer::PlistSettings* ProjectSettingsContainer::GetPlistSettingsForPlatform(const Platform& plat)
|
||||
{
|
||||
PlistSettings* result = nullptr;
|
||||
|
||||
if (plat.m_type == PlatformDataType::Plist)
|
||||
{
|
||||
auto iter = m_pListsMap.find(plat.m_id);
|
||||
|
||||
if (iter != m_pListsMap.end())
|
||||
{
|
||||
result = &iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Assert(false, "Failed to find pList for platform.");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ProjectSettingsContainer::IsPlistPlatform(const Platform& plat)
|
||||
{
|
||||
if (plat.m_type == PlatformDataType::Plist)
|
||||
{
|
||||
auto iter = m_pListsMap.find(plat.m_id);
|
||||
|
||||
if (iter != m_pListsMap.end())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
AZ::Outcome<void, SettingsError> ProjectSettingsContainer::GetError()
|
||||
{
|
||||
if (!m_errors.empty())
|
||||
{
|
||||
SettingsError error = m_errors.front();
|
||||
m_errors.pop();
|
||||
|
||||
return AZ::Failure(error);
|
||||
}
|
||||
return AZ::Success();
|
||||
}
|
||||
|
||||
void ProjectSettingsContainer::SavePlatformData(const Platform& plat)
|
||||
{
|
||||
PlistSettings* plistSettings = GetPlistSettingsForPlatform(plat);
|
||||
if (plistSettings != nullptr)
|
||||
{
|
||||
SavePlist(*plistSettings);
|
||||
}
|
||||
else
|
||||
{
|
||||
SaveProjectJsonData();
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectSettingsContainer::SaveProjectJsonData()
|
||||
{
|
||||
// Needed to write a document out to a string
|
||||
rapidjson::StringBuffer jsonDataBuffer;
|
||||
// Use pretty writer so it can be read easier
|
||||
rapidjson::PrettyWriter<rapidjson::StringBuffer> jsonDatawriter(jsonDataBuffer);
|
||||
|
||||
m_projectJson.m_document->Accept(jsonDatawriter);
|
||||
const AZStd::string jsonDataString = jsonDataBuffer.GetString();
|
||||
|
||||
StringOutcome outcome = WriteConfigFile(m_projectJson.m_path, jsonDataString);
|
||||
|
||||
if (!outcome.IsSuccess())
|
||||
{
|
||||
m_errors.push(SettingsError("Failed to save project.json", outcome.GetError()));
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectSettingsContainer::ReloadProjectJsonData()
|
||||
{
|
||||
m_projectJson.m_document.reset(new rapidjson::Document);
|
||||
LoadProjectJsonData();
|
||||
}
|
||||
|
||||
void ProjectSettingsContainer::SavePlistsData()
|
||||
{
|
||||
for (AZStd::pair<PlatformId, PlistSettings>& plist : m_pListsMap)
|
||||
{
|
||||
LoadPlist(plist.second);
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectSettingsContainer::SavePlistData(const Platform& plat)
|
||||
{
|
||||
PlistSettings* settings = GetPlistSettingsForPlatform(plat);
|
||||
if (settings != nullptr)
|
||||
{
|
||||
SavePlist(*settings);
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectSettingsContainer::ReloadPlistData()
|
||||
{
|
||||
for (AZStd::pair<PlatformId, PlistSettings>& plist : m_pListsMap)
|
||||
{
|
||||
PlistSettings& plistSettings = plist.second;
|
||||
|
||||
plistSettings.m_document.reset(new XmlDocument());
|
||||
LoadPlist(plistSettings);
|
||||
}
|
||||
}
|
||||
|
||||
rapidjson::Document& ProjectSettingsContainer::GetProjectJsonDocument()
|
||||
{
|
||||
return *m_projectJson.m_document.get();
|
||||
}
|
||||
|
||||
AZ::Outcome<rapidjson::Value*, void> ProjectSettingsContainer::GetProjectJsonValue(const char* key)
|
||||
{
|
||||
// Try to find member
|
||||
rapidjson::Document& settings = *m_projectJson.m_document;
|
||||
rapidjson::Value::MemberIterator memberIterator = settings.FindMember(key);
|
||||
if (memberIterator != settings.MemberEnd())
|
||||
{
|
||||
return AZ::Success(&memberIterator->value);
|
||||
}
|
||||
else
|
||||
{
|
||||
settings.AddMember(rapidjson::Value(key, settings.GetAllocator()),
|
||||
rapidjson::Value(rapidjson::kNullType), settings.GetAllocator());
|
||||
return AZ::Success(&settings.FindMember(key)->value);
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<PlistDictionary> ProjectSettingsContainer::GetPlistDictionary(const Platform& plat)
|
||||
{
|
||||
if (plat.m_type == PlatformDataType::Plist)
|
||||
{
|
||||
PlistSettings* settings = GetPlistSettingsForPlatform(plat);
|
||||
if (settings != nullptr)
|
||||
{
|
||||
|
||||
if (PlistDictionary::ContainsValidDict(settings->m_document.get()))
|
||||
{
|
||||
return AZStd::make_unique<PlistDictionary>(settings->m_document.get());
|
||||
}
|
||||
else
|
||||
{
|
||||
//TODO: Query user if they would like to remake a valid plist then do it
|
||||
AZStd::string platformName;
|
||||
switch (plat.m_id)
|
||||
{
|
||||
case PlatformId::Ios:
|
||||
platformName = "iOS";
|
||||
break;
|
||||
default:
|
||||
platformName = "unknown";
|
||||
break;
|
||||
}
|
||||
AZ_Assert(false, "%s pList is in invalid state.", platformName.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AZ_Assert(false, "This platform does not use pLists to store data.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator>& ProjectSettingsContainer::GetProjectJsonAllocator()
|
||||
{
|
||||
return m_projectJson.m_document->GetAllocator();
|
||||
}
|
||||
|
||||
const char* ProjectSettingsContainer::GetFailedLoadingPlistText()
|
||||
{
|
||||
return "Failed to load info.plist";
|
||||
}
|
||||
|
||||
void ProjectSettingsContainer::LoadProjectJsonData()
|
||||
{
|
||||
StringOutcome outcome = ReadConfigFile(m_projectJson.m_path, m_projectJson.m_rawData);
|
||||
if (!outcome.IsSuccess())
|
||||
{
|
||||
m_errors.push(SettingsError("Failed to load project.json", outcome.GetError()));
|
||||
}
|
||||
|
||||
m_projectJson.m_document->Parse(m_projectJson.m_rawData.c_str());
|
||||
}
|
||||
|
||||
// Loads info.plist for iOS from disk
|
||||
void ProjectSettingsContainer::LoadPlist(PlistSettings& plistSettings)
|
||||
{
|
||||
StringOutcome outcome = ReadConfigFile(plistSettings.m_path, plistSettings.m_rawData);
|
||||
if (!outcome.IsSuccess())
|
||||
{
|
||||
m_errors.push(SettingsError(GetFailedLoadingPlistText(), outcome.GetError()));
|
||||
}
|
||||
|
||||
plistSettings.m_document->parse<xmlFlags>(plistSettings.m_rawData.data());
|
||||
}
|
||||
|
||||
void ProjectSettingsContainer::SavePlist(PlistSettings& plistSettings)
|
||||
{
|
||||
// Needed to write a document out to a string
|
||||
AZStd::string xmlDocString;
|
||||
rapidxml::print(std::back_inserter(xmlDocString), *plistSettings.m_document);
|
||||
|
||||
StringOutcome outcome = WriteConfigFile(plistSettings.m_path, xmlDocString);
|
||||
|
||||
if (!outcome.IsSuccess())
|
||||
{
|
||||
m_errors.push(SettingsError("Failed to save info.pList", outcome.GetError()));
|
||||
}
|
||||
}
|
||||
} // namespace ProjectSettingsTool
|
||||
Reference in New Issue
Block a user