Merge commit '2ae8477683394a4cb550c58d6e024fdb7c684db3' into puvvadar/gitflow_211118_o3de
This commit is contained in:
+272
-125
@@ -8,6 +8,7 @@
|
||||
|
||||
|
||||
#include "BuilderSettingManager.h"
|
||||
#include <QCoreApplication>
|
||||
#include <QDirIterator>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
@@ -17,8 +18,9 @@
|
||||
#include <BuilderSettings/CubemapSettings.h>
|
||||
#include <BuilderSettings/TextureSettings.h>
|
||||
#include <Converters/Cubemap.h>
|
||||
#include <Processing/PixelFormatInfo.h>
|
||||
#include <Processing/ImageToProcess.h>
|
||||
#include <Processing/PixelFormatInfo.h>
|
||||
#include <Processing/Utils.h>
|
||||
#include <ImageLoader/ImageLoaders.h>
|
||||
#include <ImageProcessing_Traits_Platform.h>
|
||||
|
||||
@@ -41,13 +43,18 @@
|
||||
|
||||
namespace ImageProcessingAtom
|
||||
{
|
||||
const char* BuilderSettingManager::s_defaultConfigRelativeFolder = "Gems/Atom/Asset/ImageProcessingAtom/Config/";
|
||||
const char* BuilderSettingManager::s_defaultConfigRelativeFolder = "Gems/Atom/Asset/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* BuilderSettingManager::s_presetFileExtension = "preset";
|
||||
|
||||
const char FileMaskDelimiter = '_';
|
||||
|
||||
namespace
|
||||
{
|
||||
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 \
|
||||
@@ -69,13 +76,15 @@ namespace ImageProcessingAtom
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<BuilderSettingManager>()
|
||||
->Version(1)
|
||||
->Field("AnalysisFingerprint", &BuilderSettingManager::m_analysisFingerprint)
|
||||
->Version(2)
|
||||
->Field("BuildSettings", &BuilderSettingManager::m_builderSettings)
|
||||
->Field("DefaultPresetsByFileMask", &BuilderSettingManager::m_defaultPresetByFileMask)
|
||||
->Field("PresetsByFileMask", &BuilderSettingManager::m_presetFilterMap)
|
||||
->Field("DefaultPreset", &BuilderSettingManager::m_defaultPreset)
|
||||
->Field("DefaultPresetAlpha", &BuilderSettingManager::m_defaultPresetAlpha)
|
||||
->Field("DefaultPresetNonePOT", &BuilderSettingManager::m_defaultPresetNonePOT);
|
||||
->Field("DefaultPresetNonePOT", &BuilderSettingManager::m_defaultPresetNonePOT)
|
||||
// deprecated properties
|
||||
->Field("DefaultPresetsByFileMask", &BuilderSettingManager::m_defaultPresetByFileMask)
|
||||
->Field("AnalysisFingerprint", &BuilderSettingManager::m_analysisFingerprint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +131,7 @@ namespace ImageProcessingAtom
|
||||
s_globalInstance.Reset();
|
||||
}
|
||||
|
||||
const PresetSettings* BuilderSettingManager::GetPreset(const PresetName& presetName, const PlatformName& platform, AZStd::string_view* settingsFilePathOut)
|
||||
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);
|
||||
@@ -137,16 +146,17 @@ namespace ImageProcessingAtom
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const BuilderSettings* BuilderSettingManager::GetBuilderSetting(const PlatformName& platform)
|
||||
const BuilderSettings* BuilderSettingManager::GetBuilderSetting(const PlatformName& platform) const
|
||||
{
|
||||
if (m_builderSettings.find(platform) != m_builderSettings.end())
|
||||
auto itr = m_builderSettings.find(platform);
|
||||
if (itr != m_builderSettings.end())
|
||||
{
|
||||
return &m_builderSettings[platform];
|
||||
return &itr->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const PlatformNameList BuilderSettingManager::GetPlatformList()
|
||||
const PlatformNameList BuilderSettingManager::GetPlatformList() const
|
||||
{
|
||||
PlatformNameList platforms;
|
||||
|
||||
@@ -161,7 +171,7 @@ namespace ImageProcessingAtom
|
||||
return platforms;
|
||||
}
|
||||
|
||||
const AZStd::map <FileMask, AZStd::unordered_set<PresetName>>& BuilderSettingManager::GetPresetFilterMap()
|
||||
const AZStd::map <FileMask, AZStd::unordered_set<PresetName>>& BuilderSettingManager::GetPresetFilterMap() const
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
|
||||
return m_presetFilterMap;
|
||||
@@ -188,7 +198,6 @@ namespace ImageProcessingAtom
|
||||
m_presetFilterMap.clear();
|
||||
m_builderSettings.clear();
|
||||
m_presets.clear();
|
||||
m_defaultPresetByFileMask.clear();
|
||||
}
|
||||
|
||||
StringOutcome BuilderSettingManager::LoadConfig()
|
||||
@@ -198,44 +207,53 @@ namespace ImageProcessingAtom
|
||||
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"));
|
||||
return AZ::Failure(
|
||||
AZStd::string("File IO instance needs to be initialized to resolve ImageProcessing builder file aliases"));
|
||||
}
|
||||
|
||||
// Construct the default setting path
|
||||
|
||||
AZ::IO::FixedMaxPath defaultConfigFolder;
|
||||
if (auto engineRoot = fileIoBase->ResolvePath("@engroot@"); engineRoot.has_value())
|
||||
{
|
||||
defaultConfigFolder = *engineRoot;
|
||||
defaultConfigFolder /= s_defaultConfigRelativeFolder;
|
||||
m_defaultConfigFolder = *engineRoot;
|
||||
m_defaultConfigFolder /= s_defaultConfigRelativeFolder;
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPath projectConfigFolder;
|
||||
if (auto sourceGameRoot = fileIoBase->ResolvePath("@projectroot@"); sourceGameRoot.has_value())
|
||||
{
|
||||
projectConfigFolder = *sourceGameRoot;
|
||||
projectConfigFolder /= s_projectConfigRelativeFolder;
|
||||
m_projectConfigFolder = *sourceGameRoot;
|
||||
m_projectConfigFolder /= s_projectConfigRelativeFolder;
|
||||
}
|
||||
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
|
||||
ClearSettings();
|
||||
|
||||
outcome = LoadSettings((projectConfigFolder / s_builderSettingFileName).Native());
|
||||
|
||||
if (!outcome.IsSuccess())
|
||||
{
|
||||
outcome = LoadSettings((defaultConfigFolder / s_builderSettingFileName).Native());
|
||||
}
|
||||
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(defaultConfigFolder.Native());
|
||||
LoadPresets(projectConfigFolder.Native());
|
||||
LoadPresets(m_defaultConfigFolder.Native());
|
||||
LoadPresets(m_projectConfigFolder.Native());
|
||||
}
|
||||
|
||||
// Regenerate file mask mapping after all presets loaded
|
||||
RegenerateMappings();
|
||||
// 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;
|
||||
@@ -243,36 +261,84 @@ namespace ImageProcessingAtom
|
||||
|
||||
void BuilderSettingManager::LoadPresets(AZStd::string_view presetFolder)
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
|
||||
|
||||
QDirIterator it(presetFolder.data(), QStringList() << "*.preset", QDir::Files, QDirIterator::NoIteratorFlags);
|
||||
while (it.hasNext())
|
||||
{
|
||||
QString filePath = it.next();
|
||||
QFileInfo fileInfo = it.fileInfo();
|
||||
LoadPreset(filePath.toUtf8().data());
|
||||
}
|
||||
}
|
||||
|
||||
MultiplatformPresetSettings preset;
|
||||
auto result = AZ::JsonSerializationUtils::LoadObjectFromFile(preset, filePath.toUtf8().data());
|
||||
if (!result.IsSuccess())
|
||||
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())
|
||||
{
|
||||
AZ_Warning("Image Processing", false, "Failed to load preset file %s. Error: %s",
|
||||
filePath.toUtf8().data(), result.GetError().c_str());
|
||||
if (m_presets[presetName].m_lastModifiedTime == fileInfo.lastModified()
|
||||
&& m_presets[presetName].m_presetFilePath == filePath.c_str())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PresetName presetName(fileInfo.baseName().toUtf8().data());
|
||||
// remove preset
|
||||
m_presets.erase(presetName);
|
||||
|
||||
AZ_Warning("Image Processing", presetName == preset.GetPresetName(), "Preset file name '%s' is not"
|
||||
" same as preset name '%s'. Using preset file name as preset name",
|
||||
filePath.toUtf8().data(), preset.GetPresetName().GetCStr());
|
||||
|
||||
preset.SetPresetName(presetName);
|
||||
|
||||
m_presets[presetName] = PresetEntry{preset, filePath.toUtf8().data()};
|
||||
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);
|
||||
@@ -282,12 +348,108 @@ namespace ImageProcessingAtom
|
||||
if (result.IsSuccess())
|
||||
{
|
||||
LoadPresets(configFolder);
|
||||
RegenerateMappings();
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -336,13 +498,13 @@ namespace ImageProcessingAtom
|
||||
return m_analysisFingerprint;
|
||||
}
|
||||
|
||||
void BuilderSettingManager::RegenerateMappings()
|
||||
void BuilderSettingManager::CollectFileMasksFromPresets()
|
||||
{
|
||||
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
|
||||
|
||||
AZStd::string noFilter = AZStd::string();
|
||||
|
||||
m_presetFilterMap.clear();
|
||||
|
||||
AZStd::string extraString;
|
||||
|
||||
for (const auto& presetIter : m_presets)
|
||||
{
|
||||
@@ -357,22 +519,31 @@ namespace ImageProcessingAtom
|
||||
{
|
||||
if (filemask.empty() || filemask[0] != FileMaskDelimiter)
|
||||
{
|
||||
AZ_Warning("Image Processing", false, "File mask '%s' is invalid. It must start with '%c'.", filemask.c_str(), 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("Image Processing", false, "File mask '%s' is invalid. The '%c' must be followed by at least one other character.", filemask.c_str());
|
||||
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("Image Processing", false, "File mask '%s' is invalid. It must contain only a single '%c' character.", filemask.c_str(), FileMaskDelimiter);
|
||||
AZ_Warning(LogWindow, false, "File mask '%s' is invalid. It must contain only a single '%c' character.", filemask.c_str(), FileMaskDelimiter);
|
||||
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)
|
||||
@@ -419,38 +590,15 @@ namespace ImageProcessingAtom
|
||||
return m_presets.find(presetName) != m_presets.end();
|
||||
}
|
||||
|
||||
PresetName BuilderSettingManager::GetSuggestedPreset(AZStd::string_view imageFilePath, IImageObjectPtr imageFromFile)
|
||||
PresetName BuilderSettingManager::GetSuggestedPreset(AZStd::string_view imageFilePath) const
|
||||
{
|
||||
PresetName emptyPreset;
|
||||
|
||||
//load the image to get its size for later use
|
||||
IImageObjectPtr image = imageFromFile;
|
||||
//if the input image is empty we will try to load it from the path
|
||||
if (imageFromFile == nullptr)
|
||||
{
|
||||
image = IImageObjectPtr(LoadImageFromFile(imageFilePath));
|
||||
}
|
||||
|
||||
if (image == nullptr)
|
||||
{
|
||||
return emptyPreset;
|
||||
}
|
||||
|
||||
//get file mask of this image file
|
||||
AZStd::string fileMask = GetFileMask(imageFilePath);
|
||||
|
||||
PresetName outPreset = emptyPreset;
|
||||
|
||||
//check default presets for some file masks
|
||||
if (m_defaultPresetByFileMask.find(fileMask) != m_defaultPresetByFileMask.end())
|
||||
{
|
||||
outPreset = m_defaultPresetByFileMask[fileMask];
|
||||
if (!IsValidPreset(outPreset))
|
||||
{
|
||||
outPreset = emptyPreset;
|
||||
}
|
||||
}
|
||||
|
||||
//use the preset filter map to find
|
||||
if (outPreset.IsEmpty() && !fileMask.empty())
|
||||
{
|
||||
@@ -461,54 +609,21 @@ namespace ImageProcessingAtom
|
||||
}
|
||||
}
|
||||
|
||||
const PresetSettings* presetInfo = nullptr;
|
||||
|
||||
if (!outPreset.IsEmpty())
|
||||
{
|
||||
presetInfo = GetPreset(outPreset);
|
||||
|
||||
//special case for cubemap
|
||||
if (presetInfo && presetInfo->m_cubemapSetting)
|
||||
{
|
||||
// If it's not a latitude-longitude map or it doesn't match any cubemap layouts then reset its preset
|
||||
if (!IsValidLatLongMap(image) && CubemapLayout::GetCubemapLayoutInfo(image) == nullptr)
|
||||
{
|
||||
outPreset = emptyPreset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (outPreset == emptyPreset)
|
||||
{
|
||||
if (image->GetAlphaContent() == EAlphaContent::eAlphaContent_Absent)
|
||||
{
|
||||
outPreset = m_defaultPreset;
|
||||
}
|
||||
else
|
||||
{
|
||||
outPreset = m_defaultPresetAlpha;
|
||||
}
|
||||
outPreset = m_defaultPreset;
|
||||
}
|
||||
|
||||
//get the pixel format for selected preset
|
||||
presetInfo = GetPreset(outPreset);
|
||||
return outPreset;
|
||||
}
|
||||
|
||||
if (presetInfo)
|
||||
{
|
||||
//valid whether image size work with pixel format
|
||||
if (CPixelFormats::GetInstance().IsImageSizeValid(presetInfo->m_pixelFormat,
|
||||
image->GetWidth(0), image->GetHeight(0), false))
|
||||
{
|
||||
return outPreset;
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning("Image Processing", false, "Image dimensions are not compatible with preset '%s'. The default preset will be used.", presetInfo->m_name.GetCStr());
|
||||
}
|
||||
}
|
||||
|
||||
//uncompressed one which could be used for almost everything
|
||||
return m_defaultPresetNonePOT;
|
||||
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)
|
||||
@@ -526,18 +641,50 @@ namespace ImageProcessingAtom
|
||||
AZStd::string filePath;
|
||||
if (!AzFramework::StringFunc::Path::Join(outputFolder.data(), fileName.c_str(), filePath))
|
||||
{
|
||||
AZ_Warning("Image Processing", false, "Failed to construct path with folder '%.*s' and file: '%s' to save preset",
|
||||
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("Image Processing", false, "Failed to save preset '%s' to file '%s'. Error: %s",
|
||||
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
|
||||
|
||||
+52
-12
@@ -10,10 +10,15 @@
|
||||
|
||||
#include <BuilderSettings/ImageProcessingDefines.h>
|
||||
#include <BuilderSettings/BuilderSettings.h>
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/std/containers/set.h>
|
||||
#include <Atom/ImageProcessing/ImageObject.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QScopedPointer>
|
||||
|
||||
class QSettings;
|
||||
class QString;
|
||||
|
||||
@@ -36,6 +41,7 @@ namespace ImageProcessingAtom
|
||||
* Each preset setting may have different values on different platform, but they are using same uuid.
|
||||
*/
|
||||
class BuilderSettingManager
|
||||
: public QObject // required for using QFileSystemWatcher
|
||||
{
|
||||
friend class ImageProcessingTest;
|
||||
|
||||
@@ -49,17 +55,17 @@ namespace ImageProcessingAtom
|
||||
static void DestroyInstance();
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
const PresetSettings* GetPreset(const PresetName& presetName, const PlatformName& platform = "", AZStd::string_view* settingsFilePathOut = nullptr);
|
||||
const PresetSettings* GetPreset(const PresetName& presetName, const PlatformName& platform = "", AZStd::string_view* settingsFilePathOut = nullptr) const;
|
||||
|
||||
const BuilderSettings* GetBuilderSetting(const PlatformName& platform);
|
||||
const BuilderSettings* GetBuilderSetting(const PlatformName& platform) const;
|
||||
|
||||
//! Return A list of platform supported
|
||||
const PlatformNameList GetPlatformList();
|
||||
const PlatformNameList GetPlatformList() const;
|
||||
|
||||
//! Return A map of preset settings based on their filemasks.
|
||||
//! @key filemask string, empty string means no filemask
|
||||
//! @value set of preset setting names supporting the specified filemask
|
||||
const AZStd::map<FileMask, AZStd::unordered_set<PresetName>>& GetPresetFilterMap();
|
||||
const AZStd::map<FileMask, AZStd::unordered_set<PresetName>>& GetPresetFilterMap() const;
|
||||
|
||||
//! Find preset name based on the preset id.
|
||||
const PresetName GetPresetNameFromId(const AZ::Uuid& presetId);
|
||||
@@ -68,7 +74,11 @@ namespace ImageProcessingAtom
|
||||
StringOutcome LoadConfig();
|
||||
|
||||
//! Load configurations files from a folder which includes builder settings and presets
|
||||
StringOutcome LoadConfigFromFolder(AZStd::string_view configFolder);
|
||||
//! Note: this is only used for unit test. Use LoadConfig() for editor or game launcher
|
||||
StringOutcome LoadConfigFromFolder(AZStd::string_view configFolder);
|
||||
|
||||
//! Reload preset from config folders
|
||||
void ReloadPreset(const PresetName& presetName);
|
||||
|
||||
const AZStd::string& GetAnalysisFingerprint() const;
|
||||
|
||||
@@ -81,7 +91,12 @@ namespace ImageProcessingAtom
|
||||
//! @param imageFilePath: Filepath string of the image file. The function may load the image from the path for better detection
|
||||
//! @param image: an optional image object which can be used for preset selection if there is no match based file mask.
|
||||
//! @return suggested preset name.
|
||||
PresetName GetSuggestedPreset(AZStd::string_view imageFilePath, IImageObjectPtr image = nullptr);
|
||||
PresetName GetSuggestedPreset(AZStd::string_view imageFilePath) const;
|
||||
|
||||
//! Get the possible preset config's full file paths
|
||||
//! This function is only used for setting up image's source dependency if a preset file is missing
|
||||
//! Otherwise, the preset's file path can be retrieved in GetPreset() function
|
||||
AZStd::vector<AZStd::string> GetPossiblePresetPaths(const PresetName& presetName) const;
|
||||
|
||||
bool IsValidPreset(PresetName presetName) const;
|
||||
|
||||
@@ -105,25 +120,41 @@ namespace ImageProcessingAtom
|
||||
private: // functions
|
||||
AZ_DISABLE_COPY_MOVE(BuilderSettingManager);
|
||||
|
||||
// Write image builder setting to the file specified by filepath
|
||||
StringOutcome WriteSettings(AZStd::string_view filepath);
|
||||
// Load image builder settings from the file specified by filepath
|
||||
StringOutcome LoadSettings(AZStd::string_view filepath);
|
||||
|
||||
// Load merge image builder settings (project and default)
|
||||
StringOutcome LoadSettings();
|
||||
|
||||
// report warnings for the deprecated properties in image builder setting data
|
||||
void ReportDeprecatedSettings();
|
||||
|
||||
// Clear Builder Settings and any cached maps/lists
|
||||
void ClearSettings();
|
||||
|
||||
// Regenerate Builder Settings and any cached maps/lists
|
||||
void RegenerateMappings();
|
||||
// collect file masks
|
||||
void CollectFileMasksFromPresets();
|
||||
|
||||
// Functions to save/load preset from a folder
|
||||
void SavePresets(AZStd::string_view outputFolder);
|
||||
void LoadPresets(AZStd::string_view presetFolder);
|
||||
|
||||
// Load a preset to m_presets and return true if success
|
||||
bool LoadPreset(const AZStd::string& filePath);
|
||||
|
||||
// handle preset files changes
|
||||
void OnFileChanged(const QString &path);
|
||||
void OnFolderChanged(const QString &path);
|
||||
|
||||
private: // variables
|
||||
|
||||
struct PresetEntry
|
||||
{
|
||||
MultiplatformPresetSettings m_multiPreset;
|
||||
AZStd::string m_presetFilePath; // Can be used for debug output
|
||||
QDateTime m_lastModifiedTime;
|
||||
};
|
||||
|
||||
// Builder settings for each platform
|
||||
@@ -131,13 +162,13 @@ namespace ImageProcessingAtom
|
||||
|
||||
AZStd::unordered_map<PresetName, PresetEntry> m_presets;
|
||||
|
||||
// Cached list of presets mapped by their file masks.
|
||||
// a list of presets mapped by their file masks.
|
||||
// @Key file mask, use empty string to indicate all presets without filtering
|
||||
// @Value set of preset names that matches the file mask
|
||||
AZStd::map <FileMask, AZStd::unordered_set<PresetName>> m_presetFilterMap;
|
||||
|
||||
// A mutex to protect when modifying any map in this manager
|
||||
AZStd::recursive_mutex m_presetMapLock;
|
||||
// A mutex to protect when modifying any map in this manager
|
||||
mutable AZStd::recursive_mutex m_presetMapLock;
|
||||
|
||||
// Default presets for certain file masks
|
||||
AZStd::map <FileMask, PresetName > m_defaultPresetByFileMask;
|
||||
@@ -153,5 +184,14 @@ namespace ImageProcessingAtom
|
||||
|
||||
// Image builder's version
|
||||
AZStd::string m_analysisFingerprint;
|
||||
|
||||
// default config folder
|
||||
AZ::IO::FixedMaxPath m_defaultConfigFolder;
|
||||
|
||||
// project config folder
|
||||
AZ::IO::FixedMaxPath m_projectConfigFolder;
|
||||
|
||||
// File system watcher to detect preset file changes
|
||||
QScopedPointer<QFileSystemWatcher> m_fileWatcher;
|
||||
};
|
||||
} // namespace ImageProcessingAtom
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace ImageProcessingAtomEditor
|
||||
if (!preset)
|
||||
{
|
||||
AZ_Warning("Texture Editor", false, "Cannot find preset %s! Will assign a suggested one for the texture.", presetName.GetCStr());
|
||||
presetName = BuilderSettingManager::Instance()->GetSuggestedPreset(m_fullPath, m_img);
|
||||
presetName = BuilderSettingManager::Instance()->GetSuggestedPreset(m_fullPath);
|
||||
|
||||
for (auto& settingIter : m_settingsMap)
|
||||
{
|
||||
|
||||
@@ -221,6 +221,58 @@ namespace ImageProcessingAtom
|
||||
m_isShuttingDown = true;
|
||||
}
|
||||
|
||||
PresetName GetImagePreset(const AZStd::string& filepath)
|
||||
{
|
||||
// first let preset from asset info
|
||||
TextureSettings textureSettings;
|
||||
StringOutcome output = TextureSettings::LoadTextureSetting(filepath, textureSettings);
|
||||
|
||||
if (!textureSettings.m_preset.IsEmpty())
|
||||
{
|
||||
return textureSettings.m_preset;
|
||||
}
|
||||
|
||||
return BuilderSettingManager::Instance()->GetSuggestedPreset(filepath);
|
||||
}
|
||||
|
||||
void HandlePresetDependency(PresetName presetName, AZStd::vector<AssetBuilderSDK::SourceFileDependency>& sourceDependencyList)
|
||||
{
|
||||
// Reload preset if it was changed
|
||||
ImageProcessingAtom::BuilderSettingManager::Instance()->ReloadPreset(presetName);
|
||||
|
||||
AZStd::string_view filePath;
|
||||
auto presetSettings = BuilderSettingManager::Instance()->GetPreset(presetName, /*default platform*/"", &filePath);
|
||||
|
||||
AssetBuilderSDK::SourceFileDependency sourceFileDependency;
|
||||
sourceFileDependency.m_sourceDependencyType = AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Absolute;
|
||||
|
||||
// Need to watch any possibe preset paths
|
||||
AZStd::vector<AZStd::string> possiblePresetPaths = BuilderSettingManager::Instance()->GetPossiblePresetPaths(presetName);
|
||||
for (const auto& path:possiblePresetPaths)
|
||||
{
|
||||
sourceFileDependency.m_sourceFileDependencyPath = path;
|
||||
sourceDependencyList.push_back(sourceFileDependency);
|
||||
}
|
||||
|
||||
if (presetSettings)
|
||||
{
|
||||
// handle special case here
|
||||
// Cubemap setting may reference some other presets
|
||||
if (presetSettings->m_cubemapSetting)
|
||||
{
|
||||
if (presetSettings->m_cubemapSetting->m_generateIBLDiffuse && !presetSettings->m_cubemapSetting->m_iblDiffusePreset.IsEmpty())
|
||||
{
|
||||
HandlePresetDependency(presetSettings->m_cubemapSetting->m_iblDiffusePreset, sourceDependencyList);
|
||||
}
|
||||
|
||||
if (presetSettings->m_cubemapSetting->m_generateIBLSpecular && !presetSettings->m_cubemapSetting->m_iblSpecularPreset.IsEmpty())
|
||||
{
|
||||
HandlePresetDependency(presetSettings->m_cubemapSetting->m_iblSpecularPreset, sourceDependencyList);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this happens early on in the file scanning pass
|
||||
// this function should consistently always create the same jobs, and should do no checking whether the job is up to date or not - just be consistent.
|
||||
void ImageBuilderWorker::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response)
|
||||
@@ -242,13 +294,26 @@ namespace ImageProcessingAtom
|
||||
if (ImageProcessingAtom::BuilderSettingManager::Instance()->DoesSupportPlatform(platformInfo.m_identifier))
|
||||
{
|
||||
AssetBuilderSDK::JobDescriptor descriptor;
|
||||
descriptor.m_jobKey = ext + " Atom Compile";
|
||||
descriptor.m_jobKey = "Image Compile: " + ext;
|
||||
descriptor.SetPlatformIdentifier(platformInfo.m_identifier.c_str());
|
||||
descriptor.m_critical = false;
|
||||
descriptor.m_additionalFingerprintInfo = "";
|
||||
response.m_createJobOutputs.push_back(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
// add source dependency for .assetinfo file
|
||||
AssetBuilderSDK::SourceFileDependency sourceFileDependency;
|
||||
sourceFileDependency.m_sourceDependencyType = AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Absolute;
|
||||
sourceFileDependency.m_sourceFileDependencyPath = request.m_sourceFile;
|
||||
AZ::StringFunc::Path::ReplaceExtension(sourceFileDependency.m_sourceFileDependencyPath, TextureSettings::ExtensionName);
|
||||
response.m_sourceFileDependencyList.push_back(sourceFileDependency);
|
||||
|
||||
// add source dependencies for .preset files
|
||||
// Get the preset for this file
|
||||
auto presetName = GetImagePreset(request.m_sourceFile);
|
||||
HandlePresetDependency(presetName, response.m_sourceFileDependencyList);
|
||||
|
||||
response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <Processing/ImageConvert.h>
|
||||
#include <Processing/ImageAssetProducer.h>
|
||||
#include <Processing/ImageFlags.h>
|
||||
#include <Processing/Utils.h>
|
||||
#include <Converters/FIR-Weights.h>
|
||||
#include <Converters/Cubemap.h>
|
||||
#include <Converters/PixelOperation.h>
|
||||
@@ -229,12 +230,24 @@ namespace ImageProcessingAtom
|
||||
AZStd::unique_ptr<CubemapSettings>& cubemapSettings = m_input->m_presetSetting.m_cubemapSetting;
|
||||
if (cubemapSettings->m_generateIBLSpecular && !cubemapSettings->m_iblSpecularPreset.IsEmpty())
|
||||
{
|
||||
CreateIBLCubemap(cubemapSettings->m_iblSpecularPreset, SpecularCubemapSuffix, m_iblSpecularCubemapImage);
|
||||
bool success = CreateIBLCubemap(cubemapSettings->m_iblSpecularPreset, SpecularCubemapSuffix, m_iblSpecularCubemapImage);
|
||||
if (!success)
|
||||
{
|
||||
m_isSucceed = false;
|
||||
m_isFinished = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cubemapSettings->m_generateIBLDiffuse && !cubemapSettings->m_iblDiffusePreset.IsEmpty())
|
||||
{
|
||||
CreateIBLCubemap(cubemapSettings->m_iblDiffusePreset, DiffuseCubemapSuffix, m_iblDiffuseCubemapImage);
|
||||
bool success = CreateIBLCubemap(cubemapSettings->m_iblDiffusePreset, DiffuseCubemapSuffix, m_iblDiffuseCubemapImage);
|
||||
if (!success)
|
||||
{
|
||||
m_isSucceed = false;
|
||||
m_isFinished = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,7 +264,12 @@ namespace ImageProcessingAtom
|
||||
{
|
||||
if (m_input->m_presetSetting.m_cubemapSetting->m_requiresConvolve)
|
||||
{
|
||||
FillCubemapMipmaps();
|
||||
bool success = FillCubemapMipmaps();
|
||||
if (!success)
|
||||
{
|
||||
m_isSucceed = false;
|
||||
m_isFinished = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -268,9 +286,7 @@ namespace ImageProcessingAtom
|
||||
// get gloss from normal for all mipmaps and save to alpha channel
|
||||
if (m_input->m_presetSetting.m_glossFromNormals)
|
||||
{
|
||||
bool hasAlpha = (m_alphaContent == EAlphaContent::eAlphaContent_OnlyBlack
|
||||
|| m_alphaContent == EAlphaContent::eAlphaContent_OnlyBlackAndWhite
|
||||
|| m_alphaContent == EAlphaContent::eAlphaContent_Greyscale);
|
||||
bool hasAlpha = Utils::NeedAlphaChannel(m_alphaContent);
|
||||
|
||||
m_image->Get()->GlossFromNormals(hasAlpha);
|
||||
// set alpha content so it won't be ignored later.
|
||||
@@ -347,7 +363,11 @@ namespace ImageProcessingAtom
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_TracePrintf("Image Processing", "Image converted with preset [%s] [%s] and saved to [%s] (%d bytes) taking %f seconds\n",
|
||||
|
||||
[[maybe_unused]] const PixelFormatInfo* formatInfo = CPixelFormats::GetInstance().GetPixelFormatInfo(m_image->Get()->GetPixelFormat());
|
||||
AZ_TracePrintf("Image Processing", "Image [%dx%d] [%s] converted with preset [%s] [%s] and saved to [%s] (%d bytes) taking %f seconds\n",
|
||||
m_image->Get()->GetWidth(0), m_image->Get()->GetHeight(0),
|
||||
formatInfo->szName,
|
||||
m_input->m_presetSetting.m_name.GetCStr(),
|
||||
m_input->m_filePath.c_str(),
|
||||
m_input->m_outputFolder.c_str(), sizeTotal, m_processTime);
|
||||
@@ -421,6 +441,17 @@ namespace ImageProcessingAtom
|
||||
outHeight >>= 1;
|
||||
outReduce++;
|
||||
}
|
||||
|
||||
// resize to min texture size if it's smaller
|
||||
if (outWidth < presetSettings->m_minTextureSize)
|
||||
{
|
||||
outWidth = presetSettings->m_minTextureSize;
|
||||
}
|
||||
|
||||
if (outHeight < presetSettings->m_minTextureSize)
|
||||
{
|
||||
outHeight = presetSettings->m_minTextureSize;
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageConvertProcess::ConvertToLinear()
|
||||
@@ -647,7 +678,7 @@ namespace ImageProcessingAtom
|
||||
}
|
||||
else if (!CPixelFormats::GetInstance().IsImageSizeValid(dstFmt, dwWidth, dwHeight, false))
|
||||
{
|
||||
AZ_Warning("Image Processing", false, "Image size will be scaled for pixel format %s", CPixelFormats::GetInstance().GetPixelFormatInfo(dstFmt)->szName);
|
||||
AZ_TracePrintf("Image processing", "Image size will be scaled for pixel format %s\n", CPixelFormats::GetInstance().GetPixelFormatInfo(dstFmt)->szName);
|
||||
}
|
||||
|
||||
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
|
||||
@@ -758,7 +789,7 @@ namespace ImageProcessingAtom
|
||||
// in very rare user case, an old texture setting file may not have a preset. We fix it over here too.
|
||||
if (textureSettings.m_preset.IsEmpty())
|
||||
{
|
||||
textureSettings.m_preset = BuilderSettingManager::Instance()->GetSuggestedPreset(imageFilePath, srcImage);
|
||||
textureSettings.m_preset = BuilderSettingManager::Instance()->GetSuggestedPreset(imageFilePath);
|
||||
}
|
||||
|
||||
// Get preset
|
||||
@@ -795,7 +826,7 @@ namespace ImageProcessingAtom
|
||||
return process;
|
||||
}
|
||||
|
||||
void ImageConvertProcess::CreateIBLCubemap(PresetName preset, const char* fileNameSuffix, IImageObjectPtr& cubemapImage)
|
||||
bool ImageConvertProcess::CreateIBLCubemap(PresetName preset, const char* fileNameSuffix, IImageObjectPtr& cubemapImage)
|
||||
{
|
||||
const AZStd::string& platformId = m_input->m_platform;
|
||||
AZStd::string_view filePath;
|
||||
@@ -803,7 +834,7 @@ namespace ImageProcessingAtom
|
||||
if (presetSettings == nullptr)
|
||||
{
|
||||
AZ_Error("Image Processing", false, "Couldn't find preset for IBL cubemap generation");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// generate export file name
|
||||
@@ -838,14 +869,14 @@ namespace ImageProcessingAtom
|
||||
if (!imageConvertProcess)
|
||||
{
|
||||
AZ_Error("Image Processing", false, "Failed to create image convert process for the IBL cubemap");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
imageConvertProcess->ProcessAll();
|
||||
if (!imageConvertProcess->IsSucceed())
|
||||
{
|
||||
AZ_Error("Image Processing", false, "Image convert process for the IBL cubemap failed");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// append the output products to the job's product list
|
||||
@@ -853,6 +884,7 @@ namespace ImageProcessingAtom
|
||||
|
||||
// store the output cubemap so it can be accessed by unit tests
|
||||
cubemapImage = imageConvertProcess->m_image->Get();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConvertImageFile(const AZStd::string& imageFilePath, const AZStd::string& exportDir,
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace ImageProcessingAtom
|
||||
bool FillCubemapMipmaps();
|
||||
|
||||
//IBL cubemap generation, this creates a separate ImageConvertProcess
|
||||
void CreateIBLCubemap(PresetName preset, const char* fileNameSuffix, IImageObjectPtr& cubemapImage);
|
||||
bool CreateIBLCubemap(PresetName preset, const char* fileNameSuffix, IImageObjectPtr& cubemapImage);
|
||||
|
||||
//convert color space to linear with pixel format rgba32f
|
||||
bool ConvertToLinear();
|
||||
|
||||
@@ -183,10 +183,9 @@ namespace ImageProcessingAtom
|
||||
return EAlphaContent::eAlphaContent_Absent;
|
||||
}
|
||||
|
||||
//if it's compressed format, return indeterminate. if user really want to know the content, they may convert the format to ARGB8 first
|
||||
if (!CPixelFormats::GetInstance().IsPixelFormatUncompressed(m_pixelFormat))
|
||||
{
|
||||
AZ_Assert(false, "the function only works right with uncompressed formats. convert to uncompressed format if you get accurate result");
|
||||
AZ_TracePrintf("Image processing", "GetAlphaContent() was called for compressed format\n");
|
||||
return EAlphaContent::eAlphaContent_Indeterminate;
|
||||
}
|
||||
|
||||
|
||||
@@ -385,6 +385,13 @@ namespace ImageProcessingAtom
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NeedAlphaChannel(EAlphaContent alphaContent)
|
||||
{
|
||||
return (alphaContent == EAlphaContent::eAlphaContent_OnlyBlack
|
||||
|| alphaContent == EAlphaContent::eAlphaContent_OnlyBlackAndWhite
|
||||
|| alphaContent == EAlphaContent::eAlphaContent_Greyscale);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ImageProcessingAtom
|
||||
|
||||
@@ -26,5 +26,7 @@ namespace ImageProcessingAtom
|
||||
IImageObjectPtr LoadImageFromImageAsset(const AZ::Data::Asset<AZ::RPI::StreamingImageAsset>& asset);
|
||||
|
||||
bool SaveImageToDdsFile(IImageObjectPtr image, AZStd::string_view filePath);
|
||||
|
||||
bool NeedAlphaChannel(EAlphaContent alphaContent);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user