diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py
index f84e367d1d..0b75760e05 100644
--- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py
+++ b/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py
@@ -18,7 +18,7 @@ import pytest
import editor_python_test_tools.hydra_test_utils as hydra
logger = logging.getLogger(__name__)
-EDITOR_TIMEOUT = 120
+EDITOR_TIMEOUT = 300
TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "atom_hydra_scripts")
diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp
index c94978c63d..540178f4d9 100644
--- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp
+++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp
@@ -95,32 +95,32 @@ namespace UnitTest
class ImageProcessingTest
: public ::testing::Test
, public AllocatorsBase
- , public ComponentApplicationBus::Handler
+ , public AZ::ComponentApplicationBus::Handler
{
public:
//////////////////////////////////////////////////////////////////////////
// ComponentApplicationMessages.
- ComponentApplication* GetApplication() override { return nullptr; }
- void RegisterComponentDescriptor(const ComponentDescriptor*) override { }
- void UnregisterComponentDescriptor(const ComponentDescriptor*) override { }
- void RegisterEntityAddedEventHandler(EntityAddedEvent::Handler&) override { }
- void RegisterEntityRemovedEventHandler(EntityRemovedEvent::Handler&) override { }
- void RegisterEntityActivatedEventHandler(EntityActivatedEvent::Handler&) override { }
- void RegisterEntityDeactivatedEventHandler(EntityDeactivatedEvent::Handler&) override { }
- void SignalEntityActivated(Entity*) override { }
- void SignalEntityDeactivated(Entity*) override { }
- bool AddEntity(Entity*) override { return false; }
- bool RemoveEntity(Entity*) override { return false; }
- bool DeleteEntity(const EntityId&) override { return false; }
- Entity* FindEntity(const EntityId&) override { return nullptr; }
- SerializeContext* GetSerializeContext() override { return m_context.get(); }
- BehaviorContext* GetBehaviorContext() override { return nullptr; }
+ AZ::ComponentApplication* GetApplication() override { return nullptr; }
+ void RegisterComponentDescriptor(const AZ::ComponentDescriptor*) override { }
+ void UnregisterComponentDescriptor(const AZ::ComponentDescriptor*) override { }
+ void RegisterEntityAddedEventHandler(AZ::EntityAddedEvent::Handler&) override { }
+ void RegisterEntityRemovedEventHandler(AZ::EntityRemovedEvent::Handler&) override { }
+ void RegisterEntityActivatedEventHandler(AZ::EntityActivatedEvent::Handler&) override { }
+ void RegisterEntityDeactivatedEventHandler(AZ::EntityDeactivatedEvent::Handler&) override { }
+ void SignalEntityActivated(AZ::Entity*) override { }
+ void SignalEntityDeactivated(AZ::Entity*) override { }
+ bool AddEntity(AZ::Entity*) override { return false; }
+ bool RemoveEntity(AZ::Entity*) override { return false; }
+ bool DeleteEntity(const AZ::EntityId&) override { return false; }
+ Entity* FindEntity(const AZ::EntityId&) override { return nullptr; }
+ AZ::SerializeContext* GetSerializeContext() override { return m_context.get(); }
+ AZ::BehaviorContext* GetBehaviorContext() override { return nullptr; }
AZ::JsonRegistrationContext* GetJsonRegistrationContext() override { return m_jsonRegistrationContext.get(); }
const char* GetAppRoot() const override { return nullptr; }
const char* GetEngineRoot() const override { return nullptr; }
const char* GetExecutableFolder() const override { return nullptr; }
- Debug::DrillerManager* GetDrillerManager() override { return nullptr; }
- void EnumerateEntities(const EntityCallback& /*callback*/) override {}
+ AZ::Debug::DrillerManager* GetDrillerManager() override { return nullptr; }
+ void EnumerateEntities(const AZ::ComponentApplicationRequests::EntityCallback& /*callback*/) override {}
void QueryApplicationType(AZ::ApplicationTypeQuery& /*appType*/) const override {}
//////////////////////////////////////////////////////////////////////////
diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp
index e0b79e23aa..3497855c07 100644
--- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp
+++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp
@@ -120,13 +120,13 @@ namespace AZ
{
// stencil Srg
// Note: the stencil pass uses a slightly reduced inner AABB to avoid seams
- Vector3 innerExtentsReduced = m_innerExtents * m_transform.GetScale() - Vector3(0.1f, 0.1f, 0.1f);
+ Vector3 innerExtentsReduced = m_innerExtents - Vector3(0.1f, 0.1f, 0.1f);
Matrix3x4 modelToWorldStencil = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(innerExtentsReduced);
m_stencilSrg->SetConstant(m_reflectionRenderData->m_modelToWorldStencilConstantIndex, modelToWorldStencil);
m_stencilSrg->Compile();
// blend weight Srg
- Matrix3x4 modelToWorldOuter = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_outerExtents * m_transform.GetScale());
+ Matrix3x4 modelToWorldOuter = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_outerExtents);
m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldOuter);
m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter());
m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin());
@@ -149,7 +149,7 @@ namespace AZ
m_renderOuterSrg->Compile();
// render inner Srg
- Matrix3x4 modelToWorldInner = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_innerExtents * m_transform.GetScale());
+ Matrix3x4 modelToWorldInner = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_innerExtents);
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldInner);
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter());
m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin());
@@ -208,6 +208,12 @@ namespace AZ
void ReflectionProbe::SetTransform(const AZ::Transform& transform)
{
+ // retrieve previous scale and revert the scale on the inner/outer extents
+ AZ::Vector3 previousScale = m_transform.GetScale();
+ m_outerExtents /= previousScale;
+ m_innerExtents /= previousScale;
+
+ // store new transform
m_transform = transform;
// avoid scaling the visualization sphere
@@ -215,22 +221,26 @@ namespace AZ
visualizationTransform.ExtractScale();
m_meshFeatureProcessor->SetTransform(m_visualizationMeshHandle, visualizationTransform);
- m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents * m_transform.GetScale() / 2.0f);
- m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents * m_transform.GetScale() / 2.0f);
+ // update the inner/outer extents with the new scale
+ m_outerExtents *= m_transform.GetScale();
+ m_innerExtents *= m_transform.GetScale();
+
+ m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents / 2.0f);
+ m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents / 2.0f);
m_updateSrg = true;
}
void ReflectionProbe::SetOuterExtents(const AZ::Vector3& outerExtents)
{
- m_outerExtents = outerExtents;
- m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents * m_transform.GetScale() / 2.0f);
+ m_outerExtents = outerExtents * m_transform.GetScale();
+ m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents / 2.0f);
m_updateSrg = true;
}
void ReflectionProbe::SetInnerExtents(const AZ::Vector3& innerExtents)
{
- m_innerExtents = innerExtents;
- m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents * m_transform.GetScale() / 2.0f);
+ m_innerExtents = innerExtents * m_transform.GetScale();
+ m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents / 2.0f);
m_updateSrg = true;
}
diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h
index ab0e7a81d3..f062e0a42f 100644
--- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h
+++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h
@@ -78,10 +78,10 @@ namespace AZ
const Vector3& GetPosition() const { return m_transform.GetTranslation(); }
void SetTransform(const AZ::Transform& transform);
- AZ::Vector3 GetOuterExtents() const { return m_outerExtents * m_transform.GetScale(); }
+ const AZ::Vector3& GetOuterExtents() const { return m_outerExtents; }
void SetOuterExtents(const AZ::Vector3& outerExtents);
- AZ::Vector3 GetInnerExtents() const { return m_innerExtents * m_transform.GetScale(); }
+ const AZ::Vector3& GetInnerExtents() const { return m_innerExtents; }
void SetInnerExtents(const AZ::Vector3& innerExtents);
const Aabb& GetOuterAabbWs() const { return m_outerAabbWs; }
diff --git a/Gems/ImGui/External/ImGui/v1.82/imgui/imgui.cpp b/Gems/ImGui/External/ImGui/v1.82/imgui/imgui.cpp
index 2555d1a6af..c2db0da54a 100644
--- a/Gems/ImGui/External/ImGui/v1.82/imgui/imgui.cpp
+++ b/Gems/ImGui/External/ImGui/v1.82/imgui/imgui.cpp
@@ -7118,7 +7118,9 @@ static void ImGui::ErrorCheckEndFrameSanityChecks()
// We silently accommodate for this case by ignoring/ the case where all io.KeyXXX modifiers were released (aka key_mod_flags == 0),
// while still correctly asserting on mid-frame key press events.
const ImGuiKeyModFlags key_mod_flags = GetMergedKeyModFlags();
- IM_ASSERT((key_mod_flags == 0 || g.IO.KeyMods == key_mod_flags) && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
+
+ // [GFX TODO] Commented this line until Atom ImGuiPass is refactored (ATOM-15495).
+ // IM_ASSERT((key_mod_flags == 0 || g.IO.KeyMods == key_mod_flags) && "Mismatching io.KeyCtrl/io.KeyShift/io.KeyAlt/io.KeySuper vs io.KeyMods");
IM_UNUSED(key_mod_flags);
// Recover from errors
diff --git a/Gems/ImageProcessing/AssetProcessorGemConfig.setreg b/Gems/ImageProcessing/AssetProcessorGemConfig.setreg
deleted file mode 100644
index 17d9887fe8..0000000000
--- a/Gems/ImageProcessing/AssetProcessorGemConfig.setreg
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "Amazon": {
- "AssetProcessor": {
- "Settings": {}
- }
- }
-}
diff --git a/Gems/ImageProcessing/Assets/Editor/Backward.png b/Gems/ImageProcessing/Assets/Editor/Backward.png
deleted file mode 100644
index 82b3eafbd9..0000000000
--- a/Gems/ImageProcessing/Assets/Editor/Backward.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:1a1623477f4e2e5ef0440ecfc0c08e775d9b5f12d8ebc6b434e8212bf3445bcd
-size 224
diff --git a/Gems/ImageProcessing/Assets/Editor/Forward.png b/Gems/ImageProcessing/Assets/Editor/Forward.png
deleted file mode 100644
index a7a29a4c25..0000000000
--- a/Gems/ImageProcessing/Assets/Editor/Forward.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:31b247223c1116d4fc014189a9d8d86d4458b792c1120442673631136fd89520
-size 222
diff --git a/Gems/ImageProcessing/Assets/Editor/Resources.qrc b/Gems/ImageProcessing/Assets/Editor/Resources.qrc
deleted file mode 100644
index c309d19053..0000000000
--- a/Gems/ImageProcessing/Assets/Editor/Resources.qrc
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
- refresh-active.png
- warning.png
- refresh.png
- info.png
- Backward.png
- Forward.png
- reset.png
-
-
diff --git a/Gems/ImageProcessing/Assets/Editor/info.png b/Gems/ImageProcessing/Assets/Editor/info.png
deleted file mode 100644
index 002cf9c775..0000000000
--- a/Gems/ImageProcessing/Assets/Editor/info.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:3fec3caae92b9c9290c4157b3aeca29dcb366edd12719355e1d93dfb9d80cfed
-size 825
diff --git a/Gems/ImageProcessing/Assets/Editor/refresh-active.png b/Gems/ImageProcessing/Assets/Editor/refresh-active.png
deleted file mode 100644
index 33bc1c592a..0000000000
--- a/Gems/ImageProcessing/Assets/Editor/refresh-active.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:d29af2b69b74815c88352f85a7131384482e4f2d26ecf36581b46dede542fccb
-size 2973
diff --git a/Gems/ImageProcessing/Assets/Editor/refresh.png b/Gems/ImageProcessing/Assets/Editor/refresh.png
deleted file mode 100644
index fc9ef09987..0000000000
--- a/Gems/ImageProcessing/Assets/Editor/refresh.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:36591b457ee3519b16405d281674fcdd18645e3570bfc960a22b8f142ee99a14
-size 436
diff --git a/Gems/ImageProcessing/Assets/Editor/reset.png b/Gems/ImageProcessing/Assets/Editor/reset.png
deleted file mode 100644
index ed9c2f016d..0000000000
--- a/Gems/ImageProcessing/Assets/Editor/reset.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:0362da38d3804e2911130d138be4fd73040d66c8ac7d1b5f9f60c70037e8ca93
-size 1292
diff --git a/Gems/ImageProcessing/Assets/Editor/warning.png b/Gems/ImageProcessing/Assets/Editor/warning.png
deleted file mode 100644
index 6020245f86..0000000000
--- a/Gems/ImageProcessing/Assets/Editor/warning.png
+++ /dev/null
@@ -1,3 +0,0 @@
-version https://git-lfs.github.com/spec/v1
-oid sha256:cf5e987ea92164dcaa6deb88989aaac962bc092f5745274017f71224f48dbf7a
-size 651
diff --git a/Gems/ImageProcessing/CMakeLists.txt b/Gems/ImageProcessing/CMakeLists.txt
deleted file mode 100644
index 20a680bce9..0000000000
--- a/Gems/ImageProcessing/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-#
-# 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.
-#
-
-add_subdirectory(Code)
diff --git a/Gems/ImageProcessing/Code/CMakeLists.txt b/Gems/ImageProcessing/Code/CMakeLists.txt
deleted file mode 100644
index a5cb6f6cb9..0000000000
--- a/Gems/ImageProcessing/Code/CMakeLists.txt
+++ /dev/null
@@ -1,147 +0,0 @@
-#
-# 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.
-#
-
-ly_add_target(
- NAME ImageProcessing.Headers HEADERONLY
- NAMESPACE Gem
- FILES_CMAKE
- imageprocessing_headers_files.cmake
- INCLUDE_DIRECTORIES
- INTERFACE
- Include
-)
-
-if (NOT PAL_TRAIT_BUILD_HOST_TOOLS)
- return()
-endif()
-
-ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${PAL_PLATFORM_NAME})
-
-set(platform_tools_files)
-set(pal_tools_include_files)
-set(pal_tools_dirs)
-foreach(enabled_platform ${LY_PAL_TOOLS_ENABLED})
- string(TOLOWER ${enabled_platform} enabled_platform_lowercase)
- ly_get_list_relative_pal_filename(pal_tools_dir ${CMAKE_CURRENT_LIST_DIR}/Source/Platform/${enabled_platform})
- list(APPEND platform_tools_files ${pal_tools_dir}/pal_tools_${enabled_platform_lowercase}.cmake)
- list(APPEND pal_tools_include_files ${pal_tools_dir}/pal_tools_${enabled_platform_lowercase}_files.cmake)
- list(APPEND pal_tools_dirs ${pal_tools_dir})
-endforeach()
-
-ly_add_target(
- NAME ImageProcessing.Static STATIC
- NAMESPACE Gem
- AUTOMOC
- AUTOUIC
- FILES_CMAKE
- imageprocessing_static_files.cmake
- ${pal_tools_include_files}
- ${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
- PLATFORM_INCLUDE_FILES
- ${pal_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}.cmake
- ${platform_tools_files}
- INCLUDE_DIRECTORIES
- PRIVATE
- .
- Source
- ../External
- ${pal_dir}
- ${pal_tools_dirs}
- PUBLIC
- Include
- BUILD_DEPENDENCIES
- PRIVATE
- 3rdParty::Qt::Core
- 3rdParty::Qt::Widgets
- 3rdParty::etc2comp
- 3rdParty::PVRTexTool
- 3rdParty::squish-ccr
- 3rdParty::zlib
- 3rdParty::tiff
- Legacy::CryCommon
- AZ::AzCore
- AZ::AssetBuilderSDK
- Gem::TextureAtlas
-)
-ly_add_source_properties(
- SOURCES
- Source/BuilderSettings/BuilderSettingManager.cpp
- Source/Processing/ImageConvert.cpp
- PROPERTY COMPILE_DEFINITIONS
- VALUES ${LY_PAL_TOOLS_DEFINES}
-)
-
-ly_add_target(
- NAME ImageProcessing.Editor GEM_MODULE
-
- NAMESPACE Gem
- AUTOMOC
- AUTORCC
- FILES_CMAKE
- imageprocessing_files.cmake
- PLATFORM_INCLUDE_FILES
- ${platform_tools_files}
- INCLUDE_DIRECTORIES
- PRIVATE
- .
- Source
- ${pal_dir}
- PUBLIC
- Include
- BUILD_DEPENDENCIES
- PRIVATE
- 3rdParty::Qt::Widgets
- 3rdParty::PVRTexTool
- 3rdParty::squish-ccr
- Legacy::CryCommon
- AZ::AzCore
- AZ::AzToolsFramework
- AZ::AssetBuilderSDK
- Gem::ImageProcessing.Static
- Gem::TextureAtlas
- RUNTIME_DEPENDENCIES
- 3rdParty::ASTCEncoder
- Gem::TextureAtlas
-)
-
-if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
- ly_add_target(
- NAME ImageProcessing.Tests ${PAL_TRAIT_TEST_TARGET_TYPE}
- NAMESPACE Gem
- FILES_CMAKE
- imageprocessing_tests_files.cmake
- INCLUDE_DIRECTORIES
- PRIVATE
- Tests
- .
- Source
- ${pal_dir}
- BUILD_DEPENDENCIES
- PRIVATE
- AZ::AzTest
- 3rdParty::Qt::Widgets
- Legacy::CryCommon
- AZ::AssetBuilderSDK
- Gem::ImageProcessing.Static
- Gem::ImageProcessing.Editor
- Gem::TextureAtlas
- )
- ly_add_googletest(
- NAME Gem::ImageProcessing.Tests
- )
-
- ly_add_source_properties(
- SOURCES Tests/ImageProcessing_Test.cpp
- PROPERTY COMPILE_DEFINITIONS
- VALUES ${LY_PAL_TOOLS_DEFINES}
- )
-
-endif()
diff --git a/Gems/ImageProcessing/Code/Include/ImageProcessing/ImageObject.h b/Gems/ImageProcessing/Code/Include/ImageProcessing/ImageObject.h
deleted file mode 100644
index baa6613daf..0000000000
--- a/Gems/ImageProcessing/Code/Include/ImageProcessing/ImageObject.h
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
-* 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.
-*
-*/
-
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-namespace AZ
-{
- namespace IO
- {
- class SystemFileStream;
- }
-}
-
-namespace ImageProcessing
-{
- class IImageObject;
- class TextureSettings;
- typedef AZStd::shared_ptr IImageObjectPtr;
-
- enum class EAlphaContent
- {
- eAlphaContent_Indeterminate, // the format may have alpha, but can't be calculated
- eAlphaContent_Absent, // the format has no alpha
- eAlphaContent_OnlyWhite, // alpha contains just white
- eAlphaContent_OnlyBlack, // alpha contains just black
- eAlphaContent_OnlyBlackAndWhite, // alpha contains just black and white
- eAlphaContent_Greyscale // alpha contains grey tones
- };
-
- //interface for image object. The image object may have mipmaps.
- class IImageObject
- {
- public:
- //static functions
- static IImageObject* CreateImage(AZ::u32 width, AZ::u32 height, AZ::u32 maxMipCount, EPixelFormat pixelFormat);
-
- virtual ~IImageObject() {};
- public:
- //creating new image object outof this image object
- virtual IImageObject* Clone() const = 0;
- // allocate an empty image object with requested format and same properties with current image
- virtual IImageObject* AllocateImage(EPixelFormat pixelFormat) const = 0;
- virtual IImageObject* AllocateImage() const = 0;
-
- //get pixel format
- virtual EPixelFormat GetPixelFormat() const = 0;
-
- virtual AZ::u32 GetPixelCount(AZ::u32 mip) const = 0;
- virtual AZ::u32 GetWidth(AZ::u32 mip) const = 0;
- virtual AZ::u32 GetHeight(AZ::u32 mip) const = 0;
- virtual bool IsCubemap() const = 0;
- virtual AZ::u32 GetMipCount() const = 0;
-
- //get pixel data buffer
- virtual void GetImagePointer(AZ::u32 mip, AZ::u8*& pMem, AZ::u32& pitch) const = 0;
- virtual AZ::u32 GetMipBufSize(AZ::u32 mip) const = 0;
- virtual void SetMipData(AZ::u32 mip, AZ::u8* mipBuf, AZ::u32 bufSize, AZ::u32 pitch) = 0;
-
- //get/set image flags
- virtual AZ::u32 GetImageFlags() const = 0;
- virtual void SetImageFlags(AZ::u32 imageFlags) = 0;
- virtual void AddImageFlags(AZ::u32 imageFlags) = 0;
- virtual void RemoveImageFlags(AZ::u32 imageFlags) = 0;
- virtual bool HasImageFlags(AZ::u32 imageFlags) const = 0;
-
- // image data operations and calculation
- // Calculates "(pixel.rgba * scale) + bias"
- virtual void ScaleAndBiasChannels(AZ::u32 firstMip, AZ::u32 maxMipCount, const AZ::Vector4& scale, const AZ::Vector4& bias) = 0;
- // Calculates "clamp(pixel.rgba, min, max)"
- virtual void ClampChannels(AZ::u32 firstMip, AZ::u32 maxMipCount, const AZ::Vector4& min, const AZ::Vector4& max) = 0;
-
- //transfer alpha coverage from source image
- virtual void TransferAlphaCoverage(const TextureSettings* textureSetting, const IImageObjectPtr srcImg) = 0;
- // Routines to measure and manipulate alpha coverage
- virtual float ComputeAlphaCoverageScaleFactor(AZ::u32 mip, float fDesiredCoverage, float fAlphaRef) const = 0;
- virtual float ComputeAlphaCoverage(AZ::u32 mip, float fAlphaRef) const = 0;
-
- //helper functions
- //compare whether two images are same. return true if they are same.
- virtual bool CompareImage(const IImageObjectPtr otherImage) const = 0;
-
- // Writes this image to file used for runtime, overwrites any existing file.
- // It may write alpha image as attached image into the same file
- // outFilePaths will save filenames finally saved to since the image might be split and saved to multiple files
- virtual bool SaveImage(const char* filename, IImageObjectPtr alphaImage, AZStd::vector& outFilePaths) const = 0;
- virtual bool SaveImage(AZ::IO::SystemFileStream& out) const = 0;
- virtual bool SaveMipToFile(AZ::u32 mip, const AZStd::string& filename) const = 0;
-
- //get total image data size in memory of all mipmaps. Not includs header and flags.
- virtual AZ::u32 GetTextureMemory() const = 0;
-
- //identify content of the alpha channel
- virtual EAlphaContent GetAlphaContent() const = 0;
-
- //normalize rgb channel for specified mips
- virtual void NormalizeVectors(AZ::u32 firstMip, AZ::u32 maxMipCount) = 0;
-
- // use when you convert an image to another one
- virtual void CopyPropertiesFrom(const IImageObjectPtr src) = 0;
-
- //swizzle data for source channels to dest channels
- virtual void Swizzle(const char channels[4]) = 0;
-
- //get/set properties of the image object
- virtual void GetColorRange(AZ::Color& minColor, AZ::Color& maxColor) const = 0;
- virtual void SetColorRange(const AZ::Color& minColor, const AZ::Color& maxColor) = 0;
- virtual AZ::u32 GetNumPersistentMips() const = 0;
- virtual void SetNumPersistentMips(AZ::u32 nMips) = 0;
- virtual float GetAverageBrightness() const = 0;
- virtual void SetAverageBrightness(float avgBrightness) = 0;
-
- // Derive new roughness from normal variance to preserve the bumpiness of normal map mips and to reduce specular aliasing.
- // The derived roughness is combined with the artist authored roughness stored in the alpha channel of the normal map.
- // The algorithm is based on the Frequency Domain Normal Mapping implementation presented by Neubelt and Pettineo at Siggraph 2013.
- virtual void GlossFromNormals(bool hasAuthoredGloss) = 0;
-
- //convert gloss map from legacy distribution to new one. New World is still using legacy gloss map.
- virtual void ConvertLegacyGloss() = 0;
-
- //clear image with color
- virtual void ClearColor(float r, float g, float b, float a) = 0;
-
- virtual bool HasPowerOfTwoSizes() const = 0;
- };
-
- //loading function to load output dds file to a IImageObject
- IImageObject* LoadImageFromDdsFile(const AZStd::string& filename);
- IImageObject* LoadImageFromDdsFile(AZ::IO::SystemFileStream& fileLoadStream);
- IImageObject* LoadAttachedImageFromDdsFile(const AZStd::string& filename, IImageObjectPtr originImage);
-
-} // namespace ImageProcessing
diff --git a/Gems/ImageProcessing/Code/Include/ImageProcessing/ImageProcessingBus.h b/Gems/ImageProcessing/Code/Include/ImageProcessing/ImageProcessingBus.h
deleted file mode 100644
index 8b127b3f6e..0000000000
--- a/Gems/ImageProcessing/Code/Include/ImageProcessing/ImageProcessingBus.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-* 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.
-*
-*/
-
-#pragma once
-
-#include
-#include
-
-namespace ImageProcessing
-{
- class ImageProcessingRequests
- : public AZ::EBusTraits
- {
- public:
- //////////////////////////////////////////////////////////////////////////
- // EBusTraits overrides
- static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
- static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
- //////////////////////////////////////////////////////////////////////////
-
- // Loads an image from a source file path
- virtual IImageObjectPtr LoadImage(const AZStd::string& filePath) = 0;
-
- // Loads an image from a source file path and converts it to a format suitable for previewing in tools
- virtual IImageObjectPtr LoadImagePreview(const AZStd::string& filePath) = 0;
- };
- using ImageProcessingRequestBus = AZ::EBus;
-} // namespace ImageProcessing
diff --git a/Gems/ImageProcessing/Code/Include/ImageProcessing/ImageProcessingEditorBus.h b/Gems/ImageProcessing/Code/Include/ImageProcessing/ImageProcessingEditorBus.h
deleted file mode 100644
index eae1fdeb6d..0000000000
--- a/Gems/ImageProcessing/Code/Include/ImageProcessing/ImageProcessingEditorBus.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
-* 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.
-*
-*/
-#pragma once
-
-#include
-
-class QString;
-
-namespace ImageProcessingEditor
-{
- class ImageProcessingEditorRequests
- : public AZ::EBusTraits
- {
- public:
- //////////////////////////////////////////////////////////////////////////
- // EBusTraits overrides
- static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
- static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
- /////////////////////////////////////////////////////////////////////////
-
- //! Open single texture file
- virtual void OpenSourceTextureFile(const AZ::Uuid& textureSourceID) = 0;
- };
-
- using ImageProcessingEditorRequestBus = AZ::EBus;
-}//namespace ImageProcessingEditor
-
diff --git a/Gems/ImageProcessing/Code/Include/ImageProcessing/PixelFormats.h b/Gems/ImageProcessing/Code/Include/ImageProcessing/PixelFormats.h
deleted file mode 100644
index 2ceb889ac9..0000000000
--- a/Gems/ImageProcessing/Code/Include/ImageProcessing/PixelFormats.h
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
-* 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.
-*
-*/
-#pragma once
-
-namespace ImageProcessing
-{
- enum EPixelFormat : int
- {
- //unsigned formats
- ePixelFormat_R8G8B8A8 = 0,
- ePixelFormat_R8G8B8X8,
- ePixelFormat_R8G8,
- ePixelFormat_R8,
- ePixelFormat_A8,
- ePixelFormat_R16G16B16A16,
- ePixelFormat_R16G16,
- ePixelFormat_R16,
-
- //Custom FourCC Formats
- // Data in these FourCC formats is custom compressed data and only decodable by certain hardware.
- //ASTC formats supported by ios devices with A8 processor. Also supported by Android Extension Pack.
- ePixelFormat_ASTC_4x4,
- ePixelFormat_ASTC_5x4,
- ePixelFormat_ASTC_5x5,
- ePixelFormat_ASTC_6x5,
- ePixelFormat_ASTC_6x6,
- ePixelFormat_ASTC_8x5,
- ePixelFormat_ASTC_8x6,
- ePixelFormat_ASTC_8x8,
- ePixelFormat_ASTC_10x5,
- ePixelFormat_ASTC_10x6,
- ePixelFormat_ASTC_10x8,
- ePixelFormat_ASTC_10x10,
- ePixelFormat_ASTC_12x10,
- ePixelFormat_ASTC_12x12,
- //Formats supported by PowerVR GPU. Mainly for ios devices.
- ePixelFormat_PVRTC2, //2bpp
- ePixelFormat_PVRTC4, //4bpp
- //formats for opengl and opengles 3.0 (android devices)
- ePixelFormat_EAC_R11, //one channel unsigned data
- ePixelFormat_EAC_RG11, //two channel unsigned data
- ePixelFormat_ETC2, //Compresses RGB888 data, it taks 4x4 groups of pixel data and compresses each into a 64-bit
- ePixelFormat_ETC2a, //Compresses RGBA8888 data with full alpha support
-
- // Standardized Compressed DXGI Formats (DX10+)
- // Data in these compressed formats is hardware decodable on all DX10 chips, and manageable with the DX10-API.
- ePixelFormat_BC1, // RGB without alpha, 0.5 byte/px
- ePixelFormat_BC1a, // RGB with 1 bit of alpha, 0.5 byte/px.
- ePixelFormat_BC3, // RGBA 1 byte/px, color maps with full alpha.
- ePixelFormat_BC3t, // BC3 with alpha weighted color
- ePixelFormat_BC4, // One color channel, 0.5 byte/px, unsigned
- ePixelFormat_BC4s, // BC4, signed
- ePixelFormat_BC5, // Two color channels, 1 byte/px, unsigned. Usually use for tangent-space normal maps
- ePixelFormat_BC5s, // BC5, signed
- ePixelFormat_BC6UH, // RGB, floating-point. Used for HDR images. Decompress to RGB in half floating point
- ePixelFormat_BC7, // RGB or RGBA. 1 byte/px. Three color channels (4 to 7 bits per channel) with 0 to 8 bits of alpha
- ePixelFormat_BC7t, // BC& with alpha weighted color
-
- // Float formats
- // Data in a Float format is floating point data.
- ePixelFormat_R9G9B9E5,
- ePixelFormat_R32G32B32A32F,
- ePixelFormat_R32G32F,
- ePixelFormat_R32F,
- ePixelFormat_R16G16B16A16F,
- ePixelFormat_R16G16F,
- ePixelFormat_R16F,
-
- //legacy format. Only used to load old converted dds files.
- ePixelFormat_B8G8R8A8, //32bits rgba format
-
- ePixelFormat_R32,
-
- ePixelFormat_Count,
- ePixelFormat_Unknown = ePixelFormat_Count
- };
-
- inline bool IsASTCFormat(EPixelFormat fmt)
- {
- return fmt == ePixelFormat_ASTC_4x4 || fmt == ePixelFormat_ASTC_5x4 || fmt == ePixelFormat_ASTC_5x5 ||
- fmt == ePixelFormat_ASTC_6x5 || fmt == ePixelFormat_ASTC_6x6 || fmt == ePixelFormat_ASTC_8x5 ||
- fmt == ePixelFormat_ASTC_8x6 || fmt == ePixelFormat_ASTC_8x8 || fmt == ePixelFormat_ASTC_10x5 ||
- fmt == ePixelFormat_ASTC_10x6 || fmt == ePixelFormat_ASTC_10x8 || fmt == ePixelFormat_ASTC_10x10 ||
- fmt == ePixelFormat_ASTC_12x10 || fmt == ePixelFormat_ASTC_12x12;
- }
-
- inline bool IsETCFormat(EPixelFormat fmt)
- {
- return fmt == ePixelFormat_ETC2 || fmt == ePixelFormat_ETC2a || fmt == ePixelFormat_EAC_R11 ||
- fmt == ePixelFormat_EAC_RG11;
- }
-
- inline bool IsPVRTCFormat(EPixelFormat fmt)
- {
- return fmt == ePixelFormat_PVRTC2 || fmt == ePixelFormat_PVRTC4;
- }
-
-} // namespace ImageProcessing
diff --git a/Gems/ImageProcessing/Code/Source/AtlasBuilder/AtlasBuilderComponent.cpp b/Gems/ImageProcessing/Code/Source/AtlasBuilder/AtlasBuilderComponent.cpp
deleted file mode 100644
index e8d4948cc9..0000000000
--- a/Gems/ImageProcessing/Code/Source/AtlasBuilder/AtlasBuilderComponent.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
-* 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 "ImageProcessing_precompiled.h"
-#include "AtlasBuilderComponent.h"
-
-#include
-
-namespace TextureAtlasBuilder
-{
- // AZ Components should only initialize their members to null and empty in constructor
- // Allocation of data should occur in Init(), once we can guarantee reflection and registration of types
- AtlasBuilderComponent::AtlasBuilderComponent()
- {
- }
-
- // Handle deallocation of your memory allocated in Init()
- AtlasBuilderComponent::~AtlasBuilderComponent()
- {
- }
-
- // Init is where you'll actually allocate memory or create objects
- // This ensures that any dependency components will have been been created and serialized
- void AtlasBuilderComponent::Init()
- {
- }
-
- // Activate is where you'd perform registration with other objects and systems.
- // All builder classes owned by this component should be registered here
- // Any EBuses for the builder classes should also be connected at this point
- void AtlasBuilderComponent::Activate()
- {
- AssetBuilderSDK::AssetBuilderDesc builderDescriptor;
- builderDescriptor.m_name = "Atlas Worker Builder";
- builderDescriptor.m_version = 1;
- builderDescriptor.m_patterns.emplace_back(AssetBuilderSDK::AssetBuilderPattern("*.texatlas", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
- builderDescriptor.m_busId = azrtti_typeid();
- builderDescriptor.m_createJobFunction = AZStd::bind(&AtlasBuilderWorker::CreateJobs, &m_atlasBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);
- builderDescriptor.m_processJobFunction = AZStd::bind(&AtlasBuilderWorker::ProcessJob, &m_atlasBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2);
-
- m_atlasBuilder.BusConnect(builderDescriptor.m_busId);
-
- AssetBuilderSDK::AssetBuilderBus::Broadcast(&AssetBuilderSDK::AssetBuilderBusTraits::RegisterBuilderInformation, builderDescriptor);
- }
-
- // Disconnects from any EBuses we connected to in Activate()
- // Unregisters from objects and systems we register with in Activate()
- void AtlasBuilderComponent::Deactivate()
- {
- m_atlasBuilder.BusDisconnect();
-
- // We don't need to unregister the builder - the AP will handle this for us, because it is managing the lifecycle of this component
- }
-
- // Reflect the input and output formats for the serializer
- void AtlasBuilderComponent::Reflect(AZ::ReflectContext* context)
- {
- // components also get Reflect called automatically
- // this is your opportunity to perform static reflection or type registration of any types you want the serializer to know about
- if (AZ::SerializeContext* serialize = azrtti_cast(context))
- {
- serialize->Class()
- ->Version(0)
- ->Attribute(AZ::Edit::Attributes::SystemComponentTags, AZStd::vector({ AssetBuilderSDK::ComponentTags::AssetBuilder }))
- ;
- }
-
- AtlasBuilderInput::Reflect(context);
- }
-
- void AtlasBuilderComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
- {
- provided.push_back(AZ_CRC("Atlas Builder Plugin Service", 0x35974d0d));
- }
-
- void AtlasBuilderComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
- {
- incompatible.push_back(AZ_CRC("Atlas Builder Plugin Service", 0x35974d0d));
- }
-
- void AtlasBuilderComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
- {
- AZ_UNUSED(required);
- }
-
- void AtlasBuilderComponent::GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent)
- {
- AZ_UNUSED(dependent);
- }
-}
diff --git a/Gems/ImageProcessing/Code/Source/AtlasBuilder/AtlasBuilderComponent.h b/Gems/ImageProcessing/Code/Source/AtlasBuilder/AtlasBuilderComponent.h
deleted file mode 100644
index eb8b85dfcf..0000000000
--- a/Gems/ImageProcessing/Code/Source/AtlasBuilder/AtlasBuilderComponent.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * 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.
- *
- */
-
-#pragma once
-
-#include
-#include
-#include "AtlasBuilderWorker.h"
-
-namespace TextureAtlasBuilder
-{
- class AtlasBuilderComponent : public AZ::Component
- {
- public:
- AZ_COMPONENT(AtlasBuilderComponent, "{F49987FB-3375-4417-AB83-97B44C78B335}");
-
- AtlasBuilderComponent();
- ~AtlasBuilderComponent() override;
-
- void Init() override;
- void Activate() override;
- void Deactivate() override;
-
- //! Reflect formats for input and output
- static void Reflect(AZ::ReflectContext* context);
-
- static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
- static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
- static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
- static void GetDependentServices(AZ::ComponentDescriptor::DependencyArrayType& dependent);
-
- private:
- AtlasBuilderWorker m_atlasBuilder;
- };
-} // namespace TextureAtlasBuilder
diff --git a/Gems/ImageProcessing/Code/Source/AtlasBuilder/AtlasBuilderWorker.cpp b/Gems/ImageProcessing/Code/Source/AtlasBuilder/AtlasBuilderWorker.cpp
deleted file mode 100644
index 95cc9b851f..0000000000
--- a/Gems/ImageProcessing/Code/Source/AtlasBuilder/AtlasBuilderWorker.cpp
+++ /dev/null
@@ -1,1494 +0,0 @@
-/*
-* 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 "ImageProcessing_precompiled.h"
-#include "AtlasBuilderWorker.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-namespace TextureAtlasBuilder
-{
- //! Counts leading zeros
- uint32 CountLeadingZeros32(uint32 x)
- {
- return x == 0 ? 32 : az_clz_u32(x);
- }
-
- //! Integer log2
- uint32 IntegerLog2(uint32 x)
- {
- return 31 - CountLeadingZeros32(x);
- }
-
- bool IsFolderPath(const AZStd::string& path)
- {
- bool hasExtension = AzFramework::StringFunc::Path::HasExtension(path.c_str());
- return !hasExtension;
- }
-
- bool HasTrailingSlash(const AZStd::string& path)
- {
- size_t pathLength = path.size();
- return (pathLength > 0 && (path.at(pathLength - 1) == '/' || path.at(pathLength - 1) == '\\'));
- }
-
- bool ResolveRelativePath(const AZStd::string& relativePath, const AZStd::string& watchDirectory, AZStd::string& resolvedFullPathOut)
- {
- // Get full path by appending the relative path to the watch directory
- AZ::IO::FixedMaxPath resolvedPath;
- AZ::IO::FileIOBase::GetInstance()->ReplaceAlias(resolvedPath, AZ::IO::PathView{relativePath});
-
- resolvedPath = (AZ::IO::FixedMaxPath{watchDirectory} / resolvedPath).LexicallyNormal();
- resolvedFullPathOut = resolvedPath.String();
-
- return true;
- }
-
- bool GetAbsoluteSourcePathFromRelativePath(const AZStd::string& relativeSourcePath, AZStd::string& absoluteSourcePathOut)
- {
- bool result = false;
- AZ::Data::AssetInfo info;
- AZStd::string watchFolder;
- AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, relativeSourcePath.c_str(), info, watchFolder);
- if (result)
- {
- absoluteSourcePathOut = AZStd::string::format("%s/%s", watchFolder.c_str(), info.m_relativePath.c_str());
-
- // Normalize path
- AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::NormalizePathKeepCase, absoluteSourcePathOut);
- }
- return result;
- }
-
- const ImageProcessing::PresetSettings* GetImageProcessPresetSettings(const AZStd::string& presetName, const AZStd::string& platformIdentifier)
- {
- // Get the specified presetId
- AZ::Uuid presetId = ImageProcessing::BuilderSettingManager::Instance()->GetPresetIdFromName(presetName);
- if (presetId.IsNull())
- {
- AZ_Error("Texture Editor", false, "Texture Preset %s has no associated UUID.", presetName.c_str());
- return nullptr;
- }
-
- // Get the preset settings for the platform this job is building for
- const ImageProcessing::PresetSettings* presetSettings = ImageProcessing::BuilderSettingManager::Instance()->GetPreset(
- presetId, platformIdentifier);
-
- return presetSettings;
- }
-
- // Reflect the input parameters
- void AtlasBuilderInput::Reflect(AZ::ReflectContext* context)
- {
- if (AZ::SerializeContext* serialize = azrtti_cast(context))
- {
- serialize->Class()
- ->Version(1)
- ->Field("Force Square", &AtlasBuilderInput::m_forceSquare)
- ->Field("Force Power of Two", &AtlasBuilderInput::m_forcePowerOf2)
- ->Field("Include White Texture", &AtlasBuilderInput::m_includeWhiteTexture)
- ->Field("Maximum Dimension", &AtlasBuilderInput::m_maxDimension)
- ->Field("Padding", &AtlasBuilderInput::m_padding)
- ->Field("UnusedColor", &AtlasBuilderInput::m_unusedColor)
- ->Field("PresetName", &AtlasBuilderInput::m_presetName)
- ->Field("Textures to Add", &AtlasBuilderInput::m_filePaths);
- }
- }
-
- // Supports a custom parser format
- AtlasBuilderInput AtlasBuilderInput::ReadFromFile(const AZStd::string& path, const AZStd::string& directory, bool& valid)
- {
- // Open the file
- AZ::IO::FileIOBase* input = AZ::IO::FileIOBase::GetInstance();
- AZ::IO::HandleType handle;
- input->Open(path.c_str(), AZ::IO::OpenMode::ModeRead, handle);
-
- // Read the file
- AZ::u64 size;
- input->Size(handle, size);
- char* buffer = new char[size + 1];
- input->Read(handle, buffer, size);
- buffer[size] = 0;
-
- // Close the file
- input->Close(handle);
-
- // Prepare the output
- AtlasBuilderInput data;
-
- // Parse the input into lines
- AZStd::vector lines;
- AzFramework::StringFunc::Tokenize(buffer, lines, "\n\t");
- delete[] buffer;
-
- // Parse the individual lines
- for (auto line : lines)
- {
- line = AzFramework::StringFunc::TrimWhiteSpace(line, true, true);
- // Check for comments and empty lines
- if ((line.length() >= 2 && line[0] == '/' && line[1] == '/') || line.length() < 1)
- {
- continue;
- }
- else if (line.find('=') != -1)
- {
- AZStd::vector args;
- AzFramework::StringFunc::Tokenize(line.c_str(), args, '=', true, true);
-
- if (args.size() > 2)
- {
- AZ_Error("AtlasBuilder", false, AZStd::string::format("Atlas Builder unable to parse line: Excessive '=' symbols were found: \"%s\"", line.c_str()).c_str());
- valid = false;
- }
-
- // Trim whitespace
- args[0] = AzFramework::StringFunc::TrimWhiteSpace(args[0], true, true);
- args[1] = AzFramework::StringFunc::TrimWhiteSpace(args[1], true, true);
-
- // No case sensitivity for property names
- AZStd::to_lower(args[0].begin(), args[0].end());
-
- // Keep track of if the value is rejected
- bool accepted = false;
-
- if (args[0] == "square")
- {
- accepted = AzFramework::StringFunc::LooksLikeBool(args[1].c_str());
- if (accepted)
- {
- data.m_forceSquare = AzFramework::StringFunc::ToBool(args[1].c_str());
- }
- }
- else if (args[0] == "poweroftwo")
- {
- accepted = AzFramework::StringFunc::LooksLikeBool(args[1].c_str());
- if (accepted)
- {
- data.m_forcePowerOf2 = AzFramework::StringFunc::ToBool(args[1].c_str());
- }
- }
- else if (args[0] == "whitetexture")
- {
- accepted = AzFramework::StringFunc::LooksLikeBool(args[1].c_str());
- if (accepted)
- {
- data.m_includeWhiteTexture = AzFramework::StringFunc::ToBool(args[1].c_str());
- }
- }
- else if (args[0] == "maxdimension")
- {
- accepted = AzFramework::StringFunc::LooksLikeInt(args[1].c_str());
- if (accepted)
- {
- data.m_maxDimension = AzFramework::StringFunc::ToInt(args[1].c_str());
- }
- }
- else if (args[0] == "padding")
- {
- accepted = AzFramework::StringFunc::LooksLikeInt(args[1].c_str());
- if (accepted)
- {
- data.m_padding = AzFramework::StringFunc::ToInt(args[1].c_str());
- }
- }
- else if (args[0] == "unusedcolor")
- {
- accepted = args[1].at(0) == '#' && args[1].length() == 9;
- if (accepted)
- {
- AZStd::string color = AZStd::string::format("%s%s%s%s", args[1].substr(7).c_str(), args[1].substr(5, 2).c_str(),
- args[1].substr(3, 2).c_str(), args[1].substr(1, 2).c_str());
- data.m_unusedColor.FromU32(AZStd::stoul(color, nullptr, 16));
- }
- }
- else if (args[0] == "presetname")
- {
- accepted = true;
- data.m_presetName = args[1];
- }
- else
- {
- // Supress accepted error because this error superceeds it
- accepted = true;
- valid = false;
- AZ_Error("AtlasBuilder", false, AZStd::string::format("Atlas Builder unable to parse line: Unrecognized property: \"%s\"", args[0].c_str()).c_str());
- }
-
- // If the property is recognized but the value is rejected, fail the job
- if (!accepted)
- {
- valid = false;
- AZ_Error("AtlasBuilder", false, AZStd::string::format("Atlas Builder unable to parse line: Invalid value assigned to property: Property: \"%s\" Value: \"%s\"", args[0].c_str(), args[1].c_str()).c_str());
- }
- }
- else if ((line[0] == '-'))
- {
- // Remove image files
- AZStd::string remove = line.substr(1);
- remove = AzFramework::StringFunc::TrimWhiteSpace(remove, true, true);
- if (remove.find('*') != -1)
- {
- AZStd::string resolvedAbsolutePath;
- bool resolved = ResolveRelativePath(remove, directory, resolvedAbsolutePath);
- if (resolved)
- {
- RemoveFilesUsingWildCard(data.m_filePaths, resolvedAbsolutePath);
- }
- else
- {
- valid = false;
- AZ_Error("AtlasBuilder", false, AZStd::string::format("Atlas Builder unable to resolve relative path: %s", remove.c_str()).c_str());
- }
- }
- else if (IsFolderPath(remove))
- {
- AZStd::string resolvedAbsolutePath;
- bool resolved = ResolveRelativePath(remove, directory, resolvedAbsolutePath);
- if (resolved)
- {
- RemoveFolderContents(data.m_filePaths, resolvedAbsolutePath);
- }
- else
- {
- valid = false;
- AZ_Error("AtlasBuilder", false, AZStd::string::format("Atlas Builder unable to resolve relative path: %s", remove.c_str()).c_str());
- }
- }
- else
- {
- // Get the full path to the source image from the relative source path
- AZStd::string fullSourceAssetPathName;
- bool fullPathFound = GetAbsoluteSourcePathFromRelativePath(remove, fullSourceAssetPathName);
-
- if (!fullPathFound)
- {
- // Try to resolve relative path as it might be using "./" or "../"
- fullPathFound = ResolveRelativePath(remove, directory, fullSourceAssetPathName);
- }
-
- if (fullPathFound)
- {
- for (size_t i = 0; i < data.m_filePaths.size(); ++i)
- {
- if (data.m_filePaths[i] == fullSourceAssetPathName)
- {
- data.m_filePaths.erase(data.m_filePaths.begin() + i);
- }
- }
- }
- else
- {
- valid = false;
- AZ_Error("AtlasBuilder", false, AZStd::string::format("Atlas Builder unable to get source asset path for image: %s", remove.c_str()).c_str());
- }
- }
- }
- else
- {
- // Add image files
- AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::NormalizePathKeepCase, line);
- bool duplicate = false;
- if (line.find('*') != -1)
- {
- AZStd::string resolvedAbsolutePath;
- bool resolved = ResolveRelativePath(line, directory, resolvedAbsolutePath);
- if (resolved)
- {
- AddFilesUsingWildCard(data.m_filePaths, resolvedAbsolutePath);
- }
- else
- {
- valid = false;
- AZ_Error("AtlasBuilder", false, AZStd::string::format("Atlas Builder unable to resolve relative path: %s", line.c_str()).c_str());
- }
- }
- else if (IsFolderPath(line))
- {
- AZStd::string resolvedAbsolutePath;
- bool resolved = ResolveRelativePath(line, directory, resolvedAbsolutePath);
- if (resolved)
- {
- AddFolderContents(data.m_filePaths, resolvedAbsolutePath, valid);
- }
- else
- {
- valid = false;
- AZ_Error("AtlasBuilder", false, AZStd::string::format("Atlas Builder unable to resolve relative path: %s", line.c_str()).c_str());
- }
- }
- else
- {
- // Get the full path to the source image from the relative source path
- AZStd::string fullSourceAssetPathName;
- bool fullPathFound = GetAbsoluteSourcePathFromRelativePath(line, fullSourceAssetPathName);
-
- if (!fullPathFound)
- {
- // Try to resolve relative path as it might be using "./" or "../"
- fullPathFound = ResolveRelativePath(line, directory, fullSourceAssetPathName);
- }
-
- if (fullPathFound)
- {
- // Prevent duplicates
- for (size_t i = 0; i < data.m_filePaths.size() && !duplicate; ++i)
- {
- duplicate = data.m_filePaths[i] == fullSourceAssetPathName;
- }
- if (!duplicate)
- {
- data.m_filePaths.push_back(fullSourceAssetPathName);
- }
- }
- else
- {
- valid = false;
- AZ_Error("AtlasBuilder", false, AZStd::string::format("Atlas Builder unable to get source asset path for image: %s", line.c_str()).c_str());
- }
- }
- }
- }
-
- return data;
- }
-
- void AtlasBuilderInput::AddFilesUsingWildCard(AZStd::vector& paths, const AZStd::string& insert)
- {
- AZ::IO::PathView fullPathView(insert);
-
- // Find first path element with a wild card in it
- AZ::IO::Path staticPath;
- auto wildCardPathElementIter = fullPathView.begin();
- for (; wildCardPathElementIter != fullPathView.end(); ++wildCardPathElementIter)
- {
- if (wildCardPathElementIter->Native().contains('*'))
- {
- break;
- }
- staticPath /= *wildCardPathElementIter;
- }
-
- // The remaining path segments are part of the wild card path
-
- AZStd::vector candidates{ AZStd::move(staticPath) };
- for(; wildCardPathElementIter != fullPathView.end() && !candidates.empty(); ++wildCardPathElementIter)
- {
- AZStd::vector nextCandidates;
- for (const AZ::IO::Path& candidate : candidates)
- {
- if (QDir inputFolder(QString::fromUtf8(candidate.c_str(), aznumeric_cast(candidate.Native().size())));
- inputFolder.exists())
- {
- QFileInfoList entries = inputFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files);
- for (const QFileInfo& entry : entries)
- {
- AZ::IO::Path filenameEntry(entry.fileName().toUtf8().data());
- if (filenameEntry.Match(wildCardPathElementIter->Native()))
- {
- nextCandidates.push_back(entry.filePath().toUtf8().data());
- }
- }
- }
- }
- candidates = nextCandidates;
- }
-
- for (const AZ::IO::Path& candidate : candidates)
- {
- QFileInfo fileInfo(QString::fromUtf8(candidate.c_str(), aznumeric_cast(candidate.Native().size())));
- if (fileInfo.isFile())
- {
- AZStd::string ext = fileInfo.suffix().toUtf8().data();
- if (ImageProcessing::IsExtensionSupported(ext.c_str()) && ext != "dds")
- {
- auto FindExistingPath = [&candidate](const AZStd::string& path)
- {
- return candidate == AZ::IO::PathView(path);
- };
- if (auto foundIt = AZStd::find_if(paths.begin(), paths.end(), FindExistingPath);
- foundIt == paths.end())
- {
- AZStd::string normalizedPath = AZ::IO::Path(candidate.Native(), AZ::IO::PosixPathSeparator).LexicallyNormal().Native();
- paths.push_back(AZStd::move(normalizedPath));
- }
- }
- }
- else if (fileInfo.isDir())
- {
- bool waste = true;
- AddFolderContents(paths, candidate.Native(), waste);
- }
- }
- }
-
- void AtlasBuilderInput::RemoveFilesUsingWildCard(AZStd::vector& paths, const AZStd::string& remove)
- {
- auto RemoveWildCardPath = [&remove](const AZStd::string& subPath)
- {
- return AZ::IO::PathView(subPath).Match(remove);
- };
- AZStd::erase_if(paths, RemoveWildCardPath);
- }
-
- // Replaces all folder paths with the files they contain
- void AtlasBuilderInput::AddFolderContents(AZStd::vector& paths, const AZStd::string& insert, bool& valid)
- {
- if (QDir inputFolder(insert.c_str()); inputFolder.exists())
- {
- QFileInfoList entries = inputFolder.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Files);
- for (const QFileInfo& entry : entries)
- {
- AZ::IO::Path child = entry.filePath().toUtf8().data();
- AZStd::string ext = entry.suffix().toUtf8().data();
- const bool isDir = entry.isDir();
- if (isDir)
- {
- AddFolderContents(paths, child.Native(), valid);
- }
- else if (ImageProcessing::IsExtensionSupported(ext.c_str()) && ext != "dds")
- {
- auto FindExistingPath = [&child](const AZStd::string& path)
- {
- return child == AZ::IO::PathView(path);
- };
- if (auto foundIter = AZStd::find_if(paths.begin(), paths.end(), FindExistingPath);
- foundIter == paths.end())
- {
- // Normalize the path to have posix slashes
- AZStd::string normalizedPath = AZ::IO::Path(child.Native(), AZ::IO::PosixPathSeparator).LexicallyNormal().Native();
- paths.push_back(AZStd::move(normalizedPath));
- }
- }
- }
- }
- else
- {
- valid = false;
- AZ_Error("AtlasBuilder", false, AZStd::string::format("Atlas Builder unable to find requested directory: %s", insert.c_str()).c_str());
- }
- }
-
- // Removes all of the contents of a folder
- void AtlasBuilderInput::RemoveFolderContents(AZStd::vector& paths, const AZStd::string& remove)
- {
- auto RemoveSubPath = [folder = AZ::IO::PathView(remove)](const AZStd::string& subPath)
- {
- return AZ::IO::PathView(subPath).IsRelativeTo(folder);
- };
- AZStd::erase_if(paths, RemoveSubPath);
- }
-
- // Note - Shutdown will be called on a different thread than your process job thread
- void AtlasBuilderWorker::ShutDown() { m_isShuttingDown = true; }
-
- void AtlasBuilderWorker::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request,
- AssetBuilderSDK::CreateJobsResponse& response)
- {
- // Read in settings/filepaths to set dependencies
- AZStd::string fullPath;
- AzFramework::StringFunc::Path::Join(
- request.m_watchFolder.c_str(), request.m_sourceFile.c_str(), fullPath, true, true);
- // Check if input is valid
- bool valid = true;
- AtlasBuilderInput input = AtlasBuilderInput::ReadFromFile(fullPath, request.m_watchFolder, valid);
-
- // Set dependencies
- for (int i = 0; i < input.m_filePaths.size(); ++i)
- {
- AssetBuilderSDK::SourceFileDependency dependency;
- dependency.m_sourceFileDependencyPath = input.m_filePaths[i].c_str();
- response.m_sourceFileDependencyList.push_back(dependency);
- }
-
- // We process the same file for all platforms
- for (const AssetBuilderSDK::PlatformInfo& info : request.m_enabledPlatforms)
- {
- if (ImageProcessing::BuilderSettingManager::Instance()->DoesSupportPlatform(info.m_identifier))
- {
- AssetBuilderSDK::JobDescriptor descriptor = GetJobDescriptor(request.m_sourceFile, input);
- descriptor.SetPlatformIdentifier(info.m_identifier.c_str());
- response.m_createJobOutputs.push_back(descriptor);
- }
- }
-
- if (valid)
- {
- response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success;
- }
-
- return;
- }
-
- AssetBuilderSDK::JobDescriptor AtlasBuilderWorker::GetJobDescriptor(const AZStd::string& sourceFile, const AtlasBuilderInput& input)
- {
- // Get the extension of the file
- AZStd::string ext;
- AzFramework::StringFunc::Path::GetExtension(sourceFile.c_str(), ext, false);
- AZStd::to_upper(ext.begin(), ext.end());
-
- AssetBuilderSDK::JobDescriptor descriptor;
- descriptor.m_jobKey = ext + " Atlas";
- descriptor.m_critical = false;
- descriptor.m_jobParameters[AZ_CRC("forceSquare")] = input.m_forceSquare ? "true" : "false";
- descriptor.m_jobParameters[AZ_CRC("forcePowerOf2")] = input.m_forcePowerOf2 ? "true" : "false";
- descriptor.m_jobParameters[AZ_CRC("includeWhiteTexture")] = input.m_includeWhiteTexture ? "true" : "false";
- descriptor.m_jobParameters[AZ_CRC("padding")] = AZStd::to_string(input.m_padding);
- descriptor.m_jobParameters[AZ_CRC("maxDimension")] = AZStd::to_string(input.m_maxDimension);
- descriptor.m_jobParameters[AZ_CRC("filePaths")] = AZStd::to_string(input.m_filePaths.size());
-
- AZ::u32 col = input.m_unusedColor.ToU32();
- descriptor.m_jobParameters[AZ_CRC("unusedColor")] = AZStd::to_string(*reinterpret_cast(&col));
- descriptor.m_jobParameters[AZ_CRC("presetName")] = input.m_presetName;
-
- // The starting point for the list
- const int start = static_cast(descriptor.m_jobParameters.size()) + 1;
- descriptor.m_jobParameters[AZ_CRC("startPoint")] = AZStd::to_string(start);
-
- for (int i = 0; i < input.m_filePaths.size(); ++i)
- {
- descriptor.m_jobParameters[start + i] = input.m_filePaths[i];
- }
-
- return descriptor;
- }
-
- void AtlasBuilderWorker::ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request,
- AssetBuilderSDK::ProcessJobResponse& response)
- {
- // Before we begin, let's make sure we are not meant to abort.
- AssetBuilderSDK::JobCancelListener jobCancelListener(request.m_jobId);
-
- AZStd::vector productFilepaths;
-
- const AZStd::string path = request.m_fullPath;
-
- bool imageProcessingSuccessful = false;
-
- // read in settings/filepaths
- AtlasBuilderInput input;
- input.m_forceSquare = AzFramework::StringFunc::ToBool(request.m_jobDescription.m_jobParameters.find(AZ_CRC("forceSquare"))->second.c_str());
- input.m_forcePowerOf2 = AzFramework::StringFunc::ToBool(request.m_jobDescription.m_jobParameters.find(AZ_CRC("forcePowerOf2"))->second.c_str());
- input.m_includeWhiteTexture = AzFramework::StringFunc::ToBool(request.m_jobDescription.m_jobParameters.find(AZ_CRC("includeWhiteTexture"))->second.c_str());
- input.m_padding = AzFramework::StringFunc::ToInt(request.m_jobDescription.m_jobParameters.find(AZ_CRC("padding"))->second.c_str());
- input.m_maxDimension = AzFramework::StringFunc::ToInt(request.m_jobDescription.m_jobParameters.find(AZ_CRC("maxDimension"))->second.c_str());
- int startAsInt = AzFramework::StringFunc::ToInt(request.m_jobDescription.m_jobParameters.find(AZ_CRC("startPoint"))->second.c_str());
- int sizeAsInt = AzFramework::StringFunc::ToInt(request.m_jobDescription.m_jobParameters.find(AZ_CRC("filePaths"))->second.c_str());
- AZ::u32 start = static_cast(AZStd::max(0, startAsInt));
- AZ::u32 size = static_cast(AZStd::max(0, sizeAsInt));
-
- int col = AzFramework::StringFunc::ToInt(request.m_jobDescription.m_jobParameters.find(AZ_CRC("unusedColor"))->second.c_str());
- input.m_unusedColor.FromU32(*reinterpret_cast(&col));
-
- input.m_presetName = request.m_jobDescription.m_jobParameters.find(AZ_CRC("presetName"))->second;
-
- for (AZ::u32 i = 0; i < size; ++i)
- {
- input.m_filePaths.push_back(request.m_jobDescription.m_jobParameters.find(start + i)->second);
- }
-
- if (input.m_filePaths.empty())
- {
- AZ_Error("AtlasBuilder", false, "No image files specified. Cannot create an empty atlas.");
- return;
- }
-
- // Don't allow padding to be less than zero
- if (input.m_padding < 0)
- {
- input.m_padding = 0;
- }
-
- if (input.m_presetName.empty())
- {
- // Default to the TextureAtlas preset which is currently set to use compression for all platforms except for iOS.
- // Currently the only fully supported compression for iOS is PVRTC which requires the texture to be square and a power of 2.
- // Due to this limitation, we default to using no compression for iOS until ASTC is fully supported
- const AZStd::string defaultPresetName = "TextureAtlas";
- input.m_presetName = defaultPresetName;
- }
-
- // Get a preset to use for the output image
- const ImageProcessing::PresetSettings* preset = GetImageProcessPresetSettings(input.m_presetName, request.m_platformInfo.m_identifier);
- if (preset)
- {
- // Check the preset's pixel format requirements
- const ImageProcessing::PixelFormatInfo* pixelFormatInfo = ImageProcessing::CPixelFormats::GetInstance().GetPixelFormatInfo(preset->m_pixelFormat);
- if (pixelFormatInfo && pixelFormatInfo->bSquarePow2)
- {
- // Override the user config settings to force square and power of 2.
- // Otherwise the image conversion process will stretch the image to satisfy these requirements
- input.m_forceSquare = true;
- input.m_forcePowerOf2 = true;
- }
- }
- else
- {
- AZ_Error("AtlasBuilder", false, "Could not find a preset setting for the output image.");
- return;
- }
-
- // Read in images
- AZStd::vector images;
- AZ::u64 totalArea = 0;
- int maxArea = input.m_maxDimension * input.m_maxDimension;
- bool sizeFailure = false;
- for (int i = 0; i < input.m_filePaths.size() && !jobCancelListener.IsCancelled(); ++i)
- {
- ImageProcessing::IImageObject* inputImage = ImageProcessing::LoadImageFromFile(input.m_filePaths[i]);
- // Check if we were able to load the image
- if (inputImage)
- {
- ImageProcessing::IImageObjectPtr image = ImageProcessing::IImageObjectPtr(inputImage);
- images.push_back(image);
- totalArea += inputImage->GetWidth(0) * inputImage->GetHeight(0);
- }
- else
- {
- AZ_Error("AtlasBuilder", false, AZStd::string::format("Atlas Builder unable to load file: %s", input.m_filePaths[i].c_str()).c_str());
- return;
- }
- if (maxArea < totalArea)
- {
- sizeFailure = true;
- }
- }
- // If we get cancelled, return
- if (jobCancelListener.IsCancelled())
- {
- return;
- }
-
- if (sizeFailure)
- {
- AZ_Error("AtlasBuilder", false, AZStd::string::format("Total image area exceeds maximum alotted area. %llu > %d", totalArea, maxArea).c_str());
- return;
- }
-
- // Convert all image paths to their output format referenced at runtime
- for (auto& filePath : input.m_filePaths)
- {
- // Get path relative to the watch folder
- bool result = false;
- AZ::Data::AssetInfo info;
- AZStd::string watchFolder;
- AzToolsFramework::AssetSystemRequestBus::BroadcastResult(result, &AzToolsFramework::AssetSystemRequestBus::Events::GetSourceInfoBySourcePath, filePath.c_str(), info, watchFolder);
- if (!result)
- {
- AZ_Error("AtlasBuilder", false, AZStd::string::format("Atlas Builder unable to get relative source path for image: %s", filePath.c_str()).c_str());
- return;
- }
-
- // Remove extension
- filePath = info.m_relativePath.substr(0, info.m_relativePath.find_last_of('.'));
-
- // Normalize path
- AzFramework::ApplicationRequests::Bus::Broadcast(&AzFramework::ApplicationRequests::NormalizePathKeepCase, filePath);
- }
-
- // Add white texture if we need to
- if (input.m_includeWhiteTexture)
- {
- ImageProcessing::IImageObjectPtr texture(ImageProcessing::IImageObject::CreateImage(
- cellSize, cellSize, 1, ImageProcessing::EPixelFormat::ePixelFormat_R8G8B8A8));
-
- // Make the texture white
- texture->ClearColor(1, 1, 1, 1);
- images.push_back(texture);
- input.m_filePaths.push_back("WhiteTexture");
- }
-
- // Generate algorithm inputs
- ImageDimensionData data;
- for (int i = 0; i < images.size(); ++i)
- {
- data.push_back(IndexImageDimension(i,
- ImageDimension(images[i]->GetWidth(0),
- images[i]->GetHeight(0))));
- }
- AZStd::sort(data.begin(), data.end());
-
- // Run algorithm
-
- // Variables that keep track of the optimal solution
- int resultWidth = -1;
- int resultHeight = -1;
-
- // Check that the max dimension is not large enough for the area to loop past the maximum integer
- // This is important because we do not want the area to be calculated negative
- if (input.m_maxDimension > 65535)
- {
- input.m_maxDimension = 65535;
- }
-
- // Get the optimal mappings based on the input settings
- AZStd::vector paddedMap;
- size_t amountFit = 0;
- if (!TryTightening(
- input, data, GetWidest(data), GetTallest(data), aznumeric_cast(totalArea), input.m_padding, resultWidth, resultHeight, amountFit, paddedMap))
- {
- AZ_Error("AtlasBuilder", false, AZStd::string::format("Cannot fit images into given maximum atlas size (%dx%d). Only %zu out of %zu images fit.", input.m_maxDimension, input.m_maxDimension, amountFit, input.m_filePaths.size()).c_str());
- // For some reason, failing the assert isn't enough to stop the Asset builder. It will still fail further
- // down when it tries to assemble the atlas, but returning here is cleaner.
- return;
- }
-
- // Move coordinates from algorithm space to padded result space
- TextureAtlasNamespace::AtlasCoordinateSets output;
- resultWidth = 0;
- resultHeight = 0;
- AZStd::vector map;
- for (int i = 0; i < paddedMap.size(); ++i)
- {
- map.push_back(AtlasCoordinates(paddedMap[i].GetLeft(), paddedMap[i].GetLeft() + images[data[i].first]->GetWidth(0), paddedMap[i].GetTop(), paddedMap[i].GetTop() + images[data[i].first]->GetHeight(0)));
- resultHeight = resultHeight > map[i].GetBottom() ? resultHeight : map[i].GetBottom();
- resultWidth = resultWidth > map[i].GetRight() ? resultWidth : map[i].GetRight();
-
- const AZStd::string& outputFilePath = input.m_filePaths[data[i].first];
- output.push_back(AZStd::pair(outputFilePath, map[i]));
- }
- if (input.m_forcePowerOf2)
- {
- resultWidth = aznumeric_cast(pow(2, 1 + IntegerLog2(static_cast(resultWidth - 1))));
- resultHeight = aznumeric_cast(pow(2, 1 + IntegerLog2(static_cast(resultHeight - 1))));
- }
- else
- {
- resultWidth = (resultWidth + (cellSize - 1)) / cellSize * cellSize;
- resultHeight = (resultHeight + (cellSize - 1)) / cellSize * cellSize;
- }
- if (input.m_forceSquare)
- {
- if (resultWidth > resultHeight)
- {
- resultHeight = resultWidth;
- }
- else
- {
- resultWidth = resultHeight;
- }
- }
-
- // Process texture sheet
- ImageProcessing::IImageObjectPtr outImage(ImageProcessing::IImageObject::CreateImage(
- resultWidth, resultHeight, 1, ImageProcessing::EPixelFormat::ePixelFormat_R8G8B8A8));
-
- // Clear the sheet
- outImage->ClearColor(input.m_unusedColor.GetR(), input.m_unusedColor.GetG(), input.m_unusedColor.GetB(), input.m_unusedColor.GetA());
-
- AZ::u8* outBuffer = nullptr;
- AZ::u32 outPitch;
- outImage->GetImagePointer(0, outBuffer, outPitch);
-
- // Copy images over
- for (int i = 0; i < map.size() && !jobCancelListener.IsCancelled(); ++i)
- {
- AZ::u8* inBuffer = nullptr;
- AZ::u32 inPitch;
- images[data[i].first]->GetImagePointer(0, inBuffer, inPitch);
- int j = 0;
-
- // The padding calculated here is the amount of excess horizontal space measured in bytes that are in each
- // row of the destination space AFTER the placement of the source row.
- int rightPadding = (paddedMap[i].GetRight() - map[i].GetRight() - input.m_padding);
- if (map[i].GetRight() + rightPadding > resultWidth)
- {
- rightPadding = resultWidth - map[i].GetRight();
- }
- rightPadding *= bytesPerPixel;
- int bottomPadding = (paddedMap[i].GetBottom() - map[i].GetBottom() - input.m_padding);
- if (map[i].GetBottom() + bottomPadding > resultHeight)
- {
- bottomPadding = resultHeight - map[i].GetBottom();
- }
-
- int leftPadding = 0;
- if (map[i].GetLeft() - input.m_padding >= 0)
- {
- leftPadding = input.m_padding * bytesPerPixel;
- }
-
- int topPadding = 0;
- if (map[i].GetTop() - input.m_padding >= 0)
- {
- topPadding = input.m_padding;
- }
-
- for (j = 0; j < map[i].GetHeight(); ++j)
- {
- // When we multiply `map[i].GetLeft()` by 4, we are changing the measure from atlas space, to byte array
- // space. The number is 4 because in this format, each pixel is 4 bytes long.
- memcpy(outBuffer + (map[i].GetTop() + j) * outPitch + (map[i].GetLeft() * bytesPerPixel),
- inBuffer + inPitch * j,
- inPitch);
- // Fill in the last bit of the row in the destination space with the same colors
- SetPixels(outBuffer + (map[i].GetTop() + j) * outPitch + (map[i].GetLeft() * bytesPerPixel) + inPitch,
- outBuffer + (map[i].GetTop() + j) * outPitch + (map[i].GetLeft() * bytesPerPixel) + inPitch - bytesPerPixel,
- rightPadding);
- // Fill in the first bit of the row in the destination space with the same colors
- SetPixels(outBuffer + (map[i].GetTop() + j) * outPitch + (map[i].GetLeft() * bytesPerPixel) - leftPadding,
- outBuffer + (map[i].GetTop() + j) * outPitch + (map[i].GetLeft() * bytesPerPixel),
- leftPadding);
- }
- // Fill in the last few rows of the buffer with the same colors
- for (; j < map[i].GetHeight() + bottomPadding; ++j)
- {
- memcpy(outBuffer + (map[i].GetTop() + j) * outPitch + (map[i].GetLeft() * bytesPerPixel) - leftPadding,
- outBuffer + (map[i].GetBottom() - 1) * outPitch + (map[i].GetLeft() * bytesPerPixel) - leftPadding,
- inPitch + leftPadding + rightPadding);
- }
- for (j = 1; j <= topPadding; ++j)
- {
- memcpy(outBuffer + (map[i].GetTop() - j) * outPitch + (map[i].GetLeft() * bytesPerPixel) - leftPadding,
- outBuffer + map[i].GetTop() * outPitch + (map[i].GetLeft() * bytesPerPixel) - leftPadding,
- inPitch + rightPadding + leftPadding);
- }
- }
-
- // If we get cancelled, return
- if (jobCancelListener.IsCancelled())
- {
- return;
- }
-
- // Output Atlas Coordinates
- AZStd::string fileName;
- AZStd::string outputPath;
- AzFramework::StringFunc::Path::GetFullFileName(request.m_sourceFile.c_str(), fileName);
- fileName = fileName.append("idx");
- AzFramework::StringFunc::Path::Join(
- request.m_tempDirPath.c_str(), fileName.c_str(), outputPath, true, true);
-
- // Output texture sheet
- AZStd::string imageFileName, imageOutputPath;
- AzFramework::StringFunc::Path::GetFileName(request.m_sourceFile.c_str(), imageFileName);
- imageFileName += ".dds";
- AzFramework::StringFunc::Path::Join(
- request.m_tempDirPath.c_str(), imageFileName.c_str(), imageOutputPath, true, true);
-
- // Let the ImageProcessor do the rest of the work.
- ImageProcessing::TextureSettings textureSettings;
- textureSettings.m_preset = preset->m_uuid;
-
- // Mipmaps for the texture atlas would require more work than the Image Processor does. This is because if we
- // let the Image Processor make mipmaps, it might bleed the textures in the atlas together.
- textureSettings.m_enableMipmap = false;
-
- // Check if the ImageBuilder wants to enable streaming
- bool isStreaming = ImageProcessing::BuilderSettingManager::Instance()
- ->GetBuilderSetting(request.m_platformInfo.m_identifier)
- ->m_enableStreaming;
-
- bool canOverridePreset = false;
- ImageProcessing::ImageConvertProcess* process =
- new ImageProcessing::ImageConvertProcess(outImage,
- textureSettings,
- *preset,
- false,
- isStreaming,
- canOverridePreset,
- imageOutputPath,
- request.m_platformInfo.m_identifier);
-
- if (process != nullptr)
- {
- // the process can be stopped if the job is cancelled or the worker is shutting down
- while (!process->IsFinished() && !m_isShuttingDown && !jobCancelListener.IsCancelled())
- {
- process->UpdateProcess();
- }
-
- // get process result
- imageProcessingSuccessful = process->IsSucceed();
- process->GetAppendOutputFilePaths(productFilepaths);
-
- delete process;
- }
- else
- {
- imageProcessingSuccessful = false;
- }
-
- if (imageProcessingSuccessful)
- {
- TextureAtlasNamespace::TextureAtlasRequestBus::Broadcast(
- &TextureAtlasNamespace::TextureAtlasRequests::SaveAtlasToFile, outputPath, output, resultWidth, resultHeight);
- response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(outputPath));
- response.m_outputProducts[static_cast(Product::TexatlasidxProduct)].m_productAssetType = azrtti_typeid();
- response.m_outputProducts[static_cast(Product::TexatlasidxProduct)].m_productSubID = 0;
-
- // The Image Processing Gem can produce multiple output files under certain
- // circumstances, but the texture atlas is not expected to produce such output
- if (productFilepaths.size() > 1)
- {
- AZ_Error("AtlasBuilder", false, "Image processing resulted in multiple output files. Texture atlas is expected to produce one output.");
- response.m_outputProducts.clear();
- return;
- }
-
- if (productFilepaths.size() > 0)
- {
- response.m_outputProducts.push_back(AssetBuilderSDK::JobProduct(productFilepaths[0]));
- response.m_outputProducts.back().m_productAssetType = azrtti_typeid();
- response.m_outputProducts.back().m_productSubID = 1;
-
- // The texatlasidx file is a data file that indicates where the original parts are inside the atlas,
- // and this would usually imply that it refers to its dds file in some way or needs it to function.
- // The texatlasidx file should be the one that depends on the DDS because its possible to use the DDS
- // without the texatlasid, but not the other way around
- AZ::Data::AssetId productAssetId(request.m_sourceFileUUID, response.m_outputProducts.back().m_productSubID);
- response.m_outputProducts[static_cast(Product::TexatlasidxProduct)].m_dependencies.push_back(AssetBuilderSDK::ProductDependency(productAssetId, 0));
- response.m_outputProducts[static_cast(Product::TexatlasidxProduct)].m_dependenciesHandled = true; // We've populated the dependencies immediately above so it's OK to tell the AP we've handled dependencies
- }
- response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;
- }
- }
-
- bool AtlasBuilderWorker::TryPack(const ImageDimensionData& images,
- int targetWidth,
- int targetHeight,
- int padding,
- size_t& amountFit,
- AZStd::vector& out)
- {
- // Start with one open slot and initialize a vector to store the closed products
- AZStd::vector open;
- AZStd::vector closed;
- open.push_back(AtlasCoordinates(0, targetWidth, 0, targetHeight));
- bool slotNotFound = false;
- for (size_t i = 0; i < images.size() && !slotNotFound; ++i)
- {
- slotNotFound = true;
- // Try to place the image in every open slot
- for (size_t j = 0; j < open.size(); ++j)
- {
- if (CanInsert(open[j], images[i].second, padding, targetWidth, targetHeight))
- {
- // if it fits, subdivide the excess space in the slot, add it back to the open list and place the
- // filled space into the closed vector
- slotNotFound = false;
- AtlasCoordinates spent(open[j].GetLeft(),
- open[j].GetLeft() + images[i].second.m_width,
- open[j].GetTop(),
- open[j].GetTop() + images[i].second.m_height);
-
- // We are going to try pushing the object up / left to try to avoid creating tight open spaces.
- bool needTrim = false;
- AtlasCoordinates coords = spent;
- // Modifying left will preserve width
- coords.SetLeft(coords.GetLeft() - 1);
- AddPadding(coords, padding, targetWidth, targetHeight);
- while (spent.GetLeft() > 0 && !Collides(coords, closed))
- {
- spent.SetLeft(coords.GetLeft());
- coords = spent;
- coords.SetLeft(coords.GetLeft() - 1);
- AddPadding(coords, padding, targetWidth, targetHeight);
- needTrim = true;
- }
- // Refocus the search to see if we can push up
- coords = spent;
- coords.SetTop(coords.GetTop() - 1);
- AddPadding(coords, padding, targetWidth, targetHeight);
- while (spent.GetTop() > 0 && !Collides(coords, closed))
- {
- spent.SetTop(coords.GetTop());
- coords = spent;
- coords.SetTop(coords.GetTop() - 1);
- AddPadding(coords, padding, targetWidth, targetHeight);
- needTrim = true;
- }
- AddPadding(spent, padding, targetWidth, targetHeight);
- if (needTrim)
- {
- TrimOverlap(open, spent);
- closed.push_back(spent);
- break;
- }
- AtlasCoordinates bigCoords;
- AtlasCoordinates smallCoords;
-
- // Create the largest possible subdivision and another subdivision that uses the left over space
- if (open[j].GetBottom() - spent.GetBottom() < open[j].GetRight() - spent.GetRight())
- {
- smallCoords = AtlasCoordinates(
- open[j].GetLeft(), spent.GetRight(), spent.GetBottom(), open[j].GetBottom());
- bigCoords = AtlasCoordinates(spent.GetRight(), open[j].GetRight(), open[j].GetTop(), smallCoords.GetBottom());
- }
- else
- {
- bigCoords = AtlasCoordinates(
- open[j].GetLeft(), open[j].GetRight(), spent.GetBottom(), open[j].GetBottom());
- smallCoords = AtlasCoordinates(spent.GetRight(), open[j].GetRight(), open[j].GetTop(), bigCoords.GetTop());
- }
-
- open.erase(open.begin() + j, open.begin() + j + 1);
- if (bigCoords.GetHeight() > 0 && bigCoords.GetHeight() > 0)
- {
- InsertInOrder(open, bigCoords);
- }
- if (smallCoords.GetHeight() > 0 && smallCoords.GetHeight() > 0)
- {
- InsertInOrder(open, smallCoords);
- }
-
- closed.push_back(spent);
- break;
- }
- }
- if (slotNotFound)
- {
- // If no single open slot can fit the object, do one last check to see if we can fit it in at any open
- // corner. The reason we perform this check is in case the object can be fit across multiple different
- // open spaces. If there is a space that an object can be fit in, it will probably involve the top left
- // corner of that object in the top left corner of an open slot. This may miss some odd fits, but due to
- // the nature of the packing algorithm, such solutions are highly unlikely to exist. If we wanted to
- // expand the algorithm, we could theoretically base it on edges instead of corners to find all results,
- // but it would not be time efficient.
- for (size_t j = 0; j < open.size(); ++j)
- {
- AtlasCoordinates insert = AtlasCoordinates(open[j].GetLeft(),
- open[j].GetLeft() + images[i].second.m_width,
- open[j].GetTop(),
- open[j].GetTop() + images[i].second.m_height);
- AddPadding(insert, padding, targetWidth, targetHeight);
- if (insert.GetRight() <= targetWidth && insert.GetBottom() <= targetHeight)
- {
- bool collision = Collides(insert, closed);
- if (!collision)
- {
- closed.push_back(insert);
- // Trim overlapping open slots
- TrimOverlap(open, insert);
- slotNotFound = false;
- break;
- }
- }
- }
- }
- }
- // If we succeeded, update the output
- if (!slotNotFound)
- {
- out = closed;
- }
- amountFit = amountFit > closed.size() ? amountFit : closed.size();
- return !slotNotFound;
- }
-
- // Modifies slotList so that no items in slotList overlap with item
- void AtlasBuilderWorker::TrimOverlap(AZStd::vector& slotList, AtlasCoordinates item)
- {
- for (size_t i = 0; i < slotList.size(); ++i)
- {
- if (Collides(slotList[i], item))
- {
- // Subdivide the overlapping slot to seperate overlapping and non overlapping portions
- AtlasCoordinates overlap = GetOverlap(item, slotList[i]);
- AZStd::vector excess;
- excess.push_back(AtlasCoordinates(
- slotList[i].GetLeft(), overlap.GetRight(), slotList[i].GetTop(), overlap.GetTop()));
- excess.push_back(AtlasCoordinates(
- slotList[i].GetLeft(), overlap.GetLeft(), overlap.GetTop(), slotList[i].GetBottom()));
- excess.push_back(AtlasCoordinates(
- overlap.GetRight(), slotList[i].GetRight(), slotList[i].GetTop(), overlap.GetBottom()));
- excess.push_back(AtlasCoordinates(
- overlap.GetLeft(), slotList[i].GetRight(), overlap.GetBottom(), slotList[i].GetBottom()));
- slotList.erase(slotList.begin() + i);
- for (size_t j = 0; j < excess.size(); ++j)
- {
- if (excess[j].GetWidth() > 0 && excess[j].GetHeight() > 0)
- {
- InsertInOrder(slotList, excess[j]);
- }
- }
- --i;
- }
- }
- }
-
- // This function interprets input and performs the proper tightening option
- bool AtlasBuilderWorker::TryTightening(AtlasBuilderInput input,
- const ImageDimensionData& images,
- int smallestWidth,
- int smallestHeight,
- int targetArea,
- int padding,
- int& resultWidth,
- int& resultHeight,
- size_t& amountFit,
- AZStd::vector& out)
- {
- if (input.m_forceSquare)
- {
- return TryTighteningSquare(images,
- smallestWidth > smallestHeight ? smallestWidth : smallestHeight,
- input.m_maxDimension,
- targetArea,
- input.m_forcePowerOf2,
- padding,
- resultWidth,
- resultHeight,
- amountFit,
- out);
- }
- else
- {
- return TryTighteningOptimal(images,
- smallestWidth,
- smallestHeight,
- input.m_maxDimension,
- targetArea,
- input.m_forcePowerOf2,
- padding,
- resultWidth,
- resultHeight,
- amountFit,
- out);
- }
- }
-
- // Finds the optimal square solution by starting with the ideal solution and expanding the size of the space until everything fits
- bool AtlasBuilderWorker::TryTighteningSquare(const ImageDimensionData& images,
- int lowerBound,
- int maxDimension,
- int targetArea,
- bool powerOfTwo,
- int padding,
- int& resultWidth,
- int& resultHeight,
- size_t& amountFit,
- AZStd::vector& out)
- {
- // Square solution cannot be smaller than the target area
- int dimension = aznumeric_cast(sqrt(static_cast(targetArea)));
- // Solution cannot be smaller than the smallest side
- dimension = dimension > lowerBound ? dimension : lowerBound;
- if (powerOfTwo)
- {
- // Starting dimension needs to be rounded up to the nearest power of two
- dimension = aznumeric_cast(pow(2, 1 + IntegerLog2(static_cast(dimension - 1))));
- }
-
- AZStd::vector track;
- // Expand the square until the contents fit
- while (!TryPack(images, dimension, dimension, padding, amountFit, track) && dimension <= maxDimension)
- {
- // Step to the next valid value
- dimension = powerOfTwo ? dimension * 2 : dimension + cellSize;
- }
- // Make sure we found a solution
- if (dimension > maxDimension)
- {
- return false;
- }
-
- resultHeight = dimension;
- resultWidth = dimension;
- out = track;
- return true;
- }
-
- // Finds the optimal solution by starting with a somewhat optimal solution and searching for better solutions
- bool AtlasBuilderWorker::TryTighteningOptimal(const ImageDimensionData& images,
- int smallestWidth,
- int smallestHeight,
- int maxDimension,
- int targetArea,
- bool powerOfTwo,
- int padding,
- int& resultWidth,
- int& resultHeight,
- size_t& amountFit,
- AZStd::vector& out)
- {
- AZStd::vector track;
-
- // round max dimension down to a multiple of cellSize
- AZ::u32 maxDimensionRounded = maxDimension - (maxDimension % cellSize);
-
- // The starting width is the larger of the widest individual texture and the width required
- // to fit the total texture area given the max dimension
- AZ::u32 smallestWidthDueToArea = targetArea / maxDimensionRounded;
- AZ::u32 minWidth = AZStd::max(static_cast(smallestWidth), smallestWidthDueToArea);
-
- if (powerOfTwo)
- {
- // Starting dimension needs to be rounded up to the nearest power of two
- minWidth = aznumeric_cast(pow(2, 1 + IntegerLog2(static_cast(minWidth - 1))));
- }
-
- // Round min width up to the nearest compression unit
- minWidth = (minWidth + (cellSize - 1)) / cellSize * cellSize;
-
- AZ::u32 height = 0;
- // Finds the optimal thin solution
- // This uses a standard binary search to find the smallest width that can pack everything
- AZ::u32 lower = minWidth;
- AZ::u32 upper = maxDimensionRounded;
- AZ::u32 width = 0;
- while (lower <= upper)
- {
- AZ::u32 testWidth = (lower + upper) / 2; // must be divisible by cellSize because lower and upper are
- bool canPack = TryPack(images, testWidth, maxDimension, padding, amountFit, track);
- if (canPack)
- {
- // it packed, continue looking for smaller widths that pack
- width = testWidth; // best fit so far
- upper = testWidth - cellSize;
- }
- else
- {
- // it failed to pack, don't try any widths smaller than this
- lower = testWidth + cellSize;
- }
- }
- // Make sure we found a solution
- if (width == 0)
- {
- return false;
- }
-
- // Find the height of the solution
- for (int i = 0; i < track.size(); ++i)
- {
- uint32 bottom = static_cast(AZStd::max(0, track[i].GetBottom()));
- if (height < bottom)
- {
- height = bottom;
- }
- }
-
- // Fix height for power of two when applicable
- if (powerOfTwo)
- {
- // Starting dimensions need to be rounded up to the nearest power of two
- height = aznumeric_cast(pow(2, 1 + IntegerLog2(static_cast(height - 1))));
- }
-
- AZ::u32 resultArea = height * width;
- // This for loop starts with the optimal thin width and makes it wider at each step. For each width, it
- // calculates what height would be neccesary to have a more optimal solution than the stored solution. If the
- // more optimal solution is valid, it tries shrinking the height until the solution fails. The loop ends when it
- // is determined that a valid solution cannot exist at further steps
- for (AZ::u32 testWidth = width; testWidth <= maxDimensionRounded && resultArea / testWidth >= static_cast(smallestHeight);
- testWidth = powerOfTwo ? testWidth * 2 : testWidth + cellSize)
- {
- // The area of test height and width should be equal or less than resultArea
- // Note: We don't need to force powers of two here because the Area and the width are already powers of two
- int testHeight = resultArea / testWidth * cellSize / cellSize;
- // Try the tighter pack
- while (TryPack(images, static_cast(testWidth), testHeight, padding, amountFit, track))
- {
- // Loop and continue to shrink the height until you cannot do so any further
- width = testWidth;
- height = testHeight;
- resultArea = height * width;
- // Try to step down a level
- testHeight = powerOfTwo ? testHeight / 2 : testHeight - cellSize;
- }
- }
- // Output the results of the function
- out = track;
- resultHeight = height;
- resultWidth = width;
- return true;
- }
-
- // Allows us to keep the list of open spaces in order from lowest to highest area
- void AtlasBuilderWorker::InsertInOrder(AZStd::vector& slotList, AtlasCoordinates item)
- {
- int area = item.GetWidth() * item.GetHeight();
- for (size_t i = 0; i < slotList.size(); ++i)
- {
- if (area < slotList[i].GetWidth() * slotList[i].GetHeight())
- {
- slotList.insert(slotList.begin() + i, item);
- return;
- }
- }
- slotList.push_back(item);
- }
-
- // Defines priority so that sorting can be meaningful. It may seem odd that larger items are "less than" smaller
- // ones, but as this is a deduction of priority, not value, it is correct.
- static bool operator<(ImageDimension a, ImageDimension b)
- {
- // Prioritize first by longest size
- if ((a.m_width > a.m_height ? a.m_width : a.m_height) != (b.m_width > b.m_height ? b.m_width : b.m_height))
- {
- return (a.m_width > a.m_height ? a.m_width : a.m_height) > (b.m_width > b.m_height ? b.m_width : b.m_height);
- }
- // Prioritize second by the length of the smaller side
- if (a.m_width * a.m_height != b.m_width * b.m_height)
- {
- return a.m_width * a.m_height > b.m_width * b.m_height;
- }
- // Prioritize wider objects over taller objects for objects of the same size
- else
- {
- return a.m_width > b.m_width;
- }
- }
-
- // Exposes priority logic to the sorting algorithm
- static bool operator<(IndexImageDimension a, IndexImageDimension b) { return a.second < b.second; }
-
- // Tests if two coordinate sets intersect
- bool Collides(AtlasCoordinates a, AtlasCoordinates b)
- {
- return !((a.GetRight() <= b.GetLeft()) || (a.GetBottom() <= b.GetTop()) || (b.GetRight() <= a.GetLeft())
- || (b.GetBottom() <= a.GetTop()));
- }
-
- // Tests if an item collides with any items in a list
- bool Collides(AtlasCoordinates item, AZStd::vector list)
- {
- for (size_t i = 0; i < list.size(); ++i)
- {
- if (Collides(list[i], item))
- {
- return true;
- }
- }
- return false;
- }
-
- // Returns the overlap of two intersecting coordinate sets
- AtlasCoordinates GetOverlap(AtlasCoordinates a, AtlasCoordinates b)
- {
- return AtlasCoordinates(b.GetLeft() > a.GetLeft() ? b.GetLeft() : a.GetLeft(),
- b.GetRight() < a.GetRight() ? b.GetRight() : a.GetRight(),
- b.GetTop() > a.GetTop() ? b.GetTop() : a.GetTop(),
- b.GetBottom() < a.GetBottom() ? b.GetBottom() : a.GetBottom());
- }
-
- // Returns the width of the widest element in imageList
- int AtlasBuilderWorker::GetWidest(const ImageDimensionData& imageList)
- {
- int max = 0;
- for (size_t i = 0; i < imageList.size(); ++i)
- {
- if (max < imageList[i].second.m_width)
- {
- max = imageList[i].second.m_width;
- }
- }
- return max;
- }
-
- // Returns the height of the tallest element in imageList
- int AtlasBuilderWorker::GetTallest(const ImageDimensionData& imageList)
- {
- int max = 0;
- for (size_t i = 0; i < imageList.size(); ++i)
- {
- if (max < imageList[i].second.m_height)
- {
- max = imageList[i].second.m_height;
- }
- }
- return max;
- }
-
- // Performs an operation that copies a pixel to the output
- void SetPixels(AZ::u8* dest, const AZ::u8* source, int destBytes)
- {
- if (destBytes >= bytesPerPixel)
- {
- memcpy(dest, source, bytesPerPixel);
- int bytesCopied = bytesPerPixel;
- while (bytesCopied * 2 < destBytes)
- {
- memcpy(dest + bytesCopied, dest, bytesCopied);
- bytesCopied *= 2;
- }
- memcpy(dest + bytesCopied, dest, destBytes - bytesCopied);
- }
- }
-
- // Checks if we can insert an image into a slot
- bool CanInsert(AtlasCoordinates slot, ImageDimension image, int padding, int farRight, int farBot)
- {
- int right = slot.GetLeft() + image.m_width;
- if (slot.GetRight() < farRight)
- {
- // Add padding for my right border
- right += padding;
- // Round up to the nearest compression unit
- right = (right + (cellSize - 1)) / cellSize * cellSize;
- // Add padding for an adjacent unit's left border
- right += padding;
- }
-
- int bot = slot.GetTop() + image.m_height;
- if (slot.GetBottom() < farBot)
- {
- // Add padding for my right border
- bot += padding;
- // Round up to the nearest compression unit
- bot = (bot + (cellSize - 1)) / cellSize * cellSize;
- // Add padding for an adjacent unit's left border
- bot += padding;
- }
-
- return slot.GetRight() >= right && slot.GetBottom() >= bot;
- }
-
- // Adds the necessary padding to an Atlas Coordinate
- void AddPadding(AtlasCoordinates& slot, int padding, [[maybe_unused]] int farRight, [[maybe_unused]] int farBot)
- {
- // Add padding for my right border
- int right = slot.GetRight() + padding;
- // Round up to the nearest compression unit
- right = (right + (cellSize - 1)) / cellSize * cellSize;
- // Add padding for an adjacent unit's left border
- right += padding;
-
- // Add padding for my right border
- int bot = slot.GetBottom() + padding;
- // Round up to the nearest compression unit
- bot = (bot + (cellSize - 1)) / cellSize * cellSize;
- // Add padding for an adjacent unit's left border
- bot += padding;
-
- slot.SetRight(right);
- slot.SetBottom(bot);
- }
-
-}
diff --git a/Gems/ImageProcessing/Code/Source/AtlasBuilder/AtlasBuilderWorker.h b/Gems/ImageProcessing/Code/Source/AtlasBuilder/AtlasBuilderWorker.h
deleted file mode 100644
index f28535998e..0000000000
--- a/Gems/ImageProcessing/Code/Source/AtlasBuilder/AtlasBuilderWorker.h
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
-* 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.
-*
-*/
-
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-
-namespace TextureAtlasBuilder
-{
- //! Struct that is used to communicate input commands
- struct AtlasBuilderInput
- {
- AZ_CLASS_ALLOCATOR(AtlasBuilderInput, AZ::SystemAllocator, 0);
- AZ_TYPE_INFO(AtlasBuilderInput, "{F54477F9-1BDE-4274-8CC0-8320A3EF4A42}");
-
- bool m_forceSquare;
- bool m_forcePowerOf2;
- // Includes a white default texture for the UI to use under certain circumstances
- bool m_includeWhiteTexture;
- int m_maxDimension;
- // At least this much padding will surround each texture except on the edges of the atlas
- int m_padding;
- // Color used in wasted space
- AZ::Color m_unusedColor;
- // A preset to use for the texture atlas image processing
- AZStd::string m_presetName;
-
- AZStd::vector m_filePaths;
- AtlasBuilderInput():
- m_forceSquare(false),
- m_forcePowerOf2(false),
- m_includeWhiteTexture(true),
- m_maxDimension(4096),
- m_padding(1),
- // Default color should be a non-transparent color that isn't used often in uis
- m_unusedColor(.235f, .702f, .443f, 1)
- {
- }
-
- static void Reflect(AZ::ReflectContext* context);
-
- //! Attempts to read the input from a .texatlas file. "valid" is for reporting exceptions and telling the asset
- //! proccesor to fail the job. Supports parsing through a human readable custom parser.
- static AtlasBuilderInput ReadFromFile(const AZStd::string& path, const AZStd::string& directory, bool& valid);
-
- //! Resolves any wild cards in paths
- static void AddFilesUsingWildCard(AZStd::vector& paths, const AZStd::string& insert);
-
- //! Removes anything that matches the wildcard
- static void RemoveFilesUsingWildCard(AZStd::vector& paths, const AZStd::string& remove);
-
- //! Resolves any folder paths into image file paths
- static void AddFolderContents(AZStd::vector& paths, const AZStd::string& insert, bool& valid);
-
- //! Resolves remove commands for folders
- static void RemoveFolderContents(AZStd::vector& paths, const AZStd::string& remove);
- };
-
- //! Struct that is used to represent an object with a width and height in pixels
- struct ImageDimension
- {
- int m_width;
- int m_height;
-
- ImageDimension(int width, int height)
- {
- m_width = width;
- m_height = height;
- }
- };
-
- //! Typedef for an ImageDimension paired with an integer
- using IndexImageDimension = AZStd::pair;
-
- //! Typedef for a list of ImageDimensions paired with integers
- using ImageDimensionData = AZStd::vector;
-
- //! Typedef to simplify references to TextureAtlas::AtlasCoordinates
- using AtlasCoordinates = TextureAtlasNamespace::AtlasCoordinates;
-
- //! Number of bytes in a pixel
- const int bytesPerPixel = 4;
-
- //! The size of the padded sorting units (important for compression)
- const int cellSize = 4;
-
- //! Indexes of the products
- enum class Product
- {
- TexatlasidxProduct = 0,
- DdsProduct = 1
- };
-
- //! An asset builder for texture atlases
- class AtlasBuilderWorker : public AssetBuilderSDK::AssetBuilderCommandBus::Handler
- {
- public:
- AZ_RTTI(AtlasBuilderWorker, "{79036188-E017-4575-9EC0-8D39CB560EA6}");
-
- AtlasBuilderWorker() = default;
- ~AtlasBuilderWorker() = default;
-
- //! Asset Builder Callback Functions
-
- //! Called by asset processor to gather information on a job for a ".texatlas" file
- void CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request,
- AssetBuilderSDK::CreateJobsResponse& response);
- //! Called by asset proccessor when it wants us to execute a job
- void ProcessJob(const AssetBuilderSDK::ProcessJobRequest& request,
- AssetBuilderSDK::ProcessJobResponse& response);
-
- //! Returns the job related information used by the builder
- static AssetBuilderSDK::JobDescriptor GetJobDescriptor(const AZStd::string& sourceFile, const AtlasBuilderInput& input);
-
- //////////////////////////////////////////////////////////////////////////
- //! AssetBuilderSDK::AssetBuilderCommandBus interface
- void ShutDown() override; // if you get this you must fail all existing jobs and return.
- //////////////////////////////////////////////////////////////////////////
-
- private:
- bool m_isShuttingDown = false;
-
- //! This is the main function that takes a set of inputs and attempts to pack them into an atlas of a given
- //! size. Returns true if succesful, does not update out on failure.
- static bool TryPack(const ImageDimensionData& images,
- int targetWidth,
- int targetHeight,
- int padding,
- size_t& amountFit,
- AZStd::vector& out);
-
- //! Removes any overlap between slotList and the given item
- static void TrimOverlap(AZStd::vector& slotList, AtlasCoordinates item);
-
- //! Uses the proper tightening method based on the input and returns the maximum number of items that were able to be fit
- bool TryTightening(AtlasBuilderInput input,
- const ImageDimensionData& images,
- int smallestWidth,
- int smallestHeight,
- int targetArea,
- int padding,
- int& resultWidth,
- int& resultHeight,
- size_t& amountFit,
- AZStd::vector& out);
-
- //! Finds the tightest square fit achievable by expanding a square area until a valid fit is found
- bool TryTighteningSquare(const ImageDimensionData& images,
- int lowerBound,
- int maxDimension,
- int targetArea,
- bool powerOfTwo,
- int padding,
- int& resultWidth,
- int& resultHeight,
- size_t& amountFit,
- AZStd::vector& out);
-
- //! Finds the tightest fit achievable by starting with the optimal thin solution and attempting to resize to be
- //! a better shape
- bool TryTighteningOptimal(const ImageDimensionData& images,
- int smallestWidth,
- int smallestHeight,
- int maxDimension,
- int targetArea,
- bool powerOfTwo,
- int padding,
- int& resultWidth,
- int& resultHeight,
- size_t& amountFit,
- AZStd::vector& out);
-
- //! Sorting logic for adding a slot to a sorted list in order to maintain increasing order
- static void InsertInOrder(AZStd::vector& slotList, AtlasCoordinates item);
-
- //! Misc Logic For Estimating Target Shape
-
- //! Returns the width of the widest element
- static int GetWidest(const ImageDimensionData& imageList);
-
- //! Returns the height of the tallest area
- static int GetTallest(const ImageDimensionData& imageList);
- };
-
- //! Used for sorting ImageDimensions
- static bool operator<(ImageDimension a, ImageDimension b);
-
- //! Used to expose the ImageDimension in a pair to AZStd::Sort
- static bool operator<(IndexImageDimension a, IndexImageDimension b);
-
- //! Returns true if two coordinate sets overlap
- static bool Collides(AtlasCoordinates a, AtlasCoordinates b);
-
- //! Returns true if item collides with any object in list
- static bool Collides(AtlasCoordinates item, AZStd::vector list);
-
- //! Returns the portion of the second item that overlaps with the first
- static AtlasCoordinates GetOverlap(AtlasCoordinates a, AtlasCoordinates b);
-
- //! Performs an operation that copies a pixel to the output
- static void SetPixels(AZ::u8* dest, const AZ::u8* source, int destBytes);
-
- //! Checks if we can insert an image into a slot
- static bool CanInsert(AtlasCoordinates slot, ImageDimension image, int padding, int farRight, int farBot);
-
- //! Adds the necessary padding to an Atlas Coordinate
- static void AddPadding(AtlasCoordinates& slot, int padding, int farRight, int farBot);
-}
diff --git a/Gems/ImageProcessing/Code/Source/BuilderSettings/BuilderSettingManager.cpp b/Gems/ImageProcessing/Code/Source/BuilderSettings/BuilderSettingManager.cpp
deleted file mode 100644
index f8b0a1651b..0000000000
--- a/Gems/ImageProcessing/Code/Source/BuilderSettings/BuilderSettingManager.cpp
+++ /dev/null
@@ -1,1114 +0,0 @@
-/*
-* 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 "ImageProcessing_precompiled.h"
-
-#include "BuilderSettingManager.h"
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-namespace ImageProcessing
-{
-
-#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";
- AZ::EnvironmentVariable BuilderSettingManager::s_globalInstance = nullptr;
- AZStd::mutex BuilderSettingManager::s_instanceMutex;
- const PlatformName BuilderSettingManager::s_defaultPlatform = AZ_TRAIT_IMAGEPROCESSING_DEFAULT_PLATFORM;
-
- AZ::Outcome, AZStd::string> GetPlatformNamesFromRC(AZStd::string& filePath)
- {
- QFile inputFile(filePath.c_str());
-
- if (inputFile.exists() == false)
- {
- return AZ::Failure(AZStd::string::format("'%s' does not exist", filePath.c_str()));
- }
-
- AZStd::vector all_platforms;
- if (inputFile.open(QIODevice::ReadOnly))
- {
- QTextStream in(&inputFile);
- while (!in.atEnd())
- {
- if (in.readLine() == "[_platform]")
- {
- QString name_line = in.readLine();
- if (name_line.contains("name="))
- {
- QString name_value = name_line.split("=")[1];
- // Remove name alias after ','
- AZStd::string az_name_value = name_value.split(",")[0].toUtf8().constData();
- all_platforms.push_back(az_name_value);
- }
- }
- }
- inputFile.close();
- }
- return AZ::Success(all_platforms);
- }
-
- StringOutcome ParseKeyToData(QString settingKey, const QSettings& rcINI, PresetSettings& presetSettings)
- {
- // We may be parsing platform-specific settings denoted by a colon and a platform (ex. mintexturesize:ios=35).
- // We always extract the actual setting name to determine the setting we are parsing. We must reference the key
- // as a whole to properly index into the rcINI file content.
- QString key = settingKey.split(":")[0];
-
- // There is no standard way to map an enum to string--
- // Also, can't seem to make this static because it allocates something that the destructor doesn't catch.
- const AZStd::map colorSpaceMap{
- { "linear" , ColorSpace::linear },
- { "sRGB" , ColorSpace::sRGB },
- { "auto" , ColorSpace::autoSelect }
- };
-
- const AZStd::map rgbWeightMap{
- { "uniform" , RGBWeight::uniform },
- { "luminance" , RGBWeight::luminance },
- { "ciexyz" , RGBWeight::ciexyz }
- };
-
- //cm_ftype: gaussian, cone, disc, cosine, cosine_power, ggx
- const AZStd::map cubemapFilterTypeMap{
- { "cone" , CubemapFilterType::cone },
- { "gaussian" , CubemapFilterType::gaussian },
- { "ggx" , CubemapFilterType::ggx },
- { "cosine" , CubemapFilterType::cosine },
- { "cosine_power" , CubemapFilterType::cosine_power }
- };
-
- // To avoid abusing '#define', we use lambda instead.
- auto INI_VALUE = [&rcINI, &settingKey]() { return rcINI.value(settingKey); };
- auto INI_VALUE_QSTRING = [&rcINI, &settingKey]() { return rcINI.value(settingKey).toString(); };
-
- /************************************************************************/
- /* GENERAL PRESET SETTINGS */
- /************************************************************************/
- if (key == "rgbweights")
- {
- auto rgbWeightStr = INI_VALUE_QSTRING().toUtf8();
- auto rgbWeightIter = rgbWeightMap.find(rgbWeightStr);
- if (rgbWeightIter != rgbWeightMap.end())
- {
- presetSettings.m_rgbWeight = rgbWeightIter->second;
- }
- else
- {
- return AZ::Failure(AZStd::string("Unmapped rgbweights enum detected."));
- }
- }
- else if (key == "powof2")
- {
- presetSettings.m_isPowerOf2 = INI_VALUE().toBool();
- }
- else if (key == "discardalpha")
- {
- presetSettings.m_discardAlpha = INI_VALUE().toBool();
- }
- else if (key == "reduce")
- {
- int reduce = INI_VALUE().toInt();
- if (reduce > 0)
- {
- presetSettings.m_sizeReduceLevel = reduce;
- }
- }
- else if (key == "ser")
- {
- presetSettings.m_suppressEngineReduce = INI_VALUE().toBool();
- }
- else if (key == "colorchart")
- {
- presetSettings.m_isColorChart = INI_VALUE().toBool();
- }
- else if (key == "highpass")
- {
- presetSettings.m_highPassMip = INI_VALUE().toInt();
- }
- else if (key == "glossfromnormals")
- {
- presetSettings.m_glossFromNormals = INI_VALUE().toBool();
- }
- else if (key == "glosslegacydist")
- {
- presetSettings.m_isLegacyGloss = INI_VALUE().toBool();
- }
- else if (key == "swizzle")
- {
- presetSettings.m_swizzle = INI_VALUE_QSTRING().toUtf8().constData();
- }
- else if (key == "mipnormalize")
- {
- presetSettings.m_isMipRenormalize = INI_VALUE().toBool();
- }
- else if (key == "numstreamablemips")
- {
- presetSettings.m_numStreamableMips = INI_VALUE().toInt();
- }
- else if (key == "colorspace")
- {
- // By default, RC.ini contains data written in non-standard INI format inherited from CryEngine.
- // We need to parse in the value as string list.
- // Example:
- //
- // [MyValues]
- // colorspace=src,dst
- //
- QVariant paramValue = rcINI.value(key, QString());
- if (paramValue.type() != QVariant::StringList)
- {
- return AZ::Failure(AZStd::string("Expect ColorSpace parameter to be a string list!"));
- }
- QStringList stringValueList = paramValue.toStringList(); // The order of values for this key is... (SRC, DST)
-
- if (stringValueList.size() != 2)
- {
- return AZ::Failure(AZStd::string("Expect ColorSpace parameter list size to be 2!"));
- }
-
- auto srcColorSpaceIter = colorSpaceMap.find(stringValueList[0]);
- if (srcColorSpaceIter != colorSpaceMap.end())
- {
- presetSettings.m_srcColorSpace = srcColorSpaceIter->second;
- }
- else
- {
- return AZ::Failure(AZStd::string("Unmapped ColorSpace enum detected."));
- }
-
- auto dstColorSpaceIter = colorSpaceMap.find(stringValueList[1]);
- if (dstColorSpaceIter != colorSpaceMap.end())
- {
- presetSettings.m_destColorSpace = dstColorSpaceIter->second;
- }
- else
- {
- return AZ::Failure(AZStd::string("Unmapped ColorSpace enum detected."));
- }
- }
- else if (key == "filemasks")
- {
- QVariant iniVariant = rcINI.value(settingKey);
- QStringList stringValueList = iniVariant.toStringList();
- for (QString value : stringValueList)
- {
- //remove stars. For example: "*_ddna*" => "_ddna"
- QString suffix = value.mid(1, value.length()-2);
- QByteArray suffixByteArray = suffix.toUtf8();
- presetSettings.m_fileMasks.emplace_back(suffixByteArray.constData());
- }
- }
- else if (key == "pixelformat")
- {
- auto pixelFormatQBytes = INI_VALUE_QSTRING().toUtf8();
- const char* pixelFormatString = pixelFormatQBytes.constData();
-
- EPixelFormat pixelFormatEnum = CPixelFormats::GetInstance().FindPixelFormatByLegacyName(pixelFormatString);
- if (pixelFormatEnum == EPixelFormat::ePixelFormat_Unknown)
- {
- return AZ::Failure(AZStd::string::format("Unsupported ePixelFormat detected: %s", pixelFormatString));
- }
-
- presetSettings.m_pixelFormat = pixelFormatEnum;
- presetSettings.m_pixelFormatName = CPixelFormats::GetInstance().GetPixelFormatInfo(pixelFormatEnum)->szName;
- }
- else if (key == "pixelformatalpha")
- {
- auto pixelFormatQBytes = INI_VALUE_QSTRING().toUtf8();
- const char* pixelFormatString = pixelFormatQBytes.constData();
-
- EPixelFormat pixelFormatEnum = CPixelFormats::GetInstance().FindPixelFormatByLegacyName(pixelFormatString);
- if (pixelFormatEnum == EPixelFormat::ePixelFormat_Unknown)
- {
- return AZ::Failure(AZStd::string::format("Unsupported ePixelFormat detected: %s", pixelFormatString));
- }
-
- presetSettings.m_pixelFormatAlpha = pixelFormatEnum;
- presetSettings.m_pixelFormatAlphaName = CPixelFormats::GetInstance().GetPixelFormatInfo(pixelFormatEnum)->szName;
- }
- else if (key == "maxtexturesize")
- {
- bool isOk = false;
- auto maxTextureSize = INI_VALUE().toUInt(&isOk);
- if (isOk)
- {
- presetSettings.m_maxTextureSize = maxTextureSize;
- }
- else
- {
- return AZ::Failure(AZStd::string::format("Invalid number for key 'maxtexturesize' for [%s]", presetSettings.m_name.c_str()));
- }
- }
- else if (key == "mintexturesize")
- {
- bool isOk = false;
- auto minTextureSize = INI_VALUE().toUInt(&isOk);
- if (isOk)
- {
- presetSettings.m_minTextureSize = minTextureSize;
- }
- else
- {
- return AZ::Failure(AZStd::string::format("Invalid number for key 'mintexturesize' for [%s]", presetSettings.m_name.c_str()));
- }
- }
- /************************************************************************/
- /* CUBEMAP PRESET SETTINGS */
- /************************************************************************/
- else if (key == "cm")
- {
- if (presetSettings.m_cubemapSetting == nullptr && INI_VALUE().toBool())
- {
- presetSettings.m_cubemapSetting = AZStd::make_unique();
- }
- else
- {
- return AZ::Failure(AZStd::string("Multiple CubeMap settings detected. Reduce to a single settings entry."));
- }
- }
- else if (key == "cm_ftype")
- {
- if (presetSettings.m_cubemapSetting == nullptr)
- {
- if (rcINI.value("cm").toBool())
- {
- presetSettings.m_cubemapSetting = AZStd::make_unique();
- }
- }
-
- if (presetSettings.m_cubemapSetting)
- {
- auto filterTypeStr = INI_VALUE_QSTRING().toUtf8();
- auto filterTypeIter = cubemapFilterTypeMap.find(filterTypeStr);
- if (filterTypeIter != cubemapFilterTypeMap.end())
- {
- presetSettings.m_cubemapSetting->m_filter = filterTypeIter->second;
- }
- else
- {
- return AZ::Failure(AZStd::string("Unmapped cubemap filter type enum detected."));
- }
- }
- }
- else if (key == "cm_fangle")
- {
- if (presetSettings.m_cubemapSetting == nullptr)
- {
- if (rcINI.value("cm").toBool())
- {
- presetSettings.m_cubemapSetting = AZStd::make_unique();
- presetSettings.m_cubemapSetting->m_angle = INI_VALUE().toFloat();
- }
- }
- else
- {
- presetSettings.m_cubemapSetting->m_angle = INI_VALUE().toFloat();
- }
- }
- else if (key == "cm_fmipangle")
- {
- if (presetSettings.m_cubemapSetting == nullptr)
- {
- if (rcINI.value("cm").toBool())
- {
- presetSettings.m_cubemapSetting = AZStd::make_unique();
- presetSettings.m_cubemapSetting->m_mipAngle = INI_VALUE().toFloat();
- }
- }
- else
- {
- presetSettings.m_cubemapSetting->m_mipAngle = INI_VALUE().toFloat();
- }
- }
- else if (key == "cm_fmipslope")
- {
- if (presetSettings.m_cubemapSetting == nullptr)
- {
- if (rcINI.value("cm").toBool())
- {
- presetSettings.m_cubemapSetting = AZStd::make_unique();
- presetSettings.m_cubemapSetting->m_mipSlope = INI_VALUE().toFloat();
- }
- }
- else
- {
- presetSettings.m_cubemapSetting->m_mipSlope = INI_VALUE().toFloat();
- }
- }
- else if (key == "cm_edgefixup")
- {
- if (presetSettings.m_cubemapSetting == nullptr)
- {
- if (rcINI.value("cm").toBool())
- {
- presetSettings.m_cubemapSetting = AZStd::make_unique();
- presetSettings.m_cubemapSetting->m_edgeFixup = INI_VALUE().toFloat();
- }
- }
- else
- {
- presetSettings.m_cubemapSetting->m_edgeFixup = INI_VALUE().toFloat();
- }
- }
- else if (key == "cm_diff")
- {
- if (presetSettings.m_cubemapSetting == nullptr)
- {
- if (rcINI.value("cm").toBool())
- {
- presetSettings.m_cubemapSetting = AZStd::make_unique();
- presetSettings.m_cubemapSetting->m_generateDiff = INI_VALUE().toBool();
- }
- }
- else
- {
- presetSettings.m_cubemapSetting->m_generateDiff = INI_VALUE().toBool();
- }
- }
- else if (key == "cm_diffpreset")
- {
- QByteArray presetNameByteArray = INI_VALUE().toString().toUtf8();
- AZ::Uuid presetID = BuilderSettingManager::Instance()->GetPresetIdFromName(presetNameByteArray.constData());
- if (presetID.IsNull())
- {
- return STRING_OUTCOME_ERROR(AZStd::string::format("Parsing error [cm_diffpreset]. Unable to find UUID for preset: %s", presetNameByteArray.constData()));
- }
-
- if (presetSettings.m_cubemapSetting == nullptr)
- {
- if (rcINI.value("cm").toBool())
- {
- presetSettings.m_cubemapSetting = AZStd::make_unique();
- presetSettings.m_cubemapSetting->m_diffuseGenPreset = presetID;
- }
- }
- else
- {
- presetSettings.m_cubemapSetting->m_diffuseGenPreset = presetID;
- }
- }
- /************************************************************************/
- /* MIPMAP PRESET SETTINGS */
- /************************************************************************/
- else if (key == "mipmaps")
- {
- // We convey whether 'mipmaps' is enabled/available by whether the pointer is valid or empty.
- if (presetSettings.m_mipmapSetting == nullptr && INI_VALUE().toBool())
- {
- presetSettings.m_mipmapSetting = AZStd::make_unique();
- }
- }
- else if (key == "mipgentype")
- {
- // We must handle parsing settings of missing/disabled parent settings ("mipmaps")
- if (rcINI.value("mipmaps") == QVariant())
- {
- return AZ::Failure(AZStd::string("'mipgentype' specified, but dependent 'mipmaps' setting is missing in rc.ini."));
- }
-
- // If we are missing the mipmap settings (possibly yet to be parsed)...
- if (presetSettings.m_mipmapSetting == nullptr)
- {
- if (rcINI.value("mipmaps").toBool())
- {
- presetSettings.m_mipmapSetting = AZStd::make_unique();
- }
- else
- {
- return AZ::Failure(AZStd::string::format(
- "Cannot assign 'mipgentype' because current Preset [%s] has 'mipmaps' disabled.", presetSettings.m_name.c_str()));
- }
- }
-
- presetSettings.m_mipmapSetting->m_type = MipGenType::blackmanHarris;
- if ("average" == INI_VALUE_QSTRING().toUtf8())
- {
- presetSettings.m_mipmapSetting->m_type = MipGenType::box;
- }
- }
- else
- {
- QByteArray keyByteArray = key.toUtf8();
- return STRING_OUTCOME_WARNING(AZStd::string::format("Unsupported key parsed from RC.ini: %s", keyByteArray.constData()));
- }
-
- return STRING_OUTCOME_SUCCESS;
- }
-
- void LoadPresetAliasFromRC(QSettings& rcINI, AZStd::map & presetAliases)
- {
- rcINI.beginGroup("_presetAliases");
-
- for (QString legacyPresetString : rcINI.childKeys())
- {
- QString modernPresetString = rcINI.value(legacyPresetString).toString();
-
- // We must store this intermediary data in order to convert to a c-string.
- QByteArray legacyPresetUtf8 = legacyPresetString.toUtf8();
- QByteArray modernPresetUtf8 = modernPresetString.toUtf8();
-
- PresetName legacyPresetName(legacyPresetUtf8.constData());
- PresetName modernPresetName(modernPresetUtf8.constData());
-
- presetAliases.insert(AZStd::pair(legacyPresetName, modernPresetName));
- }
-
- rcINI.endGroup();
- }
-
- void BuilderSettingManager::Reflect(AZ::ReflectContext* context)
- {
- AZ::SerializeContext* serialize = azrtti_cast(context);
- if (serialize)
- {
- serialize->Class()
- ->Version(1)
- ->Field("BuildSettings", &BuilderSettingManager::m_builderSettings)
- ->Field("PresetAliases", &BuilderSettingManager::m_presetAliases)
- ->Field("DefaultPresetsByFileMask", &BuilderSettingManager::m_defaultPresetByFileMask)
- ->Field("DefaultPreset", &BuilderSettingManager::m_defaultPreset)
- ->Field("DefaultPresetAlpha", &BuilderSettingManager::m_defaultPresetAlpha)
- ->Field("DefaultPresetNonePOT", &BuilderSettingManager::m_defaultPresetNonePOT);
- }
- }
-
- BuilderSettingManager* BuilderSettingManager::Instance()
- {
- AZStd::lock_guard lock(s_instanceMutex);
-
- if (!s_globalInstance)
- {
- s_globalInstance = AZ::Environment::FindVariable(s_environmentVariableName);
- }
- AZ_Assert(s_globalInstance, "BuilderSettingManager not created!");
-
- return s_globalInstance.Get();
- }
-
- void BuilderSettingManager::CreateInstance()
- {
- AZStd::lock_guard lock(s_instanceMutex);
-
- if (s_globalInstance)
- {
- AZ_Assert(false, "BuilderSettingManager already created!");
- return;
- }
-
- if (!s_globalInstance)
- {
- s_globalInstance = AZ::Environment::CreateVariable(s_environmentVariableName);
- }
- if (!s_globalInstance.Get())
- {
- s_globalInstance.Set(aznew BuilderSettingManager());
- }
- }
-
- void BuilderSettingManager::DestroyInstance()
- {
- AZStd::lock_guard 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 AZ::Uuid presetId, const PlatformName& platform)
- {
- AZStd::lock_guard lock(m_presetMapLock);
- PlatformName platformName = platform;
- if (platformName.empty())
- {
- platformName = BuilderSettingManager::s_defaultPlatform;
- }
-
- if (m_builderSettings.find(platformName) != m_builderSettings.end())
- {
- const BuilderSettings& platformBuilderSetting = m_builderSettings[platformName];
- auto settingsIter = platformBuilderSetting.m_presets.find(presetId);
- if (settingsIter != platformBuilderSetting.m_presets.end())
- {
- return &settingsIter->second;
- }
- else
- {
- AZ_Error("Image Processing", false, "Cannot find preset settings on platform [%s] for preset id: %s", platformName.c_str(), presetId.ToString().c_str());
- }
- }
- else
- {
- AZ_Error("Image Processing", false, "Cannot find platform [%s]", platformName.c_str());
- }
-
- return nullptr;
- }
-
-
- const BuilderSettings* BuilderSettingManager::GetBuilderSetting(const PlatformName& platform)
- {
- if (m_builderSettings.find(platform) != m_builderSettings.end())
- {
- return &m_builderSettings[platform];
- }
- return nullptr;
- }
-
- const PlatformNameList BuilderSettingManager::GetPlatformList()
- {
- PlatformNameList platforms;
-
- for(auto& builderSetting : m_builderSettings)
- {
- if (builderSetting.second.m_enablePlatform)
- {
- platforms.push_back(builderSetting.first);
- }
- }
-
- return platforms;
- }
-
- const AZStd::map >& BuilderSettingManager::GetPresetFilterMap()
- {
- AZStd::lock_guard lock(m_presetMapLock);
- return m_presetFilterMap;
- }
-
- const AZ::Uuid BuilderSettingManager::GetPresetIdFromName(const PresetName& presetName)
- {
- AZStd::lock_guard lock(m_presetMapLock);
-
- // Each preset shares the same UUID across platforms, therefore, it's safe to pick a random
- // platform to search for the preset UUID. We'll use PC, in this case.
- const PlatformName defaultPlatform = BuilderSettingManager::s_defaultPlatform;
- if (m_builderSettings.find(defaultPlatform) != m_builderSettings.end())
- {
- auto presets = m_builderSettings[defaultPlatform].m_presets;
-
- for (auto curIter : presets)
- {
- if (curIter.second.m_name == presetName)
- {
- return curIter.first;
- }
- }
- }
-
- return AZ::Uuid::CreateNull();
- }
-
- const PresetName BuilderSettingManager::GetPresetNameFromId(const AZ::Uuid& presetId)
- {
- AZStd::lock_guard lock(m_presetMapLock);
- const PlatformName defaultPlatform = BuilderSettingManager::s_defaultPlatform;
- if (m_builderSettings.find(defaultPlatform) != m_builderSettings.end())
- {
- auto& presetMap = m_builderSettings[defaultPlatform].m_presets;
- auto presetIter = presetMap.find(presetId);
- if (presetIter != presetMap.end())
- {
- return presetIter->second.m_name;
- }
- }
-
- return "Unknown";
- }
-
- void BuilderSettingManager::ClearSettings()
- {
- AZStd::lock_guard lock(m_presetMapLock);
- m_presetFilterMap.clear();
- m_presetAliases.clear();
- m_builderSettings.clear();
- }
-
- StringOutcome BuilderSettingManager::LoadBuilderSettings()
- {
- StringOutcome outcome = STRING_OUTCOME_ERROR("");
- // Construct the project setting path that is used by the tool for loading setting file
- const char* gameFolderPath = nullptr;
- AzToolsFramework::AssetSystemRequestBus::BroadcastResult(gameFolderPath, &AzToolsFramework::AssetSystemRequestBus::Events::GetAbsoluteDevGameFolderPath);
- AZStd::string projectSettingPath = "";
-
- if (gameFolderPath)
- {
- AzFramework::StringFunc::Path::Join(gameFolderPath, "Config/ImageBuilder/ImageBuilderPresets.settings", projectSettingPath);
- outcome = LoadBuilderSettings(projectSettingPath);
- }
-
- if (!outcome.IsSuccess())
- {
- AZ_TracePrintf(AssetBuilderSDK::InfoWindow, "Failed to read project specific preset setting at [%s], will use default setting file.\n", projectSettingPath.c_str());
- // Construct the default setting path
- const char* engineRoot = nullptr;
- AzFramework::ApplicationRequests::Bus::BroadcastResult(engineRoot, &AzFramework::ApplicationRequests::GetEngineRoot);
-
- if (engineRoot)
- {
- AZStd::string defaultSettingPath = "";
- AzFramework::StringFunc::Path::Join(engineRoot, "Gems/ImageProcessing/Code/Source/ImageBuilderDefaultPresets.settings", defaultSettingPath);
- outcome = LoadBuilderSettings(defaultSettingPath);
- }
- }
-
- return outcome;
- }
-
- StringOutcome BuilderSettingManager::LoadBuilderSettings(AZStd::string filepath, AZ::SerializeContext* context)
- {
- // Ensure filepath exists.
- AZ::IO::FileIOBase* fileReader = AZ::IO::FileIOBase::GetInstance();
- if(false == fileReader->Exists(filepath.c_str()))
- {
- return AZ::Failure(AZStd::string::format("Build settings file not found: %s", filepath.c_str()));
- }
-
- AZ::IO::HandleType settingsFileHandle;
- m_builderSettingsFileVersion = 0;
- if (fileReader->Open(filepath.c_str(), AZ::IO::OpenMode::ModeRead | AZ::IO::OpenMode::ModeBinary, settingsFileHandle) == AZ::IO::ResultCode::Success)
- {
- // Read the contents of the file and hash it. The first u32 of the result of this will be used as a version
- // number. Any changes to the builder settings file will then cause all textures to be reconverted to pick
- // up that change.
- AZStd::string settingsFileBuffer;
- AZ::u64 settingsFileSize = 0;
- fileReader->Size(settingsFileHandle, settingsFileSize);
- settingsFileBuffer.resize_no_construct(settingsFileSize);
- fileReader->Read(settingsFileHandle, settingsFileBuffer.data(), settingsFileSize);
- fileReader->Close(settingsFileHandle);
-
- AZ::Sha1 block;
- AZ::u32 hashDigest[5];
- block.ProcessBytes(settingsFileBuffer.data(), settingsFileSize);
- block.GetDigest(hashDigest);
- m_builderSettingsFileVersion = hashDigest[0];
- }
-
- auto loadedSettingsPtr = AZStd::unique_ptr(AZ::Utils::LoadObjectFromFile(filepath, context));
-
- // Ensure file is loaded.
- if (!loadedSettingsPtr)
- {
- return AZ::Failure(AZStd::string::format("Failed to read from file: %s", filepath.c_str()));
- }
-
- m_presetMapLock.lock();
- // Normally, we would perform a deep-copy from the loaded settings onto 'this' via assignment operator overload. However, we have deleted our
- // assignment operator overloads, because we intend for this class to be a singleton. Instead, we will manually perform a deep-copy
- // in this function since it's the only time we require something akin to assignment operation.
- m_builderSettings = loadedSettingsPtr->m_builderSettings;
- m_presetAliases = loadedSettingsPtr->m_presetAliases;
- m_defaultPresetByFileMask = loadedSettingsPtr->m_defaultPresetByFileMask;
- m_defaultPreset = loadedSettingsPtr->m_defaultPreset;
- m_defaultPresetAlpha = loadedSettingsPtr->m_defaultPresetAlpha;
- m_defaultPresetNonePOT = loadedSettingsPtr->m_defaultPresetNonePOT;
-
- m_presetFilterMap.clear();
-
- //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
-
- //convert pixel format string to enum for each preset
- for (auto& buildSetting : m_builderSettings)
- {
- for (auto& preset : buildSetting.second.m_presets)
- {
- preset.second.m_pixelFormat = CPixelFormats::GetInstance().FindPixelFormatByName(preset.second.m_pixelFormatName.c_str());
- preset.second.m_pixelFormatAlpha = CPixelFormats::GetInstance().FindPixelFormatByName(preset.second.m_pixelFormatAlphaName.c_str());
- }
- }
- m_presetMapLock.unlock();
-
- RegenerateMappings();
-
- return AZ::Success(AZStd::string());
- }
-
- StringOutcome BuilderSettingManager::WriteBuilderSettings(AZStd::string filepath, AZ::SerializeContext* context)
- {
- if( false == AZ::Utils::SaveObjectToFile(filepath, AZ::DataStream::StreamType::ST_XML, this, context))
- {
- return STRING_OUTCOME_ERROR(AZStd::string::format("Failed to write file: %s", filepath.c_str()));
- }
- return STRING_OUTCOME_SUCCESS;
- }
-
- const PresetName BuilderSettingManager::TranslateLegacyPresetName(const PresetName& legacyName)
- {
- auto iterResult = m_presetAliases.find(legacyName);
-
- if (iterResult == m_presetAliases.end())
- {
- return legacyName;
- }
-
- return iterResult->second;
- }
-
- StringOutcome BuilderSettingManager::LoadBuilderSettingsFromRC(AZStd::string& filePath)
- {
- //Clear previous settings first
- ClearSettings();
-
- // Find all the platforms
- auto outcome = GetPlatformNamesFromRC(filePath);
- AZ_ENSURE_STRING_OUTCOME(outcome);
- PlatformNameVector all_platforms = outcome.TakeValue();
-
- m_presetMapLock.lock();
- // Register all the platforms with empty settings.
- for (const AZStd::string& platformName : all_platforms)
- {
- auto newEntry = AZStd::pair(platformName, BuilderSettings());
- m_builderSettings.insert(newEntry);
- }
-
- // Open settings for parsing
- QSettings set(filePath.c_str(), QSettings::IniFormat);
-
- // Load the preset alias mapping
- LoadPresetAliasFromRC(set, m_presetAliases);
-
- QStringList childGroups = set.childGroups();
- QStringList exemptGroups;
- exemptGroups.append("_platform");
- exemptGroups.append("_presetAliases");
-
- // We must generate new preset settings and UUID's prior to parsing the rest of the data, because
- // some preset settings make references to other presets within RC.ini. We must make sure all presets
- // are identified, before making references to them via their UUID.
- for (QString groupName : childGroups)
- {
- auto newPresetUuid = AZ::Uuid::CreateRandom();
- PresetSettings newPresetSetting;
- newPresetSetting.m_name = groupName.toUtf8().constData();
- newPresetSetting.m_uuid = newPresetUuid;
- for (const PlatformName& platform : all_platforms)
- {
- m_builderSettings[platform].m_presets.insert(AZStd::make_pair(newPresetUuid, newPresetSetting));
- }
- }
- m_presetMapLock.unlock();
-
- // Apply preset settings from file to the existing presets (process each platform).
- for(QString groupName : childGroups)
- {
- // Only process Presets from here on out.
- if (exemptGroups.contains(groupName))
- {
- continue;
- }
-
- auto outcome2 = ProcessPreset(groupName, set, all_platforms);
- AZ_ENSURE_STRING_OUTCOME(outcome2);
- }
-
- RegenerateMappings();
-
- // The original rc.ini doesn't have the information below. Included here for GetSuggestedPreset() to work properly.
- m_defaultPresetByFileMask["_diff"] = GetPresetIdFromName("Albedo");
- m_defaultPresetByFileMask["_spec"] = GetPresetIdFromName("Reflectance");
- m_defaultPresetByFileMask["_refl"] = GetPresetIdFromName("Reflectance");
- m_defaultPresetByFileMask["_ddn"] = GetPresetIdFromName("Normals");
- m_defaultPresetByFileMask["_ddna"] = GetPresetIdFromName("NormalsWithSmoothness");
- m_defaultPresetByFileMask["_cch"] = GetPresetIdFromName("ColorChart");
- m_defaultPresetByFileMask["_cm"] = GetPresetIdFromName("EnvironmentProbeHDR");
-
- m_defaultPreset = GetPresetIdFromName("Albedo");
- m_defaultPresetAlpha = GetPresetIdFromName("AlbedoWithGenericAlpha");
- m_defaultPresetNonePOT = GetPresetIdFromName("ReferenceImage");
-
- return STRING_OUTCOME_SUCCESS;
- }
-
- AZ::u32 BuilderSettingManager::BuilderSettingsVersion() const
- {
- return m_builderSettingsFileVersion;
- }
-
- void BuilderSettingManager::RegenerateMappings()
- {
- AZStd::lock_guard lock(m_presetMapLock);
-
- AZStd::string noFilter = AZStd::string();
-
- m_presetFilterMap.clear();
-
- for (auto& builderSettingIter : m_builderSettings)
- {
- const BuilderSettings& builderSetting = builderSettingIter.second;
- for (auto& presetIter : builderSetting.m_presets)
- {
- //Put into no filter preset list
- m_presetFilterMap[noFilter].insert(presetIter.second.m_name);
-
- //Put into file mask preset list if any
- for (const PlatformName& filemask : presetIter.second.m_fileMasks)
- {
- m_presetFilterMap[filemask].insert(presetIter.second.m_name);
- }
- }
- }
- }
-
- StringOutcome BuilderSettingManager::ProcessPreset(QString& preset, QSettings& rcINI, PlatformNameVector& all_platforms)
- {
- // Early-out check. We should have the preset available before processing.
- QByteArray presetByteArray = preset.toUtf8();
- AZ::Uuid parsingPresetUuid = GetPresetIdFromName(presetByteArray.constData());
- if (parsingPresetUuid.IsNull())
- {
- return STRING_OUTCOME_ERROR(AZStd::string::format("Unable to find UUID for preset: %s", presetByteArray.constData()));
- }
-
- rcINI.beginGroup(preset);
- QStringList groupKeys = rcINI.allKeys();
-
- // Build a list for common & platform-specific settings
- QStringList commonPresetSettingKeys;
- QStringList platformSpecificPresetSettingKeys;
- for (QString key : groupKeys)
- {
- if (key.contains(":"))
- {
- platformSpecificPresetSettingKeys.append(key);
- }
- else
- {
- commonPresetSettingKeys.append(key);
- }
- }
-
- // Parse the common settings (retain preset name & uuid)
- PresetSettings commonPresetSettings;
- commonPresetSettings.m_name = presetByteArray.constData();
- commonPresetSettings.m_uuid = parsingPresetUuid;
- for (QString settingKey : commonPresetSettingKeys)
- {
- AZ_ENSURE_STRING_OUTCOME(ParseKeyToData(settingKey, rcINI, commonPresetSettings));
- }
-
- // When loading a preset, the UUID is the same per-preset, regardless of the target-platform.
- for (AZStd::string& platformId : all_platforms)
- {
- // Begin platform-specific settings loading with a copy of common Preset settings.
- PresetSettings currentPlatformPresetSetting = commonPresetSettings;
-
- // Obtain platform-specific settings
- QString platformFilter = QString(":%1").arg(platformId.c_str()); // Example results-> ":ios", ":osx", ":es3"
- QStringList currentPlatformSettings = platformSpecificPresetSettingKeys.filter(platformFilter);
-
- // Overwrite values for platform-specific settings...
- for (QString platformSetting : currentPlatformSettings)
- {
- AZ_ENSURE_STRING_OUTCOME(ParseKeyToData(platformSetting, rcINI, currentPlatformPresetSetting));
- }
-
- // Assign the overridden platform preset settings to the BuilderSettingManager.
- m_builderSettings[platformId].m_presets[parsingPresetUuid] = currentPlatformPresetSetting;
- }
-
- rcINI.endGroup();
- return STRING_OUTCOME_SUCCESS;
- }
-
- void BuilderSettingManager::MetafilePathFromImagePath(const AZStd::string& imagePath, AZStd::string& metafilePath)
- {
- // Determine if we have a meta file (legacy or modern).
- AZ::IO::LocalFileIO fileIO;
-
- AZStd::string modernMetaFilepath = imagePath + TextureSettings::modernExtensionName;
- if (fileIO.Exists(modernMetaFilepath.c_str()))
- {
- metafilePath = modernMetaFilepath;
- return;
- }
-
- AZStd::string legacyMetaFilepath = imagePath + TextureSettings::legacyExtensionName;
- if (fileIO.Exists(legacyMetaFilepath.c_str()))
- {
- metafilePath = legacyMetaFilepath;
- return;
- }
-
- // We found neither.
- metafilePath = AZStd::string();
- }
-
- AZStd::string GetFileMask(const AZStd::string& imageFilePath)
- {
- //get file name
- AZStd::string fileName;
- QString lowerFileName = imageFilePath.c_str();
- lowerFileName = lowerFileName.toLower();
- AzFramework::StringFunc::Path::GetFileName(lowerFileName.toUtf8().constData(), fileName);
-
- //get the substring from last '_'
- size_t lastUnderScore = fileName.find_last_of('_');
- if (lastUnderScore != AZStd::string::npos)
- {
- return fileName.substr(lastUnderScore);
- }
-
- return AZStd::string();
- }
-
- AZ::Uuid BuilderSettingManager::GetSuggestedPreset(const AZStd::string& imageFilePath, IImageObjectPtr imageFromFile)
- {
- //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)
- {
- AZ_Error("Image Processing", image, "Cannot load image file [%s]. Invalid image format or corrupt data. Note that \"Indexed Color\" is not currently supported for .tga files.", imageFilePath.c_str());
- return AZ::Uuid::CreateNull();
- }
-
- //get file mask of this image file
- AZStd::string fileMask = GetFileMask(imageFilePath);
-
- AZ::Uuid outPreset = AZ::Uuid::CreateNull();
-
- if ("_diff" == fileMask && image->GetAlphaContent() != EAlphaContent::eAlphaContent_Absent)
- {
- outPreset = m_defaultPresetAlpha;
- }
- else
- {
- //check default presets for some file masks
- if (m_defaultPresetByFileMask.find(fileMask) != m_defaultPresetByFileMask.end())
- {
- outPreset = m_defaultPresetByFileMask[fileMask];
- }
- }
-
- //use the preset filter map to find
- if (outPreset.IsNull() && !fileMask.empty())
- {
- auto& presetFilterMap = GetPresetFilterMap();
- if (presetFilterMap.find(fileMask) != presetFilterMap.end())
- {
- AZStd::string presetName = *(presetFilterMap.find(fileMask)->second.begin());
- outPreset = GetPresetIdFromName(presetName);
- }
- }
-
- const PresetSettings* presetInfo = nullptr;
-
- if (!outPreset.IsNull())
- {
- presetInfo = GetPreset(outPreset);
-
- //special case for cubemap
- if (presetInfo && presetInfo->m_cubemapSetting)
- {
- if (CubemapLayout::GetCubemapLayoutInfo(image) == nullptr)
- {
- outPreset = AZ::Uuid::CreateNull();
- }
- }
- }
-
- if (outPreset.IsNull())
- {
- if (!image->HasPowerOfTwoSizes())
- {
- // The resource compiler used the non power of 2 preset if the width or the height is not power of 2
- // even if it would have been possible to compress the image, so this behavior is matched here.
- return m_defaultPresetNonePOT;
- }
- else if (image->GetAlphaContent() == EAlphaContent::eAlphaContent_Absent)
- {
- outPreset = m_defaultPreset;
- }
- else
- {
- outPreset = m_defaultPresetAlpha;
- }
- }
-
- //get the pixel format for selected preset
- presetInfo = GetPreset(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;
- }
- }
-
- //uncompressed one which could be used for almost everything
- return m_defaultPresetNonePOT;
- }
-
- bool BuilderSettingManager::DoesSupportPlatform(const AZStd::string& platformId)
- {
- bool rv = m_builderSettings.find(platformId) != m_builderSettings.end();
- return rv;
- }
-
-} // namespace ImageProcessing
diff --git a/Gems/ImageProcessing/Code/Source/BuilderSettings/BuilderSettingManager.h b/Gems/ImageProcessing/Code/Source/BuilderSettings/BuilderSettingManager.h
deleted file mode 100644
index c6d03eae54..0000000000
--- a/Gems/ImageProcessing/Code/Source/BuilderSettings/BuilderSettingManager.h
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
-* 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.
-*
-*/
-
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-
-class QSettings;
-class QString;
-
-namespace AZ
-{
- template class EnvironmentVariable;
- class SerializeContext;
-}
-
-namespace ImageProcessing
-{
- class BuilderSettingManager
- {
- public:
- AZ_TYPE_INFO(CBuilderSettingManager, "{DAA55241-64FA-4A9B-A37F-C0A36B36D536}");
- AZ_CLASS_ALLOCATOR(BuilderSettingManager, AZ::SystemAllocator, 0);
- //load builder settings for all platform
- //contain builder setting for all platforms
- //this manager should be able to get texture setting for a platform
-
-
- static BuilderSettingManager* Instance();
- // life cycle management:
- static void CreateInstance();
- static void DestroyInstance();
- static void Reflect(AZ::ReflectContext* context);
-
- const PresetSettings* GetPreset(const AZ::Uuid presetId, const PlatformName& platform = "");
-
- const BuilderSettings* GetBuilderSetting(const PlatformName& platform);
-
- /**
- * Attempts to translate a legacy preset name into Open 3D Engine preset name.
- * @param legacy preset name string
- * @return A translated preset name. If no translation is available, returns the same value as input argument.
- */
- const PresetName TranslateLegacyPresetName(const PresetName& legacyName);
-
- /**
- * @return A list of platform supported
- */
- const PlatformNameList GetPlatformList();
-
- /**
- * @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>& GetPresetFilterMap();
-
- /**
- * Find preset id list based on the preset name.
- * @param preset name string
- * @return a map of preset ids whose name are specified by the input on different platforms
- * @key platform name string
- * @value uuid of the preset setting
- */
- const AZ::Uuid GetPresetIdFromName(const PresetName& presetName);
-
- /**
- * Find preset name based on the preset id.
- * @param uuid of the preset setting
- * @return preset name string
- */
- const PresetName GetPresetNameFromId(const AZ::Uuid& presetId);
-
- /**
- * Writes preset data to file using AZ::Serialization format.
- * @param filepath string to the build settings xml
- */
- StringOutcome WriteBuilderSettings(AZStd::string filepath, AZ::SerializeContext* context = nullptr);
-
- /**
- * Loads preset data from file using AZ::Serialization format.
- * @param filepath string to the build settings xml
- */
- StringOutcome LoadBuilderSettings(AZStd::string filepath, AZ::SerializeContext* context = nullptr);
-
- /**
- * Overload function. Loads preset data from project setting file if any
- * Otherwise, the function will load default setting file inside the gem
- */
- StringOutcome LoadBuilderSettings();
-
- /**
- * Loads preset data from legacy format found in RC.ini.
- * @param filepath string to RC.ini
- */
- StringOutcome LoadBuilderSettingsFromRC(AZStd::string& filePath);
-
- /**
- * Returns the first u32 generated from a hash of the builder settings
- * file that can be used as a version to detect changes to the file.
- */
- AZ::u32 BuilderSettingsVersion() const;
-
- /**
- * Provides a full path to the adjacent metafile of a given texture/image file.
- * @param Filepath string to the texture/image file.
- * @param Output filepath string to the adjacent texture/image metafile.
- * Will output whichever metafile is present, whether it is legacy or modern format.
- * If both are present, modern format is returned.
- * If none are present, an empty string is returned.
- */
- void MetafilePathFromImagePath(const AZStd::string& imagePath, AZStd::string& metafilePath);
-
- /**
- * Find a suitable preset a given image file.
- * @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 uuid.
- */
- AZ::Uuid GetSuggestedPreset(const AZStd::string& imageFilePath, IImageObjectPtr image = nullptr);
-
- bool DoesSupportPlatform(const AZStd::string& platformId);
-
- static const char* s_environmentVariableName;
- static AZ::EnvironmentVariable s_globalInstance;
- static AZStd::mutex s_instanceMutex;
- static const PlatformName s_defaultPlatform;
-
- BuilderSettingManager(){}
-
- private: // functions
- AZ_DISABLE_COPY_MOVE(BuilderSettingManager);
-
- StringOutcome ProcessPreset(QString& preset, QSettings& rcINI, PlatformNameVector& all_platforms);
-
- /**
- * Clear Builder Settings and any cached maps/lists
- */
- void ClearSettings();
-
- /**
- * Regenerate Builder Settings and any cached maps/lists
- */
- void RegenerateMappings();
-
- private: // variables
-
- //builder settings for each platform
- AZStd::map m_builderSettings;
- AZStd::map m_presetAliases;
-
- /**
- * Cached 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 > m_presetFilterMap;
-
- /**
- * A mutex to protect when modifying any map in this manager
- */
- AZStd::mutex m_presetMapLock;
-
- //default presets for certian file masks
- AZStd::map m_defaultPresetByFileMask;
-
- //default preset for none power of two image
- AZ::Uuid m_defaultPresetNonePOT;
-
- //default preset for power of two
- AZ::Uuid m_defaultPreset;
-
- //default preset for power of two with alpha
- AZ::Uuid m_defaultPresetAlpha;
-
- //generated from hashing the builder settings file
- AZ::u32 m_builderSettingsFileVersion;
- };
-} // namespace ImageProcessing
diff --git a/Gems/ImageProcessing/Code/Source/BuilderSettings/BuilderSettings.cpp b/Gems/ImageProcessing/Code/Source/BuilderSettings/BuilderSettings.cpp
deleted file mode 100644
index 6f68ea7581..0000000000
--- a/Gems/ImageProcessing/Code/Source/BuilderSettings/BuilderSettings.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-* 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 "ImageProcessing_precompiled.h"
-#include
-#include
-
-namespace ImageProcessing
-{
- void BuilderSettings::Reflect(AZ::ReflectContext* context)
- {
- AZ::SerializeContext* serialize = azrtti_cast(context);
- if (serialize)
- {
- serialize->Class()
- ->Version(1)
- ->Field("GlossScale", &BuilderSettings::m_brdfGlossScale)
- ->Field("GlossBias", &BuilderSettings::m_brdfGlossBias)
- ->Field("Streaming", &BuilderSettings::m_enableStreaming)
- ->Field("Enable", &BuilderSettings::m_enablePlatform)
- ->Field("Presets", &BuilderSettings::m_presets);
- }
- }
-} // namespace ImageProcessing
diff --git a/Gems/ImageProcessing/Code/Source/BuilderSettings/BuilderSettings.h b/Gems/ImageProcessing/Code/Source/BuilderSettings/BuilderSettings.h
deleted file mode 100644
index 500b69f472..0000000000
--- a/Gems/ImageProcessing/Code/Source/BuilderSettings/BuilderSettings.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
-* 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.
-*
-*/
-
-#pragma once
-
-#include
-
-namespace ImageProcessing
-{
- //builder setting for a platform
- struct BuilderSettings
- {
- AZ_TYPE_INFO(BuilderSettings, "{4085AB56-934C-43A6-AF25-4443E1EEB71D}");
- AZ_CLASS_ALLOCATOR(BuilderSettings, AZ::SystemAllocator, 0);
- static void Reflect(AZ::ReflectContext* context);
-
- //global settings
- float m_brdfGlossScale = 16.0f;
- float m_brdfGlossBias = 0.0f;
- bool m_enableStreaming = true;
- bool m_enablePlatform = true;
- AZStd::map m_presets;
- };
-} // namespace ImageProcessing
diff --git a/Gems/ImageProcessing/Code/Source/BuilderSettings/CubemapSettings.cpp b/Gems/ImageProcessing/Code/Source/BuilderSettings/CubemapSettings.cpp
deleted file mode 100644
index 43f2a50535..0000000000
--- a/Gems/ImageProcessing/Code/Source/BuilderSettings/CubemapSettings.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
-* 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 "ImageProcessing_precompiled.h"
-#include
-#include
-
-namespace ImageProcessing
-{
-
- bool CubemapSettings::operator!=(const CubemapSettings& other)
- {
- return !(*this == other);
- }
-
- bool CubemapSettings::operator==(const CubemapSettings& other)
- {
- return
- m_angle == other.m_angle &&
- m_mipAngle == other.m_mipAngle &&
- m_mipSlope == other.m_mipSlope &&
- m_edgeFixup == other.m_edgeFixup &&
- m_generateDiff == other.m_generateDiff &&
- m_diffuseGenPreset == other.m_diffuseGenPreset;
- }
-
- void CubemapSettings::Reflect(AZ::ReflectContext* context)
- {
- AZ::SerializeContext* serialize = azrtti_cast(context);
- if (serialize)
- {
- serialize->Class()
- ->Version(1)
- ->Field("Filter", &CubemapSettings::m_filter)
- ->Field("Angle", &CubemapSettings::m_angle)
- ->Field("MipAngle", &CubemapSettings::m_mipAngle)
- ->Field("MipSlope", &CubemapSettings::m_mipSlope)
- ->Field("EdgeFixup", &CubemapSettings::m_edgeFixup)
- ->Field("GenerateDiff", &CubemapSettings::m_generateDiff)
- ->Field("DiffuseProbePreset", &CubemapSettings::m_diffuseGenPreset);
- }
- }
-} // namespace ImageProcessing
diff --git a/Gems/ImageProcessing/Code/Source/BuilderSettings/CubemapSettings.h b/Gems/ImageProcessing/Code/Source/BuilderSettings/CubemapSettings.h
deleted file mode 100644
index edfdde8cbe..0000000000
--- a/Gems/ImageProcessing/Code/Source/BuilderSettings/CubemapSettings.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
-* 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.
-*
-*/
-
-#pragma once
-
-#include
-#include
-#include
-#include
-
-namespace ImageProcessing
-{
- //! settings related to cubemap. Part of texture preset setting. only useful when cubemap enabled
- struct CubemapSettings
- {
- AZ_TYPE_INFO(CubemapSettings, "{C6BDEB7B-8E05-4B2D-8F39-8F6275BC84E8}");
- AZ_CLASS_ALLOCATOR(CubemapSettings, AZ::SystemAllocator, 0);
- bool operator!=(const CubemapSettings& other);
- bool operator==(const CubemapSettings& other);
- static void Reflect(AZ::ReflectContext* context);
-
- // "cm_ftype", cubemap angular filter type: gaussian, cone, disc, cosine, cosine_power, ggx
- CubemapFilterType m_filter;
-
- // "cm_fangle", base filter angle for cubemap filtering(degrees), 0 - disabled
- float m_angle;
-
- // "cm_fmipangle", initial mip filter angle for cubemap filtering(degrees), 0 - disabled
- float m_mipAngle;
-
- // "cm_fmipslope", mip filter angle multiplier for cubemap filtering, 1 - default"
- float m_mipSlope;
-
- // "cm_edgefixup", cubemap edge fix-up width, 0 - disabled
- float m_edgeFixup;
-
- // "cm_diff", generate a diffuse illumination light-probe in addition
- bool m_generateDiff;
-
- // "cm_diffpreset", the name of the preset to be used for the diffuse probe
- AZ::Uuid m_diffuseGenPreset;
- };
-} // namespace ImageProcessing
diff --git a/Gems/ImageProcessing/Code/Source/BuilderSettings/ImageProcessingDefines.h b/Gems/ImageProcessing/Code/Source/BuilderSettings/ImageProcessingDefines.h
deleted file mode 100644
index c9fa860240..0000000000
--- a/Gems/ImageProcessing/Code/Source/BuilderSettings/ImageProcessingDefines.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
-* 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.
-*
-*/
-
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-/**
-* Shorthand for checking a condition, and failing if false.
-* Works with any function that returns AZ::Outcome<..., AZStd::string>.
-* Unlike assert, it is not removed in release builds.
-* Ensure all strings are passed with c_str(), as they are passed to AZStd::string::format().
-*/
-#define AZ_ENSURE_STRING_OUTCOME_CONDITION(cond, ...) if (!(cond)) { return AZ::Failure(AZStd::string::format(__VA_ARGS__)); }
-
-// Similar to above macro, but ensures on an AZ::Outcome. Not removed in release builds.
-#define AZ_ENSURE_STRING_OUTCOME(outcome) if (!(outcome.IsSuccess())) { return AZ::Failure(outcome.GetError()); }
-
-namespace ImageProcessing
-{
- //! Common return type for operations that can fail.
- // Empty success string == Success.
- // Populated success string == Warning.
- // Populated error string == Failure.
- using StringOutcome = AZ::Outcome;
-#define STRING_OUTCOME_SUCCESS AZ::Success(AZStd::string())
-#define STRING_OUTCOME_WARNING(warning) AZ::Success(AZStd::string(warning))
-#define STRING_OUTCOME_ERROR(error) AZ::Failure(AZStd::string(error))
-
- // Common typedefs (with dependent forward-declarations)
- typedef AZStd::string PlatformName, PresetName, FileMask;
- typedef AZStd::vector PlatformNameVector;
- typedef AZStd::list PlatformNameList;
-
- //! min and max reduce level
- static const unsigned int s_MinReduceLevel = 0;
- static const unsigned int s_MaxReduceLevel = 5;
-
- static const int s_TotalSupportedImageExtensions = 8;
- static const char* s_SupportedImageExtensions[s_TotalSupportedImageExtensions] = {
- "*.tif",
- "*.tiff",
- "*.png",
- "*.bmp",
- "*.jpg",
- "*.jpeg",
- "*.tga",
- "*.gif"
- };
-
- enum class RGBWeight : AZ::u32
- {
- uniform, // uniform weights (1.0, 1.0, 1.0) (default)
- luminance, // luminance-based weights (0.3086, 0.6094, 0.0820)
- ciexyz // ciexyz-based weights (0.2126, 0.7152, 0.0722)
- };
-
- enum class ColorSpace : AZ::u32
- {
- linear,
- sRGB,
- autoSelect,
- };
-
- enum class MipGenType : AZ::u32
- {
- point, //Also called nearest neighbor
- box, //Also called 'average'. When shrinking images it will average, and merge the pixels together.
- triangle, //Also called linear or Bartlett window
- quadratic, //Also called bilinear or Welch window
- gaussian, //It remove high frequency noise in a highly controllable way.
- blackmanHarris,
- kaiserSinc //Good for foliage and tree assets exported from Speedtree.
- };
-
- enum class MipGenEvalType : AZ::u32
- {
- sum,
- max,
- min
- };
-
- //cubemap angular filter type. Only two filter types were used in rc.ini
- enum class CubemapFilterType : AZ::u32
- {
- disc = 0, // same as CP_FILTER_TYPE_DISC in CubemapGen
- cone = 1, // same as CP_FILTER_TYPE_CONE
- cosine = 2, // same as CP_FILTER_TYPE_COSINE. only used for [EnvironmentProbeHDR_Irradiance]
- gaussian = 3, // same as CP_FILTER_TYPE_ANGULAR_GAUSSIAN
- cosine_power = 4, // same as CP_FILTER_TYPE_COSINE_POWER
- ggx = 5 // same as CP_FILTER_TYPE_GGX. only used for [EnvironmentProbeHDR]
- };
-
-} // namespace ImageProcessing
diff --git a/Gems/ImageProcessing/Code/Source/BuilderSettings/MipmapSettings.cpp b/Gems/ImageProcessing/Code/Source/BuilderSettings/MipmapSettings.cpp
deleted file mode 100644
index 0285404f50..0000000000
--- a/Gems/ImageProcessing/Code/Source/BuilderSettings/MipmapSettings.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-* 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 "ImageProcessing_precompiled.h"
-#include
-#include
-#include
-
-namespace ImageProcessing
-{
- bool MipmapSettings::operator!=(const MipmapSettings& other) const
- {
- return !(*this == other);
- }
-
- bool MipmapSettings::operator==(const MipmapSettings& other) const
- {
- return
- m_type == other.m_type &&
- m_borderColor == other.m_borderColor &&
- m_normalize == other.m_normalize &&
- m_streamableMips == other.m_streamableMips;
- }
-
- void MipmapSettings::Reflect(AZ::ReflectContext* context)
- {
- AZ::SerializeContext* serialize = azrtti_cast(context);
- if (serialize)
- {
- serialize->Class()
- ->Version(1)
- ->Field("MipGenType", &MipmapSettings::m_type)
- ->Field("BorderColor", &MipmapSettings::m_borderColor)
- ->Field("Normalize", &MipmapSettings::m_normalize)
- ->Field("StreamableMips", &MipmapSettings::m_streamableMips);
-
- AZ::EditContext* editContext = serialize->GetEditContext();
- if (editContext)
- {
- editContext->Class("Mipmap Setting", "")
- ->DataElement(AZ::Edit::UIHandlers::ComboBox, &MipmapSettings::m_type, "Type", "")
- ->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::Color, &MipmapSettings::m_borderColor, "Color", "")
- ->DataElement(AZ::Edit::UIHandlers::CheckBox, &MipmapSettings::m_normalize, "Normalized", "")
- ->DataElement(AZ::Edit::UIHandlers::SpinBox, &MipmapSettings::m_streamableMips, "Streamable Mips", "")
- ->Attribute(AZ::Edit::Attributes::Min, 0)
- ;
- }
- }
- }
-} // namespace ImageProcessing
diff --git a/Gems/ImageProcessing/Code/Source/BuilderSettings/MipmapSettings.h b/Gems/ImageProcessing/Code/Source/BuilderSettings/MipmapSettings.h
deleted file mode 100644
index 4a2864d2b7..0000000000
--- a/Gems/ImageProcessing/Code/Source/BuilderSettings/MipmapSettings.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-* 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.
-*
-*/
-
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-
-namespace ImageProcessing
-{
- struct MipmapSettings
- {
- AZ_TYPE_INFO(MipmapSettings, "{9239618E-23A6-43C8-9B87-50528CBFA6FF}");
- AZ_CLASS_ALLOCATOR(MipmapSettings, AZ::SystemAllocator, 0);
- bool operator!=(const MipmapSettings& other) const;
- bool operator==(const MipmapSettings& other) const;
-
- static void Reflect(AZ::ReflectContext* context);
-
- MipGenType m_type = MipGenType::blackmanHarris;
-
- //Unused or duplicated properties. We may want to move same properties from perset setting to here.
- AZ::Color m_borderColor;
- bool m_normalize;
- AZ::u32 m_streamableMips;
- };
-} // namespace ImageProcessing
diff --git a/Gems/ImageProcessing/Code/Source/BuilderSettings/PlatformSettings.h b/Gems/ImageProcessing/Code/Source/BuilderSettings/PlatformSettings.h
deleted file mode 100644
index 5cfc7757b2..0000000000
--- a/Gems/ImageProcessing/Code/Source/BuilderSettings/PlatformSettings.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-* 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.
-*
-*/
-
-#pragma once
-
-#include
-#include
-#include
-#include
-
-namespace ImageProcessing
-{
- //! default settings for platform
- struct PlatformSetting
- {
- AZ_TYPE_INFO(PlatformSetting, "{19EF828B-DDFF-4591-AD5A-946801FCC98E}");
- AZ_CLASS_ALLOCATOR(PlatformSetting, AZ::SystemAllocator, 0);
-
- //! Platform's name
- PlatformName m_name;
-
- //! pixel formats supported for the platform
- AZStd::list m_availableFormat;
- };
-} // namespace ImageProcessing
diff --git a/Gems/ImageProcessing/Code/Source/BuilderSettings/PresetSettings.cpp b/Gems/ImageProcessing/Code/Source/BuilderSettings/PresetSettings.cpp
deleted file mode 100644
index 8f904058d3..0000000000
--- a/Gems/ImageProcessing/Code/Source/BuilderSettings/PresetSettings.cpp
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
-* 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 "ImageProcessing_precompiled.h"
-#include
-#include
-
-namespace ImageProcessing
-{
- PresetSettings::PresetSettings()
- : m_uuid(0)
- , m_rgbWeight(RGBWeight::uniform)
- , m_srcColorSpace(ColorSpace::sRGB)
- , m_destColorSpace(ColorSpace::autoSelect)
- , m_suppressEngineReduce(false)
- , m_pixelFormat(ePixelFormat_R8G8B8A8)
- , m_pixelFormatName("R8G8B8A8")
- , m_pixelFormatAlpha(ePixelFormat_Unknown)
- , m_pixelFormatAlphaName("")
- , m_discardAlpha(false)
- , m_maxTextureSize(0)
- , m_minTextureSize(0)
- , m_isPowerOf2(false)
- , m_sizeReduceLevel(0)
- , m_isColorChart(0)
- , m_highPassMip(0)
- , m_glossFromNormals(false)
- , m_isMipRenormalize(false)
- , m_numStreamableMips(100)
- , m_isLegacyGloss(false)
- {
-
- }
-
- PresetSettings::PresetSettings(const PresetSettings& other)
- {
- DeepCopyMembers(other);
- }
-
- void PresetSettings::Reflect(AZ::ReflectContext* context)
- {
- AZ::SerializeContext* serialize = azrtti_cast(context);
- if (serialize)
- {
- serialize->Class()
- ->Version(1)
- ->Field("UUID", &PresetSettings::m_uuid)
- ->Field("Name", &PresetSettings::m_name)
- ->Field("Description", &PresetSettings::m_description)
- ->Field("RGB_Weight", &PresetSettings::m_rgbWeight)
- ->Field("SourceColor", &PresetSettings::m_srcColorSpace)
- ->Field("DestColor", &PresetSettings::m_destColorSpace)
- ->Field("FileMasks", &PresetSettings::m_fileMasks)
- ->Field("SuppressEngineReduce", &PresetSettings::m_suppressEngineReduce)
- ->Field("PixelFormat", &PresetSettings::m_pixelFormatName)
- ->Field("PixelFormatAlpha", &PresetSettings::m_pixelFormatAlphaName)
- ->Field("DiscardAlpha", &PresetSettings::m_discardAlpha)
- ->Field("MaxTextureSize", &PresetSettings::m_maxTextureSize)
- ->Field("MinTextureSize", &PresetSettings::m_minTextureSize)
- ->Field("IsPowerOf2", &PresetSettings::m_isPowerOf2)
- ->Field("SizeReduceLevel", &PresetSettings::m_sizeReduceLevel)
- ->Field("IsColorChart", &PresetSettings::m_isColorChart)
- ->Field("HighPassMip", &PresetSettings::m_highPassMip)
- ->Field("GlossFromNormal", &PresetSettings::m_glossFromNormals)
- ->Field("UseLegacyGloss", &PresetSettings::m_isLegacyGloss)
- ->Field("MipRenormalize", &PresetSettings::m_isMipRenormalize)
- ->Field("NumberStreamableMips", &PresetSettings::m_numStreamableMips)
- ->Field("Swizzle", &PresetSettings::m_swizzle)
- ->Field("CubemapSettings", &PresetSettings::m_cubemapSetting)
- ->Field("MipMapSetting", &PresetSettings::m_mipmapSetting);
- }
- }
-
- PresetSettings& PresetSettings::operator= (const PresetSettings& other)
- {
- DeepCopyMembers(other);
- return *this;
- }
-
- bool PresetSettings::operator==(const PresetSettings& other) const
- {
- bool arePointersEqual = true;
-
- ///////
- // MipMap Settings
- //////
- // If both pointers are allocated...
- if (m_mipmapSetting && other.m_mipmapSetting)
- {
- // If the allocated values are different...
- if (*m_mipmapSetting != *other.m_mipmapSetting)
- {
- arePointersEqual = false;
- }
- }
- // Otherwise, one or both pointers are un-allocated.
- // If only one pointer is allocated (via unequivalency)...
- else if (m_mipmapSetting != other.m_mipmapSetting)
- {
- arePointersEqual = false;
- }
- ///////
- // CubeMap Settings
- //////
- // If both pointers are allocated...
- if (m_cubemapSetting && other.m_cubemapSetting)
- {
- // If the allocated values are different...
- if (*m_cubemapSetting != *other.m_cubemapSetting)
- {
- arePointersEqual = false;
- }
- }
- // Otherwise, one or both pointers are un-allocated.
- // If only one pointer is allocated (via unequivalency)...
- else if (m_cubemapSetting != other.m_cubemapSetting)
- {
- arePointersEqual = false;
- }
- return
- arePointersEqual &&
- m_uuid == other.m_uuid &&
- m_name == other.m_name &&
- m_description == other.m_description &&
- m_rgbWeight == other.m_rgbWeight &&
- m_srcColorSpace == other.m_srcColorSpace &&
- m_destColorSpace == other.m_destColorSpace &&
- m_fileMasks == other.m_fileMasks &&
- m_suppressEngineReduce == other.m_suppressEngineReduce &&
- m_pixelFormat == other.m_pixelFormat &&
- m_pixelFormatName == other.m_pixelFormatName &&
- m_pixelFormatAlpha == other.m_pixelFormatAlpha &&
- m_pixelFormatAlphaName == other.m_pixelFormatAlphaName &&
- m_discardAlpha == other.m_discardAlpha &&
- m_minTextureSize == other.m_minTextureSize &&
- m_maxTextureSize == other.m_maxTextureSize &&
- m_isPowerOf2 == other.m_isPowerOf2 &&
- m_sizeReduceLevel == other.m_sizeReduceLevel &&
- m_isColorChart == other.m_isColorChart &&
- m_highPassMip == other.m_highPassMip &&
- m_glossFromNormals == other.m_glossFromNormals &&
- m_isLegacyGloss == other.m_isLegacyGloss &&
- m_swizzle == other.m_swizzle &&
- m_isMipRenormalize == other.m_isMipRenormalize &&
- m_numStreamableMips == other.m_numStreamableMips;
- }
-
- void PresetSettings::DeepCopyMembers(const PresetSettings & other)
- {
- if (this != &other)
- {
- if(other.m_mipmapSetting)
- {
- m_mipmapSetting = AZStd::make_unique(*other.m_mipmapSetting);
- }
-
- if(other.m_cubemapSetting)
- {
- m_cubemapSetting = AZStd::make_unique(*other.m_cubemapSetting);
- }
-
- m_uuid = other.m_uuid;
- m_name = other.m_name;
- m_description = other.m_description;
- m_rgbWeight = other.m_rgbWeight;
- m_srcColorSpace = other.m_srcColorSpace;
- m_destColorSpace = other.m_destColorSpace;
- m_fileMasks = other.m_fileMasks;
- m_suppressEngineReduce = other.m_suppressEngineReduce;
- m_pixelFormat = other.m_pixelFormat;
- m_pixelFormatAlpha = other.m_pixelFormatAlpha;
- m_pixelFormatName = other.m_pixelFormatName;
- m_pixelFormatAlphaName = other.m_pixelFormatAlphaName;
- m_discardAlpha = other.m_discardAlpha;
- m_minTextureSize = other.m_minTextureSize;
- m_maxTextureSize = other.m_maxTextureSize;
- m_isPowerOf2 = other.m_isPowerOf2;
- m_sizeReduceLevel = other.m_sizeReduceLevel;
- m_isColorChart = other.m_isColorChart;
- m_highPassMip = other.m_highPassMip;
- m_glossFromNormals = other.m_glossFromNormals;
- m_isLegacyGloss = other.m_isLegacyGloss;
- m_swizzle = other.m_swizzle;
- m_isMipRenormalize = other.m_isMipRenormalize;
- m_numStreamableMips = other.m_numStreamableMips;
- }
- }
-
- AZ::Vector3 PresetSettings::GetColorWeight()
- {
- switch (m_rgbWeight)
- {
- case RGBWeight::uniform:
- return AZ::Vector3(0.3333f, 0.3334f, 0.3333f);
- case RGBWeight::ciexyz:
- return AZ::Vector3(0.2126f, 0.7152f, 0.0722f);
- case RGBWeight::luminance:
- return AZ::Vector3(0.3086f, 0.6094f, 0.0820f);
- default:
- AZ_Assert(false, "color weight value need to be added to new rgbWeight enum");
- return AZ::Vector3(0.3333f, 0.3334f, 0.3333f);
- }
- }
-} // namespace ImageProcessing
diff --git a/Gems/ImageProcessing/Code/Source/BuilderSettings/PresetSettings.h b/Gems/ImageProcessing/Code/Source/BuilderSettings/PresetSettings.h
deleted file mode 100644
index fa881e853b..0000000000
--- a/Gems/ImageProcessing/Code/Source/BuilderSettings/PresetSettings.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
-* 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.
-*
-*/
-
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-
-namespace ImageProcessing
-{
- //settings for texture process preset
- class PresetSettings
- {
- public:
- AZ_TYPE_INFO(PresetSettings, "{935BCE3F-9E76-494E-9408-47C5937D7288}");
- AZ_CLASS_ALLOCATOR(PresetSettings, AZ::SystemAllocator, 0);
-
- PresetSettings();
- PresetSettings(const PresetSettings& other);
- PresetSettings& operator= (const PresetSettings& other);
- bool operator== (const PresetSettings& other) const;
- static void Reflect(AZ::ReflectContext* context);
-
- //unique id for the preset
- AZ::Uuid m_uuid;
-
- PresetName m_name;
-
- //a brief description for the usage of this Preset
- AZStd::string m_description;
-
- //misc options
- // "rgbweights". specify preset for weighting of R,G,B channels (used by compressor)
- RGBWeight m_rgbWeight;
- ColorSpace m_srcColorSpace;
- ColorSpace m_destColorSpace;
-
- // file masks used for helping select default preset and option preset list in texture property dialog
- AZStd::vector m_fileMasks;
-
- // "ser". Whether to enable supress reduce resolution (m_sizeReduceLevel) during loading, 0(default)
- bool m_suppressEngineReduce;
-
- //pixel format
- EPixelFormat m_pixelFormat;
- AZStd::string m_pixelFormatName;
- //pixel format for image which only contains alpha channel. this is for if we need to save alpha channel into a seperate image
- EPixelFormat m_pixelFormatAlpha;
- AZStd::string m_pixelFormatAlphaName;
- bool m_discardAlpha;
-
- // Resolution related settings
-
- // "maxtexturesize", upper limit of the resolution of generated textures. It should be a power-of-2 number larger than 1
- // resulting texture will be downscaled if its width or height larger than this value
- // 0 - no upper resolution limit (default)
- unsigned int m_maxTextureSize;
-
- // "mintexturesize", lower limit of the resolution of generated textures.It should be a power-of-2 number larger than 1
- // resulting texture will be upscaled if its width or height smaller than this value
- // 0 - no lower resolution limit (default)
- unsigned int m_minTextureSize;
-
- bool m_isPowerOf2;
-
- //"reduce", 0=no size reduce /1=half resolution /2=quarter resolution, etc"
- unsigned int m_sizeReduceLevel;
-
- //settings for cubemap generation. it's null if this preset is not for cubemap.
- //"cm" equals 1 to enable cubemap in rc.ini
- AZStd::unique_ptr m_cubemapSetting;
-
- //settings for mipmap generation. it's null if this preset disable mipmap.
- AZStd::unique_ptr m_mipmapSetting;
-
- //some specific settings
- // "colorchart". This is to indicate if need to extract color chart from the image and output the color chart data.
- // This is very specific usage for cryEngine. Check ColorChart.cpp for better explaination.
- bool m_isColorChart;
-
- //"highpass". Defines which mip level is subtracted when applying the high pass filter
- //this is only used for terrain asset. we might remove it later since it can be done with source image directly
- AZ::u32 m_highPassMip;
-
- //"glossfromnormals". Bake normal variance into smoothness stored in alpha channel
- AZ::u32 m_glossFromNormals;
-
- //"mipnormalize". need normalize the rgb
- bool m_isMipRenormalize;
-
- //function to get color's rgb weight in vec3 based on m_rgbWeight enum
- //this is useful for squisher compression
- AZ::Vector3 GetColorWeight();
-
- //numstreamablemips
- AZ::u32 m_numStreamableMips;
-
- //legacy options might be removed later
- //"glosslegacydist". If the gloss map use legacy distribution. NW is still using legacy dist
- bool m_isLegacyGloss;
-
- //"swizzle". need to be 4 character and each character need to be one of "rgba01"
- AZStd::string m_swizzle;
-
- private:
- void DeepCopyMembers(const PresetSettings& other);
- };
-} // namespace ImageProcessing
diff --git a/Gems/ImageProcessing/Code/Source/BuilderSettings/TextureSettings.cpp b/Gems/ImageProcessing/Code/Source/BuilderSettings/TextureSettings.cpp
deleted file mode 100644
index b465ec81f3..0000000000
--- a/Gems/ImageProcessing/Code/Source/BuilderSettings/TextureSettings.cpp
+++ /dev/null
@@ -1,589 +0,0 @@
-/*
-* 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 "ImageProcessing_precompiled.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include