89e6df1c7f
ATOM-16575 clean up image builder presets files Removed unused image builder presets Deprecating preset UUID and use preset name as unique id Delete all .exportsettings file which were only used for legacy imageProcessing gem. Signed-off-by: Qing Tao <qingtao@amazon.com>
343 lines
15 KiB
C++
343 lines
15 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 <BuilderSettings/TextureSettings.h>
|
|
#include <AzCore/RTTI/ReflectContext.h>
|
|
#include <AzCore/Serialization/EditContext.h>
|
|
#include <AzFramework/StringFunc/StringFunc.h>
|
|
#include <AzCore/IO/FileIO.h>
|
|
#include <AzCore/IO/SystemFile.h>
|
|
#include <AzCore/Serialization/Utils.h>
|
|
|
|
#include <BuilderSettings/BuilderSettingManager.h>
|
|
#include <ImageLoader/ImageLoaders.h>
|
|
|
|
|
|
namespace ImageProcessingAtom
|
|
{
|
|
const char* TextureSettings::ExtensionName = ".assetinfo";
|
|
|
|
TextureSettings::TextureSettings()
|
|
: m_presetId(0)
|
|
, m_sizeReduceLevel(0)
|
|
, m_suppressEngineReduce(false)
|
|
, m_enableMipmap(true)
|
|
, m_maintainAlphaCoverage(false)
|
|
, m_mipGenEval(MipGenEvalType::sum)
|
|
, m_mipGenType(MipGenType::blackmanHarris)
|
|
{
|
|
const int defaultMipMapValue = 50;
|
|
|
|
for (int i = 0; i < s_MaxMipMaps; ++i)
|
|
{
|
|
m_mipAlphaAdjust.push_back(defaultMipMapValue);
|
|
}
|
|
}
|
|
|
|
void TextureSettings::Reflect(AZ::ReflectContext* context)
|
|
{
|
|
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
|
if (serialize)
|
|
{
|
|
serialize->Class<TextureSettings>()
|
|
->Version(2)
|
|
->Field("PresetID", &TextureSettings::m_presetId)
|
|
->Field("Preset", &TextureSettings::m_preset)
|
|
->Field("SizeReduceLevel", &TextureSettings::m_sizeReduceLevel)
|
|
->Field("EngineReduce", &TextureSettings::m_suppressEngineReduce)
|
|
->Field("EnableMipmap", &TextureSettings::m_enableMipmap)
|
|
->Field("MaintainAlphaCoverage", &TextureSettings::m_maintainAlphaCoverage)
|
|
->Field("MipMapAlphaAdjustments", &TextureSettings::m_mipAlphaAdjust)
|
|
->Field("MipMapGenEval", &TextureSettings::m_mipGenEval)
|
|
->Field("MipMapGenType", &TextureSettings::m_mipGenType)
|
|
->Field("PlatformSpecificOverrides", &TextureSettings::m_platfromOverrides)
|
|
->Field("OverridingPlatform", &TextureSettings::m_overridingPlatform);
|
|
|
|
AZ::EditContext* edit = serialize->GetEditContext();
|
|
if (edit)
|
|
{
|
|
edit->Class<TextureSettings>("Texture Setting", "")
|
|
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
|
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
|
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
|
->DataElement(AZ::Edit::UIHandlers::Default, &TextureSettings::m_mipAlphaAdjust, "Alpha Test Bias", "Multiplies the mipmap's alpha with a scale value that is based on alpha coverage. \
|
|
Set the mip 0 to mip 5 values to offset the alpha test values and ensure the mipmap's alpha coverage matches the original image. Specify a value from 0 to 100.")
|
|
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
|
->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, false)
|
|
->ElementAttribute(AZ::Edit::UIHandlers::Handler, AZ::Edit::UIHandlers::Slider)
|
|
->ElementAttribute(AZ::Edit::Attributes::Min, 0)
|
|
->ElementAttribute(AZ::Edit::Attributes::Max, 100)
|
|
->ElementAttribute(AZ::Edit::Attributes::Step, 1)
|
|
->DataElement(AZ::Edit::UIHandlers::ComboBox, &TextureSettings::m_mipGenType, "Filter Method", "")
|
|
->EnumAttribute(MipGenType::point, "Point")
|
|
->EnumAttribute(MipGenType::box, "Average")
|
|
->EnumAttribute(MipGenType::triangle, "Linear")
|
|
->EnumAttribute(MipGenType::quadratic, "Bilinear")
|
|
->EnumAttribute(MipGenType::gaussian, "Gaussian")
|
|
->EnumAttribute(MipGenType::blackmanHarris, "BlackmanHarris")
|
|
->EnumAttribute(MipGenType::kaiserSinc, "KaiserSinc")
|
|
->DataElement(AZ::Edit::UIHandlers::ComboBox, &TextureSettings::m_mipGenEval, "Pixel Sampling Type", "")
|
|
->EnumAttribute(MipGenEvalType::max, "Max")
|
|
->EnumAttribute(MipGenEvalType::min, "Min")
|
|
->EnumAttribute(MipGenEvalType::sum, "Sum")
|
|
->DataElement(AZ::Edit::UIHandlers::CheckBox, &TextureSettings::m_maintainAlphaCoverage, "Maintain Alpha Coverage", "Select this option to manually adjust Alpha channel mipmaps.")
|
|
;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool TextureSettings::operator!=(const TextureSettings& other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
|
|
bool TextureSettings::operator==(const TextureSettings& other) const
|
|
{
|
|
/////////////////////////////
|
|
// Compare Alpha Adjust
|
|
/////////////////////////////
|
|
bool matchingAlphaTestAdjust = true;
|
|
for (AZ::u8 curIndex = 0; curIndex < s_MaxMipMaps; ++curIndex)
|
|
{
|
|
if (m_mipAlphaAdjust[curIndex] != other.m_mipAlphaAdjust[curIndex])
|
|
{
|
|
matchingAlphaTestAdjust = false;
|
|
break;
|
|
}
|
|
}
|
|
return
|
|
matchingAlphaTestAdjust &&
|
|
m_preset == other.m_preset &&
|
|
m_sizeReduceLevel == other.m_sizeReduceLevel &&
|
|
m_suppressEngineReduce == other.m_suppressEngineReduce &&
|
|
m_maintainAlphaCoverage == other.m_maintainAlphaCoverage &&
|
|
m_mipGenEval == other.m_mipGenEval &&
|
|
m_mipGenType == other.m_mipGenType;
|
|
}
|
|
|
|
bool TextureSettings::Equals(const TextureSettings& other, AZ::SerializeContext* serializeContext)
|
|
{
|
|
/////////////////////////////
|
|
// Compare Common Settings
|
|
/////////////////////////////
|
|
if (*this != other)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/////////////////////////////
|
|
// Compare Overrides
|
|
/////////////////////////////
|
|
const MultiplatformTextureSettings selfOverrides = GetMultiplatformTextureSetting(*this, serializeContext);
|
|
const MultiplatformTextureSettings otherOverrides = GetMultiplatformTextureSetting(other, serializeContext);
|
|
auto selfOverridesIter = selfOverrides.begin();
|
|
auto otherOverridesIter = otherOverrides.begin();
|
|
|
|
while (selfOverridesIter != selfOverrides.end() && otherOverridesIter != otherOverrides.end())
|
|
{
|
|
if (selfOverridesIter->second != otherOverridesIter->second)
|
|
{
|
|
return false;
|
|
}
|
|
otherOverridesIter++;
|
|
selfOverridesIter++;
|
|
}
|
|
|
|
AZ_Assert(selfOverridesIter == selfOverrides.end() && otherOverridesIter == otherOverrides.end(), "Both iterators must be at the end by now.")
|
|
return true;
|
|
}
|
|
|
|
float TextureSettings::ComputeMIPAlphaOffset(AZ::u32 mip) const
|
|
{
|
|
if (mip / 2 + 1 >= s_MaxMipMaps)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
float fVal = static_cast<float>(m_mipAlphaAdjust[s_MaxMipMaps - 1]);
|
|
if (mip / 2 + 1 < s_MaxMipMaps)
|
|
{
|
|
float fInterpolationSlider1 = static_cast<float>(m_mipAlphaAdjust[mip / 2]);
|
|
float fInterpolationSlider2 = static_cast<float>(m_mipAlphaAdjust[mip / 2 + 1]);
|
|
fVal = fInterpolationSlider1 + (fInterpolationSlider2 - fInterpolationSlider1) * (mip & 1) * 0.5f;
|
|
}
|
|
|
|
return 0.5f - fVal / 100.0f;
|
|
}
|
|
|
|
void TextureSettings::ApplyPreset(PresetName presetName)
|
|
{
|
|
const PresetSettings* presetSetting = BuilderSettingManager::Instance()->GetPreset(presetName);
|
|
if (presetSetting != nullptr)
|
|
{
|
|
m_sizeReduceLevel = presetSetting->m_sizeReduceLevel;
|
|
m_suppressEngineReduce = presetSetting->m_suppressEngineReduce;
|
|
if (presetSetting->m_mipmapSetting)
|
|
{
|
|
m_mipGenType = presetSetting->m_mipmapSetting->m_type;
|
|
}
|
|
|
|
m_preset = presetName;
|
|
}
|
|
else
|
|
{
|
|
AZ_Error("Image Processing", false, "Cannot set an invalid preset %s!", presetName.GetCStr());
|
|
}
|
|
}
|
|
|
|
StringOutcome TextureSettings::LoadTextureSetting(const AZStd::string& filepath, TextureSettings& textureSettingPtrOut, AZ::SerializeContext* serializeContext /*= nullptr*/)
|
|
{
|
|
auto loadedTextureSettingPtr = AZStd::unique_ptr<TextureSettings>(AZ::Utils::LoadObjectFromFile<TextureSettings>(filepath, serializeContext));
|
|
|
|
if (!loadedTextureSettingPtr)
|
|
{
|
|
return AZ::Failure(AZStd::string());
|
|
}
|
|
|
|
textureSettingPtrOut = *loadedTextureSettingPtr;
|
|
|
|
// In old format, the preset name doesn't exist. Using preset id to get preset name
|
|
// We can remove this when we fully deprecate the preset uuid
|
|
if (textureSettingPtrOut.m_preset.IsEmpty())
|
|
{
|
|
textureSettingPtrOut.m_preset = BuilderSettingManager::Instance()->GetPresetNameFromId(textureSettingPtrOut.m_presetId);
|
|
}
|
|
|
|
return AZ::Success(AZStd::string());
|
|
}
|
|
|
|
StringOutcome TextureSettings::WriteTextureSetting(const AZStd::string& filepath, TextureSettings& textureSetting, AZ::SerializeContext* serializeContext)
|
|
{
|
|
if (false == AZ::Utils::SaveObjectToFile<TextureSettings>(filepath, AZ::DataStream::StreamType::ST_XML, &textureSetting, serializeContext))
|
|
{
|
|
return STRING_OUTCOME_ERROR("Failed to write to file: " + filepath);
|
|
}
|
|
|
|
return STRING_OUTCOME_SUCCESS;
|
|
}
|
|
|
|
MultiplatformTextureSettings TextureSettings::GenerateDefaultMultiplatformTextureSettings(const AZStd::string& imageFilepath)
|
|
{
|
|
MultiplatformTextureSettings settings;
|
|
PlatformNameList platformsList = BuilderSettingManager::Instance()->GetPlatformList();
|
|
PresetName suggestedPreset = BuilderSettingManager::Instance()->GetSuggestedPreset(imageFilepath);
|
|
for (PlatformName& platform : platformsList)
|
|
{
|
|
TextureSettings textureSettings;
|
|
textureSettings.ApplyPreset(suggestedPreset);
|
|
settings.insert(AZStd::pair<PlatformName, TextureSettings>(platform, textureSettings));
|
|
}
|
|
return settings;
|
|
}
|
|
|
|
StringOutcome TextureSettings::GetPlatformSpecificTextureSetting(const PlatformName& platformName, const TextureSettings& baseTextureSettings,
|
|
TextureSettings& textureSettingsOut, AZ::SerializeContext* serializeContext)
|
|
{
|
|
// Obtain the DataPatch (if platform exists)
|
|
auto overrideIter = baseTextureSettings.m_platfromOverrides.find(platformName);
|
|
if (overrideIter == baseTextureSettings.m_platfromOverrides.end())
|
|
{
|
|
return STRING_OUTCOME_ERROR(AZStd::string::format("TextureSettings preset [%s] does not have override for platform [%s]",
|
|
baseTextureSettings.m_preset.GetCStr(), platformName.c_str()));
|
|
}
|
|
AZ::DataPatch& platformOverride = const_cast<AZ::DataPatch&>(overrideIter->second);
|
|
|
|
// Update settings instance with override values.
|
|
if (platformOverride.IsData())
|
|
{
|
|
// Apply the AZ::DataPatch to obtain a platform-overridden version of the TextureSettings.
|
|
AZStd::unique_ptr<TextureSettings> platformSpecificTextureSettings(platformOverride.Apply(&baseTextureSettings, serializeContext));
|
|
AZ_Assert(platformSpecificTextureSettings->m_mipAlphaAdjust.size() == s_MaxMipMaps, "Unexpected m_mipAlphaAdjust size.");
|
|
|
|
// Adjust overrides data to imply 'platformSpecificTextureSettings' *IS* the override.
|
|
platformSpecificTextureSettings->m_platfromOverrides.clear();
|
|
platformSpecificTextureSettings->m_overridingPlatform = platformName;
|
|
textureSettingsOut = *platformSpecificTextureSettings;
|
|
}
|
|
else
|
|
{
|
|
textureSettingsOut = baseTextureSettings;
|
|
}
|
|
|
|
return STRING_OUTCOME_SUCCESS;
|
|
}
|
|
|
|
const MultiplatformTextureSettings TextureSettings::GetMultiplatformTextureSetting(const TextureSettings& textureSettings, AZ::SerializeContext* serializeContext)
|
|
{
|
|
MultiplatformTextureSettings loadedSettingsReturn;
|
|
PlatformNameList platformsList = BuilderSettingManager::Instance()->GetPlatformList();
|
|
// Generate MultiplatformTextureSettings based on existing available overrides.
|
|
for (const PlatformName& curPlatformName : platformsList)
|
|
{
|
|
// Start with a copy of the base settings
|
|
TextureSettings curPlatformOverride = textureSettings;
|
|
if (!GetPlatformSpecificTextureSetting(curPlatformName, textureSettings, curPlatformOverride, serializeContext).IsSuccess())
|
|
{
|
|
// We have failed to obtain an override. Maintain base settings to indicate zero overrides.
|
|
// We still want to designate these TextureSettings as an (empty) override.
|
|
curPlatformOverride.m_platfromOverrides.clear();
|
|
curPlatformOverride.m_overridingPlatform = curPlatformName;
|
|
}
|
|
|
|
// Add as an entry to the multiplatform texture settings
|
|
loadedSettingsReturn.insert(AZStd::pair<PlatformName, TextureSettings>(curPlatformName, curPlatformOverride));
|
|
}
|
|
|
|
// return a copy of the results
|
|
return loadedSettingsReturn;
|
|
}
|
|
|
|
const MultiplatformTextureSettings TextureSettings::GetMultiplatformTextureSetting(const AZStd::string& imageFilepath, bool& canOverridePreset, AZ::SerializeContext* serializeContext)
|
|
{
|
|
TextureSettings loadedTextureSetting;
|
|
|
|
// Attempt to get metadata file path from image path.
|
|
AZStd::string metadataFilepath = imageFilepath + TextureSettings::ExtensionName;
|
|
bool hasMetafile = AZ::IO::SystemFile::Exists(metadataFilepath.c_str());
|
|
|
|
canOverridePreset = true;
|
|
|
|
// If the image has an accompanying metadata...
|
|
if(hasMetafile)
|
|
{
|
|
// Parse the metadata file.
|
|
if (LoadTextureSetting(metadataFilepath, loadedTextureSetting, serializeContext).IsSuccess())
|
|
{
|
|
canOverridePreset = false;
|
|
return GetMultiplatformTextureSetting(loadedTextureSetting, serializeContext);
|
|
}
|
|
else
|
|
{
|
|
AZ_Error("Image processing", false, "Failed to load the image's meta file %s", metadataFilepath.c_str());
|
|
}
|
|
}
|
|
|
|
return GenerateDefaultMultiplatformTextureSettings(imageFilepath);
|
|
}
|
|
|
|
StringOutcome TextureSettings::ApplySettings(const TextureSettings& settings, const PlatformName& overridePlatform, AZ::SerializeContext* serializeContext)
|
|
{
|
|
if (overridePlatform.empty())
|
|
{
|
|
*this = settings;
|
|
}
|
|
else
|
|
{
|
|
AZ::DataPatch newOverride;
|
|
if (false == newOverride.Create<TextureSettings, TextureSettings>(this, &settings, AZ::DataPatch::FlagsMap(), AZ::DataPatch::FlagsMap(), serializeContext))
|
|
{
|
|
return STRING_OUTCOME_ERROR("Failed to create TextureSettings platform override data. See AZ_Error log for details.");
|
|
}
|
|
|
|
m_platfromOverrides[overridePlatform] = newOverride;
|
|
}
|
|
|
|
return STRING_OUTCOME_SUCCESS;
|
|
}
|
|
}
|