627012840d
* Fixed the return value of the ConvertToAbsolutePath function Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Added the generated cmake_dependencies.*.setreg files to engine.pak (#5073) * Copied the generated cmake_dependencies.*.setreg file to the Cache directory Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Removed the platform name from the bootstrap.game.*.setreg Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Update how the project related file paths are determined when not supplied. The project-path determination now goes back to only detecting a "project.json" file. It no longer attempts to detect a "Cache" directory The project-cache-path determination now in addition to checking the project_cache_path key searches for a "Cache" directory. The project-path defaults to executable folder if it cannot be detected. The copying of generated executable folder Registry directory contents to the product cache is now removed after the archive step. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the invocation of the AssetProcessor in Jenkins to supply an absolute path to the project. The project-path is no longer treated as relative to the engine root, but instead relative to the current working directory at application startup. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Added constant for the storing the name of Cache directory Fixed typos and grammatical errors in the SettingsRegistryMergeUtils.cpp Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated UnitTest prepend the EngineRoot path to "AutomatedTesting" when setting the project path. This is needed now that the project-path isn't treated relative to the EngineRoot if it is not absolute. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Fix AssetSeedManagerTest and PlatformAddressedAssetCatalogManagerTest Instead of trying to used the AutomatedTesting directory as the project root, the temp directory created during the test is used as the project root. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Moved the setting of the project cache root folder and project asset platform root folder into the `if (!projectCachePath.empty())` block Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Removing the scan up logic for the "Cache" directory. This is no longer needed to locate the project cache path in a Project Game Release Layout. Because the project path defaults to the executable directory if, it is not found, the Cache directory will be set to the "Cache" directory within the executable directory. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com>
478 lines
23 KiB
C++
478 lines
23 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 <limits>
|
|
#include <AssetBuilderSDK/AssetBuilderSDK.h>
|
|
#include <AzCore/Component/ComponentApplicationBus.h>
|
|
#include <AzCore/Settings/SettingsRegistryImpl.h>
|
|
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
|
#include <AzCore/Utils/Utils.h>
|
|
#include <AzFramework/Platform/PlatformDefaults.h>
|
|
#include <AzFramework/StringFunc/StringFunc.h>
|
|
#include <native/InternalBuilders/SettingsRegistryBuilder.h>
|
|
#include <native/utilities/PlatformConfiguration.h>
|
|
|
|
namespace AssetProcessor
|
|
{
|
|
void SettingsRegistryBuilder::SettingsExporter::WriteName(AZStd::string_view name)
|
|
{
|
|
if (m_includeName)
|
|
{
|
|
m_writer.Key(name.data(), aznumeric_caster(name.length()));
|
|
}
|
|
}
|
|
|
|
SettingsRegistryBuilder::SettingsExporter::SettingsExporter(
|
|
rapidjson::StringBuffer& buffer, const AZStd::vector<AZStd::string>& excludes)
|
|
: m_writer(rapidjson::Writer<rapidjson::StringBuffer>(buffer))
|
|
, m_excludes(excludes)
|
|
{
|
|
}
|
|
|
|
AZ::SettingsRegistryInterface::VisitResponse SettingsRegistryBuilder::SettingsExporter::Traverse(
|
|
AZStd::string_view path, AZStd::string_view valueName, AZ::SettingsRegistryInterface::VisitAction action,
|
|
AZ::SettingsRegistryInterface::Type type)
|
|
{
|
|
for (const AZStd::string& exclude : m_excludes)
|
|
{
|
|
if (exclude == path)
|
|
{
|
|
return AZ::SettingsRegistryInterface::VisitResponse::Skip;
|
|
}
|
|
}
|
|
|
|
if (action == AZ::SettingsRegistryInterface::VisitAction::Begin)
|
|
{
|
|
AZ_Assert(type == AZ::SettingsRegistryInterface::Type::Object || type == AZ::SettingsRegistryInterface::Type::Array,
|
|
"Unexpected type visited: %i.", type);
|
|
WriteName(valueName);
|
|
if (type == AZ::SettingsRegistryInterface::Type::Object)
|
|
{
|
|
m_result = m_result && m_writer.StartObject();
|
|
m_includeNameStack.push(true);
|
|
m_includeName = true;
|
|
}
|
|
else
|
|
{
|
|
m_result = m_result && m_writer.StartArray();
|
|
m_includeNameStack.push(false);
|
|
m_includeName = false;
|
|
}
|
|
}
|
|
else if (action == AZ::SettingsRegistryInterface::VisitAction::End)
|
|
{
|
|
if (type == AZ::SettingsRegistryInterface::Type::Object)
|
|
{
|
|
m_result = m_result && m_writer.EndObject();
|
|
}
|
|
else
|
|
{
|
|
m_result = m_result && m_writer.EndArray();
|
|
}
|
|
AZ_Assert(!m_includeNameStack.empty(), "Attempting to close a json array or object that wasn't started.");
|
|
m_includeNameStack.pop();
|
|
m_includeName = !m_includeNameStack.empty() ? m_includeNameStack.top() : true;
|
|
}
|
|
else if (type == AZ::SettingsRegistryInterface::Type::Null)
|
|
{
|
|
WriteName(valueName);
|
|
m_result = m_result && m_writer.Null();
|
|
}
|
|
|
|
return m_result ?
|
|
AZ::SettingsRegistryInterface::VisitResponse::Continue :
|
|
AZ::SettingsRegistryInterface::VisitResponse::Done;
|
|
}
|
|
|
|
void SettingsRegistryBuilder::SettingsExporter::Visit(
|
|
AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, bool value)
|
|
{
|
|
WriteName(valueName);
|
|
m_result = m_result && m_writer.Bool(value);
|
|
}
|
|
|
|
void SettingsRegistryBuilder::SettingsExporter::Visit(
|
|
AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZ::s64 value)
|
|
{
|
|
WriteName(valueName);
|
|
m_result = m_result && m_writer.Int64(value);
|
|
}
|
|
|
|
void SettingsRegistryBuilder::SettingsExporter::Visit(
|
|
AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZ::u64 value)
|
|
{
|
|
WriteName(valueName);
|
|
m_result = m_result && m_writer.Uint64(value);
|
|
}
|
|
|
|
void SettingsRegistryBuilder::SettingsExporter::Visit(
|
|
AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, double value)
|
|
{
|
|
WriteName(valueName);
|
|
m_result = m_result && m_writer.Double(value);
|
|
}
|
|
|
|
void SettingsRegistryBuilder::SettingsExporter::Visit(
|
|
AZStd::string_view, AZStd::string_view valueName, AZ::SettingsRegistryInterface::Type, AZStd::string_view value)
|
|
{
|
|
WriteName(valueName);
|
|
m_result = m_result && m_writer.String(value.data(), aznumeric_caster(value.length()));
|
|
}
|
|
|
|
bool SettingsRegistryBuilder::SettingsExporter::Finalize()
|
|
{
|
|
if (!m_includeNameStack.empty())
|
|
{
|
|
AZ_Assert(false, "m_includeNameStack is expected to be empty. This means that there was an object or array what wasn't closed.");
|
|
return false;
|
|
}
|
|
return m_result;
|
|
}
|
|
|
|
void SettingsRegistryBuilder::SettingsExporter::Reset(rapidjson::StringBuffer& buffer)
|
|
{
|
|
m_writer.Reset(buffer);
|
|
m_includeName = false;
|
|
m_result = true;
|
|
}
|
|
|
|
|
|
|
|
SettingsRegistryBuilder::SettingsRegistryBuilder()
|
|
: m_builderId("{1BB18B28-2953-4922-A80B-E7375FCD7FC1}")
|
|
, m_assetType("{FEBB3C7B-9C8B-46C3-8AAF-3D132D811087}")
|
|
{
|
|
AssetBuilderSDK::AssetBuilderCommandBus::Handler::BusConnect(m_builderId);
|
|
}
|
|
|
|
bool SettingsRegistryBuilder::Initialize()
|
|
{
|
|
AssetBuilderSDK::AssetBuilderDesc builderDesc;
|
|
builderDesc.m_name = "Settings Registry Builder";
|
|
builderDesc.m_patterns.emplace_back("*/engine.json", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard);
|
|
builderDesc.m_builderType = AssetBuilderSDK::AssetBuilderDesc::AssetBuilderType::Internal;
|
|
builderDesc.m_busId = m_builderId;
|
|
builderDesc.m_createJobFunction = AZStd::bind(&SettingsRegistryBuilder::CreateJobs, this, AZStd::placeholders::_1, AZStd::placeholders::_2);
|
|
builderDesc.m_processJobFunction = AZStd::bind(&SettingsRegistryBuilder::ProcessJob, this, AZStd::placeholders::_1, AZStd::placeholders::_2);
|
|
builderDesc.m_version = 1;
|
|
|
|
AssetBuilderSDK::AssetBuilderBus::Broadcast(&AssetBuilderSDK::AssetBuilderBusTraits::RegisterBuilderInformation, builderDesc);
|
|
|
|
return true;
|
|
}
|
|
|
|
void SettingsRegistryBuilder::Uninitialize() {}
|
|
|
|
void SettingsRegistryBuilder::ShutDown()
|
|
{
|
|
m_isShuttingDown = true;
|
|
}
|
|
|
|
void SettingsRegistryBuilder::CreateJobs(
|
|
const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response)
|
|
{
|
|
if (m_isShuttingDown)
|
|
{
|
|
response.m_result = AssetBuilderSDK::CreateJobsResultCode::ShuttingDown;
|
|
return;
|
|
}
|
|
|
|
for (const AssetBuilderSDK::PlatformInfo& info : request.m_enabledPlatforms)
|
|
{
|
|
AssetBuilderSDK::JobDescriptor job;
|
|
job.m_jobKey = "Settings Registry";
|
|
// The settings are the very first thing the game reads so needs to available before anything else.
|
|
job.m_priority = std::numeric_limits<decltype(job.m_priority)>::max();
|
|
job.m_critical = true;
|
|
job.SetPlatformIdentifier(info.m_identifier.c_str());
|
|
response.m_createJobOutputs.push_back(AZStd::move(job));
|
|
}
|
|
|
|
AZ::IO::Path settingsRegistryWildcard = AZStd::string_view(AZ::Utils::GetEnginePath());
|
|
settingsRegistryWildcard /= AZ::SettingsRegistryInterface::RegistryFolder;
|
|
settingsRegistryWildcard /= "*.setreg";
|
|
response.m_sourceFileDependencyList.emplace_back(AZStd::move(settingsRegistryWildcard.Native()), AZ::Uuid::CreateNull(),
|
|
AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Wildcards);
|
|
|
|
auto projectPath = AZ::IO::Path(AZStd::string_view(AZ::Utils::GetProjectPath()));
|
|
response.m_sourceFileDependencyList.emplace_back(
|
|
AZStd::move((projectPath / AZ::SettingsRegistryInterface::RegistryFolder / "*.setreg").Native()),
|
|
AZ::Uuid::CreateNull(),
|
|
AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Wildcards);
|
|
response.m_sourceFileDependencyList.emplace_back(
|
|
AZStd::move((projectPath / AZ::SettingsRegistryInterface::DevUserRegistryFolder / "*.setreg").Native()),
|
|
AZ::Uuid::CreateNull(),
|
|
AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Wildcards);
|
|
|
|
if (auto settingsRegistry = AZ::Interface<AZ::SettingsRegistryInterface>::Get(); settingsRegistry != nullptr)
|
|
{
|
|
AZStd::vector<AzFramework::GemInfo> gemInfos;
|
|
if (AzFramework::GetGemsInfo(gemInfos, *settingsRegistry))
|
|
{
|
|
// Gather unique list of Settings Registry wildcard directories
|
|
AZStd::vector<AZ::IO::Path> gemSettingsRegistryWildcards;
|
|
for (const AzFramework::GemInfo& gemInfo : gemInfos)
|
|
{
|
|
for (const AZ::IO::Path& absoluteSourcePath : gemInfo.m_absoluteSourcePaths)
|
|
{
|
|
auto gemSettingsRegistryWildcard = absoluteSourcePath / AZ::SettingsRegistryInterface::RegistryFolder / "*.setreg";
|
|
if (auto foundIt = AZStd::find(gemSettingsRegistryWildcards.begin(), gemSettingsRegistryWildcards.end(), gemSettingsRegistryWildcard);
|
|
foundIt == gemSettingsRegistryWildcards.end())
|
|
{
|
|
gemSettingsRegistryWildcards.emplace_back(gemSettingsRegistryWildcard);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Add to the Source File Dependency list
|
|
for (AZ::IO::Path& gemSettingsRegistryWildcard : gemSettingsRegistryWildcards)
|
|
{
|
|
response.m_sourceFileDependencyList.emplace_back(
|
|
AZStd::move(gemSettingsRegistryWildcard.Native()), AZ::Uuid::CreateNull(),
|
|
AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Wildcards);
|
|
}
|
|
}
|
|
}
|
|
response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success;
|
|
}
|
|
|
|
void SettingsRegistryBuilder::ProcessJob(
|
|
const AssetBuilderSDK::ProcessJobRequest& request, AssetBuilderSDK::ProcessJobResponse& response)
|
|
{
|
|
if (m_isShuttingDown)
|
|
{
|
|
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Cancelled;
|
|
return;
|
|
}
|
|
|
|
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Failed;
|
|
|
|
AZStd::vector<AZStd::string> excludes = ReadExcludesFromRegistry();
|
|
// Exclude the AssetProcessor settings from the game regsitry
|
|
excludes.emplace_back(AssetProcessor::AssetProcessorSettingsKey);
|
|
|
|
AZStd::vector<char> scratchBuffer;
|
|
scratchBuffer.reserve(512 * 1024); // Reserve 512kb to avoid repeatedly resizing the buffer;
|
|
AZStd::fixed_vector<AZStd::string_view, AzFramework::MaxPlatformCodeNames> platformCodes;
|
|
AzFramework::PlatformHelper::AppendPlatformCodeNames(platformCodes, request.m_platformInfo.m_identifier);
|
|
AZ_Assert(platformCodes.size() <= 1, "A one-to-one mapping of asset type platform identifier"
|
|
" to platform codename is required in the SettingsRegistryBuilder."
|
|
" The bootstrap.game is now only produced per build configuration and doesn't take into account"
|
|
" different platforms names");
|
|
|
|
const AZStd::string& assetPlatformIdentifier = request.m_jobDescription.GetPlatformIdentifier();
|
|
// Determines the suffix that will be used for the launcher based on processing server vs non-server assets
|
|
const char* launcherType = assetPlatformIdentifier != AzFramework::PlatformHelper::GetPlatformName(AzFramework::PlatformId::SERVER)
|
|
? "_GameLauncher" : "_ServerLauncher";
|
|
|
|
AZ::SettingsRegistryInterface::Specializations specializations[] =
|
|
{
|
|
{ AZStd::string_view{"release"}, AZStd::string_view{"game"} },
|
|
{ AZStd::string_view{"profile"}, AZStd::string_view{"game"} },
|
|
{ AZStd::string_view{"debug"}, AZStd::string_view{"game"} }
|
|
};
|
|
|
|
// Add the project specific specializations
|
|
auto projectName = AZ::Utils::GetProjectName();
|
|
if (!projectName.empty())
|
|
{
|
|
for (AZ::SettingsRegistryInterface::Specializations& specialization : specializations)
|
|
{
|
|
specialization.Append(projectName);
|
|
// The Game Launcher normally has a build target name of <ProjectName>Launcher
|
|
// Add that as a specialization to pick up the gem dependencies files that are specialized
|
|
// on a the Game Launcher target if the asset platform isn't "server"
|
|
specialization.Append(projectName + launcherType);
|
|
}
|
|
}
|
|
|
|
AZStd::string outputPath;
|
|
AzFramework::StringFunc::Path::Join(request.m_tempDirPath.c_str(), "bootstrap.game.", outputPath);
|
|
size_t extensionOffset = outputPath.length();
|
|
|
|
rapidjson::StringBuffer outputBuffer;
|
|
outputBuffer.Reserve(512 * 1024); // Reserve 512kb to avoid repeatedly resizing the buffer;
|
|
SettingsExporter exporter(outputBuffer, excludes);
|
|
|
|
if (!platformCodes.empty())
|
|
{
|
|
AZStd::string_view platform = platformCodes.front();
|
|
for (size_t i = 0; i < AZStd::size(specializations); ++i)
|
|
{
|
|
const AZ::SettingsRegistryInterface::Specializations& specialization = specializations[i];
|
|
if (m_isShuttingDown)
|
|
{
|
|
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Cancelled;
|
|
return;
|
|
}
|
|
|
|
using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString;
|
|
// Placeholder Key used by the local Settings Registry for storing all Gems SourcePaths
|
|
// array entries.
|
|
constexpr auto PlaceholderGemKey = FixedValueString(AZ::SettingsRegistryMergeUtils::OrganizationRootKey)
|
|
+ "/Gems/__SettingsRegistryBuilderPlaceholder";
|
|
|
|
AZ::SettingsRegistryImpl registry;
|
|
|
|
// Seed the local settings registry using the AssetProcessor Settings Registry
|
|
if (auto settingsRegistry = AZ::Interface<AZ::SettingsRegistryInterface>::Get(); settingsRegistry != nullptr)
|
|
{
|
|
AZStd::array settingsToCopy{
|
|
AZStd::string::format("%s/project_path", AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey),
|
|
AZStd::string{AZ::SettingsRegistryMergeUtils::FilePathKey_BinaryFolder},
|
|
AZStd::string{AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder},
|
|
AZStd::string{AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath},
|
|
AZStd::string{AZ::SettingsRegistryMergeUtils::FilePathKey_CacheProjectRootFolder},
|
|
AZStd::string{AZ::SettingsRegistryMergeUtils::FilePathKey_CacheRootFolder},
|
|
};
|
|
|
|
for (const auto& settingsKey : settingsToCopy)
|
|
{
|
|
FixedValueString settingsValue;
|
|
[[maybe_unused]] bool settingsCopied = settingsRegistry->Get(settingsValue, settingsKey)
|
|
&& registry.Set(settingsKey, settingsValue);
|
|
AZ_Warning("Settings Registry Builder", settingsCopied, "Unable to copy setting %s from AssetProcessor settings registry"
|
|
" to local settings registry", settingsKey.c_str());
|
|
}
|
|
|
|
// The purpose of this section is to copy the Gem's SourcePaths from the Global Settings Registry
|
|
// the local SettingsRegistry. The reason this is needed is so that the call to
|
|
// `MergeSettingsToRegistry_GemRegistries` below is able to locate each gem's "<gem-root>/Registry" folder
|
|
// that will be merged into the bootstrap.game.<configuration>.setreg file
|
|
// This is used by the GameLauncher applications to read from a single merged .setreg file
|
|
// containing the settings needed to run a game/simulation without have access to the source code base registry
|
|
AZStd::vector<AzFramework::GemInfo> gemInfos;
|
|
size_t pathIndex{};
|
|
if (AzFramework::GetGemsInfo(gemInfos, *settingsRegistry))
|
|
{
|
|
AZStd::vector<AZ::IO::PathView> sourcePaths;
|
|
for (const AzFramework::GemInfo& gemInfo : gemInfos)
|
|
{
|
|
for (const AZ::IO::Path& absoluteSourcePath : gemInfo.m_absoluteSourcePaths)
|
|
{
|
|
if (auto foundIt = AZStd::find(sourcePaths.begin(), sourcePaths.end(), absoluteSourcePath);
|
|
foundIt == sourcePaths.end())
|
|
{
|
|
sourcePaths.emplace_back(absoluteSourcePath);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (const AZ::IO::PathView& sourcePath : sourcePaths)
|
|
{
|
|
// Use JSON Pointer to append elements to the SourcePaths array
|
|
registry.Set(FixedValueString::format("%s/SourcePaths/%zu", PlaceholderGemKey.c_str(), pathIndex++),
|
|
sourcePath.Native());
|
|
}
|
|
}
|
|
}
|
|
|
|
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_EngineRegistry(registry, platform, specialization, &scratchBuffer);
|
|
// This function iterates over each path for each the "/Amazon/Gems/<gem-name>/SourcePaths" key and attempts
|
|
// to merge the "Registry" directory in each path.
|
|
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_GemRegistries(registry, platform, specialization, &scratchBuffer);
|
|
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectRegistry(registry, platform, specialization, &scratchBuffer);
|
|
|
|
// The Placeholder Key is removed now that each gem's "<gem-root>/Registry" directory have been merged to
|
|
// the local Settings Registry instance via `MergeSettingsToRegistry_GemRegistries`
|
|
registry.Remove(PlaceholderGemKey);
|
|
|
|
// Merge the Project User and User home settings registry only in non-release builds
|
|
constexpr bool executeRegDumpCommands = false;
|
|
AZ::CommandLine* commandLine{};
|
|
AZ::ComponentApplicationBus::Broadcast([&commandLine](AZ::ComponentApplicationRequests* appRequests)
|
|
{
|
|
commandLine = appRequests->GetAzCommandLine();
|
|
});
|
|
|
|
if (!specialization.Contains("release"))
|
|
{
|
|
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_O3deUserRegistry(registry, platform, specialization, &scratchBuffer);
|
|
if (commandLine)
|
|
{
|
|
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, *commandLine, executeRegDumpCommands);
|
|
}
|
|
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, platform, specialization, &scratchBuffer);
|
|
}
|
|
|
|
if (commandLine)
|
|
{
|
|
AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, *commandLine, executeRegDumpCommands);
|
|
}
|
|
|
|
|
|
if (registry.Visit(exporter, ""))
|
|
{
|
|
if (!exporter.Finalize())
|
|
{
|
|
return;
|
|
}
|
|
|
|
AZStd::string_view specializationString(specialization.GetSpecialization(0));
|
|
outputPath += specializationString; // Append configuration
|
|
outputPath += ".setreg";
|
|
|
|
AZ::IO::SystemFile file;
|
|
if (!file.Open(outputPath.c_str(),
|
|
AZ::IO::SystemFile::OpenMode::SF_OPEN_CREATE | AZ::IO::SystemFile::OpenMode::SF_OPEN_WRITE_ONLY))
|
|
{
|
|
AZ_Error("Settings Registry Builder", false, R"(Failed to open file "%s" for writing.)", outputPath.c_str());
|
|
return;
|
|
}
|
|
if (file.Write(outputBuffer.GetString(), outputBuffer.GetSize()) != outputBuffer.GetSize())
|
|
{
|
|
AZ_Error("Settings Registry Builder", false, R"(Failed to write settings registry to file "%s".)", outputPath.c_str());
|
|
return;
|
|
}
|
|
file.Close();
|
|
|
|
const AZ::u32 hashedSpecialization = static_cast<AZ::u32>(AZStd::hash<AZStd::string_view>{}(specializationString));
|
|
AZ_Assert(hashedSpecialization != 0, "Product ID generation failed for specialization %.*s."
|
|
" This can result in a product ID collision with other builders for this asset.",
|
|
AZ_STRING_ARG(specializationString));
|
|
response.m_outputProducts.emplace_back(outputPath, m_assetType, hashedSpecialization);
|
|
response.m_outputProducts.back().m_dependenciesHandled = true;
|
|
|
|
outputPath.erase(extensionOffset);
|
|
}
|
|
|
|
outputBuffer.Clear();
|
|
exporter.Reset(outputBuffer);
|
|
}
|
|
}
|
|
|
|
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
|
|
}
|
|
|
|
AZStd::vector<AZStd::string> SettingsRegistryBuilder::ReadExcludesFromRegistry() const
|
|
{
|
|
AZStd::vector<AZStd::string> excludes;
|
|
auto builderRegistry = AZ::SettingsRegistry::Get();
|
|
AZStd::string path = "/Amazon/AssetBuilder/SettingsRegistry/Excludes/";
|
|
size_t offset = path.length();
|
|
size_t counter = 0;
|
|
do
|
|
{
|
|
path += AZStd::to_string(counter);
|
|
|
|
AZStd::string exclude;
|
|
if (builderRegistry->Get(exclude, path))
|
|
{
|
|
excludes.push_back(AZStd::move(exclude));
|
|
}
|
|
else
|
|
{
|
|
return excludes;
|
|
}
|
|
|
|
counter++;
|
|
path.erase(offset);
|
|
} while (true);
|
|
}
|
|
} // namespace AssetProcessor
|