| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766 |
- /*
- * 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 "BuilderSettingManager.h"
- #include <QCoreApplication>
- #include <QDirIterator>
- #include <QFile>
- #include <QFileInfo>
- #include <QString>
- #include <Atom/ImageProcessing/PixelFormats.h>
- #include <BuilderSettings/CubemapSettings.h>
- #include <BuilderSettings/TextureSettings.h>
- #include <Converters/Cubemap.h>
- #include <Processing/ImageToProcess.h>
- #include <Processing/PixelFormatInfo.h>
- #include <Processing/Utils.h>
- #include <ImageLoader/ImageLoaders.h>
- #include <ImageProcessing_Traits_Platform.h>
- #include <AssetBuilderSDK/AssetBuilderSDK.h>
- #include <AzCore/IO/Path/Path.h>
- #include <AzCore/Math/Sha1.h>
- #include <AzCore/Serialization/Json/JsonSerialization.h>
- #include <AzCore/Serialization/SerializeContext.h>
- #include <AzCore/Serialization/ObjectStream.h>
- #include <AzCore/Serialization/Utils.h>
- #include <AzCore/std/smart_ptr/make_shared.h>
- #include <AzCore/std/string/string.h>
- #include <AzFramework/IO/LocalFileIO.h>
- #include <AzFramework/StringFunc/StringFunc.h>
- #include <AzFramework/Application/Application.h>
- #include <AzToolsFramework/API/EditorAssetSystemAPI.h>
- #include <AzCore/Serialization/Json/JsonUtils.h>
- namespace ImageProcessingAtom
- {
- const char* BuilderSettingManager::s_defaultConfigFolder = "@gemroot:ImageProcessingAtom@/Assets/Config/";
- const char* BuilderSettingManager::s_projectConfigRelativeFolder = "Config/AtomImageBuilder/";
- const char* BuilderSettingManager::s_builderSettingFileName = "ImageBuilder.settings";
- const char* BuilderSettingManager::s_presetFileExtension = "preset";
- const char FileMaskDelimiter = '_';
- namespace
- {
- [[maybe_unused]] static constexpr const char* const LogWindow = "Image Processing";
- }
- #if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
- #define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3) \
- namespace ImageProcess##PrivateName \
- { \
- bool DoesSupport(AZStd::string); \
- }
- AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS
- #undef AZ_RESTRICTED_PLATFORM_EXPANSION
- #endif //AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS
- const char* BuilderSettingManager::s_environmentVariableName = "ImageBuilderSettingManager_Atom";
- AZ::EnvironmentVariable<BuilderSettingManager*> BuilderSettingManager::s_globalInstance = nullptr;
- AZStd::mutex BuilderSettingManager::s_instanceMutex;
- const PlatformName BuilderSettingManager::s_defaultPlatform = AZ_TRAIT_IMAGEPROCESSING_DEFAULT_PLATFORM;
-
- void BuilderSettingManager::Reflect(AZ::ReflectContext* context)
- {
- AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
- if (serialize)
- {
- serialize->Class<BuilderSettingManager>()
- ->Version(2)
- ->Field("BuildSettings", &BuilderSettingManager::m_builderSettings)
- ->Field("PresetsByFileMask", &BuilderSettingManager::m_presetFilterMap)
- ->Field("DefaultPreset", &BuilderSettingManager::m_defaultPreset)
- ->Field("DefaultPresetAlpha", &BuilderSettingManager::m_defaultPresetAlpha)
- ->Field("DefaultPresetNonePOT", &BuilderSettingManager::m_defaultPresetNonePOT)
- // deprecated properties
- ->Field("DefaultPresetsByFileMask", &BuilderSettingManager::m_defaultPresetByFileMask)
- ->Field("AnalysisFingerprint", &BuilderSettingManager::m_analysisFingerprint);
- }
- }
- BuilderSettingManager* BuilderSettingManager::Instance()
- {
- AZStd::lock_guard<AZStd::mutex> lock(s_instanceMutex);
- if (!s_globalInstance)
- {
- s_globalInstance = AZ::Environment::FindVariable<BuilderSettingManager*>(s_environmentVariableName);
- }
- AZ_Assert(s_globalInstance, "BuilderSettingManager not created!");
- return s_globalInstance.Get();
- }
- void BuilderSettingManager::CreateInstance()
- {
- AZStd::lock_guard<AZStd::mutex> lock(s_instanceMutex);
- if (s_globalInstance)
- {
- AZ_Assert(false, "BuilderSettingManager already created!");
- return;
- }
- if (!s_globalInstance)
- {
- s_globalInstance = AZ::Environment::CreateVariable<BuilderSettingManager*>(s_environmentVariableName);
- }
- if (!s_globalInstance.Get())
- {
- s_globalInstance.Set(aznew BuilderSettingManager());
- }
- }
-
- void BuilderSettingManager::DestroyInstance()
- {
- AZStd::lock_guard<AZStd::mutex> lock(s_instanceMutex);
- AZ_Assert(s_globalInstance, "Invalid call to DestroyInstance - no instance exists.");
- AZ_Assert(s_globalInstance.Get(), "You can only call DestroyInstance if you have called CreateInstance.");
- delete s_globalInstance.Get();
- s_globalInstance.Reset();
- }
-
- const PresetSettings* BuilderSettingManager::GetPreset(const PresetName& presetName, const PlatformName& platform, AZStd::string_view* settingsFilePathOut) const
- {
- AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
- auto itr = m_presets.find(presetName);
- if (itr != m_presets.end())
- {
- if (settingsFilePathOut)
- {
- *settingsFilePathOut = itr->second.m_presetFilePath;
- }
- return itr->second.m_multiPreset.GetPreset(platform);
- }
- return nullptr;
- }
- AZStd::vector<AZStd::string> BuilderSettingManager::GetFileMasksForPreset(const PresetName& presetName) const
- {
- AZStd::vector<AZStd::string> fileMasks;
-
- AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
- for (const auto& mapping:m_presetFilterMap)
- {
- for (const auto& preset : mapping.second)
- {
- if (preset == presetName)
- {
- fileMasks.push_back(mapping.first);
- break;
- }
- }
- }
- return fileMasks;
- }
- const BuilderSettings* BuilderSettingManager::GetBuilderSetting(const PlatformName& platform) const
- {
- auto itr = m_builderSettings.find(platform);
- if (itr != m_builderSettings.end())
- {
- return &itr->second;
- }
- return nullptr;
- }
- const PlatformNameList BuilderSettingManager::GetPlatformList() const
- {
- PlatformNameList platforms;
- for (auto& builderSetting : m_builderSettings)
- {
- if (builderSetting.second.m_enablePlatform)
- {
- platforms.push_back(builderSetting.first);
- }
- }
- return platforms;
- }
- const AZStd::map <FileMask, AZStd::unordered_set<PresetName>>& BuilderSettingManager::GetPresetFilterMap() const
- {
- AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
- return m_presetFilterMap;
- }
- const AZStd::unordered_set<PresetName>& BuilderSettingManager::GetFullPresetList() const
- {
- AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
- AZStd::string noFilter = AZStd::string();
- return m_presetFilterMap.find(noFilter)->second;
- }
- const PresetName BuilderSettingManager::GetPresetNameFromId(const AZ::Uuid& presetId)
- {
- AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
- for (const auto& itr : m_presets)
- {
- if (itr.second.m_multiPreset.GetPresetId() == presetId)
- {
- return itr.second.m_multiPreset.GetPresetName();
- }
- }
- return {};
- }
- void BuilderSettingManager::ClearSettings()
- {
- AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
- m_presetFilterMap.clear();
- m_builderSettings.clear();
- m_presets.clear();
- }
- StringOutcome BuilderSettingManager::LoadConfig()
- {
- StringOutcome outcome = STRING_OUTCOME_ERROR("");
- auto fileIoBase = AZ::IO::FileIOBase::GetInstance();
- if (fileIoBase == nullptr)
- {
- return AZ::Failure(
- AZStd::string("File IO instance needs to be initialized to resolve ImageProcessing builder file aliases"));
- }
- if (auto defaultConfigFolder = fileIoBase->ResolvePath(s_defaultConfigFolder); defaultConfigFolder.has_value())
- {
- m_defaultConfigFolder = *defaultConfigFolder;
- }
- if (auto sourceGameRoot = fileIoBase->ResolvePath("@projectroot@"); sourceGameRoot.has_value())
- {
- m_projectConfigFolder = *sourceGameRoot;
- m_projectConfigFolder /= s_projectConfigRelativeFolder;
- }
- AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
- ClearSettings();
-
- outcome = LoadSettings();
-
- if (outcome.IsSuccess())
- {
- // Load presets in default folder first, then load from project folder.
- // The same presets which loaded last will overwrite previous loaded one.
- LoadPresets(m_defaultConfigFolder.Native());
- LoadPresets(m_projectConfigFolder.Native());
- }
- // Collect extra file masks from preset files
- CollectFileMasksFromPresets();
-
- if (QCoreApplication::instance())
- {
- m_fileWatcher.reset(new QFileSystemWatcher);
- // track preset files
- // Note, the QT signal would only works for AP but not AssetBuilder
- // We use file time stamp to track preset file change in builder's CreateJob
- for (auto& preset : m_presets)
- {
- m_fileWatcher.data()->addPath(QString(preset.second.m_presetFilePath.c_str()));
- }
- m_fileWatcher.data()->addPath(QString(m_defaultConfigFolder.c_str()));
- m_fileWatcher.data()->addPath(QString(m_projectConfigFolder.c_str()));
- QObject::connect(m_fileWatcher.data(), &QFileSystemWatcher::fileChanged, this, &BuilderSettingManager::OnFileChanged);
- QObject::connect(m_fileWatcher.data(), &QFileSystemWatcher::directoryChanged, this, &BuilderSettingManager::OnFolderChanged);
- }
- return outcome;
- }
- void BuilderSettingManager::LoadPresets(AZStd::string_view presetFolder)
- {
- QDirIterator it(presetFolder.data(), QStringList() << "*.preset", QDir::Files, QDirIterator::NoIteratorFlags);
- while (it.hasNext())
- {
- QString filePath = it.next();
- LoadPreset(filePath.toUtf8().data());
- }
- }
- bool BuilderSettingManager::LoadPreset(const AZStd::string& filePath)
- {
- QFileInfo fileInfo (filePath.c_str());
- if (!fileInfo.exists())
- {
- return false;
- }
- MultiplatformPresetSettings preset;
- auto result = AZ::JsonSerializationUtils::LoadObjectFromFile(preset, filePath);
- if (!result.IsSuccess())
- {
- AZ_Warning(LogWindow, false, "Failed to load preset file %s. Error: %s",
- filePath.c_str(), result.GetError().c_str());
- return false;
- }
- PresetName presetName(fileInfo.baseName().toUtf8().data());
- AZ_Warning(LogWindow, presetName == preset.GetPresetName(), "Preset file name '%s' is not"
- " same as preset name '%s'. Using preset file name as preset name",
- filePath.c_str(), preset.GetPresetName().GetCStr());
- preset.SetPresetName(presetName);
- m_presets[presetName] = PresetEntry{preset, filePath.c_str(), fileInfo.lastModified()};
- return true;
- }
- void BuilderSettingManager::ReloadPreset(const PresetName& presetName)
- {
- // Find the preset file from project or default config folder
- AZStd::string presetFileName = AZStd::string::format("%s.%s", presetName.GetCStr(), s_presetFileExtension);
- AZ::IO::FixedMaxPath filePath = m_projectConfigFolder/presetFileName;
- QFileInfo fileInfo (filePath.c_str());
- if (!fileInfo.exists())
- {
- filePath = (m_defaultConfigFolder/presetFileName).c_str();
- fileInfo = QFileInfo(filePath.c_str());
- }
-
- AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
- //Skip the loading if the file wasn't chagned
- if (fileInfo.exists())
- {
- if (m_presets.find(presetName) != m_presets.end())
- {
- if (m_presets[presetName].m_lastModifiedTime == fileInfo.lastModified()
- && m_presets[presetName].m_presetFilePath == filePath.c_str())
- {
- return;
- }
- }
- }
- // remove preset
- m_presets.erase(presetName);
- if (fileInfo.exists())
- {
- LoadPreset(filePath.c_str());
- }
- }
- StringOutcome BuilderSettingManager::LoadConfigFromFolder(AZStd::string_view configFolder)
- {
- AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
- // Load builder settings
- AZStd::string settingFilePath = AZStd::string::format("%.*s%s", aznumeric_cast<int>(configFolder.size()),
- configFolder.data(), s_builderSettingFileName);
- auto result = LoadSettings(settingFilePath);
- // Load presets
- if (result.IsSuccess())
- {
- LoadPresets(configFolder);
- }
- return result;
- }
- void BuilderSettingManager::ReportDeprecatedSettings()
- {
- // reported deprecated attributes in image builder settings
- if (!m_analysisFingerprint.empty())
- {
- AZ_Warning(LogWindow, false, "'AnalysisFingerprint' is deprecated and it should be removed from file [%s]", s_builderSettingFileName);
- }
- if (!m_defaultPresetByFileMask.empty())
- {
- AZ_Warning(LogWindow, false, "'DefaultPresetsByFileMask' is deprecated and it should be removed from file [%s]. Use PresetsByFileMask instead", s_builderSettingFileName);
- }
- }
- StringOutcome BuilderSettingManager::LoadSettings()
- {
- // If the project image build setting file exist, it will merge image builder settings from project folder to the settings from default config folder.
- bool needMerge = false;
- AZStd::string projectSettingFile{ (m_projectConfigFolder / s_builderSettingFileName).Native() };
- if (AZ::IO::SystemFile::Exists(projectSettingFile.c_str()))
- {
- needMerge = true;
- }
- AZ::Outcome<void, AZStd::string> outcome;
- AZStd::string defaultSettingFile{ (m_defaultConfigFolder / s_builderSettingFileName).Native() };
- if (needMerge)
- {
- auto outcome1 = AZ::JsonSerializationUtils::ReadJsonFile(defaultSettingFile);
- auto outcome2 = AZ::JsonSerializationUtils::ReadJsonFile(projectSettingFile);
- // return error if it failed to load default settings
- if (!outcome1.IsSuccess())
- {
- return STRING_OUTCOME_ERROR(outcome1.GetError());
- }
- // if project config was loaded successfully, apply merge patch
- rapidjson::Document& originDoc = outcome1.GetValue();
- if (outcome2.IsSuccess())
- {
- const rapidjson::Document& patchDoc = outcome2.GetValue();
- AZ::JsonSerializationResult::ResultCode result =
- AZ::JsonSerialization::ApplyPatch(originDoc, originDoc.GetAllocator(), patchDoc, AZ::JsonMergeApproach::JsonMergePatch);
- if (result.GetProcessing() == AZ::JsonSerializationResult::Processing::Completed)
- {
- AZStd::vector<char> outBuffer;
- AZ::IO::ByteContainerStream<AZStd::vector<char>> outStream{ &outBuffer };
- AZ::JsonSerializationUtils::WriteJsonStream(originDoc, outStream);
- outStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
- outcome = AZ::JsonSerializationUtils::LoadObjectFromStream(*this, outStream);
- if (!outcome.IsSuccess())
- {
- return STRING_OUTCOME_ERROR(outcome.GetError());
- }
-
- ReportDeprecatedSettings();
- // Generate config file fingerprint
- outStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
- AZ::u64 hash = AssetBuilderSDK::GetHashFromIOStream(outStream);
- m_analysisFingerprint = AZStd::string::format("%llX", hash);
- }
- else
- {
- needMerge = false;
- AZ_Warning(LogWindow, false, "Failed to fully merge data into image builder settings. Skipping project build setting file [%s]", projectSettingFile.c_str());
- }
- }
- else
- {
- AZ_Warning(LogWindow, false, "Failed to load project setting file [%s]. Skipping", projectSettingFile.c_str());
- }
- }
- if (!needMerge)
- {
- outcome = AZ::JsonSerializationUtils::LoadObjectFromFile(*this, defaultSettingFile);
- if (!outcome.IsSuccess())
- {
- return STRING_OUTCOME_ERROR(outcome.GetError());
- }
- ReportDeprecatedSettings();
- // Generate config file fingerprint
- AZ::u64 hash = AssetBuilderSDK::GetFileHash(defaultSettingFile.c_str());
- m_analysisFingerprint = AZStd::string::format("%llX", hash);
- }
- return STRING_OUTCOME_SUCCESS;
- }
- StringOutcome BuilderSettingManager::LoadSettings(AZStd::string_view filepath)
- {
- AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
- auto result = AZ::JsonSerializationUtils::LoadObjectFromFile(*this, filepath);
- if (!result.IsSuccess())
- {
- return STRING_OUTCOME_ERROR(result.GetError());
- }
- //enable builder settings for enabled restricted platforms. These settings should be disabled by default in the setting file
- #if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
- #define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3) \
- for (auto& buildSetting : m_builderSettings) \
- { \
- if (ImageProcess##PrivateName::DoesSupport(buildSetting.first)) \
- { \
- buildSetting.second.m_enablePlatform = true; \
- break; \
- } \
- }
- AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS
- #undef AZ_RESTRICTED_PLATFORM_EXPANSION
- #endif //AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS
-
- return STRING_OUTCOME_SUCCESS;
- }
- StringOutcome BuilderSettingManager::WriteSettings(AZStd::string_view filepath)
- {
- AZ::JsonSerializerSettings saveSettings;
- saveSettings.m_keepDefaults = true;
- auto result = AZ::JsonSerializationUtils::SaveObjectToFile(this, filepath,
- (BuilderSettingManager*)nullptr, &saveSettings);
- if (!result.IsSuccess())
- {
- return STRING_OUTCOME_ERROR(result.GetError());
- }
- return STRING_OUTCOME_SUCCESS;
- }
- const AZStd::string& BuilderSettingManager::GetAnalysisFingerprint() const
- {
- return m_analysisFingerprint;
- }
- void BuilderSettingManager::CollectFileMasksFromPresets()
- {
- AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
- AZStd::string noFilter = AZStd::string();
-
- AZStd::string extraString;
- for (const auto& presetIter : m_presets)
- {
- const MultiplatformPresetSettings& multiPreset = presetIter.second.m_multiPreset;
- const PresetSettings& preset = multiPreset.GetDefaultPreset();
-
- //Put into no filter preset list
- m_presetFilterMap[noFilter].insert(preset.m_name);
- //Put into file mask preset list if any
- for (const PlatformName& filemask : preset.m_fileMasks)
- {
- if (filemask.empty() || filemask[0] != FileMaskDelimiter)
- {
- AZ_Warning(LogWindow, false, "File mask '%s' is invalid. It must start with '%c'.", filemask.c_str(), FileMaskDelimiter);
- continue;
- }
- else if (filemask.size() < 2)
- {
- AZ_Warning(LogWindow, false, "File mask '%s' is invalid. The '%c' must be followed by at least one other character.", filemask.c_str());
- continue;
- }
- else if (filemask.find(FileMaskDelimiter, 1) != AZStd::string::npos)
- {
- AZ_Warning(LogWindow, false, "File mask '%s' is invalid. It must contain only a single '%c' character.", filemask.c_str(), FileMaskDelimiter);
- continue;
- }
- else if (filemask.find(AZ_FILESYSTEM_EXTENSION_SEPARATOR) != AZStd::string::npos)
- {
- AZ_Warning(LogWindow, false,
- "File mask '%s' is invalid. It must not contain a file extension separator ('%c').",
- filemask.c_str(),
- AZ_FILESYSTEM_EXTENSION_SEPARATOR);
- continue;
- }
- extraString += (filemask + preset.m_name.GetCStr());
- m_presetFilterMap[filemask].insert(preset.m_name);
- }
- }
- if (!extraString.empty())
- {
- AZ::u64 hash = AZStd::hash<AZStd::string>{}(extraString);
- m_analysisFingerprint += AZStd::string::format("%llX", hash);
- }
- }
- void BuilderSettingManager::MetafilePathFromImagePath(AZStd::string_view imagePath, AZStd::string& metafilePath)
- {
- // Determine if we have a meta file
- AZ::IO::LocalFileIO fileIO;
- AZStd::string settingFilePath = AZStd::string::format("%.*s%s", aznumeric_cast<int>(imagePath.size()),
- imagePath.data(), TextureSettings::ExtensionName);
- if (fileIO.Exists(settingFilePath.c_str()))
- {
- metafilePath = settingFilePath;
- return;
- }
- metafilePath = AZStd::string();
- }
- AZStd::string BuilderSettingManager::GetFileMask(AZStd::string_view imageFilePath) const
- {
- //get file name
- QString lowerFileName = imageFilePath.data();
- lowerFileName = lowerFileName.toLower();
- // If the complete file name contains multiple extension separators ('.'), only use the base name before the first separator
- // for the file mask. For example, 'name_filemask.something.extension' will only use 'name_filemask', producing a result
- // of '_filemask' that is returned from this method.
- AZStd::string fileName(QFileInfo(lowerFileName).baseName().toUtf8());
- //get the substring from last '_'
- size_t lastUnderScore = fileName.find_last_of(FileMaskDelimiter);
- if (lastUnderScore != AZStd::string::npos)
- {
- return fileName.substr(lastUnderScore);
- }
- return AZStd::string();
- }
- PresetName BuilderSettingManager::GetDefaultPreset() const
- {
- return m_defaultPreset;
- }
- PresetName BuilderSettingManager::GetDefaultAlphaPreset() const
- {
- return m_defaultPresetAlpha;
- }
- AZStd::vector<PresetName> BuilderSettingManager::GetPresetsForFileMask(const FileMask& fileMask) const
- {
- AZStd::vector<PresetName> presets;
- AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
- if (auto it = m_presetFilterMap.find(fileMask); it != m_presetFilterMap.end())
- {
- for (const PresetName& presetName : it->second)
- {
- presets.push_back(presetName);
- }
- }
- return presets;
- }
- bool BuilderSettingManager::IsValidPreset(PresetName presetName) const
- {
- if (presetName.IsEmpty())
- {
- return false;
- }
- return m_presets.find(presetName) != m_presets.end();
- }
- PresetName BuilderSettingManager::GetSuggestedPreset(AZStd::string_view imageFilePath) const
- {
- PresetName emptyPreset;
- //get file mask of this image file
- AZStd::string fileMask = GetFileMask(imageFilePath);
- PresetName outPreset = emptyPreset;
- //use the preset filter map to find
- if (outPreset.IsEmpty() && !fileMask.empty())
- {
- auto& presetFilterMap = GetPresetFilterMap();
- if (presetFilterMap.find(fileMask) != presetFilterMap.end())
- {
- outPreset = *(presetFilterMap.find(fileMask)->second.begin());
- }
- }
- if (outPreset == emptyPreset)
- {
- auto image = IImageObjectPtr(LoadImageFromFile(imageFilePath));
- if (image && ((image->GetAlphaContent() == EAlphaContent::eAlphaContent_Absent
- || image->GetAlphaContent() == EAlphaContent::eAlphaContent_OnlyWhite)))
- {
- outPreset = m_defaultPreset;
- }
- else
- {
- outPreset = m_defaultPresetAlpha;
- }
- }
- return outPreset;
- }
- AZStd::vector<AZStd::string> BuilderSettingManager::GetPossiblePresetPaths(const PresetName& presetName) const
- {
- AZStd::vector<AZStd::string> paths;
- AZStd::string presetFile = AZStd::string::format("%s.preset", presetName.GetCStr());
- paths.push_back((m_defaultConfigFolder / presetFile).c_str());
- paths.push_back((m_projectConfigFolder / presetFile).c_str());
- return paths;
- }
- bool BuilderSettingManager::DoesSupportPlatform(AZStd::string_view platformId)
- {
- if (const auto& itr = m_builderSettings.find(platformId); itr != m_builderSettings.end())
- {
- return itr->second.m_enablePlatform;
- }
- return false;
- }
-
- void BuilderSettingManager::SavePresets(AZStd::string_view outputFolder)
- {
- for (const auto& element : m_presets)
- {
- const PresetEntry& presetEntry = element.second;
- AZStd::string fileName = AZStd::string::format("%s.preset", presetEntry.m_multiPreset.GetDefaultPreset().m_name.GetCStr());
- AZStd::string filePath;
- if (!AzFramework::StringFunc::Path::Join(outputFolder.data(), fileName.c_str(), filePath))
- {
- AZ_Warning(LogWindow, false, "Failed to construct path with folder '%.*s' and file: '%s' to save preset",
- aznumeric_cast<int>(outputFolder.size()), outputFolder.data(), filePath.c_str());
- continue;
- }
- auto result = AZ::JsonSerializationUtils::SaveObjectToFile(&presetEntry.m_multiPreset, filePath);
- if (!result.IsSuccess())
- {
- AZ_Warning(LogWindow, false, "Failed to save preset '%s' to file '%s'. Error: %s",
- presetEntry.m_multiPreset.GetDefaultPreset().m_name.GetCStr(), filePath.c_str(), result.GetError().c_str());
- }
- }
- }
- void BuilderSettingManager::OnFileChanged(const QString &path)
- {
- // handles preset file change
- // Note: this signal only works with AP but not AssetBuilder
- AZ_TracePrintf(LogWindow, "File changed %s\n", path.toUtf8().data());
- QFileInfo info(path);
- // skip if the file is not a preset file
- // Note: for .settings file change it's handled when restart AP.
- if (info.suffix() != s_presetFileExtension)
- {
- return;
- }
-
- ReloadPreset(PresetName(info.baseName().toUtf8().data()));
- }
-
- void BuilderSettingManager::OnFolderChanged([[maybe_unused]] const QString &path)
- {
- // handles new file added or removed
- // Note: this signal only works with AP but not AssetBuilder
- AZ_TracePrintf(LogWindow, "folder changed %s\n", path.toUtf8().data());
- AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
- m_presets.clear();
- LoadPresets(m_defaultConfigFolder.Native());
- LoadPresets(m_projectConfigFolder.Native());
- for (auto& preset : m_presets)
- {
- m_fileWatcher.data()->addPath(QString(preset.second.m_presetFilePath.c_str()));
- }
- }
- } // namespace ImageProcessingAtom
|