Merge branch 'stabilization/2110' into Atom/santorac/FixChickenMohawkMaterial

monroegm-disable-blank-issue-2
santorac 4 years ago
commit a3d018f30f

@ -6,7 +6,11 @@
# #
# #
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) # for PAL_TRAIT_BLAST Traits
if(PAL_TRAIT_BLAST_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_pytest( ly_add_pytest(
NAME AutomatedTesting::BlastTests_Main NAME AutomatedTesting::BlastTests_Main
TEST_SUITE main TEST_SUITE main

@ -0,0 +1,9 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
set(PAL_TRAIT_BLAST_TESTS_SUPPORTED FALSE)

@ -0,0 +1,9 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
set(PAL_TRAIT_BLAST_TESTS_SUPPORTED FALSE)

@ -0,0 +1,9 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
set(PAL_TRAIT_BLAST_TESTS_SUPPORTED FALSE)

@ -0,0 +1,9 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
set(PAL_TRAIT_BLAST_TESTS_SUPPORTED TRUE)

@ -0,0 +1,9 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
set(PAL_TRAIT_BLAST_TESTS_SUPPORTED FALSE)

@ -6,7 +6,11 @@
# #
# #
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS) ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME})
include(${pal_dir}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) # for PAL_TRAIT_WHITEBOX Traits
if(PAL_TRAIT_WHITEBOX_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS)
ly_add_pytest( ly_add_pytest(
NAME AutomatedTesting::WhiteBoxTests NAME AutomatedTesting::WhiteBoxTests
TEST_SUITE main TEST_SUITE main

@ -0,0 +1,9 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
set(PAL_TRAIT_WHITEBOX_TESTS_SUPPORTED FALSE)

@ -0,0 +1,9 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
set(PAL_TRAIT_WHITEBOX_TESTS_SUPPORTED FALSE)

@ -0,0 +1,9 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
set(PAL_TRAIT_WHITEBOX_TESTS_SUPPORTED FALSE)

@ -0,0 +1,9 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
set(PAL_TRAIT_WHITEBOX_TESTS_SUPPORTED TRUE)

@ -0,0 +1,9 @@
#
# Copyright (c) Contributors to the Open 3D Engine Project.
# For complete copyright and license terms please see the LICENSE at the root of this distribution.
#
# SPDX-License-Identifier: Apache-2.0 OR MIT
#
#
set(PAL_TRAIT_WHITEBOX_TESTS_SUPPORTED FALSE)

@ -1124,7 +1124,9 @@ void EditorViewportWidget::OnTitleMenu(QMenu* menu)
action = menu->addAction(tr("Create camera entity from current view")); action = menu->addAction(tr("Create camera entity from current view"));
connect(action, &QAction::triggered, this, &EditorViewportWidget::OnMenuCreateCameraEntityFromCurrentView); connect(action, &QAction::triggered, this, &EditorViewportWidget::OnMenuCreateCameraEntityFromCurrentView);
if (!gameEngine || !gameEngine->IsLevelLoaded()) const auto prefabEditorEntityOwnershipInterface = AZ::Interface<AzToolsFramework::PrefabEditorEntityOwnershipInterface>::Get();
if (!gameEngine || !gameEngine->IsLevelLoaded() ||
(prefabEditorEntityOwnershipInterface && !prefabEditorEntityOwnershipInterface->IsRootPrefabAssigned()))
{ {
action->setEnabled(false); action->setEnabled(false);
action->setToolTip(tr(AZ::ViewportHelpers::TextCantCreateCameraNoLevel)); action->setToolTip(tr(AZ::ViewportHelpers::TextCantCreateCameraNoLevel));

@ -85,6 +85,7 @@ namespace UnitTest
m_rootWidget = AZStd::make_unique<QWidget>(); m_rootWidget = AZStd::make_unique<QWidget>();
m_rootWidget->setFixedSize(QSize(100, 100)); m_rootWidget->setFixedSize(QSize(100, 100));
QApplication::setActiveWindow(m_rootWidget.get());
m_controllerList = AZStd::make_shared<AzFramework::ViewportControllerList>(); m_controllerList = AZStd::make_shared<AzFramework::ViewportControllerList>();
m_controllerList->RegisterViewportContext(TestViewportId); m_controllerList->RegisterViewportContext(TestViewportId);
@ -100,6 +101,8 @@ namespace UnitTest
m_controllerList.reset(); m_controllerList.reset();
m_rootWidget.reset(); m_rootWidget.reset();
QApplication::setActiveWindow(nullptr);
AllocatorsTestFixture::TearDown(); AllocatorsTestFixture::TearDown();
} }
@ -110,7 +113,7 @@ namespace UnitTest
const AzFramework::ViewportId ViewportManipulatorControllerFixture::TestViewportId = AzFramework::ViewportId(0); const AzFramework::ViewportId ViewportManipulatorControllerFixture::TestViewportId = AzFramework::ViewportId(0);
TEST_F(ViewportManipulatorControllerFixture, An_event_is_not_propagated_to_the_viewport_when_a_manipulator_handles_it_first) TEST_F(ViewportManipulatorControllerFixture, AnEventIsNotPropagatedToTheViewportWhenAManipulatorHandlesItFirst)
{ {
// forward input events to our controller list // forward input events to our controller list
QObject::connect( QObject::connect(
@ -151,4 +154,77 @@ namespace UnitTest
editorInteractionViewportFake.Disconnect(); editorInteractionViewportFake.Disconnect();
} }
TEST_F(ViewportManipulatorControllerFixture, ChangingFocusDoesNotClearInput)
{
bool endedEvent = false;
// detect input events and ensure that the Alt key press does not end before the end of the test
QObject::connect(
m_inputChannelMapper.get(), &AzToolsFramework::QtEventToAzInputMapper::InputChannelUpdated, m_rootWidget.get(),
[&endedEvent](const AzFramework::InputChannel* inputChannel, [[maybe_unused]] QEvent* event)
{
if (inputChannel->GetInputChannelId() == AzFramework::InputDeviceKeyboard::Key::ModifierAltL &&
inputChannel->IsStateEnded())
{
endedEvent = true;
}
});
// given
auto* secondaryWidget = new QWidget(m_rootWidget.get());
m_rootWidget->show();
secondaryWidget->show();
m_rootWidget->setFocus();
// simulate a key press when root widget has focus
QTest::keyPress(m_rootWidget.get(), Qt::Key_Alt, Qt::KeyboardModifier::AltModifier);
// when
// change focus to secondary widget
secondaryWidget->setFocus();
// then
// the alt key was not released (cleared)
EXPECT_FALSE(endedEvent);
}
// note: Application State Change includes events such as switching to another application or minimizing
// the current application
TEST_F(ViewportManipulatorControllerFixture, ApplicationStateChangeDoesClearInput)
{
bool endedEvent = false;
// detect input events and ensure that the Alt key press does not end before the end of the test
QObject::connect(
m_inputChannelMapper.get(), &AzToolsFramework::QtEventToAzInputMapper::InputChannelUpdated, m_rootWidget.get(),
[&endedEvent](const AzFramework::InputChannel* inputChannel, [[maybe_unused]] QEvent* event)
{
if (inputChannel->GetInputChannelId() == AzFramework::InputDeviceKeyboard::Key::AlphanumericW &&
inputChannel->IsStateEnded())
{
endedEvent = true;
}
});
// given
auto* secondaryWidget = new QWidget(m_rootWidget.get());
m_rootWidget->show();
secondaryWidget->show();
m_rootWidget->setFocus();
// simulate a key press when root widget has focus
QTest::keyPress(m_rootWidget.get(), Qt::Key_W);
// when
// simulate changing the window state
QApplicationStateChangeEvent applicationStateChangeEvent(Qt::ApplicationState::ApplicationInactive);
QCoreApplication::sendEvent(m_rootWidget.get(), &applicationStateChangeEvent);
// then
// the key was released (cleared)
EXPECT_TRUE(endedEvent);
}
} // namespace UnitTest } // namespace UnitTest

@ -383,36 +383,36 @@ namespace AZ
AZ_MATH_INLINE bool CmpAllEq(__m128 arg1, __m128 arg2, int32_t mask) AZ_MATH_INLINE bool CmpAllEq(__m128 arg1, __m128 arg2, int32_t mask)
{ {
const __m128i compare = CastToInt(CmpNeq(arg1, arg2)); const __m128 compare = CmpEq(arg1, arg2);
return (_mm_movemask_epi8(compare) & mask) == 0; return (_mm_movemask_ps(compare) & mask) == mask;
} }
AZ_MATH_INLINE bool CmpAllLt(__m128 arg1, __m128 arg2, int32_t mask) AZ_MATH_INLINE bool CmpAllLt(__m128 arg1, __m128 arg2, int32_t mask)
{ {
const __m128i compare = CastToInt(CmpGtEq(arg1, arg2)); const __m128 compare = CmpLt(arg1, arg2);
return (_mm_movemask_epi8(compare) & mask) == 0; return (_mm_movemask_ps(compare) & mask) == mask;
} }
AZ_MATH_INLINE bool CmpAllLtEq(__m128 arg1, __m128 arg2, int32_t mask) AZ_MATH_INLINE bool CmpAllLtEq(__m128 arg1, __m128 arg2, int32_t mask)
{ {
const __m128i compare = CastToInt(CmpGt(arg1, arg2)); const __m128 compare = CmpLtEq(arg1, arg2);
return (_mm_movemask_epi8(compare) & mask) == 0; return (_mm_movemask_ps(compare) & mask) == mask;
} }
AZ_MATH_INLINE bool CmpAllGt(__m128 arg1, __m128 arg2, int32_t mask) AZ_MATH_INLINE bool CmpAllGt(__m128 arg1, __m128 arg2, int32_t mask)
{ {
const __m128i compare = CastToInt(CmpLtEq(arg1, arg2)); const __m128 compare = CmpGt(arg1, arg2);
return (_mm_movemask_epi8(compare) & mask) == 0; return (_mm_movemask_ps(compare) & mask) == mask;
} }
AZ_MATH_INLINE bool CmpAllGtEq(__m128 arg1, __m128 arg2, int32_t mask) AZ_MATH_INLINE bool CmpAllGtEq(__m128 arg1, __m128 arg2, int32_t mask)
{ {
const __m128i compare = CastToInt(CmpLt(arg1, arg2)); const __m128 compare = CmpGtEq(arg1, arg2);
return (_mm_movemask_epi8(compare) & mask) == 0; return (_mm_movemask_ps(compare) & mask) == mask;
} }

@ -331,31 +331,32 @@ namespace AZ
AZ_MATH_INLINE bool Vec1::CmpAllEq(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec1::CmpAllEq(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllEq(arg1, arg2, 0x000F); // Only check the first bit for Vector1
return Sse::CmpAllEq(arg1, arg2, 0b0001);
} }
AZ_MATH_INLINE bool Vec1::CmpAllLt(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec1::CmpAllLt(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllLt(arg1, arg2, 0x000F); return Sse::CmpAllLt(arg1, arg2, 0b0001);
} }
AZ_MATH_INLINE bool Vec1::CmpAllLtEq(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec1::CmpAllLtEq(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllLtEq(arg1, arg2, 0x000F); return Sse::CmpAllLtEq(arg1, arg2, 0b0001);
} }
AZ_MATH_INLINE bool Vec1::CmpAllGt(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec1::CmpAllGt(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllGt(arg1, arg2, 0x000F); return Sse::CmpAllGt(arg1, arg2, 0b0001);
} }
AZ_MATH_INLINE bool Vec1::CmpAllGtEq(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec1::CmpAllGtEq(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllGtEq(arg1, arg2, 0x000F); return Sse::CmpAllGtEq(arg1, arg2, 0b0001);
} }
@ -397,7 +398,7 @@ namespace AZ
AZ_MATH_INLINE bool Vec1::CmpAllEq(Int32ArgType arg1, Int32ArgType arg2) AZ_MATH_INLINE bool Vec1::CmpAllEq(Int32ArgType arg1, Int32ArgType arg2)
{ {
return Sse::CmpAllEq(arg1, arg2, 0x000F); return Sse::CmpAllEq(arg1, arg2, 0b0001);
} }

@ -383,31 +383,32 @@ namespace AZ
AZ_MATH_INLINE bool Vec2::CmpAllEq(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec2::CmpAllEq(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllEq(arg1, arg2, 0x00FF); // Only check the first two bits for Vector2
return Sse::CmpAllEq(arg1, arg2, 0b0011);
} }
AZ_MATH_INLINE bool Vec2::CmpAllLt(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec2::CmpAllLt(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllLt(arg1, arg2, 0x00FF); return Sse::CmpAllLt(arg1, arg2, 0b0011);
} }
AZ_MATH_INLINE bool Vec2::CmpAllLtEq(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec2::CmpAllLtEq(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllLtEq(arg1, arg2, 0x00FF); return Sse::CmpAllLtEq(arg1, arg2, 0b0011);
} }
AZ_MATH_INLINE bool Vec2::CmpAllGt(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec2::CmpAllGt(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllGt(arg1, arg2, 0x00FF); return Sse::CmpAllGt(arg1, arg2, 0b0011);
} }
AZ_MATH_INLINE bool Vec2::CmpAllGtEq(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec2::CmpAllGtEq(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllGtEq(arg1, arg2, 0x00FF); return Sse::CmpAllGtEq(arg1, arg2, 0b0011);
} }

@ -419,31 +419,32 @@ namespace AZ
AZ_MATH_INLINE bool Vec3::CmpAllEq(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec3::CmpAllEq(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllEq(arg1, arg2, 0x0FFF); // Only check the first three bits for Vector3
return Sse::CmpAllEq(arg1, arg2, 0b0111);
} }
AZ_MATH_INLINE bool Vec3::CmpAllLt(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec3::CmpAllLt(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllLt(arg1, arg2, 0x0FFF); return Sse::CmpAllLt(arg1, arg2, 0b0111);
} }
AZ_MATH_INLINE bool Vec3::CmpAllLtEq(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec3::CmpAllLtEq(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllLtEq(arg1, arg2, 0x0FFF); return Sse::CmpAllLtEq(arg1, arg2, 0b0111);
} }
AZ_MATH_INLINE bool Vec3::CmpAllGt(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec3::CmpAllGt(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllGt(arg1, arg2, 0x0FFF); return Sse::CmpAllGt(arg1, arg2, 0b0111);
} }
AZ_MATH_INLINE bool Vec3::CmpAllGtEq(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec3::CmpAllGtEq(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllGtEq(arg1, arg2, 0x0FFF); return Sse::CmpAllGtEq(arg1, arg2, 0b0111);
} }
@ -485,7 +486,7 @@ namespace AZ
AZ_MATH_INLINE bool Vec3::CmpAllEq(Int32ArgType arg1, Int32ArgType arg2) AZ_MATH_INLINE bool Vec3::CmpAllEq(Int32ArgType arg1, Int32ArgType arg2)
{ {
return Sse::CmpAllEq(arg1, arg2, 0x0FFF); return Sse::CmpAllEq(arg1, arg2, 0b0111);
} }

@ -455,31 +455,32 @@ namespace AZ
AZ_MATH_INLINE bool Vec4::CmpAllEq(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec4::CmpAllEq(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllEq(arg1, arg2, 0xFFFF); // Check the first four bits for Vector4
return Sse::CmpAllEq(arg1, arg2, 0b1111);
} }
AZ_MATH_INLINE bool Vec4::CmpAllLt(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec4::CmpAllLt(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllLt(arg1, arg2, 0xFFFF); return Sse::CmpAllLt(arg1, arg2, 0b1111);
} }
AZ_MATH_INLINE bool Vec4::CmpAllLtEq(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec4::CmpAllLtEq(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllLtEq(arg1, arg2, 0xFFFF); return Sse::CmpAllLtEq(arg1, arg2, 0b1111);
} }
AZ_MATH_INLINE bool Vec4::CmpAllGt(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec4::CmpAllGt(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllGt(arg1, arg2, 0xFFFF); return Sse::CmpAllGt(arg1, arg2, 0b1111);
} }
AZ_MATH_INLINE bool Vec4::CmpAllGtEq(FloatArgType arg1, FloatArgType arg2) AZ_MATH_INLINE bool Vec4::CmpAllGtEq(FloatArgType arg1, FloatArgType arg2)
{ {
return Sse::CmpAllGtEq(arg1, arg2, 0xFFFF); return Sse::CmpAllGtEq(arg1, arg2, 0b1111);
} }
@ -521,7 +522,7 @@ namespace AZ
AZ_MATH_INLINE bool Vec4::CmpAllEq(Int32ArgType arg1, Int32ArgType arg2) AZ_MATH_INLINE bool Vec4::CmpAllEq(Int32ArgType arg1, Int32ArgType arg2)
{ {
return Sse::CmpAllEq(arg1, arg2, 0xFFFF); return Sse::CmpAllEq(arg1, arg2, 0b1111);
} }

@ -87,6 +87,8 @@ void ScriptSystemComponent::Activate()
AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::AddExtension, "lua"); AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::AddExtension, "lua");
AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::AddExtension, "luac"); AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequests::AddExtension, "luac");
AZ::Data::AssetCatalogRequestBus::Broadcast(
&AZ::Data::AssetCatalogRequests::EnableCatalogForAsset, AZ::AzTypeInfo<AZ::ScriptAsset>::Uuid());
if (Data::AssetManager::Instance().IsReady()) if (Data::AssetManager::Instance().IsReady())
{ {

@ -59,7 +59,7 @@ namespace AZ::Utils
{ {
// Fix the size value of the fixed string by calculating the c-string length using char traits // Fix the size value of the fixed string by calculating the c-string length using char traits
absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data())); absolutePath.resize_no_construct(AZStd::char_traits<char>::length(absolutePath.data()));
return srcPath; return absolutePath;
} }
return AZStd::nullopt; return AZStd::nullopt;

@ -635,6 +635,7 @@ namespace AZ
size_t longestMatch = 0; size_t longestMatch = 0;
size_t bufStringLength = inBuffer.size(); size_t bufStringLength = inBuffer.size();
AZStd::string_view longestAlias; AZStd::string_view longestAlias;
AZStd::string_view longestResolvedAlias;
for (const auto& [alias, resolvedAlias] : m_aliases) for (const auto& [alias, resolvedAlias] : m_aliases)
{ {
@ -653,6 +654,7 @@ namespace AZ
{ {
longestMatch = resolvedAlias.size(); longestMatch = resolvedAlias.size();
longestAlias = alias; longestAlias = alias;
longestResolvedAlias = resolvedAlias;
} }
} }
} }
@ -661,7 +663,10 @@ namespace AZ
// rearrange the buffer to have // rearrange the buffer to have
// [alias][old path] // [alias][old path]
size_t aliasSize = longestAlias.size(); size_t aliasSize = longestAlias.size();
size_t charsToAbsorb = longestMatch; // If the resolved alias ends in a path separator, do not consume it.
const bool resolvedAliasEndsInPathSeparator = (longestResolvedAlias.ends_with(AZ::IO::PosixPathSeparator) ||
longestResolvedAlias.ends_with(AZ::IO::WindowsPathSeparator));
const size_t charsToAbsorb = resolvedAliasEndsInPathSeparator ? longestMatch - 1 : longestMatch;
size_t remainingData = bufStringLength - charsToAbsorb; size_t remainingData = bufStringLength - charsToAbsorb;
size_t finalStringSize = aliasSize + remainingData; size_t finalStringSize = aliasSize + remainingData;
if (finalStringSize >= outBufferLength) if (finalStringSize >= outBufferLength)

@ -9,19 +9,71 @@
#include <AzCore/IO/Path/Path.h> #include <AzCore/IO/Path/Path.h>
#include <AzCore/IO/SystemFile.h> #include <AzCore/IO/SystemFile.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h> #include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/Console/IConsole.h>
#include <AzCore/std/containers/array.h> #include <AzCore/std/containers/array.h>
#include <AzCore/std/tuple.h> #include <AzCore/std/tuple.h>
#include <errno.h> #include <cerrno>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/prctl.h>
#include <unistd.h> #include <unistd.h>
AZ_CVAR(bool, ap_tether_lifetime, true, nullptr, AZ::ConsoleFunctorFlags::Null,
"If enabled, a parent process that launches the AP will terminate the AP on exit");
namespace AzFramework::AssetSystem::Platform namespace AzFramework::AssetSystem::Platform
{ {
void AllowAssetProcessorToForeground() void AllowAssetProcessorToForeground()
{} {}
[[noreturn]] static void LaunchAssetProcessorDirectly(const AZ::IO::FixedMaxPath& assetProcessorPath, AZStd::string_view engineRoot, AZStd::string_view projectPath)
{
AZStd::fixed_vector<const char*, 5> args {
assetProcessorPath.c_str(),
"--start-hidden",
};
// Add the engine path to the launch command if not empty
AZ::IO::FixedMaxPathString engineRootArg;
if (!engineRoot.empty())
{
// No need to quote these paths, this code calls exec directly and
// does not go through shell string interpolation
engineRootArg = AZ::IO::FixedMaxPathString{"--engine-path="} + AZ::IO::FixedMaxPathString{engineRoot};
args.push_back(engineRootArg.data());
}
// Add the active project path to the launch command if not empty
AZ::IO::FixedMaxPathString projectPathArg;
if (!projectPath.empty())
{
projectPathArg = AZ::IO::FixedMaxPathString{"--regset=/Amazon/AzCore/Bootstrap/project_path="} + AZ::IO::FixedMaxPathString{projectPath};
args.push_back(projectPathArg.data());
}
// Make sure this is at the end
args.push_back(nullptr); // argv itself needs to be null-terminated
execv(args[0], const_cast<char**>(args.data()));
// exec* family of functions only return on error
fprintf(stderr, "Asset Processor failed with error: %s\n", strerror(errno));
_exit(1);
}
static pid_t LaunchAssetProcessorDaemonized(const AZ::IO::FixedMaxPath& assetProcessorPath, AZStd::string_view engineRoot, AZStd::string_view projectPath)
{
// detach the child from parent
setsid();
const pid_t secondChildPid = fork();
if (secondChildPid == 0)
{
LaunchAssetProcessorDirectly(assetProcessorPath, engineRoot, projectPath);
}
return secondChildPid;
}
bool LaunchAssetProcessor(AZStd::string_view executableDirectory, AZStd::string_view engineRoot, bool LaunchAssetProcessor(AZStd::string_view executableDirectory, AZStd::string_view engineRoot,
AZStd::string_view projectPath) AZStd::string_view projectPath)
{ {
@ -40,7 +92,8 @@ namespace AzFramework::AssetSystem::Platform
} }
} }
pid_t firstChildPid = fork(); const pid_t parentPid = getpid();
const pid_t firstChildPid = fork();
if (firstChildPid == 0) if (firstChildPid == 0)
{ {
// redirect output to dev/null so it doesn't hijack an existing console window // redirect output to dev/null so it doesn't hijack an existing console window
@ -53,51 +106,33 @@ namespace AzFramework::AssetSystem::Platform
AZ::IO::FileDescriptorRedirector stderrRedirect(STDERR_FILENO); AZ::IO::FileDescriptorRedirector stderrRedirect(STDERR_FILENO);
stderrRedirect.RedirectTo(devNull, mode); stderrRedirect.RedirectTo(devNull, mode);
// detach the child from parent if (ap_tether_lifetime)
setsid();
pid_t secondChildPid = fork();
if (secondChildPid == 0)
{ {
AZStd::array args { prctl(PR_SET_PDEATHSIG, SIGTERM);
assetProcessorPath.c_str(), assetProcessorPath.c_str(), "--start-hidden", if (getppid() != parentPid)
static_cast<const char*>(nullptr), static_cast<const char*>(nullptr), static_cast<const char*>(nullptr)
};
int optionalArgPos = 3;
// Add the engine path to the launch command if not empty
AZ::IO::FixedMaxPathString engineRootArg;
if (!engineRoot.empty())
{
engineRootArg = AZ::IO::FixedMaxPathString::format(R"(--engine-path="%.*s")",
aznumeric_cast<int>(engineRoot.size()), engineRoot.data());
args[optionalArgPos++] = engineRootArg.data();
}
// Add the active project path to the launch command if not empty
AZ::IO::FixedMaxPathString projectPathArg;
if (!projectPath.empty())
{ {
projectPathArg = AZ::IO::FixedMaxPathString::format(R"(--regset="/Amazon/AzCore/Bootstrap/project_path=%.*s")", _exit(1);
aznumeric_cast<int>(projectPath.size()), projectPath.data());
args[optionalArgPos++] = projectPathArg.data();
} }
LaunchAssetProcessorDirectly(assetProcessorPath, engineRoot, projectPath);
AZStd::apply(execl, args);
// exec* family of functions only exit on error
AZ_Error("AssetSystemComponent", false, "Asset Processor failed with error: %s", strerror(errno));
_exit(1);
} }
else
{
const pid_t secondChildPid = LaunchAssetProcessorDaemonized(assetProcessorPath, engineRoot, projectPath);
stdoutRedirect.Reset();
stderrRedirect.Reset();
stdoutRedirect.Reset(); // exit the transient child with proper return code
stderrRedirect.Reset(); int ret = (secondChildPid < 0) ? 1 : 0;
_exit(ret);
}
// exit the transient child with proper return code
int ret = (secondChildPid < 0) ? 1 : 0;
_exit(ret);
} }
else if (firstChildPid > 0) else if (firstChildPid > 0)
{ {
if (ap_tether_lifetime)
{
return true;
}
// wait for first child to exit to ensure the second child was started // wait for first child to exit to ensure the second child was started
int status = 0; int status = 0;
pid_t ret = waitpid(firstChildPid, &status, 0); pid_t ret = waitpid(firstChildPid, &status, 0);
@ -106,4 +141,4 @@ namespace AzFramework::AssetSystem::Platform
return false; return false;
} }
} } // namespace AzFramework::AssetSystem::Platform

@ -102,7 +102,7 @@ namespace AzToolsFramework
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
AZ::TickBus::Handler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect();
AssetSystemBus::Handler::BusDisconnect(); AssetSystemBus::Handler::BusDisconnect();
m_assetBrowserModel.release(); m_assetBrowserModel.reset();
EntryCache::DestroyInstance(); EntryCache::DestroyInstance();
} }

@ -26,8 +26,12 @@ namespace AzToolsFramework
AZ::Interface<ContainerEntityInterface>::Unregister(this); AZ::Interface<ContainerEntityInterface>::Unregister(this);
} }
void ContainerEntitySystemComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context) void ContainerEntitySystemComponent::Reflect(AZ::ReflectContext* context)
{ {
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<ContainerEntitySystemComponent, AZ::Component>()->Version(1);
}
} }
void ContainerEntitySystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) void ContainerEntitySystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)

@ -47,8 +47,12 @@ namespace AzToolsFramework
AZ::Interface<FocusModeInterface>::Unregister(this); AZ::Interface<FocusModeInterface>::Unregister(this);
} }
void FocusModeSystemComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context) void FocusModeSystemComponent::Reflect(AZ::ReflectContext* context)
{ {
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<FocusModeSystemComponent, AZ::Component>()->Version(1);
}
} }
void FocusModeSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) void FocusModeSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)

@ -210,8 +210,8 @@ namespace AzToolsFramework
m_enabled = enabled; m_enabled = enabled;
if (!enabled) if (!enabled)
{ {
// Send an internal focus change event to reset our input state to fresh if we're disabled. // Clear input channels to reset our input state if we're disabled.
HandleFocusChange(nullptr); ClearInputChannels(nullptr);
} }
} }
@ -246,7 +246,7 @@ namespace AzToolsFramework
if (eventType == QEvent::Type::MouseMove) if (eventType == QEvent::Type::MouseMove)
{ {
// clear override cursor when moving outside of the viewport // Clear override cursor when moving outside of the viewport
const auto* mouseEvent = static_cast<const QMouseEvent*>(event); const auto* mouseEvent = static_cast<const QMouseEvent*>(event);
if (m_overrideCursor && !m_sourceWidget->geometry().contains(m_sourceWidget->mapFromGlobal(mouseEvent->globalPos()))) if (m_overrideCursor && !m_sourceWidget->geometry().contains(m_sourceWidget->mapFromGlobal(mouseEvent->globalPos())))
{ {
@ -255,6 +255,13 @@ namespace AzToolsFramework
} }
} }
// If the application state changes (e.g. we have alt-tabbed or minimized the
// main editor window) then ensure all input channels are cleared
if (eventType == QEvent::ApplicationStateChange)
{
ClearInputChannels(event);
}
// Only accept mouse & key release events that originate from an object that is not our target widget, // Only accept mouse & key release events that originate from an object that is not our target widget,
// as we don't want to erroneously intercept user input meant for another component. // as we don't want to erroneously intercept user input meant for another component.
if (object != m_sourceWidget && eventType != QEvent::Type::KeyRelease && eventType != QEvent::Type::MouseButtonRelease) if (object != m_sourceWidget && eventType != QEvent::Type::KeyRelease && eventType != QEvent::Type::MouseButtonRelease)
@ -264,9 +271,6 @@ namespace AzToolsFramework
if (eventType == QEvent::FocusIn || eventType == QEvent::FocusOut) if (eventType == QEvent::FocusIn || eventType == QEvent::FocusOut)
{ {
// If our focus changes, go ahead and reset all input devices.
HandleFocusChange(event);
// If we focus in on the source widget and the mouse is contained in its // If we focus in on the source widget and the mouse is contained in its
// bounds, refresh the cached cursor position to ensure it is up to date (this // bounds, refresh the cached cursor position to ensure it is up to date (this
// ensures cursor positions are refreshed correctly with context menu focus changes) // ensures cursor positions are refreshed correctly with context menu focus changes)
@ -451,7 +455,7 @@ namespace AzToolsFramework
NotifyUpdateChannelIfNotIdle(cursorZChannel, wheelEvent); NotifyUpdateChannelIfNotIdle(cursorZChannel, wheelEvent);
} }
void QtEventToAzInputMapper::HandleFocusChange(QEvent* event) void QtEventToAzInputMapper::ClearInputChannels(QEvent* event)
{ {
for (auto& channelData : m_channels) for (auto& channelData : m_channels)
{ {

@ -138,8 +138,9 @@ namespace AzToolsFramework
void HandleKeyEvent(QKeyEvent* keyEvent); void HandleKeyEvent(QKeyEvent* keyEvent);
// Handles mouse wheel events. // Handles mouse wheel events.
void HandleWheelEvent(QWheelEvent* wheelEvent); void HandleWheelEvent(QWheelEvent* wheelEvent);
// Handles focus change events.
void HandleFocusChange(QEvent* event); // Clear all input channels (set all channel states to 'ended').
void ClearInputChannels(QEvent* event);
// Populates m_keyMappings. // Populates m_keyMappings.
void InitializeKeyMappings(); void InitializeKeyMappings();

@ -46,11 +46,10 @@ namespace AzToolsFramework
//! Updates the template links (updating instances) for the given template and triggers propagation on its instances. //! Updates the template links (updating instances) for the given template and triggers propagation on its instances.
//! @param providedPatch The patch to apply to the template. //! @param providedPatch The patch to apply to the template.
//! @param templateId The id of the template to update. //! @param templateId The id of the template to update.
//! @param immediate An optional flag whether to apply the patch immediately (needed for Undo/Redos) or wait until next system tick.
//! @param instanceToExclude An optional reference to an instance of the template being updated that should not be refreshes as part of propagation. //! @param instanceToExclude An optional reference to an instance of the template being updated that should not be refreshes as part of propagation.
//! Defaults to nullopt, which means that all instances will be refreshed. //! Defaults to nullopt, which means that all instances will be refreshed.
//! @return True if the template was patched correctly, false if the operation failed. //! @return True if the template was patched correctly, false if the operation failed.
virtual bool PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId, bool immediate = false, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0; virtual bool PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0;
virtual void ApplyPatchesToInstance(const AZ::EntityId& entityId, PrefabDom& patches, const Instance& instanceToAddPatches) = 0; virtual void ApplyPatchesToInstance(const AZ::EntityId& entityId, PrefabDom& patches, const Instance& instanceToAddPatches) = 0;

@ -156,7 +156,7 @@ namespace AzToolsFramework
} }
} }
bool InstanceToTemplatePropagator::PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId, bool immediate, InstanceOptionalReference instanceToExclude) bool InstanceToTemplatePropagator::PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId, InstanceOptionalReference instanceToExclude)
{ {
PrefabDom& templateDomReference = m_prefabSystemComponentInterface->FindTemplateDom(templateId); PrefabDom& templateDomReference = m_prefabSystemComponentInterface->FindTemplateDom(templateId);
@ -178,7 +178,7 @@ namespace AzToolsFramework
(result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::PartialSkip), (result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::PartialSkip),
"Some of the patches were not successfully applied."); "Some of the patches were not successfully applied.");
m_prefabSystemComponentInterface->SetTemplateDirtyFlag(templateId, true); m_prefabSystemComponentInterface->SetTemplateDirtyFlag(templateId, true);
m_prefabSystemComponentInterface->PropagateTemplateChanges(templateId, immediate, instanceToExclude); m_prefabSystemComponentInterface->PropagateTemplateChanges(templateId, instanceToExclude);
return true; return true;
} }
} }

@ -33,7 +33,7 @@ namespace AzToolsFramework
InstanceOptionalReference GetTopMostInstanceInHierarchy(AZ::EntityId entityId) override; InstanceOptionalReference GetTopMostInstanceInHierarchy(AZ::EntityId entityId) override;
bool PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId, bool immediate = false, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override; bool PatchTemplate(PrefabDomValue& providedPatch, TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override;
void ApplyPatchesToInstance(const AZ::EntityId& entityId, PrefabDom& patches, const Instance& instanceToAddPatches) override; void ApplyPatchesToInstance(const AZ::EntityId& entityId, PrefabDom& patches, const Instance& instanceToAddPatches) override;

@ -52,7 +52,7 @@ namespace AzToolsFramework
AZ::Interface<InstanceUpdateExecutorInterface>::Unregister(this); AZ::Interface<InstanceUpdateExecutorInterface>::Unregister(this);
} }
void InstanceUpdateExecutor::AddTemplateInstancesToQueue(TemplateId instanceTemplateId, bool immediate, InstanceOptionalReference instanceToExclude) void InstanceUpdateExecutor::AddTemplateInstancesToQueue(TemplateId instanceTemplateId, InstanceOptionalReference instanceToExclude)
{ {
auto findInstancesResult = auto findInstancesResult =
m_templateInstanceMapperInterface->FindInstancesOwnedByTemplate(instanceTemplateId); m_templateInstanceMapperInterface->FindInstancesOwnedByTemplate(instanceTemplateId);
@ -79,11 +79,6 @@ namespace AzToolsFramework
m_instancesUpdateQueue.emplace_back(instance); m_instancesUpdateQueue.emplace_back(instance);
} }
} }
if (immediate)
{
UpdateTemplateInstancesInQueue();
}
} }
void InstanceUpdateExecutor::RemoveTemplateInstanceFromQueue(const Instance* instance) void InstanceUpdateExecutor::RemoveTemplateInstanceFromQueue(const Instance* instance)

@ -31,7 +31,7 @@ namespace AzToolsFramework
explicit InstanceUpdateExecutor(int instanceCountToUpdateInBatch = 0); explicit InstanceUpdateExecutor(int instanceCountToUpdateInBatch = 0);
void AddTemplateInstancesToQueue(TemplateId instanceTemplateId, bool immediate = false, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override; void AddTemplateInstancesToQueue(TemplateId instanceTemplateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override;
bool UpdateTemplateInstancesInQueue() override; bool UpdateTemplateInstancesInQueue() override;
virtual void RemoveTemplateInstanceFromQueue(const Instance* instance) override; virtual void RemoveTemplateInstanceFromQueue(const Instance* instance) override;

@ -23,7 +23,7 @@ namespace AzToolsFramework
virtual ~InstanceUpdateExecutorInterface() = default; virtual ~InstanceUpdateExecutorInterface() = default;
// Add all Instances of Template with given Id into a queue for updating them later. // Add all Instances of Template with given Id into a queue for updating them later.
virtual void AddTemplateInstancesToQueue(TemplateId instanceTemplateId, bool immediate = false, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0; virtual void AddTemplateInstancesToQueue(TemplateId instanceTemplateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0;
// Update Instances in the waiting queue. // Update Instances in the waiting queue.
virtual bool UpdateTemplateInstancesInQueue() = 0; virtual bool UpdateTemplateInstancesInQueue() = 0;

@ -1051,7 +1051,7 @@ namespace AzToolsFramework
DuplicateNestedEntitiesInInstance(commonOwningInstance->get(), DuplicateNestedEntitiesInInstance(commonOwningInstance->get(),
entities, instanceDomAfter, duplicatedEntityAndInstanceIds, duplicateEntityAliasMap); entities, instanceDomAfter, duplicatedEntityAndInstanceIds, duplicateEntityAliasMap);
PrefabUndoInstance* command = aznew PrefabUndoInstance("Entity/Instance duplication", false); PrefabUndoInstance* command = aznew PrefabUndoInstance("Entity/Instance duplication");
command->SetParent(undoBatch.GetUndoBatch()); command->SetParent(undoBatch.GetUndoBatch());
command->Capture(instanceDomBefore, instanceDomAfter, commonOwningInstance->get().GetTemplateId()); command->Capture(instanceDomBefore, instanceDomAfter, commonOwningInstance->get().GetTemplateId());
command->Redo(); command->Redo();
@ -1322,7 +1322,7 @@ namespace AzToolsFramework
Prefab::PrefabDom instanceDomAfter; Prefab::PrefabDom instanceDomAfter;
m_instanceToTemplateInterface->GenerateDomForInstance(instanceDomAfter, parentInstance); m_instanceToTemplateInterface->GenerateDomForInstance(instanceDomAfter, parentInstance);
PrefabUndoInstance* command = aznew PrefabUndoInstance("Instance detachment", false); PrefabUndoInstance* command = aznew PrefabUndoInstance("Instance detachment");
command->Capture(instanceDomBefore, instanceDomAfter, parentTemplateId); command->Capture(instanceDomBefore, instanceDomAfter, parentTemplateId);
command->SetParent(undoBatch.GetUndoBatch()); command->SetParent(undoBatch.GetUndoBatch());
{ {

@ -159,10 +159,10 @@ namespace AzToolsFramework
newInstance->SetTemplateId(newTemplateId); newInstance->SetTemplateId(newTemplateId);
} }
} }
void PrefabSystemComponent::PropagateTemplateChanges(TemplateId templateId, bool immediate, InstanceOptionalReference instanceToExclude) void PrefabSystemComponent::PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude)
{ {
UpdatePrefabInstances(templateId, immediate, instanceToExclude); UpdatePrefabInstances(templateId, instanceToExclude);
auto templateIdToLinkIdsIterator = m_templateToLinkIdsMap.find(templateId); auto templateIdToLinkIdsIterator = m_templateToLinkIdsMap.find(templateId);
if (templateIdToLinkIdsIterator != m_templateToLinkIdsMap.end()) if (templateIdToLinkIdsIterator != m_templateToLinkIdsMap.end())
@ -191,9 +191,9 @@ namespace AzToolsFramework
} }
} }
void PrefabSystemComponent::UpdatePrefabInstances(TemplateId templateId, bool immediate, InstanceOptionalReference instanceToExclude) void PrefabSystemComponent::UpdatePrefabInstances(TemplateId templateId, InstanceOptionalReference instanceToExclude)
{ {
m_instanceUpdateExecutor.AddTemplateInstancesToQueue(templateId, immediate, instanceToExclude); m_instanceUpdateExecutor.AddTemplateInstancesToQueue(templateId, instanceToExclude);
} }
void PrefabSystemComponent::UpdateLinkedInstances(AZStd::queue<LinkIds>& linkIdsQueue) void PrefabSystemComponent::UpdateLinkedInstances(AZStd::queue<LinkIds>& linkIdsQueue)

@ -231,17 +231,16 @@ namespace AzToolsFramework
*/ */
void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) override; void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) override;
void PropagateTemplateChanges(TemplateId templateId, bool immediate = false, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override; void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) override;
/** /**
* Updates all Instances owned by a Template. * Updates all Instances owned by a Template.
* *
* @param templateId The id of the Template owning Instances to update. * @param templateId The id of the Template owning Instances to update.
* @param immediate An optional flag whether to apply the patch immediately (needed for Undo/Redos) or wait until next system tick. * @param instanceToExclude An optional reference to an instance of the template being updated that should not be refreshed
* @param instanceToExclude An optional reference to an instance of the template being updated that should not be refreshes as part of propagation. * as part of propagation.Defaults to nullopt, which means that all instances will be refreshed.
* Defaults to nullopt, which means that all instances will be refreshed.
*/ */
void UpdatePrefabInstances(TemplateId templateId, bool immediate = false, InstanceOptionalReference instanceToExclude = AZStd::nullopt); void UpdatePrefabInstances(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt);
private: private:
AZ_DISABLE_COPY_MOVE(PrefabSystemComponent); AZ_DISABLE_COPY_MOVE(PrefabSystemComponent);

@ -67,7 +67,7 @@ namespace AzToolsFramework
virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0; virtual PrefabDom& FindTemplateDom(TemplateId templateId) = 0;
virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0; virtual void UpdatePrefabTemplate(TemplateId templateId, const PrefabDom& updatedDom) = 0;
virtual void PropagateTemplateChanges(TemplateId templateId, bool immediate = false, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0; virtual void PropagateTemplateChanges(TemplateId templateId, InstanceOptionalReference instanceToExclude = AZStd::nullopt) = 0;
virtual AZStd::unique_ptr<Instance> InstantiatePrefab( virtual AZStd::unique_ptr<Instance> InstantiatePrefab(
AZ::IO::PathView filePath, InstanceOptionalReference parent = AZStd::nullopt) = 0; AZ::IO::PathView filePath, InstanceOptionalReference parent = AZStd::nullopt) = 0;

@ -17,16 +17,17 @@ namespace AzToolsFramework
{ {
PrefabUndoBase::PrefabUndoBase(const AZStd::string& undoOperationName) PrefabUndoBase::PrefabUndoBase(const AZStd::string& undoOperationName)
: UndoSystem::URSequencePoint(undoOperationName) : UndoSystem::URSequencePoint(undoOperationName)
, m_changed(true)
, m_templateId(InvalidTemplateId)
{ {
m_instanceToTemplateInterface = AZ::Interface<InstanceToTemplateInterface>::Get(); m_instanceToTemplateInterface = AZ::Interface<InstanceToTemplateInterface>::Get();
AZ_Assert(m_instanceToTemplateInterface, "Failed to grab instance to template interface"); AZ_Assert(m_instanceToTemplateInterface, "Failed to grab instance to template interface");
} }
//PrefabInstanceUndo //PrefabInstanceUndo
PrefabUndoInstance::PrefabUndoInstance(const AZStd::string& undoOperationName, bool useImmediatePropagation) PrefabUndoInstance::PrefabUndoInstance(const AZStd::string& undoOperationName)
: PrefabUndoBase(undoOperationName) : PrefabUndoBase(undoOperationName)
{ {
m_useImmediatePropagation = useImmediatePropagation;
} }
void PrefabUndoInstance::Capture( void PrefabUndoInstance::Capture(
@ -42,12 +43,12 @@ namespace AzToolsFramework
void PrefabUndoInstance::Undo() void PrefabUndoInstance::Undo()
{ {
m_instanceToTemplateInterface->PatchTemplate(m_undoPatch, m_templateId, m_useImmediatePropagation); m_instanceToTemplateInterface->PatchTemplate(m_undoPatch, m_templateId);
} }
void PrefabUndoInstance::Redo() void PrefabUndoInstance::Redo()
{ {
m_instanceToTemplateInterface->PatchTemplate(m_redoPatch, m_templateId, m_useImmediatePropagation); m_instanceToTemplateInterface->PatchTemplate(m_redoPatch, m_templateId);
} }
@ -90,7 +91,7 @@ namespace AzToolsFramework
void PrefabUndoEntityUpdate::Undo() void PrefabUndoEntityUpdate::Undo()
{ {
[[maybe_unused]] bool isPatchApplicationSuccessful = [[maybe_unused]] bool isPatchApplicationSuccessful =
m_instanceToTemplateInterface->PatchTemplate(m_undoPatch, m_templateId, true); m_instanceToTemplateInterface->PatchTemplate(m_undoPatch, m_templateId);
AZ_Error( AZ_Error(
"Prefab", isPatchApplicationSuccessful, "Prefab", isPatchApplicationSuccessful,
@ -101,7 +102,7 @@ namespace AzToolsFramework
void PrefabUndoEntityUpdate::Redo() void PrefabUndoEntityUpdate::Redo()
{ {
[[maybe_unused]] bool isPatchApplicationSuccessful = [[maybe_unused]] bool isPatchApplicationSuccessful =
m_instanceToTemplateInterface->PatchTemplate(m_redoPatch, m_templateId, true); m_instanceToTemplateInterface->PatchTemplate(m_redoPatch, m_templateId);
AZ_Error( AZ_Error(
"Prefab", isPatchApplicationSuccessful, "Prefab", isPatchApplicationSuccessful,
@ -112,7 +113,7 @@ namespace AzToolsFramework
void PrefabUndoEntityUpdate::Redo(InstanceOptionalReference instanceToExclude) void PrefabUndoEntityUpdate::Redo(InstanceOptionalReference instanceToExclude)
{ {
[[maybe_unused]] bool isPatchApplicationSuccessful = [[maybe_unused]] bool isPatchApplicationSuccessful =
m_instanceToTemplateInterface->PatchTemplate(m_redoPatch, m_templateId, false, instanceToExclude); m_instanceToTemplateInterface->PatchTemplate(m_redoPatch, m_templateId, instanceToExclude);
AZ_Error( AZ_Error(
"Prefab", isPatchApplicationSuccessful, "Prefab", isPatchApplicationSuccessful,
@ -328,7 +329,7 @@ namespace AzToolsFramework
//propagate the link changes //propagate the link changes
link->get().UpdateTarget(); link->get().UpdateTarget();
m_prefabSystemComponentInterface->PropagateTemplateChanges(link->get().GetTargetTemplateId(), false, instanceToExclude); m_prefabSystemComponentInterface->PropagateTemplateChanges(link->get().GetTargetTemplateId(), instanceToExclude);
//mark as dirty //mark as dirty
m_prefabSystemComponentInterface->SetTemplateDirtyFlag(link->get().GetTargetTemplateId(), true); m_prefabSystemComponentInterface->SetTemplateDirtyFlag(link->get().GetTargetTemplateId(), true);

@ -29,15 +29,14 @@ namespace AzToolsFramework
bool Changed() const override { return m_changed; } bool Changed() const override { return m_changed; }
protected: protected:
TemplateId m_templateId = InvalidTemplateId; TemplateId m_templateId;
PrefabDom m_redoPatch; PrefabDom m_redoPatch;
PrefabDom m_undoPatch; PrefabDom m_undoPatch;
InstanceToTemplateInterface* m_instanceToTemplateInterface = nullptr; InstanceToTemplateInterface* m_instanceToTemplateInterface = nullptr;
bool m_changed = true; bool m_changed;
bool m_useImmediatePropagation = true;
}; };
//! handles the addition and removal of entities from instances //! handles the addition and removal of entities from instances
@ -45,7 +44,7 @@ namespace AzToolsFramework
: public PrefabUndoBase : public PrefabUndoBase
{ {
public: public:
explicit PrefabUndoInstance(const AZStd::string& undoOperationName, bool useImmediatePropagation = true); explicit PrefabUndoInstance(const AZStd::string& undoOperationName);
void Capture( void Capture(
const PrefabDom& initialState, const PrefabDom& initialState,

@ -23,7 +23,7 @@ namespace AzToolsFramework
PrefabDom instanceDomAfterUpdate; PrefabDom instanceDomAfterUpdate;
PrefabDomUtils::StoreInstanceInPrefabDom(instance, instanceDomAfterUpdate); PrefabDomUtils::StoreInstanceInPrefabDom(instance, instanceDomAfterUpdate);
PrefabUndoInstance* state = aznew Prefab::PrefabUndoInstance(undoMessage, false); PrefabUndoInstance* state = aznew Prefab::PrefabUndoInstance(undoMessage);
state->Capture(instanceDomBeforeUpdate, instanceDomAfterUpdate, instance.GetTemplateId()); state->Capture(instanceDomBeforeUpdate, instanceDomAfterUpdate, instance.GetTemplateId());
state->SetParent(undoBatch); state->SetParent(undoBatch);
state->Redo(); state->Redo();

@ -943,13 +943,15 @@ namespace AzToolsFramework
{ {
return false; return false;
} }
const int count = rowCount(parent);
AZ::EntityId newParentId = GetEntityFromIndex(parent); AZ::EntityId newParentId = GetEntityFromIndex(parent);
AZ::EntityId beforeEntityId = GetEntityFromIndex(index(row, 0, parent)); AZ::EntityId beforeEntityId = (row >= 0 && row < count) ? GetEntityFromIndex(index(row, 0, parent)) : AZ::EntityId();
EntityIdList topLevelEntityIds; EntityIdList topLevelEntityIds;
topLevelEntityIds.reserve(entityIdListContainer.m_entityIds.size()); topLevelEntityIds.reserve(entityIdListContainer.m_entityIds.size());
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::FindTopLevelEntityIdsInactive, entityIdListContainer.m_entityIds, topLevelEntityIds); ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::FindTopLevelEntityIdsInactive, entityIdListContainer.m_entityIds, topLevelEntityIds);
if (!ReparentEntities(newParentId, topLevelEntityIds, beforeEntityId)) const auto appendActionForInvalid = newParentId.IsValid() && (row >= count) ? AppendEnd : AppendBeginning;
if (!ReparentEntities(newParentId, topLevelEntityIds, beforeEntityId, appendActionForInvalid))
{ {
return false; return false;
} }
@ -1046,7 +1048,7 @@ namespace AzToolsFramework
return true; return true;
} }
bool EntityOutlinerListModel::ReparentEntities(const AZ::EntityId& newParentId, const EntityIdList &selectedEntityIds, const AZ::EntityId& beforeEntityId) bool EntityOutlinerListModel::ReparentEntities(const AZ::EntityId& newParentId, const EntityIdList &selectedEntityIds, const AZ::EntityId& beforeEntityId, ReparentForInvalid forInvalid)
{ {
AZ_PROFILE_FUNCTION(AzToolsFramework); AZ_PROFILE_FUNCTION(AzToolsFramework);
if (!CanReparentEntities(newParentId, selectedEntityIds)) if (!CanReparentEntities(newParentId, selectedEntityIds))
@ -1056,10 +1058,18 @@ namespace AzToolsFramework
m_isFilterDirty = true; m_isFilterDirty = true;
ScopedUndoBatch undo("Reparent Entities");
//capture child entity order before re-parent operation, which will automatically add order info if not present //capture child entity order before re-parent operation, which will automatically add order info if not present
EntityOrderArray entityOrderArray = GetEntityChildOrder(newParentId); EntityOrderArray entityOrderArray = GetEntityChildOrder(newParentId);
//search for the insertion entity in the order array
const auto beforeEntityItr = AZStd::find(entityOrderArray.begin(), entityOrderArray.end(), beforeEntityId);
const bool hasInvalidIndex = beforeEntityItr == entityOrderArray.end();
if (hasInvalidIndex && forInvalid == None)
{
return false;
}
ScopedUndoBatch undo("Reparent Entities");
// The new parent is dirty due to sort change(s) // The new parent is dirty due to sort change(s)
undo.MarkEntityDirty(GetEntityIdForSortInfo(newParentId)); undo.MarkEntityDirty(GetEntityIdForSortInfo(newParentId));
@ -1088,9 +1098,7 @@ namespace AzToolsFramework
} }
} }
//search for the insertion entity in the order array
auto beforeEntityItr = AZStd::find(entityOrderArray.begin(), entityOrderArray.end(), beforeEntityId);
//replace order info matching selection with bad values rather than remove to preserve layout //replace order info matching selection with bad values rather than remove to preserve layout
for (auto& id : entityOrderArray) for (auto& id : entityOrderArray)
{ {
@ -1100,17 +1108,25 @@ namespace AzToolsFramework
} }
} }
if (newParentId.IsValid()) //if adding to a valid parent entity, insert at the found entity location or at the head/tail depending on placeAtTail flag
if (hasInvalidIndex)
{ {
//if adding to a valid parent entity, insert at the found entity location or at the head of the container switch(forInvalid)
auto insertItr = beforeEntityItr != entityOrderArray.end() ? beforeEntityItr : entityOrderArray.begin(); {
entityOrderArray.insert(insertItr, processedEntityIds.begin(), processedEntityIds.end()); case AppendEnd:
} entityOrderArray.insert(entityOrderArray.end(), processedEntityIds.begin(), processedEntityIds.end());
else break;
case AppendBeginning:
entityOrderArray.insert(entityOrderArray.begin(), processedEntityIds.begin(), processedEntityIds.end());
break;
default:
AZ_Assert(false, "Unexpected type for ReparentForInvalid");
break;
}
}
else
{ {
//if adding to an invalid parent entity (the root), insert at the found entity location or at the tail of the container entityOrderArray.insert(beforeEntityItr, processedEntityIds.begin(), processedEntityIds.end());
auto insertItr = beforeEntityItr != entityOrderArray.end() ? beforeEntityItr : entityOrderArray.end();
entityOrderArray.insert(insertItr, processedEntityIds.begin(), processedEntityIds.end());
} }
//remove placeholder entity ids //remove placeholder entity ids

@ -72,6 +72,13 @@ namespace AzToolsFramework
ColumnCount //!< Total number of columns ColumnCount //!< Total number of columns
}; };
enum ReparentForInvalid
{
None, //!< For an invalid location the entity does not change location
AppendEnd, //!< Append Item to end of target parent list
AppendBeginning, //!< Append Item to the beginning of target parent list
};
// Note: the ColumnSortIndex column isn't shown, hence the -1 and the need for a separate counter. // Note: the ColumnSortIndex column isn't shown, hence the -1 and the need for a separate counter.
// A wrong column count number causes refresh issues and hover mismatch on model update. // A wrong column count number causes refresh issues and hover mismatch on model update.
static const int VisibleColumnCount = ColumnCount - 1; static const int VisibleColumnCount = ColumnCount - 1;
@ -162,7 +169,7 @@ namespace AzToolsFramework
// Buffer Processing Slots - These are called using single-shot events when the buffers begin to fill. // Buffer Processing Slots - These are called using single-shot events when the buffers begin to fill.
bool CanReparentEntities(const AZ::EntityId& newParentId, const EntityIdList& selectedEntityIds) const; bool CanReparentEntities(const AZ::EntityId& newParentId, const EntityIdList& selectedEntityIds) const;
bool ReparentEntities(const AZ::EntityId& newParentId, const EntityIdList& selectedEntityIds, const AZ::EntityId& beforeEntityId = AZ::EntityId()); bool ReparentEntities(const AZ::EntityId& newParentId, const EntityIdList& selectedEntityIds, const AZ::EntityId& beforeEntityId = AZ::EntityId(), ReparentForInvalid forInvalid = None);
//! Use the current filter setting and re-evaluate the filter. //! Use the current filter setting and re-evaluate the filter.
void InvalidateFilter(); void InvalidateFilter();

@ -80,8 +80,9 @@ namespace AzToolsFramework
private: private:
AZStd::string m_message; //!< Message to display for fading text. AZStd::string m_message; //!< Message to display for fading text.
float m_opacity = 1.0f; //!< The opacity of the invalid click message. float m_opacity = 0.0f; //!< The opacity of the invalid click message.
AzFramework::ScreenPoint m_invalidClickPosition; //!< The position to display the invalid click message. //! The position to display the invalid click message.
AzFramework::ScreenPoint m_invalidClickPosition = AzFramework::ScreenPoint(0, 0);
}; };
//! Interface to begin invalid click feedback (will run all added InvalidClick behaviors). //! Interface to begin invalid click feedback (will run all added InvalidClick behaviors).

@ -28,9 +28,12 @@ namespace UnitTest
return true; return true;
} }
void BoundsTestComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context) void BoundsTestComponent::Reflect(AZ::ReflectContext* context)
{ {
// noop if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<BoundsTestComponent, EditorComponentBase>()->Version(1);
}
} }
void BoundsTestComponent::Activate() void BoundsTestComponent::Activate()

@ -42,5 +42,4 @@ namespace UnitTest
AZ::Aabb GetWorldBounds() override; AZ::Aabb GetWorldBounds() override;
AZ::Aabb GetLocalBounds() override; AZ::Aabb GetLocalBounds() override;
}; };
} // namespace UnitTest } // namespace UnitTest

@ -34,6 +34,7 @@ ly_add_target(
INCLUDE_DIRECTORIES INCLUDE_DIRECTORIES
PRIVATE PRIVATE
Source Source
Platform/${PAL_PLATFORM_NAME}
BUILD_DEPENDENCIES BUILD_DEPENDENCIES
PRIVATE PRIVATE
3rdParty::Qt::Core 3rdParty::Qt::Core

@ -11,4 +11,6 @@ set(FILES
ProjectBuilderWorker_linux.cpp ProjectBuilderWorker_linux.cpp
ProjectUtils_linux.cpp ProjectUtils_linux.cpp
ProjectManagerDefs_linux.cpp ProjectManagerDefs_linux.cpp
ProjectManager_Traits_Platform.h
ProjectManager_Traits_Linux.h
) )

@ -0,0 +1,11 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#define AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR false

@ -0,0 +1,11 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <ProjectManager_Traits_Linux.h>

@ -11,4 +11,6 @@ set(FILES
ProjectBuilderWorker_mac.cpp ProjectBuilderWorker_mac.cpp
ProjectUtils_mac.cpp ProjectUtils_mac.cpp
ProjectManagerDefs_mac.cpp ProjectManagerDefs_mac.cpp
ProjectManager_Traits_Platform.h
ProjectManager_Traits_Mac.h
) )

@ -0,0 +1,11 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#define AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR false

@ -0,0 +1,11 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <ProjectManager_Traits_Mac.h>

@ -11,4 +11,6 @@ set(FILES
ProjectBuilderWorker_windows.cpp ProjectBuilderWorker_windows.cpp
ProjectUtils_windows.cpp ProjectUtils_windows.cpp
ProjectManagerDefs_windows.cpp ProjectManagerDefs_windows.cpp
ProjectManager_Traits_Platform.h
ProjectManager_Traits_Windows.h
) )

@ -0,0 +1,11 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <ProjectManager_Traits_Windows.h>

@ -0,0 +1,11 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#define AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR true

@ -9,7 +9,7 @@ QMainWindow {
#ScreensCtrl { #ScreensCtrl {
min-width:1200px; min-width:1200px;
min-height:800px; min-height:700px;
} }
QPushButton:focus { QPushButton:focus {
@ -242,11 +242,15 @@ QTabBar::tab:focus {
/************** Project Settings **************/ /************** Project Settings **************/
#projectSettings { #projectSettings {
margin-top:42px; margin-top:30px;
}
#projectPreviewLabel {
margin: 10px 0 5px 0;
} }
#projectTemplate { #projectTemplate {
margin: 55px 0 0 50px; margin: 25px 0 0 50px;
} }
#projectTemplateLabel { #projectTemplateLabel {
font-size:16px; font-size:16px;

@ -16,6 +16,7 @@
#include <AzQtComponents/Utilities/HandleDpiAwareness.h> #include <AzQtComponents/Utilities/HandleDpiAwareness.h>
#include <AzQtComponents/Components/StyleManager.h> #include <AzQtComponents/Components/StyleManager.h>
#include <AzQtComponents/Components/WindowDecorationWrapper.h> #include <AzQtComponents/Components/WindowDecorationWrapper.h>
#include <ProjectManager_Traits_Platform.h>
#include <QApplication> #include <QApplication>
#include <QDir> #include <QDir>
@ -194,8 +195,12 @@ namespace O3DE::ProjectManager
// set stylesheet after creating the main window or their styles won't get updated // set stylesheet after creating the main window or their styles won't get updated
AzQtComponents::StyleManager::setStyleSheet(m_mainWindow.data(), QStringLiteral("style:ProjectManager.qss")); AzQtComponents::StyleManager::setStyleSheet(m_mainWindow.data(), QStringLiteral("style:ProjectManager.qss"));
// the decoration wrapper is intended to remember window positioning and sizing // the decoration wrapper is intended to remember window positioning and sizing
#if AZ_TRAIT_PROJECT_MANAGER_CUSTOM_TITLEBAR
auto wrapper = new AzQtComponents::WindowDecorationWrapper(); auto wrapper = new AzQtComponents::WindowDecorationWrapper();
#else
auto wrapper = new AzQtComponents::WindowDecorationWrapper(AzQtComponents::WindowDecorationWrapper::OptionDisabled);
#endif
wrapper->setGuest(m_mainWindow.data()); wrapper->setGuest(m_mainWindow.data());
// show the main window here to apply the stylesheet before restoring geometry or we // show the main window here to apply the stylesheet before restoring geometry or we

@ -240,7 +240,7 @@ namespace O3DE::ProjectManager
PythonBindingsInterface::Get()->AddProject(projectInfo.m_path); PythonBindingsInterface::Get()->AddProject(projectInfo.m_path);
#ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED #ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED
const GemCatalogScreen::EnableDisableGemsResult gemResult = m_gemCatalogScreen->EnableDisableGemsForProject(m_projectInfo.m_path); const GemCatalogScreen::EnableDisableGemsResult gemResult = m_gemCatalogScreen->EnableDisableGemsForProject(projectInfo.m_path);
if (gemResult == GemCatalogScreen::EnableDisableGemsResult::Failed) if (gemResult == GemCatalogScreen::EnableDisableGemsResult::Failed)
{ {
QMessageBox::critical(this, tr("Failed to configure gems"), tr("Failed to configure gems for template.")); QMessageBox::critical(this, tr("Failed to configure gems"), tr("Failed to configure gems for template."));

@ -62,9 +62,6 @@ namespace O3DE::ProjectManager
QPushButton* m_secondaryButton = nullptr; QPushButton* m_secondaryButton = nullptr;
#endif // TEMPLATE_GEM_CONFIGURATION_ENABLED #endif // TEMPLATE_GEM_CONFIGURATION_ENABLED
QString m_projectTemplatePath;
ProjectInfo m_projectInfo;
NewProjectSettingsScreen* m_newProjectSettingsScreen = nullptr; NewProjectSettingsScreen* m_newProjectSettingsScreen = nullptr;
GemCatalogScreen* m_gemCatalogScreen = nullptr; GemCatalogScreen* m_gemCatalogScreen = nullptr;
}; };

@ -11,19 +11,28 @@
#include <FormFolderBrowseEditWidget.h> #include <FormFolderBrowseEditWidget.h>
#include <PythonBindingsInterface.h> #include <PythonBindingsInterface.h>
#include <PathValidator.h> #include <PathValidator.h>
#include <AzQtComponents/Utilities/DesktopUtilities.h>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
#include <QMessageBox> #include <QMessageBox>
#include <QScrollArea>
namespace O3DE::ProjectManager namespace O3DE::ProjectManager
{ {
EngineSettingsScreen::EngineSettingsScreen(QWidget* parent) EngineSettingsScreen::EngineSettingsScreen(QWidget* parent)
: ScreenWidget(parent) : ScreenWidget(parent)
{ {
auto* layout = new QVBoxLayout(); QScrollArea* scrollArea = new QScrollArea(this);
scrollArea->setWidgetResizable(true);
QWidget* scrollWidget = new QWidget(this);
scrollArea->setWidget(scrollWidget);
QVBoxLayout* layout = new QVBoxLayout(scrollWidget);
layout->setAlignment(Qt::AlignTop); layout->setAlignment(Qt::AlignTop);
scrollWidget->setLayout(layout);
setObjectName("engineSettingsScreen"); setObjectName("engineSettingsScreen");
@ -39,9 +48,18 @@ namespace O3DE::ProjectManager
formTitleLabel->setObjectName("formTitleLabel"); formTitleLabel->setObjectName("formTitleLabel");
layout->addWidget(formTitleLabel); layout->addWidget(formTitleLabel);
m_engineVersion = new FormLineEditWidget(tr("Engine Version"), engineInfo.m_version, this); FormLineEditWidget* engineName = new FormLineEditWidget(tr("Engine Name"), engineInfo.m_name, this);
m_engineVersion->lineEdit()->setReadOnly(true); engineName->lineEdit()->setReadOnly(true);
layout->addWidget(m_engineVersion); layout->addWidget(engineName);
FormLineEditWidget* engineVersion = new FormLineEditWidget(tr("Engine Version"), engineInfo.m_version, this);
engineVersion->lineEdit()->setReadOnly(true);
layout->addWidget(engineVersion);
FormBrowseEditWidget* engineFolder = new FormBrowseEditWidget(tr("Engine Folder"), engineInfo.m_path, this);
engineFolder->lineEdit()->setReadOnly(true);
connect( engineFolder, &FormBrowseEditWidget::OnBrowse, [engineInfo]{ AzQtComponents::ShowFileOnDesktop(engineInfo.m_path); });
layout->addWidget(engineFolder);
m_thirdParty = new FormFolderBrowseEditWidget(tr("3rd Party Software Folder"), engineInfo.m_thirdPartyPath, this); m_thirdParty = new FormFolderBrowseEditWidget(tr("3rd Party Software Folder"), engineInfo.m_thirdPartyPath, this);
m_thirdParty->lineEdit()->setValidator(new PathValidator(PathValidator::PathMode::ExistingFolder, this)); m_thirdParty->lineEdit()->setValidator(new PathValidator(PathValidator::PathMode::ExistingFolder, this));
@ -71,7 +89,11 @@ namespace O3DE::ProjectManager
connect(m_defaultProjectTemplates->lineEdit(), &QLineEdit::textChanged, this, &EngineSettingsScreen::OnTextChanged); connect(m_defaultProjectTemplates->lineEdit(), &QLineEdit::textChanged, this, &EngineSettingsScreen::OnTextChanged);
layout->addWidget(m_defaultProjectTemplates); layout->addWidget(m_defaultProjectTemplates);
setLayout(layout); QVBoxLayout* mainLayout = new QVBoxLayout();
mainLayout->setAlignment(Qt::AlignTop);
mainLayout->setMargin(0);
mainLayout->addWidget(scrollArea);
setLayout(mainLayout);
} }
ProjectManagerScreen EngineSettingsScreen::GetScreenEnum() ProjectManagerScreen EngineSettingsScreen::GetScreenEnum()

@ -29,7 +29,6 @@ namespace O3DE::ProjectManager
void OnTextChanged(); void OnTextChanged();
private: private:
FormLineEditWidget* m_engineVersion;
FormBrowseEditWidget* m_thirdParty; FormBrowseEditWidget* m_thirdParty;
FormBrowseEditWidget* m_defaultProjects; FormBrowseEditWidget* m_defaultProjects;
FormBrowseEditWidget* m_defaultGems; FormBrowseEditWidget* m_defaultGems;

@ -20,7 +20,8 @@ namespace O3DE::ProjectManager
setObjectName("formBrowseEditWidget"); setObjectName("formBrowseEditWidget");
QPushButton* browseButton = new QPushButton(this); QPushButton* browseButton = new QPushButton(this);
connect(browseButton, &QPushButton::pressed, this, &FormBrowseEditWidget::HandleBrowseButton); connect( browseButton, &QPushButton::pressed, [this]{ emit OnBrowse(); });
connect( this, &FormBrowseEditWidget::OnBrowse, this, &FormBrowseEditWidget::HandleBrowseButton);
m_frameLayout->addWidget(browseButton); m_frameLayout->addWidget(browseButton);
} }
@ -34,7 +35,7 @@ namespace O3DE::ProjectManager
int key = event->key(); int key = event->key();
if (key == Qt::Key_Return || key == Qt::Key_Enter) if (key == Qt::Key_Return || key == Qt::Key_Enter)
{ {
HandleBrowseButton(); emit OnBrowse();
} }
} }

@ -24,10 +24,13 @@ namespace O3DE::ProjectManager
explicit FormBrowseEditWidget(const QString& labelText = "", QWidget* parent = nullptr); explicit FormBrowseEditWidget(const QString& labelText = "", QWidget* parent = nullptr);
~FormBrowseEditWidget() = default; ~FormBrowseEditWidget() = default;
signals:
void OnBrowse();
protected: protected:
void keyPressEvent(QKeyEvent* event) override; void keyPressEvent(QKeyEvent* event) override;
protected slots: protected slots:
virtual void HandleBrowseButton() = 0; virtual void HandleBrowseButton() {};
}; };
} // namespace O3DE::ProjectManager } // namespace O3DE::ProjectManager

@ -30,7 +30,7 @@ namespace O3DE::ProjectManager
: ScreenWidget(parent) : ScreenWidget(parent)
{ {
m_gemModel = new GemModel(this); m_gemModel = new GemModel(this);
m_proxModel = new GemSortFilterProxyModel(m_gemModel, this); m_proxyModel = new GemSortFilterProxyModel(m_gemModel, this);
QVBoxLayout* vLayout = new QVBoxLayout(); QVBoxLayout* vLayout = new QVBoxLayout();
vLayout->setMargin(0); vLayout->setMargin(0);
@ -39,7 +39,7 @@ namespace O3DE::ProjectManager
m_downloadController = new DownloadController(); m_downloadController = new DownloadController();
m_headerWidget = new GemCatalogHeaderWidget(m_gemModel, m_proxModel, m_downloadController); m_headerWidget = new GemCatalogHeaderWidget(m_gemModel, m_proxyModel, m_downloadController);
vLayout->addWidget(m_headerWidget); vLayout->addWidget(m_headerWidget);
connect(m_gemModel, &GemModel::gemStatusChanged, this, &GemCatalogScreen::OnGemStatusChanged); connect(m_gemModel, &GemModel::gemStatusChanged, this, &GemCatalogScreen::OnGemStatusChanged);
@ -50,10 +50,12 @@ namespace O3DE::ProjectManager
hLayout->setMargin(0); hLayout->setMargin(0);
vLayout->addLayout(hLayout); vLayout->addLayout(hLayout);
m_gemListView = new GemListView(m_proxModel, m_proxModel->GetSelectionModel(), this); m_gemListView = new GemListView(m_proxyModel, m_proxyModel->GetSelectionModel(), this);
m_gemInspector = new GemInspector(m_gemModel, this); m_gemInspector = new GemInspector(m_gemModel, this);
m_gemInspector->setFixedWidth(240); m_gemInspector->setFixedWidth(240);
connect(m_gemInspector, &GemInspector::TagClicked, this, &GemCatalogScreen::SelectGem);
QWidget* filterWidget = new QWidget(this); QWidget* filterWidget = new QWidget(this);
filterWidget->setFixedWidth(240); filterWidget->setFixedWidth(240);
m_filterWidgetLayout = new QVBoxLayout(); m_filterWidgetLayout = new QVBoxLayout();
@ -61,7 +63,7 @@ namespace O3DE::ProjectManager
m_filterWidgetLayout->setSpacing(0); m_filterWidgetLayout->setSpacing(0);
filterWidget->setLayout(m_filterWidgetLayout); filterWidget->setLayout(m_filterWidgetLayout);
GemListHeaderWidget* listHeaderWidget = new GemListHeaderWidget(m_proxModel); GemListHeaderWidget* listHeaderWidget = new GemListHeaderWidget(m_proxyModel);
QVBoxLayout* middleVLayout = new QVBoxLayout(); QVBoxLayout* middleVLayout = new QVBoxLayout();
middleVLayout->setMargin(0); middleVLayout->setMargin(0);
@ -80,19 +82,21 @@ namespace O3DE::ProjectManager
void GemCatalogScreen::ReinitForProject(const QString& projectPath) void GemCatalogScreen::ReinitForProject(const QString& projectPath)
{ {
m_gemModel->clear(); m_gemModel->Clear();
m_gemsToRegisterWithProject.clear(); m_gemsToRegisterWithProject.clear();
FillModel(projectPath); FillModel(projectPath);
m_proxyModel->ResetFilters();
if (m_filterWidget) if (m_filterWidget)
{ {
m_filterWidget->hide(); m_filterWidget->ResetAllFilters();
m_filterWidget->deleteLater(); }
else
{
m_filterWidget = new GemFilterWidget(m_proxyModel);
m_filterWidgetLayout->addWidget(m_filterWidget);
} }
m_proxModel->ResetFilters();
m_filterWidget = new GemFilterWidget(m_proxModel);
m_filterWidgetLayout->addWidget(m_filterWidget);
m_headerWidget->ReinitForProject(); m_headerWidget->ReinitForProject();
@ -192,6 +196,20 @@ namespace O3DE::ProjectManager
} }
} }
void GemCatalogScreen::SelectGem(const QString& gemName)
{
QModelIndex modelIndex = m_gemModel->FindIndexByNameString(gemName);
if (!m_proxyModel->filterAcceptsRow(modelIndex.row(), QModelIndex()))
{
m_proxyModel->ResetFilters();
m_filterWidget->ResetAllFilters();
}
QModelIndex proxyIndex = m_proxyModel->mapFromSource(modelIndex);
m_proxyModel->GetSelectionModel()->select(proxyIndex, QItemSelectionModel::ClearAndSelect);
m_gemListView->scrollTo(proxyIndex);
}
void GemCatalogScreen::hideEvent(QHideEvent* event) void GemCatalogScreen::hideEvent(QHideEvent* event)
{ {
ScreenWidget::hideEvent(event); ScreenWidget::hideEvent(event);

@ -48,6 +48,7 @@ namespace O3DE::ProjectManager
public slots: public slots:
void OnGemStatusChanged(const QString& gemName, uint32_t numChangedDependencies); void OnGemStatusChanged(const QString& gemName, uint32_t numChangedDependencies);
void OnAddGemClicked(); void OnAddGemClicked();
void SelectGem(const QString& gemName);
protected: protected:
void hideEvent(QHideEvent* event) override; void hideEvent(QHideEvent* event) override;
@ -68,7 +69,7 @@ namespace O3DE::ProjectManager
GemInspector* m_gemInspector = nullptr; GemInspector* m_gemInspector = nullptr;
GemModel* m_gemModel = nullptr; GemModel* m_gemModel = nullptr;
GemCatalogHeaderWidget* m_headerWidget = nullptr; GemCatalogHeaderWidget* m_headerWidget = nullptr;
GemSortFilterProxyModel* m_proxModel = nullptr; GemSortFilterProxyModel* m_proxyModel = nullptr;
QVBoxLayout* m_filterWidgetLayout = nullptr; QVBoxLayout* m_filterWidgetLayout = nullptr;
GemFilterWidget* m_filterWidget = nullptr; GemFilterWidget* m_filterWidget = nullptr;
DownloadController* m_downloadController = nullptr; DownloadController* m_downloadController = nullptr;

@ -213,11 +213,99 @@ namespace O3DE::ProjectManager
m_filterLayout->setContentsMargins(0, 0, 0, 0); m_filterLayout->setContentsMargins(0, 0, 0, 0);
filterSection->setLayout(m_filterLayout); filterSection->setLayout(m_filterLayout);
ResetAllFilters();
}
void GemFilterWidget::ResetAllFilters()
{
ResetGemStatusFilter(); ResetGemStatusFilter();
AddGemOriginFilter(); ResetGemOriginFilter();
AddTypeFilter(); ResetTypeFilter();
AddPlatformFilter(); ResetPlatformFilter();
AddFeatureFilter(); ResetFeatureFilter();
}
void GemFilterWidget::ResetFilterWidget(
FilterCategoryWidget*& filterPtr,
const QString& filterName,
const QVector<QString>& elementNames,
const QVector<int>& elementCounts,
int defaultShowCount)
{
bool wasCollapsed = false;
if (filterPtr)
{
wasCollapsed = filterPtr->IsCollapsed();
}
FilterCategoryWidget* filterWidget = new FilterCategoryWidget(
filterName, elementNames, elementCounts, /*showAllLessButton=*/defaultShowCount != 4, /*collapsed*/ wasCollapsed,
/*defaultShowCount=*/defaultShowCount);
if (filterPtr)
{
m_filterLayout->replaceWidget(filterPtr, filterWidget);
}
else
{
m_filterLayout->addWidget(filterWidget);
}
filterPtr->deleteLater();
filterPtr = filterWidget;
}
template<typename filterType, typename filterFlagsType>
void GemFilterWidget::ResetSimpleOrFilter(
FilterCategoryWidget*& filterPtr,
const QString& filterName,
int numFilterElements,
bool (*filterMatcher)(GemModel*, filterType, int),
QString (*typeStringGetter)(filterType),
filterFlagsType (GemSortFilterProxyModel::*filterFlagsGetter)() const,
void (GemSortFilterProxyModel::*filterFlagsSetter)(const filterFlagsType&))
{
QVector<QString> elementNames;
QVector<int> elementCounts;
const int numGems = m_gemModel->rowCount();
for (int filterIndex = 0; filterIndex < numFilterElements; ++filterIndex)
{
const filterType gemFilterToBeCounted = static_cast<filterType>(1 << filterIndex);
int gemFilterCount = 0;
for (int gemIndex = 0; gemIndex < numGems; ++gemIndex)
{
// If filter matches increment filter count
gemFilterCount += filterMatcher(m_gemModel, gemFilterToBeCounted, gemIndex);
}
elementNames.push_back(typeStringGetter(gemFilterToBeCounted));
elementCounts.push_back(gemFilterCount);
}
// Replace existing filter and delete old one
ResetFilterWidget(filterPtr, filterName, elementNames, elementCounts);
const QList<QAbstractButton*> buttons = filterPtr->GetButtonGroup()->buttons();
for (int i = 0; i < buttons.size(); ++i)
{
const filterType gemFilter = static_cast<filterType>(1 << i);
QAbstractButton* button = buttons[i];
connect(
button, &QAbstractButton::toggled, this,
[=](bool checked)
{
filterFlagsType gemFilters = (m_filterProxyModel->*filterFlagsGetter)();
if (checked)
{
gemFilters |= gemFilter;
}
else
{
gemFilters &= ~gemFilter;
}
(m_filterProxyModel->*filterFlagsSetter)(gemFilters);
});
}
} }
void GemFilterWidget::ResetGemStatusFilter() void GemFilterWidget::ResetGemStatusFilter()
@ -241,25 +329,7 @@ namespace O3DE::ProjectManager
elementNames.push_back(GemSortFilterProxyModel::GetGemActiveString(GemSortFilterProxyModel::GemActive::Inactive)); elementNames.push_back(GemSortFilterProxyModel::GetGemActiveString(GemSortFilterProxyModel::GemActive::Inactive));
elementCounts.push_back(totalGems - enabledGemTotal); elementCounts.push_back(totalGems - enabledGemTotal);
bool wasCollapsed = false; ResetFilterWidget(m_statusFilter, "Status", elementNames, elementCounts);
if (m_statusFilter)
{
wasCollapsed = m_statusFilter->IsCollapsed();
}
FilterCategoryWidget* filterWidget =
new FilterCategoryWidget("Status", elementNames, elementCounts, /*showAllLessButton=*/false, /*collapsed*/wasCollapsed);
if (m_statusFilter)
{
m_filterLayout->replaceWidget(m_statusFilter, filterWidget);
}
else
{
m_filterLayout->addWidget(filterWidget);
}
m_statusFilter->deleteLater();
m_statusFilter = filterWidget;
const QList<QAbstractButton*> buttons = m_statusFilter->GetButtonGroup()->buttons(); const QList<QAbstractButton*> buttons = m_statusFilter->GetButtonGroup()->buttons();
@ -317,157 +387,42 @@ namespace O3DE::ProjectManager
connect(activeButton, &QAbstractButton::toggled, this, updateGemActive); connect(activeButton, &QAbstractButton::toggled, this, updateGemActive);
} }
void GemFilterWidget::AddGemOriginFilter() void GemFilterWidget::ResetGemOriginFilter()
{ {
QVector<QString> elementNames; ResetSimpleOrFilter<GemInfo::GemOrigin, GemInfo::GemOrigins>
QVector<int> elementCounts; (
const int numGems = m_gemModel->rowCount(); m_originFilter, "Provider", GemInfo::NumGemOrigins,
for (int originIndex = 0; originIndex < GemInfo::NumGemOrigins; ++originIndex) [](GemModel* gemModel, GemInfo::GemOrigin origin, int gemIndex)
{
const GemInfo::GemOrigin gemOriginToBeCounted = static_cast<GemInfo::GemOrigin>(1 << originIndex);
int gemOriginCount = 0;
for (int gemIndex = 0; gemIndex < numGems; ++gemIndex)
{ {
const GemInfo::GemOrigin gemOrigin = m_gemModel->GetGemOrigin(m_gemModel->index(gemIndex, 0)); return origin == gemModel->GetGemOrigin(gemModel->index(gemIndex, 0));
},
// Is the gem of the given origin? &GemInfo::GetGemOriginString, &GemSortFilterProxyModel::GetGemOrigins, &GemSortFilterProxyModel::SetGemOrigins
if (gemOriginToBeCounted == gemOrigin) );
{
gemOriginCount++;
}
}
elementNames.push_back(GemInfo::GetGemOriginString(gemOriginToBeCounted));
elementCounts.push_back(gemOriginCount);
}
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Provider", elementNames, elementCounts, /*showAllLessButton=*/false);
m_filterLayout->addWidget(filterWidget);
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
for (int i = 0; i < buttons.size(); ++i)
{
const GemInfo::GemOrigin gemOrigin = static_cast<GemInfo::GemOrigin>(1 << i);
QAbstractButton* button = buttons[i];
connect(button, &QAbstractButton::toggled, this, [=](bool checked)
{
GemInfo::GemOrigins gemOrigins = m_filterProxyModel->GetGemOrigins();
if (checked)
{
gemOrigins |= gemOrigin;
}
else
{
gemOrigins &= ~gemOrigin;
}
m_filterProxyModel->SetGemOrigins(gemOrigins);
});
}
} }
void GemFilterWidget::AddTypeFilter() void GemFilterWidget::ResetTypeFilter()
{ {
QVector<QString> elementNames; ResetSimpleOrFilter<GemInfo::Type, GemInfo::Types>(
QVector<int> elementCounts; m_typeFilter, "Type", GemInfo::NumTypes,
const int numGems = m_gemModel->rowCount(); [](GemModel* gemModel, GemInfo::Type type, int gemIndex)
for (int typeIndex = 0; typeIndex < GemInfo::NumTypes; ++typeIndex)
{
const GemInfo::Type type = static_cast<GemInfo::Type>(1 << typeIndex);
int typeGemCount = 0;
for (int gemIndex = 0; gemIndex < numGems; ++gemIndex)
{ {
const GemInfo::Types types = m_gemModel->GetTypes(m_gemModel->index(gemIndex, 0)); return static_cast<bool>(type & gemModel->GetTypes(gemModel->index(gemIndex, 0)));
},
// Is type (Asset, Code, Tool) part of the gem? &GemInfo::GetTypeString, &GemSortFilterProxyModel::GetTypes, &GemSortFilterProxyModel::SetTypes);
if (types & type)
{
typeGemCount++;
}
}
elementNames.push_back(GemInfo::GetTypeString(type));
elementCounts.push_back(typeGemCount);
}
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Type", elementNames, elementCounts, /*showAllLessButton=*/false);
m_filterLayout->addWidget(filterWidget);
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
for (int i = 0; i < buttons.size(); ++i)
{
const GemInfo::Type type = static_cast<GemInfo::Type>(1 << i);
QAbstractButton* button = buttons[i];
connect(button, &QAbstractButton::toggled, this, [=](bool checked)
{
GemInfo::Types types = m_filterProxyModel->GetTypes();
if (checked)
{
types |= type;
}
else
{
types &= ~type;
}
m_filterProxyModel->SetTypes(types);
});
}
} }
void GemFilterWidget::AddPlatformFilter() void GemFilterWidget::ResetPlatformFilter()
{ {
QVector<QString> elementNames; ResetSimpleOrFilter<GemInfo::Platform, GemInfo::Platforms>(
QVector<int> elementCounts; m_platformFilter, "Supported Platforms", GemInfo::NumPlatforms,
const int numGems = m_gemModel->rowCount(); [](GemModel* gemModel, GemInfo::Platform platform, int gemIndex)
for (int platformIndex = 0; platformIndex < GemInfo::NumPlatforms; ++platformIndex)
{
const GemInfo::Platform platform = static_cast<GemInfo::Platform>(1 << platformIndex);
int platformGemCount = 0;
for (int gemIndex = 0; gemIndex < numGems; ++gemIndex)
{ {
const GemInfo::Platforms platforms = m_gemModel->GetPlatforms(m_gemModel->index(gemIndex, 0)); return static_cast<bool>(platform & gemModel->GetPlatforms(gemModel->index(gemIndex, 0)));
},
// Is platform supported? &GemInfo::GetPlatformString, &GemSortFilterProxyModel::GetPlatforms, &GemSortFilterProxyModel::SetPlatforms);
if (platforms & platform)
{
platformGemCount++;
}
}
elementNames.push_back(GemInfo::GetPlatformString(platform));
elementCounts.push_back(platformGemCount);
}
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Supported Platforms", elementNames, elementCounts, /*showAllLessButton=*/false);
m_filterLayout->addWidget(filterWidget);
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
for (int i = 0; i < buttons.size(); ++i)
{
const GemInfo::Platform platform = static_cast<GemInfo::Platform>(1 << i);
QAbstractButton* button = buttons[i];
connect(button, &QAbstractButton::toggled, this, [=](bool checked)
{
GemInfo::Platforms platforms = m_filterProxyModel->GetPlatforms();
if (checked)
{
platforms |= platform;
}
else
{
platforms &= ~platform;
}
m_filterProxyModel->SetPlatforms(platforms);
});
}
} }
void GemFilterWidget::AddFeatureFilter() void GemFilterWidget::ResetFeatureFilter()
{ {
// Alphabetically sorted, unique features and their number of occurrences in the gem database. // Alphabetically sorted, unique features and their number of occurrences in the gem database.
QMap<QString, int> uniqueFeatureCounts; QMap<QString, int> uniqueFeatureCounts;
@ -497,11 +452,15 @@ namespace O3DE::ProjectManager
elementCounts.push_back(iterator.value()); elementCounts.push_back(iterator.value());
} }
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Features", elementNames, elementCounts, ResetFilterWidget(m_featureFilter, "Features", elementNames, elementCounts, /*defaultShowCount=*/5);
/*showAllLessButton=*/true, false, /*defaultShowCount=*/5);
m_filterLayout->addWidget(filterWidget);
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons(); for (QMetaObject::Connection& connection : m_featureTagConnections)
{
disconnect(connection);
}
m_featureTagConnections.clear();
const QList<QAbstractButton*> buttons = m_featureFilter->GetButtonGroup()->buttons();
for (int i = 0; i < buttons.size(); ++i) for (int i = 0; i < buttons.size(); ++i)
{ {
const QString& feature = elementNames[i]; const QString& feature = elementNames[i];
@ -523,13 +482,13 @@ namespace O3DE::ProjectManager
}); });
// Sync the UI state with the proxy model filtering. // Sync the UI state with the proxy model filtering.
connect(m_filterProxyModel, &GemSortFilterProxyModel::OnInvalidated, this, [=] m_featureTagConnections.push_back(connect(m_filterProxyModel, &GemSortFilterProxyModel::OnInvalidated, this, [=]
{ {
const QSet<QString>& filteredFeatureTags = m_filterProxyModel->GetFeatures(); const QSet<QString>& filteredFeatureTags = m_filterProxyModel->GetFeatures();
const bool isChecked = filteredFeatureTags.contains(button->text()); const bool isChecked = filteredFeatureTags.contains(button->text());
QSignalBlocker signalsBlocker(button); QSignalBlocker signalsBlocker(button);
button->setChecked(isChecked); button->setChecked(isChecked);
}); }));
} }
} }
} // namespace O3DE::ProjectManager } // namespace O3DE::ProjectManager

@ -66,17 +66,41 @@ namespace O3DE::ProjectManager
~GemFilterWidget() = default; ~GemFilterWidget() = default;
public slots: public slots:
void ResetAllFilters();
void ResetGemStatusFilter(); void ResetGemStatusFilter();
private: private:
void AddGemOriginFilter(); void ResetGemOriginFilter();
void AddTypeFilter(); void ResetTypeFilter();
void AddPlatformFilter(); void ResetPlatformFilter();
void AddFeatureFilter(); void ResetFeatureFilter();
void ResetFilterWidget(
FilterCategoryWidget*& filterPtr,
const QString& filterName,
const QVector<QString>& elementNames,
const QVector<int>& elementCounts,
int defaultShowCount = 4);
template<typename filterType, typename filterFlagsType>
void ResetSimpleOrFilter(
FilterCategoryWidget*& filterPtr,
const QString& filterName,
int numFilterElements,
bool (*filterMatcher)(GemModel*, filterType, int),
QString (*typeStringGetter)(filterType),
filterFlagsType (GemSortFilterProxyModel::*filterFlagsGetter)() const,
void (GemSortFilterProxyModel::*filterFlagsSetter)(const filterFlagsType&));
QVBoxLayout* m_filterLayout = nullptr; QVBoxLayout* m_filterLayout = nullptr;
GemModel* m_gemModel = nullptr; GemModel* m_gemModel = nullptr;
GemSortFilterProxyModel* m_filterProxyModel = nullptr; GemSortFilterProxyModel* m_filterProxyModel = nullptr;
FilterCategoryWidget* m_statusFilter = nullptr; FilterCategoryWidget* m_statusFilter = nullptr;
FilterCategoryWidget* m_originFilter = nullptr;
FilterCategoryWidget* m_typeFilter = nullptr;
FilterCategoryWidget* m_platformFilter = nullptr;
FilterCategoryWidget* m_featureFilter = nullptr;
QVector<QMetaObject::Connection> m_featureTagConnections;
}; };
} // namespace O3DE::ProjectManager } // namespace O3DE::ProjectManager

@ -175,6 +175,7 @@ namespace O3DE::ProjectManager
// Depending gems // Depending gems
m_dependingGems = new GemsSubWidget(); m_dependingGems = new GemsSubWidget();
connect(m_dependingGems, &GemsSubWidget::TagClicked, this, [=](const QString& tag){ emit TagClicked(tag); });
m_mainLayout->addWidget(m_dependingGems); m_mainLayout->addWidget(m_dependingGems);
m_mainLayout->addSpacing(20); m_mainLayout->addSpacing(20);

@ -40,6 +40,9 @@ namespace O3DE::ProjectManager
inline constexpr static const char* s_headerColor = "#FFFFFF"; inline constexpr static const char* s_headerColor = "#FFFFFF";
inline constexpr static const char* s_textColor = "#DDDDDD"; inline constexpr static const char* s_textColor = "#DDDDDD";
signals:
void TagClicked(const QString& tag);
private slots: private slots:
void OnSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected); void OnSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected);

@ -62,12 +62,14 @@ namespace O3DE::ProjectManager
appendRow(item); appendRow(item);
const QModelIndex modelIndex = index(rowCount()-1, 0); const QModelIndex modelIndex = index(rowCount()-1, 0);
m_nameToIndexMap[gemInfo.m_displayName] = modelIndex;
m_nameToIndexMap[gemInfo.m_name] = modelIndex; m_nameToIndexMap[gemInfo.m_name] = modelIndex;
} }
void GemModel::Clear() void GemModel::Clear()
{ {
clear(); clear();
m_nameToIndexMap.clear();
} }
void GemModel::UpdateGemDependencies() void GemModel::UpdateGemDependencies()

@ -207,6 +207,8 @@ namespace O3DE::ProjectManager
void GemSortFilterProxyModel::ResetFilters() void GemSortFilterProxyModel::ResetFilters()
{ {
m_searchString.clear(); m_searchString.clear();
m_gemSelectedFilter = GemSelected::NoFilter;
m_gemActiveFilter = GemActive::NoFilter;
m_gemOriginFilter = {}; m_gemOriginFilter = {};
m_platformFilter = {}; m_platformFilter = {};
m_typeFilter = {}; m_typeFilter = {};

@ -39,7 +39,6 @@ namespace O3DE::ProjectManager
QRect fullRect, itemRect, contentRect; QRect fullRect, itemRect, contentRect;
CalcRects(options, fullRect, itemRect, contentRect); CalcRects(options, fullRect, itemRect, contentRect);
QRect buttonRect = CalcButtonRect(contentRect);
QFont standardFont(options.font); QFont standardFont(options.font);
standardFont.setPixelSize(static_cast<int>(s_fontSize)); standardFont.setPixelSize(static_cast<int>(s_fontSize));
@ -70,15 +69,12 @@ namespace O3DE::ProjectManager
painter->restore(); painter->restore();
} }
// Repo enabled
DrawButton(painter, buttonRect, modelIndex);
// Repo name // Repo name
QString repoName = GemRepoModel::GetName(modelIndex); QString repoName = GemRepoModel::GetName(modelIndex);
repoName = QFontMetrics(standardFont).elidedText(repoName, Qt::TextElideMode::ElideRight, s_nameMaxWidth); repoName = QFontMetrics(standardFont).elidedText(repoName, Qt::TextElideMode::ElideRight, s_nameMaxWidth);
QRect repoNameRect = GetTextRect(standardFont, repoName, s_fontSize); QRect repoNameRect = GetTextRect(standardFont, repoName, s_fontSize);
int currentHorizontalOffset = buttonRect.left() + s_buttonWidth + s_buttonSpacing; int currentHorizontalOffset = contentRect.left();
repoNameRect.moveTo(currentHorizontalOffset, contentRect.center().y() - repoNameRect.height() / 2); repoNameRect.moveTo(currentHorizontalOffset, contentRect.center().y() - repoNameRect.height() / 2);
repoNameRect = painter->boundingRect(repoNameRect, Qt::TextSingleLine, repoName); repoNameRect = painter->boundingRect(repoNameRect, Qt::TextSingleLine, repoName);
@ -126,7 +122,7 @@ namespace O3DE::ProjectManager
initStyleOption(&options, modelIndex); initStyleOption(&options, modelIndex);
int marginsHorizontal = s_itemMargins.left() + s_itemMargins.right() + s_contentMargins.left() + s_contentMargins.right(); int marginsHorizontal = s_itemMargins.left() + s_itemMargins.right() + s_contentMargins.left() + s_contentMargins.right();
return QSize(marginsHorizontal + s_buttonWidth + s_buttonSpacing + s_nameMaxWidth + s_creatorMaxWidth + s_updatedMaxWidth + s_contentSpacing * 3, s_height); return QSize(marginsHorizontal + s_nameMaxWidth + s_creatorMaxWidth + s_updatedMaxWidth + s_contentSpacing * 3, s_height);
} }
bool GemRepoItemDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) bool GemRepoItemDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& modelIndex)
@ -139,13 +135,8 @@ namespace O3DE::ProjectManager
if (event->type() == QEvent::KeyPress) if (event->type() == QEvent::KeyPress)
{ {
auto keyEvent = static_cast<const QKeyEvent*>(event); auto keyEvent = static_cast<const QKeyEvent*>(event);
if (keyEvent->key() == Qt::Key_Space)
{ if (keyEvent->key() == Qt::Key_X)
const bool isAdded = GemRepoModel::IsEnabled(modelIndex);
GemRepoModel::SetEnabled(*model, modelIndex, !isAdded);
return true;
}
else if (keyEvent->key() == Qt::Key_X)
{ {
emit RemoveRepo(modelIndex); emit RemoveRepo(modelIndex);
return true; return true;
@ -163,17 +154,10 @@ namespace O3DE::ProjectManager
QRect fullRect, itemRect, contentRect; QRect fullRect, itemRect, contentRect;
CalcRects(option, fullRect, itemRect, contentRect); CalcRects(option, fullRect, itemRect, contentRect);
const QRect buttonRect = CalcButtonRect(contentRect);
const QRect deleteButtonRect = CalcDeleteButtonRect(contentRect); const QRect deleteButtonRect = CalcDeleteButtonRect(contentRect);
const QRect refreshButtonRect = CalcRefreshButtonRect(contentRect, buttonRect); const QRect refreshButtonRect = CalcRefreshButtonRect(contentRect);
if (buttonRect.contains(mouseEvent->pos())) if (deleteButtonRect.contains(mouseEvent->pos()))
{
const bool isAdded = GemRepoModel::IsEnabled(modelIndex);
GemRepoModel::SetEnabled(*model, modelIndex, !isAdded);
return true;
}
else if (deleteButtonRect.contains(mouseEvent->pos()))
{ {
emit RemoveRepo(modelIndex); emit RemoveRepo(modelIndex);
return true; return true;
@ -201,50 +185,15 @@ namespace O3DE::ProjectManager
return QFontMetrics(font).boundingRect(text); return QFontMetrics(font).boundingRect(text);
} }
QRect GemRepoItemDelegate::CalcButtonRect(const QRect& contentRect) const
{
const QPoint topLeft = QPoint(contentRect.left(), contentRect.top() + contentRect.height() / 2 - s_buttonHeight / 2);
const QSize size = QSize(s_buttonWidth, s_buttonHeight);
return QRect(topLeft, size);
}
void GemRepoItemDelegate::DrawButton(QPainter* painter, const QRect& buttonRect, const QModelIndex& modelIndex) const
{
painter->save();
QPoint circleCenter;
const bool isEnabled = GemRepoModel::IsEnabled(modelIndex);
if (isEnabled)
{
painter->setBrush(m_buttonEnabledColor);
painter->setPen(m_buttonEnabledColor);
circleCenter = buttonRect.center() + QPoint(buttonRect.width() / 2 - s_buttonBorderRadius + 1, 1);
}
else
{
circleCenter = buttonRect.center() + QPoint(-buttonRect.width() / 2 + s_buttonBorderRadius + 1, 1);
}
// Rounded rect
painter->drawRoundedRect(buttonRect, s_buttonBorderRadius, s_buttonBorderRadius);
// Circle
painter->setBrush(m_textColor);
painter->drawEllipse(circleCenter, s_buttonCircleRadius, s_buttonCircleRadius);
painter->restore();
}
QRect GemRepoItemDelegate::CalcDeleteButtonRect(const QRect& contentRect) const QRect GemRepoItemDelegate::CalcDeleteButtonRect(const QRect& contentRect) const
{ {
const QPoint topLeft = QPoint(contentRect.right() - s_iconSize, contentRect.center().y() - s_iconSize / 2); const QPoint topLeft = QPoint(contentRect.right() - s_iconSize, contentRect.center().y() - s_iconSize / 2);
return QRect(topLeft, QSize(s_iconSize, s_iconSize)); return QRect(topLeft, QSize(s_iconSize, s_iconSize));
} }
QRect GemRepoItemDelegate::CalcRefreshButtonRect(const QRect& contentRect, const QRect& buttonRect) const QRect GemRepoItemDelegate::CalcRefreshButtonRect(const QRect& contentRect) const
{ {
const int topLeftX = buttonRect.left() + s_buttonWidth + s_buttonSpacing + s_nameMaxWidth + s_creatorMaxWidth + s_updatedMaxWidth + s_contentSpacing * 2 + s_refreshIconSpacing; const int topLeftX = contentRect.left() + s_nameMaxWidth + s_creatorMaxWidth + s_updatedMaxWidth + s_contentSpacing * 2 + s_refreshIconSpacing;
const QPoint topLeft = QPoint(topLeftX, contentRect.center().y() - s_refreshIconSize / 3); const QPoint topLeft = QPoint(topLeftX, contentRect.center().y() - s_refreshIconSize / 3);
return QRect(topLeft, QSize(s_refreshIconSize, s_refreshIconSize)); return QRect(topLeft, QSize(s_refreshIconSize, s_refreshIconSize));
} }

@ -36,7 +36,6 @@ namespace O3DE::ProjectManager
const QColor m_backgroundColor = QColor("#333333"); // Outside of the actual repo item const QColor m_backgroundColor = QColor("#333333"); // Outside of the actual repo item
const QColor m_itemBackgroundColor = QColor("#404040"); // Background color of the repo item const QColor m_itemBackgroundColor = QColor("#404040"); // Background color of the repo item
const QColor m_borderColor = QColor("#1E70EB"); const QColor m_borderColor = QColor("#1E70EB");
const QColor m_buttonEnabledColor = QColor("#1E70EB");
// Item // Item
inline constexpr static int s_height = 72; // Repo item total height inline constexpr static int s_height = 72; // Repo item total height
@ -53,13 +52,6 @@ namespace O3DE::ProjectManager
inline constexpr static int s_creatorMaxWidth = 115; inline constexpr static int s_creatorMaxWidth = 115;
inline constexpr static int s_updatedMaxWidth = 125; inline constexpr static int s_updatedMaxWidth = 125;
// Button
inline constexpr static int s_buttonWidth = 32;
inline constexpr static int s_buttonHeight = 16;
inline constexpr static int s_buttonBorderRadius = 8;
inline constexpr static int s_buttonCircleRadius = s_buttonBorderRadius - 2;
inline constexpr static int s_buttonSpacing = 20;
// Icon // Icon
inline constexpr static int s_iconSize = 24; inline constexpr static int s_iconSize = 24;
inline constexpr static int s_iconSpacing = 16; inline constexpr static int s_iconSpacing = 16;
@ -75,8 +67,7 @@ namespace O3DE::ProjectManager
QRect GetTextRect(QFont& font, const QString& text, qreal fontSize) const; QRect GetTextRect(QFont& font, const QString& text, qreal fontSize) const;
QRect CalcButtonRect(const QRect& contentRect) const; QRect CalcButtonRect(const QRect& contentRect) const;
QRect CalcDeleteButtonRect(const QRect& contentRect) const; QRect CalcDeleteButtonRect(const QRect& contentRect) const;
QRect CalcRefreshButtonRect(const QRect& contentRect, const QRect& buttonRect) const; QRect CalcRefreshButtonRect(const QRect& contentRect) const;
void DrawButton(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const;
void DrawEditButtons(QPainter* painter, const QRect& contentRect) const; void DrawEditButtons(QPainter* painter, const QRect& contentRect) const;
QAbstractItemModel* m_model = nullptr; QAbstractItemModel* m_model = nullptr;

@ -289,23 +289,22 @@ namespace O3DE::ProjectManager
m_gemRepoHeaderTable->setObjectName("gemRepoHeaderTable"); m_gemRepoHeaderTable->setObjectName("gemRepoHeaderTable");
m_gemRepoListHeader = m_gemRepoHeaderTable->horizontalHeader(); m_gemRepoListHeader = m_gemRepoHeaderTable->horizontalHeader();
m_gemRepoListHeader->setObjectName("gemRepoListHeader"); m_gemRepoListHeader->setObjectName("gemRepoListHeader");
m_gemRepoListHeader->setDefaultAlignment(Qt::AlignLeft);
m_gemRepoListHeader->setSectionResizeMode(QHeaderView::ResizeMode::Fixed); m_gemRepoListHeader->setSectionResizeMode(QHeaderView::ResizeMode::Fixed);
// Insert columns so the header labels will show up // Insert columns so the header labels will show up
m_gemRepoHeaderTable->insertColumn(0); m_gemRepoHeaderTable->insertColumn(0);
m_gemRepoHeaderTable->insertColumn(1); m_gemRepoHeaderTable->insertColumn(1);
m_gemRepoHeaderTable->insertColumn(2); m_gemRepoHeaderTable->insertColumn(2);
m_gemRepoHeaderTable->insertColumn(3); m_gemRepoHeaderTable->setHorizontalHeaderLabels({ tr("Repository Name"), tr("Creator"), tr("Updated") });
m_gemRepoHeaderTable->setHorizontalHeaderLabels({ tr("Enabled"), tr("Repository Name"), tr("Creator"), tr("Updated") });
const int headerExtraMargin = 10; const int headerExtraMargin = 18;
m_gemRepoListHeader->resizeSection(0, GemRepoItemDelegate::s_buttonWidth + GemRepoItemDelegate::s_buttonSpacing - 3); m_gemRepoListHeader->resizeSection(0, GemRepoItemDelegate::s_nameMaxWidth + GemRepoItemDelegate::s_contentSpacing + headerExtraMargin);
m_gemRepoListHeader->resizeSection(1, GemRepoItemDelegate::s_nameMaxWidth + GemRepoItemDelegate::s_contentSpacing - headerExtraMargin); m_gemRepoListHeader->resizeSection(1, GemRepoItemDelegate::s_creatorMaxWidth + GemRepoItemDelegate::s_contentSpacing);
m_gemRepoListHeader->resizeSection(2, GemRepoItemDelegate::s_creatorMaxWidth + GemRepoItemDelegate::s_contentSpacing - headerExtraMargin); m_gemRepoListHeader->resizeSection(2, GemRepoItemDelegate::s_updatedMaxWidth + GemRepoItemDelegate::s_contentSpacing);
m_gemRepoListHeader->resizeSection(3, GemRepoItemDelegate::s_updatedMaxWidth + GemRepoItemDelegate::s_contentSpacing - headerExtraMargin);
// Required to set stylesheet in code as it will not be respected if set in qss // Required to set stylesheet in code as it will not be respected if set in qss
m_gemRepoHeaderTable->horizontalHeader()->setStyleSheet("QHeaderView::section { background-color:transparent; color:white; font-size:12px; text-align:left; border-style:none; }"); m_gemRepoHeaderTable->horizontalHeader()->setStyleSheet("QHeaderView::section { background-color:transparent; color:white; font-size:12px; border-style:none; }");
middleVLayout->addWidget(m_gemRepoHeaderTable); middleVLayout->addWidget(m_gemRepoHeaderTable);
m_gemRepoListView = new GemRepoListView(m_gemRepoModel, m_gemRepoModel->GetSelectionModel(), this); m_gemRepoListView = new GemRepoListView(m_gemRepoModel, m_gemRepoModel->GetSelectionModel(), this);

@ -33,6 +33,7 @@ namespace O3DE::ProjectManager
m_layout->addWidget(m_textLabel); m_layout->addWidget(m_textLabel);
m_tagWidget = new TagContainerWidget(); m_tagWidget = new TagContainerWidget();
connect(m_tagWidget, &TagContainerWidget::TagClicked, this, [=](const QString& tag){ emit TagClicked(tag); });
m_layout->addWidget(m_tagWidget); m_layout->addWidget(m_tagWidget);
} }

@ -22,10 +22,15 @@ namespace O3DE::ProjectManager
class GemsSubWidget class GemsSubWidget
: public QWidget : public QWidget
{ {
Q_OBJECT // AUTOMOC
public: public:
GemsSubWidget(QWidget* parent = nullptr); GemsSubWidget(QWidget* parent = nullptr);
void Update(const QString& title, const QString& text, const QStringList& gemNames); void Update(const QString& title, const QString& text, const QStringList& gemNames);
signals:
void TagClicked(const QString& tag);
private: private:
QLabel* m_titleLabel = nullptr; QLabel* m_titleLabel = nullptr;
QLabel* m_textLabel = nullptr; QLabel* m_textLabel = nullptr;

@ -18,6 +18,11 @@ namespace O3DE::ProjectManager
setObjectName("TagWidget"); setObjectName("TagWidget");
} }
void TagWidget::mousePressEvent([[maybe_unused]] QMouseEvent* event)
{
emit(TagClicked(text()));
}
TagContainerWidget::TagContainerWidget(QWidget* parent) TagContainerWidget::TagContainerWidget(QWidget* parent)
: QWidget(parent) : QWidget(parent)
{ {
@ -45,7 +50,9 @@ namespace O3DE::ProjectManager
foreach (const QString& tag, tags) foreach (const QString& tag, tags)
{ {
flowLayout->addWidget(new TagWidget(tag)); TagWidget* tagWidget = new TagWidget(tag);
connect(tagWidget, &TagWidget::TagClicked, this, [=](const QString& tag){ emit TagClicked(tag); });
flowLayout->addWidget(tagWidget);
} }
} }
} // namespace O3DE::ProjectManager } // namespace O3DE::ProjectManager

@ -25,6 +25,12 @@ namespace O3DE::ProjectManager
public: public:
explicit TagWidget(const QString& text, QWidget* parent = nullptr); explicit TagWidget(const QString& text, QWidget* parent = nullptr);
~TagWidget() = default; ~TagWidget() = default;
signals:
void TagClicked(const QString& tag);
protected:
void mousePressEvent(QMouseEvent* event) override;
}; };
// Widget containing multiple tags, automatically wrapping based on the size // Widget containing multiple tags, automatically wrapping based on the size
@ -38,5 +44,8 @@ namespace O3DE::ProjectManager
~TagContainerWidget() = default; ~TagContainerWidget() = default;
void Update(const QStringList& tags); void Update(const QStringList& tags);
signals:
void TagClicked(const QString& tag);
}; };
} // namespace O3DE::ProjectManager } // namespace O3DE::ProjectManager

@ -36,6 +36,7 @@ namespace O3DE::ProjectManager
QLabel* projectPreviewLabel = new QLabel(tr("Select an image (PNG). Minimum %1 x %2 pixels.") QLabel* projectPreviewLabel = new QLabel(tr("Select an image (PNG). Minimum %1 x %2 pixels.")
.arg(QString::number(ProjectPreviewImageWidth), QString::number(ProjectPreviewImageHeight))); .arg(QString::number(ProjectPreviewImageWidth), QString::number(ProjectPreviewImageHeight)));
projectPreviewLabel->setObjectName("projectPreviewLabel");
previewExtrasLayout->addWidget(projectPreviewLabel); previewExtrasLayout->addWidget(projectPreviewLabel);
m_projectPreviewImage = new QLabel(this); m_projectPreviewImage = new QLabel(this);

@ -0,0 +1,13 @@
<ObjectStream version="3">
<Class name="AZStd::vector" type="{82FC5264-88D0-57CD-9307-FC52E4DAD550}">
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{3C004E81-244A-51C1-B3BB-50EFFD1373C9}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="passes/mainrenderpipeline.azasset" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</Class>
</ObjectStream>

@ -1574,15 +1574,6 @@
"shaderOption": "o_baseColor_useTexture" "shaderOption": "o_baseColor_useTexture"
} }
}, },
{
"type": "UseTexture",
"args": {
"textureProperty": "metallic.textureMap",
"useTextureProperty": "metallic.useTexture",
"dependentProperties": ["metallic.textureMapUv"],
"shaderOption": "o_metallic_useTexture"
}
},
{ {
"type": "UseTexture", "type": "UseTexture",
"args": { "args": {
@ -1649,6 +1640,12 @@
"file": "StandardPBR_Roughness.lua" "file": "StandardPBR_Roughness.lua"
} }
}, },
{
"type": "Lua",
"args": {
"file": "StandardPBR_Metallic.lua"
}
},
{ {
"type": "Lua", "type": "Lua",
"args": { "args": {

@ -2698,16 +2698,12 @@
} }
}, },
{ {
"type": "UseTexture", "type": "Lua",
"args": { "args": {
"textureProperty": "layer1_metallic.textureMap", "file": "StandardPBR_Metallic.lua",
"useTextureProperty": "layer1_metallic.useTexture", "propertyNamePrefix": "layer1_",
"dependentProperties": ["layer1_metallic.textureMapUv"], "srgNamePrefix": "m_layer1_",
"shaderTags": [ "optionsNamePrefix": "o_layer1_"
"ForwardPass",
"ForwardPass_EDS"
],
"shaderOption": "o_layer1_o_metallic_useTexture"
} }
}, },
{ {
@ -2835,16 +2831,12 @@
} }
}, },
{ {
"type": "UseTexture", "type": "Lua",
"args": { "args": {
"textureProperty": "layer2_metallic.textureMap", "file": "StandardPBR_Metallic.lua",
"useTextureProperty": "layer2_metallic.useTexture", "propertyNamePrefix": "layer2_",
"dependentProperties": ["layer2_metallic.textureMapUv"], "srgNamePrefix": "m_layer2_",
"shaderTags": [ "optionsNamePrefix": "o_layer2_"
"ForwardPass",
"ForwardPass_EDS"
],
"shaderOption": "o_layer2_o_metallic_useTexture"
} }
}, },
{ {
@ -2963,8 +2955,8 @@
"args": { "args": {
"textureProperty": "layer3_baseColor.textureMap", "textureProperty": "layer3_baseColor.textureMap",
"useTextureProperty": "layer3_baseColor.useTexture", "useTextureProperty": "layer3_baseColor.useTexture",
"dependentProperties": ["layer3_baseColor.textureMapUv", "layer3_baseColor.textureBlendMode"], "dependentProperties": [ "layer3_baseColor.textureMapUv", "layer3_baseColor.textureBlendMode" ],
"shaderTags": [ "shaderTags": [
"ForwardPass", "ForwardPass",
"ForwardPass_EDS" "ForwardPass_EDS"
], ],
@ -2972,16 +2964,12 @@
} }
}, },
{ {
"type": "UseTexture", "type": "Lua",
"args": { "args": {
"textureProperty": "layer3_metallic.textureMap", "file": "StandardPBR_Metallic.lua",
"useTextureProperty": "layer3_metallic.useTexture", "propertyNamePrefix": "layer3_",
"dependentProperties": ["layer3_metallic.textureMapUv"], "srgNamePrefix": "m_layer3_",
"shaderTags": [ "optionsNamePrefix": "o_layer3_"
"ForwardPass",
"ForwardPass_EDS"
],
"shaderOption": "o_layer3_o_metallic_useTexture"
} }
}, },
{ {

@ -1104,15 +1104,6 @@
"shaderOption": "o_baseColor_useTexture" "shaderOption": "o_baseColor_useTexture"
} }
}, },
{
"type": "UseTexture",
"args": {
"textureProperty": "metallic.textureMap",
"useTextureProperty": "metallic.useTexture",
"dependentProperties": ["metallic.textureMapUv"],
"shaderOption": "o_metallic_useTexture"
}
},
{ {
"type": "UseTexture", "type": "UseTexture",
"args": { "args": {
@ -1179,6 +1170,12 @@
"file": "StandardPBR_Roughness.lua" "file": "StandardPBR_Roughness.lua"
} }
}, },
{
"type": "Lua",
"args": {
"file": "StandardPBR_Metallic.lua"
}
},
{ {
"type": "Lua", "type": "Lua",
"args": { "args": {

@ -0,0 +1,43 @@
--------------------------------------------------------------------------------------
--
-- Copyright (c) Contributors to the Open 3D Engine Project.
-- For complete copyright and license terms please see the LICENSE at the root of this distribution.
--
-- SPDX-License-Identifier: Apache-2.0 OR MIT
--
--
--
----------------------------------------------------------------------------------------------------
function GetMaterialPropertyDependencies()
return {"metallic.textureMap", "metallic.useTexture"}
end
function GetShaderOptionDependencies()
return {"o_metallic_useTexture"}
end
function Process(context)
local textureMap = context:GetMaterialPropertyValue_Image("metallic.textureMap")
local useTexture = context:GetMaterialPropertyValue_bool("metallic.useTexture")
context:SetShaderOptionValue_bool("o_metallic_useTexture", useTexture and textureMap ~= nil)
end
function ProcessEditor(context)
local textureMap = context:GetMaterialPropertyValue_Image("metallic.textureMap")
local useTexture = context:GetMaterialPropertyValue_bool("metallic.useTexture")
if(nil == textureMap) then
context:SetMaterialPropertyVisibility("metallic.useTexture", MaterialPropertyVisibility_Hidden)
context:SetMaterialPropertyVisibility("metallic.textureMapUv", MaterialPropertyVisibility_Hidden)
context:SetMaterialPropertyVisibility("metallic.factor", MaterialPropertyVisibility_Enabled)
elseif(not useTexture) then
context:SetMaterialPropertyVisibility("metallic.useTexture", MaterialPropertyVisibility_Enabled)
context:SetMaterialPropertyVisibility("metallic.textureMapUv", MaterialPropertyVisibility_Disabled)
context:SetMaterialPropertyVisibility("metallic.factor", MaterialPropertyVisibility_Enabled)
else
context:SetMaterialPropertyVisibility("metallic.useTexture", MaterialPropertyVisibility_Enabled)
context:SetMaterialPropertyVisibility("metallic.textureMapUv", MaterialPropertyVisibility_Enabled)
context:SetMaterialPropertyVisibility("metallic.factor", MaterialPropertyVisibility_Hidden)
end
end

@ -91,10 +91,10 @@
"LoadStoreAction": { "LoadStoreAction": {
"ClearValue": { "ClearValue": {
"Value": [ "Value": [
0.4000000059604645, 0.0,
0.4000000059604645, 0.0,
0.4000000059604645, 0.0,
{} 0.0
] ]
}, },
"LoadAction": "Clear" "LoadAction": "Clear"
@ -107,10 +107,10 @@
"LoadStoreAction": { "LoadStoreAction": {
"ClearValue": { "ClearValue": {
"Value": [ "Value": [
0.4000000059604645, 0.0,
0.4000000059604645, 0.0,
0.4000000059604645, 0.0,
{} 0.0
] ]
}, },
"LoadAction": "Clear" "LoadAction": "Clear"

@ -0,0 +1,158 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "PassAsset",
"ClassData": {
"PassTemplate": {
"Name": "EnvironmentCubeMapForwardSubsurfaceMSAAPassTemplate",
"PassClass": "RasterPass",
"Slots": [
// Inputs...
{
"Name": "BRDFTextureInput",
"ShaderInputName": "m_brdfMap",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader"
},
{
"Name": "DirectionalLightShadowmap",
"ShaderInputName": "m_directionalLightShadowmap",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ImageViewDesc": {
"IsArray": 1
}
},
{
"Name": "ExponentialShadowmapDirectional",
"ShaderInputName": "m_directionalLightExponentialShadowmap",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ImageViewDesc": {
"IsArray": 1
}
},
{
"Name": "ProjectedShadowmap",
"ShaderInputName": "m_projectedShadowmaps",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ImageViewDesc": {
"IsArray": 1
}
},
{
"Name": "ExponentialShadowmapProjected",
"ShaderInputName": "m_projectedExponentialShadowmap",
"SlotType": "Input",
"ScopeAttachmentUsage": "Shader",
"ImageViewDesc": {
"IsArray": 1
}
},
{
"Name": "TileLightData",
"SlotType": "Input",
"ShaderInputName": "m_tileLightData",
"ScopeAttachmentUsage": "Shader"
},
{
"Name": "LightListRemapped",
"SlotType": "Input",
"ShaderInputName": "m_lightListRemapped",
"ScopeAttachmentUsage": "Shader"
},
// Input/Outputs...
{
"Name": "DepthStencilInputOutput",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "DepthStencil"
},
{
"Name": "DiffuseOutput",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "RenderTarget"
},
{
"Name": "SpecularOutput",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "RenderTarget"
},
{
"Name": "AlbedoOutput",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "RenderTarget"
},
{
"Name": "SpecularF0Output",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "RenderTarget"
},
{
"Name": "NormalOutput",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "RenderTarget"
},
// Outputs...
{
"Name": "ScatterDistanceOutput",
"SlotType": "Output",
"ScopeAttachmentUsage": "RenderTarget",
"LoadStoreAction": {
"ClearValue": {
"Value": [
0.0,
0.0,
0.0,
0.0
]
},
"LoadAction": "Clear"
}
}
],
"ImageAttachments": [
{
"Name": "BRDFTexture",
"Lifetime": "Imported",
"AssetRef": {
"FilePath": "Textures/BRDFTexture.attimage"
}
},
{
"Name": "ScatterDistanceImage",
"SizeSource": {
"Source": {
"Pass": "Parent",
"Attachment": "Output"
}
},
"MultisampleSource": {
"Pass": "This",
"Attachment": "DepthStencilInputOutput"
},
"ImageDescriptor": {
"Format": "R11G11B10_FLOAT",
"SharedQueueMask": "Graphics"
}
}
],
"Connections": [
{
"LocalSlot": "BRDFTextureInput",
"AttachmentRef": {
"Pass": "This",
"Attachment": "BRDFTexture"
}
},
{
"LocalSlot": "ScatterDistanceOutput",
"AttachmentRef": {
"Pass": "This",
"Attachment": "ScatterDistanceImage"
}
}
]
}
}
}

@ -211,6 +211,105 @@
} }
} }
}, },
{
"Name": "ForwardSubsurfaceMSAAPass",
"TemplateName": "EnvironmentCubeMapForwardSubsurfaceMSAAPassTemplate",
"Connections": [
{
"LocalSlot": "DirectionalLightShadowmap",
"AttachmentRef": {
"Pass": "CascadedShadowmapsPass",
"Attachment": "Shadowmap"
}
},
{
"LocalSlot": "ExponentialShadowmapDirectional",
"AttachmentRef": {
"Pass": "EsmShadowmapsPassDirectional",
"Attachment": "EsmShadowmaps"
}
},
{
"LocalSlot": "ProjectedShadowmap",
"AttachmentRef": {
"Pass": "ProjectedShadowmapsPass",
"Attachment": "Shadowmap"
}
},
{
"LocalSlot": "ExponentialShadowmapProjected",
"AttachmentRef": {
"Pass": "EsmShadowmapsPassProjected",
"Attachment": "EsmShadowmaps"
}
},
{
"LocalSlot": "TileLightData",
"AttachmentRef": {
"Pass": "LightCullingPass",
"Attachment": "TileLightData"
}
},
{
"LocalSlot": "LightListRemapped",
"AttachmentRef": {
"Pass": "LightCullingPass",
"Attachment": "LightListRemapped"
}
},
// Input/Outputs...
{
"LocalSlot": "DepthStencilInputOutput",
"AttachmentRef": {
"Pass": "DepthPrePass",
"Attachment": "DepthMSAA"
}
},
{
"LocalSlot": "DiffuseOutput",
"AttachmentRef": {
"Pass": "ForwardMSAAPass",
"Attachment": "DiffuseOutput"
}
},
{
"LocalSlot": "SpecularOutput",
"AttachmentRef": {
"Pass": "ForwardMSAAPass",
"Attachment": "SpecularOutput"
}
},
{
"LocalSlot": "AlbedoOutput",
"AttachmentRef": {
"Pass": "ForwardMSAAPass",
"Attachment": "AlbedoOutput"
}
},
{
"LocalSlot": "SpecularF0Output",
"AttachmentRef": {
"Pass": "ForwardMSAAPass",
"Attachment": "SpecularF0Output"
}
},
{
"LocalSlot": "NormalOutput",
"AttachmentRef": {
"Pass": "ForwardMSAAPass",
"Attachment": "NormalOutput"
}
}
],
"PassData": {
"$type": "RasterPassData",
"DrawListTag": "forwardWithSubsurfaceOutput",
"PipelineViewTag": "MainCamera",
"PassSrgShaderAsset": {
"FilePath": "Shaders/ForwardPassSrg.shader"
}
}
},
{ {
"Name": "SkyBoxPass", "Name": "SkyBoxPass",
"TemplateName": "EnvironmentCubeMapSkyBoxPassTemplate", "TemplateName": "EnvironmentCubeMapSkyBoxPassTemplate",
@ -325,6 +424,75 @@
} }
] ]
}, },
{
"Name": "MSAAResolveScatterDistancePass",
"TemplateName": "MSAAResolveColorTemplate",
"Connections": [
{
"LocalSlot": "Input",
"AttachmentRef": {
"Pass": "ForwardSubsurfaceMSAAPass",
"Attachment": "ScatterDistanceOutput"
}
}
]
},
{
"Name": "SubsurfaceScatteringPass",
"TemplateName": "SubsurfaceScatteringPassTemplate",
"Enabled": true,
"Connections": [
{
"LocalSlot": "InputDiffuse",
"AttachmentRef": {
"Pass": "MSAAResolveDiffusePass",
"Attachment": "Output"
}
},
{
"LocalSlot": "InputLinearDepth",
"AttachmentRef": {
"Pass": "DepthPrePass",
"Attachment": "DepthLinear"
}
},
{
"LocalSlot": "InputScatterDistance",
"AttachmentRef": {
"Pass": "MSAAResolveScatterDistancePass",
"Attachment": "Output"
}
}
],
"PassData": {
"$type": "ComputePassData",
"ShaderAsset": {
"FilePath": "Shaders/PostProcessing/ScreenSpaceSubsurfaceScatteringCS.shader"
},
"Make Fullscreen Pass": true,
"PipelineViewTag": "MainCamera"
}
},
{
"Name": "Ssao",
"TemplateName": "SsaoParentTemplate",
"Connections": [
{
"LocalSlot": "LinearDepth",
"AttachmentRef": {
"Pass": "DepthPrePass",
"Attachment": "DepthLinear"
}
},
{
"LocalSlot": "Modulate",
"AttachmentRef": {
"Pass": "SubsurfaceScatteringPass",
"Attachment": "Output"
}
}
]
},
{ {
"Name": "DiffuseSpecularMergePass", "Name": "DiffuseSpecularMergePass",
"TemplateName": "DiffuseSpecularMergeTemplate", "TemplateName": "DiffuseSpecularMergeTemplate",
@ -332,7 +500,7 @@
{ {
"LocalSlot": "InputDiffuse", "LocalSlot": "InputDiffuse",
"AttachmentRef": { "AttachmentRef": {
"Pass": "MSAAResolveDiffusePass", "Pass": "Ssao",
"Attachment": "Output" "Attachment": "Output"
} }
}, },

@ -252,6 +252,10 @@
"Name": "EnvironmentCubeMapForwardMSAAPassTemplate", "Name": "EnvironmentCubeMapForwardMSAAPassTemplate",
"Path": "Passes/EnvironmentCubeMapForwardMSAA.pass" "Path": "Passes/EnvironmentCubeMapForwardMSAA.pass"
}, },
{
"Name": "EnvironmentCubeMapForwardSubsurfaceMSAAPassTemplate",
"Path": "Passes/EnvironmentCubeMapForwardSubsurfaceMSAA.pass"
},
{ {
"Name": "EnvironmentCubeMapDepthMSAAPassTemplate", "Name": "EnvironmentCubeMapDepthMSAAPassTemplate",
"Path": "Passes/EnvironmentCubeMapDepthMSAA.pass" "Path": "Passes/EnvironmentCubeMapDepthMSAA.pass"

@ -0,0 +1,317 @@
<ObjectStream version="3">
<Class name="AZStd::vector" type="{82FC5264-88D0-57CD-9307-FC52E4DAD550}">
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{88B442CC-1F5B-5B8A-BC10-EDEB9998BEF9}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="passes/passtemplates.azasset" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{6B01EDAB-1951-5588-AB7B-DF2F703950D4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="passes/smaaconfiguration.azasset" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{0302DBFA-309B-50F9-912A-F5EB9A3FFC89}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaderlib/atom/features/raytracing/raytracingsrgs.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{558ADDDC-9CF3-5EE9-9FE2-288A1F404072}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/auxgeom/auxgeomworld.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{920D0051-A477-555A-BA28-441D779DF7FE}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/auxgeom/auxgeomobject.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{7DB9C0CD-EE20-5B1D-92E0-423B4832461E}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/auxgeom/auxgeomobjectlit.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{34E20A18-CB2E-5D93-84CF-C2B9E144DA75}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/diffuseglobalillumination/diffuseprobegridblenddistance.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{F70A2001-CC2C-5DFE-BC87-B98A4E0E57EB}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/diffuseglobalillumination/diffuseprobegridblendirradiance.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{44260D05-99D8-5A86-83E7-B7C5EC48F297}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/diffuseglobalillumination/diffuseprobegridborderupdaterow.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{F60AFD1E-1CED-5E33-930E-17DB4EAA1F81}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/diffuseglobalillumination/diffuseprobegridborderupdatecolumn.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{7547FD2E-1630-58B1-9293-F4C9F33E0D72}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/diffuseglobalillumination/diffuseprobegridclassification.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{5A28BC26-22C8-5DC2-870B-3EE03A6DC723}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/diffuseglobalillumination/diffuseprobegridrender.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{55BDC206-9859-52D8-AE08-457F5664F509}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/diffuseglobalillumination/diffuseprobegridraytracing.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{3E4941A5-56BF-5ECD-95B3-64E6D6803159}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/diffuseglobalillumination/diffuseprobegridraytracingclosesthit.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{EB5538D4-1028-534C-9FC0-1421E0926E31}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/diffuseglobalillumination/diffuseprobegridraytracingmiss.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{582D6038-5953-585B-8840-CA5B993B5B08}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/diffuseglobalillumination/diffuseprobegridrelocation.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{B1E8CBB8-00F8-552B-AA3F-07F3DAA9C79C}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/imgui/imgui.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{72B3ED19-D85C-5674-B331-F1D8758EBC83}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/postprocessing/displaymapper.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{AAC80DB3-C758-5B36-864A-9AD9923387E1}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/postprocessing/acesoutputtransformlut.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{91F6209C-D41E-5F6A-9070-EEED973ED34A}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/postprocessing/bakeacesoutputtransformlutcs.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{BF6EC912-C8EB-56AF-A3A7-5FE2570465B9}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/postprocessing/fullscreencopy.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{5895909F-3FF9-5A21-AFA1-A7DD2B48BD38}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/postprocessing/displaymapperonlygammacorrection.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{CC4B44B0-1DCB-5A50-B2C0-6C8D778D60C6}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/postprocessing/applyshaperlookuptable.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{D24FDB86-AE3A-5AF3-8CF2-A398A7DE7ECD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/postprocessing/outputtransform.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{45485BD7-DFDD-5B8D-99C7-2464D2FEF506}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/reflections/reflectionprobestencil.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{2173DB42-64C3-5AB3-B394-CBC093258D01}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/reflections/reflectionprobeblendweight.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{6FD5B51E-51D8-54C2-B8B1-914C4D33950D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/reflections/reflectionproberenderouter.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{7C15D605-EAAD-5AF4-A5F7-AF2781156064}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/reflections/reflectionproberenderinner.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{FE7E2F65-2F34-5231-AF26-D0D836668294}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/reflections/reflectionscreenspaceblurvertical.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{27A231B1-F585-5D0E-AD1F-AD08D9C1E8F2}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/reflections/reflectionscreenspaceblurhorizontal.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{1AA24D31-66E5-52B6-8F21-ABADFECE661D}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="textures/cloudnoise_01.jpg.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{49F60E08-3BAF-5132-B6E7-0F4A32310B12}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="3000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="textures/default/default_iblglobalcm_ibldiffuse.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{49F60E08-3BAF-5132-B6E7-0F4A32310B12}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="2000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="textures/default/default_iblglobalcm_iblspecular.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{FDC3F4B9-5C6C-5D85-9628-892826185D85}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="textures/default/default_skyboxcm.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{2BD005F4-D37A-59DD-9DDE-F5ADD4668B9B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="textures/ltc/ltc_mat_lutrgba32f.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{F9E4A926-0E27-595A-B147-69822B4E1F98}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="textures/ltc/ltc_amp_lutrg32f.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{8ECFB722-130A-55F8-9FD0-428ACEEA1EAF}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="textures/postprocessing/depthoffield_pencilmap_35mmfilm.bmp.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{54023EDC-B393-544A-9C80-E8E2ACB1BE53}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="textures/postprocessing/areatex.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{1553E50C-D99C-5CD1-BB5C-747FD47C354B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="1000" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="textures/postprocessing/searchtex.dds.streamingimage" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</Class>
</ObjectStream>

@ -19,7 +19,6 @@
#include <AzCore/Serialization/SerializeContext.h> #include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h> #include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/EditContextConstants.inl> #include <AzCore/Serialization/EditContextConstants.inl>
#include <AzCore/Script/ScriptAsset.h>
#include <AssetBuilderSDK/AssetBuilderSDK.h> #include <AssetBuilderSDK/AssetBuilderSDK.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h> #include <AzToolsFramework/API/EditorAssetSystemAPI.h>
@ -101,13 +100,6 @@ namespace AZ
materialFunctorRegistration->RegisterMaterialFunctor("ConvertEmissiveUnit", azrtti_typeid<ConvertEmissiveUnitFunctorSourceData>()); materialFunctorRegistration->RegisterMaterialFunctor("ConvertEmissiveUnit", azrtti_typeid<ConvertEmissiveUnitFunctorSourceData>());
materialFunctorRegistration->RegisterMaterialFunctor("HandleSubsurfaceScatteringParameters", azrtti_typeid<SubsurfaceTransmissionParameterFunctorSourceData>()); materialFunctorRegistration->RegisterMaterialFunctor("HandleSubsurfaceScatteringParameters", azrtti_typeid<SubsurfaceTransmissionParameterFunctorSourceData>());
materialFunctorRegistration->RegisterMaterialFunctor("Lua", azrtti_typeid<RPI::LuaMaterialFunctorSourceData>()); materialFunctorRegistration->RegisterMaterialFunctor("Lua", azrtti_typeid<RPI::LuaMaterialFunctorSourceData>());
// Add asset types and extensions to AssetCatalog. Uses "AssetCatalogService".
auto assetCatalog = AZ::Data::AssetCatalogRequestBus::FindFirstHandler();
if (assetCatalog)
{
assetCatalog->EnableCatalogForAsset(AZ::AzTypeInfo<AZ::ScriptAsset>::Uuid());
}
} }
void EditorCommonSystemComponent::Deactivate() void EditorCommonSystemComponent::Deactivate()

@ -0,0 +1,29 @@
<ObjectStream version="3">
<Class name="AZStd::vector" type="{82FC5264-88D0-57CD-9307-FC52E4DAD550}">
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{454C374E-E2FA-5DD3-81D8-08BE5904112C}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shader/decomposemsimage.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{7DCE2AC7-7EDA-5C04-A1E3-C7465B4CD8B7}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shader/imagepreview.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{A1B7396F-7D03-5A88-B71E-29441B04C123}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shader/sceneandviewsrgs.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</Class>
</ObjectStream>

@ -10,8 +10,8 @@
#include <Atom/RPI.Edit/Common/AssetUtils.h> #include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <AzCore/Asset/AssetManagerBus.h> #include <AzCore/Asset/AssetManagerBus.h>
#include <AzCore/Serialization/Json/JsonUtils.h> #include <AzCore/Serialization/Json/JsonUtils.h>
#include <AzCore/StringFunc/StringFunc.h>
#include <Atom/RPI.Reflect/Asset/AssetReference.h> #include <Atom/RPI.Reflect/Asset/AssetReference.h>
#include <Atom/RPI.Reflect/Pass/PassAsset.h> #include <Atom/RPI.Reflect/Pass/PassAsset.h>
@ -33,11 +33,27 @@ namespace AZ
static const char* PassAssetExtension = "pass"; static const char* PassAssetExtension = "pass";
} }
namespace PassBuilderNamespace
{
enum PassDependencies
{
Shader,
AttachmentImage,
Count
};
static const AZStd::tuple<const char*, const char*> DependencyExtensionJobKeyTable[PassDependencies::Count] =
{
{".shader", "Shader Asset"},
{".attimage", "Any Asset Builder"}
};
}
void PassBuilder::RegisterBuilder() void PassBuilder::RegisterBuilder()
{ {
AssetBuilderSDK::AssetBuilderDesc builder; AssetBuilderSDK::AssetBuilderDesc builder;
builder.m_name = PassBuilderJobKey; builder.m_name = PassBuilderJobKey;
builder.m_version = 13; // antonmic: making .pass files declare dependency on shaders they reference builder.m_version = 14; // making .pass files emit product dependencies for the shaders they reference so they are picked up by the asset bundler
builder.m_busId = azrtti_typeid<PassBuilder>(); builder.m_busId = azrtti_typeid<PassBuilder>();
builder.m_createJobFunction = AZStd::bind(&PassBuilder::CreateJobs, this, AZStd::placeholders::_1, AZStd::placeholders::_2); builder.m_createJobFunction = AZStd::bind(&PassBuilder::CreateJobs, this, AZStd::placeholders::_1, AZStd::placeholders::_2);
builder.m_processJobFunction = AZStd::bind(&PassBuilder::ProcessJob, this, AZStd::placeholders::_1, AZStd::placeholders::_2); builder.m_processJobFunction = AZStd::bind(&PassBuilder::ProcessJob, this, AZStd::placeholders::_1, AZStd::placeholders::_2);
@ -104,8 +120,27 @@ namespace AZ
} }
} }
bool SetJobKeyForExtension(const AZStd::string& filePath, FindPassReferenceAssetParams& params)
{
AZStd::string extension;
StringFunc::Path::GetExtension(filePath.c_str(), extension);
for (const auto& [dependencyExtension, jobKey] : PassBuilderNamespace::DependencyExtensionJobKeyTable)
{
if (extension == dependencyExtension)
{
params.jobKey = jobKey;
return true;
}
}
AZ_Error(PassBuilderName, false, "PassBuilder found a dependency with extension '%s', but does not know the corresponding job key. Add the job key for that extension to SetJobKeyForExtension in PassBuilder.cpp", extension.c_str());
params.jobKey = "Unknown";
return false;
}
// Helper function to find all assetId's and object references // Helper function to find all assetId's and object references
bool FindReferencedAssets(FindPassReferenceAssetParams& params, AssetBuilderSDK::JobDescriptor* job) bool FindReferencedAssets(
FindPassReferenceAssetParams& params, AssetBuilderSDK::JobDescriptor* job, AZStd::vector<AssetBuilderSDK::ProductDependency>* productDependencies)
{ {
SerializeContext::ErrorHandler errorLogger; SerializeContext::ErrorHandler errorLogger;
errorLogger.Reset(); errorLogger.Reset();
@ -129,8 +164,8 @@ namespace AZ
if (job != nullptr) // Create Job Phase if (job != nullptr) // Create Job Phase
{ {
params.dependencySourceFile = path; params.dependencySourceFile = path;
bool dependencyAddedSuccessfully = AddDependency(params, job); success &= SetJobKeyForExtension(path, params);
success = dependencyAddedSuccessfully && success; success &= AddDependency(params, job);
} }
else // Process Job Phase else // Process Job Phase
{ {
@ -139,6 +174,9 @@ namespace AZ
if (assetIdOutcome) if (assetIdOutcome)
{ {
assetReference->m_assetId = assetIdOutcome.GetValue(); assetReference->m_assetId = assetIdOutcome.GetValue();
productDependencies->push_back(
AssetBuilderSDK::ProductDependency{assetReference->m_assetId, AZ::Data::ProductDependencyInfo::CreateFlags(Data::AssetLoadBehavior::NoLoad)}
);
} }
else else
{ {
@ -223,9 +261,9 @@ namespace AZ
params.passAssetSourceFile = request.m_sourceFile; params.passAssetSourceFile = request.m_sourceFile;
params.passAssetUuid = passAssetUuid; params.passAssetUuid = passAssetUuid;
params.serializeContext = serializeContext; params.serializeContext = serializeContext;
params.jobKey = "Shader Asset"; params.jobKey = "Unknown";
if (!FindReferencedAssets(params, &job)) if (!FindReferencedAssets(params, &job, nullptr))
{ {
return; return;
} }
@ -287,9 +325,10 @@ namespace AZ
params.passAssetSourceFile = request.m_sourceFile; params.passAssetSourceFile = request.m_sourceFile;
params.passAssetUuid = passAssetUuid; params.passAssetUuid = passAssetUuid;
params.serializeContext = serializeContext; params.serializeContext = serializeContext;
params.jobKey = "Shader Asset"; params.jobKey = "Unknown";
if (!FindReferencedAssets(params, nullptr)) AZStd::vector<AssetBuilderSDK::ProductDependency> productDependencies;
if (!FindReferencedAssets(params, nullptr, &productDependencies))
{ {
return; return;
} }
@ -313,6 +352,7 @@ namespace AZ
// --- Save output product(s) to response --- // --- Save output product(s) to response ---
AssetBuilderSDK::JobProduct jobProduct(destPath, PassAsset::RTTI_Type(), 0); AssetBuilderSDK::JobProduct jobProduct(destPath, PassAsset::RTTI_Type(), 0);
jobProduct.m_dependencies = productDependencies;
jobProduct.m_dependenciesHandled = true; jobProduct.m_dependenciesHandled = true;
response.m_outputProducts.push_back(jobProduct); response.m_outputProducts.push_back(jobProduct);
response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success; response.m_resultCode = AssetBuilderSDK::ProcessJobResult_Success;

@ -0,0 +1,13 @@
<ObjectStream version="3">
<Class name="AZStd::vector" type="{82FC5264-88D0-57CD-9307-FC52E4DAD550}">
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{400C0F36-1069-5F0E-8E55-87123BA075CD}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/simpletextured.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</Class>
</ObjectStream>

@ -0,0 +1,13 @@
<ObjectStream version="3">
<Class name="AZStd::vector" type="{82FC5264-88D0-57CD-9307-FC52E4DAD550}">
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{7B093FA3-A834-5061-9ADD-C6DCA97A4B60}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="shaders/texturedicon.azshader" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</Class>
</ObjectStream>

@ -0,0 +1,45 @@
<ObjectStream version="3">
<Class name="AZStd::vector" type="{82FC5264-88D0-57CD-9307-FC52E4DAD550}">
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{4F3761EF-E279-5FDD-98C3-EF90F924FBAC}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="lightingpresets/thumbnail.lightingpreset.azasset" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{6DE0E9A8-A1C7-5D0F-9407-4E627C1F223C}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="284780167" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="models/sphere.azmodel" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{CF91AE08-8FD5-538B-A5F2-427DFA9D5E1C}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="materials/basic_grey.azmaterial" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{DCE9A5B2-1907-5A0D-8A96-5ABF608D103B}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="passes/mainpipeline.pass" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
<Class name="SeedInfo" field="element" version="2" type="{FACC3682-2ACA-4AA4-B85A-07AD276D18A0}">
<Class name="AssetId" field="assetId" version="1" type="{652ED536-3402-439B-AEBE-4A5DBC554085}">
<Class name="AZ::Uuid" field="guid" value="{6B01EDAB-1951-5588-AB7B-DF2F703950D4}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
<Class name="unsigned int" field="subId" value="0" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
</Class>
<Class name="unsigned int" field="platformFlags" value="3" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
<Class name="AZStd::string" field="pathHint" value="passes/smaaconfiguration.azasset" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
</Class>
</Class>
</ObjectStream>

@ -6,23 +6,24 @@
* *
*/ */
#include <Material/EditorMaterialComponent.h>
#include <Material/EditorMaterialComponentExporter.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h> #include <Atom/RPI.Edit/Common/AssetUtils.h>
#include <Atom/RPI.Edit/Material/MaterialPropertyId.h> #include <Atom/RPI.Edit/Material/MaterialPropertyId.h>
#include <Atom/RPI.Public/Image/StreamingImage.h> #include <Atom/RPI.Public/Image/StreamingImage.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h> #include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <Atom/RPI.Reflect/Material/MaterialTypeAsset.h> #include <Atom/RPI.Reflect/Material/MaterialTypeAsset.h>
#include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h> #include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/Serialization/Json/RegistrationContext.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <Material/EditorMaterialComponent.h>
#include <Material/EditorMaterialComponentExporter.h>
#include <Material/EditorMaterialComponentSerializer.h>
AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
#include <QMenu>
#include <QAction> #include <QAction>
#include <QCursor> #include <QCursor>
#include <QMenu>
AZ_POP_DISABLE_WARNING AZ_POP_DISABLE_WARNING
namespace AZ namespace AZ
@ -59,7 +60,12 @@ namespace AZ
BaseClass::Reflect(context); BaseClass::Reflect(context);
EditorMaterialComponentSlot::Reflect(context); EditorMaterialComponentSlot::Reflect(context);
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) if (auto jsonContext = azrtti_cast<JsonRegistrationContext*>(context))
{
jsonContext->Serializer<JsonEditorMaterialComponentSerializer>()->HandlesType<EditorMaterialComponent>();
}
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{ {
serializeContext->RegisterGenericType<EditorMaterialComponentSlotContainer>(); serializeContext->RegisterGenericType<EditorMaterialComponentSlotContainer>();
serializeContext->RegisterGenericType<EditorMaterialComponentSlotsByLodContainer>(); serializeContext->RegisterGenericType<EditorMaterialComponentSlotsByLodContainer>();
@ -76,7 +82,7 @@ namespace AZ
serializeContext->RegisterGenericType<AZStd::unordered_map<MaterialAssignmentId, Data::AssetId, AZStd::hash<MaterialAssignmentId>, AZStd::equal_to<MaterialAssignmentId>, AZStd::allocator>>(); serializeContext->RegisterGenericType<AZStd::unordered_map<MaterialAssignmentId, Data::AssetId, AZStd::hash<MaterialAssignmentId>, AZStd::equal_to<MaterialAssignmentId>, AZStd::allocator>>();
serializeContext->RegisterGenericType<AZStd::unordered_map<MaterialAssignmentId, MaterialPropertyOverrideMap, AZStd::hash<MaterialAssignmentId>, AZStd::equal_to<MaterialAssignmentId>, AZStd::allocator>>(); serializeContext->RegisterGenericType<AZStd::unordered_map<MaterialAssignmentId, MaterialPropertyOverrideMap, AZStd::hash<MaterialAssignmentId>, AZStd::equal_to<MaterialAssignmentId>, AZStd::allocator>>();
if (AZ::EditContext* editContext = serializeContext->GetEditContext()) if (auto editContext = serializeContext->GetEditContext())
{ {
editContext->Class<EditorMaterialComponent>( editContext->Class<EditorMaterialComponent>(
"Material", "The material component specifies the material to use for this entity") "Material", "The material component specifies the material to use for this entity")
@ -129,7 +135,7 @@ namespace AZ
} }
} }
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context)) if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{ {
behaviorContext->ConstantProperty("EditorMaterialComponentTypeId", BehaviorConstant(Uuid(EditorMaterialComponentTypeId))) behaviorContext->ConstantProperty("EditorMaterialComponentTypeId", BehaviorConstant(Uuid(EditorMaterialComponentTypeId)))
->Attribute(AZ::Script::Attributes::Module, "render") ->Attribute(AZ::Script::Attributes::Module, "render")

@ -27,6 +27,8 @@ namespace AZ
, public EditorMaterialSystemComponentNotificationBus::Handler , public EditorMaterialSystemComponentNotificationBus::Handler
{ {
public: public:
friend class JsonEditorMaterialComponentSerializer;
using BaseClass = EditorRenderComponentAdapter<MaterialComponentController, MaterialComponent, MaterialComponentConfig>; using BaseClass = EditorRenderComponentAdapter<MaterialComponentController, MaterialComponent, MaterialComponentConfig>;
AZ_EDITOR_COMPONENT(EditorMaterialComponent, EditorMaterialComponentTypeId, BaseClass); AZ_EDITOR_COMPONENT(EditorMaterialComponent, EditorMaterialComponentTypeId, BaseClass);

@ -0,0 +1,109 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
#include <Material/EditorMaterialComponent.h>
#include <Material/EditorMaterialComponentSerializer.h>
namespace AZ
{
namespace Render
{
AZ_CLASS_ALLOCATOR_IMPL(JsonEditorMaterialComponentSerializer, AZ::SystemAllocator, 0);
AZ::JsonSerializationResult::Result JsonEditorMaterialComponentSerializer::Load(
void* outputValue,
[[maybe_unused]] const AZ::Uuid& outputValueTypeId,
const rapidjson::Value& inputValue,
AZ::JsonDeserializerContext& context)
{
namespace JSR = AZ::JsonSerializationResult;
AZ_Assert(
azrtti_typeid<EditorMaterialComponent>() == outputValueTypeId,
"Unable to deserialize EditorMaterialComponent from json because the provided type is %s.",
outputValueTypeId.ToString<AZStd::string>().c_str());
auto componentInstance = reinterpret_cast<EditorMaterialComponent*>(outputValue);
AZ_Assert(componentInstance, "Output value for JsonEditorMaterialComponentSerializer can't be null.");
JSR::ResultCode result(JSR::Tasks::ReadField);
result.Combine(ContinueLoadingFromJsonObjectField(
&componentInstance->m_id, azrtti_typeid<decltype(componentInstance->m_id)>(), inputValue, "Id", context));
result.Combine(ContinueLoadingFromJsonObjectField(
&componentInstance->m_controller, azrtti_typeid<decltype(componentInstance->m_controller)>(), inputValue, "Controller",
context));
result.Combine(ContinueLoadingFromJsonObjectField(
&componentInstance->m_materialSlotsByLodEnabled, azrtti_typeid<decltype(componentInstance->m_materialSlotsByLodEnabled)>(),
inputValue, "materialSlotsByLodEnabled", context));
return context.Report(
result,
result.GetProcessing() != JSR::Processing::Halted ? "Successfully loaded EditorMaterialComponent information."
: "Failed to load EditorMaterialComponent information.");
}
AZ::JsonSerializationResult::Result JsonEditorMaterialComponentSerializer::Store(
rapidjson::Value& outputValue,
const void* inputValue,
const void* defaultValue,
[[maybe_unused]] const AZ::Uuid& valueTypeId,
AZ::JsonSerializerContext& context)
{
namespace JSR = AZ::JsonSerializationResult;
AZ_Assert(
azrtti_typeid<EditorMaterialComponent>() == valueTypeId,
"Unable to Serialize EditorMaterialComponent because the provided type is %s.",
valueTypeId.ToString<AZStd::string>().c_str());
auto componentInstance = reinterpret_cast<const EditorMaterialComponent*>(inputValue);
AZ_Assert(componentInstance, "Input value for JsonEditorMaterialComponentSerializer can't be null.");
auto defaultComponentInstance = reinterpret_cast<const EditorMaterialComponent*>(defaultValue);
JSR::ResultCode result(JSR::Tasks::WriteValue);
{
AZ::ScopedContextPath subPathName(context, "m_id");
const auto componentId = &componentInstance->m_id;
const auto defaultComponentId = defaultComponentInstance ? &defaultComponentInstance->m_id : nullptr;
result.Combine(ContinueStoringToJsonObjectField(
outputValue, "Id", componentId, defaultComponentId, azrtti_typeid<decltype(componentInstance->m_id)>(), context));
}
{
AZ::ScopedContextPath subPathName(context, "Controller");
const auto controller = &componentInstance->m_controller;
const auto defaultController = defaultComponentInstance ? &defaultComponentInstance->m_controller : nullptr;
result.Combine(ContinueStoringToJsonObjectField(
outputValue, "Controller", controller, defaultController, azrtti_typeid<decltype(componentInstance->m_controller)>(),
context));
}
{
AZ::ScopedContextPath subPathName(context, "materialSlotsByLodEnabled");
const auto enabled = &componentInstance->m_materialSlotsByLodEnabled;
const auto defaultEnabled = defaultComponentInstance ? &defaultComponentInstance->m_materialSlotsByLodEnabled : nullptr;
result.Combine(ContinueStoringToJsonObjectField(
outputValue, "materialSlotsByLodEnabled", enabled, defaultEnabled,
azrtti_typeid<decltype(componentInstance->m_materialSlotsByLodEnabled)>(), context));
}
return context.Report(
result,
result.GetProcessing() != JSR::Processing::Halted ? "Successfully stored EditorMaterialComponent information."
: "Failed to store EditorMaterialComponent information.");
}
} // namespace Render
} // namespace AZ

@ -0,0 +1,41 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzCore/Memory/Memory.h>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
namespace AZ
{
namespace Render
{
// JsonEditorMaterialComponentSerializer skips serialization of EditorMaterialComponentSlot(s) which are only needed at runtime in
// the editor
class JsonEditorMaterialComponentSerializer : public AZ::BaseJsonSerializer
{
public:
AZ_RTTI(JsonEditorMaterialComponentSerializer, "{D354FE3C-34D2-4E80-B3F9-49450D252336}", BaseJsonSerializer);
AZ_CLASS_ALLOCATOR_DECL;
AZ::JsonSerializationResult::Result Load(
void* outputValue,
const AZ::Uuid& outputValueTypeId,
const rapidjson::Value& inputValue,
AZ::JsonDeserializerContext& context) override;
AZ::JsonSerializationResult::Result Store(
rapidjson::Value& outputValue,
const void* inputValue,
const void* defaultValue,
const AZ::Uuid& valueTypeId,
AZ::JsonSerializerContext& context) override;
};
} // namespace Render
} // namespace AZ

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save