From a1d836e36b2a0dd1be9bb82ca1f913b89ec827a4 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 2 Sep 2021 13:29:49 -0500 Subject: [PATCH 01/84] AtomTools: Removing unnecessary cmake files and setting up tool variant Signed-off-by: Guthrie Adams --- .../Application/AtomToolsApplication.cpp | 2 +- .../Tools/MaterialEditor/Code/CMakeLists.txt | 19 ++--- .../Code/materialeditor_files.cmake | 1 - .../Code/tool_dependencies.cmake | 22 ------ .../Tools/MaterialEditor/MaterialEditor.xml | 69 ------------------- .../Code/CMakeLists.txt | 10 +-- .../Code/tool_dependencies.cmake | 22 ------ 7 files changed, 10 insertions(+), 135 deletions(-) delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/tool_dependencies.cmake delete mode 100644 Gems/Atom/Tools/MaterialEditor/MaterialEditor.xml delete mode 100644 Gems/Atom/Tools/ShaderManagementConsole/Code/tool_dependencies.cmake diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 36e45bb7ca..bd04ba9395 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -468,7 +468,7 @@ namespace AtomToolsFramework void AtomToolsApplication::QueryApplicationType(AZ::ApplicationTypeQuery& appType) const { - appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Game; + appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Tool; } void AtomToolsApplication::OnTraceMessage([[maybe_unused]] AZStd::string_view message) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt b/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt index 6230217ac2..0206cebf8b 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt +++ b/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt @@ -108,8 +108,14 @@ ly_add_target( Gem::MaterialEditor.Window Gem::MaterialEditor.Viewport Gem::MaterialEditor.Document + RUNTIME_DEPENDENCIES + Gem::AtomToolsFramework.Editor + Gem::EditorPythonBindings.Editor + Gem::ImageProcessingAtom.Editor ) +ly_set_gem_variant_to_load(TARGETS MaterialEditor VARIANTS Tools) + # Add a 'builders' alias to allow the MaterialEditor root gem path to be added to the generated # cmake_dependencies..assetprocessor.setreg to allow the asset scan folder for it to be added ly_create_alias(NAME MaterialEditor.Builders NAMESPACE Gem) @@ -118,24 +124,11 @@ ly_create_alias(NAME MaterialEditor.Builders NAMESPACE Gem) # Editor opens up the MaterialEditor ly_add_dependencies(Editor Gem::MaterialEditor) -ly_add_target_files( - TARGETS - MaterialEditor - FILES - ${CMAKE_CURRENT_LIST_DIR}/../MaterialEditor.xml - OUTPUT_SUBDIRECTORY - Gems/Atom/Tools/MaterialEditor -) - ly_add_target_dependencies( TARGETS MaterialEditor DEPENDENCIES_FILES - tool_dependencies.cmake Source/Platform/${PAL_PLATFORM_NAME}/tool_dependencies_${PAL_PLATFORM_NAME_LOWERCASE}.cmake - # The Material Editor needs the LyShine "Tools" gem variant for the custom LyShine pass - DEPENDENT_TARGETS - Gem::LyShine.Tools ) # Inject the project path into the MaterialEditor VS debugger command arguments if the build system being invoked diff --git a/Gems/Atom/Tools/MaterialEditor/Code/materialeditor_files.cmake b/Gems/Atom/Tools/MaterialEditor/Code/materialeditor_files.cmake index 2b554a852e..d4c4364ba7 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/materialeditor_files.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/materialeditor_files.cmake @@ -10,5 +10,4 @@ set(FILES Source/main.cpp Source/MaterialEditorApplication.cpp Source/MaterialEditorApplication.h - tool_dependencies.cmake ) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/tool_dependencies.cmake b/Gems/Atom/Tools/MaterialEditor/Code/tool_dependencies.cmake deleted file mode 100644 index 8803be3852..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/tool_dependencies.cmake +++ /dev/null @@ -1,22 +0,0 @@ -# -# 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(GEM_DEPENDENCIES - Gem::Atom_RHI_Null.Private - Gem::Atom_RHI_DX12.Private - Gem::Atom_RHI_Vulkan.Private - Gem::Atom_RHI.Private - Gem::Atom_Component_DebugCamera - Gem::Atom_RPI.Editor - Gem::Atom_RPI.Builders - Gem::Atom_Feature_Common.Editor - Gem::AtomToolsFramework.Editor - Gem::AtomLyIntegration_CommonFeatures.Editor - Gem::EditorPythonBindings.Editor - Gem::ImageProcessingAtom.Editor -) diff --git a/Gems/Atom/Tools/MaterialEditor/MaterialEditor.xml b/Gems/Atom/Tools/MaterialEditor/MaterialEditor.xml deleted file mode 100644 index 9f91001f66..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/MaterialEditor.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt b/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt index d7e415a279..5710a186d3 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt @@ -78,15 +78,12 @@ ly_add_target( Gem::ShaderManagementConsole.Window Gem::ShaderManagementConsole.Document RUNTIME_DEPENDENCIES - Gem::Atom_RHI_DX12.Private - Gem::Atom_RHI_Vulkan.Private - Gem::Atom_RHI.Private - Gem::Atom_RPI.Private - Gem::Atom_RPI.Builders - Gem::Atom_Feature_Common.Editor + Gem::AtomToolsFramework.Editor Gem::EditorPythonBindings.Editor ) +ly_set_gem_variant_to_load(TARGETS ShaderManagementConsole VARIANTS Tools) + # Add build dependency to Editor for the ShaderManagementConsole application since # Editor opens up the ShaderManagementConsole ly_add_dependencies(Editor Gem::ShaderManagementConsole) @@ -95,7 +92,6 @@ ly_add_target_dependencies( TARGETS ShaderManagementConsole DEPENDENCIES_FILES - tool_dependencies.cmake Source/Platform/${PAL_PLATFORM_NAME}/tool_dependencies_${PAL_PLATFORM_NAME_LOWERCASE}.cmake ) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/tool_dependencies.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/tool_dependencies.cmake deleted file mode 100644 index 8803be3852..0000000000 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/tool_dependencies.cmake +++ /dev/null @@ -1,22 +0,0 @@ -# -# 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(GEM_DEPENDENCIES - Gem::Atom_RHI_Null.Private - Gem::Atom_RHI_DX12.Private - Gem::Atom_RHI_Vulkan.Private - Gem::Atom_RHI.Private - Gem::Atom_Component_DebugCamera - Gem::Atom_RPI.Editor - Gem::Atom_RPI.Builders - Gem::Atom_Feature_Common.Editor - Gem::AtomToolsFramework.Editor - Gem::AtomLyIntegration_CommonFeatures.Editor - Gem::EditorPythonBindings.Editor - Gem::ImageProcessingAtom.Editor -) From 76219f6c5f150f56ed38da85424f00189792d6a6 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 8 Sep 2021 17:25:02 -0500 Subject: [PATCH 02/84] Releasing style manager with window Signed-off-by: Guthrie Adams --- .../Code/Source/Application/AtomToolsApplication.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index bd04ba9395..bad4ad97de 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -87,6 +87,7 @@ namespace AtomToolsFramework AtomToolsApplication ::~AtomToolsApplication() { + m_styleManager.reset(); AtomToolsMainWindowNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); @@ -206,6 +207,7 @@ namespace AtomToolsFramework { // before modules are unloaded, destroy UI to free up any assets it cached AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::DestroyMainWindow); + m_styleManager.reset(); AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); @@ -461,6 +463,7 @@ namespace AtomToolsFramework void AtomToolsApplication::Stop() { AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::DestroyMainWindow); + m_styleManager.reset(); UnloadSettings(); Base::Stop(); From a0ada8fcd388d441f018fc1619845682a09f9c27 Mon Sep 17 00:00:00 2001 From: pereslav Date: Thu, 9 Sep 2021 16:44:35 +0100 Subject: [PATCH 03/84] Reworked net entities instantiation in order to fix entity references e.g. parent-child relationship. Note: Only entities within network spawnable keep the references until the ticket system refactoring is done Signed-off-by: pereslav --- .../Code/Source/MultiplayerGem.cpp | 2 - .../NetworkEntity/NetworkEntityManager.cpp | 68 ++++++++++- .../NetworkEntity/NetworkEntityManager.h | 7 ++ .../NetworkEntity/NetworkEntityTracker.h | 1 + .../Pipeline/NetBindMarkerComponent.cpp | 115 ------------------ .../Source/Pipeline/NetBindMarkerComponent.h | 47 ------- .../Pipeline/NetworkPrefabProcessor.cpp | 24 +--- .../NetworkSpawnableHolderComponent.cpp | 2 +- .../NetworkSpawnableHolderComponent.h | 2 +- Gems/Multiplayer/Code/Tests/MainTools.cpp | 2 - Gems/Multiplayer/Code/multiplayer_files.cmake | 2 - 11 files changed, 78 insertions(+), 194 deletions(-) delete mode 100644 Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.cpp delete mode 100644 Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.h diff --git a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp index 1ad7be1a0a..8028e0c5d1 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -23,7 +22,6 @@ namespace Multiplayer AzNetworking::NetworkingSystemComponent::CreateDescriptor(), MultiplayerSystemComponent::CreateDescriptor(), NetBindComponent::CreateDescriptor(), - NetBindMarkerComponent::CreateDescriptor(), NetworkSpawnableHolderComponent::CreateDescriptor(), }); diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 69d2726c65..88f0b221ec 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -467,6 +467,54 @@ namespace Multiplayer return netEntityId; } + AzFramework::EntitySpawnTicket NetworkEntityManager::RequestNetSpawnableInstantiation(const AZ::Data::Asset& rootSpawnable) + { + const AzFramework::Spawnable::EntityList& entityList = rootSpawnable->GetEntities(); + if (entityList.size() == 0) + { + AZ_Assert(false, "RequestNetSpawnableInstantiation: No entities in the spawnable %s", rootSpawnable.GetHint().c_str()) + return {}; + } + + // The first entity in every spawnable is the root one + const AZ::Entity* rootEntity = (entityList.begin())->get(); + + const auto* holderComponent = rootEntity->FindComponent(); + if(!holderComponent) + { + // This spawnable doesn't have a corresponding network spawnable. + return {}; + } + + // Retrieve the corresponding network spawnable asset + AZ::Data::Asset netSpawnableAsset = holderComponent->GetNetworkSpawnableAsset(); + + // Prepare the parameters for the spawning process + AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs; + optionalArgs.m_priority = AzFramework::SpawnablePriority_High; + + // Pre-insertion callback allows us to do network-specific setup for the entities before they are added to the scene + optionalArgs.m_preInsertionCallback = [spawnableAssetId = netSpawnableAsset.GetId()](AzFramework::EntitySpawnTicket::Id, + AzFramework::SpawnableEntityContainerView entities) + { + for (uint32_t netEntityIndex = 0; netEntityIndex < entities.size(); netEntityIndex++) + { + AZ::Entity* netEntity = *(entities.begin() + netEntityIndex); + AZ::Name spawnableName = AZ::Interface::Get()->GetSpawnableNameFromAssetId(spawnableAssetId); + + PrefabEntityId prefabEntityId; + prefabEntityId.m_prefabName = spawnableName; + prefabEntityId.m_entityOffset = netEntityIndex; + AZ::Interface::Get()->SetupNetEntity(netEntity, prefabEntityId, NetEntityRole::Authority); + } + }; + + // Spawn with the newly created ticket. This allows the calling code to manage the lifetime of the constructed entities + AzFramework::EntitySpawnTicket ticket(netSpawnableAsset); + AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(ticket, AZStd::move(optionalArgs)); + return ticket; + } + void NetworkEntityManager::OnRootSpawnableAssigned( [[maybe_unused]] AZ::Data::Asset rootSpawnable, [[maybe_unused]] uint32_t generation) { @@ -477,11 +525,15 @@ namespace Multiplayer { multiplayer->SendReadyForEntityUpdates(true); } + + if(ShouldSpawnNetEntities()) + { + m_rootNetSpawnableTicket = RequestNetSpawnableInstantiation(rootSpawnable); + } } void NetworkEntityManager::OnRootSpawnableReleased([[maybe_unused]] uint32_t generation) { - // TODO: Do we need to clear all entities here? auto* multiplayer = GetMultiplayer(); const auto agentType = multiplayer->GetAgentType(); @@ -489,6 +541,12 @@ namespace Multiplayer { multiplayer->SendReadyForEntityUpdates(false); } + + // Despawn any remaining net entities created locally + if (m_rootNetSpawnableTicket.IsValid()) + { + AzFramework::SpawnableEntitiesInterface::Get()->DespawnAllEntities(m_rootNetSpawnableTicket); + } } void NetworkEntityManager::SetupNetEntity(AZ::Entity* netEntity, PrefabEntityId prefabEntityId, NetEntityRole netEntityRole) @@ -506,4 +564,12 @@ namespace Multiplayer netEntity->GetName().c_str()); } } + + bool NetworkEntityManager::ShouldSpawnNetEntities() const + { + const auto agentType = GetMultiplayer()->GetAgentType(); + const bool shouldSpawnNetEntities = + (agentType == MultiplayerAgentType::ClientServer || agentType == MultiplayerAgentType::DedicatedServer); + return shouldSpawnNetEntities; + } } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h index 9ccc576447..a5956b448f 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -92,6 +93,11 @@ namespace Multiplayer private: void RemoveEntities(); NetEntityId NextId(); + bool ShouldSpawnNetEntities() const; + + // Note: This is an async function. + // The instantiated entities are not available immediately but will be constructed by the spawnable system + AzFramework::EntitySpawnTicket RequestNetSpawnableInstantiation(const AZ::Data::Asset& rootSpawnable); NetworkEntityTracker m_networkEntityTracker; NetworkEntityAuthorityTracker m_networkEntityAuthorityTracker; @@ -120,5 +126,6 @@ namespace Multiplayer DeferredRpcMessages m_localDeferredRpcMessages; NetworkSpawnableLibrary m_networkPrefabLibrary; + AzFramework::EntitySpawnTicket m_rootNetSpawnableTicket; }; } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityTracker.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityTracker.h index 09238acaee..0e632dc7b4 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityTracker.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityTracker.h @@ -37,6 +37,7 @@ namespace Multiplayer NetworkEntityHandle Get(NetEntityId netEntityId); ConstNetworkEntityHandle Get(NetEntityId netEntityId) const; + //! Returns Net Entity ID for a given AZ Entity ID. NetEntityId Get(const AZ::EntityId& entityId) const; //! Returns true if the netEntityId exists. diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.cpp deleted file mode 100644 index c8abac25cb..0000000000 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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 -#include -#include -#include -#include -#include -#include - -namespace Multiplayer -{ - void NetBindMarkerComponent::Reflect(AZ::ReflectContext* context) - { - AZ::SerializeContext* serializeContext = azrtti_cast(context); - if (serializeContext) - { - serializeContext->Class() - ->Version(1) - ->Field("NetEntityIndex", &NetBindMarkerComponent::m_netEntityIndex) - ->Field("NetSpawnableAsset", &NetBindMarkerComponent::m_networkSpawnableAsset); - } - } - - AzFramework::Spawnable* GetSpawnableFromAsset(AZ::Data::Asset& asset) - { - AzFramework::Spawnable* spawnable = asset.GetAs(); - if (!spawnable) - { - asset = - AZ::Data::AssetManager::Instance().GetAsset(asset.GetId(), AZ::Data::AssetLoadBehavior::PreLoad); - AZ::Data::AssetManager::Instance().BlockUntilLoadComplete(asset); - - spawnable = asset.GetAs(); - } - - return spawnable; - } - - - void NetBindMarkerComponent::Activate() - { - const auto agentType = AZ::Interface::Get()->GetAgentType(); - const bool spawnImmediately = - (agentType == MultiplayerAgentType::ClientServer || agentType == MultiplayerAgentType::DedicatedServer); - - if (spawnImmediately && m_networkSpawnableAsset.GetId().IsValid()) - { - AZ::Transform worldTm = GetEntity()->FindComponent()->GetWorldTM(); - auto preInsertionCallback = - [worldTm = AZStd::move(worldTm), netEntityIndex = m_netEntityIndex, spawnableAssetId = m_networkSpawnableAsset.GetId()] - (AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableEntityContainerView entities) - { - if (entities.size() == 1) - { - AZ::Entity* netEntity = *entities.begin(); - - auto* transformComponent = netEntity->FindComponent(); - transformComponent->SetWorldTM(worldTm); - - AZ::Name spawnableName = AZ::Interface::Get()->GetSpawnableNameFromAssetId(spawnableAssetId); - PrefabEntityId prefabEntityId; - prefabEntityId.m_prefabName = spawnableName; - prefabEntityId.m_entityOffset = static_cast(netEntityIndex); - AZ::Interface::Get()->SetupNetEntity(netEntity, prefabEntityId, NetEntityRole::Authority); - } - else - { - AZ_Error("NetBindMarkerComponent", false, "Requested to spawn 1 entity, but received %d", entities.size()); - } - }; - - m_netSpawnTicket = AzFramework::EntitySpawnTicket(m_networkSpawnableAsset); - AzFramework::SpawnEntitiesOptionalArgs optionalArgs; - optionalArgs.m_preInsertionCallback = AZStd::move(preInsertionCallback); - AzFramework::SpawnableEntitiesInterface::Get()->SpawnEntities( - m_netSpawnTicket, { m_netEntityIndex }, AZStd::move(optionalArgs)); - } - } - - void NetBindMarkerComponent::Deactivate() - { - if(m_netSpawnTicket.IsValid()) - { - AzFramework::SpawnableEntitiesInterface::Get()->DespawnAllEntities(m_netSpawnTicket); - } - } - - size_t NetBindMarkerComponent::GetNetEntityIndex() const - { - return m_netEntityIndex; - } - - void NetBindMarkerComponent::SetNetEntityIndex(size_t netEntityIndex) - { - m_netEntityIndex = netEntityIndex; - } - - void NetBindMarkerComponent::SetNetworkSpawnableAsset(AZ::Data::Asset networkSpawnableAsset) - { - m_networkSpawnableAsset = networkSpawnableAsset; - } - - AZ::Data::Asset NetBindMarkerComponent::GetNetworkSpawnableAsset() const - { - return m_networkSpawnableAsset; - } - -} diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.h b/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.h deleted file mode 100644 index dce3252200..0000000000 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetBindMarkerComponent.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 -#include -#include -#include - -namespace Multiplayer -{ - //! @class NetBindMarkerComponent - //! @brief Component for tracking net entities in the original non-networked spawnable. - class NetBindMarkerComponent final : public AZ::Component - { - public: - AZ_COMPONENT(NetBindMarkerComponent, "{40612C1B-427D-45C6-A2F0-04E16DF5B718}"); - - static void Reflect(AZ::ReflectContext* context); - - NetBindMarkerComponent() = default; - ~NetBindMarkerComponent() override = default; - - //! AZ::Component overrides. - //! @{ - void Activate() override; - void Deactivate() override; - //! @} - - size_t GetNetEntityIndex() const; - void SetNetEntityIndex(size_t val); - - void SetNetworkSpawnableAsset(AZ::Data::Asset networkSpawnableAsset); - AZ::Data::Asset GetNetworkSpawnableAsset() const; - - private: - AZ::Data::Asset m_networkSpawnableAsset{AZ::Data::AssetLoadBehavior::PreLoad}; - size_t m_netEntityIndex = 0; - AzFramework::EntitySpawnTicket m_netSpawnTicket; - }; -} // namespace Multiplayer diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp index acfec5eb38..e0990aa785 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkPrefabProcessor.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include @@ -46,7 +45,7 @@ namespace Multiplayer { if (auto* serializeContext = azrtti_cast(context); serializeContext != nullptr) { - serializeContext->Class()->Version(1); + serializeContext->Class()->Version(2); } } @@ -137,8 +136,6 @@ namespace Multiplayer networkSpawnableAsset.Create(networkSpawnable->GetId()); networkSpawnableAsset.SetAutoLoadBehavior(AZ::Data::AssetLoadBehavior::PreLoad); - size_t netEntitiesIndexCounter = 0; - for (auto* prefabEntity : prefabNetEntities) { Instance* instance = netEntityToInstanceMap[prefabEntity]; @@ -148,30 +145,11 @@ namespace Multiplayer AZ_Assert(netEntity, "Unable to detach entity %s [%s] from the source prefab instance", prefabEntity->GetName().c_str(), entityId.ToString().c_str()); - // Net entity will need a new ID to avoid IDs collision - netEntity->SetId(AZ::Entity::MakeId()); netEntity->InvalidateDependencies(); netEntity->EvaluateDependencies(); // Insert the entity into the target net spawnable netSpawnableEntities.emplace_back(netEntity); - - // Use the old ID for the breadcrumb entity to keep parent-child relationship in the original spawnable - AZ::Entity* breadcrumbEntity = aznew AZ::Entity(entityId, netEntity->GetName()); - breadcrumbEntity->SetRuntimeActiveByDefault(netEntity->IsRuntimeActiveByDefault()); - - // Marker component is responsible to spawning entities based on the index. - NetBindMarkerComponent* netBindMarkerComponent = breadcrumbEntity->CreateComponent(); - netBindMarkerComponent->SetNetEntityIndex(netEntitiesIndexCounter); - netBindMarkerComponent->SetNetworkSpawnableAsset(networkSpawnableAsset); - - // Copy the transform component from the original entity to have the correct transform and parent-child relationship - AzFramework::TransformComponent* transformComponent = netEntity->FindComponent(); - breadcrumbEntity->CreateComponent(*transformComponent); - - instance->AddEntity(*breadcrumbEntity); - - netEntitiesIndexCounter++; } // Add net spawnable asset holder to the prefab root diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp index c40cb3677b..e83f6fea84 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp @@ -39,7 +39,7 @@ namespace Multiplayer m_networkSpawnableAsset = networkSpawnableAsset; } - AZ::Data::Asset NetworkSpawnableHolderComponent::GetNetworkSpawnableAsset() + AZ::Data::Asset NetworkSpawnableHolderComponent::GetNetworkSpawnableAsset() const { return m_networkSpawnableAsset; } diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h index d369bbefd3..f32e8d31ab 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h @@ -33,7 +33,7 @@ namespace Multiplayer //! @} void SetNetworkSpawnableAsset(AZ::Data::Asset networkSpawnableAsset); - AZ::Data::Asset GetNetworkSpawnableAsset(); + AZ::Data::Asset GetNetworkSpawnableAsset() const; private: AZ::Data::Asset m_networkSpawnableAsset{ AZ::Data::AssetLoadBehavior::PreLoad }; diff --git a/Gems/Multiplayer/Code/Tests/MainTools.cpp b/Gems/Multiplayer/Code/Tests/MainTools.cpp index 89b2492bc6..53dfad62d1 100644 --- a/Gems/Multiplayer/Code/Tests/MainTools.cpp +++ b/Gems/Multiplayer/Code/Tests/MainTools.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include @@ -30,7 +29,6 @@ namespace Multiplayer { AZStd::vector descriptors({ NetBindComponent::CreateDescriptor(), - NetBindMarkerComponent::CreateDescriptor(), NetworkSpawnableHolderComponent::CreateDescriptor() }); diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake index 0b2adb1530..bdc0129137 100644 --- a/Gems/Multiplayer/Code/multiplayer_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_files.cmake @@ -101,8 +101,6 @@ set(FILES Source/NetworkInput/NetworkInputMigrationVector.h Source/NetworkTime/NetworkTime.cpp Source/NetworkTime/NetworkTime.h - Source/Pipeline/NetBindMarkerComponent.cpp - Source/Pipeline/NetBindMarkerComponent.h Source/Pipeline/NetworkSpawnableHolderComponent.cpp Source/Pipeline/NetworkSpawnableHolderComponent.h Source/Physics/PhysicsUtils.cpp From c2b2cc060a788edb0d398578384de5939eb6c4f8 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Thu, 9 Sep 2021 10:52:12 -0500 Subject: [PATCH 04/84] WIP Signed-off-by: Guthrie Adams --- .../Application/AtomToolsApplication.h | 7 +++++ .../Application/AtomToolsApplication.cpp | 26 ++++++++++++------- .../Viewport/MaterialViewportRenderer.cpp | 7 ----- .../Viewport/MaterialViewportRenderer.h | 5 ---- .../Viewport/MaterialViewportWidget.cpp | 12 ++++++--- .../Code/Source/HttpRequestManager.cpp | 2 +- 6 files changed, 33 insertions(+), 26 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h index d55755a242..f87aca641d 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -35,6 +36,7 @@ namespace AtomToolsFramework , public AzQtComponents::AzQtApplication , protected AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler , protected AzFramework::AssetSystemStatusBus::Handler + , protected AzFramework::AssetCatalogEventBus::Handler , protected AzToolsFramework::EditorPythonConsoleNotificationBus::Handler , protected AZ::UserSettingsOwnerRequestBus::Handler , protected AtomToolsMainWindowNotificationBus::Handler @@ -67,6 +69,11 @@ namespace AtomToolsFramework void OnMainWindowClosing() override; ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// + // AzFramework::AssetCatalogEventBus::Handler overrides ... + void OnCatalogLoaded(const char* catalogFile) override; + ////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////// // AssetDatabaseRequestsBus::Handler overrides... bool GetAssetDatabaseLocation(AZStd::string& result) override; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index bad4ad97de..5751271312 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -91,6 +92,7 @@ namespace AtomToolsFramework AtomToolsMainWindowNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); + AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); } void AtomToolsApplication::CreateReflectionManager() @@ -173,16 +175,11 @@ namespace AtomToolsFramework AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotificationBus::Broadcast( &AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotifications::OnDatabaseInitialized); + AzFramework::AssetCatalogEventBus::Handler::BusConnect(); AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::LoadCatalog, "@assets@/assetcatalog.xml"); - AZ::RPI::RPISystemInterface::Get()->InitializeSystemAssets(); - LoadSettings(); - AtomToolsMainWindowNotificationBus::Handler::BusConnect(); - - AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::CreateMainWindow); - auto editorPythonEventsInterface = AZ::Interface::Get(); if (editorPythonEventsInterface) { @@ -192,9 +189,6 @@ namespace AtomToolsFramework editorPythonEventsInterface->StartPython(); } - // Delay execution of commands and scripts post initialization - QTimer::singleShot(0, [this]() { ProcessCommandLine(m_commandLine); }); - m_timer.start(); } @@ -203,12 +197,26 @@ namespace AtomToolsFramework ExitMainLoop(); } + void AtomToolsApplication::OnCatalogLoaded(const char* catalogFile) + { + AZ_UNUSED(catalogFile); + + // Delay execution of commands and scripts post initialization + AZ::TickBus::QueueFunction([this]() { + AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::CreateMainWindow); + AtomToolsMainWindowNotificationBus::Handler::BusConnect(); + ProcessCommandLine(m_commandLine); + }); + AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); + } + void AtomToolsApplication::Destroy() { // before modules are unloaded, destroy UI to free up any assets it cached AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::DestroyMainWindow); m_styleManager.reset(); + AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); AtomToolsMainWindowNotificationBus::Handler::BusDisconnect(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp index f98cdce91b..ceaed0e498 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.cpp @@ -247,12 +247,10 @@ namespace MaterialEditor MaterialViewportNotificationBus::Handler::BusConnect(); AZ::TickBus::Handler::BusConnect(); AZ::TransformNotificationBus::MultiHandler::BusConnect(m_cameraEntity->GetId()); - AzFramework::WindowSystemRequestBus::Handler::BusConnect(); } MaterialViewportRenderer::~MaterialViewportRenderer() { - AzFramework::WindowSystemRequestBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); AZ::TickBus::Handler::BusDisconnect(); AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler::BusDisconnect(); @@ -303,11 +301,6 @@ namespace MaterialEditor return m_viewportController; } - AzFramework::NativeWindowHandle MaterialViewportRenderer::GetDefaultWindowHandle() - { - return (m_windowContext) ? m_windowContext->GetWindowHandle() : nullptr; - } - void MaterialViewportRenderer::OnDocumentOpened(const AZ::Uuid& documentId) { AZ::Data::Instance materialInstance; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h index 240d66fd43..df77b91356 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportRenderer.h @@ -16,7 +16,6 @@ #include #include #include -#include #include namespace AZ @@ -46,7 +45,6 @@ namespace MaterialEditor , public AtomToolsFramework::AtomToolsDocumentNotificationBus::Handler , public MaterialViewportNotificationBus::Handler , public AZ::TransformNotificationBus::MultiHandler - , public AzFramework::WindowSystemRequestBus::Handler { public: AZ_CLASS_ALLOCATOR(MaterialViewportRenderer, AZ::SystemAllocator, 0); @@ -81,9 +79,6 @@ namespace MaterialEditor // AZ::TransformNotificationBus::MultiHandler overrides... void OnTransformChanged(const AZ::Transform&, const AZ::Transform&) override; - // AzFramework::WindowSystemRequestBus::Handler overrides ... - AzFramework::NativeWindowHandle GetDefaultWindowHandle() override; - using DirectionalLightHandle = AZ::Render::DirectionalLightFeatureProcessorInterface::LightHandle; AZ::Data::Instance m_swapChainPass; diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp index c78951ed45..d2fe78cb89 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp @@ -13,17 +13,18 @@ #include #include -#include -#include +#include +#include -AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT +AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknow n-warning-option") // disable warnings spawned by QT #include #include -#include "Source/Viewport/ui_MaterialViewportWidget.h" +#include "Viewport/ui_MaterialViewportWidget.h" AZ_POP_DISABLE_WARNING #include #include +#include namespace Platform { @@ -45,6 +46,9 @@ namespace MaterialEditor dispatcher->installNativeEventFilter(this); } + AzFramework::WindowSystemNotificationBus::Broadcast( + &AzFramework::WindowSystemNotificationBus::Events::OnWindowCreated, GetViewportContext()->GetWindowHandle()); + // The viewport context created by AtomToolsFramework::RenderViewportWidget has no name. // Systems like frame capturing and post FX expect there to be a context with DefaultViewportContextName auto viewportContextManager = AZ::Interface::Get(); diff --git a/Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp b/Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp index 8ed40c1599..c4753d2e94 100644 --- a/Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp +++ b/Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp @@ -50,7 +50,7 @@ namespace HttpRequestor { m_thread.join(); } - + AWSNativeSDKInit::InitializationManager::Shutdown(); } void Manager::AddRequest(Parameters && httpRequestParameters) From 1f66e8a76054a7a136e13fcf1b2cd126c73c1d8a Mon Sep 17 00:00:00 2001 From: pereslav Date: Mon, 13 Sep 2021 13:35:35 +0100 Subject: [PATCH 05/84] PR feedback addressing Signed-off-by: pereslav --- .../NetworkEntity/NetworkEntityManager.cpp | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 88f0b221ec..4e0818323e 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -470,14 +470,21 @@ namespace Multiplayer AzFramework::EntitySpawnTicket NetworkEntityManager::RequestNetSpawnableInstantiation(const AZ::Data::Asset& rootSpawnable) { const AzFramework::Spawnable::EntityList& entityList = rootSpawnable->GetEntities(); - if (entityList.size() == 0) + if (entityList.empty()) { - AZ_Assert(false, "RequestNetSpawnableInstantiation: No entities in the spawnable %s", rootSpawnable.GetHint().c_str()) + AZ_Error("NetworkEntityManager", false, + "RequestNetSpawnableInstantiation: No entities in the spawnable %s", rootSpawnable.GetHint().c_str()); return {}; } // The first entity in every spawnable is the root one const AZ::Entity* rootEntity = (entityList.begin())->get(); + if(!rootEntity) + { + AZ_Error("NetworkEntityManager", false, + "RequestNetSpawnableInstantiation: Root entity is null in the spawnable %s", rootSpawnable.GetHint().c_str()); + return {}; + } const auto* holderComponent = rootEntity->FindComponent(); if(!holderComponent) @@ -493,17 +500,19 @@ namespace Multiplayer AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs; optionalArgs.m_priority = AzFramework::SpawnablePriority_High; + AZ::Name netSpawnableName = AZ::Interface::Get()->GetSpawnableNameFromAssetId(netSpawnableAsset.GetId()); + // Pre-insertion callback allows us to do network-specific setup for the entities before they are added to the scene - optionalArgs.m_preInsertionCallback = [spawnableAssetId = netSpawnableAsset.GetId()](AzFramework::EntitySpawnTicket::Id, + optionalArgs.m_preInsertionCallback = [netSpawnableName = netSpawnableName](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableEntityContainerView entities) { - for (uint32_t netEntityIndex = 0; netEntityIndex < entities.size(); netEntityIndex++) + for (uint32_t netEntityIndex = 0, entitiesSize = aznumeric_cast(entities.size()); + netEntityIndex < entitiesSize; netEntityIndex++) { AZ::Entity* netEntity = *(entities.begin() + netEntityIndex); - AZ::Name spawnableName = AZ::Interface::Get()->GetSpawnableNameFromAssetId(spawnableAssetId); PrefabEntityId prefabEntityId; - prefabEntityId.m_prefabName = spawnableName; + prefabEntityId.m_prefabName = netSpawnableName; prefabEntityId.m_entityOffset = netEntityIndex; AZ::Interface::Get()->SetupNetEntity(netEntity, prefabEntityId, NetEntityRole::Authority); } From 9b0e3f26b14e6573ad0877a63ef9e9d66879cefb Mon Sep 17 00:00:00 2001 From: pereslav Date: Mon, 13 Sep 2021 16:30:42 +0100 Subject: [PATCH 06/84] PR feedback addressing 2 Signed-off-by: pereslav --- .../Code/Source/NetworkEntity/NetworkEntityManager.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 4e0818323e..793acc17ff 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -500,10 +500,11 @@ namespace Multiplayer AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs; optionalArgs.m_priority = AzFramework::SpawnablePriority_High; - AZ::Name netSpawnableName = AZ::Interface::Get()->GetSpawnableNameFromAssetId(netSpawnableAsset.GetId()); + const AZ::Name netSpawnableName = + AZ::Interface::Get()->GetSpawnableNameFromAssetId(netSpawnableAsset.GetId()); // Pre-insertion callback allows us to do network-specific setup for the entities before they are added to the scene - optionalArgs.m_preInsertionCallback = [netSpawnableName = netSpawnableName](AzFramework::EntitySpawnTicket::Id, + optionalArgs.m_preInsertionCallback = [netSpawnableName](AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableEntityContainerView entities) { for (uint32_t netEntityIndex = 0, entitiesSize = aznumeric_cast(entities.size()); From aa6c03888051eb90999428936efa7c5d28455ba0 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 13 Sep 2021 16:51:50 -0400 Subject: [PATCH 07/84] Hierarchical components, phase 1, unittests Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Multiplayer/Components/NetBindComponent.h | 2 + .../Components/NetworkHierarchyBus.h | 46 + .../NetworkHierarchyChildComponent.h | 66 + .../NetworkHierarchyRootComponent.h | 76 ++ .../Components/NetworkTransformComponent.h | 4 + ...kHierarchyChildComponent.AutoComponent.xml | 14 + ...rkHierarchyRootComponent.AutoComponent.xml | 14 + .../NetworkHierarchyChildComponent.cpp | 134 ++ .../NetworkHierarchyRootComponent.cpp | 277 ++++ .../Components/NetworkTransformComponent.cpp | 43 +- .../Code/Source/MultiplayerGem.cpp | 6 +- .../EntityReplicationManager.cpp | 26 +- .../EntityReplication/EntityReplicator.cpp | 96 +- .../EntityReplication/EntityReplicator.h | 4 +- .../Code/Tests/ClientHierarchyTests.cpp | 379 ++++++ .../Code/Tests/CommonHierarchySetup.h | 387 ++++++ Gems/Multiplayer/Code/Tests/MockInterfaces.h | 166 +++ .../Code/Tests/ServerHierarchyTests.cpp | 1145 +++++++++++++++++ Gems/Multiplayer/Code/multiplayer_files.cmake | 42 +- .../Code/multiplayer_tests_files.cmake | 4 + 20 files changed, 2886 insertions(+), 45 deletions(-) create mode 100644 Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h create mode 100644 Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h create mode 100644 Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h create mode 100644 Gems/Multiplayer/Code/Source/AutoGen/NetworkHierarchyChildComponent.AutoComponent.xml create mode 100644 Gems/Multiplayer/Code/Source/AutoGen/NetworkHierarchyRootComponent.AutoComponent.xml create mode 100644 Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp create mode 100644 Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp create mode 100644 Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp create mode 100644 Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h create mode 100644 Gems/Multiplayer/Code/Tests/MockInterfaces.h create mode 100644 Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h index 65bac09726..855d109145 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetBindComponent.h @@ -199,6 +199,8 @@ namespace Multiplayer friend class NetworkEntityManager; friend class EntityReplicationManager; + + friend class HierarchyTests; }; bool NetworkRoleHasController(NetEntityRole networkRole); diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h new file mode 100644 index 0000000000..72dff65401 --- /dev/null +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h @@ -0,0 +1,46 @@ +/* + * 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 + +namespace Multiplayer +{ + class NetworkHierarchyNotifications + : public AZ::ComponentBus + { + public: + //! Called when a hierarchy has been updated (a child added or removed, etc.) + virtual void OnNetworkHierarchyUpdated([[maybe_unused]] const AZ::EntityId& rootEntityId) {} + + //! Called when an entity has left a hierarchy + virtual void OnLeavingNetworkHierarchy() {} + }; + + typedef AZ::EBus NetworkHierarchyNotificationBus; + + class NetworkHierarchyRequests + : public AZ::ComponentBus + { + public: + //! @returns hierarchical entities, the first element is the top level root + virtual AZStd::vector GetHierarchicalEntities() const = 0; + + //! @returns the top level root of a hierarchy, or nullptr if this entity is not in a hierarchy + virtual AZ::Entity* GetHierarchicalRoot() const = 0; + + //! @return true if this entity is a child entity within a hierarchy + virtual bool IsHierarchicalChild() const = 0; + + //! @return true if this entity is the top level root of a hierarchy + virtual bool IsHierarchicalRoot() const = 0; + }; + + typedef AZ::EBus NetworkHierarchyRequestBus; +} diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h new file mode 100644 index 0000000000..27f794ec21 --- /dev/null +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h @@ -0,0 +1,66 @@ +/* + * 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 +#include +#include + +namespace Multiplayer +{ + class NetworkHierarchyRootComponent; + + //! @class NetworkHierarchyChildComponent + //! @brief Component that declares network dependency on the parent of this entity + /* + * The parent of this entity should have @NetworkHierarchyChildComponent (or @NetworkHierarchyRootComponent). + * A network hierarchy is a collection of entities with one @NetworkHierarchyRootComponent at the top parent + * and one or more @NetworkHierarchyChildComponent on its child entities. + */ + class NetworkHierarchyChildComponent final + : public NetworkHierarchyChildComponentBase + , public NetworkHierarchyRequestBus::Handler + { + friend class NetworkHierarchyRootComponent; + + public: + AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkHierarchyChildComponent, s_networkHierarchyChildComponentConcreteUuid, Multiplayer::NetworkHierarchyChildComponentBase); + + static void Reflect(AZ::ReflectContext* context); + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + + NetworkHierarchyChildComponent(); + + //! @{ + void OnInit() override; + void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + //! @} + + //! NetworkHierarchyRequestBus overrides + //! @{ + bool IsHierarchicalChild() const override; + bool IsHierarchicalRoot() const override { return false; } + AZ::Entity* GetHierarchicalRoot() const override; + AZStd::vector GetHierarchicalEntities() const override; + //! @} + + protected: + //! Used by @NetworkHierarchyRootComponent + void SetTopLevelHierarchyRootComponent(NetworkHierarchyRootComponent* hierarchyRoot); + + private: + const NetworkHierarchyRootComponent* m_hierarchyRootComponent = nullptr; + + AZ::Event::Handler m_hierarchyRootNetIdChanged; + void OnHierarchyRootNetIdChanged(NetEntityId rootNetId); + }; +} diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h new file mode 100644 index 0000000000..48c003d9e7 --- /dev/null +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h @@ -0,0 +1,76 @@ +/* + * 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 +#include +#include +#include + +namespace Multiplayer +{ + //! @class NetworkHierarchyRootComponent + //! @brief Component that declares the top level entity of a network hierarchy. + /* + * Call @GetHierarchyChildren to get the list of hierarchical entities. + * A network hierarchy is meant to be a small group of entities. You can control the maximum supported size of + * a network hierarchy by modifying CVar @bg_hierarchyEntityMaxLimit. + * + * A root component marks either a top most root of a hierarchy, or an inner root of an attach hierarchy. + */ + class NetworkHierarchyRootComponent final + : public NetworkHierarchyRootComponentBase + , public NetworkHierarchyRequestBus::Handler + , protected AZ::TransformNotificationBus::MultiHandler + { + public: + AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkHierarchyRootComponent, s_networkHierarchyRootComponentConcreteUuid, Multiplayer::NetworkHierarchyRootComponentBase); + + static void Reflect(AZ::ReflectContext* context); + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + + //! NetworkHierarchyRootComponentBase overrides. + //! @{ + void OnInit() override; + void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + //! @} + + //! NetworkHierarchyRequestBus overrides. + //! @{ + bool IsHierarchicalRoot() const override; + bool IsHierarchicalChild() const override; + AZStd::vector GetHierarchicalEntities() const override; + AZ::Entity* GetHierarchicalRoot() const override; + //! @} + + protected: + //! AZ::TransformNotificationBus::Handler overrides. + //! @{ + void OnParentChanged(AZ::EntityId oldParent, AZ::EntityId newParent) override; + void OnChildAdded(AZ::EntityId child) override; + void OnChildRemoved(AZ::EntityId childRemovedId) override; + //! @} + + void SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot); + + private: + AZ::Entity* m_higherRootEntity = nullptr; + AZStd::vector m_hierarchicalEntities; + + void RebuildHierarchy(); + + //! @returns false if the maximum supported hierarchy size has been reached + bool RecursiveAttachHierarchicalEntities(AZ::EntityId underEntity, uint32_t& currentEntityCount); + //! @returns false if the maximum supported hierarchy size has been reached + bool RecursiveAttachHierarchicalChild(AZ::EntityId entity, uint32_t& currentEntityCount); + }; +} diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h index 914aeaadd3..969b59a672 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h @@ -36,6 +36,7 @@ namespace Multiplayer void OnTranslationChangedEvent(const AZ::Vector3& translation); void OnScaleChangedEvent(float scale); void OnResetCountChangedEvent(); + void OnParentIdChangedEvent(NetEntityId newParent); void UpdateTargetHostFrameId(); @@ -46,6 +47,7 @@ namespace Multiplayer AZ::Event::Handler m_translationEventHandler; AZ::Event::Handler m_scaleEventHandler; AZ::Event::Handler m_resetCountEventHandler; + AZ::Event::Handler m_parentIdChangedEventHandler; EntityPreRenderEvent::Handler m_entityPreRenderEventHandler; EntityCorrectionEvent::Handler m_entityCorrectionEventHandler; @@ -64,7 +66,9 @@ namespace Multiplayer private: void OnTransformChangedEvent(const AZ::Transform& worldTm); + void OnParentIdChangedEvent(AZ::EntityId oldParent, AZ::EntityId newParent); AZ::TransformChangedEvent::Handler m_transformChangedHandler; + AZ::ParentChangedEvent::Handler m_parentIdChangedHandler; }; } diff --git a/Gems/Multiplayer/Code/Source/AutoGen/NetworkHierarchyChildComponent.AutoComponent.xml b/Gems/Multiplayer/Code/Source/AutoGen/NetworkHierarchyChildComponent.AutoComponent.xml new file mode 100644 index 0000000000..46523d3724 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/AutoGen/NetworkHierarchyChildComponent.AutoComponent.xml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/Gems/Multiplayer/Code/Source/AutoGen/NetworkHierarchyRootComponent.AutoComponent.xml b/Gems/Multiplayer/Code/Source/AutoGen/NetworkHierarchyRootComponent.AutoComponent.xml new file mode 100644 index 0000000000..0f33e1f642 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/AutoGen/NetworkHierarchyRootComponent.AutoComponent.xml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp new file mode 100644 index 0000000000..c644b832a0 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp @@ -0,0 +1,134 @@ +/* + * 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 +#include +#include +#include +#include +#include + +namespace Multiplayer +{ + void NetworkHierarchyChildComponent::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Version(1); + + if (AZ::EditContext* editContext = serializeContext->GetEditContext()) + { + editContext->Class( + "Network Hierarchy Child", "declares a network dependency on the root of this hierarchy") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::Category, "Multiplayer") + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game")) + ; + } + } + NetworkHierarchyChildComponentBase::Reflect(context); + } + + void NetworkHierarchyChildComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + { + required.push_back(AZ_CRC_CE("NetworkTransformComponent")); + } + + void NetworkHierarchyChildComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("NetworkHierarchyChildComponent")); + } + + void NetworkHierarchyChildComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC_CE("NetworkHierarchyChildComponent")); + incompatible.push_back(AZ_CRC_CE("NetworkHierarchyRootComponent")); + } + + NetworkHierarchyChildComponent::NetworkHierarchyChildComponent() + : m_hierarchyRootNetIdChanged([this](NetEntityId rootNetId) {OnHierarchyRootNetIdChanged(rootNetId); }) + { + + } + + void NetworkHierarchyChildComponent::OnInit() + { + } + + void NetworkHierarchyChildComponent::OnActivate([[maybe_unused]] EntityIsMigrating entityIsMigrating) + { + HierarchyRootAddEvent(m_hierarchyRootNetIdChanged); + NetworkHierarchyRequestBus::Handler::BusConnect(GetEntityId()); + } + + void NetworkHierarchyChildComponent::OnDeactivate([[maybe_unused]] EntityIsMigrating entityIsMigrating) + { + NetworkHierarchyRequestBus::Handler::BusDisconnect(); + } + + bool NetworkHierarchyChildComponent::IsHierarchicalChild() const + { + if (GetHierarchyRoot() != InvalidNetEntityId) + { + return true; + } + + return false; + } + + AZ::Entity* NetworkHierarchyChildComponent::GetHierarchicalRoot() const + { + return m_hierarchyRootComponent ? m_hierarchyRootComponent->GetEntity() : nullptr; + } + + AZStd::vector NetworkHierarchyChildComponent::GetHierarchicalEntities() const + { + if (m_hierarchyRootComponent) + { + return m_hierarchyRootComponent->GetHierarchicalEntities(); + } + + return {}; + } + + void NetworkHierarchyChildComponent::SetTopLevelHierarchyRootComponent(NetworkHierarchyRootComponent* hierarchyRoot) + { + m_hierarchyRootComponent = hierarchyRoot; + if (HasController() && GetNetBindComponent()->GetNetEntityRole() == NetEntityRole::Authority) + { + NetworkHierarchyChildComponentController* controller = static_cast(GetController()); + if (hierarchyRoot) + { + const NetEntityId netRootId = GetNetworkEntityManager()->GetNetEntityIdById(hierarchyRoot->GetEntityId()); + controller->SetHierarchyRoot(netRootId); + + NetworkHierarchyNotificationBus::Event(GetEntityId(), &NetworkHierarchyNotificationBus::Events::OnNetworkHierarchyUpdated, hierarchyRoot->GetEntityId()); + } + else + { + controller->SetHierarchyRoot(InvalidNetEntityId); + NetworkHierarchyNotificationBus::Event(GetEntityId(), &NetworkHierarchyNotificationBus::Events::OnLeavingNetworkHierarchy); + } + } + } + + void NetworkHierarchyChildComponent::OnHierarchyRootNetIdChanged(NetEntityId rootNetId) + { + const ConstNetworkEntityHandle rootHandle = GetNetworkEntityManager()->GetEntity(rootNetId); + if (rootHandle.Exists()) + { + m_hierarchyRootComponent = rootHandle.FindComponent(); + } + else + { + m_hierarchyRootComponent = nullptr; + } + } +} diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp new file mode 100644 index 0000000000..2fa960ed2a --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp @@ -0,0 +1,277 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +AZ_CVAR(uint32_t, bg_hierarchyEntityMaxLimit, 16, nullptr, AZ::ConsoleFunctorFlags::Null, + "Maximum allowed size of network entity hierarchies, including top level entity."); + +namespace Multiplayer +{ + void NetworkHierarchyRootComponent::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serializeContext = azrtti_cast(context); + if (serializeContext) + { + serializeContext->Class() + ->Version(1); + + if (AZ::EditContext* editContext = serializeContext->GetEditContext()) + { + editContext->Class( + "Network Hierarchy Root", "marks the entity as the root of an entity hierarchy") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::Category, "Multiplayer") + ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game")) + ; + } + } + NetworkHierarchyRootComponentBase::Reflect(context); + } + + void NetworkHierarchyRootComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + { + required.push_back(AZ_CRC_CE("NetworkTransformComponent")); + } + + void NetworkHierarchyRootComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("NetworkHierarchyRootComponent")); + } + + void NetworkHierarchyRootComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC_CE("NetworkHierarchyChildComponent")); + incompatible.push_back(AZ_CRC_CE("NetworkHierarchyRootComponent")); + } + + void NetworkHierarchyRootComponent::OnInit() + { + } + + void NetworkHierarchyRootComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + m_hierarchicalEntities.push_back(GetEntity()); + + NetworkHierarchyRequestBus::Handler::BusConnect(GetEntityId()); + AZ::TransformNotificationBus::MultiHandler::BusConnect(GetEntityId()); + } + + void NetworkHierarchyRootComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) + { + AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); + NetworkHierarchyRequestBus::Handler::BusDisconnect(); + + for (const AZ::Entity* childEntity : m_hierarchicalEntities) + { + auto* hierarchyChildComponent = childEntity->FindComponent(); + auto* hierarchyRootComponent = childEntity->FindComponent(); + + if (hierarchyChildComponent) + { + hierarchyChildComponent->SetTopLevelHierarchyRootComponent(nullptr); + } + if (hierarchyRootComponent) + { + hierarchyRootComponent->SetTopLevelHierarchyRootEntity(nullptr); + } + } + + m_hierarchicalEntities.clear(); + m_higherRootEntity = nullptr; + } + + bool NetworkHierarchyRootComponent::IsHierarchicalRoot() const + { + if (GetHierarchyRoot() != InvalidNetEntityId) + { + return false; + } + + return true; + } + + bool NetworkHierarchyRootComponent::IsHierarchicalChild() const + { + return !IsHierarchicalRoot(); + } + + AZStd::vector NetworkHierarchyRootComponent::GetHierarchicalEntities() const + { + return m_hierarchicalEntities; + } + + AZ::Entity* NetworkHierarchyRootComponent::GetHierarchicalRoot() const + { + if (m_higherRootEntity) + { + return m_higherRootEntity; + } + + return GetEntity(); + } + + void NetworkHierarchyRootComponent::OnParentChanged([[maybe_unused]] AZ::EntityId oldParent, AZ::EntityId newParent) + { + const AZ::EntityId entityBusId = *AZ::TransformNotificationBus::GetCurrentBusId(); + if (GetEntityId() != entityBusId) + { + return; // ignore parent changes of child entities + } + + if (AZ::Entity* parentEntity = AZ::Interface::Get()->FindEntity(newParent)) + { + if (parentEntity->FindComponent()) + { + m_higherRootEntity = parentEntity; + m_hierarchicalEntities.clear(); + AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); + + // Should still listen for its events, such as when this root detaches + AZ::TransformNotificationBus::MultiHandler::BusConnect(GetEntityId()); + } + } + else + { + // detached from parent + RebuildHierarchy(); + } + } + + void NetworkHierarchyRootComponent::OnChildAdded([[maybe_unused]] AZ::EntityId child) + { + // Parent-child notifications from TransformNotificationBus are not reliable enough to avoid duplicate notifications, + // so we will rebuild from scratch to avoid duplicate entries in @m_hierarchicalEntities. + RebuildHierarchy(); + } + + void NetworkHierarchyRootComponent::RebuildHierarchy() + { + m_hierarchicalEntities.clear(); + m_hierarchicalEntities.push_back(GetEntity()); // add the root itself + + AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); + AZ::TransformNotificationBus::MultiHandler::BusConnect(GetEntityId()); + + uint32_t currentEntityCount = aznumeric_cast(m_hierarchicalEntities.size()); + RecursiveAttachHierarchicalEntities(GetEntityId(), currentEntityCount); + } + + bool NetworkHierarchyRootComponent::RecursiveAttachHierarchicalEntities(AZ::EntityId underEntity, uint32_t& currentEntityCount) + { + AZStd::vector allChildren; + AZ::TransformBus::EventResult(allChildren, underEntity, &AZ::TransformBus::Events::GetChildren); + + for (const AZ::EntityId newChildId : allChildren) + { + if (!RecursiveAttachHierarchicalChild(newChildId, currentEntityCount)) + { + return false; + } + } + + return true; + } + + bool NetworkHierarchyRootComponent::RecursiveAttachHierarchicalChild(AZ::EntityId entity, uint32_t& currentEntityCount) + { + if (currentEntityCount >= bg_hierarchyEntityMaxLimit) + { + AZLOG_WARN("Entity %s is trying to build a network hierarchy that is too large. bg_hierarchyEntityMaxLimit is currently set to (%u)", + GetEntity()->GetName().c_str(), static_cast(bg_hierarchyEntityMaxLimit)); + return false; + } + + if (AZ::Entity* childEntity = AZ::Interface::Get()->FindEntity(entity)) + { + auto* hierarchyChildComponent = childEntity->FindComponent(); + auto* hierarchyRootComponent = childEntity->FindComponent(); + + if (hierarchyChildComponent || hierarchyRootComponent) + { + AZ::TransformNotificationBus::MultiHandler::BusConnect(entity); + m_hierarchicalEntities.push_back(childEntity); + ++currentEntityCount; + + if (hierarchyChildComponent) + { + hierarchyChildComponent->SetTopLevelHierarchyRootComponent(this); + } + else if (hierarchyRootComponent) + { + hierarchyRootComponent->SetTopLevelHierarchyRootEntity(GetEntity()); + } + + if (!RecursiveAttachHierarchicalEntities(entity, currentEntityCount)) + { + return false; + } + } + } + + return true; + } + + void NetworkHierarchyRootComponent::OnChildRemoved(AZ::EntityId childRemovedId) + { + AZStd::vector allChildren; + AZ::TransformBus::EventResult(allChildren, childRemovedId, &AZ::TransformBus::Events::GetEntityAndAllDescendants); + + for (AZ::EntityId childId : allChildren) + { + AZ::TransformNotificationBus::MultiHandler::BusDisconnect(childId); + + const AZ::Entity* childEntity = nullptr; + + AZStd::erase_if(m_hierarchicalEntities, [childId, &childEntity](const AZ::Entity* entity) + { + if (entity->GetId() == childId) + { + childEntity = entity; + return true; + } + + return false; + }); + + if (childEntity) + { + if (NetworkHierarchyChildComponent* childComponent = childEntity->FindComponent()) + { + childComponent->SetTopLevelHierarchyRootComponent(nullptr); + } + } + } + } + + void NetworkHierarchyRootComponent::SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot) + { + m_higherRootEntity = hierarchyRoot; + if (HasController() && GetNetBindComponent()->GetNetEntityRole() == NetEntityRole::Authority) + { + NetworkHierarchyChildComponentController* controller = static_cast(GetController()); + if (hierarchyRoot) + { + const NetEntityId netRootId = GetNetworkEntityManager()->GetNetEntityIdById(hierarchyRoot->GetId()); + controller->SetHierarchyRoot(netRootId); + } + else + { + controller->SetHierarchyRoot(InvalidNetEntityId); + } + } + } +} diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp index fa08794c4d..a37b6b52ed 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp @@ -30,6 +30,7 @@ namespace Multiplayer , m_translationEventHandler([this](const AZ::Vector3& translation) { OnTranslationChangedEvent(translation); }) , m_scaleEventHandler([this](float scale) { OnScaleChangedEvent(scale); }) , m_resetCountEventHandler([this](const uint8_t&) { OnResetCountChangedEvent(); }) + , m_parentIdChangedEventHandler([this](NetEntityId newParent) { OnParentIdChangedEvent(newParent); }) , m_entityPreRenderEventHandler([this](float deltaTime, float blendFactor) { OnPreRender(deltaTime, blendFactor); }) , m_entityCorrectionEventHandler([this]() { OnCorrection(); }) { @@ -47,8 +48,12 @@ namespace Multiplayer TranslationAddEvent(m_translationEventHandler); ScaleAddEvent(m_scaleEventHandler); ResetCountAddEvent(m_resetCountEventHandler); - GetNetBindComponent()->AddEntityPreRenderEventHandler(m_entityPreRenderEventHandler); - GetNetBindComponent()->AddEntityCorrectionEventHandler(m_entityCorrectionEventHandler); + ParentEntityIdAddEvent(m_parentIdChangedEventHandler); + if (GetNetBindComponent()) + { + GetNetBindComponent()->AddEntityPreRenderEventHandler(m_entityPreRenderEventHandler); + GetNetBindComponent()->AddEntityCorrectionEventHandler(m_entityCorrectionEventHandler); + } // When coming into relevance, reset all blending factors so we don't interpolate to our start position OnResetCountChangedEvent(); @@ -82,15 +87,33 @@ namespace Multiplayer void NetworkTransformComponent::OnResetCountChangedEvent() { + OnParentIdChangedEvent(GetParentEntityId()); + m_targetTransform.SetRotation(GetRotation()); m_targetTransform.SetTranslation(GetTranslation()); m_targetTransform.SetUniformScale(GetScale()); m_previousTransform = m_targetTransform; } + void NetworkTransformComponent::OnParentIdChangedEvent([[maybe_unused]] NetEntityId newParent) + { + const ConstNetworkEntityHandle rootHandle = GetNetworkEntityManager()->GetEntity(newParent); + if (rootHandle.Exists()) + { + const AZ::EntityId parentEntityId = rootHandle.GetEntity()->GetId(); + if (AzFramework::TransformComponent* transformComponent = GetEntity()->FindComponent()) + { + if (transformComponent->GetParentId() != parentEntityId) + { + transformComponent->SetParent(parentEntityId); + } + } + } + } + void NetworkTransformComponent::UpdateTargetHostFrameId() { - HostFrameId currentHostFrameId = Multiplayer::GetNetworkTime()->GetHostFrameId(); + const HostFrameId currentHostFrameId = Multiplayer::GetNetworkTime()->GetHostFrameId(); if (currentHostFrameId > m_targetHostFrameId) { m_targetHostFrameId = currentHostFrameId; @@ -137,6 +160,7 @@ namespace Multiplayer NetworkTransformComponentController::NetworkTransformComponentController(NetworkTransformComponent& parent) : NetworkTransformComponentControllerBase(parent) , m_transformChangedHandler([this](const AZ::Transform&, const AZ::Transform& worldTm) { OnTransformChangedEvent(worldTm); }) + , m_parentIdChangedHandler([this](AZ::EntityId oldParent, AZ::EntityId newParent) { OnParentIdChangedEvent(oldParent, newParent); }) { ; } @@ -145,6 +169,9 @@ namespace Multiplayer { GetParent().GetTransformComponent()->BindTransformChangedEventHandler(m_transformChangedHandler); OnTransformChangedEvent(GetParent().GetTransformComponent()->GetWorldTM()); + + GetParent().GetTransformComponent()->BindParentChangedEventHandler(m_parentIdChangedHandler); + OnParentIdChangedEvent(AZ::EntityId(), GetParent().GetTransformComponent()->GetParentId()); } void NetworkTransformComponentController::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) @@ -158,4 +185,14 @@ namespace Multiplayer SetTranslation(worldTm.GetTranslation()); SetScale(worldTm.GetUniformScale()); } + + void NetworkTransformComponentController::OnParentIdChangedEvent([[maybe_unused]] AZ::EntityId oldParent, AZ::EntityId newParent) + { + AZ::Entity* parentEntity = AZ::Interface::Get()->FindEntity(newParent); + if (parentEntity) + { + const ConstNetworkEntityHandle parentHandle(parentEntity, GetNetworkEntityTracker()); + SetParentEntityId(parentHandle.GetNetEntityId()); + } + } } diff --git a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp index 1ad7be1a0a..849dc15e10 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerGem.cpp @@ -6,13 +6,15 @@ * */ +#include +#include +#include +#include #include #include #include #include #include -#include -#include namespace Multiplayer { diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp index 482d3a1ee8..b45c05cda7 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp @@ -75,6 +75,8 @@ namespace Multiplayer void EntityReplicationManager::ActivatePendingEntities() { + AZStd::vector notReadyEntities; + const AZ::TimeMs endTimeMs = AZ::GetElapsedTimeMs() + m_entityActivationTimeSliceMs; while (!m_entitiesPendingActivation.empty()) { @@ -83,7 +85,14 @@ namespace Multiplayer EntityReplicator* entityReplicator = GetEntityReplicator(entityId); if (entityReplicator && !entityReplicator->IsMarkedForRemoval()) { - entityReplicator->ActivateNetworkEntity(); + if (entityReplicator->IsReadyToActivate()) + { + entityReplicator->ActivateNetworkEntity(); + } + else + { + notReadyEntities.push_back(entityId); + } } if (m_entityActivationTimeSliceMs > AZ::TimeMs{ 0 } && AZ::GetElapsedTimeMs() > endTimeMs) { @@ -91,6 +100,11 @@ namespace Multiplayer break; } } + + for (NetEntityId netEntityId : notReadyEntities) + { + m_entitiesPendingActivation.push_back(netEntityId); + } } void EntityReplicationManager::SendUpdates(AZ::TimeMs hostTimeMs) @@ -249,15 +263,15 @@ namespace Multiplayer void EntityReplicationManager::SendEntityUpdates(AZ::TimeMs hostTimeMs) { EntityReplicatorList toSendList = GenerateEntityUpdateList(); - + AZLOG(NET_ReplicationInfo, "Sending %zd updates from %d to %d", toSendList.size(), (uint8_t)GetNetworkEntityManager()->GetHostId(), (uint8_t)GetRemoteHostId()); - + // prep a replication record for send, at this point, everything needs to be sent for (EntityReplicator* replicator : toSendList) { replicator->GetPropertyPublisher()->PrepareSerialization(); } - + // While our to send list is not empty, build up another packet to send do { @@ -524,7 +538,7 @@ namespace Multiplayer bool EntityReplicationManager::HandlePropertyChangeMessage ( - AzNetworking::IConnection* invokingConnection, + AzNetworking::IConnection* invokingConnection, EntityReplicator* entityReplicator, AzNetworking::PacketId packetId, NetEntityId netEntityId, @@ -1137,7 +1151,7 @@ namespace Multiplayer AzNetworking::TrackChangedSerializer outputSerializer(message.m_propertyUpdateData.GetBuffer(), static_cast(message.m_propertyUpdateData.GetSize())); if (!HandlePropertyChangeMessage ( - invokingConnection, + invokingConnection, replicator, AzNetworking::InvalidPacketId, message.m_entityId, diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp index 14df1bb028..ad8c883f34 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp @@ -6,23 +6,25 @@ * */ -#include -#include -#include -#include -#include -#include -#include #include #include +#include +#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include #include -#include #include #include @@ -30,6 +32,8 @@ #include +AZ_CVAR(bool, bg_debugHierarchyActivation, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Helpful messages when debugging network hierarchy behavior"); + namespace Multiplayer { EntityReplicator::EntityReplicator @@ -48,7 +52,7 @@ namespace Multiplayer , m_onForwardRpcHandler([this](NetworkEntityRpcMessage& entityRpcMessage) { OnSendRpcEvent(entityRpcMessage); }) , m_onSendAutonomousRpcHandler([this](NetworkEntityRpcMessage& entityRpcMessage) { OnSendRpcEvent(entityRpcMessage); }) , m_onForwardAutonomousRpcHandler([this](NetworkEntityRpcMessage& entityRpcMessage) { OnSendRpcEvent(entityRpcMessage); }) - , m_onEntityStopHandler([this](const ConstNetworkEntityHandle &) { OnEntityRemovedEvent(); }) + , m_onEntityStopHandler([this](const ConstNetworkEntityHandle&) { OnEntityRemovedEvent(); }) , m_proxyRemovalEvent([this] { OnProxyRemovalTimedEvent(); }, AZ::Name("ProxyRemovalTimedEvent")) { if (auto localEnt = m_entityHandle.GetEntity()) @@ -119,12 +123,12 @@ namespace Multiplayer { m_replicationManager.AddReplicatorToPendingSend(*this); m_propertyPublisher = AZStd::make_unique - ( - GetRemoteNetworkRole(), - !RemoteManagerOwnsEntityLifetime() ? PropertyPublisher::OwnsLifetime::True : PropertyPublisher::OwnsLifetime::False, - m_netBindComponent, - *m_connection - ); + ( + GetRemoteNetworkRole(), + !RemoteManagerOwnsEntityLifetime() ? PropertyPublisher::OwnsLifetime::True : PropertyPublisher::OwnsLifetime::False, + m_netBindComponent, + *m_connection + ); m_netBindComponent->AddEntityDirtiedEventHandler(m_onEntityDirtiedHandler); } else @@ -279,7 +283,7 @@ namespace Multiplayer AZ_Assert(netBindComponent, "No Multiplayer::NetBindComponent"); bool isAuthority = (GetBoundLocalNetworkRole() == NetEntityRole::Authority) - && (GetBoundLocalNetworkRole() == netBindComponent->GetNetEntityRole()); + && (GetBoundLocalNetworkRole() == netBindComponent->GetNetEntityRole()); bool isClient = GetRemoteNetworkRole() == NetEntityRole::Client; bool isAutonomous = GetBoundLocalNetworkRole() == NetEntityRole::Autonomous; if (isAuthority || isClient || isAutonomous) @@ -306,9 +310,9 @@ namespace Multiplayer bool EntityReplicator::RemoteManagerOwnsEntityLifetime() const { bool isServer = (GetBoundLocalNetworkRole() == NetEntityRole::Server) - && (GetRemoteNetworkRole() == NetEntityRole::Authority); + && (GetRemoteNetworkRole() == NetEntityRole::Authority); bool isClient = (GetBoundLocalNetworkRole() == NetEntityRole::Client) - || (GetBoundLocalNetworkRole() == NetEntityRole::Autonomous); + || (GetBoundLocalNetworkRole() == NetEntityRole::Autonomous); return isServer || isClient; } @@ -405,6 +409,62 @@ namespace Multiplayer return m_replicationManager.GetResendTimeoutTimeMs(); } + bool EntityReplicator::IsReadyToActivate() const + { + const AZ::Entity* entity = m_entityHandle.GetEntity(); + AZ_Assert(entity, "Entity replicator entity unexpectedly missing"); + + const NetworkHierarchyChildComponent* hierarchyChildComponent = entity->FindComponent(); + const NetworkHierarchyRootComponent* hierarchyRootComponent = nullptr; + + if (hierarchyChildComponent == nullptr) + { + // child and root hierarchy components are mutually exclusive + hierarchyRootComponent = entity->FindComponent(); + } + + if ((hierarchyChildComponent && hierarchyChildComponent->IsHierarchicalChild()) + || (hierarchyRootComponent && hierarchyRootComponent->IsHierarchicalChild())) + { + // if hierarchy is enabled for the entity, check if the parent is available + if (const NetworkTransformComponent* networkTransform = entity->FindComponent()) + { + const NetEntityId parentId = networkTransform->GetParentEntityId(); + /* + * For root entities attached to a level, a network parent won't be set. + * In this case, this entity is the root entity of the hierarchy and it will be activated first. + */ + if (parentId != InvalidNetEntityId) + { + ConstNetworkEntityHandle parentHandle = GetNetworkEntityManager()->GetEntity(parentId); + + const AZ::Entity* parentEntity = parentHandle.GetEntity(); + if (parentEntity && parentEntity->GetState() == AZ::Entity::State::Active) + { + if (bg_debugHierarchyActivation) + { + AZLOG_DEBUG( + "Entity %s asking for activation - granted", + entity->GetName().c_str()); + } + return true; + } + + if (bg_debugHierarchyActivation) + { + AZLOG_DEBUG( + "Entity %s asking for activation - waiting on the parent %u", + entity->GetName().c_str(), + aznumeric_cast(parentId)); + } + return false; + } + } + } + + return true; + } + NetworkEntityUpdateMessage EntityReplicator::GenerateUpdatePacket() { if (IsMarkedForRemoval() && OwnsReplicatorLifetime()) // TODO: clean this up diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.h b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.h index ec4bd8c4f5..e4dc62bc26 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.h @@ -36,7 +36,7 @@ namespace Multiplayer { public: EntityReplicator(EntityReplicationManager& replicationManager, AzNetworking::IConnection* connection, NetEntityRole remoteNetworkRole, const ConstNetworkEntityHandle& entityHandle); - virtual ~EntityReplicator(); + ~EntityReplicator() override; NetEntityRole GetBoundLocalNetworkRole() const; NetEntityRole GetRemoteNetworkRole() const; @@ -62,6 +62,8 @@ namespace Multiplayer bool IsDeletionAcknowledged() const; bool WasMigrated() const; void SetWasMigrated(bool wasMigrated); + // If an entity is part of a network hierarchy then it is only ready to activate when its direct parent entity is active. + bool IsReadyToActivate() const; NetworkEntityUpdateMessage GenerateUpdatePacket(); diff --git a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp new file mode 100644 index 0000000000..d1b01a279c --- /dev/null +++ b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp @@ -0,0 +1,379 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Multiplayer +{ + using namespace testing; + using namespace ::UnitTest; + + /* + * Test NetBindComponent activation. This must work before more complicated tests. + */ + TEST_F(HierarchyTests, On_Client_NetBindComponent_Activate) + { + AZ::Entity entity; + entity.CreateComponent(); + SetupEntity(entity, NetEntityId{ 1 }, NetEntityRole::Client); + entity.Activate(); + + StopEntity(entity); + + entity.Deactivate(); + } + + /* + * Hierarchy test - a child entity on a client delaying activation until its hierarchical parent has been activated + */ + TEST_F(HierarchyTests, On_Client_EntityReplicator_DontActivate_BeforeParent) + { + // Create a child entity that will be tested for activation inside a hierarchy + AZ::Entity childEntity; + CreateEntityWithChildHierarchy(childEntity); + SetupEntity(childEntity, NetEntityId{ 2 }, NetEntityRole::Client); + // child entity is not activated on purpose here, we are about to test conditional activation check + + // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + SetParentIdOnNetworkTransform(childEntity, NetEntityId{ 1 }); + SetHierarchyRootFieldOnNetworkHierarchyChild(childEntity, NetEntityId{ 1 }); + + // Create an entity replicator for the child entity + const NetworkEntityHandle childHandle(&childEntity, m_networkEntityTracker.get()); + EntityReplicator entityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childHandle); + entityReplicator.Initialize(childHandle); + + // Entity replicator should not be ready to activate the entity because its parent does not exist + EXPECT_EQ(entityReplicator.IsReadyToActivate(), false); + } + + TEST_F(HierarchyTests, On_Client_EntityReplicator_DontActivate_Inner_Root_Before_Top_Root) + { + // Create a child entity that will be tested for activation inside a hierarchy + AZ::Entity innerRootEntity; + CreateEntityWithRootHierarchy(innerRootEntity); + SetupEntity(innerRootEntity, NetEntityId{ 2 }, NetEntityRole::Client); + // child entity is not activated on purpose here, we are about to test conditional activation check + + // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + SetParentIdOnNetworkTransform(innerRootEntity, NetEntityId{ 1 }); + SetHierarchyRootFieldOnNetworkHierarchyChild(innerRootEntity, NetEntityId{ 1 }); + + // Create an entity replicator for the child entity + const NetworkEntityHandle innerRootHandle(&innerRootEntity, m_networkEntityTracker.get()); + EntityReplicator entityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, innerRootHandle); + entityReplicator.Initialize(innerRootHandle); + + // Entity replicator should not be ready to activate the entity because its parent does not exist + EXPECT_EQ(entityReplicator.IsReadyToActivate(), false); + } + + TEST_F(HierarchyTests, On_Client_Not_In_Hierarchy_EntityReplicator_Ignores_Parent) + { + // Create a child entity that will be tested for activation inside a hierarchy + AZ::Entity childEntity; + CreateEntityWithChildHierarchy(childEntity); + SetupEntity(childEntity, NetEntityId{ 2 }, NetEntityRole::Client); + // child entity is not activated on purpose here, we are about to test conditional activation check + + // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + SetParentIdOnNetworkTransform(childEntity, NetEntityId{ 1 }); + SetHierarchyRootFieldOnNetworkHierarchyChild(childEntity, InvalidNetEntityId); + + // Create an entity replicator for the child entity + const NetworkEntityHandle childHandle(&childEntity, m_networkEntityTracker.get()); + EntityReplicator entityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childHandle); + entityReplicator.Initialize(childHandle); + + // Entity replicator should not be ready to activate the entity because its parent does not exist + EXPECT_EQ(entityReplicator.IsReadyToActivate(), true); + } + + /* + * Hierarchy test - a child entity on a client allowing activation when its hierarchical parent is active + */ + TEST_F(HierarchyTests, On_Client_EntityReplicator_Activates_AfterParent) + { + AZ::Entity childEntity; + CreateEntityWithChildHierarchy(childEntity); + SetupEntity(childEntity, NetEntityId{ 2 }, NetEntityRole::Client); + + // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + SetParentIdOnNetworkTransform(childEntity, NetEntityId{ 1 }); + SetHierarchyRootFieldOnNetworkHierarchyChild(childEntity, NetEntityId{ 1 }); + + // Create an entity replicator for the child entity + const NetworkEntityHandle childHandle(&childEntity, m_networkEntityTracker.get()); + EntityReplicator childEntityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childHandle); + childEntityReplicator.Initialize(childHandle); + + // Now let's create a parent entity and activate it + AZ::Entity parentEntity; + CreateEntityWithRootHierarchy(parentEntity); + SetupEntity(parentEntity, NetEntityId{ 1 }, NetEntityRole::Client); + + // Create an entity replicator for the parent entity + const NetworkEntityHandle parentHandle(&parentEntity, m_networkEntityTracker.get()); + ON_CALL(*m_mockNetworkEntityManager, GetEntity(_)).WillByDefault(Return(parentHandle)); + EntityReplicator parentEntityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, parentHandle); + parentEntityReplicator.Initialize(parentHandle); + + parentEntity.Activate(); + + // The child should be ready to be activated + EXPECT_EQ(childEntityReplicator.IsReadyToActivate(), true); + + StopEntity(parentEntity); + + parentEntity.Deactivate(); + } + + /* + * Parent -> Child + */ + class ClientSimpleHierarchyTests : public HierarchyTests + { + public: + static const NetEntityId RootNetEntityId = NetEntityId{ 1 }; + static const NetEntityId ChildNetEntityId = NetEntityId{ 2 }; + + void SetUp() override + { + HierarchyTests::SetUp(); + + m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); + m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); + + m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), RootNetEntityId, EntityInfo::Role::Root); + m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), ChildNetEntityId, EntityInfo::Role::Child); + + CreateSimpleHierarchy(*m_rootEntityInfo, *m_childEntityInfo); + + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + // now the two entities are under one hierarchy + } + + void TearDown() override + { + m_childEntityInfo.reset(); + m_rootEntityInfo.reset(); + + StopAndDeleteEntity(m_childEntity); + StopAndDeleteEntity(m_rootEntity); + + HierarchyTests::TearDown(); + } + + void CreateSimpleHierarchy(EntityInfo& root, EntityInfo& child) + { + PopulateHierarchicalEntity(root); + SetupEntity(root.m_entity, root.m_netId, NetEntityRole::Client); + + PopulateHierarchicalEntity(child); + SetupEntity(child.m_entity, child.m_netId, NetEntityRole::Client); + + // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + SetParentIdOnNetworkTransform(child.m_entity, root.m_netId); + SetHierarchyRootFieldOnNetworkHierarchyChild(child.m_entity, root.m_netId); + + // Create an entity replicator for the child entity + const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); + child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childHandle); + child.m_replicator->Initialize(childHandle); + + // Create an entity replicator for the root entity + const NetworkEntityHandle rootHandle(&root.m_entity, m_networkEntityTracker.get()); + root.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, rootHandle); + root.m_replicator->Initialize(rootHandle); + + root.m_entity.Activate(); + child.m_entity.Activate(); + } + + void SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(const AZ::Entity& entity, NetEntityId value) + { + /* Derived from NetworkHierarchyChildComponent.AutoComponent.xml */ + constexpr int totalBits = 1 /*NetworkHierarchyChildComponentInternal::AuthorityToClientDirtyEnum::Count*/; + constexpr int inHierarchyBit = 0 /*NetworkHierarchyChildComponentInternal::AuthorityToClientDirtyEnum::hierarchyRoot_DirtyFlag*/; + + ReplicationRecord currentRecord(NetEntityRole::Client); + currentRecord.m_authorityToClient.AddBits(totalBits); + currentRecord.m_authorityToClient.SetBit(inHierarchyBit, true); + + constexpr uint32_t bufferSize = 100; + AZStd::array buffer = {}; + NetworkInputSerializer inSerializer(buffer.begin(), bufferSize); + inSerializer.Serialize(reinterpret_cast(value), + "hierarchyRoot", /* Derived from NetworkHierarchyChildComponent.AutoComponent.xml */ + AZStd::numeric_limits::min(), AZStd::numeric_limits::max()); + + NetworkOutputSerializer outSerializer(buffer.begin(), bufferSize); + + ReplicationRecord notifyRecord = currentRecord; + + entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); + + entity.FindComponent()->NotifyStateDeltaChanges(notifyRecord); + } + + AZStd::unique_ptr m_rootEntity; + AZStd::unique_ptr m_childEntity; + + AZStd::unique_ptr m_rootEntityInfo; + AZStd::unique_ptr m_childEntityInfo; + }; + + TEST_F(ClientSimpleHierarchyTests, Client_Activates_Hierarchy_From_Network_Fields) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchicalRoot(), + m_rootEntity.get() + ); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 2) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], + m_rootEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], + m_childEntity.get() + ); + } + } + + TEST_F(ClientSimpleHierarchyTests, Client_Detaches_Child_When_Server_Detaches) + { + // simulate server detaching child entity + SetParentIdOnNetworkTransform(*m_childEntity, InvalidNetEntityId); + SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(*m_childEntity, InvalidNetEntityId); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchicalRoot(), + nullptr + ); + } + + /* + * Parent -> Child + */ + class ClientDeepHierarchyTests : public ClientSimpleHierarchyTests + { + public: + static const NetEntityId ChildOfChildNetEntityId = NetEntityId{ 3 }; + + void SetUp() override + { + ClientSimpleHierarchyTests::SetUp(); + + m_childOfChildEntity = AZStd::make_unique(AZ::EntityId(3), "child of child"); + m_childOfChildEntityInfo = AZStd::make_unique(*m_childOfChildEntity.get(), ChildOfChildNetEntityId, EntityInfo::Role::Child); + + CreateDeepHierarchyOnClient(*m_childOfChildEntityInfo); + + m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + } + + void TearDown() override + { + m_childOfChildEntityInfo.reset(); + StopAndDeleteEntity(m_childOfChildEntity); + + ClientSimpleHierarchyTests::TearDown(); + } + + void CreateDeepHierarchyOnClient(EntityInfo& childOfChild) + { + PopulateHierarchicalEntity(childOfChild); + SetupEntity(childOfChild.m_entity, childOfChild.m_netId, NetEntityRole::Client); + + // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + SetParentIdOnNetworkTransform(childOfChild.m_entity, m_childEntityInfo->m_netId); + SetHierarchyRootFieldOnNetworkHierarchyChild(childOfChild.m_entity, m_rootEntityInfo->m_netId); + + // Create an entity replicator for the child entity + const NetworkEntityHandle childOfChildHandle(&childOfChild.m_entity, m_networkEntityTracker.get()); + childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childOfChildHandle); + childOfChild.m_replicator->Initialize(childOfChildHandle); + + childOfChild.m_entity.Activate(); + } + + AZStd::unique_ptr m_childOfChildEntity; + AZStd::unique_ptr m_childOfChildEntityInfo; + }; + + TEST_F(ClientDeepHierarchyTests, Client_Activates_Hierarchy_From_Network_Fields) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + EXPECT_EQ( + m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchicalRoot(), + m_rootEntity.get() + ); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 3) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], + m_rootEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], + m_childEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChildEntity.get() + ); + } + } +} diff --git a/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h b/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h new file mode 100644 index 0000000000..89d0d32428 --- /dev/null +++ b/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h @@ -0,0 +1,387 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Multiplayer +{ + using namespace testing; + using namespace ::UnitTest; + + class HierarchyTests + : public AllocatorsFixture + { + public: + void SetUp() override + { + SetupAllocator(); + AZ::NameDictionary::Create(); + + m_mockComponentApplicationRequests = AZStd::make_unique>(); + AZ::Interface::Register(m_mockComponentApplicationRequests.get()); + + ON_CALL(*m_mockComponentApplicationRequests, AddEntity(_)).WillByDefault(Invoke(this, &HierarchyTests::AddEntity)); + ON_CALL(*m_mockComponentApplicationRequests, FindEntity(_)).WillByDefault(Invoke(this, &HierarchyTests::FindEntity)); + + // register components involved in testing + m_serializeContext = AZStd::make_unique(); + + m_transformDescriptor.reset(AzFramework::TransformComponent::CreateDescriptor()); + m_transformDescriptor->Reflect(m_serializeContext.get()); + + m_netBindDescriptor.reset(NetBindComponent::CreateDescriptor()); + m_netBindDescriptor->Reflect(m_serializeContext.get()); + + m_hierarchyRootDescriptor.reset(NetworkHierarchyRootComponent::CreateDescriptor()); + m_hierarchyRootDescriptor->Reflect(m_serializeContext.get()); + + m_hierarchyChildDescriptor.reset(NetworkHierarchyChildComponent::CreateDescriptor()); + m_hierarchyChildDescriptor->Reflect(m_serializeContext.get()); + + m_netTransformDescriptor.reset(NetworkTransformComponent::CreateDescriptor()); + m_netTransformDescriptor->Reflect(m_serializeContext.get()); + + m_mockMultiplayer = AZStd::make_unique>(); + AZ::Interface::Register(m_mockMultiplayer.get()); + + EXPECT_NE(AZ::Interface::Get(), nullptr); + + // Create space for replication stats + // Without Multiplayer::RegisterMultiplayerComponents() the stats go to invalid id, which is fine for unit tests + GetMultiplayer()->GetStats().ReserveComponentStats(Multiplayer::InvalidNetComponentId, 50, 0); + + m_mockNetworkEntityManager = AZStd::make_unique>(); + + ON_CALL(*m_mockNetworkEntityManager, AddEntityToEntityMap(_, _)).WillByDefault(Invoke(this, &HierarchyTests::AddEntityToEntityMap)); + ON_CALL(*m_mockNetworkEntityManager, GetEntity(_)).WillByDefault(Invoke(this, &HierarchyTests::GetEntity)); + ON_CALL(*m_mockNetworkEntityManager, GetNetEntityIdById(_)).WillByDefault(Invoke(this, &HierarchyTests::GetNetEntityIdById)); + + m_mockTime = AZStd::make_unique>(); + AZ::Interface::Register(m_mockTime.get()); + + m_mockNetworkTime = AZStd::make_unique>(); + AZ::Interface::Register(m_mockNetworkTime.get()); + + ON_CALL(*m_mockMultiplayer, GetNetworkEntityManager()).WillByDefault(Return(m_mockNetworkEntityManager.get())); + EXPECT_NE(AZ::Interface::Get()->GetNetworkEntityManager(), nullptr); + + const IpAddress address("localhost", 1, ProtocolType::Udp); + m_mockConnection = AZStd::make_unique>(ConnectionId{ 1 }, address, ConnectionRole::Connector); + m_mockConnectionListener = AZStd::make_unique(); + + m_networkEntityTracker = AZStd::make_unique(); + ON_CALL(*m_mockNetworkEntityManager, GetNetworkEntityTracker()).WillByDefault(Return(m_networkEntityTracker.get())); + + m_networkEntityAuthorityTracker = AZStd::make_unique(*m_mockNetworkEntityManager); + ON_CALL(*m_mockNetworkEntityManager, GetNetworkEntityAuthorityTracker()).WillByDefault(Return(m_networkEntityAuthorityTracker.get())); + + m_entityReplicationManager = AZStd::make_unique(*m_mockConnection, *m_mockConnectionListener, EntityReplicationManager::Mode::LocalClientToRemoteServer); + + m_console.reset(aznew AZ::Console()); + AZ::Interface::Register(m_console.get()); + m_console->LinkDeferredFunctors(AZ::ConsoleFunctorBase::GetDeferredHead()); + + m_multiplayerComponentRegistry = AZStd::make_unique(); + ON_CALL(*m_mockNetworkEntityManager, GetMultiplayerComponentRegistry()).WillByDefault(Return(m_multiplayerComponentRegistry.get())); + RegisterMultiplayerComponents(); + } + + void TearDown() override + { + m_multiplayerComponentRegistry.reset(); + + AZ::Interface::Unregister(m_console.get()); + m_console.reset(); + + m_networkEntityMap.clear(); + m_entities.clear(); + + m_entityReplicationManager.reset(); + + m_mockConnection.reset(); + m_mockConnectionListener.reset(); + m_networkEntityTracker.reset(); + m_networkEntityAuthorityTracker.reset(); + + AZ::Interface::Unregister(m_mockNetworkTime.get()); + AZ::Interface::Unregister(m_mockTime.get()); + AZ::Interface::Unregister(m_mockMultiplayer.get()); + AZ::Interface::Unregister(m_mockComponentApplicationRequests.get()); + + m_mockTime.reset(); + + m_mockNetworkEntityManager.reset(); + m_mockMultiplayer.reset(); + + m_transformDescriptor.reset(); + m_netTransformDescriptor.reset(); + m_hierarchyRootDescriptor.reset(); + m_hierarchyChildDescriptor.reset(); + m_netBindDescriptor.reset(); + m_serializeContext.reset(); + m_mockComponentApplicationRequests.reset(); + + AZ::NameDictionary::Destroy(); + TeardownAllocator(); + } + + AZStd::unique_ptr m_console; + + AZStd::unique_ptr> m_mockComponentApplicationRequests; + AZStd::unique_ptr m_serializeContext; + AZStd::unique_ptr m_transformDescriptor; + AZStd::unique_ptr m_netBindDescriptor; + AZStd::unique_ptr m_hierarchyRootDescriptor; + AZStd::unique_ptr m_hierarchyChildDescriptor; + AZStd::unique_ptr m_netTransformDescriptor; + + AZStd::unique_ptr> m_mockMultiplayer; + AZStd::unique_ptr m_mockNetworkEntityManager; + AZStd::unique_ptr> m_mockTime; + AZStd::unique_ptr> m_mockNetworkTime; + + AZStd::unique_ptr> m_mockConnection; + AZStd::unique_ptr m_mockConnectionListener; + AZStd::unique_ptr m_networkEntityTracker; + AZStd::unique_ptr m_networkEntityAuthorityTracker; + + AZStd::unique_ptr m_entityReplicationManager; + + AZStd::unique_ptr m_multiplayerComponentRegistry;; + + mutable AZStd::map m_networkEntityMap; + + NetworkEntityHandle AddEntityToEntityMap(NetEntityId netEntityId, AZ::Entity* entity) + { + m_networkEntityMap[netEntityId] = entity; + return NetworkEntityHandle(entity, netEntityId, m_networkEntityTracker.get()); + } + + ConstNetworkEntityHandle GetEntity(NetEntityId netEntityId) const + { + AZ::Entity* entity = m_networkEntityMap[netEntityId]; + return ConstNetworkEntityHandle(entity, m_networkEntityTracker.get()); + } + + NetEntityId GetNetEntityIdById(const AZ::EntityId& entityId) const + { + for (const auto& pair : m_networkEntityMap) + { + if (pair.second->GetId() == entityId) + { + return pair.first; + } + } + + return InvalidNetEntityId; + } + + AZStd::map m_entities; + + bool AddEntity(AZ::Entity* entity) + { + m_entities[entity->GetId()] = entity; + return true; + } + + AZ::Entity* FindEntity(AZ::EntityId entityId) + { + const auto iterator = m_entities.find(entityId); + if (iterator != m_entities.end()) + { + return iterator->second; + } + + return nullptr; + } + + void SetupEntity(AZ::Entity& entity, NetEntityId netId, NetEntityRole role) + { + const auto netBindComponent = entity.FindComponent(); + EXPECT_NE(netBindComponent, nullptr); + netBindComponent->PreInit(&entity, PrefabEntityId{ AZ::Name("test"), 1 }, netId, role); + entity.Init(); + } + + void StopEntity(const AZ::Entity& entity) + { + const auto netBindComponent = entity.FindComponent(); + EXPECT_NE(netBindComponent, nullptr); + netBindComponent->StopEntity(); + } + + void StopAndDeleteEntity(AZStd::unique_ptr& entity) + { + if (entity) + { + StopEntity(*entity); + entity->Deactivate(); + entity.reset(); + } + } + + void CreateEntityWithRootHierarchy(AZ::Entity& rootEntity) + { + rootEntity.CreateComponent(); + rootEntity.CreateComponent(); + rootEntity.CreateComponent(); + rootEntity.CreateComponent(); + } + + void CreateEntityWithChildHierarchy(AZ::Entity& childEntity) + { + childEntity.CreateComponent(); + childEntity.CreateComponent(); + childEntity.CreateComponent(); + childEntity.CreateComponent(); + } + + void SetParentIdOnNetworkTransform(const AZ::Entity& entity, NetEntityId netParentId) + { + /* Derived from NetworkTransformComponent.AutoComponent.xml */ + constexpr int totalBits = 6 /*NetworkTransformComponentInternal::AuthorityToClientDirtyEnum::Count*/; + constexpr int parentIdBit = 4 /*NetworkTransformComponentInternal::AuthorityToClientDirtyEnum::parentEntityId_DirtyFlag*/; + + ReplicationRecord currentRecord; + currentRecord.m_authorityToClient.AddBits(totalBits); + currentRecord.m_authorityToClient.SetBit(parentIdBit, true); + + constexpr uint32_t bufferSize = 100; + AZStd::array buffer = {}; + NetworkInputSerializer inSerializer(buffer.begin(), bufferSize); + inSerializer.Serialize(reinterpret_cast(netParentId), + "parentEntityId", /* Derived from NetworkTransformComponent.AutoComponent.xml */ + AZStd::numeric_limits::min(), AZStd::numeric_limits::max()); + + NetworkOutputSerializer outSerializer(buffer.begin(), bufferSize); + + entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); + // now the parent id is in the component + } + + template + void SetHierarchyRootFieldOnNetworkHierarchyChild(const AZ::Entity& entity, NetEntityId value) + { + /* Derived from NetworkHierarchyChildComponent.AutoComponent.xml */ + constexpr int totalBits = 1 /*NetworkHierarchyChildComponentInternal::AuthorityToClientDirtyEnum::Count*/; + constexpr int inHierarchyBit = 0 /*NetworkHierarchyChildComponentInternal::AuthorityToClientDirtyEnum::hierarchyRoot_DirtyFlag*/; + + ReplicationRecord currentRecord; + currentRecord.m_authorityToClient.AddBits(totalBits); + currentRecord.m_authorityToClient.SetBit(inHierarchyBit, true); + + constexpr uint32_t bufferSize = 100; + AZStd::array buffer = {}; + NetworkInputSerializer inSerializer(buffer.begin(), bufferSize); + inSerializer.Serialize(reinterpret_cast(value), + "hierarchyRoot", /* Derived from NetworkHierarchyChildComponent.AutoComponent.xml */ + AZStd::numeric_limits::min(), AZStd::numeric_limits::max()); + + NetworkOutputSerializer outSerializer(buffer.begin(), bufferSize); + + entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); + // now the parent id is in the component + } + + struct EntityInfo + { + enum class Role + { + Root, + Child, + None + }; + + EntityInfo(AZ::Entity& entity, NetEntityId netId, Role role) + : m_entity(entity) + , m_netId(netId) + , m_role(role) + { + } + + AZ::Entity& m_entity; + NetEntityId m_netId; + AZStd::unique_ptr m_replicator; + Role m_role = Role::None; + }; + + void PopulateHierarchicalEntity(const EntityInfo& entityInfo) + { + entityInfo.m_entity.CreateComponent(); + entityInfo.m_entity.CreateComponent(); + entityInfo.m_entity.CreateComponent(); + switch (entityInfo.m_role) + { + case EntityInfo::Role::Root: + entityInfo.m_entity.CreateComponent(); + break; + case EntityInfo::Role::Child: + entityInfo.m_entity.CreateComponent(); + break; + case EntityInfo::Role::None: + break; + } + } + + void CreateDeepHierarchy(EntityInfo& root, EntityInfo& child, EntityInfo& childOfChild) + { + PopulateHierarchicalEntity(root); + PopulateHierarchicalEntity(child); + PopulateHierarchicalEntity(childOfChild); + + SetupEntity(root.m_entity, root.m_netId, NetEntityRole::Authority); + SetupEntity(child.m_entity, child.m_netId, NetEntityRole::Authority); + SetupEntity(childOfChild.m_entity, childOfChild.m_netId, NetEntityRole::Authority); + + // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + SetParentIdOnNetworkTransform(child.m_entity, root.m_netId); + SetParentIdOnNetworkTransform(childOfChild.m_entity, child.m_netId); + + // Create an entity replicator for the child entity + const NetworkEntityHandle childOfChildHandle(&childOfChild.m_entity, m_networkEntityTracker.get()); + childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childOfChildHandle); + childOfChild.m_replicator->Initialize(childOfChildHandle); + + // Create an entity replicator for the child entity + const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); + child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childHandle); + child.m_replicator->Initialize(childHandle); + + // Create an entity replicator for the root entity + const NetworkEntityHandle rootHandle(&root.m_entity, m_networkEntityTracker.get()); + root.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, rootHandle); + root.m_replicator->Initialize(rootHandle); + + root.m_entity.Activate(); + child.m_entity.Activate(); + childOfChild.m_entity.Activate(); + } + }; +} diff --git a/Gems/Multiplayer/Code/Tests/MockInterfaces.h b/Gems/Multiplayer/Code/Tests/MockInterfaces.h new file mode 100644 index 0000000000..375fe2c5ba --- /dev/null +++ b/Gems/Multiplayer/Code/Tests/MockInterfaces.h @@ -0,0 +1,166 @@ +/* + * 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 +#include +#include +#include +#include +#include + +namespace UnitTest +{ + class MockMultiplayer : public Multiplayer::IMultiplayer + { + public: + MOCK_CONST_METHOD0(GetCurrentBlendFactor, float ()); + MOCK_CONST_METHOD0(GetAgentType, Multiplayer::MultiplayerAgentType()); + MOCK_METHOD1(InitializeMultiplayer, void(Multiplayer::MultiplayerAgentType)); + MOCK_METHOD2(StartHosting, bool(uint16_t, bool)); + MOCK_METHOD2(Connect, bool(AZStd::string, uint16_t)); + MOCK_METHOD1(Terminate, void(AzNetworking::DisconnectReason)); + MOCK_METHOD1(AddClientDisconnectedHandler, void(AZ::Event<>::Handler&)); + MOCK_METHOD1(AddConnectionAcquiredHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(AddSessionInitHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(AddSessionShutdownHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(SendReadyForEntityUpdates, void(bool)); + MOCK_CONST_METHOD0(GetCurrentHostTimeMs, AZ::TimeMs()); + MOCK_METHOD0(GetNetworkTime, Multiplayer::INetworkTime* ()); + MOCK_METHOD0(GetNetworkEntityManager, Multiplayer::INetworkEntityManager* ()); + MOCK_METHOD1(SetFilterEntityManager, void(Multiplayer::IFilterEntityManager*)); + MOCK_METHOD0(GetFilterEntityManager, Multiplayer::IFilterEntityManager* ()); + }; + + class MockNetworkEntityManager : public Multiplayer::INetworkEntityManager + { + public: + MOCK_METHOD4(CreateEntitiesImmediate, EntityList (const Multiplayer::PrefabEntityId&, Multiplayer::NetEntityRole, const AZ::Transform&, Multiplayer::AutoActivate)); + MOCK_CONST_METHOD1(GetNetEntityIdById, Multiplayer::NetEntityId (const AZ::EntityId&)); + MOCK_METHOD0(GetNetworkEntityTracker, Multiplayer::NetworkEntityTracker* ()); + MOCK_METHOD0(GetNetworkEntityAuthorityTracker, Multiplayer::NetworkEntityAuthorityTracker* ()); + MOCK_METHOD0(GetMultiplayerComponentRegistry, Multiplayer::MultiplayerComponentRegistry* ()); + MOCK_CONST_METHOD0(GetHostId, Multiplayer::HostId()); + MOCK_METHOD3(CreateEntitiesImmediate, EntityList(const Multiplayer::PrefabEntityId&, Multiplayer::NetEntityRole, const AZ:: + Transform&)); + MOCK_METHOD5(CreateEntitiesImmediate, EntityList(const Multiplayer::PrefabEntityId&, Multiplayer::NetEntityId, Multiplayer:: + NetEntityRole, Multiplayer::AutoActivate, const AZ::Transform&)); + MOCK_METHOD3(SetupNetEntity, void(AZ::Entity*, Multiplayer::PrefabEntityId, Multiplayer::NetEntityRole)); + MOCK_CONST_METHOD1(GetEntity, Multiplayer::ConstNetworkEntityHandle(Multiplayer::NetEntityId)); + MOCK_CONST_METHOD0(GetEntityCount, uint32_t()); + MOCK_METHOD2(AddEntityToEntityMap, Multiplayer::NetworkEntityHandle(Multiplayer::NetEntityId, AZ::Entity*)); + MOCK_METHOD1(MarkForRemoval, void(const Multiplayer::ConstNetworkEntityHandle&)); + MOCK_CONST_METHOD1(IsMarkedForRemoval, bool(const Multiplayer::ConstNetworkEntityHandle&)); + MOCK_METHOD1(ClearEntityFromRemovalList, void(const Multiplayer::ConstNetworkEntityHandle&)); + MOCK_METHOD0(ClearAllEntities, void()); + MOCK_METHOD1(AddEntityMarkedDirtyHandler, void(AZ::Event<>::Handler&)); + MOCK_METHOD1(AddEntityNotifyChangesHandler, void(AZ::Event<>::Handler&)); + MOCK_METHOD1(AddEntityExitDomainHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(AddControllersActivatedHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(AddControllersDeactivatedHandler, void(AZ::Event::Handler&)); + MOCK_METHOD0(NotifyEntitiesDirtied, void()); + MOCK_METHOD0(NotifyEntitiesChanged, void()); + MOCK_METHOD2(NotifyControllersActivated, void(const Multiplayer::ConstNetworkEntityHandle&, Multiplayer::EntityIsMigrating)); + MOCK_METHOD2(NotifyControllersDeactivated, void(const Multiplayer::ConstNetworkEntityHandle&, Multiplayer::EntityIsMigrating)); + MOCK_METHOD1(HandleLocalRpcMessage, void(Multiplayer::NetworkEntityRpcMessage&)); + }; + + class MockConnectionListener : public AzNetworking::IConnectionListener + { + public: + MOCK_METHOD3(ValidateConnect, ConnectResult(const IpAddress&, const IPacketHeader&, ISerializer&)); + MOCK_METHOD1(OnConnect, void(IConnection*)); + MOCK_METHOD3(OnPacketReceived, PacketDispatchResult (IConnection*, const IPacketHeader&, ISerializer&)); + MOCK_METHOD2(OnPacketLost, void(IConnection*, PacketId)); + MOCK_METHOD3(OnDisconnect, void(IConnection*, DisconnectReason, TerminationEndpoint)); + }; + + class MockTime : public AZ::ITime + { + public: + MOCK_CONST_METHOD0(GetElapsedTimeMs, AZ::TimeMs()); + }; + + class MockNetworkTime : public Multiplayer::INetworkTime + { + public: + MOCK_METHOD2(ForceSetTime, void (Multiplayer::HostFrameId, AZ::TimeMs)); + MOCK_CONST_METHOD0(GetHostBlendFactor, float ()); + MOCK_METHOD1(AlterBlendFactor, void (float)); + MOCK_CONST_METHOD0(IsTimeRewound, bool()); + MOCK_CONST_METHOD0(GetHostFrameId, Multiplayer::HostFrameId()); + MOCK_CONST_METHOD0(GetUnalteredHostFrameId, Multiplayer::HostFrameId()); + MOCK_METHOD0(IncrementHostFrameId, void()); + MOCK_CONST_METHOD0(GetHostTimeMs, AZ::TimeMs()); + MOCK_CONST_METHOD0(GetRewindingConnectionId, AzNetworking::ConnectionId()); + MOCK_CONST_METHOD1(GetHostFrameIdForRewindingConnection, Multiplayer::HostFrameId(AzNetworking::ConnectionId)); + MOCK_METHOD3(AlterTime, void(Multiplayer::HostFrameId, AZ::TimeMs, AzNetworking::ConnectionId)); + MOCK_METHOD1(SyncEntitiesToRewindState, void(const AZ::Aabb&)); + MOCK_METHOD0(ClearRewoundEntities, void()); + }; + + class MockComponentApplicationRequests : public AZ::ComponentApplicationRequests + { + public: + MOCK_METHOD1(RegisterComponentDescriptor, void(const AZ::ComponentDescriptor*)); + MOCK_METHOD1(UnregisterComponentDescriptor, void(const AZ::ComponentDescriptor*)); + MOCK_METHOD0(GetApplication, AZ::ComponentApplication* ()); + MOCK_METHOD1(RegisterEntityAddedEventHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(RegisterEntityRemovedEventHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(RegisterEntityActivatedEventHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(RegisterEntityDeactivatedEventHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(SignalEntityActivated, void(AZ::Entity*)); + MOCK_METHOD1(SignalEntityDeactivated, void(AZ::Entity*)); + MOCK_METHOD1(AddEntity, bool(AZ::Entity*)); + MOCK_METHOD1(RemoveEntity, bool(AZ::Entity*)); + MOCK_METHOD1(DeleteEntity, bool(const AZ::EntityId&)); + MOCK_METHOD1(FindEntity, AZ::Entity* (const AZ::EntityId&)); + MOCK_METHOD1(GetEntityName, AZStd::string(const AZ::EntityId&)); + MOCK_METHOD1(EnumerateEntities, void(const EntityCallback&)); + MOCK_METHOD0(GetSerializeContext, AZ::SerializeContext* ()); + MOCK_METHOD0(GetBehaviorContext, AZ::BehaviorContext* ()); + MOCK_METHOD0(GetJsonRegistrationContext, AZ::JsonRegistrationContext* ()); + MOCK_CONST_METHOD0(GetAppRoot, const char* ()); + MOCK_CONST_METHOD0(GetEngineRoot, const char* ()); + MOCK_CONST_METHOD0(GetExecutableFolder, const char* ()); + MOCK_METHOD0(GetDrillerManager, AZ::Debug::DrillerManager* ()); + MOCK_METHOD1(ResolveModulePath, void(AZ::OSString&)); + MOCK_METHOD0(GetAzCommandLine, AZ::CommandLine* ()); + MOCK_CONST_METHOD1(QueryApplicationType, void(AZ::ApplicationTypeQuery&)); + }; + + class MockSerializer : public ISerializer + { + public: + MOCK_CONST_METHOD0(IsValid, bool ()); + MOCK_CONST_METHOD0(GetSerializerMode, SerializerMode ()); + MOCK_METHOD2(Serialize, bool (bool&, const char*)); + MOCK_METHOD4(Serialize, bool (char&, const char*, char, char)); + MOCK_METHOD4(Serialize, bool (int8_t&, const char*, int8_t, int8_t)); + MOCK_METHOD4(Serialize, bool (int16_t&, const char*, int16_t, int16_t)); + MOCK_METHOD4(Serialize, bool (int32_t&, const char*, int32_t, int32_t)); + MOCK_METHOD4(Serialize, bool (int64_t&, const char*, int64_t, int64_t)); + MOCK_METHOD4(Serialize, bool (uint8_t&, const char*, uint8_t, uint8_t)); + MOCK_METHOD4(Serialize, bool (uint16_t&, const char*, uint16_t, uint16_t)); + MOCK_METHOD4(Serialize, bool (uint32_t&, const char*, uint32_t, uint32_t)); + MOCK_METHOD4(Serialize, bool (uint64_t&, const char*, uint64_t, uint64_t)); + MOCK_METHOD4(Serialize, bool (float&, const char*, float, float)); + MOCK_METHOD4(Serialize, bool (double&, const char*, double, double)); + MOCK_METHOD5(SerializeBytes, bool (uint8_t*, uint32_t, bool, uint32_t&, const char*)); + MOCK_METHOD2(BeginObject, bool (const char*, const char*)); + MOCK_METHOD2(EndObject, bool (const char*, const char*)); + MOCK_CONST_METHOD0(GetBuffer, const uint8_t* ()); + MOCK_CONST_METHOD0(GetCapacity, uint32_t ()); + MOCK_CONST_METHOD0(GetSize, uint32_t ()); + MOCK_METHOD0(ClearTrackedChangesFlag, void ()); + MOCK_CONST_METHOD0(GetTrackedChangesFlag, bool ()); + }; +} + diff --git a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp new file mode 100644 index 0000000000..ae2d8b162d --- /dev/null +++ b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp @@ -0,0 +1,1145 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Multiplayer +{ + using namespace testing; + using namespace ::UnitTest; + + /* + * Parent -> Child + */ + class ServerSimpleHierarchyTests : public HierarchyTests + { + public: + void SetUp() override + { + HierarchyTests::SetUp(); + + m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); + m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); + + m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), NetEntityId{ 1 }, EntityInfo::Role::Root); + m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), NetEntityId{ 2 }, EntityInfo::Role::Child); + + CreateSimpleHierarchy(*m_rootEntityInfo, *m_childEntityInfo); + + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + // now the two entities are under one hierarchy + } + + void TearDown() override + { + m_childEntityInfo.reset(); + m_rootEntityInfo.reset(); + + StopAndDeleteEntity(m_childEntity); + StopAndDeleteEntity(m_rootEntity); + + HierarchyTests::TearDown(); + } + + void CreateSimpleHierarchy(EntityInfo& root, EntityInfo& child) + { + PopulateHierarchicalEntity(root); + SetupEntity(root.m_entity, root.m_netId, NetEntityRole::Authority); + + PopulateHierarchicalEntity(child); + SetupEntity(child.m_entity, child.m_netId, NetEntityRole::Authority); + + //// we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + //SetParentIdOnNetworkTransform(child.m_entity, root.m_netId); + + // Create an entity replicator for the child entity + const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); + child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childHandle); + child.m_replicator->Initialize(childHandle); + + // Create an entity replicator for the root entity + const NetworkEntityHandle rootHandle(&root.m_entity, m_networkEntityTracker.get()); + root.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, rootHandle); + root.m_replicator->Initialize(rootHandle); + + root.m_entity.Activate(); + child.m_entity.Activate(); + } + + AZStd::unique_ptr m_rootEntity; + AZStd::unique_ptr m_childEntity; + + AZStd::unique_ptr m_rootEntityInfo; + AZStd::unique_ptr m_childEntityInfo; + }; + + TEST_F(ServerSimpleHierarchyTests, Server_Sets_Appropriate_Network_Fields_For_Clients) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + NetEntityId{ 1 } + ); + } + + TEST_F(ServerSimpleHierarchyTests, Root_Is_Top_Level_Root) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->IsHierarchicalChild(), + false + ); + } + + TEST_F(ServerSimpleHierarchyTests, Child_Has_Root_Set) + { + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + NetEntityId{ 1 } + ); + } + + TEST_F(ServerSimpleHierarchyTests, Child_Has_Root_Cleared_On_Detach) + { + // now detach the child + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + } + + TEST_F(ServerSimpleHierarchyTests, Root_Has_Child_Reference) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + } + + TEST_F(ServerSimpleHierarchyTests, Root_Has_Child_References_Removed_On_Detach) + { + // now detach the child + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 1 + ); + } + + TEST_F(ServerSimpleHierarchyTests, Root_Deactivates_Child_Has_No_References_To_Root) + { + StopEntity(*m_rootEntity); + m_rootEntity->Deactivate(); + m_rootEntity.reset(); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + } + + TEST_F(ServerSimpleHierarchyTests, Child_Deactivates_Root_Has_No_References_To_Child) + { + StopEntity(*m_childEntity); + m_childEntity->Deactivate(); + m_childEntity.reset(); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 1 + ); + } + + /* + * Parent -> Child -> ChildOfChild + */ + class ServerDeepHierarchyTests : public HierarchyTests + { + public: + static const NetEntityId RootNetEntityId = NetEntityId{ 1 }; + static const NetEntityId ChildNetEntityId = NetEntityId{ 2 }; + static const NetEntityId ChildOfChildNetEntityId = NetEntityId{ 3 }; + + void SetUp() override + { + HierarchyTests::SetUp(); + + m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); + m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); + m_childOfChildEntity = AZStd::make_unique(AZ::EntityId(3), "child of child"); + + m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), RootNetEntityId, EntityInfo::Role::Root); + m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), ChildNetEntityId, EntityInfo::Role::Child); + m_childOfChildEntityInfo = AZStd::make_unique(*m_childOfChildEntity.get(), ChildOfChildNetEntityId, EntityInfo::Role::Child); + + CreateDeepHierarchy(*m_rootEntityInfo, *m_childEntityInfo, *m_childOfChildEntityInfo); + + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + // now the entities are under one hierarchy + } + + void TearDown() override + { + m_childOfChildEntityInfo.reset(); + m_childEntityInfo.reset(); + m_rootEntityInfo.reset(); + + StopAndDeleteEntity(m_childOfChildEntity); + StopAndDeleteEntity(m_childEntity); + StopAndDeleteEntity(m_rootEntity); + + HierarchyTests::TearDown(); + } + + AZStd::unique_ptr m_rootEntity; + AZStd::unique_ptr m_childEntity; + AZStd::unique_ptr m_childOfChildEntity; + + AZStd::unique_ptr m_rootEntityInfo; + AZStd::unique_ptr m_childEntityInfo; + AZStd::unique_ptr m_childOfChildEntityInfo; + }; + + TEST_F(ServerDeepHierarchyTests, Root_Is_Top_Level_Root) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->IsHierarchicalChild(), + false + ); + } + + TEST_F(ServerDeepHierarchyTests, Root_Has_Child_References) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + + if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 3) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], + m_rootEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], + m_childEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChildEntity.get() + ); + } + } + + TEST_F(ServerDeepHierarchyTests, Root_Has_Child_Of_Child_Reference_Removed_On_Detach) + { + m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + } + + TEST_F(ServerDeepHierarchyTests, Root_Has_All_References_Removed_On_Detach_Of_Mid_Child) + { + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 1 + ); + } + + TEST_F(ServerDeepHierarchyTests, Root_Has_All_References_If_Mid_Child_Added_With_Child) + { + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + // reconnect + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerDeepHierarchyTests, Root_Has_All_References_If_Child_Of_Child_Added) + { + m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + // reconnect + m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerDeepHierarchyTests, Child_Of_Child_Points_To_Root_After_Attach) + { + m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + // reconnect + m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + + EXPECT_EQ( + m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + } + + TEST_F(ServerDeepHierarchyTests, All_New_Children_Point_To_Root_If_Mid_Child_Added_With_Child) + { + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + // reconnect + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + EXPECT_EQ( + m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + } + + TEST_F(ServerDeepHierarchyTests, Children_Clear_Reference_To_Root_After_Mid_Child_Detached) + { + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + EXPECT_EQ( + m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + } + + TEST_F(ServerDeepHierarchyTests, Child_Of_Child_Clears_Reference_To_Root_After_Detached) + { + m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + } + + TEST_F(ServerDeepHierarchyTests, Root_Deactivates_Children_Have_No_References_To_Root) + { + StopAndDeleteEntity(m_rootEntity); + + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + + EXPECT_EQ( + m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + InvalidNetEntityId + ); + } + + TEST_F(ServerDeepHierarchyTests, Child_Of_Child_Deactivates_Root_Removes_References_To_It) + { + StopAndDeleteEntity(m_childOfChildEntity); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + } + + TEST_F(ServerDeepHierarchyTests, Testing_Limiting_Hierarchy_Maximum_Size) + { + uint32_t currentMaxLimit = 0; + m_console->GetCvarValue("bg_hierarchyEntityMaxLimit", currentMaxLimit); + m_console->PerformCommand("bg_hierarchyEntityMaxLimit 2"); + + // remake the hierarchy + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + + m_console->PerformCommand((AZStd::string("bg_hierarchyEntityMaxLimit ") + AZStd::to_string(currentMaxLimit)).c_str()); + m_console->GetCvarValue("bg_hierarchyEntityMaxLimit", currentMaxLimit); + } + + /* + * Parent -> Child -> Child Of Child + * -> Child2 -> Child Of Child2 + * -> Child2 Of Child2 + */ + class ServerBranchedHierarchyTests : public HierarchyTests + { + public: + static const NetEntityId RootNetEntityId = NetEntityId{ 1 }; + static const NetEntityId ChildNetEntityId = NetEntityId{ 2 }; + static const NetEntityId ChildOfChildNetEntityId = NetEntityId{ 3 }; + static const NetEntityId Child2NetEntityId = NetEntityId{ 4 }; + static const NetEntityId ChildOfChild2NetEntityId = NetEntityId{ 5 }; + static const NetEntityId Child2OfChild2NetEntityId = NetEntityId{ 6 }; + + void SetUp() override + { + HierarchyTests::SetUp(); + + m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); + m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); + m_childOfChildEntity = AZStd::make_unique(AZ::EntityId(3), "child of child"); + m_child2Entity = AZStd::make_unique(AZ::EntityId(4), "child2"); + m_childOfChild2Entity = AZStd::make_unique(AZ::EntityId(5), "child of child2"); + m_child2OfChild2Entity = AZStd::make_unique(AZ::EntityId(6), "child2 of child2"); + + m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), RootNetEntityId, EntityInfo::Role::Root); + m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), ChildNetEntityId, EntityInfo::Role::Child); + m_childOfChildEntityInfo = AZStd::make_unique(*m_childOfChildEntity.get(), ChildOfChildNetEntityId, EntityInfo::Role::Child); + m_child2EntityInfo = AZStd::make_unique(*m_child2Entity.get(), Child2NetEntityId, EntityInfo::Role::Child); + m_childOfChild2EntityInfo = AZStd::make_unique(*m_childOfChild2Entity.get(), ChildOfChild2NetEntityId, EntityInfo::Role::Child); + m_child2OfChild2EntityInfo = AZStd::make_unique(*m_child2OfChild2Entity.get(), Child2OfChild2NetEntityId, EntityInfo::Role::Child); + + CreateBranchedHierarchy(*m_rootEntityInfo, *m_childEntityInfo, *m_childOfChildEntityInfo, + *m_child2EntityInfo, *m_childOfChild2EntityInfo, *m_child2OfChild2EntityInfo); + + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + // now the entities are under one hierarchy + } + + void TearDown() override + { + m_child2OfChild2EntityInfo.reset(); + m_childOfChild2EntityInfo.reset(); + m_child2EntityInfo.reset(); + m_childOfChildEntityInfo.reset(); + m_childEntityInfo.reset(); + m_rootEntityInfo.reset(); + + StopAndDeleteEntity(m_child2OfChild2Entity); + StopAndDeleteEntity(m_childOfChild2Entity); + StopAndDeleteEntity(m_child2Entity); + StopAndDeleteEntity(m_childOfChildEntity); + StopAndDeleteEntity(m_childEntity); + StopAndDeleteEntity(m_rootEntity); + + HierarchyTests::TearDown(); + } + + + void CreateBranchedHierarchy(EntityInfo& root, EntityInfo& child, EntityInfo& childOfChild, + EntityInfo& child2, EntityInfo& childOfChild2, EntityInfo& child2OfChild2) + { + PopulateHierarchicalEntity(root); + PopulateHierarchicalEntity(child); + PopulateHierarchicalEntity(childOfChild); + PopulateHierarchicalEntity(child2); + PopulateHierarchicalEntity(childOfChild2); + PopulateHierarchicalEntity(child2OfChild2); + + SetupEntity(root.m_entity, root.m_netId, NetEntityRole::Authority); + SetupEntity(child.m_entity, child.m_netId, NetEntityRole::Authority); + SetupEntity(childOfChild.m_entity, childOfChild.m_netId, NetEntityRole::Authority); + SetupEntity(child2.m_entity, child2.m_netId, NetEntityRole::Authority); + SetupEntity(childOfChild2.m_entity, childOfChild2.m_netId, NetEntityRole::Authority); + SetupEntity(child2OfChild2.m_entity, child2OfChild2.m_netId, NetEntityRole::Authority); + + // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) + SetParentIdOnNetworkTransform(child.m_entity, root.m_netId); + SetParentIdOnNetworkTransform(childOfChild.m_entity, child.m_netId); + SetParentIdOnNetworkTransform(child2.m_entity, root.m_netId); + SetParentIdOnNetworkTransform(childOfChild2.m_entity, child2.m_netId); + SetParentIdOnNetworkTransform(child2OfChild2.m_entity, child2.m_netId); + + // Create entity replicators + const NetworkEntityHandle childOfChild2Handle(&childOfChild2.m_entity, m_networkEntityTracker.get()); + childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childOfChild2Handle); + childOfChild.m_replicator->Initialize(childOfChild2Handle); + + const NetworkEntityHandle child2OfChild2Handle(&child2OfChild2.m_entity, m_networkEntityTracker.get()); + childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, child2OfChild2Handle); + childOfChild.m_replicator->Initialize(child2OfChild2Handle); + + const NetworkEntityHandle child2Handle(&child2.m_entity, m_networkEntityTracker.get()); + child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, child2Handle); + child.m_replicator->Initialize(child2Handle); + + const NetworkEntityHandle childOfChildHandle(&childOfChild.m_entity, m_networkEntityTracker.get()); + childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childOfChildHandle); + childOfChild.m_replicator->Initialize(childOfChildHandle); + + const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); + child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childHandle); + child.m_replicator->Initialize(childHandle); + + const NetworkEntityHandle rootHandle(&root.m_entity, m_networkEntityTracker.get()); + root.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, rootHandle); + root.m_replicator->Initialize(rootHandle); + + root.m_entity.Activate(); + child.m_entity.Activate(); + childOfChild.m_entity.Activate(); + child2.m_entity.Activate(); + childOfChild2.m_entity.Activate(); + child2OfChild2.m_entity.Activate(); + } + + AZStd::unique_ptr m_rootEntity; + AZStd::unique_ptr m_childEntity; + AZStd::unique_ptr m_childOfChildEntity; + AZStd::unique_ptr m_child2Entity; + AZStd::unique_ptr m_childOfChild2Entity; + AZStd::unique_ptr m_child2OfChild2Entity; + + AZStd::unique_ptr m_rootEntityInfo; + AZStd::unique_ptr m_childEntityInfo; + AZStd::unique_ptr m_childOfChildEntityInfo; + AZStd::unique_ptr m_child2EntityInfo; + AZStd::unique_ptr m_childOfChild2EntityInfo; + AZStd::unique_ptr m_child2OfChild2EntityInfo; + }; + + TEST_F(ServerBranchedHierarchyTests, Sanity_Check) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 6 + ); + + if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 6) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], + m_rootEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], + m_childEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChildEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[3], + m_child2Entity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[4], + m_child2OfChild2Entity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[5], + m_childOfChild2Entity.get() + ); + } + } + + TEST_F(ServerBranchedHierarchyTests, Detach_Child_While_Child2_Remains_Attached) + { + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 4 + ); + + if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 4) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], + m_rootEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], + m_child2Entity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], + m_child2OfChild2Entity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[3], + m_childOfChild2Entity.get() + ); + } + + EXPECT_EQ( + m_child2Entity->FindComponent()->GetHierarchicalRoot(), + m_rootEntity.get() + ); + EXPECT_EQ( + m_childEntity->FindComponent()->GetHierarchicalRoot(), + nullptr + ); + EXPECT_EQ( + m_childOfChildEntity->FindComponent()->GetHierarchicalRoot(), + nullptr + ); + } + + TEST_F(ServerBranchedHierarchyTests, Detach_Child_Then_Attach_To_Child2) + { + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childEntity->FindComponent()->SetParent(m_child2Entity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 6 + ); + } + + /* + * Sets up 2 deep hierarchies. + */ + class ServerHierarchyOfHierarchyTests : public ServerDeepHierarchyTests + { + public: + static const NetEntityId Root2NetEntityId = NetEntityId{ 4 }; + static const NetEntityId Child2NetEntityId = NetEntityId{ 5 }; + static const NetEntityId ChildOfChild2NetEntityId = NetEntityId{ 6 }; + + void SetUp() override + { + ServerDeepHierarchyTests::SetUp(); + + m_rootEntity2 = AZStd::make_unique(AZ::EntityId(4), "root 2"); + m_childEntity2 = AZStd::make_unique(AZ::EntityId(5), "child 2"); + m_childOfChildEntity2 = AZStd::make_unique(AZ::EntityId(6), "child of child 2"); + + m_rootEntityInfo2 = AZStd::make_unique(*m_rootEntity2.get(), Root2NetEntityId, EntityInfo::Role::Root); + m_childEntityInfo2 = AZStd::make_unique(*m_childEntity2.get(), Child2NetEntityId, EntityInfo::Role::Child); + m_childOfChildEntityInfo2 = AZStd::make_unique(*m_childOfChildEntity2.get(), ChildOfChild2NetEntityId, EntityInfo::Role::Child); + + CreateDeepHierarchy(*m_rootEntityInfo2, *m_childEntityInfo2, *m_childOfChildEntityInfo2); + + m_childEntity2->FindComponent()->SetParent(m_rootEntity2->GetId()); + m_childOfChildEntity2->FindComponent()->SetParent(m_childEntity2->GetId()); + // now the entities are under one hierarchy + } + + void TearDown() override + { + m_childOfChildEntityInfo2.reset(); + m_childEntityInfo2.reset(); + m_rootEntityInfo2.reset(); + + StopAndDeleteEntity(m_childOfChildEntity2); + StopAndDeleteEntity(m_childEntity2); + StopAndDeleteEntity(m_rootEntity2); + + ServerDeepHierarchyTests::TearDown(); + } + + AZStd::unique_ptr m_rootEntity2; + AZStd::unique_ptr m_childEntity2; + AZStd::unique_ptr m_childOfChildEntity2; + + AZStd::unique_ptr m_rootEntityInfo2; + AZStd::unique_ptr m_childEntityInfo2; + AZStd::unique_ptr m_childOfChildEntityInfo2; + }; + + TEST_F(ServerHierarchyOfHierarchyTests, Hierarchies_Are_Not_Related) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + + if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 3) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], + m_rootEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], + m_childEntity.get() + ); + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChildEntity.get() + ); + } + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + + if (m_rootEntity2->FindComponent()->GetHierarchicalEntities().size() == 3) + { + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities()[0], + m_rootEntity2.get() + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities()[1], + m_childEntity2.get() + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChildEntity2.get() + ); + } + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Is_Not_Top_Level_Root) + { + m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->IsHierarchicalChild(), + false + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->IsHierarchicalChild(), + true + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_References_All_When_Another_Hierarchy_Attached_At_Root) + { + m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 6 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_References_All_When_Another_Hierarchy_Attached_At_Child) + { + m_rootEntity2->FindComponent()->SetParent(m_childEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 6 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_References_All_When_Another_Hierarchy_Attached_At_Child_Of_Child) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 6 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_References_Top_Root_When_Another_Hierarchy_Attached_At_Root) + { + m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->IsHierarchicalChild(), + true + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_References_Top_Root_When_Another_Hierarchy_Attached_At_Child) + { + m_rootEntity2->FindComponent()->SetParent(m_childEntity->GetId()); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->IsHierarchicalChild(), + true + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_References_Top_Root_When_Another_Hierarchy_Attached_At_Child_Of_Child) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->IsHierarchicalChild(), + true + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchyRoot(), + RootNetEntityId + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Doesnt_Keep_Child_References) + { + m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 0 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Detachment_From_Top_Root) + { + m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + // detach + m_rootEntity2->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + if (m_rootEntity2->FindComponent()->GetHierarchicalEntities().size() == 3) + { + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities()[0], + m_rootEntity2.get() + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities()[1], + m_childEntity2.get() + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChildEntity2.get() + ); + } + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Detachment_From_Child_Of_Child) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + // detach + m_rootEntity2->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Stress_Test_Inner_Root_Has_Child_References_After_Detachment_From_Child_Of_Child) + { + for (int i = 0; i < 100; ++i) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + // detach + m_rootEntity2->FindComponent()->SetParent(AZ::EntityId()); + } + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Detachment_Of_Child_Of_Child_In_Inner_Hierarchy) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + // detach + m_childOfChildEntity2->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 5 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Attachment_Of_Child_Of_Child_In_Inner_Hierarchy) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + // detach + m_childOfChildEntity2->FindComponent()->SetParent(AZ::EntityId()); + // re-connect + m_childOfChildEntity2->FindComponent()->SetParent(m_childEntity2->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 6 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Child_Of_Child_Changed_Hierarchies) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + // detach + m_childOfChildEntity2->FindComponent()->SetParent(AZ::EntityId()); + + // connect to a different hierarchy + m_childOfChildEntity2->FindComponent()->SetParent(m_childEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 6 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Detachment_Of_Child_In_Inner_Hierarchy) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + // detach + m_childEntity2->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 4 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Child_Changed_Hierarchies) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + // detach + m_childEntity2->FindComponent()->SetParent(AZ::EntityId()); + + // connect to a different hierarchy + m_childEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 6 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_No_Child_References_After_All_Children_Moved_To_Another_Hierarchy) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + + m_childEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + + // detach + m_rootEntity2->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 1 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Child_Deactivated_Top_Root_Has_No_Child_Reference_To_It) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + + StopAndDeleteEntity(m_childEntity2); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 4 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Testing_Limiting_Hierarchy_Maximum_Size) + { + uint32_t currentMaxLimit = 0; + m_console->GetCvarValue("bg_hierarchyEntityMaxLimit", currentMaxLimit); + m_console->PerformCommand("bg_hierarchyEntityMaxLimit 2"); + + // remake the top level hierarchy + m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + + m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + + m_console->PerformCommand((AZStd::string("bg_hierarchyEntityMaxLimit ") + AZStd::to_string(currentMaxLimit)).c_str()); + m_console->GetCvarValue("bg_hierarchyEntityMaxLimit", currentMaxLimit); + } + + /* + * Parent -> Child -> ChildOfChild (not marked as in a hierarchy) + */ + class ServerMixedDeepHierarchyTests : public HierarchyTests + { + public: + void SetUp() override + { + HierarchyTests::SetUp(); + + m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); + m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); + m_childOfChildEntity = AZStd::make_unique(AZ::EntityId(3), "child of child"); + + m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), NetEntityId{ 1 }, EntityInfo::Role::Root); + m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), NetEntityId{ 2 }, EntityInfo::Role::Child); + m_childOfChildEntityInfo = AZStd::make_unique(*m_childOfChildEntity.get(), NetEntityId{ 3 }, EntityInfo::Role::None); + + CreateDeepHierarchy(*m_rootEntityInfo, *m_childEntityInfo, *m_childOfChildEntityInfo); + + m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + // now the entities are under one hierarchy + } + + void TearDown() override + { + m_childOfChildEntityInfo.reset(); + m_childEntityInfo.reset(); + m_rootEntityInfo.reset(); + + StopAndDeleteEntity(m_childOfChildEntity); + StopAndDeleteEntity(m_childEntity); + StopAndDeleteEntity(m_rootEntity); + + HierarchyTests::TearDown(); + } + + AZStd::unique_ptr m_rootEntity; + AZStd::unique_ptr m_childEntity; + AZStd::unique_ptr m_childOfChildEntity; + + AZStd::unique_ptr m_rootEntityInfo; + AZStd::unique_ptr m_childEntityInfo; + AZStd::unique_ptr m_childOfChildEntityInfo; + }; + + TEST_F(ServerMixedDeepHierarchyTests, Top_Root_Ignores_Non_Hierarchical_Entities) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + } + + TEST_F(ServerMixedDeepHierarchyTests, Detaching_Non_Hierarchical_Entity_Has_No_Effect_On_Top_Root) + { + m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + } + + TEST_F(ServerMixedDeepHierarchyTests, Attaching_Non_Hierarchical_Entity_Has_No_Effect_On_Top_Root) + { + m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChildEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + } + + /* + * 1st hierarchy: Parent -> Child -> ChildOfChild (not marked as in a hierarchy) + * 2nd hierarchy: Parent2 -> Child2 (not marked as in a hierarchy) -> ChildOfChild2 + */ + class ServerMixedHierarchyOfHierarchyTests : public ServerMixedDeepHierarchyTests + { + public: + void SetUp() override + { + ServerMixedDeepHierarchyTests::SetUp(); + + m_rootEntity2 = AZStd::make_unique(AZ::EntityId(4), "root 2"); + m_childEntity2 = AZStd::make_unique(AZ::EntityId(5), "child 2"); + m_childOfChildEntity2 = AZStd::make_unique(AZ::EntityId(6), "child of child 2"); + + m_rootEntityInfo2 = AZStd::make_unique(*m_rootEntity2.get(), NetEntityId{ 4 }, EntityInfo::Role::Root); + m_childEntityInfo2 = AZStd::make_unique(*m_childEntity2.get(), NetEntityId{ 5 }, EntityInfo::Role::None); + m_childOfChildEntityInfo2 = AZStd::make_unique(*m_childOfChildEntity2.get(), NetEntityId{ 6 }, EntityInfo::Role::Child); + + CreateDeepHierarchy(*m_rootEntityInfo2, *m_childEntityInfo2, *m_childOfChildEntityInfo2); + + m_childEntity2->FindComponent()->SetParent(m_rootEntity2->GetId()); + m_childOfChildEntity2->FindComponent()->SetParent(m_childEntity2->GetId()); + // now the entities are under one hierarchy + } + + void TearDown() override + { + m_childOfChildEntityInfo2.reset(); + m_childEntityInfo2.reset(); + m_rootEntityInfo2.reset(); + + + StopAndDeleteEntity(m_childOfChildEntity2); + StopAndDeleteEntity(m_childEntity2); + StopAndDeleteEntity(m_rootEntity2); + + ServerMixedDeepHierarchyTests::TearDown(); + } + + AZStd::unique_ptr m_rootEntity2; + AZStd::unique_ptr m_childEntity2; + AZStd::unique_ptr m_childOfChildEntity2; + + AZStd::unique_ptr m_rootEntityInfo2; + AZStd::unique_ptr m_childEntityInfo2; + AZStd::unique_ptr m_childOfChildEntityInfo2; + }; + + TEST_F(ServerMixedHierarchyOfHierarchyTests, Sanity_Check_Ingore_Children_Without_Hierarchy_Components) + { + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 2 + ); + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 1 + ); + } + + TEST_F(ServerMixedHierarchyOfHierarchyTests, Adding_Mixed_Hierarchy_Ingores_Children_Without_Hierarchy_Components) + { + m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + + EXPECT_EQ( + m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerMixedHierarchyOfHierarchyTests, Attaching_Hierarchy_To_Non_Hierarchical_Entity_Does_Not_Merge_Hierarchies) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->IsHierarchicalChild(), + false + ); + } +} diff --git a/Gems/Multiplayer/Code/multiplayer_files.cmake b/Gems/Multiplayer/Code/multiplayer_files.cmake index 0b2adb1530..6475155f40 100644 --- a/Gems/Multiplayer/Code/multiplayer_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_files.cmake @@ -15,20 +15,28 @@ set(FILES Include/Multiplayer/MultiplayerTypes.h Include/Multiplayer/Components/LocalPredictionPlayerInputComponent.h Include/Multiplayer/Components/MultiplayerComponent.h - Include/Multiplayer/Components/MultiplayerController.h Include/Multiplayer/Components/MultiplayerComponentRegistry.h + Include/Multiplayer/Components/MultiplayerController.h Include/Multiplayer/Components/NetBindComponent.h + Include/Multiplayer/Components/NetworkHierarchyChildComponent.h + Include/Multiplayer/Components/NetworkHierarchyRootComponent.h + Include/Multiplayer/Components/NetworkHierarchyBus.h Include/Multiplayer/Components/NetworkTransformComponent.h Include/Multiplayer/ConnectionData/IConnectionData.h Include/Multiplayer/EntityDomains/IEntityDomain.h - Include/Multiplayer/NetworkEntity/INetworkEntityManager.h + Include/Multiplayer/IMultiplayer.h + Include/Multiplayer/IMultiplayerTools.h Include/Multiplayer/INetworkSpawnableLibrary.h + Include/Multiplayer/MultiplayerConstants.h + Include/Multiplayer/MultiplayerStats.h + Include/Multiplayer/MultiplayerTypes.h + Include/Multiplayer/NetworkEntity/EntityReplication/ReplicationRecord.h Include/Multiplayer/NetworkEntity/IFilterEntityManager.h - Include/Multiplayer/NetworkEntity/NetworkEntityRpcMessage.h - Include/Multiplayer/NetworkEntity/NetworkEntityUpdateMessage.h + Include/Multiplayer/NetworkEntity/INetworkEntityManager.h Include/Multiplayer/NetworkEntity/NetworkEntityHandle.h Include/Multiplayer/NetworkEntity/NetworkEntityHandle.inl - Include/Multiplayer/NetworkEntity/EntityReplication/ReplicationRecord.h + Include/Multiplayer/NetworkEntity/NetworkEntityRpcMessage.h + Include/Multiplayer/NetworkEntity/NetworkEntityUpdateMessage.h Include/Multiplayer/NetworkInput/IMultiplayerComponentInput.h Include/Multiplayer/NetworkInput/NetworkInput.h Include/Multiplayer/NetworkTime/INetworkTime.h @@ -40,23 +48,24 @@ set(FILES Include/Multiplayer/NetworkTime/RewindableObject.inl Include/Multiplayer/Physics/PhysicsUtils.h Include/Multiplayer/ReplicationWindows/IReplicationWindow.h - Source/MultiplayerSystemComponent.cpp - Source/MultiplayerSystemComponent.h - Source/MultiplayerStats.cpp - Source/AutoGen/AutoComponent_Header.jinja - Source/AutoGen/AutoComponent_Source.jinja - Source/AutoGen/AutoComponent_Common.jinja Source/AutoGen/AutoComponentTypes_Header.jinja Source/AutoGen/AutoComponentTypes_Source.jinja + Source/AutoGen/AutoComponent_Common.jinja + Source/AutoGen/AutoComponent_Header.jinja + Source/AutoGen/AutoComponent_Source.jinja Source/AutoGen/LocalPredictionPlayerInputComponent.AutoComponent.xml Source/AutoGen/Multiplayer.AutoPackets.xml Source/AutoGen/MultiplayerEditor.AutoPackets.xml Source/AutoGen/NetworkTransformComponent.AutoComponent.xml + Source/AutoGen/NetworkHierarchyChildComponent.AutoComponent.xml + Source/AutoGen/NetworkHierarchyRootComponent.AutoComponent.xml Source/Components/LocalPredictionPlayerInputComponent.cpp Source/Components/MultiplayerComponent.cpp - Source/Components/MultiplayerController.cpp Source/Components/MultiplayerComponentRegistry.cpp + Source/Components/MultiplayerController.cpp Source/Components/NetBindComponent.cpp + Source/Components/NetworkHierarchyChildComponent.cpp + Source/Components/NetworkHierarchyRootComponent.cpp Source/Components/NetworkTransformComponent.cpp Source/ConnectionData/ClientToServerConnectionData.cpp Source/ConnectionData/ClientToServerConnectionData.h @@ -68,6 +77,9 @@ set(FILES Source/Editor/MultiplayerEditorConnection.h Source/EntityDomains/FullOwnershipEntityDomain.cpp Source/EntityDomains/FullOwnershipEntityDomain.h + Source/MultiplayerStats.cpp + Source/MultiplayerSystemComponent.cpp + Source/MultiplayerSystemComponent.h Source/NetworkEntity/EntityReplication/EntityReplicationManager.cpp Source/NetworkEntity/EntityReplication/EntityReplicationManager.h Source/NetworkEntity/EntityReplication/EntityReplicator.cpp @@ -83,13 +95,13 @@ set(FILES Source/NetworkEntity/NetworkEntityHandle.cpp Source/NetworkEntity/NetworkEntityManager.cpp Source/NetworkEntity/NetworkEntityManager.h - Source/NetworkEntity/NetworkSpawnableLibrary.cpp - Source/NetworkEntity/NetworkSpawnableLibrary.h Source/NetworkEntity/NetworkEntityRpcMessage.cpp Source/NetworkEntity/NetworkEntityTracker.cpp Source/NetworkEntity/NetworkEntityTracker.h Source/NetworkEntity/NetworkEntityTracker.inl Source/NetworkEntity/NetworkEntityUpdateMessage.cpp + Source/NetworkEntity/NetworkSpawnableLibrary.cpp + Source/NetworkEntity/NetworkSpawnableLibrary.h Source/NetworkInput/NetworkInput.cpp Source/NetworkInput/NetworkInputArray.cpp Source/NetworkInput/NetworkInputArray.h @@ -101,11 +113,11 @@ set(FILES Source/NetworkInput/NetworkInputMigrationVector.h Source/NetworkTime/NetworkTime.cpp Source/NetworkTime/NetworkTime.h + Source/Physics/PhysicsUtils.cpp Source/Pipeline/NetBindMarkerComponent.cpp Source/Pipeline/NetBindMarkerComponent.h Source/Pipeline/NetworkSpawnableHolderComponent.cpp Source/Pipeline/NetworkSpawnableHolderComponent.h - Source/Physics/PhysicsUtils.cpp Source/ReplicationWindows/NullReplicationWindow.cpp Source/ReplicationWindows/NullReplicationWindow.h Source/ReplicationWindows/ServerToClientReplicationWindow.cpp diff --git a/Gems/Multiplayer/Code/multiplayer_tests_files.cmake b/Gems/Multiplayer/Code/multiplayer_tests_files.cmake index f385a21600..3f4fcc9efa 100644 --- a/Gems/Multiplayer/Code/multiplayer_tests_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_tests_files.cmake @@ -8,6 +8,10 @@ set(FILES Tests/Main.cpp + Tests/MockInterfaces.h + Tests/ClientHierarchyTests.cpp + Tests/ServerHierarchyTests.cpp + Tests/CommonHierarchySetup.h Tests/IMultiplayerConnectionMock.h Tests/MultiplayerSystemTests.cpp Tests/RewindableContainerTests.cpp From 2a10c400a7ac5b94c7eb86ce542e489f1b8a2609 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 13 Sep 2021 18:28:52 -0400 Subject: [PATCH 08/84] Comments cleanup Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Multiplayer/Components/NetworkHierarchyRootComponent.h | 2 +- .../Code/Source/Components/NetworkHierarchyChildComponent.cpp | 2 +- .../Code/Source/Components/NetworkHierarchyRootComponent.cpp | 2 +- Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp | 4 ++-- Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp | 3 --- 5 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h index 48c003d9e7..6192d41ad6 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h @@ -18,7 +18,7 @@ namespace Multiplayer //! @class NetworkHierarchyRootComponent //! @brief Component that declares the top level entity of a network hierarchy. /* - * Call @GetHierarchyChildren to get the list of hierarchical entities. + * Call @GetHierarchicalEntities to get the list of hierarchical entities. * A network hierarchy is meant to be a small group of entities. You can control the maximum supported size of * a network hierarchy by modifying CVar @bg_hierarchyEntityMaxLimit. * diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp index c644b832a0..c04fc2cf3b 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp @@ -26,7 +26,7 @@ namespace Multiplayer if (AZ::EditContext* editContext = serializeContext->GetEditContext()) { editContext->Class( - "Network Hierarchy Child", "declares a network dependency on the root of this hierarchy") + "Network Hierarchy Child", "Declares a network dependency on the root of this hierarchy.") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Category, "Multiplayer") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game")) diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp index 2fa960ed2a..d20aa8d898 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp @@ -32,7 +32,7 @@ namespace Multiplayer if (AZ::EditContext* editContext = serializeContext->GetEditContext()) { editContext->Class( - "Network Hierarchy Root", "marks the entity as the root of an entity hierarchy") + "Network Hierarchy Root", "Marks the entity as the root of an entity hierarchy.") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Category, "Multiplayer") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game")) diff --git a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp index d1b01a279c..23de4d2f04 100644 --- a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp @@ -287,8 +287,8 @@ namespace Multiplayer ); } - /* - * Parent -> Child + /* + * Parent -> Child -> ChildOfChild */ class ClientDeepHierarchyTests : public ClientSimpleHierarchyTests { diff --git a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp index ae2d8b162d..d119ade937 100644 --- a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp @@ -66,9 +66,6 @@ namespace Multiplayer PopulateHierarchicalEntity(child); SetupEntity(child.m_entity, child.m_netId, NetEntityRole::Authority); - //// we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) - //SetParentIdOnNetworkTransform(child.m_entity, root.m_netId); - // Create an entity replicator for the child entity const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childHandle); From 853cffbf7bcfde4ebdb9cab4fd4bc1cd2fa6f2c1 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 13 Sep 2021 18:37:05 -0400 Subject: [PATCH 09/84] Comment cleanup Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Code/Include/Multiplayer/Components/NetworkHierarchyBus.h | 2 +- .../Multiplayer/Components/NetworkHierarchyChildComponent.h | 3 ++- .../Code/Source/Components/NetworkHierarchyChildComponent.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h index 72dff65401..d644d6eb5a 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h @@ -20,7 +20,7 @@ namespace Multiplayer virtual void OnNetworkHierarchyUpdated([[maybe_unused]] const AZ::EntityId& rootEntityId) {} //! Called when an entity has left a hierarchy - virtual void OnLeavingNetworkHierarchy() {} + virtual void OnNetworkHierarchyLeave() {} }; typedef AZ::EBus NetworkHierarchyNotificationBus; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h index 27f794ec21..cfc3803d28 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h @@ -39,13 +39,14 @@ namespace Multiplayer NetworkHierarchyChildComponent(); + //! NetworkHierarchyChildComponentBase overrides. //! @{ void OnInit() override; void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; //! @} - //! NetworkHierarchyRequestBus overrides + //! NetworkHierarchyRequestBus overrides. //! @{ bool IsHierarchicalChild() const override; bool IsHierarchicalRoot() const override { return false; } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp index c04fc2cf3b..cbdf214dfc 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp @@ -114,7 +114,7 @@ namespace Multiplayer else { controller->SetHierarchyRoot(InvalidNetEntityId); - NetworkHierarchyNotificationBus::Event(GetEntityId(), &NetworkHierarchyNotificationBus::Events::OnLeavingNetworkHierarchy); + NetworkHierarchyNotificationBus::Event(GetEntityId(), &NetworkHierarchyNotificationBus::Events::OnNetworkHierarchyLeave); } } } From 05e464b31bd8b99d7757874ef1e01c70089adeae Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 13 Sep 2021 18:45:22 -0400 Subject: [PATCH 10/84] Improving comments Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Components/NetworkHierarchyRootComponent.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h index 6192d41ad6..4be8b24d8a 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h @@ -67,10 +67,19 @@ namespace Multiplayer AZStd::vector m_hierarchicalEntities; void RebuildHierarchy(); - - //! @returns false if the maximum supported hierarchy size has been reached + + //! @param underEntity Walk the child entities that belong to @underEntity and consider adding them to the hierarchy + //! @param currentEntityCount The total number of entities in the hierarchy prior to calling this method, + //! used to avoid adding too many entities to the hierarchy while walking recursively the relevant entities. + //! @currentEntityCount will be modified to reflect the total entity count upon completion of this method. + //! @returns false if an attempt was made to go beyond the maximum supported hierarchy size, true otherwise bool RecursiveAttachHierarchicalEntities(AZ::EntityId underEntity, uint32_t& currentEntityCount); - //! @returns false if the maximum supported hierarchy size has been reached + + //! @param entity Add the child entity and any of its relevant children to the hierarchy + //! @param currentEntityCount The total number of entities in the hierarchy prior to calling this method, + //! used to avoid adding too many entities to the hierarchy while walking recursively the relevant entities. + //! @currentEntityCount will be modified to reflect the total entity count upon completion of this method. + //! @returns false if an attempt was made to go beyond the maximum supported hierarchy size, true otherwise bool RecursiveAttachHierarchicalChild(AZ::EntityId entity, uint32_t& currentEntityCount); }; } From 0d8b0fe496a3b62bba714acc32add2befcee3321 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 13 Sep 2021 18:51:39 -0400 Subject: [PATCH 11/84] Fixes for clang builds Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Code/Source/Components/NetworkHierarchyRootComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp index d20aa8d898..5f546298cb 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp @@ -175,7 +175,7 @@ namespace Multiplayer AZStd::vector allChildren; AZ::TransformBus::EventResult(allChildren, underEntity, &AZ::TransformBus::Events::GetChildren); - for (const AZ::EntityId newChildId : allChildren) + for (const AZ::EntityId& newChildId : allChildren) { if (!RecursiveAttachHierarchicalChild(newChildId, currentEntityCount)) { From 088511577b9a4ae6169d72411c36992a4a572cc0 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 13 Sep 2021 20:33:32 -0400 Subject: [PATCH 12/84] Fix for clan compiler Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp | 4 ++-- Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp index 23de4d2f04..29d4f7f809 100644 --- a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp @@ -148,8 +148,8 @@ namespace Multiplayer class ClientSimpleHierarchyTests : public HierarchyTests { public: - static const NetEntityId RootNetEntityId = NetEntityId{ 1 }; - static const NetEntityId ChildNetEntityId = NetEntityId{ 2 }; + const NetEntityId RootNetEntityId = NetEntityId{ 1 }; + const NetEntityId ChildNetEntityId = NetEntityId{ 2 }; void SetUp() override { diff --git a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp index d119ade937..708a39d439 100644 --- a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp @@ -176,9 +176,9 @@ namespace Multiplayer class ServerDeepHierarchyTests : public HierarchyTests { public: - static const NetEntityId RootNetEntityId = NetEntityId{ 1 }; - static const NetEntityId ChildNetEntityId = NetEntityId{ 2 }; - static const NetEntityId ChildOfChildNetEntityId = NetEntityId{ 3 }; + const NetEntityId RootNetEntityId = NetEntityId{ 1 }; + const NetEntityId ChildNetEntityId = NetEntityId{ 2 }; + const NetEntityId ChildOfChildNetEntityId = NetEntityId{ 3 }; void SetUp() override { From fcd5b3f184af27c4514a4f6eab2c6d912ae1d1e9 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Tue, 14 Sep 2021 11:50:51 -0400 Subject: [PATCH 13/84] Converted to use AZ::Events for hiearchy notifications. Added unittests. Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Components/NetworkHierarchyBus.h | 22 +++++++------- .../NetworkHierarchyChildComponent.h | 5 ++++ .../NetworkHierarchyRootComponent.h | 5 ++++ .../NetworkHierarchyChildComponent.cpp | 17 +++++++++-- .../NetworkHierarchyRootComponent.cpp | 14 +++++++++ .../Components/NetworkTransformComponent.cpp | 23 +++++++++++---- .../EntityReplication/EntityReplicator.cpp | 28 +++++++++--------- .../Code/Tests/ClientHierarchyTests.cpp | 25 +++++++++++++++- .../Code/Tests/CommonHierarchySetup.h | 29 +++++++++++++++++-- 9 files changed, 131 insertions(+), 37 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h index d644d6eb5a..1401856afe 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h @@ -12,18 +12,8 @@ namespace Multiplayer { - class NetworkHierarchyNotifications - : public AZ::ComponentBus - { - public: - //! Called when a hierarchy has been updated (a child added or removed, etc.) - virtual void OnNetworkHierarchyUpdated([[maybe_unused]] const AZ::EntityId& rootEntityId) {} - - //! Called when an entity has left a hierarchy - virtual void OnNetworkHierarchyLeave() {} - }; - - typedef AZ::EBus NetworkHierarchyNotificationBus; + using NetworkHierarchyChangedEvent = AZ::Event; + using NetworkHierarchyLeaveEvent = AZ::Event<>; class NetworkHierarchyRequests : public AZ::ComponentBus @@ -40,6 +30,14 @@ namespace Multiplayer //! @return true if this entity is the top level root of a hierarchy virtual bool IsHierarchicalRoot() const = 0; + + //! Binds the provided NetworkHierarchyChangedEvent handler to a Network Hierarchy component. + //! @param handler the handler to invoke when the entity's network hierarchy has been modified. + virtual void BindNetworkHierarchyChangedEventHandler(NetworkHierarchyChangedEvent::Handler& handler) = 0; + + //! Binds the provided NetworkHierarchyLeaveEvent handler to a Network Hierarchy component. + //! @param handler the handler to invoke when the entity left its network hierarchy. + virtual void BindNetworkHierarchyLeaveEventHandler(NetworkHierarchyLeaveEvent::Handler& handler) = 0; }; typedef AZ::EBus NetworkHierarchyRequestBus; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h index cfc3803d28..93ce3e25d0 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h @@ -52,6 +52,8 @@ namespace Multiplayer bool IsHierarchicalRoot() const override { return false; } AZ::Entity* GetHierarchicalRoot() const override; AZStd::vector GetHierarchicalEntities() const override; + void BindNetworkHierarchyChangedEventHandler(NetworkHierarchyChangedEvent::Handler& handler) override; + void BindNetworkHierarchyLeaveEventHandler(NetworkHierarchyLeaveEvent::Handler& handler) override; //! @} protected: @@ -63,5 +65,8 @@ namespace Multiplayer AZ::Event::Handler m_hierarchyRootNetIdChanged; void OnHierarchyRootNetIdChanged(NetEntityId rootNetId); + + NetworkHierarchyChangedEvent m_networkHierarchyChangedEvent; + NetworkHierarchyLeaveEvent m_networkHierarchyLeaveEvent; }; } diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h index 4be8b24d8a..228f953a32 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h @@ -50,6 +50,8 @@ namespace Multiplayer bool IsHierarchicalChild() const override; AZStd::vector GetHierarchicalEntities() const override; AZ::Entity* GetHierarchicalRoot() const override; + void BindNetworkHierarchyChangedEventHandler(NetworkHierarchyChangedEvent::Handler& handler) override; + void BindNetworkHierarchyLeaveEventHandler(NetworkHierarchyLeaveEvent::Handler& handler) override; //! @} protected: @@ -63,6 +65,9 @@ namespace Multiplayer void SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot); private: + NetworkHierarchyChangedEvent m_networkHierarchyChangedEvent; + NetworkHierarchyLeaveEvent m_networkHierarchyLeaveEvent; + AZ::Entity* m_higherRootEntity = nullptr; AZStd::vector m_hierarchicalEntities; diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp index cbdf214dfc..93574ec5b4 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp @@ -98,6 +98,16 @@ namespace Multiplayer return {}; } + void NetworkHierarchyChildComponent::BindNetworkHierarchyChangedEventHandler(NetworkHierarchyChangedEvent::Handler& handler) + { + handler.Connect(m_networkHierarchyChangedEvent); + } + + void NetworkHierarchyChildComponent::BindNetworkHierarchyLeaveEventHandler(NetworkHierarchyLeaveEvent::Handler& handler) + { + handler.Connect(m_networkHierarchyLeaveEvent); + } + void NetworkHierarchyChildComponent::SetTopLevelHierarchyRootComponent(NetworkHierarchyRootComponent* hierarchyRoot) { m_hierarchyRootComponent = hierarchyRoot; @@ -109,12 +119,13 @@ namespace Multiplayer const NetEntityId netRootId = GetNetworkEntityManager()->GetNetEntityIdById(hierarchyRoot->GetEntityId()); controller->SetHierarchyRoot(netRootId); - NetworkHierarchyNotificationBus::Event(GetEntityId(), &NetworkHierarchyNotificationBus::Events::OnNetworkHierarchyUpdated, hierarchyRoot->GetEntityId()); + m_networkHierarchyChangedEvent.Signal(hierarchyRoot->GetEntityId()); } else { controller->SetHierarchyRoot(InvalidNetEntityId); - NetworkHierarchyNotificationBus::Event(GetEntityId(), &NetworkHierarchyNotificationBus::Events::OnNetworkHierarchyLeave); + + m_networkHierarchyLeaveEvent.Signal(); } } } @@ -125,10 +136,12 @@ namespace Multiplayer if (rootHandle.Exists()) { m_hierarchyRootComponent = rootHandle.FindComponent(); + m_networkHierarchyChangedEvent.Signal(m_hierarchyRootComponent->GetEntityId()); } else { m_hierarchyRootComponent = nullptr; + m_networkHierarchyLeaveEvent.Signal(); } } } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp index 5f546298cb..ced2c79bce 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp @@ -124,6 +124,16 @@ namespace Multiplayer return GetEntity(); } + void NetworkHierarchyRootComponent::BindNetworkHierarchyChangedEventHandler(NetworkHierarchyChangedEvent::Handler& handler) + { + handler.Connect(m_networkHierarchyChangedEvent); + } + + void NetworkHierarchyRootComponent::BindNetworkHierarchyLeaveEventHandler(NetworkHierarchyLeaveEvent::Handler& handler) + { + handler.Connect(m_networkHierarchyLeaveEvent); + } + void NetworkHierarchyRootComponent::OnParentChanged([[maybe_unused]] AZ::EntityId oldParent, AZ::EntityId newParent) { const AZ::EntityId entityBusId = *AZ::TransformNotificationBus::GetCurrentBusId(); @@ -168,6 +178,8 @@ namespace Multiplayer uint32_t currentEntityCount = aznumeric_cast(m_hierarchicalEntities.size()); RecursiveAttachHierarchicalEntities(GetEntityId(), currentEntityCount); + + m_networkHierarchyChangedEvent.Signal(GetEntityId()); } bool NetworkHierarchyRootComponent::RecursiveAttachHierarchicalEntities(AZ::EntityId underEntity, uint32_t& currentEntityCount) @@ -255,6 +267,8 @@ namespace Multiplayer } } } + + m_networkHierarchyChangedEvent.Signal(GetEntityId()); } void NetworkHierarchyRootComponent::SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot) diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp index a37b6b52ed..8461f950fd 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp @@ -97,15 +97,28 @@ namespace Multiplayer void NetworkTransformComponent::OnParentIdChangedEvent([[maybe_unused]] NetEntityId newParent) { - const ConstNetworkEntityHandle rootHandle = GetNetworkEntityManager()->GetEntity(newParent); - if (rootHandle.Exists()) + if (newParent == InvalidNetEntityId) { - const AZ::EntityId parentEntityId = rootHandle.GetEntity()->GetId(); if (AzFramework::TransformComponent* transformComponent = GetEntity()->FindComponent()) { - if (transformComponent->GetParentId() != parentEntityId) + if (transformComponent->GetParentId() != AZ::EntityId()) { - transformComponent->SetParent(parentEntityId); + transformComponent->SetParent(AZ::EntityId()); + } + } + } + else + { + const ConstNetworkEntityHandle rootHandle = GetNetworkEntityManager()->GetEntity(newParent); + if (rootHandle.Exists()) + { + const AZ::EntityId parentEntityId = rootHandle.GetEntity()->GetId(); + if (AzFramework::TransformComponent* transformComponent = GetEntity()->FindComponent()) + { + if (transformComponent->GetParentId() != parentEntityId) + { + transformComponent->SetParent(parentEntityId); + } } } } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp index ad8c883f34..bd98d15923 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp @@ -32,8 +32,6 @@ #include -AZ_CVAR(bool, bg_debugHierarchyActivation, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Helpful messages when debugging network hierarchy behavior"); - namespace Multiplayer { EntityReplicator::EntityReplicator @@ -441,22 +439,22 @@ namespace Multiplayer const AZ::Entity* parentEntity = parentHandle.GetEntity(); if (parentEntity && parentEntity->GetState() == AZ::Entity::State::Active) { - if (bg_debugHierarchyActivation) - { - AZLOG_DEBUG( - "Entity %s asking for activation - granted", - entity->GetName().c_str()); - } + AZLOG + ( + NET_HierarchyActivationInfo, + "Hierchical entity %s asking for activation - granted", + entity->GetName().c_str() + ); return true; } - if (bg_debugHierarchyActivation) - { - AZLOG_DEBUG( - "Entity %s asking for activation - waiting on the parent %u", - entity->GetName().c_str(), - aznumeric_cast(parentId)); - } + AZLOG + ( + NET_HierarchyActivationInfo, + "Hierchical entity %s asking for activation - waiting on the parent %u", + entity->GetName().c_str(), + aznumeric_cast(parentId) + ); return false; } } diff --git a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp index 29d4f7f809..1483f32023 100644 --- a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp @@ -226,7 +226,6 @@ namespace Multiplayer ReplicationRecord notifyRecord = currentRecord; entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); - entity.FindComponent()->NotifyStateDeltaChanges(notifyRecord); } @@ -287,6 +286,30 @@ namespace Multiplayer ); } + TEST_F(ClientSimpleHierarchyTests, Client_Sends_NetworkHierarchy_Updated_Event_On_Child_Detached_On_Server) + { + MockNetworkHierarchyCallbackHandler mock; + EXPECT_CALL(mock, OnNetworkHierarchyUpdated(m_rootEntity->GetId())); + + m_rootEntity->FindComponent()->BindNetworkHierarchyChangedEventHandler(mock.m_changedHandler); + + // simulate server detaching a child entity + SetParentIdOnNetworkTransform(*m_childEntity, InvalidNetEntityId); + SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(*m_childEntity, InvalidNetEntityId); + } + + TEST_F(ClientSimpleHierarchyTests, Client_Sends_NetworkHierarchy_Leave_Event_On_Child_Detached_On_Server) + { + MockNetworkHierarchyCallbackHandler mock; + EXPECT_CALL(mock, OnNetworkHierarchyLeave); + + m_childEntity->FindComponent()->BindNetworkHierarchyLeaveEventHandler(mock.m_leaveHandler); + + // simulate server detaching a child entity + SetParentIdOnNetworkTransform(*m_childEntity, InvalidNetEntityId); + SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(*m_childEntity, InvalidNetEntityId); + } + /* * Parent -> Child -> ChildOfChild */ diff --git a/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h b/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h index 89d0d32428..d4f9d218e2 100644 --- a/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h +++ b/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h @@ -35,6 +35,29 @@ namespace Multiplayer using namespace testing; using namespace ::UnitTest; + class NetworkHierarchyCallbacks + { + public: + virtual void OnNetworkHierarchyLeave() = 0; + virtual void OnNetworkHierarchyUpdated(const AZ::EntityId& hierarchyRootId) = 0; + }; + + class MockNetworkHierarchyCallbackHandler : public NetworkHierarchyCallbacks + { + public: + MockNetworkHierarchyCallbackHandler() + : m_leaveHandler([this]() { OnNetworkHierarchyLeave(); }) + , m_changedHandler([this](const AZ::EntityId& rootId) { OnNetworkHierarchyUpdated(rootId); }) + { + } + + NetworkHierarchyLeaveEvent::Handler m_leaveHandler; + NetworkHierarchyChangedEvent::Handler m_changedHandler; + + MOCK_METHOD0(OnNetworkHierarchyLeave, void()); + MOCK_METHOD1(OnNetworkHierarchyUpdated, void(const AZ::EntityId&)); + }; + class HierarchyTests : public AllocatorsFixture { @@ -282,8 +305,9 @@ namespace Multiplayer NetworkOutputSerializer outSerializer(buffer.begin(), bufferSize); + ReplicationRecord notifyRecord = currentRecord; entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); - // now the parent id is in the component + entity.FindComponent()->NotifyStateDeltaChanges(notifyRecord); } template @@ -306,8 +330,9 @@ namespace Multiplayer NetworkOutputSerializer outSerializer(buffer.begin(), bufferSize); + ReplicationRecord notifyRecord = currentRecord; entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); - // now the parent id is in the component + entity.FindComponent()->NotifyStateDeltaChanges(notifyRecord); } struct EntityInfo From 714dc0a0e8255a62b72e87029a542cbf41957cb9 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Wed, 15 Sep 2021 11:29:10 -0400 Subject: [PATCH 14/84] Refactoring away the use of AZ::TransformNotificationBus. Added unittests for deactivating parents of inner roots. Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Components/NetworkHierarchyBus.h | 4 + .../NetworkHierarchyChildComponent.h | 21 +- .../NetworkHierarchyRootComponent.h | 29 ++- .../NetworkHierarchyChildComponent.cpp | 108 +++++++-- .../NetworkHierarchyRootComponent.cpp | 210 +++++++++++------- .../Code/Tests/ServerHierarchyTests.cpp | 35 +++ 6 files changed, 296 insertions(+), 111 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h index 1401856afe..45119a89e3 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyBus.h @@ -19,6 +19,10 @@ namespace Multiplayer : public AZ::ComponentBus { public: + //! @returns true if the entity a hierarchical component attached should be considered for inclusion in a hierarchy + //! this should return false when an entity is deactivating + virtual bool IsHierarchyEnabled() const = 0; + //! @returns hierarchical entities, the first element is the top level root virtual AZStd::vector GetHierarchicalEntities() const = 0; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h index 93ce3e25d0..2effb18bb8 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include @@ -42,12 +43,13 @@ namespace Multiplayer //! NetworkHierarchyChildComponentBase overrides. //! @{ void OnInit() override; - void OnActivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; - void OnDeactivate(Multiplayer::EntityIsMigrating entityIsMigrating) override; + void OnActivate(EntityIsMigrating entityIsMigrating) override; + void OnDeactivate(EntityIsMigrating entityIsMigrating) override; //! @} //! NetworkHierarchyRequestBus overrides. //! @{ + bool IsHierarchyEnabled() const override; bool IsHierarchicalChild() const override; bool IsHierarchicalRoot() const override { return false; } AZ::Entity* GetHierarchicalRoot() const override; @@ -58,15 +60,26 @@ namespace Multiplayer protected: //! Used by @NetworkHierarchyRootComponent - void SetTopLevelHierarchyRootComponent(NetworkHierarchyRootComponent* hierarchyRoot); + void SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot); private: - const NetworkHierarchyRootComponent* m_hierarchyRootComponent = nullptr; + AZ::ChildChangedEvent::Handler m_childChangedHandler; + AZ::ParentChangedEvent::Handler m_parentChangedHandler; + + void OnChildChanged(AZ::ChildChangeType type, AZ::EntityId child); + void OnParentChanged(AZ::EntityId oldParent, AZ::EntityId parent); + + //! Points to the top level root. + AZ::Entity* m_rootEntity = nullptr; AZ::Event::Handler m_hierarchyRootNetIdChanged; void OnHierarchyRootNetIdChanged(NetEntityId rootNetId); NetworkHierarchyChangedEvent m_networkHierarchyChangedEvent; NetworkHierarchyLeaveEvent m_networkHierarchyLeaveEvent; + + bool m_isDeactivating = false; + + void NotifyChildrenHierarchyDisbanded(); }; } diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h index 228f953a32..35f0da5965 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h @@ -10,8 +10,8 @@ #include #include -#include #include +#include namespace Multiplayer { @@ -27,8 +27,8 @@ namespace Multiplayer class NetworkHierarchyRootComponent final : public NetworkHierarchyRootComponentBase , public NetworkHierarchyRequestBus::Handler - , protected AZ::TransformNotificationBus::MultiHandler { + friend class NetworkHierarchyChildComponent; public: AZ_MULTIPLAYER_COMPONENT(Multiplayer::NetworkHierarchyRootComponent, s_networkHierarchyRootComponentConcreteUuid, Multiplayer::NetworkHierarchyRootComponentBase); @@ -37,6 +37,8 @@ namespace Multiplayer static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + NetworkHierarchyRootComponent(); + //! NetworkHierarchyRootComponentBase overrides. //! @{ void OnInit() override; @@ -46,6 +48,7 @@ namespace Multiplayer //! NetworkHierarchyRequestBus overrides. //! @{ + bool IsHierarchyEnabled() const override; bool IsHierarchicalRoot() const override; bool IsHierarchicalChild() const override; AZStd::vector GetHierarchicalEntities() const override; @@ -55,22 +58,24 @@ namespace Multiplayer //! @} protected: - //! AZ::TransformNotificationBus::Handler overrides. - //! @{ - void OnParentChanged(AZ::EntityId oldParent, AZ::EntityId newParent) override; - void OnChildAdded(AZ::EntityId child) override; - void OnChildRemoved(AZ::EntityId childRemovedId) override; - //! @} - void SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot); private: + AZ::ChildChangedEvent::Handler m_childChangedHandler; + AZ::ParentChangedEvent::Handler m_parentChangedHandler; + + void OnChildChanged(AZ::ChildChangeType type, AZ::EntityId child); + void OnParentChanged(AZ::EntityId oldParent, AZ::EntityId parent); + NetworkHierarchyChangedEvent m_networkHierarchyChangedEvent; NetworkHierarchyLeaveEvent m_networkHierarchyLeaveEvent; - AZ::Entity* m_higherRootEntity = nullptr; + //! Points to the top level root, if this root is an inner root in this hierarchy. + AZ::Entity* m_rootEntity = nullptr; + AZStd::vector m_hierarchicalEntities; + //! Rebuilds hierarchy starting from this root component's entity. void RebuildHierarchy(); //! @param underEntity Walk the child entities that belong to @underEntity and consider adding them to the hierarchy @@ -86,5 +91,9 @@ namespace Multiplayer //! @currentEntityCount will be modified to reflect the total entity count upon completion of this method. //! @returns false if an attempt was made to go beyond the maximum supported hierarchy size, true otherwise bool RecursiveAttachHierarchicalChild(AZ::EntityId entity, uint32_t& currentEntityCount); + + void SetRootForEntity(AZ::Entity* root, const AZ::Entity* childEntity); + + bool m_isDeactivating = false; }; } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp index 93574ec5b4..eff051ed93 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -53,7 +54,9 @@ namespace Multiplayer } NetworkHierarchyChildComponent::NetworkHierarchyChildComponent() - : m_hierarchyRootNetIdChanged([this](NetEntityId rootNetId) {OnHierarchyRootNetIdChanged(rootNetId); }) + : m_childChangedHandler([this](AZ::ChildChangeType type, AZ::EntityId child) { OnChildChanged(type, child); }) + , m_parentChangedHandler([this](AZ::EntityId oldParent, AZ::EntityId parent) { OnParentChanged(oldParent, parent); }) + , m_hierarchyRootNetIdChanged([this](NetEntityId rootNetId) {OnHierarchyRootNetIdChanged(rootNetId); }) { } @@ -66,13 +69,36 @@ namespace Multiplayer { HierarchyRootAddEvent(m_hierarchyRootNetIdChanged); NetworkHierarchyRequestBus::Handler::BusConnect(GetEntityId()); + + if (AzFramework::TransformComponent* transformComponent = GetEntity()->FindComponent()) + { + transformComponent->BindChildChangedEventHandler(m_childChangedHandler); + transformComponent->BindParentChangedEventHandler(m_parentChangedHandler); + } } void NetworkHierarchyChildComponent::OnDeactivate([[maybe_unused]] EntityIsMigrating entityIsMigrating) { + m_isDeactivating = true; + + if (m_rootEntity) + { + if (NetworkHierarchyRootComponent* root = m_rootEntity->FindComponent()) + { + root->RebuildHierarchy(); + } + } + + NotifyChildrenHierarchyDisbanded(); + NetworkHierarchyRequestBus::Handler::BusDisconnect(); } + bool NetworkHierarchyChildComponent::IsHierarchyEnabled() const + { + return !m_isDeactivating; + } + bool NetworkHierarchyChildComponent::IsHierarchicalChild() const { if (GetHierarchyRoot() != InvalidNetEntityId) @@ -85,14 +111,14 @@ namespace Multiplayer AZ::Entity* NetworkHierarchyChildComponent::GetHierarchicalRoot() const { - return m_hierarchyRootComponent ? m_hierarchyRootComponent->GetEntity() : nullptr; + return m_rootEntity; } AZStd::vector NetworkHierarchyChildComponent::GetHierarchicalEntities() const { - if (m_hierarchyRootComponent) + if (m_rootEntity) { - return m_hierarchyRootComponent->GetHierarchicalEntities(); + return m_rootEntity->FindComponent()->GetHierarchicalEntities(); } return {}; @@ -108,18 +134,18 @@ namespace Multiplayer handler.Connect(m_networkHierarchyLeaveEvent); } - void NetworkHierarchyChildComponent::SetTopLevelHierarchyRootComponent(NetworkHierarchyRootComponent* hierarchyRoot) + void NetworkHierarchyChildComponent::SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot) { - m_hierarchyRootComponent = hierarchyRoot; + m_rootEntity = hierarchyRoot; if (HasController() && GetNetBindComponent()->GetNetEntityRole() == NetEntityRole::Authority) { NetworkHierarchyChildComponentController* controller = static_cast(GetController()); - if (hierarchyRoot) + if (m_rootEntity) { - const NetEntityId netRootId = GetNetworkEntityManager()->GetNetEntityIdById(hierarchyRoot->GetEntityId()); + const NetEntityId netRootId = GetNetworkEntityManager()->GetNetEntityIdById(m_rootEntity->GetId()); controller->SetHierarchyRoot(netRootId); - m_networkHierarchyChangedEvent.Signal(hierarchyRoot->GetEntityId()); + m_networkHierarchyChangedEvent.Signal(m_rootEntity->GetId()); } else { @@ -128,20 +154,74 @@ namespace Multiplayer m_networkHierarchyLeaveEvent.Signal(); } } + + if (m_rootEntity == nullptr) + { + NotifyChildrenHierarchyDisbanded(); + } + } + + void NetworkHierarchyChildComponent::OnChildChanged([[maybe_unused]] AZ::ChildChangeType type, [[maybe_unused]] AZ::EntityId child) + { + if (m_rootEntity) + { + if (NetworkHierarchyRootComponent* root = m_rootEntity->FindComponent()) + { + root->RebuildHierarchy(); + } + } + } + + void NetworkHierarchyChildComponent::OnParentChanged([[maybe_unused]] AZ::EntityId oldParent, [[maybe_unused]] AZ::EntityId parent) + { + if (m_rootEntity) + { + if (NetworkHierarchyRootComponent* root = m_rootEntity->FindComponent()) + { + root->RebuildHierarchy(); + } + } } void NetworkHierarchyChildComponent::OnHierarchyRootNetIdChanged(NetEntityId rootNetId) { - const ConstNetworkEntityHandle rootHandle = GetNetworkEntityManager()->GetEntity(rootNetId); + ConstNetworkEntityHandle rootHandle = GetNetworkEntityManager()->GetEntity(rootNetId); if (rootHandle.Exists()) { - m_hierarchyRootComponent = rootHandle.FindComponent(); - m_networkHierarchyChangedEvent.Signal(m_hierarchyRootComponent->GetEntityId()); + AZ::Entity* newRoot = rootHandle.GetEntity(); + if (m_rootEntity != newRoot) + { + m_rootEntity = newRoot; + m_networkHierarchyChangedEvent.Signal(m_rootEntity->GetId()); + } } else { - m_hierarchyRootComponent = nullptr; - m_networkHierarchyLeaveEvent.Signal(); + if (!m_rootEntity) + { + m_rootEntity = nullptr; + m_networkHierarchyLeaveEvent.Signal(); + } + } + } + + void NetworkHierarchyChildComponent::NotifyChildrenHierarchyDisbanded() + { + AZStd::vector allChildren; + AZ::TransformBus::EventResult(allChildren, GetEntityId(), &AZ::TransformBus::Events::GetChildren); + for (const AZ::EntityId& childEntityId : allChildren) + { + if (const AZ::Entity* childEntity = AZ::Interface::Get()->FindEntity(childEntityId)) + { + if (auto* hierarchyChildComponent = childEntity->FindComponent()) + { + hierarchyChildComponent->SetTopLevelHierarchyRootEntity(nullptr); + } + else if (auto* hierarchyRootComponent = childEntity->FindComponent()) + { + hierarchyRootComponent->SetTopLevelHierarchyRootEntity(nullptr); + } + } } } } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp index ced2c79bce..d2b45a8971 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,12 @@ namespace Multiplayer incompatible.push_back(AZ_CRC_CE("NetworkHierarchyRootComponent")); } + NetworkHierarchyRootComponent::NetworkHierarchyRootComponent() + : m_childChangedHandler([this](AZ::ChildChangeType type, AZ::EntityId child) { OnChildChanged(type, child); }) + , m_parentChangedHandler([this](AZ::EntityId oldParent, AZ::EntityId parent) { OnParentChanged(oldParent, parent); }) + { + } + void NetworkHierarchyRootComponent::OnInit() { } @@ -67,31 +74,54 @@ namespace Multiplayer m_hierarchicalEntities.push_back(GetEntity()); NetworkHierarchyRequestBus::Handler::BusConnect(GetEntityId()); - AZ::TransformNotificationBus::MultiHandler::BusConnect(GetEntityId()); + + if (AzFramework::TransformComponent* transformComponent = GetEntity()->FindComponent()) + { + transformComponent->BindChildChangedEventHandler(m_childChangedHandler); + transformComponent->BindParentChangedEventHandler(m_parentChangedHandler); + } } void NetworkHierarchyRootComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) { - AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); - NetworkHierarchyRequestBus::Handler::BusDisconnect(); + m_isDeactivating = true; - for (const AZ::Entity* childEntity : m_hierarchicalEntities) + if (m_rootEntity) { - auto* hierarchyChildComponent = childEntity->FindComponent(); - auto* hierarchyRootComponent = childEntity->FindComponent(); - - if (hierarchyChildComponent) + // tell parent to re-build the hierarchy + if (NetworkHierarchyRootComponent* root = m_rootEntity->FindComponent()) { - hierarchyChildComponent->SetTopLevelHierarchyRootComponent(nullptr); + root->RebuildHierarchy(); } - if (hierarchyRootComponent) + } + else + { + // notify children to that a hierarchy is disbanded + + AZStd::vector allChildren; + AZ::TransformBus::EventResult(allChildren, GetEntityId(), &AZ::TransformBus::Events::GetChildren); + + for (const AZ::EntityId& childEntityId : allChildren) { - hierarchyRootComponent->SetTopLevelHierarchyRootEntity(nullptr); + if (const AZ::Entity* childEntity = AZ::Interface::Get()->FindEntity(childEntityId)) + { + SetRootForEntity(nullptr, childEntity); + } } } + m_childChangedHandler.Disconnect(); + m_parentChangedHandler.Disconnect(); + + NetworkHierarchyRequestBus::Handler::BusDisconnect(); + m_hierarchicalEntities.clear(); - m_higherRootEntity = nullptr; + m_rootEntity = nullptr; + } + + bool NetworkHierarchyRootComponent::IsHierarchyEnabled() const + { + return !m_isDeactivating; } bool NetworkHierarchyRootComponent::IsHierarchicalRoot() const @@ -116,9 +146,9 @@ namespace Multiplayer AZ::Entity* NetworkHierarchyRootComponent::GetHierarchicalRoot() const { - if (m_higherRootEntity) + if (m_rootEntity) { - return m_higherRootEntity; + return m_rootEntity; } return GetEntity(); @@ -134,24 +164,36 @@ namespace Multiplayer handler.Connect(m_networkHierarchyLeaveEvent); } + void NetworkHierarchyRootComponent::OnChildChanged([[maybe_unused]] AZ::ChildChangeType type, [[maybe_unused]] AZ::EntityId child) + { + if (IsHierarchicalRoot()) + { + // Parent-child notifications are not reliable enough to avoid duplicate notifications, + // so we will rebuild from scratch to avoid duplicate entries in @m_hierarchicalEntities. + RebuildHierarchy(); + } + else if (NetworkHierarchyRootComponent* root = GetHierarchicalRoot()->FindComponent()) + { + root->RebuildHierarchy(); + } + } + void NetworkHierarchyRootComponent::OnParentChanged([[maybe_unused]] AZ::EntityId oldParent, AZ::EntityId newParent) { - const AZ::EntityId entityBusId = *AZ::TransformNotificationBus::GetCurrentBusId(); - if (GetEntityId() != entityBusId) - { - return; // ignore parent changes of child entities - } + // If the parent is part of a hierarchy, it will detect this entity as a new child and rebuild hierarchy. + // Thus, we only need to take care of a case when the parent is not part of a hierarchy, + // in which case, this entity will be a new root of a new hierarchy. if (AZ::Entity* parentEntity = AZ::Interface::Get()->FindEntity(newParent)) { - if (parentEntity->FindComponent()) + if (parentEntity->FindComponent() == nullptr && + parentEntity->FindComponent() == nullptr) + { + RebuildHierarchy(); + } + else { - m_higherRootEntity = parentEntity; m_hierarchicalEntities.clear(); - AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); - - // Should still listen for its events, such as when this root detaches - AZ::TransformNotificationBus::MultiHandler::BusConnect(GetEntityId()); } } else @@ -161,25 +203,63 @@ namespace Multiplayer } } - void NetworkHierarchyRootComponent::OnChildAdded([[maybe_unused]] AZ::EntityId child) - { - // Parent-child notifications from TransformNotificationBus are not reliable enough to avoid duplicate notifications, - // so we will rebuild from scratch to avoid duplicate entries in @m_hierarchicalEntities. - RebuildHierarchy(); - } - void NetworkHierarchyRootComponent::RebuildHierarchy() { - m_hierarchicalEntities.clear(); - m_hierarchicalEntities.push_back(GetEntity()); // add the root itself + AZStd::vector previousEntities; + m_hierarchicalEntities.swap(previousEntities); - AZ::TransformNotificationBus::MultiHandler::BusDisconnect(); - AZ::TransformNotificationBus::MultiHandler::BusConnect(GetEntityId()); + m_hierarchicalEntities.push_back(GetEntity()); // Add the root. uint32_t currentEntityCount = aznumeric_cast(m_hierarchicalEntities.size()); RecursiveAttachHierarchicalEntities(GetEntityId(), currentEntityCount); - m_networkHierarchyChangedEvent.Signal(GetEntityId()); + bool hierarchyChanged = false; + + // Send out join and leave events. + + for (AZ::Entity* currentEntity : m_hierarchicalEntities) + { + const auto prevEntityIterator = AZStd::find(previousEntities.begin(), previousEntities.end(), currentEntity); + if (prevEntityIterator != previousEntities.end()) + { + // This entity was here before the build of the hierarchy. + previousEntities.erase(prevEntityIterator); + } + else + { + // This is a newly added entity to the network hierarchy. + hierarchyChanged = true; + SetRootForEntity(GetEntity(), currentEntity); + } + } + + // These entities were removed since last rebuild. + for (const AZ::Entity* previousEntity : previousEntities) + { + SetRootForEntity(nullptr, previousEntity); + } + + if (!previousEntities.empty()) + { + hierarchyChanged = true; + } + + if (hierarchyChanged) + { + m_networkHierarchyChangedEvent.Signal(GetEntityId()); + } + } + + void NetworkHierarchyRootComponent::SetRootForEntity(AZ::Entity* root, const AZ::Entity* childEntity) + { + if (auto* hierarchyChildComponent = childEntity->FindComponent()) + { + hierarchyChildComponent->SetTopLevelHierarchyRootEntity(root); + } + else if (auto* hierarchyRootComponent = childEntity->FindComponent()) + { + hierarchyRootComponent->SetTopLevelHierarchyRootEntity(root); + } } bool NetworkHierarchyRootComponent::RecursiveAttachHierarchicalEntities(AZ::EntityId underEntity, uint32_t& currentEntityCount) @@ -212,21 +292,12 @@ namespace Multiplayer auto* hierarchyChildComponent = childEntity->FindComponent(); auto* hierarchyRootComponent = childEntity->FindComponent(); - if (hierarchyChildComponent || hierarchyRootComponent) + if ((hierarchyChildComponent && hierarchyChildComponent->IsHierarchyEnabled()) || + (hierarchyRootComponent && hierarchyRootComponent->IsHierarchyEnabled())) { - AZ::TransformNotificationBus::MultiHandler::BusConnect(entity); m_hierarchicalEntities.push_back(childEntity); ++currentEntityCount; - if (hierarchyChildComponent) - { - hierarchyChildComponent->SetTopLevelHierarchyRootComponent(this); - } - else if (hierarchyRootComponent) - { - hierarchyRootComponent->SetTopLevelHierarchyRootEntity(GetEntity()); - } - if (!RecursiveAttachHierarchicalEntities(entity, currentEntityCount)) { return false; @@ -237,43 +308,10 @@ namespace Multiplayer return true; } - void NetworkHierarchyRootComponent::OnChildRemoved(AZ::EntityId childRemovedId) - { - AZStd::vector allChildren; - AZ::TransformBus::EventResult(allChildren, childRemovedId, &AZ::TransformBus::Events::GetEntityAndAllDescendants); - - for (AZ::EntityId childId : allChildren) - { - AZ::TransformNotificationBus::MultiHandler::BusDisconnect(childId); - - const AZ::Entity* childEntity = nullptr; - - AZStd::erase_if(m_hierarchicalEntities, [childId, &childEntity](const AZ::Entity* entity) - { - if (entity->GetId() == childId) - { - childEntity = entity; - return true; - } - - return false; - }); - - if (childEntity) - { - if (NetworkHierarchyChildComponent* childComponent = childEntity->FindComponent()) - { - childComponent->SetTopLevelHierarchyRootComponent(nullptr); - } - } - } - - m_networkHierarchyChangedEvent.Signal(GetEntityId()); - } - void NetworkHierarchyRootComponent::SetTopLevelHierarchyRootEntity(AZ::Entity* hierarchyRoot) { - m_higherRootEntity = hierarchyRoot; + m_rootEntity = hierarchyRoot; + if (HasController() && GetNetBindComponent()->GetNetEntityRole() == NetEntityRole::Authority) { NetworkHierarchyChildComponentController* controller = static_cast(GetController()); @@ -287,5 +325,11 @@ namespace Multiplayer controller->SetHierarchyRoot(InvalidNetEntityId); } } + + if (m_rootEntity == nullptr) + { + // We lost the parent hierarchical entity, so as a root we need to re-build our own hierarchy. + RebuildHierarchy(); + } } } diff --git a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp index 708a39d439..0b76e276fd 100644 --- a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp @@ -847,6 +847,41 @@ namespace Multiplayer ); } + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Top_Root_Deactivates) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + + StopAndDeleteEntity(m_rootEntity); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Child_Of_Top_Root_Deactivates) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + + StopAndDeleteEntity(m_childEntity); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Child_Of_Child_Deactivates) + { + m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + StopAndDeleteEntity(m_childOfChildEntity); + + EXPECT_EQ( + m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + TEST_F(ServerHierarchyOfHierarchyTests, Stress_Test_Inner_Root_Has_Child_References_After_Detachment_From_Child_Of_Child) { for (int i = 0; i < 100; ++i) From c673988935b0602c8ed33b347c02bbc1605e178f Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Wed, 15 Sep 2021 17:58:06 -0400 Subject: [PATCH 15/84] Unittest refactoring Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Code/Tests/ClientHierarchyTests.cpp | 160 ++-- .../Code/Tests/CommonHierarchySetup.h | 82 +- .../Code/Tests/ServerHierarchyTests.cpp | 754 +++++++++--------- 3 files changed, 507 insertions(+), 489 deletions(-) diff --git a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp index 1483f32023..38ea451c85 100644 --- a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp @@ -27,14 +27,14 @@ namespace Multiplayer */ TEST_F(HierarchyTests, On_Client_NetBindComponent_Activate) { - AZ::Entity entity; - entity.CreateComponent(); + AZStd::unique_ptr entity = AZStd::make_unique(); + entity->CreateComponent(); SetupEntity(entity, NetEntityId{ 1 }, NetEntityRole::Client); - entity.Activate(); + entity->Activate(); StopEntity(entity); - entity.Deactivate(); + entity->Deactivate(); } /* @@ -43,7 +43,7 @@ namespace Multiplayer TEST_F(HierarchyTests, On_Client_EntityReplicator_DontActivate_BeforeParent) { // Create a child entity that will be tested for activation inside a hierarchy - AZ::Entity childEntity; + AZStd::unique_ptr childEntity = AZStd::make_unique(); CreateEntityWithChildHierarchy(childEntity); SetupEntity(childEntity, NetEntityId{ 2 }, NetEntityRole::Client); // child entity is not activated on purpose here, we are about to test conditional activation check @@ -53,7 +53,7 @@ namespace Multiplayer SetHierarchyRootFieldOnNetworkHierarchyChild(childEntity, NetEntityId{ 1 }); // Create an entity replicator for the child entity - const NetworkEntityHandle childHandle(&childEntity, m_networkEntityTracker.get()); + const NetworkEntityHandle childHandle(childEntity.get(), m_networkEntityTracker.get()); EntityReplicator entityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childHandle); entityReplicator.Initialize(childHandle); @@ -64,7 +64,7 @@ namespace Multiplayer TEST_F(HierarchyTests, On_Client_EntityReplicator_DontActivate_Inner_Root_Before_Top_Root) { // Create a child entity that will be tested for activation inside a hierarchy - AZ::Entity innerRootEntity; + AZStd::unique_ptr innerRootEntity = AZStd::make_unique(); CreateEntityWithRootHierarchy(innerRootEntity); SetupEntity(innerRootEntity, NetEntityId{ 2 }, NetEntityRole::Client); // child entity is not activated on purpose here, we are about to test conditional activation check @@ -74,7 +74,7 @@ namespace Multiplayer SetHierarchyRootFieldOnNetworkHierarchyChild(innerRootEntity, NetEntityId{ 1 }); // Create an entity replicator for the child entity - const NetworkEntityHandle innerRootHandle(&innerRootEntity, m_networkEntityTracker.get()); + const NetworkEntityHandle innerRootHandle(innerRootEntity.get(), m_networkEntityTracker.get()); EntityReplicator entityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, innerRootHandle); entityReplicator.Initialize(innerRootHandle); @@ -85,7 +85,7 @@ namespace Multiplayer TEST_F(HierarchyTests, On_Client_Not_In_Hierarchy_EntityReplicator_Ignores_Parent) { // Create a child entity that will be tested for activation inside a hierarchy - AZ::Entity childEntity; + AZStd::unique_ptr childEntity = AZStd::make_unique(); CreateEntityWithChildHierarchy(childEntity); SetupEntity(childEntity, NetEntityId{ 2 }, NetEntityRole::Client); // child entity is not activated on purpose here, we are about to test conditional activation check @@ -95,7 +95,7 @@ namespace Multiplayer SetHierarchyRootFieldOnNetworkHierarchyChild(childEntity, InvalidNetEntityId); // Create an entity replicator for the child entity - const NetworkEntityHandle childHandle(&childEntity, m_networkEntityTracker.get()); + const NetworkEntityHandle childHandle(childEntity.get(), m_networkEntityTracker.get()); EntityReplicator entityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childHandle); entityReplicator.Initialize(childHandle); @@ -108,7 +108,7 @@ namespace Multiplayer */ TEST_F(HierarchyTests, On_Client_EntityReplicator_Activates_AfterParent) { - AZ::Entity childEntity; + AZStd::unique_ptr childEntity = AZStd::make_unique(); CreateEntityWithChildHierarchy(childEntity); SetupEntity(childEntity, NetEntityId{ 2 }, NetEntityRole::Client); @@ -117,29 +117,29 @@ namespace Multiplayer SetHierarchyRootFieldOnNetworkHierarchyChild(childEntity, NetEntityId{ 1 }); // Create an entity replicator for the child entity - const NetworkEntityHandle childHandle(&childEntity, m_networkEntityTracker.get()); + const NetworkEntityHandle childHandle(childEntity.get(), m_networkEntityTracker.get()); EntityReplicator childEntityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childHandle); childEntityReplicator.Initialize(childHandle); // Now let's create a parent entity and activate it - AZ::Entity parentEntity; + AZStd::unique_ptr parentEntity = AZStd::make_unique(); CreateEntityWithRootHierarchy(parentEntity); SetupEntity(parentEntity, NetEntityId{ 1 }, NetEntityRole::Client); // Create an entity replicator for the parent entity - const NetworkEntityHandle parentHandle(&parentEntity, m_networkEntityTracker.get()); + const NetworkEntityHandle parentHandle(parentEntity.get(), m_networkEntityTracker.get()); ON_CALL(*m_mockNetworkEntityManager, GetEntity(_)).WillByDefault(Return(parentHandle)); EntityReplicator parentEntityReplicator(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, parentHandle); parentEntityReplicator.Initialize(parentHandle); - parentEntity.Activate(); + parentEntity->Activate(); // The child should be ready to be activated EXPECT_EQ(childEntityReplicator.IsReadyToActivate(), true); StopEntity(parentEntity); - parentEntity.Deactivate(); + parentEntity->Deactivate(); } /* @@ -155,25 +155,19 @@ namespace Multiplayer { HierarchyTests::SetUp(); - m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); - m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); + m_root = AZStd::make_unique(1, "root", RootNetEntityId, EntityInfo::Role::Root); + m_child = AZStd::make_unique(2, "child", ChildNetEntityId, EntityInfo::Role::Child); - m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), RootNetEntityId, EntityInfo::Role::Root); - m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), ChildNetEntityId, EntityInfo::Role::Child); + CreateSimpleHierarchy(*m_root, *m_child); - CreateSimpleHierarchy(*m_rootEntityInfo, *m_childEntityInfo); - - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_child->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); // now the two entities are under one hierarchy } void TearDown() override { - m_childEntityInfo.reset(); - m_rootEntityInfo.reset(); - - StopAndDeleteEntity(m_childEntity); - StopAndDeleteEntity(m_rootEntity); + m_child.reset(); + m_root.reset(); HierarchyTests::TearDown(); } @@ -191,20 +185,20 @@ namespace Multiplayer SetHierarchyRootFieldOnNetworkHierarchyChild(child.m_entity, root.m_netId); // Create an entity replicator for the child entity - const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle childHandle(child.m_entity.get(), m_networkEntityTracker.get()); child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childHandle); child.m_replicator->Initialize(childHandle); // Create an entity replicator for the root entity - const NetworkEntityHandle rootHandle(&root.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle rootHandle(root.m_entity.get(), m_networkEntityTracker.get()); root.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, rootHandle); root.m_replicator->Initialize(rootHandle); - root.m_entity.Activate(); - child.m_entity.Activate(); + root.m_entity->Activate(); + child.m_entity->Activate(); } - void SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(const AZ::Entity& entity, NetEntityId value) + void SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(const AZStd::unique_ptr& entity, NetEntityId value) { /* Derived from NetworkHierarchyChildComponent.AutoComponent.xml */ constexpr int totalBits = 1 /*NetworkHierarchyChildComponentInternal::AuthorityToClientDirtyEnum::Count*/; @@ -225,47 +219,44 @@ namespace Multiplayer ReplicationRecord notifyRecord = currentRecord; - entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); - entity.FindComponent()->NotifyStateDeltaChanges(notifyRecord); + entity->FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); + entity->FindComponent()->NotifyStateDeltaChanges(notifyRecord); } - AZStd::unique_ptr m_rootEntity; - AZStd::unique_ptr m_childEntity; - - AZStd::unique_ptr m_rootEntityInfo; - AZStd::unique_ptr m_childEntityInfo; + AZStd::unique_ptr m_root; + AZStd::unique_ptr m_child; }; TEST_F(ClientSimpleHierarchyTests, Client_Activates_Hierarchy_From_Network_Fields) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchyRoot(), + m_root->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchicalRoot(), - m_rootEntity.get() + m_child->m_entity->FindComponent()->GetHierarchicalRoot(), + m_root->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); - if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 2) + if (m_root->m_entity->FindComponent()->GetHierarchicalEntities().size() == 2) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], - m_rootEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[0], + m_root->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], - m_childEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[1], + m_child->m_entity.get() ); } } @@ -273,15 +264,15 @@ namespace Multiplayer TEST_F(ClientSimpleHierarchyTests, Client_Detaches_Child_When_Server_Detaches) { // simulate server detaching child entity - SetParentIdOnNetworkTransform(*m_childEntity, InvalidNetEntityId); - SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(*m_childEntity, InvalidNetEntityId); + SetParentIdOnNetworkTransform(m_child->m_entity, InvalidNetEntityId); + SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(m_child->m_entity, InvalidNetEntityId); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchicalRoot(), + m_child->m_entity->FindComponent()->GetHierarchicalRoot(), nullptr ); } @@ -289,13 +280,13 @@ namespace Multiplayer TEST_F(ClientSimpleHierarchyTests, Client_Sends_NetworkHierarchy_Updated_Event_On_Child_Detached_On_Server) { MockNetworkHierarchyCallbackHandler mock; - EXPECT_CALL(mock, OnNetworkHierarchyUpdated(m_rootEntity->GetId())); + EXPECT_CALL(mock, OnNetworkHierarchyUpdated(m_root->m_entity->GetId())); - m_rootEntity->FindComponent()->BindNetworkHierarchyChangedEventHandler(mock.m_changedHandler); + m_root->m_entity->FindComponent()->BindNetworkHierarchyChangedEventHandler(mock.m_changedHandler); // simulate server detaching a child entity - SetParentIdOnNetworkTransform(*m_childEntity, InvalidNetEntityId); - SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(*m_childEntity, InvalidNetEntityId); + SetParentIdOnNetworkTransform(m_child->m_entity, InvalidNetEntityId); + SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(m_child->m_entity, InvalidNetEntityId); } TEST_F(ClientSimpleHierarchyTests, Client_Sends_NetworkHierarchy_Leave_Event_On_Child_Detached_On_Server) @@ -303,11 +294,11 @@ namespace Multiplayer MockNetworkHierarchyCallbackHandler mock; EXPECT_CALL(mock, OnNetworkHierarchyLeave); - m_childEntity->FindComponent()->BindNetworkHierarchyLeaveEventHandler(mock.m_leaveHandler); + m_child->m_entity->FindComponent()->BindNetworkHierarchyLeaveEventHandler(mock.m_leaveHandler); // simulate server detaching a child entity - SetParentIdOnNetworkTransform(*m_childEntity, InvalidNetEntityId); - SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(*m_childEntity, InvalidNetEntityId); + SetParentIdOnNetworkTransform(m_child->m_entity, InvalidNetEntityId); + SetHierarchyRootFieldOnNetworkHierarchyChildOnClient(m_child->m_entity, InvalidNetEntityId); } /* @@ -322,18 +313,16 @@ namespace Multiplayer { ClientSimpleHierarchyTests::SetUp(); - m_childOfChildEntity = AZStd::make_unique(AZ::EntityId(3), "child of child"); - m_childOfChildEntityInfo = AZStd::make_unique(*m_childOfChildEntity.get(), ChildOfChildNetEntityId, EntityInfo::Role::Child); + m_childOfChild = AZStd::make_unique((3), "child of child", ChildOfChildNetEntityId, EntityInfo::Role::Child); - CreateDeepHierarchyOnClient(*m_childOfChildEntityInfo); + CreateDeepHierarchyOnClient(*m_childOfChild); - m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + m_childOfChild->m_entity->FindComponent()->SetParent(m_child->m_entity->GetId()); } void TearDown() override { - m_childOfChildEntityInfo.reset(); - StopAndDeleteEntity(m_childOfChildEntity); + m_childOfChild.reset(); ClientSimpleHierarchyTests::TearDown(); } @@ -344,58 +333,57 @@ namespace Multiplayer SetupEntity(childOfChild.m_entity, childOfChild.m_netId, NetEntityRole::Client); // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) - SetParentIdOnNetworkTransform(childOfChild.m_entity, m_childEntityInfo->m_netId); - SetHierarchyRootFieldOnNetworkHierarchyChild(childOfChild.m_entity, m_rootEntityInfo->m_netId); + SetParentIdOnNetworkTransform(childOfChild.m_entity, m_childOfChild->m_netId); + SetHierarchyRootFieldOnNetworkHierarchyChild(childOfChild.m_entity, m_root->m_netId); // Create an entity replicator for the child entity - const NetworkEntityHandle childOfChildHandle(&childOfChild.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle childOfChildHandle(childOfChild.m_entity.get(), m_networkEntityTracker.get()); childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Authority, childOfChildHandle); childOfChild.m_replicator->Initialize(childOfChildHandle); - childOfChild.m_entity.Activate(); + childOfChild.m_entity->Activate(); } - AZStd::unique_ptr m_childOfChildEntity; - AZStd::unique_ptr m_childOfChildEntityInfo; + AZStd::unique_ptr m_childOfChild; }; TEST_F(ClientDeepHierarchyTests, Client_Activates_Hierarchy_From_Network_Fields) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchyRoot(), + m_root->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); EXPECT_EQ( - m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + m_childOfChild->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchicalRoot(), - m_rootEntity.get() + m_child->m_entity->FindComponent()->GetHierarchicalRoot(), + m_root->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); - if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 3) + if (m_root->m_entity->FindComponent()->GetHierarchicalEntities().size() == 3) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], - m_rootEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[0], + m_root->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], - m_childEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[1], + m_child->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], - m_childOfChildEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChild->m_entity.get() ); } } diff --git a/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h b/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h index d4f9d218e2..7fc1eef8b7 100644 --- a/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h +++ b/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h @@ -38,6 +38,7 @@ namespace Multiplayer class NetworkHierarchyCallbacks { public: + virtual ~NetworkHierarchyCallbacks() = default; virtual void OnNetworkHierarchyLeave() = 0; virtual void OnNetworkHierarchyUpdated(const AZ::EntityId& hierarchyRootId) = 0; }; @@ -245,48 +246,48 @@ namespace Multiplayer return nullptr; } - void SetupEntity(AZ::Entity& entity, NetEntityId netId, NetEntityRole role) + void SetupEntity(const AZStd::unique_ptr& entity, NetEntityId netId, NetEntityRole role) { - const auto netBindComponent = entity.FindComponent(); + const auto netBindComponent = entity->FindComponent(); EXPECT_NE(netBindComponent, nullptr); - netBindComponent->PreInit(&entity, PrefabEntityId{ AZ::Name("test"), 1 }, netId, role); - entity.Init(); + netBindComponent->PreInit(entity.get(), PrefabEntityId{ AZ::Name("test"), 1 }, netId, role); + entity->Init(); } - void StopEntity(const AZ::Entity& entity) + static void StopEntity(const AZStd::unique_ptr& entity) { - const auto netBindComponent = entity.FindComponent(); + const auto netBindComponent = entity->FindComponent(); EXPECT_NE(netBindComponent, nullptr); netBindComponent->StopEntity(); } - void StopAndDeleteEntity(AZStd::unique_ptr& entity) + static void StopAndDeactivateEntity(AZStd::unique_ptr& entity) { if (entity) { - StopEntity(*entity); + StopEntity(entity); entity->Deactivate(); entity.reset(); } } - void CreateEntityWithRootHierarchy(AZ::Entity& rootEntity) + void CreateEntityWithRootHierarchy(AZStd::unique_ptr& rootEntity) { - rootEntity.CreateComponent(); - rootEntity.CreateComponent(); - rootEntity.CreateComponent(); - rootEntity.CreateComponent(); + rootEntity->CreateComponent(); + rootEntity->CreateComponent(); + rootEntity->CreateComponent(); + rootEntity->CreateComponent(); } - void CreateEntityWithChildHierarchy(AZ::Entity& childEntity) + void CreateEntityWithChildHierarchy(AZStd::unique_ptr& childEntity) { - childEntity.CreateComponent(); - childEntity.CreateComponent(); - childEntity.CreateComponent(); - childEntity.CreateComponent(); + childEntity->CreateComponent(); + childEntity->CreateComponent(); + childEntity->CreateComponent(); + childEntity->CreateComponent(); } - void SetParentIdOnNetworkTransform(const AZ::Entity& entity, NetEntityId netParentId) + void SetParentIdOnNetworkTransform(const AZStd::unique_ptr& entity, NetEntityId netParentId) { /* Derived from NetworkTransformComponent.AutoComponent.xml */ constexpr int totalBits = 6 /*NetworkTransformComponentInternal::AuthorityToClientDirtyEnum::Count*/; @@ -306,12 +307,12 @@ namespace Multiplayer NetworkOutputSerializer outSerializer(buffer.begin(), bufferSize); ReplicationRecord notifyRecord = currentRecord; - entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); - entity.FindComponent()->NotifyStateDeltaChanges(notifyRecord); + entity->FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); + entity->FindComponent()->NotifyStateDeltaChanges(notifyRecord); } template - void SetHierarchyRootFieldOnNetworkHierarchyChild(const AZ::Entity& entity, NetEntityId value) + void SetHierarchyRootFieldOnNetworkHierarchyChild(const AZStd::unique_ptr& entity, NetEntityId value) { /* Derived from NetworkHierarchyChildComponent.AutoComponent.xml */ constexpr int totalBits = 1 /*NetworkHierarchyChildComponentInternal::AuthorityToClientDirtyEnum::Count*/; @@ -331,8 +332,8 @@ namespace Multiplayer NetworkOutputSerializer outSerializer(buffer.begin(), bufferSize); ReplicationRecord notifyRecord = currentRecord; - entity.FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); - entity.FindComponent()->NotifyStateDeltaChanges(notifyRecord); + entity->FindComponent()->SerializeStateDeltaMessage(currentRecord, outSerializer); + entity->FindComponent()->NotifyStateDeltaChanges(notifyRecord); } struct EntityInfo @@ -344,14 +345,19 @@ namespace Multiplayer None }; - EntityInfo(AZ::Entity& entity, NetEntityId netId, Role role) - : m_entity(entity) + EntityInfo(AZ::u64 entityId, const char* entityName, NetEntityId netId, Role role) + : m_entity(AZStd::make_unique(AZ::EntityId(entityId), entityName)) , m_netId(netId) , m_role(role) { } - AZ::Entity& m_entity; + ~EntityInfo() + { + StopAndDeactivateEntity(m_entity); + } + + AZStd::unique_ptr m_entity; NetEntityId m_netId; AZStd::unique_ptr m_replicator; Role m_role = Role::None; @@ -359,16 +365,16 @@ namespace Multiplayer void PopulateHierarchicalEntity(const EntityInfo& entityInfo) { - entityInfo.m_entity.CreateComponent(); - entityInfo.m_entity.CreateComponent(); - entityInfo.m_entity.CreateComponent(); + entityInfo.m_entity->CreateComponent(); + entityInfo.m_entity->CreateComponent(); + entityInfo.m_entity->CreateComponent(); switch (entityInfo.m_role) { case EntityInfo::Role::Root: - entityInfo.m_entity.CreateComponent(); + entityInfo.m_entity->CreateComponent(); break; case EntityInfo::Role::Child: - entityInfo.m_entity.CreateComponent(); + entityInfo.m_entity->CreateComponent(); break; case EntityInfo::Role::None: break; @@ -390,23 +396,23 @@ namespace Multiplayer SetParentIdOnNetworkTransform(childOfChild.m_entity, child.m_netId); // Create an entity replicator for the child entity - const NetworkEntityHandle childOfChildHandle(&childOfChild.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle childOfChildHandle(childOfChild.m_entity.get(), m_networkEntityTracker.get()); childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childOfChildHandle); childOfChild.m_replicator->Initialize(childOfChildHandle); // Create an entity replicator for the child entity - const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle childHandle(child.m_entity.get(), m_networkEntityTracker.get()); child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childHandle); child.m_replicator->Initialize(childHandle); // Create an entity replicator for the root entity - const NetworkEntityHandle rootHandle(&root.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle rootHandle(root.m_entity.get(), m_networkEntityTracker.get()); root.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, rootHandle); root.m_replicator->Initialize(rootHandle); - root.m_entity.Activate(); - child.m_entity.Activate(); - childOfChild.m_entity.Activate(); + root.m_entity->Activate(); + child.m_entity->Activate(); + childOfChild.m_entity->Activate(); } }; } diff --git a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp index 0b76e276fd..05e36e466d 100644 --- a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp @@ -35,25 +35,19 @@ namespace Multiplayer { HierarchyTests::SetUp(); - m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); - m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); + m_root = AZStd::make_unique(1, "root", NetEntityId{ 1 }, EntityInfo::Role::Root); + m_child = AZStd::make_unique(2, "child", NetEntityId{ 2 }, EntityInfo::Role::Child); - m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), NetEntityId{ 1 }, EntityInfo::Role::Root); - m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), NetEntityId{ 2 }, EntityInfo::Role::Child); + CreateSimpleHierarchy(*m_root, *m_child); - CreateSimpleHierarchy(*m_rootEntityInfo, *m_childEntityInfo); - - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_child->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); // now the two entities are under one hierarchy } void TearDown() override { - m_childEntityInfo.reset(); - m_rootEntityInfo.reset(); - - StopAndDeleteEntity(m_childEntity); - StopAndDeleteEntity(m_rootEntity); + m_child.reset(); + m_root.reset(); HierarchyTests::TearDown(); } @@ -67,35 +61,32 @@ namespace Multiplayer SetupEntity(child.m_entity, child.m_netId, NetEntityRole::Authority); // Create an entity replicator for the child entity - const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle childHandle(child.m_entity.get(), m_networkEntityTracker.get()); child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childHandle); child.m_replicator->Initialize(childHandle); // Create an entity replicator for the root entity - const NetworkEntityHandle rootHandle(&root.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle rootHandle(root.m_entity.get(), m_networkEntityTracker.get()); root.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, rootHandle); root.m_replicator->Initialize(rootHandle); - root.m_entity.Activate(); - child.m_entity.Activate(); + root.m_entity->Activate(); + child.m_entity->Activate(); } - AZStd::unique_ptr m_rootEntity; - AZStd::unique_ptr m_childEntity; - - AZStd::unique_ptr m_rootEntityInfo; - AZStd::unique_ptr m_childEntityInfo; + AZStd::unique_ptr m_root; + AZStd::unique_ptr m_child; }; TEST_F(ServerSimpleHierarchyTests, Server_Sets_Appropriate_Network_Fields_For_Clients) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchyRoot(), + m_root->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), NetEntityId{ 1 } ); } @@ -103,7 +94,7 @@ namespace Multiplayer TEST_F(ServerSimpleHierarchyTests, Root_Is_Top_Level_Root) { EXPECT_EQ( - m_rootEntity->FindComponent()->IsHierarchicalChild(), + m_root->m_entity->FindComponent()->IsHierarchicalChild(), false ); } @@ -111,18 +102,18 @@ namespace Multiplayer TEST_F(ServerSimpleHierarchyTests, Child_Has_Root_Set) { EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), NetEntityId{ 1 } ); } TEST_F(ServerSimpleHierarchyTests, Child_Has_Root_Cleared_On_Detach) { - // now detach the child - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + // now detach the child + m_child->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); } @@ -130,7 +121,7 @@ namespace Multiplayer TEST_F(ServerSimpleHierarchyTests, Root_Has_Child_Reference) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); } @@ -138,34 +129,32 @@ namespace Multiplayer TEST_F(ServerSimpleHierarchyTests, Root_Has_Child_References_Removed_On_Detach) { // now detach the child - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_child->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 1 ); } TEST_F(ServerSimpleHierarchyTests, Root_Deactivates_Child_Has_No_References_To_Root) { - StopEntity(*m_rootEntity); - m_rootEntity->Deactivate(); - m_rootEntity.reset(); + StopEntity(m_root->m_entity); + m_root->m_entity->Deactivate(); + m_root->m_entity.reset(); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); } TEST_F(ServerSimpleHierarchyTests, Child_Deactivates_Root_Has_No_References_To_Child) { - StopEntity(*m_childEntity); - m_childEntity->Deactivate(); - m_childEntity.reset(); + m_child.reset(); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 1 ); } @@ -184,47 +173,35 @@ namespace Multiplayer { HierarchyTests::SetUp(); - m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); - m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); - m_childOfChildEntity = AZStd::make_unique(AZ::EntityId(3), "child of child"); + m_root = AZStd::make_unique((1), "root", RootNetEntityId, EntityInfo::Role::Root); + m_child = AZStd::make_unique((2), "child", ChildNetEntityId, EntityInfo::Role::Child); + m_childOfChild = AZStd::make_unique((3), "child of child", ChildOfChildNetEntityId, EntityInfo::Role::Child); - m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), RootNetEntityId, EntityInfo::Role::Root); - m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), ChildNetEntityId, EntityInfo::Role::Child); - m_childOfChildEntityInfo = AZStd::make_unique(*m_childOfChildEntity.get(), ChildOfChildNetEntityId, EntityInfo::Role::Child); + CreateDeepHierarchy(*m_root, *m_child, *m_childOfChild); - CreateDeepHierarchy(*m_rootEntityInfo, *m_childEntityInfo, *m_childOfChildEntityInfo); - - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); - m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + m_child->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); + m_childOfChild->m_entity->FindComponent()->SetParent(m_child->m_entity->GetId()); // now the entities are under one hierarchy } void TearDown() override { - m_childOfChildEntityInfo.reset(); - m_childEntityInfo.reset(); - m_rootEntityInfo.reset(); - - StopAndDeleteEntity(m_childOfChildEntity); - StopAndDeleteEntity(m_childEntity); - StopAndDeleteEntity(m_rootEntity); + m_childOfChild.reset(); + m_child.reset(); + m_root.reset(); HierarchyTests::TearDown(); } - AZStd::unique_ptr m_rootEntity; - AZStd::unique_ptr m_childEntity; - AZStd::unique_ptr m_childOfChildEntity; - - AZStd::unique_ptr m_rootEntityInfo; - AZStd::unique_ptr m_childEntityInfo; - AZStd::unique_ptr m_childOfChildEntityInfo; + AZStd::unique_ptr m_root; + AZStd::unique_ptr m_child; + AZStd::unique_ptr m_childOfChild; }; TEST_F(ServerDeepHierarchyTests, Root_Is_Top_Level_Root) { EXPECT_EQ( - m_rootEntity->FindComponent()->IsHierarchicalChild(), + m_root->m_entity->FindComponent()->IsHierarchicalChild(), false ); } @@ -232,144 +209,144 @@ namespace Multiplayer TEST_F(ServerDeepHierarchyTests, Root_Has_Child_References) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); - if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 3) + if (m_root->m_entity->FindComponent()->GetHierarchicalEntities().size() == 3) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], - m_rootEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[0], + m_root->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], - m_childEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[1], + m_child->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], - m_childOfChildEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChild->m_entity.get() ); } } TEST_F(ServerDeepHierarchyTests, Root_Has_Child_Of_Child_Reference_Removed_On_Detach) { - m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); } TEST_F(ServerDeepHierarchyTests, Root_Has_All_References_Removed_On_Detach_Of_Mid_Child) { - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_child->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 1 ); } TEST_F(ServerDeepHierarchyTests, Root_Has_All_References_If_Mid_Child_Added_With_Child) { - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_root->m_entity->FindComponent()->SetParent(AZ::EntityId()); // reconnect - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); } TEST_F(ServerDeepHierarchyTests, Root_Has_All_References_If_Child_Of_Child_Added) { - m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild->m_entity->FindComponent()->SetParent(AZ::EntityId()); // reconnect - m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + m_childOfChild->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); } TEST_F(ServerDeepHierarchyTests, Child_Of_Child_Points_To_Root_After_Attach) { - m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild->m_entity->FindComponent()->SetParent(AZ::EntityId()); // reconnect - m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + m_childOfChild->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + m_childOfChild->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); } TEST_F(ServerDeepHierarchyTests, All_New_Children_Point_To_Root_If_Mid_Child_Added_With_Child) { - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_root->m_entity->FindComponent()->SetParent(AZ::EntityId()); // reconnect - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); EXPECT_EQ( - m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + m_childOfChild->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); } TEST_F(ServerDeepHierarchyTests, Children_Clear_Reference_To_Root_After_Mid_Child_Detached) { - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_child->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); EXPECT_EQ( - m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + m_childOfChild->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); } TEST_F(ServerDeepHierarchyTests, Child_Of_Child_Clears_Reference_To_Root_After_Detached) { - m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + m_childOfChild->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); } TEST_F(ServerDeepHierarchyTests, Root_Deactivates_Children_Have_No_References_To_Root) { - StopAndDeleteEntity(m_rootEntity); + m_root.reset(); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchyRoot(), + m_child->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); EXPECT_EQ( - m_childOfChildEntity->FindComponent()->GetHierarchyRoot(), + m_childOfChild->m_entity->FindComponent()->GetHierarchyRoot(), InvalidNetEntityId ); } TEST_F(ServerDeepHierarchyTests, Child_Of_Child_Deactivates_Root_Removes_References_To_It) { - StopAndDeleteEntity(m_childOfChildEntity); + m_childOfChild.reset(); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); } @@ -381,11 +358,11 @@ namespace Multiplayer m_console->PerformCommand("bg_hierarchyEntityMaxLimit 2"); // remake the hierarchy - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root->m_entity->FindComponent()->SetParent(AZ::EntityId()); + m_root->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); @@ -412,43 +389,29 @@ namespace Multiplayer { HierarchyTests::SetUp(); - m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); - m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); - m_childOfChildEntity = AZStd::make_unique(AZ::EntityId(3), "child of child"); - m_child2Entity = AZStd::make_unique(AZ::EntityId(4), "child2"); - m_childOfChild2Entity = AZStd::make_unique(AZ::EntityId(5), "child of child2"); - m_child2OfChild2Entity = AZStd::make_unique(AZ::EntityId(6), "child2 of child2"); + m_root = AZStd::make_unique((1), "root", RootNetEntityId, EntityInfo::Role::Root); + m_child = AZStd::make_unique((2), "child", ChildNetEntityId, EntityInfo::Role::Child); + m_childOfChild = AZStd::make_unique((3), "child of child", ChildOfChildNetEntityId, EntityInfo::Role::Child); + m_child2 = AZStd::make_unique((4), "child2", Child2NetEntityId, EntityInfo::Role::Child); + m_childOfChild2 = AZStd::make_unique((5), "child of child2", ChildOfChild2NetEntityId, EntityInfo::Role::Child); + m_child2OfChild2 = AZStd::make_unique((6), "child2 of child2", Child2OfChild2NetEntityId, EntityInfo::Role::Child); - m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), RootNetEntityId, EntityInfo::Role::Root); - m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), ChildNetEntityId, EntityInfo::Role::Child); - m_childOfChildEntityInfo = AZStd::make_unique(*m_childOfChildEntity.get(), ChildOfChildNetEntityId, EntityInfo::Role::Child); - m_child2EntityInfo = AZStd::make_unique(*m_child2Entity.get(), Child2NetEntityId, EntityInfo::Role::Child); - m_childOfChild2EntityInfo = AZStd::make_unique(*m_childOfChild2Entity.get(), ChildOfChild2NetEntityId, EntityInfo::Role::Child); - m_child2OfChild2EntityInfo = AZStd::make_unique(*m_child2OfChild2Entity.get(), Child2OfChild2NetEntityId, EntityInfo::Role::Child); + CreateBranchedHierarchy(*m_root, *m_child, *m_childOfChild, + *m_child2, *m_childOfChild2, *m_child2OfChild2); - CreateBranchedHierarchy(*m_rootEntityInfo, *m_childEntityInfo, *m_childOfChildEntityInfo, - *m_child2EntityInfo, *m_childOfChild2EntityInfo, *m_child2OfChild2EntityInfo); - - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); - m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + m_child->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); + m_childOfChild->m_entity->FindComponent()->SetParent(m_child->m_entity->GetId()); // now the entities are under one hierarchy } void TearDown() override { - m_child2OfChild2EntityInfo.reset(); - m_childOfChild2EntityInfo.reset(); - m_child2EntityInfo.reset(); - m_childOfChildEntityInfo.reset(); - m_childEntityInfo.reset(); - m_rootEntityInfo.reset(); - - StopAndDeleteEntity(m_child2OfChild2Entity); - StopAndDeleteEntity(m_childOfChild2Entity); - StopAndDeleteEntity(m_child2Entity); - StopAndDeleteEntity(m_childOfChildEntity); - StopAndDeleteEntity(m_childEntity); - StopAndDeleteEntity(m_rootEntity); + m_child2OfChild2.reset(); + m_childOfChild2.reset(); + m_child2.reset(); + m_childOfChild.reset(); + m_child.reset(); + m_root.reset(); HierarchyTests::TearDown(); } @@ -479,139 +442,132 @@ namespace Multiplayer SetParentIdOnNetworkTransform(child2OfChild2.m_entity, child2.m_netId); // Create entity replicators - const NetworkEntityHandle childOfChild2Handle(&childOfChild2.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle childOfChild2Handle(childOfChild2.m_entity.get(), m_networkEntityTracker.get()); childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childOfChild2Handle); childOfChild.m_replicator->Initialize(childOfChild2Handle); - const NetworkEntityHandle child2OfChild2Handle(&child2OfChild2.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle child2OfChild2Handle(child2OfChild2.m_entity.get(), m_networkEntityTracker.get()); childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, child2OfChild2Handle); childOfChild.m_replicator->Initialize(child2OfChild2Handle); - const NetworkEntityHandle child2Handle(&child2.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle child2Handle(child2.m_entity.get(), m_networkEntityTracker.get()); child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, child2Handle); child.m_replicator->Initialize(child2Handle); - const NetworkEntityHandle childOfChildHandle(&childOfChild.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle childOfChildHandle(childOfChild.m_entity.get(), m_networkEntityTracker.get()); childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childOfChildHandle); childOfChild.m_replicator->Initialize(childOfChildHandle); - const NetworkEntityHandle childHandle(&child.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle childHandle(child.m_entity.get(), m_networkEntityTracker.get()); child.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childHandle); child.m_replicator->Initialize(childHandle); - const NetworkEntityHandle rootHandle(&root.m_entity, m_networkEntityTracker.get()); + const NetworkEntityHandle rootHandle(root.m_entity.get(), m_networkEntityTracker.get()); root.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, rootHandle); root.m_replicator->Initialize(rootHandle); - root.m_entity.Activate(); - child.m_entity.Activate(); - childOfChild.m_entity.Activate(); - child2.m_entity.Activate(); - childOfChild2.m_entity.Activate(); - child2OfChild2.m_entity.Activate(); + root.m_entity->Activate(); + child.m_entity->Activate(); + childOfChild.m_entity->Activate(); + child2.m_entity->Activate(); + childOfChild2.m_entity->Activate(); + child2OfChild2.m_entity->Activate(); } - AZStd::unique_ptr m_rootEntity; - AZStd::unique_ptr m_childEntity; - AZStd::unique_ptr m_childOfChildEntity; - AZStd::unique_ptr m_child2Entity; - AZStd::unique_ptr m_childOfChild2Entity; - AZStd::unique_ptr m_child2OfChild2Entity; - - AZStd::unique_ptr m_rootEntityInfo; - AZStd::unique_ptr m_childEntityInfo; - AZStd::unique_ptr m_childOfChildEntityInfo; - AZStd::unique_ptr m_child2EntityInfo; - AZStd::unique_ptr m_childOfChild2EntityInfo; - AZStd::unique_ptr m_child2OfChild2EntityInfo; + AZStd::unique_ptr m_root; + AZStd::unique_ptr m_child; + AZStd::unique_ptr m_childOfChild; + AZStd::unique_ptr m_child2; + AZStd::unique_ptr m_childOfChild2; + AZStd::unique_ptr m_child2OfChild2; }; TEST_F(ServerBranchedHierarchyTests, Sanity_Check) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 6 ); - if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 6) + if (m_root->m_entity->FindComponent()->GetHierarchicalEntities().size() == 6) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], - m_rootEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[0], + m_root->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], - m_childEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[1], + m_child->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], - m_childOfChildEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChild->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[3], - m_child2Entity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[3], + m_child2->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[4], - m_child2OfChild2Entity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[4], + m_child2OfChild2->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[5], - m_childOfChild2Entity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[5], + m_childOfChild2->m_entity.get() ); } } TEST_F(ServerBranchedHierarchyTests, Detach_Child_While_Child2_Remains_Attached) { - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); + m_child->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 4 ); - if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 4) + if (m_root->m_entity->FindComponent()->GetHierarchicalEntities().size() == 4) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], - m_rootEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[0], + m_root->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], - m_child2Entity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[1], + m_child2->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], - m_child2OfChild2Entity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[2], + m_child2OfChild2->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[3], - m_childOfChild2Entity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[3], + m_childOfChild2->m_entity.get() ); } EXPECT_EQ( - m_child2Entity->FindComponent()->GetHierarchicalRoot(), - m_rootEntity.get() + m_child2->m_entity->FindComponent()->GetHierarchicalRoot(), + m_root->m_entity.get() ); EXPECT_EQ( - m_childEntity->FindComponent()->GetHierarchicalRoot(), + m_child->m_entity->FindComponent()->GetHierarchicalRoot(), nullptr ); EXPECT_EQ( - m_childOfChildEntity->FindComponent()->GetHierarchicalRoot(), + m_childOfChild->m_entity->FindComponent()->GetHierarchicalRoot(), nullptr ); } TEST_F(ServerBranchedHierarchyTests, Detach_Child_Then_Attach_To_Child2) { - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); - m_childEntity->FindComponent()->SetParent(m_child2Entity->GetId()); + m_child->m_entity->FindComponent()->SetParent(AZ::EntityId()); + m_child->m_entity->FindComponent()->SetParent(m_child2->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 6 ); } @@ -630,254 +586,242 @@ namespace Multiplayer { ServerDeepHierarchyTests::SetUp(); - m_rootEntity2 = AZStd::make_unique(AZ::EntityId(4), "root 2"); - m_childEntity2 = AZStd::make_unique(AZ::EntityId(5), "child 2"); - m_childOfChildEntity2 = AZStd::make_unique(AZ::EntityId(6), "child of child 2"); + m_root2 = AZStd::make_unique((4), "root 2", Root2NetEntityId, EntityInfo::Role::Root); + m_child2 = AZStd::make_unique((5), "child 2", Child2NetEntityId, EntityInfo::Role::Child); + m_childOfChild2 = AZStd::make_unique((6), "child of child 2", ChildOfChild2NetEntityId, EntityInfo::Role::Child); - m_rootEntityInfo2 = AZStd::make_unique(*m_rootEntity2.get(), Root2NetEntityId, EntityInfo::Role::Root); - m_childEntityInfo2 = AZStd::make_unique(*m_childEntity2.get(), Child2NetEntityId, EntityInfo::Role::Child); - m_childOfChildEntityInfo2 = AZStd::make_unique(*m_childOfChildEntity2.get(), ChildOfChild2NetEntityId, EntityInfo::Role::Child); + CreateDeepHierarchy(*m_root2, *m_child2, *m_childOfChild2); - CreateDeepHierarchy(*m_rootEntityInfo2, *m_childEntityInfo2, *m_childOfChildEntityInfo2); - - m_childEntity2->FindComponent()->SetParent(m_rootEntity2->GetId()); - m_childOfChildEntity2->FindComponent()->SetParent(m_childEntity2->GetId()); + m_child2->m_entity->FindComponent()->SetParent(m_root2->m_entity->GetId()); + m_childOfChild2->m_entity->FindComponent()->SetParent(m_child2->m_entity->GetId()); // now the entities are under one hierarchy } void TearDown() override { - m_childOfChildEntityInfo2.reset(); - m_childEntityInfo2.reset(); - m_rootEntityInfo2.reset(); - - StopAndDeleteEntity(m_childOfChildEntity2); - StopAndDeleteEntity(m_childEntity2); - StopAndDeleteEntity(m_rootEntity2); + m_childOfChild2.reset(); + m_child2.reset(); + m_root2.reset(); ServerDeepHierarchyTests::TearDown(); } - AZStd::unique_ptr m_rootEntity2; - AZStd::unique_ptr m_childEntity2; - AZStd::unique_ptr m_childOfChildEntity2; - - AZStd::unique_ptr m_rootEntityInfo2; - AZStd::unique_ptr m_childEntityInfo2; - AZStd::unique_ptr m_childOfChildEntityInfo2; + AZStd::unique_ptr m_root2; + AZStd::unique_ptr m_child2; + AZStd::unique_ptr m_childOfChild2; }; TEST_F(ServerHierarchyOfHierarchyTests, Hierarchies_Are_Not_Related) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); - if (m_rootEntity->FindComponent()->GetHierarchicalEntities().size() == 3) + if (m_root->m_entity->FindComponent()->GetHierarchicalEntities().size() == 3) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[0], - m_rootEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[0], + m_root->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[1], - m_childEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[1], + m_child->m_entity.get() ); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities()[2], - m_childOfChildEntity.get() + m_root->m_entity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChild->m_entity.get() ); } EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); - if (m_rootEntity2->FindComponent()->GetHierarchicalEntities().size() == 3) + if (m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size() == 3) { EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities()[0], - m_rootEntity2.get() + m_root2->m_entity->FindComponent()->GetHierarchicalEntities()[0], + m_root2->m_entity.get() ); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities()[1], - m_childEntity2.get() + m_root2->m_entity->FindComponent()->GetHierarchicalEntities()[1], + m_child2->m_entity.get() ); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities()[2], - m_childOfChildEntity2.get() + m_root2->m_entity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChild2->m_entity.get() ); } } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Is_Not_Top_Level_Root) { - m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->IsHierarchicalChild(), + m_root->m_entity->FindComponent()->IsHierarchicalChild(), false ); EXPECT_EQ( - m_rootEntity2->FindComponent()->IsHierarchicalChild(), + m_root2->m_entity->FindComponent()->IsHierarchicalChild(), true ); } TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_References_All_When_Another_Hierarchy_Attached_At_Root) { - m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 6 ); } TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_References_All_When_Another_Hierarchy_Attached_At_Child) { - m_rootEntity2->FindComponent()->SetParent(m_childEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 6 ); } TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_References_All_When_Another_Hierarchy_Attached_At_Child_Of_Child) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 6 ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_References_Top_Root_When_Another_Hierarchy_Attached_At_Root) { - m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity2->FindComponent()->IsHierarchicalChild(), + m_root2->m_entity->FindComponent()->IsHierarchicalChild(), true ); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchyRoot(), + m_root2->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_References_Top_Root_When_Another_Hierarchy_Attached_At_Child) { - m_rootEntity2->FindComponent()->SetParent(m_childEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity2->FindComponent()->IsHierarchicalChild(), + m_root2->m_entity->FindComponent()->IsHierarchicalChild(), true ); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchyRoot(), + m_root2->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_References_Top_Root_When_Another_Hierarchy_Attached_At_Child_Of_Child) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); EXPECT_EQ( - m_rootEntity2->FindComponent()->IsHierarchicalChild(), + m_root2->m_entity->FindComponent()->IsHierarchicalChild(), true ); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchyRoot(), + m_root2->m_entity->FindComponent()->GetHierarchyRoot(), RootNetEntityId ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Doesnt_Keep_Child_References) { - m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 0 ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Detachment_From_Top_Root) { - m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); // detach - m_rootEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_root2->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); - if (m_rootEntity2->FindComponent()->GetHierarchicalEntities().size() == 3) + if (m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size() == 3) { EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities()[0], - m_rootEntity2.get() + m_root2->m_entity->FindComponent()->GetHierarchicalEntities()[0], + m_root2->m_entity.get() ); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities()[1], - m_childEntity2.get() + m_root2->m_entity->FindComponent()->GetHierarchicalEntities()[1], + m_child2->m_entity.get() ); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities()[2], - m_childOfChildEntity2.get() + m_root2->m_entity->FindComponent()->GetHierarchicalEntities()[2], + m_childOfChild2->m_entity.get() ); } } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Detachment_From_Child_Of_Child) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); // detach - m_rootEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_root2->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Top_Root_Deactivates) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); - StopAndDeleteEntity(m_rootEntity); + m_root.reset(); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Child_Of_Top_Root_Deactivates) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); - StopAndDeleteEntity(m_childEntity); + m_child.reset(); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_Child_References_After_Child_Of_Child_Deactivates) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); - StopAndDeleteEntity(m_childOfChildEntity); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + m_childOfChild.reset(); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); } @@ -886,108 +830,108 @@ namespace Multiplayer { for (int i = 0; i < 100; ++i) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); // detach - m_rootEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_root2->m_entity->FindComponent()->SetParent(AZ::EntityId()); } EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); } TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Detachment_Of_Child_Of_Child_In_Inner_Hierarchy) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); // detach - m_childOfChildEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild2->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 5 ); } TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Attachment_Of_Child_Of_Child_In_Inner_Hierarchy) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); // detach - m_childOfChildEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild2->m_entity->FindComponent()->SetParent(AZ::EntityId()); // re-connect - m_childOfChildEntity2->FindComponent()->SetParent(m_childEntity2->GetId()); + m_childOfChild2->m_entity->FindComponent()->SetParent(m_child2->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 6 ); } TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Child_Of_Child_Changed_Hierarchies) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); // detach - m_childOfChildEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild2->m_entity->FindComponent()->SetParent(AZ::EntityId()); // connect to a different hierarchy - m_childOfChildEntity2->FindComponent()->SetParent(m_childEntity->GetId()); + m_childOfChild2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 6 ); } TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Detachment_Of_Child_In_Inner_Hierarchy) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); // detach - m_childEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_child2->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 4 ); } TEST_F(ServerHierarchyOfHierarchyTests, Top_Root_Updates_Child_References_After_Child_Changed_Hierarchies) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); // detach - m_childEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_child2->m_entity->FindComponent()->SetParent(AZ::EntityId()); // connect to a different hierarchy - m_childEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_child2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 6 ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Has_No_Child_References_After_All_Children_Moved_To_Another_Hierarchy) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); - m_childEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_child2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); // detach - m_rootEntity2->FindComponent()->SetParent(AZ::EntityId()); + m_root2->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 1 ); } TEST_F(ServerHierarchyOfHierarchyTests, Inner_Root_Child_Deactivated_Top_Root_Has_No_Child_Reference_To_It) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); - StopAndDeleteEntity(m_childEntity2); + m_child2.reset(); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 4 ); } @@ -999,18 +943,18 @@ namespace Multiplayer m_console->PerformCommand("bg_hierarchyEntityMaxLimit 2"); // remake the top level hierarchy - m_childEntity->FindComponent()->SetParent(AZ::EntityId()); - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root->m_entity->FindComponent()->SetParent(AZ::EntityId()); + m_root->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); - m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); @@ -1028,68 +972,56 @@ namespace Multiplayer { HierarchyTests::SetUp(); - m_rootEntity = AZStd::make_unique(AZ::EntityId(1), "root"); - m_childEntity = AZStd::make_unique(AZ::EntityId(2), "child"); - m_childOfChildEntity = AZStd::make_unique(AZ::EntityId(3), "child of child"); + m_root = AZStd::make_unique((1), "root", NetEntityId{ 1 }, EntityInfo::Role::Root); + m_child = AZStd::make_unique((2), "child", NetEntityId{ 2 }, EntityInfo::Role::Child); + m_childOfChild = AZStd::make_unique((3), "child of child", NetEntityId{ 3 }, EntityInfo::Role::None); - m_rootEntityInfo = AZStd::make_unique(*m_rootEntity.get(), NetEntityId{ 1 }, EntityInfo::Role::Root); - m_childEntityInfo = AZStd::make_unique(*m_childEntity.get(), NetEntityId{ 2 }, EntityInfo::Role::Child); - m_childOfChildEntityInfo = AZStd::make_unique(*m_childOfChildEntity.get(), NetEntityId{ 3 }, EntityInfo::Role::None); + CreateDeepHierarchy(*m_root, *m_child, *m_childOfChild); - CreateDeepHierarchy(*m_rootEntityInfo, *m_childEntityInfo, *m_childOfChildEntityInfo); - - m_childEntity->FindComponent()->SetParent(m_rootEntity->GetId()); - m_childOfChildEntity->FindComponent()->SetParent(m_childEntity->GetId()); + m_root->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); + m_childOfChild->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); // now the entities are under one hierarchy } void TearDown() override { - m_childOfChildEntityInfo.reset(); - m_childEntityInfo.reset(); - m_rootEntityInfo.reset(); - - StopAndDeleteEntity(m_childOfChildEntity); - StopAndDeleteEntity(m_childEntity); - StopAndDeleteEntity(m_rootEntity); + m_childOfChild.reset(); + m_child.reset(); + m_root.reset(); HierarchyTests::TearDown(); } - AZStd::unique_ptr m_rootEntity; - AZStd::unique_ptr m_childEntity; - AZStd::unique_ptr m_childOfChildEntity; - - AZStd::unique_ptr m_rootEntityInfo; - AZStd::unique_ptr m_childEntityInfo; - AZStd::unique_ptr m_childOfChildEntityInfo; + AZStd::unique_ptr m_root; + AZStd::unique_ptr m_child; + AZStd::unique_ptr m_childOfChild; }; TEST_F(ServerMixedDeepHierarchyTests, Top_Root_Ignores_Non_Hierarchical_Entities) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); } TEST_F(ServerMixedDeepHierarchyTests, Detaching_Non_Hierarchical_Entity_Has_No_Effect_On_Top_Root) { - m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); } TEST_F(ServerMixedDeepHierarchyTests, Attaching_Non_Hierarchical_Entity_Has_No_Effect_On_Top_Root) { - m_childOfChildEntity->FindComponent()->SetParent(AZ::EntityId()); - m_childOfChildEntity->FindComponent()->SetParent(m_rootEntity->GetId()); + m_childOfChild->m_entity->FindComponent()->SetParent(AZ::EntityId()); + m_childOfChild->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); } @@ -1105,73 +1037,165 @@ namespace Multiplayer { ServerMixedDeepHierarchyTests::SetUp(); - m_rootEntity2 = AZStd::make_unique(AZ::EntityId(4), "root 2"); - m_childEntity2 = AZStd::make_unique(AZ::EntityId(5), "child 2"); - m_childOfChildEntity2 = AZStd::make_unique(AZ::EntityId(6), "child of child 2"); + m_root2 = AZStd::make_unique((4), "root 2", NetEntityId{ 4 }, EntityInfo::Role::Root); + m_child2 = AZStd::make_unique((5), "child 2", NetEntityId{ 5 }, EntityInfo::Role::None); + m_childOfChild2 = AZStd::make_unique((6), "child of child 2", NetEntityId{ 6 }, EntityInfo::Role::Child); - m_rootEntityInfo2 = AZStd::make_unique(*m_rootEntity2.get(), NetEntityId{ 4 }, EntityInfo::Role::Root); - m_childEntityInfo2 = AZStd::make_unique(*m_childEntity2.get(), NetEntityId{ 5 }, EntityInfo::Role::None); - m_childOfChildEntityInfo2 = AZStd::make_unique(*m_childOfChildEntity2.get(), NetEntityId{ 6 }, EntityInfo::Role::Child); + CreateDeepHierarchy(*m_root2, *m_child2, *m_childOfChild2); - CreateDeepHierarchy(*m_rootEntityInfo2, *m_childEntityInfo2, *m_childOfChildEntityInfo2); - - m_childEntity2->FindComponent()->SetParent(m_rootEntity2->GetId()); - m_childOfChildEntity2->FindComponent()->SetParent(m_childEntity2->GetId()); + m_child2->m_entity->FindComponent()->SetParent(m_root2->m_entity->GetId()); + m_childOfChild2->m_entity->FindComponent()->SetParent(m_child2->m_entity->GetId()); // now the entities are under one hierarchy } void TearDown() override { - m_childOfChildEntityInfo2.reset(); - m_childEntityInfo2.reset(); - m_rootEntityInfo2.reset(); - - - StopAndDeleteEntity(m_childOfChildEntity2); - StopAndDeleteEntity(m_childEntity2); - StopAndDeleteEntity(m_rootEntity2); + m_childOfChild2.reset(); + m_child2.reset(); + m_root2.reset(); ServerMixedDeepHierarchyTests::TearDown(); } - AZStd::unique_ptr m_rootEntity2; - AZStd::unique_ptr m_childEntity2; - AZStd::unique_ptr m_childOfChildEntity2; - - AZStd::unique_ptr m_rootEntityInfo2; - AZStd::unique_ptr m_childEntityInfo2; - AZStd::unique_ptr m_childOfChildEntityInfo2; + AZStd::unique_ptr m_root2; + AZStd::unique_ptr m_child2; + AZStd::unique_ptr m_childOfChild2; }; TEST_F(ServerMixedHierarchyOfHierarchyTests, Sanity_Check_Ingore_Children_Without_Hierarchy_Components) { EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 2 ); EXPECT_EQ( - m_rootEntity2->FindComponent()->GetHierarchicalEntities().size(), + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), 1 ); } TEST_F(ServerMixedHierarchyOfHierarchyTests, Adding_Mixed_Hierarchy_Ingores_Children_Without_Hierarchy_Components) { - m_rootEntity2->FindComponent()->SetParent(m_rootEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); EXPECT_EQ( - m_rootEntity->FindComponent()->GetHierarchicalEntities().size(), + m_root->m_entity->FindComponent()->GetHierarchicalEntities().size(), 3 ); } TEST_F(ServerMixedHierarchyOfHierarchyTests, Attaching_Hierarchy_To_Non_Hierarchical_Entity_Does_Not_Merge_Hierarchies) { - m_rootEntity2->FindComponent()->SetParent(m_childOfChildEntity->GetId()); + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); EXPECT_EQ( - m_rootEntity2->FindComponent()->IsHierarchicalChild(), + m_root2->m_entity->FindComponent()->IsHierarchicalChild(), false ); } + + /* + * Sets up a hierarchy with 3 roots, 2 of them being inner roots. + */ + class ServerHierarchyWithThreeRoots : public ServerHierarchyOfHierarchyTests + { + public: + static const NetEntityId Root3NetEntityId = NetEntityId{ 7 }; + static const NetEntityId Child3NetEntityId = NetEntityId{ 8 }; + static const NetEntityId ChildOfChild3NetEntityId = NetEntityId{ 9 }; + + void SetUp() override + { + ServerHierarchyOfHierarchyTests::SetUp(); + + m_root3 = AZStd::make_unique((7), "root 3", Root3NetEntityId, EntityInfo::Role::Root); + m_child3 = AZStd::make_unique((8), "child 3", Child3NetEntityId, EntityInfo::Role::Child); + m_childOfChild3 = AZStd::make_unique((9), "child of child 3", ChildOfChild3NetEntityId, EntityInfo::Role::Child); + + CreateDeepHierarchy(*m_root3, *m_child3, *m_childOfChild3); + + m_child3->m_entity->FindComponent()->SetParent(m_root3->m_entity->GetId()); + m_childOfChild3->m_entity->FindComponent()->SetParent(m_child3->m_entity->GetId()); + // now the entities are under one hierarchy + } + + void TearDown() override + { + m_childOfChild3.reset(); + m_child3.reset(); + m_root3.reset(); + + ServerHierarchyOfHierarchyTests::TearDown(); + } + + AZStd::unique_ptr m_root3; + AZStd::unique_ptr m_child3; + AZStd::unique_ptr m_childOfChild3; + }; + + TEST_F(ServerHierarchyWithThreeRoots, Top_Root_Active_Then_Inner_Roots_Have_No_Child_References) + { + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + m_root3->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + + EXPECT_EQ( + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), + 0 + ); + EXPECT_EQ( + m_root3->m_entity->FindComponent()->GetHierarchicalEntities().size(), + 0 + ); + } + + TEST_F(ServerHierarchyWithThreeRoots, Top_Root_Deactivates_Inner_Roots_Have_Child_References) + { + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + m_root3->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + + m_root.reset(); + + EXPECT_EQ( + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + EXPECT_EQ( + m_root3->m_entity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerHierarchyWithThreeRoots, Child_Of_Top_Root_Deactivates_Inner_Roots_Have_Child_References) + { + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + m_root3->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + + m_child.reset(); + + EXPECT_EQ( + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + EXPECT_EQ( + m_root3->m_entity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } + + TEST_F(ServerHierarchyWithThreeRoots, Child_Of_Child_Of_Top_Root_Deactivates_Inner_Roots_Have_Child_References) + { + m_root2->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + m_root3->m_entity->FindComponent()->SetParent(m_childOfChild->m_entity->GetId()); + + m_childOfChild.reset(); + + EXPECT_EQ( + m_root2->m_entity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + EXPECT_EQ( + m_root3->m_entity->FindComponent()->GetHierarchicalEntities().size(), + 3 + ); + } } From 9e31c3ebf53b6dd9b26c5187322b84a1ab2ac212 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Wed, 15 Sep 2021 18:41:08 -0400 Subject: [PATCH 16/84] Refactoring m_isDeactivating into m_isHierarchyEnabled Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Components/NetworkHierarchyChildComponent.h | 3 ++- .../Components/NetworkHierarchyRootComponent.h | 5 +++-- .../Components/NetworkHierarchyChildComponent.cpp | 14 +++++++------- .../Components/NetworkHierarchyRootComponent.cpp | 5 +++-- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h index 2effb18bb8..544fb3d6cb 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyChildComponent.h @@ -78,7 +78,8 @@ namespace Multiplayer NetworkHierarchyChangedEvent m_networkHierarchyChangedEvent; NetworkHierarchyLeaveEvent m_networkHierarchyLeaveEvent; - bool m_isDeactivating = false; + //! Set to false when deactivating or otherwise not to be included in hierarchy considerations. + bool m_isHierarchyEnabled = true; void NotifyChildrenHierarchyDisbanded(); }; diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h index 35f0da5965..4c9f94c004 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkHierarchyRootComponent.h @@ -93,7 +93,8 @@ namespace Multiplayer bool RecursiveAttachHierarchicalChild(AZ::EntityId entity, uint32_t& currentEntityCount); void SetRootForEntity(AZ::Entity* root, const AZ::Entity* childEntity); - - bool m_isDeactivating = false; + + //! Set to false when deactivating or otherwise not to be included in hierarchy considerations. + bool m_isHierarchyEnabled = true; }; } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp index eff051ed93..6ee407990e 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp @@ -67,6 +67,8 @@ namespace Multiplayer void NetworkHierarchyChildComponent::OnActivate([[maybe_unused]] EntityIsMigrating entityIsMigrating) { + m_isHierarchyEnabled = true; + HierarchyRootAddEvent(m_hierarchyRootNetIdChanged); NetworkHierarchyRequestBus::Handler::BusConnect(GetEntityId()); @@ -79,7 +81,7 @@ namespace Multiplayer void NetworkHierarchyChildComponent::OnDeactivate([[maybe_unused]] EntityIsMigrating entityIsMigrating) { - m_isDeactivating = true; + m_isHierarchyEnabled = false; if (m_rootEntity) { @@ -96,7 +98,7 @@ namespace Multiplayer bool NetworkHierarchyChildComponent::IsHierarchyEnabled() const { - return !m_isDeactivating; + return m_isHierarchyEnabled; } bool NetworkHierarchyChildComponent::IsHierarchicalChild() const @@ -197,11 +199,9 @@ namespace Multiplayer } else { - if (!m_rootEntity) - { - m_rootEntity = nullptr; - m_networkHierarchyLeaveEvent.Signal(); - } + m_isHierarchyEnabled = false; + m_rootEntity = nullptr; + m_networkHierarchyLeaveEvent.Signal(); } } diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp index d2b45a8971..f704242f34 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp @@ -71,6 +71,7 @@ namespace Multiplayer void NetworkHierarchyRootComponent::OnActivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) { + m_isHierarchyEnabled = true; m_hierarchicalEntities.push_back(GetEntity()); NetworkHierarchyRequestBus::Handler::BusConnect(GetEntityId()); @@ -84,7 +85,7 @@ namespace Multiplayer void NetworkHierarchyRootComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) { - m_isDeactivating = true; + m_isHierarchyEnabled = false; if (m_rootEntity) { @@ -121,7 +122,7 @@ namespace Multiplayer bool NetworkHierarchyRootComponent::IsHierarchyEnabled() const { - return !m_isDeactivating; + return m_isHierarchyEnabled; } bool NetworkHierarchyRootComponent::IsHierarchicalRoot() const From 2637fa45b8010537a1752ff84438479930f5b718 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Wed, 15 Sep 2021 18:43:56 -0400 Subject: [PATCH 17/84] Minor refactor to address CR Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Source/Components/NetworkHierarchyChildComponent.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp index 6ee407990e..3124eccaa8 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyChildComponent.cpp @@ -103,12 +103,7 @@ namespace Multiplayer bool NetworkHierarchyChildComponent::IsHierarchicalChild() const { - if (GetHierarchyRoot() != InvalidNetEntityId) - { - return true; - } - - return false; + return GetHierarchyRoot() != InvalidNetEntityId; } AZ::Entity* NetworkHierarchyChildComponent::GetHierarchicalRoot() const From 2be5854beb1fbe2398608e224895b23663dd0b06 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Wed, 15 Sep 2021 18:49:24 -0400 Subject: [PATCH 18/84] Cleanup Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Components/NetworkHierarchyRootComponent.cpp | 15 ++++----------- .../EntityReplication/EntityReplicator.cpp | 4 ++-- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp index f704242f34..4a5e9ce8d2 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkHierarchyRootComponent.cpp @@ -89,7 +89,7 @@ namespace Multiplayer if (m_rootEntity) { - // tell parent to re-build the hierarchy + // Tell parent to re-build the hierarchy if (NetworkHierarchyRootComponent* root = m_rootEntity->FindComponent()) { root->RebuildHierarchy(); @@ -97,8 +97,7 @@ namespace Multiplayer } else { - // notify children to that a hierarchy is disbanded - + // Notify children that the hierarchy is disbanding AZStd::vector allChildren; AZ::TransformBus::EventResult(allChildren, GetEntityId(), &AZ::TransformBus::Events::GetChildren); @@ -127,12 +126,7 @@ namespace Multiplayer bool NetworkHierarchyRootComponent::IsHierarchicalRoot() const { - if (GetHierarchyRoot() != InvalidNetEntityId) - { - return false; - } - - return true; + return GetHierarchyRoot() == InvalidNetEntityId; } bool NetworkHierarchyRootComponent::IsHierarchicalChild() const @@ -199,7 +193,7 @@ namespace Multiplayer } else { - // detached from parent + // Detached from parent RebuildHierarchy(); } } @@ -217,7 +211,6 @@ namespace Multiplayer bool hierarchyChanged = false; // Send out join and leave events. - for (AZ::Entity* currentEntity : m_hierarchicalEntities) { const auto prevEntityIterator = AZStd::find(previousEntities.begin(), previousEntities.end(), currentEntity); diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp index bd98d15923..b684473ea3 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/EntityReplication/EntityReplicator.cpp @@ -417,14 +417,14 @@ namespace Multiplayer if (hierarchyChildComponent == nullptr) { - // child and root hierarchy components are mutually exclusive + // Child and root hierarchy components are mutually exclusive hierarchyRootComponent = entity->FindComponent(); } if ((hierarchyChildComponent && hierarchyChildComponent->IsHierarchicalChild()) || (hierarchyRootComponent && hierarchyRootComponent->IsHierarchicalChild())) { - // if hierarchy is enabled for the entity, check if the parent is available + // If hierarchy is enabled for the entity, check if the parent is available if (const NetworkTransformComponent* networkTransform = entity->FindComponent()) { const NetEntityId parentId = networkTransform->GetParentEntityId(); From 880f4d96cc7773e2378bd051b1dcfb1ee37b9989 Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Wed, 15 Sep 2021 18:19:39 -0700 Subject: [PATCH 19/84] Changed the ReflectionProbe component to use an OBB Signed-off-by: dmcdiar --- .../Atom/Features/PBR/DefaultObjectSrg.azsli | 37 ++++++++++++-- .../Atom/Features/PBR/LightingUtils.azsli | 11 +++- .../Atom/Features/PBR/Lights/Ibl.azsli | 16 +++--- .../ReflectionProbeBlendWeight.azsl | 10 ++-- .../ReflectionProbeRenderCommon.azsli | 10 ++-- .../ReflectionProbeRenderInner.azsl | 2 +- .../ReflectionProbeRenderObjectSrg.azsli | 23 ++++++--- .../ReflectionProbeRenderOuter.azsl | 12 +++-- .../Code/Source/Mesh/MeshFeatureProcessor.cpp | 28 +++++------ .../ReflectionProbe/ReflectionProbe.cpp | 50 +++++++++---------- .../Source/ReflectionProbe/ReflectionProbe.h | 20 ++++---- .../ReflectionProbeFeatureProcessor.cpp | 40 +++++++-------- .../RPI/Assets/ShaderLib/Atom/RPI/Math.azsli | 16 ++++++ .../EditorReflectionProbeComponent.cpp | 7 +-- 14 files changed, 172 insertions(+), 110 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli index ccaf5cf5d0..7a2d2ee428 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/DefaultObjectSrg.azsli @@ -40,11 +40,10 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject //! Reflection Probe (smallest probe volume that overlaps the object position) struct ReflectionProbeData { - float3 m_aabbPos; - float3 m_outerAabbMin; - float3 m_outerAabbMax; - float3 m_innerAabbMin; - float3 m_innerAabbMax; + row_major float3x4 m_modelToWorld; + row_major float3x4 m_modelToWorldInverse; // does not include extents + float3 m_outerObbHalfLengths; + float3 m_innerObbHalfLengths; float m_padding; bool m_useReflectionProbe; bool m_useParallaxCorrection; @@ -52,4 +51,32 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject ReflectionProbeData m_reflectionProbeData; TextureCube m_reflectionProbeCubeMap; + + float4x4 GetReflectionProbeWorldMatrix() + { + float4x4 modelToWorld = float4x4( + float4(1, 0, 0, 0), + float4(0, 1, 0, 0), + float4(0, 0, 1, 0), + float4(0, 0, 0, 1)); + + modelToWorld[0] = m_reflectionProbeData.m_modelToWorld[0]; + modelToWorld[1] = m_reflectionProbeData.m_modelToWorld[1]; + modelToWorld[2] = m_reflectionProbeData.m_modelToWorld[2]; + return modelToWorld; + } + + float4x4 GetReflectionProbeWorldMatrixInverse() + { + float4x4 modelToWorldInverse = float4x4( + float4(1, 0, 0, 0), + float4(0, 1, 0, 0), + float4(0, 0, 1, 0), + float4(0, 0, 0, 1)); + + modelToWorldInverse[0] = m_reflectionProbeData.m_modelToWorldInverse[0]; + modelToWorldInverse[1] = m_reflectionProbeData.m_modelToWorldInverse[1]; + modelToWorldInverse[2] = m_reflectionProbeData.m_modelToWorldInverse[2]; + return modelToWorldInverse; + } } diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingUtils.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingUtils.azsli index 503095020c..3248fc83eb 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingUtils.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/LightingUtils.azsli @@ -50,10 +50,10 @@ float GetRoughnessMip(float roughness) return roughness * maxRoughnessMip; } -// compute parallax corrected reflection vector +// compute parallax corrected reflection vector, AABB version // we do this by finding the intersection with the volume and adjusting the reflection vector for the surface position // https://seblagarde.wordpress.com/2012/09/29/image-based-lighting-approaches-and-parallax-corrected-cubemap/ -float3 ApplyParallaxCorrection(float3 aabbMin, float3 aabbMax, float3 aabbPos, float3 positionWS, float3 reflectDir) +float3 ApplyParallaxCorrectionAABB(float3 aabbMin, float3 aabbMax, float3 aabbPos, float3 positionWS, float3 reflectDir) { float3 rcpReflectDir = 1.0f / reflectDir; float3 intersectA = (aabbMax - positionWS) * rcpReflectDir; @@ -63,3 +63,10 @@ float3 ApplyParallaxCorrection(float3 aabbMin, float3 aabbMax, float3 aabbPos, f float3 intersectPos = reflectDir * distance + positionWS; return (intersectPos - aabbPos); } + +// compute parallax corrected reflection vector, OBB version +float3 ApplyParallaxCorrectionOBB(float4x4 obbTransformInverse, float3 obbHalfExtents, float3 positionWS, float3 reflectDir) +{ + float4 p = mul(obbTransformInverse, float4(positionWS, 1.0f)); + return ApplyParallaxCorrectionAABB(-obbHalfExtents, obbHalfExtents, float3(0.0f, 0.0f, 0.0f), p, reflectDir); +} diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli index 5a0e150dbb..b1cfb47be6 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli @@ -48,10 +48,9 @@ float3 GetIblSpecular( { if (ObjectSrg::m_reflectionProbeData.m_useParallaxCorrection) { - reflectDir = ApplyParallaxCorrection( - ObjectSrg::m_reflectionProbeData.m_outerAabbMin, - ObjectSrg::m_reflectionProbeData.m_outerAabbMax, - ObjectSrg::m_reflectionProbeData.m_aabbPos, + reflectDir = ApplyParallaxCorrectionOBB( + ObjectSrg::GetReflectionProbeWorldMatrixInverse(), + ObjectSrg::m_reflectionProbeData.m_outerObbHalfLengths, position, reflectDir); } @@ -60,11 +59,10 @@ float3 GetIblSpecular( probeSpecular *= (specularF0 * brdf.x + brdf.y); // compute blend amount based on world position in the reflection probe volume - float blendAmount = ComputeLerpBetweenInnerOuterAABBs( - ObjectSrg::m_reflectionProbeData.m_innerAabbMin, - ObjectSrg::m_reflectionProbeData.m_innerAabbMax, - ObjectSrg::m_reflectionProbeData.m_outerAabbMax, - ObjectSrg::m_reflectionProbeData.m_aabbPos, + float blendAmount = ComputeLerpBetweenInnerOuterOBBs( + ObjectSrg::m_reflectionProbeData.m_modelToWorldInverse, + ObjectSrg::m_reflectionProbeData.m_innerObbHalfLengths, + ObjectSrg::m_reflectionProbeData.m_outerObbHalfLengths, position); outSpecular = lerp(outSpecular, probeSpecular, blendAmount); diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeBlendWeight.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeBlendWeight.azsl index 095576caaf..0fca4d03c6 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeBlendWeight.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeBlendWeight.azsl @@ -63,7 +63,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) // make sure the pixel belongs to this probe volume // this is necessary since it could have the correct stencil value but actually reside // in another volume that's in between the camera and the volume we're rendering - if (!AabbContainsPoint(ObjectSrg::m_outerAabbMin, ObjectSrg::m_outerAabbMax, positionWS)) + if (!ObbContainsPoint(ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_outerObbHalfLengths, positionWS)) { discard; } @@ -71,11 +71,15 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) // determine blend based on position with respect to the inner and outer AABBs // if it's inside the inner AABB it blends at 100%, otherwise it's the percentage of the distance between the inner/outer AABB float blendWeight = 1.0f; - if (!AabbContainsPoint(ObjectSrg::m_innerAabbMin, ObjectSrg::m_innerAabbMax, positionWS)) + if (!ObbContainsPoint(ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_innerObbHalfLengths, positionWS)) { // not inside the inner AABB, so it's in between the inner and outer AABBs // compute blend amount based on the distance to the outer AABB - blendWeight = ComputeLerpBetweenInnerOuterAABBs(ObjectSrg::m_innerAabbMin, ObjectSrg::m_innerAabbMax, ObjectSrg::m_outerAabbMax, ObjectSrg::m_aabbPos, positionWS); + blendWeight = ComputeLerpBetweenInnerOuterOBBs( + ObjectSrg::GetWorldMatrixInverse(), + ObjectSrg::m_innerObbHalfLengths, + ObjectSrg::m_outerObbHalfLengths, + positionWS); } // write the blend weight (additive) at this position for the probe volume diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderCommon.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderCommon.azsli index f172035177..ce4684b150 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderCommon.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderCommon.azsli @@ -12,12 +12,12 @@ #include // compute final probe specular using the probe cubemap and the roughness, normals, and specularF0 for the surface -bool ComputeProbeSpecular(float2 screenCoords, float3 positionWS, float3 aabbMin, float3 aabbMax, uint sampleIndex, out float3 specular) +bool ComputeProbeSpecular(float2 screenCoords, float3 positionWS, float4x4 obbTransformInverse, float3 outerObbHalfLengths, uint sampleIndex, out float3 specular) { // make sure the pixel belongs to this probe volume // this is necessary since it could have the correct stencil value but actually reside // in another volume that's in between the camera and the volume we're rendering - if (!AabbContainsPoint(aabbMin, aabbMax, positionWS)) + if (!ObbContainsPoint(obbTransformInverse, outerObbHalfLengths, positionWS)) { return false; } @@ -47,7 +47,11 @@ bool ComputeProbeSpecular(float2 screenCoords, float3 positionWS, float3 aabbMin float3 localReflectDir = reflectDir; if (ObjectSrg::m_useParallaxCorrection) { - localReflectDir = ApplyParallaxCorrection(ObjectSrg::m_outerAabbMin, ObjectSrg::m_outerAabbMax, ObjectSrg::m_aabbPos, positionWS, reflectDir); + localReflectDir = ApplyParallaxCorrectionOBB( + ObjectSrg::GetWorldMatrixInverse(), + ObjectSrg::m_outerObbHalfLengths, + positionWS, + reflectDir); } // sample reflection cubemap with the appropriate roughness mip diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.azsl index 209605be03..a0734caf02 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderInner.azsl @@ -75,7 +75,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) // compute specular using the probe cubemap and the roughness, normals, and specularF0 for the surface float3 specular = float3(0.0f, 0.0f, 0.0f); - if (!ComputeProbeSpecular(IN.m_position.xy, positionWS, ObjectSrg::m_innerAabbMin, ObjectSrg::m_innerAabbMax, sampleIndex, specular)) + if (!ComputeProbeSpecular(IN.m_position.xy, positionWS, ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_innerObbHalfLengths, sampleIndex, specular)) { discard; } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderObjectSrg.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderObjectSrg.azsli index 92ecd82dee..8151ed2fd5 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderObjectSrg.azsli +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderObjectSrg.azsli @@ -13,12 +13,9 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject { row_major float3x4 m_modelToWorld; - - float3 m_aabbPos; - float3 m_outerAabbMin; - float3 m_outerAabbMax; - float3 m_innerAabbMin; - float3 m_innerAabbMax; + row_major float3x4 m_modelToWorldInverse; // does not include extents + float3 m_outerObbHalfLengths; + float3 m_innerObbHalfLengths; bool m_useParallaxCorrection; TextureCube m_reflectionCubeMap; @@ -35,4 +32,18 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject modelToWorld[2] = ObjectSrg::m_modelToWorld[2]; return modelToWorld; } + + float4x4 GetWorldMatrixInverse() + { + float4x4 modelToWorldInverse = float4x4( + float4(1, 0, 0, 0), + float4(0, 1, 0, 0), + float4(0, 0, 1, 0), + float4(0, 0, 0, 1)); + + modelToWorldInverse[0] = ObjectSrg::m_modelToWorldInverse[0]; + modelToWorldInverse[1] = ObjectSrg::m_modelToWorldInverse[1]; + modelToWorldInverse[2] = ObjectSrg::m_modelToWorldInverse[2]; + return modelToWorldInverse; + } } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.azsl index be94a53588..ac97172f1f 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Reflections/ReflectionProbeRenderOuter.azsl @@ -77,7 +77,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) // compute specular using the probe cubemap and the roughness, normals, and specularF0 for the surface float3 specular = float3(0.0f, 0.0f, 0.0f); - if (!ComputeProbeSpecular(IN.m_position.xy, positionWS, ObjectSrg::m_outerAabbMin, ObjectSrg::m_outerAabbMax, sampleIndex, specular)) + if (!ComputeProbeSpecular(IN.m_position.xy, positionWS, ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_outerObbHalfLengths, sampleIndex, specular)) { discard; } @@ -85,13 +85,17 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex) // determine blend based on position with respect to the inner and outer AABBs // if it's inside the inner AABB it blends at 100%, otherwise it's the percentage of the distance between the inner/outer AABB float blendWeight = 1.0f; - if (!AabbContainsPoint(ObjectSrg::m_innerAabbMin, ObjectSrg::m_innerAabbMax, positionWS)) + if (!ObbContainsPoint(ObjectSrg::GetWorldMatrixInverse(), ObjectSrg::m_innerObbHalfLengths, positionWS)) { // not inside the inner AABB, so it's in between the inner and outer AABBs // compute blend amount based on the distance to the outer AABB - blendWeight = ComputeLerpBetweenInnerOuterAABBs(ObjectSrg::m_innerAabbMin, ObjectSrg::m_innerAabbMax, ObjectSrg::m_outerAabbMax, ObjectSrg::m_aabbPos, positionWS); + blendWeight = ComputeLerpBetweenInnerOuterOBBs( + ObjectSrg::GetWorldMatrixInverse(), + ObjectSrg::m_innerObbHalfLengths, + ObjectSrg::m_outerObbHalfLengths, + positionWS); } - + // retrieve the blend weight of all probes at this location float blendWeightAllProbes = PassSrg::m_blendWeight.Load(IN.m_position.xy, sampleIndex).r; diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index 67702a8176..41ccec0fb5 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -1119,20 +1119,17 @@ namespace AZ if (reflectionProbeFeatureProcessor && (m_descriptor.m_useForwardPassIblSpecular || m_hasForwardPassIblSpecularMaterial)) { // retrieve probe constant indices - AZ::RHI::ShaderInputConstantIndex posConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_aabbPos")); - AZ_Error("MeshDataInstance", posConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + AZ::RHI::ShaderInputConstantIndex modelToWorldConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorld")); + AZ_Error("MeshDataInstance", modelToWorldConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); - AZ::RHI::ShaderInputConstantIndex outerAabbMinConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_outerAabbMin")); - AZ_Error("MeshDataInstance", outerAabbMinConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + AZ::RHI::ShaderInputConstantIndex modelToWorldInverseConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_modelToWorldInverse")); + AZ_Error("MeshDataInstance", modelToWorldInverseConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); - AZ::RHI::ShaderInputConstantIndex outerAabbMaxConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_outerAabbMax")); - AZ_Error("MeshDataInstance", outerAabbMaxConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + AZ::RHI::ShaderInputConstantIndex outerObbHalfLengthsConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_outerObbHalfLengths")); + AZ_Error("MeshDataInstance", outerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); - AZ::RHI::ShaderInputConstantIndex innerAabbMinConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_innerAabbMin")); - AZ_Error("MeshDataInstance", innerAabbMinConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); - - AZ::RHI::ShaderInputConstantIndex innerAabbMaxConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_innerAabbMax")); - AZ_Error("MeshDataInstance", innerAabbMaxConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); + AZ::RHI::ShaderInputConstantIndex innerObbHalfLengthsConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_innerObbHalfLengths")); + AZ_Error("MeshDataInstance", innerObbHalfLengthsConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); AZ::RHI::ShaderInputConstantIndex useReflectionProbeConstantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_reflectionProbeData.m_useReflectionProbe")); AZ_Error("MeshDataInstance", useReflectionProbeConstantIndex.IsValid(), "Failed to find ReflectionProbe constant index"); @@ -1154,11 +1151,10 @@ namespace AZ if (!reflectionProbes.empty() && reflectionProbes[0]) { - m_shaderResourceGroup->SetConstant(posConstantIndex, reflectionProbes[0]->GetPosition()); - m_shaderResourceGroup->SetConstant(outerAabbMinConstantIndex, reflectionProbes[0]->GetOuterAabbWs().GetMin()); - m_shaderResourceGroup->SetConstant(outerAabbMaxConstantIndex, reflectionProbes[0]->GetOuterAabbWs().GetMax()); - m_shaderResourceGroup->SetConstant(innerAabbMinConstantIndex, reflectionProbes[0]->GetInnerAabbWs().GetMin()); - m_shaderResourceGroup->SetConstant(innerAabbMaxConstantIndex, reflectionProbes[0]->GetInnerAabbWs().GetMax()); + m_shaderResourceGroup->SetConstant(modelToWorldConstantIndex, reflectionProbes[0]->GetTransform()); + m_shaderResourceGroup->SetConstant(modelToWorldInverseConstantIndex, reflectionProbes[0]->GetTransform().GetInverse()); + m_shaderResourceGroup->SetConstant(outerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetOuterObbWs().GetHalfLengths()); + m_shaderResourceGroup->SetConstant(innerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetInnerObbWs().GetHalfLengths()); m_shaderResourceGroup->SetConstant(useReflectionProbeConstantIndex, true); m_shaderResourceGroup->SetConstant(useParallaxCorrectionConstantIndex, reflectionProbes[0]->GetUseParallaxCorrection()); diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp index 66c326e6e7..2be2ec72c8 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp @@ -138,43 +138,40 @@ namespace AZ if (m_updateSrg) { // stencil Srg - // Note: the stencil pass uses a slightly reduced inner AABB to avoid seams + // Note: the stencil pass uses a slightly reduced inner OBB to avoid seams Vector3 innerExtentsReduced = m_innerExtents - Vector3(0.1f, 0.1f, 0.1f); - Matrix3x4 modelToWorldStencil = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(innerExtentsReduced); + Matrix3x4 modelToWorldStencil = Matrix3x4::CreateFromQuaternionAndTranslation(m_transform.GetRotation(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(innerExtentsReduced); m_stencilSrg->SetConstant(m_reflectionRenderData->m_modelToWorldStencilConstantIndex, modelToWorldStencil); + m_stencilSrg->SetConstant(m_reflectionRenderData->m_modelToWorldInverseStencilConstantIndex, modelToWorldStencil.GetInverseFull()); m_stencilSrg->Compile(); + Matrix3x4 modelToWorldInverse = Matrix3x4::CreateFromTransform(m_transform).GetInverseFull(); + // blend weight Srg - Matrix3x4 modelToWorldOuter = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_outerExtents); + Matrix3x4 modelToWorldOuter = Matrix3x4::CreateFromQuaternionAndTranslation(m_transform.GetRotation(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_outerExtents); m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldOuter); - m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter()); - m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin()); - m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_outerAabbMaxRenderConstantIndex, m_outerAabbWs.GetMax()); - m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_innerAabbMinRenderConstantIndex, m_innerAabbWs.GetMin()); - m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_innerAabbMaxRenderConstantIndex, m_innerAabbWs.GetMax()); + m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_modelToWorldInverseRenderConstantIndex, modelToWorldInverse); + m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_outerObbHalfLengthsRenderConstantIndex, m_outerObbWs.GetHalfLengths()); + m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_innerObbHalfLengthsRenderConstantIndex, m_innerObbWs.GetHalfLengths()); m_blendWeightSrg->SetConstant(m_reflectionRenderData->m_useParallaxCorrectionRenderConstantIndex, m_useParallaxCorrection); m_blendWeightSrg->SetImage(m_reflectionRenderData->m_reflectionCubeMapRenderImageIndex, m_cubeMapImage); m_blendWeightSrg->Compile(); // render outer Srg m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldOuter); - m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter()); - m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin()); - m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_outerAabbMaxRenderConstantIndex, m_outerAabbWs.GetMax()); - m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_innerAabbMinRenderConstantIndex, m_innerAabbWs.GetMin()); - m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_innerAabbMaxRenderConstantIndex, m_innerAabbWs.GetMax()); + m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_modelToWorldInverseRenderConstantIndex, modelToWorldInverse); + m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_outerObbHalfLengthsRenderConstantIndex, m_outerObbWs.GetHalfLengths()); + m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_innerObbHalfLengthsRenderConstantIndex, m_innerObbWs.GetHalfLengths()); m_renderOuterSrg->SetConstant(m_reflectionRenderData->m_useParallaxCorrectionRenderConstantIndex, m_useParallaxCorrection); m_renderOuterSrg->SetImage(m_reflectionRenderData->m_reflectionCubeMapRenderImageIndex, m_cubeMapImage); m_renderOuterSrg->Compile(); // render inner Srg - Matrix3x4 modelToWorldInner = Matrix3x4::CreateFromMatrix3x3AndTranslation(Matrix3x3::CreateIdentity(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_innerExtents); + Matrix3x4 modelToWorldInner = Matrix3x4::CreateFromQuaternionAndTranslation(m_transform.GetRotation(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(m_innerExtents); m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_modelToWorldRenderConstantIndex, modelToWorldInner); - m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_aabbPosRenderConstantIndex, m_outerAabbWs.GetCenter()); - m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_outerAabbMinRenderConstantIndex, m_outerAabbWs.GetMin()); - m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_outerAabbMaxRenderConstantIndex, m_outerAabbWs.GetMax()); - m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_innerAabbMinRenderConstantIndex, m_innerAabbWs.GetMin()); - m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_innerAabbMaxRenderConstantIndex, m_innerAabbWs.GetMax()); + m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_modelToWorldInverseRenderConstantIndex, modelToWorldInverse); + m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_outerObbHalfLengthsRenderConstantIndex, m_outerObbWs.GetHalfLengths()); + m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_innerObbHalfLengthsRenderConstantIndex, m_innerObbWs.GetHalfLengths()); m_renderInnerSrg->SetConstant(m_reflectionRenderData->m_useParallaxCorrectionRenderConstantIndex, m_useParallaxCorrection); m_renderInnerSrg->SetImage(m_reflectionRenderData->m_reflectionCubeMapRenderImageIndex, m_cubeMapImage); m_renderInnerSrg->Compile(); @@ -244,22 +241,22 @@ namespace AZ m_outerExtents *= m_transform.GetUniformScale(); m_innerExtents *= m_transform.GetUniformScale(); - m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents / 2.0f); - m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents / 2.0f); + m_outerObbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_outerExtents / 2.0f); + m_innerObbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_innerExtents / 2.0f); m_updateSrg = true; } void ReflectionProbe::SetOuterExtents(const AZ::Vector3& outerExtents) { m_outerExtents = outerExtents * m_transform.GetUniformScale(); - m_outerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_outerExtents / 2.0f); + m_outerObbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_outerExtents / 2.0f); m_updateSrg = true; } void ReflectionProbe::SetInnerExtents(const AZ::Vector3& innerExtents) { m_innerExtents = innerExtents * m_transform.GetUniformScale(); - m_innerAabbWs = Aabb::CreateCenterHalfExtents(m_transform.GetTranslation(), m_innerExtents / 2.0f); + m_innerObbWs = Obb::CreateFromPositionRotationAndHalfLengths(m_transform.GetTranslation(), m_transform.GetRotation(), m_innerExtents / 2.0f); m_updateSrg = true; } @@ -394,13 +391,14 @@ namespace AZ lod.m_screenCoverageMax = 1.0f; // update cullable bounds + Aabb outerAabb = Aabb::CreateFromObb(m_outerObbWs); Vector3 center; float radius; - m_outerAabbWs.GetAsSphere(center, radius); + outerAabb.GetAsSphere(center, radius); m_cullable.m_cullData.m_boundingSphere = Sphere(center, radius); - m_cullable.m_cullData.m_boundingObb = m_outerAabbWs.GetTransformedObb(AZ::Transform::CreateIdentity()); - m_cullable.m_cullData.m_visibilityEntry.m_boundingVolume = m_outerAabbWs; + m_cullable.m_cullData.m_boundingObb = m_outerObbWs; + m_cullable.m_cullData.m_visibilityEntry.m_boundingVolume = outerAabb; m_cullable.m_cullData.m_visibilityEntry.m_userData = &m_cullable; m_cullable.m_cullData.m_visibilityEntry.m_typeFlags = AzFramework::VisibilityEntry::TYPE_RPI_Cullable; diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h index bb30ce9470..169c4f1df2 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h @@ -56,12 +56,11 @@ namespace AZ RHI::DrawListTag m_renderInnerDrawListTag; RHI::ShaderInputConstantIndex m_modelToWorldStencilConstantIndex; + RHI::ShaderInputConstantIndex m_modelToWorldInverseStencilConstantIndex; RHI::ShaderInputConstantIndex m_modelToWorldRenderConstantIndex; - RHI::ShaderInputConstantIndex m_aabbPosRenderConstantIndex; - RHI::ShaderInputConstantIndex m_outerAabbMinRenderConstantIndex; - RHI::ShaderInputConstantIndex m_outerAabbMaxRenderConstantIndex; - RHI::ShaderInputConstantIndex m_innerAabbMinRenderConstantIndex; - RHI::ShaderInputConstantIndex m_innerAabbMaxRenderConstantIndex; + RHI::ShaderInputConstantIndex m_modelToWorldInverseRenderConstantIndex; + RHI::ShaderInputConstantIndex m_outerObbHalfLengthsRenderConstantIndex; + RHI::ShaderInputConstantIndex m_innerObbHalfLengthsRenderConstantIndex; RHI::ShaderInputConstantIndex m_useParallaxCorrectionRenderConstantIndex; RHI::ShaderInputImageIndex m_reflectionCubeMapRenderImageIndex; }; @@ -78,6 +77,7 @@ namespace AZ void Simulate(uint32_t probeIndex); const Vector3& GetPosition() const { return m_transform.GetTranslation(); } + const AZ::Transform& GetTransform() const { return m_transform; } void SetTransform(const AZ::Transform& transform); const AZ::Vector3& GetOuterExtents() const { return m_outerExtents; } @@ -86,8 +86,8 @@ namespace AZ const AZ::Vector3& GetInnerExtents() const { return m_innerExtents; } void SetInnerExtents(const AZ::Vector3& innerExtents); - const Aabb& GetOuterAabbWs() const { return m_outerAabbWs; } - const Aabb& GetInnerAabbWs() const { return m_innerAabbWs; } + const Obb& GetOuterObbWs() const { return m_outerObbWs; } + const Obb& GetInnerObbWs() const { return m_innerObbWs; } const Data::Instance& GetCubeMapImage() const { return m_cubeMapImage; } void SetCubeMapImage(const Data::Instance& cubeMapImage, const AZStd::string& relativePath); @@ -133,9 +133,9 @@ namespace AZ AZ::Vector3 m_outerExtents = AZ::Vector3(0.0f, 0.0f, 0.0f); AZ::Vector3 m_innerExtents = AZ::Vector3(0.0f, 0.0f, 0.0f); - // probe volume AABBs (world space), built from position and extents - Aabb m_outerAabbWs; - Aabb m_innerAabbWs; + // probe volume OBBs (world space), built from position and extents + Obb m_outerObbWs; + Obb m_innerObbWs; // cubemap Data::Instance m_cubeMapImage; diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp index 341d1a0274..5c07fbae66 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp @@ -92,6 +92,10 @@ namespace AZ m_reflectionRenderData.m_modelToWorldStencilConstantIndex = stencilSrgLayout->FindShaderInputConstantIndex(modelToWorldConstantName); AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldStencilConstantIndex.IsValid(), "Failed to find stencil shader input constant [%s]", modelToWorldConstantName.GetCStr()); + Name modelToWorldInverseConstantName = Name("m_modelToWorldInverse"); + m_reflectionRenderData.m_modelToWorldInverseStencilConstantIndex = stencilSrgLayout->FindShaderInputConstantIndex(modelToWorldInverseConstantName); + AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldInverseStencilConstantIndex.IsValid(), "Failed to find stencil shader input constant [%s]", modelToWorldInverseConstantName.GetCStr()); + // cache probe render shader indices // Note: the outer and inner render shaders use the same Srg Data::Instance renderReflectionSrg = RPI::ShaderResourceGroup::Create( @@ -104,25 +108,16 @@ namespace AZ m_reflectionRenderData.m_modelToWorldRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(modelToWorldConstantName); AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", modelToWorldConstantName.GetCStr()); - Name aabbPosConstantName = Name("m_aabbPos"); - m_reflectionRenderData.m_aabbPosRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(aabbPosConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_aabbPosRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", aabbPosConstantName.GetCStr()); + m_reflectionRenderData.m_modelToWorldInverseRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(modelToWorldInverseConstantName); + AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", modelToWorldInverseConstantName.GetCStr()); - Name outerAabbMinConstantName = Name("m_outerAabbMin"); - m_reflectionRenderData.m_outerAabbMinRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(outerAabbMinConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_outerAabbMinRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", outerAabbMinConstantName.GetCStr()); + Name outerObbHalfLengthsConstantName = Name("m_outerObbHalfLengths"); + m_reflectionRenderData.m_outerObbHalfLengthsRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(outerObbHalfLengthsConstantName); + AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_outerObbHalfLengthsRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", outerObbHalfLengthsConstantName.GetCStr()); - Name outerAabbMaxConstantName = Name("m_outerAabbMax"); - m_reflectionRenderData.m_outerAabbMaxRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(outerAabbMaxConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_outerAabbMaxRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", outerAabbMaxConstantName.GetCStr()); - - Name innerAabbMinConstantName = Name("m_innerAabbMin"); - m_reflectionRenderData.m_innerAabbMinRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(innerAabbMinConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_innerAabbMinRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", innerAabbMinConstantName.GetCStr()); - - Name innerAabbMaxConstantName = Name("m_innerAabbMax"); - m_reflectionRenderData.m_innerAabbMaxRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(innerAabbMaxConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_innerAabbMaxRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", innerAabbMaxConstantName.GetCStr()); + Name innerObbHalfLengthsConstantName = Name("m_innerObbHalfLengths"); + m_reflectionRenderData.m_innerObbHalfLengthsRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(innerObbHalfLengthsConstantName); + AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_innerObbHalfLengthsRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", innerObbHalfLengthsConstantName.GetCStr()); Name useParallaxCorrectionConstantName = Name("m_useParallaxCorrection"); m_reflectionRenderData.m_useParallaxCorrectionRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(useParallaxCorrectionConstantName); @@ -199,10 +194,11 @@ namespace AZ // sort the probes by descending inner volume size, so the smallest volumes are rendered last auto sortFn = [](AZStd::shared_ptr const& probe1, AZStd::shared_ptr const& probe2) -> bool { - const Aabb& aabb1 = probe1->GetInnerAabbWs(); - const Aabb& aabb2 = probe2->GetInnerAabbWs(); - float size1 = aabb1.GetXExtent() * aabb1.GetZExtent() * aabb1.GetYExtent(); - float size2 = aabb2.GetXExtent() * aabb2.GetZExtent() * aabb2.GetYExtent(); + const Obb& obb1 = probe1->GetInnerObbWs(); + const Obb& obb2 = probe2->GetInnerObbWs(); + float size1 = obb1.GetHalfLengthX() * obb1.GetHalfLengthZ() * obb1.GetHalfLengthY(); + float size2 = obb2.GetHalfLengthX() * obb2.GetHalfLengthZ() * obb2.GetHalfLengthY(); + return (size1 > size2); }; @@ -347,7 +343,7 @@ namespace AZ // simple AABB check to find the reflection probes that contain the position for (auto& reflectionProbe : m_reflectionProbes) { - if (reflectionProbe->GetOuterAabbWs().Contains(position) + if (reflectionProbe->GetOuterObbWs().Contains(position) && reflectionProbe->GetCubeMapImage() && reflectionProbe->GetCubeMapImage()->IsInitialized()) { diff --git a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli index a94e01e11b..b004623c4e 100644 --- a/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli +++ b/Gems/Atom/RPI/Assets/ShaderLib/Atom/RPI/Math.azsli @@ -116,6 +116,22 @@ float ComputeLerpBetweenInnerOuterAABBs(float3 innerAabbMin, float3 innerAabbMax return totalDistance > 0.0f ? saturate(shortestDistance / totalDistance) : 1.0f; } +// returns true if the Obb contains the specified point +bool ObbContainsPoint(float4x4 obbTransformInverse, float3 obbHalfExtents, float3 testPoint) +{ + // get the position in Obb local space, force to positive quadrant with abs() + float4 p = abs(mul(obbTransformInverse, float4(testPoint, 1.0f))); + return AabbContainsPoint(-obbHalfExtents, obbHalfExtents, p); +} + +// computes [0..1] percentage of a point that's in between the inner and outer OBBs +float ComputeLerpBetweenInnerOuterOBBs(float3x4 obbTransformInverse, float3 innerObbHalfExtents, float3 outerObbHalfExtents, float3 position) +{ + // get the position in Obb local space, force to positive quadrant with abs() + float3 p = abs(mul(obbTransformInverse, float4(position, 1.0f))); + return ComputeLerpBetweenInnerOuterAABBs(-innerObbHalfExtents, innerObbHalfExtents, outerObbHalfExtents, float3(0.0f, 0.0f, 0.0f), p); +} + // ---------- Normal Encoding ----------- // Encode/Decode functions for Signed Octahedron normals diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp index 4f4f21ab0f..aa68333108 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp @@ -212,6 +212,9 @@ namespace AZ AZ::Vector3 position = AZ::Vector3::CreateZero(); AZ::TransformBus::EventResult(position, GetEntityId(), &AZ::TransformBus::Events::GetWorldTranslation); + AZ::Quaternion rotationQuaternion = AZ::Quaternion::CreateIdentity(); + AZ::TransformBus::EventResult(rotationQuaternion, GetEntityId(), &AZ::TransformBus::Events::GetWorldRotationQuaternion); + AZ::Matrix3x3 rotationMatrix = AZ::Matrix3x3::CreateFromQuaternion(rotationQuaternion); float scale = 1.0f; AZ::TransformBus::EventResult(scale, GetEntityId(), &AZ::TransformBus::Events::GetLocalUniformScale); @@ -224,9 +227,7 @@ namespace AZ AZ::Vector3 innerExtents(configuration.m_innerWidth, configuration.m_innerLength, configuration.m_innerHeight); innerExtents *= scale; - AZ::Vector3 innerMin(position.GetX() - innerExtents.GetX() / 2, position.GetY() - innerExtents.GetY() / 2, position.GetZ() - innerExtents.GetZ() / 2); - AZ::Vector3 innerMax(position.GetX() + innerExtents.GetX() / 2, position.GetY() + innerExtents.GetY() / 2, position.GetZ() + innerExtents.GetZ() / 2); - debugDisplay.DrawWireBox(innerMin, innerMax); + debugDisplay.DrawWireOBB(position, rotationMatrix.GetBasisX(), rotationMatrix.GetBasisY(), rotationMatrix.GetBasisZ(), innerExtents / 2.0f); } AZ::Aabb EditorReflectionProbeComponent::GetEditorSelectionBoundsViewport([[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo) From a3dfb8869691abf341dd27ac50dead1a890b6c52 Mon Sep 17 00:00:00 2001 From: pereslav Date: Thu, 16 Sep 2021 17:48:53 +0100 Subject: [PATCH 20/84] Added support for instantiating network spawnables for any spawnables, not just root spawnable Signed-off-by: pereslav --- .../Spawnable/SpawnableEntitiesInterface.h | 9 +++ .../Spawnable/SpawnableEntitiesManager.cpp | 20 +++++ .../Spawnable/SpawnableEntitiesManager.h | 6 ++ .../Mocks/MockSpawnableEntitiesInterface.h | 2 + .../NetworkEntity/NetworkEntityManager.cpp | 79 ++++++++++++++----- .../NetworkEntity/NetworkEntityManager.h | 12 ++- 6 files changed, 105 insertions(+), 23 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h index 4b09dcbc75..254df8f1b0 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h @@ -320,6 +320,15 @@ namespace AzFramework //! @param optionalArgs Optional additional arguments, see BarrierOptionalArgs. virtual void Barrier(EntitySpawnTicket& ticket, BarrierCallback completionCallback, BarrierOptionalArgs optionalArgs = {}) = 0; + //! Register a handler for OnSpawned events. + //! @param handler The handler to receive the event. + virtual void AddOnSpawnedHandler(AZ::Event, + const AZStd::vector&, const void*>::Handler& handler) = 0; + + //! Register a handler for OnDespawned events. + //! @param handler The handler to receive the event. + virtual void AddOnDespawnedHandler(AZ::Event, const void*>::Handler& handler) = 0; + protected: [[nodiscard]] virtual AZStd::pair CreateTicket(AZ::Data::Asset&& spawnable) = 0; virtual void DestroyTicket(void* ticket) = 0; diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp index 5fa072a451..f052f83224 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp @@ -146,6 +146,16 @@ namespace AzFramework QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry)); } + void SpawnableEntitiesManager::AddOnSpawnedHandler(AZ::Event, const AZStd::vector&, const void*>::Handler& handler) + { + handler.Connect(m_onSpawnedEvent); + } + + void SpawnableEntitiesManager::AddOnDespawnedHandler(AZ::Event, const void*>::Handler& handler) + { + handler.Connect(m_onDespawnedEvent); + } + auto SpawnableEntitiesManager::ProcessQueue(CommandQueuePriority priority) -> CommandQueueStatus { CommandQueueStatus result = CommandQueueStatus::NoCommandsLeft; @@ -349,6 +359,8 @@ namespace AzFramework ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount, ticket.m_spawnedEntities.end())); } + m_onSpawnedEvent.Signal(ticket.m_spawnable, ticket.m_spawnedEntities, &ticket); + ticket.m_currentRequestId++; return true; } @@ -429,6 +441,8 @@ namespace AzFramework ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount, ticket.m_spawnedEntities.end())); } + m_onSpawnedEvent.Signal(ticket.m_spawnable, ticket.m_spawnedEntities, &ticket); + ticket.m_currentRequestId++; return true; } @@ -460,6 +474,8 @@ namespace AzFramework request.m_completionCallback(request.m_ticketId); } + m_onDespawnedEvent.Signal(ticket.m_spawnable, &ticket); + ticket.m_currentRequestId++; return true; } @@ -487,6 +503,8 @@ namespace AzFramework } } + m_onDespawnedEvent.Signal(ticket.m_spawnable, &ticket); + // Rebuild the list of entities. ticket.m_spawnedEntities.clear(); const Spawnable::EntityList& entities = request.m_spawnable->GetEntities(); @@ -544,6 +562,8 @@ namespace AzFramework ticket.m_spawnedEntities.begin(), ticket.m_spawnedEntities.end())); } + m_onSpawnedEvent.Signal(ticket.m_spawnable, ticket.m_spawnedEntities, &ticket); + ticket.m_currentRequestId++; return true; diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h index 69985f8aa9..c78b1778a4 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h @@ -69,6 +69,9 @@ namespace AzFramework void Barrier(EntitySpawnTicket& spawnInfo, BarrierCallback completionCallback, BarrierOptionalArgs optionalArgs = {}) override; + void AddOnSpawnedHandler(AZ::Event, const AZStd::vector&, const void*>::Handler& handler) override; + void AddOnDespawnedHandler(AZ::Event, const void*>::Handler& handler) override; + // // The following function is thread safe but intended to be run from the main thread. // @@ -224,6 +227,9 @@ namespace AzFramework //! SpawnablePriority_Default which gives users a bit of room to fine tune the priorities as this value can be configured //! through the Settings Registry under the key "/O3DE/AzFramework/Spawnables/HighPriorityThreshold". SpawnablePriority m_highPriorityThreshold { 64 }; + + AZ::Event, const AZStd::vector&, const void*> m_onSpawnedEvent; + AZ::Event, const void*> m_onDespawnedEvent; }; AZ_DEFINE_ENUM_BITWISE_OPERATORS(AzFramework::SpawnableEntitiesManager::CommandQueuePriority); diff --git a/Code/Framework/AzFramework/Tests/Mocks/MockSpawnableEntitiesInterface.h b/Code/Framework/AzFramework/Tests/Mocks/MockSpawnableEntitiesInterface.h index a5df7af4c3..89e79ecf9b 100644 --- a/Code/Framework/AzFramework/Tests/Mocks/MockSpawnableEntitiesInterface.h +++ b/Code/Framework/AzFramework/Tests/Mocks/MockSpawnableEntitiesInterface.h @@ -59,6 +59,8 @@ namespace AzFramework MOCK_METHOD1(CreateTicket, AZStd::pair(AZ::Data::Asset&& spawnable)); MOCK_METHOD1(DestroyTicket, void(void* ticket)); + MOCK_METHOD1(AddOnSpawnedHandler, void(AZ::Event, const AZStd::vector&, const void*>::Handler& handler)); + MOCK_METHOD1(AddOnDespawnedHandler, void(AZ::Event, const void*>::Handler& handler)); /** Installs some default result values for the above functions. * Note that you can always override these in scope of your test by adding additional ON_CALL / EXPECT_CALL diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 793acc17ff..62b57d9603 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -30,9 +30,14 @@ namespace Multiplayer : m_networkEntityAuthorityTracker(*this) , m_removeEntitiesEvent([this] { RemoveEntities(); }, AZ::Name("NetworkEntityManager remove entities event")) , m_updateEntityDomainEvent([this] { UpdateEntityDomain(); }, AZ::Name("NetworkEntityManager update entity domain event")) + , m_onSpawnedHandler([this](AZ::Data::Asset spawnable, const AZStd::vector& entities, const void* spawnTicket) { this->OnSpawned(spawnable, entities, spawnTicket); }) + , m_onDespawnedHandler([this](AZ::Data::Asset spawnable, const void* spawnTicket) { this->OnDespawned(spawnable, spawnTicket); }) { AZ::Interface::Register(this); AzFramework::RootSpawnableNotificationBus::Handler::BusConnect(); + + AzFramework::SpawnableEntitiesInterface::Get()->AddOnSpawnedHandler(m_onSpawnedHandler); + AzFramework::SpawnableEntitiesInterface::Get()->AddOnDespawnedHandler(m_onDespawnedHandler); } NetworkEntityManager::~NetworkEntityManager() @@ -467,30 +472,39 @@ namespace Multiplayer return netEntityId; } - AzFramework::EntitySpawnTicket NetworkEntityManager::RequestNetSpawnableInstantiation(const AZ::Data::Asset& rootSpawnable) + AZStd::unique_ptr NetworkEntityManager::RequestNetSpawnableInstantiation( + const AZ::Data::Asset& rootSpawnable, const AZStd::vector& entities) { - const AzFramework::Spawnable::EntityList& entityList = rootSpawnable->GetEntities(); - if (entityList.empty()) + if (entities.empty()) { AZ_Error("NetworkEntityManager", false, "RequestNetSpawnableInstantiation: No entities in the spawnable %s", rootSpawnable.GetHint().c_str()); - return {}; + return nullptr; } // The first entity in every spawnable is the root one - const AZ::Entity* rootEntity = (entityList.begin())->get(); + const AZ::Entity* rootEntity = *entities.begin(); if(!rootEntity) { AZ_Error("NetworkEntityManager", false, "RequestNetSpawnableInstantiation: Root entity is null in the spawnable %s", rootSpawnable.GetHint().c_str()); - return {}; + return nullptr; } const auto* holderComponent = rootEntity->FindComponent(); if(!holderComponent) { // This spawnable doesn't have a corresponding network spawnable. - return {}; + return nullptr; + } + + AzFramework::TransformComponent* rootEntityTransform = + rootEntity->FindComponent(); + if (!rootEntityTransform) + { + AZ_Error("NetworkEntityManager", false, + "RequestNetSpawnableInstantiation: Root entity has no transform in the spawnable %s", rootSpawnable.GetHint().c_str()); + return nullptr; } // Retrieve the corresponding network spawnable asset @@ -504,14 +518,26 @@ namespace Multiplayer AZ::Interface::Get()->GetSpawnableNameFromAssetId(netSpawnableAsset.GetId()); // Pre-insertion callback allows us to do network-specific setup for the entities before they are added to the scene - optionalArgs.m_preInsertionCallback = [netSpawnableName](AzFramework::EntitySpawnTicket::Id, - AzFramework::SpawnableEntityContainerView entities) + optionalArgs.m_preInsertionCallback = [netSpawnableName, rootTransform = rootEntityTransform->GetWorldTM()] + (AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableEntityContainerView entities) { + bool shouldUpdateTransform = (rootTransform.IsClose(AZ::Transform::Identity()) == false); + for (uint32_t netEntityIndex = 0, entitiesSize = aznumeric_cast(entities.size()); netEntityIndex < entitiesSize; netEntityIndex++) { AZ::Entity* netEntity = *(entities.begin() + netEntityIndex); + if(shouldUpdateTransform) + { + AzFramework::TransformComponent* netEntityTransform = + netEntity->FindComponent(); + + AZ::Transform worldTm = netEntityTransform->GetWorldTM(); + worldTm = rootTransform * worldTm; + netEntityTransform->SetWorldTM(worldTm); + } + PrefabEntityId prefabEntityId; prefabEntityId.m_prefabName = netSpawnableName; prefabEntityId.m_entityOffset = netEntityIndex; @@ -520,13 +546,13 @@ namespace Multiplayer }; // Spawn with the newly created ticket. This allows the calling code to manage the lifetime of the constructed entities - AzFramework::EntitySpawnTicket ticket(netSpawnableAsset); - AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(ticket, AZStd::move(optionalArgs)); + auto ticket = AZStd::make_unique(netSpawnableAsset); + AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(*ticket, AZStd::move(optionalArgs)); return ticket; } - void NetworkEntityManager::OnRootSpawnableAssigned( - [[maybe_unused]] AZ::Data::Asset rootSpawnable, [[maybe_unused]] uint32_t generation) + void NetworkEntityManager::OnRootSpawnableAssigned(AZ::Data::Asset rootSpawnable, + [[maybe_unused]] uint32_t generation) { auto* multiplayer = GetMultiplayer(); const auto agentType = multiplayer->GetAgentType(); @@ -535,11 +561,6 @@ namespace Multiplayer { multiplayer->SendReadyForEntityUpdates(true); } - - if(ShouldSpawnNetEntities()) - { - m_rootNetSpawnableTicket = RequestNetSpawnableInstantiation(rootSpawnable); - } } void NetworkEntityManager::OnRootSpawnableReleased([[maybe_unused]] uint32_t generation) @@ -552,13 +573,29 @@ namespace Multiplayer multiplayer->SendReadyForEntityUpdates(false); } - // Despawn any remaining net entities created locally - if (m_rootNetSpawnableTicket.IsValid()) + m_netSpawnableTickets.clear(); + } + + void NetworkEntityManager::OnSpawned(AZ::Data::Asset spawnable, + const AZStd::vector& entities, const void* spawnTicket) + { + if (ShouldSpawnNetEntities()) { - AzFramework::SpawnableEntitiesInterface::Get()->DespawnAllEntities(m_rootNetSpawnableTicket); + AZStd::unique_ptr ticket = RequestNetSpawnableInstantiation(spawnable, entities); + if(ticket) + { + AZ::Data::AssetId spawnableAssetId = spawnable.GetId(); + m_netSpawnableTickets[spawnTicket] = AZStd::move(ticket); + } } } + void NetworkEntityManager::OnDespawned([[maybe_unused]] AZ::Data::Asset spawnable, + const void* spawnTicket) + { + m_netSpawnableTickets.erase(spawnTicket); + } + void NetworkEntityManager::SetupNetEntity(AZ::Entity* netEntity, PrefabEntityId prefabEntityId, NetEntityRole netEntityRole) { auto* netBindComponent = netEntity->FindComponent(); diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h index a5956b448f..14efa4feeb 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h @@ -94,10 +94,14 @@ namespace Multiplayer void RemoveEntities(); NetEntityId NextId(); bool ShouldSpawnNetEntities() const; + void OnSpawned(AZ::Data::Asset spawnable, + const AZStd::vector& entities, const void* spawnTicket); + void OnDespawned(AZ::Data::Asset spawnable, const void* spawnTicket); // Note: This is an async function. // The instantiated entities are not available immediately but will be constructed by the spawnable system - AzFramework::EntitySpawnTicket RequestNetSpawnableInstantiation(const AZ::Data::Asset& rootSpawnable); + AZStd::unique_ptr RequestNetSpawnableInstantiation( + const AZ::Data::Asset& rootSpawnable, const AZStd::vector& entities); NetworkEntityTracker m_networkEntityTracker; NetworkEntityAuthorityTracker m_networkEntityAuthorityTracker; @@ -126,6 +130,10 @@ namespace Multiplayer DeferredRpcMessages m_localDeferredRpcMessages; NetworkSpawnableLibrary m_networkPrefabLibrary; - AzFramework::EntitySpawnTicket m_rootNetSpawnableTicket; + + AZStd::unordered_map> m_netSpawnableTickets; + + AZ::Event, const AZStd::vector&, const void*>::Handler m_onSpawnedHandler; + AZ::Event, const void*>::Handler m_onDespawnedHandler; }; } From 6914cfe5bc670218562efd2ef5dd5de14a3cfcec Mon Sep 17 00:00:00 2001 From: nvsickle Date: Thu, 16 Sep 2021 14:33:15 -0700 Subject: [PATCH 21/84] Remove legacy Cry dependencies from the Camera Gem Signed-off-by: nvsickle --- Gems/Camera/Code/CMakeLists.txt | 8 +- Gems/Camera/Code/Source/CameraComponent.cpp | 2 - Gems/Camera/Code/Source/CameraComponent.h | 3 - .../Code/Source/CameraComponentController.cpp | 84 +++---------------- .../Code/Source/CameraComponentController.h | 15 ++-- .../Source/CameraEditorSystemComponent.cpp | 23 +---- Gems/Camera/Code/Source/CameraGem.cpp | 5 +- .../Code/Source/EditorCameraComponent.cpp | 11 ++- .../Code/Source/EditorCameraComponent.h | 2 - .../Source/ViewportCameraSelectorWindow.cpp | 7 +- 10 files changed, 34 insertions(+), 126 deletions(-) diff --git a/Gems/Camera/Code/CMakeLists.txt b/Gems/Camera/Code/CMakeLists.txt index 3fbeec0908..329e0c88ad 100644 --- a/Gems/Camera/Code/CMakeLists.txt +++ b/Gems/Camera/Code/CMakeLists.txt @@ -18,8 +18,8 @@ ly_add_target( PUBLIC Gem::Atom_RPI.Public AZ::AtomCore - PRIVATE - Legacy::CryCommon + AZ::AzCore + AZ::AzFramework ) ly_add_target( @@ -32,7 +32,6 @@ ly_add_target( Source BUILD_DEPENDENCIES PRIVATE - Legacy::CryCommon Gem::Camera.Static ) @@ -56,9 +55,6 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) Source BUILD_DEPENDENCIES PRIVATE - Legacy::CryCommon - Legacy::Editor.Headers - Legacy::EditorCommon AZ::AzToolsFramework Gem::Camera.Static ) diff --git a/Gems/Camera/Code/Source/CameraComponent.cpp b/Gems/Camera/Code/Source/CameraComponent.cpp index 0b892b0367..960f13a082 100644 --- a/Gems/Camera/Code/Source/CameraComponent.cpp +++ b/Gems/Camera/Code/Source/CameraComponent.cpp @@ -14,9 +14,7 @@ #include "CameraComponent.h" -#include #include -#include #include namespace Camera diff --git a/Gems/Camera/Code/Source/CameraComponent.h b/Gems/Camera/Code/Source/CameraComponent.h index de6e98154d..b9c94d482f 100644 --- a/Gems/Camera/Code/Source/CameraComponent.h +++ b/Gems/Camera/Code/Source/CameraComponent.h @@ -11,9 +11,6 @@ #include #include -#include -#include -#include #include #include diff --git a/Gems/Camera/Code/Source/CameraComponentController.cpp b/Gems/Camera/Code/Source/CameraComponentController.cpp index a8b5b8992e..b8e5738145 100644 --- a/Gems/Camera/Code/Source/CameraComponentController.cpp +++ b/Gems/Camera/Code/Source/CameraComponentController.cpp @@ -9,7 +9,6 @@ #include "CameraComponentController.h" #include "CameraViewRegistrationBus.h" -#include #include #include #include @@ -53,7 +52,7 @@ namespace Camera ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::ValuesOnly) ->DataElement(AZ::Edit::UIHandlers::Default, &CameraComponentConfig::m_fov, "Field of view", "Vertical field of view in degrees") - ->Attribute(AZ::Edit::Attributes::Min, MIN_FOV) + ->Attribute(AZ::Edit::Attributes::Min, MinFoV) ->Attribute(AZ::Edit::Attributes::Suffix, " degrees") ->Attribute(AZ::Edit::Attributes::Step, 1.f) ->Attribute(AZ::Edit::Attributes::Max, AZ::RadToDeg(AZ::Constants::Pi) - 0.0001f) //We assert at fovs >= Pi so set the max for this field to be just under that @@ -61,7 +60,7 @@ namespace Camera ->Attribute(AZ::Edit::Attributes::Visibility, &CameraComponentConfig::GetPerspectiveParameterVisibility) ->DataElement(AZ::Edit::UIHandlers::Default, &CameraComponentConfig::m_nearClipDistance, "Near clip distance", "Distance to the near clip plane of the view Frustum") - ->Attribute(AZ::Edit::Attributes::Min, CAMERA_MIN_NEAR) + ->Attribute(AZ::Edit::Attributes::Min, MinimumNearPlaneDistance) ->Attribute(AZ::Edit::Attributes::Suffix, " m") ->Attribute(AZ::Edit::Attributes::Step, 0.1f) ->Attribute(AZ::Edit::Attributes::Max, &CameraComponentConfig::GetFarClipDistance) @@ -150,6 +149,11 @@ namespace Camera } } + void CameraComponentController::SetShouldActivateFunction(AZStd::function shouldActivateFunction) + { + m_shouldActivateFn = shouldActivateFunction; + } + void CameraComponentController::Reflect(AZ::ReflectContext* context) { CameraComponentConfig::Reflect(context); @@ -202,36 +206,6 @@ namespace Camera { m_entityId = entityId; - if ((!m_viewSystem)||(!m_system)) - { - // perform first-time init - if (gEnv) - { - m_system = gEnv->pSystem; - } - if (m_system) - { - // Initialize local view. - m_viewSystem = m_system->GetIViewSystem(); - if (!m_viewSystem) - { - AZ_Error("CameraComponent", m_viewSystem != nullptr, "The CameraComponent shouldn't be used without a local view system"); - } - } - } - - if (m_viewSystem) - { - if (m_view == nullptr) - { - m_view = m_viewSystem->CreateView(); - - AZ::Entity* entity = nullptr; - AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, m_entityId); - m_view->LinkTo(entity); - } - } - auto atomViewportRequests = AZ::Interface::Get(); if (atomViewportRequests) { @@ -270,9 +244,8 @@ namespace Camera CameraBus::Handler::BusConnect(); CameraNotificationBus::Broadcast(&CameraNotificationBus::Events::OnCameraAdded, m_entityId); - // Activate our camera if we're running from the launcher or Editor game mode - // Otherwise, let the Editor keep managing the active camera - if (m_config.m_makeActiveViewOnActivation && (!gEnv || !gEnv->IsEditor() || gEnv->IsEditorGameMode())) + // Only activate if we're configured to do so, and our activation call back indicates that we should + if (m_config.m_makeActiveViewOnActivation && (!m_shouldActivateFn || m_shouldActivateFn())) { MakeActiveView(); } @@ -284,20 +257,6 @@ namespace Camera CameraBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::Handler::BusDisconnect(m_entityId); CameraRequestBus::Handler::BusDisconnect(m_entityId); - if (m_viewSystem) - { - if (m_view != nullptr && m_viewSystem->GetViewId(m_view) != 0) - { - m_view->Unlink(); - } - if (m_viewSystem->GetActiveView() == m_view) - { - m_viewSystem->SetActiveView(m_prevViewId); - } - m_viewSystem->RemoveView(m_view); - m_prevViewId = 0; - m_view = nullptr; - } auto atomViewportRequests = AZ::Interface::Get(); if (atomViewportRequests) @@ -429,13 +388,6 @@ namespace Camera return; } - // Set Legacy Cry view, if it exists - if (m_viewSystem) - { - m_prevViewId = AZ::u32(m_viewSystem->GetActiveViewId()); - m_viewSystem->SetActiveView(m_view); - } - // Set Atom camera, if it exists if (m_atomCamera) { @@ -461,12 +413,6 @@ namespace Camera return; } - if (m_view) - { - CCamera& camera = m_view->GetCamera(); - camera.SetMatrix(AZTransformToLYTransform(world.GetOrthogonalized())); - } - if (m_atomCamera) { m_updatingTransformFromEntity = true; @@ -495,25 +441,15 @@ namespace Camera void CameraComponentController::UpdateCamera() { - if (m_view) - { - auto viewParams = *m_view->GetCurrentParams(); - viewParams.fov = AZ::DegToRad(m_config.m_fov); - viewParams.nearplane = m_config.m_nearClipDistance; - viewParams.farplane = m_config.m_farClipDistance; - m_view->SetCurrentParams(viewParams); - } - if (auto viewportContext = GetViewportContext()) { AZ::Matrix4x4 viewToClipMatrix; - float aspectRatio = m_view ? m_view->GetCamera().GetPixelAspectRatio() : 1.f; if (!m_atomAuxGeom) { SetupAtomAuxGeom(viewportContext); } auto windowSize = viewportContext->GetViewportSize(); - aspectRatio = aznumeric_cast(windowSize.m_width) / aznumeric_cast(windowSize.m_height); + const float aspectRatio = aznumeric_cast(windowSize.m_width) / aznumeric_cast(windowSize.m_height); // This assumes a reversed depth buffer, in line with other LY Atom integration if (m_config.m_orthographic) diff --git a/Gems/Camera/Code/Source/CameraComponentController.h b/Gems/Camera/Code/Source/CameraComponentController.h index 923da65618..5eca6b1711 100644 --- a/Gems/Camera/Code/Source/CameraComponentController.h +++ b/Gems/Camera/Code/Source/CameraComponentController.h @@ -16,15 +16,12 @@ #include #include -#include -#include -#include - namespace Camera { static constexpr float DefaultFoV = 75.0f; static constexpr float MinFoV = std::numeric_limits::epsilon(); static constexpr float MaxFoV = AZ::RadToDeg(AZ::Constants::Pi); + static constexpr float MinimumNearPlaneDistance = 0.001f; static constexpr float DefaultNearPlaneDistance = 0.2f; static constexpr float DefaultFarClipPlaneDistance = 1024.0f; static constexpr float DefaultFrustumDimension = 256.f; @@ -69,6 +66,10 @@ namespace Camera CameraComponentController() = default; explicit CameraComponentController(const CameraComponentConfig& config); + //! Defines a callback for determining whether this camera should push itself to the top of the Atom camera stack. + //! Used by the Editor to disable undesirable camera changes in edit mode. + void SetShouldActivateFunction(AZStd::function shouldActivateFunction); + // Controller interface static void Reflect(AZ::ReflectContext* context); static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); @@ -134,10 +135,6 @@ namespace Camera bool m_updatingTransformFromEntity = false; bool m_isActiveView = false; - // Cry view integration - IView* m_view = nullptr; - AZ::u32 m_prevViewId = 0; - IViewSystem* m_viewSystem = nullptr; - ISystem* m_system = nullptr; + AZStd::function m_shouldActivateFn; }; } // namespace Camera diff --git a/Gems/Camera/Code/Source/CameraEditorSystemComponent.cpp b/Gems/Camera/Code/Source/CameraEditorSystemComponent.cpp index bf3083bf59..00a147c17a 100644 --- a/Gems/Camera/Code/Source/CameraEditorSystemComponent.cpp +++ b/Gems/Camera/Code/Source/CameraEditorSystemComponent.cpp @@ -21,17 +21,12 @@ #include #include -#include -#include -#include -#include -#include - -#include -#include #include #include "ViewportCameraSelectorWindow.h" +#include +#include + namespace Camera { void CameraEditorSystemComponent::Reflect(AZ::ReflectContext* context) @@ -72,15 +67,6 @@ namespace Camera void CameraEditorSystemComponent::PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2&, int flags) { - IEditor* editor; - AzToolsFramework::EditorRequests::Bus::BroadcastResult(editor, &AzToolsFramework::EditorRequests::GetEditor); - - CGameEngine* gameEngine = editor->GetGameEngine(); - if (!gameEngine || !gameEngine->IsLevelLoaded()) - { - return; - } - if (!(flags & AzToolsFramework::EditorEvents::eECMF_HIDE_ENTITY_CREATION)) { QAction* action = menu->addAction(QObject::tr("Create camera entity from view")); @@ -90,9 +76,6 @@ namespace Camera void CameraEditorSystemComponent::CreateCameraEntityFromViewport() { - IEditor* editor = nullptr; - AzToolsFramework::EditorRequests::Bus::BroadcastResult(editor, &AzToolsFramework::EditorRequests::GetEditor); - AzFramework::CameraState cameraState{}; AZ::EBusReduceResult> aggregator; Camera::EditorCameraRequestBus::BroadcastResult( diff --git a/Gems/Camera/Code/Source/CameraGem.cpp b/Gems/Camera/Code/Source/CameraGem.cpp index 7efb09a59c..99f270e71b 100644 --- a/Gems/Camera/Code/Source/CameraGem.cpp +++ b/Gems/Camera/Code/Source/CameraGem.cpp @@ -7,7 +7,6 @@ */ #include -#include #include "CameraComponent.h" #include "CameraSystemComponent.h" @@ -22,13 +21,13 @@ namespace Camera { class CameraModule - : public CryHooksModule + : public AZ::Module { public: AZ_RTTI(CameraModule, "{C2E72B0D-BCEF-452A-9BFA-03833015258C}", AZ::Module); CameraModule() - : CryHooksModule() + : AZ::Module() { m_descriptors.insert(m_descriptors.end(), { Camera::CameraComponent::CreateDescriptor(), diff --git a/Gems/Camera/Code/Source/EditorCameraComponent.cpp b/Gems/Camera/Code/Source/EditorCameraComponent.cpp index 4ebec334ec..3ac60cbff8 100644 --- a/Gems/Camera/Code/Source/EditorCameraComponent.cpp +++ b/Gems/Camera/Code/Source/EditorCameraComponent.cpp @@ -12,10 +12,9 @@ #include "EditorCameraComponent.h" #include "ViewportCameraSelectorWindow.h" -#include -#include #include #include +#include #include #include @@ -33,6 +32,14 @@ namespace Camera CameraComponentConfig controllerConfig = m_controller.GetConfiguration(); controllerConfig.m_editorEntityId = GetEntityId().operator AZ::u64(); m_controller.SetConfiguration(controllerConfig); + // Only allow our camera to activate with the component if we're currently in game mode. + m_controller.SetShouldActivateFunction([]() + { + bool isInGameMode = true; + AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult( + isInGameMode, &AzToolsFramework::EditorEntityContextRequestBus::Events::IsEditorRunningGame); + return isInGameMode; + }); // Call base class activate, which in turn calls Activate on our controller. EditorCameraComponentBase::Activate(); diff --git a/Gems/Camera/Code/Source/EditorCameraComponent.h b/Gems/Camera/Code/Source/EditorCameraComponent.h index 02b9d591d0..0cb130e7a0 100644 --- a/Gems/Camera/Code/Source/EditorCameraComponent.h +++ b/Gems/Camera/Code/Source/EditorCameraComponent.h @@ -21,8 +21,6 @@ #include #include "CameraComponent.h" #include "CameraComponentController.h" -#include -#include #include diff --git a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp index 7a8d6be020..dc091db9e5 100644 --- a/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp +++ b/Gems/Camera/Code/Source/ViewportCameraSelectorWindow.cpp @@ -7,17 +7,14 @@ */ #include "ViewportCameraSelectorWindow.h" #include "ViewportCameraSelectorWindow_Internals.h" -#include #include #include #include #include #include #include -#include -#include -#include #include +#include namespace Qt { @@ -308,7 +305,7 @@ namespace Camera void RegisterViewportCameraSelectorWindow() { - QtViewOptions viewOptions; + AzToolsFramework::ViewPaneOptions viewOptions; viewOptions.isPreview = true; viewOptions.showInMenu = true; viewOptions.preferedDockingArea = Qt::DockWidgetArea::LeftDockWidgetArea; From 0ed82e21d52e9c18da38d026ba9d75ee0cd3fbc6 Mon Sep 17 00:00:00 2001 From: Robin Date: Thu, 16 Sep 2021 16:39:59 -0700 Subject: [PATCH 22/84] Switch job dependency type to OrderOnce for material assets when property names are included. Signed-off-by: Robin --- .../Source/RPI.Builders/Material/MaterialBuilder.cpp | 7 ++++++- .../Model/MaterialAssetBuilderComponent.cpp | 10 +++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index 5ddeb08ef8..099fdf33dd 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -9,6 +9,7 @@ #include "MaterialBuilder.h" #include #include +#include #include #include #include @@ -93,8 +94,12 @@ namespace AZ { AssetBuilderSDK::JobDependency jobDependency; jobDependency.m_jobKey = jobKey; - jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; jobDependency.m_sourceFile.m_sourceFileDependencyPath = file; + + bool includeMaterialPropertyNames = true; + RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames); + jobDependency.m_type = includeMaterialPropertyNames ? AssetBuilderSDK::JobDependencyType::OrderOnce : AssetBuilderSDK::JobDependencyType::Order; + jobDependencies.push_back(jobDependency); } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp index cf7e53c596..b2c590a376 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp @@ -78,10 +78,7 @@ namespace AZ AZStd::string materialTypePath; RPI::MaterialConverterBus::BroadcastResult(materialTypePath, &RPI::MaterialConverterBus::Events::GetMaterialTypePath); - bool includeMaterialPropertyNames = true; - RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames); - // TODO: Use includeMaterialPropertyNames to break materialtype dependency on fbx files. Materialasset's dependency on materialtypeasset will need to be decoupled first - if (conversionEnabled && !materialTypePath.empty() /*&& !includeMaterialPropertyNames*/) + if (conversionEnabled && !materialTypePath.empty()) { AssetBuilderSDK::SourceFileDependency materialTypeSource; materialTypeSource.m_sourceFileDependencyPath = materialTypePath; @@ -90,7 +87,10 @@ namespace AZ jobDependency.m_jobKey = "Atom Material Builder"; jobDependency.m_sourceFile = materialTypeSource; jobDependency.m_platformIdentifier = platformIdentifier; - jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order; + + bool includeMaterialPropertyNames = true; + RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames); + jobDependency.m_type = includeMaterialPropertyNames ? AssetBuilderSDK::JobDependencyType::OrderOnce : AssetBuilderSDK::JobDependencyType::Order; jobDependencyList.push_back(jobDependency); } From 454ae90afb9124d2f0b126ea51bb20cb305db78e Mon Sep 17 00:00:00 2001 From: pereslav Date: Fri, 17 Sep 2021 17:15:21 +0100 Subject: [PATCH 23/84] Added a few whitespaces Signed-off-by: pereslav --- .../Code/Source/NetworkEntity/NetworkEntityManager.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 62b57d9603..61fd741dc6 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -484,7 +484,7 @@ namespace Multiplayer // The first entity in every spawnable is the root one const AZ::Entity* rootEntity = *entities.begin(); - if(!rootEntity) + if (!rootEntity) { AZ_Error("NetworkEntityManager", false, "RequestNetSpawnableInstantiation: Root entity is null in the spawnable %s", rootSpawnable.GetHint().c_str()); @@ -492,7 +492,7 @@ namespace Multiplayer } const auto* holderComponent = rootEntity->FindComponent(); - if(!holderComponent) + if (!holderComponent) { // This spawnable doesn't have a corresponding network spawnable. return nullptr; @@ -524,11 +524,11 @@ namespace Multiplayer bool shouldUpdateTransform = (rootTransform.IsClose(AZ::Transform::Identity()) == false); for (uint32_t netEntityIndex = 0, entitiesSize = aznumeric_cast(entities.size()); - netEntityIndex < entitiesSize; netEntityIndex++) + netEntityIndex < entitiesSize; ++netEntityIndex) { AZ::Entity* netEntity = *(entities.begin() + netEntityIndex); - if(shouldUpdateTransform) + if (shouldUpdateTransform) { AzFramework::TransformComponent* netEntityTransform = netEntity->FindComponent(); @@ -582,7 +582,7 @@ namespace Multiplayer if (ShouldSpawnNetEntities()) { AZStd::unique_ptr ticket = RequestNetSpawnableInstantiation(spawnable, entities); - if(ticket) + if (ticket) { AZ::Data::AssetId spawnableAssetId = spawnable.GetId(); m_netSpawnableTickets[spawnTicket] = AZStd::move(ticket); From 0c9dbb86581f5b42fbd165820cf689403aec9adb Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Sun, 19 Sep 2021 18:42:24 -0500 Subject: [PATCH 24/84] =?UTF-8?q?Adding=20new=20commands=20to=20the=20mate?= =?UTF-8?q?rial=20component=20for=20managing,=20removing,=20repairing=20ma?= =?UTF-8?q?terial=20slots=20=E2=80=A2=20Adding=20commands=20to=20material?= =?UTF-8?q?=20component=20to=20clear=20or=20repair=20material=20slots=20?= =?UTF-8?q?=E2=80=A2=20Moved=20all=20clear=20and=20repair=20functions=20fr?= =?UTF-8?q?om=20the=20editor=20component=20to=20the=20material=20component?= =?UTF-8?q?=20controller,=20bound=20to=20its=20buses=20so=20they=20can=20b?= =?UTF-8?q?e=20accessed=20from=20script=20=E2=80=A2=20Added=20new=20functi?= =?UTF-8?q?ons=20to=20clear=20model=20and=20LOD=20material=20groups=20?= =?UTF-8?q?=E2=80=A2=20Added=20function=20to=20remove=20material=20assignm?= =?UTF-8?q?ents=20with=20bad=20asset=20references=20=E2=80=A2=20Added=20fu?= =?UTF-8?q?nction=20to=20reassign=20materials=20with=20bad=20asset=20refer?= =?UTF-8?q?ences=20to=20the=20default=20asset=20=E2=80=A2=20Added=20functi?= =?UTF-8?q?on=20to=20remove=20material=20assignments=20that=20don=E2=80=99?= =?UTF-8?q?t=20match=20slots=20available=20on=20the=20active=20model.=20Th?= =?UTF-8?q?is=20case=20arises=20when=20switching=20between=20different=20m?= =?UTF-8?q?odels,=20changing=20the=20materials=20on=20a=20given=20model,?= =?UTF-8?q?=20or=20copying=20and=20pasting=20the=20material=20component=20?= =?UTF-8?q?to=20a=20different=20entity=20with=20a=20different=20model.=20T?= =?UTF-8?q?he=20user=20might=20end=20up=20with=20hidden=20material=20slots?= =?UTF-8?q?=20that=20load=20assets=20but=20have=20no=20effect.=20=E2=80=A2?= =?UTF-8?q?=20Converted=20remaining=20code=20that=20iterated=20over=20edit?= =?UTF-8?q?or=20material=20slots=20to=20instead=20use=20the=20material=20c?= =?UTF-8?q?omponent=20request=20bus=20=E2=80=A2=20Removed=20functions=20fr?= =?UTF-8?q?om=20the=20editor=20material=20component=20that=20enumerated=20?= =?UTF-8?q?editor=20material=20slots?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Guthrie Adams --- .../Material/MaterialComponentBus.h | 10 + .../Material/EditorMaterialComponent.cpp | 206 ++++++++---------- .../Source/Material/EditorMaterialComponent.h | 7 - .../EditorMaterialComponentExporter.cpp | 4 + .../Material/EditorMaterialComponentSlot.cpp | 7 +- .../Material/MaterialComponentController.cpp | 84 ++++++- .../Material/MaterialComponentController.h | 5 + 7 files changed, 187 insertions(+), 136 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h index 3b65750b5f..ab7a180dd1 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h @@ -33,6 +33,16 @@ namespace AZ virtual const MaterialAssignmentMap& GetMaterialOverrides() const = 0; //! Clear all material overrides virtual void ClearAllMaterialOverrides() = 0; + //! Clear non-lod material override + virtual void ClearModelMaterialOverrides() = 0; + //! Clear lod material override + virtual void ClearLodMaterialOverrides() = 0; + //! Clear residual materials that don't correspond to the associated model + virtual void ClearIncompatibleMaterialOverrides() = 0; + //! Clear materials that reference missing assets + virtual void ClearInvalidMaterialOverrides() = 0; + //! Repair materials that reference missing assets by assigning the default asset + virtual void RepairInvalidMaterialOverrides() = 0; //! Set default material override virtual void SetDefaultMaterialOverride(const AZ::Data::AssetId& materialAssetId) = 0; //! Get default material override diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp index c243522257..ab39e7f208 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp @@ -32,9 +32,6 @@ namespace AZ const char* EditorMaterialComponent::GenerateMaterialsButtonText = "Generate/Manage Source Materials..."; const char* EditorMaterialComponent::GenerateMaterialsToolTipText = "Generate editable source material files from materials provided by the model."; - const char* EditorMaterialComponent::ResetMaterialsButtonText = "Reset Materials"; - const char* EditorMaterialComponent::ResetMaterialsToolTipText = "Clear all settings, materials, and properties then rebuild material slots from the associated model."; - // Update serialized data to the new format and data types bool EditorMaterialComponent::ConvertVersion(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement) { @@ -178,43 +175,74 @@ namespace AZ menu->addSeparator(); - action = menu->addAction(ResetMaterialsButtonText, [this]() { ResetMaterialSlots(); }); - action->setToolTip(ResetMaterialsToolTipText); + action = menu->addAction("Clear All Materials", [this]() { + AzToolsFramework::ScopedUndoBatch undoBatch("Clearing all materials."); + SetDirty(); - menu->addSeparator(); + MaterialComponentRequestBus::Event(GetEntityId(), &MaterialComponentRequestBus::Events::ClearAllMaterialOverrides); + + m_materialSlotsByLodEnabled = false; + + UpdateMaterialSlots(); + }); + action->setToolTip("Clear all materials and properties then rebuild material slots from the associated model."); action = menu->addAction("Clear Model Materials", [this]() { AzToolsFramework::ScopedUndoBatch undoBatch("Clearing model materials."); SetDirty(); - for (auto& materialSlotPair : GetMaterialSlots()) - { - EditorMaterialComponentSlot* materialSlot = materialSlotPair.second; - if (materialSlot->m_id.IsSlotIdOnly()) - { - materialSlot->Clear(); - } - } - }); + MaterialComponentRequestBus::Event(GetEntityId(), &MaterialComponentRequestBus::Events::ClearModelMaterialOverrides); + + UpdateMaterialSlots(); + }); + action->setToolTip("Clear model materials and properties then rebuild material slots from the associated model."); + action = menu->addAction("Clear LOD Materials", [this]() { AzToolsFramework::ScopedUndoBatch undoBatch("Clearing LOD materials."); SetDirty(); - for (auto& materialSlotPair : GetMaterialSlots()) - { - EditorMaterialComponentSlot* materialSlot = materialSlotPair.second; - if (materialSlot->m_id.IsLodAndSlotId()) - { - materialSlot->Clear(); - } - } - }); - action->setEnabled(m_materialSlotsByLodEnabled); + MaterialComponentRequestBus::Event(GetEntityId(), &MaterialComponentRequestBus::Events::ClearLodMaterialOverrides); + + m_materialSlotsByLodEnabled = false; + + UpdateMaterialSlots(); + }); + action->setToolTip("Clear LOD materials and properties then rebuild material slots from the associated model."); + + action = menu->addAction("Clear Incompatible Materials", [this]() { + AzToolsFramework::ScopedUndoBatch undoBatch("Clearing incompatible materials."); + SetDirty(); + + MaterialComponentRequestBus::Event(GetEntityId(), &MaterialComponentRequestBus::Events::ClearIncompatibleMaterialOverrides); + + UpdateMaterialSlots(); + }); + action->setToolTip("Clear residual materials that don't correspond to the associated model."); + + action = menu->addAction("Clear Invalid Materials", [this]() { + AzToolsFramework::ScopedUndoBatch undoBatch("Clearing invalid materials."); + SetDirty(); + + MaterialComponentRequestBus::Event(GetEntityId(), &MaterialComponentRequestBus::Events::ClearInvalidMaterialOverrides); + + UpdateMaterialSlots(); + }); + action->setToolTip("Clear materials that reference missing assets."); + + action = menu->addAction("Repair Invalid Materials", [this]() { + AzToolsFramework::ScopedUndoBatch undoBatch("Repairing invalid materials."); + SetDirty(); + + MaterialComponentRequestBus::Event(GetEntityId(), &MaterialComponentRequestBus::Events::RepairInvalidMaterialOverrides); + + UpdateMaterialSlots(); + }); + action->setToolTip("Repair materials that reference missing assets by assigning the default asset."); } void EditorMaterialComponent::SetPrimaryAsset(const AZ::Data::AssetId& assetId) { - m_controller.SetDefaultMaterialOverride(assetId); + MaterialComponentRequestBus::Event(GetEntityId(), &MaterialComponentRequestBus::Events::SetDefaultMaterialOverride, assetId); MaterialComponentNotificationBus::Event(GetEntityId(), &MaterialComponentNotifications::OnMaterialsEdited); @@ -249,14 +277,18 @@ namespace AZ m_materialSlots = {}; m_materialSlotsByLod = {}; - const MaterialComponentConfig& config = m_controller.GetConfiguration(); + // Get current material assignments + MaterialAssignmentMap currentMaterials; + MaterialComponentRequestBus::EventResult( + currentMaterials, GetEntityId(), &MaterialComponentRequestBus::Events::GetMaterialOverrides); // Get the known material assignment slots from the associated model or other source - MaterialAssignmentMap materialsFromSource; - MaterialReceiverRequestBus::EventResult(materialsFromSource, GetEntityId(), &MaterialReceiverRequestBus::Events::GetMaterialAssignments); + MaterialAssignmentMap originalMaterials; + MaterialComponentRequestBus::EventResult( + originalMaterials, GetEntityId(), &MaterialComponentRequestBus::Events::GetOriginalMaterialAssignments); // Generate the table of editable materials using the source data to define number of groups, elements, and initial values - for (const auto& materialPair : materialsFromSource) + for (const auto& materialPair : originalMaterials) { // Setup the material slot entry EditorMaterialComponentSlot slot; @@ -264,7 +296,7 @@ namespace AZ slot.m_id = materialPair.first; // if material is present in controller configuration, assign its data - const MaterialAssignment& materialFromController = GetMaterialAssignmentFromMap(config.m_materials, slot.m_id); + const MaterialAssignment& materialFromController = GetMaterialAssignmentFromMap(currentMaterials, slot.m_id); slot.m_materialAsset = materialFromController.m_materialAsset; if (slot.m_id.IsDefault()) @@ -289,7 +321,7 @@ namespace AZ } } - // Sort all of the slots by label to ensure stable index values (materialsFromSource is an unordered map) + // Sort all of the slots by label to ensure stable index values (originalMaterials is an unordered map) AZStd::sort(m_materialSlots.begin(), m_materialSlots.end(), [](const auto& a, const auto& b) { return a.GetLabel() < b.GetLabel(); }); @@ -305,49 +337,36 @@ namespace AZ &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree); } - AZ::u32 EditorMaterialComponent::ResetMaterialSlots() - { - AzToolsFramework::ScopedUndoBatch undoBatch("Resetting materials."); - SetDirty(); - - m_controller.SetMaterialOverrides(MaterialAssignmentMap()); - UpdateMaterialSlots(); - - m_materialSlotsByLodEnabled = false; - - MaterialComponentNotificationBus::Event(GetEntityId(), &MaterialComponentNotifications::OnMaterialsEdited); - - AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree); - - return AZ::Edit::PropertyRefreshLevels::EntireTree; - } - AZ::u32 EditorMaterialComponent::OpenMaterialExporter() { AzToolsFramework::ScopedUndoBatch undoBatch("Generating materials."); SetDirty(); - // First generating a unique set of all material asset IDs that will be used for source data generation - AZStd::unordered_map assetIdMap; + MaterialAssignmentMap originalMaterials; + MaterialComponentRequestBus::EventResult( + originalMaterials, GetEntityId(), &MaterialComponentRequestBus::Events::GetOriginalMaterialAssignments); - auto materialSlots = GetMaterialSlots(); - for (auto& materialSlotPair : materialSlots) + // Generate a unique set of all material asset IDs that will be used for source data generation + AZStd::unordered_map assetIdToSlotNameMap; + for (const auto& materialPair : originalMaterials) { - Data::AssetId defaultMaterialAssetId = materialSlotPair.second->GetDefaultAssetId(); - if (defaultMaterialAssetId.IsValid()) + const Data::AssetId originalAssetId = materialPair.second.m_materialAsset.GetId(); + if (originalAssetId.IsValid()) { - assetIdMap[defaultMaterialAssetId] = materialSlotPair.second->GetLabel(); + MaterialComponentRequestBus::EventResult( + assetIdToSlotNameMap[originalAssetId], GetEntityId(), &MaterialComponentRequestBus::Events::GetMaterialSlotLabel, + materialPair.first); } } // Convert the unique set of asset IDs into export items that can be configured in the dialog // The order should not matter because the table in the dialog can sort itself for a specific row EditorMaterialComponentExporter::ExportItemsContainer exportItems; - for (auto assetIdInfo : assetIdMap) + exportItems.reserve(assetIdToSlotNameMap.size()); + + for (const auto& assetIdToSlotNamePair : assetIdToSlotNameMap) { - EditorMaterialComponentExporter::ExportItem exportItem{ assetIdInfo.first, assetIdInfo.second }; - exportItems.push_back(exportItem); + exportItems.emplace_back(assetIdToSlotNamePair.first, assetIdToSlotNamePair.second); } // Display the export dialog so that the user can configure how they want different materials to be exported @@ -363,16 +382,17 @@ namespace AZ const auto& assetIdOutcome = AZ::RPI::AssetUtils::MakeAssetId(exportItem.GetExportPath(), 0); if (assetIdOutcome) { - for (auto& materialSlotPair : materialSlots) + for (const auto& materialPair : originalMaterials) { - EditorMaterialComponentSlot* editorMaterialSlot = materialSlotPair.second; - - if (editorMaterialSlot) + // We need to check whether replaced material corresponds to this slot's default material. + const Data::AssetId originalAssetId = materialPair.second.m_materialAsset.GetId(); + if (originalAssetId == exportItem.GetOriginalAssetId()) { - // We need to check whether replaced material corresponds to this slot's default material. - if (editorMaterialSlot->GetDefaultAssetId() == exportItem.GetOriginalAssetId()) + if (m_materialSlotsByLodEnabled || !materialPair.first.IsLodAndSlotId()) { - editorMaterialSlot->SetAsset(assetIdOutcome.GetValue()); + MaterialComponentRequestBus::Event( + GetEntityId(), &MaterialComponentRequestBus::Events::SetMaterialOverride, materialPair.first, + assetIdOutcome.GetValue()); } } } @@ -380,12 +400,9 @@ namespace AZ } } - MaterialComponentNotificationBus::Event(GetEntityId(), &MaterialComponentNotifications::OnMaterialsEdited); + UpdateMaterialSlots(); - AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_AttributesAndValues); - - return AZ::Edit::PropertyRefreshLevels::AttributesAndValues; + return AZ::Edit::PropertyRefreshLevels::EntireTree; } AZ::u32 EditorMaterialComponent::OnLodsToggled() @@ -395,15 +412,10 @@ namespace AZ if (!m_materialSlotsByLodEnabled) { - MaterialComponentConfig config = m_controller.GetConfiguration(); - AZStd::erase_if(config.m_materials, [](const auto& item) { - const auto& [key, value] = item; - return key.m_lodIndex != MaterialAssignmentId::NonLodIndex; - }); - m_controller.SetMaterialOverrides(config.m_materials); + MaterialComponentRequestBus::Event(GetEntityId(), &MaterialComponentRequestBus::Events::ClearLodMaterialOverrides); } - MaterialComponentNotificationBus::Event(GetEntityId(), &MaterialComponentNotifications::OnMaterialsEdited); + UpdateMaterialSlots(); return AZ::Edit::PropertyRefreshLevels::EntireTree; } @@ -440,41 +452,5 @@ namespace AZ { return AZStd::string::format("LOD %d", lodIndex); } - - template - void EditorMaterialComponent::BuildMaterialSlotMap(ComponentType& component, ContainerType& materialSlots) - { - materialSlots[DefaultMaterialAssignmentId] = &component.m_defaultMaterialSlot; - - for (auto& slot : component.m_materialSlots) - { - materialSlots[slot.m_id] = &slot; - } - - if (component.m_materialSlotsByLodEnabled) - { - for (auto& slotsForLod : component.m_materialSlotsByLod) - { - for (auto& slot : slotsForLod) - { - materialSlots[slot.m_id] = &slot; - } - } - } - } - - AZStd::unordered_map EditorMaterialComponent::GetMaterialSlots() - { - AZStd::unordered_map materialSlots; - BuildMaterialSlotMap(*this, materialSlots); - return AZStd::move(materialSlots); - } - - AZStd::unordered_map EditorMaterialComponent::GetMaterialSlots() const - { - AZStd::unordered_map materialSlots; - BuildMaterialSlotMap(*this, materialSlots); - return AZStd::move(materialSlots); - } } // namespace Render } // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.h index 6a218e23b7..f8895d994f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.h @@ -58,9 +58,6 @@ namespace AZ // controller configuration then those values will be assigned to the editor component slots. void UpdateMaterialSlots(); - // Clears all values related to the material component and regenerates the editor slots - AZ::u32 ResetMaterialSlots(); - // Opens the source material export dialog and updates editor material slots based on // selected actions AZ::u32 OpenMaterialExporter(); @@ -82,10 +79,6 @@ namespace AZ // Evaluate if materials can be edited bool IsEditingAllowed() const; - template - static void BuildMaterialSlotMap(ComponentType& component, ContainerType& materialSlots); - AZStd::unordered_map GetMaterialSlots(); - AZStd::unordered_map GetMaterialSlots() const; AZStd::string GetLabelForLod(int lodIndex) const; AZStd::string m_message; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp index f55da28fa6..14cc28b91e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentExporter.cpp @@ -55,6 +55,10 @@ namespace AZ bool OpenExportDialog(ExportItemsContainer& exportItems) { + // Sort material entries so they are ordered by name in the table + AZStd::sort(exportItems.begin(), exportItems.end(), + [](const auto& a, const auto& b) { return a.GetMaterialSlotName() < b.GetMaterialSlotName(); }); + QWidget* activeWindow = nullptr; AzToolsFramework::EditorWindowRequestBus::BroadcastResult(activeWindow, &AzToolsFramework::EditorWindowRequests::GetAppMainWindow); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp index 37a9ee7b93..363221d3fc 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentSlot.cpp @@ -140,7 +140,7 @@ namespace AZ void EditorMaterialComponentSlot::SetAsset(const Data::AssetId& assetId) { - m_materialAsset.Create(assetId); + m_materialAsset = AZ::Data::Asset(assetId, AZ::AzTypeInfo::Uuid()); MaterialComponentRequestBus::Event( m_entityId, &MaterialComponentRequestBus::Events::SetMaterialOverride, m_id, m_materialAsset.GetId()); OnDataChanged(); @@ -164,7 +164,7 @@ namespace AZ void EditorMaterialComponentSlot::ClearToDefaultAsset() { - m_materialAsset.Create(GetDefaultAssetId()); + m_materialAsset = AZ::Data::Asset(GetDefaultAssetId(), AZ::AzTypeInfo::Uuid()); MaterialComponentRequestBus::Event( m_entityId, &MaterialComponentRequestBus::Events::SetMaterialOverride, m_id, m_materialAsset.GetId()); ClearOverrides(); @@ -204,7 +204,8 @@ namespace AZ const auto& assetIdOutcome = AZ::RPI::AssetUtils::MakeAssetId(exportItem.GetExportPath(), 0); if (assetIdOutcome) { - m_materialAsset.Create(assetIdOutcome.GetValue()); + m_materialAsset = AZ::Data::Asset( + assetIdOutcome.GetValue(), AZ::AzTypeInfo::Uuid()); changed = true; } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp index 14f81c5021..1d9f1e81dd 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.cpp @@ -43,6 +43,11 @@ namespace AZ ->Event("SetDefaultMaterialOverride", &MaterialComponentRequestBus::Events::SetDefaultMaterialOverride) ->Event("GetDefaultMaterialOverride", &MaterialComponentRequestBus::Events::GetDefaultMaterialOverride) ->Event("ClearDefaultMaterialOverride", &MaterialComponentRequestBus::Events::ClearDefaultMaterialOverride) + ->Event("ClearModelMaterialOverrides", &MaterialComponentRequestBus::Events::ClearModelMaterialOverrides) + ->Event("ClearLodMaterialOverrides", &MaterialComponentRequestBus::Events::ClearLodMaterialOverrides) + ->Event("ClearIncompatibleMaterialOverrides", &MaterialComponentRequestBus::Events::ClearIncompatibleMaterialOverrides) + ->Event("ClearInvalidMaterialOverrides", &MaterialComponentRequestBus::Events::ClearInvalidMaterialOverrides) + ->Event("RepairInvalidMaterialOverrides", &MaterialComponentRequestBus::Events::RepairInvalidMaterialOverrides) ->Event("SetMaterialOverride", &MaterialComponentRequestBus::Events::SetMaterialOverride) ->Event("GetMaterialOverride", &MaterialComponentRequestBus::Events::GetMaterialOverride) ->Event("ClearMaterialOverride", &MaterialComponentRequestBus::Events::ClearMaterialOverride) @@ -275,10 +280,10 @@ namespace AZ MaterialAssignmentMap MaterialComponentController::GetOriginalMaterialAssignments() const { - MaterialAssignmentMap materialAssignmentMap; + MaterialAssignmentMap originalMaterials; MaterialReceiverRequestBus::EventResult( - materialAssignmentMap, m_entityId, &MaterialReceiverRequestBus::Events::GetMaterialAssignments); - return materialAssignmentMap; + originalMaterials, m_entityId, &MaterialReceiverRequestBus::Events::GetMaterialAssignments); + return originalMaterials; } MaterialAssignmentId MaterialComponentController::FindMaterialAssignmentId( @@ -348,6 +353,67 @@ namespace AZ } } + void MaterialComponentController::ClearModelMaterialOverrides() + { + AZStd::erase_if(m_configuration.m_materials, [](const auto& materialPair) { + return materialPair.first.IsSlotIdOnly(); + }); + QueueMaterialUpdateNotification(); + } + + void MaterialComponentController::ClearLodMaterialOverrides() + { + AZStd::erase_if(m_configuration.m_materials, [](const auto& materialPair) { + return materialPair.first.IsLodAndSlotId(); + }); + QueueMaterialUpdateNotification(); + } + + void MaterialComponentController::ClearIncompatibleMaterialOverrides() + { + const MaterialAssignmentMap& originalMaterials = GetOriginalMaterialAssignments(); + AZStd::erase_if(m_configuration.m_materials, [&originalMaterials](const auto& materialPair) { + return originalMaterials.find(materialPair.first) == originalMaterials.end(); + }); + QueueMaterialUpdateNotification(); + } + + void MaterialComponentController::ClearInvalidMaterialOverrides() + { + AZStd::erase_if(m_configuration.m_materials, [](const auto& materialPair) { + if (materialPair.second.m_materialAsset.GetId().IsValid()) + { + AZ::Data::AssetInfo assetInfo; + AZ::Data::AssetCatalogRequestBus::BroadcastResult( + assetInfo, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetInfoById, + materialPair.second.m_materialAsset.GetId()); + return !assetInfo.m_assetId.IsValid(); + } + return false; + }); + QueueMaterialUpdateNotification(); + } + + void MaterialComponentController::RepairInvalidMaterialOverrides() + { + for (auto& materialPair : m_configuration.m_materials) + { + if (materialPair.second.m_materialAsset.GetId().IsValid()) + { + AZ::Data::AssetInfo assetInfo; + AZ::Data::AssetCatalogRequestBus::BroadcastResult( + assetInfo, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetInfoById, + materialPair.second.m_materialAsset.GetId()); + if (!assetInfo.m_assetId.IsValid()) + { + materialPair.second.m_materialAsset = AZ::Data::Asset( + GetDefaultMaterialAssetId(materialPair.first), AZ::AzTypeInfo::Uuid()); + } + } + } + LoadMaterials(); + } + void MaterialComponentController::SetDefaultMaterialOverride(const AZ::Data::AssetId& materialAssetId) { SetMaterialOverride(DefaultMaterialAssignmentId, materialAssetId); @@ -363,9 +429,11 @@ namespace AZ ClearMaterialOverride(DefaultMaterialAssignmentId); } - void MaterialComponentController::SetMaterialOverride(const MaterialAssignmentId& materialAssignmentId, const AZ::Data::AssetId& materialAssetId) + void MaterialComponentController::SetMaterialOverride( + const MaterialAssignmentId& materialAssignmentId, const AZ::Data::AssetId& materialAssetId) { - m_configuration.m_materials[materialAssignmentId].m_materialAsset.Create(materialAssetId); + m_configuration.m_materials[materialAssignmentId].m_materialAsset = + AZ::Data::Asset(materialAssetId, AZ::AzTypeInfo::Uuid()); LoadMaterials(); } @@ -616,7 +684,6 @@ namespace AZ void MaterialComponentController::ClearAllPropertyOverrides() { - bool cleared = false; for (auto& materialPair : m_configuration.m_materials) { if (!materialPair.second.m_propertyOverrides.empty()) @@ -625,13 +692,8 @@ namespace AZ materialPair.second.RebuildInstance(); MaterialComponentNotificationBus::Event(m_entityId, &MaterialComponentNotifications::OnMaterialInstanceCreated, materialPair.second); QueueMaterialUpdateNotification(); - cleared = true; } } - - if (cleared) - { - } } void MaterialComponentController::SetPropertyOverrides( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h index c9dd330412..2bf15ca3b8 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialComponentController.h @@ -52,6 +52,11 @@ namespace AZ void SetMaterialOverrides(const MaterialAssignmentMap& materials) override; const MaterialAssignmentMap& GetMaterialOverrides() const override; void ClearAllMaterialOverrides() override; + void ClearModelMaterialOverrides() override; + void ClearLodMaterialOverrides() override; + void ClearIncompatibleMaterialOverrides() override; + void ClearInvalidMaterialOverrides() override; + void RepairInvalidMaterialOverrides() override; void SetDefaultMaterialOverride(const AZ::Data::AssetId& materialAssetId) override; const AZ::Data::AssetId GetDefaultMaterialOverride() const override; void ClearDefaultMaterialOverride() override; From 78148ead7c14921a51d290943f72a70242c61c90 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Mon, 20 Sep 2021 11:56:40 -0400 Subject: [PATCH 25/84] Unittests for IsHierarchyEnabled Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Code/Tests/ServerHierarchyTests.cpp | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp index 05e36e466d..c262782006 100644 --- a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp @@ -159,6 +159,42 @@ namespace Multiplayer ); } + TEST_F(ServerSimpleHierarchyTests, Root_Deactivates_IsHierarchyEnabled_Is_False) + { + EXPECT_EQ( + m_root->m_entity->FindComponent()->IsHierarchyEnabled(), + true + ); + + StopEntity(m_root->m_entity); + m_root->m_entity->Deactivate(); + + EXPECT_EQ( + m_root->m_entity->FindComponent()->IsHierarchyEnabled(), + false + ); + + m_root->m_entity.reset(); + } + + TEST_F(ServerSimpleHierarchyTests, Child_Deactivates_IsHierarchyEnabled_Is_False) + { + EXPECT_EQ( + m_child->m_entity->FindComponent()->IsHierarchyEnabled(), + true + ); + + StopEntity(m_child->m_entity); + m_child->m_entity->Deactivate(); + + EXPECT_EQ( + m_child->m_entity->FindComponent()->IsHierarchyEnabled(), + false + ); + + m_child->m_entity.reset(); + } + /* * Parent -> Child -> ChildOfChild */ From 2bd01f09fb0b8570089524bb2549080123abe277 Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Mon, 20 Sep 2021 11:37:17 -0700 Subject: [PATCH 26/84] Removed modelToWorldInverse from the stencil Srg. Signed-off-by: dmcdiar --- .../Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp | 1 - .../Common/Code/Source/ReflectionProbe/ReflectionProbe.h | 1 - .../ReflectionProbe/ReflectionProbeFeatureProcessor.cpp | 5 +---- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp index 1c1766073b..e86d91d387 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp @@ -142,7 +142,6 @@ namespace AZ Vector3 innerExtentsReduced = m_innerExtents - Vector3(0.1f, 0.1f, 0.1f); Matrix3x4 modelToWorldStencil = Matrix3x4::CreateFromQuaternionAndTranslation(m_transform.GetRotation(), m_transform.GetTranslation()) * Matrix3x4::CreateScale(innerExtentsReduced); m_stencilSrg->SetConstant(m_reflectionRenderData->m_modelToWorldStencilConstantIndex, modelToWorldStencil); - m_stencilSrg->SetConstant(m_reflectionRenderData->m_modelToWorldInverseStencilConstantIndex, modelToWorldStencil.GetInverseFull()); m_stencilSrg->Compile(); Matrix3x4 modelToWorldInverse = Matrix3x4::CreateFromTransform(m_transform).GetInverseFull(); diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h index 169c4f1df2..4f6a3337be 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h @@ -56,7 +56,6 @@ namespace AZ RHI::DrawListTag m_renderInnerDrawListTag; RHI::ShaderInputConstantIndex m_modelToWorldStencilConstantIndex; - RHI::ShaderInputConstantIndex m_modelToWorldInverseStencilConstantIndex; RHI::ShaderInputConstantIndex m_modelToWorldRenderConstantIndex; RHI::ShaderInputConstantIndex m_modelToWorldInverseRenderConstantIndex; RHI::ShaderInputConstantIndex m_outerObbHalfLengthsRenderConstantIndex; diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp index 5c07fbae66..09f75c07a6 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp @@ -92,10 +92,6 @@ namespace AZ m_reflectionRenderData.m_modelToWorldStencilConstantIndex = stencilSrgLayout->FindShaderInputConstantIndex(modelToWorldConstantName); AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldStencilConstantIndex.IsValid(), "Failed to find stencil shader input constant [%s]", modelToWorldConstantName.GetCStr()); - Name modelToWorldInverseConstantName = Name("m_modelToWorldInverse"); - m_reflectionRenderData.m_modelToWorldInverseStencilConstantIndex = stencilSrgLayout->FindShaderInputConstantIndex(modelToWorldInverseConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldInverseStencilConstantIndex.IsValid(), "Failed to find stencil shader input constant [%s]", modelToWorldInverseConstantName.GetCStr()); - // cache probe render shader indices // Note: the outer and inner render shaders use the same Srg Data::Instance renderReflectionSrg = RPI::ShaderResourceGroup::Create( @@ -108,6 +104,7 @@ namespace AZ m_reflectionRenderData.m_modelToWorldRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(modelToWorldConstantName); AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", modelToWorldConstantName.GetCStr()); + Name modelToWorldInverseConstantName = Name("m_modelToWorldInverse"); m_reflectionRenderData.m_modelToWorldInverseRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(modelToWorldInverseConstantName); AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", modelToWorldInverseConstantName.GetCStr()); From 594981f1304dc0fc4e6c06c55deb183e01b25d74 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Mon, 20 Sep 2021 11:58:31 -0700 Subject: [PATCH 27/84] Remove the PrefabEditManager. Introduce the FocusMode system on the Editor side, and a PrefabFocusHandler on the Prefab side to handle focus. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../Application/ToolsApplication.cpp | 2 + .../AzToolsFrameworkModule.cpp | 2 + .../FocusMode/FocusModeInterface.h | 40 +++++++ .../FocusMode/FocusModeSystemComponent.cpp | 93 ++++++++++++++++ .../FocusMode/FocusModeSystemComponent.h | 49 +++++++++ .../Prefab/PrefabFocusHandler.cpp | 103 ++++++++++++++++++ .../Prefab/PrefabFocusHandler.h | 56 ++++++++++ .../Prefab/PrefabFocusInterface.h | 40 +++++++ .../Prefab/PrefabSystemComponent.cpp | 1 + .../Prefab/PrefabSystemComponent.h | 12 +- .../UI/Prefab/LevelRootUiHandler.cpp | 9 -- .../UI/Prefab/LevelRootUiHandler.h | 2 - .../UI/Prefab/PrefabEditInterface.h | 43 -------- .../UI/Prefab/PrefabEditManager.cpp | 46 -------- .../UI/Prefab/PrefabEditManager.h | 40 ------- .../UI/Prefab/PrefabIntegrationManager.cpp | 23 ++-- .../UI/Prefab/PrefabIntegrationManager.h | 12 +- .../UI/Prefab/PrefabUiHandler.cpp | 24 ++-- .../UI/Prefab/PrefabUiHandler.h | 5 +- .../aztoolsframework_files.cmake | 9 +- 20 files changed, 430 insertions(+), 181 deletions(-) create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h delete mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabEditInterface.h delete mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabEditManager.cpp delete mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabEditManager.h diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp index 75d31321c2..7238a22c51 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -248,6 +249,7 @@ namespace AzToolsFramework components.insert(components.end(), { azrtti_typeid(), azrtti_typeid(), + azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFrameworkModule.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFrameworkModule.cpp index 97f52e253b..a557754437 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFrameworkModule.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFrameworkModule.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -69,6 +70,7 @@ namespace AzToolsFramework Components::EditorSelectionAccentSystemComponent::CreateDescriptor(), EditorEntityContextComponent::CreateDescriptor(), EditorEntityFixupComponent::CreateDescriptor(), + FocusModeFramework::FocusModeSystemComponent::CreateDescriptor(), SliceMetadataEntityContextComponent::CreateDescriptor(), SliceRequestComponent::CreateDescriptor(), Prefab::PrefabSystemComponent::CreateDescriptor(), diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h new file mode 100644 index 0000000000..edd94fd6b0 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h @@ -0,0 +1,40 @@ +/* + * 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 +#include + + +namespace AzToolsFramework::FocusModeFramework +{ + /*! + * FocusModeInterface + * Interface to handle the Editor Focus Mode. + */ + class FocusModeInterface + { + public: + AZ_RTTI(FocusModeInterface, "{437243B0-F86B-422F-B7B8-4A21CC000702}"); + + //! Sets the root entity the Editor should focus on. + //! The Editor will only allow the user to select entities belonging to the sub-tree that has root in the entityId provided. + //! @param entityId The entityId that will become the new focus root. + virtual void SetFocusRoot(AZ::EntityId entityId) = 0; + + //! Returns the entity id of the root of the current Editor focus. + //! @return The id of the entity that is the root of the Editor focus. + virtual AZ::EntityId GetFocusRoot() = 0; + + //! Returns whether the entity id provided is part of the focused sub-tree. + //! @return True if entityId belongs to the focused sub-tree, false otherwise. + virtual bool IsInFocusSubTree(AZ::EntityId entityId) = 0; + }; + +} // namespace AzToolsFramework::FocusModeFrameworkclassPrefabEditPublicInterface diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp new file mode 100644 index 0000000000..3ad2dbdfb8 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp @@ -0,0 +1,93 @@ +/* + * 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 + +#include + +namespace AzToolsFramework::FocusModeFramework +{ + FocusModeSystemComponent::~FocusModeSystemComponent() + { + AZ::Interface::Unregister(this); + } + + void FocusModeSystemComponent::Init() + { + AZ::Interface::Register(this); + } + + void FocusModeSystemComponent::Activate() + { + } + + void FocusModeSystemComponent::Deactivate() + { + } + + void FocusModeSystemComponent::Reflect(AZ::ReflectContext* /*context*/) + { + } + + void FocusModeSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("EditorFocusMode")); + } + + void FocusModeSystemComponent::GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required) + { + } + + void FocusModeSystemComponent::GetIncompatibleServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + } + + void FocusModeSystemComponent::SetFocusRoot(AZ::EntityId entityId) + { + m_focusRoot = entityId; + + // TODO - If m_focusRoot != AZ::EntityId(), register focus mode + // Else, unregister focus mode + } + + AZ::EntityId FocusModeSystemComponent::GetFocusRoot() + { + return m_focusRoot; + } + + bool FocusModeSystemComponent::IsInFocusSubTree(AZ::EntityId entityId) + { + if (m_focusRoot == AZ::EntityId()) + { + return true; + } + + return IsInFocusSubTree_helper(entityId, m_focusRoot); + } + + bool FocusModeSystemComponent::IsInFocusSubTree_helper(AZ::EntityId entityId, AZ::EntityId focusRootId) + { + if (entityId == AZ::EntityId()) + { + return false; + } + + if (entityId == focusRootId) + { + return true; + } + + AZ::EntityId parentId; + AZ::TransformBus::EventResult(parentId, entityId, &AZ::TransformInterface::GetParentId); + + return IsInFocusSubTree_helper(parentId, focusRootId); + } + +} // namespace AzToolsFramework::FocusModeFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h new file mode 100644 index 0000000000..54312a1e92 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h @@ -0,0 +1,49 @@ +/* + * 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 +#include + +#include + +namespace AzToolsFramework::FocusModeFramework +{ + class FocusModeSystemComponent final + : public AZ::Component + , private FocusModeInterface + { + public: + AZ_COMPONENT(FocusModeSystemComponent, "{6CE522FE-2057-4794-BD05-61E04BD8EA30}"); + + FocusModeSystemComponent() = default; + virtual ~FocusModeSystemComponent(); + + // AZ::Component... + void Init() override; + void Activate() override; + void Deactivate() override; + + static void Reflect(AZ::ReflectContext* context); + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + + // FocusModeInterface... + void SetFocusRoot(AZ::EntityId entityId) override; + AZ::EntityId GetFocusRoot() override; + bool IsInFocusSubTree(AZ::EntityId entityId) override; + + private: + static bool IsInFocusSubTree_helper(AZ::EntityId entityId, AZ::EntityId focusRootId); + + AZ::EntityId m_focusRoot; + }; + +} // namespace AzToolsFramework::FocusModeFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp new file mode 100644 index 0000000000..a9c8c93eb0 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp @@ -0,0 +1,103 @@ +/* + * 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 + +#include +#include +#include + +namespace AzToolsFramework::Prefab +{ + FocusModeFramework::FocusModeInterface* PrefabFocusHandler::s_focusModeInterface = nullptr; + InstanceEntityMapperInterface* PrefabFocusHandler::s_instanceEntityMapperInterface = nullptr; + PrefabEditorEntityOwnershipInterface* PrefabFocusHandler::s_prefabEditorEntityOwnershipInterface = nullptr; + + PrefabFocusHandler::~PrefabFocusHandler() + { + AZ::Interface::Unregister(this); + } + + void PrefabFocusHandler::Initialize() + { + s_focusModeInterface = AZ::Interface::Get(); + AZ_Assert( + s_focusModeInterface, + "Prefab - PrefabFocusHandler - " + "Focus Mode Interface could not be found. " + "Check that it is being correctly initialized."); + + s_instanceEntityMapperInterface = AZ::Interface::Get(); + AZ_Assert( + s_instanceEntityMapperInterface, + "Prefab - PrefabFocusHandler - " + "Instance Entity Mapper Interface could not be found. " + "Check that it is being correctly initialized."); + + s_prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); + AZ_Assert( + s_prefabEditorEntityOwnershipInterface, + "Prefab - PrefabFocusHandler - " + "Prefab Editor Entity Ownership Interface could not be found. " + "Check that it is being correctly initialized."); + + AZ::Interface::Register(this); + } + + void PrefabFocusHandler::FocusOnOwningPrefab(AZ::EntityId entityId) + { + InstanceOptionalReference focusedInstance; + + if (entityId == AZ::EntityId()) + { + focusedInstance = s_prefabEditorEntityOwnershipInterface->GetRootPrefabInstance(); + } + else + { + focusedInstance = s_instanceEntityMapperInterface->FindOwningInstance(entityId); + } + + if (!focusedInstance.has_value()) + { + // TODO - ERROR + } + + m_focusedInstance = focusedInstance; + m_focusedTemplateId = focusedInstance->get().GetTemplateId(); + s_focusModeInterface->SetFocusRoot(focusedInstance->get().GetContainerEntityId()); + } + + TemplateId PrefabFocusHandler::GetFocusedPrefabTemplateId() + { + return m_focusedTemplateId; + } + + InstanceOptionalReference PrefabFocusHandler::GetFocusedPrefabInstance() + { + return m_focusedInstance; + } + + bool PrefabFocusHandler::IsOwningPrefabBeingFocused(AZ::EntityId entityId) + { + if (entityId == AZ::EntityId()) + { + // TODO - Warn? + return false; + } + + InstanceOptionalReference instance = s_instanceEntityMapperInterface->FindOwningInstance(entityId); + + if (!instance.has_value()) + { + // TODO - ERROR + } + + return (&instance->get() == &m_focusedInstance->get()); + } + +} // namespace AzToolsFramework::Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h new file mode 100644 index 0000000000..44e84dc345 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h @@ -0,0 +1,56 @@ +/* + * 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 + +#include +#include +#include + +namespace AzToolsFramework +{ + class PrefabEditorEntityOwnershipInterface; +} + +namespace AzToolsFramework::FocusModeFramework +{ + class FocusModeInterface; +} + +namespace AzToolsFramework::Prefab +{ + class InstanceEntityMapperInterface; + + class PrefabFocusHandler final + : private PrefabFocusInterface + { + public: + AZ_CLASS_ALLOCATOR(PrefabFocusHandler, AZ::SystemAllocator, 0); + + ~PrefabFocusHandler(); + + void Initialize(); + + // PrefabFocusInterface... + void FocusOnOwningPrefab(AZ::EntityId entityId) override; + TemplateId GetFocusedPrefabTemplateId() override; + InstanceOptionalReference GetFocusedPrefabInstance() override; + bool IsOwningPrefabBeingFocused(AZ::EntityId entityId) override; + + private: + InstanceOptionalReference m_focusedInstance; + TemplateId m_focusedTemplateId; + + static FocusModeFramework::FocusModeInterface* s_focusModeInterface; + static InstanceEntityMapperInterface* s_instanceEntityMapperInterface; + static PrefabEditorEntityOwnershipInterface* s_prefabEditorEntityOwnershipInterface; + }; + +} // namespace AzToolsFramework::Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h new file mode 100644 index 0000000000..d18a669f51 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h @@ -0,0 +1,40 @@ +/* + * 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 +#include + +#include +#include + +namespace AzToolsFramework::Prefab +{ + /*! + * PrefabFocusInterface + */ + class PrefabFocusInterface + { + public: + AZ_RTTI(PrefabFocusInterface, "{F3CFA37B-5FD8-436A-9C30-60EB54E350E1}"); + + // TODO - Add comment + virtual void FocusOnOwningPrefab(AZ::EntityId entityId) = 0; + + // TODO - Add comment + virtual TemplateId GetFocusedPrefabTemplateId() = 0; + + // TODO - Add comment + virtual InstanceOptionalReference GetFocusedPrefabInstance() = 0; + + // TODO - Add comment + virtual bool IsOwningPrefabBeingFocused(AZ::EntityId entityId) = 0; + }; + +} // namespace AzToolsFramework::Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index 0d2696f14b..7220cf3cce 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -34,6 +34,7 @@ namespace AzToolsFramework m_prefabLoader.RegisterPrefabLoaderInterface(); m_instanceUpdateExecutor.RegisterInstanceUpdateExecutorInterface(); m_instanceToTemplatePropagator.RegisterInstanceToTemplateInterface(); + m_prefabFocusHandler.Initialize(); m_prefabPublicHandler.RegisterPrefabPublicHandlerInterface(); m_prefabPublicRequestHandler.Connect(); AZ::SystemTickBus::Handler::BusConnect(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h index d6908922c9..a9e16374e9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -369,7 +370,7 @@ namespace AzToolsFramework // A counter for generating unique Link Ids. AZStd::atomic m_linkIdCounter = 0u; - // Used for finding the owning instance of an arbitrary entity + // Used for finding the owning instance of an arbitrary entity. InstanceEntityMapper m_instanceEntityMapper; // Used for finding the Instances owned by an arbitrary Template. @@ -378,16 +379,19 @@ namespace AzToolsFramework // Used for loading/saving Prefab Template files. PrefabLoader m_prefabLoader; - // Handler the public Prefab API used by UI and scripting + // Handles the Prefab Focus API that determines what prefab is being edited. + PrefabFocusHandler m_prefabFocusHandler; + + // Handles the public Prefab API used by UI and scripting. PrefabPublicHandler m_prefabPublicHandler; // Used for updating Instances of Prefab Template. InstanceUpdateExecutor m_instanceUpdateExecutor; - // Used for updating Templates when Instances are modified + // Used for updating Templates when Instances are modified. InstanceToTemplatePropagator m_instanceToTemplatePropagator; - // Handler of the public Prefab requests + // Handler of the public Prefab requests. PrefabPublicRequestHandler m_prefabPublicRequestHandler; }; } // namespace Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp index c75f6aa86d..bb6bdf0ebd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp @@ -8,7 +8,6 @@ #include -#include #include #include @@ -24,14 +23,6 @@ namespace AzToolsFramework LevelRootUiHandler::LevelRootUiHandler() { - m_prefabEditInterface = AZ::Interface::Get(); - - if (m_prefabEditInterface == nullptr) - { - AZ_Assert(false, "LevelRootUiHandler - could not get PrefabEditInterface on LevelRootUiHandler construction."); - return; - } - m_prefabPublicInterface = AZ::Interface::Get(); if (m_prefabPublicInterface == nullptr) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.h index 6eeccfe88d..1e485572b8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.h @@ -14,7 +14,6 @@ namespace AzToolsFramework { namespace Prefab { - class PrefabEditInterface; class PrefabPublicInterface; }; @@ -36,7 +35,6 @@ namespace AzToolsFramework void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; private: - Prefab::PrefabEditInterface* m_prefabEditInterface = nullptr; Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr; static constexpr int m_levelRootBorderThickness = 1; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabEditInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabEditInterface.h deleted file mode 100644 index 1bd4a164f8..0000000000 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabEditInterface.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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 -#include - -namespace AzToolsFramework -{ - namespace Prefab - { - /*! - * PrefabEditInterface - * Interface to expose the API to Edit Prefabs in the Editor. - */ - class PrefabEditInterface - { - public: - AZ_RTTI(PrefabEditInterface, "{DABB1D43-3760-420E-9F1E-5104F0AFF167}"); - - /** - * Sets the prefab for the instance owning the entity provided as the prefab being edited. - * @param entityId The entity whose owning prefab should be edited. - */ - virtual void EditOwningPrefab(AZ::EntityId entityId) = 0; - - /** - * Queries the Edit Manager to know if the provided entity is part of the prefab currently being edited. - * @param entityId The entity whose prefab editing state we want to query. - * @return True if the prefab owning this entity is being edited, false otherwise. - */ - virtual bool IsOwningPrefabBeingEdited(AZ::EntityId entityId) = 0; - }; - - } // namespace Prefab -} // namespace AzToolsFramework - diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabEditManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabEditManager.cpp deleted file mode 100644 index 27a4c3bcaf..0000000000 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabEditManager.cpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 - -#include - -namespace AzToolsFramework -{ - namespace Prefab - { - PrefabEditManager::PrefabEditManager() - { - m_prefabPublicInterface = AZ::Interface::Get(); - - if (m_prefabPublicInterface == nullptr) - { - AZ_Assert(false, "Prefab - could not get PrefabPublicInterface on PrefabEditManager construction."); - return; - } - - AZ::Interface::Register(this); - } - - PrefabEditManager::~PrefabEditManager() - { - AZ::Interface::Unregister(this); - } - - void PrefabEditManager::EditOwningPrefab(AZ::EntityId entityId) - { - m_instanceBeingEdited = m_prefabPublicInterface->GetInstanceContainerEntityId(entityId); - } - - bool PrefabEditManager::IsOwningPrefabBeingEdited(AZ::EntityId entityId) - { - AZ::EntityId containerEntity = m_prefabPublicInterface->GetInstanceContainerEntityId(entityId); - return m_instanceBeingEdited == containerEntity; - } - } -} diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabEditManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabEditManager.h deleted file mode 100644 index d155322e3c..0000000000 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabEditManager.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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 -#include - -#include -#include - -namespace AzToolsFramework -{ - namespace Prefab - { - class PrefabEditManager final - : private PrefabEditInterface - { - public: - AZ_CLASS_ALLOCATOR(PrefabEditManager, AZ::SystemAllocator, 0); - - PrefabEditManager(); - ~PrefabEditManager(); - - private: - // PrefabEditInterface... - void EditOwningPrefab(AZ::EntityId entityId) override; - bool IsOwningPrefabBeingEdited(AZ::EntityId entityId) override; - - AZ::EntityId m_instanceBeingEdited; - - PrefabPublicInterface* m_prefabPublicInterface; - }; - } -} diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index 0c61ccb501..9b7f2fff10 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -57,9 +58,9 @@ namespace AzToolsFramework { EditorEntityUiInterface* PrefabIntegrationManager::s_editorEntityUiInterface = nullptr; - PrefabPublicInterface* PrefabIntegrationManager::s_prefabPublicInterface = nullptr; - PrefabEditInterface* PrefabIntegrationManager::s_prefabEditInterface = nullptr; + PrefabFocusInterface* PrefabIntegrationManager::s_prefabFocusInterface = nullptr; PrefabLoaderInterface* PrefabIntegrationManager::s_prefabLoaderInterface = nullptr; + PrefabPublicInterface* PrefabIntegrationManager::s_prefabPublicInterface = nullptr; PrefabSystemComponentInterface* PrefabIntegrationManager::s_prefabSystemComponentInterface = nullptr; const AZStd::string PrefabIntegrationManager::s_prefabFileExtension = ".prefab"; @@ -102,13 +103,6 @@ namespace AzToolsFramework return; } - s_prefabEditInterface = AZ::Interface::Get(); - if (s_prefabEditInterface == nullptr) - { - AZ_Assert(false, "Prefab - could not get PrefabEditInterface on PrefabIntegrationManager construction."); - return; - } - s_prefabLoaderInterface = AZ::Interface::Get(); if (s_prefabLoaderInterface == nullptr) { @@ -123,6 +117,13 @@ namespace AzToolsFramework return; } + s_prefabFocusInterface = AZ::Interface::Get(); + if (s_prefabFocusInterface == nullptr) + { + AZ_Assert(false, "Prefab - could not get PrefabFocusInterface on PrefabIntegrationManager construction."); + return; + } + EditorContextMenuBus::Handler::BusConnect(); PrefabInstanceContainerNotificationBus::Handler::BusConnect(); AZ::Interface::Register(this); @@ -224,7 +225,7 @@ namespace AzToolsFramework // Edit Prefab if (prefabWipFeaturesEnabled) { - bool beingEdited = s_prefabEditInterface->IsOwningPrefabBeingEdited(selectedEntity); + bool beingEdited = s_prefabFocusInterface->IsOwningPrefabBeingFocused(selectedEntity); if (!beingEdited) { @@ -428,7 +429,7 @@ namespace AzToolsFramework void PrefabIntegrationManager::ContextMenu_EditPrefab(AZ::EntityId containerEntity) { - s_prefabEditInterface->EditOwningPrefab(containerEntity); + s_prefabFocusInterface->FocusOnOwningPrefab(containerEntity); } void PrefabIntegrationManager::ContextMenu_SavePrefab(AZ::EntityId containerEntity) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h index 3e66350932..6f66b1f514 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h @@ -17,7 +17,7 @@ #include #include #include -#include + #include #include #include @@ -28,7 +28,7 @@ namespace AzToolsFramework { namespace Prefab { - + class PrefabFocusInterface; class PrefabLoaderInterface; //! Structure for saving/retrieving user settings related to prefab workflows. @@ -80,9 +80,6 @@ namespace AzToolsFramework void ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) override; private: - // Manages the Edit Mode UI for prefabs - PrefabEditManager m_prefabEditManager; - // Used to handle the UI for the level root LevelRootUiHandler m_levelRootUiHandler; @@ -135,13 +132,12 @@ namespace AzToolsFramework AZStd::unique_ptr ConstructSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference); void SavePrefabsInDialog(QDialog* unsavedPrefabsDialog); - static const AZStd::string s_prefabFileExtension; static EditorEntityUiInterface* s_editorEntityUiInterface; - static PrefabPublicInterface* s_prefabPublicInterface; - static PrefabEditInterface* s_prefabEditInterface; + static PrefabFocusInterface* s_prefabFocusInterface; static PrefabLoaderInterface* s_prefabLoaderInterface; + static PrefabPublicInterface* s_prefabPublicInterface; static PrefabSystemComponentInterface* s_prefabSystemComponentInterface; }; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp index fda56b79f1..c802850c4b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp @@ -8,7 +8,7 @@ #include -#include +#include #include #include @@ -26,21 +26,19 @@ namespace AzToolsFramework PrefabUiHandler::PrefabUiHandler() { - m_prefabEditInterface = AZ::Interface::Get(); - - if (m_prefabEditInterface == nullptr) - { - AZ_Assert(false, "PrefabUiHandler - could not get PrefabEditInterface on PrefabUiHandler construction."); - return; - } - m_prefabPublicInterface = AZ::Interface::Get(); - if (m_prefabPublicInterface == nullptr) { AZ_Assert(false, "PrefabUiHandler - could not get PrefabPublicInterface on PrefabUiHandler construction."); return; } + + m_prefabFocusInterface = AZ::Interface::Get(); + if (m_prefabFocusInterface == nullptr) + { + AZ_Assert(false, "PrefabUiHandler - could not get PrefabFocusInterface on PrefabUiHandler construction."); + return; + } } QString PrefabUiHandler::GenerateItemInfoString(AZ::EntityId entityId) const @@ -83,7 +81,7 @@ namespace AzToolsFramework QIcon PrefabUiHandler::GenerateItemIcon(AZ::EntityId entityId) const { - if (m_prefabEditInterface->IsOwningPrefabBeingEdited(entityId)) + if (m_prefabFocusInterface->IsOwningPrefabBeingFocused(entityId)) { return QIcon(m_prefabEditIconPath); } @@ -105,7 +103,7 @@ namespace AzToolsFramework const bool hasVisibleChildren = index.data(EntityOutlinerListModel::ExpandedRole).value() && index.model()->hasChildren(index); QColor backgroundColor = m_prefabCapsuleColor; - if (m_prefabEditInterface->IsOwningPrefabBeingEdited(entityId)) + if (m_prefabFocusInterface->IsOwningPrefabBeingFocused(entityId)) { backgroundColor = m_prefabCapsuleEditColor; } @@ -191,7 +189,7 @@ namespace AzToolsFramework const bool isLastColumn = descendantIndex.column() == EntityOutlinerListModel::ColumnLockToggle; QColor borderColor = m_prefabCapsuleColor; - if (m_prefabEditInterface->IsOwningPrefabBeingEdited(entityId)) + if (m_prefabFocusInterface->IsOwningPrefabBeingFocused(entityId)) { borderColor = m_prefabCapsuleEditColor; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h index d900fae427..547c100eb1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h @@ -12,9 +12,10 @@ namespace AzToolsFramework { + namespace Prefab { - class PrefabEditInterface; + class PrefabFocusInterface; class PrefabPublicInterface; }; @@ -37,7 +38,7 @@ namespace AzToolsFramework const QModelIndex& descendantIndex) const override; private: - Prefab::PrefabEditInterface* m_prefabEditInterface = nullptr; + Prefab::PrefabFocusInterface* m_prefabFocusInterface = nullptr; Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr; static bool IsLastVisibleChild(const QModelIndex& parent, const QModelIndex& child); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 2d9e75a115..400b87886b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -147,6 +147,9 @@ set(FILES Entity/SliceEditorEntityOwnershipServiceBus.h Fingerprinting/TypeFingerprinter.h Fingerprinting/TypeFingerprinter.cpp + FocusMode/FocusModeInterface.h + FocusMode/FocusModeSystemComponent.h + FocusMode/FocusModeSystemComponent.cpp Logger/TraceLogger.cpp Logger/TraceLogger.h Manipulators/AngularManipulator.cpp @@ -625,6 +628,9 @@ set(FILES Prefab/PrefabDomTypes.h Prefab/PrefabDomUtils.h Prefab/PrefabDomUtils.cpp + Prefab/PrefabFocusHandler.h + Prefab/PrefabFocusHandler.cpp + Prefab/PrefabFocusInterface.h Prefab/PrefabIdTypes.h Prefab/PrefabLoader.h Prefab/PrefabLoader.cpp @@ -717,9 +723,6 @@ set(FILES UI/Layer/LayerUiHandler.cpp UI/Prefab/LevelRootUiHandler.h UI/Prefab/LevelRootUiHandler.cpp - UI/Prefab/PrefabEditInterface.h - UI/Prefab/PrefabEditManager.h - UI/Prefab/PrefabEditManager.cpp UI/Prefab/PrefabIntegrationBus.h UI/Prefab/PrefabIntegrationManager.h UI/Prefab/PrefabIntegrationManager.cpp From 71bf61491271ec781669bc240d67d746ef8b2c7a Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Mon, 20 Sep 2021 12:18:23 -0700 Subject: [PATCH 28/84] Changed FocusOnOwningPrefab to return Outcome. Added comments and error checking. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../FocusMode/FocusModeSystemComponent.cpp | 4 ++-- .../Prefab/PrefabFocusHandler.cpp | 13 ++++++------- .../AzToolsFramework/Prefab/PrefabFocusHandler.h | 2 +- .../Prefab/PrefabFocusInterface.h | 15 ++++++++++----- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp index 3ad2dbdfb8..d82ce9ffeb 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp @@ -10,6 +10,7 @@ #include +#include #include namespace AzToolsFramework::FocusModeFramework @@ -53,8 +54,7 @@ namespace AzToolsFramework::FocusModeFramework { m_focusRoot = entityId; - // TODO - If m_focusRoot != AZ::EntityId(), register focus mode - // Else, unregister focus mode + // TODO - If m_focusRoot != AZ::EntityId(), activate focus mode via ViewportEditorModeTrackerInterface; else, deactivate focus mode } AZ::EntityId FocusModeSystemComponent::GetFocusRoot() diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp index a9c8c93eb0..ee663c0c3f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp @@ -49,7 +49,7 @@ namespace AzToolsFramework::Prefab AZ::Interface::Register(this); } - void PrefabFocusHandler::FocusOnOwningPrefab(AZ::EntityId entityId) + PrefabFocusOperationResult PrefabFocusHandler::FocusOnOwningPrefab(AZ::EntityId entityId) { InstanceOptionalReference focusedInstance; @@ -64,12 +64,15 @@ namespace AzToolsFramework::Prefab if (!focusedInstance.has_value()) { - // TODO - ERROR + return AZ::Failure(AZStd::string( + "Prefab Focus Handler: Couldn't find owning instance of entityId provided.")); } m_focusedInstance = focusedInstance; m_focusedTemplateId = focusedInstance->get().GetTemplateId(); s_focusModeInterface->SetFocusRoot(focusedInstance->get().GetContainerEntityId()); + + return AZ::Success(); } TemplateId PrefabFocusHandler::GetFocusedPrefabTemplateId() @@ -86,16 +89,12 @@ namespace AzToolsFramework::Prefab { if (entityId == AZ::EntityId()) { - // TODO - Warn? return false; } InstanceOptionalReference instance = s_instanceEntityMapperInterface->FindOwningInstance(entityId); - if (!instance.has_value()) - { - // TODO - ERROR - } + AZ_Assert(instance.has_value(), "PrefabFocusHandler::IsOwningPrefabBeingFocused - Could not find owning Instance of queried entity."); return (&instance->get() == &m_focusedInstance->get()); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h index 44e84dc345..bf8b6994d1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h @@ -39,7 +39,7 @@ namespace AzToolsFramework::Prefab void Initialize(); // PrefabFocusInterface... - void FocusOnOwningPrefab(AZ::EntityId entityId) override; + PrefabFocusOperationResult FocusOnOwningPrefab(AZ::EntityId entityId) override; TemplateId GetFocusedPrefabTemplateId() override; InstanceOptionalReference GetFocusedPrefabInstance() override; bool IsOwningPrefabBeingFocused(AZ::EntityId entityId) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h index d18a669f51..7b867ab8d2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h @@ -16,6 +16,8 @@ namespace AzToolsFramework::Prefab { + typedef AZ::Outcome PrefabFocusOperationResult; + /*! * PrefabFocusInterface */ @@ -24,16 +26,19 @@ namespace AzToolsFramework::Prefab public: AZ_RTTI(PrefabFocusInterface, "{F3CFA37B-5FD8-436A-9C30-60EB54E350E1}"); - // TODO - Add comment - virtual void FocusOnOwningPrefab(AZ::EntityId entityId) = 0; + //! Set the focused prefab instance to the owning instance of the entityId provided + //! @param entityId The entityId of the entity whose owning instance we want the prefab system to focus on. + virtual PrefabFocusOperationResult FocusOnOwningPrefab(AZ::EntityId entityId) = 0; - // TODO - Add comment + //! Returns the template id of the instance the prefab system is focusing on. virtual TemplateId GetFocusedPrefabTemplateId() = 0; - // TODO - Add comment + //! Returns a reference to the instance the prefab system is focusing on. virtual InstanceOptionalReference GetFocusedPrefabInstance() = 0; - // TODO - Add comment + //! Returns whether the entity belongs to the instance that is being focused on, or one of its descendants. + //! @param entityId The entityId of the queried entity. + //! @return true if the entity belongs to the focused instance or one of its descendants, false otherwise. virtual bool IsOwningPrefabBeingFocused(AZ::EntityId entityId) = 0; }; From 376a6040d83e52ad62eb8ed4982c4f94f478a51f Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Mon, 20 Sep 2021 15:24:03 -0500 Subject: [PATCH 29/84] Addressing PR feedback Signed-off-by: Guthrie Adams --- .../CommonFeatures/Material/MaterialComponentBus.h | 4 ++-- .../Code/Source/Material/EditorMaterialComponent.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h index ab7a180dd1..ace16ba6ca 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h @@ -33,9 +33,9 @@ namespace AZ virtual const MaterialAssignmentMap& GetMaterialOverrides() const = 0; //! Clear all material overrides virtual void ClearAllMaterialOverrides() = 0; - //! Clear non-lod material override + //! Clear non-lod material overrides virtual void ClearModelMaterialOverrides() = 0; - //! Clear lod material override + //! Clear lod material overrides virtual void ClearLodMaterialOverrides() = 0; //! Clear residual materials that don't correspond to the associated model virtual void ClearIncompatibleMaterialOverrides() = 0; diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp index ab39e7f208..b7bf191bc9 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp @@ -364,9 +364,9 @@ namespace AZ EditorMaterialComponentExporter::ExportItemsContainer exportItems; exportItems.reserve(assetIdToSlotNameMap.size()); - for (const auto& assetIdToSlotNamePair : assetIdToSlotNameMap) + for (const auto& [assetId, slotName] : assetIdToSlotNameMap) { - exportItems.emplace_back(assetIdToSlotNamePair.first, assetIdToSlotNamePair.second); + exportItems.emplace_back(assetId, slotName); } // Display the export dialog so that the user can configure how they want different materials to be exported From 489a93cf91e30ff727c7e32c588c712f5efe436a Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Mon, 20 Sep 2021 13:44:25 -0700 Subject: [PATCH 30/84] Remove assert for edge case that can actually happen in normal circumstances, simply return false in those cases. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzToolsFramework/Prefab/PrefabFocusHandler.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp index ee663c0c3f..2f64234352 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp @@ -94,9 +94,7 @@ namespace AzToolsFramework::Prefab InstanceOptionalReference instance = s_instanceEntityMapperInterface->FindOwningInstance(entityId); - AZ_Assert(instance.has_value(), "PrefabFocusHandler::IsOwningPrefabBeingFocused - Could not find owning Instance of queried entity."); - - return (&instance->get() == &m_focusedInstance->get()); + return instance.has_value() && (&instance->get() == &m_focusedInstance->get()); } } // namespace AzToolsFramework::Prefab From d15d7c3a855afc1ce31b36518469b97610e9631c Mon Sep 17 00:00:00 2001 From: amzn-tommy Date: Mon, 20 Sep 2021 16:24:28 -0700 Subject: [PATCH 31/84] Modify CalcOverallHeightRange to not return nil Signed-off-by: amzn-tommy --- .../Materials/Types/StandardMultilayerPBR_Displacement.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua index 8fa010f7bd..2feeffd4f8 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua @@ -138,7 +138,8 @@ function CalcOverallHeightRange(context) if(enableLayer3) then GetMergedHeightRange(heightMinMax, offsetLayer3, factorLayer3) end else - heightMinMax = {0,0} + heightMinMax[0] = 0 + heightMinMax[1] = 0 end return heightMinMax From 88ee878025ab77e636ef157ef2a17809e220f983 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Mon, 20 Sep 2021 23:13:51 -0500 Subject: [PATCH 32/84] deleting platform specific code from ME and SMC fixed ME viewport Signed-off-by: Guthrie Adams --- .../Platform/Linux/MaterialEditor_Linux.cpp | 27 ----------- .../Platform/Mac/MaterialEditor_Mac.cpp | 27 ----------- .../Windows/MaterialEditor_Windows.cpp | 47 ------------------- .../Viewport/MaterialViewportWidget.cpp | 26 ---------- .../Source/Viewport/MaterialViewportWidget.h | 5 -- .../Mac/ShaderManagementConsole_Mac.cpp | 22 --------- .../ShaderManagementConsole_Windows.cpp | 45 ------------------ 7 files changed, 199 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Linux/MaterialEditor_Linux.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Linux/MaterialEditor_Linux.cpp index 14b5fee1fe..d588e5a656 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Linux/MaterialEditor_Linux.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Linux/MaterialEditor_Linux.cpp @@ -6,33 +6,6 @@ * */ -#include -#include -#include - namespace Platform { - void LoadPluginDependencies() - { - AZ_Warning("Material Editor", false, "LoadPluginDependencies() function is not implemented"); - } - - void ProcessInput(void* message) - { - AZ_Warning("Material Editor", false, "ProcessInput() function is not implemented"); - } - - AzFramework::NativeWindowHandle GetWindowHandle(WId winId) - { - AZ_Warning("Material Editor", false, "GetWindowHandle() function is not implemented"); - AZ_UNUSED(winId); - return nullptr; - } - - AzFramework::WindowSize GetClientAreaSize(AzFramework::NativeWindowHandle window) - { - AZ_Warning("Material Editor", false, "GetClientAreaSize() function is not implemented"); - AZ_UNUSED(window); - return AzFramework::WindowSize{1,1}; - } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Mac/MaterialEditor_Mac.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Mac/MaterialEditor_Mac.cpp index 14b5fee1fe..d588e5a656 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Mac/MaterialEditor_Mac.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Mac/MaterialEditor_Mac.cpp @@ -6,33 +6,6 @@ * */ -#include -#include -#include - namespace Platform { - void LoadPluginDependencies() - { - AZ_Warning("Material Editor", false, "LoadPluginDependencies() function is not implemented"); - } - - void ProcessInput(void* message) - { - AZ_Warning("Material Editor", false, "ProcessInput() function is not implemented"); - } - - AzFramework::NativeWindowHandle GetWindowHandle(WId winId) - { - AZ_Warning("Material Editor", false, "GetWindowHandle() function is not implemented"); - AZ_UNUSED(winId); - return nullptr; - } - - AzFramework::WindowSize GetClientAreaSize(AzFramework::NativeWindowHandle window) - { - AZ_Warning("Material Editor", false, "GetClientAreaSize() function is not implemented"); - AZ_UNUSED(window); - return AzFramework::WindowSize{1,1}; - } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/MaterialEditor_Windows.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/MaterialEditor_Windows.cpp index 65c135315b..d588e5a656 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/MaterialEditor_Windows.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/MaterialEditor_Windows.cpp @@ -6,53 +6,6 @@ * */ -#include -#include -#include -#include -#include - namespace Platform { - void ProcessInput(void* message) - { - MSG* msg = (MSG*)message; - - // Ensure that the Windows WM_INPUT messages get passed through to the AzFramework input system, - // but only while in game mode so we don't accumulate raw input events before we start actually - // ticking the input devices, otherwise the queued events will get sent when entering game mode. - if (msg->message == WM_INPUT) - { - UINT rawInputSize; - const UINT rawInputHeaderSize = sizeof(RAWINPUTHEADER); - GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, NULL, &rawInputSize, rawInputHeaderSize); - - LPBYTE rawInputBytes = new BYTE[rawInputSize]; - GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, rawInputBytes, &rawInputSize, rawInputHeaderSize); - - RAWINPUT* rawInput = (RAWINPUT*)rawInputBytes; - - AzFramework::RawInputNotificationBusWindows::Broadcast( - &AzFramework::RawInputNotificationBusWindows::Events::OnRawInputEvent, *rawInput); - } - } - - AzFramework::NativeWindowHandle GetWindowHandle(WId winId) - { - return reinterpret_cast(winId); - } - - AzFramework::WindowSize GetClientAreaSize(AzFramework::NativeWindowHandle window) - { - RECT r; - if (GetWindowRect(reinterpret_cast(window), &r)) - { - return AzFramework::WindowSize{aznumeric_cast(r.right - r.left), aznumeric_cast(r.bottom - r.top)}; - } - else - { - AZ_Assert(false, "Failed to get dimensions for window"); - return AzFramework::WindowSize{}; - } - } } diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp index d2fe78cb89..e2c5ee0026 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp @@ -17,20 +17,11 @@ #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknow n-warning-option") // disable warnings spawned by QT -#include #include #include "Viewport/ui_MaterialViewportWidget.h" AZ_POP_DISABLE_WARNING -#include #include -#include - -namespace Platform -{ - void ProcessInput(void* message); -} - namespace MaterialEditor { @@ -41,14 +32,6 @@ namespace MaterialEditor { m_ui->setupUi(this); - if (auto dispatcher = QAbstractEventDispatcher::instance()) - { - dispatcher->installNativeEventFilter(this); - } - - AzFramework::WindowSystemNotificationBus::Broadcast( - &AzFramework::WindowSystemNotificationBus::Events::OnWindowCreated, GetViewportContext()->GetWindowHandle()); - // The viewport context created by AtomToolsFramework::RenderViewportWidget has no name. // Systems like frame capturing and post FX expect there to be a context with DefaultViewportContextName auto viewportContextManager = AZ::Interface::Get(); @@ -58,13 +41,4 @@ namespace MaterialEditor m_renderer = AZStd::make_unique(GetViewportContext()->GetWindowContext()); GetControllerList()->Add(m_renderer->GetController()); } - - // This is a temporary fix to get input working in Qt window, otherwise it wont receive input events - // This will later be handled on the QApplication subclass level - bool MaterialViewportWidget::nativeEventFilter(const QByteArray& /*eventType*/, void* message, long* /*result*/) - { - Platform::ProcessInput(message); - - return false; - } } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.h b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.h index 438c7b9a9e..2a71dcc1df 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.h +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.h @@ -8,12 +8,10 @@ #pragma once #if !defined(Q_MOC_RUN) -#include #include AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include -#include AZ_POP_DISABLE_WARNING #endif @@ -38,14 +36,11 @@ namespace MaterialEditor class MaterialViewportWidget : public AtomToolsFramework::RenderViewportWidget - , public QAbstractNativeEventFilter { public: MaterialViewportWidget(QWidget* parent = nullptr); QScopedPointer m_ui; AZStd::unique_ptr m_renderer; - - bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) override; }; } // namespace MaterialEditor diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Mac/ShaderManagementConsole_Mac.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Mac/ShaderManagementConsole_Mac.cpp index 6a05b895e0..d588e5a656 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Mac/ShaderManagementConsole_Mac.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Mac/ShaderManagementConsole_Mac.cpp @@ -6,28 +6,6 @@ * */ -#include -#include -#include - namespace Platform { - void ProcessInput(void* message) - { - AZ_Warning("Shader Management Console", false, "ProcessInput() function is not implemented"); - } - - AzFramework::NativeWindowHandle GetWindowHandle(WId winId) - { - AZ_Warning("Shader Management Console", false, "GetWindowHandle() function is not implemented"); - AZ_UNUSED(winId); - return nullptr; - } - - AzFramework::WindowSize GetClientAreaSize(AzFramework::NativeWindowHandle window) - { - AZ_Warning("Shader Management Console", false, "GetClientAreaSize() function is not implemented"); - AZ_UNUSED(window); - return AzFramework::WindowSize{1,1}; - } } diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/ShaderManagementConsole_Windows.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/ShaderManagementConsole_Windows.cpp index ff94ef1196..d588e5a656 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/ShaderManagementConsole_Windows.cpp +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/ShaderManagementConsole_Windows.cpp @@ -6,51 +6,6 @@ * */ -#include -#include -#include - namespace Platform { - void ProcessInput(void* message) - { - MSG* msg = (MSG*)message; - - // Ensure that the Windows WM_INPUT messages get passed through to the AzFramework input system, - // but only while in game mode so we don't accumulate raw input events before we start actually - // ticking the input devices, otherwise the queued events will get sent when entering game mode. - if (msg->message == WM_INPUT) - { - UINT rawInputSize; - const UINT rawInputHeaderSize = sizeof(RAWINPUTHEADER); - GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, NULL, &rawInputSize, rawInputHeaderSize); - - LPBYTE rawInputBytes = new BYTE[rawInputSize]; - GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, rawInputBytes, &rawInputSize, rawInputHeaderSize); - - RAWINPUT* rawInput = (RAWINPUT*)rawInputBytes; - - AzFramework::RawInputNotificationBusWindows::Broadcast( - &AzFramework::RawInputNotificationBusWindows::Events::OnRawInputEvent, *rawInput); - } - } - - AzFramework::NativeWindowHandle GetWindowHandle(WId winId) - { - return reinterpret_cast(winId); - } - - AzFramework::WindowSize GetClientAreaSize(AzFramework::NativeWindowHandle window) - { - RECT r; - if (GetWindowRect(reinterpret_cast(window), &r)) - { - return AzFramework::WindowSize{aznumeric_cast(r.right - r.left), aznumeric_cast(r.bottom - r.top)}; - } - else - { - AZ_Assert(false, "Failed to get dimensions for window"); - return AzFramework::WindowSize{}; - } - } } From 895974db57cc6472baf94d7254f7acca23384fc4 Mon Sep 17 00:00:00 2001 From: pereslav Date: Tue, 21 Sep 2021 14:50:06 +0100 Subject: [PATCH 33/84] Removed spawn/despawn events from the spawnable system. Used NetworkSpawnableHolderComponent instead Signed-off-by: pereslav --- .../Spawnable/SpawnableEntitiesInterface.h | 9 --- .../Spawnable/SpawnableEntitiesManager.cpp | 20 ----- .../Spawnable/SpawnableEntitiesManager.h | 6 -- .../Mocks/MockSpawnableEntitiesInterface.h | 2 - .../NetworkEntity/INetworkEntityManager.h | 10 +++ .../NetworkEntity/NetworkEntityManager.cpp | 78 +------------------ .../NetworkEntity/NetworkEntityManager.h | 18 +---- .../NetworkSpawnableHolderComponent.cpp | 24 ++++++ .../NetworkSpawnableHolderComponent.h | 2 + 9 files changed, 43 insertions(+), 126 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h index 254df8f1b0..4b09dcbc75 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesInterface.h @@ -320,15 +320,6 @@ namespace AzFramework //! @param optionalArgs Optional additional arguments, see BarrierOptionalArgs. virtual void Barrier(EntitySpawnTicket& ticket, BarrierCallback completionCallback, BarrierOptionalArgs optionalArgs = {}) = 0; - //! Register a handler for OnSpawned events. - //! @param handler The handler to receive the event. - virtual void AddOnSpawnedHandler(AZ::Event, - const AZStd::vector&, const void*>::Handler& handler) = 0; - - //! Register a handler for OnDespawned events. - //! @param handler The handler to receive the event. - virtual void AddOnDespawnedHandler(AZ::Event, const void*>::Handler& handler) = 0; - protected: [[nodiscard]] virtual AZStd::pair CreateTicket(AZ::Data::Asset&& spawnable) = 0; virtual void DestroyTicket(void* ticket) = 0; diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp index f052f83224..5fa072a451 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.cpp @@ -146,16 +146,6 @@ namespace AzFramework QueueRequest(ticket, optionalArgs.m_priority, AZStd::move(queueEntry)); } - void SpawnableEntitiesManager::AddOnSpawnedHandler(AZ::Event, const AZStd::vector&, const void*>::Handler& handler) - { - handler.Connect(m_onSpawnedEvent); - } - - void SpawnableEntitiesManager::AddOnDespawnedHandler(AZ::Event, const void*>::Handler& handler) - { - handler.Connect(m_onDespawnedEvent); - } - auto SpawnableEntitiesManager::ProcessQueue(CommandQueuePriority priority) -> CommandQueueStatus { CommandQueueStatus result = CommandQueueStatus::NoCommandsLeft; @@ -359,8 +349,6 @@ namespace AzFramework ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount, ticket.m_spawnedEntities.end())); } - m_onSpawnedEvent.Signal(ticket.m_spawnable, ticket.m_spawnedEntities, &ticket); - ticket.m_currentRequestId++; return true; } @@ -441,8 +429,6 @@ namespace AzFramework ticket.m_spawnedEntities.begin() + spawnedEntitiesInitialCount, ticket.m_spawnedEntities.end())); } - m_onSpawnedEvent.Signal(ticket.m_spawnable, ticket.m_spawnedEntities, &ticket); - ticket.m_currentRequestId++; return true; } @@ -474,8 +460,6 @@ namespace AzFramework request.m_completionCallback(request.m_ticketId); } - m_onDespawnedEvent.Signal(ticket.m_spawnable, &ticket); - ticket.m_currentRequestId++; return true; } @@ -503,8 +487,6 @@ namespace AzFramework } } - m_onDespawnedEvent.Signal(ticket.m_spawnable, &ticket); - // Rebuild the list of entities. ticket.m_spawnedEntities.clear(); const Spawnable::EntityList& entities = request.m_spawnable->GetEntities(); @@ -562,8 +544,6 @@ namespace AzFramework ticket.m_spawnedEntities.begin(), ticket.m_spawnedEntities.end())); } - m_onSpawnedEvent.Signal(ticket.m_spawnable, ticket.m_spawnedEntities, &ticket); - ticket.m_currentRequestId++; return true; diff --git a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h index c78b1778a4..69985f8aa9 100644 --- a/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h +++ b/Code/Framework/AzFramework/AzFramework/Spawnable/SpawnableEntitiesManager.h @@ -69,9 +69,6 @@ namespace AzFramework void Barrier(EntitySpawnTicket& spawnInfo, BarrierCallback completionCallback, BarrierOptionalArgs optionalArgs = {}) override; - void AddOnSpawnedHandler(AZ::Event, const AZStd::vector&, const void*>::Handler& handler) override; - void AddOnDespawnedHandler(AZ::Event, const void*>::Handler& handler) override; - // // The following function is thread safe but intended to be run from the main thread. // @@ -227,9 +224,6 @@ namespace AzFramework //! SpawnablePriority_Default which gives users a bit of room to fine tune the priorities as this value can be configured //! through the Settings Registry under the key "/O3DE/AzFramework/Spawnables/HighPriorityThreshold". SpawnablePriority m_highPriorityThreshold { 64 }; - - AZ::Event, const AZStd::vector&, const void*> m_onSpawnedEvent; - AZ::Event, const void*> m_onDespawnedEvent; }; AZ_DEFINE_ENUM_BITWISE_OPERATORS(AzFramework::SpawnableEntitiesManager::CommandQueuePriority); diff --git a/Code/Framework/AzFramework/Tests/Mocks/MockSpawnableEntitiesInterface.h b/Code/Framework/AzFramework/Tests/Mocks/MockSpawnableEntitiesInterface.h index 89e79ecf9b..a5df7af4c3 100644 --- a/Code/Framework/AzFramework/Tests/Mocks/MockSpawnableEntitiesInterface.h +++ b/Code/Framework/AzFramework/Tests/Mocks/MockSpawnableEntitiesInterface.h @@ -59,8 +59,6 @@ namespace AzFramework MOCK_METHOD1(CreateTicket, AZStd::pair(AZ::Data::Asset&& spawnable)); MOCK_METHOD1(DestroyTicket, void(void* ticket)); - MOCK_METHOD1(AddOnSpawnedHandler, void(AZ::Event, const AZStd::vector&, const void*>::Handler& handler)); - MOCK_METHOD1(AddOnDespawnedHandler, void(AZ::Event, const void*>::Handler& handler)); /** Installs some default result values for the above functions. * Note that you can always override these in scope of your test by adding additional ON_CALL / EXPECT_CALL diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/INetworkEntityManager.h b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/INetworkEntityManager.h index 8a5fec869c..5bcf038eff 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/INetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/NetworkEntity/INetworkEntityManager.h @@ -13,6 +13,7 @@ #include #include #include +#include namespace Multiplayer { @@ -75,6 +76,15 @@ namespace Multiplayer const AZ::Transform& transform ) = 0; + //! Requests a network spawnable to instantiate at a given transform + //! This is an async function. The instantiated entities are not available immediately but will be constructed by the spawnable system + //! The spawnable ticket has to be kept for the whole lifetime of the entities + //! @param netSpawnable the network spawnable to spawn + //! @param transform the transform where the spawnable should be spawned + //! @return the ticket for managing the spawned entities + [[nodiscard]] virtual AZStd::unique_ptr RequestNetSpawnableInstantiation( + const AZ::Data::Asset& netSpawnable, const AZ::Transform& transform) = 0; + //! Configures new networked entity //! @param netEntity the entity to setup //! @param prefabEntryId the name of the spawnable the entity originated from diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index 61fd741dc6..f4f744494b 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -30,14 +30,9 @@ namespace Multiplayer : m_networkEntityAuthorityTracker(*this) , m_removeEntitiesEvent([this] { RemoveEntities(); }, AZ::Name("NetworkEntityManager remove entities event")) , m_updateEntityDomainEvent([this] { UpdateEntityDomain(); }, AZ::Name("NetworkEntityManager update entity domain event")) - , m_onSpawnedHandler([this](AZ::Data::Asset spawnable, const AZStd::vector& entities, const void* spawnTicket) { this->OnSpawned(spawnable, entities, spawnTicket); }) - , m_onDespawnedHandler([this](AZ::Data::Asset spawnable, const void* spawnTicket) { this->OnDespawned(spawnable, spawnTicket); }) { AZ::Interface::Register(this); AzFramework::RootSpawnableNotificationBus::Handler::BusConnect(); - - AzFramework::SpawnableEntitiesInterface::Get()->AddOnSpawnedHandler(m_onSpawnedHandler); - AzFramework::SpawnableEntitiesInterface::Get()->AddOnDespawnedHandler(m_onDespawnedHandler); } NetworkEntityManager::~NetworkEntityManager() @@ -473,52 +468,17 @@ namespace Multiplayer } AZStd::unique_ptr NetworkEntityManager::RequestNetSpawnableInstantiation( - const AZ::Data::Asset& rootSpawnable, const AZStd::vector& entities) + const AZ::Data::Asset& netSpawnable, const AZ::Transform& transform) { - if (entities.empty()) - { - AZ_Error("NetworkEntityManager", false, - "RequestNetSpawnableInstantiation: No entities in the spawnable %s", rootSpawnable.GetHint().c_str()); - return nullptr; - } - - // The first entity in every spawnable is the root one - const AZ::Entity* rootEntity = *entities.begin(); - if (!rootEntity) - { - AZ_Error("NetworkEntityManager", false, - "RequestNetSpawnableInstantiation: Root entity is null in the spawnable %s", rootSpawnable.GetHint().c_str()); - return nullptr; - } - - const auto* holderComponent = rootEntity->FindComponent(); - if (!holderComponent) - { - // This spawnable doesn't have a corresponding network spawnable. - return nullptr; - } - - AzFramework::TransformComponent* rootEntityTransform = - rootEntity->FindComponent(); - if (!rootEntityTransform) - { - AZ_Error("NetworkEntityManager", false, - "RequestNetSpawnableInstantiation: Root entity has no transform in the spawnable %s", rootSpawnable.GetHint().c_str()); - return nullptr; - } - - // Retrieve the corresponding network spawnable asset - AZ::Data::Asset netSpawnableAsset = holderComponent->GetNetworkSpawnableAsset(); - // Prepare the parameters for the spawning process AzFramework::SpawnAllEntitiesOptionalArgs optionalArgs; optionalArgs.m_priority = AzFramework::SpawnablePriority_High; const AZ::Name netSpawnableName = - AZ::Interface::Get()->GetSpawnableNameFromAssetId(netSpawnableAsset.GetId()); + AZ::Interface::Get()->GetSpawnableNameFromAssetId(netSpawnable.GetId()); // Pre-insertion callback allows us to do network-specific setup for the entities before they are added to the scene - optionalArgs.m_preInsertionCallback = [netSpawnableName, rootTransform = rootEntityTransform->GetWorldTM()] + optionalArgs.m_preInsertionCallback = [netSpawnableName, rootTransform = transform] (AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableEntityContainerView entities) { bool shouldUpdateTransform = (rootTransform.IsClose(AZ::Transform::Identity()) == false); @@ -546,7 +506,7 @@ namespace Multiplayer }; // Spawn with the newly created ticket. This allows the calling code to manage the lifetime of the constructed entities - auto ticket = AZStd::make_unique(netSpawnableAsset); + auto ticket = AZStd::make_unique(netSpawnable); AzFramework::SpawnableEntitiesInterface::Get()->SpawnAllEntities(*ticket, AZStd::move(optionalArgs)); return ticket; } @@ -572,28 +532,6 @@ namespace Multiplayer { multiplayer->SendReadyForEntityUpdates(false); } - - m_netSpawnableTickets.clear(); - } - - void NetworkEntityManager::OnSpawned(AZ::Data::Asset spawnable, - const AZStd::vector& entities, const void* spawnTicket) - { - if (ShouldSpawnNetEntities()) - { - AZStd::unique_ptr ticket = RequestNetSpawnableInstantiation(spawnable, entities); - if (ticket) - { - AZ::Data::AssetId spawnableAssetId = spawnable.GetId(); - m_netSpawnableTickets[spawnTicket] = AZStd::move(ticket); - } - } - } - - void NetworkEntityManager::OnDespawned([[maybe_unused]] AZ::Data::Asset spawnable, - const void* spawnTicket) - { - m_netSpawnableTickets.erase(spawnTicket); } void NetworkEntityManager::SetupNetEntity(AZ::Entity* netEntity, PrefabEntityId prefabEntityId, NetEntityRole netEntityRole) @@ -611,12 +549,4 @@ namespace Multiplayer netEntity->GetName().c_str()); } } - - bool NetworkEntityManager::ShouldSpawnNetEntities() const - { - const auto agentType = GetMultiplayer()->GetAgentType(); - const bool shouldSpawnNetEntities = - (agentType == MultiplayerAgentType::ClientServer || agentType == MultiplayerAgentType::DedicatedServer); - return shouldSpawnNetEntities; - } } diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h index 14efa4feeb..50e6beedad 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.h @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -61,6 +60,9 @@ namespace Multiplayer const AZ::Transform& transform ) override; + AZStd::unique_ptr RequestNetSpawnableInstantiation( + const AZ::Data::Asset& netSpawnable, const AZ::Transform& transform) override; + void SetupNetEntity(AZ::Entity* netEntity, PrefabEntityId prefabEntityId, NetEntityRole netEntityRole) override; uint32_t GetEntityCount() const override; @@ -93,15 +95,6 @@ namespace Multiplayer private: void RemoveEntities(); NetEntityId NextId(); - bool ShouldSpawnNetEntities() const; - void OnSpawned(AZ::Data::Asset spawnable, - const AZStd::vector& entities, const void* spawnTicket); - void OnDespawned(AZ::Data::Asset spawnable, const void* spawnTicket); - - // Note: This is an async function. - // The instantiated entities are not available immediately but will be constructed by the spawnable system - AZStd::unique_ptr RequestNetSpawnableInstantiation( - const AZ::Data::Asset& rootSpawnable, const AZStd::vector& entities); NetworkEntityTracker m_networkEntityTracker; NetworkEntityAuthorityTracker m_networkEntityAuthorityTracker; @@ -130,10 +123,5 @@ namespace Multiplayer DeferredRpcMessages m_localDeferredRpcMessages; NetworkSpawnableLibrary m_networkPrefabLibrary; - - AZStd::unordered_map> m_netSpawnableTickets; - - AZ::Event, const AZStd::vector&, const void*>::Handler m_onSpawnedHandler; - AZ::Event, const void*>::Handler m_onDespawnedHandler; }; } diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp index e83f6fea84..d33c3274c2 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.cpp @@ -8,6 +8,8 @@ #include #include +#include +#include namespace Multiplayer { @@ -28,10 +30,32 @@ namespace Multiplayer void NetworkSpawnableHolderComponent::Activate() { + const auto agentType = GetMultiplayer()->GetAgentType(); + const bool shouldSpawnNetEntities = + (agentType == MultiplayerAgentType::ClientServer || agentType == MultiplayerAgentType::DedicatedServer); + + if(shouldSpawnNetEntities) + { + AZ::Transform rootEntityTransform = AZ::Transform::CreateIdentity(); + + AzFramework::TransformComponent* rootEntityTransformComponent = + GetEntity()->FindComponent(); + if (rootEntityTransformComponent) + { + rootEntityTransform = rootEntityTransformComponent->GetWorldTM(); + } + + INetworkEntityManager* networkEntityManager = GetNetworkEntityManager(); + AZ_Assert(networkEntityManager != nullptr, + "Network Entity Manager must be initialized before NetworkSpawnableHolderComponent is activated"); + + m_netSpawnableTicket = networkEntityManager->RequestNetSpawnableInstantiation(m_networkSpawnableAsset, rootEntityTransform); + } } void NetworkSpawnableHolderComponent::Deactivate() { + m_netSpawnableTicket.reset(); } void NetworkSpawnableHolderComponent::SetNetworkSpawnableAsset(AZ::Data::Asset networkSpawnableAsset) diff --git a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h index f32e8d31ab..3836212c48 100644 --- a/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h +++ b/Gems/Multiplayer/Code/Source/Pipeline/NetworkSpawnableHolderComponent.h @@ -11,6 +11,7 @@ #include #include #include +#include namespace Multiplayer { @@ -37,5 +38,6 @@ namespace Multiplayer private: AZ::Data::Asset m_networkSpawnableAsset{ AZ::Data::AssetLoadBehavior::PreLoad }; + AZStd::unique_ptr m_netSpawnableTicket; }; } // namespace Multiplayer From 7fca57a16940b1085fdb7361397b672b96ae9881 Mon Sep 17 00:00:00 2001 From: AMZN-Igarri <82394219+AMZN-Igarri@users.noreply.github.com> Date: Tue, 21 Sep 2021 15:55:10 +0200 Subject: [PATCH 34/84] Fixed Assert (#4234) Signed-off-by: igarri --- .../AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp index fdbd4287ce..469a235b9f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetBrowser/AssetBrowserTableModel.cpp @@ -46,7 +46,7 @@ namespace AzToolsFramework QModelIndex AssetBrowserTableModel::mapToSource(const QModelIndex& proxyIndex) const { - Q_ASSERT(!proxyIndex.isValid() || proxyIndex.model() != this); + Q_ASSERT(!proxyIndex.isValid() || proxyIndex.model() == this); if (!proxyIndex.isValid() || !m_indexMap.contains(proxyIndex.row())) { return QModelIndex(); From dc0bb00c10ad370d9c80db157c334a47f5d7f25e Mon Sep 17 00:00:00 2001 From: pereslav Date: Tue, 21 Sep 2021 14:58:33 +0100 Subject: [PATCH 35/84] Added an error check in case of a requested spawnable is not networked Signed-off-by: pereslav --- .../Code/Source/NetworkEntity/NetworkEntityManager.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp index f4f744494b..a66b750266 100644 --- a/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkEntity/NetworkEntityManager.cpp @@ -477,6 +477,14 @@ namespace Multiplayer const AZ::Name netSpawnableName = AZ::Interface::Get()->GetSpawnableNameFromAssetId(netSpawnable.GetId()); + if (netSpawnableName.IsEmpty()) + { + AZ_Error("NetworkEntityManager", false, + "RequestNetSpawnableInstantiation: Requested spawnable %s doesn't exist in the NetworkSpawnableLibrary. Please make sure it is a network spawnable", + netSpawnable.GetHint().c_str()); + return nullptr; + } + // Pre-insertion callback allows us to do network-specific setup for the entities before they are added to the scene optionalArgs.m_preInsertionCallback = [netSpawnableName, rootTransform = transform] (AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableEntityContainerView entities) From 4e46cb0a01d1ec7105de797643228a1ce1bba41a Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Tue, 21 Sep 2021 11:14:47 -0500 Subject: [PATCH 36/84] Prevent crash in Landscape Canvas when creating a prefab from an open graph. Signed-off-by: Chris Galvan --- .../Code/Source/Editor/MainWindow.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp b/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp index 836eec682e..184f6eb886 100644 --- a/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp +++ b/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp @@ -2512,6 +2512,25 @@ namespace LandscapeCanvasEditor { // See comment above in OnPrefabInstancePropagationBegin m_prefabPropagationInProgress = false; + + // After prefab propagation is complete, the entity tied to one of our open + // graphs might have been deleted (e.g. if a prefab was created from that entity), + // so we need to close that graph to be safe. We need to close them in a separate + // iterator because the CloseEditor API will end up modifying m_dockWidgetsByEntity. + AZStd::vector dockWidgetsToDelete; + for (auto [entityId, dockWidgetId] : m_dockWidgetsByEntity) + { + AZ::Entity* entity = nullptr; + AZ::ComponentApplicationBus::BroadcastResult(entity, &AZ::ComponentApplicationRequests::FindEntity, entityId); + if (!entity) + { + dockWidgetsToDelete.push_back(dockWidgetId); + } + } + for (auto dockWidgetId : dockWidgetsToDelete) + { + CloseEditor(dockWidgetId); + } } void MainWindow::OnCryEditorEndCreate() From b8c78caa2ffc6370424ed56ce13f465e6e6efa12 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 21 Sep 2021 09:48:09 -0700 Subject: [PATCH 37/84] Remove nested FocusModeFramework namespace Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzToolsFramework/Application/ToolsApplication.cpp | 2 +- .../AzToolsFramework/AzToolsFrameworkModule.cpp | 2 +- .../AzToolsFramework/FocusMode/FocusModeInterface.h | 5 ++--- .../FocusMode/FocusModeSystemComponent.cpp | 4 ++-- .../AzToolsFramework/FocusMode/FocusModeSystemComponent.h | 4 ++-- .../AzToolsFramework/Prefab/PrefabFocusHandler.cpp | 4 ++-- .../AzToolsFramework/Prefab/PrefabFocusHandler.h | 8 ++------ 7 files changed, 12 insertions(+), 17 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp index 7238a22c51..91a916ae70 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Application/ToolsApplication.cpp @@ -249,7 +249,7 @@ namespace AzToolsFramework components.insert(components.end(), { azrtti_typeid(), azrtti_typeid(), - azrtti_typeid(), + azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), azrtti_typeid(), diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFrameworkModule.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFrameworkModule.cpp index a557754437..b68d086892 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFrameworkModule.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFrameworkModule.cpp @@ -70,7 +70,7 @@ namespace AzToolsFramework Components::EditorSelectionAccentSystemComponent::CreateDescriptor(), EditorEntityContextComponent::CreateDescriptor(), EditorEntityFixupComponent::CreateDescriptor(), - FocusModeFramework::FocusModeSystemComponent::CreateDescriptor(), + FocusModeSystemComponent::CreateDescriptor(), SliceMetadataEntityContextComponent::CreateDescriptor(), SliceRequestComponent::CreateDescriptor(), Prefab::PrefabSystemComponent::CreateDescriptor(), diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h index edd94fd6b0..70bb320a96 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h @@ -11,8 +11,7 @@ #include #include - -namespace AzToolsFramework::FocusModeFramework +namespace AzToolsFramework { /*! * FocusModeInterface @@ -37,4 +36,4 @@ namespace AzToolsFramework::FocusModeFramework virtual bool IsInFocusSubTree(AZ::EntityId entityId) = 0; }; -} // namespace AzToolsFramework::FocusModeFrameworkclassPrefabEditPublicInterface +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp index d82ce9ffeb..fcca452bf5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp @@ -13,7 +13,7 @@ #include #include -namespace AzToolsFramework::FocusModeFramework +namespace AzToolsFramework { FocusModeSystemComponent::~FocusModeSystemComponent() { @@ -90,4 +90,4 @@ namespace AzToolsFramework::FocusModeFramework return IsInFocusSubTree_helper(parentId, focusRootId); } -} // namespace AzToolsFramework::FocusModeFramework +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h index 54312a1e92..284515eeb7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h @@ -13,7 +13,7 @@ #include -namespace AzToolsFramework::FocusModeFramework +namespace AzToolsFramework { class FocusModeSystemComponent final : public AZ::Component @@ -46,4 +46,4 @@ namespace AzToolsFramework::FocusModeFramework AZ::EntityId m_focusRoot; }; -} // namespace AzToolsFramework::FocusModeFramework +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp index 2f64234352..63921cff21 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp @@ -14,7 +14,7 @@ namespace AzToolsFramework::Prefab { - FocusModeFramework::FocusModeInterface* PrefabFocusHandler::s_focusModeInterface = nullptr; + FocusModeInterface* PrefabFocusHandler::s_focusModeInterface = nullptr; InstanceEntityMapperInterface* PrefabFocusHandler::s_instanceEntityMapperInterface = nullptr; PrefabEditorEntityOwnershipInterface* PrefabFocusHandler::s_prefabEditorEntityOwnershipInterface = nullptr; @@ -25,7 +25,7 @@ namespace AzToolsFramework::Prefab void PrefabFocusHandler::Initialize() { - s_focusModeInterface = AZ::Interface::Get(); + s_focusModeInterface = AZ::Interface::Get(); AZ_Assert( s_focusModeInterface, "Prefab - PrefabFocusHandler - " diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h index bf8b6994d1..6a2ff2f62e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h @@ -15,13 +15,9 @@ #include namespace AzToolsFramework -{ - class PrefabEditorEntityOwnershipInterface; -} - -namespace AzToolsFramework::FocusModeFramework { class FocusModeInterface; + class PrefabEditorEntityOwnershipInterface; } namespace AzToolsFramework::Prefab @@ -48,7 +44,7 @@ namespace AzToolsFramework::Prefab InstanceOptionalReference m_focusedInstance; TemplateId m_focusedTemplateId; - static FocusModeFramework::FocusModeInterface* s_focusModeInterface; + static FocusModeInterface* s_focusModeInterface; static InstanceEntityMapperInterface* s_instanceEntityMapperInterface; static PrefabEditorEntityOwnershipInterface* s_prefabEditorEntityOwnershipInterface; }; From 2bba8fe9a3748c8a4c0e4e295a6a41784f740e13 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Tue, 21 Sep 2021 11:57:17 -0500 Subject: [PATCH 38/84] Clarified behavior in comment. Signed-off-by: Chris Galvan --- Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp b/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp index 184f6eb886..4574b938f6 100644 --- a/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp +++ b/Gems/LandscapeCanvas/Code/Source/Editor/MainWindow.cpp @@ -2514,9 +2514,10 @@ namespace LandscapeCanvasEditor m_prefabPropagationInProgress = false; // After prefab propagation is complete, the entity tied to one of our open - // graphs might have been deleted (e.g. if a prefab was created from that entity), - // so we need to close that graph to be safe. We need to close them in a separate - // iterator because the CloseEditor API will end up modifying m_dockWidgetsByEntity. + // graphs might have been deleted (e.g. if a prefab was created from that entity). + // Any open graphs tied to an entity that no longer exists will need to be closed. + // We need to close them in a separate iterator because the CloseEditor API will + // end up modifying m_dockWidgetsByEntity. AZStd::vector dockWidgetsToDelete; for (auto [entityId, dockWidgetId] : m_dockWidgetsByEntity) { From ed61f47b7fee292d97193531d4d01bed93ad0bae Mon Sep 17 00:00:00 2001 From: amzn-tommy Date: Tue, 21 Sep 2021 10:10:54 -0700 Subject: [PATCH 39/84] Cleaner initialization of heightMinMax plus a comment in StandardMultilayerPBR_Common.azsli to indicate that the .lua needs to be updated if the .azsli enum changes. Signed-off-by: amzn-tommy --- .../Assets/Materials/Types/StandardMultilayerPBR_Common.azsli | 1 + .../Materials/Types/StandardMultilayerPBR_Displacement.lua | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli index 2f84aaf5b2..4a66c52bf2 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Common.azsli @@ -104,6 +104,7 @@ option bool o_layer3_enabled; enum class DebugDrawMode { None, BlendMask, Displacement, FinalBlendWeights }; option DebugDrawMode o_debugDrawMode; +// If you modify this enum, you must update the BlendSourceUsesDisplacement function in StandardMultilayerPBR_Displacement.lua enum class LayerBlendSource { BlendMaskTexture, BlendMaskVertexColors, Displacement, Displacement_With_BlendMaskTexture, Displacement_With_BlendMaskVertexColors, Fallback }; option LayerBlendSource o_layerBlendSource; diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua index 2feeffd4f8..a032479d19 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_Displacement.lua @@ -88,7 +88,7 @@ end -- @return a table with two values {min,max}. Negative values are below the surface and positive values are above the surface. function CalcOverallHeightRange(context) - local heightMinMax = {nil, nil} + local heightMinMax = {} local function GetMergedHeightRange(heightMinMax, offset, factor) top = offset From 5a4476a0e426fbb45260cf0fab8c90f497642929 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 21 Sep 2021 10:26:41 -0700 Subject: [PATCH 40/84] Minor fixes to variable names and comments. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../FocusMode/FocusModeInterface.h | 14 +++---- .../FocusMode/FocusModeSystemComponent.cpp | 40 +++++++++---------- .../FocusMode/FocusModeSystemComponent.h | 9 +++-- .../Prefab/PrefabFocusHandler.cpp | 33 +++++---------- .../Prefab/PrefabFocusHandler.h | 9 +++-- .../Prefab/PrefabFocusInterface.h | 8 ++-- 6 files changed, 51 insertions(+), 62 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h index 70bb320a96..b2d008ca36 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h @@ -13,26 +13,26 @@ namespace AzToolsFramework { - /*! - * FocusModeInterface - * Interface to handle the Editor Focus Mode. - */ + //! FocusModeInterface + //! Interface to handle the Editor Focus Mode. class FocusModeInterface { public: AZ_RTTI(FocusModeInterface, "{437243B0-F86B-422F-B7B8-4A21CC000702}"); //! Sets the root entity the Editor should focus on. - //! The Editor will only allow the user to select entities belonging to the sub-tree that has root in the entityId provided. + //! The Editor will only allow the user to select entities that are descendants of the EntityId provided. //! @param entityId The entityId that will become the new focus root. virtual void SetFocusRoot(AZ::EntityId entityId) = 0; + //! Clears the Editor focus, allowing the user to select the whole level again. + virtual void ClearFocusRoot() = 0; + //! Returns the entity id of the root of the current Editor focus. - //! @return The id of the entity that is the root of the Editor focus. + //! @return The entity id of the root of the Editor focus, or an invalid entity id if no focus is set. virtual AZ::EntityId GetFocusRoot() = 0; //! Returns whether the entity id provided is part of the focused sub-tree. - //! @return True if entityId belongs to the focused sub-tree, false otherwise. virtual bool IsInFocusSubTree(AZ::EntityId entityId) = 0; }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp index fcca452bf5..e609aa2f48 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp @@ -15,6 +15,24 @@ namespace AzToolsFramework { + bool IsInFocusSubTree(AZ::EntityId entityId, AZ::EntityId focusRootId) + { + if (entityId == AZ::EntityId()) + { + return false; + } + + if (entityId == focusRootId) + { + return true; + } + + AZ::EntityId parentId; + AZ::TransformBus::EventResult(parentId, entityId, &AZ::TransformInterface::GetParentId); + + return IsInFocusSubTree(parentId, focusRootId); + } + FocusModeSystemComponent::~FocusModeSystemComponent() { AZ::Interface::Unregister(this); @@ -33,7 +51,7 @@ namespace AzToolsFramework { } - void FocusModeSystemComponent::Reflect(AZ::ReflectContext* /*context*/) + void FocusModeSystemComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context) { } @@ -69,25 +87,7 @@ namespace AzToolsFramework return true; } - return IsInFocusSubTree_helper(entityId, m_focusRoot); - } - - bool FocusModeSystemComponent::IsInFocusSubTree_helper(AZ::EntityId entityId, AZ::EntityId focusRootId) - { - if (entityId == AZ::EntityId()) - { - return false; - } - - if (entityId == focusRootId) - { - return true; - } - - AZ::EntityId parentId; - AZ::TransformBus::EventResult(parentId, entityId, &AZ::TransformInterface::GetParentId); - - return IsInFocusSubTree_helper(parentId, focusRootId); + return AzToolsFramework::IsInFocusSubTree(entityId, m_focusRoot); } } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h index 284515eeb7..2a2b1500ac 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h @@ -15,6 +15,9 @@ namespace AzToolsFramework { + bool IsInFocusSubTree(AZ::EntityId entityId, AZ::EntityId focusRootId); + + //! System Component to handle the Editor Focus Mode system class FocusModeSystemComponent final : public AZ::Component , private FocusModeInterface @@ -25,7 +28,7 @@ namespace AzToolsFramework FocusModeSystemComponent() = default; virtual ~FocusModeSystemComponent(); - // AZ::Component... + // AZ::Component overrides ... void Init() override; void Activate() override; void Deactivate() override; @@ -35,14 +38,12 @@ namespace AzToolsFramework static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); - // FocusModeInterface... + // FocusModeInterface overrides ... void SetFocusRoot(AZ::EntityId entityId) override; AZ::EntityId GetFocusRoot() override; bool IsInFocusSubTree(AZ::EntityId entityId) override; private: - static bool IsInFocusSubTree_helper(AZ::EntityId entityId, AZ::EntityId focusRootId); - AZ::EntityId m_focusRoot; }; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp index 63921cff21..bdd1b63afd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp @@ -14,10 +14,6 @@ namespace AzToolsFramework::Prefab { - FocusModeInterface* PrefabFocusHandler::s_focusModeInterface = nullptr; - InstanceEntityMapperInterface* PrefabFocusHandler::s_instanceEntityMapperInterface = nullptr; - PrefabEditorEntityOwnershipInterface* PrefabFocusHandler::s_prefabEditorEntityOwnershipInterface = nullptr; - PrefabFocusHandler::~PrefabFocusHandler() { AZ::Interface::Unregister(this); @@ -25,23 +21,23 @@ namespace AzToolsFramework::Prefab void PrefabFocusHandler::Initialize() { - s_focusModeInterface = AZ::Interface::Get(); + m_focusModeInterface = AZ::Interface::Get(); AZ_Assert( - s_focusModeInterface, + m_focusModeInterface, "Prefab - PrefabFocusHandler - " "Focus Mode Interface could not be found. " "Check that it is being correctly initialized."); - s_instanceEntityMapperInterface = AZ::Interface::Get(); + m_instanceEntityMapperInterface = AZ::Interface::Get(); AZ_Assert( - s_instanceEntityMapperInterface, + m_instanceEntityMapperInterface, "Prefab - PrefabFocusHandler - " "Instance Entity Mapper Interface could not be found. " "Check that it is being correctly initialized."); - s_prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); + m_prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); AZ_Assert( - s_prefabEditorEntityOwnershipInterface, + m_prefabEditorEntityOwnershipInterface, "Prefab - PrefabFocusHandler - " "Prefab Editor Entity Ownership Interface could not be found. " "Check that it is being correctly initialized."); @@ -51,16 +47,9 @@ namespace AzToolsFramework::Prefab PrefabFocusOperationResult PrefabFocusHandler::FocusOnOwningPrefab(AZ::EntityId entityId) { - InstanceOptionalReference focusedInstance; - - if (entityId == AZ::EntityId()) - { - focusedInstance = s_prefabEditorEntityOwnershipInterface->GetRootPrefabInstance(); - } - else - { - focusedInstance = s_instanceEntityMapperInterface->FindOwningInstance(entityId); - } + InstanceOptionalReference focusedInstance = (entityId == AZ::EntityId()) + ? m_prefabEditorEntityOwnershipInterface->GetRootPrefabInstance() + : m_instanceEntityMapperInterface->FindOwningInstance(entityId); if (!focusedInstance.has_value()) { @@ -70,7 +59,7 @@ namespace AzToolsFramework::Prefab m_focusedInstance = focusedInstance; m_focusedTemplateId = focusedInstance->get().GetTemplateId(); - s_focusModeInterface->SetFocusRoot(focusedInstance->get().GetContainerEntityId()); + m_focusModeInterface->SetFocusRoot(focusedInstance->get().GetContainerEntityId()); return AZ::Success(); } @@ -92,7 +81,7 @@ namespace AzToolsFramework::Prefab return false; } - InstanceOptionalReference instance = s_instanceEntityMapperInterface->FindOwningInstance(entityId); + InstanceOptionalReference instance = m_instanceEntityMapperInterface->FindOwningInstance(entityId); return instance.has_value() && (&instance->get() == &m_focusedInstance->get()); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h index 6a2ff2f62e..60038d9bb8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h @@ -24,6 +24,7 @@ namespace AzToolsFramework::Prefab { class InstanceEntityMapperInterface; + //! Handles Prefab Focus mode, determining which prefab file entity changes will target. class PrefabFocusHandler final : private PrefabFocusInterface { @@ -34,7 +35,7 @@ namespace AzToolsFramework::Prefab void Initialize(); - // PrefabFocusInterface... + // PrefabFocusInterface override ... PrefabFocusOperationResult FocusOnOwningPrefab(AZ::EntityId entityId) override; TemplateId GetFocusedPrefabTemplateId() override; InstanceOptionalReference GetFocusedPrefabInstance() override; @@ -44,9 +45,9 @@ namespace AzToolsFramework::Prefab InstanceOptionalReference m_focusedInstance; TemplateId m_focusedTemplateId; - static FocusModeInterface* s_focusModeInterface; - static InstanceEntityMapperInterface* s_instanceEntityMapperInterface; - static PrefabEditorEntityOwnershipInterface* s_prefabEditorEntityOwnershipInterface; + FocusModeInterface* m_focusModeInterface; + InstanceEntityMapperInterface* m_instanceEntityMapperInterface; + PrefabEditorEntityOwnershipInterface* m_prefabEditorEntityOwnershipInterface; }; } // namespace AzToolsFramework::Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h index 7b867ab8d2..c7f58f5de2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h @@ -16,17 +16,15 @@ namespace AzToolsFramework::Prefab { - typedef AZ::Outcome PrefabFocusOperationResult; + using PrefabFocusOperationResult = AZ::Outcome; - /*! - * PrefabFocusInterface - */ + //! Interface to handle operations related to the Prefab Focus system. class PrefabFocusInterface { public: AZ_RTTI(PrefabFocusInterface, "{F3CFA37B-5FD8-436A-9C30-60EB54E350E1}"); - //! Set the focused prefab instance to the owning instance of the entityId provided + //! Set the focused prefab instance to the owning instance of the entityId provided. //! @param entityId The entityId of the entity whose owning instance we want the prefab system to focus on. virtual PrefabFocusOperationResult FocusOnOwningPrefab(AZ::EntityId entityId) = 0; From 19747cb5c63ff64df05a12a4df3854c06b8ed49e Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Tue, 21 Sep 2021 10:31:42 -0700 Subject: [PATCH 41/84] Link to xcb as system-provided targets, instead of by direct library path (#4221) Signed-off-by: Chris Burel --- .../Platform/Linux/platform_linux.cmake | 13 +++------ cmake/3rdParty/FindX11.cmake | 29 +++++++++++++++++++ cmake/LYWrappers.cmake | 14 ++++++++- 3 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 cmake/3rdParty/FindX11.cmake diff --git a/Code/Framework/AzFramework/Platform/Linux/platform_linux.cmake b/Code/Framework/AzFramework/Platform/Linux/platform_linux.cmake index dc77ca0abf..5c8ca8392f 100644 --- a/Code/Framework/AzFramework/Platform/Linux/platform_linux.cmake +++ b/Code/Framework/AzFramework/Platform/Linux/platform_linux.cmake @@ -10,17 +10,12 @@ # Only 'xcb' and 'wayland' are recognized if (${PAL_TRAIT_LINUX_WINDOW_MANAGER} STREQUAL "xcb") - find_library(XCB_LIBRARY xcb) - find_library(XCB_XKB_LIBRARY xcb-xkb) - find_library(XKBCOMMON_LIBRARY xkbcommon) - find_library(XKBCOMMON_X11_LIBRARY xkbcommon-x11) - set(LY_BUILD_DEPENDENCIES PRIVATE - ${XCB_LIBRARY} - ${XKBCOMMON_LIBRARY} - ${XKBCOMMON_X11_LIBRARY} - ${XCB_XKB_LIBRARY} + 3rdParty::X11::xcb + 3rdParty::X11::xcb_xkb + 3rdParty::X11::xkbcommon + 3rdParty::X11::xkbcommon_X11 ) set(LY_COMPILE_DEFINITIONS PUBLIC PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB) diff --git a/cmake/3rdParty/FindX11.cmake b/cmake/3rdParty/FindX11.cmake new file mode 100644 index 0000000000..98cc57e40e --- /dev/null +++ b/cmake/3rdParty/FindX11.cmake @@ -0,0 +1,29 @@ +# +# 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 +# +# + +# Open a new scope so we can make changes to CMAKE_MODULE_PATH, and restore it +# when we're done +function(FindX11) + # O3DE's FindX11.cmake is a wrapper for the one that CMake provides. Remove + # our current directory from CMAKE_MODULE_PATH to avoid recursive includes + list(REMOVE_ITEM CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + + find_package(X11 COMPONENTS ${X11_FIND_COMPONENTS} QUIET) + + foreach(component IN LISTS X11_FIND_COMPONENTS) + ly_add_external_target( + SYSTEM + PACKAGE X11 + NAME ${component} + VERSION "" + BUILD_DEPENDENCIES + X11::${component} + ) + endforeach() +endfunction() +FindX11() diff --git a/cmake/LYWrappers.cmake b/cmake/LYWrappers.cmake index 8e5633b5e6..d388b03b75 100644 --- a/cmake/LYWrappers.cmake +++ b/cmake/LYWrappers.cmake @@ -477,11 +477,23 @@ function(ly_parse_third_party_dependencies ly_THIRD_PARTY_LIBRARIES) if(${dependency_namespace} STREQUAL "3rdParty") if (NOT TARGET ${dependency}) list(GET dependency_list 1 dependency_package) + list(LENGTH dependency_list dependency_list_length) ly_download_associated_package(${dependency_package}) - find_package(${dependency_package} REQUIRED MODULE) + if (dependency_list_length GREATER 2) + # There's an optional interface specified + list(GET dependency_list 2 component) + list(APPEND packages_with_components ${dependency_package}) + list(APPEND ${dependency_package}_components ${component}) + else() + find_package(${dependency_package} REQUIRED MODULE) + endif() endif() endif() endforeach() + + foreach(dependency IN LISTS packages_with_components) + find_package(${dependency} REQUIRED MODULE COMPONENTS ${${dependency}_components}) + endforeach() endfunction() #! ly_configure_target_platform_properties: Configures any platform specific properties on target From df10b56f2ab4ae0d6289aefb160c7315d9f1aee8 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 21 Sep 2021 10:47:02 -0700 Subject: [PATCH 42/84] ClearFocusRoot implementation Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp | 5 +++++ .../AzToolsFramework/FocusMode/FocusModeSystemComponent.h | 1 + 2 files changed, 6 insertions(+) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp index e609aa2f48..6d5e672df9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp @@ -75,6 +75,11 @@ namespace AzToolsFramework // TODO - If m_focusRoot != AZ::EntityId(), activate focus mode via ViewportEditorModeTrackerInterface; else, deactivate focus mode } + void FocusModeSystemComponent::ClearFocusRoot() + { + SetFocusRoot(AZ::EntityId()); + } + AZ::EntityId FocusModeSystemComponent::GetFocusRoot() { return m_focusRoot; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h index 2a2b1500ac..32386abf67 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h @@ -40,6 +40,7 @@ namespace AzToolsFramework // FocusModeInterface overrides ... void SetFocusRoot(AZ::EntityId entityId) override; + void ClearFocusRoot() override; AZ::EntityId GetFocusRoot() override; bool IsInFocusSubTree(AZ::EntityId entityId) override; From 612ba040a6f20f498ae14841f2959401c205f403 Mon Sep 17 00:00:00 2001 From: AMZN-tpeng <82184807+AMZN-tpeng@users.noreply.github.com> Date: Tue, 21 Sep 2021 10:54:50 -0700 Subject: [PATCH 43/84] =?UTF-8?q?[ATOM][RHI][Vulkan]=20-=20add=20different?= =?UTF-8?q?=20constant=20alignment=20values=20for=20pla=E2=80=A6=20(#4098)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [ATOM][RHI][Vulkan] - add different constant alignment values for platforms. Signed-off-by: Peng * More explanation of the limitation define. Signed-off-by: Peng --- .../Code/AZSL/Platform/Android/Vulkan/AzslcHeader.azsli | 9 +++++++-- .../Code/AZSL/Platform/Windows/Vulkan/AzslcHeader.azsli | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/AZSL/Platform/Android/Vulkan/AzslcHeader.azsli b/Gems/Atom/Asset/Shader/Code/AZSL/Platform/Android/Vulkan/AzslcHeader.azsli index 54c9430f87..0cab4d7a38 100644 --- a/Gems/Atom/Asset/Shader/Code/AZSL/Platform/Android/Vulkan/AzslcHeader.azsli +++ b/Gems/Atom/Asset/Shader/Code/AZSL/Platform/Android/Vulkan/AzslcHeader.azsli @@ -16,6 +16,11 @@ static const float4 s_AzslDebugColor = float4(165.0 / 255.0, 30.0 / 255.0, 36.0 / 255.0, 1); -// Uniform limitation need to be taken into consideration for mobile devices +// Uniform limitation need to be taken into consideration for mobile devices. This would help alleviate device lost errors if the constant buffer +// size overshoots the device's memory constraints. An example is a large number of constant buffers associated with mesh instances that would result in device lost, +// but otherwise OK on PC. We can separate out the number of instances for the different platforms with this define. // [ATOM-14949] -#define AZ_TRAIT_CONSTANT_BUFFER_LIMITATIONS 1 \ No newline at end of file +#define AZ_TRAIT_CONSTANT_BUFFER_LIMITATIONS 1 + +// Different constant buffer alignment on platforms +#define AZ_TRAIT_CONSTANT_BUFFER_ALIGNMENT 16 diff --git a/Gems/Atom/Asset/Shader/Code/AZSL/Platform/Windows/Vulkan/AzslcHeader.azsli b/Gems/Atom/Asset/Shader/Code/AZSL/Platform/Windows/Vulkan/AzslcHeader.azsli index b620c0d696..58395ef6a4 100644 --- a/Gems/Atom/Asset/Shader/Code/AZSL/Platform/Windows/Vulkan/AzslcHeader.azsli +++ b/Gems/Atom/Asset/Shader/Code/AZSL/Platform/Windows/Vulkan/AzslcHeader.azsli @@ -12,3 +12,7 @@ */ static const float4 s_AzslDebugColor = float4(165.0 / 255.0, 30.0 / 255.0, 36.0 / 255.0, 1); + + +// Different constant buffer alignment on platforms +#define AZ_TRAIT_CONSTANT_BUFFER_ALIGNMENT 128 \ No newline at end of file From fa163f49b996161f60bb490c52937adf9ca186e6 Mon Sep 17 00:00:00 2001 From: jromnoa <80134229+jromnoa@users.noreply.github.com> Date: Tue, 21 Sep 2021 10:55:48 -0700 Subject: [PATCH 44/84] Re-structure Atom test folders in AutomatedTesting. (#4206) * move shader asset builder test into test_Atom_MainSuite_Optimized.py, update CMakeLists.txt, and move all imports inside the test class for hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges.py Signed-off-by: jromnoa * re-organize the Atom automated test structure to match the new parallel + batched test structures Signed-off-by: jromnoa * fix CMakeLists.txt registrations for test files Signed-off-by: jromnoa --- .../{atom_renderer => Atom}/CMakeLists.txt | 16 +++++++-------- .../TestSuite_Main.py} | 4 ++-- .../TestSuite_Main_GPU.py} | 4 +--- .../TestSuite_Main_Optimized.py} | 20 +++++++++---------- .../TestSuite_Sandbox.py} | 0 .../{atom_renderer => Atom}/__init__.py | 0 .../atom_utils/__init__.py | 0 .../atom_utils/atom_component_helper.py | 0 .../atom_utils/atom_constants.py | 0 .../atom_utils/benchmark_utils.py | 0 .../atom_utils/material_editor_utils.py | 0 .../atom_utils/screenshot_utils.py | 0 .../golden_images/AreaLight_1.ppm | 0 .../golden_images/AreaLight_2.ppm | 0 .../golden_images/AreaLight_3.ppm | 0 .../golden_images/AreaLight_4.ppm | 0 .../golden_images/AreaLight_5.ppm | 0 .../golden_images/AtomBasicLevelSetup.ppm | 0 .../golden_images/SpotLight_1.ppm | 0 .../golden_images/SpotLight_2.ppm | 0 .../golden_images/SpotLight_3.ppm | 0 .../golden_images/SpotLight_4.ppm | 0 .../golden_images/SpotLight_5.ppm | 0 .../golden_images/SpotLight_6.ppm | 0 .../DependencyValidation.azsl.txt | 0 .../DependencyValidation.shader.txt | 4 ++-- .../ShaderAssetBuilder/Test1Color.azsli.txt | 0 .../ShaderAssetBuilder/Test2Color.azsli.txt | 2 +- .../ShaderAssetBuilder/Test3Color.azsli.txt | 2 +- .../tests}/__init__.py | 0 ...ydra_AtomEditorComponents_AddedToEntity.py | 0 .../hydra_AtomEditorComponents_DecalAdded.py | 0 ..._AtomEditorComponents_DepthOfFieldAdded.py | 0 ...mEditorComponents_DirectionalLightAdded.py | 0 ...AtomEditorComponents_DisplayMapperAdded.py | 0 ...omEditorComponents_ExposureControlAdded.py | 0 ...EditorComponents_GlobalSkylightIBLAdded.py | 0 .../hydra_AtomEditorComponents_LightAdded.py | 0 ...dra_AtomEditorComponents_LightComponent.py | 2 +- ...a_AtomEditorComponents_PhysicalSkyAdded.py | 0 ...ponents_PostFXRadiusWeightModifierAdded.py | 0 .../hydra_AtomMaterialEditor_BasicTests.py | 2 +- ...GPUTest_AtomFeatureIntegrationBenchmark.py | 2 +- .../tests}/hydra_GPUTest_BasicLevelSetup.py | 2 +- .../tests}/hydra_GPUTest_LightComponent.py | 2 +- ...pilesShaderAsChainOfDependenciesChanges.py | 0 .../Gem/PythonTests/CMakeLists.txt | 2 +- 47 files changed, 31 insertions(+), 33 deletions(-) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/CMakeLists.txt (75%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/test_Atom_MainSuite.py => Atom/TestSuite_Main.py} (99%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/test_Atom_GPUTests.py => Atom/TestSuite_Main_GPU.py} (98%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/test_Atom_MainSuite_Optimized.py => Atom/TestSuite_Main_Optimized.py} (56%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/test_Atom_SandboxSuite.py => Atom/TestSuite_Sandbox.py} (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/__init__.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/atom_utils/__init__.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/atom_utils/atom_component_helper.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/atom_utils/atom_constants.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/atom_utils/benchmark_utils.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/atom_utils/material_editor_utils.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/atom_utils/screenshot_utils.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/golden_images/AreaLight_1.ppm (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/golden_images/AreaLight_2.ppm (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/golden_images/AreaLight_3.ppm (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/golden_images/AreaLight_4.ppm (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/golden_images/AreaLight_5.ppm (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/golden_images/AtomBasicLevelSetup.ppm (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/golden_images/SpotLight_1.ppm (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/golden_images/SpotLight_2.ppm (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/golden_images/SpotLight_3.ppm (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/golden_images/SpotLight_4.ppm (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/golden_images/SpotLight_5.ppm (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer => Atom}/golden_images/SpotLight_6.ppm (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/TestAssets/ShaderAssetBuilder/DependencyValidation.azsl.txt (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/TestAssets/ShaderAssetBuilder/DependencyValidation.shader.txt (93%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/TestAssets/ShaderAssetBuilder/Test1Color.azsli.txt (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/TestAssets/ShaderAssetBuilder/Test2Color.azsli.txt (93%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/TestAssets/ShaderAssetBuilder/Test3Color.azsli.txt (92%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/__init__.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/hydra_AtomEditorComponents_AddedToEntity.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/hydra_AtomEditorComponents_DecalAdded.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/hydra_AtomEditorComponents_DepthOfFieldAdded.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/hydra_AtomEditorComponents_DirectionalLightAdded.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/hydra_AtomEditorComponents_DisplayMapperAdded.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/hydra_AtomEditorComponents_ExposureControlAdded.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/hydra_AtomEditorComponents_GlobalSkylightIBLAdded.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/hydra_AtomEditorComponents_LightAdded.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/hydra_AtomEditorComponents_LightComponent.py (99%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/hydra_AtomEditorComponents_PhysicalSkyAdded.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/hydra_AtomEditorComponents_PostFXRadiusWeightModifierAdded.py (100%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/hydra_AtomMaterialEditor_BasicTests.py (99%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py (98%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/hydra_GPUTest_BasicLevelSetup.py (99%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/hydra_GPUTest_LightComponent.py (99%) rename AutomatedTesting/Gem/PythonTests/{atom_renderer/atom_hydra_scripts => Atom/tests}/hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges.py (100%) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/Atom/CMakeLists.txt similarity index 75% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt rename to AutomatedTesting/Gem/PythonTests/Atom/CMakeLists.txt index 117c710824..02aaa42597 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/Atom/CMakeLists.txt @@ -13,9 +13,9 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedTesting IN_LIST LY_PROJECTS) ly_add_pytest( - NAME AutomatedTesting::AtomRenderer_HydraTests_Main + NAME AutomatedTesting::Atom_TestSuite_Main TEST_SUITE main - PATH ${CMAKE_CURRENT_LIST_DIR}/test_Atom_MainSuite.py + PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Main.py TEST_SERIAL TIMEOUT 600 RUNTIME_DEPENDENCIES @@ -26,9 +26,9 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedT Atom ) ly_add_pytest( - NAME AutomatedTesting::AtomRenderer_HydraTests_MainOptimized + NAME AutomatedTesting::Atom_TestSuite_Main_Optimized TEST_SUITE main - PATH ${CMAKE_CURRENT_LIST_DIR}/test_Atom_MainSuite_Optimized.py + PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Main_Optimized.py TEST_SERIAL TIMEOUT 600 RUNTIME_DEPENDENCIES @@ -39,9 +39,9 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedT Atom ) ly_add_pytest( - NAME AutomatedTesting::AtomRenderer_HydraTests_Sandbox + NAME AutomatedTesting::Atom_TestSuite_Sandbox TEST_SUITE sandbox - PATH ${CMAKE_CURRENT_LIST_DIR}/test_Atom_SandboxSuite.py + PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Sandbox.py TEST_SERIAL TIMEOUT 400 RUNTIME_DEPENDENCIES @@ -52,12 +52,12 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedT Atom ) ly_add_pytest( - NAME AutomatedTesting::AtomRenderer_HydraTests_GPUTests + NAME AutomatedTesting::Atom_TestSuite_Main_GPU TEST_SUITE main TEST_REQUIRES gpu TEST_SERIAL TIMEOUT 1200 - PATH ${CMAKE_CURRENT_LIST_DIR}/test_Atom_GPUTests.py + PATH ${CMAKE_CURRENT_LIST_DIR}/TestSuite_Main_GPU.py RUNTIME_DEPENDENCIES AssetProcessor AutomatedTesting.Assets diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py similarity index 99% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py rename to AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py index 16e281e494..0bc66f2614 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py @@ -13,10 +13,10 @@ import pytest import ly_test_tools.environment.file_system as file_system import editor_python_test_tools.hydra_test_utils as hydra -from atom_renderer.atom_utils.atom_constants import LIGHT_TYPES +from Atom.atom_utils.atom_constants import LIGHT_TYPES logger = logging.getLogger(__name__) -TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "atom_hydra_scripts") +TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "tests") @pytest.mark.parametrize("project", ["AutomatedTesting"]) diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py similarity index 98% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py rename to AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py index e62ab5e5dc..249b9c7096 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_GPUTests.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py @@ -3,8 +3,6 @@ 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 - -Tests that require a GPU in order to run. """ import datetime @@ -22,7 +20,7 @@ import editor_python_test_tools.hydra_test_utils as hydra logger = logging.getLogger(__name__) DEFAULT_SUBFOLDER_PATH = 'user/PythonTests/Automated/Screenshots' -TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "atom_hydra_scripts") +TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "tests") def golden_images_directory(): diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite_Optimized.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py similarity index 56% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite_Optimized.py rename to AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py index e206e77d60..47b2204d56 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_MainSuite_Optimized.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py @@ -15,32 +15,32 @@ from ly_test_tools.o3de.editor_test import EditorSharedTest, EditorTestSuite class TestAutomation(EditorTestSuite): class AtomEditorComponents_DecalAdded(EditorSharedTest): - from atom_renderer.atom_hydra_scripts import hydra_AtomEditorComponents_DecalAdded as test_module + from Atom.tests import hydra_AtomEditorComponents_DecalAdded as test_module class AtomEditorComponents_DepthOfFieldAdded(EditorSharedTest): - from atom_renderer.atom_hydra_scripts import hydra_AtomEditorComponents_DepthOfFieldAdded as test_module + from Atom.tests import hydra_AtomEditorComponents_DepthOfFieldAdded as test_module class AtomEditorComponents_DirectionalLightAdded(EditorSharedTest): - from atom_renderer.atom_hydra_scripts import hydra_AtomEditorComponents_DirectionalLightAdded as test_module + from Atom.tests import hydra_AtomEditorComponents_DirectionalLightAdded as test_module class AtomEditorComponents_ExposureControlAdded(EditorSharedTest): - from atom_renderer.atom_hydra_scripts import hydra_AtomEditorComponents_ExposureControlAdded as test_module + from Atom.tests import hydra_AtomEditorComponents_ExposureControlAdded as test_module class AtomEditorComponents_GlobalSkylightIBLAdded(EditorSharedTest): - from atom_renderer.atom_hydra_scripts import hydra_AtomEditorComponents_GlobalSkylightIBLAdded as test_module + from Atom.tests import hydra_AtomEditorComponents_GlobalSkylightIBLAdded as test_module class AtomEditorComponents_PhysicalSkyAdded(EditorSharedTest): - from atom_renderer.atom_hydra_scripts import hydra_AtomEditorComponents_PhysicalSkyAdded as test_module + from Atom.tests import hydra_AtomEditorComponents_PhysicalSkyAdded as test_module class AtomEditorComponents_PostFXRadiusWeightModifierAdded(EditorSharedTest): - from atom_renderer.atom_hydra_scripts import ( + from Atom.tests import ( hydra_AtomEditorComponents_PostFXRadiusWeightModifierAdded as test_module) class AtomEditorComponents_LightAdded(EditorSharedTest): - from atom_renderer.atom_hydra_scripts import hydra_AtomEditorComponents_LightAdded as test_module + from Atom.tests import hydra_AtomEditorComponents_LightAdded as test_module class AtomEditorComponents_DisplayMapperAdded(EditorSharedTest): - from atom_renderer.atom_hydra_scripts import hydra_AtomEditorComponents_DisplayMapperAdded as test_module + from Atom.tests import hydra_AtomEditorComponents_DisplayMapperAdded as test_module class ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges(EditorSharedTest): - from .atom_hydra_scripts import hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges as test_module + from Atom.tests import hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges as test_module diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_SandboxSuite.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/test_Atom_SandboxSuite.py rename to AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/__init__.py b/AutomatedTesting/Gem/PythonTests/Atom/__init__.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/__init__.py rename to AutomatedTesting/Gem/PythonTests/Atom/__init__.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/__init__.py b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/__init__.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/__init__.py rename to AutomatedTesting/Gem/PythonTests/Atom/atom_utils/__init__.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_component_helper.py b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_component_helper.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_component_helper.py rename to AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_component_helper.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_constants.py b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_constants.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/atom_constants.py rename to AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_constants.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/benchmark_utils.py b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/benchmark_utils.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/benchmark_utils.py rename to AutomatedTesting/Gem/PythonTests/Atom/atom_utils/benchmark_utils.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/material_editor_utils.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/material_editor_utils.py rename to AutomatedTesting/Gem/PythonTests/Atom/atom_utils/material_editor_utils.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/screenshot_utils.py b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/screenshot_utils.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_utils/screenshot_utils.py rename to AutomatedTesting/Gem/PythonTests/Atom/atom_utils/screenshot_utils.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_1.ppm b/AutomatedTesting/Gem/PythonTests/Atom/golden_images/AreaLight_1.ppm similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_1.ppm rename to AutomatedTesting/Gem/PythonTests/Atom/golden_images/AreaLight_1.ppm diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_2.ppm b/AutomatedTesting/Gem/PythonTests/Atom/golden_images/AreaLight_2.ppm similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_2.ppm rename to AutomatedTesting/Gem/PythonTests/Atom/golden_images/AreaLight_2.ppm diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_3.ppm b/AutomatedTesting/Gem/PythonTests/Atom/golden_images/AreaLight_3.ppm similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_3.ppm rename to AutomatedTesting/Gem/PythonTests/Atom/golden_images/AreaLight_3.ppm diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_4.ppm b/AutomatedTesting/Gem/PythonTests/Atom/golden_images/AreaLight_4.ppm similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_4.ppm rename to AutomatedTesting/Gem/PythonTests/Atom/golden_images/AreaLight_4.ppm diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_5.ppm b/AutomatedTesting/Gem/PythonTests/Atom/golden_images/AreaLight_5.ppm similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AreaLight_5.ppm rename to AutomatedTesting/Gem/PythonTests/Atom/golden_images/AreaLight_5.ppm diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AtomBasicLevelSetup.ppm b/AutomatedTesting/Gem/PythonTests/Atom/golden_images/AtomBasicLevelSetup.ppm similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/AtomBasicLevelSetup.ppm rename to AutomatedTesting/Gem/PythonTests/Atom/golden_images/AtomBasicLevelSetup.ppm diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_1.ppm b/AutomatedTesting/Gem/PythonTests/Atom/golden_images/SpotLight_1.ppm similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_1.ppm rename to AutomatedTesting/Gem/PythonTests/Atom/golden_images/SpotLight_1.ppm diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_2.ppm b/AutomatedTesting/Gem/PythonTests/Atom/golden_images/SpotLight_2.ppm similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_2.ppm rename to AutomatedTesting/Gem/PythonTests/Atom/golden_images/SpotLight_2.ppm diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_3.ppm b/AutomatedTesting/Gem/PythonTests/Atom/golden_images/SpotLight_3.ppm similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_3.ppm rename to AutomatedTesting/Gem/PythonTests/Atom/golden_images/SpotLight_3.ppm diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_4.ppm b/AutomatedTesting/Gem/PythonTests/Atom/golden_images/SpotLight_4.ppm similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_4.ppm rename to AutomatedTesting/Gem/PythonTests/Atom/golden_images/SpotLight_4.ppm diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_5.ppm b/AutomatedTesting/Gem/PythonTests/Atom/golden_images/SpotLight_5.ppm similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_5.ppm rename to AutomatedTesting/Gem/PythonTests/Atom/golden_images/SpotLight_5.ppm diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_6.ppm b/AutomatedTesting/Gem/PythonTests/Atom/golden_images/SpotLight_6.ppm similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/golden_images/SpotLight_6.ppm rename to AutomatedTesting/Gem/PythonTests/Atom/golden_images/SpotLight_6.ppm diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/DependencyValidation.azsl.txt b/AutomatedTesting/Gem/PythonTests/Atom/tests/TestAssets/ShaderAssetBuilder/DependencyValidation.azsl.txt similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/DependencyValidation.azsl.txt rename to AutomatedTesting/Gem/PythonTests/Atom/tests/TestAssets/ShaderAssetBuilder/DependencyValidation.azsl.txt diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/DependencyValidation.shader.txt b/AutomatedTesting/Gem/PythonTests/Atom/tests/TestAssets/ShaderAssetBuilder/DependencyValidation.shader.txt similarity index 93% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/DependencyValidation.shader.txt rename to AutomatedTesting/Gem/PythonTests/Atom/tests/TestAssets/ShaderAssetBuilder/DependencyValidation.shader.txt index b0eac1783e..4439ec0352 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/DependencyValidation.shader.txt +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/TestAssets/ShaderAssetBuilder/DependencyValidation.shader.txt @@ -2,7 +2,7 @@ { "Source" : "DependencyValidation.azsl", - "DepthStencilState" : { + "DepthStencilState" : { "Depth" : { "Enable" : false, "CompareFunc" : "GreaterEqual" } }, @@ -22,5 +22,5 @@ } ] } - + } diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test1Color.azsli.txt b/AutomatedTesting/Gem/PythonTests/Atom/tests/TestAssets/ShaderAssetBuilder/Test1Color.azsli.txt similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test1Color.azsli.txt rename to AutomatedTesting/Gem/PythonTests/Atom/tests/TestAssets/ShaderAssetBuilder/Test1Color.azsli.txt diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test2Color.azsli.txt b/AutomatedTesting/Gem/PythonTests/Atom/tests/TestAssets/ShaderAssetBuilder/Test2Color.azsli.txt similarity index 93% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test2Color.azsli.txt rename to AutomatedTesting/Gem/PythonTests/Atom/tests/TestAssets/ShaderAssetBuilder/Test2Color.azsli.txt index 2ef946b947..565493a0ab 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test2Color.azsli.txt +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/TestAssets/ShaderAssetBuilder/Test2Color.azsli.txt @@ -12,5 +12,5 @@ float4 GetTest2Color(float4 color) { - return color * 0.5; + return color * 0.5; } diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test3Color.azsli.txt b/AutomatedTesting/Gem/PythonTests/Atom/tests/TestAssets/ShaderAssetBuilder/Test3Color.azsli.txt similarity index 92% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test3Color.azsli.txt rename to AutomatedTesting/Gem/PythonTests/Atom/tests/TestAssets/ShaderAssetBuilder/Test3Color.azsli.txt index 73b0cca434..7c1ff2be42 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/TestAssets/ShaderAssetBuilder/Test3Color.azsli.txt +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/TestAssets/ShaderAssetBuilder/Test3Color.azsli.txt @@ -12,5 +12,5 @@ float4 GetTest3Color(float4 color) { - return color * 0.13; + return color * 0.13; } diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/__init__.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/__init__.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/__init__.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/__init__.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_AddedToEntity.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_AddedToEntity.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_AddedToEntity.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DecalAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DecalAdded.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DecalAdded.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DecalAdded.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DepthOfFieldAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DepthOfFieldAdded.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DepthOfFieldAdded.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DepthOfFieldAdded.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DirectionalLightAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DirectionalLightAdded.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DirectionalLightAdded.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DirectionalLightAdded.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DisplayMapperAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DisplayMapperAdded.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_DisplayMapperAdded.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DisplayMapperAdded.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_ExposureControlAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_ExposureControlAdded.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_ExposureControlAdded.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_ExposureControlAdded.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_GlobalSkylightIBLAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_GlobalSkylightIBLAdded.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_GlobalSkylightIBLAdded.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_GlobalSkylightIBLAdded.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_LightAdded.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightAdded.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_LightAdded.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_LightComponent.py similarity index 99% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_LightComponent.py index 6da922bd9f..751f425916 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_LightComponent.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_LightComponent.py @@ -17,7 +17,7 @@ import azlmbr.legacy.general as general sys.path.append(os.path.join(azlmbr.paths.devassets, "Gem", "PythonTests")) import editor_python_test_tools.hydra_editor_utils as hydra -from atom_renderer.atom_utils.atom_constants import LIGHT_TYPES +from Atom.atom_utils.atom_constants import LIGHT_TYPES LIGHT_TYPE_PROPERTY = 'Controller|Configuration|Light type' SPHERE_AND_SPOT_DISK_LIGHT_PROPERTIES = [ diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_PhysicalSkyAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PhysicalSkyAdded.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_PhysicalSkyAdded.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PhysicalSkyAdded.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_PostFXRadiusWeightModifierAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFXRadiusWeightModifierAdded.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomEditorComponents_PostFXRadiusWeightModifierAdded.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFXRadiusWeightModifierAdded.py diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomMaterialEditor_BasicTests.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomMaterialEditor_BasicTests.py similarity index 99% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomMaterialEditor_BasicTests.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomMaterialEditor_BasicTests.py index 1e250e5b9f..88a1ef4c7b 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_AtomMaterialEditor_BasicTests.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomMaterialEditor_BasicTests.py @@ -18,7 +18,7 @@ import azlmbr.paths sys.path.append(os.path.join(azlmbr.paths.devassets, "Gem", "PythonTests")) -import atom_renderer.atom_utils.material_editor_utils as material_editor +import Atom.atom_utils.material_editor_utils as material_editor NEW_MATERIAL = "test_material.material" NEW_MATERIAL_1 = "test_material_1.material" diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py similarity index 98% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py index 7e7087fb42..4f7edeba75 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py @@ -14,7 +14,7 @@ sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "P import editor_python_test_tools.hydra_editor_utils as hydra from editor_python_test_tools.editor_test_helper import EditorTestHelper -from atom_renderer.atom_utils.benchmark_utils import BenchmarkHelper +from Atom.atom_utils.benchmark_utils import BenchmarkHelper SCREEN_WIDTH = 1280 SCREEN_HEIGHT = 720 diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_BasicLevelSetup.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_BasicLevelSetup.py similarity index 99% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_BasicLevelSetup.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_BasicLevelSetup.py index 24ebbdff63..62a122a723 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_BasicLevelSetup.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_BasicLevelSetup.py @@ -21,7 +21,7 @@ sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "P import editor_python_test_tools.hydra_editor_utils as hydra from editor_python_test_tools.editor_test_helper import EditorTestHelper -from atom_renderer.atom_utils.screenshot_utils import ScreenshotHelper +from Atom.atom_utils.screenshot_utils import ScreenshotHelper SCREEN_WIDTH = 1280 SCREEN_HEIGHT = 720 diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_LightComponent.py similarity index 99% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_LightComponent.py index 5c019dc3f3..4a3ae8c85d 100644 --- a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_GPUTest_LightComponent.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_LightComponent.py @@ -17,7 +17,7 @@ import azlmbr.legacy.general as general sys.path.append(os.path.join(azlmbr.paths.devroot, "AutomatedTesting", "Gem", "PythonTests")) import editor_python_test_tools.hydra_editor_utils as hydra -from atom_renderer.atom_utils import atom_component_helper, atom_constants, screenshot_utils +from Atom.atom_utils import atom_component_helper, atom_constants, screenshot_utils from editor_python_test_tools.editor_test_helper import EditorTestHelper helper = EditorTestHelper(log_prefix="Atom_EditorTestHelper") diff --git a/AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges.py similarity index 100% rename from AutomatedTesting/Gem/PythonTests/atom_renderer/atom_hydra_scripts/hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges.py rename to AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges.py diff --git a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt index 7fd3b3a241..466a4b1679 100644 --- a/AutomatedTesting/Gem/PythonTests/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/CMakeLists.txt @@ -18,7 +18,7 @@ include(${pal_dir}/PAL_traits_${PAL_PLATFORM_NAME_LOWERCASE}.cmake) add_subdirectory(assetpipeline) ## Atom Renderer ## -add_subdirectory(atom_renderer) +add_subdirectory(Atom) ## Physics ## add_subdirectory(Physics) From b78e41f5a8332399af22a69f8311b6f895eed331 Mon Sep 17 00:00:00 2001 From: Robin Date: Tue, 21 Sep 2021 12:17:33 -0700 Subject: [PATCH 45/84] Refactor use of OrderOnce for materials to limit to materialtype dependencies only. Signed-off-by: Robin --- .../RPI.Builders/Material/MaterialBuilder.cpp | 53 +++++++++++-------- .../Model/MaterialAssetBuilderComponent.cpp | 4 +- 2 files changed, 34 insertions(+), 23 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index 099fdf33dd..e1fed6a877 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -9,7 +9,6 @@ #include "MaterialBuilder.h" #include #include -#include #include #include #include @@ -31,6 +30,7 @@ #include #include #include +#include namespace AZ { @@ -47,7 +47,7 @@ namespace AZ { AssetBuilderSDK::AssetBuilderDesc materialBuilderDescriptor; materialBuilderDescriptor.m_name = JobKey; - materialBuilderDescriptor.m_version = 107; // ATOM-14918 + materialBuilderDescriptor.m_version = 108; // ATOM-14918 materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.material", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.materialtype", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_busId = azrtti_typeid(); @@ -67,21 +67,19 @@ namespace AZ //! Adds all relevant dependencies for a referenced source file, considering that the path might be relative to the original file location or a full asset path. //! This will usually include multiple source dependencies and a single job dependency, but will include only source dependencies if the file is not found. //! Note the AssetBuilderSDK::JobDependency::m_platformIdentifier will not be set by this function. The calling code must set this value before passing back - //! to the AssetBuilderSDK::CreateJobsResponse. - void AddPossibleDependencies( - AZStd::string_view currentFilePath, AZStd::string_view referencedParentPath, - AZStd::vector& sourceFileDependencies, - const char* jobKey, AZStd::vector& jobDependencies) + //! to the AssetBuilderSDK::CreateJobsResponse. If isOrderedOnceForMaterialTypes is true and the dependency is a materialtype file, the job dependency type + //! will be set to JobDependencyType::OrderOnce. + void AddPossibleDependencies(AZStd::string_view currentFilePath, + AZStd::string_view referencedParentPath, + const char* jobKey, + AZStd::vector& jobDependencies, + bool isOrderedOnceForMaterialTypes = false) { bool dependencyFileFound = false; AZStd::vector possibleDependencies = RPI::AssetUtils::GetPossibleDepenencyPaths(currentFilePath, referencedParentPath); for (auto& file : possibleDependencies) { - AssetBuilderSDK::SourceFileDependency sourceFileDependency; - sourceFileDependency.m_sourceFileDependencyPath = file; - sourceFileDependencies.push_back(sourceFileDependency); - // The first path found is the highest priority, and will have a job dependency, as this is the one // the builder will actually use if (!dependencyFileFound) @@ -96,9 +94,8 @@ namespace AZ jobDependency.m_jobKey = jobKey; jobDependency.m_sourceFile.m_sourceFileDependencyPath = file; - bool includeMaterialPropertyNames = true; - RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames); - jobDependency.m_type = includeMaterialPropertyNames ? AssetBuilderSDK::JobDependencyType::OrderOnce : AssetBuilderSDK::JobDependencyType::Order; + const bool isMaterialTypeFile = AzFramework::StringFunc::Path::IsExtension(file.c_str(), MaterialTypeSourceData::Extension); + jobDependency.m_type = (isMaterialTypeFile && isOrderedOnceForMaterialTypes) ? AssetBuilderSDK::JobDependencyType::OrderOnce : AssetBuilderSDK::JobDependencyType::Order; jobDependencies.push_back(jobDependency); } @@ -178,8 +175,9 @@ namespace AZ for (auto& shader : materialTypeSourceData.GetValue().m_shaderCollection) { - AddPossibleDependencies(request.m_sourceFile, shader.m_shaderFilePath, - response.m_sourceFileDependencyList, "Shader Asset", + AddPossibleDependencies(request.m_sourceFile, + shader.m_shaderFilePath, + "Shader Asset", outputJobDescriptor.m_jobDependencyList); } @@ -189,9 +187,10 @@ namespace AZ for (const MaterialFunctorSourceData::AssetDependency& dependency : dependencies) { - AddPossibleDependencies(request.m_sourceFile, dependency.m_sourceFilePath, - response.m_sourceFileDependencyList, - dependency.m_jobKey.c_str(), outputJobDescriptor.m_jobDependencyList); + AddPossibleDependencies(request.m_sourceFile, + dependency.m_sourceFilePath, + dependency.m_jobKey.c_str(), + outputJobDescriptor.m_jobDependencyList); } } } @@ -224,11 +223,21 @@ namespace AZ parentMaterialPath = materialTypePath; } + // If includeMaterialPropertyNames is true, then we need materials to depend on materialtype only once in order to get + // the property names. After the initial processing, materials will no longer be dependent on materialtype files. + bool includeMaterialPropertyNames = true; + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) + { + settingsRegistry->Get(includeMaterialPropertyNames, "/O3DE/Atom/RPI/MaterialBuilder/IncludeMaterialPropertyNames"); + } + // Register dependency on the parent material source file so we can load it and use it's data to build this variant material. // Note, we don't need a direct dependency on the material type because the parent material will depend on it. - AddPossibleDependencies(request.m_sourceFile, parentMaterialPath, - response.m_sourceFileDependencyList, - JobKey, outputJobDescriptor.m_jobDependencyList); + AddPossibleDependencies(request.m_sourceFile, + parentMaterialPath, + JobKey, + outputJobDescriptor.m_jobDependencyList, + includeMaterialPropertyNames); } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp index b2c590a376..93994c567c 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp @@ -44,7 +44,7 @@ namespace AZ if (auto* serialize = azrtti_cast(context)) { serialize->Class() - ->Version(4) + ->Version(5) ->Attribute(Edit::Attributes::SystemComponentTags, AZStd::vector({ AssetBuilderSDK::ComponentTags::AssetBuilder })); } } @@ -88,6 +88,8 @@ namespace AZ jobDependency.m_sourceFile = materialTypeSource; jobDependency.m_platformIdentifier = platformIdentifier; + // If includeMaterialPropertyNames is true, then we need materials to depend on materialtype only once in order to get + // the property names. After the initial processing, materials will no longer be dependent on materialtype files. bool includeMaterialPropertyNames = true; RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames); jobDependency.m_type = includeMaterialPropertyNames ? AssetBuilderSDK::JobDependencyType::OrderOnce : AssetBuilderSDK::JobDependencyType::Order; From 0c3dc9a0cf55931b44651b654998611396262b75 Mon Sep 17 00:00:00 2001 From: Robin Date: Tue, 21 Sep 2021 12:25:05 -0700 Subject: [PATCH 46/84] Remove JIRA number. Signed-off-by: Robin --- .../RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index e1fed6a877..3e4147a949 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -47,7 +47,7 @@ namespace AZ { AssetBuilderSDK::AssetBuilderDesc materialBuilderDescriptor; materialBuilderDescriptor.m_name = JobKey; - materialBuilderDescriptor.m_version = 108; // ATOM-14918 + materialBuilderDescriptor.m_version = 108; materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.material", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.materialtype", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_busId = azrtti_typeid(); From 22e14ea90d159bb2f967c997fffac0704fece52a Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Tue, 21 Sep 2021 14:29:24 -0500 Subject: [PATCH 47/84] added m_drawContextRegistered flag to stop error calling UnregisterDynamicDrawContext in AtomViewportDisplayIconsSystemComponent Signed-off-by: Guthrie Adams --- .../Source/AtomViewportDisplayIconsSystemComponent.cpp | 7 ++++++- .../Code/Source/AtomViewportDisplayIconsSystemComponent.h | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp index 6ea6a8e85f..c0ca2fe993 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.cpp @@ -82,6 +82,8 @@ namespace AZ::Render void AtomViewportDisplayIconsSystemComponent::Activate() { + m_drawContextRegistered = false; + AzToolsFramework::EditorViewportIconDisplay::Register(this); Bootstrap::NotificationBus::Handler::BusConnect(); @@ -97,9 +99,10 @@ namespace AZ::Render { return; } - if (perViewportDynamicDrawInterface) + if (perViewportDynamicDrawInterface && m_drawContextRegistered) { perViewportDynamicDrawInterface->UnregisterDynamicDrawContext(m_drawContextName); + m_drawContextRegistered = false; } AzToolsFramework::EditorViewportIconDisplay::Unregister(this); @@ -367,6 +370,8 @@ namespace AZ::Render drawContext->EndInit(); }); + m_drawContextRegistered = true; + Data::AssetBus::Handler::BusDisconnect(); } } // namespace AZ::Render diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.h b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.h index 25cc7eb8f6..a0914e7e2d 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.h +++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/Code/Source/AtomViewportDisplayIconsSystemComponent.h @@ -77,6 +77,8 @@ namespace AZ }; AZStd::unordered_map m_iconData; IconId m_currentId = 0; + + bool m_drawContextRegistered = false; }; } // namespace Render } // namespace AZ From dd8761dd8bbf7527fcd81905d5bfe25495b2087b Mon Sep 17 00:00:00 2001 From: Robin Date: Tue, 21 Sep 2021 13:08:23 -0700 Subject: [PATCH 48/84] Edit comment and add marker for version update. Signed-off-by: Robin --- .../Source/RPI.Builders/Material/MaterialBuilder.cpp | 9 ++++++--- .../RPI.Builders/Model/MaterialAssetBuilderComponent.cpp | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp index 3e4147a949..ef0678046c 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Material/MaterialBuilder.cpp @@ -47,7 +47,7 @@ namespace AZ { AssetBuilderSDK::AssetBuilderDesc materialBuilderDescriptor; materialBuilderDescriptor.m_name = JobKey; - materialBuilderDescriptor.m_version = 108; + materialBuilderDescriptor.m_version = 108; // Set materialtype dependency to OrderOnce materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.material", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.materialtype", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); materialBuilderDescriptor.m_busId = azrtti_typeid(); @@ -223,8 +223,11 @@ namespace AZ parentMaterialPath = materialTypePath; } - // If includeMaterialPropertyNames is true, then we need materials to depend on materialtype only once in order to get - // the property names. After the initial processing, materials will no longer be dependent on materialtype files. + // If includeMaterialPropertyNames is false, then a job dependency is needed so the material builder can validate MaterialAsset properties + // against the MaterialTypeAsset at asset build time. + // If includeMaterialPropertyNames is true, the material properties will be validated at runtime when the material is loaded, so the job dependency + // is needed only for first-time processing to set up the initial MaterialAsset. This speeds up AP processing time when a materialtype file + // is edited (e.g. 10s when editing StandardPBR.materialtype on AtomTest project from 45s). bool includeMaterialPropertyNames = true; if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) { diff --git a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp index 93994c567c..c83761cf8e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Builders/Model/MaterialAssetBuilderComponent.cpp @@ -44,7 +44,7 @@ namespace AZ if (auto* serialize = azrtti_cast(context)) { serialize->Class() - ->Version(5) + ->Version(5) // Set materialtype dependency to OrderOnce ->Attribute(Edit::Attributes::SystemComponentTags, AZStd::vector({ AssetBuilderSDK::ComponentTags::AssetBuilder })); } } @@ -88,8 +88,11 @@ namespace AZ jobDependency.m_sourceFile = materialTypeSource; jobDependency.m_platformIdentifier = platformIdentifier; - // If includeMaterialPropertyNames is true, then we need materials to depend on materialtype only once in order to get - // the property names. After the initial processing, materials will no longer be dependent on materialtype files. + // If includeMaterialPropertyNames is false, then a job dependency is needed so the material builder can validate + // MaterialAsset properties against the MaterialTypeAsset at asset build time. If includeMaterialPropertyNames is true, the + // material properties will be validated at runtime when the material is loaded, so the job dependency is needed only for + // first-time processing to set up the initial MaterialAsset. This speeds up AP processing time when a materialtype file is + // edited (e.g. 10s when editing StandardPBR.materialtype on AtomTest project from 45s). bool includeMaterialPropertyNames = true; RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames); jobDependency.m_type = includeMaterialPropertyNames ? AssetBuilderSDK::JobDependencyType::OrderOnce : AssetBuilderSDK::JobDependencyType::Order; From 107732d057c0932879882b76331120a8298107fc Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 21 Sep 2021 13:45:39 -0700 Subject: [PATCH 49/84] Remove pragma once from cpp file Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp index 6d5e672df9..197119d017 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp @@ -6,8 +6,6 @@ * */ -#pragma once - #include #include From 61a92232568130970500557aae48de9b858d0cef Mon Sep 17 00:00:00 2001 From: jiaweig <51759646+jiaweig-amzn@users.noreply.github.com> Date: Tue, 21 Sep 2021 13:46:22 -0700 Subject: [PATCH 50/84] ATOM-16079 [RHI][Vulkan] - Linux Swapchain rendering issue on the first frame (#4129) * Fix out-of-date swapchain when QT window is not activated. Signed-off-by: jiaweig * Removed new code of the previous hack. Signed-off-by: jiaweig --- .../RHI/Code/Include/Atom/RHI/SwapChain.h | 9 --------- Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp | 6 ------ .../Vulkan/Code/Source/RHI/CommandQueue.cpp | 9 --------- .../RHI/Vulkan/Code/Source/RHI/SwapChain.cpp | 11 ---------- .../Viewport/RenderViewportWidget.h | 2 -- .../Source/Viewport/RenderViewportWidget.cpp | 20 +------------------ 6 files changed, 1 insertion(+), 56 deletions(-) diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h index 42ba2d2e25..14e9968e42 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/SwapChain.h @@ -81,15 +81,6 @@ namespace AZ AZ_RTTI(SwapChain, "{888B64A5-D956-406F-9C33-CF6A54FC41B0}", Object); -#if defined(PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB) - // On Linux platforms that uses XCB, a resize may occur in the swap chain but the command queue may still - // reference the original surface. This flag is a temporary fix to make sure the swap chain is ready to present - // We need to remove this work around with - - // [GFX TODO][GHI - 2678] - AZStd::atomic_bool m_readyToPresent { false }; -#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - protected: SwapChain(); diff --git a/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp b/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp index 92d7a125d8..b0501d937d 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/SwapChain.cpp @@ -164,12 +164,6 @@ namespace AZ m_currentImageIndex = 0; } -#if defined(PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB) - // If we are presenting through the editor, the resize is triggered through the editor's window, which - // won't happen until after the surface is ready to present - m_readyToPresent.store(true); -#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - return resultCode; } diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp index e4d8212228..c712099172 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp @@ -42,15 +42,6 @@ namespace AZ void CommandQueue::ExecuteWork(const RHI::ExecuteWorkRequest& rhiRequest) { -#if defined(PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB) - for (RHI::SwapChain* swapChain : rhiRequest.m_swapChainsToPresent) - { - if (!swapChain->m_readyToPresent) - { - return; - } - } -#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB const ExecuteWorkRequest& request = static_cast(rhiRequest); QueueCommand([=](void* queue) { diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp index e1d3e8c060..7040defca8 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp @@ -128,17 +128,6 @@ namespace AZ nativeDimensions->m_imageFormat = ConvertFormat(m_surfaceFormat.format); } -#if defined(PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB) - // When launching in game mode, the surface will be ready at this point, meaning that after - // intialization, this swap chain is ready to present - AZ::ApplicationTypeQuery appType; - ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationBus::Events::QueryApplicationType, appType); - if (appType.IsGame()) - { - m_readyToPresent.store(true); - } -#endif // PAL_TRAIT_LINUX_WINDOW_MANAGER_XCB - SetName(GetName()); return result; } diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h index 1b718f7710..318a49027a 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h @@ -159,8 +159,6 @@ namespace AtomToolsFramework AZ::RPI::ViewPtr m_defaultCamera; // Our viewport-local aux geom pipeline for supplemental rendering. AZ::RPI::AuxGeomDrawPtr m_auxGeom; - // Used to keep track of a pending resize event to avoid initialization before window activate. - bool m_windowResizedEvent = false; // Tracks whether the cursor is currently over our viewport, used for mouse input event book-keeping. bool m_mouseOver = false; // The last recorded mouse position, in local viewport screen coordinates. diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp index 4446e11231..2a15041e20 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp @@ -254,28 +254,11 @@ namespace AtomToolsFramework void RenderViewportWidget::resizeEvent([[maybe_unused]] QResizeEvent* event) { - // We need to wait until the window is activated, so the underlying surface - // has been created and has the correct size. - if (windowHandle()->isActive()) - { - SendWindowResizeEvent(); - } - else - { - m_windowResizedEvent = true; - } + SendWindowResizeEvent(); } bool RenderViewportWidget::event(QEvent* event) { - // Check if we have a pending resize event. - // At this point the surface has been created and has - // the proper dimensions. - if (event->type() == QEvent::WindowActivate && m_windowResizedEvent) - { - SendWindowResizeEvent(); - } - return QWidget::event(event); } @@ -372,7 +355,6 @@ namespace AtomToolsFramework AzFramework::WindowNotificationBus::Event( GetNativeWindowHandle(), &AzFramework::WindowNotifications::OnWindowResized, windowSize.width(), windowSize.height()); - m_windowResizedEvent = false; } void RenderViewportWidget::NotifyUpdateRefreshRate() From 9477da799b78146e7b1d4f1d7c6cecfa89d38ac7 Mon Sep 17 00:00:00 2001 From: Tobias Alexander Franke Date: Tue, 21 Sep 2021 23:05:11 +0200 Subject: [PATCH 51/84] Jobify view culling (#3983) * Jobify culling * Move JobCompletion to stack Signed-off-by: Tobias Alexander Franke Co-authored-by: Tobias Alexander Franke --- Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp index f67343faa1..fbfabe4f2a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp @@ -730,12 +730,22 @@ namespace AZ m_debugCtx.ResetCullStats(); m_debugCtx.m_numCullablesInScene = GetNumCullables(); + AZ::JobCompletion beginCullingCompletion; for (auto& view : views) { - view->BeginCulling(); + const auto cullingLambda = [&view]() + { + view->BeginCulling(); + }; + + AZ::Job* cullingJob = AZ::CreateJobFunction(AZStd::move(cullingLambda), true, nullptr); + cullingJob->SetDependent(&beginCullingCompletion); + cullingJob->Start(); } + beginCullingCompletion.StartAndWaitForCompletion(); + AuxGeomDrawPtr auxGeom; if (m_debugCtx.m_debugDraw) { From 30da67fe7d95c9ea13c13d0adeaba0c50aac628f Mon Sep 17 00:00:00 2001 From: hershey5045 <43485729+hershey5045@users.noreply.github.com> Date: Tue, 21 Sep 2021 14:19:30 -0700 Subject: [PATCH 52/84] Editor HDR Color Grading Component implemented under the PostFx stack (#4159) * Add HDR color grading pass and shaders. * Remove color grading pass from light adaptation parent pass due to failing ASV tests. This will be added back later on. * Editor HDR Color Grading Component implemented under the PostFx stack (#219) * Add softmin/max for unbounded color grading properties. * Revert channel mixer properties to vector3. Refactor mix to weight. Fix color grading pass to convert any color variable into vec4. Signed-off-by: rbarrand Co-authored-by: Robin --- .../Common/Assets/Passes/HDRColorGrading.pass | 8 +- .../Assets/Passes/LightAdaptationParent.pass | 18 ++- .../PostProcessing/HDRColorGrading.azsl | 19 +-- .../ColorGrading/HDRColorGradingParams.inl | 37 +++++ .../HDRColorGradingSettingsInterface.h | 33 ++++ .../PostProcess/PostProcessSettings.inl | 1 + .../PostProcessSettingsInterface.h | 1 + .../Code/Source/CommonSystemComponent.cpp | 2 + .../ColorGrading/HDRColorGradingSettings.cpp | 59 +++++++ .../ColorGrading/HDRColorGradingSettings.h | 69 +++++++++ .../Source/PostProcess/PostProcessSettings.h | 1 + .../PostProcessing/HDRColorGradingPass.cpp | 135 ++++++++++++++++ .../PostProcessing/HDRColorGradingPass.h | 77 +++++++++ .../Code/atom_feature_common_files.cmake | 4 + .../atom_feature_common_public_files.cmake | 2 + .../ColorGrading/HDRColorGradingBus.h | 34 ++++ .../HDRColorGradingComponentConfig.h | 39 +++++ .../CommonFeatures/Code/Source/Module.cpp | 4 + .../EditorHDRColorGradingComponent.cpp | 145 +++++++++++++++++ .../EditorHDRColorGradingComponent.h | 35 +++++ .../ColorGrading/HDRColorGradingComponent.cpp | 30 ++++ .../ColorGrading/HDRColorGradingComponent.h | 33 ++++ .../HDRColorGradingComponentConfig.cpp | 47 ++++++ .../HDRColorGradingComponentController.cpp | 146 ++++++++++++++++++ .../HDRColorGradingComponentController.h | 59 +++++++ ...egration_commonfeatures_editor_files.cmake | 2 + ...omlyintegration_commonfeatures_files.cmake | 5 + ...egration_commonfeatures_public_files.cmake | 2 + 28 files changed, 1030 insertions(+), 17 deletions(-) create mode 100644 Gems/Atom/Feature/Common/Code/Include/Atom/Feature/PostProcess/ColorGrading/HDRColorGradingParams.inl create mode 100644 Gems/Atom/Feature/Common/Code/Include/Atom/Feature/PostProcess/ColorGrading/HDRColorGradingSettingsInterface.h create mode 100644 Gems/Atom/Feature/Common/Code/Source/PostProcess/ColorGrading/HDRColorGradingSettings.cpp create mode 100644 Gems/Atom/Feature/Common/Code/Source/PostProcess/ColorGrading/HDRColorGradingSettings.h create mode 100644 Gems/Atom/Feature/Common/Code/Source/PostProcessing/HDRColorGradingPass.cpp create mode 100644 Gems/Atom/Feature/Common/Code/Source/PostProcessing/HDRColorGradingPass.h create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/PostProcess/ColorGrading/HDRColorGradingBus.h create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/PostProcess/ColorGrading/HDRColorGradingComponentConfig.h create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/EditorHDRColorGradingComponent.cpp create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/EditorHDRColorGradingComponent.h create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponent.cpp create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponent.h create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponentConfig.cpp create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponentController.cpp create mode 100644 Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponentController.h diff --git a/Gems/Atom/Feature/Common/Assets/Passes/HDRColorGrading.pass b/Gems/Atom/Feature/Common/Assets/Passes/HDRColorGrading.pass index f1e8304b30..adcd43ce83 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/HDRColorGrading.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/HDRColorGrading.pass @@ -5,7 +5,7 @@ "ClassData": { "PassTemplate": { "Name": "HDRColorGradingTemplate", - "PassClass": "FullScreenTriangle", + "PassClass": "HDRColorGradingPass", "Slots": [ { "Name": "Input", @@ -85,7 +85,7 @@ }, { "Name": "m_whiteBalanceKelvin", - "Value": 6500.0 // 1000.0f ... 40000.0f kelvin + "Value": 6600.0 // 1000.0f ... 40000.0f kelvin }, { "Name": "m_whiteBalanceTint", @@ -96,7 +96,7 @@ "Value": 0.0 // -1 ... 1 }, { - "Name": "m_splitToneMix", + "Name": "m_splitToneWeight", "Value": 0.0 // 0 ... 1 }, { @@ -120,7 +120,7 @@ "Value": 1.0 // 0 ... 1 }, { - "Name": "m_smhMix", + "Name": "m_smhWeight", "Value": 0.0 // 0 ... 1 } ], diff --git a/Gems/Atom/Feature/Common/Assets/Passes/LightAdaptationParent.pass b/Gems/Atom/Feature/Common/Assets/Passes/LightAdaptationParent.pass index ff55ebc200..eec3634045 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/LightAdaptationParent.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/LightAdaptationParent.pass @@ -92,8 +92,8 @@ ] }, { - "Name": "LookModificationTransformPass", - "TemplateName": "LookModificationTransformTemplate", + "Name": "HDRColorGradingPass", + "TemplateName": "HDRColorGradingTemplate", "Enabled": true, "Connections": [ { @@ -102,6 +102,20 @@ "Pass": "Parent", "Attachment": "LightingInput" } + } + ] + }, + { + "Name": "LookModificationTransformPass", + "TemplateName": "LookModificationTransformTemplate", + "Enabled": true, + "Connections": [ + { + "LocalSlot": "Input", + "AttachmentRef": { + "Pass": "HDRColorGradingPass", + "Attachment": "Output" + } }, { "LocalSlot": "EyeAdaptationDataInput", diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.azsl index 9ae4a2bd68..cfa149f0d5 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/PostProcessing/HDRColorGrading.azsl @@ -50,13 +50,13 @@ ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback float m_whiteBalanceKelvin; float m_whiteBalanceTint; float m_splitToneBalance; - float m_splitToneMix; + float m_splitToneWeight; float m_colorGradingPostSaturation; float m_smhShadowsStart; float m_smhShadowsEnd; float m_smhHighlightsStart; float m_smhHighlightsEnd; - float m_smhMix; + float m_smhWeight; float3 m_channelMixingRed; float3 m_channelMixingGreen; @@ -69,9 +69,6 @@ ShaderResourceGroup PassSrg : SRG_PerPass_WithFallback float4 m_smhShadowsColor; float4 m_smhMidtonesColor; float4 m_smhHighlightsColor; - - // my color grading output - float4 m_color; } float SaturateWithEpsilon(float value) @@ -133,7 +130,7 @@ float3 NoNanPow(float3 base, float3 power) return pow(max(abs(base), float3(FloatEpsilon, FloatEpsilon, FloatEpsilon)), power); } -float3 ColorGradeSplitTone (float3 frameColor, float balance, float mix) +float3 ColorGradeSplitTone (float3 frameColor, float balance, float weight) { float3 frameSplitTone = NoNanPow(frameColor, 1.0 / 2.2); const float t = SaturateWithEpsilon(CalculateLuminance(SaturateWithEpsilon(frameSplitTone), ColorSpaceId::ACEScg) + balance); @@ -142,7 +139,7 @@ float3 ColorGradeSplitTone (float3 frameColor, float balance, float mix) frameSplitTone = BlendMode_SoftLight(frameSplitTone, shadows); frameSplitTone = BlendMode_SoftLight(frameSplitTone, highlights); frameSplitTone = NoNanPow(frameSplitTone, 2.2); - return lerp(frameColor.rgb, frameSplitTone.rgb, mix); + return lerp(frameColor.rgb, frameSplitTone.rgb, weight); } float3 ColorGradeChannelMixer (float3 frameColor) @@ -154,7 +151,7 @@ float3 ColorGradeChannelMixer (float3 frameColor) } float3 ColorGradeShadowsMidtonesHighlights (float3 frameColor, float shadowsStart, float shadowsEnd, - float highlightsStart, float highlightsEnd, float mix, + float highlightsStart, float highlightsEnd, float weight, float4 shadowsColor, float4 midtonesColor, float4 highlightsColor) { const float3 shadowsColorACEScg = TransformColor(shadowsColor.rgb, ColorSpaceId::LinearSRGB, ColorSpaceId::ACEScg); @@ -169,7 +166,7 @@ float3 ColorGradeShadowsMidtonesHighlights (float3 frameColor, float shadowsStar const float3 frameSmh = frameColor * shadowsColorACEScg * shadowsWeight + frameColor * midtonesColorACEScg * midtonesWeight + frameColor * highlightsColorACEScg * highlightsWeight; - return lerp(frameColor.rgb, frameSmh.rgb, mix); + return lerp(frameColor.rgb, frameSmh.rgb, weight); } float3 ColorGrade (float3 frameColor) @@ -181,11 +178,11 @@ float3 ColorGrade (float3 frameColor) PassSrg::m_colorFilterMultiply); frameColor = max(frameColor, 0.0); frameColor = ColorGradeSaturation(frameColor, PassSrg::m_colorGradingPreSaturation); - frameColor = ColorGradeSplitTone(frameColor, PassSrg::m_splitToneBalance, PassSrg::m_splitToneMix); + frameColor = ColorGradeSplitTone(frameColor, PassSrg::m_splitToneBalance, PassSrg::m_splitToneWeight); frameColor = ColorGradeChannelMixer(frameColor); frameColor = max(frameColor, 0.0); frameColor = ColorGradeShadowsMidtonesHighlights(frameColor, PassSrg::m_smhShadowsStart, PassSrg::m_smhShadowsEnd, - PassSrg::m_smhHighlightsStart, PassSrg::m_smhHighlightsEnd, PassSrg::m_smhMix, + PassSrg::m_smhHighlightsStart, PassSrg::m_smhHighlightsEnd, PassSrg::m_smhWeight, PassSrg::m_smhShadowsColor, PassSrg::m_smhMidtonesColor, PassSrg::m_smhHighlightsColor); frameColor = ColorGradeHueShift(frameColor, PassSrg::m_colorGradingHueShift); frameColor = ColorGradeSaturation(frameColor, PassSrg::m_colorGradingPostSaturation); diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/PostProcess/ColorGrading/HDRColorGradingParams.inl b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/PostProcess/ColorGrading/HDRColorGradingParams.inl new file mode 100644 index 0000000000..241ba3b5de --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/PostProcess/ColorGrading/HDRColorGradingParams.inl @@ -0,0 +1,37 @@ +/* + * 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 + * + */ + +// Macros below are of the form: +// PARAM(NAME, MEMBER_NAME, DEFAULT_VALUE, ...) + +AZ_GFX_BOOL_PARAM(Enabled, m_enabled, false) +AZ_GFX_FLOAT_PARAM(ColorGradingExposure, m_colorGradingExposure, 0.0) +AZ_GFX_FLOAT_PARAM(ColorGradingContrast, m_colorGradingContrast, 0.0) +AZ_GFX_FLOAT_PARAM(ColorGradingHueShift, m_colorGradingHueShift, 0.0) +AZ_GFX_FLOAT_PARAM(ColorGradingPreSaturation, m_colorGradingPreSaturation, 1.0) +AZ_GFX_FLOAT_PARAM(ColorGradingFilterIntensity, m_colorGradingFilterIntensity, 1.0) +AZ_GFX_FLOAT_PARAM(ColorGradingFilterMultiply, m_colorGradingFilterMultiply, 0.0) +AZ_GFX_FLOAT_PARAM(ColorGradingPostSaturation, m_colorGradingPostSaturation, 1.0) +AZ_GFX_FLOAT_PARAM(WhiteBalanceKelvin, m_whiteBalanceKelvin, 6600.0) +AZ_GFX_FLOAT_PARAM(WhiteBalanceTint, m_whiteBalanceTint, 0.0) +AZ_GFX_FLOAT_PARAM(SplitToneBalance, m_splitToneBalance, 0.0) +AZ_GFX_FLOAT_PARAM(SplitToneWeight, m_splitToneWeight, 0.0) +AZ_GFX_FLOAT_PARAM(SmhShadowsStart, m_smhShadowsStart, 0.0) +AZ_GFX_FLOAT_PARAM(SmhShadowsEnd, m_smhShadowsEnd, 0.3) +AZ_GFX_FLOAT_PARAM(SmhHighlightsStart, m_smhHighlightsStart, 0.55) +AZ_GFX_FLOAT_PARAM(SmhHighlightsEnd, m_smhHighlightsEnd, 1.0) +AZ_GFX_FLOAT_PARAM(SmhWeight, m_smhWeight, 0.0) +AZ_GFX_VEC3_PARAM(ChannelMixingRed, m_channelMixingRed, AZ::Vector3(1.0f, 0.0f, 0.0f)) +AZ_GFX_VEC3_PARAM(ChannelMixingGreen, m_channelMixingGreen, AZ::Vector3(0.0f, 1.0f, 0.0f)) +AZ_GFX_VEC3_PARAM(ChannelMixingBlue, m_channelMixingBlue, AZ::Vector3(0.0f, 0.f, 1.0f)) +AZ_GFX_VEC3_PARAM(ColorFilterSwatch, m_colorFilterSwatch, AZ::Vector3(1.0f, 0.5f, 0.5f)) +AZ_GFX_VEC3_PARAM(SplitToneShadowsColor, m_splitToneShadowsColor, AZ::Vector3(1.0f, 0.5f, 0.5f)) +AZ_GFX_VEC3_PARAM(SplitToneHighlightsColor, m_splitToneHighlightsColor, AZ::Vector3(0.1f, 1.0f, 0.1f)) +AZ_GFX_VEC3_PARAM(SmhShadowsColor, m_smhShadowsColor, AZ::Vector3(1.0f, 0.25f, 0.25f)) +AZ_GFX_VEC3_PARAM(SmhMidtonesColor, m_smhMidtonesColor, AZ::Vector3(0.1f, 0.1f, 1.0f)) +AZ_GFX_VEC3_PARAM(SmhHighlightsColor, m_smhHighlightsColor, AZ::Vector3(1.0f, 0.0f, 1.0f)) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/PostProcess/ColorGrading/HDRColorGradingSettingsInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/PostProcess/ColorGrading/HDRColorGradingSettingsInterface.h new file mode 100644 index 0000000000..019df206eb --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/PostProcess/ColorGrading/HDRColorGradingSettingsInterface.h @@ -0,0 +1,33 @@ +/* + * 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 +#include +#include +#include + +namespace AZ +{ + namespace Render + { + class HDRColorGradingSettingsInterface + { + public: + AZ_RTTI(AZ::Render::HDRColorGradingSettingsInterface, "{CB5ADF78-27DE-438C-A991-1E5433046A42}"); + + // Auto-gen virtual getter and setter functions... +#include +#include +#include + + virtual void OnConfigChanged() = 0; + }; + } +} diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/PostProcess/PostProcessSettings.inl b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/PostProcess/PostProcessSettings.inl index 0259f07525..8409732f34 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/PostProcess/PostProcessSettings.inl +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/PostProcess/PostProcessSettings.inl @@ -25,3 +25,4 @@ POST_PROCESS_MEMBER(ExposureControlSettings, m_exposureControlSettings) POST_PROCESS_MEMBER(SsaoSettings, m_ssaoSettings) POST_PROCESS_MEMBER(LookModificationSettings, m_lookModificationSettings) POST_PROCESS_MEMBER(DeferredFogSettings, m_deferredFogSettings) +POST_PROCESS_MEMBER(HDRColorGradingSettings, m_hdrColorGradingSettings) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/PostProcess/PostProcessSettingsInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/PostProcess/PostProcessSettingsInterface.h index 12c0017aad..905aa9f2ca 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/PostProcess/PostProcessSettingsInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/PostProcess/PostProcessSettingsInterface.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp index de03c08c6f..db49fba96f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CommonSystemComponent.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -222,6 +223,7 @@ namespace AZ passSystem->AddPassCreator(Name("LightCullingRemapPass"), &LightCullingRemap::Create); passSystem->AddPassCreator(Name("LightCullingTilePreparePass"), &LightCullingTilePreparePass::Create); passSystem->AddPassCreator(Name("BlendColorGradingLutsPass"), &BlendColorGradingLutsPass::Create); + passSystem->AddPassCreator(Name("HDRColorGradingPass"), &HDRColorGradingPass::Create); passSystem->AddPassCreator(Name("LookModificationCompositePass"), &LookModificationCompositePass::Create); passSystem->AddPassCreator(Name("LookModificationTransformPass"), &LookModificationPass::Create); passSystem->AddPassCreator(Name("SMAAEdgeDetectionPass"), &SMAAEdgeDetectionPass::Create); diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcess/ColorGrading/HDRColorGradingSettings.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcess/ColorGrading/HDRColorGradingSettings.cpp new file mode 100644 index 0000000000..4542b53a15 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcess/ColorGrading/HDRColorGradingSettings.cpp @@ -0,0 +1,59 @@ +/* + * 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 + +#include +#include + +namespace AZ +{ + namespace Render + { + HDRColorGradingSettings::HDRColorGradingSettings(PostProcessFeatureProcessor* featureProcessor) + : PostProcessBase(featureProcessor) + { + } + + void HDRColorGradingSettings::OnConfigChanged() + { + m_parentSettings->OnConfigChanged(); + } + + void HDRColorGradingSettings::ApplySettingsTo(HDRColorGradingSettings* target, [[maybe_unused]] float alpha) const + { + AZ_Assert(target != nullptr, "HDRColorGradingSettings::ApplySettingsTo called with nullptr as argument."); + + if (GetEnabled()) + { + target->m_enabled = m_enabled; + +#define AZ_GFX_BOOL_PARAM(NAME, MEMBER_NAME, DefaultValue) ; +#define AZ_GFX_FLOAT_PARAM(NAME, MEMBER_NAME, DefaultValue) \ + { \ + target->Set##NAME(AZ::Lerp(target->MEMBER_NAME, MEMBER_NAME, alpha)); \ + } + +#define AZ_GFX_VEC3_PARAM(NAME, MEMBER_NAME, DefaultValue) \ + { \ + target->MEMBER_NAME.Set(AZ::Lerp(target->MEMBER_NAME.GetX(), MEMBER_NAME.GetX(), alpha), \ + AZ::Lerp(target->MEMBER_NAME.GetY(), MEMBER_NAME.GetY(), alpha), \ + AZ::Lerp(target->MEMBER_NAME.GetZ(), MEMBER_NAME.GetZ(), alpha)); \ + } + +#include +#include + } + } + + void HDRColorGradingSettings::Simulate([[maybe_unused]] float deltaTime) + { + } + } // namespace Render +} // namespace AZ + + diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcess/ColorGrading/HDRColorGradingSettings.h b/Gems/Atom/Feature/Common/Code/Source/PostProcess/ColorGrading/HDRColorGradingSettings.h new file mode 100644 index 0000000000..2358919c28 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcess/ColorGrading/HDRColorGradingSettings.h @@ -0,0 +1,69 @@ +/* + * 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 + +#include + +#include + +namespace AZ +{ + namespace Render + { + class PostProcessSettings; + + class HDRColorGradingSettings final + : public HDRColorGradingSettingsInterface + , public PostProcessBase + { + friend class PostProcessSettings; + friend class PostProcessFeatureProcessor; + + public: + AZ_RTTI(HDRColorGradingSettings, "{EA8C05D4-66D0-4141-8D4D-68E5D764C2ED}", HDRColorGradingSettingsInterface, PostProcessBase); + AZ_CLASS_ALLOCATOR(HDRColorGradingSettings, SystemAllocator, 0); + + HDRColorGradingSettings(PostProcessFeatureProcessor* featureProcessor); + ~HDRColorGradingSettings() = default; + + void OnConfigChanged() override; + + void ApplySettingsTo(HDRColorGradingSettings* target, float alpha) const; + + // Generate all getters and override setters. + // Declare non-override setters, which will be defined in the .cpp +#define AZ_GFX_COMMON_PARAM(ValueType, Name, MemberName, DefaultValue) \ + ValueType Get##Name() const override { return MemberName; } \ + void Set##Name(ValueType val) override \ + { \ + MemberName = val; \ + } \ + +#define AZ_GFX_COMMON_OVERRIDE(ValueType, Name, MemberName, OverrideValueType) \ + OverrideValueType Get##Name##Override() const override { return MemberName##Override; } \ + void Set##Name##Override(OverrideValueType val) override { MemberName##Override = val; } \ + +#include +#include +#include + + private: + // Generate members... +#include +#include +#include + + void Simulate(float deltaTime); + + PostProcessSettings* m_parentSettings = nullptr; + }; + } +} diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessSettings.h b/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessSettings.h index 515326e357..c2a32e6cee 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessSettings.h +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessSettings.h @@ -17,6 +17,7 @@ #include #include #include +#include #include namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/HDRColorGradingPass.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/HDRColorGradingPass.cpp new file mode 100644 index 0000000000..62fff6b6fe --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/HDRColorGradingPass.cpp @@ -0,0 +1,135 @@ +/* + * 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 +#include + +#include +#include +#include + + namespace AZ +{ + namespace Render + { + RPI::Ptr HDRColorGradingPass::Create(const RPI::PassDescriptor& descriptor) + { + RPI::Ptr pass = aznew HDRColorGradingPass(descriptor); + return AZStd::move(pass); + } + + HDRColorGradingPass::HDRColorGradingPass(const RPI::PassDescriptor& descriptor) + : AZ::RPI::FullscreenTrianglePass(descriptor) + { + } + + void HDRColorGradingPass::InitializeInternal() + { + FullscreenTrianglePass::InitializeInternal(); + + m_colorGradingExposureIndex.Reset(); + m_colorGradingContrastIndex.Reset(); + m_colorGradingHueShiftIndex.Reset(); + m_colorGradingPreSaturationIndex.Reset(); + m_colorFilterIntensityIndex.Reset(); + m_colorFilterMultiplyIndex.Reset(); + m_whiteBalanceKelvinIndex.Reset(); + m_whiteBalanceTintIndex.Reset(); + m_splitToneBalanceIndex.Reset(); + m_splitToneWeightIndex.Reset(); + m_colorGradingPostSaturationIndex.Reset(); + m_smhShadowsStartIndex.Reset(); + m_smhShadowsEndIndex.Reset(); + m_smhHighlightsStartIndex.Reset(); + m_smhHighlightsEndIndex.Reset(); + m_smhWeightIndex.Reset(); + + m_channelMixingRedIndex.Reset(); + m_channelMixingGreenIndex.Reset(); + m_channelMixingBlueIndex.Reset(); + + m_colorFilterSwatchIndex.Reset(); + m_splitToneShadowsColorIndex.Reset(); + m_splitToneHighlightsColorIndex.Reset(); + m_smhShadowsColorIndex.Reset(); + m_smhMidtonesColorIndex.Reset(); + m_smhHighlightsColorIndex.Reset(); + } + + void HDRColorGradingPass::FrameBeginInternal(FramePrepareParams params) + { + SetSrgConstants(); + + FullscreenTrianglePass::FrameBeginInternal(params); + } + + bool HDRColorGradingPass::IsEnabled() const + { + const auto* colorGradingSettings = GetHDRColorGradingSettings(); + return colorGradingSettings ? colorGradingSettings->GetEnabled() : false; + } + + void HDRColorGradingPass::SetSrgConstants() + { + const HDRColorGradingSettings* settings = GetHDRColorGradingSettings(); + if (settings) + { + m_shaderResourceGroup->SetConstant(m_colorGradingExposureIndex, settings->GetColorGradingExposure()); + m_shaderResourceGroup->SetConstant(m_colorGradingContrastIndex, settings->GetColorGradingContrast()); + m_shaderResourceGroup->SetConstant(m_colorGradingHueShiftIndex, settings->GetColorGradingHueShift()); + m_shaderResourceGroup->SetConstant(m_colorGradingPreSaturationIndex, settings->GetColorGradingPreSaturation()); + m_shaderResourceGroup->SetConstant(m_colorFilterIntensityIndex, settings->GetColorGradingFilterIntensity()); + m_shaderResourceGroup->SetConstant(m_colorFilterMultiplyIndex, settings->GetColorGradingFilterMultiply()); + m_shaderResourceGroup->SetConstant(m_whiteBalanceKelvinIndex, settings->GetWhiteBalanceKelvin()); + m_shaderResourceGroup->SetConstant(m_whiteBalanceTintIndex, settings->GetWhiteBalanceTint()); + m_shaderResourceGroup->SetConstant(m_splitToneBalanceIndex, settings->GetSplitToneBalance()); + m_shaderResourceGroup->SetConstant(m_splitToneWeightIndex, settings->GetSplitToneWeight()); + m_shaderResourceGroup->SetConstant(m_colorGradingPostSaturationIndex, settings->GetColorGradingPostSaturation()); + m_shaderResourceGroup->SetConstant(m_smhShadowsStartIndex, settings->GetSmhShadowsStart()); + m_shaderResourceGroup->SetConstant(m_smhShadowsEndIndex, settings->GetSmhShadowsEnd()); + m_shaderResourceGroup->SetConstant(m_smhHighlightsStartIndex, settings->GetSmhHighlightsStart()); + m_shaderResourceGroup->SetConstant(m_smhHighlightsEndIndex, settings->GetSmhHighlightsEnd()); + m_shaderResourceGroup->SetConstant(m_smhWeightIndex, settings->GetSmhWeight()); + + m_shaderResourceGroup->SetConstant(m_channelMixingRedIndex, settings->GetChannelMixingRed()); + m_shaderResourceGroup->SetConstant(m_channelMixingGreenIndex, settings->GetChannelMixingGreen()); + m_shaderResourceGroup->SetConstant(m_channelMixingBlueIndex, settings->GetChannelMixingBlue()); + + m_shaderResourceGroup->SetConstant(m_colorFilterSwatchIndex, AZ::Vector4(settings->GetColorFilterSwatch())); + m_shaderResourceGroup->SetConstant(m_splitToneShadowsColorIndex, AZ::Vector4(settings->GetSplitToneShadowsColor())); + m_shaderResourceGroup->SetConstant(m_splitToneHighlightsColorIndex, AZ::Vector4(settings->GetSplitToneHighlightsColor())); + m_shaderResourceGroup->SetConstant(m_smhShadowsColorIndex, AZ::Vector4(settings->GetSmhShadowsColor())); + m_shaderResourceGroup->SetConstant(m_smhMidtonesColorIndex, AZ::Vector4(settings->GetSmhMidtonesColor())); + m_shaderResourceGroup->SetConstant(m_smhHighlightsColorIndex, AZ::Vector4(settings->GetSmhHighlightsColor())); + } + } + + const AZ::Render::HDRColorGradingSettings* HDRColorGradingPass::GetHDRColorGradingSettings() const + { + RPI::Scene* scene = GetScene(); + if (scene) + { + PostProcessFeatureProcessor* fp = scene->GetFeatureProcessor(); + AZ::RPI::ViewPtr view = scene->GetDefaultRenderPipeline()->GetDefaultView(); + if (fp) + { + PostProcessSettings* postProcessSettings = fp->GetLevelSettingsFromView(view); + if (postProcessSettings) + { + const HDRColorGradingSettings* colorGradingSettings = postProcessSettings->GetHDRColorGradingSettings(); + if (colorGradingSettings != nullptr && colorGradingSettings->GetEnabled()) + { + return postProcessSettings->GetHDRColorGradingSettings(); + } + } + } + } + return nullptr; + } + } +} diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/HDRColorGradingPass.h b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/HDRColorGradingPass.h new file mode 100644 index 0000000000..e5eaf7db26 --- /dev/null +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/HDRColorGradingPass.h @@ -0,0 +1,77 @@ +/* + * 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 +#include +#include +#include +#include + +namespace AZ +{ + namespace Render + { + /** + * The color grading pass. + */ + class HDRColorGradingPass + : public AZ::RPI::FullscreenTrianglePass + //TODO: , public PostProcessingShaderOptionBase + { + public: + AZ_RTTI(HDRColorGradingPass, "{E68E31A1-DB24-4AFF-A029-456A8B74C03C}", AZ::RPI::FullscreenTrianglePass); + AZ_CLASS_ALLOCATOR(HDRColorGradingPass, SystemAllocator, 0); + + virtual ~HDRColorGradingPass() = default; + + //! Creates a ColorGradingPass + static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); + + protected: + HDRColorGradingPass(const RPI::PassDescriptor& descriptor); + + //! Pass behavior overrides + void InitializeInternal() override; + void FrameBeginInternal(FramePrepareParams params) override; + bool IsEnabled() const override; + + private: + const HDRColorGradingSettings* GetHDRColorGradingSettings() const; + void SetSrgConstants(); + + RHI::ShaderInputNameIndex m_colorGradingExposureIndex = "m_colorGradingExposure"; + RHI::ShaderInputNameIndex m_colorGradingContrastIndex = "m_colorGradingContrast"; + RHI::ShaderInputNameIndex m_colorGradingHueShiftIndex = "m_colorGradingHueShift"; + RHI::ShaderInputNameIndex m_colorGradingPreSaturationIndex = "m_colorGradingPreSaturation"; + RHI::ShaderInputNameIndex m_colorFilterIntensityIndex = "m_colorFilterIntensity"; + RHI::ShaderInputNameIndex m_colorFilterMultiplyIndex = "m_colorFilterMultiply"; + RHI::ShaderInputNameIndex m_whiteBalanceKelvinIndex = "m_whiteBalanceKelvin"; + RHI::ShaderInputNameIndex m_whiteBalanceTintIndex = "m_whiteBalanceTint"; + RHI::ShaderInputNameIndex m_splitToneBalanceIndex = "m_splitToneBalance"; + RHI::ShaderInputNameIndex m_splitToneWeightIndex = "m_splitToneWeight"; + RHI::ShaderInputNameIndex m_colorGradingPostSaturationIndex = "m_colorGradingPostSaturation"; + RHI::ShaderInputNameIndex m_smhShadowsStartIndex = "m_smhShadowsStart"; + RHI::ShaderInputNameIndex m_smhShadowsEndIndex = "m_smhShadowsEnd"; + RHI::ShaderInputNameIndex m_smhHighlightsStartIndex = "m_smhHighlightsStart"; + RHI::ShaderInputNameIndex m_smhHighlightsEndIndex = "m_smhHighlightsEnd"; + RHI::ShaderInputNameIndex m_smhWeightIndex = "m_smhWeight"; + + RHI::ShaderInputNameIndex m_channelMixingRedIndex = "m_channelMixingRed"; + RHI::ShaderInputNameIndex m_channelMixingGreenIndex = "m_channelMixingGreen"; + RHI::ShaderInputNameIndex m_channelMixingBlueIndex = "m_channelMixingBlue"; + + RHI::ShaderInputNameIndex m_colorFilterSwatchIndex = "m_colorFilterSwatch"; + RHI::ShaderInputNameIndex m_splitToneShadowsColorIndex = "m_splitToneShadowsColor"; + RHI::ShaderInputNameIndex m_splitToneHighlightsColorIndex = "m_splitToneHighlightsColor"; + RHI::ShaderInputNameIndex m_smhShadowsColorIndex = "m_smhShadowsColor"; + RHI::ShaderInputNameIndex m_smhMidtonesColorIndex = "m_smhMidtonesColor"; + RHI::ShaderInputNameIndex m_smhHighlightsColorIndex = "m_smhHighlightsColor"; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake index 40188109ca..92f96a591b 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_files.cmake @@ -183,6 +183,8 @@ set(FILES Source/PostProcess/PostProcessFeatureProcessor.h Source/PostProcess/PostProcessSettings.cpp Source/PostProcess/PostProcessSettings.h + Source/PostProcess/ColorGrading/HDRColorGradingSettings.h + Source/PostProcess/ColorGrading/HDRColorGradingSettings.cpp Source/PostProcess/Bloom/BloomSettings.cpp Source/PostProcess/Bloom/BloomSettings.h Source/PostProcess/DepthOfField/DepthOfFieldSettings.cpp @@ -205,6 +207,8 @@ set(FILES Source/PostProcessing/BloomCompositePass.cpp Source/PostProcessing/BloomParentPass.h Source/PostProcessing/BloomParentPass.cpp + Source/PostProcessing/HDRColorGradingPass.cpp + Source/PostProcessing/HDRColorGradingPass.h Source/PostProcessing/DepthOfFieldCompositePass.h Source/PostProcessing/DepthOfFieldCompositePass.cpp Source/PostProcessing/DepthOfFieldBokehBlurPass.h diff --git a/Gems/Atom/Feature/Common/Code/atom_feature_common_public_files.cmake b/Gems/Atom/Feature/Common/Code/atom_feature_common_public_files.cmake index 89febbcf3d..d7af7b0108 100644 --- a/Gems/Atom/Feature/Common/Code/atom_feature_common_public_files.cmake +++ b/Gems/Atom/Feature/Common/Code/atom_feature_common_public_files.cmake @@ -51,6 +51,8 @@ set(FILES Include/Atom/Feature/PostProcess/Bloom/BloomConstants.h Include/Atom/Feature/PostProcess/Bloom/BloomParams.inl Include/Atom/Feature/PostProcess/Bloom/BloomSettingsInterface.h + Include/Atom/Feature/PostProcess/ColorGrading/HDRColorGradingParams.inl + Include/Atom/Feature/PostProcess/ColorGrading/HDRColorGradingSettingsInterface.h Include/Atom/Feature/PostProcess/DepthOfField/DepthOfFieldConstants.h Include/Atom/Feature/PostProcess/DepthOfField/DepthOfFieldParams.inl Include/Atom/Feature/PostProcess/DepthOfField/DepthOfFieldSettingsInterface.h diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/PostProcess/ColorGrading/HDRColorGradingBus.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/PostProcess/ColorGrading/HDRColorGradingBus.h new file mode 100644 index 0000000000..32b1c97429 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/PostProcess/ColorGrading/HDRColorGradingBus.h @@ -0,0 +1,34 @@ +/* + * 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 + +namespace AZ +{ + namespace Render + { + class HDRColorGradingRequests + : public ComponentBus + { + public: + AZ_RTTI(AZ::Render::HDRColorGradingRequests, "{E414A96B-0AA7-4574-ABC0-968B1F5CEE56}"); + + /// Overrides the default AZ::EBusTraits handler policy to allow one listener only. + static const EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::Single; + virtual ~HDRColorGradingRequests() {} + // Auto-gen virtual getters/setters... +#include +#include +#include + }; + + typedef AZ::EBus HDRColorGradingRequestBus; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/PostProcess/ColorGrading/HDRColorGradingComponentConfig.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/PostProcess/ColorGrading/HDRColorGradingComponentConfig.h new file mode 100644 index 0000000000..fe7bc874a4 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Include/AtomLyIntegration/CommonFeatures/PostProcess/ColorGrading/HDRColorGradingComponentConfig.h @@ -0,0 +1,39 @@ +/* + * 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 +#include + +namespace AZ +{ + namespace Render + { + class HDRColorGradingComponentConfig final + : public ComponentConfig + { + public: + AZ_RTTI(AZ::Render::HDRColorGradingComponentConfig, "{8613EA4A-6E1C-49AD-87F3-9FECCB7EA36D}", AZ::ComponentConfig); + + static void Reflect(ReflectContext* context); + + // Generate members... +#include +#include +#include + + // Generate Getters/Setters... +#include +#include +#include + + void CopySettingsTo(HDRColorGradingSettingsInterface* settings); + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Module.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Module.cpp index a83e2e9fa1..230130826e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Module.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Module.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,7 @@ #include #include #include +#include #include #include #include @@ -93,6 +95,7 @@ namespace AZ DecalComponent::CreateDescriptor(), DirectionalLightComponent::CreateDescriptor(), BloomComponent::CreateDescriptor(), + HDRColorGradingComponent::CreateDescriptor(), DisplayMapperComponent::CreateDescriptor(), DepthOfFieldComponent::CreateDescriptor(), ExposureControlComponent::CreateDescriptor(), @@ -124,6 +127,7 @@ namespace AZ EditorDecalComponent::CreateDescriptor(), EditorDirectionalLightComponent::CreateDescriptor(), EditorBloomComponent::CreateDescriptor(), + EditorHDRColorGradingComponent::CreateDescriptor(), EditorDepthOfFieldComponent::CreateDescriptor(), EditorDisplayMapperComponent::CreateDescriptor(), EditorExposureControlComponent::CreateDescriptor(), diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/EditorHDRColorGradingComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/EditorHDRColorGradingComponent.cpp new file mode 100644 index 0000000000..49c8275141 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/EditorHDRColorGradingComponent.cpp @@ -0,0 +1,145 @@ +/* + * 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 + +namespace AZ +{ + namespace Render + { + void EditorHDRColorGradingComponent::Reflect(AZ::ReflectContext* context) + { + BaseClass::Reflect(context); + + if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) + { + serializeContext->Class()->Version(1); + + if (AZ::EditContext* editContext = serializeContext->GetEditContext()) + { + editContext->Class( + "HDR Color Grading", "Tune and apply color grading in HDR.") + ->ClassElement(Edit::ClassElements::EditorData, "") + ->Attribute(Edit::Attributes::Category, "Atom") + ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Component_Placeholder.svg") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing. + ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.svg") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing. + ->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game")) + ->Attribute(Edit::Attributes::AutoExpand, true) + ->Attribute(Edit::Attributes::HelpPageURL, "https://") // [TODO ATOM-2672][PostFX] need to create page for PostProcessing. + ; + + editContext->Class( + "HDRColorGradingComponentControl", "") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::Default, &HDRColorGradingComponentController::m_configuration, "Configuration", "") + ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) + ; + + editContext->Class("HDRColorGradingComponentConfig", "") + ->DataElement(Edit::UIHandlers::CheckBox, &HDRColorGradingComponentConfig::m_enabled, + "Enable HDR color grading", + "Enable HDR color grading.") + ->ClassElement(AZ::Edit::ClassElements::Group, "Color Adjustment") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_colorGradingExposure, "Exposure", "Exposure Value") + ->Attribute(Edit::Attributes::Min, AZStd::numeric_limits::lowest()) + ->Attribute(Edit::Attributes::Max, AZStd::numeric_limits::max()) + ->Attribute(Edit::Attributes::SoftMin, -20.0f) + ->Attribute(Edit::Attributes::SoftMax, 20.0f) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_colorGradingContrast, "Contrast", "Contrast Value") + ->Attribute(Edit::Attributes::Min, -100.0f) + ->Attribute(Edit::Attributes::Max, 100.0f) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_colorGradingPreSaturation, "Pre Saturation", "Pre Saturation Value") + ->Attribute(Edit::Attributes::Min, -100.0f) + ->Attribute(Edit::Attributes::Max, 100.0f) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_colorGradingFilterIntensity, "Filter Intensity", "Filter Intensity Value") + ->Attribute(Edit::Attributes::Min, AZStd::numeric_limits::lowest()) + ->Attribute(Edit::Attributes::Max, AZStd::numeric_limits::max()) + ->Attribute(Edit::Attributes::SoftMin, -1.0f) + ->Attribute(Edit::Attributes::SoftMax, 1.0f) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_colorGradingFilterMultiply, "Filter Multiply", "Filter Multiply Value") + ->Attribute(Edit::Attributes::Min, 0.0f) + ->Attribute(Edit::Attributes::Max, 1.0f) + ->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_colorFilterSwatch, "Color Filter Swatch", "Color Filter Swatch Value") + + ->ClassElement(AZ::Edit::ClassElements::Group, "White Balance") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_whiteBalanceKelvin, "Temperature", "Temperature in Kelvin") + ->Attribute(Edit::Attributes::Min, 1000.0f) + ->Attribute(Edit::Attributes::Max, 40000.0f) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_whiteBalanceTint, "Tint", "Tint Value") + ->Attribute(Edit::Attributes::Min, -100.0f) + ->Attribute(Edit::Attributes::Max, 100.0f) + + ->ClassElement(AZ::Edit::ClassElements::Group, "Split Toning") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_splitToneWeight, "Split Tone Weight", "Modulates the split toning effect.") + ->Attribute(Edit::Attributes::Min, 0.0f) + ->Attribute(Edit::Attributes::Max, 1.0f) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_splitToneBalance, "Split Tone Balance", "Split Tone Balance Value") + ->Attribute(Edit::Attributes::Min, 0.0f) + ->Attribute(Edit::Attributes::Max, 1.0f) + ->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_splitToneShadowsColor, "Split Tone Shadows Color", "Split Tone Shadows Color") + ->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_splitToneHighlightsColor, "Split Tone Highlights Color", "Split Tone Highlights Color") + + ->ClassElement(AZ::Edit::ClassElements::Group, "Channel Mixing") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_channelMixingRed, "Channel Mixing Red", "Channel Mixing Red Value") + ->Attribute(Edit::Attributes::Min, 0.0f) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_channelMixingGreen, "Channel Mixing Green", "Channel Mixing Green Value") + ->Attribute(Edit::Attributes::Min, 0.0f) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_channelMixingBlue, "Channel Mixing Blue", "Channel Mixing Blue Value") + ->Attribute(Edit::Attributes::Min, 0.0f) + + ->ClassElement(AZ::Edit::ClassElements::Group, "Shadow Midtones Highlights") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_smhWeight, "SMH Weight", "Modulates the SMH effect.") + ->Attribute(Edit::Attributes::Min, 0.0f) + ->Attribute(Edit::Attributes::Max, 1.0f) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_smhShadowsStart, "SMH Shadows Start", "SMH Shadows Start Value") + ->Attribute(Edit::Attributes::Min, 0.0f) + ->Attribute(Edit::Attributes::Max, 1.0f) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_smhShadowsEnd, "SMH Shadows End", "SMH Shadows End Value") + ->Attribute(Edit::Attributes::Min, 0.0f) + ->Attribute(Edit::Attributes::Max, 1.0f) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_smhHighlightsStart, "SMH Highlights Start", "SMH Highlights Start Value") + ->Attribute(Edit::Attributes::Min, 0.0f) + ->Attribute(Edit::Attributes::Max, 1.0f) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_smhHighlightsEnd, "SMH Highlights End", "SMH Highlights End Value") + ->Attribute(Edit::Attributes::Min, 0.0f) + ->Attribute(Edit::Attributes::Max, 1.0f) + ->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_smhShadowsColor, "SMH Shadows Color", "SMH Shadows Color") + ->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_smhMidtonesColor, "SMH Midtones Color", "SMH Midtones Color") + ->DataElement(AZ::Edit::UIHandlers::Color, &HDRColorGradingComponentConfig::m_smhHighlightsColor, "SMH Highlights Color", "SMH Highlights Color") + + ->ClassElement(AZ::Edit::ClassElements::Group, "Final Adjustment") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_colorGradingHueShift, "Hue Shift", "Hue Shift Value") + ->Attribute(Edit::Attributes::Min, 0.0f) + ->Attribute(Edit::Attributes::Max, 1.0f) + ->DataElement(AZ::Edit::UIHandlers::Slider, &HDRColorGradingComponentConfig::m_colorGradingPostSaturation, "Post Saturation", "Post Saturation Value") + ->Attribute(Edit::Attributes::Min, -100.0f) + ->Attribute(Edit::Attributes::Max, 100.0f) + ; + } + } + } + + EditorHDRColorGradingComponent::EditorHDRColorGradingComponent(const HDRColorGradingComponentConfig& config) + : BaseClass(config) + { + } + + u32 EditorHDRColorGradingComponent::OnConfigurationChanged() + { + m_controller.OnConfigChanged(); + return Edit::PropertyRefreshLevels::AttributesAndValues; + } + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/EditorHDRColorGradingComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/EditorHDRColorGradingComponent.h new file mode 100644 index 0000000000..8eea568e3a --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/EditorHDRColorGradingComponent.h @@ -0,0 +1,35 @@ +/* + * 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 +#include + +namespace AZ +{ + namespace Render + { + class EditorHDRColorGradingComponent final + : public AzToolsFramework::Components:: + EditorComponentAdapter + { + public: + using BaseClass = AzToolsFramework::Components::EditorComponentAdapter; + AZ_EDITOR_COMPONENT(AZ::Render::EditorHDRColorGradingComponent, "{C1FAB0B1-5847-4533-B08E-7314AC807B8E}", BaseClass); + + static void Reflect(AZ::ReflectContext* context); + + EditorHDRColorGradingComponent() = default; + EditorHDRColorGradingComponent(const HDRColorGradingComponentConfig& config); + + //! EditorRenderComponentAdapter overrides... + AZ::u32 OnConfigurationChanged() override; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponent.cpp new file mode 100644 index 0000000000..d91a91a09f --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponent.cpp @@ -0,0 +1,30 @@ +/* + * 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 + +namespace AZ +{ + namespace Render + { + HDRColorGradingComponent::HDRColorGradingComponent(const HDRColorGradingComponentConfig& config) + : BaseClass(config) + { + } + + void HDRColorGradingComponent::Reflect(AZ::ReflectContext* context) + { + BaseClass::Reflect(context); + + if (auto serializeContext = azrtti_cast(context)) + { + serializeContext->Class(); + } + } + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponent.h new file mode 100644 index 0000000000..6c4bd1418f --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponent.h @@ -0,0 +1,33 @@ +/* + * 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 +#include +#include +#include + +namespace AZ +{ + namespace Render + { + class HDRColorGradingComponent final + : public AzFramework::Components::ComponentAdapter + { + public: + using BaseClass = AzFramework::Components::ComponentAdapter; + AZ_COMPONENT(AZ::Render::HDRColorGradingComponent, "{51968E0F-4DF0-4851-8405-388CBB15B573}", BaseClass); + + HDRColorGradingComponent() = default; + HDRColorGradingComponent(const HDRColorGradingComponentConfig& config); + + static void Reflect(AZ::ReflectContext* context); + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponentConfig.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponentConfig.cpp new file mode 100644 index 0000000000..b63fa647a0 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponentConfig.cpp @@ -0,0 +1,47 @@ +/* + * 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 +#include +#include + +namespace AZ +{ + namespace Render + { + void HDRColorGradingComponentConfig::Reflect(ReflectContext* context) + { + if (auto serializeContext = azrtti_cast(context)) + { + serializeContext->Class()->Version(0) + + // Auto-gen serialize context code... +#define SERIALIZE_CLASS HDRColorGradingComponentConfig +#include +#include +#include +#undef SERIALIZE_CLASS + ; + } + } + + void HDRColorGradingComponentConfig::CopySettingsTo (HDRColorGradingSettingsInterface* settings) + { + if (!settings) + { + return; + } + +#define COPY_TARGET settings +#include +#include +#include +#undef COPY_TARGET + } + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponentController.cpp new file mode 100644 index 0000000000..c0f70ab145 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponentController.cpp @@ -0,0 +1,146 @@ +/* + * 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 + +#include + +#include + +namespace AZ +{ + namespace Render + { + void HDRColorGradingComponentController::Reflect(ReflectContext* context) + { + HDRColorGradingComponentConfig::Reflect(context); + + if (auto* serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(0) + ->Field("Configuration", &HDRColorGradingComponentController::m_configuration); + } + + if (auto* behaviorContext = azrtti_cast(context)) + { + behaviorContext->EBus("HDRColorGradingRequestBus") + ->Attribute(AZ::Script::Attributes::Module, "render") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common) + + // Auto-gen behavior context... +#define PARAM_EVENT_BUS HDRColorGradingRequestBus::Events +#include +#include +#include +#undef PARAM_EVENT_BUS + + ; + } + } + + void HDRColorGradingComponentController::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided) + { + provided.push_back(AZ_CRC_CE("HDRColorGradingService")); + } + + void HDRColorGradingComponentController::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible) + { + incompatible.push_back(AZ_CRC_CE("HDRColorGradingService")); + } + + void HDRColorGradingComponentController::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required) + { + required.push_back(AZ_CRC_CE("PostFXLayerService")); + } + + HDRColorGradingComponentController::HDRColorGradingComponentController(const HDRColorGradingComponentConfig& config) + : m_configuration(config) + { + } + + void HDRColorGradingComponentController::Activate(EntityId entityId) + { + m_entityId = entityId; + + PostProcessFeatureProcessorInterface* fp = + RPI::Scene::GetFeatureProcessorForEntity(m_entityId); + if (fp) + { + m_postProcessInterface = fp->GetOrCreateSettingsInterface(m_entityId); + if (m_postProcessInterface) + { + m_settingsInterface = m_postProcessInterface->GetOrCreateHDRColorGradingSettingsInterface(); + OnConfigChanged(); + } + } + HDRColorGradingRequestBus::Handler::BusConnect(m_entityId); + } + + void HDRColorGradingComponentController::Deactivate() + { + HDRColorGradingRequestBus::Handler::BusDisconnect(m_entityId); + + if (m_postProcessInterface) + { + m_postProcessInterface->RemoveHDRColorGradingSettingsInterface(); + } + + m_postProcessInterface = nullptr; + m_settingsInterface = nullptr; + m_entityId.SetInvalid(); + } + + void HDRColorGradingComponentController::SetConfiguration(const HDRColorGradingComponentConfig& config) + { + m_configuration = config; + OnConfigChanged(); + } + + const HDRColorGradingComponentConfig& HDRColorGradingComponentController::GetConfiguration() const + { + return m_configuration; + } + + void HDRColorGradingComponentController::OnConfigChanged() + { + if (m_settingsInterface) + { + m_configuration.CopySettingsTo(m_settingsInterface); + m_settingsInterface->OnConfigChanged(); + } + } + + // Auto-gen getter/setter function definitions... + // The setter functions will set the values on the Atom settings class, then get the value back + // from the settings class to set the local configuration. This is in case the settings class + // applies some custom logic that results in the set value being different from the input +#define AZ_GFX_COMMON_PARAM(ValueType, Name, MemberName, DefaultValue) \ + ValueType HDRColorGradingComponentController::Get##Name() const \ + { \ + return m_configuration.MemberName; \ + } \ + void HDRColorGradingComponentController::Set##Name(ValueType val) \ + { \ + if (m_settingsInterface) \ + { \ + m_settingsInterface->Set##Name(val); \ + m_settingsInterface->OnConfigChanged(); \ + m_configuration.MemberName = m_settingsInterface->Get##Name(); \ + } \ + else \ + { \ + m_configuration.MemberName = val; \ + } \ + } + +#include +#include +#include + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponentController.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponentController.h new file mode 100644 index 0000000000..d5743dfbf6 --- /dev/null +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ColorGrading/HDRColorGradingComponentController.h @@ -0,0 +1,59 @@ +/* + * 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 +#include +#include + +#include +#include +#include + +namespace AZ +{ + namespace Render + { + class HDRColorGradingComponentController final + : public HDRColorGradingRequestBus::Handler + { + public: + friend class EditorHDRColorGradingComponent; + + AZ_TYPE_INFO(AZ::Render::HDRColorGradingComponentController, "{CA1D635C-64E9-42C7-A8E0-36C6B825B15D}"); + static void Reflect(AZ::ReflectContext* context); + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible); + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required); + + HDRColorGradingComponentController() = default; + HDRColorGradingComponentController(const HDRColorGradingComponentConfig& config); + + void Activate(EntityId entityId); + void Deactivate(); + void SetConfiguration(const HDRColorGradingComponentConfig& config); + const HDRColorGradingComponentConfig& GetConfiguration() const; + + // Auto-gen function override declarations (functions definitions in .cpp)... +#include +#include +#include + + private: + AZ_DISABLE_COPY(HDRColorGradingComponentController); + + void OnConfigChanged(); + + PostProcessSettingsInterface* m_postProcessInterface = nullptr; + HDRColorGradingSettingsInterface* m_settingsInterface = nullptr; + HDRColorGradingComponentConfig m_configuration; + EntityId m_entityId; + }; + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake index 099cb378f5..174eb30b31 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_editor_files.cmake @@ -63,6 +63,8 @@ set(FILES Source/PostProcess/EditorPostFxLayerComponent.h Source/PostProcess/Bloom/EditorBloomComponent.cpp Source/PostProcess/Bloom/EditorBloomComponent.h + Source/PostProcess/ColorGrading/EditorHDRColorGradingComponent.cpp + Source/PostProcess/ColorGrading/EditorHDRColorGradingComponent.h Source/PostProcess/DepthOfField/EditorDepthOfFieldComponent.cpp Source/PostProcess/DepthOfField/EditorDepthOfFieldComponent.h Source/PostProcess/DisplayMapper/EditorDisplayMapperComponent.cpp diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_files.cmake b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_files.cmake index e353795d04..63f5aedf33 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_files.cmake +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_files.cmake @@ -83,6 +83,11 @@ set(FILES Source/PostProcess/Bloom/BloomComponentConfig.cpp Source/PostProcess/Bloom/BloomComponentController.cpp Source/PostProcess/Bloom/BloomComponentController.h + Source/PostProcess/ColorGrading/HDRColorGradingComponent.cpp + Source/PostProcess/ColorGrading/HDRColorGradingComponent.h + Source/PostProcess/ColorGrading/HDRColorGradingComponentConfig.cpp + Source/PostProcess/ColorGrading/HDRColorGradingComponentController.cpp + Source/PostProcess/ColorGrading/HDRColorGradingComponentController.h Source/PostProcess/DepthOfField/DepthOfFieldComponent.cpp Source/PostProcess/DepthOfField/DepthOfFieldComponent.h Source/PostProcess/DepthOfField/DepthOfFieldComponentConfig.cpp diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_public_files.cmake b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_public_files.cmake index 68bbe52415..133856c900 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_public_files.cmake +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/atomlyintegration_commonfeatures_public_files.cmake @@ -39,6 +39,8 @@ set(FILES Include/AtomLyIntegration/CommonFeatures/PostProcess/ExposureControl/ExposureControlBus.h Include/AtomLyIntegration/CommonFeatures/PostProcess/ExposureControl/ExposureControlComponentConfig.h Include/AtomLyIntegration/CommonFeatures/PostProcess/ExposureControl/ExposureControlComponentConstants.h + Include/AtomLyIntegration/CommonFeatures/PostProcess/ColorGrading/HDRColorGradingBus.h + Include/AtomLyIntegration/CommonFeatures/PostProcess/ColorGrading/HDRColorGradingComponentConfig.h Include/AtomLyIntegration/CommonFeatures/PostProcess/Ssao/SsaoBus.h Include/AtomLyIntegration/CommonFeatures/PostProcess/Ssao/SsaoComponentConfiguration.h Include/AtomLyIntegration/CommonFeatures/PostProcess/LookModification/LookModificationBus.h From 0bcf275ed2c70d5b12175d59405000f356b0a41f Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Tue, 21 Sep 2021 16:39:04 -0500 Subject: [PATCH 53/84] updated/removed platform specific files fixed warning message Signed-off-by: Guthrie Adams --- .../Source/Platform/Linux/MaterialEditor_Linux.cpp | 11 ----------- .../Source/Platform/Linux/platform_linux_files.cmake | 1 - .../Code/Source/Platform/Mac/MaterialEditor_Mac.cpp | 11 ----------- .../Code/Source/Platform/Mac/platform_mac_files.cmake | 1 - .../Platform/Windows/MaterialEditor_Windows.cpp | 11 ----------- .../Platform/Windows/platform_windows_files.cmake | 1 - .../Code/Source/Viewport/MaterialViewportWidget.cpp | 2 +- .../Code/Source/Platform/Linux/PAL_linux.cmake | 2 +- .../Platform/Mac/ShaderManagementConsole_Mac.cpp | 11 ----------- .../Code/Source/Platform/Mac/platform_mac_files.cmake | 1 - .../Windows/ShaderManagementConsole_Windows.cpp | 11 ----------- .../Platform/Windows/platform_windows_files.cmake | 1 - 12 files changed, 2 insertions(+), 62 deletions(-) delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Linux/MaterialEditor_Linux.cpp delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Mac/MaterialEditor_Mac.cpp delete mode 100644 Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/MaterialEditor_Windows.cpp delete mode 100644 Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Mac/ShaderManagementConsole_Mac.cpp delete mode 100644 Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/ShaderManagementConsole_Windows.cpp diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Linux/MaterialEditor_Linux.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Linux/MaterialEditor_Linux.cpp deleted file mode 100644 index d588e5a656..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Linux/MaterialEditor_Linux.cpp +++ /dev/null @@ -1,11 +0,0 @@ -/* - * 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 - * - */ - -namespace Platform -{ -} diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Linux/platform_linux_files.cmake b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Linux/platform_linux_files.cmake index c09abb0dd2..2417ad1b55 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Linux/platform_linux_files.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Linux/platform_linux_files.cmake @@ -9,5 +9,4 @@ set(FILES MaterialEditor_Traits_Platform.h MaterialEditor_Traits_Linux.h - MaterialEditor_Linux.cpp ) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Mac/MaterialEditor_Mac.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Mac/MaterialEditor_Mac.cpp deleted file mode 100644 index d588e5a656..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Mac/MaterialEditor_Mac.cpp +++ /dev/null @@ -1,11 +0,0 @@ -/* - * 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 - * - */ - -namespace Platform -{ -} diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Mac/platform_mac_files.cmake b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Mac/platform_mac_files.cmake index ec56cc1c4e..7275f82047 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Mac/platform_mac_files.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Mac/platform_mac_files.cmake @@ -9,5 +9,4 @@ set(FILES MaterialEditor_Traits_Platform.h MaterialEditor_Traits_Mac.h - MaterialEditor_Mac.cpp ) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/MaterialEditor_Windows.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/MaterialEditor_Windows.cpp deleted file mode 100644 index d588e5a656..0000000000 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/MaterialEditor_Windows.cpp +++ /dev/null @@ -1,11 +0,0 @@ -/* - * 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 - * - */ - -namespace Platform -{ -} diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/platform_windows_files.cmake b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/platform_windows_files.cmake index c104a2b8be..608cb36a28 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/platform_windows_files.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/platform_windows_files.cmake @@ -9,6 +9,5 @@ set(FILES MaterialEditor_Traits_Platform.h MaterialEditor_Traits_Windows.h - MaterialEditor_Windows.cpp MaterialEditor.rc ) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp index e2c5ee0026..0322fa194e 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/MaterialViewportWidget.cpp @@ -16,7 +16,7 @@ #include #include -AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknow n-warning-option") // disable warnings spawned by QT +AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT #include #include "Viewport/ui_MaterialViewportWidget.h" AZ_POP_DISABLE_WARNING diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/PAL_linux.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/PAL_linux.cmake index 762ac16004..b5332e2e15 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/PAL_linux.cmake +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/PAL_linux.cmake @@ -6,4 +6,4 @@ # # -set(PAL_TRAIT_ATOM_SHADER_MANAGEMENT_CONSOLE_APPLICATION_SUPPORTED FALSE) +set(PAL_TRAIT_ATOM_SHADER_MANAGEMENT_CONSOLE_APPLICATION_SUPPORTED TRUE) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Mac/ShaderManagementConsole_Mac.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Mac/ShaderManagementConsole_Mac.cpp deleted file mode 100644 index d588e5a656..0000000000 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Mac/ShaderManagementConsole_Mac.cpp +++ /dev/null @@ -1,11 +0,0 @@ -/* - * 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 - * - */ - -namespace Platform -{ -} diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Mac/platform_mac_files.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Mac/platform_mac_files.cmake index e48e836b73..6fe2859a89 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Mac/platform_mac_files.cmake +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Mac/platform_mac_files.cmake @@ -9,5 +9,4 @@ set(FILES ShaderManagementConsole_Traits_Platform.h ShaderManagementConsole_Traits_Mac.h - ShaderManagementConsole_Mac.cpp ) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/ShaderManagementConsole_Windows.cpp b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/ShaderManagementConsole_Windows.cpp deleted file mode 100644 index d588e5a656..0000000000 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/ShaderManagementConsole_Windows.cpp +++ /dev/null @@ -1,11 +0,0 @@ -/* - * 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 - * - */ - -namespace Platform -{ -} diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/platform_windows_files.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/platform_windows_files.cmake index 4ec319f402..b978cedeb4 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/platform_windows_files.cmake +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/platform_windows_files.cmake @@ -9,6 +9,5 @@ set(FILES ShaderManagementConsole_Traits_Platform.h ShaderManagementConsole_Traits_Windows.h - ShaderManagementConsole_Windows.cpp ShaderManagementConsole.rc ) From e5cc029c76cb76f0f07facc5ae3bff840cda3a07 Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Tue, 21 Sep 2021 14:40:26 -0700 Subject: [PATCH 54/84] Converted ReflectionProbe Srg indices to ShaderInputNameIndex Signed-off-by: dmcdiar --- .../Source/ReflectionProbe/ReflectionProbe.h | 14 +++--- .../ReflectionProbeFeatureProcessor.cpp | 47 ------------------- 2 files changed, 7 insertions(+), 54 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h index 4f6a3337be..5b56b70ec8 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h @@ -55,13 +55,13 @@ namespace AZ RHI::DrawListTag m_renderOuterDrawListTag; RHI::DrawListTag m_renderInnerDrawListTag; - RHI::ShaderInputConstantIndex m_modelToWorldStencilConstantIndex; - RHI::ShaderInputConstantIndex m_modelToWorldRenderConstantIndex; - RHI::ShaderInputConstantIndex m_modelToWorldInverseRenderConstantIndex; - RHI::ShaderInputConstantIndex m_outerObbHalfLengthsRenderConstantIndex; - RHI::ShaderInputConstantIndex m_innerObbHalfLengthsRenderConstantIndex; - RHI::ShaderInputConstantIndex m_useParallaxCorrectionRenderConstantIndex; - RHI::ShaderInputImageIndex m_reflectionCubeMapRenderImageIndex; + RHI::ShaderInputNameIndex m_modelToWorldStencilConstantIndex = "m_modelToWorld"; + RHI::ShaderInputNameIndex m_modelToWorldRenderConstantIndex = "m_modelToWorld"; + RHI::ShaderInputNameIndex m_modelToWorldInverseRenderConstantIndex = "m_modelToWorldInverse"; + RHI::ShaderInputNameIndex m_outerObbHalfLengthsRenderConstantIndex = "m_outerObbHalfLengths"; + RHI::ShaderInputNameIndex m_innerObbHalfLengthsRenderConstantIndex = "m_innerObbHalfLengths"; + RHI::ShaderInputNameIndex m_useParallaxCorrectionRenderConstantIndex = "m_useParallaxCorrection"; + RHI::ShaderInputNameIndex m_reflectionCubeMapRenderImageIndex = "m_reflectionCubeMap"; }; // ReflectionProbe manages all aspects of a single probe, including rendering, visualization, and cubemap generation diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp index e47a132481..9fecbc19fc 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp @@ -77,53 +77,6 @@ namespace AZ m_reflectionRenderData.m_renderInnerSrgLayout, m_reflectionRenderData.m_renderInnerDrawListTag); - // create ShaderResourceGroups here so we can get the layout and cache the indices - // Note: the SRGs are not needed beyond this method since each probe creates its own SRGs, we are just interested in the indices - - // cache probe stencil shader indices - Data::Instance stencilSrg = RPI::ShaderResourceGroup::Create( - m_reflectionRenderData.m_stencilShader->GetAsset(), - m_reflectionRenderData.m_stencilShader->GetSupervariantIndex(), - m_reflectionRenderData.m_stencilSrgLayout->GetName()); - AZ_Error("ReflectionProbeFeatureProcessor", stencilSrg.get(), "Failed to create stencil back face shader resource group"); - - const RHI::ShaderResourceGroupLayout* stencilSrgLayout = stencilSrg->GetLayout(); - Name modelToWorldConstantName = Name("m_modelToWorld"); - m_reflectionRenderData.m_modelToWorldStencilConstantIndex = stencilSrgLayout->FindShaderInputConstantIndex(modelToWorldConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldStencilConstantIndex.IsValid(), "Failed to find stencil shader input constant [%s]", modelToWorldConstantName.GetCStr()); - - // cache probe render shader indices - // Note: the outer and inner render shaders use the same Srg - Data::Instance renderReflectionSrg = RPI::ShaderResourceGroup::Create( - m_reflectionRenderData.m_renderOuterShader->GetAsset(), - m_reflectionRenderData.m_renderOuterShader->GetSupervariantIndex(), - m_reflectionRenderData.m_renderOuterSrgLayout->GetName()); - AZ_Error("ReflectionProbeFeatureProcessor", renderReflectionSrg.get(), "Failed to create render reflection shader resource group"); - - const RHI::ShaderResourceGroupLayout* renderReflectionSrgLayout = renderReflectionSrg->GetLayout(); - m_reflectionRenderData.m_modelToWorldRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(modelToWorldConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", modelToWorldConstantName.GetCStr()); - - Name modelToWorldInverseConstantName = Name("m_modelToWorldInverse"); - m_reflectionRenderData.m_modelToWorldInverseRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(modelToWorldInverseConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_modelToWorldRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", modelToWorldInverseConstantName.GetCStr()); - - Name outerObbHalfLengthsConstantName = Name("m_outerObbHalfLengths"); - m_reflectionRenderData.m_outerObbHalfLengthsRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(outerObbHalfLengthsConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_outerObbHalfLengthsRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", outerObbHalfLengthsConstantName.GetCStr()); - - Name innerObbHalfLengthsConstantName = Name("m_innerObbHalfLengths"); - m_reflectionRenderData.m_innerObbHalfLengthsRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(innerObbHalfLengthsConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_innerObbHalfLengthsRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", innerObbHalfLengthsConstantName.GetCStr()); - - Name useParallaxCorrectionConstantName = Name("m_useParallaxCorrection"); - m_reflectionRenderData.m_useParallaxCorrectionRenderConstantIndex = renderReflectionSrgLayout->FindShaderInputConstantIndex(useParallaxCorrectionConstantName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_useParallaxCorrectionRenderConstantIndex.IsValid(), "Failed to find render shader input constant [%s]", useParallaxCorrectionConstantName.GetCStr()); - - Name reflectionCubeMapImageName = Name("m_reflectionCubeMap"); - m_reflectionRenderData.m_reflectionCubeMapRenderImageIndex = renderReflectionSrgLayout->FindShaderInputImageIndex(reflectionCubeMapImageName); - AZ_Error("ReflectionProbeFeatureProcessor", m_reflectionRenderData.m_reflectionCubeMapRenderImageIndex.IsValid(), "Failed to find render shader input image [%s]", reflectionCubeMapImageName.GetCStr()); - EnableSceneNotification(); } From f14e8d6eac8d1d75a86cdc532df375f6da504dd9 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 21 Sep 2021 15:06:29 -0700 Subject: [PATCH 55/84] Fix header formatting to pass validation Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzToolsFramework/FocusMode/FocusModeInterface.h | 4 ++-- .../AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp | 4 ++-- .../AzToolsFramework/FocusMode/FocusModeSystemComponent.h | 4 ++-- .../AzToolsFramework/Prefab/PrefabFocusHandler.h | 4 ++-- .../AzToolsFramework/Prefab/PrefabFocusInterface.h | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h index b2d008ca36..6d3a7599de 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeInterface.h @@ -1,6 +1,6 @@ /* - * 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. + * 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 * diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp index 197119d017..450e19da3e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp @@ -1,6 +1,6 @@ /* - * 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. + * 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 * diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h index 32386abf67..9943d72951 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h @@ -1,6 +1,6 @@ /* - * 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. + * 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 * diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h index 60038d9bb8..b465f97908 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h @@ -1,6 +1,6 @@ /* - * 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. + * 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 * diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h index c7f58f5de2..833a5ef7c8 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h @@ -1,6 +1,6 @@ /* - * 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. + * 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 * From d44cc844d14c7f27598df8b903cc14257f0fd495 Mon Sep 17 00:00:00 2001 From: brianherrera Date: Tue, 21 Sep 2021 15:06:31 -0700 Subject: [PATCH 56/84] Retry pipeline stages when a node goes offline This change is required to support spot instances in the AR pipeline. - When a node goes offline the job is retried on a new node - Valid script errors are handled properly and the status is updated in Jenkins Signed-off-by: brianherrera --- scripts/build/Jenkins/Jenkinsfile | 108 ++++++++++++++++-------------- 1 file changed, 59 insertions(+), 49 deletions(-) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index 5bc4b919fb..a49cf1d548 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -9,6 +9,7 @@ import groovy.json.JsonOutput PIPELINE_CONFIG_FILE = 'scripts/build/Jenkins/lumberyard.json' INCREMENTAL_BUILD_SCRIPT_PATH = 'scripts/build/bootstrap/incremental_build_util.py' +PIPELINE_RETRY_ATTEMPTS = 3 EMPTY_JSON = readJSON text: '{}' @@ -502,64 +503,73 @@ def CreateTeardownStage(Map environmentVars) { def CreateSingleNode(Map pipelineConfig, def platform, def build_job, Map envVars, String branchName, String pipelineName, String repositoryName, String projectName, boolean onlyMountEBSVolume = false) { def nodeLabel = envVars['NODE_LABEL'] return { - node("${nodeLabel}") { - if(isUnix()) { // Has to happen inside a node - envVars['IS_UNIX'] = 1 - } - withEnv(GetEnvStringList(envVars)) { - def build_job_name = build_job.key - try { - CreateSetupStage(pipelineConfig, snapshot, repositoryName, projectName, pipelineName, branchName, platform.key, build_job.key, envVars, onlyMountEBSVolume).call() + def currentResult = '' + def currentException = '' + retry(PIPELINE_RETRY_ATTEMPTS) { + node("${nodeLabel}") { + if(isUnix()) { // Has to happen inside a node + envVars['IS_UNIX'] = 1 + } + withEnv(GetEnvStringList(envVars)) { + def build_job_name = build_job.key + try { + CreateSetupStage(pipelineConfig, snapshot, repositoryName, projectName, pipelineName, branchName, platform.key, build_job.key, envVars, onlyMountEBSVolume).call() - if(build_job.value.steps) { //this is a pipe with many steps so create all the build stages - build_job.value.steps.each { build_step -> - build_job_name = build_step - envVars = GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, platform.value.build_types[build_step].PIPELINE_ENV ?: EMPTY_JSON, pipelineName) - try { - CreateBuildStage(pipelineConfig, platform.key, build_step, envVars).call() + if(build_job.value.steps) { //this is a pipe with many steps so create all the build stages + build_job.value.steps.each { build_step -> + build_job_name = build_step + envVars = GetBuildEnvVars(platform.value.PIPELINE_ENV ?: EMPTY_JSON, platform.value.build_types[build_step].PIPELINE_ENV ?: EMPTY_JSON, pipelineName) + try { + CreateBuildStage(pipelineConfig, platform.key, build_step, envVars).call() + } + catch (Exception e) { + if (envVars['NONBLOCKING_STEP']?.toBoolean()) { + unstable(message: "Build step ${build_step} failed but it's a non-blocking step in build job ${build_job.key}") + } + } } - catch (Exception e) { - if (envVars['NONBLOCKING_STEP']?.toBoolean()) { - unstable(message: "Build step ${build_step} failed but it's a non-blocking step in build job ${build_job.key}") - } - else { - error "FAILURE: ${e}" - } + } else { + CreateBuildStage(pipelineConfig, platform.key, build_job.key, envVars).call() + } + } + catch(Exception e) { + if (e instanceof org.jenkinsci.plugins.workflow.steps.FlowInterruptedException) { + def causes = e.getCauses().toString() + if (causes.contains('RemovedNodeCause')) { + error "Node disconnected during build: ${e}" // Error raised to retry stage on a new node } } - } else { - CreateBuildStage(pipelineConfig, platform.key, build_job.key, envVars).call() + // All other errors will be raised outside the retry block + currentResult = envVars['ON_FAILURE_MARK'] ?: 'FAILURE' + currentException = e.toString() } - } - catch(Exception e) { - // https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/Result.java - // {SUCCESS,UNSTABLE,FAILURE,NOT_BUILT,ABORTED} - def currentResult = envVars['ON_FAILURE_MARK'] ?: 'FAILURE' - if (currentResult == 'FAILURE') { - currentBuild.result = 'FAILURE' - error "FAILURE: ${e}" - } else if (currentResult == 'UNSTABLE') { - currentBuild.result = 'UNSTABLE' - unstable(message: "UNSTABLE: ${e}") + finally { + def params = platform.value.build_types[build_job_name].PARAMETERS + if (env.MARS_REPO && params && params.containsKey('TEST_METRICS') && params.TEST_METRICS == 'True') { + def output_directory = params.OUTPUT_DIRECTORY + def configuration = params.CONFIGURATION + CreateTestMetricsStage(pipelineConfig, branchName, envVars, build_job_name, output_directory, configuration).call() + } + if (params && params.containsKey('TEST_RESULTS') && params.TEST_RESULTS == 'True') { + CreateExportTestResultsStage(pipelineConfig, platform.key, build_job_name, envVars, params).call() + } + if (params && params.containsKey('TEST_SCREENSHOTS') && params.TEST_SCREENSHOTS == 'True' && currentResult == 'FAILURE') { + CreateExportTestScreenshotsStage(pipelineConfig, platform.key, build_job_name, envVars, params).call() + } + CreateTeardownStage(envVars).call() } } - finally { - def params = platform.value.build_types[build_job_name].PARAMETERS - if (env.MARS_REPO && params && params.containsKey('TEST_METRICS') && params.TEST_METRICS == 'True') { - def output_directory = params.OUTPUT_DIRECTORY - def configuration = params.CONFIGURATION - CreateTestMetricsStage(pipelineConfig, branchName, envVars, build_job_name, output_directory, configuration).call() - } - if (params && params.containsKey('TEST_RESULTS') && params.TEST_RESULTS == 'True') { - CreateExportTestResultsStage(pipelineConfig, platform.key, build_job_name, envVars, params).call() - } - if (params && params.containsKey('TEST_SCREENSHOTS') && params.TEST_SCREENSHOTS == 'True' && currentResult == 'FAILURE') { - CreateExportTestScreenshotsStage(pipelineConfig, platform.key, build_job_name, envVars, params).call() - } - CreateTeardownStage(envVars).call() - } } } + // https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/Result.java + // {SUCCESS,UNSTABLE,FAILURE,NOT_BUILT,ABORTED} + if (currentResult == 'FAILURE') { + currentBuild.result = 'FAILURE' + error "FAILURE: ${currentException}" + } else if (currentResult == 'UNSTABLE') { + currentBuild.result = 'UNSTABLE' + unstable(message: "UNSTABLE: ${currentException}") + } } } From 50fabb1bf7b3b5c2609890144d7691edd1c4a533 Mon Sep 17 00:00:00 2001 From: mrieggeramzn <61609885+mrieggeramzn@users.noreply.github.com> Date: Tue, 21 Sep 2021 15:06:55 -0700 Subject: [PATCH 57/84] Atom/mriegger/fixupname (#4187) * Removing atom from the Decal (atom) name * Decal component can take advantage of non-uniform scale option * Using the base class nonuniform scale property rather than firing an event * removing pragma optimize off * Python tests need the updated name Signed-off-by: mrieggeramzn --- .../Gem/PythonTests/Atom/TestSuite_Main.py | 28 +++++++++---------- ...ydra_AtomEditorComponents_AddedToEntity.py | 2 +- .../hydra_AtomEditorComponents_DecalAdded.py | 2 +- .../Source/Decals/EditorDecalComponent.cpp | 24 +++++++++++----- .../Code/Source/Decals/EditorDecalComponent.h | 6 +++- 5 files changed, 38 insertions(+), 24 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py index 0bc66f2614..4c5716d365 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py @@ -38,24 +38,24 @@ class TestAtomEditorComponentsMain(object): 7. Exposure Control 8. Directional Light 9. DepthOfField - 10. Decal (Atom) + 10. Decal """ cfg_args = [level] expected_lines = [ - # Decal (Atom) Component - "Decal (Atom) Entity successfully created", - "Decal (Atom)_test: Component added to the entity: True", - "Decal (Atom)_test: Component removed after UNDO: True", - "Decal (Atom)_test: Component added after REDO: True", - "Decal (Atom)_test: Entered game mode: True", - "Decal (Atom)_test: Exit game mode: True", - "Decal (Atom) Controller|Configuration|Material: SUCCESS", - "Decal (Atom)_test: Entity is hidden: True", - "Decal (Atom)_test: Entity is shown: True", - "Decal (Atom)_test: Entity deleted: True", - "Decal (Atom)_test: UNDO entity deletion works: True", - "Decal (Atom)_test: REDO entity deletion works: True", + # Decal Component + "Decal Entity successfully created", + "Decal_test: Component added to the entity: True", + "Decal_test: Component removed after UNDO: True", + "Decal_test: Component added after REDO: True", + "Decal_test: Entered game mode: True", + "Decal_test: Exit game mode: True", + "Decal Controller|Configuration|Material: SUCCESS", + "Decal_test: Entity is hidden: True", + "Decal_test: Entity is shown: True", + "Decal_test: Entity deleted: True", + "Decal_test: UNDO entity deletion works: True", + "Decal_test: REDO entity deletion works: True", # DepthOfField Component "DepthOfField Entity successfully created", "DepthOfField_test: Component added to the entity: True", diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_AddedToEntity.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_AddedToEntity.py index a2e950e1dc..602e7564b3 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_AddedToEntity.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_AddedToEntity.py @@ -184,7 +184,7 @@ def run(): material_asset = asset.AssetCatalogRequestBus( bus.Broadcast, "GetAssetIdByPath", material_asset_path, math.Uuid(), False) ComponentTests( - "Decal (Atom)", lambda entity_obj: verify_set_property( + "Decal", lambda entity_obj: verify_set_property( entity_obj, "Controller|Configuration|Material", material_asset)) # Directional Light Component diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DecalAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DecalAdded.py index d68e1f5844..fa02b75fe2 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DecalAdded.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_DecalAdded.py @@ -73,7 +73,7 @@ def AtomEditorComponents_Decal_AddedToEntity(): # Test steps begin. # 1. Create a Decal entity with no components. - decal_name = "Decal (Atom)" + decal_name = "Decal" decal_entity = EditorEntity.create_editor_entity_at(math.Vector3(512.0, 512.0, 34.0), decal_name) Report.critical_result(Tests.decal_creation, decal_entity.exists()) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Decals/EditorDecalComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Decals/EditorDecalComponent.cpp index c10e7e2e30..c5d61dd54a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Decals/EditorDecalComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Decals/EditorDecalComponent.cpp @@ -32,7 +32,7 @@ namespace AZ if (AZ::EditContext* editContext = serializeContext->GetEditContext()) { editContext->Class( - "Decal (Atom)", "The Decal component allows an entity to project a texture or material onto a mesh") + "Decal", "The Decal component allows an entity to project a texture or material onto a mesh") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Category, "Atom") ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Decal.svg") @@ -97,13 +97,25 @@ namespace AZ BaseClass::Deactivate(); } - AZ::Transform EditorDecalComponent::GetTransform() const + AZ::Transform EditorDecalComponent::GetWorldTransform() const { AZ::Transform transform = AZ::Transform::CreateIdentity(); AZ::TransformBus::EventResult(transform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM); return transform; } + AZ::Matrix3x4 EditorDecalComponent::GetWorldTransformWithNonUniformScale() const + { + const AZ::Transform worldTransform = GetWorldTransform(); + const AZ::Matrix3x3 rotationMat = AZ::Matrix3x3::CreateFromQuaternion(worldTransform.GetRotation()); + + const AZ::Vector3 nonUniformScale = m_controller.m_cachedNonUniformScale * worldTransform.GetUniformScale(); + const AZ::Matrix3x3 nonUniformScaleMat = AZ::Matrix3x3::CreateScale(nonUniformScale); + const AZ::Matrix3x3 rotationAndScale = rotationMat * nonUniformScaleMat; + + return AZ::Matrix3x4::CreateFromMatrix3x3AndTranslation(rotationAndScale, worldTransform.GetTranslation()); + } + void EditorDecalComponent::DisplayEntityViewport( [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) @@ -113,11 +125,9 @@ namespace AZ return; } - AZ::Transform transform = GetTransform(); - - debugDisplay.SetColor(AZ::Colors::Red); - debugDisplay.PushMatrix(transform); + const AZ::Matrix3x4 transform = GetWorldTransformWithNonUniformScale(); + debugDisplay.PushPremultipliedMatrix(transform); debugDisplay.DrawWireBox(-AZ::Vector3::CreateOne(), AZ::Vector3::CreateOne()); AZ::Vector3 x1 = AZ::Vector3(-1, 0, 1); @@ -136,7 +146,7 @@ namespace AZ // Two diagonal edges debugDisplay.DrawLine(p0, p2); debugDisplay.DrawLine(p1, p3); - debugDisplay.PopMatrix(); + debugDisplay.PopPremultipliedMatrix(); } AZ::Aabb EditorDecalComponent::GetEditorSelectionBoundsViewport([[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Decals/EditorDecalComponent.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Decals/EditorDecalComponent.h index f0748dfef5..1ca88d23fc 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Decals/EditorDecalComponent.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Decals/EditorDecalComponent.h @@ -56,7 +56,11 @@ namespace AZ private: - AZ::Transform GetTransform() const; + // Returns the component transform which includes uniform-scale, rotation and translation + AZ::Transform GetWorldTransform() const; + + // Returns the full transform, including both the uniform scale and non-uniform scale along with rotation and translation + AZ::Matrix3x4 GetWorldTransformWithNonUniformScale() const; //! EditorRenderComponentAdapter overrides ... u32 OnConfigurationChanged() override; From 39a4e054925c2dc26c71319f5aa0abc6a6160636 Mon Sep 17 00:00:00 2001 From: Mike Chang <62353586+amzn-changml@users.noreply.github.com> Date: Tue, 21 Sep 2021 15:24:14 -0700 Subject: [PATCH 58/84] Change installer domain to o3debinaries.org (#4244) * Change installer domain to o3debinaries.org * Removed 3p license parameter Signed-off-by: Mike Chang --- scripts/build/Platform/Windows/build_config.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build/Platform/Windows/build_config.json b/scripts/build/Platform/Windows/build_config.json index 02bd01038a..3848e6f980 100644 --- a/scripts/build/Platform/Windows/build_config.json +++ b/scripts/build/Platform/Windows/build_config.json @@ -360,7 +360,7 @@ "CONFIGURATION": "profile", "OUTPUT_DIRECTORY": "build\\windows_vs2019", "CMAKE_OPTIONS": "-G \"Visual Studio 16 2019\" -DCMAKE_SYSTEM_VERSION=10.0 -DLY_UNITY_BUILD=TRUE -DLY_DISABLE_TEST_MODULES=TRUE -DLY_VERSION_ENGINE_NAME=o3de-sdk -DLY_INSTALLER_WIX_ROOT=\"!WIX! \"", - "EXTRA_CMAKE_OPTIONS": "-DLY_INSTALLER_AUTO_GEN_TAG=ON -DLY_INSTALLER_DOWNLOAD_URL=https://dkb1uj4hs9ikv.cloudfront.net -DLY_INSTALLER_LICENSE_URL=https://www.o3debinaries.org/license -DLY_INSTALLER_3RD_PARTY_LICENSE_URL=https://dkb1uj4hs9ikv.cloudfront.net/SPDX-Licenses.txt", + "EXTRA_CMAKE_OPTIONS": "-DLY_INSTALLER_AUTO_GEN_TAG=ON -DLY_INSTALLER_DOWNLOAD_URL=https://www.o3debinaries.org -DLY_INSTALLER_LICENSE_URL=https://www.o3debinaries.org/license", "CPACK_BUCKET": "spectra-prism-staging-us-west-2", "CMAKE_LY_PROJECTS": "", "CMAKE_TARGET": "ALL_BUILD", From eaddd4eee77beb4eb79b71bc01adb7a7d7ae8ff9 Mon Sep 17 00:00:00 2001 From: brianherrera Date: Tue, 21 Sep 2021 16:05:25 -0700 Subject: [PATCH 59/84] Throw exception for build stage This is required so Jenkins will properly mark the build failed on valid script errors. Signed-off-by: brianherrera --- scripts/build/Jenkins/Jenkinsfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/build/Jenkins/Jenkinsfile b/scripts/build/Jenkins/Jenkinsfile index a49cf1d548..5fe19ddf46 100644 --- a/scripts/build/Jenkins/Jenkinsfile +++ b/scripts/build/Jenkins/Jenkinsfile @@ -525,6 +525,8 @@ def CreateSingleNode(Map pipelineConfig, def platform, def build_job, Map envVar catch (Exception e) { if (envVars['NONBLOCKING_STEP']?.toBoolean()) { unstable(message: "Build step ${build_step} failed but it's a non-blocking step in build job ${build_job.key}") + } else { + throw e } } } From df42377fc6933a04dca38db3160af7e78e8ebb61 Mon Sep 17 00:00:00 2001 From: dmcdiar Date: Tue, 21 Sep 2021 17:10:32 -0700 Subject: [PATCH 60/84] Minor changes to forward pass IBL specular Signed-off-by: dmcdiar --- .../Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli | 2 +- .../Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli index b1cfb47be6..d33a307dfe 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/Ibl.azsli @@ -60,7 +60,7 @@ float3 GetIblSpecular( // compute blend amount based on world position in the reflection probe volume float blendAmount = ComputeLerpBetweenInnerOuterOBBs( - ObjectSrg::m_reflectionProbeData.m_modelToWorldInverse, + ObjectSrg::GetReflectionProbeWorldMatrixInverse(), ObjectSrg::m_reflectionProbeData.m_innerObbHalfLengths, ObjectSrg::m_reflectionProbeData.m_outerObbHalfLengths, position); diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index ba3bdc0bb4..bd0d12106b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -1144,7 +1144,7 @@ namespace AZ if (!reflectionProbes.empty() && reflectionProbes[0]) { m_shaderResourceGroup->SetConstant(modelToWorldConstantIndex, reflectionProbes[0]->GetTransform()); - m_shaderResourceGroup->SetConstant(modelToWorldInverseConstantIndex, reflectionProbes[0]->GetTransform().GetInverse()); + m_shaderResourceGroup->SetConstant(modelToWorldInverseConstantIndex, Matrix3x4::CreateFromTransform(reflectionProbes[0]->GetTransform()).GetInverseFull()); m_shaderResourceGroup->SetConstant(outerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetOuterObbWs().GetHalfLengths()); m_shaderResourceGroup->SetConstant(innerObbHalfLengthsConstantIndex, reflectionProbes[0]->GetInnerObbWs().GetHalfLengths()); m_shaderResourceGroup->SetConstant(useReflectionProbeConstantIndex, true); From ceed8f692b9cfb7f8bd8c50300c1505c7c75066d Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 21 Sep 2021 17:16:27 -0700 Subject: [PATCH 61/84] Do not assert if m_focusModeInterface can't be initialized Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzToolsFramework/Prefab/PrefabFocusHandler.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp index bdd1b63afd..f74029aa73 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp @@ -22,11 +22,6 @@ namespace AzToolsFramework::Prefab void PrefabFocusHandler::Initialize() { m_focusModeInterface = AZ::Interface::Get(); - AZ_Assert( - m_focusModeInterface, - "Prefab - PrefabFocusHandler - " - "Focus Mode Interface could not be found. " - "Check that it is being correctly initialized."); m_instanceEntityMapperInterface = AZ::Interface::Get(); AZ_Assert( @@ -59,7 +54,10 @@ namespace AzToolsFramework::Prefab m_focusedInstance = focusedInstance; m_focusedTemplateId = focusedInstance->get().GetTemplateId(); - m_focusModeInterface->SetFocusRoot(focusedInstance->get().GetContainerEntityId()); + if (m_focusModeInterface) + { + m_focusModeInterface->SetFocusRoot(focusedInstance->get().GetContainerEntityId()); + } return AZ::Success(); } From 5f73061227aacfce39c8bd37486dd2f7e6b873ec Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Tue, 21 Sep 2021 22:19:21 -0400 Subject: [PATCH 62/84] Adding client side on-parent-changed logic for Network Transform Component Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Components/NetworkTransformComponent.h | 4 +++- .../Components/NetworkTransformComponent.cpp | 17 ++++++++++++++++ .../Code/Tests/CommonHierarchySetup.h | 4 ---- Gems/Multiplayer/Code/Tests/MockInterfaces.h | 2 +- .../Code/Tests/ServerHierarchyTests.cpp | 20 ++++++++----------- 5 files changed, 29 insertions(+), 18 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h index d90e7cddfe..35bf6e9f50 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/Components/NetworkTransformComponent.h @@ -31,9 +31,11 @@ namespace Multiplayer private: void OnPreRender(float deltaTime); void OnCorrection(); - + void OnParentChanged(NetEntityId parentId); + EntityPreRenderEvent::Handler m_entityPreRenderEventHandler; EntityCorrectionEvent::Handler m_entityCorrectionEventHandler; + AZ::Event::Handler m_parentChangedEventHandler; Multiplayer::HostFrameId m_targetHostFrameId = HostFrameId(0); }; diff --git a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp index 9ef585a0a0..d284f100ff 100644 --- a/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Components/NetworkTransformComponent.cpp @@ -28,6 +28,7 @@ namespace Multiplayer NetworkTransformComponent::NetworkTransformComponent() : m_entityPreRenderEventHandler([this](float deltaTime) { OnPreRender(deltaTime); }) , m_entityCorrectionEventHandler([this]() { OnCorrection(); }) + , m_parentChangedEventHandler([this](NetEntityId parentId) { OnParentChanged(parentId); }) { ; } @@ -41,6 +42,7 @@ namespace Multiplayer { GetNetBindComponent()->AddEntityPreRenderEventHandler(m_entityPreRenderEventHandler); GetNetBindComponent()->AddEntityCorrectionEventHandler(m_entityCorrectionEventHandler); + ParentEntityIdAddEvent(m_parentChangedEventHandler); } void NetworkTransformComponent::OnDeactivate([[maybe_unused]] Multiplayer::EntityIsMigrating entityIsMigrating) @@ -97,6 +99,21 @@ namespace Multiplayer } } + void NetworkTransformComponent::OnParentChanged(NetEntityId parentId) + { + const ConstNetworkEntityHandle parentEntityHandle = GetNetworkEntityManager()->GetEntity(parentId); + if (parentEntityHandle.Exists()) + { + if (const AZ::Entity* parentEntity = parentEntityHandle.GetEntity()) + { + GetEntity()->GetTransform()->SetParent(parentEntity->GetId()); + } + } + else + { + GetEntity()->GetTransform()->SetParent(AZ::EntityId()); + } + } NetworkTransformComponentController::NetworkTransformComponentController(NetworkTransformComponent& parent) : NetworkTransformComponentControllerBase(parent) diff --git a/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h b/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h index 7fc1eef8b7..2deac1aa27 100644 --- a/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h +++ b/Gems/Multiplayer/Code/Tests/CommonHierarchySetup.h @@ -391,10 +391,6 @@ namespace Multiplayer SetupEntity(child.m_entity, child.m_netId, NetEntityRole::Authority); SetupEntity(childOfChild.m_entity, childOfChild.m_netId, NetEntityRole::Authority); - // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) - SetParentIdOnNetworkTransform(child.m_entity, root.m_netId); - SetParentIdOnNetworkTransform(childOfChild.m_entity, child.m_netId); - // Create an entity replicator for the child entity const NetworkEntityHandle childOfChildHandle(childOfChild.m_entity.get(), m_networkEntityTracker.get()); childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childOfChildHandle); diff --git a/Gems/Multiplayer/Code/Tests/MockInterfaces.h b/Gems/Multiplayer/Code/Tests/MockInterfaces.h index 375fe2c5ba..6466fbb555 100644 --- a/Gems/Multiplayer/Code/Tests/MockInterfaces.h +++ b/Gems/Multiplayer/Code/Tests/MockInterfaces.h @@ -101,7 +101,7 @@ namespace UnitTest MOCK_CONST_METHOD0(GetHostTimeMs, AZ::TimeMs()); MOCK_CONST_METHOD0(GetRewindingConnectionId, AzNetworking::ConnectionId()); MOCK_CONST_METHOD1(GetHostFrameIdForRewindingConnection, Multiplayer::HostFrameId(AzNetworking::ConnectionId)); - MOCK_METHOD3(AlterTime, void(Multiplayer::HostFrameId, AZ::TimeMs, AzNetworking::ConnectionId)); + MOCK_METHOD4(AlterTime, void (Multiplayer::HostFrameId, AZ::TimeMs, float, AzNetworking::ConnectionId)); MOCK_METHOD1(SyncEntitiesToRewindState, void(const AZ::Aabb&)); MOCK_METHOD0(ClearRewoundEntities, void()); }; diff --git a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp index c262782006..70859909b3 100644 --- a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp @@ -109,7 +109,7 @@ namespace Multiplayer TEST_F(ServerSimpleHierarchyTests, Child_Has_Root_Cleared_On_Detach) { - // now detach the child + // now detach the child m_child->m_entity->FindComponent()->SetParent(AZ::EntityId()); EXPECT_EQ( @@ -165,7 +165,7 @@ namespace Multiplayer m_root->m_entity->FindComponent()->IsHierarchyEnabled(), true ); - + StopEntity(m_root->m_entity); m_root->m_entity->Deactivate(); @@ -183,7 +183,7 @@ namespace Multiplayer m_child->m_entity->FindComponent()->IsHierarchyEnabled(), true ); - + StopEntity(m_child->m_entity); m_child->m_entity->Deactivate(); @@ -435,6 +435,9 @@ namespace Multiplayer CreateBranchedHierarchy(*m_root, *m_child, *m_childOfChild, *m_child2, *m_childOfChild2, *m_child2OfChild2); + m_child2->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); + m_childOfChild2->m_entity->FindComponent()->SetParent(m_child2->m_entity->GetId()); + m_child2OfChild2->m_entity->FindComponent()->SetParent(m_child2->m_entity->GetId()); m_child->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); m_childOfChild->m_entity->FindComponent()->SetParent(m_child->m_entity->GetId()); // now the entities are under one hierarchy @@ -470,13 +473,6 @@ namespace Multiplayer SetupEntity(childOfChild2.m_entity, childOfChild2.m_netId, NetEntityRole::Authority); SetupEntity(child2OfChild2.m_entity, child2OfChild2.m_netId, NetEntityRole::Authority); - // we need a parent-id value to be present in NetworkTransformComponent (which is in client mode and doesn't have a controller) - SetParentIdOnNetworkTransform(child.m_entity, root.m_netId); - SetParentIdOnNetworkTransform(childOfChild.m_entity, child.m_netId); - SetParentIdOnNetworkTransform(child2.m_entity, root.m_netId); - SetParentIdOnNetworkTransform(childOfChild2.m_entity, child2.m_netId); - SetParentIdOnNetworkTransform(child2OfChild2.m_entity, child2.m_netId); - // Create entity replicators const NetworkEntityHandle childOfChild2Handle(childOfChild2.m_entity.get(), m_networkEntityTracker.get()); childOfChild.m_replicator = AZStd::make_unique(*m_entityReplicationManager, m_mockConnection.get(), NetEntityRole::Client, childOfChild2Handle); @@ -1014,8 +1010,8 @@ namespace Multiplayer CreateDeepHierarchy(*m_root, *m_child, *m_childOfChild); - m_root->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); - m_childOfChild->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); + m_child->m_entity->FindComponent()->SetParent(m_root->m_entity->GetId()); + m_childOfChild->m_entity->FindComponent()->SetParent(m_child->m_entity->GetId()); // now the entities are under one hierarchy } From 9bd23dc5d8b8f6ca52991f6693ebbfd4cddcac50 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 22 Sep 2021 00:04:55 -0500 Subject: [PATCH 63/84] reverting call to AWSNativeSDKInit::InitializationManager::Shutdown() Signed-off-by: Guthrie Adams --- Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp b/Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp index 2dad7cc3cc..d33f37a2d7 100644 --- a/Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp +++ b/Gems/HttpRequestor/Code/Source/HttpRequestManager.cpp @@ -49,7 +49,6 @@ namespace HttpRequestor { m_thread.join(); } - AWSNativeSDKInit::InitializationManager::Shutdown(); } void Manager::AddRequest(Parameters && httpRequestParameters) From 7db46da755e4422ca1523e4319ebe1a5e41770c2 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 22 Sep 2021 00:35:19 -0500 Subject: [PATCH 64/84] updating SMC Linux config Signed-off-by: Guthrie Adams --- .../Platform/Android/tool_dependencies_android.cmake | 10 ---------- .../Linux/ShaderManagementConsole_Traits_Linux.h | 11 +++++++++++ .../Linux/ShaderManagementConsole_Traits_Platform.h | 10 ++++++++++ .../Source/Platform/Linux/platform_linux_files.cmake | 2 ++ .../Source/Platform/iOS/tool_dependencies_ios.cmake | 10 ---------- 5 files changed, 23 insertions(+), 20 deletions(-) delete mode 100644 Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Android/tool_dependencies_android.cmake create mode 100644 Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/ShaderManagementConsole_Traits_Linux.h create mode 100644 Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/ShaderManagementConsole_Traits_Platform.h delete mode 100644 Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/iOS/tool_dependencies_ios.cmake diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Android/tool_dependencies_android.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Android/tool_dependencies_android.cmake deleted file mode 100644 index 5bf4d7cb7e..0000000000 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Android/tool_dependencies_android.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# -# 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(GEM_DEPENDENCIES -) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/ShaderManagementConsole_Traits_Linux.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/ShaderManagementConsole_Traits_Linux.h new file mode 100644 index 0000000000..355b135f50 --- /dev/null +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/ShaderManagementConsole_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 #define AZ_TRAIT_SHADER_MANAGEMENT_CONSOLE_EXT "" + diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/ShaderManagementConsole_Traits_Platform.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/ShaderManagementConsole_Traits_Platform.h new file mode 100644 index 0000000000..d381cc79d0 --- /dev/null +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/ShaderManagementConsole_Traits_Platform.h @@ -0,0 +1,10 @@ +/* + * 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 diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/platform_linux_files.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/platform_linux_files.cmake index c2c5a11c4c..11babcdf15 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/platform_linux_files.cmake +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/platform_linux_files.cmake @@ -7,4 +7,6 @@ # set(FILES + ShaderManagementConsole_Traits_Platform.h + ShaderManagementConsole_Traits_Linux.h ) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/iOS/tool_dependencies_ios.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/iOS/tool_dependencies_ios.cmake deleted file mode 100644 index 5bf4d7cb7e..0000000000 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/iOS/tool_dependencies_ios.cmake +++ /dev/null @@ -1,10 +0,0 @@ -# -# 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(GEM_DEPENDENCIES -) From 7910803e820ff75b32e21157f175e63d6d05b250 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 22 Sep 2021 01:38:12 -0500 Subject: [PATCH 65/84] removing ly_add_target_dependencies Signed-off-by: Guthrie Adams --- .../Tools/MaterialEditor/Code/CMakeLists.txt | 13 +++------ .../Linux/tool_dependencies_linux.cmake | 2 +- .../Platform/Mac/tool_dependencies_mac.cmake | 2 +- .../Windows/tool_dependencies_windows.cmake | 2 +- .../Code/CMakeLists.txt | 27 ++++++++++--------- .../Linux/tool_dependencies_linux.cmake | 2 +- .../Platform/Mac/tool_dependencies_mac.cmake | 2 +- .../Windows/tool_dependencies_windows.cmake | 2 +- 8 files changed, 24 insertions(+), 28 deletions(-) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt b/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt index 0206cebf8b..d585e81162 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt +++ b/Gems/Atom/Tools/MaterialEditor/Code/CMakeLists.txt @@ -93,12 +93,14 @@ ly_add_target( AUTOMOC FILES_CMAKE materialeditor_files.cmake - Source/Platform/${PAL_PLATFORM_NAME}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake + ${pal_source_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake + PLATFORM_INCLUDE_FILES + ${pal_source_dir}/tool_dependencies_${PAL_PLATFORM_NAME_LOWERCASE}.cmake INCLUDE_DIRECTORIES PRIVATE . Source - Source/Platform/${PAL_PLATFORM_NAME} + ${pal_source_dir} PUBLIC Include BUILD_DEPENDENCIES @@ -124,13 +126,6 @@ ly_create_alias(NAME MaterialEditor.Builders NAMESPACE Gem) # Editor opens up the MaterialEditor ly_add_dependencies(Editor Gem::MaterialEditor) -ly_add_target_dependencies( - TARGETS - MaterialEditor - DEPENDENCIES_FILES - Source/Platform/${PAL_PLATFORM_NAME}/tool_dependencies_${PAL_PLATFORM_NAME_LOWERCASE}.cmake -) - # Inject the project path into the MaterialEditor VS debugger command arguments if the build system being invoked # in a project centric view if(NOT PROJECT_NAME STREQUAL "O3DE") diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Linux/tool_dependencies_linux.cmake b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Linux/tool_dependencies_linux.cmake index 5bf4d7cb7e..b2885100e9 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Linux/tool_dependencies_linux.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Linux/tool_dependencies_linux.cmake @@ -6,5 +6,5 @@ # # -set(GEM_DEPENDENCIES +set(LY_RUNTIME_DEPENDENCIES ) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Mac/tool_dependencies_mac.cmake b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Mac/tool_dependencies_mac.cmake index 5bf4d7cb7e..b2885100e9 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Mac/tool_dependencies_mac.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Mac/tool_dependencies_mac.cmake @@ -6,5 +6,5 @@ # # -set(GEM_DEPENDENCIES +set(LY_RUNTIME_DEPENDENCIES ) diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/tool_dependencies_windows.cmake b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/tool_dependencies_windows.cmake index 374438983f..e1e811ff67 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/tool_dependencies_windows.cmake +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Platform/Windows/tool_dependencies_windows.cmake @@ -6,6 +6,6 @@ # # -set(GEM_DEPENDENCIES +set(LY_RUNTIME_DEPENDENCIES Gem::QtForPython.Editor ) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt b/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt index 5710a186d3..d384378b09 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/CMakeLists.txt @@ -43,6 +43,7 @@ ly_add_target( NAMESPACE Gem AUTOMOC AUTOUIC + AUTORCC FILES_CMAKE shadermanagementconsolewindow_files.cmake INCLUDE_DIRECTORIES @@ -64,6 +65,8 @@ ly_add_target( FILES_CMAKE shadermanagementconsole_files.cmake ${pal_source_dir}/platform_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake + PLATFORM_INCLUDE_FILES + ${pal_source_dir}/tool_dependencies_${PAL_PLATFORM_NAME_LOWERCASE}.cmake INCLUDE_DIRECTORIES PRIVATE . @@ -88,13 +91,6 @@ ly_set_gem_variant_to_load(TARGETS ShaderManagementConsole VARIANTS Tools) # Editor opens up the ShaderManagementConsole ly_add_dependencies(Editor Gem::ShaderManagementConsole) -ly_add_target_dependencies( - TARGETS - ShaderManagementConsole - DEPENDENCIES_FILES - Source/Platform/${PAL_PLATFORM_NAME}/tool_dependencies_${PAL_PLATFORM_NAME_LOWERCASE}.cmake -) - # Inject the project path into the ShaderManagementConsole VS debugger command arguments if the build system being invoked # in a project centric view if(NOT PROJECT_NAME STREQUAL "O3DE") @@ -104,9 +100,14 @@ endif() # Adds the ShaderManagementConsole target as a C preprocessor define so that it can be used as a Settings Registry # specialization in order to look up the generated .setreg which contains the dependencies # specified for the target. -set_source_files_properties( - Source/ShaderManagementConsoleApplication.cpp - PROPERTIES - COMPILE_DEFINITIONS - LY_CMAKE_TARGET="ShaderManagementConsole" -) +if(TARGET ShaderManagementConsole) + set_source_files_properties( + Source/ShaderManagementConsoleApplication.cpp + PROPERTIES + COMPILE_DEFINITIONS + LY_CMAKE_TARGET="ShaderManagementConsole" + ) +else() + message(FATAL_ERROR "Cannot set LY_CMAKE_TARGET define to ShaderManagementConsole as the target doesn't exist anymore." + " Perhaps it has been renamed") +endif() diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/tool_dependencies_linux.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/tool_dependencies_linux.cmake index 5bf4d7cb7e..b2885100e9 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/tool_dependencies_linux.cmake +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/tool_dependencies_linux.cmake @@ -6,5 +6,5 @@ # # -set(GEM_DEPENDENCIES +set(LY_RUNTIME_DEPENDENCIES ) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Mac/tool_dependencies_mac.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Mac/tool_dependencies_mac.cmake index 5bf4d7cb7e..b2885100e9 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Mac/tool_dependencies_mac.cmake +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Mac/tool_dependencies_mac.cmake @@ -6,5 +6,5 @@ # # -set(GEM_DEPENDENCIES +set(LY_RUNTIME_DEPENDENCIES ) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/tool_dependencies_windows.cmake b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/tool_dependencies_windows.cmake index 374438983f..e1e811ff67 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/tool_dependencies_windows.cmake +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Windows/tool_dependencies_windows.cmake @@ -6,6 +6,6 @@ # # -set(GEM_DEPENDENCIES +set(LY_RUNTIME_DEPENDENCIES Gem::QtForPython.Editor ) From b865d2aec1ead951a5ab303a591699409f59195c Mon Sep 17 00:00:00 2001 From: hultonha <82228511+hultonha@users.noreply.github.com> Date: Wed, 22 Sep 2021 09:08:24 +0100 Subject: [PATCH 66/84] Add support for camera reference frames to support camera yaw in certain situations (#4088) * proof of concept change for fixing camera yaw rotation being ignored Signed-off-by: hultonha * updates to fully support camera roll Signed-off-by: hultonha * small fixes for PR Signed-off-by: hultonha * undo changes in EditorCameraComponent Signed-off-by: hultonha * add test to verify interaction between editor viewport view entity change and modular camera controller Signed-off-by: hultonha * add additional tests for updated camera behaviors Signed-off-by: hultonha * revert change to Camera Gem Output Name Signed-off-by: hultonha * move location of new files Signed-off-by: hultonha * fix tab/spaces issue Signed-off-by: hultonha * remove static from potentially unused functions Signed-off-by: hultonha * set camera lib name in CMakeLists.txt file Signed-off-by: hultonha * cosmetic CMakeLists.txt change Signed-off-by: hultonha --- Code/Editor/CMakeLists.txt | 31 +++ .../EditorModularViewportCameraComposer.cpp | 21 ++ .../EditorModularViewportCameraComposer.h | 8 +- .../Camera/editor_lib_camera_test_files.cmake | 11 + .../Lib/Tests/Camera/test_EditorCamera.cpp | 225 ++++++++++++++++++ .../test_ModularViewportCameraController.cpp | 24 +- .../EditorTransformComponentSelection.cpp | 8 +- .../EditorTransformComponentSelection.h | 2 +- .../ModularViewportCameraController.h | 23 ++ ...odularViewportCameraControllerRequestBus.h | 10 + .../ModularViewportCameraController.cpp | 90 ++++++- Gems/Camera/Code/CMakeLists.txt | 1 + 12 files changed, 418 insertions(+), 36 deletions(-) create mode 100644 Code/Editor/Lib/Tests/Camera/editor_lib_camera_test_files.cmake create mode 100644 Code/Editor/Lib/Tests/Camera/test_EditorCamera.cpp diff --git a/Code/Editor/CMakeLists.txt b/Code/Editor/CMakeLists.txt index 5158ebc6d5..5884795413 100644 --- a/Code/Editor/CMakeLists.txt +++ b/Code/Editor/CMakeLists.txt @@ -254,4 +254,35 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_googletest( NAME Legacy::EditorLib.Tests ) + + ly_add_target( + NAME EditorLib.Camera.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} + NAMESPACE Legacy + FILES_CMAKE + Lib/Tests/Camera/editor_lib_camera_test_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + . + BUILD_DEPENDENCIES + PRIVATE + AZ::AzCore + AZ::AzTest + AZ::AzToolsFramework + AZ::AzTestShared + Legacy::EditorLib + Gem::Camera.Editor + Gem::AtomToolsFramework.Static + RUNTIME_DEPENDENCIES + Legacy::EditorLib + ) + + ly_add_source_properties( + SOURCES Lib/Tests/Camera/test_EditorCamera.cpp + PROPERTY COMPILE_DEFINITIONS + VALUES CAMERA_EDITOR_MODULE="$" + ) + + ly_add_googletest( + NAME Legacy::EditorLib.Camera.Tests + ) endif() diff --git a/Code/Editor/EditorModularViewportCameraComposer.cpp b/Code/Editor/EditorModularViewportCameraComposer.cpp index 498d6f3353..e375e98fb6 100644 --- a/Code/Editor/EditorModularViewportCameraComposer.cpp +++ b/Code/Editor/EditorModularViewportCameraComposer.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -34,10 +35,12 @@ namespace SandboxEditor : m_viewportId(viewportId) { EditorModularViewportCameraComposerNotificationBus::Handler::BusConnect(viewportId); + Camera::EditorCameraNotificationBus::Handler::BusConnect(); } EditorModularViewportCameraComposer::~EditorModularViewportCameraComposer() { + Camera::EditorCameraNotificationBus::Handler::BusDisconnect(); EditorModularViewportCameraComposerNotificationBus::Handler::BusDisconnect(); } @@ -283,4 +286,22 @@ namespace SandboxEditor m_orbitCamera->SetOrbitInputChannelId(SandboxEditor::CameraOrbitChannelId()); m_orbitDollyMoveCamera->SetDollyInputChannelId(SandboxEditor::CameraOrbitDollyChannelId()); } + + void EditorModularViewportCameraComposer::OnViewportViewEntityChanged(const AZ::EntityId& viewEntityId) + { + if (viewEntityId.IsValid()) + { + AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity(); + AZ::TransformBus::EventResult(worldFromLocal, viewEntityId, &AZ::TransformBus::Events::GetWorldTM); + + AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event( + m_viewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::SetReferenceFrame, + worldFromLocal); + } + else + { + AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event( + m_viewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::ClearReferenceFrame); + } + } } // namespace SandboxEditor diff --git a/Code/Editor/EditorModularViewportCameraComposer.h b/Code/Editor/EditorModularViewportCameraComposer.h index cb223d39e6..e6e71c976c 100644 --- a/Code/Editor/EditorModularViewportCameraComposer.h +++ b/Code/Editor/EditorModularViewportCameraComposer.h @@ -10,13 +10,16 @@ #include #include +#include #include #include namespace SandboxEditor { //! Type responsible for building the editor's modular viewport camera controller. - class EditorModularViewportCameraComposer : private EditorModularViewportCameraComposerNotificationBus::Handler + class EditorModularViewportCameraComposer + : private EditorModularViewportCameraComposerNotificationBus::Handler + , private Camera::EditorCameraNotificationBus::Handler { public: SANDBOX_API explicit EditorModularViewportCameraComposer(AzFramework::ViewportId viewportId); @@ -32,6 +35,9 @@ namespace SandboxEditor // EditorModularViewportCameraComposerNotificationBus overrides ... void OnEditorModularViewportCameraComposerSettingsChanged() override; + // EditorCameraNotificationBus overrides ... + void OnViewportViewEntityChanged(const AZ::EntityId& viewEntityId) override; + AZStd::shared_ptr m_firstPersonRotateCamera; AZStd::shared_ptr m_firstPersonPanCamera; AZStd::shared_ptr m_firstPersonTranslateCamera; diff --git a/Code/Editor/Lib/Tests/Camera/editor_lib_camera_test_files.cmake b/Code/Editor/Lib/Tests/Camera/editor_lib_camera_test_files.cmake new file mode 100644 index 0000000000..69d3e37f2d --- /dev/null +++ b/Code/Editor/Lib/Tests/Camera/editor_lib_camera_test_files.cmake @@ -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 +# +# + +set(FILES + test_EditorCamera.cpp +) diff --git a/Code/Editor/Lib/Tests/Camera/test_EditorCamera.cpp b/Code/Editor/Lib/Tests/Camera/test_EditorCamera.cpp new file mode 100644 index 0000000000..affe5794cc --- /dev/null +++ b/Code/Editor/Lib/Tests/Camera/test_EditorCamera.cpp @@ -0,0 +1,225 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +namespace UnitTest +{ + class EditorCameraTestEnvironment : public AZ::Test::GemTestEnvironment + { + // AZ::Test::GemTestEnvironment overrides ... + void AddGemsAndComponents() override; + }; + + void EditorCameraTestEnvironment::AddGemsAndComponents() + { + AddDynamicModulePaths({ CAMERA_EDITOR_MODULE }); + AddComponentDescriptors({ AzToolsFramework::Components::TransformComponent::CreateDescriptor() }); + } + + class EditorCameraFixture : public ::testing::Test + { + public: + AtomToolsFramework::ModularCameraViewportContext* m_cameraViewportContextView = nullptr; + AZStd::unique_ptr m_editorModularViewportCameraComposer; + AZStd::unique_ptr m_editorLibHandle; + AzFramework::ViewportControllerListPtr m_controllerList; + AZStd::unique_ptr m_entity; + + static const AzFramework::ViewportId TestViewportId; + + void SetUp() override + { + m_editorLibHandle = AZ::DynamicModuleHandle::Create("EditorLib"); + [[maybe_unused]] const bool loaded = m_editorLibHandle->Load(true); + AZ_Assert(loaded, "EditorLib could not be loaded"); + + m_controllerList = AZStd::make_shared(); + m_controllerList->RegisterViewportContext(TestViewportId); + + m_entity = AZStd::make_unique(); + m_entity->Init(); + m_entity->CreateComponent(); + m_entity->Activate(); + + m_editorModularViewportCameraComposer = AZStd::make_unique(TestViewportId); + + auto controller = m_editorModularViewportCameraComposer->CreateModularViewportCameraController(); + // set some overrides for the test + controller->SetCameraViewportContextBuilderCallback( + [this](AZStd::unique_ptr& cameraViewportContext) mutable + { + cameraViewportContext = AZStd::make_unique(); + m_cameraViewportContextView = cameraViewportContext.get(); + }); + + m_controllerList->Add(controller); + } + + void TearDown() override + { + m_editorModularViewportCameraComposer.reset(); + m_cameraViewportContextView = nullptr; + m_entity.reset(); + m_editorLibHandle = {}; + } + }; + + const AzFramework::ViewportId EditorCameraFixture::TestViewportId = AzFramework::ViewportId(1337); + + TEST_F(EditorCameraFixture, ModularViewportCameraControllerReferenceFrameUpdatedWhenViewportEntityisChanged) + { + // Given + const auto entityTransform = AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateRotationX(AZ::DegToRad(90.0f)), AZ::Vector3(10.0f, 5.0f, -2.0f)); + AZ::TransformBus::Event(m_entity->GetId(), &AZ::TransformBus::Events::SetWorldTM, entityTransform); + + // When + // imitate viewport entity changing + Camera::EditorCameraNotificationBus::Broadcast( + &Camera::EditorCameraNotificationBus::Events::OnViewportViewEntityChanged, m_entity->GetId()); + + // ensure the viewport updates after the viewport view entity change + const float deltaTime = 1.0f / 60.0f; + m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(deltaTime), AZ::ScriptTimePoint() }); + + // retrieve updated camera transform + const AZ::Transform cameraTransform = m_cameraViewportContextView->GetCameraTransform(); + + // Then + // camera transform matches that of the entity + EXPECT_THAT(cameraTransform, IsClose(entityTransform)); + } + + TEST_F(EditorCameraFixture, ReferenceFrameRemainsIdentityAfterExternalCameraTransformChangeWhenNotSet) + { + // Given + m_cameraViewportContextView->SetCameraTransform(AZ::Transform::CreateTranslation(AZ::Vector3(10.0f, 20.0f, 30.0f))); + + // When + AZ::Transform referenceFrame = AZ::Transform::CreateTranslation(AZ::Vector3(1.0f, 2.0f, 3.0f)); + AtomToolsFramework::ModularViewportCameraControllerRequestBus::EventResult( + referenceFrame, TestViewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::GetReferenceFrame); + + // Then + // reference frame is still the identity + EXPECT_THAT(referenceFrame, IsClose(AZ::Transform::CreateIdentity())); + } + + TEST_F(EditorCameraFixture, ExternalCameraTransformChangeWhenReferenceFrameIsSetUpdatesReferenceFrame) + { + // Given + const AZ::Transform referenceFrame = AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateRotationX(AZ::DegToRad(90.0f)), AZ::Vector3(1.0f, 2.0f, 3.0f)); + AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event( + TestViewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::SetReferenceFrame, referenceFrame); + + const AZ::Transform nextTransform = AZ::Transform::CreateTranslation(AZ::Vector3(10.0f, 20.0f, 30.0f)); + m_cameraViewportContextView->SetCameraTransform(nextTransform); + + // When + AZ::Transform currentReferenceFrame = AZ::Transform::CreateTranslation(AZ::Vector3(1.0f, 2.0f, 3.0f)); + AtomToolsFramework::ModularViewportCameraControllerRequestBus::EventResult( + currentReferenceFrame, TestViewportId, + &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::GetReferenceFrame); + + // Then + EXPECT_THAT(currentReferenceFrame, IsClose(nextTransform)); + } + + TEST_F(EditorCameraFixture, ReferenceFrameReturnedToIdentityAfterClear) + { + // Given + const AZ::Transform referenceFrame = AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateRotationX(AZ::DegToRad(90.0f)), AZ::Vector3(1.0f, 2.0f, 3.0f)); + AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event( + TestViewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::SetReferenceFrame, referenceFrame); + + // When + AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event( + TestViewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::ClearReferenceFrame); + + AZ::Transform currentReferenceFrame = AZ::Transform::CreateTranslation(AZ::Vector3(1.0f, 2.0f, 3.0f)); + AtomToolsFramework::ModularViewportCameraControllerRequestBus::EventResult( + currentReferenceFrame, TestViewportId, + &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::GetReferenceFrame); + + // Then + EXPECT_THAT(currentReferenceFrame, IsClose(AZ::Transform::CreateIdentity())); + } + + TEST_F(EditorCameraFixture, InterpolateToTransform) + { + // When + AZ::Transform transformToInterpolateTo = AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateRotationZ(AZ::DegToRad(90.0f)), AZ::Vector3(20.0f, 40.0f, 60.0f)); + AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event( + TestViewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, + transformToInterpolateTo, 0.0f); + + // simulate interpolation + m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(0.5f), AZ::ScriptTimePoint() }); + m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(0.5f), AZ::ScriptTimePoint() }); + + const auto finalTransform = m_cameraViewportContextView->GetCameraTransform(); + + // Then + EXPECT_THAT(finalTransform, IsClose(transformToInterpolateTo)); + } + + TEST_F(EditorCameraFixture, InterpolateToTransformWithReferenceSpaceSet) + { + // Given + const AZ::Transform referenceFrame = AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateRotationX(AZ::DegToRad(90.0f)), AZ::Vector3(1.0f, 2.0f, 3.0f)); + AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event( + TestViewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::SetReferenceFrame, referenceFrame); + + AZ::Transform transformToInterpolateTo = AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateRotationZ(AZ::DegToRad(90.0f)), AZ::Vector3(20.0f, 40.0f, 60.0f)); + + // When + AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event( + TestViewportId, &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, + transformToInterpolateTo, 0.0f); + + // simulate interpolation + m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(0.5f), AZ::ScriptTimePoint() }); + m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(0.5f), AZ::ScriptTimePoint() }); + + AZ::Transform currentReferenceFrame = AZ::Transform::CreateTranslation(AZ::Vector3(1.0f, 2.0f, 3.0f)); + AtomToolsFramework::ModularViewportCameraControllerRequestBus::EventResult( + currentReferenceFrame, TestViewportId, + &AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::GetReferenceFrame); + + const auto finalTransform = m_cameraViewportContextView->GetCameraTransform(); + + // Then + EXPECT_THAT(finalTransform, IsClose(transformToInterpolateTo)); + EXPECT_THAT(currentReferenceFrame, IsClose(AZ::Transform::CreateIdentity())); + } +} // namespace UnitTest + +// required to support running integration tests with the Camera Gem +AZTEST_EXPORT int AZ_UNIT_TEST_HOOK_NAME(int argc, char** argv) +{ + ::testing::InitGoogleMock(&argc, argv); + AZ::Test::printUnusedParametersWarning(argc, argv); + AZ::Test::addTestEnvironments({ new UnitTest::EditorCameraTestEnvironment() }); + int result = RUN_ALL_TESTS(); + return result; +} + +IMPLEMENT_TEST_EXECUTABLE_MAIN(); diff --git a/Code/Editor/Lib/Tests/test_ModularViewportCameraController.cpp b/Code/Editor/Lib/Tests/test_ModularViewportCameraController.cpp index ce5564c7f6..157291cfc2 100644 --- a/Code/Editor/Lib/Tests/test_ModularViewportCameraController.cpp +++ b/Code/Editor/Lib/Tests/test_ModularViewportCameraController.cpp @@ -58,28 +58,6 @@ namespace UnitTest return true; } - class TestModularCameraViewportContextImpl : public AtomToolsFramework::ModularCameraViewportContext - { - public: - AZ::Transform GetCameraTransform() const override - { - return m_cameraTransform; - } - - void SetCameraTransform(const AZ::Transform& transform) override - { - m_cameraTransform = transform; - } - - void ConnectViewMatrixChangedHandler(AZ::RPI::ViewportContext::MatrixChangedEvent::Handler&) override - { - // noop - } - - private: - AZ::Transform m_cameraTransform = AZ::Transform::CreateIdentity(); - }; - class ModularViewportCameraControllerFixture : public AllocatorsTestFixture { public: @@ -146,7 +124,7 @@ namespace UnitTest controller->SetCameraViewportContextBuilderCallback( [this](AZStd::unique_ptr& cameraViewportContext) { - cameraViewportContext = AZStd::make_unique(); + cameraViewportContext = AZStd::make_unique(); m_cameraViewportContextView = cameraViewportContext.get(); }); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 27a77f9ce7..8157d369d2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -3642,7 +3642,7 @@ namespace AzToolsFramework } } - void EditorTransformComponentSelection::OnViewportViewEntityChanged(const AZ::EntityId& newViewId) + void EditorTransformComponentSelection::OnViewportViewEntityChanged(const AZ::EntityId& viewEntityId) { AZ_PROFILE_FUNCTION(AzToolsFramework); @@ -3650,12 +3650,12 @@ namespace AzToolsFramework // match the editor camera translation/orientation), record the entity id if we have // a manipulator tracking it (entity id exists in m_entityIdManipulator lookups) // and remove it when recreating manipulators (see InitializeManipulators) - if (newViewId.IsValid()) + if (viewEntityId.IsValid()) { - const auto entityIdLookupIt = m_entityIdManipulators.m_lookups.find(newViewId); + const auto entityIdLookupIt = m_entityIdManipulators.m_lookups.find(viewEntityId); if (entityIdLookupIt != m_entityIdManipulators.m_lookups.end()) { - m_editorCameraComponentEntityId = newViewId; + m_editorCameraComponentEntityId = viewEntityId; RegenerateManipulators(); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h index 935e80951a..6cc89b2d10 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h @@ -270,7 +270,7 @@ namespace AzToolsFramework void OnTransformChanged(const AZ::Transform& localTM, const AZ::Transform& worldTM) override; // Camera::EditorCameraNotificationBus overrides ... - void OnViewportViewEntityChanged(const AZ::EntityId& newViewId) override; + void OnViewportViewEntityChanged(const AZ::EntityId& viewEntityId) override; // EditorContextVisibilityNotificationBus overrides ... void OnEntityVisibilityChanged(bool visibility) override; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h index 42fe9a01c9..4956fbc1dc 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h @@ -116,11 +116,18 @@ namespace AtomToolsFramework // ModularViewportCameraControllerRequestBus overrides ... void InterpolateToTransform(const AZ::Transform& worldFromLocal, float lookAtDistance) override; AZStd::optional LookAtAfterInterpolation() const override; + AZ::Transform GetReferenceFrame() const override; + void SetReferenceFrame(const AZ::Transform& worldFromLocal) override; + void ClearReferenceFrame() override; private: // AzFramework::ViewportDebugDisplayEventBus overrides ... void DisplayViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override; + //! Update the reference frame after a change has been made to the camera + //! view without updating the internal camera via user input. + void RefreshReferenceFrame(); + //! The current mode the camera controller is in. enum class CameraMode { @@ -139,6 +146,8 @@ namespace AtomToolsFramework AzFramework::Camera m_camera; //!< The current camera state (pitch/yaw/position/look-distance). AzFramework::Camera m_targetCamera; //!< The target (next) camera state that m_camera is catching up to. + AzFramework::Camera m_previousCamera; //!< The state of the camera from the previous frame. + AZStd::optional m_storedCamera; //!< A potentially stored camera for when a custom reference frame is set. AzFramework::CameraSystem m_cameraSystem; //!< The camera system responsible for managing all CameraInputs. AzFramework::CameraProps m_cameraProps; //!< Camera properties to control rotate and translate smoothness. CameraControllerPriorityFn m_priorityFn; //!< Controls at what priority the camera controller should respond to events. @@ -147,6 +156,7 @@ namespace AtomToolsFramework CameraMode m_cameraMode = CameraMode::Control; //!< The current mode the camera is operating in. AZStd::optional m_lookAtAfterInterpolation; //!< The look at point after an interpolation has finished. //!< Will be cleared when the view changes (camera looks away). + AZ::Transform m_referenceFrameOverride = AZ::Transform::CreateIdentity(); //!< //! Flag to prevent circular updates of the camera transform (while the viewport transform is being updated internally). bool m_updatingTransformInternally = false; //! Listen for camera view changes outside of the camera controller. @@ -154,4 +164,17 @@ namespace AtomToolsFramework //! The current instance of the modular camera viewport context. AZStd::unique_ptr m_modularCameraViewportContext; }; + + //! Placeholder implementation for ModularCameraViewportContext (useful for verifying the interface). + class PlaceholderModularCameraViewportContextImpl : public AtomToolsFramework::ModularCameraViewportContext + { + public: + AZ::Transform GetCameraTransform() const override; + void SetCameraTransform(const AZ::Transform& transform) override; + void ConnectViewMatrixChangedHandler(AZ::RPI::ViewportContext::MatrixChangedEvent::Handler& handler) override; + + private: + AZ::Transform m_cameraTransform = AZ::Transform::CreateIdentity(); + AZ::RPI::ViewportContext::MatrixChangedEvent m_viewMatrixChangedEvent; + }; } // namespace AtomToolsFramework diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h index ae4dc5dd25..388d24164a 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h @@ -35,6 +35,16 @@ namespace AtomToolsFramework //! Look at point after an interpolation has finished and no translation has occurred. virtual AZStd::optional LookAtAfterInterpolation() const = 0; + //! Return the current reference frame. + //! @note If a reference frame has not been set or a frame has been cleared, this is just the identity. + virtual AZ::Transform GetReferenceFrame() const = 0; + + //! Set a new reference frame other than the identity for the camera controller. + virtual void SetReferenceFrame(const AZ::Transform& worldFromLocal) = 0; + + //! Clear the current reference frame to restore the identity. + virtual void ClearReferenceFrame() = 0; + protected: ~ModularViewportCameraControllerRequests() = default; }; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp index 4419e0c49f..bcc9a08f77 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/ModularViewportCameraController.cpp @@ -30,6 +30,18 @@ namespace AtomToolsFramework ""); AZ_CVAR(float, ed_cameraSystemOrbitPointSize, 0.1f, nullptr, AZ::ConsoleFunctorFlags::Null, ""); + AZ::Transform TransformFromMatrix4x4(const AZ::Matrix4x4& matrix) + { + const auto rotation = AZ::Matrix3x3::CreateFromMatrix4x4(matrix); + const auto translation = matrix.GetTranslation(); + return AZ::Transform::CreateFromMatrix3x3AndTranslation(rotation, translation); + } + + AZ::Matrix4x4 Matrix4x4FromTransform(const AZ::Transform& transform) + { + return AZ::Matrix4x4::CreateFromQuaternionAndTranslation(transform.GetRotation(), transform.GetTranslation()); + } + // debug void DrawPreviewAxis(AzFramework::DebugDisplayRequests& display, const AZ::Transform& transform, const float axisLength) { @@ -167,11 +179,19 @@ namespace AtomToolsFramework controller->SetupCameraControllerPriority(m_priorityFn); controller->SetupCameraControllerViewportContext(m_modularCameraViewportContext); - auto handleCameraChange = [this](const AZ::Matrix4x4&) + auto handleCameraChange = [this]([[maybe_unused]] const AZ::Matrix4x4& cameraView) { // ignore these updates if the camera is being updated internally if (!m_updatingTransformInternally) { + if (m_storedCamera.has_value()) + { + // if an external change occurs ensure we update the stored reference frame if one is set + RefreshReferenceFrame(); + return; + } + + m_previousCamera = m_targetCamera; UpdateCameraFromTransform(m_targetCamera, m_modularCameraViewportContext->GetCameraTransform()); m_camera = m_targetCamera; } @@ -231,7 +251,7 @@ namespace AtomToolsFramework } } - m_modularCameraViewportContext->SetCameraTransform(m_camera.Transform()); + m_modularCameraViewportContext->SetCameraTransform(m_referenceFrameOverride * m_camera.Transform()); } else if (m_cameraMode == CameraMode::Animation) { @@ -240,6 +260,8 @@ namespace AtomToolsFramework return t * t * t * (t * (t * 6.0f - 15.0f) + 10.0f); }; + m_cameraAnimation.m_time = AZ::GetClamp(m_cameraAnimation.m_time + event.m_deltaTime.count(), 0.0f, 1.0f); + const auto& [transformStart, transformEnd, animationTime] = m_cameraAnimation; const float transitionTime = smootherStepFn(animationTime); @@ -253,14 +275,13 @@ namespace AtomToolsFramework m_camera.m_lookAt = current.GetTranslation(); m_targetCamera = m_camera; + m_modularCameraViewportContext->SetCameraTransform(current); + if (animationTime >= 1.0f) { m_cameraMode = CameraMode::Control; + RefreshReferenceFrame(); } - - m_cameraAnimation.m_time = AZ::GetClamp(animationTime + event.m_deltaTime.count(), 0.0f, 1.0f); - - m_modularCameraViewportContext->SetCameraTransform(current); } m_updatingTransformInternally = false; @@ -280,7 +301,7 @@ namespace AtomToolsFramework void ModularViewportCameraControllerInstance::InterpolateToTransform(const AZ::Transform& worldFromLocal, const float lookAtDistance) { m_cameraMode = CameraMode::Animation; - m_cameraAnimation = CameraAnimation{ m_camera.Transform(), worldFromLocal, 0.0f }; + m_cameraAnimation = CameraAnimation{ m_referenceFrameOverride * m_camera.Transform(), worldFromLocal, 0.0f }; m_lookAtAfterInterpolation = worldFromLocal.GetTranslation() + worldFromLocal.GetBasisY() * lookAtDistance; } @@ -288,4 +309,59 @@ namespace AtomToolsFramework { return m_lookAtAfterInterpolation; } + + AZ::Transform ModularViewportCameraControllerInstance::GetReferenceFrame() const + { + return m_referenceFrameOverride; + } + + void ModularViewportCameraControllerInstance::SetReferenceFrame(const AZ::Transform& worldFromLocal) + { + if (!m_storedCamera.has_value()) + { + m_storedCamera = m_previousCamera; + } + + m_referenceFrameOverride = worldFromLocal; + m_targetCamera.m_pitch = 0.0f; + m_targetCamera.m_yaw = 0.0f; + m_targetCamera.m_lookAt = AZ::Vector3::CreateZero(); + m_targetCamera.m_lookDist = 0.0f; + m_camera = m_targetCamera; + } + + void ModularViewportCameraControllerInstance::ClearReferenceFrame() + { + m_referenceFrameOverride = AZ::Transform::CreateIdentity(); + + if (m_storedCamera.has_value()) + { + m_targetCamera = m_storedCamera.value(); + m_camera = m_targetCamera; + } + + m_storedCamera.reset(); + } + + void ModularViewportCameraControllerInstance::RefreshReferenceFrame() + { + m_referenceFrameOverride = m_modularCameraViewportContext->GetCameraTransform() * m_camera.Transform().GetInverse(); + } + + AZ::Transform PlaceholderModularCameraViewportContextImpl::GetCameraTransform() const + { + return m_cameraTransform; + } + + void PlaceholderModularCameraViewportContextImpl::SetCameraTransform(const AZ::Transform& transform) + { + m_cameraTransform = transform; + m_viewMatrixChangedEvent.Signal(AzFramework::CameraViewFromCameraTransform(Matrix4x4FromTransform(transform))); + } + + void PlaceholderModularCameraViewportContextImpl::ConnectViewMatrixChangedHandler( + AZ::RPI::ViewportContext::MatrixChangedEvent::Handler& handler) + { + handler.Connect(m_viewMatrixChangedEvent); + } } // namespace AtomToolsFramework diff --git a/Gems/Camera/Code/CMakeLists.txt b/Gems/Camera/Code/CMakeLists.txt index f34ac8a698..c9f0bf768f 100644 --- a/Gems/Camera/Code/CMakeLists.txt +++ b/Gems/Camera/Code/CMakeLists.txt @@ -57,6 +57,7 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) PRIVATE AZ::AzToolsFramework Gem::Camera.Static + Gem::AtomToolsFramework.Static RUNTIME_DEPENDENCIES Legacy::EditorCommon ) From 8b7439556096337988d476a026abb8d42f268270 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Wed, 22 Sep 2021 10:15:20 +0200 Subject: [PATCH 67/84] EMotionFX: Basic profile instrumentation for anim graph (#4240) Signed-off-by: Benjamin Jillich --- Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp | 4 ++++ .../Code/EMotionFX/Source/AnimGraphInstance.cpp | 10 ++++++++++ .../Code/EMotionFX/Source/AnimGraphMotionNode.cpp | 4 ++++ .../Code/EMotionFX/Source/AnimGraphStateMachine.cpp | 8 ++++++++ .../Code/EMotionFX/Source/BlendSpace1DNode.cpp | 4 ++++ .../Code/EMotionFX/Source/BlendSpace2DNode.cpp | 4 ++++ Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.cpp | 9 ++++++++- .../Code/EMotionFX/Source/BlendTreeBlend2Node.cpp | 5 ++++- Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp | 2 ++ 9 files changed, 48 insertions(+), 2 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp index 5a4ca95670..b547b92306 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorInstance.cpp @@ -372,6 +372,8 @@ namespace EMotionFX // updates the skinning matrices of all nodes void ActorInstance::UpdateSkinningMatrices() { + AZ_PROFILE_SCOPE(Animation, "ActorInstance::UpdateSkinningMatrices"); + AZ::Matrix3x4* skinningMatrices = m_transformData->GetSkinningMatrices(); const Pose* pose = m_transformData->GetCurrentPose(); @@ -596,6 +598,8 @@ namespace EMotionFX // update the bounding volume void ActorInstance::UpdateBounds(size_t geomLODLevel, EBoundsType boundsType, uint32 itemFrequency) { + AZ_PROFILE_SCOPE(Animation, "ActorInstance::UpdateBounds"); + // depending on the bounding volume update type switch (boundsType) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp index d0c77721d1..7f9e8ba6fc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphInstance.cpp @@ -218,6 +218,8 @@ namespace EMotionFX // output the results into the internal pose object void AnimGraphInstance::Output(Pose* outputPose) { + AZ_PROFILE_SCOPE(Animation, "AnimGraphInstance::Output"); + // reset max used const uint32 threadIndex = m_actorInstance->GetThreadIndex(); AnimGraphPosePool& posePool = GetEMotionFX().GetThreadData(threadIndex)->GetPosePool(); @@ -854,6 +856,8 @@ namespace EMotionFX // synchronize all nodes, based on sync tracks etc void AnimGraphInstance::Update(float timePassedInSeconds) { + AZ_PROFILE_SCOPE(Animation, "AnimGraphInstance::Update"); + // pass 0: (Optional, networking only) When this instance is shared between network, restore the instance using an animgraph snapshot. if (m_snapshot) { @@ -940,6 +944,8 @@ namespace EMotionFX // reset all node pose ref counts void AnimGraphInstance::ResetPoseRefCountsForAllNodes() { + AZ_PROFILE_SCOPE(Animation, "AnimGraphInstance::ResetPoseRefCountsForAllNodes"); + const size_t numNodes = m_animGraph->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { @@ -951,6 +957,8 @@ namespace EMotionFX // reset all node pose ref counts void AnimGraphInstance::ResetRefDataRefCountsForAllNodes() { + AZ_PROFILE_SCOPE(Animation, "AnimGraphInstance::ResetRefDataRefCountsForAllNodes"); + const size_t numNodes = m_animGraph->GetNumNodes(); for (size_t i = 0; i < numNodes; ++i) { @@ -962,6 +970,8 @@ namespace EMotionFX // reset all node flags void AnimGraphInstance::ResetFlagsForAllObjects() { + AZ_PROFILE_SCOPE(Animation, "AnimGraphInstance::ResetFlagsForAllObjects"); + MCore::MemSet(m_objectFlags.data(), 0, sizeof(uint32) * m_objectFlags.size()); for (AnimGraphInstance* childInstance : m_childAnimGraphInstances) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.cpp index 6bcc69360b..c5e50ed9dd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphMotionNode.cpp @@ -394,6 +394,8 @@ namespace EMotionFX // the main process method of the final node void AnimGraphMotionNode::Output(AnimGraphInstance* animGraphInstance) { + AZ_PROFILE_SCOPE(Animation, "AnimGraphMotionNode::Output"); + // if this motion is disabled, output the bind pose if (m_disabled) { @@ -537,6 +539,8 @@ namespace EMotionFX void AnimGraphMotionNode::UniqueData::Update() { + AZ_PROFILE_SCOPE(Animation, "AnimGraphMotionNode::Update"); + AnimGraphMotionNode* motionNode = azdynamic_cast(m_object); AZ_Assert(motionNode, "Unique data linked to incorrect node type."); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.cpp index 9b4c2d07ac..0024d97a45 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/AnimGraphStateMachine.cpp @@ -92,6 +92,8 @@ namespace EMotionFX void AnimGraphStateMachine::Output(AnimGraphInstance* animGraphInstance) { + AZ_PROFILE_SCOPE(Animation, "AnimGraphStateMachine::Update"); + ActorInstance* actorInstance = animGraphInstance->GetActorInstance(); AnimGraphPose* outputPose = nullptr; @@ -476,6 +478,8 @@ namespace EMotionFX void AnimGraphStateMachine::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { + AZ_PROFILE_SCOPE(Animation, "AnimGraphStateMachine::Update"); + UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); // Defer switch to entry state. @@ -622,6 +626,8 @@ namespace EMotionFX void AnimGraphStateMachine::PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { + AZ_PROFILE_SCOPE(Animation, "AnimGraphStateMachine::PostUpdate"); + RequestRefDatas(animGraphInstance); UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); AnimGraphRefCountedData* data = uniqueData->GetRefCountedData(); @@ -1344,6 +1350,8 @@ namespace EMotionFX void AnimGraphStateMachine::TopDownUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { + AZ_PROFILE_SCOPE(Animation, "AnimGraphStateMachine::TopDownUpdate"); + UniqueData* uniqueData = static_cast(FindOrCreateUniqueNodeData(animGraphInstance)); if (!IsTransitioning(uniqueData)) diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpace1DNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpace1DNode.cpp index 0e823075a4..deeb593c96 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpace1DNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpace1DNode.cpp @@ -166,6 +166,8 @@ namespace EMotionFX void BlendSpace1DNode::Output(AnimGraphInstance* animGraphInstance) { + AZ_PROFILE_SCOPE(Animation, "BlendSpace1DNode::Output"); + if (!AnimGraphInstanceExists(animGraphInstance)) { return; @@ -276,6 +278,8 @@ namespace EMotionFX void BlendSpace1DNode::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { + AZ_PROFILE_SCOPE(Animation, "BlendSpace1DNode::Update"); + if (!m_disabled) { EMotionFX::BlendTreeConnection* paramConnection = GetInputPort(INPUTPORT_VALUE).m_connection; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpace2DNode.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpace2DNode.cpp index 03a7552410..66366087f8 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpace2DNode.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendSpace2DNode.cpp @@ -282,6 +282,8 @@ namespace EMotionFX void BlendSpace2DNode::Output(AnimGraphInstance* animGraphInstance) { + AZ_PROFILE_SCOPE(Animation, "BlendSpace2DNode::Output"); + if (!AnimGraphInstanceExists(animGraphInstance)) { return; @@ -402,6 +404,8 @@ namespace EMotionFX void BlendSpace2DNode::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { + AZ_PROFILE_SCOPE(Animation, "BlendSpace2DNode::Update"); + if (!AnimGraphInstanceExists(animGraphInstance)) { return; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.cpp index f742696275..a4109a5a60 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTree.cpp @@ -116,10 +116,11 @@ namespace EMotionFX return nullptr; } - // process the blend tree and calculate its output void BlendTree::Output(AnimGraphInstance* animGraphInstance) { + AZ_PROFILE_SCOPE(Animation, "BlendTree::Output"); + AZ_Assert(m_finalNode, "There should always be a final node. Something seems to be wrong with the blend tree creation."); // get the output pose @@ -164,6 +165,8 @@ namespace EMotionFX // post sync update void BlendTree::PostUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { + AZ_PROFILE_SCOPE(Animation, "AnimGraphStateMachine::PostUpdate"); + // if this node is disabled, exit if (m_disabled) { @@ -212,6 +215,8 @@ namespace EMotionFX // update all nodes void BlendTree::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { + AZ_PROFILE_SCOPE(Animation, "BlendTree::Update"); + // if this node is disabled, output the bind pose if (m_disabled) { @@ -256,6 +261,8 @@ namespace EMotionFX // top down update void BlendTree::TopDownUpdate(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { + AZ_PROFILE_SCOPE(Animation, "BlendTree::TopDownUpdate"); + // get the final node AnimGraphNode* finalNode = GetRealFinalNode(); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2Node.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2Node.cpp index 06223d4b14..b14f72c7c3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2Node.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/BlendTreeBlend2Node.cpp @@ -45,6 +45,8 @@ namespace EMotionFX void BlendTreeBlend2Node::Update(AnimGraphInstance* animGraphInstance, float timePassedInSeconds) { + AZ_PROFILE_SCOPE(Animation, "BlendTreeBlend2Node::Update"); + if (m_disabled) { AnimGraphNodeData* uniqueData = FindOrCreateUniqueNodeData(animGraphInstance); @@ -88,9 +90,10 @@ namespace EMotionFX } } - void BlendTreeBlend2Node::Output(AnimGraphInstance* animGraphInstance) { + AZ_PROFILE_SCOPE(Animation, "BlendTreeBlend2Node::Output"); + if (m_disabled) { RequestPoses(animGraphInstance); diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp index a6ddb776c2..237389312f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/MotionSystem.cpp @@ -147,6 +147,8 @@ namespace EMotionFX // update motion queue and instances void MotionSystem::Update(float timePassed, bool updateNodes) { + AZ_PROFILE_SCOPE(Animation, "MotionSystem::Update"); + MCORE_UNUSED(updateNodes); // update the motion queue From ce1614bd575b1b877b50dfba88c3c49c933eb4a9 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Wed, 22 Sep 2021 08:35:35 -0400 Subject: [PATCH 68/84] Merged with dev Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- Gems/Multiplayer/Code/Tests/MockInterfaces.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Gems/Multiplayer/Code/Tests/MockInterfaces.h b/Gems/Multiplayer/Code/Tests/MockInterfaces.h index 6466fbb555..42e034d234 100644 --- a/Gems/Multiplayer/Code/Tests/MockInterfaces.h +++ b/Gems/Multiplayer/Code/Tests/MockInterfaces.h @@ -40,7 +40,10 @@ namespace UnitTest class MockNetworkEntityManager : public Multiplayer::INetworkEntityManager { public: - MOCK_METHOD4(CreateEntitiesImmediate, EntityList (const Multiplayer::PrefabEntityId&, Multiplayer::NetEntityRole, const AZ::Transform&, Multiplayer::AutoActivate)); + MOCK_METHOD2(RequestNetSpawnableInstantiation, AZStd::unique_ptr (const AZ::Data::Asset&, const AZ::Transform&)); + MOCK_METHOD4( + CreateEntitiesImmediate, + EntityList (const Multiplayer::PrefabEntityId&, Multiplayer::NetEntityRole, const AZ::Transform&, Multiplayer::AutoActivate)); MOCK_CONST_METHOD1(GetNetEntityIdById, Multiplayer::NetEntityId (const AZ::EntityId&)); MOCK_METHOD0(GetNetworkEntityTracker, Multiplayer::NetworkEntityTracker* ()); MOCK_METHOD0(GetNetworkEntityAuthorityTracker, Multiplayer::NetworkEntityAuthorityTracker* ()); From 6a1b685ea7028185554c8cbf1f670fd0fc896d8b Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 22 Sep 2021 09:03:24 -0500 Subject: [PATCH 69/84] fixing duplicate define Signed-off-by: Guthrie Adams --- .../Platform/Linux/ShaderManagementConsole_Traits_Linux.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/ShaderManagementConsole_Traits_Linux.h b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/ShaderManagementConsole_Traits_Linux.h index 355b135f50..2897402f04 100644 --- a/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/ShaderManagementConsole_Traits_Linux.h +++ b/Gems/Atom/Tools/ShaderManagementConsole/Code/Source/Platform/Linux/ShaderManagementConsole_Traits_Linux.h @@ -7,5 +7,5 @@ */ #pragma once -#define #define AZ_TRAIT_SHADER_MANAGEMENT_CONSOLE_EXT "" +#define AZ_TRAIT_SHADER_MANAGEMENT_CONSOLE_EXT "" From a93c1758f4b8d94d1539f598ccb317006c8fb37d Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 22 Sep 2021 11:03:46 -0500 Subject: [PATCH 70/84] restoring immediate rpi initialization and window creation to fix broken tests Signed-off-by: Guthrie Adams --- .../Code/Source/BootstrapSystemComponent.cpp | 5 +++- .../Application/AtomToolsApplication.h | 7 ----- .../Application/AtomToolsApplication.cpp | 27 ++++++++----------- 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp index e3749175bc..8a6b7db1ca 100644 --- a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp +++ b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp @@ -176,7 +176,10 @@ namespace AZ m_isAssetCatalogLoaded = true; - RPI::RPISystemInterface::Get()->InitializeSystemAssets(); + if (!RPI::RPISystemInterface::Get()->IsInitialized()) + { + RPI::RPISystemInterface::Get()->InitializeSystemAssets(); + } if (!RPI::RPISystemInterface::Get()->IsInitialized()) { diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h index f87aca641d..d55755a242 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Application/AtomToolsApplication.h @@ -16,7 +16,6 @@ #include #include -#include #include #include @@ -36,7 +35,6 @@ namespace AtomToolsFramework , public AzQtComponents::AzQtApplication , protected AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler , protected AzFramework::AssetSystemStatusBus::Handler - , protected AzFramework::AssetCatalogEventBus::Handler , protected AzToolsFramework::EditorPythonConsoleNotificationBus::Handler , protected AZ::UserSettingsOwnerRequestBus::Handler , protected AtomToolsMainWindowNotificationBus::Handler @@ -69,11 +67,6 @@ namespace AtomToolsFramework void OnMainWindowClosing() override; ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// - // AzFramework::AssetCatalogEventBus::Handler overrides ... - void OnCatalogLoaded(const char* catalogFile) override; - ////////////////////////////////////////////////////////////////////////// - ////////////////////////////////////////////////////////////////////////// // AssetDatabaseRequestsBus::Handler overrides... bool GetAssetDatabaseLocation(AZStd::string& result) override; diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index 5751271312..a949852b5e 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -92,7 +92,6 @@ namespace AtomToolsFramework AtomToolsMainWindowNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); - AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); } void AtomToolsApplication::CreateReflectionManager() @@ -175,11 +174,18 @@ namespace AtomToolsFramework AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotificationBus::Broadcast( &AzToolsFramework::AssetBrowser::AssetDatabaseLocationNotifications::OnDatabaseInitialized); - AzFramework::AssetCatalogEventBus::Handler::BusConnect(); AZ::Data::AssetCatalogRequestBus::Broadcast(&AZ::Data::AssetCatalogRequestBus::Events::LoadCatalog, "@assets@/assetcatalog.xml"); + if (!AZ::RPI::RPISystemInterface::Get()->IsInitialized()) + { + AZ::RPI::RPISystemInterface::Get()->InitializeSystemAssets(); + } + LoadSettings(); + AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::CreateMainWindow); + AtomToolsMainWindowNotificationBus::Handler::BusConnect(); + auto editorPythonEventsInterface = AZ::Interface::Get(); if (editorPythonEventsInterface) { @@ -189,6 +195,9 @@ namespace AtomToolsFramework editorPythonEventsInterface->StartPython(); } + QTimer::singleShot(0, this, [this]() { + ProcessCommandLine(m_commandLine); + }); m_timer.start(); } @@ -197,26 +206,12 @@ namespace AtomToolsFramework ExitMainLoop(); } - void AtomToolsApplication::OnCatalogLoaded(const char* catalogFile) - { - AZ_UNUSED(catalogFile); - - // Delay execution of commands and scripts post initialization - AZ::TickBus::QueueFunction([this]() { - AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::CreateMainWindow); - AtomToolsMainWindowNotificationBus::Handler::BusConnect(); - ProcessCommandLine(m_commandLine); - }); - AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); - } - void AtomToolsApplication::Destroy() { // before modules are unloaded, destroy UI to free up any assets it cached AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::DestroyMainWindow); m_styleManager.reset(); - AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); AzToolsFramework::EditorPythonConsoleNotificationBus::Handler::BusDisconnect(); AzToolsFramework::AssetDatabase::AssetDatabaseRequestsBus::Handler::BusDisconnect(); AtomToolsMainWindowNotificationBus::Handler::BusDisconnect(); From 9912e68c5966fcff4fa885625239d08448e03bc7 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 22 Sep 2021 11:19:13 -0500 Subject: [PATCH 71/84] reverting unneeded changes Signed-off-by: Guthrie Adams --- .../Code/Source/Application/AtomToolsApplication.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp index a949852b5e..13b9a2ba27 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Application/AtomToolsApplication.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -183,8 +182,8 @@ namespace AtomToolsFramework LoadSettings(); - AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::CreateMainWindow); AtomToolsMainWindowNotificationBus::Handler::BusConnect(); + AtomToolsMainWindowFactoryRequestBus::Broadcast(&AtomToolsMainWindowFactoryRequestBus::Handler::CreateMainWindow); auto editorPythonEventsInterface = AZ::Interface::Get(); if (editorPythonEventsInterface) @@ -195,9 +194,9 @@ namespace AtomToolsFramework editorPythonEventsInterface->StartPython(); } - QTimer::singleShot(0, this, [this]() { - ProcessCommandLine(m_commandLine); - }); + // Delay execution of commands and scripts post initialization + QTimer::singleShot(0, [this]() { ProcessCommandLine(m_commandLine); }); + m_timer.start(); } From d00d9a9515363ed5474462c6460693ec08532925 Mon Sep 17 00:00:00 2001 From: Roman <69218254+amzn-rhhong@users.noreply.github.com> Date: Wed, 22 Sep 2021 09:41:45 -0700 Subject: [PATCH 72/84] Fix the crash when switching between sim obj and physix layout in animation editor. (#4185) * Update the simulated object layout Signed-off-by: rhhong * Fixed the bug. Do not store uncessory cached selected model indices which would become stall. Signed-off-by: rhhong * update the simulted object layout. Signed-off-by: rhhong * Get rid of locally cached selectedIndices variable. Signed-off-by: rhhong * Remove debug code Signed-off-by: rhhong --- .../Editor/Layouts/SimulatedObjects.layout | Bin 6901 -> 7805 bytes .../Editor/Plugins/Cloth/ClothJointWidget.cpp | 10 +-- .../HitDetection/HitDetectionJointWidget.cpp | 10 +-- .../Plugins/Ragdoll/RagdollNodeWidget.cpp | 16 +++-- .../SimulatedObjectColliderWidget.cpp | 20 +++--- .../SkeletonOutlinerPlugin.cpp | 8 +-- .../Editor/SkeletonModelJointWidget.cpp | 61 +++++++++--------- .../Source/Editor/SkeletonModelJointWidget.h | 4 +- 8 files changed, 67 insertions(+), 62 deletions(-) diff --git a/Gems/EMotionFX/Assets/Editor/Layouts/SimulatedObjects.layout b/Gems/EMotionFX/Assets/Editor/Layouts/SimulatedObjects.layout index a7879584a9601f005f1c5aeba8d04f3320c8c66c..f52df642e84ae9f7b9b8b2f3685b3cb684345746 100644 GIT binary patch literal 7805 zcmc&&TWl0n82-20ZZQa=KumnlAzlK;;LgnM&Q871f>29J+fXZDjO~_AV9R!QZMR-X z)I_3*5ie1y#3ziJ7!!jJCM3cGi9RU45CSIfps3M^#v4yw3ibQW%yf6#Y29Avp3R&y zGkebW-@fyoGiT$L&eo)X-%N#eLhGe=;P}vG3x#v1de< zEN}RbEncbOKcD<->=a+{eJReek5=Ed7caFVznvnE-~W7r`^+&%S$QQ2eF#FF(n5TW z*N)tJ<}S473u_dvk2kTu|IGdz*LdLEX|~@+T>U$4xbzgCSxj7h|7hm(ca$7)@%{c& z`9lGejGy@I%kQcALgD&&nujmq`q!7w@%0|ahTOnFD%+>6PYp`G*R|uz7598V|ND4F zy?n_cIo$gF_pN!qv9v#X(LP_EKih`>oZEn@JI@vyFP}`Qy_T?Uz1^0s)wRBsz60xLZ*mgDi(7DISIE7qRYacFT(phIv zs^JISh{jFbu;PYc#w}YGo)24cg>)`EB-QnUVHt5tPwG)yPuNMbYJSi0j1pL!ZXy9YhAlAkV7{7kVVfnQW?(Sa68dDst$ghywGT$Ew}H7clq zT(=L1VJz5Kbwd~CimU@Qj$e#AFN4k_E^_$X+>xUagVu2%*Ix(ZCAfN_`z( zUZyu<%Fjz4g}#VqEyMiQ>~z){GvHb9MHKjmC3Ifg0+KunecuG~6S%NxslUu(N+?x<&NRm)1aHVmnLf9K2xeM)k zfW54w)zGrlWw565hpRie7xRSJViOc4)b6$-9Q|+w%q~a@A=;^U&-*m^@5taJ#*>dU z#8y%f6Hg+YA^pl3FyS$%@Gf2)D>vh|GBe@;Nx(ZcykUcggpK*0!QjwARI1Fc5yi=6 zLMA2qZYxHV67Q8JI3bOc&oG~mBBxU3JZVxJuT%OjEG;K)5d zz+4r1o)t?_AZb6@06st$5F1ZP>IAoj&tT9aYN$85oLz=uRvfjiMymvb@iv}Jjwg}E zeF%1iKSgK`!?ByjNgKc}3t=E#sT5~~sg$FeEXEoP4QXf}BnC|?SBhB$Ghbm)!MMUP zIa;|n)C3*QV%UhsmB=svU%-pnqEeg*$Qw1UqebGz1fyi7Yrk}=kPIUbDdcAd&Tj{E z`*F7u&)e{C9|Gjy-VIPU@;HMy)rc0A>GR(B9Kz@Y5Hjm-hFmD1o3r-bHtbFQqfB~GC11j3gR>jEGaPst&7#I2-j^)bUMzEomXHp&*+B->@}3?|3_^_^~7gf2n{b;d(IX!YF{d2y?n zWSnBmm}TKw2awG~V*%Z34xoh?l(PAMOW6_O>@AQ2>U3nkuPkyDyI25<1zUM?dUMYeGV0gF4d&|(i<+0$4NdNM*yP^ zr)!}*akJh>-CUthcU2U#x(nd(N*^CBipq05-@-mq7O`b+XAUxF*_(#Z1Eg6z!Z3K0^#JQT1@v z@X0Gd*7{%Zkxwv)teUyC#qW&qk9gn&F*r1UseiU;ZDkCea&PCE72-C#wDjO1$X5Sc zA@V2w{{@}qV(a*^0&s#DOk2Yzinh+3!Qm4SRZ`S48Dyt_%2EF`?95`s-0buYIe>E< z*CYn_l-s$$yEJITGSN5OY6o(_Kc}f5!k`~H64(4~{K<+52M6BDHF?RK=6C}-vCN-d y0UsnKdQ~T8^J$%*gT_xfJnIxxah&qERbiEh%i%+CYN}h26lGcDJ^>k?^32 zL?Z^GQ9<+teK5Xgf>G2&A9ye^A;cIHCHSJe7=L0!eL@iYzS%o_?=A~&Y3a^pX71cO z^PO|PIcI)$_1eL{?&0*%qZ=Q0TBV%2OWP8rk+2NQlnY3F`!>FxeMZDc$1*2kVSDrF zzFxMwkePx?)lr;R7FLfx*dp?s?u>CSy5;ZTtKq{0dEm?{B~O7z3a!uS{$onM(edS1 zQ9O~}!)$B3{*U(bQ%~Iw;)V9;?~DH~%h7G!Uu0O}e9%+YPxGPi`**)^>L1|fq{r8` zHJ-Ld+ioOb}GAW`t1Ev{e43{z3VK~cMRKfZQHXPNA@iGkoa9eJ#pMU z66OD`Wp5~XKkp6sp}eD|Wyhoa4(>lt#ouBnd*Rn74!y^IS}*FGp2+5V`Vs@#d?q`Y zSf9&h3Qx(L^I#jE>6>2CNqLsJF;Wh zVj-VMmx^P#e0EZru|AlV;o7F$qbq*(WmZ1RgH1^)E8_{YpB=R@+$=56LFU%D5DyC^?jQnZi>^GO9I& zdIx$W>i#V8#SoN0Yuhank7HXcApbH`WD}?^eh!e^7emecW#stxGeBO?5j}xJ&w_PllvNdSxA;sW!n)z?*C0DE3ZYawh`6|AlJDC_P4%n5|};u91pmM+&ghT`F|2K=um zBbcJC$~*a-gO_Gyvc@mzGi1z0NvW8VKqASIQAGxbyA5XCf)}4xn{h{#87@GQV8>UW zu7Y(mGZ-8@h(e{=H6jc&8!~-_fTk^+QA)f|xp)osRIyJ1-zE_51rWId2#8gY=UFfjvvwkBKfM9|0A1kNXr-tVXpMi10Z(uw6GvBj zm!&+*MQN(h2F7u`kCx5xLl{!w5Z=}LDPC^C%QY3Jt>axDW|!_tr5F*mQjRovoNIV! zY!dZ7#JE@~dI%z4VNgL=;n*ClXpX%K9p1(GuE1A1mjLiLyl4%TVkBVQXhB~j1{ftP zT}Ne5O-Tt8F@jYz3-Z(O+)+GjMSDHIW-vinJeMbE6INSJ;-yCPs`Ypx7+=6N1``OG zZMQ>iiApfh+S!Yx&5%sab5LlGwBKv4-# z*@$tiF9G$7h^RVKp%%5-w3)6-zoL&Y^qs(`LKDeyW5)Hv0~na&YPPvrg)`T};Mp88 zF7^kA<;xm}TG>#PQ`DFeQ_W%fBH(?ZP*Geh2jPON)+&(Iz7TdyL?z~BwXBtgWrM7k zMsWOJ-^+zX>@Vo>O;m?_8)9)l1sOw(D`wSn-4C=i8WC>a@){ZtgH#p&%d55!N3AqG zYj7_zRSQchXo|0Zio6D2;<5Gg%@2d@hDUTz~}%GoLe z0gETJ*!%!Is8r1G9}S#Yq?0w*3kDQ79@f>{4UZw*w+-b?T%&Q`K{Pt$C?wJ9D2sv7 z)P~0NkFa$PZNPaMxpG{lhDfd00c4jtL&X{o{>$yV3U-$&!-8#+#Z0m~NfwemM_&6J z2t0rn)3>$GF%md?k!x*@@5jpxp{+AmeE_5qH}q&4K%<_W`c%8{2iSQAou+SRxMfwY zCBUgSr?GK3;K|U=#uoHT?pA?)v6I1rt~TSLo~`<()cz;F^KdZ}TPqhO;MAK_+8RF= z+B)+&jUR)kNK%1c&rW@B>v$S=<}qSsb_Ulr;2cG+^<8eKQ9I{&-+@LsQ)VT@;>*vJ_?`1A*(1~gG^h#inuQ_5x^lHwW&8BsF4XWJT0_!-t Y4c;%&vwCCXjrClearInstances(false); @@ -142,7 +143,7 @@ namespace EMotionFX m_collidersWidget->Reset(); } - m_jointLimitWidget->Update(m_selectedModelIndices[0]); + m_jointLimitWidget->Update(selectedModelIndices[0]); m_ragdollNodeCard->setExpanded(true); m_ragdollNodeCard->show(); m_jointLimitWidget->show(); @@ -169,31 +170,32 @@ namespace EMotionFX void RagdollNodeWidget::OnAddRemoveRagdollNode() { + const QModelIndexList& selectedModelIndices = GetSelectedModelIndices(); if (GetRagdollNodeConfig()) { // The node is present in the ragdoll, remove it. - RagdollNodeInspectorPlugin::RemoveFromRagdoll(m_selectedModelIndices); + RagdollNodeInspectorPlugin::RemoveFromRagdoll(selectedModelIndices); } else { // The node is not part of the ragdoll, add it. - RagdollNodeInspectorPlugin::AddToRagdoll(m_selectedModelIndices); + RagdollNodeInspectorPlugin::AddToRagdoll(selectedModelIndices); } } void RagdollNodeWidget::OnAddCollider(const AZ::TypeId& colliderType) { - ColliderHelpers::AddCollider(m_selectedModelIndices, PhysicsSetup::Ragdoll, colliderType); + ColliderHelpers::AddCollider(GetSelectedModelIndices(), PhysicsSetup::Ragdoll, colliderType); } void RagdollNodeWidget::OnCopyCollider(size_t colliderIndex) { - ColliderHelpers::CopyColliderToClipboard(m_selectedModelIndices.first(), colliderIndex, PhysicsSetup::Ragdoll); + ColliderHelpers::CopyColliderToClipboard(GetSelectedModelIndices().first(), colliderIndex, PhysicsSetup::Ragdoll); } void RagdollNodeWidget::OnPasteCollider(size_t colliderIndex, bool replace) { - ColliderHelpers::PasteColliderFromClipboard(m_selectedModelIndices.first(), colliderIndex, PhysicsSetup::Ragdoll, replace); + ColliderHelpers::PasteColliderFromClipboard(GetSelectedModelIndices().first(), colliderIndex, PhysicsSetup::Ragdoll, replace); } void RagdollNodeWidget::OnRemoveCollider(size_t colliderIndex) diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectColliderWidget.cpp b/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectColliderWidget.cpp index 8c6c72934d..b56cafc9be 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectColliderWidget.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectColliderWidget.cpp @@ -131,7 +131,8 @@ namespace EMotionFX void SimulatedObjectColliderWidget::InternalReinit() { - if (m_selectedModelIndices.size() == 1) + const QModelIndexList& selectedModelIndices = GetSelectedModelIndices(); + if (selectedModelIndices.size() == 1) { Physics::CharacterColliderNodeConfiguration* nodeConfig = GetNodeConfig(); if (nodeConfig) @@ -172,12 +173,13 @@ namespace EMotionFX } AZStd::string labelText; + const QModelIndexList& selectedModelIndices = GetSelectedModelIndices(); const AZStd::vector& simObjs = actor->GetSimulatedObjectSetup()->GetSimulatedObjects(); for (const SimulatedObject* obj : simObjs) { - for (int i = 0; i < m_selectedModelIndices.size(); ++i) + for (int i = 0; i < selectedModelIndices.size(); ++i) { - Node* node = m_selectedModelIndices[i].data(SkeletonModel::ROLE_POINTER).value(); + Node* node = selectedModelIndices[i].data(SkeletonModel::ROLE_POINTER).value(); if (obj->FindSimulatedJointBySkeletonJointIndex(node->GetNodeIndex())) { if (!labelText.empty()) @@ -208,8 +210,9 @@ namespace EMotionFX return; } + const QModelIndexList& selectedModelIndices = GetSelectedModelIndices(); // Only show the notification when it is single selection. - if (m_selectedModelIndices.size() != 1) + if (selectedModelIndices.size() != 1) { return; } @@ -250,17 +253,18 @@ namespace EMotionFX void SimulatedObjectColliderWidget::OnAddCollider(const AZ::TypeId& colliderType) { - ColliderHelpers::AddCollider(m_selectedModelIndices, PhysicsSetup::SimulatedObjectCollider, colliderType); + ColliderHelpers::AddCollider(GetSelectedModelIndices(), PhysicsSetup::SimulatedObjectCollider, colliderType); } void SimulatedObjectColliderWidget::OnCopyCollider(size_t colliderIndex) { - ColliderHelpers::CopyColliderToClipboard(m_selectedModelIndices.first(), colliderIndex, PhysicsSetup::SimulatedObjectCollider); + ColliderHelpers::CopyColliderToClipboard(GetSelectedModelIndices().first(), colliderIndex, PhysicsSetup::SimulatedObjectCollider); } void SimulatedObjectColliderWidget::OnPasteCollider(size_t colliderIndex, bool replace) { - ColliderHelpers::PasteColliderFromClipboard(m_selectedModelIndices.first(), colliderIndex, PhysicsSetup::SimulatedObjectCollider, replace); + ColliderHelpers::PasteColliderFromClipboard( + GetSelectedModelIndices().first(), colliderIndex, PhysicsSetup::SimulatedObjectCollider, replace); } void SimulatedObjectColliderWidget::OnRemoveCollider(size_t colliderIndex) @@ -270,7 +274,7 @@ namespace EMotionFX Physics::CharacterColliderNodeConfiguration* SimulatedObjectColliderWidget::GetNodeConfig() const { - AZ_Assert(m_selectedModelIndices.size() == 1, "Get Node config function only return the config when it is single seleted"); + AZ_Assert(GetSelectedModelIndices().size() == 1, "Get Node config function only return the config when it is single seleted"); Actor* actor = GetActor(); Node* joint = GetNode(); if (!actor || !joint) diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/SkeletonOutliner/SkeletonOutlinerPlugin.cpp b/Gems/EMotionFX/Code/Source/Editor/Plugins/SkeletonOutliner/SkeletonOutlinerPlugin.cpp index f8ca291d55..ec8d1147f2 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/SkeletonOutliner/SkeletonOutlinerPlugin.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/SkeletonOutliner/SkeletonOutlinerPlugin.cpp @@ -211,15 +211,15 @@ namespace EMotionFX AZ::Outcome SkeletonOutlinerPlugin::GetSelectedRowIndices() { - return AZ::Success(m_selectedRows); + return AZ::Success(m_treeView->selectionModel()->selectedRows()); } void SkeletonOutlinerPlugin::OnSelectionChanged([[maybe_unused]] const QItemSelection& selected, [[maybe_unused]] const QItemSelection& deselected) { - m_selectedRows = m_treeView->selectionModel()->selectedRows(); - if (m_selectedRows.size() == 1) + QModelIndexList selectedRows = m_treeView->selectionModel()->selectedRows(); + if (selectedRows.size() == 1) { - const QModelIndex& modelIndex = m_selectedRows[0]; + const QModelIndex& modelIndex = selectedRows[0]; Node* selectedNode = modelIndex.data(SkeletonModel::ROLE_POINTER).value(); Actor* selectedActor = modelIndex.data(SkeletonModel::ROLE_ACTOR_POINTER).value(); SkeletonOutlinerNotificationBus::Broadcast(&SkeletonOutlinerNotifications::SingleNodeSelectionChanged, selectedActor, selectedNode); diff --git a/Gems/EMotionFX/Code/Source/Editor/SkeletonModelJointWidget.cpp b/Gems/EMotionFX/Code/Source/Editor/SkeletonModelJointWidget.cpp index e9eeb7530d..9cfc763fc6 100644 --- a/Gems/EMotionFX/Code/Source/Editor/SkeletonModelJointWidget.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/SkeletonModelJointWidget.cpp @@ -72,14 +72,7 @@ namespace EMotionFX setLayout(mainLayout); - AZ::Outcome selectedRowIndicesOutcome; - QModelIndexList selectedModelIndices; - SkeletonOutlinerRequestBus::BroadcastResult(selectedRowIndicesOutcome, &SkeletonOutlinerRequests::GetSelectedRowIndices); - if (selectedRowIndicesOutcome.IsSuccess()) - { - selectedModelIndices = selectedRowIndicesOutcome.GetValue(); - } - Reinit(selectedModelIndices); + Reinit(); // Connect to the model. SkeletonModel* skeletonModel = nullptr; @@ -92,9 +85,9 @@ namespace EMotionFX } } - void SkeletonModelJointWidget::Reinit(const QModelIndexList& selectedModelIndices) + void SkeletonModelJointWidget::Reinit() { - m_selectedModelIndices = selectedModelIndices; + const QModelIndexList& selectedModelIndices = GetSelectedModelIndices(); if (!EMStudio::GetManager()->GetIgnoreVisibility() && !isVisible()) { @@ -103,15 +96,15 @@ namespace EMotionFX if (GetActor()) { - if (!m_selectedModelIndices.isEmpty()) + if (!selectedModelIndices.isEmpty()) { - if (m_selectedModelIndices.size() == 1) + if (selectedModelIndices.size() == 1) { m_jointNameLabel->setText(GetNode()->GetName()); } else { - m_jointNameLabel->setText(QString("%1 joints selected").arg(m_selectedModelIndices.size())); + m_jointNameLabel->setText(QString("%1 joints selected").arg(selectedModelIndices.size())); } m_noSelectionWidget->hide(); @@ -136,7 +129,7 @@ namespace EMotionFX void SkeletonModelJointWidget::showEvent(QShowEvent* event) { QWidget::showEvent(event); - Reinit(m_selectedModelIndices); + Reinit(); } void SkeletonModelJointWidget::OnSelectionChanged([[maybe_unused]] const QItemSelection& selected, [[maybe_unused]] const QItemSelection& deselected) @@ -146,36 +139,28 @@ namespace EMotionFX if (skeletonModel) { const QModelIndexList selectedRows = skeletonModel->GetSelectionModel().selectedRows(); - Reinit(selectedRows); } + Reinit(); } void SkeletonModelJointWidget::OnDataChanged([[maybe_unused]] const QModelIndex& topLeft, [[maybe_unused]] const QModelIndex& bottomRight, [[maybe_unused]] const QVector& roles) { - Reinit(m_selectedModelIndices); + Reinit(); } void SkeletonModelJointWidget::OnModelReset() { - Reinit(QModelIndexList()); + Reinit(); } Actor* SkeletonModelJointWidget::GetActor() const { Actor* actor = nullptr; - if (!m_selectedModelIndices.empty()) + SkeletonModel* skeletonModel = nullptr; + SkeletonOutlinerRequestBus::BroadcastResult(skeletonModel, &SkeletonOutlinerRequests::GetModel); + if (skeletonModel) { - actor = m_selectedModelIndices[0].data(SkeletonModel::ROLE_ACTOR_POINTER).value(); - } - - if (!actor) - { - SkeletonModel* skeletonModel = nullptr; - SkeletonOutlinerRequestBus::BroadcastResult(skeletonModel, &SkeletonOutlinerRequests::GetModel); - if (skeletonModel) - { - actor = skeletonModel->GetActor(); - } + actor = skeletonModel->GetActor(); } return actor; } @@ -183,10 +168,24 @@ namespace EMotionFX Node* SkeletonModelJointWidget::GetNode() const { Node* node = nullptr; - if (!m_selectedModelIndices.empty()) + const QModelIndexList& selectedModelIndices = GetSelectedModelIndices(); + if (!selectedModelIndices.empty()) { - node = m_selectedModelIndices[0].data(SkeletonModel::ROLE_POINTER).value(); + node = selectedModelIndices[0].data(SkeletonModel::ROLE_POINTER).value(); } return node; } + + QModelIndexList SkeletonModelJointWidget::GetSelectedModelIndices() const + { + QModelIndexList selectedModelIndices; + SkeletonModel* skeletonModel = nullptr; + SkeletonOutlinerRequestBus::BroadcastResult(skeletonModel, &SkeletonOutlinerRequests::GetModel); + if (skeletonModel) + { + selectedModelIndices = skeletonModel->GetSelectionModel().selectedRows(); + } + + return selectedModelIndices; + } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Source/Editor/SkeletonModelJointWidget.h b/Gems/EMotionFX/Code/Source/Editor/SkeletonModelJointWidget.h index 52178b4b55..399615c42a 100644 --- a/Gems/EMotionFX/Code/Source/Editor/SkeletonModelJointWidget.h +++ b/Gems/EMotionFX/Code/Source/Editor/SkeletonModelJointWidget.h @@ -33,13 +33,14 @@ namespace EMotionFX virtual void CreateGUI(); - void Reinit(const QModelIndexList& selectedModelIndices); + void Reinit(); void showEvent(QShowEvent* event) override; protected: Actor* GetActor() const; Node* GetNode() const; + QModelIndexList GetSelectedModelIndices() const; virtual QWidget* CreateContentWidget(QWidget* parent) = 0; virtual QWidget* CreateNoSelectionWidget(QWidget* parent) = 0; virtual void InternalReinit() = 0; @@ -50,7 +51,6 @@ namespace EMotionFX void OnModelReset(); protected: - QModelIndexList m_selectedModelIndices; QLabel* m_jointNameLabel; static int s_jointLabelSpacing; static int s_jointNameSpacing; From 20849655ea498d0b3a43b73db17417b70f36c8e6 Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Wed, 22 Sep 2021 11:56:53 -0700 Subject: [PATCH 73/84] Initial gem dependencies (#4229) These are immediate dependencies, and include many circular dependencies, largely amongst the Atom gems, as indicated by cmake Signed-off-by: AMZN-alexpete <26804013+AMZN-alexpete@users.noreply.github.com> --- Gems/AWSClientAuth/gem.json | 16 +++++++++--- Gems/AWSCore/gem.json | 13 +++++++--- Gems/AWSGameLift/gem.json | 15 ++++++++--- Gems/AWSMetrics/gem.json | 15 ++++++++--- Gems/Achievements/gem.json | 12 ++++++--- Gems/AssetMemoryAnalyzer/gem.json | 15 ++++++++--- Gems/AssetValidation/gem.json | 13 +++++++--- Gems/Atom/Asset/ImageProcessingAtom/gem.json | 10 +++++--- Gems/Atom/Asset/Shader/gem.json | 9 ++++--- Gems/Atom/Bootstrap/gem.json | 8 +++--- Gems/Atom/Component/DebugCamera/gem.json | 8 +++--- Gems/Atom/Feature/Common/gem.json | 11 +++++--- Gems/Atom/RHI/DX12/gem.json | 8 +++--- Gems/Atom/RHI/Metal/gem.json | 8 +++--- Gems/Atom/RHI/Null/gem.json | 8 +++--- Gems/Atom/RHI/Vulkan/gem.json | 8 +++--- Gems/Atom/RHI/gem.json | 12 ++++++--- Gems/Atom/RPI/gem.json | 8 +++--- Gems/Atom/Tools/AtomToolsFramework/gem.json | 10 +++++--- Gems/Atom/Tools/MaterialEditor/gem.json | 15 ++++++++--- Gems/Atom/gem.json | 22 +++++++++++++--- Gems/AtomContent/ReferenceMaterials/gem.json | 3 ++- Gems/AtomContent/Sponza/gem.json | 11 +++++--- Gems/AtomContent/gem.json | 16 +++++++++--- Gems/AtomLyIntegration/AtomBridge/gem.json | 25 ++++++++++++++++--- Gems/AtomLyIntegration/AtomFont/gem.json | 10 +++++--- .../AtomLyIntegration/AtomImGuiTools/gem.json | 6 ++++- .../AtomViewportDisplayIcons/gem.json | 11 +++++--- .../AtomViewportDisplayInfo/gem.json | 9 ++++--- .../AtomLyIntegration/CommonFeatures/gem.json | 14 ++++++++--- Gems/AtomLyIntegration/EMotionFXAtom/gem.json | 13 +++++++--- Gems/AtomLyIntegration/ImguiAtom/gem.json | 9 ++++--- .../DccScriptingInterface/gem.json | 9 ++++--- Gems/AtomLyIntegration/gem.json | 22 +++++++++++++--- Gems/AudioEngineWwise/gem.json | 15 ++++++++--- Gems/AudioSystem/gem.json | 15 ++++++++--- Gems/BarrierInput/gem.json | 15 ++++++++--- Gems/Blast/gem.json | 19 +++++++++++--- Gems/Camera/gem.json | 14 ++++++++--- Gems/CameraFramework/gem.json | 13 +++++++--- Gems/CertificateManager/gem.json | 12 ++++++--- Gems/CrashReporting/gem.json | 12 ++++++--- Gems/CustomAssetExample/gem.json | 12 ++++++--- Gems/DebugDraw/gem.json | 16 +++++++++--- Gems/DevTextures/gem.json | 13 +++++++--- Gems/EMotionFX/gem.json | 16 +++++++++--- Gems/EditorPythonBindings/gem.json | 12 ++++++--- Gems/ExpressionEvaluation/gem.json | 12 ++++++--- Gems/FastNoise/gem.json | 17 ++++++++++--- Gems/GameState/gem.json | 13 +++++++--- Gems/GameStateSamples/gem.json | 22 +++++++++++++--- Gems/Gestures/gem.json | 15 ++++++++--- Gems/GradientSignal/gem.json | 17 ++++++++++--- Gems/GraphCanvas/gem.json | 13 +++++++--- Gems/GraphModel/gem.json | 15 ++++++++--- Gems/HttpRequestor/gem.json | 12 ++++++--- Gems/ImGui/gem.json | 15 ++++++++--- Gems/InAppPurchases/gem.json | 12 ++++++--- Gems/LandscapeCanvas/gem.json | 20 ++++++++++++--- Gems/LmbrCentral/gem.json | 14 ++++++++--- Gems/LocalUser/gem.json | 13 +++++++--- Gems/LyShine/gem.json | 21 +++++++++++++--- Gems/LyShineExamples/gem.json | 16 +++++++++--- Gems/Maestro/gem.json | 16 +++++++++--- Gems/MessagePopup/gem.json | 12 ++++++--- Gems/Metastream/gem.json | 13 +++++++--- Gems/Microphone/gem.json | 14 ++++++++--- Gems/Multiplayer/gem.json | 17 ++++++++++--- Gems/MultiplayerCompression/gem.json | 13 +++++++--- Gems/NvCloth/gem.json | 16 +++++++++--- Gems/PBSreferenceMaterials/gem.json | 13 +++++++--- Gems/PhysX/gem.json | 16 +++++++++--- Gems/PhysXDebug/gem.json | 16 +++++++++--- Gems/PhysXSamples/gem.json | 13 +++++++--- Gems/Prefab/PrefabBuilder/gem.json | 13 +++++++--- Gems/Presence/gem.json | 13 +++++++--- Gems/PrimitiveAssets/gem.json | 13 +++++++--- Gems/PythonAssetBuilder/gem.json | 15 ++++++++--- Gems/QtForPython/gem.json | 15 ++++++++--- Gems/SaveData/gem.json | 12 ++++++--- Gems/SceneLoggingExample/gem.json | 12 ++++++--- Gems/SceneProcessing/gem.json | 13 +++++++--- Gems/ScriptCanvas/gem.json | 17 ++++++++++--- Gems/ScriptCanvasDeveloper/gem.json | 16 +++++++++--- Gems/ScriptCanvasPhysics/gem.json | 15 ++++++++--- Gems/ScriptCanvasTesting/gem.json | 17 ++++++++++--- Gems/ScriptEvents/gem.json | 13 +++++++--- Gems/ScriptedEntityTweener/gem.json | 13 +++++++--- Gems/SliceFavorites/gem.json | 8 ++++-- Gems/StartingPointCamera/gem.json | 16 +++++++++--- Gems/StartingPointInput/gem.json | 15 ++++++++--- Gems/StartingPointMovement/gem.json | 13 +++++++--- Gems/SurfaceData/gem.json | 17 ++++++++++--- Gems/Terrain/gem.json | 20 ++++++++++++--- Gems/TestAssetBuilder/gem.json | 13 +++++++--- Gems/TextureAtlas/gem.json | 16 +++++++++--- Gems/TickBusOrderViewer/gem.json | 13 +++++++--- Gems/Twitch/gem.json | 15 ++++++++--- Gems/UiBasics/gem.json | 13 +++++++--- Gems/Vegetation/gem.json | 18 ++++++++++--- Gems/VideoPlaybackFramework/gem.json | 12 ++++++--- Gems/VirtualGamepad/gem.json | 12 ++++++--- Gems/WhiteBox/gem.json | 17 ++++++++++--- 103 files changed, 1100 insertions(+), 307 deletions(-) diff --git a/Gems/AWSClientAuth/gem.json b/Gems/AWSClientAuth/gem.json index 42996e7f4f..75c07d025b 100644 --- a/Gems/AWSClientAuth/gem.json +++ b/Gems/AWSClientAuth/gem.json @@ -5,9 +5,19 @@ "origin": "Amazon Web Services, Inc.", "type": "Code", "summary": "AWS Client Auth provides client authentication and AWS authorization solution.", - "canonical_tags": ["Gem"], - "user_tags": ["AWS", "Network", "SDK"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "AWS", + "Network", + "SDK" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/aws/aws-client-auth/", + "dependencies": [ + "AWSCore", + "HttpRequestor" + ] } diff --git a/Gems/AWSCore/gem.json b/Gems/AWSCore/gem.json index 4c7889ace4..1bb9da9192 100644 --- a/Gems/AWSCore/gem.json +++ b/Gems/AWSCore/gem.json @@ -5,9 +5,16 @@ "origin": "Amazon Web Services, Inc.", "type": "Code", "summary": "The AWS Core Gem provides basic shared AWS functionality such as AWS SDK initialization and client configuration, and is automatically added when selecting any AWS feature Gem.", - "canonical_tags": ["Gem"], - "user_tags": ["AWS", "Network", "SDK"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "AWS", + "Network", + "SDK" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/aws/aws-core/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/aws/aws-core/", + "dependencies": [] } diff --git a/Gems/AWSGameLift/gem.json b/Gems/AWSGameLift/gem.json index 7711495ee7..a0d7f62cd1 100644 --- a/Gems/AWSGameLift/gem.json +++ b/Gems/AWSGameLift/gem.json @@ -5,9 +5,18 @@ "origin": "Amazon Web Services, Inc.", "type": "Code", "summary": "The AWS GameLift Gem provides a framework to extend O3DE networking layer to work with GameLift resources via GameLift server and client SDK.", - "canonical_tags": ["Gem"], - "user_tags": ["AWS", "Framework", "Network"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "AWS", + "Framework", + "Network" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/aws/aws-gamelift/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/aws/aws-gamelift/", + "dependencies": [ + "AWSCore" + ] } diff --git a/Gems/AWSMetrics/gem.json b/Gems/AWSMetrics/gem.json index 5faeb66787..df16890012 100644 --- a/Gems/AWSMetrics/gem.json +++ b/Gems/AWSMetrics/gem.json @@ -5,9 +5,18 @@ "origin": "Amazon Web Services, Inc.", "type": "Code", "summary": "The AWS Metrics Gem provides a solution for AWS metrics submission and analytics.", - "canonical_tags": ["Gem"], - "user_tags": ["AWS", "Network", "SDK"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "AWS", + "Network", + "SDK" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/aws/aws-metrics/", + "dependencies": [ + "AWSCore" + ] } diff --git a/Gems/Achievements/gem.json b/Gems/Achievements/gem.json index ca2bc7f3e9..bd643f471a 100644 --- a/Gems/Achievements/gem.json +++ b/Gems/Achievements/gem.json @@ -5,9 +5,15 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Achievements Gem provides a target platform agnostic interface for retrieving achievement details and unlocking achievements.", - "canonical_tags": ["Gem"], - "user_tags": ["Gameplay", "Achievements"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Gameplay", + "Achievements" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/gameplay/achievements/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/gameplay/achievements/", + "dependencies": [] } diff --git a/Gems/AssetMemoryAnalyzer/gem.json b/Gems/AssetMemoryAnalyzer/gem.json index 544e0f7948..902102fa27 100644 --- a/Gems/AssetMemoryAnalyzer/gem.json +++ b/Gems/AssetMemoryAnalyzer/gem.json @@ -5,9 +5,18 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Asset Memory Analyzer Gem provides tools to profile asset memory usage in Open 3D Engine through ImGUI (Immediate Mode Graphical User Interface).", - "canonical_tags": ["Gem"], - "user_tags": ["Debug", "Utility", "Tools"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Debug", + "Utility", + "Tools" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/debug/asset-memory-analyzer/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/debug/asset-memory-analyzer/", + "dependencies": [ + "ImGui" + ] } diff --git a/Gems/AssetValidation/gem.json b/Gems/AssetValidation/gem.json index 83e37ddaf5..1e57f60dc4 100644 --- a/Gems/AssetValidation/gem.json +++ b/Gems/AssetValidation/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Asset Validation Gem provides seed-related commands to ensure assets have valid seeds for asset bundling.", - "canonical_tags": ["Gem"], - "user_tags": ["Assets", "Utility", "Scripting"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Assets", + "Utility", + "Scripting" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/assets/asset-validation/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/assets/asset-validation/", + "dependencies": [] } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/gem.json b/Gems/Atom/Asset/ImageProcessingAtom/gem.json index 45d96f7168..1424841256 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/gem.json +++ b/Gems/Atom/Asset/ImageProcessingAtom/gem.json @@ -8,7 +8,11 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_RPI", + "Atom_RHI", + "Atom" + ] } diff --git a/Gems/Atom/Asset/Shader/gem.json b/Gems/Atom/Asset/Shader/gem.json index eadf34acff..6d5e9f4dbe 100644 --- a/Gems/Atom/Asset/Shader/gem.json +++ b/Gems/Atom/Asset/Shader/gem.json @@ -8,7 +8,10 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_RHI", + "Atom_RPI" + ] } diff --git a/Gems/Atom/Bootstrap/gem.json b/Gems/Atom/Bootstrap/gem.json index d5f287eb7f..5e98a1887d 100644 --- a/Gems/Atom/Bootstrap/gem.json +++ b/Gems/Atom/Bootstrap/gem.json @@ -8,7 +8,9 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_RPI" + ] } diff --git a/Gems/Atom/Component/DebugCamera/gem.json b/Gems/Atom/Component/DebugCamera/gem.json index cb2c597b07..586cb37058 100644 --- a/Gems/Atom/Component/DebugCamera/gem.json +++ b/Gems/Atom/Component/DebugCamera/gem.json @@ -8,7 +8,9 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_RPI" + ] } diff --git a/Gems/Atom/Feature/Common/gem.json b/Gems/Atom/Feature/Common/gem.json index cbaa56e0d7..36a61fbbbb 100644 --- a/Gems/Atom/Feature/Common/gem.json +++ b/Gems/Atom/Feature/Common/gem.json @@ -8,7 +8,12 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_RPI", + "Atom", + "ImGui", + "Atom_RHI" + ] } diff --git a/Gems/Atom/RHI/DX12/gem.json b/Gems/Atom/RHI/DX12/gem.json index df0ae12cc4..eb876a1b9f 100644 --- a/Gems/Atom/RHI/DX12/gem.json +++ b/Gems/Atom/RHI/DX12/gem.json @@ -8,7 +8,9 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_RHI" + ] } diff --git a/Gems/Atom/RHI/Metal/gem.json b/Gems/Atom/RHI/Metal/gem.json index 497e0149b6..8da6bfabec 100644 --- a/Gems/Atom/RHI/Metal/gem.json +++ b/Gems/Atom/RHI/Metal/gem.json @@ -8,7 +8,9 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_RHI" + ] } diff --git a/Gems/Atom/RHI/Null/gem.json b/Gems/Atom/RHI/Null/gem.json index aa2e08501a..0870efaae7 100644 --- a/Gems/Atom/RHI/Null/gem.json +++ b/Gems/Atom/RHI/Null/gem.json @@ -8,7 +8,9 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_RHI" + ] } diff --git a/Gems/Atom/RHI/Vulkan/gem.json b/Gems/Atom/RHI/Vulkan/gem.json index 2b43de4ab1..81e8dd22ea 100644 --- a/Gems/Atom/RHI/Vulkan/gem.json +++ b/Gems/Atom/RHI/Vulkan/gem.json @@ -8,7 +8,9 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_RHI" + ] } diff --git a/Gems/Atom/RHI/gem.json b/Gems/Atom/RHI/gem.json index 015ee64994..5f916e5224 100644 --- a/Gems/Atom/RHI/gem.json +++ b/Gems/Atom/RHI/gem.json @@ -8,7 +8,13 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_RHI_DX12", + "Atom_RHI_Metal", + "Atom_RHI_Vulkan", + "Atom_RHI_Null", + "Atom_Feature_Common" + ] } diff --git a/Gems/Atom/RPI/gem.json b/Gems/Atom/RPI/gem.json index f30a1c3201..b5a6fd5a1a 100644 --- a/Gems/Atom/RPI/gem.json +++ b/Gems/Atom/RPI/gem.json @@ -8,7 +8,9 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_RHI" + ] } diff --git a/Gems/Atom/Tools/AtomToolsFramework/gem.json b/Gems/Atom/Tools/AtomToolsFramework/gem.json index 5cea71c5cc..2b0380bdae 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/gem.json +++ b/Gems/Atom/Tools/AtomToolsFramework/gem.json @@ -8,7 +8,11 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_RPI", + "Atom_RHI", + "Atom_Bootstrap" + ] } diff --git a/Gems/Atom/Tools/MaterialEditor/gem.json b/Gems/Atom/Tools/MaterialEditor/gem.json index 83d9909a84..85ff434eab 100644 --- a/Gems/Atom/Tools/MaterialEditor/gem.json +++ b/Gems/Atom/Tools/MaterialEditor/gem.json @@ -8,7 +8,16 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "AtomToolsFramework", + "Atom_RPI", + "Atom_RHI", + "Atom_Feature_Common", + "ImageProcessingAtom", + "Atom_Component_DebugCamera", + "CommonFeaturesAtom", + "LyShine" + ] } diff --git a/Gems/Atom/gem.json b/Gems/Atom/gem.json index 99ca26025a..1f5e4a37f3 100644 --- a/Gems/Atom/gem.json +++ b/Gems/Atom/gem.json @@ -5,8 +5,24 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Atom Renderer Gem provides Atom Renderer and its associated tools (such as Material Editor), utilites, libraries, and interfaces.", - "canonical_tags": ["Gem"], - "user_tags": ["Rendering", "Core"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Rendering", + "Core" + ], "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/atom/atom/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/atom/atom/", + "dependencies": [ + "Atom_Feature_Common", + "AtomShader", + "Atom_Bootstrap", + "Atom_Component_DebugCamera", + "Atom_RHI", + "Atom_RPI", + "AtomToolsFramework", + "MaterialEditor", + "Atom_AtomBridge" + ] } diff --git a/Gems/AtomContent/ReferenceMaterials/gem.json b/Gems/AtomContent/ReferenceMaterials/gem.json index 9e145c20cc..f697d50bc4 100644 --- a/Gems/AtomContent/ReferenceMaterials/gem.json +++ b/Gems/AtomContent/ReferenceMaterials/gem.json @@ -7,5 +7,6 @@ "summary": "Atom Asset Gem with a library of reference materials for StandardPBR (and others in the future)", "canonical_tags": ["Gem"], "user_tags": ["Assets", "PBR", "Materials"], - "icon_path": "preview.png" + "icon_path": "preview.png", + "dependencies": [] } diff --git a/Gems/AtomContent/Sponza/gem.json b/Gems/AtomContent/Sponza/gem.json index 3fc76927e1..64de0e5da0 100644 --- a/Gems/AtomContent/Sponza/gem.json +++ b/Gems/AtomContent/Sponza/gem.json @@ -5,7 +5,12 @@ "origin": "Open 3D Engine - o3de.org", "type": "Asset", "summary": "A standard test scene for Global Illumination (forked from crytek sponza scene)", - "canonical_tags": ["Gem"], - "user_tags": ["Assets"], - "requirements": "" + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Assets" + ], + "requirements": "", + "dependencies": [] } diff --git a/Gems/AtomContent/gem.json b/Gems/AtomContent/gem.json index 6fcb8903e4..1bffe7d989 100644 --- a/Gems/AtomContent/gem.json +++ b/Gems/AtomContent/gem.json @@ -5,8 +5,18 @@ "origin": "Open 3D Engine - o3de.org", "type": "Asset", "summary": "The Atom Content Gem provides assets for Atom Renderer and a modified version of the Pixar Look Development Studio.", - "canonical_tags": ["Gem"], - "user_tags": ["Rendering", "Assets", "Tools"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Rendering", + "Assets", + "Tools" + ], "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/atom/atom-content/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/atom/atom-content/", + "dependencies": [ + "ReferenceMaterials", + "Sponza" + ] } diff --git a/Gems/AtomLyIntegration/AtomBridge/gem.json b/Gems/AtomLyIntegration/AtomBridge/gem.json index 49a56d2201..1d48d8be61 100644 --- a/Gems/AtomLyIntegration/AtomBridge/gem.json +++ b/Gems/AtomLyIntegration/AtomBridge/gem.json @@ -8,7 +8,26 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_RPI", + "Atom_Bootstrap", + "Atom_RHI", + "Atom_RHI_Null", + "Atom_Feature_Common", + "Atom_Component_DebugCamera", + "AtomImGuiTools", + "CommonFeaturesAtom", + "EMotionFX_Atom", + "ImguiAtom", + "AtomFont", + "AtomViewportDisplayInfo", + "Atom", + "AtomShader", + "ImageProcessingAtom", + "AtomToolsFramework", + "AtomViewportDisplayIcons", + "MaterialEditor" + ] } diff --git a/Gems/AtomLyIntegration/AtomFont/gem.json b/Gems/AtomLyIntegration/AtomFont/gem.json index 7e1a71db86..ed5b488de7 100644 --- a/Gems/AtomLyIntegration/AtomFont/gem.json +++ b/Gems/AtomLyIntegration/AtomFont/gem.json @@ -8,7 +8,11 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_RHI", + "Atom_RPI", + "Atom_AtomBridge" + ] } diff --git a/Gems/AtomLyIntegration/AtomImGuiTools/gem.json b/Gems/AtomLyIntegration/AtomImGuiTools/gem.json index ff20d5a19f..564eeedee2 100644 --- a/Gems/AtomLyIntegration/AtomImGuiTools/gem.json +++ b/Gems/AtomLyIntegration/AtomImGuiTools/gem.json @@ -12,5 +12,9 @@ "Debug", "Rendering" ], - "requirements": "" + "requirements": "", + "dependencies": [ + "ImguiAtom", + "Atom" + ] } diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/gem.json b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/gem.json index 52dbb219d3..a2a7ba4b77 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayIcons/gem.json +++ b/Gems/AtomLyIntegration/AtomViewportDisplayIcons/gem.json @@ -8,7 +8,12 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_RHI", + "Atom_RPI", + "Atom_Bootstrap", + "Atom_AtomBridge" + ] } diff --git a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json index f277d6cf82..be5cc96f95 100644 --- a/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json +++ b/Gems/AtomLyIntegration/AtomViewportDisplayInfo/gem.json @@ -8,7 +8,10 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_RHI", + "Atom_RPI" + ] } diff --git a/Gems/AtomLyIntegration/CommonFeatures/gem.json b/Gems/AtomLyIntegration/CommonFeatures/gem.json index 8eceb50932..30738ad14c 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/gem.json +++ b/Gems/AtomLyIntegration/CommonFeatures/gem.json @@ -8,7 +8,15 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "Atom_Feature_Common", + "LmbrCentral", + "GradientSignal", + "SurfaceData", + "Atom_Bootstrap", + "Atom_RPI", + "AtomToolsFramework" + ] } diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/gem.json b/Gems/AtomLyIntegration/EMotionFXAtom/gem.json index a7c3e96d2b..f921990360 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/gem.json +++ b/Gems/AtomLyIntegration/EMotionFXAtom/gem.json @@ -8,7 +8,14 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "EMotionFX", + "Atom", + "Atom_Feature_Common", + "Atom_RPI", + "Atom_RHI", + "CommonFeaturesAtom" + ] } diff --git a/Gems/AtomLyIntegration/ImguiAtom/gem.json b/Gems/AtomLyIntegration/ImguiAtom/gem.json index 918414f053..6b032275b9 100644 --- a/Gems/AtomLyIntegration/ImguiAtom/gem.json +++ b/Gems/AtomLyIntegration/ImguiAtom/gem.json @@ -8,7 +8,10 @@ "canonical_tags": [ "Gem" ], - "user_tags": [ - ], - "requirements": "" + "user_tags": [], + "requirements": "", + "dependencies": [ + "ImGui", + "Atom_Feature_Common" + ] } diff --git a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/gem.json b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/gem.json index f978d777cf..1cee5c8298 100644 --- a/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/gem.json +++ b/Gems/AtomLyIntegration/TechnicalArt/DccScriptingInterface/gem.json @@ -10,9 +10,10 @@ ], "user_tags": [ "DCC", - "Digital", - "Content", - "Creation" + "Digital", + "Content", + "Creation" ], - "requirements": "" + "requirements": "", + "dependencies": [] } diff --git a/Gems/AtomLyIntegration/gem.json b/Gems/AtomLyIntegration/gem.json index 5af133c8e8..00b3a25f74 100644 --- a/Gems/AtomLyIntegration/gem.json +++ b/Gems/AtomLyIntegration/gem.json @@ -5,8 +5,24 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Atom O3DE Integration Gem provides components, libraries, and functionality to support and integrate Atom Renderer in Open 3D Engine.", - "canonical_tags": ["Gem"], - "user_tags": ["Rendering", "Core", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Rendering", + "Core", + "Utility" + ], "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/atom/atom-ly-integration/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/atom/atom-ly-integration/", + "dependencies": [ + "Atom_AtomBridge", + "AtomFont", + "AtomImGuiTools", + "AtomViewportDisplayIcons", + "AtomViewportDisplayInfo", + "CommonFeaturesAtom", + "EMotionFX_Atom", + "ImguiAtom" + ] } diff --git a/Gems/AudioEngineWwise/gem.json b/Gems/AudioEngineWwise/gem.json index 084c924977..0588af1908 100644 --- a/Gems/AudioEngineWwise/gem.json +++ b/Gems/AudioEngineWwise/gem.json @@ -5,9 +5,18 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Wwise Audio Engine Gem provides support for Audiokinetic Wave Works Interactive Sound Engine (Wwise).", - "canonical_tags": ["Gem"], - "user_tags": ["Audio", "Utility", "Tools"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Audio", + "Utility", + "Tools" + ], "icon_path": "preview.png", "requirements": "Users will need to download Wwise from the Audiokinetic Web Site.", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/audio/wwise/audio-engine-wwise/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/audio/wwise/audio-engine-wwise/", + "dependencies": [ + "AudioSystem" + ] } diff --git a/Gems/AudioSystem/gem.json b/Gems/AudioSystem/gem.json index f618103803..64d4d9af5a 100644 --- a/Gems/AudioSystem/gem.json +++ b/Gems/AudioSystem/gem.json @@ -5,9 +5,18 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Audio System Gem provides the Audio Translation Layer (ATL) and Audio Controls Editor, which add support for audio in Open 3D Engine.", - "canonical_tags": ["Gem"], - "user_tags": ["Audio", "Utility", "Tools"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Audio", + "Utility", + "Tools" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/audio/audio-system/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/audio/audio-system/", + "dependencies": [ + "LmbrCentral" + ] } diff --git a/Gems/BarrierInput/gem.json b/Gems/BarrierInput/gem.json index 738d644d84..7fdc58e8b3 100644 --- a/Gems/BarrierInput/gem.json +++ b/Gems/BarrierInput/gem.json @@ -5,8 +5,17 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Barrier Input Gem allows the Open 3D Engine to function as a Barrier client so that it can receive input from a remote Barrier server.", - "canonical_tags": ["Gem"], - "user_tags": ["Input", "Barrier", "Synergy"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Input", + "Barrier", + "Synergy" + ], "icon_path": "preview.png", - "requirements": "" + "requirements": "", + "dependencies": [ + "Atom_RPI" + ] } diff --git a/Gems/Blast/gem.json b/Gems/Blast/gem.json index 3b1205d6fe..d6af47f482 100644 --- a/Gems/Blast/gem.json +++ b/Gems/Blast/gem.json @@ -5,9 +5,22 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The NVIDIA Blast Gem provides tools to author fractured mesh assets in Houdini, and functionality to create realistic destruction simulations in Open 3D Engine.", - "canonical_tags": ["Gem"], - "user_tags": ["Physics", "Simulation", "Animation"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Physics", + "Simulation", + "Animation" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/physics/nvidia/nvidia-blast/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/physics/nvidia/nvidia-blast/", + "dependencies": [ + "Atom_Feature_Common", + "CommonFeaturesAtom", + "PhysX", + "Atom_RPI", + "PythonAssetBuilder" + ] } diff --git a/Gems/Camera/gem.json b/Gems/Camera/gem.json index 2fc2ea8355..9f8ea22412 100644 --- a/Gems/Camera/gem.json +++ b/Gems/Camera/gem.json @@ -5,9 +5,17 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Camera Gem provides a basic camera component that defines a frustum for runtime rendering.", - "canonical_tags": ["Gem"], - "user_tags": ["Rendering", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Rendering", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/camera/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/camera/", + "dependencies": [ + "Atom_RPI" + ] } diff --git a/Gems/CameraFramework/gem.json b/Gems/CameraFramework/gem.json index 2ab25a84b4..c5520fd5b4 100644 --- a/Gems/CameraFramework/gem.json +++ b/Gems/CameraFramework/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Camera Framework Gem provides a base for implementing more complex camera systems.", - "canonical_tags": ["Gem"], - "user_tags": ["Rendering", "Framework", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Rendering", + "Framework", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/camera-framework/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/camera-framework/", + "dependencies": [] } diff --git a/Gems/CertificateManager/gem.json b/Gems/CertificateManager/gem.json index cb49abc6b6..968da2788a 100644 --- a/Gems/CertificateManager/gem.json +++ b/Gems/CertificateManager/gem.json @@ -5,9 +5,15 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Certificate Manager Gem provides access to authentication files for secure game connections from Amazon S3, files on disk, and other 3rd party sources.", - "canonical_tags": ["Gem"], - "user_tags": ["Network", "Framework"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Network", + "Framework" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/network/certificate-manager/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/network/certificate-manager/", + "dependencies": [] } diff --git a/Gems/CrashReporting/gem.json b/Gems/CrashReporting/gem.json index bff54dcf36..9b8d3a9e0a 100644 --- a/Gems/CrashReporting/gem.json +++ b/Gems/CrashReporting/gem.json @@ -5,9 +5,15 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Crash Reporting Gem provides support for external crash reporting for Open 3D Engine projects.", - "canonical_tags": ["Gem"], - "user_tags": ["Debug", "Framework"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Debug", + "Framework" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/debug/crash-reporting/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/debug/crash-reporting/", + "dependencies": [] } diff --git a/Gems/CustomAssetExample/gem.json b/Gems/CustomAssetExample/gem.json index ac7c2788d7..ab5ed7002d 100644 --- a/Gems/CustomAssetExample/gem.json +++ b/Gems/CustomAssetExample/gem.json @@ -5,9 +5,15 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Custom Asset Example Gem provides example code for creating a custom asset for Open 3D Engine's asset pipeline.", - "canonical_tags": ["Gem"], - "user_tags": ["Assets", "Tools"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Assets", + "Tools" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/assets/custom-asset-example/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/assets/custom-asset-example/", + "dependencies": [] } diff --git a/Gems/DebugDraw/gem.json b/Gems/DebugDraw/gem.json index a7939f4077..7e0da07103 100644 --- a/Gems/DebugDraw/gem.json +++ b/Gems/DebugDraw/gem.json @@ -5,9 +5,19 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Debug Draw Gem provides Editor and runtime debug visualization features for Open 3D Engine.", - "canonical_tags": ["Gem"], - "user_tags": ["Debug", "Tools", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Debug", + "Tools", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/debug/debug-draw/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/debug/debug-draw/", + "dependencies": [ + "Atom_RPI", + "Atom_Bootstrap" + ] } diff --git a/Gems/DevTextures/gem.json b/Gems/DevTextures/gem.json index 81d14e78cb..8b40badbf1 100644 --- a/Gems/DevTextures/gem.json +++ b/Gems/DevTextures/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Asset", "summary": "The Dev Textures Gem provides a collection of general purpose texture assets useful for prototypes and preproduction.", - "canonical_tags": ["Gem"], - "user_tags": ["Assets", "Debug", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Assets", + "Debug", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/assets/dev-textures/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/assets/dev-textures/", + "dependencies": [] } diff --git a/Gems/EMotionFX/gem.json b/Gems/EMotionFX/gem.json index f00803ec2c..f1734d854d 100644 --- a/Gems/EMotionFX/gem.json +++ b/Gems/EMotionFX/gem.json @@ -5,9 +5,19 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The EMotion FX Animation Gem provides Open 3D Engine's animation system for rigged actors and includes Animation Editor, a tool for creating animated behaviors, simulated objects, and colliders for rigged actors.", - "canonical_tags": ["Gem"], - "user_tags": ["Animation", "Tools", "Simulation"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Animation", + "Tools", + "Simulation" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/animation/emotionfx/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/animation/emotionfx/", + "dependencies": [ + "Atom_RPI", + "LmbrCentral" + ] } diff --git a/Gems/EditorPythonBindings/gem.json b/Gems/EditorPythonBindings/gem.json index fae091a63f..13c5800dd7 100644 --- a/Gems/EditorPythonBindings/gem.json +++ b/Gems/EditorPythonBindings/gem.json @@ -5,9 +5,15 @@ "origin": "Open 3D Engine - o3de.org", "type": "Tool", "summary": "The Editor Python Bindings Gem provides Python commands for Open 3D Engine Editor functions.", - "canonical_tags": ["Gem"], - "user_tags": ["Scripting", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Scripting", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/python/editor-python-bindings/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/python/editor-python-bindings/", + "dependencies": [] } diff --git a/Gems/ExpressionEvaluation/gem.json b/Gems/ExpressionEvaluation/gem.json index 2f555916a5..6bcc666a4d 100644 --- a/Gems/ExpressionEvaluation/gem.json +++ b/Gems/ExpressionEvaluation/gem.json @@ -5,9 +5,15 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Expression Evaluation Gem provides a method for parsing and executing string expressions in Open 3D Engine.", - "canonical_tags": ["Gem"], - "user_tags": ["Scripting", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Scripting", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/expression-evaluation/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/expression-evaluation/", + "dependencies": [] } diff --git a/Gems/FastNoise/gem.json b/Gems/FastNoise/gem.json index 5ee5bbaf89..ac59fe804e 100644 --- a/Gems/FastNoise/gem.json +++ b/Gems/FastNoise/gem.json @@ -5,9 +5,20 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The FastNoise Gradient Gem uses the third-party, open source FastNoise library to provide a variety of high-performance noise generation algorithms.", - "canonical_tags": ["Gem"], - "user_tags": ["Utility", "Tools", "Design"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Utility", + "Tools", + "Design" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/utility/fast-noise/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/utility/fast-noise/", + "dependencies": [ + "GradientSignal", + "LmbrCentral", + "SurfaceData" + ] } diff --git a/Gems/GameState/gem.json b/Gems/GameState/gem.json index a1f272c290..7bb3cf4214 100644 --- a/Gems/GameState/gem.json +++ b/Gems/GameState/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Game State Gem provides a generic framework to determine and manage game states and game state transitions in Open 3D Engine.", - "canonical_tags": ["Gem"], - "user_tags": ["Gameplay", "Framework", "Scripting"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Gameplay", + "Framework", + "Scripting" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/gameplay/game-state/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/gameplay/game-state/", + "dependencies": [] } diff --git a/Gems/GameStateSamples/gem.json b/Gems/GameStateSamples/gem.json index f0dd82c5fa..be982b9c5b 100644 --- a/Gems/GameStateSamples/gem.json +++ b/Gems/GameStateSamples/gem.json @@ -5,9 +5,25 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Game State Samples Gem provides a set of sample game states (built on top of the Game State Gem), including primary user selection, main menu, level loading, level running, and level paused.", - "canonical_tags": ["Gem"], - "user_tags": ["Gameplay", "Sample", "Assets"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Gameplay", + "Sample", + "Assets" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/gameplay/game-state-samples/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/gameplay/game-state-samples/", + "dependencies": [ + "GameState", + "LocalUser", + "LyShine", + "SaveData", + "MessagePopup", + "LmbrCentral", + "UiBasics", + "LyShineExamples" + ] } diff --git a/Gems/Gestures/gem.json b/Gems/Gestures/gem.json index 4412e58c6d..fcc56b4704 100644 --- a/Gems/Gestures/gem.json +++ b/Gems/Gestures/gem.json @@ -5,9 +5,18 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Gestures Gem provides detection for common gesture-based input actions on iOS and Android devices.", - "canonical_tags": ["Gem"], - "user_tags": ["Input", "Gameplay", "Scripting"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Input", + "Gameplay", + "Scripting" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/input/gestures/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/input/gestures/", + "dependencies": [ + "Atom_RPI" + ] } diff --git a/Gems/GradientSignal/gem.json b/Gems/GradientSignal/gem.json index 67afb1f819..e87ccfe13a 100644 --- a/Gems/GradientSignal/gem.json +++ b/Gems/GradientSignal/gem.json @@ -5,9 +5,20 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Gradient Signal Gem provides a number of components for generating, modifying, and mixing gradient signals.", - "canonical_tags": ["Gem"], - "user_tags": ["Utility", "Tools", "Design"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Utility", + "Tools", + "Design" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/utility/gradient-signal/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/utility/gradient-signal/", + "dependencies": [ + "SurfaceData", + "ImageProcessingAtom", + "LmbrCentral" + ] } diff --git a/Gems/GraphCanvas/gem.json b/Gems/GraphCanvas/gem.json index ab1e7ac77a..760bd157df 100644 --- a/Gems/GraphCanvas/gem.json +++ b/Gems/GraphCanvas/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Tool", "summary": "The Graph Canvas Gem provides a C++ framework for creating custom graphical node based editors for Open 3D Engine.", - "canonical_tags": ["Gem"], - "user_tags": ["Framework", "Tools", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Framework", + "Tools", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/framework/graph-canvas/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/framework/graph-canvas/", + "dependencies": [] } diff --git a/Gems/GraphModel/gem.json b/Gems/GraphModel/gem.json index 62f1effb7c..256de75f6c 100644 --- a/Gems/GraphModel/gem.json +++ b/Gems/GraphModel/gem.json @@ -5,9 +5,18 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Graph Model Gem provides a generic node graph data model framework for Open 3D Engine.", - "canonical_tags": ["Gem"], - "user_tags": ["Framework", "Tools", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Framework", + "Tools", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/framework/graph-model/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/framework/graph-model/", + "dependencies": [ + "GraphCanvas" + ] } diff --git a/Gems/HttpRequestor/gem.json b/Gems/HttpRequestor/gem.json index e5eb8d6f44..eb1a112b0e 100644 --- a/Gems/HttpRequestor/gem.json +++ b/Gems/HttpRequestor/gem.json @@ -5,9 +5,15 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The HTTP Requestor Gem provides functionality to make asynchronous HTTP/HTTPS requests and return data through a user-provided call back function.", - "canonical_tags": ["Gem"], - "user_tags": ["Network", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Network", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/network/http-requestor/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/network/http-requestor/", + "dependencies": [] } diff --git a/Gems/ImGui/gem.json b/Gems/ImGui/gem.json index deaac9925a..c1d89d1728 100644 --- a/Gems/ImGui/gem.json +++ b/Gems/ImGui/gem.json @@ -5,9 +5,18 @@ "origin": "Open 3D Engine - o3de.org", "type": "Tool", "summary": "The Immediate Mode GUI Gem provides the 3rdParty library IMGUI which can be used to create run time immediate mode overlays for debugging and profiling information in Open 3D Engine.", - "canonical_tags": ["Gem"], - "user_tags": ["Debug", "Rendering", "Framework"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Debug", + "Rendering", + "Framework" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/debug/imgui/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/debug/imgui/", + "dependencies": [ + "LmbrCentral" + ] } diff --git a/Gems/InAppPurchases/gem.json b/Gems/InAppPurchases/gem.json index ab43075896..1f1debd5fb 100644 --- a/Gems/InAppPurchases/gem.json +++ b/Gems/InAppPurchases/gem.json @@ -5,9 +5,15 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The In-App Purchases Gem provides functionality for in app purchases for iOS and Android.", - "canonical_tags": ["Gem"], - "user_tags": ["SDK", "Network"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "SDK", + "Network" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/sdk/in-app-purchases/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/sdk/in-app-purchases/", + "dependencies": [] } diff --git a/Gems/LandscapeCanvas/gem.json b/Gems/LandscapeCanvas/gem.json index 63a80ec57e..ce0c64b75d 100644 --- a/Gems/LandscapeCanvas/gem.json +++ b/Gems/LandscapeCanvas/gem.json @@ -5,9 +5,23 @@ "origin": "Open 3D Engine - o3de.org", "type": "Tool", "summary": "The Landscape Canvas Gem provides the Landscape Canvas editor, a node-based graph tool for authoring workflows to populate landscape with dynamic vegetation.", - "canonical_tags": ["Gem"], - "user_tags": ["Environment", "Design", "Tools"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Environment", + "Design", + "Tools" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/environment/landscape-canvas/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/environment/landscape-canvas/", + "dependencies": [ + "GraphModel", + "GradientSignal", + "SurfaceData", + "Vegetation", + "LmbrCentral", + "GraphCanvas" + ] } diff --git a/Gems/LmbrCentral/gem.json b/Gems/LmbrCentral/gem.json index b6442bfd06..36de4c4ed3 100644 --- a/Gems/LmbrCentral/gem.json +++ b/Gems/LmbrCentral/gem.json @@ -5,10 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The O3DE Core (LmbrCentral) Gem provides required code and assets for running Open 3D Engine Editor.", - "canonical_tags": ["Gem"], - "user_tags": ["Core", "Framework", "Assets"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Core", + "Framework", + "Assets" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/core/lmbr-central/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/core/lmbr-central/", + "dependencies": [] } - diff --git a/Gems/LocalUser/gem.json b/Gems/LocalUser/gem.json index dcf4d44abb..f86e6e1bf6 100644 --- a/Gems/LocalUser/gem.json +++ b/Gems/LocalUser/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Local User Gem provides functionality for mapping local user ids to local player slots and managing local user profiles.", - "canonical_tags": ["Gem"], - "user_tags": ["Input", "Gameplay", "Scripting"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Input", + "Gameplay", + "Scripting" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/input/local-user/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/input/local-user/", + "dependencies": [] } diff --git a/Gems/LyShine/gem.json b/Gems/LyShine/gem.json index e0fdb860e5..e2da8afa4d 100644 --- a/Gems/LyShine/gem.json +++ b/Gems/LyShine/gem.json @@ -5,9 +5,24 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The LyShine Gem provides the runtime UI system and creation tools for Open 3D Engine projects.", - "canonical_tags": ["Gem"], - "user_tags": ["UI", "Tools", "Framework"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "UI", + "Tools", + "Framework" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/ui/lyshine/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/ui/lyshine/", + "dependencies": [ + "LmbrCentral", + "Atom_RPI", + "Atom", + "Atom_Bootstrap", + "AtomFont", + "TextureAtlas", + "AtomToolsFramework" + ] } diff --git a/Gems/LyShineExamples/gem.json b/Gems/LyShineExamples/gem.json index a411bfb363..122273f6d9 100644 --- a/Gems/LyShineExamples/gem.json +++ b/Gems/LyShineExamples/gem.json @@ -5,9 +5,19 @@ "origin": "Open 3D Engine - o3de.org", "type": "Asset", "summary": "The LyShine Examples Gem provides example code and assets for LyShine, the runtime UI system and editor for Open 3D Engine projects.", - "canonical_tags": ["Gem"], - "user_tags": ["UI", "Sample", "Assets"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "UI", + "Sample", + "Assets" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/ui/lyshine-examples/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/ui/lyshine-examples/", + "dependencies": [ + "LmbrCentral", + "LyShine" + ] } diff --git a/Gems/Maestro/gem.json b/Gems/Maestro/gem.json index 6ee989aa55..5149df7c14 100644 --- a/Gems/Maestro/gem.json +++ b/Gems/Maestro/gem.json @@ -5,10 +5,18 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Maestro Cinematics Gem provides Track View, Open 3D Engine's animated sequence and cinematics editor.", - "canonical_tags": ["Gem"], - "user_tags": ["Animation", "Tools", "Scripting"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Animation", + "Tools", + "Scripting" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/animation/maestro/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/animation/maestro/", + "dependencies": [ + "LmbrCentral" + ] } - diff --git a/Gems/MessagePopup/gem.json b/Gems/MessagePopup/gem.json index 2560b8869a..05d36bc2df 100644 --- a/Gems/MessagePopup/gem.json +++ b/Gems/MessagePopup/gem.json @@ -5,9 +5,15 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Message Popup Gem provides an example implementation of popup messages using LyShine in Open 3D Engine.", - "canonical_tags": ["Gem"], - "user_tags": ["Gameplay", "Sample"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Gameplay", + "Sample" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/ui/message-popup/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/ui/message-popup/", + "dependencies": [] } diff --git a/Gems/Metastream/gem.json b/Gems/Metastream/gem.json index 429d174cf5..862b17dd1d 100644 --- a/Gems/Metastream/gem.json +++ b/Gems/Metastream/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Metastream Gem provides functionality for an HTTP server that allows broadcasters to customize game streams with overlays of statistics and event data from a game session.", - "canonical_tags": ["Gem"], - "user_tags": ["Gameplay", "Network", "Framework"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Gameplay", + "Network", + "Framework" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/network/twitch/metastream/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/network/twitch/metastream/", + "dependencies": [] } diff --git a/Gems/Microphone/gem.json b/Gems/Microphone/gem.json index cc47cbcd7e..68492ea786 100644 --- a/Gems/Microphone/gem.json +++ b/Gems/Microphone/gem.json @@ -5,9 +5,17 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Microphone Gem provides support for audio input through microphones.", - "canonical_tags": ["Gem"], - "user_tags": ["Audio", "Input"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Audio", + "Input" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/audio/microphone/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/audio/microphone/", + "dependencies": [ + "AudioSystem" + ] } diff --git a/Gems/Multiplayer/gem.json b/Gems/Multiplayer/gem.json index 8abbddea5f..47dbddfcbd 100644 --- a/Gems/Multiplayer/gem.json +++ b/Gems/Multiplayer/gem.json @@ -5,8 +5,19 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Multiplayer Gem provides a public API for multiplayer functionality such as connecting and hosting.", - "canonical_tags": ["Gem"], - "user_tags": ["Multiplayer", "Network", "Framework"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Multiplayer", + "Network", + "Framework" + ], "icon_path": "preview.png", - "requirements": "" + "requirements": "", + "dependencies": [ + "CertificateManager", + "Atom_Feature_Common", + "ImGui" + ] } diff --git a/Gems/MultiplayerCompression/gem.json b/Gems/MultiplayerCompression/gem.json index 178cca0ffe..7dd31476e3 100644 --- a/Gems/MultiplayerCompression/gem.json +++ b/Gems/MultiplayerCompression/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Multiplayer Compression Gem provides an open source Compressor for use with AzNetworking's transport layer.", - "canonical_tags": ["Gem"], - "user_tags": ["Multiplayer", "Network", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Multiplayer", + "Network", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/multiplayer/multiplayer-compression/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/multiplayer/multiplayer-compression/", + "dependencies": [] } diff --git a/Gems/NvCloth/gem.json b/Gems/NvCloth/gem.json index 49ccbf32f1..019ce23742 100644 --- a/Gems/NvCloth/gem.json +++ b/Gems/NvCloth/gem.json @@ -5,9 +5,19 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The NVIDIA Cloth Gem provides functionality to create fast, realistic cloth simulation with the NVIDIA Cloth library.", - "canonical_tags": ["Gem"], - "user_tags": ["Physics", "Simulation", "SDK"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Physics", + "Simulation", + "SDK" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/physics/nvidia/nvidia-cloth/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/physics/nvidia/nvidia-cloth/", + "dependencies": [ + "CommonFeaturesAtom", + "EMotionFX" + ] } diff --git a/Gems/PBSreferenceMaterials/gem.json b/Gems/PBSreferenceMaterials/gem.json index 563dd31a38..feddc1e465 100644 --- a/Gems/PBSreferenceMaterials/gem.json +++ b/Gems/PBSreferenceMaterials/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Asset", "summary": "The PBS Reference Materials Gem provides physically based reference materials for Open 3D Engine.", - "canonical_tags": ["Gem"], - "user_tags": ["Rendering", "Sample", "Assets"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Rendering", + "Sample", + "Assets" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/pbs-reference-materials/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/pbs-reference-materials/", + "dependencies": [] } diff --git a/Gems/PhysX/gem.json b/Gems/PhysX/gem.json index 0fbd3e44f9..bacbcf2dee 100644 --- a/Gems/PhysX/gem.json +++ b/Gems/PhysX/gem.json @@ -5,9 +5,19 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The PhysX Gem provides physics simulation with NVIDIA PhysX including static and dynamic rigid body simulation, force regions, ragdolls, and dynamic PhysX joints.", - "canonical_tags": ["Gem"], - "user_tags": ["Physics", "Simulation", "SDK"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Physics", + "Simulation", + "SDK" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/physics/nvidia/physx/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/physics/nvidia/physx/", + "dependencies": [ + "LmbrCentral", + "CommonFeaturesAtom" + ] } diff --git a/Gems/PhysXDebug/gem.json b/Gems/PhysXDebug/gem.json index f7877cabdd..ece0774210 100644 --- a/Gems/PhysXDebug/gem.json +++ b/Gems/PhysXDebug/gem.json @@ -5,9 +5,19 @@ "origin": "Open 3D Engine - o3de.org", "type": "Tool", "summary": "The PhysX Debug Gem provides debugging functionality and visualizations for NVIDIA PhysX in Open 3D Engine.", - "canonical_tags": ["Gem"], - "user_tags": ["Physics", "Simulation", "Debug"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Physics", + "Simulation", + "Debug" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/physics/nvidia/physx-debug/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/physics/nvidia/physx-debug/", + "dependencies": [ + "PhysX", + "ImGui" + ] } diff --git a/Gems/PhysXSamples/gem.json b/Gems/PhysXSamples/gem.json index e48dc6991b..0c84a29f47 100644 --- a/Gems/PhysXSamples/gem.json +++ b/Gems/PhysXSamples/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Asset", "summary": "The PhysX Samples Gem provides sample assets and scripts that demonstrate PhysX Gem features in Open 3D Engine.", - "canonical_tags": ["Gem"], - "user_tags": ["Physics", "Simulation", "Sample"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Physics", + "Simulation", + "Sample" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/physics/nvidia/physx-samples/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/physics/nvidia/physx-samples/", + "dependencies": [] } diff --git a/Gems/Prefab/PrefabBuilder/gem.json b/Gems/Prefab/PrefabBuilder/gem.json index ad6062ae3b..ba78f96358 100644 --- a/Gems/Prefab/PrefabBuilder/gem.json +++ b/Gems/Prefab/PrefabBuilder/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Prefab Builder Gem provides an Asset Processor module for prefabs, which are complex assets built by combining smaller entities.", - "canonical_tags": ["Gem"], - "user_tags": ["Assets", "Utility", "Core"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Assets", + "Utility", + "Core" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/assets/prefab/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/assets/prefab/", + "dependencies": [] } diff --git a/Gems/Presence/gem.json b/Gems/Presence/gem.json index 49d937946d..a70953ae4e 100644 --- a/Gems/Presence/gem.json +++ b/Gems/Presence/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Presence Gem provides a target platform agnostic interface for Presence services.", - "canonical_tags": ["Gem"], - "user_tags": ["Network", "Gameplay", "Framework"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Network", + "Gameplay", + "Framework" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/network/presence/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/network/presence/", + "dependencies": [] } diff --git a/Gems/PrimitiveAssets/gem.json b/Gems/PrimitiveAssets/gem.json index d1789d46fe..4ad3cb62ad 100644 --- a/Gems/PrimitiveAssets/gem.json +++ b/Gems/PrimitiveAssets/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Asset", "summary": "The Primitive Assets Gem provides primitive shape mesh assets with physics enabled.", - "canonical_tags": ["Gem"], - "user_tags": ["Assets", "Sample", "Debug"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Assets", + "Sample", + "Debug" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/assets/primitive-assets/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/assets/primitive-assets/", + "dependencies": [] } diff --git a/Gems/PythonAssetBuilder/gem.json b/Gems/PythonAssetBuilder/gem.json index 1a76d7d2c2..ce30ba9e82 100644 --- a/Gems/PythonAssetBuilder/gem.json +++ b/Gems/PythonAssetBuilder/gem.json @@ -5,9 +5,18 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Python Asset Builder Gem provides functionality to implement custom asset builders in Python for Asset Processor.", - "canonical_tags": ["Gem"], - "user_tags": ["Scripting", "Assets", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Scripting", + "Assets", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/python/python-asset-builder/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/python/python-asset-builder/", + "dependencies": [ + "EditorPythonBindings" + ] } diff --git a/Gems/QtForPython/gem.json b/Gems/QtForPython/gem.json index 1519d46c52..f83be43342 100644 --- a/Gems/QtForPython/gem.json +++ b/Gems/QtForPython/gem.json @@ -5,9 +5,18 @@ "origin": "Open 3D Engine - o3de.org", "type": "Tool", "summary": "The Qt for Python Gem provides the PySide2 Python libraries to manage Qt widgets.", - "canonical_tags": ["Gem"], - "user_tags": ["Scripting", "UI", "Framework"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Scripting", + "UI", + "Framework" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/python/qt-for-python/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/python/qt-for-python/", + "dependencies": [ + "EditorPythonBindings" + ] } diff --git a/Gems/SaveData/gem.json b/Gems/SaveData/gem.json index 3892cc80c2..333b4682d2 100644 --- a/Gems/SaveData/gem.json +++ b/Gems/SaveData/gem.json @@ -5,9 +5,15 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Save Data Gem provides a platform independent API to save and load persistent user data in Open 3D Engine projects.", - "canonical_tags": ["Gem"], - "user_tags": ["Utility", "Gameplay"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Utility", + "Gameplay" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/utility/save-data/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/utility/save-data/", + "dependencies": [] } diff --git a/Gems/SceneLoggingExample/gem.json b/Gems/SceneLoggingExample/gem.json index ff7def1b32..16961b9c5b 100644 --- a/Gems/SceneLoggingExample/gem.json +++ b/Gems/SceneLoggingExample/gem.json @@ -5,9 +5,15 @@ "origin": "Open 3D Engine - o3de.org", "type": "Asset", "summary": "The Scene Logging Example Gem demonstrates the basics of extending the Open 3D Engine Scene API by adding additional logging to the pipeline.", - "canonical_tags": ["Gem"], - "user_tags": ["Debug", "Sample"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Debug", + "Sample" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/utility/scene-logging-example/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/utility/scene-logging-example/", + "dependencies": [] } diff --git a/Gems/SceneProcessing/gem.json b/Gems/SceneProcessing/gem.json index a6c2cefbd6..de1dfeb23f 100644 --- a/Gems/SceneProcessing/gem.json +++ b/Gems/SceneProcessing/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Tool", "summary": "The Scene Processing Gem provides Scene Settings, a tool you can use to specify the default settings for processing asset files for actors, meshes, motions, and PhysX.", - "canonical_tags": ["Gem"], - "user_tags": ["Assets", "Tools", "Core"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Assets", + "Tools", + "Core" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/assets/scene-processing/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/assets/scene-processing/", + "dependencies": [] } diff --git a/Gems/ScriptCanvas/gem.json b/Gems/ScriptCanvas/gem.json index b6b5522d7d..621ea42961 100644 --- a/Gems/ScriptCanvas/gem.json +++ b/Gems/ScriptCanvas/gem.json @@ -5,9 +5,20 @@ "origin": "Open 3D Engine - o3de.org", "type": "Tool", "summary": "The Script Canvas Gem provides Open 3D Engine's visual scripting environment, Script Canvas.", - "canonical_tags": ["Gem"], - "user_tags": ["Scripting", "Tools", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Scripting", + "Tools", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/script-canvas/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/script-canvas/", + "dependencies": [ + "ScriptEvents", + "ExpressionEvaluation", + "GraphCanvas" + ] } diff --git a/Gems/ScriptCanvasDeveloper/gem.json b/Gems/ScriptCanvasDeveloper/gem.json index d7b0aefad3..ee1bfcec84 100644 --- a/Gems/ScriptCanvasDeveloper/gem.json +++ b/Gems/ScriptCanvasDeveloper/gem.json @@ -5,9 +5,19 @@ "origin": "Open 3D Engine - o3de.org", "type": "Tool", "summary": "The Script Canvas Developer Gem provides a suite of utility features for the development and debugging of Script Canvas systems.", - "canonical_tags": ["Gem"], - "user_tags": ["Scripting", "Utility", "Debug"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Scripting", + "Utility", + "Debug" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/script-canvas-developer/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/script-canvas-developer/", + "dependencies": [ + "ScriptCanvas", + "GraphCanvas" + ] } diff --git a/Gems/ScriptCanvasPhysics/gem.json b/Gems/ScriptCanvasPhysics/gem.json index 46e2ef1194..417fa6893a 100644 --- a/Gems/ScriptCanvasPhysics/gem.json +++ b/Gems/ScriptCanvasPhysics/gem.json @@ -5,9 +5,18 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Script Canvas Physics Gem provides Script Canvas nodes for physics scene queries such as raycasts.", - "canonical_tags": ["Gem"], - "user_tags": ["Scripting", "Physics", "Simulation"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Scripting", + "Physics", + "Simulation" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/script-canvas-physics/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/script-canvas-physics/", + "dependencies": [ + "ScriptCanvas" + ] } diff --git a/Gems/ScriptCanvasTesting/gem.json b/Gems/ScriptCanvasTesting/gem.json index 303eab8c7e..c45d2ac165 100644 --- a/Gems/ScriptCanvasTesting/gem.json +++ b/Gems/ScriptCanvasTesting/gem.json @@ -5,9 +5,20 @@ "origin": "Open 3D Engine - o3de.org", "type": "Tool", "summary": "The Script Canvas Testing Gem provides a framework for testing for and with Script Canvas.", - "canonical_tags": ["Gem"], - "user_tags": ["Scripting", "Debug", "Framework"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Scripting", + "Debug", + "Framework" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/script-canvas-testing/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/script-canvas-testing/", + "dependencies": [ + "ScriptCanvas", + "GraphCanvas", + "ScriptEvents" + ] } diff --git a/Gems/ScriptEvents/gem.json b/Gems/ScriptEvents/gem.json index 2b7d74ef3f..386d9b5614 100644 --- a/Gems/ScriptEvents/gem.json +++ b/Gems/ScriptEvents/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Script Events Gem provides a framework for creating event assets usable from any scripting solution in Open 3D Engine.", - "canonical_tags": ["Gem"], - "user_tags": ["Scripting", "Framework", "Gameplay"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Scripting", + "Framework", + "Gameplay" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/script-events/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/script-events/", + "dependencies": [] } diff --git a/Gems/ScriptedEntityTweener/gem.json b/Gems/ScriptedEntityTweener/gem.json index a0f558356b..c51f05df9a 100644 --- a/Gems/ScriptedEntityTweener/gem.json +++ b/Gems/ScriptedEntityTweener/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Tool", "summary": "The Scripted Entity Tweener Gem provides a script driven animation system for Open 3D Engine projects.", - "canonical_tags": ["Gem"], - "user_tags": ["Scripting", "UI", "Animation"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Scripting", + "UI", + "Animation" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/scripted-entity-tweener/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/script/scripted-entity-tweener/", + "dependencies": [] } diff --git a/Gems/SliceFavorites/gem.json b/Gems/SliceFavorites/gem.json index 3ae37e2145..84f42fc1a2 100644 --- a/Gems/SliceFavorites/gem.json +++ b/Gems/SliceFavorites/gem.json @@ -5,7 +5,11 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "Add the ability to favorite a slice to allow easy access and instantiation", - "user_tags": ["Editor", "Slices"], + "user_tags": [ + "Editor", + "Slices" + ], "icon_path": "preview.png", - "requirements": "" + "requirements": "", + "dependencies": [] } diff --git a/Gems/StartingPointCamera/gem.json b/Gems/StartingPointCamera/gem.json index 5a9aa0df9b..613eb76267 100644 --- a/Gems/StartingPointCamera/gem.json +++ b/Gems/StartingPointCamera/gem.json @@ -5,9 +5,19 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Starting Point Camera Gem provides the behaviors used with the Camera Framework Gem to define a camera rig.", - "canonical_tags": ["Gem"], - "user_tags": ["Rendering", "Gameplay", "Scripting"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Rendering", + "Gameplay", + "Scripting" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/starting-point-camera/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/starting-point-camera/", + "dependencies": [ + "CameraFramework", + "LmbrCentral" + ] } diff --git a/Gems/StartingPointInput/gem.json b/Gems/StartingPointInput/gem.json index e65f271fe5..d2641ea27b 100644 --- a/Gems/StartingPointInput/gem.json +++ b/Gems/StartingPointInput/gem.json @@ -5,9 +5,18 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Starting Point Input Gem provides functionality to map low-level input events to high-level actions.", - "canonical_tags": ["Gem"], - "user_tags": ["Input", "Gameplay", "Scripting"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Input", + "Gameplay", + "Scripting" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/input/starting-point-input/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/input/starting-point-input/", + "dependencies": [ + "ScriptCanvas" + ] } diff --git a/Gems/StartingPointMovement/gem.json b/Gems/StartingPointMovement/gem.json index 70e1d105c1..7def6da768 100644 --- a/Gems/StartingPointMovement/gem.json +++ b/Gems/StartingPointMovement/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Starting Point Movement Gem provides a series of Lua scripts that listen and respond to input events and trigger transform operations such as translation and rotation.", - "canonical_tags": ["Gem"], - "user_tags": ["Input", "Gameplay", "Scripting"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Input", + "Gameplay", + "Scripting" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/input/starting-point-movement/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/input/starting-point-movement/", + "dependencies": [] } diff --git a/Gems/SurfaceData/gem.json b/Gems/SurfaceData/gem.json index 57e4d8fb70..51a134d5df 100644 --- a/Gems/SurfaceData/gem.json +++ b/Gems/SurfaceData/gem.json @@ -5,9 +5,20 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Surface Data Gem provides functionality to emit signals or tags from surfaces such as meshes and terrain.", - "canonical_tags": ["Gem"], - "user_tags": ["Environment", "Utility", "Design"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Environment", + "Utility", + "Design" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/environment/surface-data/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/environment/surface-data/", + "dependencies": [ + "LmbrCentral", + "Atom_RPI", + "Atom_Feature_Common" + ] } diff --git a/Gems/Terrain/gem.json b/Gems/Terrain/gem.json index c01ea7e534..cd72a91708 100644 --- a/Gems/Terrain/gem.json +++ b/Gems/Terrain/gem.json @@ -4,7 +4,21 @@ "license": "Apache-2.0 Or MIT", "origin": "Open 3D Engine - o3de.org", "summary": "The Terrain Gem is an experimental terrain system. The terrain system maps height, color, and surface data to regions of the world, provides gradient-based and shape-based authoring tools and workflows, includes specialized rendering for efficient display, and integrates with physics for physical simulation.", - "canonical_tags": [ "Gem" ], - "user_tags": [ "Environment", "Tools", "Design", "Terrain" ], - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/terrain/" + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Environment", + "Tools", + "Design", + "Terrain" + ], + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/terrain/", + "dependencies": [ + "Atom_RPI", + "Atom", + "GradientSignal", + "SurfaceData", + "LmbrCentral" + ] } diff --git a/Gems/TestAssetBuilder/gem.json b/Gems/TestAssetBuilder/gem.json index 1e0b84894a..ba7568005f 100644 --- a/Gems/TestAssetBuilder/gem.json +++ b/Gems/TestAssetBuilder/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Test Asset Builder Gem is used to feature test Asset Processor.", - "canonical_tags": ["Gem"], - "user_tags": ["Assets", "Debug", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Assets", + "Debug", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/assets/test-asset-builder/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/assets/test-asset-builder/", + "dependencies": [] } diff --git a/Gems/TextureAtlas/gem.json b/Gems/TextureAtlas/gem.json index 832dee0e62..345e085359 100644 --- a/Gems/TextureAtlas/gem.json +++ b/Gems/TextureAtlas/gem.json @@ -5,9 +5,19 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Texture Atlas Gem provides the formatting for texture atlases from 2D textures for LyShine.", - "canonical_tags": ["Gem"], - "user_tags": ["Rendering", "Assets", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Rendering", + "Assets", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/utility/texture-atlas/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/utility/texture-atlas/", + "dependencies": [ + "Atom_RPI", + "ImageProcessingAtom" + ] } diff --git a/Gems/TickBusOrderViewer/gem.json b/Gems/TickBusOrderViewer/gem.json index 5ea936960a..dc5cb6f66c 100644 --- a/Gems/TickBusOrderViewer/gem.json +++ b/Gems/TickBusOrderViewer/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Tool", "summary": "The Tick Bus Order Viewer Gem provides a console variable that displays the order of runtime tick events.", - "canonical_tags": ["Gem"], - "user_tags": ["Gameplay", "Simulation", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Gameplay", + "Simulation", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/gameplay/tick-bus-order-viewer/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/gameplay/tick-bus-order-viewer/", + "dependencies": [] } diff --git a/Gems/Twitch/gem.json b/Gems/Twitch/gem.json index 6f875e9171..f45433bc3f 100644 --- a/Gems/Twitch/gem.json +++ b/Gems/Twitch/gem.json @@ -5,9 +5,18 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Twitch Gem provides access to the Twitch API v5 SDK including social functions, channels, and other APIs.", - "canonical_tags": ["Gem"], - "user_tags": ["Network", "SDK", "Multiplayer"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Network", + "SDK", + "Multiplayer" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/network/twitch/twitch/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/network/twitch/twitch/", + "dependencies": [ + "HttpRequestor" + ] } diff --git a/Gems/UiBasics/gem.json b/Gems/UiBasics/gem.json index d1e06eb15a..9a1e16a462 100644 --- a/Gems/UiBasics/gem.json +++ b/Gems/UiBasics/gem.json @@ -5,9 +5,16 @@ "origin": "Open 3D Engine - o3de.org", "type": "Asset", "summary": "The UI Basics Gem provides a collection of basic UI prefabs such as image, text, and button, that can be used with LyShine, the Open 3D Engine runtime User Interface system and editor.", - "canonical_tags": ["Gem"], - "user_tags": ["UI", "Assets", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "UI", + "Assets", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/ui/ui-basics/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/ui/ui-basics/", + "dependencies": [] } diff --git a/Gems/Vegetation/gem.json b/Gems/Vegetation/gem.json index 3119d67560..9dbcc3450b 100644 --- a/Gems/Vegetation/gem.json +++ b/Gems/Vegetation/gem.json @@ -5,9 +5,21 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Vegetation Gem provides tools to place natural-looking vegetation in Open 3D Engine.", - "canonical_tags": ["Gem"], - "user_tags": ["Environment", "Tools", "Design"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Environment", + "Tools", + "Design" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/environment/vegetation/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/environment/vegetation/", + "dependencies": [ + "LmbrCentral", + "SurfaceData", + "CommonFeaturesAtom", + "GradientSignal" + ] } diff --git a/Gems/VideoPlaybackFramework/gem.json b/Gems/VideoPlaybackFramework/gem.json index 15b200c8db..9f491f47cb 100644 --- a/Gems/VideoPlaybackFramework/gem.json +++ b/Gems/VideoPlaybackFramework/gem.json @@ -5,9 +5,15 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Video Playback Framework Gem provides the interface to play back video.", - "canonical_tags": ["Gem"], - "user_tags": ["Rendering", "Framework"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Rendering", + "Framework" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/video-playback-framework/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/video-playback-framework/", + "dependencies": [] } diff --git a/Gems/VirtualGamepad/gem.json b/Gems/VirtualGamepad/gem.json index 472e8b93fe..c6305f1754 100644 --- a/Gems/VirtualGamepad/gem.json +++ b/Gems/VirtualGamepad/gem.json @@ -5,9 +5,15 @@ "origin": "Open 3D Engine - o3de.org", "type": "Code", "summary": "The Virtual Gamepad Gem provides controls that emulate a gamepad on touch screen devices.", - "canonical_tags": ["Gem"], - "user_tags": ["Input", "Gameplay"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Input", + "Gameplay" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/input/virtual-gamepad/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/input/virtual-gamepad/", + "dependencies": [] } diff --git a/Gems/WhiteBox/gem.json b/Gems/WhiteBox/gem.json index 0e44e2fe5e..81e0ad5f88 100644 --- a/Gems/WhiteBox/gem.json +++ b/Gems/WhiteBox/gem.json @@ -5,9 +5,20 @@ "origin": "Open 3D Engine - o3de.org", "type": "Tool", "summary": "The White Box Gem provides White Box rapid design components for Open 3D Engine.", - "canonical_tags": ["Gem"], - "user_tags": ["Design", "Tools", "Utility"], + "canonical_tags": [ + "Gem" + ], + "user_tags": [ + "Design", + "Tools", + "Utility" + ], "icon_path": "preview.png", "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/design/white-box/" + "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/design/white-box/", + "dependencies": [ + "Atom_RPI", + "Atom_Feature_Common", + "CommonFeaturesAtom" + ] } From 4ae95719dee570926fd29696f66f04fde2f66d5f Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Wed, 22 Sep 2021 12:44:18 -0700 Subject: [PATCH 74/84] Initialization changes to pass unit tests. Some interfaces are now retrieved on demand and there's clearer failure paths that don't involve asserts to better handle test/headless initializations. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../FocusMode/FocusModeSystemComponent.cpp | 8 +-- .../FocusMode/FocusModeSystemComponent.h | 2 +- .../Prefab/PrefabFocusHandler.cpp | 49 +++++++++++-------- .../Prefab/PrefabFocusHandler.h | 11 +---- .../Prefab/PrefabPublicHandler.h | 4 ++ .../Prefab/PrefabSystemComponent.cpp | 1 - .../Prefab/PrefabSystemComponent.h | 4 -- 7 files changed, 37 insertions(+), 42 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp index 450e19da3e..e08191032d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp @@ -31,22 +31,18 @@ namespace AzToolsFramework return IsInFocusSubTree(parentId, focusRootId); } - FocusModeSystemComponent::~FocusModeSystemComponent() - { - AZ::Interface::Unregister(this); - } - void FocusModeSystemComponent::Init() { - AZ::Interface::Register(this); } void FocusModeSystemComponent::Activate() { + AZ::Interface::Register(this); } void FocusModeSystemComponent::Deactivate() { + AZ::Interface::Unregister(this); } void FocusModeSystemComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h index 9943d72951..697a4ff998 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.h @@ -26,7 +26,7 @@ namespace AzToolsFramework AZ_COMPONENT(FocusModeSystemComponent, "{6CE522FE-2057-4794-BD05-61E04BD8EA30}"); FocusModeSystemComponent() = default; - virtual ~FocusModeSystemComponent(); + virtual ~FocusModeSystemComponent() = default; // AZ::Component overrides ... void Init() override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp index f74029aa73..2338c8892b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp @@ -14,15 +14,8 @@ namespace AzToolsFramework::Prefab { - PrefabFocusHandler::~PrefabFocusHandler() + PrefabFocusHandler::PrefabFocusHandler() { - AZ::Interface::Unregister(this); - } - - void PrefabFocusHandler::Initialize() - { - m_focusModeInterface = AZ::Interface::Get(); - m_instanceEntityMapperInterface = AZ::Interface::Get(); AZ_Assert( m_instanceEntityMapperInterface, @@ -30,21 +23,35 @@ namespace AzToolsFramework::Prefab "Instance Entity Mapper Interface could not be found. " "Check that it is being correctly initialized."); - m_prefabEditorEntityOwnershipInterface = AZ::Interface::Get(); - AZ_Assert( - m_prefabEditorEntityOwnershipInterface, - "Prefab - PrefabFocusHandler - " - "Prefab Editor Entity Ownership Interface could not be found. " - "Check that it is being correctly initialized."); - AZ::Interface::Register(this); } + PrefabFocusHandler::~PrefabFocusHandler() + { + AZ::Interface::Unregister(this); + } + PrefabFocusOperationResult PrefabFocusHandler::FocusOnOwningPrefab(AZ::EntityId entityId) { - InstanceOptionalReference focusedInstance = (entityId == AZ::EntityId()) - ? m_prefabEditorEntityOwnershipInterface->GetRootPrefabInstance() - : m_instanceEntityMapperInterface->FindOwningInstance(entityId); + InstanceOptionalReference focusedInstance; + + if (entityId == AZ::EntityId()) + { + PrefabEditorEntityOwnershipInterface* prefabEditorEntityOwnershipInterface = + AZ::Interface::Get(); + + if(!prefabEditorEntityOwnershipInterface) + { + return AZ::Failure(AZStd::string("Could not focus on root prefab instance - internal error " + "(PrefabEditorEntityOwnershipInterface unavailable).")); + } + + focusedInstance = prefabEditorEntityOwnershipInterface->GetRootPrefabInstance(); + } + else + { + focusedInstance = m_instanceEntityMapperInterface->FindOwningInstance(entityId); + } if (!focusedInstance.has_value()) { @@ -54,9 +61,11 @@ namespace AzToolsFramework::Prefab m_focusedInstance = focusedInstance; m_focusedTemplateId = focusedInstance->get().GetTemplateId(); - if (m_focusModeInterface) + + FocusModeInterface* focusModeInterface = AZ::Interface::Get(); + if (focusModeInterface) { - m_focusModeInterface->SetFocusRoot(focusedInstance->get().GetContainerEntityId()); + focusModeInterface->SetFocusRoot(focusedInstance->get().GetContainerEntityId()); } return AZ::Success(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h index b465f97908..fa7727894d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h @@ -14,12 +14,6 @@ #include #include -namespace AzToolsFramework -{ - class FocusModeInterface; - class PrefabEditorEntityOwnershipInterface; -} - namespace AzToolsFramework::Prefab { class InstanceEntityMapperInterface; @@ -31,10 +25,9 @@ namespace AzToolsFramework::Prefab public: AZ_CLASS_ALLOCATOR(PrefabFocusHandler, AZ::SystemAllocator, 0); + PrefabFocusHandler(); ~PrefabFocusHandler(); - void Initialize(); - // PrefabFocusInterface override ... PrefabFocusOperationResult FocusOnOwningPrefab(AZ::EntityId entityId) override; TemplateId GetFocusedPrefabTemplateId() override; @@ -45,9 +38,7 @@ namespace AzToolsFramework::Prefab InstanceOptionalReference m_focusedInstance; TemplateId m_focusedTemplateId; - FocusModeInterface* m_focusModeInterface; InstanceEntityMapperInterface* m_instanceEntityMapperInterface; - PrefabEditorEntityOwnershipInterface* m_prefabEditorEntityOwnershipInterface; }; } // namespace AzToolsFramework::Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h index 42b6bc1666..f3c0e67d46 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -189,6 +190,9 @@ namespace AzToolsFramework PrefabLoaderInterface* m_prefabLoaderInterface = nullptr; PrefabSystemComponentInterface* m_prefabSystemComponentInterface = nullptr; + // Handles the Prefab Focus API that determines what prefab is being edited. + PrefabFocusHandler m_prefabFocusHandler; + // Caches entity states for undo/redo purposes PrefabUndoCache m_prefabUndoCache; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp index 7220cf3cce..0d2696f14b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.cpp @@ -34,7 +34,6 @@ namespace AzToolsFramework m_prefabLoader.RegisterPrefabLoaderInterface(); m_instanceUpdateExecutor.RegisterInstanceUpdateExecutorInterface(); m_instanceToTemplatePropagator.RegisterInstanceToTemplateInterface(); - m_prefabFocusHandler.Initialize(); m_prefabPublicHandler.RegisterPrefabPublicHandlerInterface(); m_prefabPublicRequestHandler.Connect(); AZ::SystemTickBus::Handler::BusConnect(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h index a9e16374e9..746c306c2b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabSystemComponent.h @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -379,9 +378,6 @@ namespace AzToolsFramework // Used for loading/saving Prefab Template files. PrefabLoader m_prefabLoader; - // Handles the Prefab Focus API that determines what prefab is being edited. - PrefabFocusHandler m_prefabFocusHandler; - // Handles the public Prefab API used by UI and scripting. PrefabPublicHandler m_prefabPublicHandler; From cfc9ec2530dbb389a4e123db7d0448c8f22ccff9 Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Wed, 22 Sep 2021 13:44:21 -0700 Subject: [PATCH 75/84] Implement Project Manager 'build' button for Mac and Linux(#4248) Signed-off-by: Steve Pham --- .../Linux/ProjectBuilderWorker_linux.cpp | 65 +++++- .../Platform/Linux/ProjectUtils_linux.cpp | 39 +++- .../Platform/Mac/ProjectBuilderWorker_mac.cpp | 76 ++++++- .../Platform/Mac/ProjectUtils_mac.cpp | 52 ++++- .../Windows/ProjectBuilderWorker_windows.cpp | 194 ++---------------- .../Platform/Windows/ProjectUtils_windows.cpp | 78 +++++-- .../Source/ProjectBuilderWorker.cpp | 179 ++++++++++++++++ .../Source/ProjectBuilderWorker.h | 7 + .../Source/ProjectManagerDefs.h | 5 + .../ProjectManager/Source/ProjectUtils.cpp | 30 +++ .../ProjectManager/Source/ProjectUtils.h | 14 +- .../ProjectManager/Source/PythonBindings.cpp | 2 +- 12 files changed, 532 insertions(+), 209 deletions(-) diff --git a/Code/Tools/ProjectManager/Platform/Linux/ProjectBuilderWorker_linux.cpp b/Code/Tools/ProjectManager/Platform/Linux/ProjectBuilderWorker_linux.cpp index cffac78365..2987fc4dc2 100644 --- a/Code/Tools/ProjectManager/Platform/Linux/ProjectBuilderWorker_linux.cpp +++ b/Code/Tools/ProjectManager/Platform/Linux/ProjectBuilderWorker_linux.cpp @@ -7,14 +7,69 @@ */ #include +#include +#include + +#include +#include namespace O3DE::ProjectManager { - AZ::Outcome ProjectBuilderWorker::BuildProjectForPlatform() + AZ::Outcome ProjectBuilderWorker::ConstructCmakeGenerateProjectArguments(const QString& thirdPartyPath) const { - QString error = tr("Automatic building on Linux not currently supported!"); - QStringToAZTracePrint(error); - return AZ::Failure(error); + // Attempt to use the Ninja build system if it is installed (described in the o3de documentation) if possible, + // otherwise default to the the default for Linux (Unix Makefiles) + auto whichNinjaResult = ProjectUtils::ExecuteCommandResult("which", QStringList{"ninja"}, QProcessEnvironment::systemEnvironment()); + QString cmakeGenerator = (whichNinjaResult.IsSuccess()) ? "Ninja Multi-Config" : "Unix Makefiles"; + bool compileProfileOnBuild = (whichNinjaResult.IsSuccess()); + + // On Linux the default compiler is gcc. For O3DE, it is clang, so we need to specify the version of clang that is detected + // in order to get the compiler option. + auto compilerOptionResult = ProjectUtils::FindSupportedCompilerForPlatform(); + if (!compilerOptionResult.IsSuccess()) + { + return AZ::Failure(compilerOptionResult.GetError()); + } + auto clangCompilers = compilerOptionResult.GetValue().split('|'); + AZ_Assert(clangCompilers.length()==2, "Invalid clang compiler pair specification"); + + QString clangCompilerOption = clangCompilers[0]; + QString clangPPCompilerOption = clangCompilers[1]; + QString targetBuildPath = QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix); + QStringList generateProjectArgs = QStringList{ProjectCMakeCommand, + "-B", ProjectBuildPathPostfix, + "-S", ".", + QString("-G%1").arg(cmakeGenerator), + QString("-DCMAKE_C_COMPILER=").append(clangCompilerOption), + QString("-DCMAKE_CXX_COMPILER=").append(clangPPCompilerOption), + QString("-DLY_3RDPARTY_PATH=").append(thirdPartyPath)}; + if (!compileProfileOnBuild) + { + generateProjectArgs.append("-DCMAKE_BUILD_TYPE=profile"); + } + return AZ::Success(generateProjectArgs); } - + + AZ::Outcome ProjectBuilderWorker::ConstructCmakeBuildCommandArguments() const + { + auto whichNinjaResult = ProjectUtils::ExecuteCommandResult("which", QStringList{"ninja"}, QProcessEnvironment::systemEnvironment()); + bool compileProfileOnBuild = (whichNinjaResult.IsSuccess()); + QString targetBuildPath = QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix); + QString launcherTargetName = m_projectInfo.m_projectName + ".GameLauncher"; + + QStringList buildProjectArgs = QStringList{ProjectCMakeCommand, + "--build", ProjectBuildPathPostfix, + "--target", launcherTargetName, ProjectCMakeBuildTargetEditor}; + if (compileProfileOnBuild) + { + buildProjectArgs.append(QStringList{"--config","profile"}); + } + return AZ::Success(buildProjectArgs); + } + + AZ::Outcome ProjectBuilderWorker::ConstructKillProcessCommandArguments(const QString& pidToKill) const + { + return AZ::Success(QStringList{"kill", "-9", pidToKill}); + } + } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp b/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp index 64d18ec605..56feb9f70a 100644 --- a/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp +++ b/Code/Tools/ProjectManager/Platform/Linux/ProjectUtils_linux.cpp @@ -6,15 +6,48 @@ */ #include +#include +#include namespace O3DE::ProjectManager { namespace ProjectUtils { - AZ::Outcome FindSupportedCompilerForPlatform() + // The list of clang C/C++ compiler command lines to validate on the host Linux system + const QStringList SupportedClangCommands = {"clang-12|clang++-12"}; + + AZ::Outcome GetCommandLineProcessEnvironment() { - // Compiler detection not supported on platform - return AZ::Success(); + return AZ::Success(QProcessEnvironment(QProcessEnvironment::systemEnvironment())); + } + + AZ::Outcome FindSupportedCompilerForPlatform() + { + // Validate that cmake is installed and is in the command line + auto whichCMakeResult = ProjectUtils::ExecuteCommandResult("which", QStringList{ProjectCMakeCommand}, QProcessEnvironment::systemEnvironment()); + if (!whichCMakeResult.IsSuccess()) + { + return AZ::Failure(QObject::tr("CMake not found. \n\n" + "Make sure that the minimum version of CMake is installed and available from the command prompt. " + "Refer to the O3DE requirements page for more information.")); + } + + // Look for the first compatible version of clang. The list below will contain the known clang compilers that have been tested for O3DE. + for (const QString& supportClangCommand : SupportedClangCommands) + { + auto clangCompilers = supportClangCommand.split('|'); + AZ_Assert(clangCompilers.length()==2, "Invalid clang compiler pair specification"); + + auto whichClangResult = ProjectUtils::ExecuteCommandResult("which", QStringList{clangCompilers[0]}, QProcessEnvironment::systemEnvironment()); + auto whichClangPPResult = ProjectUtils::ExecuteCommandResult("which", QStringList{clangCompilers[1]}, QProcessEnvironment::systemEnvironment()); + if (whichClangResult.IsSuccess() && whichClangPPResult.IsSuccess()) + { + return AZ::Success(supportClangCommand); + } + } + return AZ::Failure(QObject::tr("Clang not found. \n\n" + "Make sure that the clang is installed and available from the command prompt. " + "Refer to the O3DE requirements page for more information.")); } } // namespace ProjectUtils diff --git a/Code/Tools/ProjectManager/Platform/Mac/ProjectBuilderWorker_mac.cpp b/Code/Tools/ProjectManager/Platform/Mac/ProjectBuilderWorker_mac.cpp index 7f4c5eb5d0..ab412d84d8 100644 --- a/Code/Tools/ProjectManager/Platform/Mac/ProjectBuilderWorker_mac.cpp +++ b/Code/Tools/ProjectManager/Platform/Mac/ProjectBuilderWorker_mac.cpp @@ -7,14 +7,82 @@ */ #include +#include +#include + +#include +#include namespace O3DE::ProjectManager { - AZ::Outcome ProjectBuilderWorker::BuildProjectForPlatform() + namespace Internal { - QString error = tr("Automatic building on MacOS not currently supported!"); - QStringToAZTracePrint(error); - return AZ::Failure(error); + AZ::Outcome QueryInstalledCmakeFullPath() + { + auto environmentRequest = ProjectUtils::GetCommandLineProcessEnvironment(); + if (!environmentRequest.IsSuccess()) + { + return AZ::Failure(environmentRequest.GetError()); + } + auto currentEnvironment = environmentRequest.GetValue(); + + auto queryCmakeInstalled = ProjectUtils::ExecuteCommandResult("which", + QStringList{ProjectCMakeCommand}, + currentEnvironment); + if (!queryCmakeInstalled.IsSuccess()) + { + return AZ::Failure(QObject::tr("Unable to detect CMake on this host.")); + } + QString cmakeInstalledPath = queryCmakeInstalled.GetValue().split("\n")[0]; + return AZ::Success(cmakeInstalledPath); + } + } + + AZ::Outcome ProjectBuilderWorker::ConstructCmakeGenerateProjectArguments(const QString& thirdPartyPath) const + { + // For Mac, we need to resolve the full path of cmake and use that in the process request. For + // some reason, 'which' will resolve the full path, but when you just specify cmake with the same + // environment, it is unable to resolve. To work around this, we will use 'which' to resolve the + // full path and then use it as the command argument + auto cmakeInstalledPathQuery = Internal::QueryInstalledCmakeFullPath(); + if (!cmakeInstalledPathQuery.IsSuccess()) + { + return AZ::Failure(cmakeInstalledPathQuery.GetError()); + } + QString cmakeInstalledPath = cmakeInstalledPathQuery.GetValue(); + QString targetBuildPath = QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix); + + return AZ::Success(QStringList{cmakeInstalledPath, + "-B", targetBuildPath, + "-S", m_projectInfo.m_path, + "-GXcode"}); + } + + AZ::Outcome ProjectBuilderWorker::ConstructCmakeBuildCommandArguments() const + { + // For Mac, we need to resolve the full path of cmake and use that in the process request. For + // some reason, 'which' will resolve the full path, but when you just specify cmake with the same + // environment, it is unable to resolve. To work around this, we will use 'which' to resolve the + // full path and then use it as the command argument + auto cmakeInstalledPathQuery = Internal::QueryInstalledCmakeFullPath(); + if (!cmakeInstalledPathQuery.IsSuccess()) + { + return AZ::Failure(cmakeInstalledPathQuery.GetError()); + } + + QString cmakeInstalledPath = cmakeInstalledPathQuery.GetValue(); + QString targetBuildPath = QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix); + QString launcherTargetName = m_projectInfo.m_projectName + ".GameLauncher"; + + return AZ::Success(QStringList{cmakeInstalledPath, + "--build", targetBuildPath, + "--config", "profile", + "--target", launcherTargetName, ProjectCMakeBuildTargetEditor}); + } + + AZ::Outcome ProjectBuilderWorker::ConstructKillProcessCommandArguments(const QString& pidToKill) const + { + return AZ::Success(QStringList{"kill", "-9", pidToKill}); } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Platform/Mac/ProjectUtils_mac.cpp b/Code/Tools/ProjectManager/Platform/Mac/ProjectUtils_mac.cpp index 64d18ec605..0d150abc3b 100644 --- a/Code/Tools/ProjectManager/Platform/Mac/ProjectUtils_mac.cpp +++ b/Code/Tools/ProjectManager/Platform/Mac/ProjectUtils_mac.cpp @@ -7,15 +7,59 @@ #include +#include + namespace O3DE::ProjectManager { namespace ProjectUtils { - AZ::Outcome FindSupportedCompilerForPlatform() + AZ::Outcome GetCommandLineProcessEnvironment() { - // Compiler detection not supported on platform - return AZ::Success(); + // For CMake on Mac, if its installed through home-brew, then it will be installed + // under /usr/local/bin, which may not be in the system PATH environment. + // Add that path for the command line process so that it will be able to locate + // a home-brew installed version of CMake + QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment()); + QString pathValue = currentEnvironment.value("PATH"); + pathValue += ":/usr/local/bin"; + currentEnvironment.insert("PATH", pathValue); + return AZ::Success(currentEnvironment); } - + + AZ::Outcome FindSupportedCompilerForPlatform() + { + QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment()); + QString pathValue = currentEnvironment.value("PATH"); + pathValue += ":/usr/local/bin"; + currentEnvironment.insert("PATH", pathValue); + + // Validate that we have cmake installed first + auto queryCmakeInstalled = ExecuteCommandResult("which", QStringList{ProjectCMakeCommand}, currentEnvironment); + if (!queryCmakeInstalled.IsSuccess()) + { + return AZ::Failure(QObject::tr("Unable to detect CMake on this host.")); + } + QString cmakeInstalledPath = queryCmakeInstalled.GetValue().split("\n")[0]; + + // Query the version of the installed cmake + auto queryCmakeVersionQuery = ExecuteCommandResult(cmakeInstalledPath, QStringList{"-version"}, currentEnvironment); + if (!queryCmakeVersionQuery.IsSuccess()) + { + return AZ::Failure(QObject::tr("Unable to determine the version of CMake on this host.")); + } + AZ_TracePrintf("Project Manager", "Cmake version %s detected.", queryCmakeVersionQuery.GetValue().split("\n")[0].toUtf8().constData()); + + // Query for the version of xcodebuild (if installed) + auto queryXcodeBuildVersion = ExecuteCommandResult("xcodebuild", QStringList{"-version"}, currentEnvironment); + if (!queryCmakeInstalled.IsSuccess()) + { + return AZ::Failure(QObject::tr("Unable to detect XCodeBuilder on this host.")); + } + QString xcodeBuilderVersionNumber = queryXcodeBuildVersion.GetValue().split("\n")[0]; + AZ_TracePrintf("Project Manager", "XcodeBuilder version %s detected.", xcodeBuilderVersionNumber.toUtf8().constData()); + + + return AZ::Success(xcodeBuilderVersionNumber); + } } // namespace ProjectUtils } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Platform/Windows/ProjectBuilderWorker_windows.cpp b/Code/Tools/ProjectManager/Platform/Windows/ProjectBuilderWorker_windows.cpp index 8856e2312a..075c6de774 100644 --- a/Code/Tools/ProjectManager/Platform/Windows/ProjectBuilderWorker_windows.cpp +++ b/Code/Tools/ProjectManager/Platform/Windows/ProjectBuilderWorker_windows.cpp @@ -8,189 +8,37 @@ #include #include -#include #include -#include -#include -#include -#include -#include +#include namespace O3DE::ProjectManager { - AZ::Outcome ProjectBuilderWorker::BuildProjectForPlatform() + AZ::Outcome ProjectBuilderWorker::ConstructCmakeGenerateProjectArguments(const QString& thirdPartyPath) const { - // Check if we are trying to cancel task - if (QThread::currentThread()->isInterruptionRequested()) - { - QStringToAZTracePrint(BuildCancelled); - return AZ::Failure(BuildCancelled); - } + QString targetBuildPath = QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix); - QFile logFile(GetLogFilePath()); - if (!logFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) - { - QString error = tr("Failed to open log file."); - QStringToAZTracePrint(error); - return AZ::Failure(error); - } + return AZ::Success(QStringList{ ProjectCMakeCommand, + "-B", targetBuildPath, + "-S", m_projectInfo.m_path, + QString("-DLY_3RDPARTY_PATH=").append(thirdPartyPath), + "-DLY_UNITY_BUILD=ON" } ); + } - EngineInfo engineInfo; + AZ::Outcome ProjectBuilderWorker::ConstructCmakeBuildCommandArguments() const + { + QString targetBuildPath = QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix); + QString launcherTargetName = m_projectInfo.m_projectName + ".GameLauncher"; - AZ::Outcome engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo(); - if (engineInfoResult.IsSuccess()) - { - engineInfo = engineInfoResult.GetValue(); - } - else - { - QString error = tr("Failed to get engine info."); - QStringToAZTracePrint(error); - return AZ::Failure(error); - } + return AZ::Success(QStringList{ ProjectCMakeCommand, + "--build", targetBuildPath, + "--config", "profile", + "--target", launcherTargetName, ProjectCMakeBuildTargetEditor }); + } - QTextStream logStream(&logFile); - if (QThread::currentThread()->isInterruptionRequested()) - { - logFile.close(); - QStringToAZTracePrint(BuildCancelled); - return AZ::Failure(BuildCancelled); - } - - // Show some kind of progress with very approximate estimates - UpdateProgress(++m_progressEstimate); - - QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment()); - // Append cmake path to PATH incase it is missing - QDir cmakePath(engineInfo.m_path); - cmakePath.cd("cmake/runtime/bin"); - QString pathValue = currentEnvironment.value("PATH"); - pathValue += ";" + cmakePath.path(); - currentEnvironment.insert("PATH", pathValue); - - m_configProjectProcess = new QProcess(this); - m_configProjectProcess->setProcessChannelMode(QProcess::MergedChannels); - m_configProjectProcess->setWorkingDirectory(m_projectInfo.m_path); - m_configProjectProcess->setProcessEnvironment(currentEnvironment); - - m_configProjectProcess->start( - "cmake", - QStringList - { - "-B", - QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix), - "-S", - m_projectInfo.m_path, - "-G", - "Visual Studio 16", - "-DLY_3RDPARTY_PATH=" + engineInfo.m_thirdPartyPath, - "-DLY_UNITY_BUILD=1" - }); - - if (!m_configProjectProcess->waitForStarted()) - { - QString error = tr("Configuring project failed to start."); - QStringToAZTracePrint(error); - return AZ::Failure(error); - } - bool containsGeneratingDone = false; - while (m_configProjectProcess->waitForReadyRead(MaxBuildTimeMSecs)) - { - QString configOutput = m_configProjectProcess->readAllStandardOutput(); - - if (configOutput.contains("Generating done")) - { - containsGeneratingDone = true; - } - - logStream << configOutput; - logStream.flush(); - - UpdateProgress(qMin(++m_progressEstimate, 19)); - - if (QThread::currentThread()->isInterruptionRequested()) - { - logFile.close(); - m_configProjectProcess->close(); - QStringToAZTracePrint(BuildCancelled); - return AZ::Failure(BuildCancelled); - } - } - - if (m_configProjectProcess->exitStatus() != QProcess::ExitStatus::NormalExit - || m_configProjectProcess->exitCode() != 0 - || !containsGeneratingDone) - { - QString error = tr("Configuring project failed. See log for details."); - QStringToAZTracePrint(error); - return AZ::Failure(error); - } - - UpdateProgress(++m_progressEstimate); - - m_buildProjectProcess = new QProcess(this); - m_buildProjectProcess->setProcessChannelMode(QProcess::MergedChannels); - m_buildProjectProcess->setWorkingDirectory(m_projectInfo.m_path); - m_buildProjectProcess->setProcessEnvironment(currentEnvironment); - - m_buildProjectProcess->start( - "cmake", - QStringList - { - "--build", - QDir(m_projectInfo.m_path).filePath(ProjectBuildPathPostfix), - "--target", - m_projectInfo.m_projectName + ".GameLauncher", - "Editor", - "--config", - "profile" - }); - - if (!m_buildProjectProcess->waitForStarted()) - { - QString error = tr("Building project failed to start."); - QStringToAZTracePrint(error); - return AZ::Failure(error); - } - - // There are a lot of steps when building so estimate around 800 more steps ((100 - 20) * 10) remaining - m_progressEstimate = 200; - while (m_buildProjectProcess->waitForReadyRead(MaxBuildTimeMSecs)) - { - logStream << m_buildProjectProcess->readAllStandardOutput(); - logStream.flush(); - - // Show 1% progress for every 10 steps completed - UpdateProgress(qMin(++m_progressEstimate / 10, 99)); - - if (QThread::currentThread()->isInterruptionRequested()) - { - // QProcess is unable to kill its child processes so we need to ask the operating system to do that for us - QProcess killBuildProcess; - killBuildProcess.setProcessChannelMode(QProcess::MergedChannels); - killBuildProcess.start( - "cmd.exe", QStringList{ "/C", "taskkill", "/pid", QString::number(m_buildProjectProcess->processId()), "/f", "/t" }); - killBuildProcess.waitForFinished(); - - logStream << "Killing Project Build."; - logStream << killBuildProcess.readAllStandardOutput(); - m_buildProjectProcess->kill(); - logFile.close(); - QStringToAZTracePrint(BuildCancelled); - return AZ::Failure(BuildCancelled); - } - } - - if (m_configProjectProcess->exitStatus() != QProcess::ExitStatus::NormalExit - || m_configProjectProcess->exitCode() != 0) - { - QString error = tr("Building project failed. See log for details."); - QStringToAZTracePrint(error); - return AZ::Failure(error); - } - - return AZ::Success(); + AZ::Outcome ProjectBuilderWorker::ConstructKillProcessCommandArguments(const QString& pidToKill) const + { + return AZ::Success(QStringList { "cmd.exe", "/C", "taskkill", "/pid", pidToKill, "/f", "/t" } ); } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Platform/Windows/ProjectUtils_windows.cpp b/Code/Tools/ProjectManager/Platform/Windows/ProjectUtils_windows.cpp index 7ca51fb9c5..d012ca8921 100644 --- a/Code/Tools/ProjectManager/Platform/Windows/ProjectUtils_windows.cpp +++ b/Code/Tools/ProjectManager/Platform/Windows/ProjectUtils_windows.cpp @@ -7,6 +7,8 @@ #include +#include + #include #include #include @@ -16,8 +18,44 @@ namespace O3DE::ProjectManager { namespace ProjectUtils { - AZ::Outcome FindSupportedCompilerForPlatform() + AZ::Outcome GetCommandLineProcessEnvironment() { + // Use the engine path to insert a path for cmake + auto engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo(); + if (!engineInfoResult.IsSuccess()) + { + return AZ::Failure(QObject::tr("Failed to get engine info")); + } + auto engineInfo = engineInfoResult.GetValue(); + + QProcessEnvironment currentEnvironment(QProcessEnvironment::systemEnvironment()); + + // Append cmake path to PATH incase it is missing + QDir cmakePath(engineInfo.m_path); + cmakePath.cd("cmake/runtime/bin"); + QString pathValue = currentEnvironment.value("PATH"); + pathValue += ";" + cmakePath.path(); + currentEnvironment.insert("PATH", pathValue); + return AZ::Success(currentEnvironment); + } + + AZ::Outcome FindSupportedCompilerForPlatform() + { + // Validate that cmake is installed + auto cmakeProcessEnvResult = GetCommandLineProcessEnvironment(); + if (!cmakeProcessEnvResult.IsSuccess()) + { + return AZ::Failure(cmakeProcessEnvResult.GetError()); + } + auto cmakeVersionQueryResult = ExecuteCommandResult("cmake", QStringList{"--version"}, cmakeProcessEnvResult.GetValue()); + if (!cmakeVersionQueryResult.IsSuccess()) + { + return AZ::Failure(QObject::tr("CMake not found. \n\n" + "Make sure that the minimum version of CMake is installed and available from the command prompt. " + "Refer to the O3DE requirements for more information.")); + } + + // Validate that the minimal version of visual studio is installed QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); QString programFilesPath = environment.value("ProgramFiles(x86)"); QString vsWherePath = QDir(programFilesPath).filePath("Microsoft Visual Studio/Installer/vswhere.exe"); @@ -25,27 +63,31 @@ namespace O3DE::ProjectManager QFileInfo vsWhereFile(vsWherePath); if (vsWhereFile.exists() && vsWhereFile.isFile()) { - QProcess vsWhereProcess; - vsWhereProcess.setProcessChannelMode(QProcess::MergedChannels); + QStringList vsWhereBaseArguments = QStringList{"-version", + "16.9.2", + "-latest", + "-requires", + "Microsoft.VisualStudio.Component.VC.Tools.x86.x64"}; - vsWhereProcess.start( - vsWherePath, - QStringList{ - "-version", - "16.9.2", - "-latest", - "-requires", - "Microsoft.VisualStudio.Component.VC.Tools.x86.x64", - "-property", - "isComplete" - }); + QProcess vsWhereIsCompleteProcess; + vsWhereIsCompleteProcess.setProcessChannelMode(QProcess::MergedChannels); - if (vsWhereProcess.waitForStarted() && vsWhereProcess.waitForFinished()) + vsWhereIsCompleteProcess.start(vsWherePath, vsWhereBaseArguments + QStringList{ "-property", "isComplete" }); + + if (vsWhereIsCompleteProcess.waitForStarted() && vsWhereIsCompleteProcess.waitForFinished()) { - QString vsWhereOutput(vsWhereProcess.readAllStandardOutput()); - if (vsWhereOutput.startsWith("1")) + QString vsWhereIsCompleteOutput(vsWhereIsCompleteProcess.readAllStandardOutput()); + if (vsWhereIsCompleteOutput.startsWith("1")) { - return AZ::Success(); + QProcess vsWhereCompilerVersionProcess; + vsWhereCompilerVersionProcess.setProcessChannelMode(QProcess::MergedChannels); + vsWhereCompilerVersionProcess.start(vsWherePath, vsWhereBaseArguments + QStringList{"-property", "catalog_productDisplayVersion"}); + + if (vsWhereCompilerVersionProcess.waitForStarted() && vsWhereCompilerVersionProcess.waitForFinished()) + { + QString vsWhereCompilerVersionOutput(vsWhereCompilerVersionProcess.readAllStandardOutput()); + return AZ::Success(vsWhereCompilerVersionOutput); + } } } } diff --git a/Code/Tools/ProjectManager/Source/ProjectBuilderWorker.cpp b/Code/Tools/ProjectManager/Source/ProjectBuilderWorker.cpp index 2fe1c6db15..c6a6b20a1d 100644 --- a/Code/Tools/ProjectManager/Source/ProjectBuilderWorker.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectBuilderWorker.cpp @@ -8,8 +8,15 @@ #include #include +#include +#include #include +#include +#include +#include +#include +#include //#define MOCK_BUILD_PROJECT true @@ -67,4 +74,176 @@ namespace O3DE::ProjectManager { AZ_TracePrintf("Project Manager", error.toStdString().c_str()); } + + AZ::Outcome ProjectBuilderWorker::BuildProjectForPlatform() + { + // Check if we are trying to cancel task + if (QThread::currentThread()->isInterruptionRequested()) + { + QStringToAZTracePrint(BuildCancelled); + return AZ::Failure(BuildCancelled); + } + + QFile logFile(GetLogFilePath()); + if (!logFile.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) + { + QString error = tr("Failed to open log file."); + QStringToAZTracePrint(error); + return AZ::Failure(error); + } + + EngineInfo engineInfo; + + AZ::Outcome engineInfoResult = PythonBindingsInterface::Get()->GetEngineInfo(); + if (engineInfoResult.IsSuccess()) + { + engineInfo = engineInfoResult.GetValue(); + } + else + { + QString error = tr("Failed to get engine info."); + QStringToAZTracePrint(error); + return AZ::Failure(error); + } + + QTextStream logStream(&logFile); + if (QThread::currentThread()->isInterruptionRequested()) + { + logFile.close(); + QStringToAZTracePrint(BuildCancelled); + return AZ::Failure(BuildCancelled); + } + + // Show some kind of progress with very approximate estimates + UpdateProgress(++m_progressEstimate); + + auto currentEnvironmentRequest = ProjectUtils::GetCommandLineProcessEnvironment(); + if (!currentEnvironmentRequest.IsSuccess()) + { + QStringToAZTracePrint(currentEnvironmentRequest.GetError()); + return AZ::Failure(currentEnvironmentRequest.GetError()); + } + QProcessEnvironment currentEnvironment = currentEnvironmentRequest.GetValue(); + + m_configProjectProcess = new QProcess(this); + m_configProjectProcess->setProcessChannelMode(QProcess::MergedChannels); + m_configProjectProcess->setWorkingDirectory(m_projectInfo.m_path); + m_configProjectProcess->setProcessEnvironment(currentEnvironment); + + auto cmakeGenerateArgumentsResult = ConstructCmakeGenerateProjectArguments(engineInfo.m_thirdPartyPath); + if (!cmakeGenerateArgumentsResult.IsSuccess()) + { + QStringToAZTracePrint(cmakeGenerateArgumentsResult.GetError()); + return AZ::Failure(cmakeGenerateArgumentsResult.GetError()); + } + auto cmakeGenerateArguments = cmakeGenerateArgumentsResult.GetValue(); + m_configProjectProcess->start(cmakeGenerateArguments.front(), cmakeGenerateArguments.mid(1)); + if (!m_configProjectProcess->waitForStarted()) + { + QString error = tr("Configuring project failed to start."); + QStringToAZTracePrint(error); + return AZ::Failure(error); + } + bool containsGeneratingDone = false; + while (m_configProjectProcess->waitForReadyRead(MaxBuildTimeMSecs)) + { + QString configOutput = m_configProjectProcess->readAllStandardOutput(); + + if (configOutput.contains("Generating done")) + { + containsGeneratingDone = true; + } + + logStream << configOutput; + logStream.flush(); + + UpdateProgress(qMin(++m_progressEstimate, 19)); + + if (QThread::currentThread()->isInterruptionRequested()) + { + logFile.close(); + m_configProjectProcess->close(); + QStringToAZTracePrint(BuildCancelled); + return AZ::Failure(BuildCancelled); + } + } + + if (m_configProjectProcess->exitStatus() != QProcess::ExitStatus::NormalExit || m_configProjectProcess->exitCode() != 0 || + !containsGeneratingDone) + { + QString error = tr("Configuring project failed. See log for details."); + QStringToAZTracePrint(error); + return AZ::Failure(error); + } + + UpdateProgress(++m_progressEstimate); + + m_buildProjectProcess = new QProcess(this); + m_buildProjectProcess->setProcessChannelMode(QProcess::MergedChannels); + m_buildProjectProcess->setWorkingDirectory(m_projectInfo.m_path); + m_buildProjectProcess->setProcessEnvironment(currentEnvironment); + + auto cmakeBuildArgumentsResult = ConstructCmakeBuildCommandArguments(); + if (!cmakeBuildArgumentsResult.IsSuccess()) + { + QStringToAZTracePrint(cmakeBuildArgumentsResult.GetError()); + return AZ::Failure(cmakeBuildArgumentsResult.GetError()); + } + auto cmakeBuildArguments = cmakeBuildArgumentsResult.GetValue(); + + m_buildProjectProcess->start(cmakeBuildArguments.front(), cmakeBuildArguments.mid(1)); + if (!m_buildProjectProcess->waitForStarted()) + { + QString error = tr("Building project failed to start."); + QStringToAZTracePrint(error); + return AZ::Failure(error); + } + + // There are a lot of steps when building so estimate around 800 more steps ((100 - 20) * 10) remaining + m_progressEstimate = 200; + while (m_buildProjectProcess->waitForReadyRead(MaxBuildTimeMSecs)) + { + logStream << m_buildProjectProcess->readAllStandardOutput(); + logStream.flush(); + + // Show 1% progress for every 10 steps completed + UpdateProgress(qMin(++m_progressEstimate / 10, 99)); + + if (QThread::currentThread()->isInterruptionRequested()) + { + // QProcess is unable to kill its child processes so we need to ask the operating system to do that for us + auto killProcessArgumentsResult = ConstructKillProcessCommandArguments(QString::number(m_buildProjectProcess->processId())); + if (!killProcessArgumentsResult.IsSuccess()) + { + return AZ::Failure(killProcessArgumentsResult.GetError()); + } + auto killProcessArguments = killProcessArgumentsResult.GetValue(); + + + QProcess killBuildProcess; + + + killBuildProcess.setProcessChannelMode(QProcess::MergedChannels); + killBuildProcess.start(killProcessArguments.front(), killProcessArguments.mid(1)); + killBuildProcess.waitForFinished(); + + logStream << "Killing Project Build."; + logStream << killBuildProcess.readAllStandardOutput(); + m_buildProjectProcess->kill(); + logFile.close(); + QStringToAZTracePrint(BuildCancelled); + return AZ::Failure(BuildCancelled); + } + } + + if (m_buildProjectProcess->exitStatus() != QProcess::ExitStatus::NormalExit || m_buildProjectProcess->exitCode() != 0) + { + QString error = tr("Building project failed. See log for details."); + QStringToAZTracePrint(error); + return AZ::Failure(error); + } + + return AZ::Success(); + } + } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectBuilderWorker.h b/Code/Tools/ProjectManager/Source/ProjectBuilderWorker.h index f42c87f47b..94c4a6bd52 100644 --- a/Code/Tools/ProjectManager/Source/ProjectBuilderWorker.h +++ b/Code/Tools/ProjectManager/Source/ProjectBuilderWorker.h @@ -12,6 +12,7 @@ #include #include +#include #endif QT_FORWARD_DECLARE_CLASS(QProcess) @@ -44,6 +45,12 @@ namespace O3DE::ProjectManager AZ::Outcome BuildProjectForPlatform(); void QStringToAZTracePrint(const QString& error); + // Command line argument builders + AZ::Outcome ConstructCmakeGenerateProjectArguments(const QString& thirdPartyPath) const; + AZ::Outcome ConstructCmakeBuildCommandArguments() const; + AZ::Outcome ConstructKillProcessCommandArguments(const QString& pidToKill) const; + + QProcess* m_configProjectProcess = nullptr; QProcess* m_buildProjectProcess = nullptr; ProjectInfo m_projectInfo; diff --git a/Code/Tools/ProjectManager/Source/ProjectManagerDefs.h b/Code/Tools/ProjectManager/Source/ProjectManagerDefs.h index 8ab5128741..264515652f 100644 --- a/Code/Tools/ProjectManager/Source/ProjectManagerDefs.h +++ b/Code/Tools/ProjectManager/Source/ProjectManagerDefs.h @@ -14,6 +14,7 @@ namespace O3DE::ProjectManager inline constexpr static int ProjectPreviewImageWidth = 210; inline constexpr static int ProjectPreviewImageHeight = 280; inline constexpr static int ProjectTemplateImageWidth = 92; + inline constexpr static int ProjectCommandLineTimeoutSeconds = 30; static const QString ProjectBuildDirectoryName = "build"; extern const QString ProjectBuildPathPostfix; @@ -21,4 +22,8 @@ namespace O3DE::ProjectManager static const QString ProjectBuildErrorLogName = "CMakeProjectBuildError.log"; static const QString ProjectCacheDirectoryName = "Cache"; static const QString ProjectPreviewImagePath = "preview.png"; + + static const QString ProjectCMakeCommand = "cmake"; + static const QString ProjectCMakeBuildTargetEditor = "Editor"; + } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp index 84d731832e..81eb70391d 100644 --- a/Code/Tools/ProjectManager/Source/ProjectUtils.cpp +++ b/Code/Tools/ProjectManager/Source/ProjectUtils.cpp @@ -22,6 +22,8 @@ #include #include +#include + namespace O3DE::ProjectManager { namespace ProjectUtils @@ -507,5 +509,33 @@ namespace O3DE::ProjectManager return ProjectManagerScreen::Invalid; } + + AZ::Outcome ExecuteCommandResult( + const QString& cmd, + const QStringList& arguments, + const QProcessEnvironment& processEnv, + int commandTimeoutSeconds /*= ProjectCommandLineTimeoutSeconds*/) + { + QProcess execProcess; + execProcess.setProcessEnvironment(processEnv); + execProcess.setProcessChannelMode(QProcess::MergedChannels); + execProcess.start(cmd, arguments); + if (!execProcess.waitForStarted()) + { + return AZ::Failure(QObject::tr("Unable to start process for command '%1'").arg(cmd)); + } + + if (!execProcess.waitForFinished(commandTimeoutSeconds * 1000 /* Milliseconds per second */)) + { + return AZ::Failure(QObject::tr("Process for command '%1' timed out at %2 seconds").arg(cmd).arg(commandTimeoutSeconds)); + } + int resultCode = execProcess.exitCode(); + if (resultCode != 0) + { + return AZ::Failure(QObject::tr("Process for command '%1' failed (result code %2").arg(cmd).arg(resultCode)); + } + QString resultOutput = execProcess.readAllStandardOutput(); + return AZ::Success(resultOutput); + } } // namespace ProjectUtils } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/ProjectUtils.h b/Code/Tools/ProjectManager/Source/ProjectUtils.h index f1050531d4..0866b57923 100644 --- a/Code/Tools/ProjectManager/Source/ProjectUtils.h +++ b/Code/Tools/ProjectManager/Source/ProjectUtils.h @@ -9,8 +9,11 @@ #include #include +#include #include +#include + #include namespace O3DE::ProjectManager @@ -28,8 +31,17 @@ namespace O3DE::ProjectManager bool ReplaceProjectFile(const QString& origFile, const QString& newFile, QWidget* parent = nullptr, bool interactive = true); bool FindSupportedCompiler(QWidget* parent = nullptr); - AZ::Outcome FindSupportedCompilerForPlatform(); + AZ::Outcome FindSupportedCompilerForPlatform(); ProjectManagerScreen GetProjectManagerScreen(const QString& screen); + + AZ::Outcome ExecuteCommandResult( + const QString& cmd, + const QStringList& arguments, + const QProcessEnvironment& processEnv, + int commandTimeoutSeconds = ProjectCommandLineTimeoutSeconds); + + AZ::Outcome GetCommandLineProcessEnvironment(); + } // namespace ProjectUtils } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 6f8ff9abce..c92ad53cd4 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -339,7 +339,7 @@ namespace O3DE::ProjectManager { for (auto engine : allEngines) { - AZ::IO::FixedMaxPath enginePath(Py_To_String(engine["path"])); + AZ::IO::FixedMaxPath enginePath(Py_To_String(engine)); if (enginePath.Compare(m_enginePath) == 0) { return; From 62f7fbb6654b7b28b92f33db17f7704f06720df9 Mon Sep 17 00:00:00 2001 From: Qing Tao <55564570+VickyAtAZ@users.noreply.github.com> Date: Wed, 22 Sep 2021 14:43:57 -0700 Subject: [PATCH 76/84] LYN-6793 [iOS] [asset_profile] 4 assets fail to process for iOS (#4268) * LYN-6793 [iOS] [asset_profile] 4 assets fail to process for iOS The issue was because the compression of ETC formats took too long. Replaced all ETC and PVRTC formats with ASTC formats. Update all pixel operation for formats with single R channel to align the change with R8. Signed-off-by: Qing Tao --- .../Code/Source/Converters/PixelOperation.cpp | 16 ++++++++-------- .../ImageProcessingAtom/Config/Albedo.preset | 2 +- .../Config/AlbedoWithCoverage.preset | 2 +- .../Config/AlbedoWithGenericAlpha.preset | 2 +- .../Config/AlbedoWithOpacity.preset | 2 +- .../Config/AmbientOcclusion.preset | 4 ++-- .../Config/CloudShadows.preset | 4 ++-- .../Config/Decal_AlbedoWithOpacity.preset | 4 ++-- .../Detail_MergedAlbedoNormalsSmoothness.preset | 2 +- .../Config/Displacement.preset | 4 ++-- .../ImageProcessingAtom/Config/Emissive.preset | 2 +- .../ImageProcessingAtom/Config/Greyscale.preset | 4 ++-- .../ImageProcessingAtom/Config/LensOptics.preset | 2 +- .../Config/LightProjector.preset | 4 ++-- .../ImageProcessingAtom/Config/Minimap.preset | 2 +- .../Config/MuzzleFlash.preset | 2 +- .../ImageProcessingAtom/Config/Opacity.preset | 4 ++-- .../Config/Reflectance.preset | 2 +- .../ReflectanceWithSmoothness_Legacy.preset | 2 +- .../Config/Reflectance_Linear.preset | 2 +- .../ImageProcessingAtom/Config/SF_Image.preset | 4 ++-- .../Config/SF_Image_nonpower2.preset | 4 ++-- .../Config/Terrain_Albedo.preset | 2 +- .../Config/Terrain_Albedo_HighPassed.preset | 2 +- .../Config/UserInterface_Compressed.preset | 2 +- 25 files changed, 41 insertions(+), 41 deletions(-) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/PixelOperation.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/PixelOperation.cpp index 3e897078fa..fa4baeefc0 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/PixelOperation.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Converters/PixelOperation.cpp @@ -248,8 +248,8 @@ namespace ImageProcessingAtom { const uint8* data = buf; r = U8ToF32(data[0]); - g = 0.f; - b = 0.f; + g = r; + b = r; a = 1.f; } @@ -333,8 +333,8 @@ namespace ImageProcessingAtom { const uint16* data = (uint16*)(buf); r = U16ToF32(data[0]); - g = 0.f; - b = 0.f; + g = r; + b = r; a = 1.f; } @@ -418,8 +418,8 @@ namespace ImageProcessingAtom { const float* data = (float*)(buf); r = data[0]; - g = 0.f; - b = 0.f; + g = r; + b = r; a = 1.f; } @@ -485,8 +485,8 @@ namespace ImageProcessingAtom { const SHalf* data = (SHalf*)(buf); r = data[0]; - g = 0.f; - b = 0.f; + g = r; + b = r; a = 1.f; } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Albedo.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Albedo.preset index 3a5122f18e..e0d043cf20 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Albedo.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Albedo.preset @@ -39,7 +39,7 @@ "_bc", "_diffuse" ], - "PixelFormat": "ETC2", + "PixelFormat": "ASTC_6x6", "DiscardAlpha": true, "IsPowerOf2": true, "MipMapSetting": { diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithCoverage.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithCoverage.preset index 692ef99b1c..fda5a9cc52 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithCoverage.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithCoverage.preset @@ -36,7 +36,7 @@ "_bc", "_diffuse" ], - "PixelFormat": "ETC2a1", + "PixelFormat": "ASTC_6x6", "IsPowerOf2": true, "MipMapSetting": { "MipGenType": "Box" diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithGenericAlpha.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithGenericAlpha.preset index 4ebe773f0e..8c196530e9 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithGenericAlpha.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithGenericAlpha.preset @@ -36,7 +36,7 @@ "_bc", "_diffuse" ], - "PixelFormat": "ETC2a", + "PixelFormat": "ASTC_6x6", "IsPowerOf2": true, "MipMapSetting": { "MipGenType": "Box" diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithOpacity.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithOpacity.preset index 6049ef5bd4..346f0f8cac 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithOpacity.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithOpacity.preset @@ -36,7 +36,7 @@ "_bc", "_diffuse" ], - "PixelFormat": "ETC2a", + "PixelFormat": "ASTC_6x6", "IsPowerOf2": true, "MipMapSetting": { "MipGenType": "Box" diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/AmbientOcclusion.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/AmbientOcclusion.preset index 56dec20f3e..638e31f838 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/AmbientOcclusion.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/AmbientOcclusion.preset @@ -28,7 +28,7 @@ "_amb", "_ambientocclusion" ], - "PixelFormat": "EAC_R11" + "PixelFormat": "ASTC_4x4" }, "ios": { "UUID": "{02ED0ECE-B198-49D9-85BC-CEBA6C28546C}", @@ -41,7 +41,7 @@ "_amb", "_ambientocclusion" ], - "PixelFormat": "EAC_R11" + "PixelFormat": "ASTC_4x4" }, "mac": { "UUID": "{02ED0ECE-B198-49D9-85BC-CEBA6C28546C}", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/CloudShadows.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/CloudShadows.preset index 2280a06302..8d1105cdfc 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/CloudShadows.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/CloudShadows.preset @@ -15,14 +15,14 @@ "UUID": "{884B5F7C-44AC-4E9E-8B8A-559D098BE2C7}", "Name": "CloudShadows", "DestColor": "Linear", - "PixelFormat": "EAC_R11", + "PixelFormat": "ASTC_4x4", "IsPowerOf2": true }, "ios": { "UUID": "{884B5F7C-44AC-4E9E-8B8A-559D098BE2C7}", "Name": "CloudShadows", "DestColor": "Linear", - "PixelFormat": "EAC_R11", + "PixelFormat": "ASTC_4x4", "IsPowerOf2": true }, "mac": { diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Decal_AlbedoWithOpacity.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Decal_AlbedoWithOpacity.preset index f1e43e74b1..628cd673e9 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Decal_AlbedoWithOpacity.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Decal_AlbedoWithOpacity.preset @@ -24,13 +24,13 @@ "FileMasks": [ "_decal" ], - "PixelFormat": "ETC2a", + "PixelFormat": "ASTC_4x4", "IsPowerOf2": true, "MipMapSetting": { "MipGenType": "Box" }, // Decal Texture Arrays need all mips available immediately for packing. - "NumberResidentMips": 255 + "NumberResidentMips": 255 }, "ios": { "UUID": "{E06B5087-2640-49B6-B9BA-D40048162B90}", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness.preset index 991692c5cc..5bfea9a376 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness.preset @@ -26,7 +26,7 @@ "FileMasks": [ "_detail" ], - "PixelFormat": "ETC2a", + "PixelFormat": "ASTC_4x4", "IsPowerOf2": true, "MipMapSetting": { "MipGenType": "Box" diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Displacement.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Displacement.preset index 520e4ae193..8f21ad005b 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Displacement.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Displacement.preset @@ -45,7 +45,7 @@ "_ht", "_h" ], - "PixelFormat": "EAC_R11", + "PixelFormat": "ASTC_4x4", "DiscardAlpha": true, "IsPowerOf2": true, "SizeReduceLevel": 3, @@ -70,7 +70,7 @@ "_ht", "_h" ], - "PixelFormat": "EAC_R11", + "PixelFormat": "ASTC_4x4", "DiscardAlpha": true, "IsPowerOf2": true, "MipMapSetting": { diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Emissive.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Emissive.preset index ffb16482fd..8f6c846e82 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Emissive.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Emissive.preset @@ -29,7 +29,7 @@ "_em", "_emit" ], - "PixelFormat": "ETC2", + "PixelFormat": "ASTC_6x6", "DiscardAlpha": true }, "ios": { diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Greyscale.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Greyscale.preset index f06682be42..c71ada1269 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Greyscale.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Greyscale.preset @@ -26,7 +26,7 @@ "FileMasks": [ "_mask" ], - "PixelFormat": "EAC_R11", + "PixelFormat": "ASTC_4x4", "IsPowerOf2": true, "MipMapSetting": { "MipGenType": "Box" @@ -40,7 +40,7 @@ "FileMasks": [ "_mask" ], - "PixelFormat": "EAC_R11", + "PixelFormat": "ASTC_4x4", "IsPowerOf2": true, "MipMapSetting": { "MipGenType": "Box" diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LensOptics.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LensOptics.preset index 9f4b5bf68d..d277785151 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/LensOptics.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/LensOptics.preset @@ -12,7 +12,7 @@ "android": { "UUID": "{3000A993-0A04-4E08-A813-DFB1A47A0980}", "Name": "LensOptics", - "PixelFormat": "ETC2" + "PixelFormat": "ASTC_4x4" }, "ios": { "UUID": "{3000A993-0A04-4E08-A813-DFB1A47A0980}", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LightProjector.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LightProjector.preset index ede264a78e..4de95427d6 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/LightProjector.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/LightProjector.preset @@ -18,7 +18,7 @@ "UUID": "{1DFEF41A-D97F-40FB-99D3-C142A3E5225E}", "Name": "LightProjector", "DestColor": "Linear", - "PixelFormat": "EAC_RG11", + "PixelFormat": "ASTC_4x4", "IsPowerOf2": true, "MipMapSetting": { "MipGenType": "Box" @@ -28,7 +28,7 @@ "UUID": "{1DFEF41A-D97F-40FB-99D3-C142A3E5225E}", "Name": "LightProjector", "DestColor": "Linear", - "PixelFormat": "EAC_RG11", + "PixelFormat": "ASTC_4x4", "IsPowerOf2": true, "MipMapSetting": { "MipGenType": "Box" diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Minimap.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Minimap.preset index 9370de063d..79dda1977e 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Minimap.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Minimap.preset @@ -19,7 +19,7 @@ "UUID": "{0D2F4C31-A665-4862-9C63-9E49A58E9A37}", "Name": "Minimap", "SuppressEngineReduce": true, - "PixelFormat": "ETC2", + "PixelFormat": "ASTC_6x6", "IsPowerOf2": true, "SizeReduceLevel": 1, "MipMapSetting": { diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/MuzzleFlash.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/MuzzleFlash.preset index 459cd5b1fb..b02227b454 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/MuzzleFlash.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/MuzzleFlash.preset @@ -18,7 +18,7 @@ "UUID": "{8BCC23A5-D08E-458E-B0B3-087C65FA1D31}", "Name": "MuzzleFlash", "SuppressEngineReduce": true, - "PixelFormat": "ETC2", + "PixelFormat": "ASTC_6x6", "IsPowerOf2": true, "MipMapSetting": { "MipGenType": "Box" diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Opacity.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Opacity.preset index bbd7fd5db9..8b66b30f28 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Opacity.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Opacity.preset @@ -44,7 +44,7 @@ "_msk", "_blend" ], - "PixelFormat": "EAC_R11", + "PixelFormat": "ASTC_4x4", "IsPowerOf2": true, "MipMapSetting": { "MipGenType": "Box" @@ -67,7 +67,7 @@ "_msk", "_blend" ], - "PixelFormat": "EAC_R11", + "PixelFormat": "ASTC_4x4", "IsPowerOf2": true, "MipMapSetting": { "MipGenType": "Box" diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance.preset index 1844e0186e..e9ea34060b 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance.preset @@ -57,7 +57,7 @@ "_roughness", "_rough" ], - "PixelFormat": "ETC2", + "PixelFormat": "ASTC_6x6", "IsPowerOf2": true, "MipMapSetting": { "MipGenType": "Box" diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/ReflectanceWithSmoothness_Legacy.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/ReflectanceWithSmoothness_Legacy.preset index e51cc7122b..e868a44096 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/ReflectanceWithSmoothness_Legacy.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/ReflectanceWithSmoothness_Legacy.preset @@ -22,7 +22,7 @@ "FileMasks": [ "_spec" ], - "PixelFormat": "ETC2a", + "PixelFormat": "ASTC_4x4", "IsPowerOf2": true, "MipMapSetting": { "MipGenType": "Box" diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance_Linear.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance_Linear.preset index 07cc39c955..e52b616f48 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance_Linear.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance_Linear.preset @@ -26,7 +26,7 @@ "_spec", "_refl" ], - "PixelFormat": "ETC2", + "PixelFormat": "ASTC_4x4", "IsPowerOf2": true, "MipMapSetting": { "MipGenType": "Box" diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image.preset index 46a32ce5d4..191425bb92 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image.preset @@ -19,7 +19,7 @@ "SourceColor": "Linear", "DestColor": "Linear", "SuppressEngineReduce": true, - "PixelFormat": "ETC2", + "PixelFormat": "ASTC_4x4", "IsPowerOf2": true }, "ios": { @@ -28,7 +28,7 @@ "SourceColor": "Linear", "DestColor": "Linear", "SuppressEngineReduce": true, - "PixelFormat": "PVRTC4", + "PixelFormat": "ASTC_4x4", "IsPowerOf2": true }, "mac": { diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image_nonpower2.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image_nonpower2.preset index 0ba70d2ca3..9b1a9c7c45 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image_nonpower2.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image_nonpower2.preset @@ -18,7 +18,7 @@ "SourceColor": "Linear", "DestColor": "Linear", "SuppressEngineReduce": true, - "PixelFormat": "ETC2" + "PixelFormat": "ASTC_4x4" }, "ios": { "UUID": "{C456B8AB-C360-4822-BCDD-225252D0E697}", @@ -26,7 +26,7 @@ "SourceColor": "Linear", "DestColor": "Linear", "SuppressEngineReduce": true, - "PixelFormat": "PVRTC4" + "PixelFormat": "ASTC_4x4" }, "mac": { "UUID": "{C456B8AB-C360-4822-BCDD-225252D0E697}", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo.preset index 84a70935f1..8b12a08465 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo.preset @@ -21,7 +21,7 @@ "Name": "Terrain_Albedo", "SourceColor": "Linear", "DestColor": "Linear", - "PixelFormat": "ETC2", + "PixelFormat": "ASTC_6x6", "IsPowerOf2": true, "HighPassMip": 5, "MipMapSetting": { diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo_HighPassed.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo_HighPassed.preset index 1d83737ef9..d24531858f 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo_HighPassed.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo_HighPassed.preset @@ -20,7 +20,7 @@ "Name": "Terrain_Albedo_HighPassed", "SourceColor": "Linear", "DestColor": "Linear", - "PixelFormat": "ETC2", + "PixelFormat": "ASTC_6x6", "IsPowerOf2": true, "MipMapSetting": { "MipGenType": "Box" diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Compressed.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Compressed.preset index 6f70e8f14f..13334de700 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Compressed.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/UserInterface_Compressed.preset @@ -17,7 +17,7 @@ "UUID": "{2828FBFE-BDF9-45A7-9370-F93822719CCF}", "Name": "UserInterface_Compressed", "SuppressEngineReduce": true, - "PixelFormat": "ETC2" + "PixelFormat": "ASTC_6x6" }, "ios": { "UUID": "{2828FBFE-BDF9-45A7-9370-F93822719CCF}", From 1e5e6094f5e53cdd94fa47ff58905cebbf8c700b Mon Sep 17 00:00:00 2001 From: amzn-tommy Date: Wed, 22 Sep 2021 15:46:29 -0700 Subject: [PATCH 77/84] Expose Transform::CreateLookAt to behavior context to use with hydra tests Signed-off-by: amzn-tommy --- Code/Framework/AzCore/AzCore/Math/Transform.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Framework/AzCore/AzCore/Math/Transform.cpp b/Code/Framework/AzCore/AzCore/Math/Transform.cpp index 5cb09fe9a8..1701820bae 100644 --- a/Code/Framework/AzCore/AzCore/Math/Transform.cpp +++ b/Code/Framework/AzCore/AzCore/Math/Transform.cpp @@ -353,6 +353,7 @@ namespace AZ Method("CreateFromMatrix3x3AndTranslation", &Transform::CreateFromMatrix3x3AndTranslation)-> Method("CreateUniformScale", &Transform::CreateUniformScale)-> Method("CreateTranslation", &Transform::CreateTranslation)-> + Method("CreateLookAt", &Transform::CreateLookAt)-> Method("ConstructFromValuesNumeric", &Internal::ConstructTransformFromValues); } } From 982bef8766c0008d4deade605ddb21a66503088a Mon Sep 17 00:00:00 2001 From: Tommy Walton <82672795+amzn-tommy@users.noreply.github.com> Date: Wed, 22 Sep 2021 15:48:43 -0700 Subject: [PATCH 78/84] Use resize_no_construct when creating a buffer asset, since the initial data is going to be memcopy'd anyways. (#4249) Signed-off-by: amzn-tommy --- .../RPI/Code/Source/RPI.Reflect/Buffer/BufferAssetCreator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Buffer/BufferAssetCreator.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Buffer/BufferAssetCreator.cpp index bb80a1b8d2..feeeff36cf 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Buffer/BufferAssetCreator.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Buffer/BufferAssetCreator.cpp @@ -57,7 +57,7 @@ namespace AZ // Only allocate buffer if initial data is not empty if (initialData != nullptr && initialDataSize > 0) { - bufferAsset->m_buffer.resize(descriptor.m_byteCount); + bufferAsset->m_buffer.resize_no_construct(descriptor.m_byteCount); memcpy(bufferAsset->m_buffer.data(), initialData, initialDataSize); } From 92c4b224450aff852bc64b52dcccc842c7784088 Mon Sep 17 00:00:00 2001 From: Tommy Walton <82672795+amzn-tommy@users.noreply.github.com> Date: Wed, 22 Sep 2021 15:49:01 -0700 Subject: [PATCH 79/84] Fix a minor spelling mistake (#4247) Signed-off-by: amzn-tommy --- Gems/EditorPythonBindings/Code/Source/PythonProxyBus.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/EditorPythonBindings/Code/Source/PythonProxyBus.cpp b/Gems/EditorPythonBindings/Code/Source/PythonProxyBus.cpp index 38b29bcdf2..f9f9580c1a 100644 --- a/Gems/EditorPythonBindings/Code/Source/PythonProxyBus.cpp +++ b/Gems/EditorPythonBindings/Code/Source/PythonProxyBus.cpp @@ -195,7 +195,7 @@ namespace EditorPythonBindings if (!m_handler) { - AZ_Error("python", false, "No EBus connection deteced; missing call or failed call to connect()?"); + AZ_Error("python", false, "No EBus connection detected; missing call or failed call to connect()?"); return false; } From 5ae35810ae4d98f64b543fdd43cad6a092e2b04f Mon Sep 17 00:00:00 2001 From: SJ Date: Wed, 22 Sep 2021 19:11:20 -0700 Subject: [PATCH 80/84] 1. Update iOS deployment target to 14 (#4266) 2. Set MacOS default deployment target to 11. Signed-off-by: amzn-sj --- cmake/Platform/Mac/PAL_mac.cmake | 4 ++++ cmake/Platform/iOS/Toolchain_ios.cmake | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cmake/Platform/Mac/PAL_mac.cmake b/cmake/Platform/Mac/PAL_mac.cmake index 065b35d69c..561ce86570 100644 --- a/cmake/Platform/Mac/PAL_mac.cmake +++ b/cmake/Platform/Mac/PAL_mac.cmake @@ -37,6 +37,10 @@ endif() # Set the default asset type for deployment set(LY_ASSET_DEPLOY_ASSET_TYPE "mac" CACHE STRING "Set the asset type for deployment.") +# Set the deployment target for MacOS +set(LY_MAC_DEPLOYMENT_TARGET "11.0" CACHE STRING "Mac Deployment Target") +set(CMAKE_OSX_DEPLOYMENT_TARGET ${LY_MAC_DEPLOYMENT_TARGET}) + # Set the python cmd tool ly_set(LY_PYTHON_CMD ${CMAKE_CURRENT_SOURCE_DIR}/python/python.sh) diff --git a/cmake/Platform/iOS/Toolchain_ios.cmake b/cmake/Platform/iOS/Toolchain_ios.cmake index 49f0b23461..719c492ebb 100644 --- a/cmake/Platform/iOS/Toolchain_ios.cmake +++ b/cmake/Platform/iOS/Toolchain_ios.cmake @@ -13,7 +13,7 @@ set(CMAKE_OSX_ARCHITECTURES arm64) set(LY_IOS_CODE_SIGNING_IDENTITY "iPhone Developer" CACHE STRING "iPhone Developer") -set(LY_IOS_DEPLOYMENT_TARGET "13.0" CACHE STRING "iOS Deployment Target") +set(LY_IOS_DEPLOYMENT_TARGET "14.0" CACHE STRING "iOS Deployment Target") set(LY_IOS_DEVELOPMENT_TEAM "CF9TGN983S" CACHE STRING "The development team ID") From 4308db0c6dee22a351a65fe78dc453670bb510be Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Thu, 23 Sep 2021 11:59:43 -0400 Subject: [PATCH 81/84] Debug build clang fixes Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../Code/Tests/ClientHierarchyTests.cpp | 2 +- .../Code/Tests/ServerHierarchyTests.cpp | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp index 38ea451c85..316f85c214 100644 --- a/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ClientHierarchyTests.cpp @@ -307,7 +307,7 @@ namespace Multiplayer class ClientDeepHierarchyTests : public ClientSimpleHierarchyTests { public: - static const NetEntityId ChildOfChildNetEntityId = NetEntityId{ 3 }; + const NetEntityId ChildOfChildNetEntityId = NetEntityId{ 3 }; void SetUp() override { diff --git a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp index 70859909b3..385a4b83ae 100644 --- a/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp +++ b/Gems/Multiplayer/Code/Tests/ServerHierarchyTests.cpp @@ -414,12 +414,12 @@ namespace Multiplayer class ServerBranchedHierarchyTests : public HierarchyTests { public: - static const NetEntityId RootNetEntityId = NetEntityId{ 1 }; - static const NetEntityId ChildNetEntityId = NetEntityId{ 2 }; - static const NetEntityId ChildOfChildNetEntityId = NetEntityId{ 3 }; - static const NetEntityId Child2NetEntityId = NetEntityId{ 4 }; - static const NetEntityId ChildOfChild2NetEntityId = NetEntityId{ 5 }; - static const NetEntityId Child2OfChild2NetEntityId = NetEntityId{ 6 }; + const NetEntityId RootNetEntityId = NetEntityId{ 1 }; + const NetEntityId ChildNetEntityId = NetEntityId{ 2 }; + const NetEntityId ChildOfChildNetEntityId = NetEntityId{ 3 }; + const NetEntityId Child2NetEntityId = NetEntityId{ 4 }; + const NetEntityId ChildOfChild2NetEntityId = NetEntityId{ 5 }; + const NetEntityId Child2OfChild2NetEntityId = NetEntityId{ 6 }; void SetUp() override { @@ -610,9 +610,9 @@ namespace Multiplayer class ServerHierarchyOfHierarchyTests : public ServerDeepHierarchyTests { public: - static const NetEntityId Root2NetEntityId = NetEntityId{ 4 }; - static const NetEntityId Child2NetEntityId = NetEntityId{ 5 }; - static const NetEntityId ChildOfChild2NetEntityId = NetEntityId{ 6 }; + const NetEntityId Root2NetEntityId = NetEntityId{ 4 }; + const NetEntityId Child2NetEntityId = NetEntityId{ 5 }; + const NetEntityId ChildOfChild2NetEntityId = NetEntityId{ 6 }; void SetUp() override { @@ -1132,9 +1132,9 @@ namespace Multiplayer class ServerHierarchyWithThreeRoots : public ServerHierarchyOfHierarchyTests { public: - static const NetEntityId Root3NetEntityId = NetEntityId{ 7 }; - static const NetEntityId Child3NetEntityId = NetEntityId{ 8 }; - static const NetEntityId ChildOfChild3NetEntityId = NetEntityId{ 9 }; + const NetEntityId Root3NetEntityId = NetEntityId{ 7 }; + const NetEntityId Child3NetEntityId = NetEntityId{ 8 }; + const NetEntityId ChildOfChild3NetEntityId = NetEntityId{ 9 }; void SetUp() override { From d10cf1e4957e61b33c773483c5daae53636fc6c1 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Thu, 23 Sep 2021 10:47:21 -0700 Subject: [PATCH 82/84] Add guard against edge case. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzToolsFramework/Prefab/PrefabFocusHandler.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp index 2338c8892b..4fd202a73d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp @@ -83,6 +83,12 @@ namespace AzToolsFramework::Prefab bool PrefabFocusHandler::IsOwningPrefabBeingFocused(AZ::EntityId entityId) { + if (!m_focusedInstance.has_value()) + { + // PrefabFocusHandler has not been initialized yet. + return false; + } + if (entityId == AZ::EntityId()) { return false; From 2ef5a6453eda1bc99e537738d83d4e71a7e33702 Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Thu, 23 Sep 2021 11:07:36 -0700 Subject: [PATCH 83/84] Fix failed 'server' platform assets on Linux related to Shaders (#4275) * Add missing 'server' platform identifier for the ShaderBuilder * Use the current host platform as the fallback platform identifier (and not 'pc') Signed-off-by: Steve Pham --- .../Shader/Code/Source/Editor/ShaderBuilderUtility.cpp | 10 ++++++++-- .../Platform/Android/ShaderBuilder_Traits_Android.h | 1 + .../Source/Platform/Linux/ShaderBuilder_Traits_Linux.h | 2 +- .../Source/Platform/Mac/ShaderBuilder_Traits_Mac.h | 1 + .../Platform/Windows/ShaderBuilder_Traits_Windows.h | 1 + .../Source/Platform/iOS/ShaderBuilder_Traits_iOS.h | 1 + 6 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp index eb91d9e866..e9ac18a432 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/ShaderBuilderUtility.cpp @@ -37,6 +37,7 @@ #include #include "ShaderPlatformInterfaceRequest.h" +#include "ShaderBuilder_Traits_Platform.h" #include "AtomShaderConfig.h" #include "SrgLayoutUtility.h" @@ -456,8 +457,9 @@ namespace AZ const uint32_t rhiUniqueIndex, const AZStd::string& platformIdentifier, const AZStd::string& shaderJsonPath, const uint32_t supervariantIndex, RPI::ShaderAssetSubId shaderAssetSubId) { - // platform id from identifier - AzFramework::PlatformId platformId = AzFramework::PlatformId::PC; + // Define a fallback platform ID based on the current host platform + AzFramework::PlatformId platformId = AZ_TRAIT_ATOM_FALLBACK_ASSET_HOST_PLATFORM; + if (platformIdentifier == "pc") { platformId = AzFramework::PlatformId::PC; @@ -478,6 +480,10 @@ namespace AZ { platformId = AzFramework::PlatformId::IOS; } + else if (platformIdentifier == "server") + { + platformId = AzFramework::PlatformId::SERVER; + } uint32_t assetSubId = RPI::ShaderAsset::MakeProductAssetSubId(rhiUniqueIndex, supervariantIndex, aznumeric_cast(shaderAssetSubId)); auto assetIdOutcome = RPI::AssetUtils::MakeAssetId(shaderJsonPath, assetSubId); diff --git a/Gems/Atom/Asset/Shader/Code/Source/Platform/Android/ShaderBuilder_Traits_Android.h b/Gems/Atom/Asset/Shader/Code/Source/Platform/Android/ShaderBuilder_Traits_Android.h index f8d93059f3..86afcd201c 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Platform/Android/ShaderBuilder_Traits_Android.h +++ b/Gems/Atom/Asset/Shader/Code/Source/Platform/Android/ShaderBuilder_Traits_Android.h @@ -8,3 +8,4 @@ #pragma once #define AZ_TRAIT_ATOM_SHADERBUILDER_AZSLC UNUSED_TRAIT +#define AZ_TRAIT_ATOM_FALLBACK_ASSET_HOST_PLATFORM UNUSED_TRAIT diff --git a/Gems/Atom/Asset/Shader/Code/Source/Platform/Linux/ShaderBuilder_Traits_Linux.h b/Gems/Atom/Asset/Shader/Code/Source/Platform/Linux/ShaderBuilder_Traits_Linux.h index efa5a3e9ea..54a0a1fd5d 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Platform/Linux/ShaderBuilder_Traits_Linux.h +++ b/Gems/Atom/Asset/Shader/Code/Source/Platform/Linux/ShaderBuilder_Traits_Linux.h @@ -8,4 +8,4 @@ #pragma once #define AZ_TRAIT_ATOM_SHADERBUILDER_AZSLC "azslc" - +#define AZ_TRAIT_ATOM_FALLBACK_ASSET_HOST_PLATFORM AzFramework::PlatformId::LINUX_ID diff --git a/Gems/Atom/Asset/Shader/Code/Source/Platform/Mac/ShaderBuilder_Traits_Mac.h b/Gems/Atom/Asset/Shader/Code/Source/Platform/Mac/ShaderBuilder_Traits_Mac.h index d47967a559..7b93324711 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Platform/Mac/ShaderBuilder_Traits_Mac.h +++ b/Gems/Atom/Asset/Shader/Code/Source/Platform/Mac/ShaderBuilder_Traits_Mac.h @@ -8,3 +8,4 @@ #pragma once #define AZ_TRAIT_ATOM_SHADERBUILDER_AZSLC "azslc" +#define AZ_TRAIT_ATOM_FALLBACK_ASSET_HOST_PLATFORM AzFramework::PlatformId::MAC_ID diff --git a/Gems/Atom/Asset/Shader/Code/Source/Platform/Windows/ShaderBuilder_Traits_Windows.h b/Gems/Atom/Asset/Shader/Code/Source/Platform/Windows/ShaderBuilder_Traits_Windows.h index 3645897fa2..d6dd19fbfb 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Platform/Windows/ShaderBuilder_Traits_Windows.h +++ b/Gems/Atom/Asset/Shader/Code/Source/Platform/Windows/ShaderBuilder_Traits_Windows.h @@ -8,3 +8,4 @@ #pragma once #define AZ_TRAIT_ATOM_SHADERBUILDER_AZSLC "azslc.exe" +#define AZ_TRAIT_ATOM_FALLBACK_ASSET_HOST_PLATFORM AzFramework::PlatformId::PC diff --git a/Gems/Atom/Asset/Shader/Code/Source/Platform/iOS/ShaderBuilder_Traits_iOS.h b/Gems/Atom/Asset/Shader/Code/Source/Platform/iOS/ShaderBuilder_Traits_iOS.h index f8d93059f3..86afcd201c 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Platform/iOS/ShaderBuilder_Traits_iOS.h +++ b/Gems/Atom/Asset/Shader/Code/Source/Platform/iOS/ShaderBuilder_Traits_iOS.h @@ -8,3 +8,4 @@ #pragma once #define AZ_TRAIT_ATOM_SHADERBUILDER_AZSLC UNUSED_TRAIT +#define AZ_TRAIT_ATOM_FALLBACK_ASSET_HOST_PLATFORM UNUSED_TRAIT From 8cbc5bc4475485c9d7661f24725e65c1b6625859 Mon Sep 17 00:00:00 2001 From: Scott Romero <24445312+AMZN-ScottR@users.noreply.github.com> Date: Thu, 23 Sep 2021 11:14:22 -0700 Subject: [PATCH 84/84] [development] Atom CPU profiler include cleanup (#4272) - Removed all unnecessary includes to Atom CpuProfiler.h - Added includes to AzCore Profiler.h where necessary Signed-off-by: AMZN-ScottR 24445312+AMZN-ScottR@users.noreply.github.com --- .../Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp | 2 -- .../Common/Code/Source/AuxGeom/AuxGeomFeatureProcessor.cpp | 1 - .../Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp | 3 ++- .../Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp | 1 - .../Code/Source/CoreLights/CapsuleLightFeatureProcessor.cpp | 1 - .../Source/CoreLights/DirectionalLightFeatureProcessor.cpp | 1 - .../Code/Source/CoreLights/DiskLightFeatureProcessor.cpp | 1 - .../Code/Source/CoreLights/PointLightFeatureProcessor.cpp | 1 - .../Code/Source/CoreLights/PolygonLightFeatureProcessor.cpp | 1 - .../Code/Source/CoreLights/QuadLightFeatureProcessor.cpp | 1 - .../Source/CoreLights/SimplePointLightFeatureProcessor.cpp | 1 - .../Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.cpp | 1 - .../Common/Code/Source/Decals/DecalFeatureProcessor.cpp | 1 - Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp | 1 - .../ImageBasedLights/ImageBasedLightFeatureProcessor.cpp | 2 -- .../Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp | 1 - .../Code/Source/PostProcess/PostProcessFeatureProcessor.cpp | 2 -- .../Common/Code/Source/PostProcessing/SMAAFeatureProcessor.cpp | 2 -- .../Common/Code/Source/ProfilingCaptureSystemComponent.cpp | 1 - .../Common/Code/Source/ProfilingCaptureSystemComponent.h | 1 - .../Code/Source/RayTracing/RayTracingFeatureProcessor.cpp | 1 - .../Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp | 1 - .../Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp | 1 - .../Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp | 1 - .../Common/Code/Source/SkyBox/SkyBoxFeatureProcessor.cpp | 1 - .../TransformService/TransformServiceFeatureProcessor.cpp | 1 - Gems/Atom/RHI/Code/Include/Atom/RHI/MemorySubAllocator.h | 1 - Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h | 3 ++- Gems/Atom/RHI/Code/Source/RHI/BufferPool.cpp | 1 - Gems/Atom/RHI/Code/Source/RHI/CommandQueue.cpp | 3 ++- Gems/Atom/RHI/Code/Source/RHI/Device.cpp | 1 - Gems/Atom/RHI/Code/Source/RHI/Fence.cpp | 2 ++ Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp | 1 - Gems/Atom/RHI/Code/Source/RHI/FrameGraphCompiler.cpp | 1 - Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuter.cpp | 1 - Gems/Atom/RHI/Code/Source/RHI/FrameScheduler.cpp | 1 - Gems/Atom/RHI/Code/Source/RHI/PipelineStateCache.cpp | 3 ++- Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp | 2 +- Gems/Atom/RHI/DX12/Code/Source/RHI/CommandListPool.cpp | 1 - Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.cpp | 2 +- Gems/Atom/RHI/DX12/Code/Source/RHI/DescriptorContext.cpp | 1 - Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp | 1 - Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueueContext.cpp | 1 - Gems/Atom/RHI/Metal/Code/Source/RHI/FrameGraphCompiler.cpp | 2 +- Gems/Atom/RHI/Metal/Code/Source/RHI/Scope.cpp | 2 +- Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp | 2 +- Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.cpp | 1 - Gems/Atom/RHI/Vulkan/Code/Source/RHI/FrameGraphCompiler.cpp | 1 - Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp | 2 -- .../RPI/Code/Source/RPI.Public/GpuQuery/GpuQuerySystem.cpp | 1 - Gems/Atom/RPI/Code/Source/RPI.Public/Image/ImageSystem.cpp | 1 - Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp | 1 - Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp | 2 -- 53 files changed, 15 insertions(+), 58 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp index 2057c596e5..29db7d6673 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomDrawQueue.cpp @@ -9,8 +9,6 @@ #include "AuxGeomDrawQueue.h" -#include - #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomFeatureProcessor.cpp index ee6d3ba4a3..a4720ad131 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/AuxGeomFeatureProcessor.cpp @@ -12,7 +12,6 @@ #include "DynamicPrimitiveProcessor.h" #include "FixedShapeProcessor.h" -#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp index 9af6493413..ae9e55ac8d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/DynamicPrimitiveProcessor.cpp @@ -9,7 +9,6 @@ #include "DynamicPrimitiveProcessor.h" #include "AuxGeomDrawProcessorShared.h" -#include #include #include #include @@ -21,6 +20,8 @@ #include #include +#include + namespace AZ { namespace Render diff --git a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp index 8b5e439ca0..c2ee397b4c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/AuxGeom/FixedShapeProcessor.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/CapsuleLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/CapsuleLightFeatureProcessor.cpp index 849c930afd..bbea462ac8 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/CapsuleLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/CapsuleLightFeatureProcessor.cpp @@ -16,7 +16,6 @@ #include #include -#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp index 702818dcd9..42cca0e57c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DirectionalLightFeatureProcessor.cpp @@ -12,7 +12,6 @@ #include #include -#include #include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp index ca2c038e46..26e1757a5a 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/DiskLightFeatureProcessor.cpp @@ -16,7 +16,6 @@ #include -#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp index bfb0b1252b..d3b5646e0b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PointLightFeatureProcessor.cpp @@ -16,7 +16,6 @@ #include #include -#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PolygonLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PolygonLightFeatureProcessor.cpp index 9dbf01ae26..f3c05eeeec 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/PolygonLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/PolygonLightFeatureProcessor.cpp @@ -16,7 +16,6 @@ #include -#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/QuadLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/QuadLightFeatureProcessor.cpp index aadc8c2020..787e150646 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/QuadLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/QuadLightFeatureProcessor.cpp @@ -16,7 +16,6 @@ #include -#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimplePointLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimplePointLightFeatureProcessor.cpp index f49a5e94fc..bc13d3d508 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimplePointLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimplePointLightFeatureProcessor.cpp @@ -16,7 +16,6 @@ #include #include -#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.cpp index 277b5026d7..49b7f7d12c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/CoreLights/SimpleSpotLightFeatureProcessor.cpp @@ -16,7 +16,6 @@ #include #include -#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalFeatureProcessor.cpp index 4ff718b5ad..f00c902a73 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalFeatureProcessor.cpp @@ -10,7 +10,6 @@ #include -#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp index 1a68317532..0ff8d2c165 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ImGui/ImGuiPass.cpp @@ -15,7 +15,6 @@ #include -#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/ImageBasedLights/ImageBasedLightFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ImageBasedLights/ImageBasedLightFeatureProcessor.cpp index 9cdad34f17..6a2eda8f22 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ImageBasedLights/ImageBasedLightFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ImageBasedLights/ImageBasedLightFeatureProcessor.cpp @@ -11,8 +11,6 @@ #include #include -#include - #include namespace AZ diff --git a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp index bd0d12106b..82568126df 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Mesh/MeshFeatureProcessor.cpp @@ -8,7 +8,6 @@ #include -#include #include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.cpp index d5b3ebd63b..a9d8d5105f 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcess/PostProcessFeatureProcessor.cpp @@ -8,8 +8,6 @@ #include -#include - #include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/SMAAFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/SMAAFeatureProcessor.cpp index a795d88212..eef0c51e95 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/SMAAFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/SMAAFeatureProcessor.cpp @@ -16,8 +16,6 @@ #include -#include - #include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp index 920326e081..a476b5b839 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp @@ -8,7 +8,6 @@ #include "ProfilingCaptureSystemComponent.h" -#include #include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.h b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.h index 1846767139..9f8a8a90c6 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.h +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.h @@ -12,7 +12,6 @@ #include #include -#include namespace AZ { diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp index a17ecaf1aa..98d32b1050 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp index 9fecbc19fc..52d089ae0d 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp index 8fb971f8f5..c0202c7c74 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp index 500eadf110..e0209702dc 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshFeatureProcessor.cpp @@ -22,7 +22,6 @@ #include #include -#include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/SkyBox/SkyBoxFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/SkyBox/SkyBoxFeatureProcessor.cpp index d4fa3f52be..ca8775a073 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkyBox/SkyBoxFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkyBox/SkyBoxFeatureProcessor.cpp @@ -12,7 +12,6 @@ #include -#include #include #include #include diff --git a/Gems/Atom/Feature/Common/Code/Source/TransformService/TransformServiceFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/TransformService/TransformServiceFeatureProcessor.cpp index 6f9c0dc73a..141acbd744 100644 --- a/Gems/Atom/Feature/Common/Code/Source/TransformService/TransformServiceFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/TransformService/TransformServiceFeatureProcessor.cpp @@ -8,7 +8,6 @@ #include -#include #include #include diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/MemorySubAllocator.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/MemorySubAllocator.h index bdeb252174..3e464a6974 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/MemorySubAllocator.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/MemorySubAllocator.h @@ -7,7 +7,6 @@ */ #pragma once -#include #include #include #include diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h index 988416326e..7558442ad1 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/ObjectCollector.h @@ -7,8 +7,9 @@ */ #pragma once -#include #include + +#include #include #include #include diff --git a/Gems/Atom/RHI/Code/Source/RHI/BufferPool.cpp b/Gems/Atom/RHI/Code/Source/RHI/BufferPool.cpp index 5d06d02668..94b0b57c37 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/BufferPool.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/BufferPool.cpp @@ -7,7 +7,6 @@ */ #include -#include #include #include diff --git a/Gems/Atom/RHI/Code/Source/RHI/CommandQueue.cpp b/Gems/Atom/RHI/Code/Source/RHI/CommandQueue.cpp index 0983d4db22..b50c36d3f9 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/CommandQueue.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/CommandQueue.cpp @@ -7,9 +7,10 @@ */ #include -#include #include +#include + namespace AZ { namespace RHI diff --git a/Gems/Atom/RHI/Code/Source/RHI/Device.cpp b/Gems/Atom/RHI/Code/Source/RHI/Device.cpp index 9453ff79ee..2f4ca297a1 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/Device.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/Device.cpp @@ -6,7 +6,6 @@ * */ -#include #include #include diff --git a/Gems/Atom/RHI/Code/Source/RHI/Fence.cpp b/Gems/Atom/RHI/Code/Source/RHI/Fence.cpp index ca0493a52c..d030ff8d2b 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/Fence.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/Fence.cpp @@ -8,6 +8,8 @@ #include +#include + namespace AZ { namespace RHI diff --git a/Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp b/Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp index b85fa88f34..9f3d21a2f1 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/FrameGraph.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff --git a/Gems/Atom/RHI/Code/Source/RHI/FrameGraphCompiler.cpp b/Gems/Atom/RHI/Code/Source/RHI/FrameGraphCompiler.cpp index 5c5691d975..d06ec002e4 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/FrameGraphCompiler.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/FrameGraphCompiler.cpp @@ -6,7 +6,6 @@ * */ -#include #include #include #include diff --git a/Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuter.cpp b/Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuter.cpp index 429081cd2c..6888531b67 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuter.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/FrameGraphExecuter.cpp @@ -6,7 +6,6 @@ * */ #include -#include #include #include #include diff --git a/Gems/Atom/RHI/Code/Source/RHI/FrameScheduler.cpp b/Gems/Atom/RHI/Code/Source/RHI/FrameScheduler.cpp index 90218709fa..df887379fe 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/FrameScheduler.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/FrameScheduler.cpp @@ -6,7 +6,6 @@ * */ -#include #include #include #include diff --git a/Gems/Atom/RHI/Code/Source/RHI/PipelineStateCache.cpp b/Gems/Atom/RHI/Code/Source/RHI/PipelineStateCache.cpp index 868580f0c7..0c06887dd6 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/PipelineStateCache.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/PipelineStateCache.cpp @@ -6,9 +6,10 @@ * */ -#include #include #include + +#include #include #include diff --git a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp index 69f7002435..ad3ab119ef 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp @@ -6,12 +6,12 @@ * */ -#include #include #include #include #include +#include #include #include diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandListPool.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandListPool.cpp index 94262064da..20021e71ba 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandListPool.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandListPool.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include namespace AZ diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.cpp index eee137026d..9bf25d8bc6 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.cpp @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#include + #include #include #include diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/DescriptorContext.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/DescriptorContext.cpp index 816b904e16..635c66f1cd 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/DescriptorContext.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/DescriptorContext.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include namespace AZ diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp index 722d535cb1..4ff7d581a4 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/FrameGraphCompiler.cpp @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueueContext.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueueContext.cpp index fb11700e04..e4c651c2b1 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueueContext.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueueContext.cpp @@ -7,7 +7,6 @@ */ #include -#include #include #include #include diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/FrameGraphCompiler.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/FrameGraphCompiler.cpp index a347ed9b12..9ee000e166 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/FrameGraphCompiler.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/FrameGraphCompiler.cpp @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#include + #include #include #include diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/Scope.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/Scope.cpp index 7e4d510dfa..c680684efd 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/Scope.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/Scope.cpp @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#include + #include #include #include diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp index 567f89b6e0..d05e1a00a3 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/SwapChain.cpp @@ -6,10 +6,10 @@ * */ +#include #include #include #include -#include #include #include #include diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.cpp index c0d34e2bf9..ec7311cd6e 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include #include diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/FrameGraphCompiler.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/FrameGraphCompiler.cpp index 2a30e36e04..e153ad6645 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/FrameGraphCompiler.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/FrameGraphCompiler.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp index fbfabe4f2a..348f0aa57a 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Culling.cpp @@ -14,8 +14,6 @@ #include #include -#include - #include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/GpuQuerySystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/GpuQuerySystem.cpp index 8077038ea7..0143c8ee2d 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/GpuQuerySystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/GpuQuery/GpuQuerySystem.cpp @@ -7,7 +7,6 @@ */ #include -#include #include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Image/ImageSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Image/ImageSystem.cpp index 71e2eaa2f5..f201e8414c 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Image/ImageSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Image/ImageSystem.cpp @@ -23,7 +23,6 @@ #include #include -#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp index 34d72338dc..f4f51f97b7 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Pass/PassSystem.cpp @@ -19,7 +19,6 @@ #include -#include #include #include diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp index 778548f14c..a7ecf089c0 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Scene.cpp @@ -6,8 +6,6 @@ * */ -#include - #include #include #include