/* * All or portions of this file Copyright(c) Amazon.com, Inc.or its affiliates or * its licensors. * * For complete copyright and license terms please see the LICENSE at the root of this * distribution(the "License").All use of this software is governed by the License, *or, if provided, by the license below or the license accompanying this file.Do not * remove or modify any license notices.This file is distributed on an "AS IS" BASIS, *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * */ #include #include "CfgBuilderWorker.h" #include #include #include namespace CopyDependencyBuilder { // m_skipServer (3rd Param) should be false - we want to process xml files on the server as it's a generic data format which could // have meaningful data for a server CfgBuilderWorker::CfgBuilderWorker() : CopyDependencyBuilderWorker("CFG", true, false) { } void CfgBuilderWorker::RegisterBuilderWorker() { AssetBuilderSDK::AssetBuilderDesc cfgBuilderDescriptor; cfgBuilderDescriptor.m_name = "CfgBuilderWorker"; cfgBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.cfg", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); cfgBuilderDescriptor.m_busId = azrtti_typeid(); cfgBuilderDescriptor.m_version = 3; cfgBuilderDescriptor.m_createJobFunction = AZStd::bind(&CfgBuilderWorker::CreateJobs, this, AZStd::placeholders::_1, AZStd::placeholders::_2); cfgBuilderDescriptor.m_processJobFunction = AZStd::bind(&CfgBuilderWorker::ProcessJob, this, AZStd::placeholders::_1, AZStd::placeholders::_2); BusConnect(cfgBuilderDescriptor.m_busId); AssetBuilderSDK::AssetBuilderBus::Broadcast(&AssetBuilderSDK::AssetBuilderBusTraits::RegisterBuilderInformation, cfgBuilderDescriptor); } void CfgBuilderWorker::UnregisterBuilderWorker() { BusDisconnect(); } struct CfgValueExtensionAndDependencyType { CfgValueExtensionAndDependencyType(const AZStd::string& extension, const AssetBuilderSDK::ProductPathDependencyType dependencyType) : m_extension(extension), m_dependencyType(dependencyType) { } AZStd::string m_extension; AssetBuilderSDK::ProductPathDependencyType m_dependencyType; }; struct CfgKeysAndValuesWithDependencies { CfgKeysAndValuesWithDependencies(const AZStd::string& key, const AZStd::vector& values) : m_key(key), m_values(values) { } AZStd::string ExtensionsToString() const { AZStd::string extensionList; for (const CfgValueExtensionAndDependencyType& cfgValue : m_values) { extensionList = AZStd::string::format("%s%s%s", extensionList.c_str(), extensionList.empty() ? "" : ", ", cfgValue.m_extension.c_str()); } return extensionList; } AZStd::string m_key; AZStd::vector m_values; }; bool CfgBuilderWorker::ParseProductDependencies( const AssetBuilderSDK::ProcessJobRequest& request, AZStd::vector& /*productDependencies*/, AssetBuilderSDK::ProductPathDependencySet& pathDependencies) { AZ::Outcome configFileContents(AzFramework::FileFunc::GetCfgFileContents(request.m_fullPath)); if (!configFileContents.IsSuccess()) { AZ_Error("CfgBuilderWorker", false, configFileContents.GetError().c_str()); return false; } return ParseProductDependenciesFromCfgContents(request.m_fullPath, configFileContents.GetValue(), pathDependencies); } bool CfgBuilderWorker::ParseProductDependenciesFromCfgContents(const AZStd::string& fullPath, const AZStd::string& contents, AssetBuilderSDK::ProductPathDependencySet& pathDependencies) { const AZStd::vector uiCanvas = { {".uicanvas", AssetBuilderSDK::ProductPathDependencyType::ProductFile } }; const AZStd::vector imageFiles = { // There is no common place this extension list is defined, it is copy & pasted in many places. {".bmp", AssetBuilderSDK::ProductPathDependencyType::SourceFile }, {".gif", AssetBuilderSDK::ProductPathDependencyType::SourceFile }, {".jpeg", AssetBuilderSDK::ProductPathDependencyType::SourceFile }, {".jpg", AssetBuilderSDK::ProductPathDependencyType::SourceFile }, {".png", AssetBuilderSDK::ProductPathDependencyType::SourceFile }, {".tif", AssetBuilderSDK::ProductPathDependencyType::SourceFile }, {".tiff", AssetBuilderSDK::ProductPathDependencyType::SourceFile }, {".tga", AssetBuilderSDK::ProductPathDependencyType::SourceFile }, // Only need to look for DDS as a product, if it's in the source it gets copied to the cache. {".dds", AssetBuilderSDK::ProductPathDependencyType::ProductFile } }; CfgKeysAndValuesWithDependencies supportedConfigFileDependencies[] = { // These commands are defined in CrySystem\SystemInit.cpp {"game_load_screen_uicanvas_path", uiCanvas }, {"level_load_screen_uicanvas_path", uiCanvas }, {"sys_splashscreen", imageFiles }, }; bool allConfigDependenciesValid = true; for (const CfgKeysAndValuesWithDependencies& config : supportedConfigFileDependencies) { AZ::Outcome valueForKey( AzFramework::FileFunc::GetValueForKeyInCfgFileContents(contents, config.m_key.c_str())); if (!valueForKey.IsSuccess()) { // No error here, the key was either not in the file or not set to something valid. continue; } AZStd::string cleanedUpKey(valueForKey.GetValue()); AzFramework::StringFunc::AssetDatabasePath::Normalize(cleanedUpKey); AZStd::to_lower(cleanedUpKey.begin(), cleanedUpKey.end()); CfgValueExtensionAndDependencyType const* validExtension(nullptr); for (const CfgValueExtensionAndDependencyType& cfgValue : config.m_values) { if (AzFramework::StringFunc::Path::IsExtension(cleanedUpKey.c_str(), cfgValue.m_extension.c_str())) { validExtension = &cfgValue; break; } } if (!validExtension) { AZ_Error("CfgBuilderWorker", false, "Unsupported extension in config file '%s' for key '%s'. Expected '%s', found value '%s'", fullPath.c_str(), config.m_key.c_str(), config.ExtensionsToString().c_str(), valueForKey.GetValue().c_str()); allConfigDependenciesValid = false; } else { pathDependencies.emplace(cleanedUpKey.c_str(), validExtension->m_dependencyType); } } return allConfigDependenciesValid; } }