From 79af7d3c0053eb4d7fc673c449ef65c8f594233b Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Thu, 5 Aug 2021 17:47:19 -0400 Subject: [PATCH 001/169] Make the maximum amount of vmem available for skinning related things configurable at runtime Signed-off-by: Yuriy Toporovskyy --- .../SkinnedMeshOutputStreamManager.cpp | 33 ++++++++++++++++++- .../SkinnedMeshOutputStreamManager.h | 3 ++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp index c4eac30431..ffbe850160 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp @@ -8,6 +8,8 @@ #include +#include + #include #include @@ -72,11 +74,36 @@ namespace AZ creator.End(m_bufferAsset); } + AZ_CVAR( + int, + r_skinnedMeshInstanceMemoryPoolSize, + 256, + nullptr, + AZ::ConsoleFunctorFlags::NeedsReload, + "The amount of memory in Mb available for all actor skinning data. Note that this must only be set once at application startup" + ); + void SkinnedMeshOutputStreamManager::Init() { + } + + void SkinnedMeshOutputStreamManager::EnsureInit() const + { + const_cast(this)->EnsureInit(); + } + + void SkinnedMeshOutputStreamManager::EnsureInit() + { + if (!m_needsInit) + { + return; + } + m_needsInit = false; + // 256mb supports roughly 42 character instances at 100,000 vertices per character x 64 bytes per vertex (12 byte position + 12 byte previous frame position + 12 byte normal + 16 byte tangent + 12 byte bitangent) // This includes only the output of the skinning compute shader, not the input buffers or bone transforms - m_sizeInBytes = 256u * (1024u * 1024u); + const AZ::u64 sizeInMb = r_skinnedMeshInstanceMemoryPoolSize; + m_sizeInBytes = AZ::GetMax(sizeInMb, 256ull) * (1024u * 1024u); CalculateAlignment(); @@ -90,6 +117,8 @@ namespace AZ RHI::VirtualAddress result; { AZStd::lock_guard lock(m_allocatorMutex); + + EnsureInit(); result = m_freeListAllocator.Allocate(byteCount, m_alignment); } @@ -129,11 +158,13 @@ namespace AZ Data::Asset SkinnedMeshOutputStreamManager::GetBufferAsset() const { + EnsureInit(); return m_bufferAsset; } Data::Instance SkinnedMeshOutputStreamManager::GetBuffer() { + EnsureInit(); if (!m_buffer) { m_buffer = RPI::Buffer::FindOrCreate(m_bufferAsset); diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.h b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.h index 3cec34a2e2..6009a62362 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.h +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.h @@ -46,6 +46,8 @@ namespace AZ // SystemTickBus void OnSystemTick() override; + void EnsureInit() const; + void EnsureInit(); void GarbageCollect(); void CalculateAlignment(); void CreateBufferAsset(); @@ -58,6 +60,7 @@ namespace AZ size_t m_sizeInBytes = 0; bool m_memoryWasFreed = false; bool m_broadcastMemoryAvailableEvent = false; + bool m_needsInit = true; }; } // namespace Render } // namespace AZ From dbc1f3bb62ec246115f6f7f22c9f766da58d9897 Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Mon, 13 Sep 2021 11:57:39 -0400 Subject: [PATCH 002/169] Don't const_cast, instead remove const qualifier from function Signed-off-by: Yuriy Toporovskyy --- .../SkinnedMesh/SkinnedMeshOutputStreamManagerInterface.h | 2 +- .../Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp | 7 +------ .../Source/SkinnedMesh/SkinnedMeshOutputStreamManager.h | 3 +-- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshOutputStreamManagerInterface.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshOutputStreamManagerInterface.h index 3c3ddc7ddc..fea6d090f7 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshOutputStreamManagerInterface.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/SkinnedMesh/SkinnedMeshOutputStreamManagerInterface.h @@ -51,7 +51,7 @@ namespace AZ } //! Returns the buffer asset that is used for all skinned mesh outputs - virtual Data::Asset GetBufferAsset() const = 0; + virtual Data::Asset GetBufferAsset() = 0; //! Returns the buffer that is used for all skinned mesh outputs virtual Data::Instance GetBuffer() = 0; diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp index ffbe850160..f3744fe119 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp @@ -87,11 +87,6 @@ namespace AZ { } - void SkinnedMeshOutputStreamManager::EnsureInit() const - { - const_cast(this)->EnsureInit(); - } - void SkinnedMeshOutputStreamManager::EnsureInit() { if (!m_needsInit) @@ -156,7 +151,7 @@ namespace AZ } } - Data::Asset SkinnedMeshOutputStreamManager::GetBufferAsset() const + Data::Asset SkinnedMeshOutputStreamManager::GetBufferAsset() { EnsureInit(); return m_bufferAsset; diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.h b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.h index 6009a62362..d0d00ead18 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.h +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.h @@ -39,14 +39,13 @@ namespace AZ AZStd::intrusive_ptr Allocate(size_t byteCount) override; void DeAllocate(RHI::VirtualAddress allocation) override; void DeAllocateNoSignal(RHI::VirtualAddress allocation) override; - Data::Asset GetBufferAsset() const override; + Data::Asset GetBufferAsset() override; Data::Instance GetBuffer() override; private: // SystemTickBus void OnSystemTick() override; - void EnsureInit() const; void EnsureInit(); void GarbageCollect(); void CalculateAlignment(); From 6cd770a9448cfd00274efb3647e70395fc4d40bb Mon Sep 17 00:00:00 2001 From: Pinfel Date: Sun, 19 Sep 2021 12:57:57 -0400 Subject: [PATCH 003/169] Fixed in-editor "Scripting" category components reference links to o3de.org docs Signed-off-by: Pinfel --- .../AzToolsFramework/ToolsComponents/ScriptEditorComponent.cpp | 2 +- .../Code/Editor/Components/EditorScriptCanvasComponent.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/ScriptEditorComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/ScriptEditorComponent.cpp index cc350c8107..376cd67e32 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/ScriptEditorComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ToolsComponents/ScriptEditorComponent.cpp @@ -1024,7 +1024,7 @@ namespace AzToolsFramework ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/LuaScript.svg") ->Attribute(AZ::Edit::Attributes::PrimaryAssetType, AZ::AzTypeInfo::Uuid()) ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Script.png") - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/lua-script/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/scripting/lua-script/") ->DataElement("AssetRef", &ScriptEditorComponent::m_scriptAsset, "Script", "Which script to use") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &ScriptEditorComponent::ScriptHasChanged) ->Attribute("BrowseIcon", ":/stylesheet/img/UI20/browse-edit-select-files.svg") diff --git a/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp b/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp index 2708f95f92..043e034062 100644 --- a/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Components/EditorScriptCanvasComponent.cpp @@ -170,7 +170,7 @@ namespace ScriptCanvasEditor ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("UI", 0x27ff46b0)) ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Level", 0x9aeacc13)) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/script-canvas/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/scripting/script-canvas/") ->DataElement(AZ::Edit::UIHandlers::Default, &EditorScriptCanvasComponent::m_scriptCanvasAssetHolder, "Script Canvas Asset", "Script Canvas asset associated with this component") ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) ->DataElement(AZ::Edit::UIHandlers::Default, &EditorScriptCanvasComponent::m_variableOverrides, "Properties", "Script Canvas Graph Properties") From 890dbbf2e9180983110ac02a8832737e781fefc9 Mon Sep 17 00:00:00 2001 From: Pinfel Date: Sun, 19 Sep 2021 13:01:40 -0400 Subject: [PATCH 004/169] Fixed in-editor "AI" category components reference links to o3de.org docs Signed-off-by: Pinfel --- .../Code/Source/Ai/EditorNavigationAreaComponent.cpp | 2 +- .../Code/Source/Ai/EditorNavigationSeedComponent.cpp | 2 +- Gems/LmbrCentral/Code/Source/Ai/NavigationComponent.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/LmbrCentral/Code/Source/Ai/EditorNavigationAreaComponent.cpp b/Gems/LmbrCentral/Code/Source/Ai/EditorNavigationAreaComponent.cpp index 4a290443d0..f723918cf3 100644 --- a/Gems/LmbrCentral/Code/Source/Ai/EditorNavigationAreaComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Ai/EditorNavigationAreaComponent.cpp @@ -51,7 +51,7 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/NavigationArea.svg") ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/NavigationArea.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/nav-area/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/ai/nav-area/") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement(AZ::Edit::UIHandlers::CheckBox, &EditorNavigationAreaComponent::m_exclusion, "Exclusion", "Does this area add or subtract from the Navigation Mesh") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorNavigationAreaComponent::OnNavigationAreaChanged) diff --git a/Gems/LmbrCentral/Code/Source/Ai/EditorNavigationSeedComponent.cpp b/Gems/LmbrCentral/Code/Source/Ai/EditorNavigationSeedComponent.cpp index 975eb17da1..47999dbd4b 100644 --- a/Gems/LmbrCentral/Code/Source/Ai/EditorNavigationSeedComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Ai/EditorNavigationSeedComponent.cpp @@ -36,7 +36,7 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/NavigationSeed.svg") ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/NavigationSeed.svg") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/nav-seed/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/ai/nav-seed/") ->DataElement(AZ::Edit::UIHandlers::ComboBox, &EditorNavigationSeedComponent::m_agentType, "Agent Type", "Describes the type of the Entity for navigation purposes.") ->Attribute(AZ::Edit::Attributes::StringList, &PopulateAgentTypeList) ->Attribute("ChangeNotify", &EditorNavigationSeedComponent::OnAgentTypeChanged); diff --git a/Gems/LmbrCentral/Code/Source/Ai/NavigationComponent.cpp b/Gems/LmbrCentral/Code/Source/Ai/NavigationComponent.cpp index 9897895dcd..500d5c17da 100644 --- a/Gems/LmbrCentral/Code/Source/Ai/NavigationComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Ai/NavigationComponent.cpp @@ -125,7 +125,7 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Navigation.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/navigation/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/ai/navigation/") ->DataElement(AZ::Edit::UIHandlers::Default, &NavigationComponent::m_agentSpeed, "Agent Speed", "The speed of the agent while navigating ") ->DataElement(AZ::Edit::UIHandlers::ComboBox, &NavigationComponent::m_agentType, "Agent Type", From 1fc8ef44c7da3c54b50fc2071a96f75176a68386 Mon Sep 17 00:00:00 2001 From: Pinfel Date: Sun, 19 Sep 2021 13:07:50 -0400 Subject: [PATCH 005/169] Fixed in-editor "Animation" category components reference links to o3de.org docs Signed-off-by: Pinfel --- .../Code/Source/Animation/EditorAttachmentComponent.cpp | 2 +- .../Integration/Editor/Components/EditorActorComponent.cpp | 2 +- .../Integration/Editor/Components/EditorAnimGraphComponent.cpp | 2 +- .../Editor/Components/EditorSimpleMotionComponent.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.cpp index 878eb51efb..c494b08b22 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Animation/EditorAttachmentComponent.cpp @@ -70,7 +70,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->Attribute( AZ::Edit::Attributes::HelpPageURL, - "https://o3de.org/docs/user-guide/components/reference/attachment/") + "https://o3de.org/docs/user-guide/components/reference/animation/attachment/") ->DataElement(0, &EditorAttachmentComponent::m_targetId, "Target entity", "Attach to this entity.") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorAttachmentComponent::OnTargetIdChanged) ->DataElement( diff --git a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp index ed4edda891..293f9a1015 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.cpp @@ -106,7 +106,7 @@ namespace EMotionFX ->Attribute(AZ::Edit::Attributes::ViewportIcon, ":/EMotionFX/Viewport/ActorComponent.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/actor/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/animation/actor/") ->DataElement(0, &EditorActorComponent::m_actorAsset, "Actor asset", "Assigned actor asset") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorActorComponent::OnAssetSelected) diff --git a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorAnimGraphComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorAnimGraphComponent.cpp index 8721acbf3d..3e5de8237c 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorAnimGraphComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorAnimGraphComponent.cpp @@ -64,7 +64,7 @@ namespace EMotionFX ->Attribute(AZ::Edit::Attributes::ViewportIcon, ":/EMotionFX/Viewport/AnimGraphComponent.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/animgraph/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/animation/animgraph/") ->DataElement(AZ::Edit::UIHandlers::Default, &EditorAnimGraphComponent::m_motionSetAsset, "Motion set asset", "EMotion FX motion set asset to be loaded for this actor.") ->Attribute("EditButton", "") diff --git a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorSimpleMotionComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorSimpleMotionComponent.cpp index 8446050254..783399c956 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorSimpleMotionComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorSimpleMotionComponent.cpp @@ -46,12 +46,12 @@ namespace EMotionFX ->Attribute(AZ::Edit::Attributes::PrimaryAssetType, azrtti_typeid()) ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Mannequin.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/animation/simple-motion/") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement(0, &EditorSimpleMotionComponent::m_previewInEditor, "Preview In Editor", "Plays motion in Editor") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorSimpleMotionComponent::OnEditorPropertyChanged) ->DataElement(0, &EditorSimpleMotionComponent::m_configuration, "Configuration", "Settings for this Simple Motion") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorSimpleMotionComponent::OnEditorPropertyChanged) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/simple-motion/") ; } } From 00b5b7ba2d0cfa357ee7386562c4ab28dbefee81 Mon Sep 17 00:00:00 2001 From: Pinfel Date: Sun, 19 Sep 2021 13:15:05 -0400 Subject: [PATCH 006/169] Fixed in-editor "Atom" category components reference links to o3de.org docs Signed-off-by: Pinfel --- .../Code/Source/CoreLights/EditorAreaLightComponent.cpp | 2 +- .../Code/Source/CoreLights/EditorDirectionalLightComponent.cpp | 2 +- .../EditorDiffuseProbeGridComponent.cpp | 1 + .../CommonFeatures/Code/Source/Grid/EditorGridComponent.cpp | 2 +- .../Source/ImageBasedLights/EditorImageBasedLightComponent.cpp | 2 +- .../Code/Source/Material/EditorMaterialComponent.cpp | 2 +- .../CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp | 2 +- .../EditorOcclusionCullingPlaneComponent.cpp | 1 + .../Code/Source/PostProcess/Bloom/EditorBloomComponent.cpp | 2 +- .../PostProcess/DepthOfField/EditorDepthOfFieldComponent.cpp | 2 +- .../PostProcess/DisplayMapper/EditorDisplayMapperComponent.cpp | 2 +- .../Code/Source/PostProcess/EditorPostFxLayerComponent.cpp | 2 +- .../ExposureControl/EditorExposureControlComponent.cpp | 2 +- .../EditorGradientWeightModifierComponent.cpp | 2 +- .../LookModification/EditorLookModificationComponent.cpp | 2 +- .../EditorRadiusWeightModifierComponent.cpp | 2 +- .../ShapeWeightModifier/EditorShapeWeightModifierComponent.cpp | 2 +- .../Code/Source/PostProcess/Ssao/EditorSsaoComponent.cpp | 2 +- .../Source/ReflectionProbe/EditorReflectionProbeComponent.cpp | 1 + .../Code/Source/ScreenSpace/EditorDeferredFogComponent.cpp | 2 +- .../Code/Source/Scripting/EditorEntityReferenceComponent.cpp | 2 +- .../Code/Source/SkyBox/EditorHDRiSkyboxComponent.cpp | 2 +- .../Code/Source/SkyBox/EditorPhysicalSkyComponent.cpp | 2 +- 23 files changed, 23 insertions(+), 20 deletions(-) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp index 659c394cba..954ec4cad8 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorAreaLightComponent.cpp @@ -49,7 +49,7 @@ namespace AZ ->Attribute(Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/AreaLight.svg") ->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(Edit::Attributes::AutoExpand, true) - ->Attribute(Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/area-light/") + ->Attribute(Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/light/") ; editContext->Class( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorDirectionalLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorDirectionalLightComponent.cpp index ef9c73c0b4..2854244f6b 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorDirectionalLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/CoreLights/EditorDirectionalLightComponent.cpp @@ -44,7 +44,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.svg") // [GFX TODO][ATOM-1998] create icons. ->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(Edit::Attributes::AutoExpand, true) - ->Attribute(Edit::Attributes::HelpPageURL, "https://") // [GFX TODO][ATOM-1998] create page + ->Attribute(Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/directional-light/") // [GFX TODO][ATOM-1998] create page ; editContext->Class( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.cpp index 013a8ee1b4..8383ac0f17 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/DiffuseGlobalIllumination/EditorDiffuseProbeGridComponent.cpp @@ -53,6 +53,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute(Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/diffuse-probe-grid/") ->Attribute(AZ::Edit::Attributes::PrimaryAssetType, AZ::AzTypeInfo::Uuid()) ->ClassElement(AZ::Edit::ClassElements::Group, "Probe Spacing") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Grid/EditorGridComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Grid/EditorGridComponent.cpp index 76f198852e..253f3ddd90 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Grid/EditorGridComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Grid/EditorGridComponent.cpp @@ -34,7 +34,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/grid/") ; editContext->Class( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ImageBasedLights/EditorImageBasedLightComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ImageBasedLights/EditorImageBasedLightComponent.cpp index 0547da6240..31eb0d51b1 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ImageBasedLights/EditorImageBasedLightComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ImageBasedLights/EditorImageBasedLightComponent.cpp @@ -34,7 +34,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/global-skylight-ibl/") ; editContext->Class( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp index c243522257..899dce4feb 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponent.cpp @@ -89,7 +89,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/material/") ->Attribute(AZ::Edit::Attributes::PrimaryAssetType, AZ::AzTypeInfo::Uuid()) ->DataElement(AZ::Edit::UIHandlers::MultiLineEdit, &EditorMaterialComponent::m_message, "Message", "") ->Attribute(AZ_CRC("PlaceholderText", 0xa23ec278), "Component cannot be edited with multiple entities selected") diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp index 3324bdfa8d..c89546264a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp @@ -48,7 +48,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Mesh.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/mesh/") ->Attribute(AZ::Edit::Attributes::PrimaryAssetType, AZ::AzTypeInfo::Uuid()) ->DataElement(AZ::Edit::UIHandlers::Button, &EditorMeshComponent::m_addMaterialComponentFlag, "Add Material Component", "Add Material Component") ->Attribute(AZ::Edit::Attributes::NameLabelOverride, "") diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/OcclusionCullingPlane/EditorOcclusionCullingPlaneComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/OcclusionCullingPlane/EditorOcclusionCullingPlaneComponent.cpp index 3908aafe89..85eb4a209a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/OcclusionCullingPlane/EditorOcclusionCullingPlaneComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/OcclusionCullingPlane/EditorOcclusionCullingPlaneComponent.cpp @@ -37,6 +37,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/occlusion-culling-plane/") ; editContext->Class( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/Bloom/EditorBloomComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/Bloom/EditorBloomComponent.cpp index 22c8e2dceb..9018b0860b 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/Bloom/EditorBloomComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/Bloom/EditorBloomComponent.cpp @@ -32,7 +32,7 @@ namespace AZ ->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("Game", 0x232b318c)) ->Attribute(Edit::Attributes::AutoExpand, true) - ->Attribute(Edit::Attributes::HelpPageURL, "https://") // [TODO ATOM-2672][PostFX] need create page for PostProcessing. + ->Attribute(Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/bloom/") // [TODO ATOM-2672][PostFX] need create page for PostProcessing. ; editContext->Class( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DepthOfField/EditorDepthOfFieldComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DepthOfField/EditorDepthOfFieldComponent.cpp index b3f77b1b8f..4b9ed8f6af 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DepthOfField/EditorDepthOfFieldComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DepthOfField/EditorDepthOfFieldComponent.cpp @@ -32,7 +32,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.svg") // [GFX TODO ATOM-2672][PostFX] need to create icons for PostProcessing.y ->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(Edit::Attributes::AutoExpand, true) - ->Attribute(Edit::Attributes::HelpPageURL, "https://") // [GFX TODO][ATOM-2672][PostFX] need create page for PostProcessing. + ->Attribute(Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/depth-of-field/") // [GFX TODO][ATOM-2672][PostFX] need create page for PostProcessing. ; editContext->Class( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/EditorDisplayMapperComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/EditorDisplayMapperComponent.cpp index d06bc981fe..246fbbff5d 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/EditorDisplayMapperComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/DisplayMapper/EditorDisplayMapperComponent.cpp @@ -33,7 +33,7 @@ namespace AZ ->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, AZStd::vector({ AZ_CRC("Level", 0x9aeacc13), AZ_CRC("Game", 0x232b318c) })) ->Attribute(Edit::Attributes::AutoExpand, true) - ->Attribute(Edit::Attributes::HelpPageURL, "https://") // [GFX TODO][ATOM-2672][PostFX] need to create page for PostProcessing. + ->Attribute(Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/display-mapper/") // [GFX TODO][ATOM-2672][PostFX] need to create page for PostProcessing. ; editContext->Class( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/EditorPostFxLayerComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/EditorPostFxLayerComponent.cpp index 344c5f8edd..b61cce839e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/EditorPostFxLayerComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/EditorPostFxLayerComponent.cpp @@ -32,7 +32,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/postfx-layer/") ; editContext->Class( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ExposureControl/EditorExposureControlComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ExposureControl/EditorExposureControlComponent.cpp index 5bf3e0ec9c..d8bf13dd81 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ExposureControl/EditorExposureControlComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ExposureControl/EditorExposureControlComponent.cpp @@ -32,7 +32,7 @@ namespace AZ ->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("Game", 0x232b318c)) ->Attribute(Edit::Attributes::AutoExpand, true) - ->Attribute(Edit::Attributes::HelpPageURL, "https://") // [TODO ATOM-2672][PostFX] need create page for PostProcessing. + ->Attribute(Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/exposure-control/") // [TODO ATOM-2672][PostFX] need create page for PostProcessing. ; editContext->Class( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/GradientWeightModifier/EditorGradientWeightModifierComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/GradientWeightModifier/EditorGradientWeightModifierComponent.cpp index 86b5ad554a..2f143491f5 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/GradientWeightModifier/EditorGradientWeightModifierComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/GradientWeightModifier/EditorGradientWeightModifierComponent.cpp @@ -32,7 +32,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.svg") ->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(Edit::Attributes::AutoExpand, true) - ->Attribute(Edit::Attributes::HelpPageURL, "") + ->Attribute(Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/postfx-gradient-weight-modifier/") ; editContext->Class("GradientWeightModifierComponentController", "") diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/LookModification/EditorLookModificationComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/LookModification/EditorLookModificationComponent.cpp index 310762863a..b23ae9805b 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/LookModification/EditorLookModificationComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/LookModification/EditorLookModificationComponent.cpp @@ -32,7 +32,7 @@ namespace AZ ->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("Game", 0x232b318c)) ->Attribute(Edit::Attributes::AutoExpand, true) - ->Attribute(Edit::Attributes::HelpPageURL, "https://") // [TODO ATOM-2672][PostFX] need to create page for PostProcessing. + ->Attribute(Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/look-modification/") // [TODO ATOM-2672][PostFX] need to create page for PostProcessing. ; editContext->Class( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/RadiusWeightModifier/EditorRadiusWeightModifierComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/RadiusWeightModifier/EditorRadiusWeightModifierComponent.cpp index 219ab6acb9..d4d86d6496 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/RadiusWeightModifier/EditorRadiusWeightModifierComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/RadiusWeightModifier/EditorRadiusWeightModifierComponent.cpp @@ -32,7 +32,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.svg") ->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(Edit::Attributes::AutoExpand, true) - ->Attribute(Edit::Attributes::HelpPageURL, "") + ->Attribute(Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/radius-weight-modifier/") ; editContext->Class("RadiusWeightModifierComponentController", "") diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ShapeWeightModifier/EditorShapeWeightModifierComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ShapeWeightModifier/EditorShapeWeightModifierComponent.cpp index 46de0f0c68..842e1a6995 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ShapeWeightModifier/EditorShapeWeightModifierComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/ShapeWeightModifier/EditorShapeWeightModifierComponent.cpp @@ -32,7 +32,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.svg") ->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(Edit::Attributes::AutoExpand, true) - ->Attribute(Edit::Attributes::HelpPageURL, "") + ->Attribute(Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/postfx-shape-weight-modifier/") ; editContext->Class("ShapeWeightModifierComponentController", "") diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/Ssao/EditorSsaoComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/Ssao/EditorSsaoComponent.cpp index b018ac7a54..43f311a77e 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/Ssao/EditorSsaoComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/PostProcess/Ssao/EditorSsaoComponent.cpp @@ -32,7 +32,7 @@ namespace AZ ->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://") // [GFX TODO][ATOM-2672][PostFX] need create page for PostProcessing. + ->Attribute(Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/ssao/") // [GFX TODO][ATOM-2672][PostFX] need create page for PostProcessing. ; editContext->Class( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp index 4f4f21ab0f..deb26f869d 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ReflectionProbe/EditorReflectionProbeComponent.cpp @@ -51,6 +51,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) + ->Attribute(Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/reflection-probe/") ->Attribute(AZ::Edit::Attributes::PrimaryAssetType, AZ::AzTypeInfo::Uuid()) ->ClassElement(AZ::Edit::ClassElements::Group, "Cubemap Bake") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ScreenSpace/EditorDeferredFogComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ScreenSpace/EditorDeferredFogComponent.cpp index 208747abaa..139c24a959 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ScreenSpace/EditorDeferredFogComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ScreenSpace/EditorDeferredFogComponent.cpp @@ -32,7 +32,7 @@ namespace AZ ->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("Game", 0x232b318c)) ->Attribute(Edit::Attributes::AutoExpand, true) - ->Attribute(Edit::Attributes::HelpPageURL, "https://") // [TODO][ATOM-13427] Create Wiki for Deferred Fog + ->Attribute(Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/deferred-fog/") // [TODO][ATOM-13427] Create Wiki for Deferred Fog ; editContext->Class( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Scripting/EditorEntityReferenceComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Scripting/EditorEntityReferenceComponent.cpp index 65491a9833..e297b7cc12 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Scripting/EditorEntityReferenceComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Scripting/EditorEntityReferenceComponent.cpp @@ -31,7 +31,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.svg") ->Attribute(Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(Edit::Attributes::AutoExpand, true) - ->Attribute(Edit::Attributes::HelpPageURL, "") + ->Attribute(Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/entity-reference/") ; editContext->Class("EntityReferenceComponentController", "") diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/EditorHDRiSkyboxComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/EditorHDRiSkyboxComponent.cpp index a0ffb4e509..1cf14cca71 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/EditorHDRiSkyboxComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/EditorHDRiSkyboxComponent.cpp @@ -32,7 +32,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/hdri-skybox/") ; editContext->Class( diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/EditorPhysicalSkyComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/EditorPhysicalSkyComponent.cpp index 28cb4121cf..81b182ccaa 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/EditorPhysicalSkyComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/EditorPhysicalSkyComponent.cpp @@ -32,7 +32,7 @@ namespace AZ ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Component_Placeholder.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/atom/physical-sky/") ; editContext->Class( From 83616242c7ce2650e1feb6cad88009d9948a9d56 Mon Sep 17 00:00:00 2001 From: Pinfel Date: Sun, 19 Sep 2021 13:15:55 -0400 Subject: [PATCH 007/169] Fixed in-editor "Camera" category components reference links to o3de.org docs Signed-off-by: Pinfel --- Gems/Camera/Code/Source/EditorCameraComponent.cpp | 2 +- Gems/CameraFramework/Code/Source/CameraRigComponent.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gems/Camera/Code/Source/EditorCameraComponent.cpp b/Gems/Camera/Code/Source/EditorCameraComponent.cpp index 4ebec334ec..0a922b4c4c 100644 --- a/Gems/Camera/Code/Source/EditorCameraComponent.cpp +++ b/Gems/Camera/Code/Source/EditorCameraComponent.cpp @@ -95,7 +95,7 @@ namespace Camera ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Editor/Icons/Components/Viewport/Camera.svg") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/camera/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/camera/camera/") ->UIElement(AZ::Edit::UIHandlers::Button,"", "Sets the view to this camera") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorCameraComponent::OnPossessCameraButtonClicked) ->Attribute(AZ::Edit::Attributes::ButtonText, &EditorCameraComponent::GetCameraViewButtonText) diff --git a/Gems/CameraFramework/Code/Source/CameraRigComponent.cpp b/Gems/CameraFramework/Code/Source/CameraRigComponent.cpp index e8df095ed0..12c1e5861b 100644 --- a/Gems/CameraFramework/Code/Source/CameraRigComponent.cpp +++ b/Gems/CameraFramework/Code/Source/CameraRigComponent.cpp @@ -126,7 +126,7 @@ namespace Camera ->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/CameraRig.svg") ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Editor/Icons/Components/Viewport/CameraRig.png") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/camera-rig/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/camera/camera-rig/") ->DataElement(0, &CameraRigComponent::m_targetAcquirers, "Target acquirers", "A list of behaviors that define how a camera will select a target. They are executed in order until one succeeds") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) From 9b29ea7ae24ac1b58ad6f3bdfcbe8e49c774ca75 Mon Sep 17 00:00:00 2001 From: Pinfel Date: Sun, 19 Sep 2021 13:16:26 -0400 Subject: [PATCH 008/169] Fixed in-editor "Editor" category components reference links to o3de.org docs Signed-off-by: Pinfel --- Gems/LmbrCentral/Code/Source/Editor/EditorCommentComponent.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/LmbrCentral/Code/Source/Editor/EditorCommentComponent.cpp b/Gems/LmbrCentral/Code/Source/Editor/EditorCommentComponent.cpp index 97f8dc60a2..6c929bd3c4 100644 --- a/Gems/LmbrCentral/Code/Source/Editor/EditorCommentComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Editor/EditorCommentComponent.cpp @@ -33,7 +33,7 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Comment.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZStd::vector({ AZ_CRC("Level", 0x9aeacc13), AZ_CRC("Game", 0x232b318c), AZ_CRC("Layer", 0xe4db211a) })) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/comment/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/editor/comment/") ->DataElement(AZ::Edit::UIHandlers::MultiLineEdit, &EditorCommentComponent::m_comment,"", "Comment") ->Attribute(AZ_CRC("PlaceholderText", 0xa23ec278), "Add comment text here"); } From c2a3351676dd24bbbe8b907480adfab408f3fe72 Mon Sep 17 00:00:00 2001 From: Pinfel Date: Sun, 19 Sep 2021 13:19:17 -0400 Subject: [PATCH 009/169] Fixed in-editor "Gameplay" category components reference links to o3de.org docs Signed-off-by: Pinfel --- Gems/LmbrCentral/Code/Source/Scripting/EditorTagComponent.cpp | 2 +- Gems/LmbrCentral/Code/Source/Scripting/SimpleStateComponent.cpp | 2 +- .../Code/Source/InputConfigurationComponent.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/LmbrCentral/Code/Source/Scripting/EditorTagComponent.cpp b/Gems/LmbrCentral/Code/Source/Scripting/EditorTagComponent.cpp index fa98601a11..90fc0db437 100644 --- a/Gems/LmbrCentral/Code/Source/Scripting/EditorTagComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Scripting/EditorTagComponent.cpp @@ -38,7 +38,7 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/Tag.svg") ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/Tag.svg") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/tag/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/gameplay/tag/") ->DataElement(AZ::Edit::UIHandlers::Default, &EditorTagComponent::m_tags, "Tags", "The tags that will be on this entity by default") ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorTagComponent::OnTagChanged); } diff --git a/Gems/LmbrCentral/Code/Source/Scripting/SimpleStateComponent.cpp b/Gems/LmbrCentral/Code/Source/Scripting/SimpleStateComponent.cpp index e278f18e8b..29c97cdde1 100644 --- a/Gems/LmbrCentral/Code/Source/Scripting/SimpleStateComponent.cpp +++ b/Gems/LmbrCentral/Code/Source/Scripting/SimpleStateComponent.cpp @@ -204,7 +204,7 @@ namespace LmbrCentral ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/SimpleState.svg") ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/SimpleState.svg") - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/simple-state/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/gameplay/simple-state/") ->DataElement(AZ::Edit::UIHandlers::ComboBox, &SimpleStateComponent::m_initialStateName, "Initial state", "The initial active state") ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ_CRC("RefreshAttributesAndValues", 0xcbc2147c)) ->Attribute(AZ::Edit::Attributes::StringList, &SimpleStateComponent::GetStateNames) diff --git a/Gems/StartingPointInput/Code/Source/InputConfigurationComponent.cpp b/Gems/StartingPointInput/Code/Source/InputConfigurationComponent.cpp index 42fa05473c..b2a1251662 100644 --- a/Gems/StartingPointInput/Code/Source/InputConfigurationComponent.cpp +++ b/Gems/StartingPointInput/Code/Source/InputConfigurationComponent.cpp @@ -55,7 +55,7 @@ namespace StartingPointInput ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Editor/Icons/Components/Viewport/InputConfig.svg") ->Attribute(AZ::Edit::Attributes::PrimaryAssetType, AZ::AzTypeInfo::Uuid()) ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game")) - ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/input/") + ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/gameplay/input/") ->DataElement(AZ::Edit::UIHandlers::Default, &InputConfigurationComponent::m_inputEventBindingsAsset, "Input to event bindings", "Asset containing input to event binding information.") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) From 779edb7fe5fd54ab67c1acb2439522a5c13eded4 Mon Sep 17 00:00:00 2001 From: kritin Date: Thu, 30 Sep 2021 16:43:15 -0700 Subject: [PATCH 010/169] Sample Editor test for QA Automation project Signed-off-by: kritin --- .../EditorScripts/Sample_Editor_Tests.py | 143 ++++++++++++++++++ .../editor/TestSuite_Main_Optimized.py | 3 + 2 files changed, 146 insertions(+) create mode 100644 AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Sample_Editor_Tests.py diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Sample_Editor_Tests.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Sample_Editor_Tests.py new file mode 100644 index 0000000000..746c0a936d --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Sample_Editor_Tests.py @@ -0,0 +1,143 @@ +""" +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 + +Test Case: Creating tests for basic editor feature like creating a level, adding new entities, modifying the entities etc. +""" + + +class Tests: + create_level = ("Level created and loaded successfully", "Failed to create the level") + open_level = ("Level loaded successfully", "Failed to load the level") + create_entity = ("Parent entity created successfully", "Failed to create a parent entity") + set_entity_name = ("Entity name set successfully", "Failed to set entity name") + delete_entity = ("Parent entity deleted successfully", "Failed to delete parent entity") + game_mode_enter = ("Game Mode entered successfully", "Failed to enter the game mode") + game_mode_exit = ("Game mode exited successfully", "Failed to exit game mode") + create_child_entity = ("Child entity created successfully", "Failed to create a child entity") + delete_child_entity = ("Child entity deleted successfully", "Failed to delete child entity") + add_mesh_component = ("Mesh component added successfully", "Failed to add mesh component") + found_component_typeId = ("Found component typeId", "Unable to find component TypeId") + remove_mesh_component = ("Mesh component removed successfully", "Failed to remove mesh component") + + +def sample_editor_tests(): + """ + Performing basic test in editor + 01. create_level if it does not exist else 02. open exiting level + + 03. create parent entity and set name + 04. create child entity + 05. delete child entity + 06. add mesh component + 07. remove mesh component + 08. enter game mode + 09. exit game_mode + 10. delete parent entity + 11. save level + + """ + import os + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + import editor_python_test_tools.hydra_editor_utils as hydra + + import azlmbr.math as math + import azlmbr.asset as asset + import azlmbr.bus as bus + import azlmbr.editor as editor + import azlmbr.entity as entity + import azlmbr.legacy.general as general + import azlmbr.object + + def search_entity(entity_to_search, entity_name): + """ + + :param entity_to_search: entity to be searched + :param entity_name: name of the entity used in the set command + :return: True if entity id exists in the entity_list + False if entity id does not exist in the entity_list + """ + entity_list = [] + entity_search_filter = entity.SearchFilter() + entity_search_filter.names = entity_name + entity_list = entity.SearchBus(bus.Broadcast, 'SearchEntities', entity_search_filter) + if entity_list: + if entity_to_search in entity_list: + return True + return False + return False + + # 01. create_level + + test_level = 'Simple' + general.open_level_no_prompt(test_level) + Report.result(Tests.create_level, general.get_current_level_name() == test_level) + + # 02. load existing level - skipping this since this could alter existing level that other test depends on + + # 03. create_entity and set name + # Delete any exiting entity and Create a new Entity at the root level + search_filter = azlmbr.entity.SearchFilter() + all_entities = entity.SearchBus(azlmbr.bus.Broadcast, "SearchEntities", search_filter) + editor.ToolsApplicationRequestBus(bus.Broadcast, "DeleteEntities", all_entities) + parent_entity = editor.ToolsApplicationRequestBus(bus.Broadcast, "CreateNewEntity", entity.EntityId()) + Report.result(Tests.create_entity, parent_entity.IsValid()) + + # Setting a new name + parent_entity_name = "Parent_1" + editor.EditorEntityAPIBus(bus.Event, 'SetName', parent_entity, parent_entity_name) + Report.result(Tests.set_entity_name, + editor.EditorEntityInfoRequestBus(bus.Event, 'GetName', parent_entity) == parent_entity_name) + + # 04. Creating child Entity and setting name to above created parent entity + child_1_entity = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', parent_entity) + Report.result(Tests.create_child_entity, child_1_entity.IsValid()) + child_entity_name = "Child_1" + editor.EditorEntityAPIBus(bus.Event, 'SetName', child_1_entity, child_entity_name) + Report.result(Tests.set_entity_name, + editor.EditorEntityInfoRequestBus(bus.Event, 'GetName', child_1_entity) == child_entity_name) + + # 05. delete_Child_entity + editor.ToolsApplicationRequestBus(bus.Broadcast, 'DeleteEntityById', child_1_entity) + Report.result(Tests.delete_entity, search_entity(child_1_entity, "Child_1") == False) + + # 06. add mesh component to parent entity + type_id_list = editor.EditorComponentAPIBus(bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Mesh"], + entity.EntityType().Game) + if type_id_list is not None: + component_outcome = editor.EditorComponentAPIBus(bus.Broadcast, 'AddComponentsOfType', parent_entity, + type_id_list) + Report.result(Tests.add_mesh_component, component_outcome.IsSuccess()) + else: + Report.result(Tests.found_component_typeId, type_id_list is not None) + + # 09. remove mesh component + outcome_get_component = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', parent_entity, + type_id_list[0]) + if outcome_get_component.IsSuccess(): + component_entity_pair = outcome_get_component.GetValue() + editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', [component_entity_pair]) + component_exists = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', parent_entity, + type_id_list[0]) + mesh_test = True + if component_exists: + mesh_test = False + Report.result(Tests.remove_mesh_component, mesh_test) + else: + Report.result(Tests.found_component_typeId, outcome_get_component.IsSuccess()) + + # 10. delete parent entity + editor.ToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'DeleteEntityById', parent_entity) + Report.result(Tests.delete_entity, search_entity(parent_entity, "Parent_1") == False) + + # Close editor without saving + editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'ExitNoPrompt') + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + + Report.start_test(sample_editor_tests) diff --git a/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main_Optimized.py index 9c0b99daff..9aef8a8b2c 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main_Optimized.py +++ b/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main_Optimized.py @@ -73,3 +73,6 @@ class TestAutomationAutoTestMode(EditorTestSuite): @pytest.mark.skip(reason="Times out due to dialogs failing to dismiss: LYN-4208") class test_Menus_FileMenuOptions_Work(EditorSharedTest): from .EditorScripts import Menus_FileMenuOptions as test_module + + class test_Sample_Editor_Tests(EditorSharedTest): + from .EditorScripts import Sample_Editor_Tests as test_module \ No newline at end of file From 73891c71b777ed1e8e1402ffdbc7463bff6670a8 Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Sun, 3 Oct 2021 22:49:13 -0700 Subject: [PATCH 011/169] Fix EditorServer connection by ensuring that SendReadyForEntityUpdates is only called after a handshake is finished and the editor has accepted the editorserver's connection. Also allow engine-centric projects to use editor-server by passing in the project-path when launching the editor-server. Also allow devs to set sv_defaultPlayerSpawnAsset from inside the editor and it'll be used by the editor-server Signed-off-by: Gene Walters --- .../Editor/MultiplayerEditorConnection.cpp | 1 - .../MultiplayerEditorSystemComponent.cpp | 8 ++++++- .../Source/MultiplayerSystemComponent.cpp | 22 ++++++++++++++----- .../Code/Source/MultiplayerSystemComponent.h | 2 ++ 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.cpp b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.cpp index 3ca1af8b66..24858e6412 100644 --- a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.cpp +++ b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorConnection.cpp @@ -146,7 +146,6 @@ namespace Multiplayer { // Connect the Editor to the editor server for Multiplayer simulation AZ::Interface::Get()->Connect(remoteAddress.c_str(), remotePort); - AZ::Interface::Get()->SendReadyForEntityUpdates(true); } } } diff --git a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp index 377fb1eb56..d13c6538db 100644 --- a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp @@ -142,8 +142,14 @@ namespace Multiplayer } // Start the configured server if it's available + AZStd::string projectPath(AZ::Utils::GetProjectPath().c_str()); + AZStd::replace(projectPath.begin(), projectPath.end(), AZ::IO::WindowsPathSeparator, AZ::IO::PosixPathSeparator); AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo; - processLaunchInfo.m_commandlineParameters = AZStd::string::format("\"%s\" --editorsv_isDedicated true", serverPath.c_str()); + processLaunchInfo.m_commandlineParameters = AZStd::string::format( + R"("%s" --project-path "%s" --editorsv_isDedicated true --sv_defaultPlayerSpawnAsset "%s")", + serverPath.c_str(), + projectPath.c_str(), + static_cast(sv_defaultPlayerSpawnAsset).c_str()); processLaunchInfo.m_showWindow = true; processLaunchInfo.m_processPriority = AzFramework::ProcessPriority::PROCESSPRIORITY_NORMAL; diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index e66eb8d3a3..9b04cd98d4 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -489,11 +489,23 @@ namespace Multiplayer { m_didHandshake = true; - AZ::CVarFixedString commandString = "sv_map " + packet.GetMap(); - AZ::Interface::Get()->PerformCommand(commandString.c_str()); + // If this is an Editor then we're now accepting the connection to the EditorServer. + // In normal game clients SendReadyForEntityUpdates will be enabled once the appropriate level's root spawnable is loaded, + // but since we're in Editor, we're already in the level. + AZ::ApplicationTypeQuery applicationType; + AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationRequests::QueryApplicationType, applicationType); + if (applicationType.IsEditor()) + { + SendReadyForEntityUpdates(true); + } + else + { + AZ::CVarFixedString commandString = "sv_map " + packet.GetMap(); + AZ::Interface::Get()->PerformCommand(commandString.c_str()); - AZ::CVarFixedString loadLevelString = "LoadLevel " + packet.GetMap(); - AZ::Interface::Get()->PerformCommand(loadLevelString.c_str()); + AZ::CVarFixedString loadLevelString = "LoadLevel " + packet.GetMap(); + AZ::Interface::Get()->PerformCommand(loadLevelString.c_str()); + } return true; } @@ -981,7 +993,7 @@ namespace Multiplayer INetworkEntityManager::EntityList entityList = m_networkEntityManager.CreateEntitiesImmediate(playerPrefabEntityId, NetEntityRole::Authority, AZ::Transform::CreateIdentity(), Multiplayer::AutoActivate::DoNotActivate); NetworkEntityHandle controlledEntity; - if (entityList.size() > 0) + if (!entityList.empty()) { controlledEntity = entityList[0]; } diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h index c467ed9ad9..ba014f814a 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h @@ -37,6 +37,8 @@ namespace AzNetworking namespace Multiplayer { + AZ_CVAR_EXTERNED(AZ::CVarFixedString, sv_defaultPlayerSpawnAsset); + //! Multiplayer system component wraps the bridging logic between the game and transport layer. class MultiplayerSystemComponent final : public AZ::Component From e306321b6150ad51234c12a0b24a752850cce41f Mon Sep 17 00:00:00 2001 From: jckand-amzn Date: Mon, 4 Oct 2021 10:56:16 -0500 Subject: [PATCH 012/169] Removing xfail from optimized Landscape Canvas suite and disabling non-optimized suites Signed-off-by: jckand-amzn --- .../PythonTests/largeworlds/CMakeLists.txt | 26 ------------------- .../TestSuite_Main_Optimized.py | 1 - 2 files changed, 27 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/largeworlds/CMakeLists.txt index f1299ddc2d..59ccdffdca 100644 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/CMakeLists.txt @@ -55,32 +55,6 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED AND PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_ ## LandscapeCanvas ## - ly_add_pytest( - NAME AutomatedTesting::LandscapeCanvasTests_Main - TEST_SERIAL - TEST_SUITE main - PATH ${CMAKE_CURRENT_LIST_DIR}/landscape_canvas/TestSuite_Main.py - RUNTIME_DEPENDENCIES - AZ::AssetProcessor - Legacy::Editor - AutomatedTesting.Assets - COMPONENT - LargeWorlds - ) - - ly_add_pytest( - NAME AutomatedTesting::LandscapeCanvasTests_Periodic - TEST_SERIAL - TEST_SUITE periodic - PATH ${CMAKE_CURRENT_LIST_DIR}/landscape_canvas/TestSuite_Periodic.py - RUNTIME_DEPENDENCIES - AZ::AssetProcessor - Legacy::Editor - AutomatedTesting.Assets - COMPONENT - LargeWorlds - ) - ly_add_pytest( NAME AutomatedTesting::LandscapeCanvasTests_Main_Optimized TEST_SERIAL diff --git a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/TestSuite_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/TestSuite_Main_Optimized.py index 9cc572ad69..0461ff2647 100644 --- a/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/TestSuite_Main_Optimized.py +++ b/AutomatedTesting/Gem/PythonTests/largeworlds/landscape_canvas/TestSuite_Main_Optimized.py @@ -12,7 +12,6 @@ import ly_test_tools.environment.file_system as file_system from ly_test_tools.o3de.editor_test import EditorSingleTest, EditorSharedTest, EditorParallelTest, EditorTestSuite -@pytest.mark.xfail(reason="Optimized tests are experimental, we will enable xfail and monitor them temporarily.") @pytest.mark.SUITE_periodic @pytest.mark.parametrize("launcher_platform", ['windows_editor']) @pytest.mark.parametrize("project", ["AutomatedTesting"]) From 118834efdedb4ebe5290c2de1826ef2e562a5741 Mon Sep 17 00:00:00 2001 From: nggieber Date: Mon, 4 Oct 2021 15:08:13 -0700 Subject: [PATCH 013/169] Added ability to list gem repos using CLI and integrated support into Project Manager Signed-off-by: nggieber --- .../Source/GemRepo/GemRepoInfo.h | 2 +- .../Source/GemRepo/GemRepoItemDelegate.cpp | 3 +- .../Source/GemRepo/GemRepoScreen.cpp | 21 ++ .../Source/ProjectManagerDefs.h | 2 + .../ProjectManager/Source/PythonBindings.cpp | 60 +++++- .../ProjectManager/Source/PythonBindings.h | 2 +- scripts/o3de/o3de/manifest.py | 190 +++++++----------- scripts/o3de/o3de/validation.py | 1 - 8 files changed, 152 insertions(+), 129 deletions(-) diff --git a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoInfo.h b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoInfo.h index 14c76bd0c2..61220cefe7 100644 --- a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoInfo.h +++ b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoInfo.h @@ -30,7 +30,7 @@ namespace O3DE::ProjectManager bool operator<(const GemRepoInfo& gemRepoInfo) const; QString m_path = ""; - QString m_name = "Unknown Gem Repo Name"; + QString m_name = "Unknown Repo Name"; QString m_creator = "Unknown Creator"; bool m_isEnabled = false; //! Is the repo currently enabled for this engine? QString m_summary = "No summary provided."; diff --git a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoItemDelegate.cpp b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoItemDelegate.cpp index 88ccee2636..58b10a1d1a 100644 --- a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoItemDelegate.cpp +++ b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoItemDelegate.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -95,7 +96,7 @@ namespace O3DE::ProjectManager painter->drawText(repoCreatorRect, Qt::TextSingleLine, repoCreator); // Repo update - QString repoUpdatedDate = GemRepoModel::GetLastUpdated(modelIndex).toString("dd/MM/yyyy hh:mmap"); + QString repoUpdatedDate = GemRepoModel::GetLastUpdated(modelIndex).toString(RepoTimeFormat); repoUpdatedDate = standardFontMetrics.elidedText(repoUpdatedDate, Qt::TextElideMode::ElideRight, s_updatedMaxWidth); QRect repoUpdatedDateRect = GetTextRect(standardFont, repoUpdatedDate, s_fontSize); diff --git a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp index 9c432884e6..a233010225 100644 --- a/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemRepo/GemRepoScreen.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -104,9 +105,29 @@ namespace O3DE::ProjectManager { // Add all available repos to the model const QVector allGemRepoInfos = allGemRepoInfosResult.GetValue(); + QDateTime oldestRepoUpdate; + if (!allGemRepoInfos.isEmpty()) + { + oldestRepoUpdate = allGemRepoInfos[0].m_lastUpdated; + } for (const GemRepoInfo& gemRepoInfo : allGemRepoInfos) { m_gemRepoModel->AddGemRepo(gemRepoInfo); + + // Find least recently updated repo + if (gemRepoInfo.m_lastUpdated < oldestRepoUpdate) + { + oldestRepoUpdate = gemRepoInfo.m_lastUpdated; + } + } + + if (!allGemRepoInfos.isEmpty()) + { + m_lastAllUpdateLabel->setText(tr("Last Updated: %1").arg(oldestRepoUpdate.toString(RepoTimeFormat))); + } + else + { + m_lastAllUpdateLabel->setText(tr("Last Updated: Never")); } } else diff --git a/Code/Tools/ProjectManager/Source/ProjectManagerDefs.h b/Code/Tools/ProjectManager/Source/ProjectManagerDefs.h index 264515652f..e8e290ad02 100644 --- a/Code/Tools/ProjectManager/Source/ProjectManagerDefs.h +++ b/Code/Tools/ProjectManager/Source/ProjectManagerDefs.h @@ -26,4 +26,6 @@ namespace O3DE::ProjectManager static const QString ProjectCMakeCommand = "cmake"; static const QString ProjectCMakeBuildTargetEditor = "Editor"; + static const QString RepoTimeFormat = "dd/MM/yyyy hh:mmap"; + } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index b9369b5bb0..96c54d8af2 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -929,13 +929,55 @@ namespace O3DE::ProjectManager return AZ::Failure("Adding Gem Repo not implemented yet in o3de scripts."); } - GemRepoInfo PythonBindings::GemRepoInfoFromPath(pybind11::handle path, pybind11::handle pyEnginePath) + GemRepoInfo PythonBindings::GetGemRepoInfo(pybind11::handle repoUri) { - /* Placeholder Logic */ - (void)path; - (void)pyEnginePath; + GemRepoInfo gemRepoInfo; + gemRepoInfo.m_repoLink = Py_To_String(repoUri); - return GemRepoInfo(); + auto data = m_manifest.attr("get_repo_json_data")(repoUri); + if (pybind11::isinstance(data)) + { + try + { + // required + gemRepoInfo.m_repoLink = Py_To_String(data["repo_uri"]); + gemRepoInfo.m_name = Py_To_String(data["repo_name"]); + gemRepoInfo.m_creator = Py_To_String(data["origin"]); + + // optional + gemRepoInfo.m_summary = Py_To_String_Optional(data, "summary", "No summary provided."); + gemRepoInfo.m_additionalInfo = Py_To_String_Optional(data, "additional_info", ""); + + auto repoPath = m_manifest.attr("get_repo_path")(repoUri); + gemRepoInfo.m_path = gemRepoInfo.m_directoryLink = Py_To_String(repoPath); + + QString lastUpdated = Py_To_String_Optional(data, "last_updated", ""); + gemRepoInfo.m_lastUpdated = QDateTime::fromString(lastUpdated, RepoTimeFormat); + + if (data.contains("enabled")) + { + gemRepoInfo.m_isEnabled = data["enabled"].cast(); + } + else + { + gemRepoInfo.m_isEnabled = false; + } + + if (data.contains("gem_paths")) + { + for (auto gemPath : data["gem_paths"]) + { + gemRepoInfo.m_includedGemPaths.push_back(Py_To_String(gemPath)); + } + } + } + catch ([[maybe_unused]] const std::exception& e) + { + AZ_Warning("PythonBindings", false, "Failed to get GemRepoInfo for repo %s", Py_To_String(repoUri)); + } + } + + return gemRepoInfo; } //#define MOCK_GEM_REPO_INFO true @@ -948,14 +990,10 @@ namespace O3DE::ProjectManager auto result = ExecuteWithLockErrorHandling( [&] { - /* Placeholder Logic, o3de scripts need method added - * - for (auto path : m_manifest.attr("get_gem_repos")()) + for (auto repoUri : m_manifest.attr("get_repos")()) { - gemRepos.push_back(GemRepoInfoFromPath(path, pybind11::none())); + gemRepos.push_back(GetGemRepoInfo(repoUri)); } - * - */ }); if (!result.IsSuccess()) { diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.h b/Code/Tools/ProjectManager/Source/PythonBindings.h index 42f04ed6e6..195915a18f 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.h +++ b/Code/Tools/ProjectManager/Source/PythonBindings.h @@ -66,7 +66,7 @@ namespace O3DE::ProjectManager AZ::Outcome ExecuteWithLockErrorHandling(AZStd::function executionCallback); bool ExecuteWithLock(AZStd::function executionCallback); GemInfo GemInfoFromPath(pybind11::handle path, pybind11::handle pyProjectPath); - GemRepoInfo GemRepoInfoFromPath(pybind11::handle path, pybind11::handle pyEnginePath); + GemRepoInfo GetGemRepoInfo(pybind11::handle repoUri); ProjectInfo ProjectInfoFromPath(pybind11::handle path); ProjectTemplateInfo ProjectTemplateInfoFromPath(pybind11::handle path, pybind11::handle pyProjectPath); bool RegisterThisEngine(); diff --git a/scripts/o3de/o3de/manifest.py b/scripts/o3de/o3de/manifest.py index 7e504d29cd..ccb5cda761 100644 --- a/scripts/o3de/o3de/manifest.py +++ b/scripts/o3de/o3de/manifest.py @@ -13,8 +13,10 @@ import json import logging import os import pathlib +import shutil +import hashlib -from o3de import validation +from o3de import validation, utils logger = logging.getLogger() logging.basicConfig() @@ -135,12 +137,12 @@ def get_o3de_manifest() -> pathlib.Path: json_data.update({'default_restricted_folder': default_restricted_folder.as_posix()}) json_data.update({'default_third_party_folder': default_third_party_folder.as_posix()}) + json_data.update({'engines': []}) json_data.update({'projects': []}) json_data.update({'external_subdirectories': []}) json_data.update({'templates': []}) json_data.update({'restricted': []}) json_data.update({'repos': []}) - json_data.update({'engines': []}) default_restricted_folder_json = default_restricted_folder / 'restricted.json' if not default_restricted_folder_json.is_file(): @@ -195,23 +197,25 @@ def load_o3de_manifest(manifest_path: pathlib.Path = None) -> dict: return json_data -def save_o3de_manifest(json_data: dict, manifest_path: pathlib.Path = None) -> bool: +def save_o3de_manifest(json_data: dict, manifest_path: pathlib.Path = None) -> None: """ - Save the json dictionary to the supplied manifest file or ~/.o3de/o3de_manifest.json if manifest_path is None + Save the json dictionary to the supplied manifest file or ~/.o3de/o3de_manifest.json if None - :param json_data: dictionary to save in json format at the file path - :param manifest_path: optional path to manifest file to save - """ + :param json_data: dictionary to save in json format at the file path + :param manifest_path: optional path to manifest file to save + """ if not manifest_path: manifest_path = get_o3de_manifest() + backup_name = utils.backup_file(manifest_path) with manifest_path.open('w') as s: try: s.write(json.dumps(json_data, indent=4) + '\n') - return True - except OSError as e: + except Exception as e: logger.error(f'Manifest json failed to save: {str(e)}') - return False - + os.unlink(manifest_path) + os.rename(backup_name, manifest_path) + finally: + os.unlink(backup_name) def get_gems_from_subdirectories(external_subdirs: list) -> list: @@ -236,6 +240,12 @@ def get_gems_from_subdirectories(external_subdirs: list) -> list: # Data query methods +def get_this_engine() -> dict: + json_data = load_o3de_manifest() + engine_data = find_engine_data(json_data) + return engine_data + + def get_engines() -> list: json_data = load_o3de_manifest() engine_list = json_data['engines'] if 'engines' in json_data else [] @@ -421,6 +431,35 @@ def get_templates_for_generic_creation(): # temporary until we have a better wa return list(filter(filter_project_and_gem_templates_out, get_all_templates())) +def get_json_data(object_typename: str = None, + object_path: str or pathlib.Path = None, + object_validator = callable) -> dict or None: + if not object_typename or not object_validator: + logger.error(f'Missing object info.') + + if not object_path: + logger.error(f'{object_typename} Path {object_path} has not been registered.') + return None + + object_path = pathlib.Path(object_path).resolve() + object_json = object_path / f'{object_typename}.json' + if not object_json.is_file(): + logger.error(f'{object_typename} json {object_json} is not present.') + return None + if not object_validator(object_json): + logger.error(f'{object_typename} json {object_json} is not valid.') + return None + + with object_json.open('r') as f: + try: + object_json_data = json.load(f) + except json.JSONDecodeError as e: + logger.warn(f'{object_json} failed to load: {str(e)}') + else: + return object_json_data + + return None + def get_engine_json_data(engine_name: str = None, engine_path: str or pathlib.Path = None) -> dict or None: @@ -431,28 +470,7 @@ def get_engine_json_data(engine_name: str = None, if engine_name and not engine_path: engine_path = get_registered(engine_name=engine_name) - if not engine_path: - logger.error(f'Engine Path {engine_path} has not been registered.') - return None - - engine_path = pathlib.Path(engine_path).resolve() - engine_json = engine_path / 'engine.json' - if not engine_json.is_file(): - logger.error(f'Engine json {engine_json} is not present.') - return None - if not validation.valid_o3de_engine_json(engine_json): - logger.error(f'Engine json {engine_json} is not valid.') - return None - - with engine_json.open('r') as f: - try: - engine_json_data = json.load(f) - except json.JSONDecodeError as e: - logger.warn(f'{engine_json} failed to load: {str(e)}') - else: - return engine_json_data - - return None + return get_json_data('engine', engine_path, validation.valid_o3de_engine_json) def get_project_json_data(project_name: str = None, @@ -464,28 +482,7 @@ def get_project_json_data(project_name: str = None, if project_name and not project_path: project_path = get_registered(project_name=project_name) - if not project_path: - logger.error(f'Project Path {project_path} has not been registered.') - return None - - project_path = pathlib.Path(project_path).resolve() - project_json = project_path / 'project.json' - if not project_json.is_file(): - logger.error(f'Project json {project_json} is not present.') - return None - if not validation.valid_o3de_project_json(project_json): - logger.error(f'Project json {project_json} is not valid.') - return None - - with project_json.open('r') as f: - try: - project_json_data = json.load(f) - except json.JSONDecodeError as e: - logger.warn(f'{project_json} failed to load: {str(e)}') - else: - return project_json_data - - return None + return get_json_data('project', project_path, validation.valid_o3de_project_json) def get_gem_json_data(gem_name: str = None, gem_path: str or pathlib.Path = None, @@ -497,28 +494,7 @@ def get_gem_json_data(gem_name: str = None, gem_path: str or pathlib.Path = None if gem_name and not gem_path: gem_path = get_registered(gem_name=gem_name, project_path=project_path) - if not gem_path: - logger.error(f'Gem Path {gem_path} has not been registered.') - return None - - gem_path = pathlib.Path(gem_path).resolve() - gem_json = gem_path / 'gem.json' - if not gem_json.is_file(): - logger.error(f'Gem json {gem_json} is not present.') - return None - if not validation.valid_o3de_gem_json(gem_json): - logger.error(f'Gem json {gem_json} is not valid.') - return None - - with gem_json.open('r') as f: - try: - gem_json_data = json.load(f) - except json.JSONDecodeError as e: - logger.warn(f'{gem_json} failed to load: {str(e)}') - else: - return gem_json_data - - return None + return get_json_data('gem', gem_path, validation.valid_o3de_gem_json) def get_template_json_data(template_name: str = None, template_path: str or pathlib.Path = None, @@ -530,28 +506,7 @@ def get_template_json_data(template_name: str = None, template_path: str or path if template_name and not template_path: template_path = get_registered(template_name=template_name, project_path=project_path) - if not template_path: - logger.error(f'Template Path {template_path} has not been registered.') - return None - - template_path = pathlib.Path(template_path).resolve() - template_json = template_path / 'template.json' - if not template_json.is_file(): - logger.error(f'Template json {template_json} is not present.') - return None - if not validation.valid_o3de_template_json(template_json): - logger.error(f'Template json {template_json} is not valid.') - return None - - with template_json.open('r') as f: - try: - template_json_data = json.load(f) - except json.JSONDecodeError as e: - logger.warn(f'{template_json} failed to load: {str(e)}') - else: - return template_json_data - - return None + return get_json_data('template', template_path, validation.valid_o3de_template_json) def get_restricted_json_data(restricted_name: str = None, restricted_path: str or pathlib.Path = None, @@ -563,29 +518,38 @@ def get_restricted_json_data(restricted_name: str = None, restricted_path: str o if restricted_name and not restricted_path: restricted_path = get_registered(restricted_name=restricted_name, project_path=project_path) - if not restricted_path: - logger.error(f'Restricted Path {restricted_path} has not been registered.') + return get_json_data('restricted', restricted_path, validation.valid_o3de_restricted_json) + +def get_repo_json_data(repo_uri: str = None) -> dict or None: + if not repo_uri: + logger.error('Must specify a Repo Uri.') return None - restricted_path = pathlib.Path(restricted_path).resolve() - restricted_json = restricted_path / 'restricted.json' - if not restricted_json.is_file(): - logger.error(f'Restricted json {restricted_json} is not present.') + repo_json = get_repo_path(repo_uri=repo_uri) + + if not repo_json.is_file(): + logger.error(f'Repo json {repo_json} is not present.') return None - if not validation.valid_o3de_restricted_json(restricted_json): - logger.error(f'Restricted json {restricted_json} is not valid.') + if not validation.valid_o3de_repo_json(repo_json): + logger.error(f'Repo json {repo_json} is not valid.') return None - with restricted_json.open('r') as f: + with repo_json.open('r') as f: try: - restricted_json_data = json.load(f) + repo_json_data = json.load(f) except json.JSONDecodeError as e: - logger.warn(f'{restricted_json} failed to load: {str(e)}') + logger.warn(f'{repo_json} failed to load: {str(e)}') else: - return restricted_json_data + return repo_json_data return None +def get_repo_path(repo_uri: str = None, cache_folder: str = None) -> pathlib.Path: + if not cache_folder: + cache_folder = get_o3de_cache_folder() + + repo_sha256 = hashlib.sha256(repo_uri.encode()) + return cache_folder / str(repo_sha256.hexdigest() + '.json') def get_registered(engine_name: str = None, project_name: str = None, @@ -721,9 +685,7 @@ def get_registered(engine_name: str = None, elif isinstance(repo_name, str): cache_folder = get_o3de_cache_folder() for repo_uri in json_data['repos']: - repo_uri = pathlib.Path(repo_uri).resolve() - repo_sha256 = hashlib.sha256(repo_uri.encode()) - cache_file = cache_folder / str(repo_sha256.hexdigest() + '.json') + cache_file = get_repo_path(repo_uri=repo_uri, cache_folder=cache_folder) if cache_file.is_file(): repo = pathlib.Path(cache_file).resolve() with repo.open('r') as f: diff --git a/scripts/o3de/o3de/validation.py b/scripts/o3de/o3de/validation.py index 8fcc0d7e7d..5c683f0667 100644 --- a/scripts/o3de/o3de/validation.py +++ b/scripts/o3de/o3de/validation.py @@ -27,7 +27,6 @@ def valid_o3de_repo_json(file_name: str or pathlib.Path) -> bool: test = json_data['origin'] except (json.JSONDecodeError, KeyError) as e: return False - return True From b7e3a63faea416a22ba8f3a7d13dc22728bfd64a Mon Sep 17 00:00:00 2001 From: kritin Date: Mon, 4 Oct 2021 23:18:31 -0700 Subject: [PATCH 014/169] responded to code reviews Signed-off-by: kritin --- ...flows_ExistingLevel_EntityComponentCRUD.py | 159 ++++++++++++++++++ .../editor/TestSuite_Main_Optimized.py | 3 +- 2 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD.py diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD.py new file mode 100644 index 0000000000..451b3a6714 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD.py @@ -0,0 +1,159 @@ +""" +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 +""" + + +class Tests: + load_level = ( + "Level loaded successfully", + "Failed to load the level" + ) + create_entity = ( + "Parent entity created successfully", + "Failed to create a parent entity" + ) + set_entity_name = ( + "Entity name set successfully", + "Failed to set entity name" + ) + delete_entity = ( + "Parent Entity deleted successfully", + "Failed to delete parent entity" + ) + create_child_entity = ( + "Child entity created successfully", + "Failed to create a child entity" + ) + delete_child_entity = ( + "Child entity deleted successfully", + "Failed to delete child entity" + ) + add_mesh_component = ( + "Mesh component added successfully", + "Failed to add mesh component" + ) + found_component_typeId = ( + "Found component typeId", + "Unable to find component TypeId" + ) + remove_mesh_component = ( + "Mesh component removed successfully", + "Failed to remove mesh component" + ) + + +def BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD(): + """ + Performing basic test in editor + 01. Load exiting level + 02. create parent entity and set name + 03. create child entity and set a name + 04. delete child entity + 05. add mesh component to parent entity + 06. remove mesh component + 07. delete parent entity + Close editor without saving + """ + import os + from editor_python_test_tools.utils import Report + from editor_python_test_tools.utils import TestHelper as helper + import editor_python_test_tools.hydra_editor_utils as hydra + + import azlmbr.math as math + import azlmbr.asset as asset + import azlmbr.bus as bus + import azlmbr.editor as editor + import azlmbr.entity as entity + import azlmbr.legacy.general as general + import azlmbr.object + + def search_entity(entity_to_search, entity_name): + """ + + :param entity_to_search: entity to be searched + :param entity_name: name of the entity used in the set command + :return: True if entity id exists in the entity_list + False if entity id does not exist in the entity_list + """ + entity_list = [] + entity_search_filter = entity.SearchFilter() + entity_search_filter.names = entity_name + entity_list = entity.SearchBus(bus.Broadcast, 'SearchEntities', entity_search_filter) + if entity_list: + if entity_to_search in entity_list: + return True + return False + return False + + # 01. load an existing level + + test_level = 'Simple' + general.open_level_no_prompt(test_level) + Report.result(Tests.load_level, general.get_current_level_name() == test_level) + + # 02. create parent entity and set name + # Delete any exiting entity and Create a new Entity at the root level + search_filter = azlmbr.entity.SearchFilter() + all_entities = entity.SearchBus(azlmbr.bus.Broadcast, "SearchEntities", search_filter) + editor.ToolsApplicationRequestBus(bus.Broadcast, "DeleteEntities", all_entities) + parent_entity = editor.ToolsApplicationRequestBus(bus.Broadcast, "CreateNewEntity", entity.EntityId()) + Report.result(Tests.create_entity, parent_entity.IsValid()) + + # Setting a new name + parent_entity_name = "Parent_1" + editor.EditorEntityAPIBus(bus.Event, 'SetName', parent_entity, parent_entity_name) + Report.result(Tests.set_entity_name, + editor.EditorEntityInfoRequestBus(bus.Event, 'GetName', parent_entity) == parent_entity_name) + + # 03. Create child Entity to above created parent entity and set a name + child_1_entity = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', parent_entity) + Report.result(Tests.create_child_entity, child_1_entity.IsValid()) + child_entity_name = "Child_1" + editor.EditorEntityAPIBus(bus.Event, 'SetName', child_1_entity, child_entity_name) + Report.result(Tests.set_entity_name, + editor.EditorEntityInfoRequestBus(bus.Event, 'GetName', child_1_entity) == child_entity_name) + + # 04. delete_Child_entity + editor.ToolsApplicationRequestBus(bus.Broadcast, 'DeleteEntityById', child_1_entity) + Report.result(Tests.delete_child_entity, search_entity(child_1_entity, "Child_1") == False) + + # 05. add mesh component to parent entity + type_id_list = editor.EditorComponentAPIBus(bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Mesh"], + entity.EntityType().Game) + if type_id_list is not None: + component_outcome = editor.EditorComponentAPIBus(bus.Broadcast, 'AddComponentsOfType', parent_entity, + type_id_list) + Report.result(Tests.add_mesh_component, component_outcome.IsSuccess()) + else: + Report.result(Tests.found_component_typeId, type_id_list is not None) + + # 06. remove mesh component + outcome_get_component = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', parent_entity, + type_id_list[0]) + if outcome_get_component.IsSuccess(): + component_entity_pair = outcome_get_component.GetValue() + editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', [component_entity_pair]) + component_exists = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', parent_entity, + type_id_list[0]) + mesh_test = True + if component_exists: + mesh_test = False + Report.result(Tests.remove_mesh_component, mesh_test) + else: + Report.result(Tests.found_component_typeId, outcome_get_component.IsSuccess()) + + # 7. delete parent entity + editor.ToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'DeleteEntityById', parent_entity) + Report.result(Tests.delete_entity, search_entity(parent_entity, "Parent_1") == False) + + # Close editor without saving + editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'ExitNoPrompt') + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + + Report.start_test(BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD) diff --git a/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main_Optimized.py index 9aef8a8b2c..755f75216b 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main_Optimized.py +++ b/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main_Optimized.py @@ -73,6 +73,7 @@ class TestAutomationAutoTestMode(EditorTestSuite): @pytest.mark.skip(reason="Times out due to dialogs failing to dismiss: LYN-4208") class test_Menus_FileMenuOptions_Work(EditorSharedTest): from .EditorScripts import Menus_FileMenuOptions as test_module + class test_Sample_Editor_Tests(EditorSharedTest): - from .EditorScripts import Sample_Editor_Tests as test_module \ No newline at end of file + from .EditorScripts import BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD as test_module From f1fe2912e45ba6e493ba0fee3e6edd4876ccfc20 Mon Sep 17 00:00:00 2001 From: kritin Date: Tue, 5 Oct 2021 14:54:07 -0700 Subject: [PATCH 015/169] responded to code reviews Signed-off-by: kritin --- ...flows_ExistingLevel_EntityComponentCRUD.py | 80 +++------- .../EditorScripts/Sample_Editor_Tests.py | 143 ------------------ .../editor/TestSuite_Main_Optimized.py | 2 +- 3 files changed, 20 insertions(+), 205 deletions(-) delete mode 100644 AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Sample_Editor_Tests.py diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD.py index 451b3a6714..803b9e9a11 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD.py @@ -53,40 +53,19 @@ def BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD(): 03. create child entity and set a name 04. delete child entity 05. add mesh component to parent entity - 06. remove mesh component 07. delete parent entity Close editor without saving """ import os from editor_python_test_tools.utils import Report - from editor_python_test_tools.utils import TestHelper as helper - import editor_python_test_tools.hydra_editor_utils as hydra + from editor_python_test_tools.editor_entity_utils import EditorEntity - import azlmbr.math as math - import azlmbr.asset as asset import azlmbr.bus as bus import azlmbr.editor as editor import azlmbr.entity as entity import azlmbr.legacy.general as general import azlmbr.object - def search_entity(entity_to_search, entity_name): - """ - - :param entity_to_search: entity to be searched - :param entity_name: name of the entity used in the set command - :return: True if entity id exists in the entity_list - False if entity id does not exist in the entity_list - """ - entity_list = [] - entity_search_filter = entity.SearchFilter() - entity_search_filter.names = entity_name - entity_list = entity.SearchBus(bus.Broadcast, 'SearchEntities', entity_search_filter) - if entity_list: - if entity_to_search in entity_list: - return True - return False - return False # 01. load an existing level @@ -94,60 +73,39 @@ def BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD(): general.open_level_no_prompt(test_level) Report.result(Tests.load_level, general.get_current_level_name() == test_level) + # 02. create parent entity and set name # Delete any exiting entity and Create a new Entity at the root level + search_filter = azlmbr.entity.SearchFilter() all_entities = entity.SearchBus(azlmbr.bus.Broadcast, "SearchEntities", search_filter) editor.ToolsApplicationRequestBus(bus.Broadcast, "DeleteEntities", all_entities) - parent_entity = editor.ToolsApplicationRequestBus(bus.Broadcast, "CreateNewEntity", entity.EntityId()) - Report.result(Tests.create_entity, parent_entity.IsValid()) + parent_entity = EditorEntity.create_editor_entity("Parent_1") + Report.result(Tests.create_entity, parent_entity.exists()) - # Setting a new name - parent_entity_name = "Parent_1" - editor.EditorEntityAPIBus(bus.Event, 'SetName', parent_entity, parent_entity_name) - Report.result(Tests.set_entity_name, - editor.EditorEntityInfoRequestBus(bus.Event, 'GetName', parent_entity) == parent_entity_name) # 03. Create child Entity to above created parent entity and set a name - child_1_entity = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', parent_entity) - Report.result(Tests.create_child_entity, child_1_entity.IsValid()) - child_entity_name = "Child_1" - editor.EditorEntityAPIBus(bus.Event, 'SetName', child_1_entity, child_entity_name) - Report.result(Tests.set_entity_name, - editor.EditorEntityInfoRequestBus(bus.Event, 'GetName', child_1_entity) == child_entity_name) + + child_1_entity = EditorEntity.create_editor_entity("Child_1", parent_entity.id ) + Report.result(Tests.create_child_entity, child_1_entity.exists()) + # 04. delete_Child_entity - editor.ToolsApplicationRequestBus(bus.Broadcast, 'DeleteEntityById', child_1_entity) - Report.result(Tests.delete_child_entity, search_entity(child_1_entity, "Child_1") == False) + + child_1_entity.delete() + Report.result(Tests.delete_child_entity, not child_1_entity.exists()) + # 05. add mesh component to parent entity - type_id_list = editor.EditorComponentAPIBus(bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Mesh"], - entity.EntityType().Game) - if type_id_list is not None: - component_outcome = editor.EditorComponentAPIBus(bus.Broadcast, 'AddComponentsOfType', parent_entity, - type_id_list) - Report.result(Tests.add_mesh_component, component_outcome.IsSuccess()) - else: - Report.result(Tests.found_component_typeId, type_id_list is not None) - # 06. remove mesh component - outcome_get_component = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', parent_entity, - type_id_list[0]) - if outcome_get_component.IsSuccess(): - component_entity_pair = outcome_get_component.GetValue() - editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', [component_entity_pair]) - component_exists = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', parent_entity, - type_id_list[0]) - mesh_test = True - if component_exists: - mesh_test = False - Report.result(Tests.remove_mesh_component, mesh_test) - else: - Report.result(Tests.found_component_typeId, outcome_get_component.IsSuccess()) + parent_entity.add_component("Mesh") + Report.result(Tests.add_mesh_component, parent_entity.has_component("Mesh")) + # 7. delete parent entity - editor.ToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'DeleteEntityById', parent_entity) - Report.result(Tests.delete_entity, search_entity(parent_entity, "Parent_1") == False) + + parent_entity.delete() + Report.result(Tests.delete_entity, not parent_entity.exists()) # Close editor without saving editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'ExitNoPrompt') diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Sample_Editor_Tests.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Sample_Editor_Tests.py deleted file mode 100644 index 746c0a936d..0000000000 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/Sample_Editor_Tests.py +++ /dev/null @@ -1,143 +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 - -Test Case: Creating tests for basic editor feature like creating a level, adding new entities, modifying the entities etc. -""" - - -class Tests: - create_level = ("Level created and loaded successfully", "Failed to create the level") - open_level = ("Level loaded successfully", "Failed to load the level") - create_entity = ("Parent entity created successfully", "Failed to create a parent entity") - set_entity_name = ("Entity name set successfully", "Failed to set entity name") - delete_entity = ("Parent entity deleted successfully", "Failed to delete parent entity") - game_mode_enter = ("Game Mode entered successfully", "Failed to enter the game mode") - game_mode_exit = ("Game mode exited successfully", "Failed to exit game mode") - create_child_entity = ("Child entity created successfully", "Failed to create a child entity") - delete_child_entity = ("Child entity deleted successfully", "Failed to delete child entity") - add_mesh_component = ("Mesh component added successfully", "Failed to add mesh component") - found_component_typeId = ("Found component typeId", "Unable to find component TypeId") - remove_mesh_component = ("Mesh component removed successfully", "Failed to remove mesh component") - - -def sample_editor_tests(): - """ - Performing basic test in editor - 01. create_level if it does not exist else 02. open exiting level - - 03. create parent entity and set name - 04. create child entity - 05. delete child entity - 06. add mesh component - 07. remove mesh component - 08. enter game mode - 09. exit game_mode - 10. delete parent entity - 11. save level - - """ - import os - from editor_python_test_tools.utils import Report - from editor_python_test_tools.utils import TestHelper as helper - import editor_python_test_tools.hydra_editor_utils as hydra - - import azlmbr.math as math - import azlmbr.asset as asset - import azlmbr.bus as bus - import azlmbr.editor as editor - import azlmbr.entity as entity - import azlmbr.legacy.general as general - import azlmbr.object - - def search_entity(entity_to_search, entity_name): - """ - - :param entity_to_search: entity to be searched - :param entity_name: name of the entity used in the set command - :return: True if entity id exists in the entity_list - False if entity id does not exist in the entity_list - """ - entity_list = [] - entity_search_filter = entity.SearchFilter() - entity_search_filter.names = entity_name - entity_list = entity.SearchBus(bus.Broadcast, 'SearchEntities', entity_search_filter) - if entity_list: - if entity_to_search in entity_list: - return True - return False - return False - - # 01. create_level - - test_level = 'Simple' - general.open_level_no_prompt(test_level) - Report.result(Tests.create_level, general.get_current_level_name() == test_level) - - # 02. load existing level - skipping this since this could alter existing level that other test depends on - - # 03. create_entity and set name - # Delete any exiting entity and Create a new Entity at the root level - search_filter = azlmbr.entity.SearchFilter() - all_entities = entity.SearchBus(azlmbr.bus.Broadcast, "SearchEntities", search_filter) - editor.ToolsApplicationRequestBus(bus.Broadcast, "DeleteEntities", all_entities) - parent_entity = editor.ToolsApplicationRequestBus(bus.Broadcast, "CreateNewEntity", entity.EntityId()) - Report.result(Tests.create_entity, parent_entity.IsValid()) - - # Setting a new name - parent_entity_name = "Parent_1" - editor.EditorEntityAPIBus(bus.Event, 'SetName', parent_entity, parent_entity_name) - Report.result(Tests.set_entity_name, - editor.EditorEntityInfoRequestBus(bus.Event, 'GetName', parent_entity) == parent_entity_name) - - # 04. Creating child Entity and setting name to above created parent entity - child_1_entity = editor.ToolsApplicationRequestBus(bus.Broadcast, 'CreateNewEntity', parent_entity) - Report.result(Tests.create_child_entity, child_1_entity.IsValid()) - child_entity_name = "Child_1" - editor.EditorEntityAPIBus(bus.Event, 'SetName', child_1_entity, child_entity_name) - Report.result(Tests.set_entity_name, - editor.EditorEntityInfoRequestBus(bus.Event, 'GetName', child_1_entity) == child_entity_name) - - # 05. delete_Child_entity - editor.ToolsApplicationRequestBus(bus.Broadcast, 'DeleteEntityById', child_1_entity) - Report.result(Tests.delete_entity, search_entity(child_1_entity, "Child_1") == False) - - # 06. add mesh component to parent entity - type_id_list = editor.EditorComponentAPIBus(bus.Broadcast, 'FindComponentTypeIdsByEntityType', ["Mesh"], - entity.EntityType().Game) - if type_id_list is not None: - component_outcome = editor.EditorComponentAPIBus(bus.Broadcast, 'AddComponentsOfType', parent_entity, - type_id_list) - Report.result(Tests.add_mesh_component, component_outcome.IsSuccess()) - else: - Report.result(Tests.found_component_typeId, type_id_list is not None) - - # 09. remove mesh component - outcome_get_component = editor.EditorComponentAPIBus(bus.Broadcast, 'GetComponentOfType', parent_entity, - type_id_list[0]) - if outcome_get_component.IsSuccess(): - component_entity_pair = outcome_get_component.GetValue() - editor.EditorComponentAPIBus(bus.Broadcast, 'RemoveComponents', [component_entity_pair]) - component_exists = editor.EditorComponentAPIBus(bus.Broadcast, 'HasComponentOfType', parent_entity, - type_id_list[0]) - mesh_test = True - if component_exists: - mesh_test = False - Report.result(Tests.remove_mesh_component, mesh_test) - else: - Report.result(Tests.found_component_typeId, outcome_get_component.IsSuccess()) - - # 10. delete parent entity - editor.ToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'DeleteEntityById', parent_entity) - Report.result(Tests.delete_entity, search_entity(parent_entity, "Parent_1") == False) - - # Close editor without saving - editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'ExitNoPrompt') - - -if __name__ == "__main__": - from editor_python_test_tools.utils import Report - - Report.start_test(sample_editor_tests) diff --git a/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main_Optimized.py index 755f75216b..afc52f962d 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main_Optimized.py +++ b/AutomatedTesting/Gem/PythonTests/editor/TestSuite_Main_Optimized.py @@ -75,5 +75,5 @@ class TestAutomationAutoTestMode(EditorTestSuite): from .EditorScripts import Menus_FileMenuOptions as test_module - class test_Sample_Editor_Tests(EditorSharedTest): + class test_BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD(EditorSharedTest): from .EditorScripts import BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD as test_module From be166d68b8313397c8c79a36630f4f84bdc255d7 Mon Sep 17 00:00:00 2001 From: rgba16f <82187279+rgba16f@users.noreply.github.com> Date: Wed, 29 Sep 2021 16:16:29 -0500 Subject: [PATCH 016/169] Reduce the default worker thread priority for the Job system, Job system is now aimed at long running or idle tasks Add cvars to control the number of worker threads created by the TaskGraph and Job systems. The cvars are scales on the hw concurrency of the cpu. Signed-off-by: rgba16f <82187279+rgba16f@users.noreply.github.com> --- .../Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp | 9 +++++++-- Code/Framework/AzCore/AzCore/Jobs/JobManagerDesc.h | 2 +- Code/Framework/AzCore/AzCore/Task/TaskExecutor.cpp | 4 ++-- .../AzCore/AzCore/Task/TaskGraphSystemComponent.cpp | 8 ++++++-- .../AzCore/std/parallel/internal/thread_UnixLike.cpp | 4 ++++ 5 files changed, 20 insertions(+), 7 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp b/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp index 25dfc7a493..2cd740bf9e 100644 --- a/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp @@ -18,6 +18,11 @@ #include #include +#include + +AZ_CVAR(uint32_t, cl_numeratorJobThreads, 1, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system multiplier on the number of hw threads the machine supports to create at initialization"); +AZ_CVAR(uint32_t, cl_denominatorJobThreads, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system divisor on the number of hw threads the machine supports to create at initialization"); + namespace AZ { //========================================================================= @@ -46,9 +51,9 @@ namespace AZ JobManagerThreadDesc threadDesc; int numberOfWorkerThreads = m_numberOfWorkerThreads; - if (numberOfWorkerThreads <= 0) + if (numberOfWorkerThreads <= 0) // spawn default number of threads { - numberOfWorkerThreads = AZ::GetMin(static_cast(desc.m_workerThreads.capacity()), AZStd::thread::hardware_concurrency()); + numberOfWorkerThreads = AZ::GetMin(static_cast(desc.m_workerThreads.capacity()), cl_numeratorJobThreads * AZStd::thread::hardware_concurrency() / cl_denominatorJobThreads); #if (AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS) numberOfWorkerThreads = AZ::GetMin(numberOfWorkerThreads, AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS); #endif // (AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS) diff --git a/Code/Framework/AzCore/AzCore/Jobs/JobManagerDesc.h b/Code/Framework/AzCore/AzCore/Jobs/JobManagerDesc.h index 5594d7aa15..94f84f27b3 100644 --- a/Code/Framework/AzCore/AzCore/Jobs/JobManagerDesc.h +++ b/Code/Framework/AzCore/AzCore/Jobs/JobManagerDesc.h @@ -36,7 +36,7 @@ namespace AZ */ int m_stackSize; - JobManagerThreadDesc(int cpuId = -1, int priority = -100000, int stackSize = -1) + JobManagerThreadDesc(int cpuId = -1, int priority = 0, int stackSize = -1) : m_cpuId(cpuId) , m_priority(priority) , m_stackSize(stackSize) diff --git a/Code/Framework/AzCore/AzCore/Task/TaskExecutor.cpp b/Code/Framework/AzCore/AzCore/Task/TaskExecutor.cpp index 7da04d7301..4097348798 100644 --- a/Code/Framework/AzCore/AzCore/Task/TaskExecutor.cpp +++ b/Code/Framework/AzCore/AzCore/Task/TaskExecutor.cpp @@ -308,11 +308,11 @@ namespace AZ void TaskExecutor::SetInstance(TaskExecutor* executor) { - if (!executor) + if (!executor) // allow unsetting the executor { s_executor.Reset(); } - else if (!s_executor) // ignore any calls to set after the first (this happens in unit tests that create new system entities) + else if (!s_executor) // ignore any extra executors after the first (this happens during unit tests) { s_executor = AZ::Environment::CreateVariable(s_executorName, executor); } diff --git a/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp index eed461ecb4..198969dbce 100644 --- a/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp @@ -14,6 +14,9 @@ // Create a cvar as a central location for experimentation with switching from the Job system to TaskGraph system. AZ_CVAR(bool, cl_activateTaskGraph, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Flag clients of TaskGraph to switch between jobs/taskgraph (Note does not disable task graph system)"); +AZ_CVAR(uint32_t, cl_numeratorTaskGraphThreads, 3, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph multiplier on the number of hw threads the machine supports to create at initialization"); +AZ_CVAR(uint32_t, cl_denominatorTaskGraphThreads, 4, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph divisor on the number of hw threads the machine supports to create at initialization"); + static constexpr uint32_t TaskExecutorServiceCrc = AZ_CRC_CE("TaskExecutorService"); namespace AZ @@ -24,9 +27,10 @@ namespace AZ if (Interface::Get() == nullptr) { - Interface::Register(this); - m_taskExecutor = aznew TaskExecutor(); + uint32_t numThreads = cl_numeratorTaskGraphThreads * AZStd::thread::hardware_concurrency() / cl_denominatorTaskGraphThreads; + m_taskExecutor = aznew TaskExecutor(numThreads); TaskExecutor::SetInstance(m_taskExecutor); + Interface::Register(this); } } diff --git a/Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/std/parallel/internal/thread_UnixLike.cpp b/Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/std/parallel/internal/thread_UnixLike.cpp index 079f167408..b615f677f1 100644 --- a/Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/std/parallel/internal/thread_UnixLike.cpp +++ b/Code/Framework/AzCore/Platform/Common/UnixLike/AzCore/std/parallel/internal/thread_UnixLike.cpp @@ -59,6 +59,10 @@ namespace AZStd { priority = desc->m_priority; } + else + { + priority = SCHED_OTHER; + } if (desc->m_name) { name = desc->m_name; From 5308a0fbbb729c0355a4abee490cc5d4551d0cb7 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 6 Oct 2021 11:57:42 +0100 Subject: [PATCH 017/169] Remove redundant editor mode notifications. Signed-off-by: John --- Code/Editor/Core/LevelEditorMenuHandler.cpp | 48 ++++++++------ Code/Editor/Core/LevelEditorMenuHandler.h | 12 ++-- Code/Editor/Objects/ObjectManager.cpp | 37 ++++++----- Code/Editor/Objects/ObjectManager.h | 13 ++-- .../UI/Outliner/OutlinerWidget.cpp | 22 ++++--- .../UI/Outliner/OutlinerWidget.hxx | 12 ++-- Code/Editor/QtViewPaneManager.cpp | 59 ++++++++++++++--- Code/Editor/QtViewPaneManager.h | 8 +-- .../API/ComponentModeCollectionInterface.h | 28 +++++++++ ...ewportEditorModeTrackerNotificationBus.cpp | 27 ++++++++ ...ViewportEditorModeTrackerNotificationBus.h | 5 ++ .../ComponentMode/ComponentModeCollection.cpp | 20 ++---- .../ComponentMode/ComponentModeCollection.h | 5 ++ .../ComponentMode/ComponentModeDelegate.cpp | 16 +---- .../ComponentMode/EditorComponentModeBus.h | 42 ------------- .../UI/Outliner/EntityOutlinerWidget.cpp | 22 ++++--- .../UI/Outliner/EntityOutlinerWidget.hxx | 12 ++-- .../UI/PropertyEditor/ComponentEditor.hxx | 1 - .../PropertyEditor/EntityPropertyEditor.cpp | 63 ++++++++++++------- .../PropertyEditor/EntityPropertyEditor.hxx | 13 +++- .../UnitTest/AzToolsFrameworkTestHelpers.cpp | 20 ++++-- .../UnitTest/AzToolsFrameworkTestHelpers.h | 12 ++-- .../EditorDefaultSelection.cpp | 9 +++ .../EditorTransformComponentSelection.cpp | 32 ++++++---- .../EditorTransformComponentSelection.h | 10 +-- .../aztoolsframework_files.cmake | 2 + 26 files changed, 345 insertions(+), 205 deletions(-) create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/API/ComponentModeCollectionInterface.h create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.cpp diff --git a/Code/Editor/Core/LevelEditorMenuHandler.cpp b/Code/Editor/Core/LevelEditorMenuHandler.cpp index e568f05167..25467756ac 100644 --- a/Code/Editor/Core/LevelEditorMenuHandler.cpp +++ b/Code/Editor/Core/LevelEditorMenuHandler.cpp @@ -32,6 +32,7 @@ #include // AzToolsFramework +#include #include // AzQtComponents @@ -166,15 +167,14 @@ LevelEditorMenuHandler::LevelEditorMenuHandler(MainWindow* mainWindow, QtViewPan m_mainWindow->menuBar()->setNativeMenuBar(true); #endif - ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect( - AzToolsFramework::GetEntityContextId()); + ViewportEditorModeNotificationsBus::Handler::BusConnect(GetEntityContextId()); EditorMenuRequestBus::Handler::BusConnect(); } LevelEditorMenuHandler::~LevelEditorMenuHandler() { EditorMenuRequestBus::Handler::BusDisconnect(); - ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect(); + ViewportEditorModeNotificationsBus::Handler::BusDisconnect(); } void LevelEditorMenuHandler::Initialize() @@ -1186,30 +1186,38 @@ void LevelEditorMenuHandler::AddDisableActionInSimModeListener(QAction* action) })); } -void LevelEditorMenuHandler::EnteredComponentMode(const AZStd::vector& /*componentModeTypes*/) +void LevelEditorMenuHandler::OnEditorModeActivated( + [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) { - auto menuWrapper = m_actionManager->FindMenu(s_editMenuId); - if (!menuWrapper.isNull()) + if (mode == ViewportEditorMode::Component) { - // copy of menu actions - auto actions = menuWrapper.Get()->actions(); - // remove all non-reserved edit menu options - actions.erase( - std::remove_if(actions.begin(), actions.end(), [](QAction* action) - { - return !action->property("Reserved").toBool(); - }), - actions.end()); + auto menuWrapper = m_actionManager->FindMenu(s_editMenuId); + if (!menuWrapper.isNull()) + { + // copy of menu actions + auto actions = menuWrapper.Get()->actions(); + // remove all non-reserved edit menu options + actions.erase( + std::remove_if(actions.begin(), actions.end(), [](QAction* action) + { + return !action->property("Reserved").toBool(); + }), + actions.end()); - // clear and update the menu with new actions - menuWrapper.Get()->clear(); - menuWrapper.Get()->addActions(actions); + // clear and update the menu with new actions + menuWrapper.Get()->clear(); + menuWrapper.Get()->addActions(actions); + } } } -void LevelEditorMenuHandler::LeftComponentMode(const AZStd::vector& /*componentModeTypes*/) +void LevelEditorMenuHandler::OnEditorModeDeactivated( + [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) { - RestoreEditMenuToDefault(); + if (mode == ViewportEditorMode::Component) + { + RestoreEditMenuToDefault(); + } } void LevelEditorMenuHandler::AddEditMenuAction(QAction* action) diff --git a/Code/Editor/Core/LevelEditorMenuHandler.h b/Code/Editor/Core/LevelEditorMenuHandler.h index 5ac8e63786..ff03c7748c 100644 --- a/Code/Editor/Core/LevelEditorMenuHandler.h +++ b/Code/Editor/Core/LevelEditorMenuHandler.h @@ -18,7 +18,7 @@ #include #include "ActionManager.h" #include "QtViewPaneManager.h" -#include +#include #endif class MainWindow; @@ -28,7 +28,7 @@ struct QtViewPane; class LevelEditorMenuHandler : public QObject - , private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler + , private AzToolsFramework::ViewportEditorModeNotificationsBus::Handler , private AzToolsFramework::EditorMenuRequestBus::Handler { Q_OBJECT @@ -88,9 +88,11 @@ private: void AddDisableActionInSimModeListener(QAction* action); - // EditorComponentModeNotificationBus - void EnteredComponentMode(const AZStd::vector& componentModeTypes) override; - void LeftComponentMode(const AZStd::vector& componentModeTypes) override; + // ViewportEditorModeNotificationsBus overrides ... + void OnEditorModeActivated( + const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override; + void OnEditorModeDeactivated( + const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override; // EditorMenuRequestBus void AddEditMenuAction(QAction* action) override; diff --git a/Code/Editor/Objects/ObjectManager.cpp b/Code/Editor/Objects/ObjectManager.cpp index f67cf24553..7057cc5b7b 100644 --- a/Code/Editor/Objects/ObjectManager.cpp +++ b/Code/Editor/Objects/ObjectManager.cpp @@ -30,6 +30,8 @@ #include "Plugins/ComponentEntityEditorPlugin/Objects/ComponentEntityObject.h" #include +#include +#include AZ_CVAR_EXTERNED(bool, ed_visibility_logTiming); @@ -107,14 +109,13 @@ CObjectManager::CObjectManager() m_objectsByName.reserve(1024); LoadRegistry(); - AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect( - AzToolsFramework::GetEntityContextId()); + AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId()); } ////////////////////////////////////////////////////////////////////////// CObjectManager::~CObjectManager() { - AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect(); + AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusDisconnect(); m_bExiting = true; SaveRegistry(); @@ -2306,25 +2307,33 @@ void CObjectManager::SelectObjectInRect(CBaseObject* pObj, CViewport* view, HitC } } -void CObjectManager::EnteredComponentMode(const AZStd::vector& /*componentModeTypes*/) +void CObjectManager::OnEditorModeActivated( + [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) { - // hide current gizmo for entity (translate/rotate/scale) - IGizmoManager* gizmoManager = GetGizmoManager(); - const size_t gizmoCount = static_cast(gizmoManager->GetGizmoCount()); - for (size_t i = 0; i < gizmoCount; ++i) + if (mode == AzToolsFramework::ViewportEditorMode::Component) { - gizmoManager->RemoveGizmo(gizmoManager->GetGizmoByIndex(static_cast(i))); + // hide current gizmo for entity (translate/rotate/scale) + IGizmoManager* gizmoManager = GetGizmoManager(); + const size_t gizmoCount = static_cast(gizmoManager->GetGizmoCount()); + for (size_t i = 0; i < gizmoCount; ++i) + { + gizmoManager->RemoveGizmo(gizmoManager->GetGizmoByIndex(static_cast(i))); + } } } -void CObjectManager::LeftComponentMode(const AZStd::vector& /*componentModeTypes*/) +void CObjectManager::OnEditorModeDeactivated( + [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) { - // show translate/rotate/scale gizmo again - if (IGizmoManager* gizmoManager = GetGizmoManager()) + if (mode == AzToolsFramework::ViewportEditorMode::Component) { - if (CBaseObject* selectedObject = GetIEditor()->GetSelectedObject()) + // show translate/rotate/scale gizmo again + if (IGizmoManager* gizmoManager = GetGizmoManager()) { - gizmoManager->AddGizmo(new CAxisGizmo(selectedObject)); + if (CBaseObject* selectedObject = GetIEditor()->GetSelectedObject()) + { + gizmoManager->AddGizmo(new CAxisGizmo(selectedObject)); + } } } } diff --git a/Code/Editor/Objects/ObjectManager.h b/Code/Editor/Objects/ObjectManager.h index 0ad5d8323e..7fb2342e40 100644 --- a/Code/Editor/Objects/ObjectManager.h +++ b/Code/Editor/Objects/ObjectManager.h @@ -20,8 +20,9 @@ #include "ObjectManagerEventBus.h" #include -#include +#include #include +#include #include // forward declarations. @@ -58,7 +59,7 @@ public: */ class CObjectManager : public IObjectManager - , private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler + , private AzToolsFramework::ViewportEditorModeNotificationsBus::Handler { public: //! Selection functor callback. @@ -329,9 +330,11 @@ private: void FindDisplayableObjects(DisplayContext& dc, bool bDisplay); - // EditorComponentModeNotificationBus - void EnteredComponentMode(const AZStd::vector& componentModeTypes) override; - void LeftComponentMode(const AZStd::vector& componentModeTypes) override; + // ViewportEditorModeNotificationsBus overrides ... + void OnEditorModeActivated( + const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override; + void OnEditorModeDeactivated( + const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override; private: typedef std::map Objects; diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp index 9ed7c4a144..803deb3509 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -267,8 +268,7 @@ OutlinerWidget::OutlinerWidget(QWidget* pParent, Qt::WindowFlags flags) ToolsApplicationEvents::Bus::Handler::BusConnect(); AzToolsFramework::EditorEntityContextNotificationBus::Handler::BusConnect(); AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler::BusConnect(); - AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect( - AzToolsFramework::GetEntityContextId()); + AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId()); AzToolsFramework::EditorEntityInfoNotificationBus::Handler::BusConnect(); AzToolsFramework::EditorWindowUIRequestBus::Handler::BusConnect(); } @@ -276,7 +276,7 @@ OutlinerWidget::OutlinerWidget(QWidget* pParent, Qt::WindowFlags flags) OutlinerWidget::~OutlinerWidget() { AzToolsFramework::EditorWindowUIRequestBus::Handler::BusDisconnect(); - AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect(); + AzToolsFramework::ViewportEditorModeNotificationsBus::Handler::BusDisconnect(); AzToolsFramework::EditorEntityInfoNotificationBus::Handler::BusDisconnect(); AzToolsFramework::EditorPickModeNotificationBus::Handler::BusDisconnect(); EntityHighlightMessages::Bus::Handler::BusDisconnect(); @@ -1335,14 +1335,22 @@ void OutlinerWidget::SetEditorUiEnabled(bool enable) EnableUi(enable); } -void OutlinerWidget::EnteredComponentMode([[maybe_unused]] const AZStd::vector& componentModeTypes) +void OutlinerWidget::OnEditorModeActivated( + [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) { - EnableUi(false); + if (mode == AzToolsFramework::ViewportEditorMode::Component) + { + EnableUi(false); + } } -void OutlinerWidget::LeftComponentMode([[maybe_unused]] const AZStd::vector& componentModeTypes) +void OutlinerWidget::OnEditorModeDeactivated( + [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) { - EnableUi(true); + if (mode == AzToolsFramework::ViewportEditorMode::Component) + { + EnableUi(true); + } } void OutlinerWidget::OnSliceInstantiated(const AZ::Data::AssetId& /*sliceAssetId*/, AZ::SliceComponent::SliceInstanceAddress& sliceAddress, const AzFramework::SliceInstantiationTicket& /*ticket*/) diff --git a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.hxx b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.hxx index b29032a760..364ab05eb7 100644 --- a/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.hxx +++ b/Code/Editor/Plugins/ComponentEntityEditorPlugin/UI/Outliner/OutlinerWidget.hxx @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include @@ -58,7 +58,7 @@ class OutlinerWidget , private AzToolsFramework::EditorEntityContextNotificationBus::Handler , private AzToolsFramework::SliceEditorEntityOwnershipServiceNotificationBus::Handler , private AzToolsFramework::EditorEntityInfoNotificationBus::Handler - , private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler + , private AzToolsFramework::ViewportEditorModeNotificationsBus::Handler , private AzToolsFramework::EditorWindowUIRequestBus::Handler { Q_OBJECT; @@ -105,9 +105,11 @@ private: void OnEntityInfoUpdatedAddChildEnd(AZ::EntityId /*parentId*/, AZ::EntityId /*childId*/) override; void OnEntityInfoUpdatedName(AZ::EntityId entityId, const AZStd::string& /*name*/) override; - // EditorComponentModeNotificationBus - void EnteredComponentMode(const AZStd::vector& componentModeTypes) override; - void LeftComponentMode(const AZStd::vector& componentModeTypes) override; + // ViewportEditorModeNotificationsBus overrides ... + void OnEditorModeActivated( + const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override; + void OnEditorModeDeactivated( + const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override; // EditorWindowUIRequestBus overrides void SetEditorUiEnabled(bool enable) override; diff --git a/Code/Editor/QtViewPaneManager.cpp b/Code/Editor/QtViewPaneManager.cpp index eff3a7331e..0f9fd480ca 100644 --- a/Code/Editor/QtViewPaneManager.cpp +++ b/Code/Editor/QtViewPaneManager.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -44,11 +45,54 @@ #include #include #include - #include #include "ShortcutDispatcher.h" +// Helper for EditorComponentModeNotifications to be used +// as a member instead of inheriting from EBus directly. +class ViewportEditorModeNotificationsBusImpl + : public AzToolsFramework::ViewportEditorModeNotificationsBus::Handler +{ + public: + /// Set the function to be called when entering ComponentMode. + void SetEnteredComponentModeFunc( + const AZStd::function& enteredComponentModeFunc) + { + m_enteredComponentModeFunc = enteredComponentModeFunc; + } + + /// Set the function to be called when leaving ComponentMode. + void SetLeftComponentModeFunc( + const AZStd::function& leftComponentModeFunc) + { + m_leftComponentModeFunc = leftComponentModeFunc; + } + + private: + // ViewportEditorModeNotificationsBus overrides ... + void OnEditorModeActivated( + const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override + { + if (mode == AzToolsFramework::ViewportEditorMode::Component) + { + m_enteredComponentModeFunc(editorModeState); + } + } + + void OnEditorModeDeactivated( + const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override + { + if (mode == AzToolsFramework::ViewportEditorMode::Component) + { + m_leftComponentModeFunc(editorModeState); + } + } + + AZStd::function m_enteredComponentModeFunc; ///< Function to call when entering ComponentMode. + AZStd::function m_leftComponentModeFunc; ///< Function to call when leaving ComponentMode. +}; + struct ViewLayoutState { QVector viewPanes; @@ -519,16 +563,17 @@ QtViewPaneManager::QtViewPaneManager(QObject* parent) , m_settings(nullptr) , m_restoreInProgress(false) , m_advancedDockManager(nullptr) + , m_componentModeNotifications(AZStd::make_unique()) { qRegisterMetaTypeStreamOperators("ViewLayoutState"); qRegisterMetaTypeStreamOperators >("QVector"); // view pane manager is interested when we enter/exit ComponentMode - m_componentModeNotifications.BusConnect(AzToolsFramework::GetEntityContextId()); + m_componentModeNotifications->BusConnect(AzToolsFramework::GetEntityContextId()); m_windowRequest.BusConnect(); - m_componentModeNotifications.SetEnteredComponentModeFunc( - [this](const AZStd::vector& /*componentModeTypes*/) + m_componentModeNotifications->SetEnteredComponentModeFunc( + [this](const AzToolsFramework::ViewportEditorModesInterface&) { // gray out panels when entering ComponentMode SetDefaultActionsEnabled(false, m_registeredPanes, [](QWidget* widget, bool on) @@ -537,8 +582,8 @@ QtViewPaneManager::QtViewPaneManager(QObject* parent) }); }); - m_componentModeNotifications.SetLeftComponentModeFunc( - [this](const AZStd::vector& /*componentModeTypes*/) + m_componentModeNotifications->SetLeftComponentModeFunc( + [this](const AzToolsFramework::ViewportEditorModesInterface&) { // enable panels again when leaving ComponentMode SetDefaultActionsEnabled(true, m_registeredPanes, [](QWidget* widget, bool on) @@ -563,7 +608,7 @@ QtViewPaneManager::QtViewPaneManager(QObject* parent) QtViewPaneManager::~QtViewPaneManager() { m_windowRequest.BusDisconnect(); - m_componentModeNotifications.BusDisconnect(); + m_componentModeNotifications->BusDisconnect(); } static bool lessThan(const QtViewPane& v1, const QtViewPane& v2) diff --git a/Code/Editor/QtViewPaneManager.h b/Code/Editor/QtViewPaneManager.h index 3ad1cc9cf7..fe568e5438 100644 --- a/Code/Editor/QtViewPaneManager.h +++ b/Code/Editor/QtViewPaneManager.h @@ -17,7 +17,6 @@ #include #include #include -#include #include #include @@ -34,6 +33,7 @@ #endif class QMainWindow; +class ViewportEditorModeNotificationsBusImpl; struct ViewLayoutState; namespace AzQtComponents @@ -245,9 +245,9 @@ private: QPointer m_advancedDockManager; - using EditorComponentModeNotificationBusImpl = AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBusImpl; - EditorComponentModeNotificationBusImpl m_componentModeNotifications; //!< Helper for EditorComponentModeNotificationBus so - //!< QtViewPaneManager does not need to inherit directly from it. */ + AZStd::unique_ptr + m_componentModeNotifications; //!< Helper for EditorComponentModeNotificationBus so + //!< QtViewPaneManager does not need to inherit directly from it. */ using EditorWindowRequestBusImpl = AzToolsFramework::EditorWindowRequestBusImpl; EditorWindowRequestBusImpl m_windowRequest; //!< Helper for EditorWindowRequestBus so diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ComponentModeCollectionInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ComponentModeCollectionInterface.h new file mode 100644 index 0000000000..39cd6bd6a3 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ComponentModeCollectionInterface.h @@ -0,0 +1,28 @@ +/* + * 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 +{ + //! The AZ::Interface for component mode collection queries. + class ComponentModeCollectionInterface + { + public: + AZ_RTTI(ComponentModeCollectionInterface, "{DFAA4450-BBCD-47C0-9B91-FEA2DBD9B152}"); + + virtual ~ComponentModeCollectionInterface() = default; + + //! Retrieves the list of all Component types (usually one). + virtual const AZStd::vector& GetComponentTypes() const = 0; + }; +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.cpp new file mode 100644 index 0000000000..278f9db950 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.cpp @@ -0,0 +1,27 @@ +/* + * 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 +{ + void ViewportEditorModeNotifications::Reflect(AZ::ReflectContext* context) + { + if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) + { + behaviorContext->EBus("ViewportEditorModeNotificationsBus") + ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) + ->Attribute(AZ::Script::Attributes::Category, "Editor") + ->Attribute(AZ::Script::Attributes::Module, "editor") + ->Event("OnEditorModeActivated", &ViewportEditorModeNotifications::OnEditorModeActivated) + ->Event("OnEditorModeDeactivated", &ViewportEditorModeNotifications::OnEditorModeDeactivated) + ; + } + } +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.h index 4fcb891e61..4fb4191d45 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.h @@ -34,6 +34,8 @@ namespace AzToolsFramework class ViewportEditorModesInterface { public: + AZ_RTTI(ViewportEditorModesInterface, "{2421496C-4A46-41C9-8AEF-AE2B6E43E6CF}"); + virtual ~ViewportEditorModesInterface() = default; //! Returns true if the specified editor mode is active, otherwise false. @@ -52,6 +54,9 @@ namespace AzToolsFramework using BusIdType = ViewportEditorModeTrackerInfo::IdType; ////////////////////////////////////////////////////////////////////////// + AZ_RTTI(ViewportEditorModeNotifications, "{9469DE39-6C21-423C-94FA-EF3A9616B14F}", AZ::EBusTraits); + static void Reflect(AZ::ReflectContext* context); + //! Notifies subscribers of the a given viewport to the activation of the specified editor mode. virtual void OnEditorModeActivated([[maybe_unused]] const ViewportEditorModesInterface& editorModeState, [[maybe_unused]] ViewportEditorMode mode) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.cpp index df93e924b8..e816c0ce4c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.cpp @@ -203,6 +203,11 @@ namespace AzToolsFramework } } + const AZStd::vector& ComponentModeCollection::GetComponentTypes() const + { + return m_activeComponentTypes; + } + void ComponentModeCollection::BeginComponentMode() { m_selectedComponentModeIndex = 0; @@ -211,13 +216,6 @@ namespace AzToolsFramework // notify listeners the editor has entered ComponentMode - listeners may // wish to modify state to indicate this (e.g. appearance, functionality etc.) - EditorComponentModeNotificationBus::Event( - GetEntityContextId(), &EditorComponentModeNotifications::EnteredComponentMode, - m_activeComponentTypes); - - // this call to activate the component mode editor state should eventually replace the bus call in - // ComponentModeCollection::BeginComponentMode() to EditorComponentModeNotifications::EnteredComponentMode - // such that all of the notifications for activating/deactivating the different editor modes are in a central location m_viewportEditorModeTracker->ActivateMode({ GetEntityContextId() }, ViewportEditorMode::Component); // enable actions for the first/primary ComponentMode @@ -288,14 +286,6 @@ namespace AzToolsFramework // notify listeners the editor has left ComponentMode - listeners may // wish to modify state to indicate this (e.g. appearance, functionality etc.) - EditorComponentModeNotificationBus::Event( - GetEntityContextId(), - &EditorComponentModeNotifications::LeftComponentMode, - m_activeComponentTypes); - - // this call to deactivate the component mode editor state should eventually replace the bus call in - // ComponentModeCollection::EndComponentMode() to EditorComponentModeNotifications::LeftComponentMode - // such that all of the notifications for activating/deactivating the different editor modes are in a central location m_viewportEditorModeTracker->DeactivateMode({ GetEntityContextId() }, ViewportEditorMode::Component); // clear stored modes and builders for this ComponentMode diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.h index 9e299d2323..fb35ca8971 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include @@ -21,6 +22,7 @@ namespace AzToolsFramework { /// Manages all individual ComponentModes for a single instance of Editor wide ComponentMode. class ComponentModeCollection + : public ComponentModeCollectionInterface { public: AZ_CLASS_ALLOCATOR_DECL @@ -89,6 +91,9 @@ namespace AzToolsFramework /// Called once each time a ComponentMode is added. void PopulateViewportUi(); + // ComponentModeCollectionInterface overrides ... + const AZStd::vector& GetComponentTypes() const override; + private: // Internal helper used by Select[|Prev|Next]ActiveComponentMode bool ActiveComponentModeChanged(const AZ::Uuid& previousComponentType); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeDelegate.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeDelegate.cpp index 325fc3909b..f0baeaea7e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeDelegate.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeDelegate.cpp @@ -24,18 +24,8 @@ namespace AzToolsFramework : public EditorComponentModeNotificationBus::Handler , public AZ::BehaviorEBusHandler { - AZ_EBUS_BEHAVIOR_BINDER(EditorComponentModeNotificationBusHandler, "{AD2F4204-0913-4FC9-9A10-492538F60C70}", AZ::SystemAllocator, - EnteredComponentMode, LeftComponentMode, ActiveComponentModeChanged); - - void EnteredComponentMode(const AZStd::vector& componentTypes) override - { - Call(FN_EnteredComponentMode, componentTypes); - } - - void LeftComponentMode(const AZStd::vector& componentTypes) override - { - Call(FN_LeftComponentMode, componentTypes); - } + AZ_EBUS_BEHAVIOR_BINDER( + EditorComponentModeNotificationBusHandler, "{AD2F4204-0913-4FC9-9A10-492538F60C70}", AZ::SystemAllocator, ActiveComponentModeChanged); void ActiveComponentModeChanged(const AZ::Uuid& componentType) override { @@ -171,8 +161,6 @@ namespace AzToolsFramework ->Attribute(AZ::Script::Attributes::Category, "Editor") ->Attribute(AZ::Script::Attributes::Module, "editor") ->Handler() - ->Event("EnteredComponentMode", &EditorComponentModeNotifications::EnteredComponentMode) - ->Event("LeftComponentMode", &EditorComponentModeNotifications::LeftComponentMode) ->Event("ActiveComponentModeChanged", &EditorComponentModeNotifications::ActiveComponentModeChanged) ; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/EditorComponentModeBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/EditorComponentModeBus.h index 5be535e1ed..67a8291e22 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/EditorComponentModeBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/EditorComponentModeBus.h @@ -238,12 +238,6 @@ namespace AzToolsFramework using BusIdType = AzFramework::EntityContextId; static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; - /// Called when Editor enters ComponentMode - pass the list of all Component types (usually one). - virtual void EnteredComponentMode(const AZStd::vector& componentTypes) = 0; - - /// Called when Editor leaves ComponentMode - pass the list of all Component types (usually one). - virtual void LeftComponentMode(const AZStd::vector& componentTypes) = 0; - /// Called when Tab is pressed to cycle the 'selected' ComponentMode (which shortcuts/actions are active). /// Also called when directly selecting a Component in the EntityOutliner. virtual void ActiveComponentModeChanged(const AZ::Uuid& /*componentType*/) {} @@ -255,42 +249,6 @@ namespace AzToolsFramework /// Type to inherit to implement EditorComponentModeNotifications. using EditorComponentModeNotificationBus = AZ::EBus; - /// Helper for EditorComponentModeNotifications to be used - /// as a member instead of inheriting from EBus directly. - class EditorComponentModeNotificationBusImpl - : public EditorComponentModeNotificationBus::Handler - { - public: - /// Set the function to be called when entering ComponentMode. - void SetEnteredComponentModeFunc( - const AZStd::function&)>& enteredComponentModeFunc) - { - m_enteredComponentModeFunc = enteredComponentModeFunc; - } - - /// Set the function to be called when leaving ComponentMode. - void SetLeftComponentModeFunc( - const AZStd::function&)>& leftComponentModeFunc) - { - m_leftComponentModeFunc = leftComponentModeFunc; - } - - private: - // EditorComponentModeNotificationBus - void EnteredComponentMode(const AZStd::vector& componentModeTypes) override - { - m_enteredComponentModeFunc(componentModeTypes); - } - - void LeftComponentMode(const AZStd::vector& componentModeTypes) override - { - m_leftComponentModeFunc(componentModeTypes); - } - - AZStd::function&)> m_enteredComponentModeFunc; ///< Function to call when entering ComponentMode. - AZStd::function&)> m_leftComponentModeFunc; ///< Function to call when leaving ComponentMode. - }; - /// Helper to answer if the Editor is in ComponentMode or not. inline bool InComponentMode() { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp index 689e5b5dc4..347057d9ba 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -291,8 +292,7 @@ namespace AzToolsFramework EntityOutlinerModelNotificationBus::Handler::BusConnect(); ToolsApplicationEvents::Bus::Handler::BusConnect(); EditorEntityContextNotificationBus::Handler::BusConnect(); - ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect( - GetEntityContextId()); + ViewportEditorModeNotificationsBus::Handler::BusConnect(GetEntityContextId()); EditorEntityInfoNotificationBus::Handler::BusConnect(); Prefab::PrefabPublicNotificationBus::Handler::BusConnect(); EditorWindowUIRequestBus::Handler::BusConnect(); @@ -302,7 +302,7 @@ namespace AzToolsFramework { EditorWindowUIRequestBus::Handler::BusDisconnect(); Prefab::PrefabPublicNotificationBus::Handler::BusDisconnect(); - ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect(); + ViewportEditorModeNotificationsBus::Handler::BusDisconnect(); EditorEntityInfoNotificationBus::Handler::BusDisconnect(); EditorPickModeNotificationBus::Handler::BusDisconnect(); EntityHighlightMessages::Bus::Handler::BusDisconnect(); @@ -1123,14 +1123,22 @@ namespace AzToolsFramework EnableUi(enable); } - void EntityOutlinerWidget::EnteredComponentMode([[maybe_unused]] const AZStd::vector& componentModeTypes) + void EntityOutlinerWidget::OnEditorModeActivated( + [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) { - EnableUi(false); + if (mode == ViewportEditorMode::Component) + { + EnableUi(false); + } } - void EntityOutlinerWidget::LeftComponentMode([[maybe_unused]] const AZStd::vector& componentModeTypes) + void EntityOutlinerWidget::OnEditorModeDeactivated( + [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) { - EnableUi(true); + if (mode == ViewportEditorMode::Component) + { + EnableUi(true); + } } void EntityOutlinerWidget::OnPrefabInstancePropagationBegin() diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx index 78aced3587..dcf23b19c0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.hxx @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -58,7 +58,7 @@ namespace AzToolsFramework , private ToolsApplicationEvents::Bus::Handler , private EditorEntityContextNotificationBus::Handler , private EditorEntityInfoNotificationBus::Handler - , private ComponentModeFramework::EditorComponentModeNotificationBus::Handler + , private ViewportEditorModeNotificationsBus::Handler , private Prefab::PrefabPublicNotificationBus::Handler , private EditorWindowUIRequestBus::Handler { @@ -100,9 +100,11 @@ namespace AzToolsFramework void OnEntityInfoUpdatedAddChildEnd(AZ::EntityId /*parentId*/, AZ::EntityId /*childId*/) override; void OnEntityInfoUpdatedName(AZ::EntityId entityId, const AZStd::string& /*name*/) override; - // EditorComponentModeNotificationBus - void EnteredComponentMode(const AZStd::vector& componentModeTypes) override; - void LeftComponentMode(const AZStd::vector& componentModeTypes) override; + // ViewportEditorModeNotificationsBus overrides ... + void OnEditorModeActivated( + const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override; + void OnEditorModeDeactivated( + const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override; // PrefabPublicNotificationBus void OnPrefabInstancePropagationBegin() override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ComponentEditor.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ComponentEditor.hxx index b2140868da..f450ec7ac9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ComponentEditor.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ComponentEditor.hxx @@ -90,7 +90,6 @@ namespace AzToolsFramework void SetComponentOverridden(const bool overridden); - // Calls match EditorComponentModeNotificationBus - called from EntityPropertyEditor void EnteredComponentMode(const AZStd::vector& componentModeTypes); void LeftComponentMode(const AZStd::vector& componentModeTypes); void ActiveComponentModeChanged(const AZ::Uuid& componentType); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp index 87527502dd..ad62614770 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp @@ -33,6 +33,7 @@ AZ_POP_DISABLE_WARNING #include #include #include +#include #include #include #include @@ -486,8 +487,12 @@ namespace AzToolsFramework , m_isSystemEntityEditor(false) , m_isLevelEntityEditor(isLevelEntityEditor) { + initEntityPropertyEditorResources(); + m_componentModeCollection = AZ::Interface::Get(); + AZ_Assert(m_componentModeCollection, "Could not retrieve component mode collection."); + m_prefabPublicInterface = AZ::Interface::Get(); AZ_Assert(m_prefabPublicInterface != nullptr, "EntityPropertyEditor requires a PrefabPublicInterface instance on Initialize."); @@ -5698,39 +5703,49 @@ namespace AzToolsFramework SaveComponentEditorState(); } - void EntityPropertyEditor::EnteredComponentMode(const AZStd::vector& componentModeTypes) + void EntityPropertyEditor::OnEditorModeActivated( + [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) { - DisableComponentActions(this, m_entityComponentActions); - SetPropertyEditorState(m_gui, false); - m_disabled = true; - - if (!componentModeTypes.empty()) + if (mode == AzToolsFramework::ViewportEditorMode::Component) { - m_componentEditorLastSelectedIndex = GetComponentEditorIndexFromType(componentModeTypes.front()); - } + DisableComponentActions(this, m_entityComponentActions); + SetPropertyEditorState(m_gui, false); + const auto& componentModeTypes = m_componentModeCollection->GetComponentTypes(); + m_disabled = true; + + if (!componentModeTypes.empty()) + { + m_componentEditorLastSelectedIndex = GetComponentEditorIndexFromType(componentModeTypes.front()); + } - for (auto componentEditor : m_componentEditors) - { - componentEditor->EnteredComponentMode(componentModeTypes); - } + for (auto componentEditor : m_componentEditors) + { + componentEditor->EnteredComponentMode(componentModeTypes); + } - // record the selected state after entering component mode - SaveComponentEditorState(); + // record the selected state after entering component mode + SaveComponentEditorState(); + } } - void EntityPropertyEditor::LeftComponentMode(const AZStd::vector& componentModeTypes) + void EntityPropertyEditor::OnEditorModeDeactivated( + [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) { - EnableComponentActions(this, m_entityComponentActions); - SetPropertyEditorState(m_gui, true); - m_disabled = false; - - for (auto componentEditor : m_componentEditors) + if (mode == AzToolsFramework::ViewportEditorMode::Component) { - componentEditor->LeftComponentMode(componentModeTypes); - } + EnableComponentActions(this, m_entityComponentActions); + SetPropertyEditorState(m_gui, true); + const auto& componentModeTypes = m_componentModeCollection->GetComponentTypes(); + m_disabled = false; - // record the selected state after leaving component mode - SaveComponentEditorState(); + for (auto componentEditor : m_componentEditors) + { + componentEditor->LeftComponentMode(componentModeTypes); + } + + // record the selected state after leaving component mode + SaveComponentEditorState(); + } } void EntityPropertyEditor::ActiveComponentModeChanged(const AZ::Uuid& componentType) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx index 83b275b81a..5279cefa9f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.hxx @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -59,6 +60,7 @@ namespace AzToolsFramework { class ComponentEditor; class ComponentPaletteWidget; + class ComponentModeCollectionInterface; struct SourceControlFileInfo; namespace AssetBrowser @@ -108,6 +110,7 @@ namespace AzToolsFramework , public AzToolsFramework::EditorEntityContextNotificationBus::Handler , public AzToolsFramework::EntityPropertyEditorRequestBus::Handler , public AzToolsFramework::PropertyEditorEntityChangeNotificationBus::MultiHandler + , private AzToolsFramework::ViewportEditorModeNotificationsBus::Handler , public EditorInspectorComponentNotificationBus::MultiHandler , private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler , public AZ::EntitySystemBus::Handler @@ -231,10 +234,14 @@ namespace AzToolsFramework ////////////////////////////////////////////////////////////////////////// // EditorComponentModeNotificationBus - void EnteredComponentMode(const AZStd::vector& componentModeTypes) override; - void LeftComponentMode(const AZStd::vector& componentModeTypes) override; void ActiveComponentModeChanged(const AZ::Uuid& componentType) override; + // ViewportEditorModeNotificationsBus overrides ... + void OnEditorModeActivated( + const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override; + void OnEditorModeDeactivated( + const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override; + // EntityPropertEditorRequestBus void GetSelectedAndPinnedEntities(EntityIdList& selectedEntityIds) override; void GetSelectedEntities(EntityIdList& selectedEntityIds) override; @@ -627,6 +634,8 @@ namespace AzToolsFramework float m_moveFadeSecondsRemaining; AZStd::vector m_indexMapOfMovedRow; + AzToolsFramework::ComponentModeCollectionInterface* m_componentModeCollection = nullptr; + // When m_initiatingPropertyChangeNotification is set to true, it means this EntityPropertyEditor is // broadcasting a change to all listeners about a property change for a given entity. This is needed // so that we don't update the values twice for this inspector diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp index 8d30359562..a0d02f47e7 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.cpp @@ -129,7 +129,7 @@ namespace UnitTest using AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus; AzToolsFramework::EditorActionRequestBus::Handler::BusConnect(); - EditorComponentModeNotificationBus::Handler::BusConnect(GetEntityContextId()); + ViewportEditorModeNotificationsBus::Handler::BusConnect(GetEntityContextId()); m_defaultWidget.setFocus(); } @@ -137,18 +137,26 @@ namespace UnitTest { using AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus; - EditorComponentModeNotificationBus::Handler::BusDisconnect(); + ViewportEditorModeNotificationsBus::Handler::BusDisconnect(); AzToolsFramework::EditorActionRequestBus::Handler::BusDisconnect(); } - void TestEditorActions::EnteredComponentMode([[maybe_unused]] const AZStd::vector& componentTypes) + void TestEditorActions::OnEditorModeActivated( + [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) { - m_componentModeWidget.setFocus(); + if (mode == ViewportEditorMode::Component) + { + m_componentModeWidget.setFocus(); + } } - void TestEditorActions::LeftComponentMode([[maybe_unused]] const AZStd::vector& componentTypes) + void TestEditorActions::OnEditorModeDeactivated( + [[maybe_unused]] const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) { - m_defaultWidget.setFocus(); + if (mode == ViewportEditorMode::Component) + { + m_defaultWidget.setFocus(); + } } void TestEditorActions::AddActionViaBus(int id, QAction* action) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h index c4aefecce5..4a7039423c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h @@ -23,9 +23,9 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -103,7 +103,7 @@ namespace UnitTest /// component mode editing. class TestEditorActions : private AzToolsFramework::EditorActionRequestBus::Handler - , private AzToolsFramework::ComponentModeFramework::EditorComponentModeNotificationBus::Handler + , private AzToolsFramework::ViewportEditorModeNotificationsBus::Handler { // EditorActionRequestBus ... void AddActionViaBus(int id, QAction* action) override; @@ -114,9 +114,11 @@ namespace UnitTest void AttachOverride(QWidget* /*object*/) override {} void DetachOverride() override {} - // EditorComponentModeNotificationBus ... - void EnteredComponentMode(const AZStd::vector& componentTypes) override; - void LeftComponentMode(const AZStd::vector& componentTypes) override; + // ViewportEditorModeNotificationsBus overrides ... + void OnEditorModeActivated( + const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override; + void OnEditorModeDeactivated( + const AzToolsFramework::ViewportEditorModesInterface& editorModeState, AzToolsFramework::ViewportEditorMode mode) override; public: void Connect(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp index 1ad0ee8ff3..fafa1b3198 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp @@ -27,6 +27,10 @@ namespace AzToolsFramework , m_viewportEditorModeTracker(viewportEditorModeTracker) , m_componentModeCollection(viewportEditorModeTracker) { + AZ_Assert( + AZ::Interface::Get() == nullptr, "Unexpected registration of component mode collection.") + AZ::Interface::Register(&m_componentModeCollection); + ActionOverrideRequestBus::Handler::BusConnect(GetEntityContextId()); ComponentModeFramework::ComponentModeSystemRequestBus::Handler::BusConnect(); @@ -40,6 +44,11 @@ namespace AzToolsFramework ComponentModeFramework::ComponentModeSystemRequestBus::Handler::BusDisconnect(); ActionOverrideRequestBus::Handler::BusDisconnect(); m_viewportEditorModeTracker->DeactivateMode({ GetEntityContextId() }, ViewportEditorMode::Default); + + AZ_Assert( + AZ::Interface::Get() != nullptr, + "Unexpected unregistration of component mode collection.") + AZ::Interface::Unregister(&m_componentModeCollection); } void EditorDefaultSelection::SetOverridePhantomWidget(QWidget* phantomOverrideWidget) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index ccb72e1d50..4c1fefc622 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -1027,7 +1027,7 @@ namespace AzToolsFramework EditorTransformComponentSelectionRequestBus::Handler::BusConnect(entityContextId); ToolsApplicationNotificationBus::Handler::BusConnect(); Camera::EditorCameraNotificationBus::Handler::BusConnect(); - ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusConnect(entityContextId); + ViewportEditorModeNotificationsBus::Handler::BusConnect(entityContextId); EditorEntityContextNotificationBus::Handler::BusConnect(); EditorEntityVisibilityNotificationBus::Router::BusRouterConnect(); EditorEntityLockComponentNotificationBus::Router::BusRouterConnect(); @@ -1075,7 +1075,7 @@ namespace AzToolsFramework EditorEntityLockComponentNotificationBus::Router::BusRouterDisconnect(); EditorEntityVisibilityNotificationBus::Router::BusRouterDisconnect(); EditorEntityContextNotificationBus::Handler::BusDisconnect(); - ComponentModeFramework::EditorComponentModeNotificationBus::Handler::BusDisconnect(); + ViewportEditorModeNotificationsBus::Handler::BusDisconnect(); Camera::EditorCameraNotificationBus::Handler::BusDisconnect(); ToolsApplicationNotificationBus::Handler::BusDisconnect(); EditorTransformComponentSelectionRequestBus::Handler::BusDisconnect(); @@ -3707,22 +3707,30 @@ namespace AzToolsFramework m_selectedEntityIdsAndManipulatorsDirty = true; } - void EditorTransformComponentSelection::EnteredComponentMode([[maybe_unused]] const AZStd::vector& componentModeTypes) + void EditorTransformComponentSelection::OnEditorModeActivated( + [[maybe_unused]] const ViewportEditorModesInterface& editorModeState, ViewportEditorMode mode) { - SetAllViewportUiVisible(false); + if (mode == ViewportEditorMode::Component) + { + SetAllViewportUiVisible(false); - EditorEntityLockComponentNotificationBus::Router::BusRouterDisconnect(); - EditorEntityVisibilityNotificationBus::Router::BusRouterDisconnect(); - ToolsApplicationNotificationBus::Handler::BusDisconnect(); + EditorEntityLockComponentNotificationBus::Router::BusRouterDisconnect(); + EditorEntityVisibilityNotificationBus::Router::BusRouterDisconnect(); + ToolsApplicationNotificationBus::Handler::BusDisconnect(); + } } - void EditorTransformComponentSelection::LeftComponentMode([[maybe_unused]] const AZStd::vector& componentModeTypes) + void EditorTransformComponentSelection::OnEditorModeDeactivated( + [[maybe_unused]] const ViewportEditorModesInterface& editorModeState, ViewportEditorMode mode) { - SetAllViewportUiVisible(true); + if (mode == ViewportEditorMode::Component) + { + SetAllViewportUiVisible(true); - ToolsApplicationNotificationBus::Handler::BusConnect(); - EditorEntityVisibilityNotificationBus::Router::BusRouterConnect(); - EditorEntityLockComponentNotificationBus::Router::BusRouterConnect(); + ToolsApplicationNotificationBus::Handler::BusConnect(); + EditorEntityVisibilityNotificationBus::Router::BusRouterConnect(); + EditorEntityLockComponentNotificationBus::Router::BusRouterConnect(); + } } void EditorTransformComponentSelection::CreateEntityManipulatorDeselectCommand(ScopedUndoBatch& undoBatch) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h index a0e87d9d6f..1e1cc6d2e1 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -153,7 +153,7 @@ namespace AzToolsFramework , private EditorTransformComponentSelectionRequestBus::Handler , private ToolsApplicationNotificationBus::Handler , private Camera::EditorCameraNotificationBus::Handler - , private ComponentModeFramework::EditorComponentModeNotificationBus::Handler + , private ViewportEditorModeNotificationsBus::Handler , private EditorEntityContextNotificationBus::Handler , private EditorEntityVisibilityNotificationBus::Router , private EditorEntityLockComponentNotificationBus::Router @@ -286,9 +286,9 @@ namespace AzToolsFramework // EditorContextLockComponentNotificationBus overrides ... void OnEntityLockChanged(bool locked) override; - // EditorComponentModeNotificationBus overrides ... - void EnteredComponentMode(const AZStd::vector& componentModeTypes) override; - void LeftComponentMode(const AZStd::vector& componentModeTypes) override; + // ViewportEditorModeNotificationsBus overrides ... + void OnEditorModeActivated(const ViewportEditorModesInterface& editorModeState, ViewportEditorMode mode) override; + void OnEditorModeDeactivated(const ViewportEditorModesInterface& editorModeState, ViewportEditorMode mode) override; // EditorEntityContextNotificationBus overrides ... void OnStartPlayInEditor() override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index f09d4f9b72..74c5db3f5e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -30,12 +30,14 @@ set(FILES API/AssetDatabaseBus.h API/ComponentEntityObjectBus.h API/ComponentEntitySelectionBus.h + API/ComponentModeCollectionInterface.h API/EditorCameraBus.h API/EditorCameraBus.cpp API/EditorAnimationSystemRequestBus.h API/EditorEntityAPI.h API/EditorLevelNotificationBus.h API/ViewportEditorModeTrackerNotificationBus.h + API/ViewportEditorModeTrackerNotificationBus.cpp API/EditorVegetationRequestsBus.h API/EditorPythonConsoleBus.h API/EditorPythonRunnerRequestsBus.h From 317d624f6ca7b6ed867cde5c841d3abea90ab63d Mon Sep 17 00:00:00 2001 From: John Date: Wed, 6 Oct 2021 13:01:49 +0100 Subject: [PATCH 018/169] Minor formatting. Signed-off-by: John --- Code/Editor/QtViewPaneManager.cpp | 4 ++-- .../ViewportSelection/EditorDefaultSelection.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Editor/QtViewPaneManager.cpp b/Code/Editor/QtViewPaneManager.cpp index 0f9fd480ca..1ac4b9cfe3 100644 --- a/Code/Editor/QtViewPaneManager.cpp +++ b/Code/Editor/QtViewPaneManager.cpp @@ -55,14 +55,14 @@ class ViewportEditorModeNotificationsBusImpl : public AzToolsFramework::ViewportEditorModeNotificationsBus::Handler { public: - /// Set the function to be called when entering ComponentMode. + // Set the function to be called when entering ComponentMode. void SetEnteredComponentModeFunc( const AZStd::function& enteredComponentModeFunc) { m_enteredComponentModeFunc = enteredComponentModeFunc; } - /// Set the function to be called when leaving ComponentMode. + // Set the function to be called when leaving ComponentMode. void SetLeftComponentModeFunc( const AZStd::function& leftComponentModeFunc) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp index fafa1b3198..1541d4678e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorDefaultSelection.cpp @@ -29,7 +29,7 @@ namespace AzToolsFramework { AZ_Assert( AZ::Interface::Get() == nullptr, "Unexpected registration of component mode collection.") - AZ::Interface::Register(&m_componentModeCollection); + AZ::Interface::Register(&m_componentModeCollection); ActionOverrideRequestBus::Handler::BusConnect(GetEntityContextId()); ComponentModeFramework::ComponentModeSystemRequestBus::Handler::BusConnect(); From acfbed8a58d37512ef75c1098ed807cd8699444c Mon Sep 17 00:00:00 2001 From: nggieber Date: Wed, 6 Oct 2021 06:32:28 -0700 Subject: [PATCH 019/169] Fix minor PR feedback Signed-off-by: nggieber --- scripts/o3de/o3de/manifest.py | 67 ++++++++++++++++------------------- 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/scripts/o3de/o3de/manifest.py b/scripts/o3de/o3de/manifest.py index ccb5cda761..32bab05de8 100644 --- a/scripts/o3de/o3de/manifest.py +++ b/scripts/o3de/o3de/manifest.py @@ -197,7 +197,7 @@ def load_o3de_manifest(manifest_path: pathlib.Path = None) -> dict: return json_data -def save_o3de_manifest(json_data: dict, manifest_path: pathlib.Path = None) -> None: +def save_o3de_manifest(json_data: dict, manifest_path: pathlib.Path = None) -> bool: """ Save the json dictionary to the supplied manifest file or ~/.o3de/o3de_manifest.json if None @@ -206,16 +206,13 @@ def save_o3de_manifest(json_data: dict, manifest_path: pathlib.Path = None) -> N """ if not manifest_path: manifest_path = get_o3de_manifest() - backup_name = utils.backup_file(manifest_path) with manifest_path.open('w') as s: try: s.write(json.dumps(json_data, indent=4) + '\n') - except Exception as e: + return True + except OSError as e: logger.error(f'Manifest json failed to save: {str(e)}') - os.unlink(manifest_path) - os.rename(backup_name, manifest_path) - finally: - os.unlink(backup_name) + return False def get_gems_from_subdirectories(external_subdirs: list) -> list: @@ -239,13 +236,6 @@ def get_gems_from_subdirectories(external_subdirs: list) -> list: return gem_directories -# Data query methods -def get_this_engine() -> dict: - json_data = load_o3de_manifest() - engine_data = find_engine_data(json_data) - return engine_data - - def get_engines() -> list: json_data = load_o3de_manifest() engine_list = json_data['engines'] if 'engines' in json_data else [] @@ -431,21 +421,32 @@ def get_templates_for_generic_creation(): # temporary until we have a better wa return list(filter(filter_project_and_gem_templates_out, get_all_templates())) -def get_json_data(object_typename: str = None, - object_path: str or pathlib.Path = None, - object_validator = callable) -> dict or None: - if not object_typename or not object_validator: - logger.error(f'Missing object info.') +def get_json_file_path(object_typename: str = None, + object_path: str or pathlib.Path = None) -> pathlib.Path: + if not object_typename: + logger.error(f'Missing object typename.') if not object_path: logger.error(f'{object_typename} Path {object_path} has not been registered.') return None object_path = pathlib.Path(object_path).resolve() - object_json = object_path / f'{object_typename}.json' + return object_path / f'{object_typename}.json' + + +def get_json_data_file(object_typename: str = None, + object_json: str or pathlib.Path = None, + object_validator = callable) -> dict or None: + if not object_typename: + logger.error(f'Missing object typename.') + if not object_json.is_file(): logger.error(f'{object_typename} json {object_json} is not present.') return None + + if not object_validator: + logger.error(f'Missing object validator.') + if not object_validator(object_json): logger.error(f'{object_typename} json {object_json} is not valid.') return None @@ -454,12 +455,19 @@ def get_json_data(object_typename: str = None, try: object_json_data = json.load(f) except json.JSONDecodeError as e: - logger.warn(f'{object_json} failed to load: {str(e)}') + logger.warn(f'{object_json} failed to load: {e}') else: return object_json_data return None +def get_json_data(object_typename: str = None, + object_path: str or pathlib.Path = None, + object_validator = callable) -> dict or None: + object_json = get_json_file_path(object_typename, object_path) + + return get_json_data_file(object_typename, object_json, object_validator) + def get_engine_json_data(engine_name: str = None, engine_path: str or pathlib.Path = None) -> dict or None: @@ -527,22 +535,7 @@ def get_repo_json_data(repo_uri: str = None) -> dict or None: repo_json = get_repo_path(repo_uri=repo_uri) - if not repo_json.is_file(): - logger.error(f'Repo json {repo_json} is not present.') - return None - if not validation.valid_o3de_repo_json(repo_json): - logger.error(f'Repo json {repo_json} is not valid.') - return None - - with repo_json.open('r') as f: - try: - repo_json_data = json.load(f) - except json.JSONDecodeError as e: - logger.warn(f'{repo_json} failed to load: {str(e)}') - else: - return repo_json_data - - return None + get_json_data_file("Repo", repo_json, validation.valid_o3de_repo_json) def get_repo_path(repo_uri: str = None, cache_folder: str = None) -> pathlib.Path: if not cache_folder: From 49dd0d633196f55f0d83113b609dc58054317410 Mon Sep 17 00:00:00 2001 From: rgba16f <82187279+rgba16f@users.noreply.github.com> Date: Wed, 6 Oct 2021 11:06:28 -0500 Subject: [PATCH 020/169] Update with PR feedback. Use direct ratio on hardware concurrency with a set min and an a number excluded for O3DE threads Signed-off-by: rgba16f <82187279+rgba16f@users.noreply.github.com> --- .../AzCore/AzCore/Jobs/JobManagerComponent.cpp | 11 ++++++++--- .../AzCore/Task/TaskGraphSystemComponent.cpp | 15 ++++++++++----- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp b/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp index 2cd740bf9e..e98711049c 100644 --- a/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp @@ -20,8 +20,9 @@ #include -AZ_CVAR(uint32_t, cl_numeratorJobThreads, 1, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system multiplier on the number of hw threads the machine supports to create at initialization"); -AZ_CVAR(uint32_t, cl_denominatorJobThreads, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system divisor on the number of hw threads the machine supports to create at initialization"); +AZ_CVAR(float, cl_jobThreadsConcurrencyRatio, 0.5f, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system multiplier on the number of hw threads the machine creates at initialization"); +AZ_CVAR(uint32_t, cl_jobThreadsNumReserved, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system number of hardware threads that are reserved for O3DE system threads"); +AZ_CVAR(uint32_t, cl_jobThreadsMinNumber, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system minimum number of worker threads to create after scaling the number of hw threads"); namespace AZ { @@ -53,7 +54,11 @@ namespace AZ int numberOfWorkerThreads = m_numberOfWorkerThreads; if (numberOfWorkerThreads <= 0) // spawn default number of threads { - numberOfWorkerThreads = AZ::GetMin(static_cast(desc.m_workerThreads.capacity()), cl_numeratorJobThreads * AZStd::thread::hardware_concurrency() / cl_denominatorJobThreads); + // calc number of job threads = cl_jobThreadsConcurrencyRatio * (number of hardware threads - cl_jobThreadsNumReserved), + // min = cl_jobThreadsMinNumber, + // max = number of hardware threads - cl_jobThreadsNumReserved + uint32_t scaledHardwareThreads = AZ::GetMax( cl_jobThreadsMinNumber, static_cast(AZStd::floor( 0.5f + AZ::GetClamp(cl_jobThreadsConcurrencyRatio, 0.0f, 1.0f) * static_cast(AZStd::thread::hardware_concurrency() - cl_jobThreadsNumReserved)))); + numberOfWorkerThreads = AZ::GetMin(static_cast(desc.m_workerThreads.capacity()), scaledHardwareThreads); #if (AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS) numberOfWorkerThreads = AZ::GetMin(numberOfWorkerThreads, AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS); #endif // (AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS) diff --git a/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp index 198969dbce..6548d9d162 100644 --- a/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp @@ -11,11 +11,13 @@ #include #include #include +#include // Create a cvar as a central location for experimentation with switching from the Job system to TaskGraph system. AZ_CVAR(bool, cl_activateTaskGraph, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Flag clients of TaskGraph to switch between jobs/taskgraph (Note does not disable task graph system)"); -AZ_CVAR(uint32_t, cl_numeratorTaskGraphThreads, 3, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph multiplier on the number of hw threads the machine supports to create at initialization"); -AZ_CVAR(uint32_t, cl_denominatorTaskGraphThreads, 4, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph divisor on the number of hw threads the machine supports to create at initialization"); +AZ_CVAR(float, cl_taskGraphThreadsConcurrencyRatio, 0.75f, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph calculate the number of worker threads to spawn by scaling the number of hw threads, value is clamped between 0.0f and 1.0f"); +AZ_CVAR(uint32_t, cl_taskGraphThreadsNumReserved, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph number of hardware threads that are reserved for O3DE system threads"); +AZ_CVAR(uint32_t, cl_taskGraphThreadsMinNumber, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph minimum number of worker threads to create after scaling the number of hw threads"); static constexpr uint32_t TaskExecutorServiceCrc = AZ_CRC_CE("TaskExecutorService"); @@ -27,10 +29,13 @@ namespace AZ if (Interface::Get() == nullptr) { - uint32_t numThreads = cl_numeratorTaskGraphThreads * AZStd::thread::hardware_concurrency() / cl_denominatorTaskGraphThreads; - m_taskExecutor = aznew TaskExecutor(numThreads); + // calc number of worker threads = cl_taskGraphThreadsConcurrencyRatio * (number of hardware threads - cl_taskGraphThreadsNumReserved), + // min = cl_taskGraphThreadsMinNumber, + // max = number of hardware threads - cl_taskGraphThreadsNumReserved + uint32_t scaledHardwareThreads = AZ::GetMax( cl_taskGraphThreadsMinNumber, static_cast(AZStd::floor( 0.5f + AZ::GetClamp(cl_taskGraphThreadsConcurrencyRatio, 0.0f, 1.0f) * static_cast(AZStd::thread::hardware_concurrency() - cl_taskGraphThreadsNumReserved)))); + m_taskExecutor = aznew TaskExecutor(scaledHardwareThreads); TaskExecutor::SetInstance(m_taskExecutor); - Interface::Register(this); + Interface::Register(this); } } From f009e06cab8f1af7e0c74a24421b97b38955e517 Mon Sep 17 00:00:00 2001 From: kritin Date: Wed, 6 Oct 2021 13:20:48 -0700 Subject: [PATCH 021/169] responding to code reviews Signed-off-by: kritin --- ...flows_ExistingLevel_EntityComponentCRUD.py | 22 +++---------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD.py b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD.py index 803b9e9a11..39cacf9af5 100644 --- a/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD.py +++ b/AutomatedTesting/Gem/PythonTests/editor/EditorScripts/BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD.py @@ -53,10 +53,9 @@ def BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD(): 03. create child entity and set a name 04. delete child entity 05. add mesh component to parent entity - 07. delete parent entity - Close editor without saving + 06. delete parent entity """ - import os + from editor_python_test_tools.utils import Report from editor_python_test_tools.editor_entity_utils import EditorEntity @@ -66,50 +65,35 @@ def BasicEditorWorkflows_ExistingLevel_EntityComponentCRUD(): import azlmbr.legacy.general as general import azlmbr.object - # 01. load an existing level - test_level = 'Simple' general.open_level_no_prompt(test_level) Report.result(Tests.load_level, general.get_current_level_name() == test_level) - # 02. create parent entity and set name # Delete any exiting entity and Create a new Entity at the root level - search_filter = azlmbr.entity.SearchFilter() all_entities = entity.SearchBus(azlmbr.bus.Broadcast, "SearchEntities", search_filter) editor.ToolsApplicationRequestBus(bus.Broadcast, "DeleteEntities", all_entities) parent_entity = EditorEntity.create_editor_entity("Parent_1") Report.result(Tests.create_entity, parent_entity.exists()) - # 03. Create child Entity to above created parent entity and set a name - child_1_entity = EditorEntity.create_editor_entity("Child_1", parent_entity.id ) Report.result(Tests.create_child_entity, child_1_entity.exists()) - # 04. delete_Child_entity - child_1_entity.delete() Report.result(Tests.delete_child_entity, not child_1_entity.exists()) - # 05. add mesh component to parent entity - parent_entity.add_component("Mesh") Report.result(Tests.add_mesh_component, parent_entity.has_component("Mesh")) - - # 7. delete parent entity - + # 06. delete parent entity parent_entity.delete() Report.result(Tests.delete_entity, not parent_entity.exists()) - # Close editor without saving - editor.EditorToolsApplicationRequestBus(bus.Broadcast, 'ExitNoPrompt') - if __name__ == "__main__": from editor_python_test_tools.utils import Report From 029ad32c84117536f04d7b9c12d779df26081171 Mon Sep 17 00:00:00 2001 From: Pip Potter <61438964+lmbr-pip@users.noreply.github.com> Date: Wed, 6 Oct 2021 15:24:21 -0700 Subject: [PATCH 022/169] lyn7131: Ensure AWS credential Cvars are not logged or shown in plain text (#4519) Signed-off-by: rppotter --- .../Private/Credential/AWSCVarCredentialHandler.h | 2 +- .../Source/Credential/AWSCVarCredentialHandler.cpp | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Gems/AWSCore/Code/Include/Private/Credential/AWSCVarCredentialHandler.h b/Gems/AWSCore/Code/Include/Private/Credential/AWSCVarCredentialHandler.h index 542177dcc4..388f8eefd5 100644 --- a/Gems/AWSCore/Code/Include/Private/Credential/AWSCVarCredentialHandler.h +++ b/Gems/AWSCore/Code/Include/Private/Credential/AWSCVarCredentialHandler.h @@ -21,7 +21,7 @@ namespace AWSCore { public: AWSCVarCredentialHandler() = default; - ~AWSCVarCredentialHandler() = default; + ~AWSCVarCredentialHandler() override = default; //! Activate handler and its credentials provider, make sure activation //! invoked after AWSNativeSDK init to avoid memory leak diff --git a/Gems/AWSCore/Code/Source/Credential/AWSCVarCredentialHandler.cpp b/Gems/AWSCore/Code/Source/Credential/AWSCVarCredentialHandler.cpp index 83487f665d..8102efa2f8 100644 --- a/Gems/AWSCore/Code/Source/Credential/AWSCVarCredentialHandler.cpp +++ b/Gems/AWSCore/Code/Source/Credential/AWSCVarCredentialHandler.cpp @@ -5,15 +5,14 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ - #include #include namespace AWSCore { - AZ_CVAR(AZ::CVarFixedString, cl_awsAccessKey, "", nullptr, AZ::ConsoleFunctorFlags::Null, "Override AWS access key"); - AZ_CVAR(AZ::CVarFixedString, cl_awsSecretKey, "", nullptr, AZ::ConsoleFunctorFlags::Null, "Override AWS secret key"); + AZ_CVAR(AZ::CVarFixedString, cl_awsAccessKey, "", nullptr, AZ::ConsoleFunctorFlags::IsInvisible, "Override AWS access key"); + AZ_CVAR(AZ::CVarFixedString, cl_awsSecretKey, "", nullptr, AZ::ConsoleFunctorFlags::IsInvisible, "Override AWS secret key"); static constexpr char AWSCVARCREDENTIALHANDLER_ALLOC_TAG[] = "AWSCVarCredentialHandler"; @@ -36,12 +35,12 @@ namespace AWSCore std::shared_ptr AWSCVarCredentialHandler::GetCredentialsProvider() { - auto accessKey = static_cast(cl_awsAccessKey); - auto secretKey = static_cast(cl_awsSecretKey); + const auto accessKey = static_cast(cl_awsAccessKey); + const auto secretKey = static_cast(cl_awsSecretKey); if (!accessKey.empty() && !secretKey.empty()) { - AZStd::lock_guard credentialsLock{m_credentialMutex}; + AZStd::lock_guard credentialsLock{ m_credentialMutex }; m_cvarCredentialsProvider = Aws::MakeShared( AWSCVARCREDENTIALHANDLER_ALLOC_TAG, accessKey.c_str(), secretKey.c_str()); return m_cvarCredentialsProvider; @@ -52,7 +51,7 @@ namespace AWSCore void AWSCVarCredentialHandler::ResetCredentialsProvider() { // Must reset credential provider after AWSNativeSDKs init or before AWSNativeSDKs shutdown - AZStd::lock_guard credentialsLock{m_credentialMutex}; + AZStd::lock_guard credentialsLock{ m_credentialMutex }; m_cvarCredentialsProvider.reset(); } } // namespace AWSCore From d36041d1b74060b9cd69a74e0d880e3c624791db Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Wed, 6 Oct 2021 15:48:54 -0700 Subject: [PATCH 023/169] Update based on feedback. Adding event to MPSystemComponent for receiving a server acceptance packet. The editor system component subscribes to this event and tells the server we're ready for entity updates Signed-off-by: Gene Walters --- .../Code/Include/Multiplayer/IMultiplayer.h | 5 ++++ .../MultiplayerEditorSystemComponent.cpp | 10 +++++++ .../Editor/MultiplayerEditorSystemComponent.h | 7 +++++ .../Source/MultiplayerSystemComponent.cpp | 27 ++++++++----------- .../Code/Source/MultiplayerSystemComponent.h | 2 ++ 5 files changed, 35 insertions(+), 16 deletions(-) diff --git a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h index e32b6188eb..e32a5bd0f3 100644 --- a/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h +++ b/Gems/Multiplayer/Code/Include/Multiplayer/IMultiplayer.h @@ -44,6 +44,7 @@ namespace Multiplayer using ClientDisconnectedEvent = AZ::Event<>; using ConnectionAcquiredEvent = AZ::Event; + using ServerAcceptanceReceivedEvent = AZ::Event<>; using SessionInitEvent = AZ::Event; using SessionShutdownEvent = AZ::Event; @@ -102,6 +103,10 @@ namespace Multiplayer //! @param handler The ConnectionAcquiredEvent Handler to add virtual void AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler) = 0; + //! Adds a ServerAcceptanceReceived Handler which is invoked when the client receives the accept packet from the server. + //! @param handler The ServerAcceptanceReceived Handler to add + virtual void AddServerAcceptanceReceivedHandler(ServerAcceptanceReceivedEvent::Handler& handler) = 0; + //! Adds a SessionInitEvent Handler which is invoked when a new network session starts. //! @param handler The SessionInitEvent Handler to add virtual void AddSessionInitHandler(SessionInitEvent::Handler& handler) = 0; diff --git a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp index d13c6538db..3a48135bc3 100644 --- a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp @@ -62,6 +62,7 @@ namespace Multiplayer } MultiplayerEditorSystemComponent::MultiplayerEditorSystemComponent() + : m_serverAcceptanceReceivedHandler([this](){OnServerAcceptanceReceived();}) { ; } @@ -70,6 +71,7 @@ namespace Multiplayer { AzFramework::GameEntityContextEventBus::Handler::BusConnect(); AzToolsFramework::EditorEvents::Bus::Handler::BusConnect(); + AZ::Interface::Get()->AddServerAcceptanceReceivedHandler(m_serverAcceptanceReceivedHandler); } void MultiplayerEditorSystemComponent::Deactivate() @@ -245,4 +247,12 @@ namespace Multiplayer void MultiplayerEditorSystemComponent::OnGameEntitiesReset() { } + + void MultiplayerEditorSystemComponent::OnServerAcceptanceReceived() + { + // We're now accepting the connection to the EditorServer. + // In normal game clients SendReadyForEntityUpdates will be enabled once the appropriate level's root spawnable is loaded, + // but since we're in Editor, we're already in the level. + AZ::Interface::Get()->SendReadyForEntityUpdates(true); + } } diff --git a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.h b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.h index 6a9e6a79b6..b1e9335697 100644 --- a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.h @@ -8,6 +8,8 @@ #pragma once +#include "Multiplayer/IMultiplayer.h" + #include #include @@ -45,6 +47,9 @@ namespace Multiplayer MultiplayerEditorSystemComponent(); ~MultiplayerEditorSystemComponent() override = default; + //! Called once the editor receives the server's accept packet + void OnServerAcceptanceReceived(); + //! AZ::Component overrides. //! @{ void Activate() override; @@ -71,5 +76,7 @@ namespace Multiplayer IEditor* m_editor = nullptr; AzFramework::ProcessWatcher* m_serverProcess = nullptr; AzNetworking::ConnectionId m_editorConnId; + + ServerAcceptanceReceivedEvent::Handler m_serverAcceptanceReceivedHandler; }; } diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 9b04cd98d4..d05139cb41 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -489,23 +489,13 @@ namespace Multiplayer { m_didHandshake = true; - // If this is an Editor then we're now accepting the connection to the EditorServer. - // In normal game clients SendReadyForEntityUpdates will be enabled once the appropriate level's root spawnable is loaded, - // but since we're in Editor, we're already in the level. - AZ::ApplicationTypeQuery applicationType; - AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationRequests::QueryApplicationType, applicationType); - if (applicationType.IsEditor()) - { - SendReadyForEntityUpdates(true); - } - else - { - AZ::CVarFixedString commandString = "sv_map " + packet.GetMap(); - AZ::Interface::Get()->PerformCommand(commandString.c_str()); + AZ::CVarFixedString commandString = "sv_map " + packet.GetMap(); + AZ::Interface::Get()->PerformCommand(commandString.c_str()); - AZ::CVarFixedString loadLevelString = "LoadLevel " + packet.GetMap(); - AZ::Interface::Get()->PerformCommand(loadLevelString.c_str()); - } + AZ::CVarFixedString loadLevelString = "LoadLevel " + packet.GetMap(); + AZ::Interface::Get()->PerformCommand(loadLevelString.c_str()); + + m_serverAcceptanceReceivedEvent.Signal(); return true; } @@ -800,6 +790,11 @@ namespace Multiplayer handler.Connect(m_connAcquiredEvent); } + void MultiplayerSystemComponent::AddServerAcceptanceReceivedHandler(ServerAcceptanceReceivedEvent::Handler& handler) + { + handler.Connect(m_serverAcceptanceReceivedEvent); + } + void MultiplayerSystemComponent::AddSessionInitHandler(SessionInitEvent::Handler& handler) { handler.Connect(m_initEvent); diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h index ba014f814a..4a4cdd4265 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h @@ -111,6 +111,7 @@ namespace Multiplayer void AddConnectionAcquiredHandler(ConnectionAcquiredEvent::Handler& handler) override; void AddSessionInitHandler(SessionInitEvent::Handler& handler) override; void AddSessionShutdownHandler(SessionShutdownEvent::Handler& handler) override; + void AddServerAcceptanceReceivedHandler(ServerAcceptanceReceivedEvent::Handler& handler) override; bool StartHosting(uint16_t port, bool isDedicated = true) override; bool Connect(AZStd::string remoteAddress, uint16_t port) override; void Terminate(AzNetworking::DisconnectReason reason) override; @@ -151,6 +152,7 @@ namespace Multiplayer SessionInitEvent m_initEvent; SessionShutdownEvent m_shutdownEvent; ConnectionAcquiredEvent m_connAcquiredEvent; + ServerAcceptanceReceivedEvent m_serverAcceptanceReceivedEvent; ClientDisconnectedEvent m_clientDisconnectedEvent; AZStd::queue m_pendingConnectionTickets; From 50fe8bc04dcc652cb5bec4334d6c740400acfa55 Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Wed, 6 Oct 2021 16:35:21 -0700 Subject: [PATCH 024/169] pass in AZ::Utils::GetProjectPath().c_str() directly since converting projectpath is not needed Signed-off-by: Gene Walters --- .../Code/Source/Editor/MultiplayerEditorSystemComponent.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp index 3a48135bc3..55a05e33a7 100644 --- a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.cpp @@ -144,13 +144,11 @@ namespace Multiplayer } // Start the configured server if it's available - AZStd::string projectPath(AZ::Utils::GetProjectPath().c_str()); - AZStd::replace(projectPath.begin(), projectPath.end(), AZ::IO::WindowsPathSeparator, AZ::IO::PosixPathSeparator); AzFramework::ProcessLauncher::ProcessLaunchInfo processLaunchInfo; processLaunchInfo.m_commandlineParameters = AZStd::string::format( R"("%s" --project-path "%s" --editorsv_isDedicated true --sv_defaultPlayerSpawnAsset "%s")", serverPath.c_str(), - projectPath.c_str(), + AZ::Utils::GetProjectPath().c_str(), static_cast(sv_defaultPlayerSpawnAsset).c_str()); processLaunchInfo.m_showWindow = true; processLaunchInfo.m_processPriority = AzFramework::ProcessPriority::PROCESSPRIORITY_NORMAL; From 7e6d35b046fc640ea95ccec04448510b8c99fb09 Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Wed, 6 Oct 2021 20:11:29 -0700 Subject: [PATCH 025/169] small fix to include using <> Signed-off-by: Gene Walters --- .../Code/Source/Editor/MultiplayerEditorSystemComponent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.h b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.h index b1e9335697..4e4c6b677f 100644 --- a/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/Editor/MultiplayerEditorSystemComponent.h @@ -8,7 +8,7 @@ #pragma once -#include "Multiplayer/IMultiplayer.h" +#include #include From 3f2881ea4688285e8dc4685af2b6947cf68882a5 Mon Sep 17 00:00:00 2001 From: hultonha <82228511+hultonha@users.noreply.github.com> Date: Thu, 7 Oct 2021 10:00:18 +0100 Subject: [PATCH 026/169] Simplify viewport interaction model reset functionality (#4524) * simplify entity reset functionality Signed-off-by: hultonha * remove reference to removed shortcuts Signed-off-by: hultonha --- Code/Editor/Core/LevelEditorMenuHandler.cpp | 2 - .../EditorTransformComponentSelection.cpp | 44 +------------------ ...torTransformComponentSelectionRequestBus.h | 2 - 3 files changed, 2 insertions(+), 46 deletions(-) diff --git a/Code/Editor/Core/LevelEditorMenuHandler.cpp b/Code/Editor/Core/LevelEditorMenuHandler.cpp index e568f05167..b53076361e 100644 --- a/Code/Editor/Core/LevelEditorMenuHandler.cpp +++ b/Code/Editor/Core/LevelEditorMenuHandler.cpp @@ -487,8 +487,6 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe editMenu.AddAction(AzToolsFramework::EditPivot); editMenu.AddAction(AzToolsFramework::EditReset); editMenu.AddAction(AzToolsFramework::EditResetManipulator); - editMenu.AddAction(AzToolsFramework::EditResetLocal); - editMenu.AddAction(AzToolsFramework::EditResetWorld); // Hide Selection editMenu.AddAction(AzToolsFramework::HideSelection); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index ccb72e1d50..dacae038d4 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -103,10 +103,6 @@ namespace AzToolsFramework static const char* const ResetEntityTransformDesc = "Reset transform based on manipulator mode"; static const char* const ResetManipulatorTitle = "Reset Manipulator"; static const char* const ResetManipulatorDesc = "Reset the manipulator to recenter it on the selected entity"; - static const char* const ResetTransformLocalTitle = "Reset Transform (Local)"; - static const char* const ResetTransformLocalDesc = "Reset transform to local space"; - static const char* const ResetTransformWorldTitle = "Reset Transform (World)"; - static const char* const ResetTransformWorldDesc = "Reset transform to world space"; static const char* const EntityBoxSelectUndoRedoDesc = "Box Select Entities"; static const char* const EntityDeselectUndoRedoDesc = "Deselect Entity"; @@ -2424,45 +2420,9 @@ namespace AzToolsFramework AddAction( m_actions, { QKeySequence(Qt::CTRL + Qt::Key_R) }, EditResetManipulator, ResetManipulatorTitle, ResetManipulatorDesc, - AZStd::bind(AZStd::mem_fn(&EditorTransformComponentSelection::DelegateClearManipulatorOverride), this)); - - AddAction( - m_actions, { QKeySequence(Qt::ALT + Qt::Key_R) }, EditResetLocal, ResetTransformLocalTitle, ResetTransformLocalDesc, - [this]() + [this] { - switch (m_mode) - { - case Mode::Rotation: - ResetOrientationForSelectedEntitiesLocal(); - break; - case Mode::Scale: - CopyScaleToSelectedEntitiesIndividualWorld(1.0f); - break; - case Mode::Translation: - // do nothing - break; - } - }); - - AddAction( - m_actions, { QKeySequence(Qt::SHIFT + Qt::Key_R) }, EditResetWorld, ResetTransformWorldTitle, ResetTransformWorldDesc, - [this]() - { - switch (m_mode) - { - case Mode::Rotation: - { - // begin an undo batch so operations inside CopyOrientation... and - // DelegateClear... are grouped into a single undo/redo - ScopedUndoBatch undoBatch{ ResetTransformWorldTitle }; - CopyOrientationToSelectedEntitiesIndividual(AZ::Quaternion::CreateIdentity()); - ClearManipulatorOrientationOverride(); - } - break; - case Mode::Scale: - case Mode::Translation: - break; - } + DelegateClearManipulatorOverride(); }); AddAction( diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h index d0c106a15e..35f5b0ba99 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h @@ -31,8 +31,6 @@ namespace AzToolsFramework constexpr inline AZ::Crc32 EditPivot = AZ_CRC_CE("com.o3de.action.editortransform.editpivot"); constexpr inline AZ::Crc32 EditReset = AZ_CRC_CE("com.o3de.action.editortransform.editreset"); constexpr inline AZ::Crc32 EditResetManipulator = AZ_CRC_CE("com.o3de.action.editortransform.editresetmanipulator"); - constexpr inline AZ::Crc32 EditResetLocal = AZ_CRC_CE("com.o3de.action.editortransform.editresetlocal"); - constexpr inline AZ::Crc32 EditResetWorld = AZ_CRC_CE("com.o3de.action.editortransform.editresetworld"); constexpr inline AZ::Crc32 ViewportUiVisible = AZ_CRC_CE("com.o3de.action.editortransform.viewportuivisible"); //@} From 3d1ec83f78e66e36e931a9ee50508b1397d14dbc Mon Sep 17 00:00:00 2001 From: hultonha <82228511+hultonha@users.noreply.github.com> Date: Thu, 7 Oct 2021 10:01:30 +0100 Subject: [PATCH 027/169] Update naming to CameraInput types (#4527) * rename public facing Pivot cameras to Orbit - previous rename was a mistake Signed-off-by: hultonha * some more comment and naming updates to improve camera documentation Signed-off-by: hultonha --- .../EditorModularViewportCameraComposer.cpp | 76 +++++++++---------- .../EditorModularViewportCameraComposer.h | 16 ++-- .../EditorPreferencesPageViewportCamera.cpp | 52 ++++++------- .../EditorPreferencesPageViewportCamera.h | 10 +-- Code/Editor/EditorViewportSettings.cpp | 50 ++++++------ Code/Editor/EditorViewportSettings.h | 20 ++--- .../AzFramework/Viewport/CameraInput.cpp | 46 +++++------ .../AzFramework/Viewport/CameraInput.h | 73 +++++++++++------- .../AzFramework/Tests/CameraInputTests.cpp | 50 ++++++------ 9 files changed, 204 insertions(+), 189 deletions(-) diff --git a/Code/Editor/EditorModularViewportCameraComposer.cpp b/Code/Editor/EditorModularViewportCameraComposer.cpp index c492010336..ce4a0a2e33 100644 --- a/Code/Editor/EditorModularViewportCameraComposer.cpp +++ b/Code/Editor/EditorModularViewportCameraComposer.cpp @@ -96,7 +96,7 @@ namespace SandboxEditor cameras.AddCamera(m_firstPersonTranslateCamera); cameras.AddCamera(m_firstPersonScrollCamera); cameras.AddCamera(m_firstPersonFocusCamera); - cameras.AddCamera(m_pivotCamera); + cameras.AddCamera(m_orbitCamera); }); return controller; @@ -135,7 +135,7 @@ namespace SandboxEditor m_firstPersonRotateCamera->SetActivationEndedFn(showCursor); m_firstPersonPanCamera = AZStd::make_shared( - SandboxEditor::CameraFreePanChannelId(), AzFramework::LookPan, AzFramework::TranslatePivot); + SandboxEditor::CameraFreePanChannelId(), AzFramework::LookPan, AzFramework::TranslatePivotLook); m_firstPersonPanCamera->m_panSpeedFn = [] { @@ -155,7 +155,7 @@ namespace SandboxEditor const auto translateCameraInputChannelIds = BuildTranslateCameraInputChannelIds(); m_firstPersonTranslateCamera = AZStd::make_shared( - translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslatePivot); + translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslatePivotLook); m_firstPersonTranslateCamera->m_translateSpeedFn = [] { @@ -167,7 +167,7 @@ namespace SandboxEditor return SandboxEditor::CameraBoostMultiplier(); }; - m_firstPersonScrollCamera = AZStd::make_shared(); + m_firstPersonScrollCamera = AZStd::make_shared(); m_firstPersonScrollCamera->m_scrollSpeedFn = [] { @@ -196,82 +196,82 @@ namespace SandboxEditor m_firstPersonFocusCamera->SetPivotFn(pivotFn); - m_pivotCamera = AZStd::make_shared(SandboxEditor::CameraPivotChannelId()); + m_orbitCamera = AZStd::make_shared(SandboxEditor::CameraOrbitChannelId()); - m_pivotCamera->SetPivotFn( + m_orbitCamera->SetPivotFn( [pivotFn]([[maybe_unused]] const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction) { return pivotFn(); }); - m_pivotRotateCamera = AZStd::make_shared(SandboxEditor::CameraPivotLookChannelId()); + m_orbitRotateCamera = AZStd::make_shared(SandboxEditor::CameraOrbitLookChannelId()); - m_pivotRotateCamera->m_rotateSpeedFn = [] + m_orbitRotateCamera->m_rotateSpeedFn = [] { return SandboxEditor::CameraRotateSpeed(); }; - m_pivotRotateCamera->m_invertYawFn = [] + m_orbitRotateCamera->m_invertYawFn = [] { - return SandboxEditor::CameraPivotYawRotationInverted(); + return SandboxEditor::CameraOrbitYawRotationInverted(); }; - m_pivotTranslateCamera = AZStd::make_shared( - translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslateOffset); + m_orbitTranslateCamera = AZStd::make_shared( + translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslateOffsetOrbit); - m_pivotTranslateCamera->m_translateSpeedFn = [] + m_orbitTranslateCamera->m_translateSpeedFn = [] { return SandboxEditor::CameraTranslateSpeed(); }; - m_pivotTranslateCamera->m_boostMultiplierFn = [] + m_orbitTranslateCamera->m_boostMultiplierFn = [] { return SandboxEditor::CameraBoostMultiplier(); }; - m_pivotDollyScrollCamera = AZStd::make_shared(); + m_orbitDollyScrollCamera = AZStd::make_shared(); - m_pivotDollyScrollCamera->m_scrollSpeedFn = [] + m_orbitDollyScrollCamera->m_scrollSpeedFn = [] { return SandboxEditor::CameraScrollSpeed(); }; - m_pivotDollyMoveCamera = AZStd::make_shared(SandboxEditor::CameraPivotDollyChannelId()); + m_orbitDollyMoveCamera = AZStd::make_shared(SandboxEditor::CameraOrbitDollyChannelId()); - m_pivotDollyMoveCamera->m_motionSpeedFn = [] + m_orbitDollyMoveCamera->m_motionSpeedFn = [] { return SandboxEditor::CameraDollyMotionSpeed(); }; - m_pivotPanCamera = AZStd::make_shared( - SandboxEditor::CameraPivotPanChannelId(), AzFramework::LookPan, AzFramework::TranslateOffset); + m_orbitPanCamera = AZStd::make_shared( + SandboxEditor::CameraOrbitPanChannelId(), AzFramework::LookPan, AzFramework::TranslateOffsetOrbit); - m_pivotPanCamera->m_panSpeedFn = [] + m_orbitPanCamera->m_panSpeedFn = [] { return SandboxEditor::CameraPanSpeed(); }; - m_pivotPanCamera->m_invertPanXFn = [] + m_orbitPanCamera->m_invertPanXFn = [] { return SandboxEditor::CameraPanInvertedX(); }; - m_pivotPanCamera->m_invertPanYFn = [] + m_orbitPanCamera->m_invertPanYFn = [] { return SandboxEditor::CameraPanInvertedY(); }; - m_pivotFocusCamera = - AZStd::make_shared(SandboxEditor::CameraFocusChannelId(), AzFramework::FocusPivot); + m_orbitFocusCamera = + AZStd::make_shared(SandboxEditor::CameraFocusChannelId(), AzFramework::FocusOrbit); - m_pivotFocusCamera->SetPivotFn(pivotFn); + m_orbitFocusCamera->SetPivotFn(pivotFn); - m_pivotCamera->m_pivotCameras.AddCamera(m_pivotRotateCamera); - m_pivotCamera->m_pivotCameras.AddCamera(m_pivotTranslateCamera); - m_pivotCamera->m_pivotCameras.AddCamera(m_pivotDollyScrollCamera); - m_pivotCamera->m_pivotCameras.AddCamera(m_pivotDollyMoveCamera); - m_pivotCamera->m_pivotCameras.AddCamera(m_pivotPanCamera); - m_pivotCamera->m_pivotCameras.AddCamera(m_pivotFocusCamera); + m_orbitCamera->m_orbitCameras.AddCamera(m_orbitRotateCamera); + m_orbitCamera->m_orbitCameras.AddCamera(m_orbitTranslateCamera); + m_orbitCamera->m_orbitCameras.AddCamera(m_orbitDollyScrollCamera); + m_orbitCamera->m_orbitCameras.AddCamera(m_orbitDollyMoveCamera); + m_orbitCamera->m_orbitCameras.AddCamera(m_orbitPanCamera); + m_orbitCamera->m_orbitCameras.AddCamera(m_orbitFocusCamera); } void EditorModularViewportCameraComposer::OnEditorModularViewportCameraComposerSettingsChanged() @@ -282,12 +282,12 @@ namespace SandboxEditor m_firstPersonRotateCamera->SetRotateInputChannelId(SandboxEditor::CameraFreeLookChannelId()); m_firstPersonFocusCamera->SetFocusInputChannelId(SandboxEditor::CameraFocusChannelId()); - m_pivotCamera->SetPivotInputChannelId(SandboxEditor::CameraPivotChannelId()); - m_pivotTranslateCamera->SetTranslateCameraInputChannelIds(translateCameraInputChannelIds); - m_pivotPanCamera->SetPanInputChannelId(SandboxEditor::CameraPivotPanChannelId()); - m_pivotRotateCamera->SetRotateInputChannelId(SandboxEditor::CameraPivotLookChannelId()); - m_pivotDollyMoveCamera->SetDollyInputChannelId(SandboxEditor::CameraPivotDollyChannelId()); - m_pivotFocusCamera->SetFocusInputChannelId(SandboxEditor::CameraFocusChannelId()); + m_orbitCamera->SetOrbitInputChannelId(SandboxEditor::CameraOrbitChannelId()); + m_orbitTranslateCamera->SetTranslateCameraInputChannelIds(translateCameraInputChannelIds); + m_orbitPanCamera->SetPanInputChannelId(SandboxEditor::CameraOrbitPanChannelId()); + m_orbitRotateCamera->SetRotateInputChannelId(SandboxEditor::CameraOrbitLookChannelId()); + m_orbitDollyMoveCamera->SetDollyInputChannelId(SandboxEditor::CameraOrbitDollyChannelId()); + m_orbitFocusCamera->SetFocusInputChannelId(SandboxEditor::CameraFocusChannelId()); } void EditorModularViewportCameraComposer::OnViewportViewEntityChanged(const AZ::EntityId& viewEntityId) diff --git a/Code/Editor/EditorModularViewportCameraComposer.h b/Code/Editor/EditorModularViewportCameraComposer.h index 90103dba43..9cfd6f3554 100644 --- a/Code/Editor/EditorModularViewportCameraComposer.h +++ b/Code/Editor/EditorModularViewportCameraComposer.h @@ -41,15 +41,15 @@ namespace SandboxEditor AZStd::shared_ptr m_firstPersonRotateCamera; AZStd::shared_ptr m_firstPersonPanCamera; AZStd::shared_ptr m_firstPersonTranslateCamera; - AZStd::shared_ptr m_firstPersonScrollCamera; + AZStd::shared_ptr m_firstPersonScrollCamera; AZStd::shared_ptr m_firstPersonFocusCamera; - AZStd::shared_ptr m_pivotCamera; - AZStd::shared_ptr m_pivotRotateCamera; - AZStd::shared_ptr m_pivotTranslateCamera; - AZStd::shared_ptr m_pivotDollyScrollCamera; - AZStd::shared_ptr m_pivotDollyMoveCamera; - AZStd::shared_ptr m_pivotPanCamera; - AZStd::shared_ptr m_pivotFocusCamera; + AZStd::shared_ptr m_orbitCamera; + AZStd::shared_ptr m_orbitRotateCamera; + AZStd::shared_ptr m_orbitTranslateCamera; + AZStd::shared_ptr m_orbitDollyScrollCamera; + AZStd::shared_ptr m_orbitDollyMoveCamera; + AZStd::shared_ptr m_orbitPanCamera; + AZStd::shared_ptr m_orbitFocusCamera; AzFramework::ViewportId m_viewportId; }; diff --git a/Code/Editor/EditorPreferencesPageViewportCamera.cpp b/Code/Editor/EditorPreferencesPageViewportCamera.cpp index b632163186..16176bc241 100644 --- a/Code/Editor/EditorPreferencesPageViewportCamera.cpp +++ b/Code/Editor/EditorPreferencesPageViewportCamera.cpp @@ -73,7 +73,7 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial ->Field("TranslateSmoothing", &CameraMovementSettings::m_translateSmoothing) ->Field("TranslateSmoothness", &CameraMovementSettings::m_translateSmoothness) ->Field("CaptureCursorLook", &CameraMovementSettings::m_captureCursorLook) - ->Field("PivotYawRotationInverted", &CameraMovementSettings::m_pivotYawRotationInverted) + ->Field("OrbitYawRotationInverted", &CameraMovementSettings::m_orbitYawRotationInverted) ->Field("PanInvertedX", &CameraMovementSettings::m_panInvertedX) ->Field("PanInvertedY", &CameraMovementSettings::m_panInvertedY); @@ -86,12 +86,12 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial ->Field("TranslateUp", &CameraInputSettings::m_translateUpChannelId) ->Field("TranslateDown", &CameraInputSettings::m_translateDownChannelId) ->Field("Boost", &CameraInputSettings::m_boostChannelId) - ->Field("Pivot", &CameraInputSettings::m_pivotChannelId) + ->Field("Orbit", &CameraInputSettings::m_orbitChannelId) ->Field("FreeLook", &CameraInputSettings::m_freeLookChannelId) ->Field("FreePan", &CameraInputSettings::m_freePanChannelId) - ->Field("PivotLook", &CameraInputSettings::m_pivotLookChannelId) - ->Field("PivotDolly", &CameraInputSettings::m_pivotDollyChannelId) - ->Field("PivotPan", &CameraInputSettings::m_pivotPanChannelId) + ->Field("OrbitLook", &CameraInputSettings::m_orbitLookChannelId) + ->Field("OrbitDolly", &CameraInputSettings::m_orbitDollyChannelId) + ->Field("OrbitPan", &CameraInputSettings::m_orbitPanChannelId) ->Field("Focus", &CameraInputSettings::m_focusChannelId); serialize.Class() @@ -144,8 +144,8 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial ->Attribute(AZ::Edit::Attributes::Min, minValue) ->Attribute(AZ::Edit::Attributes::Visibility, &CameraMovementSettings::TranslateSmoothingVisibility) ->DataElement( - AZ::Edit::UIHandlers::CheckBox, &CameraMovementSettings::m_pivotYawRotationInverted, "Camera Pivot Yaw Inverted", - "Inverted yaw rotation while pivoting") + AZ::Edit::UIHandlers::CheckBox, &CameraMovementSettings::m_orbitYawRotationInverted, "Camera Orbit Yaw Inverted", + "Inverted yaw rotation while orbiting") ->DataElement( AZ::Edit::UIHandlers::CheckBox, &CameraMovementSettings::m_panInvertedX, "Invert Pan X", "Invert direction of pan in local X axis") @@ -186,8 +186,8 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial "Key/button to move the camera more quickly") ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) ->DataElement( - AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_pivotChannelId, "Pivot", - "Key/button to begin the camera pivot behavior") + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_orbitChannelId, "Orbit", + "Key/button to begin the camera orbit behavior") ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) ->DataElement( AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_freeLookChannelId, "Free Look", @@ -197,19 +197,19 @@ void CEditorPreferencesPage_ViewportCamera::Reflect(AZ::SerializeContext& serial AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_freePanChannelId, "Free Pan", "Key/button to begin camera free pan") ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) ->DataElement( - AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_pivotLookChannelId, "Pivot Look", - "Key/button to begin camera pivot look") + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_orbitLookChannelId, "Orbit Look", + "Key/button to begin camera orbit look") ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) ->DataElement( - AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_pivotDollyChannelId, "Pivot Dolly", - "Key/button to begin camera pivot dolly") + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_orbitDollyChannelId, "Orbit Dolly", + "Key/button to begin camera orbit dolly") ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) ->DataElement( - AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_pivotPanChannelId, "Pivot Pan", - "Key/button to begin camera pivot pan") + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_orbitPanChannelId, "Orbit Pan", + "Key/button to begin camera orbit pan") ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames) ->DataElement( - AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_focusChannelId, "Focus", "Key/button to focus camera pivot") + AZ::Edit::UIHandlers::ComboBox, &CameraInputSettings::m_focusChannelId, "Focus", "Key/button to focus camera orbit") ->Attribute(AZ::Edit::Attributes::StringList, &GetEditorInputNames); editContext->Class("Viewport Preferences", "Viewport Preferences") @@ -268,7 +268,7 @@ void CEditorPreferencesPage_ViewportCamera::OnApply() SandboxEditor::SetCameraTranslateSmoothness(m_cameraMovementSettings.m_translateSmoothness); SandboxEditor::SetCameraTranslateSmoothingEnabled(m_cameraMovementSettings.m_translateSmoothing); SandboxEditor::SetCameraCaptureCursorForLook(m_cameraMovementSettings.m_captureCursorLook); - SandboxEditor::SetCameraPivotYawRotationInverted(m_cameraMovementSettings.m_pivotYawRotationInverted); + SandboxEditor::SetCameraOrbitYawRotationInverted(m_cameraMovementSettings.m_orbitYawRotationInverted); SandboxEditor::SetCameraPanInvertedX(m_cameraMovementSettings.m_panInvertedX); SandboxEditor::SetCameraPanInvertedY(m_cameraMovementSettings.m_panInvertedY); @@ -279,12 +279,12 @@ void CEditorPreferencesPage_ViewportCamera::OnApply() SandboxEditor::SetCameraTranslateUpChannelId(m_cameraInputSettings.m_translateUpChannelId); SandboxEditor::SetCameraTranslateDownChannelId(m_cameraInputSettings.m_translateDownChannelId); SandboxEditor::SetCameraTranslateBoostChannelId(m_cameraInputSettings.m_boostChannelId); - SandboxEditor::SetCameraPivotChannelId(m_cameraInputSettings.m_pivotChannelId); + SandboxEditor::SetCameraOrbitChannelId(m_cameraInputSettings.m_orbitChannelId); SandboxEditor::SetCameraFreeLookChannelId(m_cameraInputSettings.m_freeLookChannelId); SandboxEditor::SetCameraFreePanChannelId(m_cameraInputSettings.m_freePanChannelId); - SandboxEditor::SetCameraPivotLookChannelId(m_cameraInputSettings.m_pivotLookChannelId); - SandboxEditor::SetCameraPivotDollyChannelId(m_cameraInputSettings.m_pivotDollyChannelId); - SandboxEditor::SetCameraPivotPanChannelId(m_cameraInputSettings.m_pivotPanChannelId); + SandboxEditor::SetCameraOrbitLookChannelId(m_cameraInputSettings.m_orbitLookChannelId); + SandboxEditor::SetCameraOrbitDollyChannelId(m_cameraInputSettings.m_orbitDollyChannelId); + SandboxEditor::SetCameraOrbitPanChannelId(m_cameraInputSettings.m_orbitPanChannelId); SandboxEditor::SetCameraFocusChannelId(m_cameraInputSettings.m_focusChannelId); SandboxEditor::EditorModularViewportCameraComposerNotificationBus::Broadcast( @@ -304,7 +304,7 @@ void CEditorPreferencesPage_ViewportCamera::InitializeSettings() m_cameraMovementSettings.m_translateSmoothness = SandboxEditor::CameraTranslateSmoothness(); m_cameraMovementSettings.m_translateSmoothing = SandboxEditor::CameraTranslateSmoothingEnabled(); m_cameraMovementSettings.m_captureCursorLook = SandboxEditor::CameraCaptureCursorForLook(); - m_cameraMovementSettings.m_pivotYawRotationInverted = SandboxEditor::CameraPivotYawRotationInverted(); + m_cameraMovementSettings.m_orbitYawRotationInverted = SandboxEditor::CameraOrbitYawRotationInverted(); m_cameraMovementSettings.m_panInvertedX = SandboxEditor::CameraPanInvertedX(); m_cameraMovementSettings.m_panInvertedY = SandboxEditor::CameraPanInvertedY(); @@ -315,11 +315,11 @@ void CEditorPreferencesPage_ViewportCamera::InitializeSettings() m_cameraInputSettings.m_translateUpChannelId = SandboxEditor::CameraTranslateUpChannelId().GetName(); m_cameraInputSettings.m_translateDownChannelId = SandboxEditor::CameraTranslateDownChannelId().GetName(); m_cameraInputSettings.m_boostChannelId = SandboxEditor::CameraTranslateBoostChannelId().GetName(); - m_cameraInputSettings.m_pivotChannelId = SandboxEditor::CameraPivotChannelId().GetName(); + m_cameraInputSettings.m_orbitChannelId = SandboxEditor::CameraOrbitChannelId().GetName(); m_cameraInputSettings.m_freeLookChannelId = SandboxEditor::CameraFreeLookChannelId().GetName(); m_cameraInputSettings.m_freePanChannelId = SandboxEditor::CameraFreePanChannelId().GetName(); - m_cameraInputSettings.m_pivotLookChannelId = SandboxEditor::CameraPivotLookChannelId().GetName(); - m_cameraInputSettings.m_pivotDollyChannelId = SandboxEditor::CameraPivotDollyChannelId().GetName(); - m_cameraInputSettings.m_pivotPanChannelId = SandboxEditor::CameraPivotPanChannelId().GetName(); + m_cameraInputSettings.m_orbitLookChannelId = SandboxEditor::CameraOrbitLookChannelId().GetName(); + m_cameraInputSettings.m_orbitDollyChannelId = SandboxEditor::CameraOrbitDollyChannelId().GetName(); + m_cameraInputSettings.m_orbitPanChannelId = SandboxEditor::CameraOrbitPanChannelId().GetName(); m_cameraInputSettings.m_focusChannelId = SandboxEditor::CameraFocusChannelId().GetName(); } diff --git a/Code/Editor/EditorPreferencesPageViewportCamera.h b/Code/Editor/EditorPreferencesPageViewportCamera.h index cd31141c4a..fdc86b0f89 100644 --- a/Code/Editor/EditorPreferencesPageViewportCamera.h +++ b/Code/Editor/EditorPreferencesPageViewportCamera.h @@ -54,7 +54,7 @@ private: float m_translateSmoothness; bool m_translateSmoothing; bool m_captureCursorLook; - bool m_pivotYawRotationInverted; + bool m_orbitYawRotationInverted; bool m_panInvertedX; bool m_panInvertedY; @@ -80,12 +80,12 @@ private: AZStd::string m_translateUpChannelId; AZStd::string m_translateDownChannelId; AZStd::string m_boostChannelId; - AZStd::string m_pivotChannelId; + AZStd::string m_orbitChannelId; AZStd::string m_freeLookChannelId; AZStd::string m_freePanChannelId; - AZStd::string m_pivotLookChannelId; - AZStd::string m_pivotDollyChannelId; - AZStd::string m_pivotPanChannelId; + AZStd::string m_orbitLookChannelId; + AZStd::string m_orbitDollyChannelId; + AZStd::string m_orbitPanChannelId; AZStd::string m_focusChannelId; }; diff --git a/Code/Editor/EditorViewportSettings.cpp b/Code/Editor/EditorViewportSettings.cpp index c2539b008c..2354c6d63a 100644 --- a/Code/Editor/EditorViewportSettings.cpp +++ b/Code/Editor/EditorViewportSettings.cpp @@ -28,7 +28,7 @@ namespace SandboxEditor constexpr AZStd::string_view CameraRotateSpeedSetting = "/Amazon/Preferences/Editor/Camera/RotateSpeed"; constexpr AZStd::string_view CameraScrollSpeedSetting = "/Amazon/Preferences/Editor/Camera/DollyScrollSpeed"; constexpr AZStd::string_view CameraDollyMotionSpeedSetting = "/Amazon/Preferences/Editor/Camera/DollyMotionSpeed"; - constexpr AZStd::string_view CameraPivotYawRotationInvertedSetting = "/Amazon/Preferences/Editor/Camera/YawRotationInverted"; + constexpr AZStd::string_view CameraOrbitYawRotationInvertedSetting = "/Amazon/Preferences/Editor/Camera/YawRotationInverted"; constexpr AZStd::string_view CameraPanInvertedXSetting = "/Amazon/Preferences/Editor/Camera/PanInvertedX"; constexpr AZStd::string_view CameraPanInvertedYSetting = "/Amazon/Preferences/Editor/Camera/PanInvertedY"; constexpr AZStd::string_view CameraPanSpeedSetting = "/Amazon/Preferences/Editor/Camera/PanSpeed"; @@ -44,12 +44,12 @@ namespace SandboxEditor constexpr AZStd::string_view CameraTranslateUpIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateUpId"; constexpr AZStd::string_view CameraTranslateDownIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateUpDownId"; constexpr AZStd::string_view CameraTranslateBoostIdSetting = "/Amazon/Preferences/Editor/Camera/TranslateBoostId"; - constexpr AZStd::string_view CameraPivotIdSetting = "/Amazon/Preferences/Editor/Camera/PivotId"; + constexpr AZStd::string_view CameraOrbitIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitId"; constexpr AZStd::string_view CameraFreeLookIdSetting = "/Amazon/Preferences/Editor/Camera/FreeLookId"; constexpr AZStd::string_view CameraFreePanIdSetting = "/Amazon/Preferences/Editor/Camera/FreePanId"; - constexpr AZStd::string_view CameraPivotLookIdSetting = "/Amazon/Preferences/Editor/Camera/PivotLookId"; - constexpr AZStd::string_view CameraPivotDollyIdSetting = "/Amazon/Preferences/Editor/Camera/PivotDollyId"; - constexpr AZStd::string_view CameraPivotPanIdSetting = "/Amazon/Preferences/Editor/Camera/PivotPanId"; + constexpr AZStd::string_view CameraOrbitLookIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitLookId"; + constexpr AZStd::string_view CameraOrbitDollyIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitDollyId"; + constexpr AZStd::string_view CameraOrbitPanIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitPanId"; constexpr AZStd::string_view CameraFocusIdSetting = "/Amazon/Preferences/Editor/Camera/FocusId"; template @@ -240,14 +240,14 @@ namespace SandboxEditor SetRegistry(CameraDollyMotionSpeedSetting, speed); } - bool CameraPivotYawRotationInverted() + bool CameraOrbitYawRotationInverted() { - return GetRegistry(CameraPivotYawRotationInvertedSetting, false); + return GetRegistry(CameraOrbitYawRotationInvertedSetting, false); } - void SetCameraPivotYawRotationInverted(const bool inverted) + void SetCameraOrbitYawRotationInverted(const bool inverted) { - SetRegistry(CameraPivotYawRotationInvertedSetting, inverted); + SetRegistry(CameraOrbitYawRotationInvertedSetting, inverted); } bool CameraPanInvertedX() @@ -404,14 +404,14 @@ namespace SandboxEditor SetRegistry(CameraTranslateBoostIdSetting, cameraTranslateBoostId); } - AzFramework::InputChannelId CameraPivotChannelId() + AzFramework::InputChannelId CameraOrbitChannelId() { - return AzFramework::InputChannelId(GetRegistry(CameraPivotIdSetting, AZStd::string("keyboard_key_modifier_alt_l")).c_str()); + return AzFramework::InputChannelId(GetRegistry(CameraOrbitIdSetting, AZStd::string("keyboard_key_modifier_alt_l")).c_str()); } - void SetCameraPivotChannelId(AZStd::string_view cameraPivotId) + void SetCameraOrbitChannelId(AZStd::string_view cameraOrbitId) { - SetRegistry(CameraPivotIdSetting, cameraPivotId); + SetRegistry(CameraOrbitIdSetting, cameraOrbitId); } AzFramework::InputChannelId CameraFreeLookChannelId() @@ -434,34 +434,34 @@ namespace SandboxEditor SetRegistry(CameraFreePanIdSetting, cameraFreePanId); } - AzFramework::InputChannelId CameraPivotLookChannelId() + AzFramework::InputChannelId CameraOrbitLookChannelId() { - return AzFramework::InputChannelId(GetRegistry(CameraPivotLookIdSetting, AZStd::string("mouse_button_left")).c_str()); + return AzFramework::InputChannelId(GetRegistry(CameraOrbitLookIdSetting, AZStd::string("mouse_button_left")).c_str()); } - void SetCameraPivotLookChannelId(AZStd::string_view cameraPivotLookId) + void SetCameraOrbitLookChannelId(AZStd::string_view cameraOrbitLookId) { - SetRegistry(CameraPivotLookIdSetting, cameraPivotLookId); + SetRegistry(CameraOrbitLookIdSetting, cameraOrbitLookId); } - AzFramework::InputChannelId CameraPivotDollyChannelId() + AzFramework::InputChannelId CameraOrbitDollyChannelId() { - return AzFramework::InputChannelId(GetRegistry(CameraPivotDollyIdSetting, AZStd::string("mouse_button_right")).c_str()); + return AzFramework::InputChannelId(GetRegistry(CameraOrbitDollyIdSetting, AZStd::string("mouse_button_right")).c_str()); } - void SetCameraPivotDollyChannelId(AZStd::string_view cameraPivotDollyId) + void SetCameraOrbitDollyChannelId(AZStd::string_view cameraOrbitDollyId) { - SetRegistry(CameraPivotDollyIdSetting, cameraPivotDollyId); + SetRegistry(CameraOrbitDollyIdSetting, cameraOrbitDollyId); } - AzFramework::InputChannelId CameraPivotPanChannelId() + AzFramework::InputChannelId CameraOrbitPanChannelId() { - return AzFramework::InputChannelId(GetRegistry(CameraPivotPanIdSetting, AZStd::string("mouse_button_middle")).c_str()); + return AzFramework::InputChannelId(GetRegistry(CameraOrbitPanIdSetting, AZStd::string("mouse_button_middle")).c_str()); } - void SetCameraPivotPanChannelId(AZStd::string_view cameraPivotPanId) + void SetCameraOrbitPanChannelId(AZStd::string_view cameraOrbitPanId) { - SetRegistry(CameraPivotPanIdSetting, cameraPivotPanId); + SetRegistry(CameraOrbitPanIdSetting, cameraOrbitPanId); } AzFramework::InputChannelId CameraFocusChannelId() diff --git a/Code/Editor/EditorViewportSettings.h b/Code/Editor/EditorViewportSettings.h index 0253b01621..c1394f7404 100644 --- a/Code/Editor/EditorViewportSettings.h +++ b/Code/Editor/EditorViewportSettings.h @@ -71,8 +71,8 @@ namespace SandboxEditor SANDBOX_API float CameraDollyMotionSpeed(); SANDBOX_API void SetCameraDollyMotionSpeed(float speed); - SANDBOX_API bool CameraPivotYawRotationInverted(); - SANDBOX_API void SetCameraPivotYawRotationInverted(bool inverted); + SANDBOX_API bool CameraOrbitYawRotationInverted(); + SANDBOX_API void SetCameraOrbitYawRotationInverted(bool inverted); SANDBOX_API bool CameraPanInvertedX(); SANDBOX_API void SetCameraPanInvertedX(bool inverted); @@ -119,8 +119,8 @@ namespace SandboxEditor SANDBOX_API AzFramework::InputChannelId CameraTranslateBoostChannelId(); SANDBOX_API void SetCameraTranslateBoostChannelId(AZStd::string_view cameraTranslateBoostId); - SANDBOX_API AzFramework::InputChannelId CameraPivotChannelId(); - SANDBOX_API void SetCameraPivotChannelId(AZStd::string_view cameraPivotId); + SANDBOX_API AzFramework::InputChannelId CameraOrbitChannelId(); + SANDBOX_API void SetCameraOrbitChannelId(AZStd::string_view cameraOrbitId); SANDBOX_API AzFramework::InputChannelId CameraFreeLookChannelId(); SANDBOX_API void SetCameraFreeLookChannelId(AZStd::string_view cameraFreeLookId); @@ -128,14 +128,14 @@ namespace SandboxEditor SANDBOX_API AzFramework::InputChannelId CameraFreePanChannelId(); SANDBOX_API void SetCameraFreePanChannelId(AZStd::string_view cameraFreePanId); - SANDBOX_API AzFramework::InputChannelId CameraPivotLookChannelId(); - SANDBOX_API void SetCameraPivotLookChannelId(AZStd::string_view cameraPivotLookId); + SANDBOX_API AzFramework::InputChannelId CameraOrbitLookChannelId(); + SANDBOX_API void SetCameraOrbitLookChannelId(AZStd::string_view cameraOrbitLookId); - SANDBOX_API AzFramework::InputChannelId CameraPivotDollyChannelId(); - SANDBOX_API void SetCameraPivotDollyChannelId(AZStd::string_view cameraPivotDollyId); + SANDBOX_API AzFramework::InputChannelId CameraOrbitDollyChannelId(); + SANDBOX_API void SetCameraOrbitDollyChannelId(AZStd::string_view cameraOrbitDollyId); - SANDBOX_API AzFramework::InputChannelId CameraPivotPanChannelId(); - SANDBOX_API void SetCameraPivotPanChannelId(AZStd::string_view cameraPivotPanId); + SANDBOX_API AzFramework::InputChannelId CameraOrbitPanChannelId(); + SANDBOX_API void SetCameraOrbitPanChannelId(AZStd::string_view cameraOrbitPanId); SANDBOX_API AzFramework::InputChannelId CameraFocusChannelId(); SANDBOX_API void SetCameraFocusChannelId(AZStd::string_view cameraFocusId); diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp index 13f5303eaf..ddee63e191 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.cpp @@ -533,8 +533,8 @@ namespace AzFramework m_translateCameraInputChannelIds = translateCameraInputChannelIds; } - PivotCameraInput::PivotCameraInput(const InputChannelId& pivotChannelId) - : m_pivotChannelId(pivotChannelId) + OrbitCameraInput::OrbitCameraInput(const InputChannelId& orbitChannelId) + : m_orbitChannelId(orbitChannelId) { m_pivotFn = []([[maybe_unused]] const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction) { @@ -542,11 +542,11 @@ namespace AzFramework }; } - bool PivotCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, const float scrollDelta) + bool OrbitCameraInput::HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, const float scrollDelta) { if (const auto* input = AZStd::get_if(&event)) { - if (input->m_channelId == m_pivotChannelId) + if (input->m_channelId == m_orbitChannelId) { if (input->m_state == InputChannel::State::Began) { @@ -561,13 +561,13 @@ namespace AzFramework if (Active()) { - return m_pivotCameras.HandleEvents(event, cursorDelta, scrollDelta); + return m_orbitCameras.HandleEvents(event, cursorDelta, scrollDelta); } return !Idle(); } - Camera PivotCameraInput::StepCamera( + Camera OrbitCameraInput::StepCamera( const Camera& targetCamera, const ScreenVector& cursorDelta, const float scrollDelta, const float deltaTime) { Camera nextCamera = targetCamera; @@ -581,12 +581,12 @@ namespace AzFramework if (Active()) { MovePivotDetached(nextCamera, m_pivotFn(targetCamera.Translation(), targetCamera.Rotation().GetBasisY())); - nextCamera = m_pivotCameras.StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime); + nextCamera = m_orbitCameras.StepCamera(nextCamera, cursorDelta, scrollDelta, deltaTime); } if (Ending()) { - m_pivotCameras.Reset(); + m_orbitCameras.Reset(); nextCamera.m_pivot = nextCamera.Translation(); nextCamera.m_offset = AZ::Vector3::CreateZero(); @@ -595,12 +595,12 @@ namespace AzFramework return nextCamera; } - void PivotCameraInput::SetPivotInputChannelId(const InputChannelId& pivotChanneId) + void OrbitCameraInput::SetOrbitInputChannelId(const InputChannelId& orbitChanneId) { - m_pivotChannelId = pivotChanneId; + m_orbitChannelId = orbitChanneId; } - PivotDollyScrollCameraInput::PivotDollyScrollCameraInput() + OrbitDollyScrollCameraInput::OrbitDollyScrollCameraInput() { m_scrollSpeedFn = []() constexpr { @@ -608,7 +608,7 @@ namespace AzFramework }; } - bool PivotDollyScrollCameraInput::HandleEvents( + bool OrbitDollyScrollCameraInput::HandleEvents( const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta) { if (const auto* scroll = AZStd::get_if(&event)) @@ -619,7 +619,7 @@ namespace AzFramework return !Idle(); } - static Camera PivotDolly(const Camera& targetCamera, const float delta) + static Camera OrbitDolly(const Camera& targetCamera, const float delta) { Camera nextCamera = targetCamera; @@ -646,18 +646,18 @@ namespace AzFramework return nextCamera; } - Camera PivotDollyScrollCameraInput::StepCamera( + Camera OrbitDollyScrollCameraInput::StepCamera( const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, const float scrollDelta, [[maybe_unused]] const float deltaTime) { - const auto nextCamera = PivotDolly(targetCamera, aznumeric_cast(scrollDelta) * m_scrollSpeedFn()); + const auto nextCamera = OrbitDolly(targetCamera, aznumeric_cast(scrollDelta) * m_scrollSpeedFn()); EndActivation(); return nextCamera; } - PivotDollyMotionCameraInput::PivotDollyMotionCameraInput(const InputChannelId& dollyChannelId) + OrbitDollyMotionCameraInput::OrbitDollyMotionCameraInput(const InputChannelId& dollyChannelId) : m_dollyChannelId(dollyChannelId) { m_motionSpeedFn = []() constexpr @@ -666,28 +666,28 @@ namespace AzFramework }; } - bool PivotDollyMotionCameraInput::HandleEvents( + bool OrbitDollyMotionCameraInput::HandleEvents( const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta) { HandleActivationEvents(event, m_dollyChannelId, cursorDelta, m_clickDetector, *this); return CameraInputUpdatingAfterMotion(*this); } - Camera PivotDollyMotionCameraInput::StepCamera( + Camera OrbitDollyMotionCameraInput::StepCamera( const Camera& targetCamera, const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta, [[maybe_unused]] const float deltaTime) { - return PivotDolly(targetCamera, aznumeric_cast(cursorDelta.m_y) * m_motionSpeedFn()); + return OrbitDolly(targetCamera, aznumeric_cast(cursorDelta.m_y) * m_motionSpeedFn()); } - void PivotDollyMotionCameraInput::SetDollyInputChannelId(const InputChannelId& dollyChannelId) + void OrbitDollyMotionCameraInput::SetDollyInputChannelId(const InputChannelId& dollyChannelId) { m_dollyChannelId = dollyChannelId; } - ScrollTranslationCameraInput::ScrollTranslationCameraInput() + LookScrollTranslationCameraInput::LookScrollTranslationCameraInput() { m_scrollSpeedFn = []() constexpr { @@ -695,7 +695,7 @@ namespace AzFramework }; } - bool ScrollTranslationCameraInput::HandleEvents( + bool LookScrollTranslationCameraInput::HandleEvents( const InputEvent& event, [[maybe_unused]] const ScreenVector& cursorDelta, [[maybe_unused]] const float scrollDelta) { if (const auto* scroll = AZStd::get_if(&event)) @@ -706,7 +706,7 @@ namespace AzFramework return !Idle(); } - Camera ScrollTranslationCameraInput::StepCamera( + Camera LookScrollTranslationCameraInput::StepCamera( const Camera& targetCamera, [[maybe_unused]] const ScreenVector& cursorDelta, const float scrollDelta, diff --git a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h index 9b1988f5ec..2b7cc3ea9e 100644 --- a/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h +++ b/Code/Framework/AzFramework/AzFramework/Viewport/CameraInput.h @@ -30,8 +30,11 @@ namespace AzFramework AZ::Vector3 EulerAngles(const AZ::Matrix3x3& orientation); //! A simple camera representation using spherical coordinates as input (pitch, yaw, pivot and offset). - //! The cameras transform and view can be obtained through accessor functions that use the internal + //! The camera's transform and view can be obtained through accessor functions that use the internal //! spherical coordinates to calculate the position and orientation. + //! @note Modifying m_pivot directly and leaving m_offset as zero will produce a free look camera effect, giving + //! m_offset a value (e.g. in negative Y only) will produce an orbit camera effect, modifying X and Z of m_offset + //! will further alter the camera translation in relation to m_pivot so it appears off center. struct Camera { AZ::Vector3 m_pivot = AZ::Vector3::CreateZero(); //!< Pivot point to rotate about (modified in world space). @@ -291,7 +294,7 @@ namespace AzFramework Cameras m_cameras; //!< Represents a collection of camera inputs that together provide a camera controller. private: - ScreenVector m_motionDelta; //!< The delta used for look/pivot/pan (rotation + translation) - two dimensional. + ScreenVector m_motionDelta; //!< The delta used for look/orbit/pan (rotation + translation) - two dimensional. CursorState m_cursorState; //!< The current and previous position of the cursor (used to calculate movement delta). float m_scrollDelta = 0.0f; //!< The delta used for dolly/movement (translation) - one dimensional. bool m_handlingEvents = false; //!< Is the camera system currently handling events (events are consumed and not propagated). @@ -316,7 +319,7 @@ namespace AzFramework return AZStd::fmod(yaw + AZ::Constants::TwoPi, AZ::Constants::TwoPi); } - //! A camera input to handle motion deltas that can rotate or pivot the camera. + //! A camera input to handle motion deltas that can change the orientation of the camera (update pitch and yaw). class RotateCameraInput : public CameraInput { public: @@ -348,15 +351,16 @@ namespace AzFramework //! PanAxes build function that will return a pair of pan axes depending on the camera orientation. using PanAxesFn = AZStd::function; - //! PanAxes to use while in 'look' camera behavior (free look). + //! PanAxes to use while in 'look' or 'orbit' camera behavior. inline PanAxes LookPan(const Camera& camera) { const AZ::Matrix3x3 orientation = camera.Rotation(); return { orientation.GetBasisX(), orientation.GetBasisZ() }; } - //! PanAxes to use while in 'pivot' camera behavior. - inline PanAxes PivotPan(const Camera& camera) + //! Optional PanAxes to use while in 'orbit' camera behavior. + //! @note This will move the camera in the local X/Y plane instead of usual X/Z plane. + inline PanAxes OrbitPan(const Camera& camera) { const AZ::Matrix3x3 orientation = camera.Rotation(); @@ -370,14 +374,23 @@ namespace AzFramework return { basisX, basisY }; } + //! TranslationDeltaFn is used by PanCameraInput and TranslateCameraInput + //! @note Choose the appropriate function if the behavior should be operating as a free look camera (TranslatePivotLook) + //! or an orbit camera (TranslateOffsetOrbit). using TranslationDeltaFn = AZStd::function; - inline void TranslatePivot(Camera& camera, const AZ::Vector3& delta) + //! Update the pivot camera position. + //! @note delta will need to have been transformed to world space, e.g. To move the camera right, (1, 0, 0) must + //! first be transformed by the orientation of the camera before being applied to m_pivot. + inline void TranslatePivotLook(Camera& camera, const AZ::Vector3& delta) { camera.m_pivot += delta; } - inline void TranslateOffset(Camera& camera, const AZ::Vector3& delta) + //! Update the offset camera position. + //! @note delta still needs to be transformed to world space (as with TranslatePivotLook) but internally this is undone + //! to be performed in local space when being applied to m_offset. + inline void TranslateOffsetOrbit(Camera& camera, const AZ::Vector3& delta) { camera.m_offset += camera.View().TransformVector(delta); } @@ -409,7 +422,7 @@ namespace AzFramework //! Axes to use while translating the camera. using TranslationAxesFn = AZStd::function; - //! TranslationAxes to use while in 'look' camera behavior (free look). + //! TranslationAxes to use while in 'look' or 'orbit' camera behavior. inline AZ::Matrix3x3 LookTranslation(const Camera& camera) { const AZ::Matrix3x3 orientation = camera.Rotation(); @@ -421,8 +434,8 @@ namespace AzFramework return AZ::Matrix3x3::CreateFromColumns(basisX, basisY, basisZ); } - //! TranslationAxes to use while in 'pivot' camera behavior. - inline AZ::Matrix3x3 PivotTranslation(const Camera& camera) + //! Optional TranslationAxes to use while in 'orbit' camera behavior. + inline AZ::Matrix3x3 OrbitTranslation(const Camera& camera) { const AZ::Matrix3x3 orientation = camera.Rotation(); @@ -535,11 +548,11 @@ namespace AzFramework bool m_boost = false; //!< Is the translation speed currently being multiplied/scaled upwards. }; - //! A camera input to handle discrete scroll events that can modify the camera pivot distance. - class PivotDollyScrollCameraInput : public CameraInput + //! A camera input to handle discrete scroll events that can modify the camera offset. + class OrbitDollyScrollCameraInput : public CameraInput { public: - PivotDollyScrollCameraInput(); + OrbitDollyScrollCameraInput(); // CameraInput overrides ... bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; @@ -548,11 +561,11 @@ namespace AzFramework AZStd::function m_scrollSpeedFn; }; - //! A camera input to handle motion deltas that can modify the camera pivot distance. - class PivotDollyMotionCameraInput : public CameraInput + //! A camera input to handle motion deltas that can modify the camera offset. + class OrbitDollyMotionCameraInput : public CameraInput { public: - explicit PivotDollyMotionCameraInput(const InputChannelId& dollyChannelId); + explicit OrbitDollyMotionCameraInput(const InputChannelId& dollyChannelId); // CameraInput overrides ... bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; @@ -569,10 +582,10 @@ namespace AzFramework }; //! A camera input to handle discrete scroll events that can scroll (translate) the camera along its forward axis. - class ScrollTranslationCameraInput : public CameraInput + class LookScrollTranslationCameraInput : public CameraInput { public: - ScrollTranslationCameraInput(); + LookScrollTranslationCameraInput(); // CameraInput overrides ... bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; @@ -583,36 +596,36 @@ namespace AzFramework //! A camera input that doubles as its own set of camera inputs. //! It is 'exclusive', so does not overlap with other sibling camera inputs - it runs its own set of camera inputs as 'children'. - class PivotCameraInput : public CameraInput + class OrbitCameraInput : public CameraInput { public: using PivotFn = AZStd::function; - explicit PivotCameraInput(const InputChannelId& pivotChannelId); + explicit OrbitCameraInput(const InputChannelId& orbitChannelId); // CameraInput overrides ... bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; bool Exclusive() const override; - void SetPivotInputChannelId(const InputChannelId& pivotChanneId); + void SetOrbitInputChannelId(const InputChannelId& orbitChanneId); - Cameras m_pivotCameras; //!< The camera inputs to run when this camera input is active (only these will run as it is exclusive). + Cameras m_orbitCameras; //!< The camera inputs to run when this camera input is active (only these will run as it is exclusive). //! Override the default behavior for how a pivot point is calculated. void SetPivotFn(PivotFn pivotFn); private: - InputChannelId m_pivotChannelId; //!< Input channel to begin the pivot camera input. - PivotFn m_pivotFn; //!< The pivot position to use for this pivot camera (how is the pivot point calculated/retrieved). + InputChannelId m_orbitChannelId; //!< Input channel to begin the orbit camera input. + PivotFn m_pivotFn; //!< The pivot position to use for this orbit camera (how is the pivot point calculated/retrieved). }; - inline void PivotCameraInput::SetPivotFn(PivotFn pivotFn) + inline void OrbitCameraInput::SetPivotFn(PivotFn pivotFn) { m_pivotFn = AZStd::move(pivotFn); } - inline bool PivotCameraInput::Exclusive() const + inline bool OrbitCameraInput::Exclusive() const { return true; } @@ -624,9 +637,9 @@ namespace AzFramework return AZ::Vector3::CreateZero(); } - //! Callback to use for FocusCameraInput when a pivot camera is being used. + //! Callback to use for FocusCameraInput when a orbit camera is being used. //! @note This is when offset is non zero. - inline AZ::Vector3 FocusPivot(const float length) + inline AZ::Vector3 FocusOrbit(const float length) { return AZ::Vector3::CreateAxisY(-length); } @@ -667,7 +680,9 @@ namespace AzFramework bool HandleEvents(const InputEvent& event, const ScreenVector& cursorDelta, float scrollDelta) override; Camera StepCamera(const Camera& targetCamera, const ScreenVector& cursorDelta, float scrollDelta, float deltaTime) override; + //! HandleEvents delegates directly to m_handleEventsFn. AZStd::function m_handleEventsFn; + //! StepCamera delegates directly to m_stepCameraFn. AZStd::function m_stepCameraFn; }; diff --git a/Code/Framework/AzFramework/Tests/CameraInputTests.cpp b/Code/Framework/AzFramework/Tests/CameraInputTests.cpp index 1e0c805587..a89fb0bd84 100644 --- a/Code/Framework/AzFramework/Tests/CameraInputTests.cpp +++ b/Code/Framework/AzFramework/Tests/CameraInputTests.cpp @@ -53,31 +53,31 @@ namespace UnitTest }; m_firstPersonTranslateCamera = AZStd::make_shared( - m_translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslatePivot); + m_translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslatePivotLook); - m_pivotCamera = AZStd::make_shared(m_pivotChannelId); - m_pivotCamera->SetPivotFn( + m_orbitCamera = AZStd::make_shared(m_orbitChannelId); + m_orbitCamera->SetPivotFn( [this](const AZ::Vector3&, const AZ::Vector3&) { return m_pivot; }); - auto pivotRotateCamera = AZStd::make_shared(AzFramework::InputDeviceMouse::Button::Left); + auto orbitRotateCamera = AZStd::make_shared(AzFramework::InputDeviceMouse::Button::Left); // set rotate speed to be a value that will scale motion delta (pixels moved) by a thousandth. - pivotRotateCamera->m_rotateSpeedFn = []() + orbitRotateCamera->m_rotateSpeedFn = []() { return 0.001f; }; - auto pivotTranslateCamera = AZStd::make_shared( - m_translateCameraInputChannelIds, AzFramework::PivotTranslation, AzFramework::TranslateOffset); + auto orbitTranslateCamera = AZStd::make_shared( + m_translateCameraInputChannelIds, AzFramework::OrbitTranslation, AzFramework::TranslateOffsetOrbit); - m_pivotCamera->m_pivotCameras.AddCamera(pivotRotateCamera); - m_pivotCamera->m_pivotCameras.AddCamera(pivotTranslateCamera); + m_orbitCamera->m_orbitCameras.AddCamera(orbitRotateCamera); + m_orbitCamera->m_orbitCameras.AddCamera(orbitTranslateCamera); m_cameraSystem->m_cameras.AddCamera(m_firstPersonRotateCamera); m_cameraSystem->m_cameras.AddCamera(m_firstPersonTranslateCamera); - m_cameraSystem->m_cameras.AddCamera(m_pivotCamera); + m_cameraSystem->m_cameras.AddCamera(m_orbitCamera); // these tests rely on using motion delta, not cursor positions (default is true) AzFramework::ed_cameraSystemUseCursor = false; @@ -87,7 +87,7 @@ namespace UnitTest { AzFramework::ed_cameraSystemUseCursor = true; - m_pivotCamera.reset(); + m_orbitCamera.reset(); m_firstPersonRotateCamera.reset(); m_firstPersonTranslateCamera.reset(); @@ -97,11 +97,11 @@ namespace UnitTest AllocatorsTestFixture::TearDown(); } - AzFramework::InputChannelId m_pivotChannelId = AzFramework::InputChannelId("keyboard_key_modifier_alt_l"); + AzFramework::InputChannelId m_orbitChannelId = AzFramework::InputChannelId("keyboard_key_modifier_alt_l"); AzFramework::TranslateCameraInputChannelIds m_translateCameraInputChannelIds; AZStd::shared_ptr m_firstPersonRotateCamera; AZStd::shared_ptr m_firstPersonTranslateCamera; - AZStd::shared_ptr m_pivotCamera; + AZStd::shared_ptr m_orbitCamera; AZ::Vector3 m_pivot = AZ::Vector3::CreateZero(); //! This is approximately Pi/2 * 1000 - this can be used to rotate the camera 90 degrees (pitch or yaw based @@ -109,17 +109,17 @@ namespace UnitTest inline static const int PixelMotionDelta = 1570; }; - TEST_F(CameraInputFixture, BeginAndEndPivotCameraInputConsumesCorrectEvents) + TEST_F(CameraInputFixture, BeginAndEndOrbitCameraInputConsumesCorrectEvents) { - // begin pivot camera + // begin orbit camera const bool consumed1 = HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceKeyboard::Key::ModifierAltL, AzFramework::InputChannel::State::Began }); - // begin listening for pivot rotate (click detector) - event is not consumed + // begin listening for orbit rotate (click detector) - event is not consumed const bool consumed2 = HandleEventAndUpdate( AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceMouse::Button::Left, AzFramework::InputChannel::State::Began }); - // begin pivot rotate (mouse has moved sufficient distance to initiate) + // begin orbit rotate (mouse has moved sufficient distance to initiate) const bool consumed3 = HandleEventAndUpdate(AzFramework::HorizontalMotionEvent{ 5 }); - // end pivot (mouse up) - event is not consumed + // end orbit (mouse up) - event is not consumed const bool consumed4 = HandleEventAndUpdate( AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceMouse::Button::Left, AzFramework::InputChannel::State::Ended }); @@ -260,10 +260,10 @@ namespace UnitTest EXPECT_TRUE(activationEnded); } - TEST_F(CameraInputFixture, PivotCameraInputHandlesLookAtPointAndSelfAtSamePositionWhenPivoting) + TEST_F(CameraInputFixture, OrbitCameraInputHandlesLookAtPointAndSelfAtSamePositionWhenOrbiting) { // create pathological lookAtFn that just returns the same position as the camera - m_pivotCamera->SetPivotFn( + m_orbitCamera->SetPivotFn( [](const AZ::Vector3& position, [[maybe_unused]] const AZ::Vector3& direction) { return position; @@ -275,7 +275,7 @@ namespace UnitTest AZ::Transform::CreateFromQuaternionAndTranslation( AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), expectedCameraPosition)); - HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_pivotChannelId, AzFramework::InputChannel::State::Began }); + HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_orbitChannelId, AzFramework::InputChannel::State::Began }); // verify the camera yaw has not changed and pivot point matches the expected camera position using ::testing::FloatNear; @@ -321,14 +321,14 @@ namespace UnitTest EXPECT_THAT(m_camera.m_offset, IsClose(AZ::Vector3::CreateZero())); } - TEST_F(CameraInputFixture, PivotRotateCameraInputRotatesPitchOffsetByNinetyDegreesWithRequiredPixelDelta) + TEST_F(CameraInputFixture, OrbitRotateCameraInputRotatesPitchOffsetByNinetyDegreesWithRequiredPixelDelta) { const auto cameraStartingPosition = AZ::Vector3::CreateAxisY(-20.0f); m_targetCamera.m_pivot = cameraStartingPosition; m_pivot = AZ::Vector3::CreateAxisY(-10.0f); - HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_pivotChannelId, AzFramework::InputChannel::State::Began }); + HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_orbitChannelId, AzFramework::InputChannel::State::Began }); HandleEventAndUpdate( AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceMouse::Button::Left, AzFramework::InputChannel::State::Began }); HandleEventAndUpdate(AzFramework::VerticalMotionEvent{ PixelMotionDelta }); @@ -344,14 +344,14 @@ namespace UnitTest EXPECT_THAT(m_camera.Translation(), IsCloseTolerance(expectedCameraEndingPosition, 0.01f)); } - TEST_F(CameraInputFixture, PivotRotateCameraInputRotatesYawOffsetByNinetyDegreesWithRequiredPixelDelta) + TEST_F(CameraInputFixture, OrbitRotateCameraInputRotatesYawOffsetByNinetyDegreesWithRequiredPixelDelta) { const auto cameraStartingPosition = AZ::Vector3(15.0f, -20.0f, 0.0f); m_targetCamera.m_pivot = cameraStartingPosition; m_pivot = AZ::Vector3(10.0f, -10.0f, 0.0f); - HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_pivotChannelId, AzFramework::InputChannel::State::Began }); + HandleEventAndUpdate(AzFramework::DiscreteInputEvent{ m_orbitChannelId, AzFramework::InputChannel::State::Began }); HandleEventAndUpdate( AzFramework::DiscreteInputEvent{ AzFramework::InputDeviceMouse::Button::Left, AzFramework::InputChannel::State::Began }); HandleEventAndUpdate(AzFramework::HorizontalMotionEvent{ -PixelMotionDelta }); From 77c23b6c8f59aa1a0ee9026c670be36981f664c7 Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Thu, 7 Oct 2021 08:27:48 -0400 Subject: [PATCH 028/169] Hierarchy imgui debugger, first take Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../MultiplayerDebugHierarchyReporter.cpp | 200 ++++++++++++++++++ .../Debug/MultiplayerDebugHierarchyReporter.h | 52 +++++ .../Debug/MultiplayerDebugSystemComponent.cpp | 24 +++ .../Debug/MultiplayerDebugSystemComponent.h | 5 + .../Code/multiplayer_debug_files.cmake | 2 + 5 files changed, 283 insertions(+) create mode 100644 Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyReporter.cpp create mode 100644 Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyReporter.h diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyReporter.cpp new file mode 100644 index 0000000000..32e9a776a4 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyReporter.cpp @@ -0,0 +1,200 @@ +/* + * 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 "MultiplayerDebugHierarchyReporter.h" + +#include +#include +#include +#include + +#if defined(IMGUI_ENABLED) +#include +#endif + +#pragma optimize("", off) + +namespace Multiplayer +{ + MultiplayerDebugHierarchyReporter::MultiplayerDebugHierarchyReporter() + : m_updateDebugOverlay([this]() { UpdateDebugOverlay(); }, AZ::Name("UpdateHierarchyDebug")) + { + CollectHierarchyRoots(); + + AZ::EntitySystemBus::Handler::BusConnect(); + m_updateDebugOverlay.Enqueue(AZ::TimeMs{ 0 }, true); + } + + MultiplayerDebugHierarchyReporter::~MultiplayerDebugHierarchyReporter() + { + AZ::EntitySystemBus::Handler::BusDisconnect(); + } + + // -------------------------------------------------------------------------------------------- + void MultiplayerDebugHierarchyReporter::OnImGuiUpdate() + { +#if defined(IMGUI_ENABLED) + for (const auto& root : m_hierarchyRoots) + { + if (const auto* rootComponent = root.second.m_rootComponent) + { + if (rootComponent->IsHierarchicalRoot()) + { + const AZStd::vector& hierarchicalChildren = rootComponent->GetHierarchicalEntities(); + + if (ImGui::TreeNode(rootComponent->GetEntity()->GetName().c_str(), + "Hierarchy, Root entity name [%s]: %4zu members", + rootComponent->GetEntity()->GetName().c_str(), + hierarchicalChildren.size())) + { + ImGui::Separator(); + ImGui::Columns(4, "hierarchy_columns"); + ImGui::Text("EntityId"); + ImGui::NextColumn(); + ImGui::Text("NetEntityId"); + ImGui::NextColumn(); + ImGui::Text("Entity Name"); + ImGui::NextColumn(); + ImGui::Text("Role"); + ImGui::NextColumn(); + + ImGui::Separator(); + ImGui::Columns(4, "hierarchy child info"); + + bool firstEntity = true; + for (const AZ::Entity* entity : hierarchicalChildren) + { + ImGui::Text("%s", entity->GetId().ToString().c_str()); + ImGui::NextColumn(); + ImGui::Text("%u", GetMultiplayer()->GetNetworkEntityManager()->GetNetEntityIdById(entity->GetId())); + ImGui::NextColumn(); + ImGui::Text("%s", entity->GetName().c_str()); + ImGui::NextColumn(); + + if (firstEntity) + { + ImGui::Text("Root node"); + } + else if (entity->FindComponent()) + { + ImGui::Text("Inner root node"); + } + else if (entity->FindComponent()) + { + ImGui::Text("Child node"); + } + ImGui::NextColumn(); + + firstEntity = false; + } + + ImGui::Columns(1); + ImGui::TreePop(); + } + } + } + } +#endif + } + + + void MultiplayerDebugHierarchyReporter::UpdateDebugOverlay() + { + if (!m_hierarchyRoots.empty()) + { + if (m_debugDisplay == nullptr) + { + AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus; + AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId); + m_debugDisplay = AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus); + } + + const AZ::u32 stateBefore = m_debugDisplay->GetState(); + m_debugDisplay->SetColor(AZ::Colors::White); + + for (const auto& root : m_hierarchyRoots) + { + if (const auto* rootComponent = root.second.m_rootComponent) + { + if (rootComponent->IsHierarchicalRoot()) + { + const AZStd::vector& hierarchicalChildren = rootComponent->GetHierarchicalEntities(); + + azsprintf(m_statusBuffer, "Hierarchy [%s] %u members", rootComponent->GetEntity()->GetName().c_str(), + aznumeric_cast(hierarchicalChildren.size())); + + AZ::Vector3 entityPosition = rootComponent->GetEntity()->GetTransform()->GetWorldTranslation(); + constexpr bool centerText = true; + m_debugDisplay->DrawTextLabel(entityPosition, 1.0f, m_statusBuffer, centerText, 0, 0); + } + } + } + + m_debugDisplay->SetState(stateBefore); + } + } + + void MultiplayerDebugHierarchyReporter::OnEntityActivated(const AZ::EntityId& entityId) + { + if (const AZ::Entity* childEntity = AZ::Interface::Get()->FindEntity(entityId)) + { + if (auto* rootComponent = childEntity->FindComponent()) + { + HierarchyRootInfo info; + info.m_rootComponent = rootComponent; + rootComponent->BindNetworkHierarchyChangedEventHandler(info.m_changedEvent); + rootComponent->BindNetworkHierarchyLeaveEventHandler(info.m_leaveEvent); + + m_hierarchyRoots.insert(AZStd::make_pair(rootComponent, info)); + } + } + } + + void MultiplayerDebugHierarchyReporter::OnEntityDeactivated(const AZ::EntityId& entityId) + { + if (const AZ::Entity* childEntity = AZ::Interface::Get()->FindEntity(entityId)) + { + if (auto* rootComponent = childEntity->FindComponent()) + { + m_hierarchyRoots.erase(rootComponent); + } + } + } + + void MultiplayerDebugHierarchyReporter::CollectHierarchyRoots() + { + AZStd::vector gatheredEntries; + const AZ::Sphere awarenessSphere = AZ::Sphere(AZ::Vector3::CreateZero(), 1000.f); + AZ::Interface::Get()->GetDefaultVisibilityScene()->Enumerate(awarenessSphere, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) + { + gatheredEntries.reserve(gatheredEntries.size() + nodeData.m_entries.size()); + for (AzFramework::VisibilityEntry* visEntry : nodeData.m_entries) + { + if (visEntry->m_typeFlags & AzFramework::VisibilityEntry::TypeFlags::TYPE_Entity) + { + gatheredEntries.push_back(visEntry); + } + } + } + ); + + for (const AzFramework::VisibilityEntry* entry : gatheredEntries) + { + const AZ::Entity* entity = static_cast(entry->m_userData); + if (auto* rootComponent = entity->FindComponent()) + { + HierarchyRootInfo info; + info.m_rootComponent = rootComponent; + rootComponent->BindNetworkHierarchyChangedEventHandler(info.m_changedEvent); + rootComponent->BindNetworkHierarchyLeaveEventHandler(info.m_leaveEvent); + + m_hierarchyRoots.insert(AZStd::make_pair(rootComponent, info)); + } + } + } +} diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyReporter.h new file mode 100644 index 0000000000..98a131614c --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyReporter.h @@ -0,0 +1,52 @@ +/* + * 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 MultiplayerDebugHierarchyReporter + : public AZ::EntitySystemBus::Handler + { + public: + MultiplayerDebugHierarchyReporter(); + ~MultiplayerDebugHierarchyReporter() override; + + //! main update loop + void OnImGuiUpdate(); + + //! Draws bandwidth text over entities + void UpdateDebugOverlay(); + + //! EntitySystemBus overrides. + void OnEntityActivated(const AZ::EntityId& entityId) override; + void OnEntityDeactivated(const AZ::EntityId& entityId) override; + + private: + AZ::ScheduledEvent m_updateDebugOverlay; + + AzFramework::DebugDisplayRequests* m_debugDisplay = nullptr; + + struct HierarchyRootInfo + { + NetworkHierarchyRootComponent* m_rootComponent = nullptr; + NetworkHierarchyChangedEvent::Handler m_changedEvent; + NetworkHierarchyLeaveEvent::Handler m_leaveEvent; + }; + + AZStd::unordered_map m_hierarchyRoots; + void CollectHierarchyRoots(); + + char m_statusBuffer[100] = {}; + }; +} diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp index 422b2f0cae..b23bc677f0 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.cpp @@ -71,6 +71,7 @@ namespace Multiplayer ImGui::Checkbox("Networking Stats", &m_displayNetworkingStats); ImGui::Checkbox("Multiplayer Stats", &m_displayMultiplayerStats); ImGui::Checkbox("Multiplayer Entity Stats", &m_displayPerEntityStats); + ImGui::Checkbox("Multiplayer Hierarchy Debugger", &m_displayHierarchyDebugger); ImGui::EndMenu(); } } @@ -464,6 +465,29 @@ namespace Multiplayer } } } + + if (m_displayHierarchyDebugger) + { + if (ImGui::Begin("Multiplayer Hierarchy Debugger", &m_displayHierarchyDebugger)) + { + if (m_hierarchyDebugger == nullptr) + { + m_hierarchyDebugger = AZStd::make_unique(); + } + + if (m_hierarchyDebugger) + { + m_hierarchyDebugger->OnImGuiUpdate(); + } + } + } + else + { + if (m_hierarchyDebugger) + { + m_hierarchyDebugger.reset(); + } + } } #endif } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h index 7b3c852f58..9becf1543c 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugSystemComponent.h @@ -8,6 +8,8 @@ #pragma once +#include "MultiplayerDebugHierarchyReporter.h" + #include #include #include @@ -62,5 +64,8 @@ namespace Multiplayer bool m_displayPerEntityStats = false; AZStd::unique_ptr m_reporter; + + bool m_displayHierarchyDebugger = false; + AZStd::unique_ptr m_hierarchyDebugger; }; } diff --git a/Gems/Multiplayer/Code/multiplayer_debug_files.cmake b/Gems/Multiplayer/Code/multiplayer_debug_files.cmake index 37a1c91640..1d85dd8149 100644 --- a/Gems/Multiplayer/Code/multiplayer_debug_files.cmake +++ b/Gems/Multiplayer/Code/multiplayer_debug_files.cmake @@ -9,6 +9,8 @@ set(FILES Source/Debug/MultiplayerDebugByteReporter.cpp Source/Debug/MultiplayerDebugByteReporter.h + Source/Debug/MultiplayerDebugHierarchyReporter.cpp + Source/Debug/MultiplayerDebugHierarchyReporter.h Source/Debug/MultiplayerDebugPerEntityReporter.cpp Source/Debug/MultiplayerDebugPerEntityReporter.h Source/Debug/MultiplayerDebugModule.cpp From d1947c68c96e3b042851a20ad027266f44edc809 Mon Sep 17 00:00:00 2001 From: AMZN-AlexOteiza <82234181+AMZN-AlexOteiza@users.noreply.github.com> Date: Thu, 7 Oct 2021 13:29:09 +0100 Subject: [PATCH 029/169] Added extra output and callstack information for improving debugging automated tests (#4528) Signed-off-by: AMZN-AlexOteiza --- Code/Editor/CryEdit.cpp | 2 ++ Code/Framework/AzCore/AzCore/Debug/Trace.cpp | 2 ++ Code/Legacy/CrySystem/DebugCallStack.cpp | 3 +++ 3 files changed, 7 insertions(+) diff --git a/Code/Editor/CryEdit.cpp b/Code/Editor/CryEdit.cpp index 4aa3d22114..abba2bb9c6 100644 --- a/Code/Editor/CryEdit.cpp +++ b/Code/Editor/CryEdit.cpp @@ -2124,6 +2124,8 @@ bool CCryEditApp::FixDanglingSharedMemory(const QString& sharedMemName) const int CCryEditApp::ExitInstance(int exitCode) { + AZ_TracePrintf("Exit", "Called ExitInstance() with exit code: 0x%x", exitCode); + if (m_pEditor) { m_pEditor->OnBeginShutdownSequence(); diff --git a/Code/Framework/AzCore/AzCore/Debug/Trace.cpp b/Code/Framework/AzCore/AzCore/Debug/Trace.cpp index 14504cc282..3edcbaa273 100644 --- a/Code/Framework/AzCore/AzCore/Debug/Trace.cpp +++ b/Code/Framework/AzCore/AzCore/Debug/Trace.cpp @@ -224,6 +224,8 @@ namespace AZ void Debug::Trace::Terminate(int exitCode) { + AZ_TracePrintf("Exit", "Called Terminate() with exit code: 0x%x", exitCode); + AZ::Debug::Trace::PrintCallstack("Exit"); Platform::Terminate(exitCode); } diff --git a/Code/Legacy/CrySystem/DebugCallStack.cpp b/Code/Legacy/CrySystem/DebugCallStack.cpp index 8018e46d69..19fe4ce8df 100644 --- a/Code/Legacy/CrySystem/DebugCallStack.cpp +++ b/Code/Legacy/CrySystem/DebugCallStack.cpp @@ -222,6 +222,9 @@ void UpdateFPExceptionsMaskForThreads() ////////////////////////////////////////////////////////////////////////// int DebugCallStack::handleException(EXCEPTION_POINTERS* exception_pointer) { + AZ_TracePrintf("Exit", "Exception with exit code: 0x%x", exception_pointer->ExceptionRecord->ExceptionCode); + AZ::Debug::Trace::PrintCallstack("Exit"); + if (gEnv == NULL) { return EXCEPTION_EXECUTE_HANDLER; From a2c16fa24fb1f0f9509542b9f0404e2204454e1d Mon Sep 17 00:00:00 2001 From: rgba16f <82187279+rgba16f@users.noreply.github.com> Date: Thu, 7 Oct 2021 10:51:22 -0500 Subject: [PATCH 030/169] adjust the default number of worker threads created by the TaskGraph & Job systems Signed-off-by: rgba16f <82187279+rgba16f@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp | 2 +- .../Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp b/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp index e98711049c..59f9c5f6a2 100644 --- a/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp @@ -20,7 +20,7 @@ #include -AZ_CVAR(float, cl_jobThreadsConcurrencyRatio, 0.5f, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system multiplier on the number of hw threads the machine creates at initialization"); +AZ_CVAR(float, cl_jobThreadsConcurrencyRatio, 0.6f, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system multiplier on the number of hw threads the machine creates at initialization"); AZ_CVAR(uint32_t, cl_jobThreadsNumReserved, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system number of hardware threads that are reserved for O3DE system threads"); AZ_CVAR(uint32_t, cl_jobThreadsMinNumber, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system minimum number of worker threads to create after scaling the number of hw threads"); diff --git a/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp index 6548d9d162..5ae0fb0394 100644 --- a/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp @@ -15,7 +15,7 @@ // Create a cvar as a central location for experimentation with switching from the Job system to TaskGraph system. AZ_CVAR(bool, cl_activateTaskGraph, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Flag clients of TaskGraph to switch between jobs/taskgraph (Note does not disable task graph system)"); -AZ_CVAR(float, cl_taskGraphThreadsConcurrencyRatio, 0.75f, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph calculate the number of worker threads to spawn by scaling the number of hw threads, value is clamped between 0.0f and 1.0f"); +AZ_CVAR(float, cl_taskGraphThreadsConcurrencyRatio, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph calculate the number of worker threads to spawn by scaling the number of hw threads, value is clamped between 0.0f and 1.0f"); AZ_CVAR(uint32_t, cl_taskGraphThreadsNumReserved, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph number of hardware threads that are reserved for O3DE system threads"); AZ_CVAR(uint32_t, cl_taskGraphThreadsMinNumber, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph minimum number of worker threads to create after scaling the number of hw threads"); @@ -33,7 +33,7 @@ namespace AZ // min = cl_taskGraphThreadsMinNumber, // max = number of hardware threads - cl_taskGraphThreadsNumReserved uint32_t scaledHardwareThreads = AZ::GetMax( cl_taskGraphThreadsMinNumber, static_cast(AZStd::floor( 0.5f + AZ::GetClamp(cl_taskGraphThreadsConcurrencyRatio, 0.0f, 1.0f) * static_cast(AZStd::thread::hardware_concurrency() - cl_taskGraphThreadsNumReserved)))); - m_taskExecutor = aznew TaskExecutor(scaledHardwareThreads); + m_taskExecutor = aznew TaskExecutor(scaledHardwareThreads); TaskExecutor::SetInstance(m_taskExecutor); Interface::Register(this); } From 863a7c8382d484378ffc648324cb993eb7e8fd2a Mon Sep 17 00:00:00 2001 From: John Date: Thu, 7 Oct 2021 17:19:22 +0100 Subject: [PATCH 031/169] Address PR comments. Signed-off-by: John --- Code/Editor/Core/LevelEditorMenuHandler.cpp | 12 ++++++------ Code/Editor/QtViewPaneManager.h | 2 +- .../API/ComponentModeCollectionInterface.h | 3 ++- .../API/ViewportEditorModeTrackerNotificationBus.cpp | 2 +- .../ComponentMode/ComponentModeCollection.cpp | 5 +++-- .../ComponentMode/ComponentModeCollection.h | 2 +- .../UI/PropertyEditor/EntityPropertyEditor.cpp | 4 ++-- 7 files changed, 16 insertions(+), 14 deletions(-) diff --git a/Code/Editor/Core/LevelEditorMenuHandler.cpp b/Code/Editor/Core/LevelEditorMenuHandler.cpp index 25467756ac..ec92622f02 100644 --- a/Code/Editor/Core/LevelEditorMenuHandler.cpp +++ b/Code/Editor/Core/LevelEditorMenuHandler.cpp @@ -1191,8 +1191,8 @@ void LevelEditorMenuHandler::OnEditorModeActivated( { if (mode == ViewportEditorMode::Component) { - auto menuWrapper = m_actionManager->FindMenu(s_editMenuId); - if (!menuWrapper.isNull()) + if (auto menuWrapper = m_actionManager->FindMenu(s_editMenuId); + !menuWrapper.isNull()) { // copy of menu actions auto actions = menuWrapper.Get()->actions(); @@ -1222,8 +1222,8 @@ void LevelEditorMenuHandler::OnEditorModeDeactivated( void LevelEditorMenuHandler::AddEditMenuAction(QAction* action) { - auto menuWrapper = m_actionManager->FindMenu(s_editMenuId); - if (!menuWrapper.isNull()) + if (auto menuWrapper = m_actionManager->FindMenu(s_editMenuId); + !menuWrapper.isNull()) { menuWrapper.Get()->addAction(action); } @@ -1247,8 +1247,8 @@ void LevelEditorMenuHandler::AddMenuAction(AZStd::string_view categoryId, QActio void LevelEditorMenuHandler::RestoreEditMenuToDefault() { - auto menuWrapper = m_actionManager->FindMenu(s_editMenuId); - if (!menuWrapper.isNull()) + if (auto menuWrapper = m_actionManager->FindMenu(s_editMenuId); + !menuWrapper.isNull()) { menuWrapper.Get()->clear(); PopulateEditMenu(menuWrapper); diff --git a/Code/Editor/QtViewPaneManager.h b/Code/Editor/QtViewPaneManager.h index fe568e5438..0515ae726e 100644 --- a/Code/Editor/QtViewPaneManager.h +++ b/Code/Editor/QtViewPaneManager.h @@ -247,7 +247,7 @@ private: AZStd::unique_ptr m_componentModeNotifications; //!< Helper for EditorComponentModeNotificationBus so - //!< QtViewPaneManager does not need to inherit directly from it. */ + //!< QtViewPaneManager does not need to inherit directly from it. */ using EditorWindowRequestBusImpl = AzToolsFramework::EditorWindowRequestBusImpl; EditorWindowRequestBusImpl m_windowRequest; //!< Helper for EditorWindowRequestBus so diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ComponentModeCollectionInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ComponentModeCollectionInterface.h index 39cd6bd6a3..4f9d72cb4d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ComponentModeCollectionInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ComponentModeCollectionInterface.h @@ -23,6 +23,7 @@ namespace AzToolsFramework virtual ~ComponentModeCollectionInterface() = default; //! Retrieves the list of all Component types (usually one). - virtual const AZStd::vector& GetComponentTypes() const = 0; + //! @note If called outside of component mode, an empty vector will be returned. + virtual AZStd::vector GetComponentTypes() const = 0; }; } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.cpp index 278f9db950..a61ea088d0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/API/ViewportEditorModeTrackerNotificationBus.cpp @@ -13,7 +13,7 @@ namespace AzToolsFramework { void ViewportEditorModeNotifications::Reflect(AZ::ReflectContext* context) { - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) + if (auto* behaviorContext = azrtti_cast(context)) { behaviorContext->EBus("ViewportEditorModeNotificationsBus") ->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.cpp index e816c0ce4c..1768cb5920 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.cpp @@ -203,9 +203,10 @@ namespace AzToolsFramework } } - const AZStd::vector& ComponentModeCollection::GetComponentTypes() const + AZStd::vector ComponentModeCollection::GetComponentTypes() const { - return m_activeComponentTypes; + // If in component mode, return the active component types, otherwise return an empty vector + return InComponentMode() ? m_activeComponentTypes : AZStd::vector{}; } void ComponentModeCollection::BeginComponentMode() diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.h index fb35ca8971..3b7690b969 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ComponentMode/ComponentModeCollection.h @@ -92,7 +92,7 @@ namespace AzToolsFramework void PopulateViewportUi(); // ComponentModeCollectionInterface overrides ... - const AZStd::vector& GetComponentTypes() const override; + AZStd::vector GetComponentTypes() const override; private: // Internal helper used by Select[|Prev|Next]ActiveComponentMode diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp index ad62614770..9ffe8021e3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/EntityPropertyEditor.cpp @@ -5710,7 +5710,7 @@ namespace AzToolsFramework { DisableComponentActions(this, m_entityComponentActions); SetPropertyEditorState(m_gui, false); - const auto& componentModeTypes = m_componentModeCollection->GetComponentTypes(); + const auto componentModeTypes = m_componentModeCollection->GetComponentTypes(); m_disabled = true; if (!componentModeTypes.empty()) @@ -5735,7 +5735,7 @@ namespace AzToolsFramework { EnableComponentActions(this, m_entityComponentActions); SetPropertyEditorState(m_gui, true); - const auto& componentModeTypes = m_componentModeCollection->GetComponentTypes(); + const auto componentModeTypes = m_componentModeCollection->GetComponentTypes(); m_disabled = false; for (auto componentEditor : m_componentEditors) From a114077e726c95fbb21721ce4c7eb4fb2b7145ce Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Thu, 7 Oct 2021 12:53:33 -0400 Subject: [PATCH 032/169] Final touches on the first pass of imgui hierarchy debugger Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../MultiplayerDebugHierarchyDebugger.cpp | 198 ++++++++++++++++++ .../Debug/MultiplayerDebugHierarchyDebugger.h | 55 +++++ .../MultiplayerDebugHierarchyReporter.cpp | 45 +++- .../Debug/MultiplayerDebugHierarchyReporter.h | 13 +- 4 files changed, 298 insertions(+), 13 deletions(-) create mode 100644 Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyDebugger.cpp create mode 100644 Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyDebugger.h diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyDebugger.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyDebugger.cpp new file mode 100644 index 0000000000..393f67474b --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyDebugger.cpp @@ -0,0 +1,198 @@ +/* + * 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 "MultiplayerDebugHierarchyDebugger.h" + +#include +#include +#include +#include + +#if defined(IMGUI_ENABLED) +#include +#endif + +namespace Multiplayer +{ + MultiplayerDebugHierarchyReporter::MultiplayerDebugHierarchyReporter() + : m_updateDebugOverlay([this]() { UpdateDebugOverlay(); }, AZ::Name("UpdateHierarchyDebug")) + { + CollectHierarchyRoots(); + + AZ::EntitySystemBus::Handler::BusConnect(); + m_updateDebugOverlay.Enqueue(AZ::TimeMs{ 0 }, true); + } + + MultiplayerDebugHierarchyReporter::~MultiplayerDebugHierarchyReporter() + { + AZ::EntitySystemBus::Handler::BusDisconnect(); + } + + // -------------------------------------------------------------------------------------------- + void MultiplayerDebugHierarchyReporter::OnImGuiUpdate() + { +#if defined(IMGUI_ENABLED) + for (const auto& root : m_hierarchyRoots) + { + if (const auto* rootComponent = root.second.m_rootComponent) + { + if (rootComponent->IsHierarchicalRoot()) + { + const AZStd::vector& hierarchicalChildren = rootComponent->GetHierarchicalEntities(); + + if (ImGui::TreeNode(rootComponent->GetEntity()->GetName().c_str(), + "Hierarchy, Root entity name [%s]: %4zu members", + rootComponent->GetEntity()->GetName().c_str(), + hierarchicalChildren.size())) + { + ImGui::Separator(); + ImGui::Columns(4, "hierarchy_columns"); + ImGui::Text("EntityId"); + ImGui::NextColumn(); + ImGui::Text("NetEntityId"); + ImGui::NextColumn(); + ImGui::Text("Entity Name"); + ImGui::NextColumn(); + ImGui::Text("Role"); + ImGui::NextColumn(); + + ImGui::Separator(); + ImGui::Columns(4, "hierarchy child info"); + + bool firstEntity = true; + for (const AZ::Entity* entity : hierarchicalChildren) + { + ImGui::Text("%s", entity->GetId().ToString().c_str()); + ImGui::NextColumn(); + ImGui::Text("%u", GetMultiplayer()->GetNetworkEntityManager()->GetNetEntityIdById(entity->GetId())); + ImGui::NextColumn(); + ImGui::Text("%s", entity->GetName().c_str()); + ImGui::NextColumn(); + + if (firstEntity) + { + ImGui::Text("Root node"); + } + else if (entity->FindComponent()) + { + ImGui::Text("Inner root node"); + } + else if (entity->FindComponent()) + { + ImGui::Text("Child node"); + } + ImGui::NextColumn(); + + firstEntity = false; + } + + ImGui::Columns(1); + ImGui::TreePop(); + } + } + } + } +#endif + } + + + void MultiplayerDebugHierarchyReporter::UpdateDebugOverlay() + { + if (!m_hierarchyRoots.empty()) + { + if (m_debugDisplay == nullptr) + { + AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus; + AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId); + m_debugDisplay = AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus); + } + + const AZ::u32 stateBefore = m_debugDisplay->GetState(); + m_debugDisplay->SetColor(AZ::Colors::White); + + for (const auto& root : m_hierarchyRoots) + { + if (const auto* rootComponent = root.second.m_rootComponent) + { + if (rootComponent->IsHierarchicalRoot()) + { + const AZStd::vector& hierarchicalChildren = rootComponent->GetHierarchicalEntities(); + + azsprintf(m_statusBuffer, "Hierarchy [%s] %u members", rootComponent->GetEntity()->GetName().c_str(), + aznumeric_cast(hierarchicalChildren.size())); + + AZ::Vector3 entityPosition = rootComponent->GetEntity()->GetTransform()->GetWorldTranslation(); + constexpr bool centerText = true; + m_debugDisplay->DrawTextLabel(entityPosition, 1.0f, m_statusBuffer, centerText, 0, 0); + } + } + } + + m_debugDisplay->SetState(stateBefore); + } + } + + void MultiplayerDebugHierarchyReporter::OnEntityActivated(const AZ::EntityId& entityId) + { + if (const AZ::Entity* childEntity = AZ::Interface::Get()->FindEntity(entityId)) + { + if (auto* rootComponent = childEntity->FindComponent()) + { + HierarchyRootInfo info; + info.m_rootComponent = rootComponent; + rootComponent->BindNetworkHierarchyChangedEventHandler(info.m_changedEvent); + rootComponent->BindNetworkHierarchyLeaveEventHandler(info.m_leaveEvent); + + m_hierarchyRoots.insert(AZStd::make_pair(rootComponent, info)); + } + } + } + + void MultiplayerDebugHierarchyReporter::OnEntityDeactivated(const AZ::EntityId& entityId) + { + if (const AZ::Entity* childEntity = AZ::Interface::Get()->FindEntity(entityId)) + { + if (auto* rootComponent = childEntity->FindComponent()) + { + m_hierarchyRoots.erase(rootComponent); + } + } + } + + void MultiplayerDebugHierarchyReporter::CollectHierarchyRoots() + { + AZStd::vector gatheredEntries; + const AZ::Sphere awarenessSphere = AZ::Sphere(AZ::Vector3::CreateZero(), 1000.f); + AZ::Interface::Get()->GetDefaultVisibilityScene()->Enumerate(awarenessSphere, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) + { + gatheredEntries.reserve(gatheredEntries.size() + nodeData.m_entries.size()); + for (AzFramework::VisibilityEntry* visEntry : nodeData.m_entries) + { + if (visEntry->m_typeFlags & AzFramework::VisibilityEntry::TypeFlags::TYPE_Entity) + { + gatheredEntries.push_back(visEntry); + } + } + } + ); + + for (const AzFramework::VisibilityEntry* entry : gatheredEntries) + { + const AZ::Entity* entity = static_cast(entry->m_userData); + if (auto* rootComponent = entity->FindComponent()) + { + HierarchyRootInfo info; + info.m_rootComponent = rootComponent; + rootComponent->BindNetworkHierarchyChangedEventHandler(info.m_changedEvent); + rootComponent->BindNetworkHierarchyLeaveEventHandler(info.m_leaveEvent); + + m_hierarchyRoots.insert(AZStd::make_pair(rootComponent, info)); + } + } + } +} diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyDebugger.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyDebugger.h new file mode 100644 index 0000000000..978664b96b --- /dev/null +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyDebugger.h @@ -0,0 +1,55 @@ +/* + * 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 +{ + /** + * \brief Reports hierarchy information in the scene. + */ + class MultiplayerDebugHierarchyReporter + : public AZ::EntitySystemBus::Handler + { + public: + MultiplayerDebugHierarchyReporter(); + ~MultiplayerDebugHierarchyReporter() override; + + //! main update loop + void OnImGuiUpdate(); + + //! Draws hierarchy information over hierarchy root entities + void UpdateDebugOverlay(); + + //! EntitySystemBus overrides. + void OnEntityActivated(const AZ::EntityId& entityId) override; + void OnEntityDeactivated(const AZ::EntityId& entityId) override; + + private: + AZ::ScheduledEvent m_updateDebugOverlay; + + AzFramework::DebugDisplayRequests* m_debugDisplay = nullptr; + + struct HierarchyRootInfo + { + NetworkHierarchyRootComponent* m_rootComponent = nullptr; + NetworkHierarchyChangedEvent::Handler m_changedEvent; + NetworkHierarchyLeaveEvent::Handler m_leaveEvent; + }; + + AZStd::unordered_map m_hierarchyRoots; + void CollectHierarchyRoots(); + + char m_statusBuffer[100] = {}; + }; +} diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyReporter.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyReporter.cpp index 32e9a776a4..7c38a340eb 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyReporter.cpp +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyReporter.cpp @@ -8,6 +8,8 @@ #include "MultiplayerDebugHierarchyReporter.h" +#include +#include #include #include #include @@ -17,8 +19,6 @@ #include #endif -#pragma optimize("", off) - namespace Multiplayer { MultiplayerDebugHierarchyReporter::MultiplayerDebugHierarchyReporter() @@ -39,6 +39,9 @@ namespace Multiplayer void MultiplayerDebugHierarchyReporter::OnImGuiUpdate() { #if defined(IMGUI_ENABLED) + ImGui::Text("Hierarchies"); + ImGui::Separator(); + for (const auto& root : m_hierarchyRoots) { if (const auto* rootComponent = root.second.m_rootComponent) @@ -48,7 +51,7 @@ namespace Multiplayer const AZStd::vector& hierarchicalChildren = rootComponent->GetHierarchicalEntities(); if (ImGui::TreeNode(rootComponent->GetEntity()->GetName().c_str(), - "Hierarchy, Root entity name [%s]: %4zu members", + "[%s] %4zu members", rootComponent->GetEntity()->GetName().c_str(), hierarchicalChildren.size())) { @@ -99,6 +102,16 @@ namespace Multiplayer } } } + + ImGui::Separator(); + if (ImGui::InputFloat("Awareness Radius", &m_awarenessRadius)) + { + CollectHierarchyRoots(); + } + if (ImGui::Button("Refresh")) + { + CollectHierarchyRoots(); + } #endif } @@ -168,9 +181,18 @@ namespace Multiplayer void MultiplayerDebugHierarchyReporter::CollectHierarchyRoots() { + m_hierarchyRoots.clear(); + AZ::Sphere awarenessSphere(AZ::Vector3::CreateZero(), m_awarenessRadius); + + const auto viewportContextManager = AZ::Interface::Get(); + if (const auto viewportContext = viewportContextManager->GetDefaultViewportContext()) + { + awarenessSphere.SetCenter(viewportContext->GetCameraTransform().GetTranslation()); + } + AZStd::vector gatheredEntries; - const AZ::Sphere awarenessSphere = AZ::Sphere(AZ::Vector3::CreateZero(), 1000.f); - AZ::Interface::Get()->GetDefaultVisibilityScene()->Enumerate(awarenessSphere, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) + AZ::Interface::Get()->GetDefaultVisibilityScene()->Enumerate(awarenessSphere, + [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) { gatheredEntries.reserve(gatheredEntries.size() + nodeData.m_entries.size()); for (AzFramework::VisibilityEntry* visEntry : nodeData.m_entries) @@ -188,12 +210,15 @@ namespace Multiplayer const AZ::Entity* entity = static_cast(entry->m_userData); if (auto* rootComponent = entity->FindComponent()) { - HierarchyRootInfo info; - info.m_rootComponent = rootComponent; - rootComponent->BindNetworkHierarchyChangedEventHandler(info.m_changedEvent); - rootComponent->BindNetworkHierarchyLeaveEventHandler(info.m_leaveEvent); + if (awarenessSphere.GetCenter().GetDistanceEstimate(entity->GetTransform()->GetWorldTranslation()) < m_awarenessRadius) + { + HierarchyRootInfo info; + info.m_rootComponent = rootComponent; + rootComponent->BindNetworkHierarchyChangedEventHandler(info.m_changedEvent); + rootComponent->BindNetworkHierarchyLeaveEventHandler(info.m_leaveEvent); - m_hierarchyRoots.insert(AZStd::make_pair(rootComponent, info)); + m_hierarchyRoots.insert(AZStd::make_pair(rootComponent, info)); + } } } } diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyReporter.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyReporter.h index 98a131614c..2ce7e055a0 100644 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyReporter.h +++ b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyReporter.h @@ -15,6 +15,9 @@ namespace Multiplayer { + /** + * /brief Provides ImGui and debug draw hierarchy information at runtime. + */ class MultiplayerDebugHierarchyReporter : public AZ::EntitySystemBus::Handler { @@ -22,15 +25,17 @@ namespace Multiplayer MultiplayerDebugHierarchyReporter(); ~MultiplayerDebugHierarchyReporter() override; - //! main update loop + //! Main update loop. void OnImGuiUpdate(); - //! Draws bandwidth text over entities + //! Draws hierarchy information over hierarchy root entities. void UpdateDebugOverlay(); //! EntitySystemBus overrides. + //! @{ void OnEntityActivated(const AZ::EntityId& entityId) override; void OnEntityDeactivated(const AZ::EntityId& entityId) override; + //! @} private: AZ::ScheduledEvent m_updateDebugOverlay; @@ -46,7 +51,9 @@ namespace Multiplayer AZStd::unordered_map m_hierarchyRoots; void CollectHierarchyRoots(); - + char m_statusBuffer[100] = {}; + + float m_awarenessRadius = 1000.f; }; } From ecd358a53e76a2d66f538d24975142900d1a0b1a Mon Sep 17 00:00:00 2001 From: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> Date: Thu, 7 Oct 2021 12:56:44 -0400 Subject: [PATCH 033/169] Cleaning up Signed-off-by: AMZN-Olex <5432499+AMZN-Olex@users.noreply.github.com> --- .../MultiplayerDebugHierarchyDebugger.cpp | 198 ------------------ .../Debug/MultiplayerDebugHierarchyDebugger.h | 55 ----- 2 files changed, 253 deletions(-) delete mode 100644 Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyDebugger.cpp delete mode 100644 Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyDebugger.h diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyDebugger.cpp b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyDebugger.cpp deleted file mode 100644 index 393f67474b..0000000000 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyDebugger.cpp +++ /dev/null @@ -1,198 +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 "MultiplayerDebugHierarchyDebugger.h" - -#include -#include -#include -#include - -#if defined(IMGUI_ENABLED) -#include -#endif - -namespace Multiplayer -{ - MultiplayerDebugHierarchyReporter::MultiplayerDebugHierarchyReporter() - : m_updateDebugOverlay([this]() { UpdateDebugOverlay(); }, AZ::Name("UpdateHierarchyDebug")) - { - CollectHierarchyRoots(); - - AZ::EntitySystemBus::Handler::BusConnect(); - m_updateDebugOverlay.Enqueue(AZ::TimeMs{ 0 }, true); - } - - MultiplayerDebugHierarchyReporter::~MultiplayerDebugHierarchyReporter() - { - AZ::EntitySystemBus::Handler::BusDisconnect(); - } - - // -------------------------------------------------------------------------------------------- - void MultiplayerDebugHierarchyReporter::OnImGuiUpdate() - { -#if defined(IMGUI_ENABLED) - for (const auto& root : m_hierarchyRoots) - { - if (const auto* rootComponent = root.second.m_rootComponent) - { - if (rootComponent->IsHierarchicalRoot()) - { - const AZStd::vector& hierarchicalChildren = rootComponent->GetHierarchicalEntities(); - - if (ImGui::TreeNode(rootComponent->GetEntity()->GetName().c_str(), - "Hierarchy, Root entity name [%s]: %4zu members", - rootComponent->GetEntity()->GetName().c_str(), - hierarchicalChildren.size())) - { - ImGui::Separator(); - ImGui::Columns(4, "hierarchy_columns"); - ImGui::Text("EntityId"); - ImGui::NextColumn(); - ImGui::Text("NetEntityId"); - ImGui::NextColumn(); - ImGui::Text("Entity Name"); - ImGui::NextColumn(); - ImGui::Text("Role"); - ImGui::NextColumn(); - - ImGui::Separator(); - ImGui::Columns(4, "hierarchy child info"); - - bool firstEntity = true; - for (const AZ::Entity* entity : hierarchicalChildren) - { - ImGui::Text("%s", entity->GetId().ToString().c_str()); - ImGui::NextColumn(); - ImGui::Text("%u", GetMultiplayer()->GetNetworkEntityManager()->GetNetEntityIdById(entity->GetId())); - ImGui::NextColumn(); - ImGui::Text("%s", entity->GetName().c_str()); - ImGui::NextColumn(); - - if (firstEntity) - { - ImGui::Text("Root node"); - } - else if (entity->FindComponent()) - { - ImGui::Text("Inner root node"); - } - else if (entity->FindComponent()) - { - ImGui::Text("Child node"); - } - ImGui::NextColumn(); - - firstEntity = false; - } - - ImGui::Columns(1); - ImGui::TreePop(); - } - } - } - } -#endif - } - - - void MultiplayerDebugHierarchyReporter::UpdateDebugOverlay() - { - if (!m_hierarchyRoots.empty()) - { - if (m_debugDisplay == nullptr) - { - AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus; - AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId); - m_debugDisplay = AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus); - } - - const AZ::u32 stateBefore = m_debugDisplay->GetState(); - m_debugDisplay->SetColor(AZ::Colors::White); - - for (const auto& root : m_hierarchyRoots) - { - if (const auto* rootComponent = root.second.m_rootComponent) - { - if (rootComponent->IsHierarchicalRoot()) - { - const AZStd::vector& hierarchicalChildren = rootComponent->GetHierarchicalEntities(); - - azsprintf(m_statusBuffer, "Hierarchy [%s] %u members", rootComponent->GetEntity()->GetName().c_str(), - aznumeric_cast(hierarchicalChildren.size())); - - AZ::Vector3 entityPosition = rootComponent->GetEntity()->GetTransform()->GetWorldTranslation(); - constexpr bool centerText = true; - m_debugDisplay->DrawTextLabel(entityPosition, 1.0f, m_statusBuffer, centerText, 0, 0); - } - } - } - - m_debugDisplay->SetState(stateBefore); - } - } - - void MultiplayerDebugHierarchyReporter::OnEntityActivated(const AZ::EntityId& entityId) - { - if (const AZ::Entity* childEntity = AZ::Interface::Get()->FindEntity(entityId)) - { - if (auto* rootComponent = childEntity->FindComponent()) - { - HierarchyRootInfo info; - info.m_rootComponent = rootComponent; - rootComponent->BindNetworkHierarchyChangedEventHandler(info.m_changedEvent); - rootComponent->BindNetworkHierarchyLeaveEventHandler(info.m_leaveEvent); - - m_hierarchyRoots.insert(AZStd::make_pair(rootComponent, info)); - } - } - } - - void MultiplayerDebugHierarchyReporter::OnEntityDeactivated(const AZ::EntityId& entityId) - { - if (const AZ::Entity* childEntity = AZ::Interface::Get()->FindEntity(entityId)) - { - if (auto* rootComponent = childEntity->FindComponent()) - { - m_hierarchyRoots.erase(rootComponent); - } - } - } - - void MultiplayerDebugHierarchyReporter::CollectHierarchyRoots() - { - AZStd::vector gatheredEntries; - const AZ::Sphere awarenessSphere = AZ::Sphere(AZ::Vector3::CreateZero(), 1000.f); - AZ::Interface::Get()->GetDefaultVisibilityScene()->Enumerate(awarenessSphere, [&gatheredEntries](const AzFramework::IVisibilityScene::NodeData& nodeData) - { - gatheredEntries.reserve(gatheredEntries.size() + nodeData.m_entries.size()); - for (AzFramework::VisibilityEntry* visEntry : nodeData.m_entries) - { - if (visEntry->m_typeFlags & AzFramework::VisibilityEntry::TypeFlags::TYPE_Entity) - { - gatheredEntries.push_back(visEntry); - } - } - } - ); - - for (const AzFramework::VisibilityEntry* entry : gatheredEntries) - { - const AZ::Entity* entity = static_cast(entry->m_userData); - if (auto* rootComponent = entity->FindComponent()) - { - HierarchyRootInfo info; - info.m_rootComponent = rootComponent; - rootComponent->BindNetworkHierarchyChangedEventHandler(info.m_changedEvent); - rootComponent->BindNetworkHierarchyLeaveEventHandler(info.m_leaveEvent); - - m_hierarchyRoots.insert(AZStd::make_pair(rootComponent, info)); - } - } - } -} diff --git a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyDebugger.h b/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyDebugger.h deleted file mode 100644 index 978664b96b..0000000000 --- a/Gems/Multiplayer/Code/Source/Debug/MultiplayerDebugHierarchyDebugger.h +++ /dev/null @@ -1,55 +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 -{ - /** - * \brief Reports hierarchy information in the scene. - */ - class MultiplayerDebugHierarchyReporter - : public AZ::EntitySystemBus::Handler - { - public: - MultiplayerDebugHierarchyReporter(); - ~MultiplayerDebugHierarchyReporter() override; - - //! main update loop - void OnImGuiUpdate(); - - //! Draws hierarchy information over hierarchy root entities - void UpdateDebugOverlay(); - - //! EntitySystemBus overrides. - void OnEntityActivated(const AZ::EntityId& entityId) override; - void OnEntityDeactivated(const AZ::EntityId& entityId) override; - - private: - AZ::ScheduledEvent m_updateDebugOverlay; - - AzFramework::DebugDisplayRequests* m_debugDisplay = nullptr; - - struct HierarchyRootInfo - { - NetworkHierarchyRootComponent* m_rootComponent = nullptr; - NetworkHierarchyChangedEvent::Handler m_changedEvent; - NetworkHierarchyLeaveEvent::Handler m_leaveEvent; - }; - - AZStd::unordered_map m_hierarchyRoots; - void CollectHierarchyRoots(); - - char m_statusBuffer[100] = {}; - }; -} From cdca77acd1f5d5f9748d1ac0fc9fce2874c08cfc Mon Sep 17 00:00:00 2001 From: smurly Date: Thu, 7 Oct 2021 10:56:10 -0700 Subject: [PATCH 034/169] Reflection Probe component test for parallel execution (#4532) Signed-off-by: Scott Murray --- .../Atom/TestSuite_Main_Optimized.py | 3 + ...omEditorComponents_ReflectionProbeAdded.py | 194 ++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_ReflectionProbeAdded.py diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py index 47b2204d56..f5ac411a01 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py @@ -42,5 +42,8 @@ class TestAutomation(EditorTestSuite): class AtomEditorComponents_DisplayMapperAdded(EditorSharedTest): from Atom.tests import hydra_AtomEditorComponents_DisplayMapperAdded as test_module + class AtomEditorComponents_ReflectionProbeAdded(EditorSharedTest): + from Atom.tests import hydra_AtomEditorComponents_ReflectionProbeAdded as test_module + class ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges(EditorSharedTest): from Atom.tests import hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges as test_module diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_ReflectionProbeAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_ReflectionProbeAdded.py new file mode 100644 index 0000000000..9b13eb2c7e --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_ReflectionProbeAdded.py @@ -0,0 +1,194 @@ +""" +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 +""" + +class Tests: + creation_undo = ( + "UNDO Entity creation success", + "UNDO Entity creation failed") + creation_redo = ( + "REDO Entity creation success", + "REDO Entity creation failed") + reflection_probe_creation = ( + "Reflection Probe Entity successfully created", + "Reflection Probe Entity failed to be created") + reflection_probe_component = ( + "Entity has a Reflection Probe component", + "Entity failed to find Reflection Probe component") + reflection_probe_disabled = ( + "Reflection Probe component disabled", + "Reflection Probe component was not disabled.") + reflection_map_generated = ( + "Reflection Probe cubemap generated", + "Reflection Probe cubemap not generated") + box_shape_component = ( + "Entity has a Box Shape component", + "Entity did not have a Box Shape component") + reflection_probe_enabled = ( + "Reflection Probe component enabled", + "Reflection Probe component was not enabled.") + enter_game_mode = ( + "Entered game mode", + "Failed to enter game mode") + exit_game_mode = ( + "Exited game mode", + "Couldn't exit game mode") + is_visible = ( + "Entity is visible", + "Entity was not visible") + is_hidden = ( + "Entity is hidden", + "Entity was not hidden") + entity_deleted = ( + "Entity deleted", + "Entity was not deleted") + deletion_undo = ( + "UNDO deletion success", + "UNDO deletion failed") + deletion_redo = ( + "REDO deletion success", + "REDO deletion failed") + + +def AtomEditorComponents_ReflectionProbe_AddedToEntity(): + """ + Summary: + Tests the Reflection Probe component can be added to an entity and has the expected functionality. + + Test setup: + - Wait for Editor idle loop. + - Open the "Base" level. + + Expected Behavior: + The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components. + Creation and deletion undo/redo should also work. + + Test Steps: + 1) Create a Reflection Probe entity with no components. + 2) Add a Reflection Probe component to Reflection Probe entity. + 3) UNDO the entity creation and component addition. + 4) REDO the entity creation and component addition. + 5) Verify Reflection Probe component not enabled. + 6) Add Shape component since it is required by the Reflection Probe component. + 7) Verify Reflection Probe component is enabled. + 8) Enter/Exit game mode. + 9) Test IsHidden. + 10) Test IsVisible. + 11) Verify cubemap generation + 12) Delete Reflection Probe entity. + 13) UNDO deletion. + 14) REDO deletion. + 15) Look for errors. + + :return: None + """ + + import azlmbr.legacy.general as general + import azlmbr.math as math + import azlmbr.render as render + + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper + + with Tracer() as error_tracer: + # Test setup begins. + # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level. + helper.init_idle() + helper.open_level("", "Base") + + # Test steps begin. + # 1. Create a Reflection Probe entity with no components. + reflection_probe_name = "Reflection Probe" + reflection_probe_entity = EditorEntity.create_editor_entity_at( + math.Vector3(512.0, 512.0, 34.0), reflection_probe_name) + Report.critical_result(Tests.reflection_probe_creation, reflection_probe_entity.exists()) + + # 2. Add a Reflection Probe component to Reflection Probe entity. + reflection_probe_component = reflection_probe_entity.add_component(reflection_probe_name) + Report.critical_result( + Tests.reflection_probe_component, + reflection_probe_entity.has_component(reflection_probe_name)) + + # 3. UNDO the entity creation and component addition. + # -> UNDO component addition. + general.undo() + # -> UNDO naming entity. + general.undo() + # -> UNDO selecting entity. + general.undo() + # -> UNDO entity creation. + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.creation_undo, not reflection_probe_entity.exists()) + + # 4. REDO the entity creation and component addition. + # -> REDO entity creation. + general.redo() + # -> REDO selecting entity. + general.redo() + # -> REDO naming entity. + general.redo() + # -> REDO component addition. + general.redo() + general.idle_wait_frames(1) + Report.result(Tests.creation_redo, reflection_probe_entity.exists()) + + # 5. Verify Reflection Probe component not enabled. + Report.result(Tests.reflection_probe_disabled, not reflection_probe_component.is_enabled()) + + # 6. Add Box Shape component since it is required by the Reflection Probe component. + box_shape = "Box Shape" + reflection_probe_entity.add_component(box_shape) + Report.result(Tests.box_shape_component, reflection_probe_entity.has_component(box_shape)) + + # 7. Verify Reflection Probe component is enabled. + Report.result(Tests.reflection_probe_enabled, reflection_probe_component.is_enabled()) + + # 8. Enter/Exit game mode. + helper.enter_game_mode(Tests.enter_game_mode) + general.idle_wait_frames(1) + helper.exit_game_mode(Tests.exit_game_mode) + + # 9. Test IsHidden. + reflection_probe_entity.set_visibility_state(False) + Report.result(Tests.is_hidden, reflection_probe_entity.is_hidden() is True) + + # 10. Test IsVisible. + reflection_probe_entity.set_visibility_state(True) + general.idle_wait_frames(1) + Report.result(Tests.is_visible, reflection_probe_entity.is_visible() is True) + + # 11. Verify cubemap generation + render.EditorReflectionProbeBus(azlmbr.bus.Event, "BakeReflectionProbe", reflection_probe_entity.id) + Report.result( + Tests.reflection_map_generated, + helper.wait_for_condition( + lambda: reflection_probe_component.get_component_property_value("Cubemap|Baked Cubemap Path") != "", + 20.0)) + + # 12. Delete Reflection Probe entity. + reflection_probe_entity.delete() + Report.result(Tests.entity_deleted, not reflection_probe_entity.exists()) + + # 13. UNDO deletion. + general.undo() + Report.result(Tests.deletion_undo, reflection_probe_entity.exists()) + + # 14. REDO deletion. + general.redo() + Report.result(Tests.deletion_redo, not reflection_probe_entity.exists()) + + # 15. Look for errors or asserts. + helper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0) + for error_info in error_tracer.errors: + Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}") + for assert_info in error_tracer.asserts: + Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}") + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(AtomEditorComponents_ReflectionProbe_AddedToEntity) From 5f83485a1d51100dd5662a821a5485b38f5ffd4a Mon Sep 17 00:00:00 2001 From: jiaweig <51759646+jiaweig-amzn@users.noreply.github.com> Date: Thu, 7 Oct 2021 11:00:28 -0700 Subject: [PATCH 035/169] PALify driver info. No warnings if info is empty. (#4533) Signed-off-by: jiaweig --- .../RHI.Reflect/PhysicalDeviceDescriptor.cpp | 7 ++++++ .../Android/PhysicalDeviceDriverInfo.setreg | 23 +++++++++++++++++++ .../Linux/PhysicalDeviceDriverInfo.setreg | 23 +++++++++++++++++++ .../Mac/PhysicalDeviceDriverInfo.setreg | 23 +++++++++++++++++++ .../Windows}/PhysicalDeviceDriverInfo.setreg | 0 .../iOS/PhysicalDeviceDriverInfo.setreg | 23 +++++++++++++++++++ 6 files changed, 99 insertions(+) create mode 100644 Gems/Atom/RHI/Registry/Platform/Android/PhysicalDeviceDriverInfo.setreg create mode 100644 Gems/Atom/RHI/Registry/Platform/Linux/PhysicalDeviceDriverInfo.setreg create mode 100644 Gems/Atom/RHI/Registry/Platform/Mac/PhysicalDeviceDriverInfo.setreg rename Gems/Atom/RHI/Registry/{ => Platform/Windows}/PhysicalDeviceDriverInfo.setreg (100%) create mode 100644 Gems/Atom/RHI/Registry/Platform/iOS/PhysicalDeviceDriverInfo.setreg diff --git a/Gems/Atom/RHI/Code/Source/RHI.Reflect/PhysicalDeviceDescriptor.cpp b/Gems/Atom/RHI/Code/Source/RHI.Reflect/PhysicalDeviceDescriptor.cpp index 17819ab1f5..9da4f583ac 100644 --- a/Gems/Atom/RHI/Code/Source/RHI.Reflect/PhysicalDeviceDescriptor.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI.Reflect/PhysicalDeviceDescriptor.cpp @@ -86,6 +86,13 @@ namespace AZ PhysicalDeviceDriverValidator::ValidationResult PhysicalDeviceDriverValidator::ValidateDriverVersion(const PhysicalDeviceDescriptor& descriptor) const { + // [GFX TODO] Add driver info for other platforms besides Windows. Currently, avoid spamming warnings. + // ATOM-14967 [RHI][Metal] - Address driver version validator for Mac + if (m_driverInfo.size() == 0) + { + return ValidationResult::MissingInfo; + } + auto iter = m_driverInfo.find(descriptor.m_vendorId); if (iter == m_driverInfo.end()) diff --git a/Gems/Atom/RHI/Registry/Platform/Android/PhysicalDeviceDriverInfo.setreg b/Gems/Atom/RHI/Registry/Platform/Android/PhysicalDeviceDriverInfo.setreg new file mode 100644 index 0000000000..a0df86c923 --- /dev/null +++ b/Gems/Atom/RHI/Registry/Platform/Android/PhysicalDeviceDriverInfo.setreg @@ -0,0 +1,23 @@ +// +// 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 +// +// +// + +{ + "O3DE": + { + "Atom": + { + "RHI": + { + "PhysicalDeviceDriverInfo": + { + } + } + } + } +} diff --git a/Gems/Atom/RHI/Registry/Platform/Linux/PhysicalDeviceDriverInfo.setreg b/Gems/Atom/RHI/Registry/Platform/Linux/PhysicalDeviceDriverInfo.setreg new file mode 100644 index 0000000000..a0df86c923 --- /dev/null +++ b/Gems/Atom/RHI/Registry/Platform/Linux/PhysicalDeviceDriverInfo.setreg @@ -0,0 +1,23 @@ +// +// 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 +// +// +// + +{ + "O3DE": + { + "Atom": + { + "RHI": + { + "PhysicalDeviceDriverInfo": + { + } + } + } + } +} diff --git a/Gems/Atom/RHI/Registry/Platform/Mac/PhysicalDeviceDriverInfo.setreg b/Gems/Atom/RHI/Registry/Platform/Mac/PhysicalDeviceDriverInfo.setreg new file mode 100644 index 0000000000..a0df86c923 --- /dev/null +++ b/Gems/Atom/RHI/Registry/Platform/Mac/PhysicalDeviceDriverInfo.setreg @@ -0,0 +1,23 @@ +// +// 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 +// +// +// + +{ + "O3DE": + { + "Atom": + { + "RHI": + { + "PhysicalDeviceDriverInfo": + { + } + } + } + } +} diff --git a/Gems/Atom/RHI/Registry/PhysicalDeviceDriverInfo.setreg b/Gems/Atom/RHI/Registry/Platform/Windows/PhysicalDeviceDriverInfo.setreg similarity index 100% rename from Gems/Atom/RHI/Registry/PhysicalDeviceDriverInfo.setreg rename to Gems/Atom/RHI/Registry/Platform/Windows/PhysicalDeviceDriverInfo.setreg diff --git a/Gems/Atom/RHI/Registry/Platform/iOS/PhysicalDeviceDriverInfo.setreg b/Gems/Atom/RHI/Registry/Platform/iOS/PhysicalDeviceDriverInfo.setreg new file mode 100644 index 0000000000..a0df86c923 --- /dev/null +++ b/Gems/Atom/RHI/Registry/Platform/iOS/PhysicalDeviceDriverInfo.setreg @@ -0,0 +1,23 @@ +// +// 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 +// +// +// + +{ + "O3DE": + { + "Atom": + { + "RHI": + { + "PhysicalDeviceDriverInfo": + { + } + } + } + } +} From a1380940270920ba659c15a89ba811922db9d7a0 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Thu, 7 Oct 2021 14:34:29 -0500 Subject: [PATCH 036/169] Updated create-template logic to prefer the SanitizedCppName when running replacements on cpp file contents. Signed-off-by: Chris Galvan --- scripts/o3de/o3de/engine_template.py | 39 +++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/scripts/o3de/o3de/engine_template.py b/scripts/o3de/o3de/engine_template.py index 802641bd3a..06fab8752e 100755 --- a/scripts/o3de/o3de/engine_template.py +++ b/scripts/o3de/o3de/engine_template.py @@ -402,7 +402,7 @@ def create_template(source_path: pathlib.Path, # if no template path, error if not template_path: logger.info(f'Template path empty. Using source name {source_name}') - template_path = source_name + template_path = pathlib.Path(source_name) if not template_path.is_absolute(): default_templates_folder = manifest.get_registered(default_folder='templates') template_path = default_templates_folder / template_path @@ -518,21 +518,52 @@ def create_template(source_path: pathlib.Path, replacements.append((source_name.upper(), '${NameUpper}')) replacements.append((source_name, '${Name}')) replacements.append((sanitized_source_name, '${SanitizedCppName}')) + sanitized_name_index = len(replacements) - 1 - def _transform_into_template(s_data: object) -> (bool, str): + def _is_cpp_file(file_path: pathlib.Path) -> bool: + """ + Internal helper method to check if a file is a C++ file based + on its extension, so we can determine if we need to prefer + the ${SanitizedCppName} + :param file_path: The input file path + :return: bool: Whether or not the input file path has a C++ extension + """ + name, ext = os.path.splitext(file_path) + + return ext == ".h" or ext == ".hpp" or ext == ".inl" or ext == ".cpp" or ext == ".hxx" + + def _transform_into_template(s_data: object, + prefer_sanitized_name: bool = False) -> (bool, str): """ Internal function to transform any data into templated data :param s_data: the input data, this could be file data or file name data + :param prefer_sanitized_name: Optionally swap the sanitized name with the normal name + This can be necessary when creating the template, the source + name and sanitized source name might be the same, but C++ + files will need to prefer the sanitized version, or else + there might be compile errors (e.g. '-' characters in the name) :return: bool: whether or not the returned data MAY need to be transformed to instantiate it t_data: potentially transformed data 0 for success or non 0 failure code """ + def swap_sanitized_name_and_normal(): + replacements[sanitized_name_index-1], replacements[sanitized_name_index] = \ + replacements[sanitized_name_index], replacements[sanitized_name_index-1] + # copy the src data to the transformed data, then operate only on transformed data t_data = str(s_data) + # If we need to prefer the sanitized name, then swap it for the normal + if prefer_sanitized_name: + swap_sanitized_name_and_normal() + # run all the replacements for replacement in replacements: t_data = t_data.replace(replacement[0], replacement[1]) + # Once we are done running the replacements, reset the list if we had modified it + if prefer_sanitized_name: + swap_sanitized_name_and_normal() + if not keep_license_text: t_data = _replace_license_text(t_data) @@ -704,7 +735,7 @@ def create_template(source_path: pathlib.Path, # open the file and attempt to transform it with open(entry_abs, 'r') as s: source_data = s.read() - templated, source_data = _transform_into_template(source_data) + templated, source_data = _transform_into_template(source_data, _is_cpp_file(entry_abs)) # if the file type is a file that we expect to fins license header and we don't find any # warn that the we didn't find the license info, this makes it easy to make sure we didn't @@ -840,7 +871,7 @@ def create_template(source_path: pathlib.Path, # open the file and attempt to transform it with open(entry_abs, 'r') as s: source_data = s.read() - templated, source_data = _transform_into_template(source_data) + templated, source_data = _transform_into_template(source_data, _is_cpp_file(entry_abs)) # if the file type is a file that we expect to fins license header and we don't find any # warn that the we didn't find the license info, this makes it easy to make sure we didn't From 9b86749a838334e5065e9a4bcd574d8edd6a12ef Mon Sep 17 00:00:00 2001 From: Gene Walters Date: Thu, 7 Oct 2021 13:01:05 -0700 Subject: [PATCH 037/169] Making sure unit tests using iMultiplayers implement the new AddServerAcceptance events; misc cleanup Signed-off-by: Gene Walters --- Gems/Multiplayer/Code/Tests/CommonBenchmarkSetup.h | 1 + Gems/Multiplayer/Code/Tests/MockInterfaces.h | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Gems/Multiplayer/Code/Tests/CommonBenchmarkSetup.h b/Gems/Multiplayer/Code/Tests/CommonBenchmarkSetup.h index 7f98d22702..5a528ed497 100644 --- a/Gems/Multiplayer/Code/Tests/CommonBenchmarkSetup.h +++ b/Gems/Multiplayer/Code/Tests/CommonBenchmarkSetup.h @@ -328,6 +328,7 @@ namespace Multiplayer void Terminate([[maybe_unused]] AzNetworking::DisconnectReason reason) override {} void AddClientDisconnectedHandler([[maybe_unused]] ClientDisconnectedEvent::Handler& handler) override {} void AddConnectionAcquiredHandler([[maybe_unused]] ConnectionAcquiredEvent::Handler& handler) override {} + void AddServerAcceptanceReceivedHandler([[maybe_unused]] ServerAcceptanceReceivedEvent::Handler& handler) override {} void AddSessionInitHandler([[maybe_unused]] SessionInitEvent::Handler& handler) override {} void AddSessionShutdownHandler([[maybe_unused]] SessionShutdownEvent::Handler& handler) override {} void SendReadyForEntityUpdates([[maybe_unused]] bool readyForEntityUpdates) override {} diff --git a/Gems/Multiplayer/Code/Tests/MockInterfaces.h b/Gems/Multiplayer/Code/Tests/MockInterfaces.h index 44024f67ab..527aeb51bc 100644 --- a/Gems/Multiplayer/Code/Tests/MockInterfaces.h +++ b/Gems/Multiplayer/Code/Tests/MockInterfaces.h @@ -29,9 +29,10 @@ namespace UnitTest MOCK_METHOD1(AddClientDisconnectedHandler, void(AZ::Event<>::Handler&)); MOCK_METHOD1(AddNotifyClientMigrationHandler, void(Multiplayer::NotifyClientMigrationEvent::Handler&)); MOCK_METHOD1(AddNotifyEntityMigrationEventHandler, void(Multiplayer::NotifyEntityMigrationEvent::Handler&)); - MOCK_METHOD1(AddConnectionAcquiredHandler, void(AZ::Event::Handler&)); - MOCK_METHOD1(AddSessionInitHandler, void(AZ::Event::Handler&)); - MOCK_METHOD1(AddSessionShutdownHandler, void(AZ::Event::Handler&)); + MOCK_METHOD1(AddConnectionAcquiredHandler, void(Multiplayer::ConnectionAcquiredEvent::Handler&)); + MOCK_METHOD1(AddServerAcceptanceReceivedHandler, void(Multiplayer::ServerAcceptanceReceivedEvent::Handler&)); + MOCK_METHOD1(AddSessionInitHandler, void(Multiplayer::SessionInitEvent::Handler&)); + MOCK_METHOD1(AddSessionShutdownHandler, void(Multiplayer::SessionShutdownEvent::Handler&)); MOCK_METHOD3(SendNotifyClientMigrationEvent, void(const Multiplayer::HostId&, uint64_t, Multiplayer::ClientInputId)); MOCK_METHOD2(SendNotifyEntityMigrationEvent, void(const Multiplayer::ConstNetworkEntityHandle&, const Multiplayer::HostId&)); MOCK_METHOD1(SendReadyForEntityUpdates, void(bool)); From 5f52664026774c549d1fefbf4141be884873b8d4 Mon Sep 17 00:00:00 2001 From: allisaurus <34254888+allisaurus@users.noreply.github.com> Date: Thu, 7 Oct 2021 13:04:10 -0700 Subject: [PATCH 038/169] Add missing field labels to AWSMetrics node SubmitMetrics (#4534) * Add missing field labels to AWSMetrics node SubmitMetrics * Add periods to tooltips to be consistent w/ other metrics nodes Signed-off-by: Stanko --- Gems/AWSMetrics/Code/Source/AWSMetricsSystemComponent.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Gems/AWSMetrics/Code/Source/AWSMetricsSystemComponent.cpp b/Gems/AWSMetrics/Code/Source/AWSMetricsSystemComponent.cpp index 6850fe694b..7f320f398a 100644 --- a/Gems/AWSMetrics/Code/Source/AWSMetricsSystemComponent.cpp +++ b/Gems/AWSMetrics/Code/Source/AWSMetricsSystemComponent.cpp @@ -74,7 +74,12 @@ namespace AWSMetrics { behaviorContext->EBus("AWSMetricsRequestBus", "Generate and submit metrics to the metrics analytics pipeline") ->Attribute(AZ::Script::Attributes::Category, "AWSMetrics") - ->Event("SubmitMetrics", &AWSMetricsRequestBus::Events::SubmitMetrics) + ->Event( + "SubmitMetrics", &AWSMetricsRequestBus::Events::SubmitMetrics, + { { { "Metrics Attributes list", "The list of metrics attributes to submit." }, + { "Event priority", "Priority of the event. Defaults to 0, which is highest priority." }, + { "Event source override", "Event source used to override the default, 'AWSMetricGem'." }, + { "Buffer metrics", "Whether to buffer metrics and send them in a batch." } } }) ->Event("FlushMetrics", &AWSMetricsRequestBus::Events::FlushMetrics) ; From e1c02cc146a0e0ccb2b2e25d0068237a8c1bae6b Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Thu, 7 Oct 2021 15:32:57 -0500 Subject: [PATCH 039/169] Updated cpp file extension check per PR feedback. Signed-off-by: Chris Galvan --- scripts/o3de/o3de/engine_template.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/scripts/o3de/o3de/engine_template.py b/scripts/o3de/o3de/engine_template.py index 06fab8752e..cba7539aaa 100755 --- a/scripts/o3de/o3de/engine_template.py +++ b/scripts/o3de/o3de/engine_template.py @@ -59,6 +59,14 @@ binary_file_ext = { '.motionset' } +cpp_file_ext = { + '.cpp', + '.h', + '.hpp', + '.hxx', + '.inl' +} + expect_license_info_ext = { '.cpp', '.h', @@ -530,7 +538,7 @@ def create_template(source_path: pathlib.Path, """ name, ext = os.path.splitext(file_path) - return ext == ".h" or ext == ".hpp" or ext == ".inl" or ext == ".cpp" or ext == ".hxx" + return ext.lower() in cpp_file_ext def _transform_into_template(s_data: object, prefer_sanitized_name: bool = False) -> (bool, str): From 42e748760d501ea8472e89abd4f8c9681b1037be Mon Sep 17 00:00:00 2001 From: rhhong Date: Mon, 16 Aug 2021 21:43:49 -0700 Subject: [PATCH 040/169] Loading actor in editor using asset system. Signed-off-by: rhhong --- .../CommandSystem/Source/ActorCommands.cpp | 11 +- .../CommandSystem/Source/ImporterCommands.cpp | 46 +++----- .../Source/SelectionCommands.cpp | 15 --- .../RCExt/Actor/ActorGroupExporter.cpp | 1 - .../Pipeline/RCExt/Actor/ActorGroupExporter.h | 3 +- .../EMotionFX/Code/EMotionFX/Source/Actor.cpp | 22 ---- Gems/EMotionFX/Code/EMotionFX/Source/Actor.h | 9 -- .../Code/EMotionFX/Source/ActorManager.cpp | 103 +++++++++++------ .../Code/EMotionFX/Source/ActorManager.h | 21 ++-- .../EMotionFX/Source/AutoRegisteredActor.h | 109 ------------------ .../EMStudioSDK/Source/FileManager.cpp | 4 - .../EMStudioSDK/Source/MainWindow.cpp | 5 - .../Source/RenderPlugin/RenderPlugin.cpp | 4 +- .../Source/ResetSettingsDialog.cpp | 3 +- .../Source/SceneManager/ActorsWindow.cpp | 6 - .../Code/EMotionFX/emotionfx_files.cmake | 1 - .../Source/Integration/Assets/ActorAsset.cpp | 3 - .../Source/Integration/Assets/ActorAsset.h | 4 +- 18 files changed, 108 insertions(+), 262 deletions(-) delete mode 100644 Gems/EMotionFX/Code/EMotionFX/Source/AutoRegisteredActor.h diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp index 85bb726822..57e206560a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp @@ -22,6 +22,7 @@ #include "CommandManager.h" #include #include +#include namespace CommandSystem @@ -729,7 +730,8 @@ namespace CommandSystem m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); // get rid of the actor - EMotionFX::GetActorManager().UnregisterActor(EMotionFX::GetActorManager().FindSharedActorByID(actor->GetID())); + const AZ::Data::AssetId actorAssetId = EMotionFX::GetActorManager().FindAssetIdByActorId(actor->GetID()); + EMotionFX::GetActorManager().UnregisterActor(actorAssetId); // mark the workspace as dirty GetCommandManager()->SetWorkspaceDirtyFlag(true); @@ -818,7 +820,6 @@ namespace CommandSystem { continue; } - // ignore visualization actor instances if (actorInstance->GetIsUsedForVisualization()) { @@ -849,12 +850,6 @@ namespace CommandSystem // get the current actor EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i); - // ignore runtime-owned actors - if (actor->GetIsOwnedByRuntime()) - { - continue; - } - // ignore visualization actors if (actor->GetIsUsedForVisualization()) { diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp index 168de93e38..4b23bd2e0a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp @@ -17,6 +17,7 @@ #include #include "CommandManager.h" #include +#include namespace CommandSystem @@ -65,35 +66,24 @@ namespace CommandSystem filename = EMotionFX::EMotionFXManager::ResolvePath(filename.c_str()); } + AZ::Data::AssetId actorAssetId; + EBUS_EVENT_RESULT( + actorAssetId, AZ::Data::AssetCatalogRequestBus, GetAssetIdByPath, filename.c_str(), AZ::Data::s_invalidAssetType, false); + // check if we have already loaded the actor - EMotionFX::Actor* actorFromManager = EMotionFX::GetActorManager().FindActorByFileName(filename.c_str()); - if (actorFromManager) + const size_t actorIndex = EMotionFX::GetActorManager().FindActorIndex(actorAssetId); + if (actorIndex != InvalidIndex) { - AZStd::to_string(outResult, actorFromManager->GetID()); return true; } - // init the settings - EMotionFX::Importer::ActorSettings settings; - - // extract default values from the command syntax automatically, if they aren't specified explicitly - settings.m_loadLimits = parameters.GetValueAsBool("loadLimits", this); - settings.m_loadMorphTargets = parameters.GetValueAsBool("loadMorphTargets", this); - settings.m_loadSkeletalLoDs = parameters.GetValueAsBool("loadSkeletalLODs", this); - settings.m_dualQuatSkinning = parameters.GetValueAsBool("dualQuatSkinning", this); - - // try to load the actor - AZStd::shared_ptr actor {EMotionFX::GetImporter().LoadActor(filename.c_str(), &settings)}; - if (!actor) - { - outResult = AZStd::string::format("Failed to load actor from '%s'. File may not exist at this path or may have incorrect permissions", filename.c_str()); - return false; - } - - // Because the actor is directly loaded from disk (without going through an actor asset), we need to ask for a blocking - // load for the asset that actor is depend on. - actor->Finalize(EMotionFX::Actor::LoadRequirement::RequireBlockingLoad); + // Do a blocking load of the asset. + AZ::Data::Asset actorAsset = + AZ::Data::AssetManager::Instance().GetAsset( + actorAssetId, AZ::Data::AssetLoadBehavior::Default); + actorAsset.BlockUntilLoadComplete(); + EMotionFX::Actor* actor = actorAsset->GetActor(); // set the actor id in case we have specified it as parameter if (actorID != MCORE_INVALIDINDEX32) { @@ -113,7 +103,6 @@ namespace CommandSystem GetCommandManager()->ExecuteCommandInsideCommand(AZStd::string::format("Select -actorID %i", actor->GetID()).c_str(), outResult); } - // mark the workspace as dirty m_oldWorkspaceDirtyFlag = GetCommandManager()->GetWorkspaceDirtyFlag(); GetCommandManager()->SetWorkspaceDirtyFlag(true); @@ -121,7 +110,8 @@ namespace CommandSystem // return the id of the newly created actor AZStd::to_string(outResult, actor->GetID()); - EMotionFX::GetActorManager().RegisterActor(AZStd::move(actor)); + // Register actor asset. + EMotionFX::GetActorManager().RegisterActor(actorAsset); return true; } @@ -145,14 +135,14 @@ namespace CommandSystem } // find the actor based on the given id - AZStd::shared_ptr actor = EMotionFX::GetActorManager().FindSharedActorByID(actorID); - if (actor == nullptr) + AZ::Data::AssetId actorAssetId = EMotionFX::GetActorManager().FindAssetIdByActorId(actorID); + if (!actorAssetId.IsValid()) { outResult = AZStd::string::format("Cannot remove actor. Actor ID %i is not valid.", actorID); return false; } - EMotionFX::GetActorManager().UnregisterActor(actor); + EMotionFX::GetActorManager().UnregisterActor(actorAssetId); // update our render actors AZStd::string updateRenderActorsResult; diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.cpp index bcc9769c44..7e1a9fe0f5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/SelectionCommands.cpp @@ -183,11 +183,6 @@ namespace CommandSystem for (size_t i = 0; i < numActors; ++i) { EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i); - - if (actor->GetIsOwnedByRuntime()) - { - continue; - } if (unselect == false) { @@ -211,11 +206,6 @@ namespace CommandSystem return false; } - if (actor->GetIsOwnedByRuntime()) - { - return false; - } - if (unselect == false) { selection.AddActor(actor); @@ -244,11 +234,6 @@ namespace CommandSystem { EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i); - if (actor->GetIsOwnedByRuntime()) - { - continue; - } - if (AzFramework::StringFunc::Equal(valueString.c_str(), actor->GetName(), false /* no case */)) { if (unselect == false) diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp index 4cba50138a..3d5e4fa413 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include #include diff --git a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.h b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.h index e94137b317..d2db7d91c5 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.h +++ b/Gems/EMotionFX/Code/EMotionFX/Pipeline/RCExt/Actor/ActorGroupExporter.h @@ -8,7 +8,6 @@ #pragma once #include -#include #include #include #include @@ -44,7 +43,7 @@ namespace EMotionFX static AZStd::optional GetFirstProductByType( const ActorGroupExportContext& context, AZ::Data::AssetType type); - AutoRegisteredActor m_actor; + AZStd::shared_ptr m_actor; AZStd::vector m_actorMaterialReferences; }; } // namespace Pipeline diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp index 3e592113b1..861271fdb3 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.cpp @@ -91,9 +91,6 @@ namespace EMotionFX m_simulatedObjectSetup = AZStd::make_shared(this); m_optimizeSkeleton = false; -#if defined(EMFX_DEVELOPMENT_BUILD) - m_isOwnedByRuntime = false; -#endif // EMFX_DEVELOPMENT_BUILD // make sure we have at least allocated the first LOD of materials and facial setups m_materials.reserve(4); // reserve space for 4 lods @@ -2074,25 +2071,6 @@ namespace EMotionFX return m_usedForVisualization; } - void Actor::SetIsOwnedByRuntime(bool isOwnedByRuntime) - { -#if defined(EMFX_DEVELOPMENT_BUILD) - m_isOwnedByRuntime = isOwnedByRuntime; -#else - AZ_UNUSED(isOwnedByRuntime); -#endif - } - - - bool Actor::GetIsOwnedByRuntime() const - { -#if defined(EMFX_DEVELOPMENT_BUILD) - return m_isOwnedByRuntime; -#else - return true; -#endif - } - const AZ::Aabb& Actor::GetStaticAabb() const { return m_staticAabb; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h index aa5c5df45c..dc83972d40 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/Actor.h @@ -720,12 +720,6 @@ namespace EMotionFX void SetIsUsedForVisualization(bool flag); bool GetIsUsedForVisualization() const; - /** - * Marks the actor as used by the engine runtime, as opposed to the tool suite. - */ - void SetIsOwnedByRuntime(bool isOwnedByRuntime); - bool GetIsOwnedByRuntime() const; - /** * Recursively find the parent bone that is enabled in a given LOD, starting from a given node. * For example if you have a finger bone, while the finger bones are disabled in the skeletal LOD, this function will return the index to the hand bone. @@ -940,8 +934,5 @@ namespace EMotionFX bool m_usedForVisualization; /**< Indicates if the actor is used for visualization specific things and is not used as a normal in-game actor. */ bool m_optimizeSkeleton; /**< Indicates if we should perform/ */ bool m_isReady = false; /**< If actor as well as its dependent files are fully loaded and initialized.*/ -#if defined(EMFX_DEVELOPMENT_BUILD) - bool m_isOwnedByRuntime; /**< Set if the actor is used/owned by the engine runtime. */ -#endif // EMFX_DEVELOPMENT_BUILD }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp index 681efb6039..d20d0cf11c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp @@ -31,7 +31,7 @@ namespace EMotionFX SetScheduler(MultiThreadScheduler::Create()); // reserve memory - m_actors.reserve(512); + m_actorAssets.reserve(32); m_actorInstances.reserve(1024); m_rootActorInstances.reserve(1024); } @@ -111,20 +111,23 @@ namespace EMotionFX // register the actor - void ActorManager::RegisterActor(AZStd::shared_ptr actor) + void ActorManager::RegisterActor(ActorAssetData actorAsset) { LockActors(); // check if we already registered - if (FindActorIndex(actor.get()) != InvalidIndex) + if (FindActorIndex(actorAsset.GetId()) != InvalidIndex) { - MCore::LogWarning("EMotionFX::ActorManager::RegisterActor() - The actor at location 0x%x has already been registered as actor, most likely already by the LoadActor of the importer.", actor.get()); + MCore::LogWarning( + "EMotionFX::ActorManager::RegisterActor() - The actor at location 0x%x has already been registered as actor, most likely " + "already by the LoadActor of the importer.", + actorAsset.GetAs()->GetActor()); UnlockActors(); return; } // register it - m_actors.emplace_back(AZStd::move(actor)); + m_actorAssets.emplace_back(AZStd::move(actorAsset)); UnlockActors(); } @@ -146,60 +149,82 @@ namespace EMotionFX Actor* ActorManager::FindActorByName(const char* actorName) const { // get the number of actors and iterate through them - const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [actorName](const AZStd::shared_ptr& a) + const auto found = AZStd::find_if( + m_actorAssets.begin(), m_actorAssets.end(), + [actorName](const ActorAssetData& a) { - return a->GetNameString() == actorName; + return a.GetAs()->GetActor()->GetNameString() == actorName; }); - return (found != m_actors.end()) ? found->get() : nullptr; + return (found != m_actorAssets.end()) ? found->GetAs()->GetActor() : nullptr; } // find the actor for a given filename Actor* ActorManager::FindActorByFileName(const char* fileName) const { - const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [fileName](const AZStd::shared_ptr& a) + const auto found = AZStd::find_if( + m_actorAssets.begin(), m_actorAssets.end(), + [fileName](const ActorAssetData& a) { - return AzFramework::StringFunc::Equal(a->GetFileNameString().c_str(), fileName, false /* no case */); + return AzFramework::StringFunc::Equal( + a.GetAs()->GetActor()->GetFileNameString().c_str(), fileName, false /* no case */); }); - return (found != m_actors.end()) ? found->get() : nullptr; + return (found != m_actorAssets.end()) ? found->GetAs()->GetActor() : nullptr; } // find the leader actor record for a given actor - size_t ActorManager::FindActorIndex(Actor* actor) const + size_t ActorManager::FindActorIndex(AZ::Data::AssetId assetId) const { - const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [actor](const AZStd::shared_ptr& a) + const auto found = AZStd::find_if( + m_actorAssets.begin(), m_actorAssets.end(), + [assetId](const ActorAssetData& a) { - return a.get() == actor; + return a.GetId() == assetId; }); - return (found != m_actors.end()) ? AZStd::distance(m_actors.begin(), found) : InvalidIndex; + return (found != m_actorAssets.end()) ? AZStd::distance(m_actorAssets.begin(), found) : InvalidIndex; } + size_t ActorManager::FindActorIndex(const Actor* actor) const + { + const auto found = AZStd::find_if( + m_actorAssets.begin(), m_actorAssets.end(), + [actor](const ActorAssetData& a) + { + return a.GetAs()->GetActor() == actor; + }); + + return (found != m_actorAssets.end()) ? AZStd::distance(m_actorAssets.begin(), found) : InvalidIndex; + } // find the actor for a given actor name size_t ActorManager::FindActorIndexByName(const char* actorName) const { - const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [actorName](const AZStd::shared_ptr& a) + const auto found = AZStd::find_if( + m_actorAssets.begin(), m_actorAssets.end(), + [actorName](const ActorAssetData& a) { - return a->GetNameString() == actorName; + return a.GetAs()->GetActor()->GetNameString() == actorName; }); - return (found != m_actors.end()) ? AZStd::distance(m_actors.begin(), found) : InvalidIndex; + return (found != m_actorAssets.end()) ? AZStd::distance(m_actorAssets.begin(), found) : InvalidIndex; } // find the actor for a given actor filename size_t ActorManager::FindActorIndexByFileName(const char* filename) const { - const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [filename](const AZStd::shared_ptr& a) + const auto found = AZStd::find_if( + m_actorAssets.begin(), m_actorAssets.end(), + [filename](const ActorAssetData& a) { - return a->GetFileNameString() == filename; + return a.GetAs()->GetActor()->GetFileNameString() == filename; }); - return (found != m_actors.end()) ? AZStd::distance(m_actors.begin(), found) : InvalidIndex; + return (found != m_actorAssets.end()) ? AZStd::distance(m_actorAssets.begin(), found) : InvalidIndex; } @@ -237,22 +262,26 @@ namespace EMotionFX // find the actor by the identification number Actor* ActorManager::FindActorByID(uint32 id) const { - const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [id](const AZStd::shared_ptr& a) + const auto found = AZStd::find_if( + m_actorAssets.begin(), m_actorAssets.end(), + [id](const ActorAssetData& a) { - return a->GetID() == id; + return a.GetAs()->GetActor()->GetID() == id; }); - return (found != m_actors.end()) ? found->get() : nullptr; + return (found != m_actorAssets.end()) ? found->GetAs()->GetActor() : nullptr; } - AZStd::shared_ptr ActorManager::FindSharedActorByID(uint32 id) const + AZ::Data::AssetId ActorManager::FindAssetIdByActorId(uint32 id) const { - const auto found = AZStd::find_if(m_actors.begin(), m_actors.end(), [id](const AZStd::shared_ptr& a) + const auto found = AZStd::find_if( + m_actorAssets.begin(), m_actorAssets.end(), + [id](const ActorAssetData& a) { - return a->GetID() == id; + return a.GetAs()->GetActor()->GetID() == id; }); - return (found != m_actors.end()) ? *found : nullptr; + return (found != m_actorAssets.end()) ? found->GetId() : AZ::Data::AssetId(); } @@ -264,14 +293,20 @@ namespace EMotionFX // unregister an actor - void ActorManager::UnregisterActor(const AZStd::shared_ptr& actor) + void ActorManager::UnregisterActor(AZ::Data::AssetId actorAssetID) { LockActors(); - auto result = AZStd::find(m_actors.begin(), m_actors.end(), actor); - if (result != m_actors.end()) + const auto found = AZStd::find_if( + m_actorAssets.begin(), m_actorAssets.end(), + [actorAssetID](const ActorAssetData& a) + { + return a.GetId() == actorAssetID; + }); + if (found != m_actorAssets.end()) { - m_actors.erase(result); + m_actorAssets.erase(found); } + UnlockActors(); } @@ -297,7 +332,7 @@ namespace EMotionFX LockActors(); // clear all actors - m_actors.clear(); + m_actorAssets.clear(); // TODO: what if there are still references to the actors inside the list of registered actor instances? UnlockActors(); @@ -390,7 +425,7 @@ namespace EMotionFX Actor* ActorManager::GetActor(size_t nr) const { - return m_actors[nr].get(); + return m_actorAssets[nr].GetAs()->GetActor(); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h index ff78250141..e4ce0d6c94 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h @@ -16,7 +16,8 @@ #include #include #include - +#include +#include namespace EMotionFX { @@ -41,13 +42,14 @@ namespace EMotionFX friend class EMotionFXManager; public: + using ActorAssetData = AZ::Data::Asset; static ActorManager* Create(); /** * Register an actor. * @param actor The actor to register. */ - void RegisterActor(AZStd::shared_ptr actor); + void RegisterActor(ActorAssetData actorAsset); /** * Unregister all actors. @@ -60,14 +62,14 @@ namespace EMotionFX * Unregister a specific actor. * @param actor The actor you passed to the RegisterActor function sometime before. */ - void UnregisterActor(const AZStd::shared_ptr& actor); + void UnregisterActor(AZ::Data::AssetId actorAssetID); /** * Get the number of registered actors. * This does not include the clones that have been optionally created. * @result The number of registered actors. */ - MCORE_INLINE size_t GetNumActors() const { return m_actors.size(); } + MCORE_INLINE size_t GetNumActors() const { return m_actorAssets.size(); } /** * Get a given actor. @@ -99,7 +101,8 @@ namespace EMotionFX * @param actor The actor object you once passed to RegisterActor. * @result Returns the actor number, which is in range of [0..GetNumActors()-1], or returns MCORE_INVALIDINDEX32 when not found. */ - size_t FindActorIndex(Actor* actor) const; + size_t FindActorIndex(AZ::Data::AssetId assetId) const; + size_t FindActorIndex(const Actor* actor) const; /** * Find the actor number for a given actor name. @@ -160,7 +163,7 @@ namespace EMotionFX */ Actor* FindActorByID(uint32 id) const; - AZStd::shared_ptr FindSharedActorByID(uint32 id) const; + AZ::Data::AssetId FindAssetIdByActorId(uint32 id) const; /** * Check if the given actor instance is registered. @@ -255,9 +258,9 @@ namespace EMotionFX void UnlockActors(); private: - AZStd::vector m_actorInstances; /**< The registered actor instances. */ - AZStd::vector> m_actors; /**< The registered actors. */ - AZStd::vector m_rootActorInstances; /**< Root actor instances (roots of all attachment chains). */ + AZStd::vector m_actorInstances; /**< The registered actor instances. */ + AZStd::vector m_actorAssets; + AZStd::vector m_rootActorInstances; /**< Root actor instances (roots of all attachment chains). */ ActorUpdateScheduler* m_scheduler; /**< The update scheduler to use. */ MCore::MutexRecursive m_actorLock; /**< The multithread lock for touching the actors array. */ MCore::MutexRecursive m_actorInstanceLock; /**< The multithread lock for touching the actor instances array. */ diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/AutoRegisteredActor.h b/Gems/EMotionFX/Code/EMotionFX/Source/AutoRegisteredActor.h deleted file mode 100644 index 8304976b15..0000000000 --- a/Gems/EMotionFX/Code/EMotionFX/Source/AutoRegisteredActor.h +++ /dev/null @@ -1,109 +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 - -namespace EMotionFX -{ - class Actor; - - /** - * @brief An Actor pointer that unregisters itself when it goes out of - * scope - * - * This class allows for simple functionality of automatically registering - * and unregistering an actor from the manager. Its primary use case is the - * ActorAsset, that shares ownership with the manager. But it can also be - * used anywhere that needs to make an Actor that needs to be in the - * Manager for a given period of time. A good example of this is anything - * that needs Actor commands to work on an actor that is made in a given - * scope. One main place where this happens is in the Actor asset processor - * code. - */ - class AutoRegisteredActor - { - public: - AutoRegisteredActor() = default; - - template - AutoRegisteredActor(AZStd::shared_ptr actor) - : m_actor(AZStd::move(actor)) - { - Register(m_actor); - } - template - AutoRegisteredActor(AZStd::unique_ptr actor) - : m_actor(AZStd::move(actor)) - { - Register(m_actor); - } - - // This class is not copyable, because a given actor cannot be - // registered with the manager multiple times - AutoRegisteredActor(const AutoRegisteredActor&) = delete; - AutoRegisteredActor& operator=(const AutoRegisteredActor&) = delete; - - AutoRegisteredActor(AutoRegisteredActor&& other) noexcept - { - *this = AZStd::move(other); - } - - AutoRegisteredActor& operator=(AutoRegisteredActor&& other) noexcept - { - if (this != &other) - { - Unregister(m_actor); - m_actor = AZStd::move(other.m_actor); - } - return *this; - } - - ~AutoRegisteredActor() - { - Unregister(m_actor); - } - - Actor* operator->() const - { - return m_actor.operator->(); - } - - operator bool() const - { - return static_cast(m_actor); - } - - Actor* get() const - { - return m_actor.get(); - } - - private: - void Register(const AZStd::shared_ptr& actor) - { - if (actor) - { - GetActorManager().RegisterActor(actor); - } - } - - void Unregister(const AZStd::shared_ptr& actor) - { - if (actor) - { - GetActorManager().UnregisterActor(actor); - } - } - - AZStd::shared_ptr m_actor; - }; -} // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.cpp index 2d65a228b7..17438dd59a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/FileManager.cpp @@ -112,10 +112,6 @@ namespace EMStudio for (size_t i = 0; i < actorCount; ++i) { EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i); - if (actor->GetIsOwnedByRuntime()) - { - continue; - } if (AzFramework::StringFunc::Equal(filename, actor->GetFileName())) { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp index 002634ea90..b75fb71060 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.cpp @@ -1792,11 +1792,6 @@ namespace EMStudio { EMotionFX::Actor* actor = selectionList.GetActorInstance(i)->GetActor(); - if (actor->GetIsOwnedByRuntime()) - { - continue; - } - if (AZStd::find(savingActors.begin(), savingActors.end(), actor) == savingActors.end()) { savingActors.push_back(actor); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp index db0c355002..c74cb3cb0f 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderPlugin.cpp @@ -389,7 +389,7 @@ namespace EMStudio // get the current actor and the number of clones EMotionFX::Actor* actor = EMotionFX::GetActorManager().GetActor(i); - if (actor->GetIsOwnedByRuntime() || !actor->IsReady()) + if (!actor->IsReady()) { continue; } @@ -421,7 +421,7 @@ namespace EMStudio // At this point the render actor could point to an already deleted actor. // In case the actor got deleted we might get an unexpected flag as result. - if (!found || (found && actor->GetIsOwnedByRuntime()) || (!actor->IsReady())) + if (!found || (!actor->IsReady())) { DestroyEMStudioActor(actor); } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/ResetSettingsDialog.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/ResetSettingsDialog.cpp index 2f45a89ea2..5c15f4b6be 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/ResetSettingsDialog.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/ResetSettingsDialog.cpp @@ -65,8 +65,7 @@ namespace EMStudio m_actorCheckbox = new QCheckBox("Actors"); m_actorCheckbox->setObjectName("EMFX.ResetSettingsDialog.Actors"); - const bool hasActors = HasEntityInEditor( - EMotionFX::GetActorManager(), &EMotionFX::ActorManager::GetNumActors, &EMotionFX::ActorManager::GetActor); + const bool hasActors = EMotionFX::GetActorManager().GetNumActors() > 0; m_actorCheckbox->setChecked(hasActors); m_actorCheckbox->setDisabled(!hasActors); diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorsWindow.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorsWindow.cpp index 5012ee2578..c1e35967ec 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorsWindow.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/SceneManager/ActorsWindow.cpp @@ -123,12 +123,6 @@ namespace EMStudio continue; } - // ignore engine actors - if (actor->GetIsOwnedByRuntime()) - { - continue; - } - // create a tree item for the new attachment QTreeWidgetItem* newItem = new QTreeWidgetItem(m_treeWidget); diff --git a/Gems/EMotionFX/Code/EMotionFX/emotionfx_files.cmake b/Gems/EMotionFX/Code/EMotionFX/emotionfx_files.cmake index b12cbe102f..9947850471 100644 --- a/Gems/EMotionFX/Code/EMotionFX/emotionfx_files.cmake +++ b/Gems/EMotionFX/Code/EMotionFX/emotionfx_files.cmake @@ -25,7 +25,6 @@ set(FILES Source/AttachmentNode.h Source/AttachmentSkin.cpp Source/AttachmentSkin.h - Source/AutoRegisteredActor.h Source/BaseObject.cpp Source/BaseObject.h Source/CompressedKeyFrames.h diff --git a/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp b/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp index 5082d4b739..5b546c1155 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp @@ -6,7 +6,6 @@ * */ -#include #include #include #include @@ -64,8 +63,6 @@ namespace EMotionFX &actorSettings, ""); - // Set the is owned by runtime flag before finalizing the actor, as that uses the flag already. - assetData->m_emfxActor->SetIsOwnedByRuntime(true); assetData->m_emfxActor->Finalize(); // Clear out the EMFX raw asset data. diff --git a/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h b/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h index 8732c6a448..3bd2c38640 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h +++ b/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h @@ -15,7 +15,7 @@ #include #include -#include +//#include namespace EMotionFX @@ -58,7 +58,7 @@ namespace EMotionFX void InitRenderActor(); private: - AutoRegisteredActor m_emfxActor; ///< Pointer to shared EMotionFX actor + AZStd::shared_ptr m_emfxActor; AZStd::unique_ptr m_renderActor; }; From bc88d2b3819765f227cd95376e2b067535e6a123 Mon Sep 17 00:00:00 2001 From: rhhong Date: Tue, 17 Aug 2021 11:54:42 -0700 Subject: [PATCH 041/169] Address feedback from Chris. Simplified get asset call and etc. Signed-off-by: rhhong --- .../CommandSystem/Source/ImporterCommands.cpp | 2 +- .../Code/EMotionFX/Source/ActorManager.cpp | 24 +++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp index 4b23bd2e0a..80ef93c331 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp @@ -111,7 +111,7 @@ namespace CommandSystem AZStd::to_string(outResult, actor->GetID()); // Register actor asset. - EMotionFX::GetActorManager().RegisterActor(actorAsset); + EMotionFX::GetActorManager().RegisterActor(AZStd::move(actorAsset)); return true; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp index d20d0cf11c..0779e55f85 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp @@ -121,7 +121,7 @@ namespace EMotionFX MCore::LogWarning( "EMotionFX::ActorManager::RegisterActor() - The actor at location 0x%x has already been registered as actor, most likely " "already by the LoadActor of the importer.", - actorAsset.GetAs()->GetActor()); + actorAsset->GetActor()); UnlockActors(); return; } @@ -153,10 +153,10 @@ namespace EMotionFX m_actorAssets.begin(), m_actorAssets.end(), [actorName](const ActorAssetData& a) { - return a.GetAs()->GetActor()->GetNameString() == actorName; + return a->GetActor()->GetNameString() == actorName; }); - return (found != m_actorAssets.end()) ? found->GetAs()->GetActor() : nullptr; + return (found != m_actorAssets.end()) ? (*found)->GetActor() : nullptr; } @@ -168,10 +168,10 @@ namespace EMotionFX [fileName](const ActorAssetData& a) { return AzFramework::StringFunc::Equal( - a.GetAs()->GetActor()->GetFileNameString().c_str(), fileName, false /* no case */); + a->GetActor()->GetFileNameString().c_str(), fileName, false /* no case */); }); - return (found != m_actorAssets.end()) ? found->GetAs()->GetActor() : nullptr; + return (found != m_actorAssets.end()) ? (*found)->GetActor() : nullptr; } @@ -194,7 +194,7 @@ namespace EMotionFX m_actorAssets.begin(), m_actorAssets.end(), [actor](const ActorAssetData& a) { - return a.GetAs()->GetActor() == actor; + return a->GetActor() == actor; }); return (found != m_actorAssets.end()) ? AZStd::distance(m_actorAssets.begin(), found) : InvalidIndex; @@ -207,7 +207,7 @@ namespace EMotionFX m_actorAssets.begin(), m_actorAssets.end(), [actorName](const ActorAssetData& a) { - return a.GetAs()->GetActor()->GetNameString() == actorName; + return a->GetActor()->GetNameString() == actorName; }); return (found != m_actorAssets.end()) ? AZStd::distance(m_actorAssets.begin(), found) : InvalidIndex; @@ -221,7 +221,7 @@ namespace EMotionFX m_actorAssets.begin(), m_actorAssets.end(), [filename](const ActorAssetData& a) { - return a.GetAs()->GetActor()->GetFileNameString() == filename; + return a->GetActor()->GetFileNameString() == filename; }); return (found != m_actorAssets.end()) ? AZStd::distance(m_actorAssets.begin(), found) : InvalidIndex; @@ -266,10 +266,10 @@ namespace EMotionFX m_actorAssets.begin(), m_actorAssets.end(), [id](const ActorAssetData& a) { - return a.GetAs()->GetActor()->GetID() == id; + return a->GetActor()->GetID() == id; }); - return (found != m_actorAssets.end()) ? found->GetAs()->GetActor() : nullptr; + return (found != m_actorAssets.end()) ? (*found)->GetActor() : nullptr; } AZ::Data::AssetId ActorManager::FindAssetIdByActorId(uint32 id) const @@ -278,7 +278,7 @@ namespace EMotionFX m_actorAssets.begin(), m_actorAssets.end(), [id](const ActorAssetData& a) { - return a.GetAs()->GetActor()->GetID() == id; + return a->GetActor()->GetID() == id; }); return (found != m_actorAssets.end()) ? found->GetId() : AZ::Data::AssetId(); @@ -425,7 +425,7 @@ namespace EMotionFX Actor* ActorManager::GetActor(size_t nr) const { - return m_actorAssets[nr].GetAs()->GetActor(); + return m_actorAssets[nr]->GetActor(); } From bf38f0748097b981a8fa06aa3785c88fac9eeacb Mon Sep 17 00:00:00 2001 From: Yuriy Toporovskyy Date: Mon, 13 Sep 2021 11:59:08 -0400 Subject: [PATCH 042/169] Allow buffer to take any size, including 0 Signed-off-by: Yuriy Toporovskyy --- .../Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp index f3744fe119..8bf518e277 100644 --- a/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/SkinnedMesh/SkinnedMeshOutputStreamManager.cpp @@ -74,6 +74,9 @@ namespace AZ creator.End(m_bufferAsset); } + + // default value of 256mb supports roughly 42 character instances at 100,000 vertices per character x 64 bytes per vertex (12 byte position + 12 byte previous frame position + 12 byte normal + 16 byte tangent + 12 byte bitangent) + // This includes only the output of the skinning compute shader, not the input buffers or bone transforms AZ_CVAR( int, r_skinnedMeshInstanceMemoryPoolSize, @@ -95,10 +98,8 @@ namespace AZ } m_needsInit = false; - // 256mb supports roughly 42 character instances at 100,000 vertices per character x 64 bytes per vertex (12 byte position + 12 byte previous frame position + 12 byte normal + 16 byte tangent + 12 byte bitangent) - // This includes only the output of the skinning compute shader, not the input buffers or bone transforms const AZ::u64 sizeInMb = r_skinnedMeshInstanceMemoryPoolSize; - m_sizeInBytes = AZ::GetMax(sizeInMb, 256ull) * (1024u * 1024u); + m_sizeInBytes = sizeInMb * (1024u * 1024u); CalculateAlignment(); From 7650683902d01ea5d66c6c2d44c6cf9107af02a8 Mon Sep 17 00:00:00 2001 From: rhhong Date: Tue, 17 Aug 2021 16:17:27 -0700 Subject: [PATCH 043/169] Defer the nodeWindowPlugin reinit to main thread update. Set the actor file name through actor asset. Signed-off-by: rhhong --- .../Source/NodeWindow/NodeWindowPlugin.cpp | 11 ++++++++++- .../Source/NodeWindow/NodeWindowPlugin.h | 4 ++++ .../Code/Source/Integration/Assets/ActorAsset.cpp | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.cpp index 6b7beb20de..4629e8dc54 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.cpp @@ -327,7 +327,16 @@ namespace EMStudio void NodeWindowPlugin::OnActorReady([[maybe_unused]] EMotionFX::Actor* actor) { - ReInit(); + m_reinitRequested = true; + } + + void NodeWindowPlugin::ProcessFrame([[maybe_unused]] float timePassedInSeconds) + { + if (m_reinitRequested) + { + ReInit(); + m_reinitRequested = false; + } } //----------------------------------------------------------------------------------------- diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.h index 157486df10..4c530fffdc 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.h @@ -60,6 +60,8 @@ namespace EMStudio EMStudioPlugin* Clone() override; void ReInit(); + void ProcessFrame(float timePassedInSeconds) override; + public slots: void OnNodeChanged(); void VisibilityChanged(bool isVisible); @@ -87,5 +89,7 @@ namespace EMStudio AZStd::unique_ptr m_actorInfo; AZStd::unique_ptr m_nodeInfo; + + bool m_reinitRequested = false; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp b/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp index 5b546c1155..64117fa814 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.cpp @@ -63,6 +63,7 @@ namespace EMotionFX &actorSettings, ""); + assetData->m_emfxActor->SetFileName(asset.GetHint().c_str()); assetData->m_emfxActor->Finalize(); // Clear out the EMFX raw asset data. From 0b49cc38a74d772d5b55fda1d08e31db9e6edb8c Mon Sep 17 00:00:00 2001 From: rhhong Date: Tue, 17 Aug 2021 18:19:14 -0700 Subject: [PATCH 044/169] fix broken build Signed-off-by: rhhong --- .../EMotionFX/Code/Source/Integration/System/SystemComponent.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp index 08e99f97d0..cf2f9beaa4 100644 --- a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include From 5369df41953403b4fd0cb66bd3edb8e28461ad94 Mon Sep 17 00:00:00 2001 From: rhhong Date: Mon, 23 Aug 2021 21:30:46 -0700 Subject: [PATCH 045/169] remove extra line Signed-off-by: rhhong --- Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h b/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h index 3bd2c38640..c256fa5283 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h +++ b/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h @@ -15,7 +15,6 @@ #include #include -//#include namespace EMotionFX From 4767d2a8917f84a72916248a4f7966e39089011a Mon Sep 17 00:00:00 2001 From: rhhong Date: Tue, 24 Aug 2021 11:36:13 -0700 Subject: [PATCH 046/169] Fix unit test Signed-off-by: rhhong --- .../CommandSystem/Source/ImporterCommands.cpp | 5 + Gems/EMotionFX/Code/Tests/ActorFixture.cpp | 17 ++- Gems/EMotionFX/Code/Tests/ActorFixture.h | 7 +- .../Tests/AdditiveMotionSamplingTests.cpp | 16 +-- .../Code/Tests/AnimGraphDeferredInitTests.cpp | 1 + .../Code/Tests/BlendTreeRagdollNodeTests.cpp | 2 +- .../Code/Tests/ColliderCommandTests.cpp | 107 ++++++++++-------- .../Code/Tests/Integration/CanAddActor.cpp | 14 +-- .../Code/Tests/MotionExtractionBusTests.cpp | 1 + .../Code/Tests/MultiThreadSchedulerTests.cpp | 2 + .../AnimGraph/AnimGraphActivateTests.cpp | 8 +- .../AnimGraph/AnimGraphModelTests.cpp | 9 +- .../ProvidesUI/Menus/FileMenu/CanReset.cpp | 9 +- .../Ragdoll/CanCopyPasteColliders.cpp | 10 +- .../Ragdoll/CanCopyPasteJointLimits.cpp | 6 +- .../Code/Tests/RagdollCommandTests.cpp | 58 +++++----- .../Tests/SimulatedObjectCommandTests.cpp | 92 +++++++-------- .../Code/Tests/SimulatedObjectModelTests.cpp | 8 +- .../Tests/SimulatedObjectSerializeTests.cpp | 6 +- .../EMotionFX/Code/Tests/SkeletalLODTests.cpp | 4 +- .../Tests/TestAssetCode/TestActorAssets.cpp | 3 +- .../Tests/TestAssetCode/TestActorAssets.h | 12 ++ .../Code/Tests/UI/CanAddJointAndChildren.cpp | 9 +- .../Code/Tests/UI/CanAddSimulatedObject.cpp | 85 ++++++++------ .../Code/Tests/UI/CanAddToSimulatedObject.cpp | 17 ++- .../CanChangeParametersInSimulatedObject.cpp | 8 +- .../Code/Tests/UI/CanUseFileMenu.cpp | 25 ++-- .../Code/Tests/UI/CanUseLayoutMenu.cpp | 1 - .../Code/Tests/UI/ClothColliderTests.cpp | 5 +- .../Code/Tests/UI/LODSkinnedMeshTests.cpp | 17 +-- .../Code/Tests/UI/RagdollEditTests.cpp | 9 +- 31 files changed, 341 insertions(+), 232 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp index 80ef93c331..ea3f816e86 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ImporterCommands.cpp @@ -69,6 +69,11 @@ namespace CommandSystem AZ::Data::AssetId actorAssetId; EBUS_EVENT_RESULT( actorAssetId, AZ::Data::AssetCatalogRequestBus, GetAssetIdByPath, filename.c_str(), AZ::Data::s_invalidAssetType, false); + if (!actorAssetId.IsValid()) + { + outResult = AZStd::string::format("Cannot import actor. Cannot find asset at path %s.", filename.c_str()); + return false; + } // check if we have already loaded the actor const size_t actorIndex = EMotionFX::GetActorManager().FindActorIndex(actorAssetId); diff --git a/Gems/EMotionFX/Code/Tests/ActorFixture.cpp b/Gems/EMotionFX/Code/Tests/ActorFixture.cpp index e77df103e0..31c3a0c721 100644 --- a/Gems/EMotionFX/Code/Tests/ActorFixture.cpp +++ b/Gems/EMotionFX/Code/Tests/ActorFixture.cpp @@ -10,12 +10,15 @@ #include #include #include +#include #include #include #include #include #include +#include + namespace EMotionFX { @@ -23,8 +26,9 @@ namespace EMotionFX { SystemComponentFixture::SetUp(); - m_actor = ActorFactory::CreateAndInit(); - m_actorInstance = ActorInstance::Create(m_actor.get()); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + m_actorAsset = TestActorAssets::CreateActorAssetAndRegister(actorAssetId); + m_actorInstance = ActorInstance::Create(m_actorAsset->GetActor()); } void ActorFixture::TearDown() @@ -35,6 +39,7 @@ namespace EMotionFX m_actorInstance = nullptr; } + GetEMotionFX().GetActorManager()->UnregisterAllActors(); SystemComponentFixture::TearDown(); } @@ -71,7 +76,7 @@ namespace EMotionFX AZ::ObjectStream::FilterDescriptor loadFilter(nullptr, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES); SimulatedObjectSetup* setup = AZ::Utils::LoadObjectFromBuffer(data.data(), data.size(), serializeContext, loadFilter); - setup->InitAfterLoad(m_actor.get()); + setup->InitAfterLoad(m_actorAsset->GetActor()); return setup; } @@ -80,4 +85,10 @@ namespace EMotionFX { return { "Bip01__pelvis", "l_upLeg", "l_loLeg", "l_ankle" }; } + + + Actor* ActorFixture::GetActor() + { + return m_actorAsset->GetActor(); + } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Tests/ActorFixture.h b/Gems/EMotionFX/Code/Tests/ActorFixture.h index 9fee056292..fad6a2c463 100644 --- a/Gems/EMotionFX/Code/Tests/ActorFixture.h +++ b/Gems/EMotionFX/Code/Tests/ActorFixture.h @@ -9,8 +9,7 @@ #pragma once #include "SystemComponentFixture.h" -#include - +#include namespace EMotionFX { @@ -31,7 +30,9 @@ namespace EMotionFX AZStd::vector GetTestJointNames() const; protected: - AutoRegisteredActor m_actor{}; + Actor* GetActor(); + + AZ::Data::Asset m_actorAsset; ActorInstance* m_actorInstance = nullptr; }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Tests/AdditiveMotionSamplingTests.cpp b/Gems/EMotionFX/Code/Tests/AdditiveMotionSamplingTests.cpp index 4171598801..114d5c08fb 100644 --- a/Gems/EMotionFX/Code/Tests/AdditiveMotionSamplingTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AdditiveMotionSamplingTests.cpp @@ -26,7 +26,7 @@ namespace EMotionFX public: void CreateSubMotionLikeBindPose(const std::string& name) { - const Skeleton* skeleton = m_actor->GetSkeleton(); + const Skeleton* skeleton = GetActor()->GetSkeleton(); size_t jointIndex = InvalidIndex; const Node* node = skeleton->FindNodeAndIndexByName(name.c_str(), jointIndex); ASSERT_NE(node, nullptr); @@ -40,7 +40,7 @@ namespace EMotionFX void CreateSubMotion(const std::string& name, const Transform& transform) { // Find and store the joint index. - const Skeleton* skeleton = m_actor->GetSkeleton(); + const Skeleton* skeleton = GetActor()->GetSkeleton(); size_t jointIndex = InvalidIndex; const Node* node = skeleton->FindNodeAndIndexByName(name.c_str(), jointIndex); ASSERT_NE(node, nullptr); @@ -55,7 +55,7 @@ namespace EMotionFX ActorFixture::SetUp(); // Get the joint that isn't in the motion data. - Node* footNode = m_actor->GetSkeleton()->FindNodeAndIndexByName("l_ball", m_footIndex); + Node* footNode = GetActor()->GetSkeleton()->FindNodeAndIndexByName("l_ball", m_footIndex); ASSERT_NE(footNode, nullptr); ASSERT_NE(m_footIndex, InvalidIndex32); @@ -98,7 +98,7 @@ namespace EMotionFX TEST_F(MotionSamplingFixture, SampleAdditiveJoint) { - const Skeleton* skeleton = m_actor->GetSkeleton(); + const Skeleton* skeleton = GetActor()->GetSkeleton(); // Sample the joints that exist in our actor skeleton as well as inside the motion data. const Pose* bindPose = m_actorInstance->GetTransformData()->GetBindPose(); @@ -106,7 +106,7 @@ namespace EMotionFX { // Sample the motion. Transform transform = Transform::CreateZero(); // Set all to Zero, not identity as this methods might return identity and we want to verify that. - m_motion->CalcNodeTransform(m_motionInstance, &transform, m_actor.get(), skeleton->GetNode(jointIndex), /*timeValue=*/0.0f, /*enableRetargeting=*/false); + m_motion->CalcNodeTransform(m_motionInstance, &transform, GetActor(), skeleton->GetNode(jointIndex), /*timeValue=*/0.0f, /*enableRetargeting=*/false); const Transform& bindTransform = bindPose->GetLocalSpaceTransform(jointIndex); EXPECT_THAT(transform, IsClose(bindTransform)); @@ -114,7 +114,7 @@ namespace EMotionFX // Sample the motion for the foot node. Transform footTransform = Transform::CreateZero(); // Set all to Zero, not identity as this methods might return identity and we want to verify that. - m_motion->CalcNodeTransform(m_motionInstance, &footTransform, m_actor.get(), skeleton->GetNode(m_footIndex), /*timeValue=*/0.0f, /*enableRetargeting=*/false); + m_motion->CalcNodeTransform(m_motionInstance, &footTransform, GetActor(), skeleton->GetNode(m_footIndex), /*timeValue=*/0.0f, /*enableRetargeting=*/false); // Make sure we get an identity transform back as we try to sample a node that doesn't have a submotion in an additive motion. EXPECT_THAT(footTransform, IsClose(Transform::CreateIdentity())); @@ -125,7 +125,7 @@ namespace EMotionFX // Make sure we do not get an identity transform back now that it is a non-additive motion. footTransform.Zero(); // Set all to Zero, not identity as this methods might return identity and we want to verify that. const Transform& expectedFootTransform = m_actorInstance->GetTransformData()->GetCurrentPose()->GetLocalSpaceTransform(m_footIndex); - m_motion->CalcNodeTransform(m_motionInstance, &footTransform, m_actor.get(), skeleton->GetNode(m_footIndex), /*timeValue=*/0.0f, /*enableRetargeting=*/false); + m_motion->CalcNodeTransform(m_motionInstance, &footTransform, GetActor(), skeleton->GetNode(m_footIndex), /*timeValue=*/0.0f, /*enableRetargeting=*/false); EXPECT_THAT(footTransform, IsClose(expectedFootTransform)); } @@ -134,7 +134,7 @@ namespace EMotionFX // Sample a pose from the motion. Pose pose; pose.LinkToActorInstance(m_actorInstance); - pose.InitFromBindPose(m_actor.get()); + pose.InitFromBindPose(GetActor()); pose.Zero(); m_motion->Update(&pose, &pose, m_motionInstance); diff --git a/Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp b/Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp index 0449005659..4448deff27 100644 --- a/Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp +++ b/Gems/EMotionFX/Code/Tests/AnimGraphDeferredInitTests.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/Gems/EMotionFX/Code/Tests/BlendTreeRagdollNodeTests.cpp b/Gems/EMotionFX/Code/Tests/BlendTreeRagdollNodeTests.cpp index a01d333e95..4608917523 100644 --- a/Gems/EMotionFX/Code/Tests/BlendTreeRagdollNodeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/BlendTreeRagdollNodeTests.cpp @@ -105,7 +105,7 @@ namespace EMotionFX TEST_P(RagdollRootNodeFixture, RagdollRootNodeIsSimulatedTests) { - Physics::RagdollConfiguration& ragdollConfig = m_actor->GetPhysicsSetup()->GetRagdollConfig(); + Physics::RagdollConfiguration& ragdollConfig = GetActor()->GetPhysicsSetup()->GetRagdollConfig(); AZStd::vector& ragdollNodes = ragdollConfig.m_nodes; const RagdollRootNodeParam& param = GetParam(); const AZStd::string ragdollRootNodeName = param.m_ragdollRootNode.c_str(); diff --git a/Gems/EMotionFX/Code/Tests/ColliderCommandTests.cpp b/Gems/EMotionFX/Code/Tests/ColliderCommandTests.cpp index 6314253eee..a6cadc5c2f 100644 --- a/Gems/EMotionFX/Code/Tests/ColliderCommandTests.cpp +++ b/Gems/EMotionFX/Code/Tests/ColliderCommandTests.cpp @@ -24,13 +24,13 @@ namespace EMotionFX CommandSystem::CommandManager commandManager; MCore::CommandGroup commandGroup; - const AZ::u32 actorId = m_actor->GetID(); + const AZ::u32 actorId = GetActor()->GetID(); const AZStd::vector jointNames = GetTestJointNames(); const size_t jointCount = jointNames.size(); // 1. Add colliders - const AZStd::string serializedBeforeAdd = SerializePhysicsSetup(m_actor.get()); + const AZStd::string serializedBeforeAdd = SerializePhysicsSetup(GetActor()); for (const AZStd::string& jointName : jointNames) { CommandColliderHelpers::AddCollider(actorId, jointName, PhysicsSetup::HitDetection, azrtti_typeid(), &commandGroup); @@ -39,23 +39,27 @@ namespace EMotionFX } EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)); - const AZStd::string serializedAfterAdd = SerializePhysicsSetup(m_actor.get()); - EXPECT_EQ(jointCount * 3, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection)); - EXPECT_EQ(jointCount, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box)); + const AZStd::string serializedAfterAdd = SerializePhysicsSetup(GetActor()); + EXPECT_EQ(jointCount * 3, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection)); + EXPECT_EQ( + jointCount, + PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection, /*ignoreShapeType*/ false, Physics::ShapeType::Box)); EXPECT_TRUE(commandManager.Undo(result)); - EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection)); - EXPECT_EQ(serializedBeforeAdd, SerializePhysicsSetup(m_actor.get())); + EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection)); + EXPECT_EQ(serializedBeforeAdd, SerializePhysicsSetup(GetActor())); EXPECT_TRUE(commandManager.Redo(result)); - EXPECT_EQ(jointCount * 3, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection)); - EXPECT_EQ(jointCount, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box)); - EXPECT_EQ(serializedAfterAdd, SerializePhysicsSetup(m_actor.get())); + EXPECT_EQ(jointCount * 3, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection)); + EXPECT_EQ( + jointCount, + PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection, /*ignoreShapeType*/ false, Physics::ShapeType::Box)); + EXPECT_EQ(serializedAfterAdd, SerializePhysicsSetup(GetActor())); // 2. Remove colliders commandGroup.RemoveAllCommands(); - const AZStd::string serializedBeforeRemove = SerializePhysicsSetup(m_actor.get()); + const AZStd::string serializedBeforeRemove = SerializePhysicsSetup(GetActor()); size_t colliderIndexToRemove = 1; for (const AZStd::string& jointName : jointNames) @@ -64,18 +68,24 @@ namespace EMotionFX } EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)); - const AZStd::string serializedAfterRemove = SerializePhysicsSetup(m_actor.get()); - EXPECT_EQ(jointCount * 2, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection)); - EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Capsule)); + const AZStd::string serializedAfterRemove = SerializePhysicsSetup(GetActor()); + EXPECT_EQ(jointCount * 2, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection)); + EXPECT_EQ( + 0, + PhysicsSetupUtils::CountColliders( + GetActor(), PhysicsSetup::HitDetection, /*ignoreShapeType*/ false, Physics::ShapeType::Capsule)); EXPECT_TRUE(commandManager.Undo(result)); - EXPECT_EQ(jointCount * 3, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection)); - EXPECT_EQ(serializedBeforeRemove, SerializePhysicsSetup(m_actor.get())); + EXPECT_EQ(jointCount * 3, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection)); + EXPECT_EQ(serializedBeforeRemove, SerializePhysicsSetup(GetActor())); EXPECT_TRUE(commandManager.Redo(result)); - EXPECT_EQ(jointCount * 2, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection)); - EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Capsule)); - EXPECT_EQ(serializedAfterRemove, SerializePhysicsSetup(m_actor.get())); + EXPECT_EQ(jointCount * 2, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection)); + EXPECT_EQ( + 0, + PhysicsSetupUtils::CountColliders( + GetActor(), PhysicsSetup::HitDetection, /*ignoreShapeType*/ false, Physics::ShapeType::Capsule)); + EXPECT_EQ(serializedAfterRemove, SerializePhysicsSetup(GetActor())); } TEST_F(ColliderCommandTests, AddRemove1000Colliders) @@ -84,11 +94,11 @@ namespace EMotionFX CommandSystem::CommandManager commandManager; MCore::CommandGroup commandGroup; - const AZ::u32 actorId = m_actor->GetID(); + const AZ::u32 actorId = GetActor()->GetID(); const AZStd::string jointName = "Bip01__pelvis"; // 1. Add colliders - const AZStd::string serializedBeforeAdd = SerializePhysicsSetup(m_actor.get()); + const AZStd::string serializedBeforeAdd = SerializePhysicsSetup(GetActor()); const size_t colliderCount = 1000; for (AZ::u32 i = 0; i < colliderCount; ++i) { @@ -96,51 +106,51 @@ namespace EMotionFX } EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)); - const AZStd::string serializedAfterAdd = SerializePhysicsSetup(m_actor.get()); - EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection)); - EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box)); + const AZStd::string serializedAfterAdd = SerializePhysicsSetup(GetActor()); + EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection)); + EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box)); EXPECT_TRUE(commandManager.Undo(result)); - EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection)); - EXPECT_EQ(serializedBeforeAdd, SerializePhysicsSetup(m_actor.get())); + EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection)); + EXPECT_EQ(serializedBeforeAdd, SerializePhysicsSetup(GetActor())); EXPECT_TRUE(commandManager.Redo(result)); - EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection)); - EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box)); - EXPECT_EQ(serializedAfterAdd, SerializePhysicsSetup(m_actor.get())); + EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection)); + EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box)); + EXPECT_EQ(serializedAfterAdd, SerializePhysicsSetup(GetActor())); // 2. Clear colliders commandGroup.RemoveAllCommands(); - const AZStd::string serializedBeforeRemove = SerializePhysicsSetup(m_actor.get()); + const AZStd::string serializedBeforeRemove = SerializePhysicsSetup(GetActor()); CommandColliderHelpers::ClearColliders(actorId, jointName, PhysicsSetup::HitDetection, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)); - const AZStd::string serializedAfterRemove = SerializePhysicsSetup(m_actor.get()); - EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection)); - EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box)); + const AZStd::string serializedAfterRemove = SerializePhysicsSetup(GetActor()); + EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection)); + EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box)); EXPECT_TRUE(commandManager.Undo(result)); - EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection)); - EXPECT_EQ(serializedBeforeRemove, SerializePhysicsSetup(m_actor.get())); + EXPECT_EQ(colliderCount, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection)); + EXPECT_EQ(serializedBeforeRemove, SerializePhysicsSetup(GetActor())); EXPECT_TRUE(commandManager.Redo(result)); - EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection)); - EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box)); - EXPECT_EQ(serializedAfterRemove, SerializePhysicsSetup(m_actor.get())); + EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection)); + EXPECT_EQ(0, PhysicsSetupUtils::CountColliders(GetActor(), PhysicsSetup::HitDetection, /*ignoreShapeType*/false, Physics::ShapeType::Box)); + EXPECT_EQ(serializedAfterRemove, SerializePhysicsSetup(GetActor())); } TEST_F(ColliderCommandTests, AutoSizingColliders) { CommandSystem::CommandManager commandManager; - const AZ::u32 actorId = m_actor->GetID(); + const AZ::u32 actorId = GetActor()->GetID(); const AZStd::vector jointNames = GetTestJointNames(); ASSERT_TRUE(jointNames.size() > 0) << "The joint names test data needs at least one joint for this test."; const AZStd::string& jointName = jointNames[0]; CommandColliderHelpers::AddCollider(actorId, jointName, PhysicsSetup::HitDetection, azrtti_typeid()); - const AZStd::shared_ptr& physicsSetup = m_actor->GetPhysicsSetup(); + const AZStd::shared_ptr& physicsSetup = GetActor()->GetPhysicsSetup(); Physics::CharacterColliderConfiguration* colliderConfig = physicsSetup->GetColliderConfigByType(PhysicsSetup::HitDetection); EXPECT_NE(colliderConfig, nullptr) << "Collider config should be valid after we added a collider to it."; @@ -184,11 +194,11 @@ namespace EMotionFX const PhysicsSetup::ColliderConfigType m_configType = PhysicsSetup::ColliderConfigType::HitDetection; // Add collider to the given joint first. - const AZStd::shared_ptr& physicsSetup = m_actor->GetPhysicsSetup(); - EXPECT_TRUE(CommandColliderHelpers::AddCollider(m_actor->GetID(), m_jointName, m_configType, param.m_shapeType)); + const AZStd::shared_ptr& physicsSetup = GetActor()->GetPhysicsSetup(); + EXPECT_TRUE(CommandColliderHelpers::AddCollider(GetActor()->GetID(), m_jointName, m_configType, param.m_shapeType)); Physics::CharacterColliderConfiguration* characterColliderConfig = physicsSetup->GetColliderConfigByType(m_configType); ASSERT_TRUE(characterColliderConfig != nullptr); - Physics::CharacterColliderNodeConfiguration* nodeConfig = CommandColliderHelpers::GetCreateNodeConfig(m_actor.get(), m_jointName, *characterColliderConfig, result); + Physics::CharacterColliderNodeConfiguration* nodeConfig = CommandColliderHelpers::GetCreateNodeConfig(GetActor(), m_jointName, *characterColliderConfig, result); ASSERT_TRUE(nodeConfig != nullptr); EXPECT_EQ(nodeConfig->m_shapes.size(), 1); @@ -200,7 +210,8 @@ namespace EMotionFX // Create the adjust collider command and using the data from the test parameter. MCore::Command* orgCommand = CommandSystem::GetCommandManager()->FindCommand(CommandAdjustCollider::s_commandName); - CommandAdjustCollider* command = aznew CommandAdjustCollider(m_actor->GetID(), m_jointName, m_configType, /*colliderIndex=*/0, orgCommand); + CommandAdjustCollider* command = + aznew CommandAdjustCollider(GetActor()->GetID(), m_jointName, m_configType, /*colliderIndex=*/0, orgCommand); command->SetOldIsTrigger(colliderConfig->m_isTrigger); command->SetIsTrigger(param.m_isTrigger); command->SetOldPosition(colliderConfig->m_position); @@ -223,9 +234,9 @@ namespace EMotionFX } // Check execute. - const AZStd::string serializedBeforeExecute = SerializePhysicsSetup(m_actor.get()); + const AZStd::string serializedBeforeExecute = SerializePhysicsSetup(GetActor()); EXPECT_TRUE(CommandSystem::GetCommandManager()->ExecuteCommand(command, result)); - const AZStd::string serializedAfterExecute = SerializePhysicsSetup(m_actor.get()); + const AZStd::string serializedAfterExecute = SerializePhysicsSetup(GetActor()); EXPECT_EQ(colliderConfig->m_isTrigger, param.m_isTrigger); EXPECT_EQ(colliderConfig->m_position, param.m_position); @@ -243,12 +254,12 @@ namespace EMotionFX // Check undo. EXPECT_TRUE(CommandSystem::GetCommandManager()->Undo(result)); - const AZStd::string serializedAfterUndo = SerializePhysicsSetup(m_actor.get()); + const AZStd::string serializedAfterUndo = SerializePhysicsSetup(GetActor()); EXPECT_EQ(serializedAfterUndo, serializedBeforeExecute); // Check redo. EXPECT_TRUE(CommandSystem::GetCommandManager()->Redo(result)); - const AZStd::string serializedAfterRedo = SerializePhysicsSetup(m_actor.get()); + const AZStd::string serializedAfterRedo = SerializePhysicsSetup(GetActor()); EXPECT_EQ(serializedAfterRedo, serializedAfterExecute); } diff --git a/Gems/EMotionFX/Code/Tests/Integration/CanAddActor.cpp b/Gems/EMotionFX/Code/Tests/Integration/CanAddActor.cpp index 31e1f75d29..0c3228567e 100644 --- a/Gems/EMotionFX/Code/Tests/Integration/CanAddActor.cpp +++ b/Gems/EMotionFX/Code/Tests/Integration/CanAddActor.cpp @@ -13,9 +13,11 @@ #include #include +#include +#include #include #include -#include +#include namespace EMotionFX { @@ -33,14 +35,12 @@ namespace EMotionFX ASSERT_EQ(GetActorManager().GetNumActors(), 0); // Load an Actor - const char* actorCmd{ "ImportActor -filename @engroot@/Gems/EMotionFX/Code/Tests/TestAssets/Rin/rin.actor" }; - { - AZStd::string result; - EXPECT_TRUE(CommandSystem::GetCommandManager()->ExecuteCommand(actorCmd, result)) << result.c_str(); - } + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = + TestActorAssets::CreateActorAssetAndRegister(actorAssetId, "Jack"); // Ensure the Actor is correct - ASSERT_TRUE(GetActorManager().FindActorByName("rinActor")); + ASSERT_TRUE(GetActorManager().FindActorByName("Jack")); EXPECT_EQ(GetActorManager().GetNumActors(), 1); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Tests/MotionExtractionBusTests.cpp b/Gems/EMotionFX/Code/Tests/MotionExtractionBusTests.cpp index 170f4d2d75..347d8f93a8 100644 --- a/Gems/EMotionFX/Code/Tests/MotionExtractionBusTests.cpp +++ b/Gems/EMotionFX/Code/Tests/MotionExtractionBusTests.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include diff --git a/Gems/EMotionFX/Code/Tests/MultiThreadSchedulerTests.cpp b/Gems/EMotionFX/Code/Tests/MultiThreadSchedulerTests.cpp index 180da46746..02622ecd67 100644 --- a/Gems/EMotionFX/Code/Tests/MultiThreadSchedulerTests.cpp +++ b/Gems/EMotionFX/Code/Tests/MultiThreadSchedulerTests.cpp @@ -9,6 +9,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/AnimGraphActivateTests.cpp b/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/AnimGraphActivateTests.cpp index 78cac409a6..dea332b40e 100644 --- a/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/AnimGraphActivateTests.cpp +++ b/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/AnimGraphActivateTests.cpp @@ -19,11 +19,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include namespace EMotionFX @@ -78,7 +80,8 @@ namespace EMotionFX EXPECT_TRUE(CommandSystem::GetCommandManager()->ExecuteCommandGroup(group, commandResult)) << commandResult.c_str(); // Create temp Actor - m_actor = ActorFactory::CreateAndInit(1, "tempActor"); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + m_actorAsset = TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 1, "tempActor"); // Cache some local poitners. m_animGraphPlugin = static_cast(EMStudio::GetPluginManager()->FindActivePlugin(EMStudio::AnimGraphPlugin::CLASS_ID)); @@ -90,6 +93,7 @@ namespace EMotionFX void TearDown() override { + GetEMotionFX().GetActorManager()->UnregisterAllActors(); QApplication::processEvents(QEventLoop::ExcludeUserInputEvents); delete m_animGraph; UIFixture::TearDown(); @@ -104,7 +108,7 @@ namespace EMotionFX AZStd::string m_entryNodeName = "testEntry"; AnimGraph* m_animGraph = nullptr; EMStudio::AnimGraphPlugin* m_animGraphPlugin = nullptr; - AutoRegisteredActor m_actor; + AZ::Data::Asset m_actorAsset; }; TEST_F(PopulatedAnimGraphFixture, CanActivateValidGraph) diff --git a/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/AnimGraphModelTests.cpp b/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/AnimGraphModelTests.cpp index 4ffc9e0097..b9b96bb59c 100644 --- a/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/AnimGraphModelTests.cpp +++ b/Gems/EMotionFX/Code/Tests/ProvidesUI/AnimGraph/AnimGraphModelTests.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -43,6 +42,7 @@ #include #include #include +#include #include namespace EMotionFX @@ -423,7 +423,10 @@ namespace EMotionFX using testing::Eq; using testing::Not; - AutoRegisteredActor actor = EMotionFX::ActorFactory::CreateAndInit(1); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = + TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 1); + auto motionSet = AZStd::make_unique(); { @@ -432,7 +435,7 @@ namespace EMotionFX } auto* animGraph = EMotionFX::GetAnimGraphManager().FindAnimGraphByID(0); - auto* actorInstance = EMotionFX::ActorInstance::Create(actor.get()); + auto* actorInstance = EMotionFX::ActorInstance::Create(actorAsset->GetActor()); auto* animGraphInstance = EMotionFX::AnimGraphInstance::Create(animGraph, actorInstance, motionSet.get()); actorInstance->SetAnimGraphInstance(animGraphInstance); diff --git a/Gems/EMotionFX/Code/Tests/ProvidesUI/Menus/FileMenu/CanReset.cpp b/Gems/EMotionFX/Code/Tests/ProvidesUI/Menus/FileMenu/CanReset.cpp index d53ddcc924..c374938590 100644 --- a/Gems/EMotionFX/Code/Tests/ProvidesUI/Menus/FileMenu/CanReset.cpp +++ b/Gems/EMotionFX/Code/Tests/ProvidesUI/Menus/FileMenu/CanReset.cpp @@ -24,12 +24,11 @@ #include #include -#include #include #include +#include #include - namespace EMotionFX { @@ -58,8 +57,10 @@ namespace EMotionFX ASSERT_EQ(GetMotionManager().GetNumMotions(), 0) << "Expected exactly zero motions"; // Create Actor, AnimGraph, Motionset and Motion - AutoRegisteredActor actor = ActorFactory::CreateAndInit(2, "SampleActor"); - ActorInstance::Create(actor.get()); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = + TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 2, "SampleActor"); + ActorInstance::Create(actorAsset->GetActor()); { AZStd::string result; ASSERT_TRUE(CommandSystem::GetCommandManager()->ExecuteCommand(createAnimGraphCmd, result)) << result.c_str(); diff --git a/Gems/EMotionFX/Code/Tests/ProvidesUI/Ragdoll/CanCopyPasteColliders.cpp b/Gems/EMotionFX/Code/Tests/ProvidesUI/Ragdoll/CanCopyPasteColliders.cpp index 4f43e7dae5..17f07b2180 100644 --- a/Gems/EMotionFX/Code/Tests/ProvidesUI/Ragdoll/CanCopyPasteColliders.cpp +++ b/Gems/EMotionFX/Code/Tests/ProvidesUI/Ragdoll/CanCopyPasteColliders.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include namespace EMotionFX @@ -79,7 +80,11 @@ namespace EMotionFX TEST_F(CopyPasteRagdollCollidersFixture, CanCopyCollider) #endif // AZ_TRAIT_DISABLE_FAILED_EMOTION_FX_EDITOR_TESTS { - AutoRegisteredActor actor{ActorFactory::CreateAndInit(4)}; + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = + TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 4); + const Actor* actor = actorAsset->GetActor(); + const Physics::RagdollConfiguration& ragdollConfig = actor->GetPhysicsSetup()->GetRagdollConfig(); const Physics::CharacterColliderConfiguration& simulatedObjectConfig = actor->GetPhysicsSetup()->GetSimulatedObjectColliderConfig(); @@ -104,8 +109,7 @@ namespace EMotionFX { AZStd::string result; - EXPECT_TRUE(CommandSystem::GetCommandManager()->ExecuteCommand( - "Select -actorId " + AZStd::to_string(actor->GetID()), + EXPECT_TRUE(CommandSystem::GetCommandManager()->ExecuteCommand("Select -actorId " + AZStd::to_string(actor->GetID()), result)) << result.c_str(); } diff --git a/Gems/EMotionFX/Code/Tests/ProvidesUI/Ragdoll/CanCopyPasteJointLimits.cpp b/Gems/EMotionFX/Code/Tests/ProvidesUI/Ragdoll/CanCopyPasteJointLimits.cpp index 8e4fba0dd6..3f475c7916 100644 --- a/Gems/EMotionFX/Code/Tests/ProvidesUI/Ragdoll/CanCopyPasteJointLimits.cpp +++ b/Gems/EMotionFX/Code/Tests/ProvidesUI/Ragdoll/CanCopyPasteJointLimits.cpp @@ -14,7 +14,6 @@ #include #include -#include #include #include #include @@ -25,6 +24,7 @@ #include #include #include +#include #include namespace EMotionFX @@ -76,7 +76,9 @@ namespace EMotionFX return AZStd::make_unique(); }); - AutoRegisteredActor actor {ActorFactory::CreateAndInit(4)}; + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 4); + const Actor* actor = actorAsset->GetActor(); { AZStd::string result; diff --git a/Gems/EMotionFX/Code/Tests/RagdollCommandTests.cpp b/Gems/EMotionFX/Code/Tests/RagdollCommandTests.cpp index e9a4cc0c26..1004b0a1f6 100644 --- a/Gems/EMotionFX/Code/Tests/RagdollCommandTests.cpp +++ b/Gems/EMotionFX/Code/Tests/RagdollCommandTests.cpp @@ -99,28 +99,28 @@ namespace EMotionFX "l_hand", }; - CommandRagdollHelpers::AddJointsToRagdoll(m_actor->GetID(), {"l_shldr"}, &commandGroup); + CommandRagdollHelpers::AddJointsToRagdoll(GetActor()->GetID(), {"l_shldr"}, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)) << result.c_str(); EXPECT_THAT( - GetRagdollJointNames(m_actor.get()), + GetRagdollJointNames(GetActor()), testing::UnorderedPointwise( StrEq(), jointsToLeftShoulder ) ); - const AZStd::string serializedBeforeHandAdded = SerializePhysicsSetup(m_actor.get()); + const AZStd::string serializedBeforeHandAdded = SerializePhysicsSetup(GetActor()); // Adding l_hand should add l_upArm and l_loArm as well commandGroup.RemoveAllCommands(); - CommandRagdollHelpers::AddJointsToRagdoll(m_actor->GetID(), {"l_hand"}, &commandGroup); + CommandRagdollHelpers::AddJointsToRagdoll(GetActor()->GetID(), {"l_hand"}, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)) << result.c_str(); - const AZStd::string serializedAfterHandAdded = SerializePhysicsSetup(m_actor.get()); + const AZStd::string serializedAfterHandAdded = SerializePhysicsSetup(GetActor()); EXPECT_THAT( - GetRagdollJointNames(m_actor.get()), + GetRagdollJointNames(GetActor()), testing::UnorderedPointwise( StrEq(), jointsToLeftHand @@ -129,23 +129,23 @@ namespace EMotionFX EXPECT_TRUE(commandManager.Undo(result)) << result.c_str(); EXPECT_THAT( - GetRagdollJointNames(m_actor.get()), + GetRagdollJointNames(GetActor()), testing::UnorderedPointwise( StrEq(), jointsToLeftShoulder ) ); - EXPECT_THAT(SerializePhysicsSetup(m_actor.get()), StrEq(serializedBeforeHandAdded)); + EXPECT_THAT(SerializePhysicsSetup(GetActor()), StrEq(serializedBeforeHandAdded)); EXPECT_TRUE(commandManager.Redo(result)) << result.c_str(); EXPECT_THAT( - GetRagdollJointNames(m_actor.get()), + GetRagdollJointNames(GetActor()), testing::UnorderedPointwise( StrEq(), jointsToLeftHand ) ); - EXPECT_THAT(SerializePhysicsSetup(m_actor.get()), StrEq(serializedAfterHandAdded)); + EXPECT_THAT(SerializePhysicsSetup(GetActor()), StrEq(serializedAfterHandAdded)); } TEST_F(RagdollCommandTests, AddJointHigherInHierarchy) @@ -166,10 +166,10 @@ namespace EMotionFX "l_hand", }; - CommandRagdollHelpers::AddJointsToRagdoll(m_actor->GetID(), {"l_hand"}, &commandGroup); + CommandRagdollHelpers::AddJointsToRagdoll(GetActor()->GetID(), {"l_hand"}, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)) << result.c_str(); EXPECT_THAT( - GetRagdollJointNames(m_actor.get()), + GetRagdollJointNames(GetActor()), testing::UnorderedPointwise( StrEq(), jointsToLeftHand @@ -178,10 +178,10 @@ namespace EMotionFX // l_shldr should already be in the ragdoll, so adding it should do nothing commandGroup.RemoveAllCommands(); - CommandRagdollHelpers::AddJointsToRagdoll(m_actor->GetID(), {"l_shldr"}, &commandGroup); + CommandRagdollHelpers::AddJointsToRagdoll(GetActor()->GetID(), {"l_shldr"}, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)) << result.c_str(); EXPECT_THAT( - GetRagdollJointNames(m_actor.get()), + GetRagdollJointNames(GetActor()), testing::UnorderedPointwise( StrEq(), jointsToLeftHand @@ -190,11 +190,11 @@ namespace EMotionFX // Undo here undoes the addition of l_hand EXPECT_TRUE(commandManager.Undo(result)) << result.c_str(); - EXPECT_TRUE(GetRagdollJointNames(m_actor.get()).empty()); + EXPECT_TRUE(GetRagdollJointNames(GetActor()).empty()); EXPECT_TRUE(commandManager.Redo(result)) << result.c_str(); EXPECT_THAT( - GetRagdollJointNames(m_actor.get()), + GetRagdollJointNames(GetActor()), testing::UnorderedPointwise( StrEq(), jointsToLeftHand @@ -221,16 +221,16 @@ namespace EMotionFX }; // Add a joint to the ragdoll that does not make a chain all the way to the root - EXPECT_TRUE(commandManager.ExecuteCommand(aznew CommandAddRagdollJoint(m_actor->GetID(), "l_shldr"), result)) << result.c_str(); + EXPECT_TRUE(commandManager.ExecuteCommand(aznew CommandAddRagdollJoint(GetActor()->GetID(), "l_shldr"), result)) << result.c_str(); EXPECT_THAT( - GetRagdollJointNames(m_actor.get()), + GetRagdollJointNames(GetActor()), testing::UnorderedPointwise(StrEq(), AZStd::vector{"l_shldr"}) ); - CommandRagdollHelpers::AddJointsToRagdoll(m_actor->GetID(), {"l_hand"}, &commandGroup); + CommandRagdollHelpers::AddJointsToRagdoll(GetActor()->GetID(), {"l_hand"}, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)) << result.c_str(); EXPECT_THAT( - GetRagdollJointNames(m_actor.get()), + GetRagdollJointNames(GetActor()), testing::UnorderedPointwise(StrEq(), jointsToLeftHand) ); } @@ -250,17 +250,17 @@ namespace EMotionFX }; // Add joints from the root to the left hand - CommandRagdollHelpers::AddJointsToRagdoll(m_actor->GetID(), {"l_hand"}, &commandGroup); + CommandRagdollHelpers::AddJointsToRagdoll(GetActor()->GetID(), {"l_hand"}, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)) << result.c_str(); // Removing the left shoulder should remove the elbow, wrist, and hand // as well commandGroup.RemoveAllCommands(); - CommandRagdollHelpers::RemoveJointsFromRagdoll(m_actor->GetID(), {"l_shldr"}, &commandGroup); + CommandRagdollHelpers::RemoveJointsFromRagdoll(GetActor()->GetID(), {"l_shldr"}, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)) << result.c_str(); EXPECT_THAT( - GetRagdollJointNames(m_actor.get()), + GetRagdollJointNames(GetActor()), testing::UnorderedPointwise(StrEq(), jointsToSpine3) ); } @@ -271,24 +271,24 @@ namespace EMotionFX CommandSystem::CommandManager commandManager; MCore::CommandGroup commandGroup; - CommandRagdollHelpers::AddJointsToRagdoll(m_actor->GetID(), {"l_hand"}, &commandGroup); + CommandRagdollHelpers::AddJointsToRagdoll(GetActor()->GetID(), {"l_hand"}, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)) << result.c_str(); - const AZStd::string serializedBeforeSphereAdded = SerializePhysicsSetup(m_actor.get()); + const AZStd::string serializedBeforeSphereAdded = SerializePhysicsSetup(GetActor()); - CommandColliderHelpers::AddCollider(m_actor->GetID(), "l_hand", + CommandColliderHelpers::AddCollider(GetActor()->GetID(), "l_hand", PhysicsSetup::Ragdoll, azrtti_typeid()); - const AZStd::string serializedAfterSphereAdded = SerializePhysicsSetup(m_actor.get()); + const AZStd::string serializedAfterSphereAdded = SerializePhysicsSetup(GetActor()); EXPECT_THAT(serializedAfterSphereAdded, ::testing::Not(StrEq(serializedBeforeSphereAdded))); EXPECT_TRUE(commandManager.Undo(result)) << result.c_str(); - EXPECT_THAT(SerializePhysicsSetup(m_actor.get()), StrEq(serializedBeforeSphereAdded)); + EXPECT_THAT(SerializePhysicsSetup(GetActor()), StrEq(serializedBeforeSphereAdded)); EXPECT_TRUE(commandManager.Redo(result)) << result.c_str(); - EXPECT_THAT(SerializePhysicsSetup(m_actor.get()), StrEq(serializedAfterSphereAdded)); + EXPECT_THAT(SerializePhysicsSetup(GetActor()), StrEq(serializedAfterSphereAdded)); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Tests/SimulatedObjectCommandTests.cpp b/Gems/EMotionFX/Code/Tests/SimulatedObjectCommandTests.cpp index 4bac70c13d..dab761f649 100644 --- a/Gems/EMotionFX/Code/Tests/SimulatedObjectCommandTests.cpp +++ b/Gems/EMotionFX/Code/Tests/SimulatedObjectCommandTests.cpp @@ -55,25 +55,25 @@ namespace EMotionFX CommandSystem::CommandManager commandManager; MCore::CommandGroup commandGroup; - const uint32 actorId = m_actor->GetID(); + const uint32 actorId = GetActor()->GetID(); const AZStd::vector jointNames = GetTestJointNames(); // 1. Add simulated object. - const AZStd::string serializedBeforeAdd = SerializeSimulatedObjectSetup(m_actor.get()); + const AZStd::string serializedBeforeAdd = SerializeSimulatedObjectSetup(GetActor()); CommandSimulatedObjectHelpers::AddSimulatedObject(actorId, AZStd::nullopt, &commandGroup); CommandSimulatedObjectHelpers::AddSimulatedObject(actorId, AZStd::nullopt, &commandGroup); CommandSimulatedObjectHelpers::AddSimulatedObject(actorId, AZStd::nullopt, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)); - const AZStd::string serializedAfterAdd = SerializeSimulatedObjectSetup(m_actor.get()); - EXPECT_EQ(3, CountSimulatedObjects(m_actor.get())); + const AZStd::string serializedAfterAdd = SerializeSimulatedObjectSetup(GetActor()); + EXPECT_EQ(3, CountSimulatedObjects(GetActor())); EXPECT_TRUE(commandManager.Undo(result)); - EXPECT_EQ(0, CountSimulatedObjects(m_actor.get())); - EXPECT_EQ(serializedBeforeAdd, SerializeSimulatedObjectSetup(m_actor.get())); + EXPECT_EQ(0, CountSimulatedObjects(GetActor())); + EXPECT_EQ(serializedBeforeAdd, SerializeSimulatedObjectSetup(GetActor())); EXPECT_TRUE(commandManager.Redo(result)); - EXPECT_EQ(3, CountSimulatedObjects(m_actor.get())); - EXPECT_EQ(serializedAfterAdd, SerializeSimulatedObjectSetup(m_actor.get())); + EXPECT_EQ(3, CountSimulatedObjects(GetActor())); + EXPECT_EQ(serializedAfterAdd, SerializeSimulatedObjectSetup(GetActor())); // 2. Remove simulated object. commandGroup.RemoveAllCommands(); @@ -81,22 +81,22 @@ namespace EMotionFX CommandSimulatedObjectHelpers::RemoveSimulatedObject(actorId, 0, &commandGroup); CommandSimulatedObjectHelpers::RemoveSimulatedObject(actorId, 0, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)); - EXPECT_EQ(0, CountSimulatedObjects(m_actor.get())); - EXPECT_EQ(serializedBeforeAdd, SerializeSimulatedObjectSetup(m_actor.get())); + EXPECT_EQ(0, CountSimulatedObjects(GetActor())); + EXPECT_EQ(serializedBeforeAdd, SerializeSimulatedObjectSetup(GetActor())); EXPECT_TRUE(commandManager.Undo(result)); - EXPECT_EQ(3, CountSimulatedObjects(m_actor.get())); - EXPECT_EQ(serializedAfterAdd, SerializeSimulatedObjectSetup(m_actor.get())); + EXPECT_EQ(3, CountSimulatedObjects(GetActor())); + EXPECT_EQ(serializedAfterAdd, SerializeSimulatedObjectSetup(GetActor())); EXPECT_TRUE(commandManager.Redo(result)); - EXPECT_EQ(0, CountSimulatedObjects(m_actor.get())); - EXPECT_EQ(serializedBeforeAdd, SerializeSimulatedObjectSetup(m_actor.get())); + EXPECT_EQ(0, CountSimulatedObjects(GetActor())); + EXPECT_EQ(serializedBeforeAdd, SerializeSimulatedObjectSetup(GetActor())); // 3. Add simulated joints. // 3.1 Add a simulated object first to put in the simulated joints. commandGroup.RemoveAllCommands(); CommandSimulatedObjectHelpers::AddSimulatedObject(actorId); - const AZStd::string serialized3_1 = SerializeSimulatedObjectSetup(m_actor.get()); + const AZStd::string serialized3_1 = SerializeSimulatedObjectSetup(GetActor()); // 3.2 Add simulated joints. // Joint hierarchy as follow: @@ -105,7 +105,7 @@ namespace EMotionFX // --l_loLeg // --l_ankle // --l_ball - const Skeleton* skeleton = m_actor->GetSkeleton(); + const Skeleton* skeleton = GetActor()->GetSkeleton(); const size_t l_upLegIdx = skeleton->FindNodeByName("l_upLeg")->GetNodeIndex(); const size_t l_upLegRollIdx = skeleton->FindNodeByName("l_upLegRoll")->GetNodeIndex(); const size_t l_loLegIdx = skeleton->FindNodeByName("l_loLeg")->GetNodeIndex(); @@ -113,33 +113,33 @@ namespace EMotionFX const size_t l_ballIdx = skeleton->FindNodeByName("l_ball")->GetNodeIndex(); CommandSimulatedObjectHelpers::AddSimulatedJoints(actorId, {l_upLegIdx, l_upLegRollIdx, l_loLegIdx, l_ankleIdx, l_ballIdx}, 0, false, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)); - const AZStd::string serialized3_2 = SerializeSimulatedObjectSetup(m_actor.get()); - EXPECT_EQ(5, CountSimulatedJoints(m_actor.get(), 0)); - EXPECT_EQ(2, CountChildJoints(m_actor.get(), 0, l_upLegIdx)); - EXPECT_EQ(0, CountChildJoints(m_actor.get(), 0, l_upLegRollIdx)); - EXPECT_EQ(1, CountChildJoints(m_actor.get(), 0, l_loLegIdx)); + const AZStd::string serialized3_2 = SerializeSimulatedObjectSetup(GetActor()); + EXPECT_EQ(5, CountSimulatedJoints(GetActor(), 0)); + EXPECT_EQ(2, CountChildJoints(GetActor(), 0, l_upLegIdx)); + EXPECT_EQ(0, CountChildJoints(GetActor(), 0, l_upLegRollIdx)); + EXPECT_EQ(1, CountChildJoints(GetActor(), 0, l_loLegIdx)); EXPECT_TRUE(commandManager.Undo(result)); - EXPECT_EQ(0, CountSimulatedJoints(m_actor.get(), 0)); - EXPECT_EQ(serialized3_1, SerializeSimulatedObjectSetup(m_actor.get())); + EXPECT_EQ(0, CountSimulatedJoints(GetActor(), 0)); + EXPECT_EQ(serialized3_1, SerializeSimulatedObjectSetup(GetActor())); EXPECT_TRUE(commandManager.Redo(result)); - EXPECT_EQ(5, CountSimulatedJoints(m_actor.get(), 0)); - EXPECT_EQ(serialized3_2, SerializeSimulatedObjectSetup(m_actor.get())); + EXPECT_EQ(5, CountSimulatedJoints(GetActor(), 0)); + EXPECT_EQ(serialized3_2, SerializeSimulatedObjectSetup(GetActor())); // 4 Remove simulated joints. // 4.1 Test sparse chain. - EXPECT_EQ(1, CountRootJoints(m_actor.get(), 0)); + EXPECT_EQ(1, CountRootJoints(GetActor(), 0)); commandGroup.RemoveAllCommands(); CommandSimulatedObjectHelpers::RemoveSimulatedJoints(actorId, {l_loLegIdx}, 0, false, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)); - EXPECT_EQ(2, CountRootJoints(m_actor.get(), 0)); + EXPECT_EQ(2, CountRootJoints(GetActor(), 0)); EXPECT_TRUE(commandManager.Undo(result)); - EXPECT_EQ(1, CountRootJoints(m_actor.get(), 0)); + EXPECT_EQ(1, CountRootJoints(GetActor(), 0)); EXPECT_TRUE(commandManager.Redo(result)); - EXPECT_EQ(2, CountRootJoints(m_actor.get(), 0)); + EXPECT_EQ(2, CountRootJoints(GetActor(), 0)); EXPECT_TRUE(commandManager.Undo(result)); @@ -147,23 +147,23 @@ namespace EMotionFX commandGroup.RemoveAllCommands(); CommandSimulatedObjectHelpers::RemoveSimulatedJoints(actorId, { l_upLegIdx, l_upLegRollIdx, l_loLegIdx, l_ankleIdx, l_ballIdx }, 0, false, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)); - EXPECT_EQ(0, CountSimulatedJoints(m_actor.get(), 0)); - EXPECT_EQ(serialized3_1, SerializeSimulatedObjectSetup(m_actor.get())); + EXPECT_EQ(0, CountSimulatedJoints(GetActor(), 0)); + EXPECT_EQ(serialized3_1, SerializeSimulatedObjectSetup(GetActor())); EXPECT_TRUE(commandManager.Undo(result)); - EXPECT_EQ(5, CountSimulatedJoints(m_actor.get(), 0)); - EXPECT_EQ(serialized3_2, SerializeSimulatedObjectSetup(m_actor.get())); + EXPECT_EQ(5, CountSimulatedJoints(GetActor(), 0)); + EXPECT_EQ(serialized3_2, SerializeSimulatedObjectSetup(GetActor())); // 4.3 Test removing the root joint and children. commandGroup.RemoveAllCommands(); CommandSimulatedObjectHelpers::RemoveSimulatedJoints(actorId, { l_upLegIdx }, 0, true, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)); - EXPECT_EQ(0, CountSimulatedJoints(m_actor.get(), 0)); - EXPECT_EQ(serialized3_1, SerializeSimulatedObjectSetup(m_actor.get())); + EXPECT_EQ(0, CountSimulatedJoints(GetActor(), 0)); + EXPECT_EQ(serialized3_1, SerializeSimulatedObjectSetup(GetActor())); EXPECT_TRUE(commandManager.Undo(result)); - EXPECT_EQ(5, CountSimulatedJoints(m_actor.get(), 0)); - EXPECT_EQ(serialized3_2, SerializeSimulatedObjectSetup(m_actor.get())); + EXPECT_EQ(5, CountSimulatedJoints(GetActor(), 0)); + EXPECT_EQ(serialized3_2, SerializeSimulatedObjectSetup(GetActor())); } TEST_F(SimulatedObjectCommandTests, SimulatedObjectCommands_UndoRemoveJointTest) @@ -172,35 +172,35 @@ namespace EMotionFX CommandSystem::CommandManager commandManager; MCore::CommandGroup commandGroup; - const uint32 actorId = m_actor->GetID(); + const uint32 actorId = GetActor()->GetID(); const AZStd::vector jointNames = GetTestJointNames(); // 1. Add simulated object CommandSimulatedObjectHelpers::AddSimulatedObject(actorId, AZStd::nullopt, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)); - const AZStd::string serializedBase = SerializeSimulatedObjectSetup(m_actor.get()); + const AZStd::string serializedBase = SerializeSimulatedObjectSetup(GetActor()); const size_t simulatedObjectIndex = 0; // 2. Add r_upLeg simulated joints - const Skeleton* skeleton = m_actor->GetSkeleton(); + const Skeleton* skeleton = GetActor()->GetSkeleton(); const size_t r_upLegIdx = skeleton->FindNodeByName("r_upLeg")->GetNodeIndex(); const size_t r_loLegIdx = skeleton->FindNodeByName("r_loLeg")->GetNodeIndex(); CommandSimulatedObjectHelpers::AddSimulatedJoints(actorId, { r_upLegIdx, r_loLegIdx }, 0, false); - EXPECT_EQ(2, CountSimulatedJoints(m_actor.get(), 0)); - const AZStd::string serializedUpLeg = SerializeSimulatedObjectSetup(m_actor.get()); + EXPECT_EQ(2, CountSimulatedJoints(GetActor(), 0)); + const AZStd::string serializedUpLeg = SerializeSimulatedObjectSetup(GetActor()); // 3. Remove the r_loLeg simulated joint AZStd::vector jointsToBeRemoved; commandGroup.RemoveAllCommands(); CommandSimulatedObjectHelpers::RemoveSimulatedJoints(actorId, { r_upLegIdx }, simulatedObjectIndex, true, &commandGroup); EXPECT_TRUE(commandManager.ExecuteCommandGroup(commandGroup, result)); - EXPECT_EQ(0, CountSimulatedJoints(m_actor.get(), 0)); - EXPECT_EQ(serializedBase, SerializeSimulatedObjectSetup(m_actor.get())); + EXPECT_EQ(0, CountSimulatedJoints(GetActor(), 0)); + EXPECT_EQ(serializedBase, SerializeSimulatedObjectSetup(GetActor())); // 4. Undo // This recreates r_loLeg and r_loLeg but won't add all other children recursively as only these two joints got aded in step 3. EXPECT_TRUE(commandManager.Undo(result)); - EXPECT_EQ(2, CountSimulatedJoints(m_actor.get(), 0)); - EXPECT_EQ(serializedUpLeg, SerializeSimulatedObjectSetup(m_actor.get())); + EXPECT_EQ(2, CountSimulatedJoints(GetActor(), 0)); + EXPECT_EQ(serializedUpLeg, SerializeSimulatedObjectSetup(GetActor())); } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Tests/SimulatedObjectModelTests.cpp b/Gems/EMotionFX/Code/Tests/SimulatedObjectModelTests.cpp index 41269cec77..85da96412b 100644 --- a/Gems/EMotionFX/Code/Tests/SimulatedObjectModelTests.cpp +++ b/Gems/EMotionFX/Code/Tests/SimulatedObjectModelTests.cpp @@ -22,17 +22,21 @@ #include #include #include +#include namespace EMotionFX { using SimulatedObjectModelTestsFixture = UIFixture; TEST_F(SimulatedObjectModelTestsFixture, CanUndoAddSimulatedObjectAndSimulatedJointWithChildren) { - AutoRegisteredActor actor = ActorFactory::CreateAndInit(3, "simulatedObjectModelTestActor"); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = + TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 3, "simulatedObjectModelTestActor"); + const Actor* actor = actorAsset->GetActor(); EMotionFX::SimulatedObjectWidget* simulatedObjectWidget = static_cast(EMStudio::GetPluginManager()->FindActivePlugin(EMotionFX::SimulatedObjectWidget::CLASS_ID)); ASSERT_TRUE(simulatedObjectWidget) << "Simulated Object plugin not loaded"; - simulatedObjectWidget->ActorSelectionChanged(actor.get()); + simulatedObjectWidget->ActorSelectionChanged(actorAsset->GetActor()); SimulatedObjectModel* model = simulatedObjectWidget->GetSimulatedObjectModel(); diff --git a/Gems/EMotionFX/Code/Tests/SimulatedObjectSerializeTests.cpp b/Gems/EMotionFX/Code/Tests/SimulatedObjectSerializeTests.cpp index c261f63bc1..e5c2c5ce4f 100644 --- a/Gems/EMotionFX/Code/Tests/SimulatedObjectSerializeTests.cpp +++ b/Gems/EMotionFX/Code/Tests/SimulatedObjectSerializeTests.cpp @@ -20,7 +20,7 @@ namespace EMotionFX TEST_F(SimulatedObjectSerializeTests, SerializeTest) { - SimulatedObjectSetup* setup = m_actor->GetSimulatedObjectSetup().get(); + SimulatedObjectSetup* setup = GetActor()->GetSimulatedObjectSetup().get(); // Build some setup. SimulatedObject* object = setup->AddSimulatedObject(); @@ -29,7 +29,7 @@ namespace EMotionFX object->SetGravityFactor(3.0f); object->SetStiffnessFactor(4.0f); const AZStd::vector jointNames = { "l_upArm", "l_loArm", "l_hand" }; - Skeleton* skeleton = m_actor->GetSkeleton(); + Skeleton* skeleton = GetActor()->GetSkeleton(); for (const AZStd::string& name : jointNames) { size_t skeletonJointIndex; @@ -50,7 +50,7 @@ namespace EMotionFX object->GetSimulatedJoint(0)->SetPinned(true); // Serialize it and deserialize it. - const AZStd::string serialized = SerializeSimulatedObjectSetup(m_actor.get()); + const AZStd::string serialized = SerializeSimulatedObjectSetup(GetActor()); AZStd::unique_ptr loadedSetup(DeserializeSimulatedObjectSetup(serialized)); // Verify some of the contents of the deserialized version. diff --git a/Gems/EMotionFX/Code/Tests/SkeletalLODTests.cpp b/Gems/EMotionFX/Code/Tests/SkeletalLODTests.cpp index 1252eb36ae..54a81cb559 100644 --- a/Gems/EMotionFX/Code/Tests/SkeletalLODTests.cpp +++ b/Gems/EMotionFX/Code/Tests/SkeletalLODTests.cpp @@ -22,13 +22,13 @@ namespace EMotionFX void SetUp() { ActorFixture::SetUp(); - m_actor->AddLODLevel(); + GetActor()->AddLODLevel(); DisableJointsForLOD(m_disabledJointNames, 1); } void DisableJointsForLOD(const std::vector& jointNames, size_t lodLevel) { - const Skeleton* skeleton = m_actor->GetSkeleton(); + const Skeleton* skeleton = GetActor()->GetSkeleton(); for (const std::string& jointName : jointNames) { Node* joint = skeleton->FindNodeByName(jointName.c_str()); diff --git a/Gems/EMotionFX/Code/Tests/TestAssetCode/TestActorAssets.cpp b/Gems/EMotionFX/Code/Tests/TestAssetCode/TestActorAssets.cpp index 6375d48c6b..bb3c4f76e2 100644 --- a/Gems/EMotionFX/Code/Tests/TestAssetCode/TestActorAssets.cpp +++ b/Gems/EMotionFX/Code/Tests/TestAssetCode/TestActorAssets.cpp @@ -10,9 +10,10 @@ #include #include #include -#include #include #include +#include +#include namespace EMotionFX { diff --git a/Gems/EMotionFX/Code/Tests/TestAssetCode/TestActorAssets.h b/Gems/EMotionFX/Code/Tests/TestAssetCode/TestActorAssets.h index 3a041fcf34..5b75ddf590 100644 --- a/Gems/EMotionFX/Code/Tests/TestAssetCode/TestActorAssets.h +++ b/Gems/EMotionFX/Code/Tests/TestAssetCode/TestActorAssets.h @@ -10,6 +10,9 @@ #include #include +#include +#include +#include namespace EMotionFX { @@ -18,5 +21,14 @@ namespace EMotionFX public: static AZStd::string FileToBase64(const char* filePath); static AZ::Data::Asset GetAssetFromActor(const AZ::Data::AssetId& assetId, AZStd::unique_ptr&& actor); + + template + static AZ::Data::Asset CreateActorAssetAndRegister(const AZ::Data::AssetId& assetId, Args&&... args) + { + AZStd::unique_ptr actor = ActorFactory::CreateAndInit(AZStd::forward(args)...); + AZ::Data::Asset actorAsset = TestActorAssets::GetAssetFromActor(assetId, AZStd::move(actor)); + GetEMotionFX().GetActorManager()->RegisterActor(actorAsset); + return AZStd::move(actorAsset); + } }; } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Tests/UI/CanAddJointAndChildren.cpp b/Gems/EMotionFX/Code/Tests/UI/CanAddJointAndChildren.cpp index 59506a9d43..32240ba409 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanAddJointAndChildren.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanAddJointAndChildren.cpp @@ -16,13 +16,13 @@ #include #include -#include #include #include #include #include #include +#include namespace EMotionFX { @@ -37,8 +37,11 @@ namespace EMotionFX RecordProperty("test_case_id", "C13048819"); // Create an actor - AutoRegisteredActor actor = ActorFactory::CreateAndInit(5, "SimpleActor"); - ActorInstance* actorInstance = ActorInstance::Create(actor.get()); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = + TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 5, "SimpleActor"); + ActorInstance* actorInstance = ActorInstance::Create(actorAsset->GetActor()); + const Actor* actor = actorAsset->GetActor(); // Open simulated objects layout EMStudio::GetMainWindow()->ApplicationModeChanged("SimulatedObjects"); diff --git a/Gems/EMotionFX/Code/Tests/UI/CanAddSimulatedObject.cpp b/Gems/EMotionFX/Code/Tests/UI/CanAddSimulatedObject.cpp index e1c4525a9e..0820895db8 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanAddSimulatedObject.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanAddSimulatedObject.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -27,6 +26,7 @@ #include #include +#include #include #include @@ -81,9 +81,9 @@ namespace EMotionFX inputDialog->accept(); // There is one and only one simulated objects - ASSERT_EQ(m_actor->GetSimulatedObjectSetup()->GetNumSimulatedObjects(), 1); + ASSERT_EQ(m_actorAsset->GetActor()->GetSimulatedObjectSetup()->GetNumSimulatedObjects(), 1); // Check it has the correct name - EXPECT_STREQ(m_actor->GetSimulatedObjectSetup()->GetSimulatedObject(0)->GetName().c_str(), objectName); + EXPECT_STREQ(m_actorAsset->GetActor()->GetSimulatedObjectSetup()->GetSimulatedObject(0)->GetName().c_str(), objectName); } @@ -112,14 +112,16 @@ namespace EMotionFX }); ASSERT_NE(addCapsuleColliderAction, addSelectedColliderMenuActions.end()); - size_t numCapsuleColliders = PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Capsule); + size_t numCapsuleColliders = PhysicsSetupUtils::CountColliders( + m_actorAsset->GetActor(), PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Capsule); (*addCapsuleColliderAction)->trigger(); // Delete the context menu, otherwise there it will still be around during this frame as the Qt event loop has not been run. delete contextMenu; - const size_t numCapsuleCollidersAfterAdd = PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Capsule); + const size_t numCapsuleCollidersAfterAdd = PhysicsSetupUtils::CountColliders( + m_actorAsset->GetActor(), PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Capsule); ASSERT_EQ(numCapsuleCollidersAfterAdd, numCapsuleColliders + 1); @@ -127,7 +129,7 @@ namespace EMotionFX } protected: - AutoRegisteredActor m_actor; + AZ::Data::Asset m_actorAsset; EMotionFX::SimulatedObjectWidget* m_simulatedObjectWidget = nullptr; EMotionFX::SkeletonOutlinerPlugin* m_skeletonOutliner = nullptr; @@ -144,7 +146,8 @@ namespace EMotionFX { RecordProperty("test_case_id", "C13048820"); - m_actor = ActorFactory::CreateAndInit(1, "CanAddSimulatedObjectActor"); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + m_actorAsset = TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 1, "CanAddSimulatedObjectActor"); CreateSimulateObject("New simulated object"); } @@ -153,9 +156,11 @@ namespace EMotionFX { RecordProperty("test_case_id", "C13048818"); - AutoRegisteredActor actor = ActorFactory::CreateAndInit(2, "CanAddSimulatedObjectWithJointsActor"); - - ActorInstance* actorInstance = ActorInstance::Create(actor.get()); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = + TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 2, "CanAddSimulatedObjectWithJointsActor"); + Actor* actor = actorAsset->GetActor(); + ActorInstance* actorInstance = ActorInstance::Create(actor); EMStudio::GetMainWindow()->ApplicationModeChanged("SimulatedObjects"); @@ -216,7 +221,9 @@ namespace EMotionFX { RecordProperty("test_case_id", "C13048820a"); - m_actor = ActorFactory::CreateAndInit(5, "CanAddSimulatedObjectActor"); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + m_actorAsset = TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 5, "CanAddSimulatedObjectActor"); + Actor* actor = m_actorAsset->GetActor(); CreateSimulateObject("sim1"); @@ -261,8 +268,8 @@ namespace EMotionFX inputDialog->SetText("sim2"); inputDialog->accept(); - ASSERT_EQ(m_actor->GetSimulatedObjectSetup()->GetNumSimulatedObjects(), 2); - const auto simulatedObject = m_actor->GetSimulatedObjectSetup()->GetSimulatedObject(1); + ASSERT_EQ(actor->GetSimulatedObjectSetup()->GetNumSimulatedObjects(), 2); + const auto simulatedObject = actor->GetSimulatedObjectSetup()->GetSimulatedObject(1); EXPECT_STREQ(simulatedObject->GetName().c_str(), "sim2"); } @@ -270,7 +277,9 @@ namespace EMotionFX { RecordProperty("test_case_id", "C13048816"); - m_actor = ActorFactory::CreateAndInit(5, "CanAddSimulatedObjectActor"); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + m_actorAsset = TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 5, "CanAddSimulatedObjectActor"); + Actor* actor = m_actorAsset->GetActor(); CreateSimulateObject("sim1"); @@ -301,25 +310,25 @@ namespace EMotionFX QAction* addCapsuleColliderAction; ASSERT_TRUE(UIFixture::GetActionFromContextMenu(addCapsuleColliderAction, addSelectedColliderMenu, "Capsule")); - size_t numCapsuleColliders = PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Capsule); + size_t numCapsuleColliders = PhysicsSetupUtils::CountColliders(actor, PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Capsule); EXPECT_EQ(numCapsuleColliders, 0); addCapsuleColliderAction->trigger(); // Check that a collider has been added. - size_t numCollidersAfterAddCapsule = PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Capsule); + size_t numCollidersAfterAddCapsule = PhysicsSetupUtils::CountColliders(actor, PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Capsule); ASSERT_EQ(numCollidersAfterAddCapsule, numCapsuleColliders + 1) << "Capsule collider not added."; QAction* addSphereColliderAction; ASSERT_TRUE(UIFixture::GetActionFromContextMenu(addSphereColliderAction, addSelectedColliderMenu, "Sphere")); - const size_t numSphereColliders = PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Sphere); + const size_t numSphereColliders = PhysicsSetupUtils::CountColliders(actor, PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Sphere); EXPECT_EQ(numSphereColliders, 0); addSphereColliderAction->trigger(); // Check that a second collider has been added. - const size_t numCollidersAfterAddSphere = PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Sphere); + const size_t numCollidersAfterAddSphere = PhysicsSetupUtils::CountColliders(actor, PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Sphere); ASSERT_EQ(numCollidersAfterAddSphere, numSphereColliders + 1) << "Sphere collider not added."; } @@ -327,7 +336,9 @@ namespace EMotionFX { RecordProperty("test_case_id", "C13048821"); - m_actor = ActorFactory::CreateAndInit(1, "CanRemoveSimulatedObjectActor"); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + m_actorAsset = TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 1, "CanRemoveSimulatedObjectActor"); + Actor* actor = m_actorAsset->GetActor(); CreateSimulateObject("TestObject1"); @@ -350,14 +361,16 @@ namespace EMotionFX ASSERT_TRUE(UIFixture::GetActionFromContextMenu(removeObjectAction, contextMenu, "Remove object")); removeObjectAction->trigger(); - ASSERT_EQ(m_actor->GetSimulatedObjectSetup()->GetNumSimulatedObjects(), 0); + ASSERT_EQ(actor->GetSimulatedObjectSetup()->GetNumSimulatedObjects(), 0); } TEST_F(CanAddSimulatedObjectFixture, CanAddColliderToSimulatedObjectFromInspector) { RecordProperty("test_case_id", "C20385259"); - - m_actor = ActorFactory::CreateAndInit(5, "CanAddSimulatedObjectActor"); + + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + m_actorAsset = TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 5, "CanAddSimulatedObjectActor"); + Actor* actor = m_actorAsset->GetActor(); CreateSimulateObject("sim1"); @@ -380,10 +393,12 @@ namespace EMotionFX // Send the left button click directly to the button QTest::mouseClick(addColliderButton, Qt::LeftButton); - const size_t numCapsuleColliders = PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Capsule); + const size_t numCapsuleColliders = + PhysicsSetupUtils::CountColliders(actor, PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Capsule); EXPECT_EQ(numCapsuleColliders, 0); - const size_t numSphereColliders = PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Sphere); + const size_t numSphereColliders = + PhysicsSetupUtils::CountColliders(actor, PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Sphere); EXPECT_EQ(numSphereColliders, 0); QMenu* contextMenu = addColliderButton->findChild("EMFX.AddColliderButton.ContextMenu"); @@ -392,13 +407,15 @@ namespace EMotionFX QAction* addCapsuleAction; ASSERT_TRUE(UIFixture::GetActionFromContextMenu(addCapsuleAction, contextMenu, "Add capsule")); addCapsuleAction->trigger(); - const size_t numCollidersAfterAddCapsule = PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Capsule); + const size_t numCollidersAfterAddCapsule = + PhysicsSetupUtils::CountColliders(actor, PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Capsule); ASSERT_EQ(numCollidersAfterAddCapsule, numCapsuleColliders + 1) << "Capsule collider not added."; QAction* addSphereAction; ASSERT_TRUE(UIFixture::GetActionFromContextMenu(addSphereAction, contextMenu, "Add sphere")); addSphereAction->trigger(); - const size_t numCollidersAfterAddSphere = PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Sphere); + const size_t numCollidersAfterAddSphere = + PhysicsSetupUtils::CountColliders(actor, PhysicsSetup::SimulatedObjectCollider, false, Physics::ShapeType::Sphere); ASSERT_EQ(numCollidersAfterAddSphere, numSphereColliders + 1) << "Sphere collider not added."; } @@ -406,7 +423,9 @@ namespace EMotionFX { RecordProperty("test_case_id", "C13048818"); - m_actor = ActorFactory::CreateAndInit(7, "CanAddSimulatedObjectActor"); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + m_actorAsset = TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 7, "CanAddSimulatedObjectActor"); + Actor* actor = m_actorAsset->GetActor(); CreateSimulateObject("ANY"); @@ -442,7 +461,7 @@ namespace EMotionFX messageBoxPopupHandler.WaitForPopupPressDialogButton(QDialogButtonBox::No); newSimulatedObjectAction->trigger(); - const EMotionFX::SimulatedObject* simulatedObject = m_actor->GetSimulatedObjectSetup()->GetSimulatedObject(0); + const EMotionFX::SimulatedObject* simulatedObject = actor->GetSimulatedObjectSetup()->GetSimulatedObject(0); EXPECT_EQ(simulatedObject->GetNumSimulatedRootJoints(), 1); EXPECT_EQ(simulatedObject->GetNumSimulatedJoints(), 3); } @@ -450,7 +469,9 @@ namespace EMotionFX { RecordProperty("test_case_id", "C13048817"); - m_actor = ActorFactory::CreateAndInit(5, "CanAddSimulatedObjectActor"); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + m_actorAsset = TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 5, "CanAddSimulatedObjectActor"); + Actor* actor = m_actorAsset->GetActor(); EMStudio::GetMainWindow()->ApplicationModeChanged("SimulatedObjects"); @@ -470,7 +491,7 @@ namespace EMotionFX AddCapsuleColliderToJointIndex(3); AddCapsuleColliderToJointIndex(4); - const size_t numCollidersAfterAdd = PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::SimulatedObjectCollider); + const size_t numCollidersAfterAdd = PhysicsSetupUtils::CountColliders(actor, PhysicsSetup::SimulatedObjectCollider); EXPECT_EQ(numCollidersAfterAdd, 2); m_indexList.clear(); @@ -498,7 +519,7 @@ namespace EMotionFX removeAction->trigger(); // Check that one of the colliders is now gone. - const size_t numCollidersAfterFirstRemove = PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::SimulatedObjectCollider); + const size_t numCollidersAfterFirstRemove = PhysicsSetupUtils::CountColliders(actor, PhysicsSetup::SimulatedObjectCollider); ASSERT_EQ(numCollidersAfterFirstRemove, numCollidersAfterAdd - 1) << "RemoveCollider action in Simulated Object Inspector failed."; // Now do the same thing using the Simulated Object Inspector context menu. @@ -536,7 +557,7 @@ namespace EMotionFX delAction->trigger(); // Check that we have the number of colliders we started we expect. - const size_t numCollidersAfterSecondRemove = PhysicsSetupUtils::CountColliders(m_actor.get(), PhysicsSetup::SimulatedObjectCollider); + const size_t numCollidersAfterSecondRemove = PhysicsSetupUtils::CountColliders(actor, PhysicsSetup::SimulatedObjectCollider); ASSERT_EQ(numCollidersAfterSecondRemove, numCollidersAfterAdd - 2); } diff --git a/Gems/EMotionFX/Code/Tests/UI/CanAddToSimulatedObject.cpp b/Gems/EMotionFX/Code/Tests/UI/CanAddToSimulatedObject.cpp index e27d558664..a10ba352d2 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanAddToSimulatedObject.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanAddToSimulatedObject.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -52,9 +53,11 @@ namespace EMotionFX { RecordProperty("test_case_id", "C14603914"); - AutoRegisteredActor actor = ActorFactory::CreateAndInit(7, "CanAddToSimulatedObjectActor"); - - ActorInstance* actorInstance = ActorInstance::Create(actor.get()); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = + TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 7, "CanAddToSimulatedObjectActor"); + Actor* actor = actorAsset->GetActor(); + ActorInstance* actorInstance = ActorInstance::Create(actor); // Change the Editor mode to Simulated Objects EMStudio::GetMainWindow()->ApplicationModeChanged("SimulatedObjects"); @@ -165,9 +168,11 @@ namespace EMotionFX }); RecordProperty("test_case_id", "C13291807"); - AutoRegisteredActor actor = ActorFactory::CreateAndInit(7, "CanAddToSimulatedObjectActor"); - - ActorInstance* actorInstance = ActorInstance::Create(actor.get()); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = + TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 7, "CanAddToSimulatedObjectActor"); + Actor* actor = actorAsset->GetActor(); + ActorInstance* actorInstance = ActorInstance::Create(actor); // Change the Editor mode to Physics EMStudio::GetMainWindow()->ApplicationModeChanged("Physics"); diff --git a/Gems/EMotionFX/Code/Tests/UI/CanChangeParametersInSimulatedObject.cpp b/Gems/EMotionFX/Code/Tests/UI/CanChangeParametersInSimulatedObject.cpp index 510bfb2d83..108a637412 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanChangeParametersInSimulatedObject.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanChangeParametersInSimulatedObject.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -37,9 +38,10 @@ namespace EMotionFX { RecordProperty("test_case_id", "C14519563"); - AutoRegisteredActor actor = ActorFactory::CreateAndInit(7, "CanAddToSimulatedObjectActor"); - - ActorInstance* actorInstance = ActorInstance::Create(actor.get()); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = + TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 7, "CanAddToSimulatedObjectActor"); + ActorInstance* actorInstance = ActorInstance::Create(actorAsset->GetActor()); // Change the Editor mode to Simulated Objects EMStudio::GetMainWindow()->ApplicationModeChanged("SimulatedObjects"); diff --git a/Gems/EMotionFX/Code/Tests/UI/CanUseFileMenu.cpp b/Gems/EMotionFX/Code/Tests/UI/CanUseFileMenu.cpp index 73a0f1c865..2af3329203 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanUseFileMenu.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanUseFileMenu.cpp @@ -24,10 +24,12 @@ #include #include +#include #include #include #include #include +#include #include #include #include @@ -141,8 +143,10 @@ namespace EMotionFX { if (EMotionFX::GetActorManager().GetNumActorInstances() == 0) { - AutoRegisteredActor actor = ActorFactory::CreateAndInit(2, "CanAddSimulatedObjectWithJointsActor"); - ActorInstance::Create(actor.get()); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = + TestActorAssets::CreateActorAssetAndRegister(actorAssetId, 2, "CanAddSimulatedObjectWithJointsActor"); + ActorInstance::Create(actorAsset->GetActor()); EXPECT_EQ(EMotionFX::GetActorManager().GetNumActorInstances(), 1) << "Failed to create actor set for reset test."; } @@ -152,15 +156,16 @@ namespace EMotionFX { if (EMotionFX::GetActorManager().GetNumActorInstances() == 0) { - AutoRegisteredActor actor = ActorFactory::CreateAndInit(2, "CanAddSimulatedObjectWithJointsActor"); - ActorInstance::Create(actor.get()); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = TestActorAssets::CreateActorAssetAndRegister( + actorAssetId, 2, "CanAddSimulatedObjectWithJointsActor"); + ActorInstance::Create(actorAsset->GetActor()); EXPECT_EQ(EMotionFX::GetActorManager().GetNumActorInstances(), 1) << "Failed to create actor set for reset test."; - - actor->SetFileName(filename); + actorAsset->GetActor()->SetFileName(filename); AZStd::string stringFilename = filename; - ExporterLib::SaveActor(stringFilename, actor.get(), MCore::Endian::ENDIAN_LITTLE); + ExporterLib::SaveActor(stringFilename, actorAsset->GetActor(), MCore::Endian::ENDIAN_LITTLE); } } @@ -239,7 +244,6 @@ namespace EMotionFX // Load the actor we just saved, with replaceScene set to true to represent a load. LoadActor(actorFilename.toUtf8().data(), true); - ASSERT_EQ(EMotionFX::GetActorManager().GetNumActorInstances(), 1) << "Failed to load Actor."; // Do it again to verify that number of actors stays the same when replaceScene is true. @@ -696,7 +700,10 @@ namespace EMotionFX TestResetMenuItem(fileMenu); - TestActorMenus(fileMenu); + // Temporarily disable loading actor test. + // This is because the importer command now load actor asset instead of reading from disk. We do not want to add dependency to the asset processor + // in this test. + // TestActorMenus(fileMenu); TestSaveAllMenuItem(fileMenu); } diff --git a/Gems/EMotionFX/Code/Tests/UI/CanUseLayoutMenu.cpp b/Gems/EMotionFX/Code/Tests/UI/CanUseLayoutMenu.cpp index 6fbaf3a028..e615d3c9e0 100644 --- a/Gems/EMotionFX/Code/Tests/UI/CanUseLayoutMenu.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/CanUseLayoutMenu.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include diff --git a/Gems/EMotionFX/Code/Tests/UI/ClothColliderTests.cpp b/Gems/EMotionFX/Code/Tests/UI/ClothColliderTests.cpp index 6428a11e6d..d87c35a4fa 100644 --- a/Gems/EMotionFX/Code/Tests/UI/ClothColliderTests.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/ClothColliderTests.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include namespace EMotionFX @@ -102,7 +103,9 @@ namespace EMotionFX const int lastIndex = 6; RecordProperty("test_case_id", "C18970351"); - AutoRegisteredActor actor = ActorFactory::CreateAndInit(numJoints, "RagdollEditTestsActor"); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = + TestActorAssets::CreateActorAssetAndRegister(actorAssetId, numJoints, "RagdollEditTestsActor"); CreateSkeletonAndModelIndices(); EXPECT_EQ(m_indexList.size(), numJoints); diff --git a/Gems/EMotionFX/Code/Tests/UI/LODSkinnedMeshTests.cpp b/Gems/EMotionFX/Code/Tests/UI/LODSkinnedMeshTests.cpp index 6e5e14e9fc..def8bdab58 100644 --- a/Gems/EMotionFX/Code/Tests/UI/LODSkinnedMeshTests.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/LODSkinnedMeshTests.cpp @@ -80,11 +80,14 @@ namespace EMotionFX DataMembers m_data; }; - AZStd::unique_ptr CreateLODActor(int numLODs) + AZ::Data::Asset CreateLODActor(int numLODs) { - AZStd::unique_ptr actor = ActorFactory::CreateAndInit("LODSkinnedMeshTestsActor"); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = + TestActorAssets::CreateActorAssetAndRegister(actorAssetId, "LODSkinnedMeshTestsActor"); // Modify the actor to have numLODs LOD levels. + Actor* actor = actorAsset->GetActor(); Mesh* lodMesh = actor->GetMesh(0, 0); StandardMaterial* dummyMat = StandardMaterial::Create("Dummy Material"); actor->AddMaterial(0, dummyMat); // owns the material @@ -97,7 +100,7 @@ namespace EMotionFX actor->AddMaterial(i, dummyMat->Clone()); } - return actor; + return AZStd::move(actorAsset); } class LODPropertyRowWidget @@ -112,9 +115,8 @@ namespace EMotionFX const int numLODs = GetParam(); RecordProperty("test_case_id", "C29202698"); - AutoRegisteredActor actor = CreateLODActor(numLODs); - - ActorInstance* actorInstance = ActorInstance::Create(actor.get()); + AZ::Data::Asset actorAsset = CreateLODActor(numLODs); + ActorInstance* actorInstance = ActorInstance::Create(actorAsset->GetActor()); // Change the Editor mode to Character EMStudio::GetMainWindow()->ApplicationModeChanged("Character"); @@ -166,8 +168,7 @@ namespace EMotionFX gameEntity->SetId(entityId); AZ::Data::AssetId actorAssetId("{85D3EF54-7400-43F8-8A40-F6BCBF534E54}"); - AZStd::unique_ptr actor = CreateLODActor(numLODs); - AZ::Data::Asset actorAsset = TestActorAssets::GetAssetFromActor(actorAssetId, AZStd::move(actor)); + AZ::Data::Asset actorAsset = CreateLODActor(numLODs); gameEntity->CreateComponent(); Integration::ActorComponent::Configuration actorConf; diff --git a/Gems/EMotionFX/Code/Tests/UI/RagdollEditTests.cpp b/Gems/EMotionFX/Code/Tests/UI/RagdollEditTests.cpp index 1c39cde5b6..d097e67d15 100644 --- a/Gems/EMotionFX/Code/Tests/UI/RagdollEditTests.cpp +++ b/Gems/EMotionFX/Code/Tests/UI/RagdollEditTests.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -110,7 +111,9 @@ namespace EMotionFX const int numJoints = 6; RecordProperty("test_case_id", "C3122249"); - AutoRegisteredActor actor = ActorFactory::CreateAndInit(numJoints, "RagdollEditTestsActor"); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = + TestActorAssets::CreateActorAssetAndRegister(actorAssetId, numJoints, "RagdollEditTestsActor"); CreateSkeletonAndModelIndices(); @@ -138,7 +141,9 @@ namespace EMotionFX const int numJoints = 8; RecordProperty("test_case_id", "C3122248"); - AutoRegisteredActor actor = ActorFactory::CreateAndInit(numJoints, "RagdollEditTestsActor"); + AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); + AZ::Data::Asset actorAsset = + TestActorAssets::CreateActorAssetAndRegister(actorAssetId, numJoints, "RagdollEditTestsActor"); CreateSkeletonAndModelIndices(); EXPECT_EQ(m_indexList.size(), numJoints); From 975589c0c4cb7bd1c3e544b72d26c8f502daa76d Mon Sep 17 00:00:00 2001 From: rhhong Date: Tue, 10 Aug 2021 22:28:42 -0700 Subject: [PATCH 047/169] Add skeleton class for atom render plugin Signed-off-by: rhhong --- .../Source/AtomRender/AtomRenderPlugin.cpp | 27 +++++++ .../Source/AtomRender/AtomRenderPlugin.h | 72 +++++++++++++++++++ .../RenderPlugins/renderplugins_files.cmake | 2 + .../Integration/System/SystemComponent.cpp | 2 + 4 files changed, 103 insertions(+) create mode 100644 Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.cpp create mode 100644 Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.h diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.cpp new file mode 100644 index 0000000000..6b64afd50b --- /dev/null +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.cpp @@ -0,0 +1,27 @@ +/* + * 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 EMStudio +{ + AtomRenderPlugin::AtomRenderPlugin() + { + + } + + AtomRenderPlugin::~AtomRenderPlugin() + { + + } + + bool AtomRenderPlugin::Init() + { + return true; + } +} diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.h new file mode 100644 index 0000000000..59aabce3c3 --- /dev/null +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.h @@ -0,0 +1,72 @@ +/* + * 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 EMStudio +{ + class AtomRenderPlugin + : public DockWidgetPlugin + { + Q_OBJECT // AUTOMOC + + public: + enum + { + CLASS_ID = 0x32b0c04d + }; + AtomRenderPlugin(); + ~AtomRenderPlugin(); + + // Plugin information + const char* GetCompileDate() const override + { + return MCORE_DATE; + } + const char* GetName() const override + { + return "Atom Render Window"; + } + uint32 GetClassID() const override + { + return static_cast(AtomRenderPlugin::CLASS_ID); + } + const char* GetCreatorName() const override + { + return "O3DE"; + } + float GetVersion() const override + { + return 1.0f; + } + bool GetIsClosable() const override + { + return true; + } + bool GetIsFloatable() const override + { + return true; + } + bool GetIsVertical() const override + { + return false; + } + + bool Init(); + EMStudioPlugin* Clone() + { + return new AtomRenderPlugin(); + } + EMStudioPlugin::EPluginType GetPluginType() const override + { + return EMStudioPlugin::PLUGINTYPE_RENDERING; + } + }; +} diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/renderplugins_files.cmake b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/renderplugins_files.cmake index 3bce07c3c4..339052823d 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/renderplugins_files.cmake +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/renderplugins_files.cmake @@ -11,4 +11,6 @@ set(FILES Source/OpenGLRender/GLWidget.cpp Source/OpenGLRender/OpenGLRenderPlugin.h Source/OpenGLRender/OpenGLRenderPlugin.cpp + Source/AtomRender/AtomRenderPlugin.h + Source/AtomRender/AtomRenderPlugin.cpp ) diff --git a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp index cf2f9beaa4..c3823f15ed 100644 --- a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp @@ -88,6 +88,7 @@ # include # include # include +# include # include # include # include @@ -794,6 +795,7 @@ namespace EMotionFX pluginManager->RegisterPlugin(new EMStudio::NodeGroupsPlugin()); pluginManager->RegisterPlugin(new EMStudio::AnimGraphPlugin()); pluginManager->RegisterPlugin(new EMStudio::OpenGLRenderPlugin()); + pluginManager->RegisterPlugin(new EMStudio::AtomRenderPlugin()); pluginManager->RegisterPlugin(new EMotionFX::HitDetectionJointInspectorPlugin()); pluginManager->RegisterPlugin(new EMotionFX::SkeletonOutlinerPlugin()); pluginManager->RegisterPlugin(new EMotionFX::RagdollNodeInspectorPlugin()); From a96b091d3fffead19d545d868e9cbf368cd1c8e5 Mon Sep 17 00:00:00 2001 From: rhhong Date: Wed, 11 Aug 2021 22:49:59 -0700 Subject: [PATCH 048/169] Add skeleton class for animviewportwidget. Signed-off-by: rhhong --- Gems/EMotionFX/Code/CMakeLists.txt | 2 ++ .../Source/AtomRender/AnimViewportWidget.cpp | 18 +++++++++++++++++ .../Source/AtomRender/AnimViewportWidget.h | 20 +++++++++++++++++++ .../Source/AtomRender/AtomRenderPlugin.cpp | 13 +++++++++++- .../Source/AtomRender/AtomRenderPlugin.h | 10 +++++++++- .../RenderPlugins/renderplugins_files.cmake | 2 ++ 6 files changed, 63 insertions(+), 2 deletions(-) create mode 100644 Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AnimViewportWidget.cpp create mode 100644 Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AnimViewportWidget.h diff --git a/Gems/EMotionFX/Code/CMakeLists.txt b/Gems/EMotionFX/Code/CMakeLists.txt index dace02b2ae..67d0ba6d85 100644 --- a/Gems/EMotionFX/Code/CMakeLists.txt +++ b/Gems/EMotionFX/Code/CMakeLists.txt @@ -109,6 +109,8 @@ if (PAL_TRAIT_BUILD_HOST_TOOLS) AZ::AzToolsFramework Legacy::Editor.Headers 3rdParty::OpenGLInterface + Gem::AtomToolsFramework.Static + Gem::AtomToolsFramework.Editor COMPILE_DEFINITIONS PUBLIC EMFX_EMSTUDIOLYEMBEDDED diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AnimViewportWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AnimViewportWidget.cpp new file mode 100644 index 0000000000..df8edeb324 --- /dev/null +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AnimViewportWidget.cpp @@ -0,0 +1,18 @@ +/* + * 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 EMStudio +{ + AnimViewportWidget::AnimViewportWidget(QWidget* parent) + : AtomToolsFramework::RenderViewportWidget(parent) + { + + } +} diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AnimViewportWidget.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AnimViewportWidget.h new file mode 100644 index 0000000000..59ea5c6680 --- /dev/null +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AnimViewportWidget.h @@ -0,0 +1,20 @@ +/* + * 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 EMStudio +{ + class AnimViewportWidget + : public AtomToolsFramework::RenderViewportWidget + { + public: + AnimViewportWidget(QWidget* parent = nullptr); + }; +} diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.cpp index 6b64afd50b..6a95b83433 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.cpp @@ -7,12 +7,13 @@ */ #include +#include namespace EMStudio { AtomRenderPlugin::AtomRenderPlugin() + : DockWidgetPlugin() { - } AtomRenderPlugin::~AtomRenderPlugin() @@ -22,6 +23,16 @@ namespace EMStudio bool AtomRenderPlugin::Init() { + m_innerWidget = new QWidget(); + m_dock->setWidget(m_innerWidget); + + QVBoxLayout* verticalLayout = new QVBoxLayout(m_innerWidget); + verticalLayout->setSizeConstraint(QLayout::SetNoConstraint); + verticalLayout->setSpacing(1); + verticalLayout->setMargin(0); + + m_animViewportWidget = new AnimViewportWidget(m_innerWidget); + return true; } } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.h index 59aabce3c3..d7605e276a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.h @@ -8,7 +8,11 @@ #pragma once +#if !defined(Q_MOC_RUN) #include +#include +#include +#endif namespace EMStudio { @@ -59,7 +63,7 @@ namespace EMStudio return false; } - bool Init(); + bool Init() override; EMStudioPlugin* Clone() { return new AtomRenderPlugin(); @@ -68,5 +72,9 @@ namespace EMStudio { return EMStudioPlugin::PLUGINTYPE_RENDERING; } + + private: + QWidget* m_innerWidget; + AnimViewportWidget* m_animViewportWidget; }; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/renderplugins_files.cmake b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/renderplugins_files.cmake index 339052823d..c184f708f2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/renderplugins_files.cmake +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/renderplugins_files.cmake @@ -13,4 +13,6 @@ set(FILES Source/OpenGLRender/OpenGLRenderPlugin.cpp Source/AtomRender/AtomRenderPlugin.h Source/AtomRender/AtomRenderPlugin.cpp + Source/AtomRender/AnimViewportWidget.h + Source/AtomRender/AnimViewportWidget.cpp ) From f2b449c4b97091525848910ca6df3195ed594c3a Mon Sep 17 00:00:00 2001 From: rhhong Date: Mon, 30 Aug 2021 17:57:45 -0700 Subject: [PATCH 049/169] Registering an empty atom render plugin in the emfxatom gem. Signed-off-by: rhhong --- .../EMotionFXAtom/Code/CMakeLists.txt | 7 ++ .../EMotionFXAtom/Code/Source/ActorModule.cpp | 11 ++- .../Source/Editor/EditorSystemComponent.cpp | 42 +++++++++++ .../Source/Editor/EditorSystemComponent.h | 35 ++++++++++ .../Tools/EMStudio}/AnimViewportWidget.cpp | 2 +- .../Code/Tools/EMStudio}/AnimViewportWidget.h | 0 .../Code/Tools/EMStudio}/AtomRenderPlugin.cpp | 2 +- .../Code/Tools/EMStudio}/AtomRenderPlugin.h | 4 +- .../Code/emotionfx_atom_editor_files.cmake | 6 ++ .../EMStudioSDK/Source/EMStudioManager.cpp | 44 +++--------- .../EMStudioSDK/Source/EMStudioManager.h | 70 +++++++++++-------- .../EMStudioSDK/Source/MainWindow.h | 6 +- .../RenderPlugins/renderplugins_files.cmake | 4 -- .../Code/Include/Integration/AnimationBus.h | 3 + .../Integration/System/SystemComponent.cpp | 10 +-- .../Integration/System/SystemComponent.h | 5 ++ 16 files changed, 173 insertions(+), 78 deletions(-) create mode 100644 Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.cpp create mode 100644 Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.h rename Gems/{EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender => AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio}/AnimViewportWidget.cpp (81%) rename Gems/{EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender => AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio}/AnimViewportWidget.h (100%) rename Gems/{EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender => AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio}/AtomRenderPlugin.cpp (90%) rename Gems/{EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender => AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio}/AtomRenderPlugin.h (92%) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/CMakeLists.txt b/Gems/AtomLyIntegration/EMotionFXAtom/Code/CMakeLists.txt index 5a08bab4fa..dc22c8ee93 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/CMakeLists.txt +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/CMakeLists.txt @@ -54,11 +54,18 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) INCLUDE_DIRECTORIES PRIVATE Source + Tools BUILD_DEPENDENCIES PRIVATE AZ::AzCore Gem::EMotionFX_Atom.Static + Gem::EMotionFX.Editor.Static + Gem::AtomToolsFramework.Static + Gem::AtomToolsFramework.Editor RUNTIME_DEPENDENCIES Gem::EMotionFX.Editor + COMPILE_DEFINITIONS + PUBLIC + EMOTIONFXATOM_EDITOR ) endif() diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorModule.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorModule.cpp index 49c2e52c1a..93481c1da6 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorModule.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/ActorModule.cpp @@ -11,6 +11,9 @@ #include #include #include +#ifdef EMOTIONFXATOM_EDITOR +#include +#endif namespace AZ { @@ -28,7 +31,10 @@ namespace AZ : Module() { m_descriptors.insert(m_descriptors.end(), { - ActorSystemComponent::CreateDescriptor() + ActorSystemComponent::CreateDescriptor(), +#ifdef EMOTIONFXATOM_EDITOR + EMotionFXAtom::EditorSystemComponent::CreateDescriptor(), +#endif }); } @@ -39,6 +45,9 @@ namespace AZ { return ComponentTypeList{ azrtti_typeid(), +#ifdef EMOTIONFXATOM_EDITOR + azrtti_typeid(), +#endif }; } }; diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.cpp new file mode 100644 index 0000000000..86a9c36c56 --- /dev/null +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.cpp @@ -0,0 +1,42 @@ +/* + * 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 EMotionFXAtom + { + void EditorSystemComponent::Reflect(ReflectContext* context) + { + if (SerializeContext* serialize = azrtti_cast(context)) + { + serialize->Class()->Version(0); + } + } + + void EditorSystemComponent::Activate() + { + EMotionFX::Integration::SystemNotificationBus::Handler::BusConnect(); + } + + void EditorSystemComponent::Deactivate() + { + EMotionFX::Integration::SystemNotificationBus::Handler::BusDisconnect(); + } + + void EditorSystemComponent::OnRegisterPlugin() + { + EMStudio::PluginManager* pluginManager = EMStudio::EMStudioManager::GetInstance()->GetPluginManager(); + pluginManager->RegisterPlugin(new EMStudio::AtomRenderPlugin()); + } + } +} // namespace AZ diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.h new file mode 100644 index 0000000000..6121912481 --- /dev/null +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.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 EMotionFXAtom + { + class EditorSystemComponent + : public Component + , private EMotionFX::Integration::SystemNotificationBus::Handler + { + public: + AZ_COMPONENT(EditorSystemComponent, "{1FAEC046-255D-4664-8F12-D16503C34431}"); + + static void Reflect(ReflectContext* context); + + protected: + // AZ::Component + void Activate() override; + void Deactivate() override; + + // SystemNotificationBus::OnRegisterPlugin + void OnRegisterPlugin() override; + }; + } // namespace EMotionFXAtom +} // namespace AZ diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AnimViewportWidget.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp similarity index 81% rename from Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AnimViewportWidget.cpp rename to Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp index df8edeb324..2b961e6e7b 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AnimViewportWidget.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp @@ -6,7 +6,7 @@ * */ -#include +#include namespace EMStudio { diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AnimViewportWidget.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h similarity index 100% rename from Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AnimViewportWidget.h rename to Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp similarity index 90% rename from Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.cpp rename to Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp index 6a95b83433..f7da1d19a9 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp @@ -6,7 +6,7 @@ * */ -#include +#include #include namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h similarity index 92% rename from Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.h rename to Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h index d7605e276a..910b5283cd 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/Source/AtomRender/AtomRenderPlugin.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h @@ -9,8 +9,8 @@ #pragma once #if !defined(Q_MOC_RUN) -#include -#include +#include +#include #include #endif diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/emotionfx_atom_editor_files.cmake b/Gems/AtomLyIntegration/EMotionFXAtom/Code/emotionfx_atom_editor_files.cmake index 6401beb232..37e69739d0 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/emotionfx_atom_editor_files.cmake +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/emotionfx_atom_editor_files.cmake @@ -8,4 +8,10 @@ set(FILES Source/ActorModule.cpp + Source/Editor/EditorSystemComponent.h + Source/Editor/EditorSystemComponent.cpp + Tools/EMStudio/AtomRenderPlugin.h + Tools/EMStudio/AtomRenderPlugin.cpp + Tools/EMStudio/AnimViewportWidget.h + Tools/EMStudio/AnimViewportWidget.cpp ) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp index 2321d7c71b..432a351edf 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp @@ -46,15 +46,10 @@ AZ_POP_DISABLE_WARNING namespace EMStudio { - //-------------------------------------------------------------------------- - // globals - //-------------------------------------------------------------------------- - EMStudioManager* gEMStudioMgr = nullptr; - - //-------------------------------------------------------------------------- // class EMStudioManager //-------------------------------------------------------------------------- + AZ_CLASS_ALLOCATOR_IMPL(EMStudioManager, AZ::SystemAllocator, 0) // constructor EMStudioManager::EMStudioManager(QApplication* app, [[maybe_unused]] int& argc, [[maybe_unused]] char* argv[]) @@ -105,6 +100,8 @@ namespace EMStudio // log some information LogInfo(); + + AZ::Interface::Register(this); } @@ -130,6 +127,8 @@ namespace EMStudio delete m_commandManager; AZ::AllocatorInstance::Destroy(); + + AZ::Interface::Unregister(this); } MainWindow* EMStudioManager::GetMainWindow() @@ -422,6 +421,12 @@ namespace EMStudio } + EMStudioManager* EMStudioManager::GetInstance() + { + return AZ::Interface().Get(); + } + + // function to add a gizmo to the manager MCommon::TransformationManipulator* EMStudioManager::AddTransformationManipulator(MCommon::TransformationManipulator* manipulator) { @@ -493,31 +498,4 @@ namespace EMStudio path.addText(textPos, font, text); painter.drawPath(path); } - - //-------------------------------------------------------------------------- - // class Initializer - //-------------------------------------------------------------------------- - // initialize EMotion Studio - bool Initializer::Init(QApplication* app, int& argc, char* argv[]) - { - // do nothing if we already have initialized - if (gEMStudioMgr) - { - return true; - } - - // create the new EMStudio object - gEMStudioMgr = new EMStudioManager(app, argc, argv); - - // return success - return true; - } - - - // the shutdown function - void Initializer::Shutdown() - { - delete gEMStudioMgr; - gEMStudioMgr = nullptr; - } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h index 909f0231f3..8828253ea2 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h @@ -53,9 +53,10 @@ namespace EMStudio class EMSTUDIO_API EMStudioManager : private EMotionFX::SkeletonOutlinerNotificationBus::Handler { - MCORE_MEMORYOBJECTCATEGORY(EMStudioManager, MCore::MCORE_DEFAULT_ALIGNMENT, MEMCATEGORY_EMSTUDIOSDK) - public: + AZ_RTTI(EMStudio::EMStudioManager, "{D45E95CF-0C7B-44F1-A9D4-99A1E12A5AB5}") + AZ_CLASS_ALLOCATOR_DECL + EMStudioManager(QApplication* app, int& argc, char* argv[]); ~EMStudioManager(); @@ -72,6 +73,9 @@ namespace EMStudio AZStd::string GetRecoverFolder() const; AZStd::string GetAutosavesFolder() const; + // Singleton pattern + static EMStudioManager* GetInstance(); + // text rendering helper function static void RenderText(QPainter& painter, const QString& text, const QColor& textColor, const QFont& font, const QFontMetrics& fontMetrics, Qt::Alignment textAlignment, const QRect& rect); @@ -153,31 +157,41 @@ namespace EMStudio EventProcessingCallback* m_eventProcessingCallback; }; - - /** - * - * - * - */ - class EMSTUDIO_API Initializer - { - public: - static bool MCORE_CDECL Init(QApplication* app, int& argc, char* argv[]); - static void MCORE_CDECL Shutdown(); - }; - - - // the global manager - extern EMSTUDIO_API EMStudioManager* gEMStudioMgr; - // shortcuts - MCORE_INLINE QApplication* GetApp() { return gEMStudioMgr->GetApp(); } - MCORE_INLINE EMStudioManager* GetManager() { return gEMStudioMgr; } - MCORE_INLINE bool HasMainWindow() { return gEMStudioMgr->HasMainWindow(); } - MCORE_INLINE MainWindow* GetMainWindow() { return gEMStudioMgr->GetMainWindow(); } - MCORE_INLINE PluginManager* GetPluginManager() { return gEMStudioMgr->GetPluginManager(); } - MCORE_INLINE LayoutManager* GetLayoutManager() { return gEMStudioMgr->GetLayoutManager(); } - MCORE_INLINE NotificationWindowManager* GetNotificationWindowManager() { return gEMStudioMgr->GetNotificationWindowManager(); } - MCORE_INLINE MotionEventPresetManager* GetEventPresetManager() { return gEMStudioMgr->GetEventPresetManger(); } - MCORE_INLINE CommandSystem::CommandManager* GetCommandManager() { return gEMStudioMgr->GetCommandManager(); } + MCORE_INLINE QApplication* GetApp() + { + return EMStudioManager::GetInstance()->GetApp(); + } + MCORE_INLINE EMStudioManager* GetManager() + { + return EMStudioManager::GetInstance(); + } + MCORE_INLINE bool HasMainWindow() + { + return EMStudioManager::GetInstance()->HasMainWindow(); + } + MCORE_INLINE MainWindow* GetMainWindow() + { + return EMStudioManager::GetInstance()->GetMainWindow(); + } + MCORE_INLINE PluginManager* GetPluginManager() + { + return EMStudioManager::GetInstance()->GetPluginManager(); + } + MCORE_INLINE LayoutManager* GetLayoutManager() + { + return EMStudioManager::GetInstance()->GetLayoutManager(); + } + MCORE_INLINE NotificationWindowManager* GetNotificationWindowManager() + { + return EMStudioManager::GetInstance()->GetNotificationWindowManager(); + } + MCORE_INLINE MotionEventPresetManager* GetEventPresetManager() + { + return EMStudioManager::GetInstance()->GetEventPresetManger(); + } + MCORE_INLINE CommandSystem::CommandManager* GetCommandManager() + { + return EMStudioManager::GetInstance()->GetCommandManager(); + } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h index 585101f7d2..1aa8676352 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/MainWindow.h @@ -10,9 +10,9 @@ #if !defined(Q_MOC_RUN) #include -#include -#include -#include +#include +#include +#include #include #include #include diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/renderplugins_files.cmake b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/renderplugins_files.cmake index c184f708f2..3bce07c3c4 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/renderplugins_files.cmake +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/RenderPlugins/renderplugins_files.cmake @@ -11,8 +11,4 @@ set(FILES Source/OpenGLRender/GLWidget.cpp Source/OpenGLRender/OpenGLRenderPlugin.h Source/OpenGLRender/OpenGLRenderPlugin.cpp - Source/AtomRender/AtomRenderPlugin.h - Source/AtomRender/AtomRenderPlugin.cpp - Source/AtomRender/AnimViewportWidget.h - Source/AtomRender/AnimViewportWidget.cpp ) diff --git a/Gems/EMotionFX/Code/Include/Integration/AnimationBus.h b/Gems/EMotionFX/Code/Include/Integration/AnimationBus.h index 1b9eb55216..474ac1b6d5 100644 --- a/Gems/EMotionFX/Code/Include/Integration/AnimationBus.h +++ b/Gems/EMotionFX/Code/Include/Integration/AnimationBus.h @@ -46,6 +46,9 @@ namespace EMotionFX public: static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + + // Use this bus to register custom EMotionFX plugin. + virtual void OnRegisterPlugin() = 0; }; using SystemNotificationBus = AZ::EBus; diff --git a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp index c3823f15ed..38af4232ba 100644 --- a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp +++ b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.cpp @@ -46,6 +46,7 @@ #include #include +#include #include #include #include @@ -70,7 +71,6 @@ # include # include # include -# include # include # include // EMStudio plugins @@ -88,7 +88,6 @@ # include # include # include -# include # include # include # include @@ -530,7 +529,7 @@ namespace EMotionFX if (EMStudio::GetManager()) { - EMStudio::Initializer::Shutdown(); + m_emstudioManager.reset(); MysticQt::Initializer::Shutdown(); } @@ -795,12 +794,13 @@ namespace EMotionFX pluginManager->RegisterPlugin(new EMStudio::NodeGroupsPlugin()); pluginManager->RegisterPlugin(new EMStudio::AnimGraphPlugin()); pluginManager->RegisterPlugin(new EMStudio::OpenGLRenderPlugin()); - pluginManager->RegisterPlugin(new EMStudio::AtomRenderPlugin()); pluginManager->RegisterPlugin(new EMotionFX::HitDetectionJointInspectorPlugin()); pluginManager->RegisterPlugin(new EMotionFX::SkeletonOutlinerPlugin()); pluginManager->RegisterPlugin(new EMotionFX::RagdollNodeInspectorPlugin()); pluginManager->RegisterPlugin(new EMotionFX::ClothJointInspectorPlugin()); pluginManager->RegisterPlugin(new EMotionFX::SimulatedObjectWidget()); + + SystemNotificationBus::Broadcast(&SystemNotificationBus::Events::OnRegisterPlugin); } ////////////////////////////////////////////////////////////////////////// @@ -816,7 +816,7 @@ namespace EMotionFX char** argv = nullptr; MysticQt::Initializer::Init("", editorAssetsPath.c_str()); - EMStudio::Initializer::Init(qApp, argc, argv); + m_emstudioManager = AZStd::make_unique(qApp, argc, argv); InitializeEMStudioPlugins(); diff --git a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.h b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.h index 5e30820ca3..3ef626c947 100644 --- a/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.h +++ b/Gems/EMotionFX/Code/Source/Integration/System/SystemComponent.h @@ -24,6 +24,7 @@ # include # include # include +# include #endif // EMOTIONFXANIMATION_EDITOR namespace AZ @@ -126,6 +127,10 @@ namespace EMotionFX AZStd::vector > m_assetHandlers; AZStd::unique_ptr m_eventHandler; AZStd::unique_ptr m_renderBackendManager; + +#if defined(EMOTIONFXANIMATION_EDITOR) + AZStd::unique_ptr m_emstudioManager; +#endif // EMOTIONFXANIMATION_EDITOR }; } } From af9448d4ea10c248ac73b0724d402ab18ee1bdbb Mon Sep 17 00:00:00 2001 From: rhhong Date: Mon, 30 Aug 2021 22:22:19 -0700 Subject: [PATCH 050/169] delete auto moc header Signed-off-by: rhhong --- .../EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h index 910b5283cd..b3e47df91c 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h @@ -19,8 +19,6 @@ namespace EMStudio class AtomRenderPlugin : public DockWidgetPlugin { - Q_OBJECT // AUTOMOC - public: enum { From c4a3162c8543eedc7c8ea20adca737e104269dbc Mon Sep 17 00:00:00 2001 From: rhhong Date: Tue, 31 Aug 2021 12:23:05 -0700 Subject: [PATCH 051/169] CR feedback - code cleaning Signed-off-by: rhhong --- .../Source/Editor/EditorSystemComponent.cpp | 45 ++++++++--------- .../Source/Editor/EditorSystemComponent.h | 33 ++++++------ .../Code/Tools/EMStudio/AtomRenderPlugin.cpp | 45 +++++++++++++++++ .../Code/Tools/EMStudio/AtomRenderPlugin.h | 50 ++++--------------- .../EMStudioSDK/Source/EMStudioManager.cpp | 46 ++++++++++++++++- .../EMStudioSDK/Source/EMStudioManager.h | 47 ++++------------- 6 files changed, 145 insertions(+), 121 deletions(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.cpp index 86a9c36c56..64f7f2dd97 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.cpp @@ -11,32 +11,29 @@ #include -namespace AZ +namespace AZ::EMotionFXAtom { - namespace EMotionFXAtom + void EditorSystemComponent::Reflect(ReflectContext* context) { - void EditorSystemComponent::Reflect(ReflectContext* context) + if (SerializeContext* serialize = azrtti_cast(context)) { - if (SerializeContext* serialize = azrtti_cast(context)) - { - serialize->Class()->Version(0); - } - } - - void EditorSystemComponent::Activate() - { - EMotionFX::Integration::SystemNotificationBus::Handler::BusConnect(); - } - - void EditorSystemComponent::Deactivate() - { - EMotionFX::Integration::SystemNotificationBus::Handler::BusDisconnect(); - } - - void EditorSystemComponent::OnRegisterPlugin() - { - EMStudio::PluginManager* pluginManager = EMStudio::EMStudioManager::GetInstance()->GetPluginManager(); - pluginManager->RegisterPlugin(new EMStudio::AtomRenderPlugin()); + serialize->Class()->Version(0); } } -} // namespace AZ + + void EditorSystemComponent::Activate() + { + EMotionFX::Integration::SystemNotificationBus::Handler::BusConnect(); + } + + void EditorSystemComponent::Deactivate() + { + EMotionFX::Integration::SystemNotificationBus::Handler::BusDisconnect(); + } + + void EditorSystemComponent::OnRegisterPlugin() + { + EMStudio::PluginManager* pluginManager = EMStudio::EMStudioManager::GetInstance()->GetPluginManager(); + pluginManager->RegisterPlugin(new EMStudio::AtomRenderPlugin()); + } +} // namespace AZ::EMotionFXAtom diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.h index 6121912481..9da98bcf42 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.h @@ -10,26 +10,23 @@ #include #include -namespace AZ +namespace AZ::EMotionFXAtom { - namespace EMotionFXAtom + class EditorSystemComponent + : public Component + , private EMotionFX::Integration::SystemNotificationBus::Handler { - class EditorSystemComponent - : public Component - , private EMotionFX::Integration::SystemNotificationBus::Handler - { - public: - AZ_COMPONENT(EditorSystemComponent, "{1FAEC046-255D-4664-8F12-D16503C34431}"); + public: + AZ_COMPONENT(EditorSystemComponent, "{1FAEC046-255D-4664-8F12-D16503C34431}"); - static void Reflect(ReflectContext* context); + static void Reflect(ReflectContext* context); - protected: - // AZ::Component - void Activate() override; - void Deactivate() override; + protected: + // AZ::Component + void Activate() override; + void Deactivate() override; - // SystemNotificationBus::OnRegisterPlugin - void OnRegisterPlugin() override; - }; - } // namespace EMotionFXAtom -} // namespace AZ + // SystemNotificationBus::OnRegisterPlugin + void OnRegisterPlugin() override; + }; +} // namespace AZ::EMotionFXAtom diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp index f7da1d19a9..c7e2178366 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp @@ -21,6 +21,51 @@ namespace EMStudio } + const char* AtomRenderPlugin::GetName() const + { + return "Atom Render Window"; + } + + uint32 AtomRenderPlugin::GetClassID() const + { + return static_cast(AtomRenderPlugin::CLASS_ID); + } + + const char* AtomRenderPlugin::GetCreatorName() const + { + return "O3DE"; + } + + float AtomRenderPlugin::GetVersion() const + { + return 1.0f; + } + + bool AtomRenderPlugin::GetIsClosable() const + { + return true; + } + + bool AtomRenderPlugin::GetIsFloatable() const + { + return true; + } + + bool AtomRenderPlugin::GetIsVertical() const + { + return false; + } + + EMStudioPlugin* AtomRenderPlugin::Clone() + { + return new AtomRenderPlugin(); + } + + EMStudioPlugin::EPluginType AtomRenderPlugin::GetPluginType() const + { + return EMStudioPlugin::PLUGINTYPE_RENDERING; + } + bool AtomRenderPlugin::Init() { m_innerWidget = new QWidget(); diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h index b3e47df91c..0fb1443a96 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h @@ -28,48 +28,16 @@ namespace EMStudio ~AtomRenderPlugin(); // Plugin information - const char* GetCompileDate() const override - { - return MCORE_DATE; - } - const char* GetName() const override - { - return "Atom Render Window"; - } - uint32 GetClassID() const override - { - return static_cast(AtomRenderPlugin::CLASS_ID); - } - const char* GetCreatorName() const override - { - return "O3DE"; - } - float GetVersion() const override - { - return 1.0f; - } - bool GetIsClosable() const override - { - return true; - } - bool GetIsFloatable() const override - { - return true; - } - bool GetIsVertical() const override - { - return false; - } - + const char* GetName() const override; + uint32 GetClassID() const override; + const char* GetCreatorName() const override; + float GetVersion() const override; + bool GetIsClosable() const override; + bool GetIsFloatable() const override; + bool GetIsVertical() const override; bool Init() override; - EMStudioPlugin* Clone() - { - return new AtomRenderPlugin(); - } - EMStudioPlugin::EPluginType GetPluginType() const override - { - return EMStudioPlugin::PLUGINTYPE_RENDERING; - } + EMStudioPlugin* Clone(); + EMStudioPlugin::EPluginType GetPluginType() const override; private: QWidget* m_innerWidget; diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp index 432a351edf..b385de62be 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.cpp @@ -104,7 +104,6 @@ namespace EMStudio AZ::Interface::Register(this); } - // destructor EMStudioManager::~EMStudioManager() { @@ -498,4 +497,49 @@ namespace EMStudio path.addText(textPos, font, text); painter.drawPath(path); } + + // shortcuts + QApplication* GetApp() + { + return EMStudioManager::GetInstance()->GetApp(); + } + EMStudioManager* GetManager() + { + return EMStudioManager::GetInstance(); + } + + bool HasMainWindow() + { + return EMStudioManager::GetInstance()->HasMainWindow(); + } + + MainWindow* GetMainWindow() + { + return EMStudioManager::GetInstance()->GetMainWindow(); + } + + PluginManager* GetPluginManager() + { + return EMStudioManager::GetInstance()->GetPluginManager(); + } + + LayoutManager* GetLayoutManager() + { + return EMStudioManager::GetInstance()->GetLayoutManager(); + } + + NotificationWindowManager* GetNotificationWindowManager() + { + return EMStudioManager::GetInstance()->GetNotificationWindowManager(); + } + + MotionEventPresetManager* GetEventPresetManager() + { + return EMStudioManager::GetInstance()->GetEventPresetManger(); + } + + CommandSystem::CommandManager* GetCommandManager() + { + return EMStudioManager::GetInstance()->GetCommandManager(); + } } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h index 8828253ea2..e7a9397b22 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h @@ -157,41 +157,14 @@ namespace EMStudio EventProcessingCallback* m_eventProcessingCallback; }; - // shortcuts - MCORE_INLINE QApplication* GetApp() - { - return EMStudioManager::GetInstance()->GetApp(); - } - MCORE_INLINE EMStudioManager* GetManager() - { - return EMStudioManager::GetInstance(); - } - MCORE_INLINE bool HasMainWindow() - { - return EMStudioManager::GetInstance()->HasMainWindow(); - } - MCORE_INLINE MainWindow* GetMainWindow() - { - return EMStudioManager::GetInstance()->GetMainWindow(); - } - MCORE_INLINE PluginManager* GetPluginManager() - { - return EMStudioManager::GetInstance()->GetPluginManager(); - } - MCORE_INLINE LayoutManager* GetLayoutManager() - { - return EMStudioManager::GetInstance()->GetLayoutManager(); - } - MCORE_INLINE NotificationWindowManager* GetNotificationWindowManager() - { - return EMStudioManager::GetInstance()->GetNotificationWindowManager(); - } - MCORE_INLINE MotionEventPresetManager* GetEventPresetManager() - { - return EMStudioManager::GetInstance()->GetEventPresetManger(); - } - MCORE_INLINE CommandSystem::CommandManager* GetCommandManager() - { - return EMStudioManager::GetInstance()->GetCommandManager(); - } + // Shortcuts + QApplication* GetApp(); + EMStudioManager* GetManager(); + bool HasMainWindow(); + MainWindow* GetMainWindow(); + PluginManager* GetPluginManager(); + LayoutManager* GetLayoutManager(); + NotificationWindowManager* GetNotificationWindowManager(); + MotionEventPresetManager* GetEventPresetManager(); + CommandSystem::CommandManager* GetCommandManager(); } // namespace EMStudio From cda2bb9d4d080e874cecac5ce0a4345be946b8fd Mon Sep 17 00:00:00 2001 From: rhhong Date: Thu, 9 Sep 2021 21:36:52 -0700 Subject: [PATCH 052/169] Add anim viewport renderer Signed-off-by: rhhong --- .../EMotionFXAtom/Code/CMakeLists.txt | 3 + .../Tools/EMStudio/AnimViewportRenderer.cpp | 279 ++++++++++++++++++ .../Tools/EMStudio/AnimViewportRenderer.h | 79 +++++ .../Tools/EMStudio/AnimViewportWidget.cpp | 13 + .../Code/Tools/EMStudio/AnimViewportWidget.h | 5 + .../Code/emotionfx_atom_editor_files.cmake | 2 + 6 files changed, 381 insertions(+) create mode 100644 Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp create mode 100644 Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/CMakeLists.txt b/Gems/AtomLyIntegration/EMotionFXAtom/Code/CMakeLists.txt index dc22c8ee93..cc71e4f237 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/CMakeLists.txt +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/CMakeLists.txt @@ -62,6 +62,9 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS) Gem::EMotionFX.Editor.Static Gem::AtomToolsFramework.Static Gem::AtomToolsFramework.Editor + Gem::Atom_Component_DebugCamera.Static + Gem::Atom_Feature_Common.Static + Gem::AtomLyIntegration_CommonFeatures.Static RUNTIME_DEPENDENCIES Gem::EMotionFX.Editor COMPILE_DEFINITIONS diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp new file mode 100644 index 0000000000..96fae3cdaf --- /dev/null +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp @@ -0,0 +1,279 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#include +#pragma optimize("", off) + +namespace EMStudio +{ + static constexpr float DepthNear = 0.01f; + + AnimViewportRenderer::AnimViewportRenderer(AZStd::shared_ptr windowContext) + : m_windowContext(windowContext) + { + // Create a new entity context + m_entityContext = AZStd::make_unique(); + m_entityContext->InitContext(); + + // Create the scene + auto sceneSystem = AzFramework::SceneSystemInterface::Get(); + AZ_Assert(sceneSystem, "Unable to retrieve scene system."); + AZ::Outcome, AZStd::string> createSceneOutcome = sceneSystem->CreateScene("AnimViewport"); + AZ_Assert(createSceneOutcome, "%s", createSceneOutcome.GetError().data()); + m_frameworkScene = createSceneOutcome.TakeValue(); + m_frameworkScene->SetSubsystem(m_entityContext.get()); + + // Create and register a scene with all available feature processors + // TODO: We don't need every procesors. + AZ::RPI::SceneDescriptor sceneDesc; + m_scene = AZ::RPI::Scene::CreateScene(sceneDesc); + m_scene->EnableAllFeatureProcessors(); + + // Link our RPI::Scene to the AzFramework::Scene + m_frameworkScene->SetSubsystem(m_scene); + + // Create a render pipeline from the specified asset for the window context and add the pipeline to the scene + AZStd::string defaultPipelineAssetPath = "passes/MainRenderPipeline.azasset"; + AZ::Data::Asset pipelineAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath( + defaultPipelineAssetPath.c_str(), AZ::RPI::AssetUtils::TraceLevel::Error); + m_renderPipeline = AZ::RPI::RenderPipeline::CreateRenderPipelineForWindow(pipelineAsset, *m_windowContext.get()); + pipelineAsset.Release(); + m_scene->AddRenderPipeline(m_renderPipeline); + + // As part of our initialization we need to create the BRDF texture generation pipeline + /* + AZ::RPI::RenderPipelineDescriptor pipelineDesc; + pipelineDesc.m_mainViewTagName = "MainCamera"; + pipelineDesc.m_name = "BRDFTexturePipeline"; + pipelineDesc.m_rootPassTemplate = "BRDFTexturePipeline"; + pipelineDesc.m_executeOnce = true; + + AZ::RPI::RenderPipelinePtr brdfTexturePipeline = AZ::RPI::RenderPipeline::CreateRenderPipeline(pipelineDesc); + m_scene->AddRenderPipeline(brdfTexturePipeline); + */ + + // Currently the scene has to be activated after render pipeline was added so some feature processors (i.e. imgui) can be + // initialized properly + // with pipeline's pass information. + m_scene->Activate(); + AZ::RPI::RPISystemInterface::Get()->RegisterScene(m_scene); + + AzFramework::EntityContextId entityContextId = m_entityContext->GetContextId(); + + // Configure camera + AzFramework::EntityContextRequestBus::EventResult( + m_cameraEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "Cameraentity"); + AZ_Assert(m_cameraEntity != nullptr, "Failed to create camera entity."); + + // Add debug camera and controller components + AZ::Debug::CameraComponentConfig cameraConfig(m_windowContext); + cameraConfig.m_fovY = AZ::Constants::HalfPi; + cameraConfig.m_depthNear = DepthNear; + m_cameraComponent = m_cameraEntity->CreateComponent(azrtti_typeid()); + m_cameraComponent->SetConfiguration(cameraConfig); + m_cameraEntity->CreateComponent(azrtti_typeid()); + m_cameraEntity->CreateComponent(azrtti_typeid()); + m_cameraEntity->Init(); + m_cameraEntity->Activate(); + + // Connect camera to pipeline's default view after camera entity activated + m_renderPipeline->SetDefaultViewFromEntity(m_cameraEntity->GetId()); + + // Get the FeatureProcessors + m_meshFeatureProcessor = m_scene->GetFeatureProcessor(); + // Helper function to load meshes + /* + const auto LoadMesh = [this](const char* modelPath) -> AZ::Render::MeshFeatureProcessorInterface::MeshHandle + { + AZ_Assert(m_meshFeatureProcessor, "Cannot find mesh feature processor on scene"); + + auto meshAsset = AZ::RPI::AssetUtils::GetAssetByProductPath(modelPath, AZ::RPI::AssetUtils::TraceLevel::Assert); + auto materialAsset = + AZ::RPI::AssetUtils::LoadAssetByProductPath("materials/defaultpbr.azmaterial", AZ::RPI::AssetUtils::TraceLevel::Assert); + auto material = AZ::RPI::Material::FindOrCreate(materialAsset); + AZ::Render::MeshFeatureProcessorInterface::MeshHandle meshHandle = + m_meshFeatureProcessor->AcquireMesh(AZ::Render::MeshHandleDescriptor{ meshAsset }, material); + + return meshHandle; + }; + LoadMesh("objects/shaderball_simple.azmodel"); + */ + + // Configure tone mapper + AzFramework::EntityContextRequestBus::EventResult( + m_postProcessEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "postProcessEntity"); + AZ_Assert(m_postProcessEntity != nullptr, "Failed to create post process entity."); + + m_postProcessEntity->CreateComponent(AZ::Render::PostFxLayerComponentTypeId); + m_postProcessEntity->CreateComponent(AZ::Render::ExposureControlComponentTypeId); + m_postProcessEntity->CreateComponent(azrtti_typeid()); + m_postProcessEntity->Activate(); + + // Init directional light processor + m_directionalLightFeatureProcessor = m_scene->GetFeatureProcessor(); + + // Init display mapper processor + m_displayMapperFeatureProcessor = m_scene->GetFeatureProcessor(); + + // Init Skybox + m_skyboxFeatureProcessor = m_scene->GetFeatureProcessor(); + m_skyboxFeatureProcessor->Enable(true); + m_skyboxFeatureProcessor->SetSkyboxMode(AZ::Render::SkyBoxMode::Cubemap); + + // Create IBL + AzFramework::EntityContextRequestBus::EventResult( + m_iblEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "IblEntity"); + AZ_Assert(m_iblEntity != nullptr, "Failed to create ibl entity."); + + m_iblEntity->CreateComponent(AZ::Render::ImageBasedLightComponentTypeId); + m_iblEntity->CreateComponent(azrtti_typeid()); + m_iblEntity->Activate(); + + // Temp: Load light preset + AZ::Data::Asset lightingPresetAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath( + "lightingpresets/default.lightingpreset.azasset", AZ::RPI::AssetUtils::TraceLevel::Warning); + const AZ::Render::LightingPreset* preset = lightingPresetAsset->GetDataAs(); + SetLightingPreset(preset); + + // Create model + AzFramework::EntityContextRequestBus::EventResult( + m_modelEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "ViewportModel"); + AZ_Assert(m_modelEntity != nullptr, "Failed to create model entity."); + + m_modelEntity->CreateComponent(AZ::Render::MeshComponentTypeId); + m_modelEntity->CreateComponent(AZ::Render::MaterialComponentTypeId); + m_modelEntity->CreateComponent(azrtti_typeid()); + m_modelEntity->Activate(); + + // Create grid + AzFramework::EntityContextRequestBus::EventResult( + m_gridEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "ViewportGrid"); + AZ_Assert(m_gridEntity != nullptr, "Failed to create grid entity."); + + AZ::Render::GridComponentConfig gridConfig; + gridConfig.m_gridSize = 4.0f; + gridConfig.m_axisColor = AZ::Color(0.5f, 0.5f, 0.5f, 1.0f); + gridConfig.m_primaryColor = AZ::Color(0.3f, 0.3f, 0.3f, 1.0f); + gridConfig.m_secondaryColor = AZ::Color(0.5f, 0.1f, 0.1f, 1.0f); + auto gridComponent = m_gridEntity->CreateComponent(AZ::Render::GridComponentTypeId); + gridComponent->SetConfiguration(gridConfig); + + m_gridEntity->CreateComponent(azrtti_typeid()); + m_gridEntity->Activate(); + + Reset(); + AZ::TickBus::Handler::BusConnect(); + } + + AnimViewportRenderer::~AnimViewportRenderer() + { + AZ::TickBus::Handler::BusDisconnect(); + } + + void AnimViewportRenderer::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) + { + // m_renderPipeline->AddToRenderTickOnce(); + } + + void AnimViewportRenderer::Reset() + { + // Reset environment + AZ::Transform iblTransform = AZ::Transform::CreateIdentity(); + AZ::TransformBus::Event(m_iblEntity->GetId(), &AZ::TransformBus::Events::SetLocalTM, iblTransform); + + const AZ::Matrix4x4 rotationMatrix = AZ::Matrix4x4::CreateIdentity(); + AZ::RPI::ScenePtr scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene(); + auto skyBoxFeatureProcessorInterface = scene->GetFeatureProcessor(); + skyBoxFeatureProcessorInterface->SetCubemapRotationMatrix(rotationMatrix); + + // Reset model + AZ::Transform modelTransform = AZ::Transform::CreateIdentity(); + modelTransform.SetTranslation(AZ::Vector3(1.0f, 2.0f, 0.5f)); + modelTransform.SetUniformScale(3.3f); + // modelTransform.SetUniformScale(50.0f); + AZ::TransformBus::Event(m_modelEntity->GetId(), &AZ::TransformBus::Events::SetLocalTM, modelTransform); + + auto modelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath( + "objects/shaderball_simple.azmodel", AZ::RPI::AssetUtils::TraceLevel::Assert); + AZ::Render::MeshComponentRequestBus::Event( + m_modelEntity->GetId(), &AZ::Render::MeshComponentRequestBus::Events::SetModelAsset, modelAsset); + + Camera::Configuration cameraConfig; + Camera::CameraRequestBus::EventResult( + cameraConfig, m_cameraEntity->GetId(), &Camera::CameraRequestBus::Events::GetCameraConfiguration); + + // Reset the camera position + static constexpr float StartingDistanceMultiplier = 2.0f; + static constexpr float StartingRotationAngle = AZ::Constants::QuarterPi / 2.0f; + + AZ::Vector3 targetPosition = modelTransform.GetTranslation(); + const float distance = 1.0f * StartingDistanceMultiplier; + const AZ::Quaternion cameraRotation = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), StartingRotationAngle); + AZ::Vector3 cameraPosition(targetPosition.GetX(), targetPosition.GetY() - distance, targetPosition.GetZ()); + cameraPosition = cameraRotation.TransformVector(cameraPosition); + AZ::Transform cameraTransform = AZ::Transform::CreateFromQuaternionAndTranslation(cameraRotation, cameraPosition); + AZ::TransformBus::Event(m_cameraEntity->GetId(), &AZ::TransformBus::Events::SetLocalTM, cameraTransform); + + // Setup primary camera controls + AZ::Debug::CameraControllerRequestBus::Event( + m_cameraEntity->GetId(), &AZ::Debug::CameraControllerRequestBus::Events::Enable, azrtti_typeid()); + } + + void AnimViewportRenderer::SetLightingPreset(const AZ::Render::LightingPreset* preset) + { + if (!preset) + { + AZ_Warning("MaterialViewportRenderer", false, "Attempting to set invalid lighting preset."); + return; + } + + AZ::Render::ImageBasedLightFeatureProcessorInterface* iblFeatureProcessor = + m_scene->GetFeatureProcessor(); + AZ::Render::PostProcessFeatureProcessorInterface* postProcessFeatureProcessor = + m_scene->GetFeatureProcessor(); + + AZ::Render::ExposureControlSettingsInterface* exposureControlSettingInterface = + postProcessFeatureProcessor->GetOrCreateSettingsInterface(m_postProcessEntity->GetId()) + ->GetOrCreateExposureControlSettingsInterface(); + + Camera::Configuration cameraConfig; + Camera::CameraRequestBus::EventResult( + cameraConfig, m_cameraEntity->GetId(), &Camera::CameraRequestBus::Events::GetCameraConfiguration); + + bool enableAlternateSkybox = false; + + AZStd::vector lightHandles; + preset->ApplyLightingPreset( + iblFeatureProcessor, m_skyboxFeatureProcessor, exposureControlSettingInterface, m_directionalLightFeatureProcessor, + cameraConfig, lightHandles, nullptr, AZ::RPI::MaterialPropertyIndex::Null, enableAlternateSkybox); + } +} // namespace EMStudio diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h new file mode 100644 index 0000000000..9bf92aeff9 --- /dev/null +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h @@ -0,0 +1,79 @@ +/* + * 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 + +namespace AZ +{ + class Entity; + class Component; + + namespace Render + { + class DisplayMapperFeatureProcessorInterface; + class DirectionalLightFeatureProcessorInterface; + class MeshFeatureProcessorInterface; + } + + namespace RPI + { + class WindowContext; + } +} + +namespace EMStudio +{ + //! + //! + class AnimViewportRenderer + : public AZ::TickBus::Handler + { + public: + AZ_CLASS_ALLOCATOR(AnimViewportRenderer, AZ::SystemAllocator, 0); + + AnimViewportRenderer(AZStd::shared_ptr windowContext); + ~AnimViewportRenderer(); + + private: + // AZ::TickBus::Handler interface overrides... + void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; + + void Reset(); + void SetLightingPreset(const AZ::Render::LightingPreset* preset); + + AZStd::shared_ptr m_windowContext; + AZStd::unique_ptr m_entityContext; + AZStd::shared_ptr m_frameworkScene; + AZ::RPI::ScenePtr m_scene; + AZ::RPI::RenderPipelinePtr m_renderPipeline; + AZ::Render::DirectionalLightFeatureProcessorInterface* m_directionalLightFeatureProcessor = nullptr; + AZ::Render::DisplayMapperFeatureProcessorInterface* m_displayMapperFeatureProcessor = nullptr; + AZ::Render::SkyBoxFeatureProcessorInterface* m_skyboxFeatureProcessor = nullptr; + AZ::Render::MeshFeatureProcessorInterface* m_meshFeatureProcessor = nullptr; + + AZ::Entity* m_postProcessEntity = nullptr; + AZ::Entity* m_iblEntity = nullptr; + + AZ::Entity* m_cameraEntity = nullptr; + AZ::Component* m_cameraComponent = nullptr; + + AZ::Entity* m_modelEntity = nullptr; + AZ::Data::AssetId m_modelAssetId; + + AZ::Entity* m_gridEntity = nullptr; + }; +} diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp index 2b961e6e7b..39b45507da 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp @@ -6,13 +6,26 @@ * */ +#include + #include +#include namespace EMStudio { AnimViewportWidget::AnimViewportWidget(QWidget* parent) : AtomToolsFramework::RenderViewportWidget(parent) { + setObjectName(QString::fromUtf8("AtomViewportWidget")); + resize(869, 574); + QSizePolicy qSize(QSizePolicy::Preferred, QSizePolicy::Preferred); + qSize.setHorizontalStretch(0); + qSize.setVerticalStretch(0); + qSize.setHeightForWidth(sizePolicy().hasHeightForWidth()); + setSizePolicy(qSize); + setAutoFillBackground(false); + setStyleSheet(QString::fromUtf8("")); + m_renderer = AZStd::make_unique(GetViewportContext()->GetWindowContext()); } } diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h index 59ea5c6680..26bb9838b3 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h @@ -11,10 +11,15 @@ namespace EMStudio { + class AnimViewportRenderer; + class AnimViewportWidget : public AtomToolsFramework::RenderViewportWidget { public: AnimViewportWidget(QWidget* parent = nullptr); + + private: + AZStd::unique_ptr m_renderer; }; } diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/emotionfx_atom_editor_files.cmake b/Gems/AtomLyIntegration/EMotionFXAtom/Code/emotionfx_atom_editor_files.cmake index 37e69739d0..5c8728a8e9 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/emotionfx_atom_editor_files.cmake +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/emotionfx_atom_editor_files.cmake @@ -14,4 +14,6 @@ set(FILES Tools/EMStudio/AtomRenderPlugin.cpp Tools/EMStudio/AnimViewportWidget.h Tools/EMStudio/AnimViewportWidget.cpp + Tools/EMStudio/AnimViewportRenderer.h + Tools/EMStudio/AnimViewportRenderer.cpp ) From d1853389789888e8661e2b6a95b357aec1b127e9 Mon Sep 17 00:00:00 2001 From: rhhong Date: Mon, 13 Sep 2021 21:17:06 -0700 Subject: [PATCH 053/169] Code clean Signed-off-by: rhhong --- .../Tools/EMStudio/AnimViewportRenderer.cpp | 83 ++++++++----------- .../Tools/EMStudio/AnimViewportRenderer.h | 11 +-- 2 files changed, 38 insertions(+), 56 deletions(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp index 96fae3cdaf..89050cc643 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp @@ -53,7 +53,7 @@ namespace EMStudio m_frameworkScene->SetSubsystem(m_entityContext.get()); // Create and register a scene with all available feature processors - // TODO: We don't need every procesors. + // TODO: We don't need every procesors, only register the processor we are going to use. AZ::RPI::SceneDescriptor sceneDesc; m_scene = AZ::RPI::Scene::CreateScene(sceneDesc); m_scene->EnableAllFeatureProcessors(); @@ -69,21 +69,8 @@ namespace EMStudio pipelineAsset.Release(); m_scene->AddRenderPipeline(m_renderPipeline); - // As part of our initialization we need to create the BRDF texture generation pipeline - /* - AZ::RPI::RenderPipelineDescriptor pipelineDesc; - pipelineDesc.m_mainViewTagName = "MainCamera"; - pipelineDesc.m_name = "BRDFTexturePipeline"; - pipelineDesc.m_rootPassTemplate = "BRDFTexturePipeline"; - pipelineDesc.m_executeOnce = true; - - AZ::RPI::RenderPipelinePtr brdfTexturePipeline = AZ::RPI::RenderPipeline::CreateRenderPipeline(pipelineDesc); - m_scene->AddRenderPipeline(brdfTexturePipeline); - */ - // Currently the scene has to be activated after render pipeline was added so some feature processors (i.e. imgui) can be - // initialized properly - // with pipeline's pass information. + // initialized properly with pipeline's pass information. m_scene->Activate(); AZ::RPI::RPISystemInterface::Get()->RegisterScene(m_scene); @@ -110,23 +97,6 @@ namespace EMStudio // Get the FeatureProcessors m_meshFeatureProcessor = m_scene->GetFeatureProcessor(); - // Helper function to load meshes - /* - const auto LoadMesh = [this](const char* modelPath) -> AZ::Render::MeshFeatureProcessorInterface::MeshHandle - { - AZ_Assert(m_meshFeatureProcessor, "Cannot find mesh feature processor on scene"); - - auto meshAsset = AZ::RPI::AssetUtils::GetAssetByProductPath(modelPath, AZ::RPI::AssetUtils::TraceLevel::Assert); - auto materialAsset = - AZ::RPI::AssetUtils::LoadAssetByProductPath("materials/defaultpbr.azmaterial", AZ::RPI::AssetUtils::TraceLevel::Assert); - auto material = AZ::RPI::Material::FindOrCreate(materialAsset); - AZ::Render::MeshFeatureProcessorInterface::MeshHandle meshHandle = - m_meshFeatureProcessor->AcquireMesh(AZ::Render::MeshHandleDescriptor{ meshAsset }, material); - - return meshHandle; - }; - LoadMesh("objects/shaderball_simple.azmodel"); - */ // Configure tone mapper AzFramework::EntityContextRequestBus::EventResult( @@ -158,13 +128,14 @@ namespace EMStudio m_iblEntity->CreateComponent(azrtti_typeid()); m_iblEntity->Activate(); - // Temp: Load light preset + // Load light preset AZ::Data::Asset lightingPresetAsset = AZ::RPI::AssetUtils::LoadAssetByProductPath( "lightingpresets/default.lightingpreset.azasset", AZ::RPI::AssetUtils::TraceLevel::Warning); const AZ::Render::LightingPreset* preset = lightingPresetAsset->GetDataAs(); SetLightingPreset(preset); - // Create model + // Create a static model. + // TODO: Replace this with actor component. AzFramework::EntityContextRequestBus::EventResult( m_modelEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "ViewportModel"); AZ_Assert(m_modelEntity != nullptr, "Failed to create model entity."); @@ -191,17 +162,39 @@ namespace EMStudio m_gridEntity->Activate(); Reset(); - AZ::TickBus::Handler::BusConnect(); } AnimViewportRenderer::~AnimViewportRenderer() { - AZ::TickBus::Handler::BusDisconnect(); - } + const AzFramework::EntityContextId entityContextId = m_entityContext->GetContextId(); + // Destory all the entities we created. + auto DestoryEntity = [](AZ::Entity* entity, AzFramework::EntityContextId contextId) + { + AzFramework::EntityContextRequestBus::Event(contextId, &AzFramework::EntityContextRequestBus::Events::DestroyEntity, entity); + entity = nullptr; + }; + DestoryEntity(m_iblEntity, entityContextId); + DestoryEntity(m_postProcessEntity, entityContextId); + DestoryEntity(m_cameraEntity, entityContextId); + DestoryEntity(m_modelEntity, entityContextId); + DestoryEntity(m_gridEntity, entityContextId); + m_entityContext->DestroyContext(); - void AnimViewportRenderer::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) - { - // m_renderPipeline->AddToRenderTickOnce(); + for (AZ::Render::DirectionalLightFeatureProcessorInterface::LightHandle& handle : m_lightHandles) + { + m_directionalLightFeatureProcessor->ReleaseLight(handle); + } + m_lightHandles.clear(); + + m_frameworkScene->UnsetSubsystem(m_scene); + + auto sceneSystem = AzFramework::SceneSystemInterface::Get(); + AZ_Assert(sceneSystem, "AtomViewportRenderer was unable to get the scene system during destruction."); + bool removeSuccess = sceneSystem->RemoveScene("AnimViewport"); + AZ_Assert(removeSuccess, "AtomViewportRenderer should be removed."); + + AZ::RPI::RPISystemInterface::Get()->UnregisterScene(m_scene); + m_scene = nullptr; } void AnimViewportRenderer::Reset() @@ -217,9 +210,6 @@ namespace EMStudio // Reset model AZ::Transform modelTransform = AZ::Transform::CreateIdentity(); - modelTransform.SetTranslation(AZ::Vector3(1.0f, 2.0f, 0.5f)); - modelTransform.SetUniformScale(3.3f); - // modelTransform.SetUniformScale(50.0f); AZ::TransformBus::Event(m_modelEntity->GetId(), &AZ::TransformBus::Events::SetLocalTM, modelTransform); auto modelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath( @@ -252,7 +242,7 @@ namespace EMStudio { if (!preset) { - AZ_Warning("MaterialViewportRenderer", false, "Attempting to set invalid lighting preset."); + AZ_Warning("AnimViewportRenderer", false, "Attempting to set invalid lighting preset."); return; } @@ -269,11 +259,8 @@ namespace EMStudio Camera::CameraRequestBus::EventResult( cameraConfig, m_cameraEntity->GetId(), &Camera::CameraRequestBus::Events::GetCameraConfiguration); - bool enableAlternateSkybox = false; - - AZStd::vector lightHandles; preset->ApplyLightingPreset( iblFeatureProcessor, m_skyboxFeatureProcessor, exposureControlSettingInterface, m_directionalLightFeatureProcessor, - cameraConfig, lightHandles, nullptr, AZ::RPI::MaterialPropertyIndex::Null, enableAlternateSkybox); + cameraConfig, m_lightHandles, nullptr, AZ::RPI::MaterialPropertyIndex::Null, false); } } // namespace EMStudio diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h index 9bf92aeff9..85538fd568 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h @@ -15,6 +15,7 @@ #include #include #include +#include #include namespace AZ @@ -37,10 +38,7 @@ namespace AZ namespace EMStudio { - //! - //! class AnimViewportRenderer - : public AZ::TickBus::Handler { public: AZ_CLASS_ALLOCATOR(AnimViewportRenderer, AZ::SystemAllocator, 0); @@ -49,8 +47,6 @@ namespace EMStudio ~AnimViewportRenderer(); private: - // AZ::TickBus::Handler interface overrides... - void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; void Reset(); void SetLightingPreset(const AZ::Render::LightingPreset* preset); @@ -67,13 +63,12 @@ namespace EMStudio AZ::Entity* m_postProcessEntity = nullptr; AZ::Entity* m_iblEntity = nullptr; - AZ::Entity* m_cameraEntity = nullptr; AZ::Component* m_cameraComponent = nullptr; - AZ::Entity* m_modelEntity = nullptr; AZ::Data::AssetId m_modelAssetId; - AZ::Entity* m_gridEntity = nullptr; + + AZStd::vector m_lightHandles; }; } From b7900bf646a9c74b1ce1382d4dd4db0beaf6b411 Mon Sep 17 00:00:00 2001 From: rhhong Date: Tue, 21 Sep 2021 09:51:27 -0700 Subject: [PATCH 054/169] render an actor Signed-off-by: rhhong --- .../Tools/EMStudio/AnimViewportRenderer.cpp | 22 ++++++++++++++++++ .../Tools/EMStudio/AnimViewportRenderer.h | 1 + .../Assets/Editor/Layouts/Character2.layout | Bin 0 -> 5388 bytes .../Include/Integration/ActorComponentBus.h | 6 ++++- 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 Gems/EMotionFX/Assets/Editor/Layouts/Character2.layout diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp index 89050cc643..4db69cf8d9 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp @@ -9,6 +9,8 @@ #include #include +#include +#include #include #include #include @@ -145,6 +147,18 @@ namespace EMStudio m_modelEntity->CreateComponent(azrtti_typeid()); m_modelEntity->Activate(); + // Create an actor. + // TODO: Support multiple actors. + AzFramework::EntityContextRequestBus::EventResult( + m_actorEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "ViewportModel"); + AZ_Assert(m_actorEntity != nullptr, "Failed to create model entity."); + + static constexpr const char* const ActorComponentTypeId = "{BDC97E7F-A054-448B-A26F-EA2B5D78E377}"; + m_actorEntity->CreateComponent(ActorComponentTypeId); + m_actorEntity->CreateComponent(AZ::Render::MaterialComponentTypeId); + m_actorEntity->CreateComponent(azrtti_typeid()); + m_actorEntity->Activate(); + // Create grid AzFramework::EntityContextRequestBus::EventResult( m_gridEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "ViewportGrid"); @@ -177,6 +191,7 @@ namespace EMStudio DestoryEntity(m_postProcessEntity, entityContextId); DestoryEntity(m_cameraEntity, entityContextId); DestoryEntity(m_modelEntity, entityContextId); + DestoryEntity(m_actorEntity, entityContextId); DestoryEntity(m_gridEntity, entityContextId); m_entityContext->DestroyContext(); @@ -217,6 +232,13 @@ namespace EMStudio AZ::Render::MeshComponentRequestBus::Event( m_modelEntity->GetId(), &AZ::Render::MeshComponentRequestBus::Events::SetModelAsset, modelAsset); + // Reset the actor asset + AZ::TransformBus::Event(m_actorEntity->GetId(), &AZ::TransformBus::Events::SetLocalTM, modelTransform); + auto actorAsset = AZ::RPI::AssetUtils::GetAssetByProductPath( + "objects/characters/jack/jack.actor", AZ::RPI::AssetUtils::TraceLevel::Assert); + EMotionFX::Integration::ActorComponentRequestBus::Event( + m_actorEntity->GetId(), &EMotionFX::Integration::ActorComponentRequestBus::Events::SetActorAsset, actorAsset); + Camera::Configuration cameraConfig; Camera::CameraRequestBus::EventResult( cameraConfig, m_cameraEntity->GetId(), &Camera::CameraRequestBus::Events::GetCameraConfiguration); diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h index 85538fd568..eb590f8d71 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h @@ -66,6 +66,7 @@ namespace EMStudio AZ::Entity* m_cameraEntity = nullptr; AZ::Component* m_cameraComponent = nullptr; AZ::Entity* m_modelEntity = nullptr; + AZ::Entity* m_actorEntity = nullptr; AZ::Data::AssetId m_modelAssetId; AZ::Entity* m_gridEntity = nullptr; diff --git a/Gems/EMotionFX/Assets/Editor/Layouts/Character2.layout b/Gems/EMotionFX/Assets/Editor/Layouts/Character2.layout new file mode 100644 index 0000000000000000000000000000000000000000..a97581727fce4261825b056591394bf56be2044d GIT binary patch literal 5388 zcmc&&U1%It6h7Ha(^?RV4cHgUDxxAp=HB@Sg`_HJOOh7bDuPhA$(k;jov_(dtkTd2 zt*w+65g`wvAc#VRs?p~@_$FdsguVz3DEOo(;!D=V@4GX1li8Y(hqQCToqOlbIp==o zyXV}Q>@%ZBMuuKEbnK{z^rBIQW+yA!t7u0nDdB#;N96Js7k^rs6T#5POIId;<2{A_ z;JY$MJu4j2kE>EYf6k}+S2Klc_pY3w{$Xp-)myz!v-usJ=YJTx`L{29^Cadf=hFVy zrTcz2INH5C>DTJp=bvSI*3GHydyM|&Z2s=uH>z#KVf~8SW1e4MSy-gM#iecL-rC!K z*R?Ot^7;Oo3yY7FEXWGPnfuzcM3aX1ZjssUY$_cgaN)bGa zB@?yEa5I^mo{{2sP}+|Jr9&^!j<3T4@?kV-PM@qCtu`lXtr;mQA3R5eq4Gm7@}(Fa zhFY!a_{phS11uEBgNu>~a6km1uY4&Y9}XtKByp$Vy$pisvwGj z0_tL@l}vSgJrwZ$pj51*F!J1ZK)G7SfrAf;0XGaB3`6olxn18;d+wt5-4{jr#xOA7 zUjJfXzf<{C+Pv#o!sTf>E;X5wL|RhEwShuv$*fG6yBYMaK%?@%e_9;TNO%|CO7Fwj z6*&DH;|ugIvVB>k+%{`%Yh!9JZ}H?2en7XOASF&i`cS>{gPA5WGo5M6cdOb2{4oBb z7?EQ#EC*yv0=$QOfMB1FB8+`e^bRRsN_&Ky4mP(EVNyzqxV*fIivSMh0C3qD03z@Z zi6<`Z1~BJhPGcN^BRxSu^};ttQQNGmOzP!?>NL>saL5bUpklg+ZRF7)%i(BMlL;hn^`BiU;d* z4F+#mYf#pA3e>%WcBHet$M>M|(!eykj}0@s|F9C6C=TVh%2NHpji`nUx%rvp$cHeu)bC%!qL1D$IHoP5Mg* z`!3OBXJd`_U<)_UWwM_7YE@|&?ivOsqe$qcPcrY #include #include - +#include namespace EMotionFX { @@ -96,6 +96,10 @@ namespace EMotionFX /// Returns skinning method used by the actor. virtual SkinningMethod GetSkinningMethod() const = 0; + // Use this to alter the actor asset. + virtual void SetActorAsset(AZ::Data::Asset actorAsset) = 0; + // virtual AZ::Data::Asset GetAsset() const = 0; + static const size_t s_invalidJointIndex = std::numeric_limits::max(); }; From c463721b52efbb216897d3b7d7d46f26bcad5cc7 Mon Sep 17 00:00:00 2001 From: rhhong Date: Tue, 21 Sep 2021 09:51:52 -0700 Subject: [PATCH 055/169] move the function setactorasset Signed-off-by: rhhong --- .../Code/Source/Integration/Components/ActorComponent.h | 3 +-- .../Integration/Editor/Components/EditorActorComponent.h | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h index b376fa891d..15d9736f34 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h +++ b/Gems/EMotionFX/Code/Source/Integration/Components/ActorComponent.h @@ -121,6 +121,7 @@ namespace EMotionFX void SetRenderCharacter(bool enable) override; bool GetRenderActorVisible() const override; SkinningMethod GetSkinningMethod() const override; + void SetActorAsset(AZ::Data::Asset actorAsset) override; ////////////////////////////////////////////////////////////////////////// // ActorComponentNotificationBus::Handler @@ -178,8 +179,6 @@ namespace EMotionFX void OnAssetReloaded(AZ::Data::Asset asset) override; bool IsPhysicsSceneSimulationFinishEventConnected() const; - - void SetActorAsset(AZ::Data::Asset actorAsset); AZ::Data::Asset GetActorAsset() const { return m_configuration.m_actorAsset; } private: diff --git a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.h b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.h index e8f76bdd49..1d682b47d4 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.h +++ b/Gems/EMotionFX/Code/Source/Integration/Editor/Components/EditorActorComponent.h @@ -60,6 +60,7 @@ namespace EMotionFX bool GetRenderActorVisible() const override; size_t GetNumJoints() const override; SkinningMethod GetSkinningMethod() const override; + void SetActorAsset(AZ::Data::Asset actorAsset) override; // EditorActorComponentRequestBus overrides ... const AZ::Data::AssetId& GetActorAssetId() override; @@ -79,8 +80,6 @@ namespace EMotionFX void OnAssetReady(AZ::Data::Asset asset) override; void OnAssetReloaded(AZ::Data::Asset asset) override; - void SetActorAsset(AZ::Data::Asset actorAsset); - // BoundsRequestBus overrides ... AZ::Aabb GetWorldBounds() override; AZ::Aabb GetLocalBounds() override; From 82bfbd5c9819bf29a3d3e65ba5d378cd93169586 Mon Sep 17 00:00:00 2001 From: rhhong Date: Mon, 27 Sep 2021 16:27:32 -0700 Subject: [PATCH 056/169] Add ability to load actor from the ui Signed-off-by: rhhong --- .../Tools/EMStudio/AnimViewportRenderer.cpp | 149 +++++++++++------- .../Tools/EMStudio/AnimViewportRenderer.h | 17 +- .../Code/Tools/EMStudio/AnimViewportWidget.h | 2 + .../Code/Tools/EMStudio/AtomRenderPlugin.cpp | 43 ++++- .../Code/Tools/EMStudio/AtomRenderPlugin.h | 12 ++ .../Code/EMotionFX/Source/ActorManager.cpp | 6 + .../Code/EMotionFX/Source/ActorManager.h | 1 + 7 files changed, 170 insertions(+), 60 deletions(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp index 4db69cf8d9..f3294ddc09 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp @@ -9,8 +9,8 @@ #include #include -#include #include +#include #include #include #include @@ -32,12 +32,15 @@ #include #include +#include +#include #include -#pragma optimize("", off) + namespace EMStudio { static constexpr float DepthNear = 0.01f; + static constexpr const char* const s_actorComponentTypeId = "{BDC97E7F-A054-448B-A26F-EA2B5D78E377}"; AnimViewportRenderer::AnimViewportRenderer(AZStd::shared_ptr windowContext) : m_windowContext(windowContext) @@ -136,29 +139,6 @@ namespace EMStudio const AZ::Render::LightingPreset* preset = lightingPresetAsset->GetDataAs(); SetLightingPreset(preset); - // Create a static model. - // TODO: Replace this with actor component. - AzFramework::EntityContextRequestBus::EventResult( - m_modelEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "ViewportModel"); - AZ_Assert(m_modelEntity != nullptr, "Failed to create model entity."); - - m_modelEntity->CreateComponent(AZ::Render::MeshComponentTypeId); - m_modelEntity->CreateComponent(AZ::Render::MaterialComponentTypeId); - m_modelEntity->CreateComponent(azrtti_typeid()); - m_modelEntity->Activate(); - - // Create an actor. - // TODO: Support multiple actors. - AzFramework::EntityContextRequestBus::EventResult( - m_actorEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "ViewportModel"); - AZ_Assert(m_actorEntity != nullptr, "Failed to create model entity."); - - static constexpr const char* const ActorComponentTypeId = "{BDC97E7F-A054-448B-A26F-EA2B5D78E377}"; - m_actorEntity->CreateComponent(ActorComponentTypeId); - m_actorEntity->CreateComponent(AZ::Render::MaterialComponentTypeId); - m_actorEntity->CreateComponent(azrtti_typeid()); - m_actorEntity->Activate(); - // Create grid AzFramework::EntityContextRequestBus::EventResult( m_gridEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "ViewportGrid"); @@ -175,24 +155,21 @@ namespace EMStudio m_gridEntity->CreateComponent(azrtti_typeid()); m_gridEntity->Activate(); - Reset(); + Reinit(); } AnimViewportRenderer::~AnimViewportRenderer() { - const AzFramework::EntityContextId entityContextId = m_entityContext->GetContextId(); - // Destory all the entities we created. - auto DestoryEntity = [](AZ::Entity* entity, AzFramework::EntityContextId contextId) + // Destroy all the entity we created. + m_entityContext->DestroyEntity(m_iblEntity); + m_entityContext->DestroyEntity(m_postProcessEntity); + m_entityContext->DestroyEntity(m_cameraEntity); + m_entityContext->DestroyEntity(m_gridEntity); + for (AZ::Entity* entity : m_actorEntities) { - AzFramework::EntityContextRequestBus::Event(contextId, &AzFramework::EntityContextRequestBus::Events::DestroyEntity, entity); - entity = nullptr; - }; - DestoryEntity(m_iblEntity, entityContextId); - DestoryEntity(m_postProcessEntity, entityContextId); - DestoryEntity(m_cameraEntity, entityContextId); - DestoryEntity(m_modelEntity, entityContextId); - DestoryEntity(m_actorEntity, entityContextId); - DestoryEntity(m_gridEntity, entityContextId); + m_entityContext->DestroyEntity(entity); + } + m_actorEntities.clear(); m_entityContext->DestroyContext(); for (AZ::Render::DirectionalLightFeatureProcessorInterface::LightHandle& handle : m_lightHandles) @@ -212,7 +189,13 @@ namespace EMStudio m_scene = nullptr; } - void AnimViewportRenderer::Reset() + void AnimViewportRenderer::Reinit() + { + ReinitActorEntities(); + ResetEnvironment(); + } + + void AnimViewportRenderer::ResetEnvironment() { // Reset environment AZ::Transform iblTransform = AZ::Transform::CreateIdentity(); @@ -223,22 +206,6 @@ namespace EMStudio auto skyBoxFeatureProcessorInterface = scene->GetFeatureProcessor(); skyBoxFeatureProcessorInterface->SetCubemapRotationMatrix(rotationMatrix); - // Reset model - AZ::Transform modelTransform = AZ::Transform::CreateIdentity(); - AZ::TransformBus::Event(m_modelEntity->GetId(), &AZ::TransformBus::Events::SetLocalTM, modelTransform); - - auto modelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath( - "objects/shaderball_simple.azmodel", AZ::RPI::AssetUtils::TraceLevel::Assert); - AZ::Render::MeshComponentRequestBus::Event( - m_modelEntity->GetId(), &AZ::Render::MeshComponentRequestBus::Events::SetModelAsset, modelAsset); - - // Reset the actor asset - AZ::TransformBus::Event(m_actorEntity->GetId(), &AZ::TransformBus::Events::SetLocalTM, modelTransform); - auto actorAsset = AZ::RPI::AssetUtils::GetAssetByProductPath( - "objects/characters/jack/jack.actor", AZ::RPI::AssetUtils::TraceLevel::Assert); - EMotionFX::Integration::ActorComponentRequestBus::Event( - m_actorEntity->GetId(), &EMotionFX::Integration::ActorComponentRequestBus::Events::SetActorAsset, actorAsset); - Camera::Configuration cameraConfig; Camera::CameraRequestBus::EventResult( cameraConfig, m_cameraEntity->GetId(), &Camera::CameraRequestBus::Events::GetCameraConfiguration); @@ -247,7 +214,7 @@ namespace EMStudio static constexpr float StartingDistanceMultiplier = 2.0f; static constexpr float StartingRotationAngle = AZ::Constants::QuarterPi / 2.0f; - AZ::Vector3 targetPosition = modelTransform.GetTranslation(); + AZ::Vector3 targetPosition = iblTransform.GetTranslation(); const float distance = 1.0f * StartingDistanceMultiplier; const AZ::Quaternion cameraRotation = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), StartingRotationAngle); AZ::Vector3 cameraPosition(targetPosition.GetX(), targetPosition.GetY() - distance, targetPosition.GetZ()); @@ -260,6 +227,75 @@ namespace EMStudio m_cameraEntity->GetId(), &AZ::Debug::CameraControllerRequestBus::Events::Enable, azrtti_typeid()); } + void AnimViewportRenderer::ReinitActorEntities() + { + // 1. Destroy all the entities that does not point to any actorAsset anymore. + AZStd::set assetLookup; + AzFramework::EntityContext* entityContext = m_entityContext.get(); + const size_t numActors = EMotionFX::GetActorManager().GetNumActors(); + for (size_t i = 0; i < numActors; ++i) + { + assetLookup.emplace(EMotionFX::GetActorManager().GetActorAsset(i).GetId()); + } + m_actorEntities.erase( + AZStd::remove_if( + m_actorEntities.begin(), m_actorEntities.end(), + [&assetLookup, entityContext](AZ::Entity* entity) + { + EMotionFX::Integration::ActorComponent* actorComponent = + entity->FindComponent(); + if (assetLookup.find(actorComponent->GetActorAsset().GetId()) == assetLookup.end()) + { + entityContext->DestroyEntity(entity); + return true; + } + return false; + }), + m_actorEntities.end()); + + // 2. Create an entity for every actorAsset stored in actor manager. + for (size_t i = 0; i < numActors; ++i) + { + AZ::Data::Asset actorAsset = EMotionFX::GetActorManager().GetActorAsset(i); + if (!actorAsset->IsReady()) + { + continue; + } + + AZ::Entity* entity = FindActorEntity(actorAsset); + if (!entity) + { + m_actorEntities.emplace_back(CreateActorEntity(actorAsset)); + } + } + } + + AZ::Entity* AnimViewportRenderer::FindActorEntity(AZ::Data::Asset actorAsset) const + { + const auto foundEntity = AZStd::find_if( + begin(m_actorEntities), end(m_actorEntities), + [match = actorAsset](const AZ::Entity* entity) + { + EMotionFX::Integration::ActorComponent* actorComponent = entity->FindComponent(); + return actorComponent->GetActorAsset() == match; + }); + return foundEntity != end(m_actorEntities) ? (*foundEntity) : nullptr; + } + + AZ::Entity* AnimViewportRenderer::CreateActorEntity(AZ::Data::Asset actorAsset) + { + AZ::Entity* actorEntity = m_entityContext->CreateEntity(actorAsset->GetActor()->GetName()); + actorEntity->CreateComponent(s_actorComponentTypeId); + actorEntity->CreateComponent(AZ::Render::MaterialComponentTypeId); + actorEntity->CreateComponent(azrtti_typeid()); + actorEntity->Activate(); + + EMotionFX::Integration::ActorComponent* actorComponent = actorEntity->FindComponent(); + actorComponent->SetActorAsset(actorAsset); + + return actorEntity; + } + void AnimViewportRenderer::SetLightingPreset(const AZ::Render::LightingPreset* preset) { if (!preset) @@ -272,7 +308,6 @@ namespace EMStudio m_scene->GetFeatureProcessor(); AZ::Render::PostProcessFeatureProcessorInterface* postProcessFeatureProcessor = m_scene->GetFeatureProcessor(); - AZ::Render::ExposureControlSettingsInterface* exposureControlSettingInterface = postProcessFeatureProcessor->GetOrCreateSettingsInterface(m_postProcessEntity->GetId()) ->GetOrCreateExposureControlSettingsInterface(); diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h index eb590f8d71..c131605caa 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -46,9 +47,21 @@ namespace EMStudio AnimViewportRenderer(AZStd::shared_ptr windowContext); ~AnimViewportRenderer(); + void Reinit(); + private: - void Reset(); + // This function reset the light, camera and other environment settings. + void ResetEnvironment(); + + // This function create in-editor entities for all the actor asset stored in the actor manager, + // and delete all the actor entities that no longer has an actor asset in the actor manager. + // Those entities are used in atom render viewport to visualize actors in animation editor. + void ReinitActorEntities(); + + AZ::Entity* CreateActorEntity(AZ::Data::Asset actorAsset); + + AZ::Entity* FindActorEntity(AZ::Data::Asset actorAsset) const; void SetLightingPreset(const AZ::Render::LightingPreset* preset); AZStd::shared_ptr m_windowContext; @@ -66,9 +79,9 @@ namespace EMStudio AZ::Entity* m_cameraEntity = nullptr; AZ::Component* m_cameraComponent = nullptr; AZ::Entity* m_modelEntity = nullptr; - AZ::Entity* m_actorEntity = nullptr; AZ::Data::AssetId m_modelAssetId; AZ::Entity* m_gridEntity = nullptr; + AZStd::vector m_actorEntities; AZStd::vector m_lightHandles; }; diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h index 26bb9838b3..9e074c1d2c 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h @@ -9,6 +9,7 @@ #include + namespace EMStudio { class AnimViewportRenderer; @@ -18,6 +19,7 @@ namespace EMStudio { public: AnimViewportWidget(QWidget* parent = nullptr); + AnimViewportRenderer* GetAnimViewportRenderer() { return m_renderer.get();} private: AZStd::unique_ptr m_renderer; diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp index c7e2178366..735c90d762 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp @@ -7,6 +7,11 @@ */ #include +#include + +#include +#include +#include #include namespace EMStudio @@ -66,6 +71,11 @@ namespace EMStudio return EMStudioPlugin::PLUGINTYPE_RENDERING; } + void AtomRenderPlugin::ReinitRenderer() + { + m_animViewportWidget->GetAnimViewportRenderer()->Reinit(); + } + bool AtomRenderPlugin::Init() { m_innerWidget = new QWidget(); @@ -75,9 +85,40 @@ namespace EMStudio verticalLayout->setSizeConstraint(QLayout::SetNoConstraint); verticalLayout->setSpacing(1); verticalLayout->setMargin(0); - m_animViewportWidget = new AnimViewportWidget(m_innerWidget); + // Register command callbacks. + m_createActorInstanceCallback = new CreateActorInstanceCallback(false); + EMStudioManager::GetInstance()->GetCommandManager()->RegisterCommandCallback("CreateActorInstance", m_createActorInstanceCallback); + return true; } + + // Command callbacks + bool ReinitAtomRenderPlugin() + { + EMStudioPlugin* plugin = EMStudio::GetPluginManager()->FindActivePlugin(static_cast(AtomRenderPlugin::CLASS_ID)); + if (!plugin) + { + AZ_Error("AtomRenderPlugin", false, "Cannot execute command callback. Atom render plugin does not exist."); + return false; + } + + AtomRenderPlugin* atomRenderPlugin = static_cast(plugin); + atomRenderPlugin->ReinitRenderer(); + + return true; + } + + bool AtomRenderPlugin::CreateActorInstanceCallback::Execute( + [[maybe_unused]] MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine) + { + return ReinitAtomRenderPlugin(); + } + bool AtomRenderPlugin::CreateActorInstanceCallback::Undo( + [[maybe_unused]] MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine) + { + return ReinitAtomRenderPlugin(); + } + } diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h index 0fb1443a96..9e5b3b6937 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h @@ -9,11 +9,18 @@ #pragma once #if !defined(Q_MOC_RUN) +#include #include + #include #include #endif +namespace AZ +{ + class Entity; +} + namespace EMStudio { class AtomRenderPlugin @@ -39,7 +46,12 @@ namespace EMStudio EMStudioPlugin* Clone(); EMStudioPlugin::EPluginType GetPluginType() const override; + void ReinitRenderer(); + private: + MCORE_DEFINECOMMANDCALLBACK(CreateActorInstanceCallback); + CreateActorInstanceCallback* m_createActorInstanceCallback; + QWidget* m_innerWidget; AnimViewportWidget* m_animViewportWidget; }; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp index 0779e55f85..0593575623 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp @@ -429,6 +429,12 @@ namespace EMotionFX } + ActorManager::ActorAssetData ActorManager::GetActorAsset(size_t nr) const + { + return m_actorAssets[nr]; + } + + const AZStd::vector& ActorManager::GetActorInstanceArray() const { return m_actorInstances; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h index e4ce0d6c94..e8bbf40661 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h @@ -80,6 +80,7 @@ namespace EMotionFX * @result A reference to the actor object that contains the array of Actor objects. */ Actor* GetActor(size_t nr) const; + ActorAssetData GetActorAsset(size_t nr) const; /** * Find the given actor by name. From 09f9e5c6c35a04327e35a663282df16f3082906e Mon Sep 17 00:00:00 2001 From: rhhong Date: Tue, 28 Sep 2021 22:48:14 -0700 Subject: [PATCH 057/169] CR feedback Signed-off-by: rhhong --- .../Code/Tools/EMStudio/AnimViewportRenderer.cpp | 5 ++--- .../Code/Tools/EMStudio/AnimViewportRenderer.h | 6 +++--- .../Code/Tools/EMStudio/AnimViewportWidget.h | 2 +- .../Code/Tools/EMStudio/AtomRenderPlugin.cpp | 13 +++++++++++++ .../Code/Tools/EMStudio/AtomRenderPlugin.h | 2 ++ 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp index f3294ddc09..c98a244d8f 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp @@ -40,7 +40,6 @@ namespace EMStudio { static constexpr float DepthNear = 0.01f; - static constexpr const char* const s_actorComponentTypeId = "{BDC97E7F-A054-448B-A26F-EA2B5D78E377}"; AnimViewportRenderer::AnimViewportRenderer(AZStd::shared_ptr windowContext) : m_windowContext(windowContext) @@ -229,7 +228,7 @@ namespace EMStudio void AnimViewportRenderer::ReinitActorEntities() { - // 1. Destroy all the entities that does not point to any actorAsset anymore. + // 1. Destroy all the entities that do not point to any actorAsset anymore. AZStd::set assetLookup; AzFramework::EntityContext* entityContext = m_entityContext.get(); const size_t numActors = EMotionFX::GetActorManager().GetNumActors(); @@ -285,7 +284,7 @@ namespace EMStudio AZ::Entity* AnimViewportRenderer::CreateActorEntity(AZ::Data::Asset actorAsset) { AZ::Entity* actorEntity = m_entityContext->CreateEntity(actorAsset->GetActor()->GetName()); - actorEntity->CreateComponent(s_actorComponentTypeId); + actorEntity->CreateComponent(azrtti_typeid()); actorEntity->CreateComponent(AZ::Render::MaterialComponentTypeId); actorEntity->CreateComponent(azrtti_typeid()); actorEntity->Activate(); diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h index c131605caa..8671068199 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h @@ -51,11 +51,11 @@ namespace EMStudio private: - // This function reset the light, camera and other environment settings. + // This function resets the light, camera and other environment settings. void ResetEnvironment(); - // This function create in-editor entities for all the actor asset stored in the actor manager, - // and delete all the actor entities that no longer has an actor asset in the actor manager. + // This function creates in-editor entities for all actor assets stored in the actor manager, + // and deletes all the actor entities that no longer has an actor asset in the actor manager. // Those entities are used in atom render viewport to visualize actors in animation editor. void ReinitActorEntities(); diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h index 9e074c1d2c..6d1d91ac0d 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h @@ -19,7 +19,7 @@ namespace EMStudio { public: AnimViewportWidget(QWidget* parent = nullptr); - AnimViewportRenderer* GetAnimViewportRenderer() { return m_renderer.get();} + AnimViewportRenderer* GetAnimViewportRenderer() { return m_renderer.get(); } private: AZStd::unique_ptr m_renderer; diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp index 735c90d762..1f35212b8b 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp @@ -89,7 +89,9 @@ namespace EMStudio // Register command callbacks. m_createActorInstanceCallback = new CreateActorInstanceCallback(false); + m_removeActorInstanceCallback = new RemoveActorInstanceCallback(false); EMStudioManager::GetInstance()->GetCommandManager()->RegisterCommandCallback("CreateActorInstance", m_createActorInstanceCallback); + EMStudioManager::GetInstance()->GetCommandManager()->RegisterCommandCallback("RemoveActorInstance", m_removeActorInstanceCallback); return true; } @@ -121,4 +123,15 @@ namespace EMStudio return ReinitAtomRenderPlugin(); } + bool AtomRenderPlugin::RemoveActorInstanceCallback::Execute( + [[maybe_unused]] MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine) + { + return ReinitAtomRenderPlugin(); + } + bool AtomRenderPlugin::RemoveActorInstanceCallback::Undo( + [[maybe_unused]] MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine) + { + return ReinitAtomRenderPlugin(); + } + } diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h index 9e5b3b6937..475fd34180 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h @@ -50,7 +50,9 @@ namespace EMStudio private: MCORE_DEFINECOMMANDCALLBACK(CreateActorInstanceCallback); + MCORE_DEFINECOMMANDCALLBACK(RemoveActorInstanceCallback); CreateActorInstanceCallback* m_createActorInstanceCallback; + RemoveActorInstanceCallback* m_removeActorInstanceCallback; QWidget* m_innerWidget; AnimViewportWidget* m_animViewportWidget; From 47a2240fc3cd3d64c54ef93ca27e5eee99298ab8 Mon Sep 17 00:00:00 2001 From: rhhong Date: Fri, 1 Oct 2021 15:38:50 -0700 Subject: [PATCH 058/169] Using modular camera system to replace the camera entity. Signed-off-by: rhhong --- .../Tools/EMStudio/AnimViewportRenderer.cpp | 62 +++------ .../Tools/EMStudio/AnimViewportRenderer.h | 4 +- .../Tools/EMStudio/AnimViewportWidget.cpp | 122 +++++++++++++++++- .../Code/Tools/EMStudio/AnimViewportWidget.h | 8 +- .../Code/Tools/EMStudio/AtomRenderPlugin.cpp | 3 +- 5 files changed, 146 insertions(+), 53 deletions(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp index c98a244d8f..c475ad8948 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp @@ -32,17 +32,19 @@ #include #include +#include #include #include -#include +#include +#include namespace EMStudio { static constexpr float DepthNear = 0.01f; - AnimViewportRenderer::AnimViewportRenderer(AZStd::shared_ptr windowContext) - : m_windowContext(windowContext) + AnimViewportRenderer::AnimViewportRenderer(AZ::RPI::ViewportContextPtr viewportContext) + : m_windowContext(viewportContext->GetWindowContext()) { // Create a new entity context m_entityContext = AZStd::make_unique(); @@ -72,33 +74,14 @@ namespace EMStudio m_renderPipeline = AZ::RPI::RenderPipeline::CreateRenderPipelineForWindow(pipelineAsset, *m_windowContext.get()); pipelineAsset.Release(); m_scene->AddRenderPipeline(m_renderPipeline); + m_renderPipeline->SetDefaultView(viewportContext->GetDefaultView()); // Currently the scene has to be activated after render pipeline was added so some feature processors (i.e. imgui) can be // initialized properly with pipeline's pass information. m_scene->Activate(); AZ::RPI::RPISystemInterface::Get()->RegisterScene(m_scene); - AzFramework::EntityContextId entityContextId = m_entityContext->GetContextId(); - // Configure camera - AzFramework::EntityContextRequestBus::EventResult( - m_cameraEntity, entityContextId, &AzFramework::EntityContextRequestBus::Events::CreateEntity, "Cameraentity"); - AZ_Assert(m_cameraEntity != nullptr, "Failed to create camera entity."); - - // Add debug camera and controller components - AZ::Debug::CameraComponentConfig cameraConfig(m_windowContext); - cameraConfig.m_fovY = AZ::Constants::HalfPi; - cameraConfig.m_depthNear = DepthNear; - m_cameraComponent = m_cameraEntity->CreateComponent(azrtti_typeid()); - m_cameraComponent->SetConfiguration(cameraConfig); - m_cameraEntity->CreateComponent(azrtti_typeid()); - m_cameraEntity->CreateComponent(azrtti_typeid()); - m_cameraEntity->Init(); - m_cameraEntity->Activate(); - - // Connect camera to pipeline's default view after camera entity activated - m_renderPipeline->SetDefaultViewFromEntity(m_cameraEntity->GetId()); - // Get the FeatureProcessors m_meshFeatureProcessor = m_scene->GetFeatureProcessor(); @@ -162,7 +145,7 @@ namespace EMStudio // Destroy all the entity we created. m_entityContext->DestroyEntity(m_iblEntity); m_entityContext->DestroyEntity(m_postProcessEntity); - m_entityContext->DestroyEntity(m_cameraEntity); + //m_entityContext->DestroyEntity(m_cameraEntity); m_entityContext->DestroyEntity(m_gridEntity); for (AZ::Entity* entity : m_actorEntities) { @@ -204,26 +187,6 @@ namespace EMStudio AZ::RPI::ScenePtr scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene(); auto skyBoxFeatureProcessorInterface = scene->GetFeatureProcessor(); skyBoxFeatureProcessorInterface->SetCubemapRotationMatrix(rotationMatrix); - - Camera::Configuration cameraConfig; - Camera::CameraRequestBus::EventResult( - cameraConfig, m_cameraEntity->GetId(), &Camera::CameraRequestBus::Events::GetCameraConfiguration); - - // Reset the camera position - static constexpr float StartingDistanceMultiplier = 2.0f; - static constexpr float StartingRotationAngle = AZ::Constants::QuarterPi / 2.0f; - - AZ::Vector3 targetPosition = iblTransform.GetTranslation(); - const float distance = 1.0f * StartingDistanceMultiplier; - const AZ::Quaternion cameraRotation = AZ::Quaternion::CreateFromAxisAngle(AZ::Vector3::CreateAxisZ(), StartingRotationAngle); - AZ::Vector3 cameraPosition(targetPosition.GetX(), targetPosition.GetY() - distance, targetPosition.GetZ()); - cameraPosition = cameraRotation.TransformVector(cameraPosition); - AZ::Transform cameraTransform = AZ::Transform::CreateFromQuaternionAndTranslation(cameraRotation, cameraPosition); - AZ::TransformBus::Event(m_cameraEntity->GetId(), &AZ::TransformBus::Events::SetLocalTM, cameraTransform); - - // Setup primary camera controls - AZ::Debug::CameraControllerRequestBus::Event( - m_cameraEntity->GetId(), &AZ::Debug::CameraControllerRequestBus::Events::Enable, azrtti_typeid()); } void AnimViewportRenderer::ReinitActorEntities() @@ -292,6 +255,13 @@ namespace EMStudio EMotionFX::Integration::ActorComponent* actorComponent = actorEntity->FindComponent(); actorComponent->SetActorAsset(actorAsset); + // Since this entity belongs to the animation editor, we need to set the isOwnByRuntime flag to false. + actorComponent->GetActorInstance()->SetIsOwnedByRuntime(false); + // Selet the actor instance in the command manager after it has been created. + AZStd::string outResult; + EMStudioManager::GetInstance()->GetCommandManager()->ExecuteCommandInsideCommand( + AZStd::string::format("Select -actorInstanceID %i", actorComponent->GetActorInstance()->GetID()).c_str(), outResult); + return actorEntity; } @@ -312,8 +282,8 @@ namespace EMStudio ->GetOrCreateExposureControlSettingsInterface(); Camera::Configuration cameraConfig; - Camera::CameraRequestBus::EventResult( - cameraConfig, m_cameraEntity->GetId(), &Camera::CameraRequestBus::Events::GetCameraConfiguration); + cameraConfig.m_fovRadians = AZ::Constants::HalfPi; + cameraConfig.m_nearClipDistance = DepthNear; preset->ApplyLightingPreset( iblFeatureProcessor, m_skyboxFeatureProcessor, exposureControlSettingInterface, m_directionalLightFeatureProcessor, diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h index 8671068199..dd420c175c 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.h @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -44,7 +44,7 @@ namespace EMStudio public: AZ_CLASS_ALLOCATOR(AnimViewportRenderer, AZ::SystemAllocator, 0); - AnimViewportRenderer(AZStd::shared_ptr windowContext); + AnimViewportRenderer(AZ::RPI::ViewportContextPtr viewportContext); ~AnimViewportRenderer(); void Reinit(); diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp index 39b45507da..81678d477e 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp @@ -6,7 +6,11 @@ * */ +#include +#include +#include #include +#include #include #include @@ -17,7 +21,6 @@ namespace EMStudio : AtomToolsFramework::RenderViewportWidget(parent) { setObjectName(QString::fromUtf8("AtomViewportWidget")); - resize(869, 574); QSizePolicy qSize(QSizePolicy::Preferred, QSizePolicy::Preferred); qSize.setHorizontalStretch(0); qSize.setVerticalStretch(0); @@ -26,6 +29,119 @@ namespace EMStudio setAutoFillBackground(false); setStyleSheet(QString::fromUtf8("")); - m_renderer = AZStd::make_unique(GetViewportContext()->GetWindowContext()); + m_renderer = AZStd::make_unique(GetViewportContext()); + + SetupCameras(); + SetupCameraController(); } -} + + template + AZStd::remove_cvref_t GetRegistry(const AZStd::string_view setting, T&& defaultValue) + { + AZStd::remove_cvref_t value = AZStd::forward(defaultValue); + if (const auto* registry = AZ::SettingsRegistry::Get()) + { + T potentialValue; + if (registry->Get(potentialValue, setting)) + { + value = AZStd::move(potentialValue); + } + } + + return value; + } + + // TODO: TranslateCameraInput should have a way to initiate with default channel id setup. + static AzFramework::TranslateCameraInputChannelIds BuildTranslateCameraInputChannelIds() + { + constexpr AZStd::string_view CameraTranslateForwardIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateForwardId"; + constexpr AZStd::string_view CameraTranslateBackwardIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateBackwardId"; + constexpr AZStd::string_view CameraTranslateLeftIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateLeftId"; + constexpr AZStd::string_view CameraTranslateRightIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateRightId"; + constexpr AZStd::string_view CameraTranslateUpIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateUpId"; + constexpr AZStd::string_view CameraTranslateDownIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateUpDownId"; + constexpr AZStd::string_view CameraTranslateBoostIdSetting = "/Amazon/Preferences/Editor/Camera/TranslateBoostId"; + + AzFramework::TranslateCameraInputChannelIds translateCameraInputChannelIds; + translateCameraInputChannelIds.m_leftChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateLeftIdSetting, AZStd::string("keyboard_key_alphanumeric_A")).c_str()); + translateCameraInputChannelIds.m_rightChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateRightIdSetting, AZStd::string("keyboard_key_alphanumeric_D")).c_str()); + translateCameraInputChannelIds.m_forwardChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateForwardIdSetting, AZStd::string("keyboard_key_alphanumeric_W")).c_str()); + translateCameraInputChannelIds.m_backwardChannelId = AzFramework::InputChannelId( + GetRegistry(CameraTranslateBackwardIdSetting, AZStd::string("keyboard_key_alphanumeric_S")).c_str()); + translateCameraInputChannelIds.m_upChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateUpIdSetting, AZStd::string("keyboard_key_alphanumeric_E")).c_str()); + translateCameraInputChannelIds.m_downChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateDownIdSetting, AZStd::string("keyboard_key_alphanumeric_Q")).c_str()); + translateCameraInputChannelIds.m_boostChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateBoostIdSetting, AZStd::string("keyboard_key_modifier_shift_l")).c_str()); + + return translateCameraInputChannelIds; + } + + void AnimViewportWidget::SetupCameras() + { + constexpr AZStd::string_view CameraOrbitIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitId"; + constexpr AZStd::string_view CameraOrbitLookIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitLookId"; + + m_orbitRotateCamera = AZStd::make_shared( + AzFramework::InputChannelId(GetRegistry(CameraOrbitLookIdSetting, AZStd::string("mouse_button_left")).c_str())); + + const auto translateCameraInputChannelIds = BuildTranslateCameraInputChannelIds(); + m_orbitTranslateCamera = + AZStd::make_shared(AzFramework::OrbitTranslation, translateCameraInputChannelIds); + m_orbitDollyScrollCamera = AZStd::make_shared(); + } + + void AnimViewportWidget::SetupCameraController() + { + auto controller = AZStd::make_shared(); + controller->SetCameraViewportContextBuilderCallback( + [viewportId = + GetViewportContext()->GetId()](AZStd::unique_ptr& cameraViewportContext) + { + cameraViewportContext = AZStd::make_unique(viewportId); + }); + + controller->SetCameraPriorityBuilderCallback( + [](AtomToolsFramework::CameraControllerPriorityFn& cameraControllerPriorityFn) + { + cameraControllerPriorityFn = AtomToolsFramework::DefaultCameraControllerPriority; + }); + + controller->SetCameraPropsBuilderCallback( + [](AzFramework::CameraProps& cameraProps) + { + cameraProps.m_rotateSmoothnessFn = [] + { + return 5.0f; + }; + + cameraProps.m_translateSmoothnessFn = [] + { + return 5.0f; + }; + + cameraProps.m_rotateSmoothingEnabledFn = [] + { + return true; + }; + + cameraProps.m_translateSmoothingEnabledFn = [] + { + return true; + }; + }); + + controller->SetCameraListBuilderCallback( + [this](AzFramework::Cameras& cameras) + { + cameras.AddCamera(m_orbitRotateCamera); + cameras.AddCamera(m_orbitTranslateCamera); + cameras.AddCamera(m_orbitDollyScrollCamera); + }); + GetControllerList()->Add(controller); + } +} // namespace EMStudio diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h index 6d1d91ac0d..64bf4cd5dd 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h @@ -8,7 +8,7 @@ #pragma once #include - +#include namespace EMStudio { @@ -22,6 +22,12 @@ namespace EMStudio AnimViewportRenderer* GetAnimViewportRenderer() { return m_renderer.get(); } private: + void SetupCameras(); + void SetupCameraController(); + AZStd::unique_ptr m_renderer; + AZStd::shared_ptr m_orbitRotateCamera; + AZStd::shared_ptr m_orbitTranslateCamera; + AZStd::shared_ptr m_orbitDollyScrollCamera; }; } diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp index 1f35212b8b..948006e2b5 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp @@ -28,7 +28,7 @@ namespace EMStudio const char* AtomRenderPlugin::GetName() const { - return "Atom Render Window"; + return "Atom Render Window (Preview)"; } uint32 AtomRenderPlugin::GetClassID() const @@ -86,6 +86,7 @@ namespace EMStudio verticalLayout->setSpacing(1); verticalLayout->setMargin(0); m_animViewportWidget = new AnimViewportWidget(m_innerWidget); + verticalLayout->addWidget(m_animViewportWidget); // Register command callbacks. m_createActorInstanceCallback = new CreateActorInstanceCallback(false); From ffa637d115903758beecf05ce43ba21e5edbeb1c Mon Sep 17 00:00:00 2001 From: rhhong Date: Fri, 1 Oct 2021 16:04:49 -0700 Subject: [PATCH 059/169] Code cleanup Signed-off-by: rhhong --- .../EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp index c475ad8948..a75095568f 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp @@ -145,7 +145,6 @@ namespace EMStudio // Destroy all the entity we created. m_entityContext->DestroyEntity(m_iblEntity); m_entityContext->DestroyEntity(m_postProcessEntity); - //m_entityContext->DestroyEntity(m_cameraEntity); m_entityContext->DestroyEntity(m_gridEntity); for (AZ::Entity* entity : m_actorEntities) { From 10febe2a4baa4309de50ffcebfc09ffacdfc7bc5 Mon Sep 17 00:00:00 2001 From: rhhong Date: Mon, 4 Oct 2021 18:52:11 -0700 Subject: [PATCH 060/169] Move some utility class and settings to a setting file. Signed-off-by: rhhong --- .../Tools/EMStudio/AnimViewportSettings.cpp | 73 +++++++++++++++++++ .../Tools/EMStudio/AnimViewportSettings.h | 37 ++++++++++ .../Tools/EMStudio/AnimViewportWidget.cpp | 63 ++-------------- .../Code/emotionfx_atom_editor_files.cmake | 2 + 4 files changed, 119 insertions(+), 56 deletions(-) create mode 100644 Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportSettings.cpp create mode 100644 Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportSettings.h diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportSettings.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportSettings.cpp new file mode 100644 index 0000000000..99bfae91fd --- /dev/null +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportSettings.cpp @@ -0,0 +1,73 @@ +/* + * 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 EMStudio::ViewportUtil +{ + constexpr AZStd::string_view CameraRotateSmoothnessSetting = "/Amazon/Preferences/Editor/Camera/RotateSmoothness"; + constexpr AZStd::string_view CameraTranslateSmoothnessSetting = "/Amazon/Preferences/Editor/Camera/TranslateSmoothness"; + constexpr AZStd::string_view CameraTranslateSmoothingSetting = "/Amazon/Preferences/Editor/Camera/TranslateSmoothing"; + constexpr AZStd::string_view CameraRotateSmoothingSetting = "/Amazon/Preferences/Editor/Camera/RotateSmoothing"; + + constexpr AZStd::string_view CameraOrbitLookIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitLookId"; + constexpr AZStd::string_view CameraTranslateForwardIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateForwardId"; + constexpr AZStd::string_view CameraTranslateBackwardIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateBackwardId"; + constexpr AZStd::string_view CameraTranslateLeftIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateLeftId"; + constexpr AZStd::string_view CameraTranslateRightIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateRightId"; + constexpr AZStd::string_view CameraTranslateUpIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateUpId"; + constexpr AZStd::string_view CameraTranslateDownIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateUpDownId"; + constexpr AZStd::string_view CameraTranslateBoostIdSetting = "/Amazon/Preferences/Editor/Camera/TranslateBoostId"; + + AzFramework::TranslateCameraInputChannelIds BuildTranslateCameraInputChannelIds() + { + AzFramework::TranslateCameraInputChannelIds translateCameraInputChannelIds; + translateCameraInputChannelIds.m_leftChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateLeftIdSetting, AZStd::string("keyboard_key_alphanumeric_A")).c_str()); + translateCameraInputChannelIds.m_rightChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateRightIdSetting, AZStd::string("keyboard_key_alphanumeric_D")).c_str()); + translateCameraInputChannelIds.m_forwardChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateForwardIdSetting, AZStd::string("keyboard_key_alphanumeric_W")).c_str()); + translateCameraInputChannelIds.m_backwardChannelId = AzFramework::InputChannelId( + GetRegistry(CameraTranslateBackwardIdSetting, AZStd::string("keyboard_key_alphanumeric_S")).c_str()); + translateCameraInputChannelIds.m_upChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateUpIdSetting, AZStd::string("keyboard_key_alphanumeric_E")).c_str()); + translateCameraInputChannelIds.m_downChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateDownIdSetting, AZStd::string("keyboard_key_alphanumeric_Q")).c_str()); + translateCameraInputChannelIds.m_boostChannelId = + AzFramework::InputChannelId(GetRegistry(CameraTranslateBoostIdSetting, AZStd::string("keyboard_key_modifier_shift_l")).c_str()); + + return translateCameraInputChannelIds; + } + + float CameraRotateSmoothness() + { + return aznumeric_cast(GetRegistry(CameraRotateSmoothnessSetting, 5.0)); + } + + float CameraTranslateSmoothness() + { + return aznumeric_cast(GetRegistry(CameraTranslateSmoothnessSetting, 5.0)); + } + + bool CameraRotateSmoothingEnabled() + { + return GetRegistry(CameraRotateSmoothingSetting, true); + } + + bool CameraTranslateSmoothingEnabled() + { + return GetRegistry(CameraTranslateSmoothingSetting, true); + } + + AzFramework::InputChannelId BuildRotateCameraInputId() + { + AzFramework::InputChannelId inputChannelId( + EMStudio::ViewportUtil::GetRegistry(CameraOrbitLookIdSetting, AZStd::string("mouse_button_left")).c_str()); + return inputChannelId; + } +} diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportSettings.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportSettings.h new file mode 100644 index 0000000000..5fa14a8aae --- /dev/null +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportSettings.h @@ -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 + * + */ +#pragma once +#include +#include + +namespace EMStudio::ViewportUtil +{ + template + AZStd::remove_cvref_t GetRegistry(const AZStd::string_view setting, T&& defaultValue) + { + AZStd::remove_cvref_t value = AZStd::forward(defaultValue); + if (const auto* registry = AZ::SettingsRegistry::Get()) + { + T potentialValue; + if (registry->Get(potentialValue, setting)) + { + value = AZStd::move(potentialValue); + } + } + + return value; + } + + float CameraRotateSmoothness(); + float CameraTranslateSmoothness(); + bool CameraRotateSmoothingEnabled(); + bool CameraTranslateSmoothingEnabled(); + + AzFramework::TranslateCameraInputChannelIds BuildTranslateCameraInputChannelIds(); + AzFramework::InputChannelId BuildRotateCameraInputId(); +} diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp index 81678d477e..2a5006767a 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp @@ -14,6 +14,7 @@ #include #include +#include namespace EMStudio { @@ -35,61 +36,11 @@ namespace EMStudio SetupCameraController(); } - template - AZStd::remove_cvref_t GetRegistry(const AZStd::string_view setting, T&& defaultValue) - { - AZStd::remove_cvref_t value = AZStd::forward(defaultValue); - if (const auto* registry = AZ::SettingsRegistry::Get()) - { - T potentialValue; - if (registry->Get(potentialValue, setting)) - { - value = AZStd::move(potentialValue); - } - } - - return value; - } - - // TODO: TranslateCameraInput should have a way to initiate with default channel id setup. - static AzFramework::TranslateCameraInputChannelIds BuildTranslateCameraInputChannelIds() - { - constexpr AZStd::string_view CameraTranslateForwardIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateForwardId"; - constexpr AZStd::string_view CameraTranslateBackwardIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateBackwardId"; - constexpr AZStd::string_view CameraTranslateLeftIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateLeftId"; - constexpr AZStd::string_view CameraTranslateRightIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateRightId"; - constexpr AZStd::string_view CameraTranslateUpIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateUpId"; - constexpr AZStd::string_view CameraTranslateDownIdSetting = "/Amazon/Preferences/Editor/Camera/CameraTranslateUpDownId"; - constexpr AZStd::string_view CameraTranslateBoostIdSetting = "/Amazon/Preferences/Editor/Camera/TranslateBoostId"; - - AzFramework::TranslateCameraInputChannelIds translateCameraInputChannelIds; - translateCameraInputChannelIds.m_leftChannelId = - AzFramework::InputChannelId(GetRegistry(CameraTranslateLeftIdSetting, AZStd::string("keyboard_key_alphanumeric_A")).c_str()); - translateCameraInputChannelIds.m_rightChannelId = - AzFramework::InputChannelId(GetRegistry(CameraTranslateRightIdSetting, AZStd::string("keyboard_key_alphanumeric_D")).c_str()); - translateCameraInputChannelIds.m_forwardChannelId = - AzFramework::InputChannelId(GetRegistry(CameraTranslateForwardIdSetting, AZStd::string("keyboard_key_alphanumeric_W")).c_str()); - translateCameraInputChannelIds.m_backwardChannelId = AzFramework::InputChannelId( - GetRegistry(CameraTranslateBackwardIdSetting, AZStd::string("keyboard_key_alphanumeric_S")).c_str()); - translateCameraInputChannelIds.m_upChannelId = - AzFramework::InputChannelId(GetRegistry(CameraTranslateUpIdSetting, AZStd::string("keyboard_key_alphanumeric_E")).c_str()); - translateCameraInputChannelIds.m_downChannelId = - AzFramework::InputChannelId(GetRegistry(CameraTranslateDownIdSetting, AZStd::string("keyboard_key_alphanumeric_Q")).c_str()); - translateCameraInputChannelIds.m_boostChannelId = - AzFramework::InputChannelId(GetRegistry(CameraTranslateBoostIdSetting, AZStd::string("keyboard_key_modifier_shift_l")).c_str()); - - return translateCameraInputChannelIds; - } - void AnimViewportWidget::SetupCameras() { - constexpr AZStd::string_view CameraOrbitIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitId"; - constexpr AZStd::string_view CameraOrbitLookIdSetting = "/Amazon/Preferences/Editor/Camera/OrbitLookId"; + m_orbitRotateCamera = AZStd::make_shared(EMStudio::ViewportUtil::BuildRotateCameraInputId()); - m_orbitRotateCamera = AZStd::make_shared( - AzFramework::InputChannelId(GetRegistry(CameraOrbitLookIdSetting, AZStd::string("mouse_button_left")).c_str())); - - const auto translateCameraInputChannelIds = BuildTranslateCameraInputChannelIds(); + const auto translateCameraInputChannelIds = EMStudio::ViewportUtil::BuildTranslateCameraInputChannelIds(); m_orbitTranslateCamera = AZStd::make_shared(AzFramework::OrbitTranslation, translateCameraInputChannelIds); m_orbitDollyScrollCamera = AZStd::make_shared(); @@ -116,22 +67,22 @@ namespace EMStudio { cameraProps.m_rotateSmoothnessFn = [] { - return 5.0f; + return EMStudio::ViewportUtil::CameraRotateSmoothness(); }; cameraProps.m_translateSmoothnessFn = [] { - return 5.0f; + return EMStudio::ViewportUtil::CameraTranslateSmoothness(); }; cameraProps.m_rotateSmoothingEnabledFn = [] { - return true; + return EMStudio::ViewportUtil::CameraRotateSmoothingEnabled(); }; cameraProps.m_translateSmoothingEnabledFn = [] { - return true; + return EMStudio::ViewportUtil::CameraTranslateSmoothingEnabled(); }; }); diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/emotionfx_atom_editor_files.cmake b/Gems/AtomLyIntegration/EMotionFXAtom/Code/emotionfx_atom_editor_files.cmake index 5c8728a8e9..a88581099f 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/emotionfx_atom_editor_files.cmake +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/emotionfx_atom_editor_files.cmake @@ -16,4 +16,6 @@ set(FILES Tools/EMStudio/AnimViewportWidget.cpp Tools/EMStudio/AnimViewportRenderer.h Tools/EMStudio/AnimViewportRenderer.cpp + Tools/EMStudio/AnimViewportSettings.h + Tools/EMStudio/AnimViewportSettings.cpp ) From 646369c1b5b27baab176838ba0e4904d55b4ddfa Mon Sep 17 00:00:00 2001 From: rhhong Date: Tue, 5 Oct 2021 13:03:22 -0700 Subject: [PATCH 061/169] update camera naming and behavior after the merge in Signed-off-by: rhhong --- .../Tools/EMStudio/AnimViewportSettings.cpp | 4 +--- .../Tools/EMStudio/AnimViewportWidget.cpp | 19 ++++++++++++------- .../Code/Tools/EMStudio/AnimViewportWidget.h | 6 +++--- .../Source/RenderPlugin/RenderViewWidget.cpp | 4 ++-- 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportSettings.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportSettings.cpp index 99bfae91fd..347e077af3 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportSettings.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportSettings.cpp @@ -66,8 +66,6 @@ namespace EMStudio::ViewportUtil AzFramework::InputChannelId BuildRotateCameraInputId() { - AzFramework::InputChannelId inputChannelId( - EMStudio::ViewportUtil::GetRegistry(CameraOrbitLookIdSetting, AZStd::string("mouse_button_left")).c_str()); - return inputChannelId; + return AzFramework::InputChannelId(GetRegistry(CameraOrbitLookIdSetting, AZStd::string("mouse_button_left")).c_str()); } } diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp index 2a5006767a..d3fd719d38 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp @@ -38,12 +38,17 @@ namespace EMStudio void AnimViewportWidget::SetupCameras() { - m_orbitRotateCamera = AZStd::make_shared(EMStudio::ViewportUtil::BuildRotateCameraInputId()); + m_pivotRotateCamera = AZStd::make_shared(EMStudio::ViewportUtil::BuildRotateCameraInputId()); const auto translateCameraInputChannelIds = EMStudio::ViewportUtil::BuildTranslateCameraInputChannelIds(); - m_orbitTranslateCamera = - AZStd::make_shared(AzFramework::OrbitTranslation, translateCameraInputChannelIds); - m_orbitDollyScrollCamera = AZStd::make_shared(); + m_pivotTranslateCamera = AZStd::make_shared( + translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslatePivot); + m_pivotTranslateCamera.get()->m_translateSpeedFn = [] + { + return 3.0f; + }; + + m_pivotDollyScrollCamera = AZStd::make_shared(); } void AnimViewportWidget::SetupCameraController() @@ -89,9 +94,9 @@ namespace EMStudio controller->SetCameraListBuilderCallback( [this](AzFramework::Cameras& cameras) { - cameras.AddCamera(m_orbitRotateCamera); - cameras.AddCamera(m_orbitTranslateCamera); - cameras.AddCamera(m_orbitDollyScrollCamera); + cameras.AddCamera(m_pivotRotateCamera); + cameras.AddCamera(m_pivotTranslateCamera); + cameras.AddCamera(m_pivotDollyScrollCamera); }); GetControllerList()->Add(controller); } diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h index 64bf4cd5dd..70b4e1e667 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h @@ -26,8 +26,8 @@ namespace EMStudio void SetupCameraController(); AZStd::unique_ptr m_renderer; - AZStd::shared_ptr m_orbitRotateCamera; - AZStd::shared_ptr m_orbitTranslateCamera; - AZStd::shared_ptr m_orbitDollyScrollCamera; + AZStd::shared_ptr m_pivotRotateCamera; + AZStd::shared_ptr m_pivotTranslateCamera; + AZStd::shared_ptr m_pivotDollyScrollCamera; }; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.cpp index 93a6dd3019..fe8fb61f02 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/RenderPlugin/RenderViewWidget.cpp @@ -155,12 +155,12 @@ namespace EMStudio cameraMenu->addAction("Reset Camera", [this]() { this->OnResetCamera(); }); QAction* showSelectedAction = cameraMenu->addAction("Show Selected", this, &RenderViewWidget::OnShowSelected); - showSelectedAction->setShortcut(Qt::Key_S); + showSelectedAction->setShortcut(QKeySequence(Qt::Key_S + Qt::SHIFT)); GetMainWindow()->GetShortcutManager()->RegisterKeyboardShortcut(showSelectedAction, RenderPlugin::s_renderWindowShortcutGroupName, true); addAction(showSelectedAction); QAction* showEntireSceneAction = cameraMenu->addAction("Show Entire Scene", this, &RenderViewWidget::OnShowEntireScene); - showEntireSceneAction->setShortcut(Qt::Key_A); + showEntireSceneAction->setShortcut(QKeySequence(Qt::Key_A + Qt::SHIFT)); GetMainWindow()->GetShortcutManager()->RegisterKeyboardShortcut(showEntireSceneAction, RenderPlugin::s_renderWindowShortcutGroupName, true); addAction(showEntireSceneAction); From 88970403157ee9df0952d5dbf9ef5dae1ddf8f91 Mon Sep 17 00:00:00 2001 From: rhhong Date: Tue, 5 Oct 2021 18:08:02 -0700 Subject: [PATCH 062/169] Gems/EMotionFX/Assets/Editor/Layouts/Character2.layout Signed-off-by: rhhong --- .../Assets/Editor/Layouts/Character2.layout | Bin 5388 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Gems/EMotionFX/Assets/Editor/Layouts/Character2.layout diff --git a/Gems/EMotionFX/Assets/Editor/Layouts/Character2.layout b/Gems/EMotionFX/Assets/Editor/Layouts/Character2.layout deleted file mode 100644 index a97581727fce4261825b056591394bf56be2044d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5388 zcmc&&U1%It6h7Ha(^?RV4cHgUDxxAp=HB@Sg`_HJOOh7bDuPhA$(k;jov_(dtkTd2 zt*w+65g`wvAc#VRs?p~@_$FdsguVz3DEOo(;!D=V@4GX1li8Y(hqQCToqOlbIp==o zyXV}Q>@%ZBMuuKEbnK{z^rBIQW+yA!t7u0nDdB#;N96Js7k^rs6T#5POIId;<2{A_ z;JY$MJu4j2kE>EYf6k}+S2Klc_pY3w{$Xp-)myz!v-usJ=YJTx`L{29^Cadf=hFVy zrTcz2INH5C>DTJp=bvSI*3GHydyM|&Z2s=uH>z#KVf~8SW1e4MSy-gM#iecL-rC!K z*R?Ot^7;Oo3yY7FEXWGPnfuzcM3aX1ZjssUY$_cgaN)bGa zB@?yEa5I^mo{{2sP}+|Jr9&^!j<3T4@?kV-PM@qCtu`lXtr;mQA3R5eq4Gm7@}(Fa zhFY!a_{phS11uEBgNu>~a6km1uY4&Y9}XtKByp$Vy$pisvwGj z0_tL@l}vSgJrwZ$pj51*F!J1ZK)G7SfrAf;0XGaB3`6olxn18;d+wt5-4{jr#xOA7 zUjJfXzf<{C+Pv#o!sTf>E;X5wL|RhEwShuv$*fG6yBYMaK%?@%e_9;TNO%|CO7Fwj z6*&DH;|ugIvVB>k+%{`%Yh!9JZ}H?2en7XOASF&i`cS>{gPA5WGo5M6cdOb2{4oBb z7?EQ#EC*yv0=$QOfMB1FB8+`e^bRRsN_&Ky4mP(EVNyzqxV*fIivSMh0C3qD03z@Z zi6<`Z1~BJhPGcN^BRxSu^};ttQQNGmOzP!?>NL>saL5bUpklg+ZRF7)%i(BMlL;hn^`BiU;d* z4F+#mYf#pA3e>%WcBHet$M>M|(!eykj}0@s|F9C6C=TVh%2NHpji`nUx%rvp$cHeu)bC%!qL1D$IHoP5Mg* z`!3OBXJd`_U<)_UWwM_7YE@|&?ivOsqe$qcPcrY Date: Wed, 6 Oct 2021 22:28:18 -0700 Subject: [PATCH 063/169] CR feedback Signed-off-by: rhhong --- .../Source/Editor/EditorSystemComponent.cpp | 2 +- .../Source/Editor/EditorSystemComponent.h | 2 +- .../Tools/EMStudio/AnimViewportRenderer.cpp | 1 - .../Code/Tools/EMStudio/AtomRenderPlugin.cpp | 20 +++++++++++-------- .../Code/Tools/EMStudio/AtomRenderPlugin.h | 10 ++++++---- .../Code/EMotionFX/Source/ActorManager.cpp | 3 +-- .../Code/EMotionFX/Source/ActorManager.h | 1 - .../Source/NodeWindow/NodeWindowPlugin.h | 1 + .../Include/Integration/ActorComponentBus.h | 1 - .../Source/Integration/Assets/ActorAsset.h | 2 ++ 10 files changed, 24 insertions(+), 19 deletions(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.cpp index 64f7f2dd97..edd2f074fe 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.cpp @@ -34,6 +34,6 @@ namespace AZ::EMotionFXAtom void EditorSystemComponent::OnRegisterPlugin() { EMStudio::PluginManager* pluginManager = EMStudio::EMStudioManager::GetInstance()->GetPluginManager(); - pluginManager->RegisterPlugin(new EMStudio::AtomRenderPlugin()); + pluginManager->RegisterPlugin(aznew EMStudio::AtomRenderPlugin()); } } // namespace AZ::EMotionFXAtom diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.h index 9da98bcf42..80ff7b0b8d 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Source/Editor/EditorSystemComponent.h @@ -22,7 +22,7 @@ namespace AZ::EMotionFXAtom static void Reflect(ReflectContext* context); protected: - // AZ::Component + // AZ::Component overrides void Activate() override; void Deactivate() override; diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp index a75095568f..08f85ab1be 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp @@ -59,7 +59,6 @@ namespace EMStudio m_frameworkScene->SetSubsystem(m_entityContext.get()); // Create and register a scene with all available feature processors - // TODO: We don't need every procesors, only register the processor we are going to use. AZ::RPI::SceneDescriptor sceneDesc; m_scene = AZ::RPI::Scene::CreateScene(sceneDesc); m_scene->EnableAllFeatureProcessors(); diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp index 948006e2b5..90f6d54466 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp @@ -11,11 +11,14 @@ #include #include +#include #include #include namespace EMStudio { + AZ_CLASS_ALLOCATOR_IMPL(AtomRenderPlugin, EMotionFX::EditorAllocator, 0); + AtomRenderPlugin::AtomRenderPlugin() : DockWidgetPlugin() { @@ -74,6 +77,7 @@ namespace EMStudio void AtomRenderPlugin::ReinitRenderer() { m_animViewportWidget->GetAnimViewportRenderer()->Reinit(); + m_animViewportWidget->ResetCameraPosition(); } bool AtomRenderPlugin::Init() @@ -89,10 +93,10 @@ namespace EMStudio verticalLayout->addWidget(m_animViewportWidget); // Register command callbacks. - m_createActorInstanceCallback = new CreateActorInstanceCallback(false); - m_removeActorInstanceCallback = new RemoveActorInstanceCallback(false); - EMStudioManager::GetInstance()->GetCommandManager()->RegisterCommandCallback("CreateActorInstance", m_createActorInstanceCallback); - EMStudioManager::GetInstance()->GetCommandManager()->RegisterCommandCallback("RemoveActorInstance", m_removeActorInstanceCallback); + m_importActorCallback = new ImportActorCallback(false); + m_removeActorCallback = new RemoveActorCallback(false); + EMStudioManager::GetInstance()->GetCommandManager()->RegisterCommandCallback("ImportActor", m_importActorCallback); + EMStudioManager::GetInstance()->GetCommandManager()->RegisterCommandCallback("RemoveActor", m_removeActorCallback); return true; } @@ -113,23 +117,23 @@ namespace EMStudio return true; } - bool AtomRenderPlugin::CreateActorInstanceCallback::Execute( + bool AtomRenderPlugin::ImportActorCallback::Execute( [[maybe_unused]] MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine) { return ReinitAtomRenderPlugin(); } - bool AtomRenderPlugin::CreateActorInstanceCallback::Undo( + bool AtomRenderPlugin::ImportActorCallback::Undo( [[maybe_unused]] MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine) { return ReinitAtomRenderPlugin(); } - bool AtomRenderPlugin::RemoveActorInstanceCallback::Execute( + bool AtomRenderPlugin::RemoveActorCallback::Execute( [[maybe_unused]] MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine) { return ReinitAtomRenderPlugin(); } - bool AtomRenderPlugin::RemoveActorInstanceCallback::Undo( + bool AtomRenderPlugin::RemoveActorCallback::Undo( [[maybe_unused]] MCore::Command* command, [[maybe_unused]] const MCore::CommandLine& commandLine) { return ReinitAtomRenderPlugin(); diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h index 475fd34180..e890f9aa4b 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h @@ -27,6 +27,8 @@ namespace EMStudio : public DockWidgetPlugin { public: + AZ_CLASS_ALLOCATOR_DECL + enum { CLASS_ID = 0x32b0c04d @@ -49,10 +51,10 @@ namespace EMStudio void ReinitRenderer(); private: - MCORE_DEFINECOMMANDCALLBACK(CreateActorInstanceCallback); - MCORE_DEFINECOMMANDCALLBACK(RemoveActorInstanceCallback); - CreateActorInstanceCallback* m_createActorInstanceCallback; - RemoveActorInstanceCallback* m_removeActorInstanceCallback; + MCORE_DEFINECOMMANDCALLBACK(ImportActorCallback); + MCORE_DEFINECOMMANDCALLBACK(RemoveActorCallback); + ImportActorCallback* m_importActorCallback; + RemoveActorCallback* m_removeActorCallback; QWidget* m_innerWidget; AnimViewportWidget* m_animViewportWidget; diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp index 0593575623..be3ac10d45 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp @@ -31,7 +31,6 @@ namespace EMotionFX SetScheduler(MultiThreadScheduler::Create()); // reserve memory - m_actorAssets.reserve(32); m_actorInstances.reserve(1024); m_rootActorInstances.reserve(1024); } @@ -429,7 +428,7 @@ namespace EMotionFX } - ActorManager::ActorAssetData ActorManager::GetActorAsset(size_t nr) const + ActorAssetData ActorManager::GetActorAsset(size_t nr) const { return m_actorAssets[nr]; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h index e8bbf40661..003153b36c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.h @@ -42,7 +42,6 @@ namespace EMotionFX friend class EMotionFXManager; public: - using ActorAssetData = AZ::Data::Asset; static ActorManager* Create(); /** diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.h index 4c530fffdc..59c9f78719 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/Plugins/StandardPlugins/Source/NodeWindow/NodeWindowPlugin.h @@ -90,6 +90,7 @@ namespace EMStudio AZStd::unique_ptr m_actorInfo; AZStd::unique_ptr m_nodeInfo; + // Use this flag to defer the reinit function to main thread. bool m_reinitRequested = false; }; } // namespace EMStudio diff --git a/Gems/EMotionFX/Code/Include/Integration/ActorComponentBus.h b/Gems/EMotionFX/Code/Include/Integration/ActorComponentBus.h index 325191af81..4161b3c77d 100644 --- a/Gems/EMotionFX/Code/Include/Integration/ActorComponentBus.h +++ b/Gems/EMotionFX/Code/Include/Integration/ActorComponentBus.h @@ -98,7 +98,6 @@ namespace EMotionFX // Use this to alter the actor asset. virtual void SetActorAsset(AZ::Data::Asset actorAsset) = 0; - // virtual AZ::Data::Asset GetAsset() const = 0; static const size_t s_invalidJointIndex = std::numeric_limits::max(); }; diff --git a/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h b/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h index c256fa5283..4b13603ed5 100644 --- a/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h +++ b/Gems/EMotionFX/Code/Source/Integration/Assets/ActorAsset.h @@ -80,6 +80,8 @@ namespace EMotionFX const char* GetBrowserIcon() const override; }; } // namespace Integration + + using ActorAssetData = AZ::Data::Asset; } // namespace EMotionFX namespace AZ From 265d3792f07b3f557a1739a8421a5aeaff5e6133 Mon Sep 17 00:00:00 2001 From: rhhong Date: Wed, 6 Oct 2021 22:36:19 -0700 Subject: [PATCH 064/169] fix broken build Signed-off-by: rhhong --- .../Code/Tools/EMStudio/AnimViewportRenderer.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp index 08f85ab1be..ab54b1fa38 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp @@ -163,7 +163,10 @@ namespace EMStudio auto sceneSystem = AzFramework::SceneSystemInterface::Get(); AZ_Assert(sceneSystem, "AtomViewportRenderer was unable to get the scene system during destruction."); bool removeSuccess = sceneSystem->RemoveScene("AnimViewport"); - AZ_Assert(removeSuccess, "AtomViewportRenderer should be removed."); + if (!removeSuccess) + { + AZ_Assert(false, "AtomViewportRenderer should be removed."); + } AZ::RPI::RPISystemInterface::Get()->UnregisterScene(m_scene); m_scene = nullptr; From a448caea7ceca018b045971d60329a3c784b9629 Mon Sep 17 00:00:00 2001 From: rhhong Date: Thu, 7 Oct 2021 08:55:52 -0700 Subject: [PATCH 065/169] fix broken build Signed-off-by: rhhong --- .../EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp index 90f6d54466..b51a90587f 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp @@ -77,7 +77,6 @@ namespace EMStudio void AtomRenderPlugin::ReinitRenderer() { m_animViewportWidget->GetAnimViewportRenderer()->Reinit(); - m_animViewportWidget->ResetCameraPosition(); } bool AtomRenderPlugin::Init() From 4d2f65c4d88fbb1c57a74a06339dce83b8437dc9 Mon Sep 17 00:00:00 2001 From: rhhong Date: Thu, 7 Oct 2021 11:48:09 -0700 Subject: [PATCH 066/169] code review feedback 2 Signed-off-by: rhhong --- .../Code/Tools/EMStudio/AtomRenderPlugin.cpp | 3 +-- .../Code/Tools/EMStudio/AtomRenderPlugin.h | 11 +++++------ Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp | 4 ++-- .../EMStudioSDK/Source/EMStudioManager.h | 2 +- Gems/EMotionFX/Code/Tests/ActorFixture.cpp | 6 +++--- Gems/EMotionFX/Code/Tests/ActorFixture.h | 2 +- 6 files changed, 13 insertions(+), 15 deletions(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp index b51a90587f..91a34e16cd 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.cpp @@ -137,5 +137,4 @@ namespace EMStudio { return ReinitAtomRenderPlugin(); } - -} +}// namespace EMStudio diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h index e890f9aa4b..1516b45e77 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AtomRenderPlugin.h @@ -53,10 +53,9 @@ namespace EMStudio private: MCORE_DEFINECOMMANDCALLBACK(ImportActorCallback); MCORE_DEFINECOMMANDCALLBACK(RemoveActorCallback); - ImportActorCallback* m_importActorCallback; - RemoveActorCallback* m_removeActorCallback; - - QWidget* m_innerWidget; - AnimViewportWidget* m_animViewportWidget; + ImportActorCallback* m_importActorCallback = nullptr; + RemoveActorCallback* m_removeActorCallback = nullptr; + QWidget* m_innerWidget = nullptr; + AnimViewportWidget* m_animViewportWidget = nullptr; }; -} +}// namespace EMStudio diff --git a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp index be3ac10d45..184aac6e2c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Source/ActorManager.cpp @@ -118,9 +118,9 @@ namespace EMotionFX if (FindActorIndex(actorAsset.GetId()) != InvalidIndex) { MCore::LogWarning( - "EMotionFX::ActorManager::RegisterActor() - The actor at location 0x%x has already been registered as actor, most likely " + "EMotionFX::ActorManager::RegisterActor() - The actor %s has already been registered as actor, most likely " "already by the LoadActor of the importer.", - actorAsset->GetActor()); + actorAsset->GetActor()->GetName()); UnlockActors(); return; } diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h index e7a9397b22..4c3139b77a 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/EMStudioManager.h @@ -154,7 +154,7 @@ namespace EMStudio void OnRemoveCommand(size_t historyIndex) override { MCORE_UNUSED(historyIndex); } void OnSetCurrentCommand(size_t index) override { MCORE_UNUSED(index); } }; - EventProcessingCallback* m_eventProcessingCallback; + EventProcessingCallback* m_eventProcessingCallback = nullptr; }; // Shortcuts diff --git a/Gems/EMotionFX/Code/Tests/ActorFixture.cpp b/Gems/EMotionFX/Code/Tests/ActorFixture.cpp index 31c3a0c721..33c26ca11e 100644 --- a/Gems/EMotionFX/Code/Tests/ActorFixture.cpp +++ b/Gems/EMotionFX/Code/Tests/ActorFixture.cpp @@ -28,7 +28,7 @@ namespace EMotionFX AZ::Data::AssetId actorAssetId("{5060227D-B6F4-422E-BF82-41AAC5F228A5}"); m_actorAsset = TestActorAssets::CreateActorAssetAndRegister(actorAssetId); - m_actorInstance = ActorInstance::Create(m_actorAsset->GetActor()); + m_actorInstance = ActorInstance::Create(GetActor()); } void ActorFixture::TearDown() @@ -76,7 +76,7 @@ namespace EMotionFX AZ::ObjectStream::FilterDescriptor loadFilter(nullptr, AZ::ObjectStream::FILTERFLAG_IGNORE_UNKNOWN_CLASSES); SimulatedObjectSetup* setup = AZ::Utils::LoadObjectFromBuffer(data.data(), data.size(), serializeContext, loadFilter); - setup->InitAfterLoad(m_actorAsset->GetActor()); + setup->InitAfterLoad(GetActor()); return setup; } @@ -87,7 +87,7 @@ namespace EMotionFX } - Actor* ActorFixture::GetActor() + Actor* ActorFixture::GetActor() const { return m_actorAsset->GetActor(); } diff --git a/Gems/EMotionFX/Code/Tests/ActorFixture.h b/Gems/EMotionFX/Code/Tests/ActorFixture.h index fad6a2c463..569d55cf47 100644 --- a/Gems/EMotionFX/Code/Tests/ActorFixture.h +++ b/Gems/EMotionFX/Code/Tests/ActorFixture.h @@ -30,7 +30,7 @@ namespace EMotionFX AZStd::vector GetTestJointNames() const; protected: - Actor* GetActor(); + Actor* GetActor() const; AZ::Data::Asset m_actorAsset; ActorInstance* m_actorInstance = nullptr; From 4b92aa34b7edde709ed7c5422043379eb6a42a43 Mon Sep 17 00:00:00 2001 From: rgba16f <82187279+rgba16f@users.noreply.github.com> Date: Thu, 7 Oct 2021 15:24:51 -0500 Subject: [PATCH 067/169] Updated with PR feedback. Created a common function to calculate the number of worker threads. Signed-off-by: rgba16f <82187279+rgba16f@users.noreply.github.com> --- .../AzCore/Jobs/JobManagerComponent.cpp | 7 +++--- .../AzCore/Task/TaskGraphSystemComponent.cpp | 11 +++----- .../AzCore/AzCore/Threading/ThreadUtils.cpp | 25 +++++++++++++++++++ .../AzCore/AzCore/Threading/ThreadUtils.h | 22 ++++++++++++++++ .../AzCore/AzCore/azcore_files.cmake | 2 ++ 5 files changed, 56 insertions(+), 11 deletions(-) create mode 100644 Code/Framework/AzCore/AzCore/Threading/ThreadUtils.cpp create mode 100644 Code/Framework/AzCore/AzCore/Threading/ThreadUtils.h diff --git a/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp b/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp index 59f9c5f6a2..6f5ccc93e4 100644 --- a/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Jobs/JobManagerComponent.cpp @@ -20,6 +20,8 @@ #include +#include + AZ_CVAR(float, cl_jobThreadsConcurrencyRatio, 0.6f, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system multiplier on the number of hw threads the machine creates at initialization"); AZ_CVAR(uint32_t, cl_jobThreadsNumReserved, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system number of hardware threads that are reserved for O3DE system threads"); AZ_CVAR(uint32_t, cl_jobThreadsMinNumber, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "Legacy Job system minimum number of worker threads to create after scaling the number of hw threads"); @@ -54,10 +56,7 @@ namespace AZ int numberOfWorkerThreads = m_numberOfWorkerThreads; if (numberOfWorkerThreads <= 0) // spawn default number of threads { - // calc number of job threads = cl_jobThreadsConcurrencyRatio * (number of hardware threads - cl_jobThreadsNumReserved), - // min = cl_jobThreadsMinNumber, - // max = number of hardware threads - cl_jobThreadsNumReserved - uint32_t scaledHardwareThreads = AZ::GetMax( cl_jobThreadsMinNumber, static_cast(AZStd::floor( 0.5f + AZ::GetClamp(cl_jobThreadsConcurrencyRatio, 0.0f, 1.0f) * static_cast(AZStd::thread::hardware_concurrency() - cl_jobThreadsNumReserved)))); + uint32_t scaledHardwareThreads = Threading::CalcNumWorkerThreads(cl_jobThreadsConcurrencyRatio, cl_jobThreadsMinNumber, cl_jobThreadsNumReserved); numberOfWorkerThreads = AZ::GetMin(static_cast(desc.m_workerThreads.capacity()), scaledHardwareThreads); #if (AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS) numberOfWorkerThreads = AZ::GetMin(numberOfWorkerThreads, AZ_TRAIT_MAX_JOB_MANAGER_WORKER_THREADS); diff --git a/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp b/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp index 5ae0fb0394..56b56e96a1 100644 --- a/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp +++ b/Code/Framework/AzCore/AzCore/Task/TaskGraphSystemComponent.cpp @@ -12,11 +12,12 @@ #include #include #include +#include // Create a cvar as a central location for experimentation with switching from the Job system to TaskGraph system. AZ_CVAR(bool, cl_activateTaskGraph, false, nullptr, AZ::ConsoleFunctorFlags::Null, "Flag clients of TaskGraph to switch between jobs/taskgraph (Note does not disable task graph system)"); AZ_CVAR(float, cl_taskGraphThreadsConcurrencyRatio, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph calculate the number of worker threads to spawn by scaling the number of hw threads, value is clamped between 0.0f and 1.0f"); -AZ_CVAR(uint32_t, cl_taskGraphThreadsNumReserved, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph number of hardware threads that are reserved for O3DE system threads"); +AZ_CVAR(uint32_t, cl_taskGraphThreadsNumReserved, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph number of hardware threads that are reserved for O3DE system threads. Value is clamped between 0 and the number of logical cores in the system"); AZ_CVAR(uint32_t, cl_taskGraphThreadsMinNumber, 2, nullptr, AZ::ConsoleFunctorFlags::Null, "TaskGraph minimum number of worker threads to create after scaling the number of hw threads"); static constexpr uint32_t TaskExecutorServiceCrc = AZ_CRC_CE("TaskExecutorService"); @@ -29,13 +30,9 @@ namespace AZ if (Interface::Get() == nullptr) { - // calc number of worker threads = cl_taskGraphThreadsConcurrencyRatio * (number of hardware threads - cl_taskGraphThreadsNumReserved), - // min = cl_taskGraphThreadsMinNumber, - // max = number of hardware threads - cl_taskGraphThreadsNumReserved - uint32_t scaledHardwareThreads = AZ::GetMax( cl_taskGraphThreadsMinNumber, static_cast(AZStd::floor( 0.5f + AZ::GetClamp(cl_taskGraphThreadsConcurrencyRatio, 0.0f, 1.0f) * static_cast(AZStd::thread::hardware_concurrency() - cl_taskGraphThreadsNumReserved)))); - m_taskExecutor = aznew TaskExecutor(scaledHardwareThreads); + Interface::Register(this); // small window that another thread can try to use taskgraph between this line and the set instance. + m_taskExecutor = aznew TaskExecutor(Threading::CalcNumWorkerThreads(cl_taskGraphThreadsConcurrencyRatio, cl_taskGraphThreadsMinNumber, cl_taskGraphThreadsNumReserved)); TaskExecutor::SetInstance(m_taskExecutor); - Interface::Register(this); } } diff --git a/Code/Framework/AzCore/AzCore/Threading/ThreadUtils.cpp b/Code/Framework/AzCore/AzCore/Threading/ThreadUtils.cpp new file mode 100644 index 0000000000..93eba9cc3f --- /dev/null +++ b/Code/Framework/AzCore/AzCore/Threading/ThreadUtils.cpp @@ -0,0 +1,25 @@ +/* + * 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::Threading +{ + uint32_t CalcNumWorkerThreads(float workerThreadsRatio, uint32_t minNumWorkerThreads, uint32_t reservedNumThreads) + { + const uint32_t maxHardwareThreads = AZStd::thread::hardware_concurrency(); + const uint32_t numReservedThreads = AZ::GetMin(reservedNumThreads, maxHardwareThreads); // protect against num reserved being bigger than the number of hw threads + const uint32_t maxWorkerThreads = maxHardwareThreads - numReservedThreads; + const float requestedWorkerThreads = AZ::GetClamp(workerThreadsRatio, 0.0f, 1.0f) * static_cast(maxWorkerThreads); + const uint32_t requestedWorkerThreadsRounded = AZStd::lround(requestedWorkerThreads); + const uint32_t numWorkerThreads = AZ::GetMax(minNumWorkerThreads, requestedWorkerThreadsRounded); + return numWorkerThreads; + } +}; diff --git a/Code/Framework/AzCore/AzCore/Threading/ThreadUtils.h b/Code/Framework/AzCore/AzCore/Threading/ThreadUtils.h new file mode 100644 index 0000000000..505d900289 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/Threading/ThreadUtils.h @@ -0,0 +1,22 @@ +/* + * 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::Threading +{ + //! Calculates the number of worker threads a system should use based on the number of hardware threads a device has. + //! result = max (minNumWorkerThreads, workerThreadsRatio * (num_hardware_threads - reservedNumThreads)) + //! @param workerThreadsRatio scale applied to the calculated maximum number of threads available after reserved threads have been accounted for. Clamped between 0 and 1. + //! @param minNumWorkerThreads minimum value that will be returned. Value is unclamped and can be more than num_hardware_threads. + //! @param reservedNumThreads number of hardware threads to reserve for O3DE system threads. Value clamped to num_hardware_threads. + //! @return number of worker threads for the calling system to allocate + uint32_t CalcNumWorkerThreads(float workerThreadsRatio, uint32_t minNumWorkerThreads, uint32_t reservedNumThreads); +}; diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index 14579cbf33..010c748402 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -639,6 +639,8 @@ set(FILES Threading/ThreadSafeDeque.inl Threading/ThreadSafeObject.h Threading/ThreadSafeObject.inl + Threading/ThreadUtils.h + Threading/ThreadUtils.cpp Time/ITime.h Time/TimeSystemComponent.cpp Time/TimeSystemComponent.h From 38efd581738e7a8789734f6122cff1a3e2c93496 Mon Sep 17 00:00:00 2001 From: rhhong Date: Thu, 7 Oct 2021 14:54:30 -0700 Subject: [PATCH 068/169] Fix merging issue with camera input Signed-off-by: rhhong --- .../Code/Tools/EMStudio/AnimViewportWidget.cpp | 16 ++++++++-------- .../Code/Tools/EMStudio/AnimViewportWidget.h | 6 +++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp index d3fd719d38..6a6c9df901 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.cpp @@ -38,17 +38,17 @@ namespace EMStudio void AnimViewportWidget::SetupCameras() { - m_pivotRotateCamera = AZStd::make_shared(EMStudio::ViewportUtil::BuildRotateCameraInputId()); + m_rotateCamera = AZStd::make_shared(EMStudio::ViewportUtil::BuildRotateCameraInputId()); const auto translateCameraInputChannelIds = EMStudio::ViewportUtil::BuildTranslateCameraInputChannelIds(); - m_pivotTranslateCamera = AZStd::make_shared( - translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslatePivot); - m_pivotTranslateCamera.get()->m_translateSpeedFn = [] + m_translateCamera = AZStd::make_shared( + translateCameraInputChannelIds, AzFramework::LookTranslation, AzFramework::TranslatePivotLook); + m_translateCamera.get()->m_translateSpeedFn = [] { return 3.0f; }; - m_pivotDollyScrollCamera = AZStd::make_shared(); + m_orbitDollyScrollCamera = AZStd::make_shared(); } void AnimViewportWidget::SetupCameraController() @@ -94,9 +94,9 @@ namespace EMStudio controller->SetCameraListBuilderCallback( [this](AzFramework::Cameras& cameras) { - cameras.AddCamera(m_pivotRotateCamera); - cameras.AddCamera(m_pivotTranslateCamera); - cameras.AddCamera(m_pivotDollyScrollCamera); + cameras.AddCamera(m_rotateCamera); + cameras.AddCamera(m_translateCamera); + cameras.AddCamera(m_orbitDollyScrollCamera); }); GetControllerList()->Add(controller); } diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h index 70b4e1e667..7c2e085f84 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportWidget.h @@ -26,8 +26,8 @@ namespace EMStudio void SetupCameraController(); AZStd::unique_ptr m_renderer; - AZStd::shared_ptr m_pivotRotateCamera; - AZStd::shared_ptr m_pivotTranslateCamera; - AZStd::shared_ptr m_pivotDollyScrollCamera; + AZStd::shared_ptr m_rotateCamera; + AZStd::shared_ptr m_translateCamera; + AZStd::shared_ptr m_orbitDollyScrollCamera; }; } From 437a4d2d63c2af67ba9148b09341e9a0c950bec0 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Thu, 7 Oct 2021 17:38:54 -0500 Subject: [PATCH 069/169] Updated engine template unit tests. Signed-off-by: Chris Galvan --- .../o3de/tests/unit_test_engine_template.py | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/scripts/o3de/tests/unit_test_engine_template.py b/scripts/o3de/tests/unit_test_engine_template.py index 16ac24d74c..ed1c8258d3 100755 --- a/scripts/o3de/tests/unit_test_engine_template.py +++ b/scripts/o3de/tests/unit_test_engine_template.py @@ -31,17 +31,17 @@ TEST_TEMPLATED_CONTENT_WITHOUT_LICENSE = """ #include #include -namespace ${Name} +namespace ${SanitizedCppName} { - class ${Name}Requests + class ${SanitizedCppName}Requests { public: - AZ_RTTI(${Name}Requests, "{${Random_Uuid}}"); - virtual ~${Name}Requests() = default; + AZ_RTTI(${SanitizedCppName}Requests, "{${Random_Uuid}}"); + virtual ~${SanitizedCppName}Requests() = default; // Put your public methods here }; - class ${Name}BusTraits + class ${SanitizedCppName}BusTraits : public AZ::EBusTraits { public: @@ -52,31 +52,31 @@ namespace ${Name} ////////////////////////////////////////////////////////////////////////// }; - using ${Name}RequestBus = AZ::EBus<${Name}Requests, ${Name}BusTraits>; - using ${Name}Interface = AZ::Interface<${Name}Requests>; + using ${SanitizedCppName}RequestBus = AZ::EBus<${SanitizedCppName}Requests, ${SanitizedCppName}BusTraits>; + using ${SanitizedCppName}Interface = AZ::Interface<${SanitizedCppName}Requests>; -} // namespace ${Name} +} // namespace ${SanitizedCppName} """ TEST_TEMPLATED_CONTENT_WITH_LICENSE = CPP_LICENSE_TEXT + TEST_TEMPLATED_CONTENT_WITHOUT_LICENSE TEST_CONCRETE_TESTTEMPLATE_CONTENT_WITHOUT_LICENSE = string.Template( - TEST_TEMPLATED_CONTENT_WITHOUT_LICENSE).safe_substitute({'Name': "TestTemplate"}) + TEST_TEMPLATED_CONTENT_WITHOUT_LICENSE).safe_substitute({'SanitizedCppName': "TestTemplate"}) TEST_CONCRETE_TESTTEMPLATE_CONTENT_WITH_LICENSE = string.Template( - TEST_TEMPLATED_CONTENT_WITH_LICENSE).safe_substitute({'Name': "TestTemplate"}) + TEST_TEMPLATED_CONTENT_WITH_LICENSE).safe_substitute({'SanitizedCppName': "TestTemplate"}) TEST_CONCRETE_TESTPROJECT_TEMPLATE_CONTENT_WITHOUT_LICENSE = string.Template( - TEST_TEMPLATED_CONTENT_WITHOUT_LICENSE).safe_substitute({'Name': "TestProject"}) + TEST_TEMPLATED_CONTENT_WITHOUT_LICENSE).safe_substitute({'SanitizedCppName': "TestProject"}) TEST_CONCRETE_TESTPROJECT_TEMPLATE_CONTENT_WITH_LICENSE = string.Template( - TEST_TEMPLATED_CONTENT_WITH_LICENSE).safe_substitute({'Name': "TestProject"}) + TEST_TEMPLATED_CONTENT_WITH_LICENSE).safe_substitute({'SanitizedCppName': "TestProject"}) TEST_CONCRETE_TESTGEM_TEMPLATE_CONTENT_WITHOUT_LICENSE = string.Template( - TEST_TEMPLATED_CONTENT_WITHOUT_LICENSE).safe_substitute({'Name': "TestGem"}) + TEST_TEMPLATED_CONTENT_WITHOUT_LICENSE).safe_substitute({'SanitizedCppName': "TestGem"}) TEST_CONCRETE_TESTGEM_TEMPLATE_CONTENT_WITH_LICENSE = string.Template( - TEST_TEMPLATED_CONTENT_WITH_LICENSE).safe_substitute({'Name': "TestGem"}) + TEST_TEMPLATED_CONTENT_WITH_LICENSE).safe_substitute({'SanitizedCppName': "TestGem"}) TEST_TEMPLATE_JSON_CONTENTS = """\ { From e64b9d3536ccdbb9bcbbda8228522c940c91784b Mon Sep 17 00:00:00 2001 From: Qing Tao <55564570+VickyAtAZ@users.noreply.github.com> Date: Thu, 7 Oct 2021 16:23:13 -0700 Subject: [PATCH 070/169] ATOM-16320 Remove PVRTC and ETC compressor (#4557) Signed-off-by: Qing Tao --- .../AzToolsFramework/Tests/LogLines.cpp | 2 +- .../ImageProcessingAtom/Code/CMakeLists.txt | 3 - .../Atom/ImageProcessing/PixelFormats.h | 12 +- .../Source/BuilderSettings/PresetSettings.cpp | 7 - .../Code/Source/Compressors/Compressor.cpp | 22 - .../Code/Source/Compressors/ETC2.cpp | 233 --------- .../Code/Source/Compressors/ETC2.h | 31 -- .../Code/Source/Compressors/PVRTC.cpp | 338 ------------- .../Code/Source/Compressors/PVRTC.h | 30 -- .../Code/Source/Editor/PresetInfoPopup.cpp | 1 - .../Code/Source/ImageLoader/DdsLoader.cpp | 443 +----------------- .../Code/Source/ImageLoader/ImageLoaders.h | 5 - .../Source/Platform/Mac/platform_mac.cmake | 5 - .../Code/Source/Processing/DDSHeader.h | 14 +- .../Source/Processing/PixelFormatInfo.cpp | 58 --- .../Code/Source/Processing/PixelFormatInfo.h | 8 - .../Code/Source/Processing/Utils.cpp | 42 -- .../Code/Tests/ImageProcessing_Test.cpp | 142 +----- .../Code/imageprocessing_files.cmake | 4 - .../Code/Source/Editor/AtlasBuilderWorker.cpp | 4 +- .../Linux/BuiltInPackages_linux.cmake | 2 - .../Platform/Mac/BuiltInPackages_mac.cmake | 2 - .../Windows/BuiltInPackages_windows.cmake | 2 - 23 files changed, 12 insertions(+), 1398 deletions(-) delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ETC2.cpp delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ETC2.h delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/PVRTC.cpp delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/PVRTC.h diff --git a/Code/Framework/AzToolsFramework/Tests/LogLines.cpp b/Code/Framework/AzToolsFramework/Tests/LogLines.cpp index 5af6513720..1c69e855ee 100644 --- a/Code/Framework/AzToolsFramework/Tests/LogLines.cpp +++ b/Code/Framework/AzToolsFramework/Tests/LogLines.cpp @@ -25,7 +25,7 @@ namespace UnitTest R"X(Executing RC.EXE: '"E:\lyengine\dev\windows\bin\profile\rc.exe" "E:/Directory/File.tga")X", R"X(Executing RC.EXE with working directory : '')X", R"X(ResourceCompiler 64 - bit DEBUG)X", - R"X(Platform support : PC, PowerVR, etc2Comp)X", + R"X(Platform support : PC, PowerVR)X", R"X(Version 1.1.8.6 Nov 5 2018 13 : 28 : 28)X" }; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt b/Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt index 1463124e27..836f173632 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt @@ -63,13 +63,10 @@ ly_add_target( 3rdParty::Qt::Widgets 3rdParty::Qt::Gui 3rdParty::astc-encoder - 3rdParty::etc2comp - 3rdParty::PVRTexTool 3rdParty::squish-ccr 3rdParty::tiff 3rdParty::ISPCTexComp 3rdParty::ilmbase - Legacy::CryCommon AZ::AzFramework AZ::AzToolsFramework AZ::AzQtComponents diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Include/Atom/ImageProcessing/PixelFormats.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Include/Atom/ImageProcessing/PixelFormats.h index fbde69abb2..4da996dbde 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Include/Atom/ImageProcessing/PixelFormats.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Include/Atom/ImageProcessing/PixelFormats.h @@ -39,16 +39,7 @@ namespace ImageProcessingAtom ePixelFormat_ASTC_10x8, ePixelFormat_ASTC_10x10, ePixelFormat_ASTC_12x10, - ePixelFormat_ASTC_12x12, - //Formats supported by PowerVR GPU. Mainly for ios devices. - ePixelFormat_PVRTC2, //2bpp - ePixelFormat_PVRTC4, //4bpp - //formats for opengl and opengles 3.0 (android devices) - ePixelFormat_EAC_R11, //one channel unsigned data - ePixelFormat_EAC_RG11, //two channel unsigned data - ePixelFormat_ETC2, //Compresses RGB888 data, it taks 4x4 groups of pixel data and compresses each into a 64-bit - ePixelFormat_ETC2a1, //Compresses RGB888A1 data, it taks 4x4 groups of pixel data and compresses each into a 64-bit - ePixelFormat_ETC2a, //Compresses RGBA8888 data with full alpha support + ePixelFormat_ASTC_12x12, // Standardized Compressed DXGI Formats (DX10+) // Data in these compressed formats is hardware decodable on all DX10 chips, and manageable with the DX10-API. @@ -88,7 +79,6 @@ namespace ImageProcessingAtom }; bool IsASTCFormat(EPixelFormat fmt); - bool IsETCFormat(EPixelFormat fmt); } // namespace ImageProcessingAtom namespace AZ diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.cpp index 7ffabc45a9..3812b86026 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.cpp @@ -109,13 +109,6 @@ namespace ImageProcessingAtom ->Value("ASTC_10x10", EPixelFormat::ePixelFormat_ASTC_10x10) ->Value("ASTC_12x10", EPixelFormat::ePixelFormat_ASTC_12x10) ->Value("ASTC_12x12", EPixelFormat::ePixelFormat_ASTC_12x12) - ->Value("PVRTC2", EPixelFormat::ePixelFormat_PVRTC2) - ->Value("PVRTC4", EPixelFormat::ePixelFormat_PVRTC4) - ->Value("EAC_R11", EPixelFormat::ePixelFormat_EAC_R11) - ->Value("EAC_RG11", EPixelFormat::ePixelFormat_EAC_RG11) - ->Value("ETC2", EPixelFormat::ePixelFormat_ETC2) - ->Value("ETC2a1", EPixelFormat::ePixelFormat_ETC2a1) - ->Value("ETC2a", EPixelFormat::ePixelFormat_ETC2a) ->Value("BC1", EPixelFormat::ePixelFormat_BC1) ->Value("BC1a", EPixelFormat::ePixelFormat_BC1a) ->Value("BC3", EPixelFormat::ePixelFormat_BC3) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/Compressor.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/Compressor.cpp index 1dd18faaf3..ac5340eaab 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/Compressor.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/Compressor.cpp @@ -10,8 +10,6 @@ #include #include #include -#include -#include #include namespace ImageProcessingAtom @@ -42,26 +40,6 @@ namespace ImageProcessingAtom } } - // Both ETC2Compressor and PVRTCCompressor can process ETC formats - // According to Mobile team, Etc2Com is faster than PVRTexLib, so we check with ETC2Compressor before PVRTCCompressor - // Note: with the test I have done, I found out it cost similar time for both Etc2Com and PVRTexLib to compress - // a 2048x2048 test texture to EAC_R11 and EAC_RG11. It was around 7 minutes for EAC_R11 and 14 minutes for EAC_RG11 - if (ETC2Compressor::IsCompressedPixelFormatSupported(fmt)) - { - if (isCompressing || (!isCompressing && ETC2Compressor::DoesSupportDecompress(fmt))) - { - return ICompressorPtr(new ETC2Compressor()); - } - } - - if (PVRTCCompressor::IsCompressedPixelFormatSupported(fmt)) - { - if (isCompressing || (!isCompressing && PVRTCCompressor::DoesSupportDecompress(fmt))) - { - return ICompressorPtr(new PVRTCCompressor()); - } - } - return nullptr; } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ETC2.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ETC2.cpp deleted file mode 100644 index 73108d5502..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ETC2.cpp +++ /dev/null @@ -1,233 +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 -#include -#include - -namespace ImageProcessingAtom -{ - //limited to 1 thread because AP requires so. We may change to n when AP allocate n thread to a job in the furture - static const int MAX_COMP_JOBS = 1; - static const int MIN_COMP_JOBS = 1; - static const float ETC_LOW_EFFORT_LEVEL = 25.0f; - static const float ETC_MED_EFFORT_LEVEL = 40.0f; - static const float ETC_HIGH_EFFORT_LEVEL = 80.0f; - - //Grab the Etc2Comp specific pixel format enum - static Etc::Image::Format FindEtc2PixelFormat(EPixelFormat fmt) - { - switch (fmt) - { - case ePixelFormat_EAC_RG11: - return Etc::Image::Format::RG11; - case ePixelFormat_EAC_R11: - return Etc::Image::Format::R11; - case ePixelFormat_ETC2: - return Etc::Image::Format::RGB8; - case ePixelFormat_ETC2a1: - return Etc::Image::Format::RGB8A1; - case ePixelFormat_ETC2a: - return Etc::Image::Format::RGBA8; - default: - return Etc::Image::Format::FORMATS; - } - } - - //Get the errmetric required for the compression - static Etc::ErrorMetric FindErrMetric(Etc::Image::Format fmt) - { - switch (fmt) - { - case Etc::Image::Format::RG11: - return Etc::ErrorMetric::NORMALXYZ; - case Etc::Image::Format::R11: - return Etc::ErrorMetric::NUMERIC; - case Etc::Image::Format::RGB8: - return Etc::ErrorMetric::RGBX; - case Etc::Image::Format::RGBA8: - case Etc::Image::Format::RGB8A1: - return Etc::ErrorMetric::RGBA; - default: - return Etc::ErrorMetric::ERROR_METRICS; - } - } - - //Convert to sRGB format - static Etc::Image::Format FindGammaEtc2PixelFormat(Etc::Image::Format fmt) - { - switch (fmt) - { - case Etc::Image::Format::RGB8: - return Etc::Image::Format::SRGB8; - case Etc::Image::Format::RGBA8: - return Etc::Image::Format::SRGBA8; - case Etc::Image::Format::RGB8A1: - return Etc::Image::Format::SRGB8A1; - default: - return Etc::Image::Format::FORMATS; - } - } - - bool ETC2Compressor::IsCompressedPixelFormatSupported(EPixelFormat fmt) - { - return (FindEtc2PixelFormat(fmt) != Etc::Image::Format::FORMATS); - } - - bool ETC2Compressor::IsUncompressedPixelFormatSupported(EPixelFormat fmt) - { - //for uncompress format - if (fmt == ePixelFormat_R8G8B8A8) - { - return true; - } - return false; - } - - EPixelFormat ETC2Compressor::GetSuggestedUncompressedFormat([[maybe_unused]] EPixelFormat compressedfmt, [[maybe_unused]] EPixelFormat uncompressedfmt) const - { - return ePixelFormat_R8G8B8A8; - } - - bool ETC2Compressor::DoesSupportDecompress([[maybe_unused]] EPixelFormat fmtDst) - { - return false; - } - - ColorSpace ETC2Compressor::GetSupportedColorSpace([[maybe_unused]] EPixelFormat compressFormat) const - { - return ColorSpace::autoSelect; - } - - const char* ETC2Compressor::GetName() const - { - return "ETC2Compressor"; - } - - IImageObjectPtr ETC2Compressor::CompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst, - const CompressOption* compressOption) const - { - //validate input - EPixelFormat fmtSrc = srcImage->GetPixelFormat(); - - //src format need to be uncompressed and dst format need to compressed. - if (!IsUncompressedPixelFormatSupported(fmtSrc) || !IsCompressedPixelFormatSupported(fmtDst)) - { - return nullptr; - } - - IImageObjectPtr dstImage(srcImage->AllocateImage(fmtDst)); - - //determinate compression quality - ICompressor::EQuality quality = ICompressor::eQuality_Normal; - //get setting from compression option - if (compressOption) - { - quality = compressOption->compressQuality; - } - - float qualityEffort = 0.0f; - switch (quality) - { - case eQuality_Preview: - case eQuality_Fast: - { - qualityEffort = ETC_LOW_EFFORT_LEVEL; - break; - } - case eQuality_Normal: - { - qualityEffort = ETC_MED_EFFORT_LEVEL; - break; - } - default: - { - qualityEffort = ETC_HIGH_EFFORT_LEVEL; - } - } - - Etc::Image::Format dstEtc2Format = FindEtc2PixelFormat(fmtDst); - if (srcImage->GetImageFlags() & EIF_SRGBRead) - { - dstEtc2Format = FindGammaEtc2PixelFormat(dstEtc2Format); - } - - //use to read pixel data from src image - IPixelOperationPtr pixelOp = CreatePixelOperation(fmtSrc); - //get count of bytes per pixel for images - AZ::u32 pixelBytes = CPixelFormats::GetInstance().GetPixelFormatInfo(fmtSrc)->bitsPerBlock / 8; - - const AZ::u32 mipCount = dstImage->GetMipCount(); - for (AZ::u32 mip = 0; mip < mipCount; ++mip) - { - const AZ::u32 width = srcImage->GetWidth(mip); - const AZ::u32 height = srcImage->GetHeight(mip); - - // Prepare source data - AZ::u8* srcMem; - AZ::u32 srcPitch; - srcImage->GetImagePointer(mip, srcMem, srcPitch); - const AZ::u32 pixelCount = srcImage->GetPixelCount(mip); - - Etc::ColorFloatRGBA* rgbaPixels = new Etc::ColorFloatRGBA[pixelCount]; - Etc::ColorFloatRGBA* rgbaPixelPtr = rgbaPixels; - float r, g, b, a; - for (AZ::u32 pixelIdx = 0; pixelIdx < pixelCount; pixelIdx++, srcMem += pixelBytes, rgbaPixelPtr++) - { - pixelOp->GetRGBA(srcMem, r, g, b, a); - rgbaPixelPtr->fA = a; - rgbaPixelPtr->fR = r; - rgbaPixelPtr->fG = g; - rgbaPixelPtr->fB = b; - } - - //Call into etc2Comp lib to compress. https://medium.com/@duhroach/building-a-blazing-fast-etc2-compressor-307f3e9aad99 - Etc::ErrorMetric errMetric = FindErrMetric(dstEtc2Format); - unsigned char* paucEncodingBits; - unsigned int uiEncodingBitsBytes; - unsigned int uiExtendedWidth; - unsigned int uiExtendedHeight; - int iEncodingTime_ms; - - Etc::Encode(reinterpret_cast(rgbaPixels), - width, height, - dstEtc2Format, - errMetric, - qualityEffort, - MIN_COMP_JOBS, - MAX_COMP_JOBS, - &paucEncodingBits, &uiEncodingBitsBytes, - &uiExtendedWidth, &uiExtendedHeight, - &iEncodingTime_ms); - - AZ::u8* dstMem; - AZ::u32 dstPitch; - dstImage->GetImagePointer(mip, dstMem, dstPitch); - - memcpy(dstMem, paucEncodingBits, uiEncodingBitsBytes); - delete[] rgbaPixels; - } - - return dstImage; - } - - IImageObjectPtr ETC2Compressor::DecompressImage(IImageObjectPtr srcImage, [[maybe_unused]] EPixelFormat fmtDst) const - { - //etc2Comp doesn't support decompression - //Since PVRTexLib support ETC formats too. It may take over the decompression. - return nullptr; - } -} // namespace ImageProcessingAtom diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ETC2.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ETC2.h deleted file mode 100644 index 9ab5a164a5..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/ETC2.h +++ /dev/null @@ -1,31 +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 - -namespace ImageProcessingAtom -{ - class ETC2Compressor - : public ICompressor - { - public: - static bool IsCompressedPixelFormatSupported(EPixelFormat fmt); - static bool IsUncompressedPixelFormatSupported(EPixelFormat fmt); - static bool DoesSupportDecompress(EPixelFormat fmtDst); - - IImageObjectPtr CompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst, const CompressOption* compressOption) const override; - IImageObjectPtr DecompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst) const override; - - EPixelFormat GetSuggestedUncompressedFormat(EPixelFormat compressedfmt, EPixelFormat uncompressedfmt) const override; - ColorSpace GetSupportedColorSpace(EPixelFormat compressFormat) const final; - const char* GetName() const final; - - }; -} // namespace ImageProcessingAtom diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/PVRTC.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/PVRTC.cpp deleted file mode 100644 index f3a630e8c1..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/PVRTC.cpp +++ /dev/null @@ -1,338 +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 -#include - - -namespace ImageProcessingAtom -{ - // Note: PVRTexLib supports ETC formats, PVRTC formats and BC formats - // We haven't tested the performace to compress BC formats compare to CTSquisher - // For PVRTC formats, we only added PVRTC 1 support for now - // The compression for ePVRTPF_EAC_R11 and ePVRTPF_EAC_RG11 are very slow. It takes 7 and 14 minutes for a 2048x2048 texture. - EPVRTPixelFormat FindPvrPixelFormat(EPixelFormat fmt) - { - switch (fmt) - { - case ePixelFormat_PVRTC2: - return ePVRTPF_PVRTCI_2bpp_RGBA; - case ePixelFormat_PVRTC4: - return ePVRTPF_PVRTCI_4bpp_RGBA; - case ePixelFormat_EAC_R11: - return ePVRTPF_EAC_R11; - case ePixelFormat_EAC_RG11: - return ePVRTPF_EAC_RG11; - case ePixelFormat_ETC2: - return ePVRTPF_ETC2_RGB; - case ePixelFormat_ETC2a1: - return ePVRTPF_ETC2_RGB_A1; - case ePixelFormat_ETC2a: - return ePVRTPF_ETC2_RGBA; - default: - return ePVRTPF_NumCompressedPFs; - } - } - - bool PVRTCCompressor::IsCompressedPixelFormatSupported(EPixelFormat fmt) - { - return (FindPvrPixelFormat(fmt) != ePVRTPF_NumCompressedPFs); - } - - bool PVRTCCompressor::IsUncompressedPixelFormatSupported(EPixelFormat fmt) - { - //for uncompress format - if (fmt == ePixelFormat_R8G8B8A8) - { - return true; - } - return false; - } - - EPixelFormat PVRTCCompressor::GetSuggestedUncompressedFormat([[maybe_unused]] EPixelFormat compressedfmt, [[maybe_unused]] EPixelFormat uncompressedfmt) const - { - return ePixelFormat_R8G8B8A8; - } - - ColorSpace PVRTCCompressor::GetSupportedColorSpace([[maybe_unused]] EPixelFormat compressFormat) const - { - return ColorSpace::autoSelect; - } - - const char* PVRTCCompressor::GetName() const - { - return "PVRTCCompressor"; - } - - bool PVRTCCompressor::DoesSupportDecompress([[maybe_unused]] EPixelFormat fmtDst) - { - return true; - } - - IImageObjectPtr PVRTCCompressor::CompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst, - const CompressOption* compressOption) const - { - //validate input - EPixelFormat fmtSrc = srcImage->GetPixelFormat(); - - //src format need to be uncompressed and dst format need to compressed. - if (!IsUncompressedPixelFormatSupported(fmtSrc) || !IsCompressedPixelFormatSupported(fmtDst)) - { - return nullptr; - } - - IImageObjectPtr dstImage(srcImage->AllocateImage(fmtDst)); - - //determinate compression quality - pvrtexture::ECompressorQuality internalQuality = pvrtexture::eETCFast; - ICompressor::EQuality quality = ICompressor::eQuality_Normal; - AZ::Vector3 uniformWeights = AZ::Vector3(0.3333f, 0.3334f, 0.3333f); - AZ::Vector3 weights = uniformWeights; - bool isUniform = true; - //get setting from compression option - if (compressOption) - { - quality = compressOption->compressQuality; - weights = compressOption->rgbWeight; - isUniform = (weights == uniformWeights); - } - - if (IsETCFormat(fmtDst)) - { - if ((quality <= eQuality_Normal) && isUniform) - { - internalQuality = pvrtexture::eETCFast; - } - else if (quality <= eQuality_Normal) - { - internalQuality = pvrtexture::eETCNormal; - } - else if (isUniform) - { - internalQuality = pvrtexture::eETCSlow; - } - else - { - internalQuality = pvrtexture::eETCSlow; - } - } - else - { - if (quality == eQuality_Preview) - { - internalQuality = pvrtexture::ePVRTCFastest; - } - else if (quality == eQuality_Fast) - { - internalQuality = pvrtexture::ePVRTCFast; - } - else if (quality == eQuality_Normal) - { - internalQuality = pvrtexture::ePVRTCNormal; - } - else - { - internalQuality = pvrtexture::ePVRTCHigh; - } - } - - // setup color space - EPVRTColourSpace cspace = ePVRTCSpacelRGB; - if (srcImage->GetImageFlags() & EIF_SRGBRead) - { - cspace = ePVRTCSpacesRGB; - } - - //setup src texture for compression - const pvrtexture::PixelType srcPixelType('r', 'g', 'b', 'a', 8, 8, 8, 8); - const AZ::u32 dstMips = dstImage->GetMipCount(); - for (AZ::u32 mip = 0; mip < dstMips; ++mip) - { - const AZ::u32 width = srcImage->GetWidth(mip); - const AZ::u32 height = srcImage->GetHeight(mip); - - // Prepare source data - AZ::u8* srcMem; - uint32 srcPitch; - srcImage->GetImagePointer(mip, srcMem, srcPitch); - - const pvrtexture::CPVRTextureHeader srcHeader( - srcPixelType.PixelTypeID, // AZ::u64 u64PixelFormat, - width, // uint32 u32Height=1, - height, // uint32 u32Width=1, - 1, // uint32 u32Depth=1, - 1, // uint32 u32NumMipMaps=1, - 1, // uint32 u32NumArrayMembers=1, - 1, // uint32 u32NumFaces=1, - cspace, // EPVRTColourSpace eColourSpace=ePVRTCSpacelRGB, - ePVRTVarTypeUnsignedByteNorm, // EPVRTVariableType eChannelType=ePVRTVarTypeUnsignedByteNorm, - false); // bool bPreMultiplied=false); - - pvrtexture::CPVRTexture compressTexture(srcHeader, srcMem); - - //compressing - bool isSuccess = false; -#if AZ_TRAIT_IMAGEPROCESSING_SUPPORT_TRY_CATCH - try -#endif // AZ_TRAIT_IMAGEPROCESSING_SUPPORT_TRY_CATCH - { - isSuccess = pvrtexture::Transcode( - compressTexture, - pvrtexture::PixelType(FindPvrPixelFormat(fmtDst)), - ePVRTVarTypeUnsignedByteNorm, - cspace, - internalQuality); - } -#if AZ_TRAIT_IMAGEPROCESSING_SUPPORT_TRY_CATCH - catch (...) - { - AZ_Error("Image Processing", false, "Unknown exception in PVRTexLib"); - return nullptr; - } -#endif // AZ_TRAIT_IMAGEPROCESSING_SUPPORT_TRY_CATCH - - if (!isSuccess) - { - AZ_Error("Image Processing", false, "Failed to compress image with PVRTexLib."); - return nullptr; - } - - // Getting compressed data - const void* const compressedData = compressTexture.getDataPtr(); - if (!compressedData) - { - AZ_Error("Image Processing", false, "Failed to obtain compressed image data by using PVRTexLib"); - return nullptr; - } - - const AZ::u32 compressedDataSize = compressTexture.getDataSize(); - if (dstImage->GetMipBufSize(mip) != compressedDataSize) - { - AZ_Error("Image Processing", false, "Compressed image data size mismatch while using PVRTexLib"); - return nullptr; - } - - //save compressed data to dst image - AZ::u8* dstMem; - AZ::u32 dstPitch; - dstImage->GetImagePointer(mip, dstMem, dstPitch); - memcpy(dstMem, compressedData, compressedDataSize); - } - - return dstImage; - } - - IImageObjectPtr PVRTCCompressor::DecompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst) const - { - //validate input - EPixelFormat fmtSrc = srcImage->GetPixelFormat(); //compressed - - if (!IsCompressedPixelFormatSupported(fmtSrc) || !IsUncompressedPixelFormatSupported(fmtDst)) - { - return nullptr; - } - - EPVRTColourSpace colorSpace = ePVRTCSpacelRGB; - if (srcImage->GetImageFlags() & EIF_SRGBRead) - { - colorSpace = ePVRTCSpacesRGB; - } - - IImageObjectPtr dstImage(srcImage->AllocateImage(fmtDst)); - - const AZ::u32 mipCount = dstImage->GetMipCount(); - for (AZ::u32 mip = 0; mip < mipCount; ++mip) - { - const AZ::u32 width = srcImage->GetWidth(mip); - const AZ::u32 height = srcImage->GetHeight(mip); - - // Preparing source compressed data - const pvrtexture::CPVRTextureHeader compressedHeader( - FindPvrPixelFormat(fmtSrc), // AZ::u64 u64PixelFormat, - width, // uint32 u32Height=1, - height, // uint32 u32Width=1, - 1, // uint32 u32Depth=1, - 1, // uint32 u32NumMipMaps=1, - 1, // uint32 u32NumArrayMembers=1, - 1, // uint32 u32NumFaces=1, - colorSpace, // EPVRTColourSpace eColourSpace=ePVRTCSpacelRGB, - ePVRTVarTypeUnsignedByteNorm, // EPVRTVariableType eChannelType=ePVRTVarTypeUnsignedByteNorm, - false); // bool bPreMultiplied=false); - - const AZ::u32 compressedDataSize = compressedHeader.getDataSize(); - if (srcImage->GetMipBufSize(mip) != compressedDataSize) - { - AZ_Error("Image Processing", false, "Decompressed image data size mismatch while using PVRTexLib"); - return nullptr; - } - - AZ::u8* srcMem; - AZ::u32 srcPitch; - srcImage->GetImagePointer(mip, srcMem, srcPitch); - pvrtexture::CPVRTexture cTexture(compressedHeader, srcMem); - - // Decompress - bool bOk = false; -#if AZ_TRAIT_IMAGEPROCESSING_SUPPORT_TRY_CATCH - try - { -#endif // AZ_TRAIT_IMAGEPROCESSING_SUPPORT_TRY_CATCH - bOk = pvrtexture::Transcode( - cTexture, - pvrtexture::PVRStandard8PixelType, - ePVRTVarTypeUnsignedByteNorm, - colorSpace, - pvrtexture::ePVRTCHigh); - -#if AZ_TRAIT_IMAGEPROCESSING_SUPPORT_TRY_CATCH - } - catch (...) - { - AZ_Error("Image Processing", false, "Unknown exception in PVRTexLib when decompressing"); - return nullptr; - } -#endif // AZ_TRAIT_IMAGEPROCESSING_SUPPORT_TRY_CATCH - - if (!bOk) - { - AZ_Error("Image Processing", false, "Failed to decompress an image by using PVRTexLib"); - return nullptr; - } - - // Getting decompressed data - const void* const pDecompressedData = cTexture.getDataPtr(); - if (!pDecompressedData) - { - AZ_Error("Image Processing", false, "Failed to obtain decompressed image data by using PVRTexLib"); - return nullptr; - } - - const AZ::u32 decompressedDataSize = cTexture.getDataSize(); - if (dstImage->GetMipBufSize(mip) != decompressedDataSize) - { - AZ_Error("Image Processing", false, "Decompressed image data size mismatch while using PVRTexLib"); - return nullptr; - } - - //save decompressed image to dst image - AZ::u8* dstMem; - AZ::u32 dstPitch; - dstImage->GetImagePointer(mip, dstMem, dstPitch); - memcpy(dstMem, pDecompressedData, decompressedDataSize); - } - - return dstImage; - } -} //namespace ImageProcessingAtom diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/PVRTC.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/PVRTC.h deleted file mode 100644 index cedd6d6643..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Compressors/PVRTC.h +++ /dev/null @@ -1,30 +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 - -namespace ImageProcessingAtom -{ - class PVRTCCompressor - : public ICompressor - { - public: - static bool IsCompressedPixelFormatSupported(EPixelFormat fmt); - static bool IsUncompressedPixelFormatSupported(EPixelFormat fmt); - static bool DoesSupportDecompress(EPixelFormat fmtDst); - - IImageObjectPtr CompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst, const CompressOption* compressOption) const override; - IImageObjectPtr DecompressImage(IImageObjectPtr srcImage, EPixelFormat fmtDst) const override; - - EPixelFormat GetSuggestedUncompressedFormat(EPixelFormat compressedfmt, EPixelFormat uncompressedfmt) const override; - ColorSpace GetSupportedColorSpace(EPixelFormat compressFormat) const final; - const char* GetName() const final; - }; -} // namespace ImageProcessingAtom diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/PresetInfoPopup.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/PresetInfoPopup.cpp index daaac5176b..2d5c89e8f5 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/PresetInfoPopup.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/PresetInfoPopup.cpp @@ -82,7 +82,6 @@ namespace ImageProcessingAtomEditor presetInfoText += "\n"; presetInfoText += QString("Suppress Engine Reduce: %1\n").arg(presetSettings->m_suppressEngineReduce ? "True" : "False"); presetInfoText += QString("Discard Alpha: %1\n").arg(presetSettings->m_discardAlpha ? "True" : "False"); - presetInfoText += QString("Is Power Of 2: %1\n").arg(presetSettings->m_isPowerOf2 ? "True" : "False"); presetInfoText += QString("Is Color Chart: %1\n").arg(presetSettings->m_isColorChart ? "True" : "False"); presetInfoText += QString("High Pass Mip: %1\n").arg(presetSettings->m_highPassMip); presetInfoText += QString("Gloss From Normal: %1\n").arg(presetSettings->m_glossFromNormals); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageLoader/DdsLoader.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageLoader/DdsLoader.cpp index 20367227bd..d7f36398e3 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageLoader/DdsLoader.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageLoader/DdsLoader.cpp @@ -24,201 +24,6 @@ namespace ImageProcessingAtom { namespace DdsLoader { - IImageObject* CreateImageFromHeaderLegacy(DDS_HEADER_LEGACY& header, DDS_HEADER_DXT10& exthead) - { - EPixelFormat eFormat = ePixelFormat_Unknown; - AZ::u32 dwWidth, dwMips, dwHeight; - AZ::u32 imageFlags = header.dwReserved1; - AZ::Color colMinARGB, colMaxARGB; - - dwWidth = header.dwWidth; - dwHeight = header.dwHeight; - dwMips = 1; - if (header.dwHeaderFlags & DDS_HEADER_FLAGS_MIPMAP) - { - dwMips = header.dwMipMapCount; - } - if ((header.dwSurfaceFlags & DDS_SURFACE_FLAGS_CUBEMAP) && (header.dwCubemapFlags & DDS_CUBEMAP_ALLFACES)) - { - AZ_Assert(header.dwReserved1 & EIF_Cubemap, "Image flag should have cubemap flag"); - dwHeight *= 6; - } - - colMinARGB = AZ::Color(header.cMinColor[0], header.cMinColor[1], header.cMinColor[2], header.cMinColor[3]); - colMaxARGB = AZ::Color(header.cMaxColor[0], header.cMaxColor[1], header.cMaxColor[2], header.cMaxColor[3]); - - //get pixel format - { - // DX10 formats - if (header.ddspf.dwFourCC == FOURCC_DX10) - { - AZ::u32 dxgiFormat = exthead.dxgiFormat; - - //remove the SRGB from dxgi format and add sRGB to image flag - if (dxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB) - { - dxgiFormat = DXGI_FORMAT_R8G8B8A8_UNORM; - } - else if (dxgiFormat == DXGI_FORMAT_BC1_UNORM_SRGB) - { - dxgiFormat = DXGI_FORMAT_BC1_UNORM; - } - else if (dxgiFormat == DXGI_FORMAT_BC2_UNORM_SRGB) - { - dxgiFormat = DXGI_FORMAT_BC2_UNORM; - } - else if (dxgiFormat == DXGI_FORMAT_BC3_UNORM_SRGB) - { - dxgiFormat = DXGI_FORMAT_BC3_UNORM; - } - else if (dxgiFormat == DXGI_FORMAT_BC7_UNORM_SRGB) - { - dxgiFormat = DXGI_FORMAT_BC7_UNORM; - } - - //add rgb flag if the dxgiformat was changed (which means it was sRGB format) above - if (dxgiFormat != exthead.dxgiFormat) - { - AZ_Assert(imageFlags & EIF_SRGBRead, "Image flags should have SRGBRead flag"); - imageFlags |= EIF_SRGBRead; - } - - //check all the pixel formats and find matching one - if (dxgiFormat != DXGI_FORMAT_UNKNOWN) - { - int i = 0; - for (; i < ePixelFormat_Count; i++) - { - const PixelFormatInfo* info = CPixelFormats::GetInstance().GetPixelFormatInfo((EPixelFormat)i); - if (static_cast(info->d3d10Format) == dxgiFormat) - { - eFormat = (EPixelFormat)i; - break; - } - } - if (i == ePixelFormat_Count) - { - AZ_Error("Image Processing", false, "Unhandled d3d10 format: %d", dxgiFormat); - return nullptr; - } - } - } - else - { - //for non-dx10 formats, use fourCC to find out its pixel formats - //go through all pixel formats and find a match with the fourcc - for (AZ::u32 formatIdx = 0; formatIdx < ePixelFormat_Count; formatIdx++) - { - const PixelFormatInfo* info = CPixelFormats::GetInstance().GetPixelFormatInfo((EPixelFormat)formatIdx); - if (header.ddspf.dwFourCC == info->fourCC) - { - eFormat = (EPixelFormat)formatIdx; - break; - } - } - - //legacy formats. This section is only used for load dds files converted by RC.exe - //our save to dds file function won't use any of these fourcc - if (eFormat == ePixelFormat_Unknown) - { - if (header.ddspf.dwFourCC == FOURCC_DXT1) - { - eFormat = ePixelFormat_BC1; - } - else if (header.ddspf.dwFourCC == FOURCC_DXT5) - { - eFormat = ePixelFormat_BC3; - } - else if (header.ddspf.dwFourCC == FOURCC_3DCP) - { - eFormat = ePixelFormat_BC4; - } - else if (header.ddspf.dwFourCC == FOURCC_3DC) - { - eFormat = ePixelFormat_BC5; - } - else if (header.ddspf.dwFourCC == DDS_FOURCC_R32F) - { - eFormat = ePixelFormat_R32F; - } - else if (header.ddspf.dwFourCC == DDS_FOURCC_G32R32F) - { - eFormat = ePixelFormat_R32G32F; - } - else if (header.ddspf.dwFourCC == DDS_FOURCC_A32B32G32R32F) - { - eFormat = ePixelFormat_R32G32B32A32F; - } - else if (header.ddspf.dwFourCC == DDS_FOURCC_R16F) - { - eFormat = ePixelFormat_R16F; - } - else if (header.ddspf.dwFourCC == DDS_FOURCC_G16R16F) - { - eFormat = ePixelFormat_R16G16F; - } - else if (header.ddspf.dwFourCC == DDS_FOURCC_A16B16G16R16F) - { - eFormat = ePixelFormat_R16G16B16A16F; - } - else if (header.ddspf.dwFourCC == DDS_FOURCC_A16B16G16R16) - { - eFormat = ePixelFormat_R16G16B16A16; - } - else if ((header.ddspf.dwFlags == DDS_RGBA || header.ddspf.dwFlags == DDS_RGB) - && header.ddspf.dwRGBBitCount == 32) - { - if (header.ddspf.dwRBitMask == 0x00ff0000) - { - eFormat = ePixelFormat_B8G8R8A8; - } - else - { - eFormat = ePixelFormat_R8G8B8A8; - } - } - else if (header.ddspf.dwFlags == DDS_LUMINANCEA && header.ddspf.dwRGBBitCount == 8) - { - eFormat = ePixelFormat_R8G8; - } - else if (header.ddspf.dwFlags == DDS_LUMINANCE && header.ddspf.dwRGBBitCount == 8) - { - eFormat = ePixelFormat_A8; - } - else if ((header.ddspf.dwFlags == DDS_A || header.ddspf.dwFlags == DDS_A_ONLY || header.ddspf.dwFlags == (DDS_A | DDS_A_ONLY)) && header.ddspf.dwRGBBitCount == 8) - { - eFormat = ePixelFormat_A8; - } - } - } - } - - if (eFormat == ePixelFormat_Unknown) - { - AZ_Error("Image Processing", false, "Unhandled dds pixel format fourCC: %d, flags: %d", - header.ddspf.dwFourCC, header.ddspf.dwFlags); - return nullptr; - } - - IImageObject* newImage = IImageObject::CreateImage(dwWidth, dwHeight, dwMips, eFormat); - - if (dwMips != newImage->GetMipCount()) - { - AZ_Error("Image Processing", false, "Mipcount from image data doesn't match image size and pixelformat"); - delete newImage; - return nullptr; - } - - //set properties - newImage->SetImageFlags(imageFlags); - newImage->SetAverageBrightness(header.fAvgBrightness); - newImage->SetColorRange(colMinARGB, colMaxARGB); - newImage->SetNumPersistentMips(header.bNumPersistentMips); - - return newImage; - } - - bool IsExtensionSupported(const char* extension) { QString ext = QString(extension).toLower(); @@ -226,215 +31,6 @@ namespace ImageProcessingAtom return ext == "dds"; } - IImageObject* LoadImageFromFileLegacy(const AZStd::string& filename) - { - AZ::IO::SystemFile file; - file.Open(filename.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_ONLY); - - AZ::IO::SystemFileStream fileLoadStream(&file, true); - if (!fileLoadStream.IsOpen()) - { - AZ_Warning("Image Processing", false, "%s: failed to open file %s", __FUNCTION__, filename.c_str()); - return nullptr; - } - - AZStd::string ext = ""; - AzFramework::StringFunc::Path::GetExtension(filename.c_str(), ext, false); - bool isAlphaImage = (ext == "a"); - - IImageObject* imageObj = LoadImageFromFileStreamLegacy(fileLoadStream); - - //load mips from seperated files if it's splitted - if (imageObj && imageObj->HasImageFlags(EIF_Splitted)) - { - AZStd::string baseName; - if (isAlphaImage) - { - baseName = filename.substr(0, filename.size() - 2); - } - else - { - baseName = filename; - } - - AZ::u32 externalMipCount = 0; - if (imageObj->GetNumPersistentMips() < imageObj->GetMipCount()) - { - externalMipCount = imageObj->GetMipCount() - imageObj->GetNumPersistentMips(); - } - //load other mips from files with number extensions - for (AZ::u32 mipIdx = 1; mipIdx <= externalMipCount; mipIdx++) - { - AZ::u32 mip = externalMipCount - mipIdx; - AZStd::string mipFileName = AZStd::string::format("%s.%d%s", baseName.c_str(), mipIdx, isAlphaImage ? "a" : ""); - - AZ::IO::SystemFile mipFile; - mipFile.Open(mipFileName.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_ONLY); - - AZ::IO::SystemFileStream mipFileLoadStream(&mipFile, true); - - if (!mipFileLoadStream.IsOpen()) - { - AZ_Warning("Image Processing", false, "%s: failed to open mip file %s", __FUNCTION__, mipFileName.c_str()); - break; - } - - AZ::u32 pitch; - AZ::u8* mem; - imageObj->GetImagePointer(mip, mem, pitch); - AZ::u32 bufSize = imageObj->GetMipBufSize(mip); - mipFileLoadStream.Read(bufSize, mem); - } - } - - return imageObj; - } - - IImageObject* LoadImageFromFileStreamLegacy(AZ::IO::SystemFileStream& fileLoadStream) - { - if (fileLoadStream.GetLength() - fileLoadStream.GetCurPos() < sizeof(DDS_FILE_DESC_LEGACY)) - { - AZ_Error("Image Processing", false, "%s: Trying to load a none-DDS file", __FUNCTION__); - return nullptr; - } - - DDS_FILE_DESC_LEGACY desc; - DDS_HEADER_DXT10 exthead; - - AZ::IO::SizeType startPos = fileLoadStream.GetCurPos(); - fileLoadStream.Read(sizeof(desc.dwMagic), &desc.dwMagic); - - if (desc.dwMagic != FOURCC_DDS) - { - desc.dwMagic = FOURCC_DDS; - //the old cry .a file doesn't have "DDS " in the beginning of the file. - //so reset to previous position - fileLoadStream.Seek(startPos, AZ::IO::GenericStream::ST_SEEK_BEGIN); - } - - fileLoadStream.Read(sizeof(desc.header), &desc.header); - - if (!desc.IsValid()) - { - AZ_Error("Image Processing", false, "%s: Trying to load a none-DDS file", __FUNCTION__); - return nullptr; - } - - if (desc.header.IsDX10Ext()) - { - fileLoadStream.Read(sizeof(exthead), &exthead); - } - - IImageObject* outImage = CreateImageFromHeaderLegacy(desc.header, exthead); - - if (outImage == nullptr) - { - return nullptr; - } - - //load mip data - AZ::u32 mipStart = 0; - //There are at least three lowest mips are in the file if it was splitted. This is to load splitted dds file exported by legacy rc.exe - int numPersistentMips = outImage->GetNumPersistentMips(); - if (numPersistentMips == 0 && outImage->HasImageFlags(EIF_Splitted)) - { - outImage->SetNumPersistentMips(3); - } - - if (outImage->HasImageFlags(EIF_Splitted) - && outImage->GetMipCount() > outImage->GetNumPersistentMips()) - { - mipStart = outImage->GetMipCount() - outImage->GetNumPersistentMips(); - } - - AZ::u32 faces = 1; - if (outImage->HasImageFlags(EIF_Cubemap)) - { - faces = 6; - } - - for (AZ::u32 face = 0; face < faces; face++) - { - for (AZ::u32 mip = mipStart; mip < outImage->GetMipCount(); ++mip) - { - AZ::u32 pitch; - AZ::u8* mem; - outImage->GetImagePointer(mip, mem, pitch); - AZ::u32 faceBufSize = outImage->GetMipBufSize(mip) / faces; - fileLoadStream.Read(faceBufSize, mem + faceBufSize * face); - } - } - - return outImage; - } - - IImageObject* LoadAttachedImageFromDdsFileLegacy(const AZStd::string& filename, IImageObjectPtr originImage) - { - if (originImage == nullptr) - { - return nullptr; - } - - AZ_Assert(originImage->HasImageFlags(EIF_AttachedAlpha), - "this function should only be called for origin image loaded from same file with attached alpha flag"); - - AZ::IO::SystemFile file; - file.Open(filename.c_str(), AZ::IO::SystemFile::SF_OPEN_READ_ONLY); - - AZ::IO::SystemFileStream fileLoadStream(&file, true); - if (!fileLoadStream.IsOpen()) - { - AZ_Warning("Image Processing", false, "%s: failed to open file %s", __FUNCTION__, filename.c_str()); - return nullptr; - } - - DDS_FILE_DESC_LEGACY desc; - DDS_HEADER_DXT10 exthead; - - fileLoadStream.Read(sizeof(desc), &desc); - if (desc.dwMagic != FOURCC_DDS) - { - AZ_Error("Image Processing", false, "%s:Trying to load a none-DDS file", __FUNCTION__); - return nullptr; - } - - if (desc.header.IsDX10Ext()) - { - fileLoadStream.Read(sizeof(exthead), &exthead); - } - - //skip size for originImage's mip data - for (AZ::u32 mip = 0; mip < originImage->GetMipCount(); ++mip) - { - AZ::u32 bufSize = originImage->GetMipBufSize(mip); - fileLoadStream.Seek(bufSize, AZ::IO::GenericStream::ST_SEEK_CUR); - } - - IImageObject* alphaImage = nullptr; - - AZ::u32 marker = 0; - fileLoadStream.Read(4, &marker); - if (marker == FOURCC_CExt) // marker for the start of O3DE Extended data - { - fileLoadStream.Read(4, &marker); - if (FOURCC_AttC == marker) // Attached Channel chunk - { - AZ::u32 size = 0; - fileLoadStream.Read(4, &size); - - alphaImage = LoadImageFromFileStreamLegacy(fileLoadStream); - fileLoadStream.Read(4, &marker); - } - - if (FOURCC_CEnd == marker) // marker for the end of O3DE Extended data - { - fileLoadStream.Read(4, &marker); - } - } - - return alphaImage; - } - // Create an image object from standard dds header IImageObject* CreateImageFromHeader(DDS_HEADER& header, DDS_HEADER_DXT10& exthead) { @@ -526,45 +122,14 @@ namespace ImageProcessingAtom { format = ePixelFormat_BC1; } - else if (header.ddspf.dwFourCC == FOURCC_DXT5) + else if (header.ddspf.dwFourCC == FOURCC_DXT5 || header.ddspf.dwFourCC == FOURCC_DXT4) { format = ePixelFormat_BC3; } - else if (header.ddspf.dwFourCC == FOURCC_3DCP) + else { - format = ePixelFormat_BC4; - } - else if (header.ddspf.dwFourCC == FOURCC_3DC) - { - format = ePixelFormat_BC5; - } - else if (header.ddspf.dwFourCC == DDS_FOURCC_R32F) - { - format = ePixelFormat_R32F; - } - else if (header.ddspf.dwFourCC == DDS_FOURCC_G32R32F) - { - format = ePixelFormat_R32G32F; - } - else if (header.ddspf.dwFourCC == DDS_FOURCC_A32B32G32R32F) - { - format = ePixelFormat_R32G32B32A32F; - } - else if (header.ddspf.dwFourCC == DDS_FOURCC_R16F) - { - format = ePixelFormat_R16F; - } - else if (header.ddspf.dwFourCC == DDS_FOURCC_G16R16F) - { - format = ePixelFormat_R16G16F; - } - else if (header.ddspf.dwFourCC == DDS_FOURCC_A16B16G16R16F) - { - format = ePixelFormat_R16G16B16A16F; - } - else if (header.ddspf.dwFourCC == DDS_FOURCC_A16B16G16R16) - { - format = ePixelFormat_R16G16B16A16; + AZ_Error("Image Processing", false, "unsupported fourCC format: 0x%x", header.ddspf.dwFourCC); + return nullptr; } } else diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageLoader/ImageLoaders.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageLoader/ImageLoaders.h index 587c9b551b..b860e82631 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageLoader/ImageLoaders.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageLoader/ImageLoaders.h @@ -44,11 +44,6 @@ namespace ImageProcessingAtom { bool IsExtensionSupported(const char* extension); IImageObject* LoadImageFromFile(const AZStd::string& filename); - - // These functions are for loading legacy O3DE dds files - IImageObject* LoadImageFromFileLegacy(const AZStd::string& filename); - IImageObject* LoadImageFromFileStreamLegacy(AZ::IO::SystemFileStream& fileLoadStream); - IImageObject* LoadAttachedImageFromDdsFileLegacy(const AZStd::string& filename, IImageObjectPtr originImage); };// namespace DdsLoader // Load .exr files to an image object diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Platform/Mac/platform_mac.cmake b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Platform/Mac/platform_mac.cmake index 7008b352a8..7a325ca97e 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Platform/Mac/platform_mac.cmake +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Platform/Mac/platform_mac.cmake @@ -5,8 +5,3 @@ # SPDX-License-Identifier: Apache-2.0 OR MIT # # - -set(LY_COMPILE_OPTIONS - PRIVATE - -fexceptions #ImageLoader/ExrLoader.cpp and PVRTC.cpp uses exceptions -) diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/DDSHeader.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/DDSHeader.h index 785424a9b1..0f953897c9 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/DDSHeader.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/DDSHeader.h @@ -237,14 +237,8 @@ namespace ImageProcessingAtom const static AZ::u32 FOURCC_CEnd = IMAGE_BUIDER_MAKEFOURCC('C', 'E', 'n', 'd'); // O3DE extension end const static AZ::u32 FOURCC_AttC = IMAGE_BUIDER_MAKEFOURCC('A', 't', 't', 'C'); // Chunk Attached Channel - //Fourcc for pixel formats which aren't supported by dx10, such as astc formats, etc formats, pvrtc formats + //Fourcc for pixel formats which aren't supported by dx10, such as astc formats //They are used for dwFourCC of dds header's DDS_PIXELFORMAT to identify non-dx10 pixel formats - const static AZ::u32 FOURCC_EAC_R11 = IMAGE_BUIDER_MAKEFOURCC('E', 'A', 'R', ' '); - const static AZ::u32 FOURCC_EAC_RG11 = IMAGE_BUIDER_MAKEFOURCC('E', 'A', 'R', 'G'); - const static AZ::u32 FOURCC_ETC2 = IMAGE_BUIDER_MAKEFOURCC('E', 'T', '2', ' '); - const static AZ::u32 FOURCC_ETC2A = IMAGE_BUIDER_MAKEFOURCC('E', 'T', '2', 'A'); - const static AZ::u32 FOURCC_PVRTC2 = IMAGE_BUIDER_MAKEFOURCC('P', 'V', 'R', '2'); - const static AZ::u32 FOURCC_PVRTC4 = IMAGE_BUIDER_MAKEFOURCC('P', 'V', 'R', '4'); const static AZ::u32 FOURCC_ASTC_4x4 = IMAGE_BUIDER_MAKEFOURCC('A', 'S', '4', '4'); const static AZ::u32 FOURCC_ASTC_5x4 = IMAGE_BUIDER_MAKEFOURCC('A', 'S', '5', '4'); const static AZ::u32 FOURCC_ASTC_5x5 = IMAGE_BUIDER_MAKEFOURCC('A', 'S', '5', '5'); @@ -260,10 +254,10 @@ namespace ImageProcessingAtom const static AZ::u32 FOURCC_ASTC_12x10 = IMAGE_BUIDER_MAKEFOURCC('A', 'S', 'C', 'A'); const static AZ::u32 FOURCC_ASTC_12x12 = IMAGE_BUIDER_MAKEFOURCC('A', 'S', 'C', 'C'); - //legacy formats names. they are only used for load rc.exe's dds formats + //legacy formats names. they are only used for load old dds formats. const static AZ::u32 FOURCC_DXT1 = IMAGE_BUIDER_MAKEFOURCC('D', 'X', 'T', '1'); + const static AZ::u32 FOURCC_DXT2 = IMAGE_BUIDER_MAKEFOURCC('D', 'X', 'T', '2'); const static AZ::u32 FOURCC_DXT3 = IMAGE_BUIDER_MAKEFOURCC('D', 'X', 'T', '3'); + const static AZ::u32 FOURCC_DXT4 = IMAGE_BUIDER_MAKEFOURCC('D', 'X', 'T', '4'); const static AZ::u32 FOURCC_DXT5 = IMAGE_BUIDER_MAKEFOURCC('D', 'X', 'T', '5'); - const static AZ::u32 FOURCC_3DCP = IMAGE_BUIDER_MAKEFOURCC('A', 'T', 'I', '1'); - const static AZ::u32 FOURCC_3DC = IMAGE_BUIDER_MAKEFOURCC('A', 'T', 'I', '2'); } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/PixelFormatInfo.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/PixelFormatInfo.cpp index 94fce9bc1f..8a741d6637 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/PixelFormatInfo.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/PixelFormatInfo.cpp @@ -52,19 +52,6 @@ namespace ImageProcessingAtom return false; } - bool IsETCFormat(EPixelFormat fmt) - { - if (fmt == ePixelFormat_ETC2 - || fmt == ePixelFormat_ETC2a - || fmt == ePixelFormat_ETC2a1 - || fmt == ePixelFormat_EAC_R11 - || fmt == ePixelFormat_EAC_RG11) - { - return true; - } - return false; - } - PixelFormatInfo::PixelFormatInfo( uint32_t a_bitsPerPixel, uint32_t a_Channels, @@ -96,7 +83,6 @@ namespace ImageProcessingAtom , fourCC(a_fourCC) , eSampleType(a_eSampleType) , szName(a_szName) - , szLegacyName(a_szName) , szDescription(a_szDescription) , bCompressed(a_bCompressed) , bSelectable(a_bSelectable) @@ -122,15 +108,6 @@ namespace ImageProcessingAtom CPixelFormats::CPixelFormats() { InitPixelFormats(); - - m_removedLegacyFormats["DXT1"] = ePixelFormat_BC1; - m_removedLegacyFormats["DXT1a"] = ePixelFormat_BC1a; - m_removedLegacyFormats["DXT3"] = ePixelFormat_BC3; - m_removedLegacyFormats["DXT3t"] = ePixelFormat_BC3t; - m_removedLegacyFormats["DXT5"] = ePixelFormat_BC3; - m_removedLegacyFormats["DXT5t"] = ePixelFormat_BC3t; - m_removedLegacyFormats["3DCp"] = ePixelFormat_BC4; - m_removedLegacyFormats["3DC"] = ePixelFormat_BC5; } void CPixelFormats::InitPixelFormat(EPixelFormat format, const PixelFormatInfo& formatInfo) @@ -176,13 +153,6 @@ namespace ImageProcessingAtom InitPixelFormat(ePixelFormat_ASTC_10x10, PixelFormatInfo(0, 4, true, "?", 16, 16, 10, 10, 128, false, DXGI_FORMAT_UNKNOWN, FOURCC_ASTC_10x10, ESampleType::eSampleType_Compressed, "ASTC_10x10", "ASTC 10x10 compressed texture format", true, false)); InitPixelFormat(ePixelFormat_ASTC_12x10, PixelFormatInfo(0, 4, true, "?", 16, 16, 12, 10, 128, false, DXGI_FORMAT_UNKNOWN, FOURCC_ASTC_12x10, ESampleType::eSampleType_Compressed, "ASTC_12x10", "ASTC 12x10 compressed texture format", true, false)); InitPixelFormat(ePixelFormat_ASTC_12x12, PixelFormatInfo(0, 4, true, "?", 16, 16, 12, 12, 128, false, DXGI_FORMAT_UNKNOWN, FOURCC_ASTC_12x12, ESampleType::eSampleType_Compressed, "ASTC_12x12", "ASTC 12x12 compressed texture format", true, false)); - InitPixelFormat(ePixelFormat_PVRTC2, PixelFormatInfo(2, 4, true, "2", 16, 16, 8, 4, 64, true, DXGI_FORMAT_UNKNOWN, FOURCC_PVRTC2, ESampleType::eSampleType_Compressed, "PVRTC2", "POWERVR 2 bpp compressed texture format", true, false)); - InitPixelFormat(ePixelFormat_PVRTC4, PixelFormatInfo(4, 4, true, "2", 8, 8, 4, 4, 64, true, DXGI_FORMAT_UNKNOWN, FOURCC_PVRTC4, ESampleType::eSampleType_Compressed, "PVRTC4", "POWERVR 4 bpp compressed texture format", true, false)); - InitPixelFormat(ePixelFormat_EAC_R11, PixelFormatInfo(4, 1, true, "4", 4, 4, 4, 4, 64, false, DXGI_FORMAT_UNKNOWN, FOURCC_EAC_R11, ESampleType::eSampleType_Compressed, "EAC_R11", "EAC 4 bpp single channel texture format", true, false)); - InitPixelFormat(ePixelFormat_EAC_RG11, PixelFormatInfo(8, 2, false, "0", 4, 4, 4, 4, 128, false, DXGI_FORMAT_UNKNOWN, FOURCC_EAC_RG11, ESampleType::eSampleType_Compressed, "EAC_RG11", "EAC 8 bpp dual channel texture format", true, false)); - InitPixelFormat(ePixelFormat_ETC2, PixelFormatInfo(4, 3, false, "0", 4, 4, 4, 4, 64, false, DXGI_FORMAT_UNKNOWN, FOURCC_ETC2, ESampleType::eSampleType_Compressed, "ETC2", "ETC2 RGB 4 bpp compressed texture format", true, false)); - InitPixelFormat(ePixelFormat_ETC2a, PixelFormatInfo(8, 4, true, "4", 4, 4, 4, 4, 128, false, DXGI_FORMAT_UNKNOWN, FOURCC_ETC2A, ESampleType::eSampleType_Compressed, "ETC2a", "ETC2 RGBA 8 bpp compressed texture format", true, false)); - InitPixelFormat(ePixelFormat_ETC2a1, PixelFormatInfo(4, 4, true, "1", 4, 4, 4, 4, 64, false, DXGI_FORMAT_UNKNOWN, FOURCC_ETC2A, ESampleType::eSampleType_Compressed, "ETC2a1", "ETC2 RGBA1 8 bpp compressed texture format", true, false)); // Standardized Compressed DXGI Formats (DX10+) // Data in these compressed formats is hardware decodable on all DX10 chips, and manageable with the DX10-API. @@ -216,17 +186,6 @@ namespace ImageProcessingAtom InitPixelFormat(ePixelFormat_R32, PixelFormatInfo(32, 1, false, "0", 1, 1, 1, 1, 32, false, DXGI_FORMAT_FORCE_UINT, FOURCC_DX10, ESampleType::eSampleType_Uint32, "R32", "32-bit red only", false, false)); - //Set legacy name it can be used for convertion - m_pixelFormatInfo[ePixelFormat_R8G8B8A8].szLegacyName = "A8R8G8B8"; - m_pixelFormatInfo[ePixelFormat_R8G8B8X8].szLegacyName = "X8R8G8B8"; - m_pixelFormatInfo[ePixelFormat_R8G8].szLegacyName = "G8R8"; - m_pixelFormatInfo[ePixelFormat_R16G16B16A16].szLegacyName = "A16B16G16R16"; - m_pixelFormatInfo[ePixelFormat_R16G16].szLegacyName = "G16R16"; - m_pixelFormatInfo[ePixelFormat_R32G32B32A32F].szLegacyName = "A32B32G32R32F"; - m_pixelFormatInfo[ePixelFormat_R32G32F].szLegacyName = "G32R32F"; - m_pixelFormatInfo[ePixelFormat_R16G16B16A16F].szLegacyName = "A16B16G16R16F"; - m_pixelFormatInfo[ePixelFormat_R16G16F].szLegacyName = "G16R16F"; - //validate all pixel formats are proper initialized for (int i = 0; i < ePixelFormat_Count; ++i) { @@ -249,23 +208,6 @@ namespace ImageProcessingAtom return ePixelFormat_Unknown; } - EPixelFormat CPixelFormats::FindPixelFormatByLegacyName(const char* name) - { - if (m_removedLegacyFormats.find(name) != m_removedLegacyFormats.end()) - { - return m_removedLegacyFormats[name]; - } - - for (int i = 0; i < ePixelFormat_Count; ++i) - { - if (azstricmp(m_pixelFormatInfo[i].szLegacyName, name) == 0) - { - return (EPixelFormat)i; - } - } - return ePixelFormat_Unknown; - } - const PixelFormatInfo* CPixelFormats::GetPixelFormatInfo(EPixelFormat format) { AZ_Assert((format >= 0) && (format < ePixelFormat_Count), "Unsupport pixel format: %d", format); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/PixelFormatInfo.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/PixelFormatInfo.h index ec1ec1bfaf..92c4bdd99e 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/PixelFormatInfo.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/PixelFormatInfo.h @@ -119,7 +119,6 @@ namespace ImageProcessingAtom bool bSquarePow2; // whether the pixel format requires image size be square and power of 2. DXGI_FORMAT d3d10Format; // the mapping d3d10 pixel format ESampleType eSampleType; // the data type used to present pixel - const char* szLegacyName; // name used for cryEngine const char* szName; // name for showing in editors const char* szDescription; // description for showing in editors bool bCompressed; // if it's a compressed format @@ -173,10 +172,6 @@ namespace ImageProcessingAtom bool IsFormatSigned(EPixelFormat fmt); bool IsFormatFloatingPoint(EPixelFormat fmt, bool bFullPrecision); - //find the pixel format for name used by Cry's RC.ini - //returns ePixelFormat_Unknown if the name was not found in registed format list - EPixelFormat FindPixelFormatByLegacyName(const char* name); - //find pixel format by its name EPixelFormat FindPixelFormatByName(const char* name); @@ -208,9 +203,6 @@ namespace ImageProcessingAtom //pixel format name to pixel format enum AZStd::map m_pixelFormatNameMap; - - // some formats from cryEngine were removed. using this name-pixelFormat mapping to look for new format - AZStd::map m_removedLegacyFormats; }; template diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/Utils.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/Utils.cpp index d282e9b02b..29ba8c3351 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/Utils.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/Utils.cpp @@ -102,32 +102,6 @@ namespace ImageProcessingAtom case AZ::RHI::Format::ASTC_12x12_UNORM: return ePixelFormat_ASTC_12x12; - case AZ::RHI::Format::PVRTC2_UNORM_SRGB: - isSRGB = true; - case AZ::RHI::Format::PVRTC2_UNORM: - return ePixelFormat_PVRTC2; - case AZ::RHI::Format::PVRTC4_UNORM_SRGB: - isSRGB = true; - case AZ::RHI::Format::PVRTC4_UNORM: - return ePixelFormat_PVRTC4; - - case AZ::RHI::Format::EAC_R11_UNORM: - return ePixelFormat_EAC_R11; - case AZ::RHI::Format::EAC_RG11_UNORM: - return ePixelFormat_EAC_RG11; - case AZ::RHI::Format::ETC2_UNORM_SRGB: - isSRGB = true; - case AZ::RHI::Format::ETC2_UNORM: - return ePixelFormat_ETC2; - case AZ::RHI::Format::ETC2A_UNORM_SRGB: - isSRGB = true; - case AZ::RHI::Format::ETC2A_UNORM: - return ePixelFormat_ETC2a; - case AZ::RHI::Format::ETC2A1_UNORM_SRGB: - isSRGB = true; - case AZ::RHI::Format::ETC2A1_UNORM: - return ePixelFormat_ETC2a1; - case AZ::RHI::Format::BC1_UNORM_SRGB: isSRGB = true; case AZ::RHI::Format::BC1_UNORM: @@ -225,22 +199,6 @@ namespace ImageProcessingAtom case ePixelFormat_ASTC_12x12: return isSrgb ? RHI::Format::ASTC_12x12_UNORM_SRGB : RHI::Format::ASTC_12x12_UNORM; - case ePixelFormat_PVRTC2: - return isSrgb ? RHI::Format::PVRTC2_UNORM_SRGB : RHI::Format::PVRTC2_UNORM; - case ePixelFormat_PVRTC4: - return isSrgb ? RHI::Format::PVRTC4_UNORM_SRGB : RHI::Format::PVRTC4_UNORM; - - case ePixelFormat_EAC_R11: - return RHI::Format::EAC_R11_UNORM; - case ePixelFormat_EAC_RG11: - return RHI::Format::EAC_RG11_UNORM; - case ePixelFormat_ETC2: - return isSrgb ? RHI::Format::ETC2_UNORM_SRGB : RHI::Format::ETC2_UNORM; - case ePixelFormat_ETC2a: - return isSrgb ? RHI::Format::ETC2A_UNORM_SRGB : RHI::Format::ETC2A_UNORM; - case ePixelFormat_ETC2a1: - return isSrgb ? RHI::Format::ETC2A1_UNORM_SRGB : RHI::Format::ETC2A1_UNORM; - case ePixelFormat_BC1: case ePixelFormat_BC1a: return isSrgb ? RHI::Format::BC1_UNORM_SRGB : RHI::Format::BC1_UNORM; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp index c72e1dc309..9e4aa83908 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp @@ -426,60 +426,6 @@ namespace UnitTest return isDifferent; } - - bool CompareDDSImage(const QString& imagePath1, const QString& imagePath2, QString& output) - { - IImageObjectPtr image1, alphaImage1, image2, alphaImage2; - - - image1 = IImageObjectPtr(DdsLoader::LoadImageFromFileLegacy(imagePath1.toUtf8().constData())); - if (image1 && image1->HasImageFlags(EIF_AttachedAlpha)) - { - if (image1->HasImageFlags(EIF_Splitted)) - { - alphaImage1 = IImageObjectPtr(DdsLoader::LoadImageFromFileLegacy(QString(imagePath1 + ".a").toUtf8().constData())); - } - else - { - alphaImage1 = IImageObjectPtr(DdsLoader::LoadAttachedImageFromDdsFileLegacy(imagePath1.toUtf8().constData(), image1)); - } - } - - image2 = IImageObjectPtr(DdsLoader::LoadImageFromFileLegacy(imagePath2.toUtf8().constData())); - if (image2 && image2->HasImageFlags(EIF_AttachedAlpha)) - { - if (image2->HasImageFlags(EIF_Splitted)) - { - alphaImage2 = IImageObjectPtr(DdsLoader::LoadImageFromFileLegacy(QString(imagePath2 + ".a").toUtf8().constData())); - } - else - { - alphaImage2 = IImageObjectPtr(DdsLoader::LoadAttachedImageFromDdsFileLegacy(imagePath2.toUtf8().constData(), image2)); - } - } - - if (!image1 && !image2) - { - output += "Cannot load both image file! "; - return false; - } - bool isDifferent = false; - - isDifferent = GetComparisonResult(image1, image2, output); - - - QFileInfo fi(imagePath1); - AZStd::string imageName = fi.baseName().toUtf8().constData(); - SaveImageToFile(image1, imageName + "_new"); - SaveImageToFile(image2, imageName + "_old"); - - if (alphaImage1 || alphaImage2) - { - isDifferent |= GetComparisonResult(alphaImage1, alphaImage2, output); - } - - return isDifferent; - } }; // test CPixelFormats related functions @@ -487,34 +433,6 @@ namespace UnitTest { CPixelFormats& pixelFormats = CPixelFormats::GetInstance(); - //verify names which was used for legacy rc.ini - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("BC7t") == ePixelFormat_BC7t); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("ETC2A") == ePixelFormat_ETC2a); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("PVRTC4") == ePixelFormat_PVRTC4); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("BC1") == ePixelFormat_BC1); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("ETC2") == ePixelFormat_ETC2); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("BC1a") == ePixelFormat_BC1a); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("BC3") == ePixelFormat_BC3); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("BC7") == ePixelFormat_BC7); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("BC5s") == ePixelFormat_BC5s); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("EAC_RG11") == ePixelFormat_EAC_RG11); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("BC4") == ePixelFormat_BC4); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("EAC_R11") == ePixelFormat_EAC_R11); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("A8R8G8B8") == ePixelFormat_R8G8B8A8); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("BC6UH") == ePixelFormat_BC6UH); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("R9G9B9E5") == ePixelFormat_R9G9B9E5); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("X8R8G8B8") == ePixelFormat_R8G8B8X8); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("A16B16G16R16F") == ePixelFormat_R16G16B16A16F); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("G8R8") == ePixelFormat_R8G8); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("G16R16") == ePixelFormat_R16G16); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("G16R16F") == ePixelFormat_R16G16F); - - //some legacy format need to be mapping to new format. - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("DXT1") == ePixelFormat_BC1); - ASSERT_TRUE(pixelFormats.FindPixelFormatByLegacyName("DXT5") == ePixelFormat_BC3); - - //calculate mipmap count. no cubemap support at this moment - //for all the non-compressed textures, if there minimum required texture size is 1x1 for (uint32 i = 0; i < ePixelFormat_Count; i++) { @@ -543,13 +461,6 @@ namespace UnitTest } //check function IsImageSizeValid && EvaluateImageDataSize function - ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_PVRTC4, 2, 1, false) == false); - ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_PVRTC4, 4, 4, false) == false); - ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_PVRTC4, 16, 16, false) == true); - ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_PVRTC4, 16, 32, false) == false); - ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_PVRTC4, 34, 34, false) == false); - ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_PVRTC4, 256, 256, false) == true); - ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_BC1, 2, 1, false) == false); ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_BC1, 16, 16, false) == true); ASSERT_TRUE(pixelFormats.IsImageSizeValid(ePixelFormat_BC1, 16, 32, false) == true); @@ -834,9 +745,7 @@ namespace UnitTest if (formatInfo->bCompressed) { // skip ASTC formats which are tested in TestConvertASTCCompressor - if (!IsASTCFormat(pixelFormat) - && pixelFormat != ePixelFormat_PVRTC2 && pixelFormat != ePixelFormat_PVRTC4 - && !IsETCFormat(pixelFormat)) // skip ETC since it's very slow + if (!IsASTCFormat(pixelFormat)) { compressedFormats.push_back(pixelFormat); } @@ -1112,55 +1021,6 @@ namespace UnitTest } } - TEST_F(ImageProcessingTest, DISABLED_CompareOutputImage) - { - AZStd::string curretTextureFolder = "../TestAssets/TextureAssets/assets_new/textures"; - AZStd::string oldTextureFolder = "../TestAssets/TextureAssets/assets_old/textures"; - bool outputOnlyDifferent = false; - QDirIterator it(curretTextureFolder.c_str(), QStringList() << "*.dds", QDir::Files, QDirIterator::Subdirectories); - QFile f("../texture_comparison_output.csv"); - f.open(QIODevice::ReadWrite | QIODevice::Truncate); - // Write a header for csv file - f.write("Texture Name, Path, Mip new/old, MipDiff, Format new/old, Flag new/old, MemSize new/old, MemDiff, Error, AlphaMip new/old, AlphaMipDiff, AlphaFormat new/old, AlphaFlag new/old, AlphaMemSize new/old, AlphaMemDiff, AlphaError\r\n"); - int i = 0; - while (it.hasNext()) - { - i++; - it.next(); - - QString fileName = it.fileName(); - QString newFilePath = it.filePath(); - QString sharedPath = QString(newFilePath).remove(curretTextureFolder.c_str()); - QString oldFilePath = QString(oldTextureFolder.c_str()) + sharedPath; - QString output; - if (QFile::exists(oldFilePath)) - { - bool isDifferent = CompareDDSImage(newFilePath, oldFilePath, output); - if (outputOnlyDifferent && !isDifferent) - { - continue; - } - else - { - f.write(fileName.toUtf8().constData()); - f.write(","); - f.write(sharedPath.toUtf8().constData()); - f.write(output.toUtf8().constData()); - } - } - else - { - f.write(fileName.toUtf8().constData()); - f.write(","); - f.write(sharedPath.toUtf8().constData()); - output += ",No old file for comparison!"; - f.write(output.toUtf8().constData()); - } - f.write("\r\n"); - } - f.close(); - } - TEST_F(ImageProcessingTest, TextureSettingReflect_SerializingModernDataInAndOut_WritesAndParsesFileAccurately) { AZStd::string filepath = "test.xml"; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessing_files.cmake b/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessing_files.cmake index ba9e9f29b7..aad400518d 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessing_files.cmake +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/imageprocessing_files.cmake @@ -120,10 +120,6 @@ set(FILES Source/Compressors/Compressor.cpp Source/Compressors/CTSquisher.h Source/Compressors/CTSquisher.cpp - Source/Compressors/PVRTC.cpp - Source/Compressors/PVRTC.h - Source/Compressors/ETC2.cpp - Source/Compressors/ETC2.h Source/Compressors/CryTextureSquisher/ColorBlockRGBA4x4f.cpp Source/Compressors/CryTextureSquisher/ColorBlockRGBA4x4s.cpp Source/Compressors/CryTextureSquisher/ColorBlockRGBA4x4c.cpp diff --git a/Gems/TextureAtlas/Code/Source/Editor/AtlasBuilderWorker.cpp b/Gems/TextureAtlas/Code/Source/Editor/AtlasBuilderWorker.cpp index abcdce99b9..f6e6a1254c 100644 --- a/Gems/TextureAtlas/Code/Source/Editor/AtlasBuilderWorker.cpp +++ b/Gems/TextureAtlas/Code/Source/Editor/AtlasBuilderWorker.cpp @@ -757,9 +757,7 @@ namespace TextureAtlasBuilder if (input.m_presetName.empty()) { - // Default to the TextureAtlas preset which is currently set to use compression for all platforms except for iOS. - // Currently the only fully supported compression for iOS is PVRTC which requires the texture to be square and a power of 2. - // Due to this limitation, we default to using no compression for iOS until ASTC is fully supported + // Default to the TextureAtlas preset which is currently set to use compression const AZStd::string defaultPresetName = "UserInterface_Compressed"; input.m_presetName = defaultPresetName; } diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index fb02a80088..8e4a3ef828 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -20,7 +20,6 @@ ly_associate_package(PACKAGE_NAME SQLite-3.32.2-rev3-multiplatform ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS glad PACKAGE_HASH ff97ee9664e97d0854b52a3734c2289329d9f2b4cd69478df6d0ca1f1c9392ee) ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux_core PACKAGE_HASH c8c13cf7bc351643e1abd294d0841b24dee60e51647dff13db7aec396ad1e0b5) ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform TARGETS xxhash PACKAGE_HASH e81f3e6c4065975833996dd1fcffe46c3cf0f9e3a4207ec5f4a1b564ba75861e) -ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform TARGETS PVRTexTool PACKAGE_HASH d0d6da61c7557de0d2c71fc35ba56c3be49555b703f0e853d4c58225537acf1e) # platform-specific: ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-linux TARGETS AWSGameLiftServerSDK PACKAGE_HASH a8149a95bd100384af6ade97e2b21a56173740d921e6c3da8188cd51554d39af) @@ -29,7 +28,6 @@ ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-linux ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev6-linux TARGETS AWSNativeSDK PACKAGE_HASH 490291e4c8057975c3ab86feb971b8a38871c58bac5e5d86abdd1aeb7141eec4) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-linux TARGETS Lua PACKAGE_HASH 1adc812abe3dd0dbb2ca9756f81d8f0e0ba45779ac85bf1d8455b25c531a38b0) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-linux TARGETS PhysX PACKAGE_HASH a110249cbef4f266b0002c4ee9a71f59f373040cefbe6b82f1e1510c811edde6) -ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-linux TARGETS etc2comp PACKAGE_HASH 9283aa5db5bb7fb90a0ddb7a9f3895317c8ebe8044943124bbb3673a41407430) ly_associate_package(PACKAGE_NAME mcpp-2.7.2_az.2-rev1-linux TARGETS mcpp PACKAGE_HASH df7a998d0bc3fedf44b5bdebaf69ddad6033355b71a590e8642445ec77bc6c41) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-linux TARGETS mikkelsen PACKAGE_HASH 5973b1e71a64633588eecdb5b5c06ca0081f7be97230f6ef64365cbda315b9c8) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-linux TARGETS googletest PACKAGE_HASH 7b7ad330f369450c316a4c4592d17fbb4c14c731c95bd8f37757203e8c2bbc1b) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index e80956530a..631c42784a 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -21,7 +21,6 @@ ly_associate_package(PACKAGE_NAME azslc-1.7.23-rev1-multiplatform ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS glad PACKAGE_HASH ff97ee9664e97d0854b52a3734c2289329d9f2b4cd69478df6d0ca1f1c9392ee) ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux_core PACKAGE_HASH c8c13cf7bc351643e1abd294d0841b24dee60e51647dff13db7aec396ad1e0b5) ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform TARGETS xxhash PACKAGE_HASH e81f3e6c4065975833996dd1fcffe46c3cf0f9e3a4207ec5f4a1b564ba75861e) -ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform TARGETS PVRTexTool PACKAGE_HASH d0d6da61c7557de0d2c71fc35ba56c3be49555b703f0e853d4c58225537acf1e) # platform-specific: ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev3-mac TARGETS DirectXShaderCompilerDxc PACKAGE_HASH 3f77367dbb0342136ec4ebbd44bc1fedf7198089a0f83c5631248530769b2be6) @@ -31,7 +30,6 @@ ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-mac ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev5-mac TARGETS AWSNativeSDK PACKAGE_HASH ffb890bd9cf23afb429b9214ad9bac1bf04696f07a0ebb93c42058c482ab2f01) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev6-mac TARGETS Lua PACKAGE_HASH b9079fd35634774c9269028447562c6b712dbc83b9c64975c095fd423ff04c08) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-mac TARGETS PhysX PACKAGE_HASH 5e092a11d5c0a50c4dd99bb681a04b566a4f6f29aa08443d9bffc8dc12c27c8e) -ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-mac TARGETS etc2comp PACKAGE_HASH 1966ab101c89db7ecf30984917e0a48c0d02ee0e4d65b798743842b9469c0818) ly_associate_package(PACKAGE_NAME mcpp-2.7.2_az.2-rev1-mac TARGETS mcpp PACKAGE_HASH be9558905c9c49179ef3d7d84f0a5472415acdf7fe2d76eb060d9431723ddf2e) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-mac TARGETS mikkelsen PACKAGE_HASH 83af99ca8bee123684ad254263add556f0cf49486c0b3e32e6d303535714e505) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-mac TARGETS googletest PACKAGE_HASH cbf020d5ef976c5db8b6e894c6c63151ade85ed98e7c502729dd20172acae5a8) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index 7e112c405e..428e5e9526 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -21,7 +21,6 @@ ly_associate_package(PACKAGE_NAME azslc-1.7.23-rev1-multiplatform ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS glad PACKAGE_HASH ff97ee9664e97d0854b52a3734c2289329d9f2b4cd69478df6d0ca1f1c9392ee) ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux_core PACKAGE_HASH c8c13cf7bc351643e1abd294d0841b24dee60e51647dff13db7aec396ad1e0b5) ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform TARGETS xxhash PACKAGE_HASH e81f3e6c4065975833996dd1fcffe46c3cf0f9e3a4207ec5f4a1b564ba75861e) -ly_associate_package(PACKAGE_NAME PVRTexTool-4.24.0-rev4-multiplatform TARGETS PVRTexTool PACKAGE_HASH d0d6da61c7557de0d2c71fc35ba56c3be49555b703f0e853d4c58225537acf1e) # platform-specific: ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-windows TARGETS AWSGameLiftServerSDK PACKAGE_HASH a0586b006e4def65cc25f388de17dc475e417dc1e6f9d96749777c88aa8271b0) @@ -32,7 +31,6 @@ ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-windows ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev4-windows TARGETS AWSNativeSDK PACKAGE_HASH a900e80f7259e43aed5c847afee2599ada37f29db70505481397675bcbb6c76c) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-windows TARGETS Lua PACKAGE_HASH 136faccf1f73891e3fa3b95f908523187792e56f5b92c63c6a6d7e72d1158d40) ly_associate_package(PACKAGE_NAME PhysX-4.1.2.29882248-rev3-windows TARGETS PhysX PACKAGE_HASH 0c5ffbd9fa588e5cf7643721a7cfe74d0fe448bf82252d39b3a96d06dfca2298) -ly_associate_package(PACKAGE_NAME etc2comp-9cd0f9cae0-rev1-windows TARGETS etc2comp PACKAGE_HASH fc9ae937b2ec0d42d5e7d0e9e8c80e5e4d257673fb33bc9b7d6db76002117123) ly_associate_package(PACKAGE_NAME mcpp-2.7.2_az.2-rev1-windows TARGETS mcpp PACKAGE_HASH 794789aba639bfe2f4e8fcb4424d679933dd6290e523084aa0a4e287ac44acb2) ly_associate_package(PACKAGE_NAME mikkelsen-1.0.0.4-windows TARGETS mikkelsen PACKAGE_HASH 872c4d245a1c86139aa929f2b465b63ea4ea55b04ced50309135dd4597457a4e) ly_associate_package(PACKAGE_NAME googletest-1.8.1-rev4-windows TARGETS googletest PACKAGE_HASH 7e8f03ae8a01563124e3daa06386f25a2b311c10bb95bff05cae6c41eff83837) From 2fb4a9d2c391b20dfc92b1aaac0b330dff0579f9 Mon Sep 17 00:00:00 2001 From: hultonha <82228511+hultonha@users.noreply.github.com> Date: Fri, 8 Oct 2021 13:13:52 +0100 Subject: [PATCH 071/169] Add xfail to test that failed in an unrelated development build (#4569) Signed-off-by: hultonha --- AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py | 1 + 1 file changed, 1 insertion(+) diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py index 4c5716d365..b148ffdcdb 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py @@ -25,6 +25,7 @@ TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "tests") class TestAtomEditorComponentsMain(object): """Holds tests for Atom components.""" + @pytest.mark.xfail(reason="This test is being marked xfail as it failed during an unrelated development run. See LYN-7530 for more details.") def test_AtomEditorComponents_AddedToEntity(self, request, editor, level, workspace, project, launcher_platform): """ Please review the hydra script run by this test for more specific test info. From 591854c384f10ffe1e2461378bcb4134e6bdb0c6 Mon Sep 17 00:00:00 2001 From: FiniteStateGit <31811688+FiniteStateGit@users.noreply.github.com> Date: Fri, 8 Oct 2021 06:05:24 -0700 Subject: [PATCH 072/169] Edit help menu lua documentation link (#4520) --- Code/Tools/Standalone/Source/LUA/LUAEditorMainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Tools/Standalone/Source/LUA/LUAEditorMainWindow.cpp b/Code/Tools/Standalone/Source/LUA/LUAEditorMainWindow.cpp index c88ea59bdb..33d8373487 100644 --- a/Code/Tools/Standalone/Source/LUA/LUAEditorMainWindow.cpp +++ b/Code/Tools/Standalone/Source/LUA/LUAEditorMainWindow.cpp @@ -395,7 +395,7 @@ namespace LUAEditor void LUAEditorMainWindow::OnLuaDocumentation() { - QDesktopServices::openUrl(QUrl("http://docs.aws.amazon.com/lumberyard/latest/developerguide/lua-scripting-intro.html")); + QDesktopServices::openUrl(QUrl("https://o3de.org/docs/user-guide/scripting/lua/")); } void LUAEditorMainWindow::OnMenuCloseCurrentWindow() From dcadfe6e1f0138d8e1bb210c6c6f9f8352591787 Mon Sep 17 00:00:00 2001 From: Allen Jackson <23512001+jackalbe@users.noreply.github.com> Date: Fri, 8 Oct 2021 09:20:17 -0500 Subject: [PATCH 073/169] Feature json assetloading assethints (#4554) * capture assets using SerializedAssetTracker in LoadInstanceFromPrefabDom() assign assets using asset hints where the asset ID is not valid switch up SerializedAssetTracker to store pointers instead of copies of Asset<> Signed-off-by: jackalbe <23512001+jackalbe@users.noreply.github.com> * PoC for the AssetFixUp strategy Signed-off-by: jackalbe <23512001+jackalbe@users.noreply.github.com> * clean up of PoC Signed-off-by: jackalbe <23512001+jackalbe@users.noreply.github.com> --- .../AzCore/Asset/AssetJsonSerializer.cpp | 17 +++++++++- .../AzCore/AzCore/Asset/AssetJsonSerializer.h | 7 +++- .../Prefab/PrefabDomUtils.cpp | 32 +++++++++++++++++-- 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.cpp b/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.cpp index 3a83aa5d1c..3fa3b39ca5 100644 --- a/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.cpp +++ b/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.cpp @@ -173,6 +173,7 @@ namespace AZ if (assetTracker) { + assetTracker->FixUpAsset(*instance); assetTracker->AddAsset(*instance); } @@ -185,7 +186,20 @@ namespace AZ return context.Report(result, message); } - void SerializedAssetTracker::AddAsset(Asset& asset) + void SerializedAssetTracker::SetAssetFixUp(AssetFixUp assetFixUpCallback) + { + m_assetFixUpCallback = AZStd::move(assetFixUpCallback); + } + + void SerializedAssetTracker::FixUpAsset(Asset& asset) + { + if (m_assetFixUpCallback) + { + m_assetFixUpCallback(asset); + } + } + + void SerializedAssetTracker::AddAsset(Asset asset) { m_serializedAssets.emplace_back(asset); } @@ -199,5 +213,6 @@ namespace AZ { return m_serializedAssets; } + } // namespace Data } // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.h b/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.h index 879952c82d..e1b8cda00d 100644 --- a/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.h +++ b/Code/Framework/AzCore/AzCore/Asset/AssetJsonSerializer.h @@ -39,13 +39,18 @@ namespace AZ { public: AZ_RTTI(SerializedAssetTracker, "{1E067091-8C0A-44B1-A455-6E97663F6963}"); + using AssetFixUp = AZStd::function& asset)>; - void AddAsset(Asset& asset); + void SetAssetFixUp(AssetFixUp assetFixUpCallback); + void FixUpAsset(Asset& asset); + + void AddAsset(Asset asset); AZStd::vector>& GetTrackedAssets(); const AZStd::vector>& GetTrackedAssets() const; private: AZStd::vector> m_serializedAssets; + AssetFixUp m_assetFixUpCallback; }; } // namespace Data } // namespace AZ diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp index f60759f77e..ea0fa55256 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabDomUtils.cpp @@ -224,6 +224,7 @@ namespace AzToolsFramework return false; } + AZ::Data::SerializedAssetTracker* assetTracker = settings.m_metadata.Find(); referencedAssets = AZStd::move(assetTracker->GetTrackedAssets()); @@ -245,6 +246,30 @@ namespace AzToolsFramework entityIdMapper.SetEntityIdGenerationApproach(InstanceEntityIdMapper::EntityIdGenerationApproach::Random); } + // some assets may come in from the JSON serialzier with no AssetID, but have an asset hint + // this attempts to fix up the assets using the assetHint field + auto fixUpInvalidAssets = [](AZ::Data::Asset& asset) + { + if (!asset.GetId().IsValid() && !asset.GetHint().empty()) + { + AZ::Data::AssetId assetId; + AZ::Data::AssetCatalogRequestBus::BroadcastResult( + assetId, + &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, + asset.GetHint().c_str(), + AZ::Data::s_invalidAssetType, + false); + + if (assetId.IsValid()) + { + asset.Create(assetId, true); + } + } + }; + + auto tracker = AZ::Data::SerializedAssetTracker{}; + tracker.SetAssetFixUp(fixUpInvalidAssets); + AZ::JsonDeserializerSettings settings; // The InstanceEntityIdMapper is registered twice because it's used in several places during deserialization where one is // specific for the InstanceEntityIdMapper and once for the generic JsonEntityIdMapper. Because the Json Serializer's meta @@ -252,16 +277,17 @@ namespace AzToolsFramework settings.m_metadata.Add(static_cast(&entityIdMapper)); settings.m_metadata.Add(&entityIdMapper); settings.m_metadata.Create(newlyAddedEntities); + settings.m_metadata.Add(tracker); AZStd::string scratchBuffer; auto issueReportingCallback = [&scratchBuffer]( - AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, - AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode + AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, + AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode { return Internal::JsonIssueReporter(scratchBuffer, message, result, path); }; settings.m_reporting = AZStd::move(issueReportingCallback); - + AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::Load(instance, prefabDom, settings); AZ::Data::AssetManager::Instance().ResumeAssetRelease(); From 06953bb81f57ade284f1bc4daaa03ab93c8b9b7c Mon Sep 17 00:00:00 2001 From: nggieber Date: Fri, 8 Oct 2021 08:14:28 -0700 Subject: [PATCH 074/169] More PR changes Signed-off-by: nggieber --- scripts/o3de/o3de/manifest.py | 41 ++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/scripts/o3de/o3de/manifest.py b/scripts/o3de/o3de/manifest.py index 32bab05de8..5d34c4bcf9 100644 --- a/scripts/o3de/o3de/manifest.py +++ b/scripts/o3de/o3de/manifest.py @@ -421,31 +421,34 @@ def get_templates_for_generic_creation(): # temporary until we have a better wa return list(filter(filter_project_and_gem_templates_out, get_all_templates())) -def get_json_file_path(object_typename: str = None, +def get_json_file_path(object_typename: str, object_path: str or pathlib.Path = None) -> pathlib.Path: if not object_typename: - logger.error(f'Missing object typename.') + logger.error('Missing object typename.') + return None if not object_path: - logger.error(f'{object_typename} Path {object_path} has not been registered.') return None object_path = pathlib.Path(object_path).resolve() return object_path / f'{object_typename}.json' -def get_json_data_file(object_typename: str = None, - object_json: str or pathlib.Path = None, +def get_json_data_file(object_json: pathlib.Path, + object_typename: str = None, object_validator = callable) -> dict or None: if not object_typename: - logger.error(f'Missing object typename.') + logger.error('Missing object typename.') + + if not object_json: + logger.error(f'No object_json provided for {object_typename}') if not object_json.is_file(): logger.error(f'{object_typename} json {object_json} is not present.') return None if not object_validator: - logger.error(f'Missing object validator.') + logger.error('Missing object validator.') if not object_validator(object_json): logger.error(f'{object_typename} json {object_json} is not valid.') @@ -463,10 +466,14 @@ def get_json_data_file(object_typename: str = None, def get_json_data(object_typename: str = None, object_path: str or pathlib.Path = None, - object_validator = callable) -> dict or None: + object_validator = callable, + object_name: str = None) -> dict or None: object_json = get_json_file_path(object_typename, object_path) - return get_json_data_file(object_typename, object_json, object_validator) + if not object_json and object_name: + logger.error(f'{object_name} has not been registered.') + + return get_json_data_file(object_json, object_typename, object_validator) def get_engine_json_data(engine_name: str = None, @@ -478,7 +485,7 @@ def get_engine_json_data(engine_name: str = None, if engine_name and not engine_path: engine_path = get_registered(engine_name=engine_name) - return get_json_data('engine', engine_path, validation.valid_o3de_engine_json) + return get_json_data('engine', engine_path, validation.valid_o3de_engine_json, engine_name) def get_project_json_data(project_name: str = None, @@ -490,7 +497,7 @@ def get_project_json_data(project_name: str = None, if project_name and not project_path: project_path = get_registered(project_name=project_name) - return get_json_data('project', project_path, validation.valid_o3de_project_json) + return get_json_data('project', project_path, validation.valid_o3de_project_json, project_name) def get_gem_json_data(gem_name: str = None, gem_path: str or pathlib.Path = None, @@ -502,7 +509,7 @@ def get_gem_json_data(gem_name: str = None, gem_path: str or pathlib.Path = None if gem_name and not gem_path: gem_path = get_registered(gem_name=gem_name, project_path=project_path) - return get_json_data('gem', gem_path, validation.valid_o3de_gem_json) + return get_json_data('gem', gem_path, validation.valid_o3de_gem_json, gem_name) def get_template_json_data(template_name: str = None, template_path: str or pathlib.Path = None, @@ -514,7 +521,7 @@ def get_template_json_data(template_name: str = None, template_path: str or path if template_name and not template_path: template_path = get_registered(template_name=template_name, project_path=project_path) - return get_json_data('template', template_path, validation.valid_o3de_template_json) + return get_json_data('template', template_path, validation.valid_o3de_template_json, template_name) def get_restricted_json_data(restricted_name: str = None, restricted_path: str or pathlib.Path = None, @@ -526,18 +533,18 @@ def get_restricted_json_data(restricted_name: str = None, restricted_path: str o if restricted_name and not restricted_path: restricted_path = get_registered(restricted_name=restricted_name, project_path=project_path) - return get_json_data('restricted', restricted_path, validation.valid_o3de_restricted_json) + return get_json_data('restricted', restricted_path, validation.valid_o3de_restricted_json, restricted_name) -def get_repo_json_data(repo_uri: str = None) -> dict or None: +def get_repo_json_data(repo_uri: str) -> dict or None: if not repo_uri: logger.error('Must specify a Repo Uri.') return None repo_json = get_repo_path(repo_uri=repo_uri) - get_json_data_file("Repo", repo_json, validation.valid_o3de_repo_json) + return get_json_data_file(repo_json, "Repo", validation.valid_o3de_repo_json) -def get_repo_path(repo_uri: str = None, cache_folder: str = None) -> pathlib.Path: +def get_repo_path(repo_uri: str, cache_folder: str = None) -> pathlib.Path: if not cache_folder: cache_folder = get_o3de_cache_folder() From c562f0a80719b7ddc73544d5f6fd0cd03d5a23f8 Mon Sep 17 00:00:00 2001 From: greerdv Date: Fri, 8 Oct 2021 16:56:53 +0100 Subject: [PATCH 075/169] small improvements to triangle mesh rigid body warning Signed-off-by: greerdv --- .../Components/Widgets/CardNotification.cpp | 3 +++ .../Code/Source/EditorColliderComponent.cpp | 17 +++++++++++++---- .../Code/Source/EditorRigidBodyComponent.cpp | 12 ++++++++++-- .../Code/Source/EditorRigidBodyComponent.h | 2 ++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/CardNotification.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/CardNotification.cpp index d9451949ea..d2144457c8 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/CardNotification.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/CardNotification.cpp @@ -33,6 +33,9 @@ namespace AzQtComponents titleLabel->setObjectName("Title"); titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); titleLabel->setWordWrap(true); + titleLabel->setTextFormat(Qt::RichText); + titleLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); + titleLabel->setOpenExternalLinks(true); QHBoxLayout* headerLayout = new QHBoxLayout(headerFrame); headerLayout->setSizeConstraint(QLayout::SetMinimumSize); diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp index 7c07ca207c..7cc69caeb7 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -791,6 +792,7 @@ namespace PhysX if (shapes.empty()) { m_componentWarnings.clear(); + AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree); return; @@ -824,9 +826,16 @@ namespace PhysX } m_componentWarnings.push_back(AZStd::string::format( - "The Physics Asset \"%s\" is a Triangle Mesh, it is not compatible with a Dynamic Rigidbody, either:\n" - "Change the PhysicsAsset to Convex Mesh or set the Rigidbody to kinematic.", + "The asset \"%s\" contains one or more triangle meshes, which are not compatible with non-kinematic dynamic " + "rigid bodies. To make the collider compatible, you can export the asset as a primitive or convex mesh, use mesh " + "decomposition when exporting the asset, or set the rigid body to kinematic. Learn more about " + "colliders.", assetPath.c_str())); + + // make sure the entity inspector scrolls so the warning is visible by marking this component as having + // new content + AzToolsFramework::EntityPropertyEditorRequestBus::Broadcast( + &AzToolsFramework::EntityPropertyEditorRequests::SetNewComponentId, GetId()); } else { @@ -839,8 +848,8 @@ namespace PhysX } AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast( - &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree); - + &AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, + m_componentWarnings.empty() ? AzToolsFramework::Refresh_EntireTree : AzToolsFramework::Refresh_EntireTree_NewContent); } void EditorColliderComponent::OnAssetReloaded(AZ::Data::Asset asset) diff --git a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp index 447c2755c6..24b2586c9e 100644 --- a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.cpp @@ -103,7 +103,6 @@ namespace PhysX } } // namespace Internal - void EditorRigidBodyConfiguration::Reflect(AZ::ReflectContext* context) { auto serializeContext = azrtti_cast(context); @@ -310,6 +309,15 @@ namespace PhysX } } + void EditorRigidBodyComponent::OnConfigurationChanged() + { + CreateEditorWorldRigidBody(); + + // required in case the kinematic setting has changed + PhysX::EditorColliderValidationRequestBus::Event( + GetEntityId(), &PhysX::EditorColliderValidationRequestBus::Events::ValidateRigidBodyMeshGeometryType); + } + void EditorRigidBodyComponent::Reflect(AZ::ReflectContext* context) { EditorRigidBodyConfiguration::Reflect(context); @@ -336,7 +344,7 @@ namespace PhysX ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/physx/rigid-body-physics/") ->DataElement(0, &EditorRigidBodyComponent::m_config, "Configuration", "Configuration for rigid body physics.") ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorRigidBodyComponent::CreateEditorWorldRigidBody) + ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorRigidBodyComponent::OnConfigurationChanged) ; } } diff --git a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.h b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.h index 5d63ec9705..ed147ad8cb 100644 --- a/Gems/PhysX/Code/Source/EditorRigidBodyComponent.h +++ b/Gems/PhysX/Code/Source/EditorRigidBodyComponent.h @@ -120,6 +120,8 @@ namespace PhysX void InitPhysicsTickHandler(); void PrePhysicsTick(); + void OnConfigurationChanged(); + Debug::DebugDisplayDataChangedEvent::Handler m_debugDisplayDataChangeHandler; EditorRigidBodyConfiguration m_config; From e256df3f05c778d7ddad16471b18aa87fb504a54 Mon Sep 17 00:00:00 2001 From: brianherrera Date: Fri, 8 Oct 2021 10:05:50 -0700 Subject: [PATCH 076/169] Add retry config to boto3 clients This change makes the inc_build_util script more resilient against transient network issues and issues encountered during node boot-up. Signed-off-by: brianherrera --- .../build/bootstrap/incremental_build_util.py | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/scripts/build/bootstrap/incremental_build_util.py b/scripts/build/bootstrap/incremental_build_util.py index 101e31b5db..5c77559085 100644 --- a/scripts/build/bootstrap/incremental_build_util.py +++ b/scripts/build/bootstrap/incremental_build_util.py @@ -18,6 +18,8 @@ from contextlib import contextmanager import threading import _thread +from botocore.config import Config + DEFAULT_REGION = 'us-west-2' DEFAULT_DISK_SIZE = 300 DEFAULT_DISK_TYPE = 'gp2' @@ -173,10 +175,27 @@ def get_region_name(): def get_ec2_client(region): - client = boto3.client('ec2', region_name=region) + client_config = Config( + region_name=region, + retries={ + 'mode': 'standard' + } + ) + client = boto3.client('ec2', config=client_config) return client +def get_ec2_resource(region): + resource_config = Config( + region_name=region, + retries={ + 'mode': 'standard' + } + ) + resource = boto3.resource('ec2', config=resource_config) + return resource + + def get_ec2_instance_id(): try: instance_id = urllib.request.urlopen('http://169.254.169.254/latest/meta-data/instance-id').read() @@ -395,14 +414,11 @@ def detach_volume_from_ec2_instance(volume, ec2_instance_id, force, timeout_dura def mount_ebs(snapshot_hint, repository_name, project, pipeline, branch, platform, build_type, disk_size, disk_type): - session = boto3.session.Session() - region = session.region_name - if region is None: - region = DEFAULT_REGION + region = get_region_name() ec2_client = get_ec2_client(region) ec2_instance_id = get_ec2_instance_id() ec2_availability_zone = get_availability_zone() - ec2_resource = boto3.resource('ec2', region_name=region) + ec2_resource = get_ec2_resource(region) ec2_instance = ec2_resource.Instance(ec2_instance_id) for volume in ec2_instance.volumes.all(): @@ -469,7 +485,7 @@ def mount_ebs(snapshot_hint, repository_name, project, pipeline, branch, platfor def unmount_ebs(): region = get_region_name() ec2_instance_id = get_ec2_instance_id() - ec2_resource = boto3.resource('ec2', region_name=region) + ec2_resource = get_ec2_resource(region) ec2_instance = ec2_resource.Instance(ec2_instance_id) if os.path.isfile('envinject.properties'): From a5cd1b55e4c19b133f6c55fd858c27298cb9c282 Mon Sep 17 00:00:00 2001 From: Junbo Liang <68558268+junbo75@users.noreply.github.com> Date: Fri, 8 Oct 2021 10:37:50 -0700 Subject: [PATCH 077/169] Make the access log bucket optional in the AWSCore CDK application (#4553) * Make the access log bucket optional in the AWSCore CDK application Signed-off-by: Junbo Liang --- Gems/AWSCore/cdk/README.md | 10 +++++ Gems/AWSCore/cdk/app.py | 5 ++- Gems/AWSCore/cdk/core/core_stack.py | 37 ++++++++++--------- .../cdk/example/example_resources_stack.py | 18 +++++---- .../Windows/deploy_cdk_applications.cmd | 2 +- 5 files changed, 44 insertions(+), 28 deletions(-) diff --git a/Gems/AWSCore/cdk/README.md b/Gems/AWSCore/cdk/README.md index e4c0335c9c..d50ca40279 100644 --- a/Gems/AWSCore/cdk/README.md +++ b/Gems/AWSCore/cdk/README.md @@ -64,6 +64,16 @@ To add additional dependencies, for example other CDK libraries, just add them to your `setup.py` file and rerun the `pip install -r requirements.txt` command. +## Optional Features +Server access logging is enabled by default. To disable the feature, use the following commands to synthesize and deploy this CDK application. + +``` +$ cdk synth -c disable_access_log=true --all +$ cdk deploy -c disable_access_log=true --all +``` + +See https://docs.aws.amazon.com/AmazonS3/latest/userguide/ServerLogs.html for more information about server access logging. + ## Useful commands * `cdk ls` list all stacks in the app diff --git a/Gems/AWSCore/cdk/app.py b/Gems/AWSCore/cdk/app.py index 16773b5f69..9a401033ef 100755 --- a/Gems/AWSCore/cdk/app.py +++ b/Gems/AWSCore/cdk/app.py @@ -57,8 +57,9 @@ example_stack = ExampleResources( tags={Constants.O3DE_PROJECT_TAG_NAME: PROJECT_NAME, Constants.O3DE_FEATURE_TAG_NAME: FEATURE_NAME}, env=env ) -# -# Add the common stack as a dependency of the feature stack + +# Add the core stack as a dependency of the feature stack since the feature stack +# requires the core stack outputs for deployment. example_stack.add_dependency(core_construct.common_stack) app.synth() diff --git a/Gems/AWSCore/cdk/core/core_stack.py b/Gems/AWSCore/cdk/core/core_stack.py index fc1b4cf8d8..c124cb72ab 100755 --- a/Gems/AWSCore/cdk/core/core_stack.py +++ b/Gems/AWSCore/cdk/core/core_stack.py @@ -60,17 +60,6 @@ class CoreStack(core.Stack): type='TAG_FILTERS_1_0') ) - # Create an S3 bucket for Amazon S3 server access logging - # See https://docs.aws.amazon.com/AmazonS3/latest/dev/security-best-practices.html - self._server_access_logs_bucket = s3.Bucket( - self, - f'{self._project_name}-{self._feature_name}-Access-Log-Bucket', - block_public_access=s3.BlockPublicAccess.BLOCK_ALL, - encryption=s3.BucketEncryption.S3_MANAGED, - access_control=s3.BucketAccessControl.LOG_DELIVERY_WRITE - ) - self._server_access_logs_bucket.grant_read(self._admin_group) - # Define exports # Export resource group self._resource_group_output = core.CfnOutput( @@ -94,10 +83,22 @@ class CoreStack(core.Stack): export_name=f"{self._project_name}:AdminGroup", value=self._admin_group.group_arn) - # Export access log bucket name - self._server_access_logs_bucket_output = core.CfnOutput( - self, - id=f'ServerAccessLogsBucketOutput', - description='Name of the S3 bucket for storing server access logs generated by the sample CDK application(s)', - export_name=f"{self._project_name}:ServerAccessLogsBucket", - value=self._server_access_logs_bucket.bucket_name) + # Create an S3 bucket for Amazon S3 server access logging + # See https://docs.aws.amazon.com/AmazonS3/latest/dev/security-best-practices.html + if self.node.try_get_context('disable_access_log') != 'true': + self._server_access_logs_bucket = s3.Bucket( + self, + f'{self._project_name}-{self._feature_name}-Access-Log-Bucket', + block_public_access=s3.BlockPublicAccess.BLOCK_ALL, + encryption=s3.BucketEncryption.S3_MANAGED, + access_control=s3.BucketAccessControl.LOG_DELIVERY_WRITE + ) + self._server_access_logs_bucket.grant_read(self._admin_group) + + # Export access log bucket name + self._server_access_logs_bucket_output = core.CfnOutput( + self, + id=f'ServerAccessLogsBucketOutput', + description='Name of the S3 bucket for storing server access logs generated by the sample CDK application(s)', + export_name=f"{self._project_name}:ServerAccessLogsBucket", + value=self._server_access_logs_bucket.bucket_name) diff --git a/Gems/AWSCore/cdk/example/example_resources_stack.py b/Gems/AWSCore/cdk/example/example_resources_stack.py index 23bc78d8fc..ac229cb313 100755 --- a/Gems/AWSCore/cdk/example/example_resources_stack.py +++ b/Gems/AWSCore/cdk/example/example_resources_stack.py @@ -118,19 +118,23 @@ class ExampleResources(core.Stack): # https://docs.aws.amazon.com/AmazonS3/latest/userguide/serv-side-encryption.html # 3. Enable Amazon S3 server access logging # https://docs.aws.amazon.com/AmazonS3/latest/userguide/ServerLogs.html - server_access_logs_bucket = s3.Bucket.from_bucket_name( - self, - f'{self._project_name}-{self._feature_name}-ImportedAccessLogsBucket', - core.Fn.import_value(f"{self._project_name}:ServerAccessLogsBucket") - ) + server_access_logs_bucket = None + if self.node.try_get_context('disable_access_log') != 'true': + server_access_logs_bucket = s3.Bucket.from_bucket_name( + self, + f'{self._project_name}-{self._feature_name}-ImportedAccessLogsBucket', + core.Fn.import_value(f"{self._project_name}:ServerAccessLogsBucket") + ) example_bucket = s3.Bucket( self, f'{self._project_name}-{self._feature_name}-Example-S3bucket', block_public_access=s3.BlockPublicAccess.BLOCK_ALL, encryption=s3.BucketEncryption.S3_MANAGED, - server_access_logs_bucket=server_access_logs_bucket, - server_access_logs_prefix=f'{self._project_name}-{self._feature_name}-{self.region}-AccessLogs' + server_access_logs_bucket= + server_access_logs_bucket if server_access_logs_bucket else None, + server_access_logs_prefix= + f'{self._project_name}-{self._feature_name}-{self.region}-AccessLogs' if server_access_logs_bucket else None ) s3_deployment.BucketDeployment( diff --git a/scripts/build/Platform/Windows/deploy_cdk_applications.cmd b/scripts/build/Platform/Windows/deploy_cdk_applications.cmd index 2845707923..54a2485360 100644 --- a/scripts/build/Platform/Windows/deploy_cdk_applications.cmd +++ b/scripts/build/Platform/Windows/deploy_cdk_applications.cmd @@ -57,7 +57,7 @@ IF ERRORLEVEL 1 ( exit /b 1 ) -CALL :DeployCDKApplication AWSCore --all +CALL :DeployCDKApplication AWSCore --all "-c disable_access_log=true" IF ERRORLEVEL 1 ( exit /b 1 ) From 960edf857da0fce5f57ab7f0049b56fcf394c439 Mon Sep 17 00:00:00 2001 From: Pip Potter <61438964+lmbr-pip@users.noreply.github.com> Date: Fri, 8 Oct 2021 11:20:09 -0700 Subject: [PATCH 078/169] LYN-4831: AWCore code cleanup pass, fixing issues with ResolvePath (#4538) Signed-off-by: rppotter --- .../Code/Include/Private/AWSCoreModule.h | 2 +- .../Configuration/AWSCoreConfiguration.h | 2 +- .../Credential/AWSDefaultCredentialHandler.h | 2 +- .../AWSCoreAttributionConsentDialog.h | 7 ++-- .../Attribution/AWSCoreAttributionConstant.h | 2 +- .../Private/Editor/UI/AWSCoreEditorMenu.h | 2 +- .../AWSResourceMappingManager.h | 2 +- .../Public/Framework/AWSApiClientJobConfig.h | 9 ++---- .../Code/Include/Public/Framework/AWSApiJob.h | 7 ++-- .../Public/Framework/AWSApiJobConfig.h | 7 ++-- .../Public/Framework/AWSApiRequestJob.h | 6 ++-- .../Public/Framework/HttpClientComponent.h | 4 +-- .../Include/Public/Framework/HttpRequestJob.h | 2 +- .../Public/Framework/JsonObjectHandler.h | 8 ++--- .../Include/Public/Framework/JsonWriter.h | 4 +-- .../Include/Public/Framework/RequestBuilder.h | 2 +- .../Public/Framework/ServiceClientJobConfig.h | 7 ++-- .../Public/Framework/ServiceRequestJob.h | 8 ++--- .../Framework/ServiceRequestJobConfig.h | 3 -- .../Source/AWSCoreEditorSystemComponent.cpp | 4 +-- .../AWSCoreAttributionConsentDialog.cpp | 3 +- .../Attribution/AWSCoreAttributionManager.cpp | 32 +++++++++++-------- .../Source/Editor/UI/AWSCoreEditorMenu.cpp | 4 +-- .../Code/Source/Framework/AWSApiJob.cpp | 4 --- .../Source/Framework/MultipartFormData.cpp | 2 +- .../Code/Source/Framework/RequestBuilder.cpp | 4 +++ .../AWSResourceMappingManager.cpp | 3 +- .../AWSScriptBehaviorDynamoDB.cpp | 2 +- .../Code/Tests/AWSCoreSystemComponentTest.cpp | 2 +- .../AWSCVarCredentialHandlerTest.cpp | 2 +- .../Tests/Credential/AWSCredentialBusTest.cpp | 16 +++++----- .../AWSDefaultCredentialHandlerTest.cpp | 2 +- .../Framework/AWSApiClientJobConfigTest.cpp | 5 +++ .../Framework/ServiceClientJobConfigTest.cpp | 2 +- .../AWSResourceMappingManagerTest.cpp | 4 +-- .../AWSResourceMappingUtilsTest.cpp | 6 ++-- .../AWSScriptBehaviorDynamoDBTest.cpp | 2 +- .../AWSScriptBehaviorLambdaTest.cpp | 2 +- .../ScriptCanvas/AWSScriptBehaviorS3Test.cpp | 2 +- .../Code/Tests/TestFramework/AWSCoreFixture.h | 4 +-- 40 files changed, 91 insertions(+), 102 deletions(-) diff --git a/Gems/AWSCore/Code/Include/Private/AWSCoreModule.h b/Gems/AWSCore/Code/Include/Private/AWSCoreModule.h index ae5b424e69..f03579a0dd 100644 --- a/Gems/AWSCore/Code/Include/Private/AWSCoreModule.h +++ b/Gems/AWSCore/Code/Include/Private/AWSCoreModule.h @@ -24,7 +24,7 @@ namespace AWSCore /** * Add required SystemComponents to the SystemEntity. */ - virtual AZ::ComponentTypeList GetRequiredSystemComponents() const override; + AZ::ComponentTypeList GetRequiredSystemComponents() const override; }; } diff --git a/Gems/AWSCore/Code/Include/Private/Configuration/AWSCoreConfiguration.h b/Gems/AWSCore/Code/Include/Private/Configuration/AWSCoreConfiguration.h index 9834f9ca38..dd9f22f04d 100644 --- a/Gems/AWSCore/Code/Include/Private/Configuration/AWSCoreConfiguration.h +++ b/Gems/AWSCore/Code/Include/Private/Configuration/AWSCoreConfiguration.h @@ -42,7 +42,7 @@ namespace AWSCore AWSCoreConfiguration(); - ~AWSCoreConfiguration() = default; + ~AWSCoreConfiguration() override = default; void ActivateConfig(); void DeactivateConfig(); diff --git a/Gems/AWSCore/Code/Include/Private/Credential/AWSDefaultCredentialHandler.h b/Gems/AWSCore/Code/Include/Private/Credential/AWSDefaultCredentialHandler.h index 7f021f5748..068addfc24 100644 --- a/Gems/AWSCore/Code/Include/Private/Credential/AWSDefaultCredentialHandler.h +++ b/Gems/AWSCore/Code/Include/Private/Credential/AWSDefaultCredentialHandler.h @@ -23,7 +23,7 @@ namespace AWSCore { public: AWSDefaultCredentialHandler(); - ~AWSDefaultCredentialHandler() = default; + ~AWSDefaultCredentialHandler() override = default; //! Activate handler and its credentials provider, make sure activation //! invoked after AWSNativeSDK init to avoid memory leak diff --git a/Gems/AWSCore/Code/Include/Private/Editor/Attribution/AWSCoreAttributionConsentDialog.h b/Gems/AWSCore/Code/Include/Private/Editor/Attribution/AWSCoreAttributionConsentDialog.h index c2194ccfb4..8a3445c742 100644 --- a/Gems/AWSCore/Code/Include/Private/Editor/Attribution/AWSCoreAttributionConsentDialog.h +++ b/Gems/AWSCore/Code/Include/Private/Editor/Attribution/AWSCoreAttributionConsentDialog.h @@ -15,13 +15,12 @@ namespace AWSCore { //! Defines AWSCoreAttributionConsent QT dialog as QT message box. - class AWSCoreAttributionConsentDialog : - public QMessageBox + class AWSCoreAttributionConsentDialog + : public QMessageBox { public: AZ_CLASS_ALLOCATOR(AWSCoreAttributionConsentDialog, AZ::SystemAllocator, 0); AWSCoreAttributionConsentDialog(); - virtual ~AWSCoreAttributionConsentDialog() = default; - + ~AWSCoreAttributionConsentDialog() override = default; }; } // namespace AWSCore diff --git a/Gems/AWSCore/Code/Include/Private/Editor/Attribution/AWSCoreAttributionConstant.h b/Gems/AWSCore/Code/Include/Private/Editor/Attribution/AWSCoreAttributionConstant.h index e8a034e8e9..49c533cef5 100644 --- a/Gems/AWSCore/Code/Include/Private/Editor/Attribution/AWSCoreAttributionConstant.h +++ b/Gems/AWSCore/Code/Include/Private/Editor/Attribution/AWSCoreAttributionConstant.h @@ -18,4 +18,4 @@ namespace AWSCore static constexpr char AwsAttributionAttributeKeyActiveAWSGems[] = "aws_gems"; static constexpr char AwsAttributionAttributeKeyTimestamp[] = "timestamp"; -} // namespace AWSCOre +} // namespace AWSCore diff --git a/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreEditorMenu.h b/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreEditorMenu.h index 39e96517a7..62f91d36ef 100644 --- a/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreEditorMenu.h +++ b/Gems/AWSCore/Code/Include/Private/Editor/UI/AWSCoreEditorMenu.h @@ -34,7 +34,7 @@ namespace AWSCore "Failed to launch Resource Mapping Tool, please check logs for details."; AWSCoreEditorMenu(const QString& text); - ~AWSCoreEditorMenu(); + ~AWSCoreEditorMenu() override; private: QAction* AddExternalLinkAction(const AZStd::string& name, const AZStd::string& url, const AZStd::string& icon = ""); diff --git a/Gems/AWSCore/Code/Include/Private/ResourceMapping/AWSResourceMappingManager.h b/Gems/AWSCore/Code/Include/Private/ResourceMapping/AWSResourceMappingManager.h index fbc37622bf..27ff275630 100644 --- a/Gems/AWSCore/Code/Include/Private/ResourceMapping/AWSResourceMappingManager.h +++ b/Gems/AWSCore/Code/Include/Private/ResourceMapping/AWSResourceMappingManager.h @@ -71,7 +71,7 @@ namespace AWSCore }; AWSResourceMappingManager(); - ~AWSResourceMappingManager() = default; + ~AWSResourceMappingManager() override = default; void ActivateManager(); void DeactivateManager(); diff --git a/Gems/AWSCore/Code/Include/Public/Framework/AWSApiClientJobConfig.h b/Gems/AWSCore/Code/Include/Public/Framework/AWSApiClientJobConfig.h index e991b2af7e..d14509550e 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/AWSApiClientJobConfig.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/AWSApiClientJobConfig.h @@ -64,9 +64,6 @@ namespace AWSCore /// Initialize an AwsApiClientJobConfig object. /// - /// \param DefaultConfigType - the type of the config object from which - /// default values will be taken. - /// /// \param defaultConfig - the config object that provides values when /// no override has been set in this object. The default is nullptr, which /// will cause a default value to be used. @@ -83,10 +80,10 @@ namespace AWSCore } } - virtual ~AwsApiClientJobConfig() = default; + ~AwsApiClientJobConfig() override = default; /// Gets a client initialized used currently applied settings. If - /// any settings change after first use, code must call + /// any settings change after first use, code must call /// ApplySettings before those changes will take effect. std::shared_ptr GetClient() override { @@ -112,7 +109,7 @@ namespace AWSCore } else { - // If no explict credenitals are provided then AWS C++ SDK will perform standard search + // If no explicit credentials are provided then AWS C++ SDK will perform standard search return std::make_shared(Aws::Auth::AWSCredentials(), GetClientConfiguration()); } } diff --git a/Gems/AWSCore/Code/Include/Public/Framework/AWSApiJob.h b/Gems/AWSCore/Code/Include/Public/Framework/AWSApiJob.h index 00949011cb..93fc75feed 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/AWSApiJob.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/AWSApiJob.h @@ -14,14 +14,12 @@ namespace AWSCore { - - /// Base class for all AWS jobs. Primarily exists so that + /// Base class for all AWS jobs. Primarily exists so that /// AwsApiJob::s_config can be used for settings that apply to /// all AWS jobs. class AwsApiJob : public AZ::Job { - public: // To use a different allocator, extend this class and use this macro. AZ_CLASS_ALLOCATOR(AwsApiJob, AZ::SystemAllocator, 0); @@ -33,11 +31,10 @@ namespace AWSCore protected: AwsApiJob(bool isAutoDelete, IConfig* config = GetDefaultConfig()); - virtual ~AwsApiJob(); + ~AwsApiJob() override = default; /// Used for error messages. static const char* COMPONENT_DISPLAY_NAME; - }; } // namespace AWSCore diff --git a/Gems/AWSCore/Code/Include/Public/Framework/AWSApiJobConfig.h b/Gems/AWSCore/Code/Include/Public/Framework/AWSApiJobConfig.h index 0f25c648d0..516b42c0dd 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/AWSApiJobConfig.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/AWSApiJobConfig.h @@ -96,9 +96,6 @@ namespace AWSCore /// Initialize an AwsApiClientJobConfig object. /// - /// \param DefaultConfigType - the type of the config object from which - /// default values will be taken. - /// /// \param defaultConfig - the config object that provides values when /// no override has been set in this object. The default is nullptr, which /// will cause a default value to be used. @@ -146,7 +143,7 @@ namespace AWSCore #endif Override caFile; - /// Applys settings changes made after first use. + /// Applies settings changes made after first use. virtual void ApplySettings(); ////////////////////////////////////////////////////////////////////////// @@ -217,7 +214,7 @@ namespace AWSCore : protected AWSCoreNotificationsBus::Handler { public: - ~AwsApiJobConfigHolder() + ~AwsApiJobConfigHolder() override { AWSCoreNotificationsBus::Handler::BusDisconnect(); } diff --git a/Gems/AWSCore/Code/Include/Public/Framework/AWSApiRequestJob.h b/Gems/AWSCore/Code/Include/Public/Framework/AWSApiRequestJob.h index c189e94f22..80ac6657ed 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/AWSApiRequestJob.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/AWSApiRequestJob.h @@ -145,10 +145,10 @@ namespace AWSCore AWS_API_REQUEST_TRAITS_TEMPLATE_DEFINITION_HELPER typename AWS_API_REQUEST_TRAITS_TEMPLATE_INSTANCE_HELPER::AsyncFunctionType AWS_API_REQUEST_TRAITS_TEMPLATE_INSTANCE_HELPER::AsyncFunction = _AsyncFunction; - /// Macro that simplifies the declaration of an AwsRequstJob that has a result. + /// Macro that simplifies the declaration of an AwsRequestJob that has a result. #define AWS_API_REQUEST_JOB(SERVICE, REQUEST) AWSCore::AwsApiRequestJob -/// Macro that simplifies the declaration of an AwsRequstJob that has no result. +/// Macro that simplifies the declaration of an AwsRequestJob that has no result. #define AWS_API_REQUEST_JOB_NO_RESULT(SERVICE, REQUEST) AWSCore::AwsApiRequestJob /// An Az::Job that that executes a specific AWS request. @@ -257,7 +257,7 @@ namespace AWSCore /// of request data until your running on the job's worker thread, /// instead of setting the request data before calling Start. /// - /// \param true if the request should be made. + /// \return true if the request should be made. virtual bool PrepareRequest() { return true; diff --git a/Gems/AWSCore/Code/Include/Public/Framework/HttpClientComponent.h b/Gems/AWSCore/Code/Include/Public/Framework/HttpClientComponent.h index f936e7f107..48b59cc56a 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/HttpClientComponent.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/HttpClientComponent.h @@ -39,7 +39,7 @@ namespace AWSCore : public AZ::ComponentBus { public: - virtual ~HttpClientComponentNotifications() {} + ~HttpClientComponentNotifications() override = default; virtual void OnHttpRequestSuccess(int responseCode, AZStd::string responseBody) {} virtual void OnHttpRequestFailure(int responseCode) {} }; @@ -55,7 +55,7 @@ namespace AWSCore { public: AZ_COMPONENT(HttpClientComponent, "{23ECDBDF-129A-4670-B9B4-1E0B541ACD61}"); - virtual ~HttpClientComponent() = default; + ~HttpClientComponent() override = default; void Init() override; void Activate() override; diff --git a/Gems/AWSCore/Code/Include/Public/Framework/HttpRequestJob.h b/Gems/AWSCore/Code/Include/Public/Framework/HttpRequestJob.h index 60bb0ffd34..b277340be9 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/HttpRequestJob.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/HttpRequestJob.h @@ -178,7 +178,7 @@ namespace AWSCore }; /// Override to process the response to the HTTP request before callbacks are fired. - /// WARNING: This gets called on the job's thread, so observe thread safety precations. + /// WARNING: This gets called on the job's thread, so observe thread safety precautions. virtual void ProcessResponse(const std::shared_ptr& response) { AZ_UNUSED(response); diff --git a/Gems/AWSCore/Code/Include/Public/Framework/JsonObjectHandler.h b/Gems/AWSCore/Code/Include/Public/Framework/JsonObjectHandler.h index 57eabe3593..e86db54bbf 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/JsonObjectHandler.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/JsonObjectHandler.h @@ -29,24 +29,24 @@ namespace AWSCore Ch Peek() const { int c = m_is.peek(); - return c == std::char_traits::eof() ? '\0' : (Ch)c; + return c == std::char_traits::eof() ? '\0' : static_cast(c); } Ch Take() { int c = m_is.get(); - return c == std::char_traits::eof() ? '\0' : (Ch)c; + return c == std::char_traits::eof() ? '\0' : static_cast(c); } size_t Tell() const { - return (size_t)m_is.tellg(); + return static_cast(m_is.tellg()); } Ch* PutBegin() { AZ_Assert(false, "Not Implemented"); - return 0; + return nullptr; } void Put(Ch) diff --git a/Gems/AWSCore/Code/Include/Public/Framework/JsonWriter.h b/Gems/AWSCore/Code/Include/Public/Framework/JsonWriter.h index 8b3f4d55b2..261907b7ec 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/JsonWriter.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/JsonWriter.h @@ -161,7 +161,7 @@ namespace AWSCore } /// Write JSON format content directly to the writer's output stream. - /// This can be used to efficently output static content. + /// This can be used to efficiently output static content. bool WriteJson(const Ch* json) { if (json) @@ -182,7 +182,7 @@ namespace AWSCore } /// Write an object. The object can implement a WriteJson function - /// or you can provide an GobalWriteJson template function + /// or you can provide an GlobalWriteJson template function /// specialization. template bool Object(const ObjectType& obj) diff --git a/Gems/AWSCore/Code/Include/Public/Framework/RequestBuilder.h b/Gems/AWSCore/Code/Include/Public/Framework/RequestBuilder.h index 1e4b7c34c2..c12e8b1d5c 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/RequestBuilder.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/RequestBuilder.h @@ -36,7 +36,7 @@ namespace AWSCore class RequestBuilder { public: - RequestBuilder() = default; + RequestBuilder(); /// Converts the provided object to JSON and sends it as the /// body of the request. The object can implement the following diff --git a/Gems/AWSCore/Code/Include/Public/Framework/ServiceClientJobConfig.h b/Gems/AWSCore/Code/Include/Public/Framework/ServiceClientJobConfig.h index 9082498e96..89141bb492 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/ServiceClientJobConfig.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/ServiceClientJobConfig.h @@ -20,7 +20,7 @@ namespace AWSCore { public: - virtual const AZStd::string GetServiceUrl() = 0; + virtual AZStd::string GetServiceUrl() = 0; }; /// Encapsulates what code needs to know about a service in order to @@ -81,9 +81,6 @@ namespace AWSCore /// Initialize an ServiceClientJobConfig object. /// - /// \param DefaultConfigType - the type of the config object from which - /// default values will be taken. - /// /// \param defaultConfig - the config object that provides values when /// no override has been set in this object. The default is nullptr, which /// will cause a default value to be used. @@ -102,7 +99,7 @@ namespace AWSCore /// This implementation assumes the caller will cache this value as /// needed. See it's use in ServiceRequestJobConfig. - const AZStd::string GetServiceUrl() override + AZStd::string GetServiceUrl() override { if (endpointOverride.has_value()) { diff --git a/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJob.h b/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJob.h index cd0686c2d0..c24387a7ba 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJob.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJob.h @@ -119,7 +119,7 @@ namespace AWSCore Error error; /// Determines if the AWS credentials, as supplied by the credentialsProvider from - /// the ServiceReqestJobConfig object (which defaults to the user's credentials), + /// the ServiceRequestJobConfig object (which defaults to the user's credentials), /// are used to sign the request. The default is true. Override this and return false /// if calling a public API and want to avoid the overhead of signing requests. bool UseAWSCredentials() { @@ -565,13 +565,11 @@ namespace AWSCore } AZStd::string requestContent; - AZStd::string responseContent; - - std::istreambuf_iterator eos; std::shared_ptr requestStream = response->GetOriginatingRequest().GetContentBody(); if (requestStream) { + std::istreambuf_iterator eos; requestStream->clear(); requestStream->seekg(0); requestContent = AZStd::string{ std::istreambuf_iterator(*requestStream.get()),eos }; @@ -584,7 +582,7 @@ namespace AWSCore Aws::IOStream& responseStream = response->GetResponseBody(); responseStream.clear(); responseStream.seekg(0); - responseContent = AZStd::string{ std::istreambuf_iterator(responseStream),responseEos }; + AZStd::string responseContent = AZStd::string{ std::istreambuf_iterator(responseStream), responseEos }; responseContent = EscapePercentCharsInString(responseContent); responseStream.seekg(0); diff --git a/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJobConfig.h b/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJobConfig.h index 10b14ed5af..6c4e884f49 100644 --- a/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJobConfig.h +++ b/Gems/AWSCore/Code/Include/Public/Framework/ServiceRequestJobConfig.h @@ -44,9 +44,6 @@ namespace AWSCore /// Initialize an ServiceRequestJobConfig object. /// - /// \param DefaultConfigType - the type of the config object from which - /// default values will be taken. - /// /// \param defaultConfig - the config object that provides values when /// no override has been set in this object. The default is nullptr, which /// will cause a default value to be used. diff --git a/Gems/AWSCore/Code/Source/AWSCoreEditorSystemComponent.cpp b/Gems/AWSCore/Code/Source/AWSCoreEditorSystemComponent.cpp index f4420cb40a..a522f71084 100644 --- a/Gems/AWSCore/Code/Source/AWSCoreEditorSystemComponent.cpp +++ b/Gems/AWSCore/Code/Source/AWSCoreEditorSystemComponent.cpp @@ -79,7 +79,7 @@ namespace AWSCore QMenuBar* menuBar = mainWindow->menuBar(); QList actionList = menuBar->actions(); QAction* insertPivot = nullptr; - for (QList::iterator itr = actionList.begin(); itr != actionList.end(); itr++) + for (QList::iterator itr = actionList.begin(); itr != actionList.end(); ++itr) { if (QString::compare((*itr)->text(), EDITOR_HELP_MENU_TEXT) == 0) { @@ -88,7 +88,7 @@ namespace AWSCore } } - auto menu = m_awsCoreEditorManager->GetAWSCoreEditorMenu(); + const auto menu = m_awsCoreEditorManager->GetAWSCoreEditorMenu(); if (insertPivot) { menuBar->insertMenu(insertPivot, menu); diff --git a/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionConsentDialog.cpp b/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionConsentDialog.cpp index 85912616c2..7ec9f9ea4f 100644 --- a/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionConsentDialog.cpp +++ b/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionConsentDialog.cpp @@ -35,8 +35,7 @@ namespace AWSCore this->setDefaultButton(QMessageBox::Save); this->button(QMessageBox::Cancel)->hide(); this->setIcon(QMessageBox::Information); - QGridLayout* layout = (QGridLayout*)this->layout(); - if (layout) + if (QGridLayout* layout = static_cast(this->layout())) { layout->setVerticalSpacing(20); layout->setHorizontalSpacing(10); diff --git a/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionManager.cpp b/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionManager.cpp index 712c083e7a..3b9352d250 100644 --- a/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionManager.cpp +++ b/Gems/AWSCore/Code/Source/Editor/Attribution/AWSCoreAttributionManager.cpp @@ -68,19 +68,19 @@ namespace AWSCore AZ_Assert(fileIO, "File IO is not initialized."); // Resolve path to editor_aws_preferences.setreg - AZStd::string editorAWSPreferencesFilePath = + const AZStd::string editorAWSPreferencesFilePath = AZStd::string::format("@user@/%s/%s", AZ::SettingsRegistryInterface::RegistryFolder, EditorAWSPreferencesFileName); - AZStd::array resolvedPathAWSPreference{}; - if (!fileIO->ResolvePath(editorAWSPreferencesFilePath.c_str(), resolvedPathAWSPreference.data(), resolvedPathAWSPreference.size())) + AZ::IO::FixedMaxPath resolvedPathAWSPreference; + if (!fileIO->ResolvePath(resolvedPathAWSPreference, AZ::IO::PathView(editorAWSPreferencesFilePath))) { - AZ_Warning("AWSAttributionManager", false, "Error resolving path %s", resolvedPathAWSPreference.data()); + AZ_Warning("AWSAttributionManager", false, "Error resolving path %s", resolvedPathAWSPreference.c_str()); return; } - if (fileIO->Exists(resolvedPathAWSPreference.data())) + if (fileIO->Exists(resolvedPathAWSPreference.c_str())) { m_settingsRegistry->MergeSettingsFile( - resolvedPathAWSPreference.data(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, ""); + resolvedPathAWSPreference.String(), AZ::SettingsRegistryInterface::Format::JsonMergePatch, ""); } } @@ -136,8 +136,8 @@ namespace AWSCore return true; } - AZStd::chrono::seconds lastSendTimeStamp = AZStd::chrono::seconds(lastSendTimeStampSeconds); - AZStd::chrono::seconds secondsSinceLastSend = + const AZStd::chrono::seconds lastSendTimeStamp = AZStd::chrono::seconds(lastSendTimeStampSeconds); + const AZStd::chrono::seconds secondsSinceLastSend = AZStd::chrono::duration_cast(AZStd::chrono::system_clock::now().time_since_epoch()) - lastSendTimeStamp; if (static_cast(secondsSinceLastSend.count()) >= delayInSeconds) { @@ -154,7 +154,7 @@ namespace AWSCore if (credentialResult.result) { std::shared_ptr provider = credentialResult.result; - auto creds = provider->GetAWSCredentials(); + const auto creds = provider->GetAWSCredentials(); if (!creds.IsEmpty()) { return true; @@ -200,9 +200,13 @@ namespace AWSCore AZ_Assert(fileIO, "File IO is not initialized."); // Resolve path to editor_aws_preferences.setreg - AZStd::string editorPreferencesFilePath = AZStd::string::format("@user@/%s/%s", AZ::SettingsRegistryInterface::RegistryFolder, EditorAWSPreferencesFileName); - AZStd::array resolvedPath {}; - fileIO->ResolvePath(editorPreferencesFilePath.c_str(), resolvedPath.data(), resolvedPath.size()); + const AZStd::string editorPreferencesFilePath = AZStd::string::format("@user@/%s/%s", AZ::SettingsRegistryInterface::RegistryFolder, EditorAWSPreferencesFileName); + AZ::IO::FixedMaxPath resolvedPathAWSPreference; + if (!fileIO->ResolvePath(resolvedPathAWSPreference, AZ::IO::PathView(editorPreferencesFilePath))) + { + AZ_Warning("AWSAttributionManager", false, "Error resolving path %s", editorPreferencesFilePath.c_str()); + return; + } AZ::SettingsRegistryMergeUtils::DumperSettings dumperSettings; dumperSettings.m_prettifyOutput = true; @@ -215,14 +219,14 @@ namespace AWSCore { AZ_Warning( "AWSAttributionManager", false, R"(Unable to save changes to the Editor AWS Preferences registry file at "%s"\n)", - resolvedPath.data()); + resolvedPathAWSPreference.c_str()); return; } bool saved {}; constexpr auto configurationMode = AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY; - if (AZ::IO::SystemFile outputFile; outputFile.Open(resolvedPath.data(), configurationMode)) + if (AZ::IO::SystemFile outputFile; outputFile.Open(resolvedPathAWSPreference.c_str(), configurationMode)) { saved = outputFile.Write(stringBuffer.data(), stringBuffer.size()) == stringBuffer.size(); } diff --git a/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreEditorMenu.cpp b/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreEditorMenu.cpp index d55510930e..6391dd94ee 100644 --- a/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreEditorMenu.cpp +++ b/Gems/AWSCore/Code/Source/Editor/UI/AWSCoreEditorMenu.cpp @@ -54,7 +54,7 @@ namespace AWSCore { if (m_resourceMappingToolWatcher->IsProcessRunning()) { - m_resourceMappingToolWatcher->TerminateProcess(AZ::u32(-1)); + m_resourceMappingToolWatcher->TerminateProcess(static_cast(-1)); } m_resourceMappingToolWatcher.reset(); } @@ -214,7 +214,7 @@ namespace AWSCore QMenu* AWSCoreEditorMenu::SetAWSFeatureSubMenu(const AZStd::string& menuText) { auto actionList = this->actions(); - for (QList::iterator itr = actionList.begin(); itr != actionList.end(); itr++) + for (QList::iterator itr = actionList.begin(); itr != actionList.end(); ++itr) { if (QString::compare((*itr)->text(), menuText.c_str()) == 0) { diff --git a/Gems/AWSCore/Code/Source/Framework/AWSApiJob.cpp b/Gems/AWSCore/Code/Source/Framework/AWSApiJob.cpp index f203506edd..34581e00ff 100644 --- a/Gems/AWSCore/Code/Source/Framework/AWSApiJob.cpp +++ b/Gems/AWSCore/Code/Source/Framework/AWSApiJob.cpp @@ -22,10 +22,6 @@ namespace AWSCore { } - AwsApiJob::~AwsApiJob() - { - } - AwsApiJob::Config* AwsApiJob::GetDefaultConfig() { static AwsApiJobConfigHolder s_configHolder{}; diff --git a/Gems/AWSCore/Code/Source/Framework/MultipartFormData.cpp b/Gems/AWSCore/Code/Source/Framework/MultipartFormData.cpp index ff4668a62b..47059ac156 100644 --- a/Gems/AWSCore/Code/Source/Framework/MultipartFormData.cpp +++ b/Gems/AWSCore/Code/Source/Framework/MultipartFormData.cpp @@ -49,7 +49,7 @@ namespace AWSCore { m_fileFields.emplace_back(FileField{ std::move(fieldName), std::move(fileName) , AZStd::vector{} }); m_fileFields.back().m_fileData.reserve(length); - m_fileFields.back().m_fileData.assign((const char*)bytes, (const char*)bytes + length); + m_fileFields.back().m_fileData.assign(static_cast(bytes), static_cast(bytes) + length); } void MultipartFormData::SetCustomBoundary(AZStd::string boundary) diff --git a/Gems/AWSCore/Code/Source/Framework/RequestBuilder.cpp b/Gems/AWSCore/Code/Source/Framework/RequestBuilder.cpp index 16a5163fc7..d32ec9d039 100644 --- a/Gems/AWSCore/Code/Source/Framework/RequestBuilder.cpp +++ b/Gems/AWSCore/Code/Source/Framework/RequestBuilder.cpp @@ -10,6 +10,10 @@ namespace AWSCore { + RequestBuilder::RequestBuilder() + : m_httpMethod(Aws::Http::HttpMethod::HTTP_GET) + { + } bool RequestBuilder::SetPathParameterUnescaped(const char* key, const char* value) { diff --git a/Gems/AWSCore/Code/Source/ResourceMapping/AWSResourceMappingManager.cpp b/Gems/AWSCore/Code/Source/ResourceMapping/AWSResourceMappingManager.cpp index c3d87bff86..faec07b19e 100644 --- a/Gems/AWSCore/Code/Source/ResourceMapping/AWSResourceMappingManager.cpp +++ b/Gems/AWSCore/Code/Source/ResourceMapping/AWSResourceMappingManager.cpp @@ -26,7 +26,6 @@ namespace AWSCore : m_status(Status::NotLoaded) , m_defaultAccountId("") , m_defaultRegion("") - , m_resourceMappings() { } @@ -164,7 +163,7 @@ namespace AWSCore m_defaultRegion = jsonDocument.FindMember(ResourceMappingRegionKeyName)->value.GetString(); auto resourceMappings = jsonDocument.FindMember(ResourceMappingResourcesKeyName)->value.GetObject(); - for (auto mappingIter = resourceMappings.MemberBegin(); mappingIter != resourceMappings.MemberEnd(); mappingIter++) + for (auto mappingIter = resourceMappings.MemberBegin(); mappingIter != resourceMappings.MemberEnd(); ++mappingIter) { auto mappingValue = mappingIter->value.GetObject(); if (mappingValue.MemberCount() != 0) diff --git a/Gems/AWSCore/Code/Source/ScriptCanvas/AWSScriptBehaviorDynamoDB.cpp b/Gems/AWSCore/Code/Source/ScriptCanvas/AWSScriptBehaviorDynamoDB.cpp index 4467cc5db7..4183997d4a 100644 --- a/Gems/AWSCore/Code/Source/ScriptCanvas/AWSScriptBehaviorDynamoDB.cpp +++ b/Gems/AWSCore/Code/Source/ScriptCanvas/AWSScriptBehaviorDynamoDB.cpp @@ -71,7 +71,7 @@ namespace AWSCore [](DynamoDBGetItemRequestJob* job) // OnSuccess handler { auto item = job->result.GetItem(); - if (item.size() > 0) + if (!item.empty()) { DynamoDBAttributeValueMap result; for (const auto& itermPair : item) diff --git a/Gems/AWSCore/Code/Tests/AWSCoreSystemComponentTest.cpp b/Gems/AWSCore/Code/Tests/AWSCoreSystemComponentTest.cpp index f9fff631f4..648648e945 100644 --- a/Gems/AWSCore/Code/Tests/AWSCoreSystemComponentTest.cpp +++ b/Gems/AWSCore/Code/Tests/AWSCoreSystemComponentTest.cpp @@ -40,7 +40,7 @@ public: AWSCoreNotificationsBus::Handler::BusConnect(); } - ~AWSCoreNotificationsBusMock() + ~AWSCoreNotificationsBusMock() override { AWSCoreNotificationsBus::Handler::BusDisconnect(); } diff --git a/Gems/AWSCore/Code/Tests/Credential/AWSCVarCredentialHandlerTest.cpp b/Gems/AWSCore/Code/Tests/Credential/AWSCVarCredentialHandlerTest.cpp index 73120d4adc..244c945af9 100644 --- a/Gems/AWSCore/Code/Tests/Credential/AWSCVarCredentialHandlerTest.cpp +++ b/Gems/AWSCore/Code/Tests/Credential/AWSCVarCredentialHandlerTest.cpp @@ -18,7 +18,7 @@ class AWSCVarCredentialHandlerTest { public: AWSCVarCredentialHandlerTest() = default; - virtual ~AWSCVarCredentialHandlerTest() = default; + ~AWSCVarCredentialHandlerTest() override = default; void SetUp() override { diff --git a/Gems/AWSCore/Code/Tests/Credential/AWSCredentialBusTest.cpp b/Gems/AWSCore/Code/Tests/Credential/AWSCredentialBusTest.cpp index 238b5c819c..82c8c84b81 100644 --- a/Gems/AWSCore/Code/Tests/Credential/AWSCredentialBusTest.cpp +++ b/Gems/AWSCore/Code/Tests/Credential/AWSCredentialBusTest.cpp @@ -36,14 +36,14 @@ public: m_credentialsProvider.reset(); } - int GetCredentialHandlerOrder() const + int GetCredentialHandlerOrder() const override { return 1; } - std::shared_ptr GetCredentialsProvider() + std::shared_ptr GetCredentialsProvider() override { - m_handlerCounter++; + ++m_handlerCounter; return m_credentialsProvider; } @@ -72,14 +72,14 @@ public: m_credentialsProvider.reset(); } - int GetCredentialHandlerOrder() const + int GetCredentialHandlerOrder() const override { return 2; } - std::shared_ptr GetCredentialsProvider() + std::shared_ptr GetCredentialsProvider() override { - m_handlerCounter++; + ++m_handlerCounter; return m_credentialsProvider; } @@ -115,10 +115,10 @@ public: TEST_F(AWSCredentialBusTest, GetCredentialsProvider_CallFromMultithread_GetExpectedCredentialsProviderAndNumberOfCalls) { - int testThreadNumber = 10; + constexpr int testThreadNumber = 10; AZStd::atomic actualEbusCalls = 0; AZStd::vector testThreadPool; - for (int index = 0; index < testThreadNumber; index++) + for (int index = 0; index < testThreadNumber; ++index) { testThreadPool.emplace_back(AZStd::thread([&]() { AWSCredentialResult result; diff --git a/Gems/AWSCore/Code/Tests/Credential/AWSDefaultCredentialHandlerTest.cpp b/Gems/AWSCore/Code/Tests/Credential/AWSDefaultCredentialHandlerTest.cpp index b3e2ec5738..af03afb337 100644 --- a/Gems/AWSCore/Code/Tests/Credential/AWSDefaultCredentialHandlerTest.cpp +++ b/Gems/AWSCore/Code/Tests/Credential/AWSDefaultCredentialHandlerTest.cpp @@ -49,7 +49,7 @@ class AWSDefaultCredentialHandlerTest { public: AWSDefaultCredentialHandlerTest() = default; - virtual ~AWSDefaultCredentialHandlerTest() = default; + ~AWSDefaultCredentialHandlerTest() override = default; void SetUp() override { diff --git a/Gems/AWSCore/Code/Tests/Framework/AWSApiClientJobConfigTest.cpp b/Gems/AWSCore/Code/Tests/Framework/AWSApiClientJobConfigTest.cpp index b49cdc6a71..db433062ad 100644 --- a/Gems/AWSCore/Code/Tests/Framework/AWSApiClientJobConfigTest.cpp +++ b/Gems/AWSCore/Code/Tests/Framework/AWSApiClientJobConfigTest.cpp @@ -23,6 +23,11 @@ class AWSApiClientJobConfigTest , public AWSCredentialRequestBus::Handler { public: + AWSApiClientJobConfigTest() + : m_credentialHandlerCounter(0) + { + } + void SetUp() override { AWSNativeSDKInit::InitializationManager::InitAwsApi(); diff --git a/Gems/AWSCore/Code/Tests/Framework/ServiceClientJobConfigTest.cpp b/Gems/AWSCore/Code/Tests/Framework/ServiceClientJobConfigTest.cpp index 7a45ffb739..9bc43482cd 100644 --- a/Gems/AWSCore/Code/Tests/Framework/ServiceClientJobConfigTest.cpp +++ b/Gems/AWSCore/Code/Tests/Framework/ServiceClientJobConfigTest.cpp @@ -84,7 +84,7 @@ class ServiceClientJobConfigTest void ReloadConfigFile(bool reloadConfigFileName = false) override { AZ_UNUSED(reloadConfigFileName); - }; + } }; TEST_F(ServiceClientJobConfigTest, GetServiceUrl_CreateServiceWithServiceNameOnly_GetExpectedFeatureServiceUrl) diff --git a/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp b/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp index d438a99f83..fb03dea4c0 100644 --- a/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp +++ b/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingManagerTest.cpp @@ -217,7 +217,7 @@ TEST_F(AWSResourceMappingManagerTest, ActivateManager_ParseValidConfigFile_Confi CreateTestConfigFile(TEST_VALID_RESOURCE_MAPPING_CONFIG_FILE); m_resourceMappingManager->ActivateManager(); - int testThreadNumber = 10; + constexpr int testThreadNumber = 10; AZStd::atomic actualEbusCalls = 0; AZStd::vector testThreadPool; for (int index = 0; index < testThreadNumber; index++) @@ -226,7 +226,7 @@ TEST_F(AWSResourceMappingManagerTest, ActivateManager_ParseValidConfigFile_Confi AZStd::string actualAccountId; AWSResourceMappingRequestBus::BroadcastResult(actualAccountId, &AWSResourceMappingRequests::GetDefaultAccountId); EXPECT_FALSE(actualAccountId.empty()); - actualEbusCalls++; + ++actualEbusCalls; })); } diff --git a/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingUtilsTest.cpp b/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingUtilsTest.cpp index 9c23615917..f1a90aa2ae 100644 --- a/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingUtilsTest.cpp +++ b/Gems/AWSCore/Code/Tests/ResourceMapping/AWSResourceMappingUtilsTest.cpp @@ -44,19 +44,19 @@ TEST_F(AWSResourceMappingUtilsTest, FormatRESTApiUrl_PassingInvalidRESTApiId_Ret { auto actualUrl = AWSResourceMappingUtils::FormatRESTApiUrl("", TEST_VALID_RESTAPI_REGION, TEST_VALID_RESTAPI_STAGE); - EXPECT_TRUE(actualUrl == ""); + EXPECT_TRUE(actualUrl.empty()); } TEST_F(AWSResourceMappingUtilsTest, FormatRESTApiUrl_PassingInvalidRESTApiRegion_ReturnEmptyResult) { auto actualUrl = AWSResourceMappingUtils::FormatRESTApiUrl(TEST_VALID_RESTAPI_ID, "", TEST_VALID_RESTAPI_STAGE); - EXPECT_TRUE(actualUrl == ""); + EXPECT_TRUE(actualUrl.empty()); } TEST_F(AWSResourceMappingUtilsTest, FormatRESTApiUrl_PassingInvalidRESTApiStage_ReturnEmptyResult) { auto actualUrl = AWSResourceMappingUtils::FormatRESTApiUrl(TEST_VALID_RESTAPI_ID, TEST_VALID_RESTAPI_REGION, ""); - EXPECT_TRUE(actualUrl == ""); + EXPECT_TRUE(actualUrl.empty()); } diff --git a/Gems/AWSCore/Code/Tests/ScriptCanvas/AWSScriptBehaviorDynamoDBTest.cpp b/Gems/AWSCore/Code/Tests/ScriptCanvas/AWSScriptBehaviorDynamoDBTest.cpp index 52b91c306d..e42e270bc2 100644 --- a/Gems/AWSCore/Code/Tests/ScriptCanvas/AWSScriptBehaviorDynamoDBTest.cpp +++ b/Gems/AWSCore/Code/Tests/ScriptCanvas/AWSScriptBehaviorDynamoDBTest.cpp @@ -23,7 +23,7 @@ public: AWSScriptBehaviorDynamoDBNotificationBus::Handler::BusConnect(); } - ~AWSScriptBehaviorDynamoDBNotificationBusHandlerMock() + ~AWSScriptBehaviorDynamoDBNotificationBusHandlerMock() override { AWSScriptBehaviorDynamoDBNotificationBus::Handler::BusDisconnect(); } diff --git a/Gems/AWSCore/Code/Tests/ScriptCanvas/AWSScriptBehaviorLambdaTest.cpp b/Gems/AWSCore/Code/Tests/ScriptCanvas/AWSScriptBehaviorLambdaTest.cpp index 299f4a95d6..42ccd6eddc 100644 --- a/Gems/AWSCore/Code/Tests/ScriptCanvas/AWSScriptBehaviorLambdaTest.cpp +++ b/Gems/AWSCore/Code/Tests/ScriptCanvas/AWSScriptBehaviorLambdaTest.cpp @@ -22,7 +22,7 @@ public: AWSScriptBehaviorLambdaNotificationBus::Handler::BusConnect(); } - ~AWSScriptBehaviorLambdaNotificationBusHandlerMock() + ~AWSScriptBehaviorLambdaNotificationBusHandlerMock() override { AWSScriptBehaviorLambdaNotificationBus::Handler::BusDisconnect(); } diff --git a/Gems/AWSCore/Code/Tests/ScriptCanvas/AWSScriptBehaviorS3Test.cpp b/Gems/AWSCore/Code/Tests/ScriptCanvas/AWSScriptBehaviorS3Test.cpp index 118174576c..34a0166e32 100644 --- a/Gems/AWSCore/Code/Tests/ScriptCanvas/AWSScriptBehaviorS3Test.cpp +++ b/Gems/AWSCore/Code/Tests/ScriptCanvas/AWSScriptBehaviorS3Test.cpp @@ -24,7 +24,7 @@ public: AWSScriptBehaviorS3NotificationBus::Handler::BusConnect(); } - ~AWSScriptBehaviorS3NotificationBusHandlerMock() + ~AWSScriptBehaviorS3NotificationBusHandlerMock() override { AWSScriptBehaviorS3NotificationBus::Handler::BusDisconnect(); } diff --git a/Gems/AWSCore/Code/Tests/TestFramework/AWSCoreFixture.h b/Gems/AWSCore/Code/Tests/TestFramework/AWSCoreFixture.h index a5c2bf6475..1d14484387 100644 --- a/Gems/AWSCore/Code/Tests/TestFramework/AWSCoreFixture.h +++ b/Gems/AWSCore/Code/Tests/TestFramework/AWSCoreFixture.h @@ -107,8 +107,8 @@ class AWSCoreFixture : public UnitTest::ScopedAllocatorSetupFixture { public: - AWSCoreFixture() {} - virtual ~AWSCoreFixture() = default; + AWSCoreFixture() = default; + ~AWSCoreFixture() override = default; void SetUp() override { From 73f8537030aaa5efd126c991e28e61c803fc560e Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Fri, 8 Oct 2021 11:41:46 -0700 Subject: [PATCH 079/169] Fix Issue saving new assets in Asset Editor on Linux (#4537) * Add helper function to apply a selected file filter from a file dialog to the result filename if needed * Add platform traits to restrict the use of the helper function on platforms that need to apply it * Fix building of file filters of multiple extensions for a file type Signed-off-by: Steve Pham --- .../Components/Widgets/FileDialog.cpp | 92 ++++++++++++++++++- .../Components/Widgets/FileDialog.h | 6 ++ .../Platform/Linux/platform_linux_files.cmake | 2 + .../Platform/Mac/platform_mac_files.cmake | 2 + .../Windows/platform_windows_files.cmake | 2 + .../AzQtComponents/Tests/FileDialogTests.cpp | 65 +++++++++++++ .../azqtcomponents_testing_files.cmake | 1 + Code/Framework/AzQtComponents/CMakeLists.txt | 5 + .../AzQtComponents_Traits_Linux.h | 11 +++ .../AzQtComponents_Traits_Platform.h | 10 ++ .../AzQtComponents_Traits_Mac.h | 11 +++ .../AzQtComponents_Traits_Platform.h | 10 ++ .../AzQtComponents_Traits_Platform.h | 10 ++ .../AzQtComponents_Traits_Windows.h | 11 +++ .../AssetEditor/AssetEditorWidget.cpp | 2 +- 15 files changed, 234 insertions(+), 6 deletions(-) create mode 100644 Code/Framework/AzQtComponents/AzQtComponents/Tests/FileDialogTests.cpp create mode 100644 Code/Framework/AzQtComponents/Platform/Linux/AzQtComponents/AzQtComponents_Traits_Linux.h create mode 100644 Code/Framework/AzQtComponents/Platform/Linux/AzQtComponents/AzQtComponents_Traits_Platform.h create mode 100644 Code/Framework/AzQtComponents/Platform/Mac/AzQtComponents/AzQtComponents_Traits_Mac.h create mode 100644 Code/Framework/AzQtComponents/Platform/Mac/AzQtComponents/AzQtComponents_Traits_Platform.h create mode 100644 Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/AzQtComponents_Traits_Platform.h create mode 100644 Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/AzQtComponents_Traits_Windows.h diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/FileDialog.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/FileDialog.cpp index d2d773ff93..3061ceedd5 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/FileDialog.cpp +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/FileDialog.cpp @@ -6,10 +6,11 @@ * */ +#include #include #include -#include +#include namespace AzQtComponents { @@ -24,7 +25,12 @@ namespace AzQtComponents // Trigger Qt's save filename dialog // If filePath isn't empty, it means we are prompting again because the filename was invalid, // so pass it instead of the directory so the filename is pre-filled in for the user - filePath = QFileDialog::getSaveFileName(parent, caption, (filePath.isEmpty()) ? dir : filePath, filter, selectedFilter, options); + QString localSelectedFilter; + filePath = QFileDialog::getSaveFileName(parent, caption, (filePath.isEmpty()) ? dir : filePath, filter, &localSelectedFilter, options); + if (selectedFilter) + { + *selectedFilter = localSelectedFilter; + } if (!filePath.isEmpty()) { @@ -32,15 +38,39 @@ namespace AzQtComponents QString fileName = fileInfo.fileName(); // Check if the filename has any invalid characters - QRegExp validFileNameRegex("^[a-zA-Z0-9_\\-./]*$"); - shouldPromptAgain = !validFileNameRegex.exactMatch(fileName); + QRegularExpression validFileNameRegex("^[a-zA-Z0-9_\\-./]*$"); + QRegularExpressionMatch validFileNameMatch = validFileNameRegex.match(fileName); // If the filename had invalid characters, then show a warning message and then we will re-prompt the save filename dialog - if (shouldPromptAgain) + if (!validFileNameMatch.hasMatch()) { QMessageBox::warning(parent, QObject::tr("Invalid filename"), QObject::tr("O3DE assets are restricted to alphanumeric characters, hyphens (-), underscores (_), and dots (.)\n\n%1").arg(fileName)); + shouldPromptAgain = true; + continue; } + else + { + shouldPromptAgain = false; + } +#if AZ_TRAIT_AZQTCOMPONENTS_FILE_DIALOG_APPLY_MISSING_EXTENSION + // If a filter was selected, then make sure that the resulting filename ends with that extension. On systems that use the default QFileDialog, + // the extension is not guaranteed to be set in the resulting filename + if (FileDialog::ApplyMissingExtension(localSelectedFilter, filePath)) + { + // If an extension had to be applied, then the file dialog did not handle the case of overwriting existing files. + // We need to check that condition before we proceed + QFileInfo updatedFilePath(filePath); + + if (updatedFilePath.exists()) + { + QMessageBox::StandardButton overwriteSelection = QMessageBox::question(parent, + QObject::tr("File exists"), + QObject::tr("%1 exists. Do you want to overwrite the existing file?").arg(updatedFilePath.fileName())); + shouldPromptAgain = (overwriteSelection == QMessageBox::No); + } + } +#endif // AZ_TRAIT_AZQTCOMPONENTS_FILE_DIALOG_APPLY_MISSING_EXTENSION } else { @@ -51,4 +81,56 @@ namespace AzQtComponents return filePath; } + + bool FileDialog::ApplyMissingExtension(const QString& selectedFilter, QString& filePath) + { + if (selectedFilter.isEmpty()) + { + return false; + } + + // According to the QT documentation for QFileDialog, the selected filter will come in the form + // ( .. ) + // + // For example: + // "Images (*.gif *.png *.jpg)" + // + // Extract the contents of the (s) inside the parenthesis and split them based on a whitespace or comma + const QRegularExpression filterContent(".*\\((?[^\\)]+)\\)"); + QRegularExpressionMatch filterContentMatch = filterContent.match(selectedFilter); + if (!filterContentMatch.hasMatch()) + { + return false; + } + QString filterExtensionsString = filterContentMatch.captured("filters"); + QStringList filterExtensionsFull = filterExtensionsString.split(" ", Qt::SkipEmptyParts); + if (filterExtensionsFull.length() <= 0) + { + return false; + } + + // If there are multiple suffixes in the selected filter, then default to the first one if a suffix needs to be appended + QString defaultSuffix = filterExtensionsFull[0].mid(1); + + // Iterate through the filter patterns to see if the current filename matches + QFileInfo fileInfo(filePath); + bool extensionNeeded = true; + for (const QString& filterExtensionFull : filterExtensionsFull) + { + QString wildcardExpression = QRegularExpression::wildcardToRegularExpression(filterExtensionFull); + QRegularExpression filterPattern(wildcardExpression, AZ_TRAIT_AZQTCOMPONENTS_FILE_DIALOG_FILTER_CASE_SENSITIVITY); + QRegularExpressionMatch filterPatternMatch = filterPattern.match(fileInfo.fileName()); + if (filterPatternMatch.hasMatch()) + { + // The filename matches one of the filter patterns already, the extension does not need to be added to the filename + extensionNeeded = false; + } + } + if (extensionNeeded) + { + // If the current (if any) suffix does not match, automatically add the default suffix for the selected filter + filePath.append(defaultSuffix); + } + return extensionNeeded; + } } // namespace AzQtComponents diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/FileDialog.h b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/FileDialog.h index 6b63404949..9f27431400 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/FileDialog.h +++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/Widgets/FileDialog.h @@ -24,6 +24,12 @@ namespace AzQtComponents static QString GetSaveFileName(QWidget* parent = nullptr, const QString& caption = QString(), const QString& dir = QString(), const QString& filter = QString(), QString* selectedFilter = nullptr, QFileDialog::Options options = QFileDialog::Options()); + + //! Helper method that parses a selected filter from Qt's QFileDialog::getSaveFileName and applies the + //! selected filter's extension to the filePath if it doesnt already have the extension. This is needed + //! on platforms that do not have a default file dialog (These platforms uses Qt's custom file dialog which will + //! not apply the filter's extension automatically on user entered filenames) + static bool ApplyMissingExtension(const QString& selectedFilter, QString& filePath); }; } // namespace AzQtComponents diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Linux/platform_linux_files.cmake b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Linux/platform_linux_files.cmake index 7f204e5022..ec71d7b508 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Linux/platform_linux_files.cmake +++ b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Linux/platform_linux_files.cmake @@ -12,4 +12,6 @@ set(FILES ../../Utilities/QtWindowUtilities_linux.cpp ../../Utilities/ScreenGrabber_linux.cpp ../../../Platform/Linux/AzQtComponents/Components/StyledDockWidget_Linux.cpp + ../../../Platform/Linux/AzQtComponents/AzQtComponents_Traits_Linux.h + ../../../Platform/Linux/AzQtComponents/AzQtComponents_Traits_Platform.h ) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Mac/platform_mac_files.cmake b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Mac/platform_mac_files.cmake index 50084d7a1e..18f9479289 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Mac/platform_mac_files.cmake +++ b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Mac/platform_mac_files.cmake @@ -12,4 +12,6 @@ set(FILES ../../Utilities/QtWindowUtilities_mac.mm ../../Utilities/ScreenGrabber_mac.mm ../../../Platform/Mac/AzQtComponents/Components/StyledDockWidget_Mac.cpp + ../../../Platform/Mac/AzQtComponents/AzQtComponents_Traits_Mac.h + ../../../Platform/Mac/AzQtComponents/AzQtComponents_Traits_Platform.h ) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Windows/platform_windows_files.cmake b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Windows/platform_windows_files.cmake index 37d1d0f390..ca4145ef35 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Windows/platform_windows_files.cmake +++ b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Windows/platform_windows_files.cmake @@ -17,4 +17,6 @@ set(FILES ../../Components/TitleBarOverdrawScreenHandler_win.h ../../Components/TitleBarOverdrawScreenHandler_win.cpp ../../../Platform/Windows/AzQtComponents/Components/StyledDockWidget_Windows.cpp + ../../../Platform/Windows/AzQtComponents/AzQtComponents_Traits_Windows.h + ../../../Platform/Windows/AzQtComponents/AzQtComponents_Traits_Platform.h ) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Tests/FileDialogTests.cpp b/Code/Framework/AzQtComponents/AzQtComponents/Tests/FileDialogTests.cpp new file mode 100644 index 0000000000..e3dc4b4f0d --- /dev/null +++ b/Code/Framework/AzQtComponents/AzQtComponents/Tests/FileDialogTests.cpp @@ -0,0 +1,65 @@ +/* + * 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 + +TEST(AzQtComponents, ApplyMissingExtension_UpdateMissingExtension_Success) +{ + const QString textFiler{"Text Files (*.txt)"}; + QString testPath{"testFile"}; + bool result = AzQtComponents::FileDialog::ApplyMissingExtension(textFiler, testPath); + EXPECT_TRUE(result); + EXPECT_STRCASEEQ("testFile.txt", testPath.toUtf8().constData()); +} + +TEST(AzQtComponents, ApplyMissingExtension_NoUpdateExistingExtension_Success) +{ + const QString textFiler{"Text Files (*.txt)"}; + QString testPath{"testFile.txt"}; + bool result = AzQtComponents::FileDialog::ApplyMissingExtension(textFiler, testPath); + EXPECT_FALSE(result); + EXPECT_STRCASEEQ("testFile.txt", testPath.toUtf8().constData()); +} + +TEST(AzQtComponents, ApplyMissingExtension_UpdateMissingExtensionMultipleExtensionFilter_Success) +{ + const QString textFiler{"Image Files (*.jpg *.bmp *.png)"}; + QString testPath{"testFile"}; + bool result = AzQtComponents::FileDialog::ApplyMissingExtension(textFiler, testPath); + EXPECT_TRUE(result); + EXPECT_STRCASEEQ("testFile.jpg", testPath.toUtf8().constData()); +} + +TEST(AzQtComponents, ApplyMissingExtension_NoUpdateMissingExtensionMultipleExtensionFilter_Success) +{ + const QString textFiler{"Image Files (*.jpg *.bmp *.png)"}; + QString testPath{"testFile.png"}; + bool result = AzQtComponents::FileDialog::ApplyMissingExtension(textFiler, testPath); + EXPECT_FALSE(result); + EXPECT_STRCASEEQ("testFile.png", testPath.toUtf8().constData()); +} + +TEST(AzQtComponents, ApplyMissingExtension_NoUpdateMissingExtensionEmptyFilter_Success) +{ + const QString textFiler{""}; + QString testPath{"testFile"}; + bool result = AzQtComponents::FileDialog::ApplyMissingExtension(textFiler, testPath); + EXPECT_FALSE(result); + EXPECT_STRCASEEQ("testFile", testPath.toUtf8().constData()); +} + +TEST(AzQtComponents, ApplyMissingExtension_NoUpdateMissingExtensionInvalidFilter_Success) +{ + const QString textFiler{"Bad Filter!!"}; + QString testPath{"testFile"}; + bool result = AzQtComponents::FileDialog::ApplyMissingExtension(textFiler, testPath); + EXPECT_FALSE(result); + EXPECT_STRCASEEQ("testFile", testPath.toUtf8().constData()); +} diff --git a/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_testing_files.cmake b/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_testing_files.cmake index 2611063305..b4ab487c79 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_testing_files.cmake +++ b/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_testing_files.cmake @@ -9,6 +9,7 @@ set(FILES Tests/AzQtComponentTests.cpp Tests/ColorControllerTests.cpp + Tests/FileDialogTests.cpp Tests/FloatToStringConversionTests.cpp Tests/HexParsingTests.cpp Tests/StyleSheetCacheTests.cpp diff --git a/Code/Framework/AzQtComponents/CMakeLists.txt b/Code/Framework/AzQtComponents/CMakeLists.txt index dd217a7be2..a24b68bcd7 100644 --- a/Code/Framework/AzQtComponents/CMakeLists.txt +++ b/Code/Framework/AzQtComponents/CMakeLists.txt @@ -10,6 +10,8 @@ if(NOT PAL_TRAIT_BUILD_HOST_TOOLS) return() endif() +ly_get_list_relative_pal_filename(pal_dir ${CMAKE_CURRENT_LIST_DIR}/Platform/${PAL_PLATFORM_NAME}) + ly_add_target( NAME AzQtComponents SHARED NAMESPACE AZ @@ -26,6 +28,7 @@ ly_add_target( AzQtComponents PUBLIC . + ${pal_dir} COMPILE_DEFINITIONS PRIVATE AZ_QT_COMPONENTS_EXPORT_SYMBOLS @@ -53,6 +56,7 @@ ly_add_target( . AzQtComponents AzQtComponents/Gallery + ${pal_dir} BUILD_DEPENDENCIES PRIVATE 3rdParty::Qt::Svg @@ -86,6 +90,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) PRIVATE Tests AzQtComponents + ${pal_dir} BUILD_DEPENDENCIES PRIVATE AZ::AzQtComponents diff --git a/Code/Framework/AzQtComponents/Platform/Linux/AzQtComponents/AzQtComponents_Traits_Linux.h b/Code/Framework/AzQtComponents/Platform/Linux/AzQtComponents/AzQtComponents_Traits_Linux.h new file mode 100644 index 0000000000..685ac4dfed --- /dev/null +++ b/Code/Framework/AzQtComponents/Platform/Linux/AzQtComponents/AzQtComponents_Traits_Linux.h @@ -0,0 +1,11 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#define AZ_TRAIT_AZQTCOMPONENTS_FILE_DIALOG_APPLY_MISSING_EXTENSION 1 +#define AZ_TRAIT_AZQTCOMPONENTS_FILE_DIALOG_FILTER_CASE_SENSITIVITY QRegularExpression::NoPatternOption diff --git a/Code/Framework/AzQtComponents/Platform/Linux/AzQtComponents/AzQtComponents_Traits_Platform.h b/Code/Framework/AzQtComponents/Platform/Linux/AzQtComponents/AzQtComponents_Traits_Platform.h new file mode 100644 index 0000000000..101fe3a494 --- /dev/null +++ b/Code/Framework/AzQtComponents/Platform/Linux/AzQtComponents/AzQtComponents_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/Code/Framework/AzQtComponents/Platform/Mac/AzQtComponents/AzQtComponents_Traits_Mac.h b/Code/Framework/AzQtComponents/Platform/Mac/AzQtComponents/AzQtComponents_Traits_Mac.h new file mode 100644 index 0000000000..1cb91ec09e --- /dev/null +++ b/Code/Framework/AzQtComponents/Platform/Mac/AzQtComponents/AzQtComponents_Traits_Mac.h @@ -0,0 +1,11 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#define AZ_TRAIT_AZQTCOMPONENTS_FILE_DIALOG_APPLY_MISSING_EXTENSION 0 +#define AZ_TRAIT_AZQTCOMPONENTS_FILE_DIALOG_FILTER_CASE_SENSITIVITY QRegularExpression::NoPatternOption diff --git a/Code/Framework/AzQtComponents/Platform/Mac/AzQtComponents/AzQtComponents_Traits_Platform.h b/Code/Framework/AzQtComponents/Platform/Mac/AzQtComponents/AzQtComponents_Traits_Platform.h new file mode 100644 index 0000000000..9b285476c1 --- /dev/null +++ b/Code/Framework/AzQtComponents/Platform/Mac/AzQtComponents/AzQtComponents_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/Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/AzQtComponents_Traits_Platform.h b/Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/AzQtComponents_Traits_Platform.h new file mode 100644 index 0000000000..2c3efc5e6c --- /dev/null +++ b/Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/AzQtComponents_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/Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/AzQtComponents_Traits_Windows.h b/Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/AzQtComponents_Traits_Windows.h new file mode 100644 index 0000000000..edba0043b4 --- /dev/null +++ b/Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/AzQtComponents_Traits_Windows.h @@ -0,0 +1,11 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ +#pragma once + +#define AZ_TRAIT_AZQTCOMPONENTS_FILE_DIALOG_APPLY_MISSING_EXTENSION 0 +#define AZ_TRAIT_AZQTCOMPONENTS_FILE_DIALOG_FILTER_CASE_SENSITIVITY QRegularExpression::CaseInsensitiveOption diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp index 8856989911..a159882f72 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/AssetEditor/AssetEditorWidget.cpp @@ -410,7 +410,7 @@ namespace AzToolsFramework filter.append(ext); if (i < n - 1) { - filter.append(", "); + filter.append(" "); } } filter.append(")"); From b7c2401056ba31bd7cea0b5609bc08195479dd51 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 8 Oct 2021 15:14:22 -0500 Subject: [PATCH 080/169] Added a ThreadDispatch Policy to the EBus code (#4405) * Added a ThreadDispatch Policy to the EBus code The ThreadDispatch Policy can be configured by authors of an EBusTraits to invoke a callback function after an EBus has finished it's dispatching mechanism on a specific thread. It takes into account recursive calls as well and will only invoke the PostDispatch callback after all callstack entries for the current thread are cleared. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Clang build fix The Traits type is dependent on the template parameter, therefore the compiler needs to be told that the ThreadDispatchPolicy is a type and not a value. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Fixed DispatchLockGuard cxall in the TerrainWorldRendererComponent.cpp Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Added EBusTrait for configuring the DispatchLockGuard Removed the ThreadPolicy trait, now that the DispatchLockGuard for the EBus Context can be configured. Used the DispatchLockGuard template along with the IsInDispatchThisThread function to determine when an EBus has finished dispatching on thread and released it's Context Mutex. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Tweaked comment format for the IsInDispatch function Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Removed explicit GetContext call from ThreadDispatchTestBus. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Clang EBus Test fix for DispatchLockGuard trait Due to the clang compiler evalating constants within templates at the time of declaration, the LocklessDispatch value supplied to the template was always false resulting in the LocklessDispatch feature always locking. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/EBus/BusImpl.h | 26 ++- Code/Framework/AzCore/AzCore/EBus/EBus.h | 35 +++- Code/Framework/AzCore/Tests/EBus.cpp | 201 +++++++++++++++++++- 3 files changed, 243 insertions(+), 19 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/EBus/BusImpl.h b/Code/Framework/AzCore/AzCore/EBus/BusImpl.h index 8e655c0525..e2b1c2e92b 100644 --- a/Code/Framework/AzCore/AzCore/EBus/BusImpl.h +++ b/Code/Framework/AzCore/AzCore/EBus/BusImpl.h @@ -160,8 +160,8 @@ namespace AZ /** * Locking primitive that is used when executing events in the event queue. */ - using EventQueueMutexType = typename AZStd::Utils::if_c::value, // if EventQueueMutexType==NullMutex use MutexType otherwise EventQueueMutexType - MutexType, typename Traits::EventQueueMutexType>::type; + using EventQueueMutexType = AZStd::conditional_t::value, // if EventQueueMutexType==NullMutex use MutexType otherwise EventQueueMutexType + MutexType, typename Traits::EventQueueMutexType>; /** * Pointer to an address on the bus. @@ -180,14 +180,22 @@ namespace AZ * `::ExecuteQueuedEvents()`. * By default, the event queue is disabled. */ - static const bool EnableEventQueue = Traits::EnableEventQueue; - static const bool EventQueueingActiveByDefault = Traits::EventQueueingActiveByDefault; - static const bool EnableQueuedReferences = Traits::EnableQueuedReferences; + static constexpr bool EnableEventQueue = Traits::EnableEventQueue; + static constexpr bool EventQueueingActiveByDefault = Traits::EventQueueingActiveByDefault; + static constexpr bool EnableQueuedReferences = Traits::EnableQueuedReferences; /** * True if the EBus supports more than one address. Otherwise, false. */ - static const bool HasId = Traits::AddressPolicy != EBusAddressPolicy::Single; + static constexpr bool HasId = Traits::AddressPolicy != EBusAddressPolicy::Single; + + /** + * Template Lock Guard class that wraps around the Mutex + * The EBus uses for Dispatching Events. + * This is not the EBus Context Mutex if LocklessDispatch is true + */ + template + using DispatchLockGuard = typename Traits::template DispatchLockGuard; }; /** @@ -460,7 +468,7 @@ namespace AZ using BusPtr = typename Traits::BusPtr; /** - * Helper to queue an event by BusIdType only when function queueing is enabled + * Helper to queue an event by BusIdType only when function queueing is enabled * @param id Address ID. Handlers that are connected to this ID will receive the event. * @param func Function pointer of the event to dispatch. * @param args Function arguments that are passed to each handler. @@ -581,7 +589,7 @@ namespace AZ , public EBusBroadcaster , public EBusEventer , public EBusEventEnumerator - , public AZStd::Utils::if_c, EBusNullQueue>::type + , public AZStd::conditional_t, EBusNullQueue> { }; @@ -599,7 +607,7 @@ namespace AZ : public EventDispatcher , public EBusBroadcaster , public EBusBroadcastEnumerator - , public AZStd::Utils::if_c, EBusNullQueue>::type + , public AZStd::conditional_t, EBusNullQueue> { }; diff --git a/Code/Framework/AzCore/AzCore/EBus/EBus.h b/Code/Framework/AzCore/AzCore/EBus/EBus.h index da8c880963..a3dc10b103 100644 --- a/Code/Framework/AzCore/AzCore/EBus/EBus.h +++ b/Code/Framework/AzCore/AzCore/EBus/EBus.h @@ -236,6 +236,17 @@ namespace AZ * code before or after an event. */ using EventProcessingPolicy = EBusEventProcessingPolicy; + + /** + * Template Lock Guard class that wraps around the Mutex + * The EBus Context uses the LockGuard when dispatching + * (either AZStd::scoped_lock or NullLockGuard) + * The IsLocklessDispatch bool is there to defer evaluation of the LocklessDispatch constant + * Otherwise the value above in EBusTraits.h is always used and not the value + * that the derived trait class sets. + */ + template + using DispatchLockGuard = AZStd::conditional_t, AZStd::scoped_lock>; }; namespace Internal @@ -496,6 +507,14 @@ namespace AZ */ static const bool HasId = Traits::AddressPolicy != EBusAddressPolicy::Single; + /** + * Template Lock Guard class that wraps around the Mutex + * The EBus uses for Dispatching Events. + * This is not EBus Context Mutex when LocklessDispatch is set + */ + template + using DispatchLockGuard = typename ImplTraits::template DispatchLockGuard; + ////////////////////////////////////////////////////////////////////////// // Check to help identify common mistakes /// @cond EXCLUDE_DOCS @@ -620,11 +639,11 @@ namespace AZ using ContextMutexType = AZStd::conditional_t, AZStd::shared_mutex, MutexType>; /** - * The scoped lock guard to use (either AZStd::scoped_lock or NullLockGuard + * The scoped lock guard to use * during broadcast/event dispatch. * @see EBusTraits::LocklessDispatch */ - using DispatchLockGuard = AZStd::conditional_t, AZStd::scoped_lock>; + using DispatchLockGuard = DispatchLockGuard; /** * The scoped lock guard to use during connection. Some specialized policies execute handler methods which @@ -704,6 +723,11 @@ namespace AZ static Context& GetOrCreateContext(bool trackCallstack=true); static bool IsInDispatch(Context* context = GetContext(false)); + + /** + * Returns whether the EBus context is in the middle of a dispatch on the current thread + */ + static bool IsInDispatchThisThread(Context* context = GetContext(false)); /// @cond EXCLUDE_DOCS struct RouterCallstackEntry : public CallstackEntry @@ -1208,6 +1232,13 @@ AZ_POP_DISABLE_WARNING return context != nullptr && context->m_dispatches > 0; } + template + bool EBus::IsInDispatchThisThread(Context* context) + { + return context != nullptr && context->s_callstack != nullptr + && context->s_callstack->m_prev != nullptr; + } + //========================================================================= template EBus::RouterCallstackEntry::RouterCallstackEntry(Iterator it, const BusIdType* busId, bool isQueued, bool isReverse) diff --git a/Code/Framework/AzCore/Tests/EBus.cpp b/Code/Framework/AzCore/Tests/EBus.cpp index 10216a0485..9acf0f8a05 100644 --- a/Code/Framework/AzCore/Tests/EBus.cpp +++ b/Code/Framework/AzCore/Tests/EBus.cpp @@ -2088,7 +2088,7 @@ namespace UnitTest DisconnectNextHandlerByIdImpl multiHandler2; multiHandler2.BusConnect(DisconnectNextHandlerByIdImpl::firstBusAddress); multiHandler2.BusConnect(DisconnectNextHandlerByIdImpl::secondBusAddress); - + // Set the first handler m_nextHandler field to point to the second handler multiHandler1.m_nextHandler = &multiHandler2; @@ -2807,7 +2807,7 @@ namespace UnitTest AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(m_val % m_maxSleep)); } } - + void DoConnect() override { MyEventGroupBus::Handler::BusConnect(m_id); @@ -2854,7 +2854,7 @@ namespace UnitTest } MyEventGroupBus::Event(id, &MyEventGroupBus::Events::Calculate, i, i * 2, i << 4); - + LocklessConnectorBus::Event(id, &LocklessConnectorBus::Events::DoDisconnect); bool failed = (AZStd::find_if(&sentinel[0], end, [](char s) { return s != 0; }) != end); @@ -2891,7 +2891,7 @@ namespace UnitTest { MyEventGroupImpl() { - + } ~MyEventGroupImpl() override @@ -3614,7 +3614,7 @@ namespace UnitTest { AZStd::this_thread::yield(); } - + EXPECT_GE(AZStd::chrono::system_clock::now(), endTime); }; AZStd::thread connectThread([&connectHandler, &waitHandler]() @@ -3813,7 +3813,7 @@ namespace UnitTest struct LastHandlerDisconnectHandler : public LastHandlerDisconnectBus::Handler { - void OnEvent() override + void OnEvent() override { ++m_numOnEvents; BusDisconnect(); @@ -3854,7 +3854,7 @@ namespace UnitTest struct DisconnectAssertHandler : public DisconnectAssertBus::Handler { - + }; TEST_F(EBus, HandlerDestroyedWithoutDisconnect_Asserts) @@ -3995,6 +3995,191 @@ namespace UnitTest idTestRequest.Disconnect(); } + + // IsInDispatchThisThread + struct IsInThreadDispatchRequests + : AZ::EBusTraits + { + using MutexType = AZStd::recursive_mutex; + }; + + using IsInThreadDispatchBus = AZ::EBus; + + class IsInThreadDispatchHandler + : public IsInThreadDispatchBus::Handler + {}; + + TEST_F(EBus, InvokingIsInThisThread_ReturnsSuccess_OnlyIfThreadIsInDispatch) + { + IsInThreadDispatchHandler handler; + handler.BusConnect(); + + auto ThreadDispatcher = [](IsInThreadDispatchRequests*) + { + EXPECT_TRUE(IsInThreadDispatchBus::IsInDispatchThisThread()); + auto PerThreadBusDispatch = []() + { + EXPECT_FALSE(IsInThreadDispatchBus::IsInDispatchThisThread()); + }; + AZStd::array threads{ AZStd::thread(PerThreadBusDispatch), AZStd::thread(PerThreadBusDispatch) }; + for (AZStd::thread& thread : threads) + { + thread.join(); + } + }; + + static constexpr size_t ThreadDispatcherIterations = 4; + for (size_t iteration = 0; iteration < ThreadDispatcherIterations; ++iteration) + { + EXPECT_FALSE(IsInThreadDispatchBus::IsInDispatchThisThread()); + IsInThreadDispatchBus::Broadcast(ThreadDispatcher); + EXPECT_FALSE(IsInThreadDispatchBus::IsInDispatchThisThread()); + } + } + + // Thread Dispatch Policy + struct ThreadDispatchTestBusTraits + : AZ::EBusTraits + { + using MutexType = AZStd::recursive_mutex; + + struct PostThreadDispatchTestInvoker + { + ~PostThreadDispatchTestInvoker(); + }; + + template + struct ThreadDispatchTestLockGuard + { + ThreadDispatchTestLockGuard(DispatchMutex& contextMutex) + : m_lock{ contextMutex } + {} + ThreadDispatchTestLockGuard(DispatchMutex& contextMutex, AZStd::adopt_lock_t adopt_lock) + : m_lock{ contextMutex, adopt_lock } + {} + ThreadDispatchTestLockGuard(const ThreadDispatchTestLockGuard&) = delete; + ThreadDispatchTestLockGuard& operator=(const ThreadDispatchTestLockGuard&) = delete; + private: + PostThreadDispatchTestInvoker m_threadPolicyInvoker; + using LockType = AZStd::conditional_t, AZStd::scoped_lock>; + LockType m_lock; + }; + + template + using DispatchLockGuard = ThreadDispatchTestLockGuard; + + static inline AZStd::atomic s_threadPostDispatchCalls; + }; + + class ThreadDispatchTestRequests + { + public: + virtual void FirstCall() = 0; + virtual void SecondCall() = 0; + virtual void ThirdCall() = 0; + }; + + using ThreadDispatchTestBus = AZ::EBus; + + ThreadDispatchTestBusTraits::PostThreadDispatchTestInvoker::~PostThreadDispatchTestInvoker() + { + if (!ThreadDispatchTestBus::IsInDispatchThisThread()) + { + ++s_threadPostDispatchCalls; + } + } + + class ThreadDispatchTestHandler + : public ThreadDispatchTestBus::Handler + { + public: + void Connect() + { + ThreadDispatchTestBus::Handler::BusConnect(); + } + void Disconnect() + { + ThreadDispatchTestBus::Handler::BusDisconnect(); + } + + void FirstCall() override + { + ThreadDispatchTestBus::Broadcast(&ThreadDispatchTestBus::Events::SecondCall); + } + void SecondCall() override + { + ThreadDispatchTestBus::Broadcast(&ThreadDispatchTestBus::Events::ThirdCall); + } + void ThirdCall() override + { + } + }; + + template + class EBusParamFixture + : public ScopedAllocatorSetupFixture + , public ::testing::WithParamInterface + {}; + + struct ThreadDispatchParams + { + size_t m_threadCount{}; + size_t m_handlerCount{}; + }; + + using ThreadDispatchParamFixture = EBusParamFixture; + + INSTANTIATE_TEST_CASE_P( + ThreadDispatch, + ThreadDispatchParamFixture, + ::testing::Values( + ThreadDispatchParams{ 1, 1 }, + ThreadDispatchParams{ 2, 1 }, + ThreadDispatchParams{ 1, 2 }, + ThreadDispatchParams{ 2, 2 }, + ThreadDispatchParams{ 16, 8 } + ) + ); + + TEST_P(ThreadDispatchParamFixture, CustomDispatchLockGuard_InvokesPostDispatchFunction_AfterThreadHasFinishedDispatch) + { + ThreadDispatchTestBusTraits::s_threadPostDispatchCalls = 0; + ThreadDispatchParams threadDispatchParams = GetParam(); + AZStd::vector testThreads; + AZStd::vector testHandlers(threadDispatchParams.m_handlerCount); + for (ThreadDispatchTestHandler& testHandler : testHandlers) + { + testHandler.Connect(); + } + + static constexpr size_t DispatchThreadCalls = 3; + const size_t totalThreadDispatchCalls = threadDispatchParams.m_threadCount * DispatchThreadCalls; + + auto DispatchThreadWorker = []() + { + ThreadDispatchTestBus::Broadcast(&ThreadDispatchTestBus::Events::FirstCall); + ThreadDispatchTestBus::Broadcast(&ThreadDispatchTestBus::Events::SecondCall); + ThreadDispatchTestBus::Broadcast(&ThreadDispatchTestBus::Events::ThirdCall); + }; + + for (size_t threadIndex = 0; threadIndex < threadDispatchParams.m_threadCount; ++threadIndex) + { + testThreads.emplace_back(DispatchThreadWorker); + } + + for (AZStd::thread& thread : testThreads) + { + thread.join(); + } + + for (ThreadDispatchTestHandler& testHandler : testHandlers) + { + testHandler.Disconnect(); + } + + EXPECT_EQ(totalThreadDispatchCalls, ThreadDispatchTestBusTraits::s_threadPostDispatchCalls); + ThreadDispatchTestBusTraits::s_threadPostDispatchCalls = 0; + } } // namespace UnitTest #if defined(HAVE_BENCHMARK) @@ -4370,7 +4555,7 @@ namespace Benchmark Bus::ExecuteQueuedEvents(); } s_benchmarkEBusEnv.Disconnect(state); - + } BUS_BENCHMARK_REGISTER_ALL(BM_EBus_ExecuteBroadcast); From de41653d26e87eed74f1d8d71009a2d44715b40c Mon Sep 17 00:00:00 2001 From: jromnoa <80134229+jromnoa@users.noreply.github.com> Date: Fri, 8 Oct 2021 13:36:46 -0700 Subject: [PATCH 081/169] remove LY_PROJECTS check in Atom test registrations so that the targets build in project centric builds (#4581) Signed-off-by: jromnoa --- AutomatedTesting/Gem/PythonTests/Atom/CMakeLists.txt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/Atom/CMakeLists.txt b/AutomatedTesting/Gem/PythonTests/Atom/CMakeLists.txt index 0d6fe4c8fa..ff3cd5c465 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/CMakeLists.txt +++ b/AutomatedTesting/Gem/PythonTests/Atom/CMakeLists.txt @@ -6,12 +6,7 @@ # # -################################################################################ -# Atom Renderer: Automated Tests -# Runs EditorPythonBindings (hydra) scripts inside the Editor to verify test results for the Atom renderer. -################################################################################ - -if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED AND AutomatedTesting IN_LIST LY_PROJECTS) +if(PAL_TRAIT_BUILD_HOST_TOOLS AND PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_pytest( NAME AutomatedTesting::Atom_TestSuite_Main TEST_SUITE main From cef41261004e1b76171882115a38be4872e4b7fe Mon Sep 17 00:00:00 2001 From: smurly Date: Fri, 8 Oct 2021 13:49:51 -0700 Subject: [PATCH 082/169] Mesh component parallel test automation P0 (#4562) * Mesh component P0 automation for parallel testing Signed-off-by: Scott Murray * Remove unused imports Signed-off-by: Scott Murray * Decorating test classes with test_case_id to corresponding testrail cases Signed-off-by: Scott Murray --- .../Atom/TestSuite_Main_Optimized.py | 14 ++ .../hydra_AtomEditorComponents_MeshAdded.py | 171 ++++++++++++++++++ 2 files changed, 185 insertions(+) create mode 100644 AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_MeshAdded.py diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py index f5ac411a01..90436fbe27 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py @@ -14,36 +14,50 @@ from ly_test_tools.o3de.editor_test import EditorSharedTest, EditorTestSuite @pytest.mark.parametrize("launcher_platform", ['windows_editor']) class TestAutomation(EditorTestSuite): + @pytest.mark.test_case_id("C32078118") class AtomEditorComponents_DecalAdded(EditorSharedTest): from Atom.tests import hydra_AtomEditorComponents_DecalAdded as test_module + @pytest.mark.test_case_id("C32078119") class AtomEditorComponents_DepthOfFieldAdded(EditorSharedTest): from Atom.tests import hydra_AtomEditorComponents_DepthOfFieldAdded as test_module + @pytest.mark.test_case_id("C32078120") class AtomEditorComponents_DirectionalLightAdded(EditorSharedTest): from Atom.tests import hydra_AtomEditorComponents_DirectionalLightAdded as test_module + @pytest.mark.test_case_id("C32078121") class AtomEditorComponents_ExposureControlAdded(EditorSharedTest): from Atom.tests import hydra_AtomEditorComponents_ExposureControlAdded as test_module + @pytest.mark.test_case_id("C32078115") class AtomEditorComponents_GlobalSkylightIBLAdded(EditorSharedTest): from Atom.tests import hydra_AtomEditorComponents_GlobalSkylightIBLAdded as test_module + @pytest.mark.test_case_id("C32078125") class AtomEditorComponents_PhysicalSkyAdded(EditorSharedTest): from Atom.tests import hydra_AtomEditorComponents_PhysicalSkyAdded as test_module + @pytest.mark.test_case_id("C32078131") class AtomEditorComponents_PostFXRadiusWeightModifierAdded(EditorSharedTest): from Atom.tests import ( hydra_AtomEditorComponents_PostFXRadiusWeightModifierAdded as test_module) + @pytest.mark.test_case_id("C32078117") class AtomEditorComponents_LightAdded(EditorSharedTest): from Atom.tests import hydra_AtomEditorComponents_LightAdded as test_module + @pytest.mark.test_case_id("C36525660") class AtomEditorComponents_DisplayMapperAdded(EditorSharedTest): from Atom.tests import hydra_AtomEditorComponents_DisplayMapperAdded as test_module + @pytest.mark.test_case_id("C32078128") class AtomEditorComponents_ReflectionProbeAdded(EditorSharedTest): from Atom.tests import hydra_AtomEditorComponents_ReflectionProbeAdded as test_module + @pytest.mark.test_case_id("C32078124") + class AtomEditorComponents_MeshAdded(EditorSharedTest): + from Atom.tests import hydra_AtomEditorComponents_MeshAdded as test_module + class ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges(EditorSharedTest): from Atom.tests import hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges as test_module diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_MeshAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_MeshAdded.py new file mode 100644 index 0000000000..fbf5c987d1 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_MeshAdded.py @@ -0,0 +1,171 @@ +""" +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 +""" + +class Tests: + creation_undo = ( + "UNDO Entity creation success", + "UNDO Entity creation failed") + creation_redo = ( + "REDO Entity creation success", + "REDO Entity creation failed") + mesh_entity_creation = ( + "Mesh Entity successfully created", + "Mesh Entity failed to be created") + mesh_component_added = ( + "Entity has a Mesh component", + "Entity failed to find Mesh component") + mesh_asset_specified = ( + "Mesh asset set", + "Mesh asset not set") + enter_game_mode = ( + "Entered game mode", + "Failed to enter game mode") + exit_game_mode = ( + "Exited game mode", + "Couldn't exit game mode") + is_visible = ( + "Entity is visible", + "Entity was not visible") + is_hidden = ( + "Entity is hidden", + "Entity was not hidden") + entity_deleted = ( + "Entity deleted", + "Entity was not deleted") + deletion_undo = ( + "UNDO deletion success", + "UNDO deletion failed") + deletion_redo = ( + "REDO deletion success", + "REDO deletion failed") + + +def AtomEditorComponents_Mesh_AddedToEntity(): + """ + Summary: + Tests the Mesh component can be added to an entity and has the expected functionality. + + Test setup: + - Wait for Editor idle loop. + - Open the "Base" level. + + Expected Behavior: + The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components. + Creation and deletion undo/redo should also work. + + Test Steps: + 1) Create a Mesh entity with no components. + 2) Add a Mesh component to Mesh entity. + 3) UNDO the entity creation and component addition. + 4) REDO the entity creation and component addition. + 5) Specify the Mesh component asset + 6) Enter/Exit game mode. + 7) Test IsHidden. + 8) Test IsVisible. + 9) Delete Mesh entity. + 10) UNDO deletion. + 11) REDO deletion. + 12) Look for errors. + + :return: None + """ + + import os + + import azlmbr.legacy.general as general + + from editor_python_test_tools.asset_utils import Asset + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report, Tracer, TestHelper as helper + + with Tracer() as error_tracer: + # Test setup begins. + # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level. + helper.init_idle() + helper.open_level("", "Base") + + # Test steps begin. + # 1. Create a Mesh entity with no components. + mesh_name = "Mesh" + mesh_entity = EditorEntity.create_editor_entity(mesh_name) + Report.critical_result(Tests.mesh_entity_creation, mesh_entity.exists()) + + # 2. Add a Mesh component to Mesh entity. + mesh_component = mesh_entity.add_component(mesh_name) + Report.critical_result( + Tests.mesh_component_added, + mesh_entity.has_component(mesh_name)) + + # 3. UNDO the entity creation and component addition. + # -> UNDO component addition. + general.undo() + # -> UNDO naming entity. + general.undo() + # -> UNDO selecting entity. + general.undo() + # -> UNDO entity creation. + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.creation_undo, not mesh_entity.exists()) + + # 4. REDO the entity creation and component addition. + # -> REDO entity creation. + general.redo() + # -> REDO selecting entity. + general.redo() + # -> REDO naming entity. + general.redo() + # -> REDO component addition. + general.redo() + general.idle_wait_frames(1) + Report.result(Tests.creation_redo, mesh_entity.exists()) + + # 5. Set Mesh component asset property + mesh_property_asset = 'Controller|Configuration|Mesh Asset' + model_path = os.path.join('Objects', 'shaderball', 'shaderball_default_1m.azmodel') + model = Asset.find_asset_by_path(model_path) + mesh_component.set_component_property_value(mesh_property_asset, model.id) + Report.result(Tests.mesh_asset_specified, + mesh_component.get_component_property_value(mesh_property_asset) == model.id) + + # 6. Enter/Exit game mode. + helper.enter_game_mode(Tests.enter_game_mode) + general.idle_wait_frames(1) + helper.exit_game_mode(Tests.exit_game_mode) + + # 7. Test IsHidden. + mesh_entity.set_visibility_state(False) + Report.result(Tests.is_hidden, mesh_entity.is_hidden() is True) + + # 8. Test IsVisible. + mesh_entity.set_visibility_state(True) + general.idle_wait_frames(1) + Report.result(Tests.is_visible, mesh_entity.is_visible() is True) + + # 9. Delete Mesh entity. + mesh_entity.delete() + Report.result(Tests.entity_deleted, not mesh_entity.exists()) + + # 10. UNDO deletion. + general.undo() + Report.result(Tests.deletion_undo, mesh_entity.exists()) + + # 11. REDO deletion. + general.redo() + Report.result(Tests.deletion_redo, not mesh_entity.exists()) + + # 12. Look for errors or asserts. + helper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0) + for error_info in error_tracer.errors: + Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}") + for assert_info in error_tracer.asserts: + Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}") + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(AtomEditorComponents_Mesh_AddedToEntity) From d3f6898ad6e617d5f40e7f45bc7098a1ce098569 Mon Sep 17 00:00:00 2001 From: jromnoa <80134229+jromnoa@users.noreply.github.com> Date: Fri, 8 Oct 2021 15:01:20 -0700 Subject: [PATCH 083/169] Fixes test_MaterialEditorLaunch_AllRHIOptionsSucceed() test by searching for RHI log lines (#4511) * double test timeout from 60 seconds to 120 seconds in attempt to fix it for nightly GPU runs Signed-off-by: jromnoa * add a file to launch with the test to ensure we get a full viewport load completed Signed-off-by: jromnoa * fix import error Signed-off-by: jromnoa * remove python error checks Signed-off-by: jromnoa * add new log line specific to each RHI to check for Signed-off-by: jromnoa * remove the new test script as it is no longer needed with our improved log lines check - the viewport logs don't show up in AR for some reason Signed-off-by: jromnoa --- .../Gem/PythonTests/Atom/TestSuite_Main_GPU.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py index 3403d8e9b1..220623af8b 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py @@ -220,20 +220,18 @@ class TestPerformanceBenchmarkSuite(object): @pytest.mark.system class TestMaterialEditor(object): - @pytest.mark.parametrize("cfg_args", ["-rhi=dx12", "-rhi=Vulkan"]) + @pytest.mark.parametrize("cfg_args,expected_lines", [ + pytest.param("-rhi=dx12", ["Registering dx12 RHI"]), + pytest.param("-rhi=Vulkan", ["Registering vulkan RHI"]) + ]) @pytest.mark.parametrize("exe_file_name", ["MaterialEditor"]) def test_MaterialEditorLaunch_AllRHIOptionsSucceed( - self, request, workspace, project, launcher_platform, generic_launcher, exe_file_name, cfg_args): + self, request, workspace, project, launcher_platform, generic_launcher, exe_file_name, cfg_args, + expected_lines): """ Tests each valid RHI option (Null RHI excluded) can be launched with the MaterialEditor. - Checks for the "Finished loading viewport configurations." success message post launch. + Checks for the specific expected_lines messaging for each RHI type. """ - expected_lines = ["Finished loading viewport configurations."] - unexpected_lines = [ - # "Trace::Assert", - # "Trace::Error", - "Traceback (most recent call last):", - ] hydra.launch_and_validate_results( request, @@ -243,7 +241,7 @@ class TestMaterialEditor(object): run_python="--runpython", timeout=60, expected_lines=expected_lines, - unexpected_lines=unexpected_lines, + unexpected_lines=[], halt_on_unexpected=False, null_renderer=False, cfg_args=[cfg_args], From 2034cd3053d6d8af08135ded0cdb38c06381c15f Mon Sep 17 00:00:00 2001 From: sweeneys Date: Fri, 8 Oct 2021 15:36:52 -0700 Subject: [PATCH 084/169] Platform manager and sanity tests for Linux Signed-off-by: sweeneys --- Tools/LyTestTools/ly_test_tools/__init__.py | 6 +- .../managers/abstract_resource_locator.py | 2 +- .../_internal/managers/platforms/linux.py | 3 - .../environment/process_utils.py | 14 ++ .../launchers/platforms/linux/launcher.py | 28 ++- .../ly_test_tools/o3de/asset_processor.py | 170 +++++++++--------- .../o3de/asset_processor_utils.py | 19 +- Tools/LyTestTools/tests/integ/sanity_tests.py | 3 +- .../tests/unit/test_asset_processor.py | 14 +- 9 files changed, 149 insertions(+), 110 deletions(-) diff --git a/Tools/LyTestTools/ly_test_tools/__init__.py b/Tools/LyTestTools/ly_test_tools/__init__.py index 58340342ab..972e97d488 100755 --- a/Tools/LyTestTools/ly_test_tools/__init__.py +++ b/Tools/LyTestTools/ly_test_tools/__init__.py @@ -16,7 +16,7 @@ ALL_PLATFORM_OPTIONS = ['android', 'ios', 'linux', 'mac', 'windows'] ALL_LAUNCHER_OPTIONS = ['android', 'base', 'linux', 'mac', 'windows', 'windows_editor', 'windows_dedicated', 'windows_generic'] ANDROID = False IOS = False # Not implemented - see SPEC-2505 -LINUX = sys.platform.startswith('linux') # Not implemented - see SPEC-2501 +LINUX = sys.platform.startswith('linux') MAC = sys.platform.startswith('darwin') WINDOWS = sys.platform.startswith('win') @@ -54,9 +54,11 @@ elif LINUX: HOST_OS_PLATFORM = 'linux' HOST_OS_EDITOR = 'linux_editor' HOST_OS_DEDICATED_SERVER = 'linux_dedicated' - from ly_test_tools.launchers.platforms.linux.launcher import (LinuxLauncher, LinuxEditor, DedicatedLinuxLauncher) + HOST_OS_GENERIC_EXECUTABLE = 'linux_generic' + from ly_test_tools.launchers.platforms.linux.launcher import (LinuxLauncher, LinuxEditor, DedicatedLinuxLauncher, LinuxGenericLauncher) LAUNCHERS['linux'] = LinuxLauncher LAUNCHERS['linux_editor'] = LinuxEditor LAUNCHERS['linux_dedicated'] = DedicatedLinuxLauncher + LAUNCHERS['linux_generic'] = LinuxGenericLauncher else: logger.warning(f'WARNING: LyTestTools only supports Windows, Mac, and Linux. Unexpectedly detected HOST_OS_PLATFORM: "{HOST_OS_PLATFORM}".') diff --git a/Tools/LyTestTools/ly_test_tools/_internal/managers/abstract_resource_locator.py b/Tools/LyTestTools/ly_test_tools/_internal/managers/abstract_resource_locator.py index 77d58e3a48..fccc94bdcc 100755 --- a/Tools/LyTestTools/ly_test_tools/_internal/managers/abstract_resource_locator.py +++ b/Tools/LyTestTools/ly_test_tools/_internal/managers/abstract_resource_locator.py @@ -265,7 +265,7 @@ class AbstractResourceLocator(object): Return path to AssetProcessor's log file using the project bin dir :return: path to 'AP_Gui.log' file in folder """ - return os.path.join(self.ap_log_dir(), 'AP_Gui.log') + return os.path.join(self.ap_log_dir(), 'AP_GUI.log') def project_cache(self): """ diff --git a/Tools/LyTestTools/ly_test_tools/_internal/managers/platforms/linux.py b/Tools/LyTestTools/ly_test_tools/_internal/managers/platforms/linux.py index cdbd379183..fea60cc9cb 100644 --- a/Tools/LyTestTools/ly_test_tools/_internal/managers/platforms/linux.py +++ b/Tools/LyTestTools/ly_test_tools/_internal/managers/platforms/linux.py @@ -23,9 +23,6 @@ class _LinuxResourceManager(AbstractResourceLocator): """ Override for locating resources in a Linux operating system running LyTestTools. """ - def __init__(self, build_directory: str, project: str): - pass - def platform_config_file(self): """ :return: path to the platform config file diff --git a/Tools/LyTestTools/ly_test_tools/environment/process_utils.py b/Tools/LyTestTools/ly_test_tools/environment/process_utils.py index 1c0be299a8..79fc4f420a 100755 --- a/Tools/LyTestTools/ly_test_tools/environment/process_utils.py +++ b/Tools/LyTestTools/ly_test_tools/environment/process_utils.py @@ -465,3 +465,17 @@ def close_windows_process(pid, timeout=20, raise_on_missing=False): # Wait for asyncronous termination waiter.wait_for(lambda: pid not in psutil.pids(), timeout=timeout, exc=TimeoutError(f"Process {pid} never terminated")) + + +def get_display_env(): + """ + Fetches environment variables with an appropriate display (monitor) configured, + useful for subprocess calls to UI applications + :return: A dictionary containing environment variables (per os.environ) + """ + env = os.environ.copy() + if not ly_test_tools.WINDOWS: + if 'DISPLAY' not in env.keys(): + # assume Display 1 is available in another session + env['DISPLAY'] = ':1' + return env diff --git a/Tools/LyTestTools/ly_test_tools/launchers/platforms/linux/launcher.py b/Tools/LyTestTools/ly_test_tools/launchers/platforms/linux/launcher.py index 210519d197..afee522daf 100644 --- a/Tools/LyTestTools/ly_test_tools/launchers/platforms/linux/launcher.py +++ b/Tools/LyTestTools/ly_test_tools/launchers/platforms/linux/launcher.py @@ -13,6 +13,7 @@ import subprocess import ly_test_tools.environment.waiter import ly_test_tools.launchers.exceptions +import ly_test_tools.environment.process_utils as process_utils from ly_test_tools.launchers.platforms.base import Launcher from ly_test_tools.launchers.exceptions import TeardownError, ProcessNotStartedError @@ -68,7 +69,7 @@ class LinuxLauncher(Launcher): """ command = [self.binary_path()] + self.args self._tmpout = TemporaryFile() - self._proc = subprocess.Popen(command, stdout=self._tmpout, stderr=self._tmpout, universal_newlines=True) + self._proc = subprocess.Popen(command, stdout=self._tmpout, stderr=self._tmpout, universal_newlines=True, env=process_utils.get_display_env()) log.debug(f"Started Linux Launcher with command: {command}") def get_output(self, encoding="utf-8"): @@ -222,3 +223,28 @@ class LinuxEditor(LinuxLauncher): """ assert self.workspace.project is not None return os.path.join(self.workspace.paths.build_directory(), "Editor") + + +class LinuxGenericLauncher(LinuxLauncher): + + def __init__(self, build, exe_file_name, args=None): + super(LinuxLauncher, self).__init__(build, args) + self.exe_file_name = exe_file_name + self.expected_executable_path = os.path.join( + self.workspace.paths.build_directory(), f"{self.exe_file_name}") + + if not os.path.exists(self.expected_executable_path): + raise ProcessNotStartedError( + f"Unable to locate executable '{self.exe_file_name}' " + f"in path: '{self.expected_executable_path}'") + + def binary_path(self): + """ + Return full path to the executable file for this build's configuration and project + Relies on the build_directory() in self.workspace.paths to be accurate + + :return: full path to the given exe file + """ + assert self.workspace.project is not None, ( + 'Project cannot be NoneType - please specify a project name string.') + return self.expected_executable_path diff --git a/Tools/LyTestTools/ly_test_tools/o3de/asset_processor.py b/Tools/LyTestTools/ly_test_tools/o3de/asset_processor.py index 57454930eb..0623715350 100644 --- a/Tools/LyTestTools/ly_test_tools/o3de/asset_processor.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/asset_processor.py @@ -7,21 +7,22 @@ SPDX-License-Identifier: Apache-2.0 OR MIT A class to control functionality of Lumberyard's asset processor. The class manages a workspace's asset processor and asset configurations. """ -import os -import datetime import logging -import subprocess -import socket -import time -import tempfile -import shutil -import stat -from typing import List, Tuple +import os import psutil +import shutil +import socket +import stat +import subprocess +import tempfile +import time + +from typing import List, Tuple import ly_test_tools -import ly_test_tools.environment.waiter as waiter import ly_test_tools.environment.file_system as file_system +import ly_test_tools.environment.process_utils as process_utils +import ly_test_tools.environment.waiter as waiter import ly_test_tools.o3de.pipeline_utils as utils from ly_test_tools.o3de.ap_log_parser import APLogParser @@ -177,24 +178,26 @@ class AssetProcessor(object): """ Read the a port chosen by AP from the log """ - start_time = time.time() - read_port_timeout = 10 - while (time.time() - start_time) < read_port_timeout: + port = None + + def _get_port_from_log(): + nonlocal port if not os.path.exists(self._workspace.paths.ap_gui_log()): - logger.debug(f"Log at {self._workspace.paths.ap_gui_log()} doesn't exist, sleeping") - else: - log = APLogParser(self._workspace.paths.ap_gui_log()) - if len(log.runs): - try: - port = log.runs[-1][port_type] - if port: - logger.info(f"Read port type {port_type} : {port}") - return port - except Exception: # intentionally broad - pass - time.sleep(1) - logger.warning(f"Failed to read port type {port_type}") - return 0 + return False + + log = APLogParser(self._workspace.paths.ap_gui_log()) + if len(log.runs): + try: + port = log.runs[-1][port_type] + logger.debug(f"Read port type {port_type} : {port}") + return True + except Exception as ex: # intentionally broad + logger.debug("Failed to read port from file", exc_info=ex) + return False + + err = AssetProcessorError(f"Failed to read port type {port_type} from {self._workspace.paths.ap_gui_log()}") + waiter.wait_for(_get_port_from_log, timeout=10, exc=err) + return port def set_control_connection(self, connection): self._control_connection = connection @@ -206,13 +209,8 @@ class AssetProcessor(object): """ if not self._control_connection: control_timeout = 60 - try: - return self.connect_socket("Control Connection", self.read_control_port, - set_port_method=self.set_control_connection, timeout=control_timeout) - except AssetProcessorError as e: - # We dont want a failure of our test socket connection to fail the entire test automatically. - logger.error(f"Failed to connect control socket with error {e}") - pass + return self.connect_socket("Control Connection", self.read_control_port, + set_port_method=self.set_control_connection, timeout=control_timeout) return True, None def using_temp_workspace(self): @@ -227,34 +225,40 @@ class AssetProcessor(object): :param set_port_method: If set, method to call with the established connection :param timeout: Max seconds to attempt connection for """ - - connection_timeout = timeout connect_port = read_port_method() - logger.debug(f"Waiting for connection to AP {port_name}: {host}:{connect_port}, " - f"{connection_timeout} seconds remaining") - start_time = time.time() - while (time.time() - start_time) < connection_timeout: + logger.debug(f"Attempting to for connect to AP {port_name}: {host}:{connect_port} for {timeout} seconds") + + def _attempt_connection(): + nonlocal connect_port + if self._ap_proc.poll() is not None: + raise AssetProcessorError(f"Asset processor exited early with errorcode: {self._ap_proc.returncode}") + connection_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - connection_socket.settimeout(10.0) + connection_socket.settimeout(timeout) try: connection_socket.connect((host, connect_port)) logger.debug(f"Connection to AP {port_name} was successful") if set_port_method is not None: set_port_method(connection_socket) - return True, None - except Exception: # Purposefully broad - # Short delay to prevent immediate failure due to slower starting applications such as debug builds - time.sleep(0.01) + return True + except Exception as ex: # Purposefully broad + logger.debug(f"Failed to connect to {host}:{connect_port}", exc_info=ex) if not connect_port or not self.using_temp_workspace(): # If we're not using a temp workspace with a fresh log it's possible we're reading a port from # a previous run and the log just hasn't written yet, we need to keep checking the log for a new # port to use - new_connect_port = read_port_method() - if new_connect_port != connect_port: - logger.debug( - f"Read new connect port for {port_name}: {host}:{new_connect_port}") - connect_port = new_connect_port - raise AssetProcessorError(f"Could not connect to AP {port_name}") + try: + new_connect_port = read_port_method() + if new_connect_port != connect_port: + logger.debug(f"Found new connect port for {port_name}: {host}:{new_connect_port}") + connect_port = new_connect_port + except Exception as read_exception: # Purposefully broad + logger.debug(f"Failed to read port data", exc_info=read_exception) + return False + + err = AssetProcessorError(f"Could not connect to AP {port_name} on {host}:{connect_port}") + waiter.wait_for(_attempt_connection, timeout=timeout, exc=err) + return True, None def stop(self, timeout=60): """ @@ -436,15 +440,14 @@ class AssetProcessor(object): extra_params=None, add_gem_scan_folders=None, add_config_scan_folders=None, decode=True, expect_failure=False, quitonidle=False, connect_to_ap=False, accept_input=True, run_until_idle=True, scan_folder_pattern=None): - ap_path = self._workspace.paths.asset_processor() + ap_path = os.path.abspath(self._workspace.paths.asset_processor()) + ap_exe_path = os.path.dirname(ap_path) extra_gui_params = [] if quitonidle: extra_gui_params.append("--quitonidle") if accept_input: extra_gui_params.append("--acceptInput") - ap_exe_path = os.path.dirname(self._workspace.paths.asset_processor()) - logger.info("Starting asset processor") if self.process_exists(): logger.error("Asset processor already started. Stop first") @@ -483,20 +486,30 @@ class AssetProcessor(object): logger.warning(f"Cannot capture output when leaving AP connection open.") logger.info(f"Launching AP with command: {command}") - self._ap_proc = subprocess.Popen(command, cwd=ap_exe_path) + try: + self._ap_proc = subprocess.Popen(command, cwd=ap_exe_path, env=process_utils.get_display_env()) - if accept_input and not quitonidle: - self.connect_control() + if accept_input: + self.connect_control() - if connect_to_ap: - self.connect_listen() + if connect_to_ap: + self.connect_listen() - if quitonidle: - waiter.wait_for(lambda: not self.process_exists(), timeout=timeout) - elif run_until_idle and accept_input: - if not self.wait_for_idle(): - return False, None - return True, None + if quitonidle: + waiter.wait_for(lambda: not self.process_exists(), timeout=timeout, + exc=AssetProcessorError(f"Failed to quit on idle within {timeout} seconds")) + elif run_until_idle and accept_input: + if not self.wait_for_idle(): + return False, None + return True, None + except BaseException as be: # purposefully broad + logger.exception("Exception while starting Asset Processor", be) + # clean up to avoid leaking open AP process to future tests + try: + self._ap_proc.kill() + except Exception as ex: + logger.exception("Ignoring exception while trying to terminate Asset Processor", ex) + raise # raise whatever prompted us to clean up def connect_listen(self, timeout=DEFAULT_TIMEOUT_SECONDS): # Wait for the AP we launched to be ready to accept a connection @@ -574,21 +587,17 @@ class AssetProcessor(object): expect_failure=False): """ In case of a timeout, the asset processor and associated processes are killed and the function returns False. - + :param timeout: seconds to wait before aborting :param capture_output = Capture output which will be returned in the second of the return pair :param decode: decode byte strings from captured output to utf-8 :param expect_failure: asset processing is expected to fail, so don't error on a failure, and assert on no failure. """ logger.info(f"Launching AP with command: {command}") - start = datetime.datetime.now() - try: - duration = datetime.timedelta(seconds=timeout) - except TypeError: - logger.warning("Cannot set timeout value of '{}' seconds, defaulting to {} hours".format( - timeout, DEFAULT_TIMEOUT_HOURS)) - duration = datetime.timedelta(hours=DEFAULT_TIMEOUT_HOURS) - timeout = duration.total_seconds() + start = time.time() + if type(timeout) not in [int, float] or timeout < 1: + logger.warning(f"Invalid timeout {timeout} - defaulting to {DEFAULT_TIMEOUT_SECONDS} seconds") + timeout = DEFAULT_TIMEOUT_SECONDS run_result = subprocess.run(command, close_fds=True, timeout=timeout, capture_output=capture_output) output_list = None @@ -609,8 +618,7 @@ class AssetProcessor(object): elif expect_failure: logger.error(f"{command} was expected to fail, but instead ran without failure.") return True, output_list - logger.info( - f"{command} completed successfully in {(datetime.datetime.now() - start).seconds} seconds") + logger.info(f"{command} completed successfully in {time.time() - start} seconds") return True, output_list def set_failure_log_folder(self, log_root): @@ -743,14 +751,14 @@ class AssetProcessor(object): :return: Absolute path of added scan folder """ if os.path.isabs(folder_name): - if not folder_name in self._override_scan_folders: + if folder_name not in self._override_scan_folders: self._override_scan_folders.append(folder_name) logger.info(f'Adding override scan folder {folder_name}') return folder_name else: if not self._temp_asset_root: - logger.warning(f"Can't create scan folder, no temporary asset workspace has been created") - return + logger.warning(f"Can not create scan folder, no temporary asset workspace has been created") + return "" scan_folder = os.path.join(self._temp_asset_root if self._temp_asset_root else self._workspace.paths.engine_root(), folder_name) if not os.path.isdir(scan_folder): @@ -802,9 +810,9 @@ class AssetProcessor(object): if not use_current_root: self.create_temp_asset_root() test_asset_root = os.path.join(self._temp_asset_root, self._workspace.project if relative_asset_root is None - else relative_asset_root) + else relative_asset_root) test_folder = os.path.join(test_asset_root, function_name if existing_function_name is None - else existing_function_name) + else existing_function_name) if not os.path.isdir(test_folder): os.makedirs(test_folder) if add_scan_folder: diff --git a/Tools/LyTestTools/ly_test_tools/o3de/asset_processor_utils.py b/Tools/LyTestTools/ly_test_tools/o3de/asset_processor_utils.py index 34ea5f4eb8..f30ed2f233 100644 --- a/Tools/LyTestTools/ly_test_tools/o3de/asset_processor_utils.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/asset_processor_utils.py @@ -9,8 +9,7 @@ import logging import os import subprocess -import ly_test_tools -from ly_test_tools.environment.process_utils import kill_processes_named as kill_processes_named +import ly_test_tools.environment.process_utils as process_utils logger = logging.getLogger(__name__) @@ -23,7 +22,7 @@ def start_asset_processor(bin_dir): :return: A subprocess.Popen object for the AssetProcessor process. """ os.chdir(bin_dir) - asset_processor = subprocess.Popen(['AssetProcessor.exe']) + asset_processor = subprocess.Popen(['AssetProcessor'], env=process_utils.get_display_env()) return_code = asset_processor.poll() if return_code is not None and return_code != 0: @@ -40,11 +39,9 @@ def kill_asset_processor(): :return: None """ - - kill_processes_named('AssetProcessor_tmp', ignore_extensions=True) - kill_processes_named('AssetProcessor', ignore_extensions=True) - kill_processes_named('AssetProcessorBatch', ignore_extensions=True) - kill_processes_named('AssetBuilder', ignore_extensions=True) - kill_processes_named('rc', ignore_extensions=True) - kill_processes_named('Lua Editor', ignore_extensions=True) - + process_utils.kill_processes_named('AssetProcessor_tmp', ignore_extensions=True) + process_utils.kill_processes_named('AssetProcessor', ignore_extensions=True) + process_utils.kill_processes_named('AssetProcessorBatch', ignore_extensions=True) + process_utils.kill_processes_named('AssetBuilder', ignore_extensions=True) + process_utils.kill_processes_named('rc', ignore_extensions=True) + process_utils.kill_processes_named('Lua Editor', ignore_extensions=True) diff --git a/Tools/LyTestTools/tests/integ/sanity_tests.py b/Tools/LyTestTools/tests/integ/sanity_tests.py index e27398c477..ed77d7b8db 100755 --- a/Tools/LyTestTools/tests/integ/sanity_tests.py +++ b/Tools/LyTestTools/tests/integ/sanity_tests.py @@ -58,12 +58,11 @@ class TestAutomatedTestingProject(object): # Call the game client executable with launcher.start(): # Wait for the process to exist - waiter.wait_for(lambda: process_utils.process_exists(f"{project}.GameLauncher.exe", ignore_extensions=True)) + waiter.wait_for(lambda: process_utils.process_exists(f"{project}.GameLauncher", ignore_extensions=True)) finally: # Clean up processes after the test is finished process_utils.kill_processes_named(names=process_utils.LY_PROCESS_KILL_LIST, ignore_extensions=True) - @pytest.mark.skipif(not ly_test_tools.WINDOWS, reason="Editor currently only functions on Windows") def test_StartEditor_Sanity(self, project): """ The `test_StartEditor_Sanity` test function is similar to the previous example with minor adjustments. A diff --git a/Tools/LyTestTools/tests/unit/test_asset_processor.py b/Tools/LyTestTools/tests/unit/test_asset_processor.py index f487cc8537..aabbf2f2f5 100755 --- a/Tools/LyTestTools/tests/unit/test_asset_processor.py +++ b/Tools/LyTestTools/tests/unit/test_asset_processor.py @@ -58,10 +58,8 @@ class TestAssetProcessor(object): under_test.start(connect_to_ap=True) assert under_test._ap_proc is not None - mock_popen.assert_called_once_with([mock_ap_path, '--zeroAnalysisMode', - f'--regset="/Amazon/AzCore/Bootstrap/project_path={mock_project_path}"', - '--logDir', under_test.log_root(), - '--acceptInput', '--platforms', 'bar'], cwd=os.path.dirname(mock_ap_path)) + mock_popen.assert_called_once() + assert '--zeroAnalysisMode' in mock_popen.call_args[0][0] mock_connect.assert_called() @mock.patch('ly_test_tools._internal.managers.workspace.AbstractWorkspaceManager') @@ -114,7 +112,7 @@ class TestAssetProcessor(object): assert result mock_run.assert_called_once_with([apb_path, - f'--regset="/Amazon/AzCore/Bootstrap/project_path={mock_project_path}"', + f'--regset="/Amazon/AzCore/Bootstrap/project_path={mock_project_path}"', '--logDir', under_test.log_root()], close_fds=True, capture_output=False, timeout=1) @@ -150,10 +148,8 @@ class TestAssetProcessor(object): result, _ = under_test.batch_process(None, False) assert not result - mock_run.assert_called_once_with([apb_path, - f'--regset="/Amazon/AzCore/Bootstrap/project_path={mock_project_path}"', - '--logDir', under_test.log_root()], - close_fds=True, capture_output=False, timeout=28800.0) + mock_run.assert_called_once() + assert f'--regset="/Amazon/AzCore/Bootstrap/project_path={mock_project_path}"' in mock_run.call_args[0][0] @mock.patch('ly_test_tools._internal.managers.workspace.AbstractWorkspaceManager') From e4d3ab118c02071d5533ea90525cb8b43589ea62 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 8 Oct 2021 17:59:57 -0500 Subject: [PATCH 085/169] Console changes: Added a new SettingsRegistry root key for executing (#4567) console commands. The new key is "/O3DE/Autoexec/ConsoleCommands" and the only difference with the "/Amazon/AzCore/Runtime/ConosleCommands" key is that it isn't excluded by the SettingsRegistryBuilder. Due to not being excluded by the SettingsRegistryBuilder this key can be used to forward console commands to the aggregate `bootstrap.game...setreg` files. For GameLauncher specific console commands it is recommend to be put them in .setreg file that uses the "game" specialization, such as "autoexec.game.setreg". Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- .../AzCore/AzCore/Console/Console.cpp | 32 +++++++++++++------ .../AzCore/AzCore/Console/IConsole.h | 3 +- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Console/Console.cpp b/Code/Framework/AzCore/AzCore/Console/Console.cpp index a1b8a1759d..9f207d9afd 100644 --- a/Code/Framework/AzCore/AzCore/Console/Console.cpp +++ b/Code/Framework/AzCore/AzCore/Console/Console.cpp @@ -476,15 +476,16 @@ namespace AZ // Responsible for using the Json Serialization Issue Callback system // to determine when a JSON Patch or JSON Merge Patch modifies a value - // at a path underneath the IConsole::ConsoleRootCommandKey JSON pointer + // at a path underneath the IConsole::ConsoleRuntimeCommandKey JSON pointer JsonSerializationResult::ResultCode operator()(AZStd::string_view message, JsonSerializationResult::ResultCode result, AZStd::string_view path) { - AZ::IO::PathView consoleRootCommandKey{ IConsole::ConsoleRootCommandKey, AZ::IO::PosixPathSeparator }; + constexpr AZ::IO::PathView consoleRootCommandKey{ IConsole::ConsoleRuntimeCommandKey, AZ::IO::PosixPathSeparator }; + constexpr AZ::IO::PathView consoleAutoexecCommandKey{ IConsole::ConsoleAutoexecCommandKey, AZ::IO::PosixPathSeparator }; AZ::IO::PathView inputKey{ path, AZ::IO::PosixPathSeparator }; if (result.GetTask() == JsonSerializationResult::Tasks::Merge && result.GetProcessing() == JsonSerializationResult::Processing::Completed - && inputKey.IsRelativeTo(consoleRootCommandKey)) + && (inputKey.IsRelativeTo(consoleRootCommandKey) || inputKey.IsRelativeTo(consoleAutoexecCommandKey))) { if (auto type = m_settingsRegistry.GetType(path); type != SettingsRegistryInterface::Type::NoType) { @@ -510,12 +511,24 @@ namespace AZ { using FixedValueString = AZ::SettingsRegistryInterface::FixedValueString; - AZ::IO::PathView consoleRootCommandKey{ IConsole::ConsoleRootCommandKey, AZ::IO::PosixPathSeparator }; + constexpr AZ::IO::PathView consoleRuntimeCommandKey{ IConsole::ConsoleRuntimeCommandKey, AZ::IO::PosixPathSeparator }; + constexpr AZ::IO::PathView consoleAutoexecCommandKey{ IConsole::ConsoleAutoexecCommandKey, AZ::IO::PosixPathSeparator }; AZ::IO::PathView inputKey{ path, AZ::IO::PosixPathSeparator }; - // The ConsoleRootComamndKey is not a command itself so strictly children keys are being examined - if (inputKey.IsRelativeTo(consoleRootCommandKey) && inputKey != consoleRootCommandKey) + + // Abuses the IsRelativeToFuncton function of the path class to extract the console + // command from the settings registry objects + FixedValueString command; + if (inputKey != consoleRuntimeCommandKey && inputKey.IsRelativeTo(consoleRuntimeCommandKey)) + { + command = inputKey.LexicallyRelative(consoleRuntimeCommandKey).Native(); + } + else if (inputKey != consoleAutoexecCommandKey && inputKey.IsRelativeTo(consoleAutoexecCommandKey)) + { + command = inputKey.LexicallyRelative(consoleAutoexecCommandKey).Native(); + } + + if (!command.empty()) { - FixedValueString command = inputKey.LexicallyRelative(consoleRootCommandKey).Native(); ConsoleCommandContainer commandArgs; // Argument string which stores the value from the Settings Registry long enough // to pass into the PerformCommand. The ConsoleCommandContainer stores string_views @@ -603,9 +616,10 @@ namespace AZ void Console::RegisterCommandInvokerWithSettingsRegistry(AZ::SettingsRegistryInterface& settingsRegistry) { - // Make sure the there is a JSON object at the path of AZ::IConsole::ConsoleRootCommandKey + // Make sure the there is a JSON object at the ConsoleRuntimeCommandKey or ConsoleAutoexecKey // So that JSON Patch is able to add values underneath that object (JSON Patch doesn't create intermediate objects) - settingsRegistry.MergeSettings(R"({ "Amazon": { "AzCore": { "Runtime": { "ConsoleCommands": {} } }}})", + settingsRegistry.MergeSettings(R"({ "Amazon": { "AzCore": { "Runtime": { "ConsoleCommands": {} } } })" + R"(,"O3DE": { "Autoexec": { "ConsoleCommands": {} } } })", SettingsRegistryInterface::Format::JsonMergePatch); m_consoleCommandKeyHandler = settingsRegistry.RegisterNotifier(ConsoleCommandKeyNotificationHandler{ settingsRegistry, *this }); diff --git a/Code/Framework/AzCore/AzCore/Console/IConsole.h b/Code/Framework/AzCore/AzCore/Console/IConsole.h index dafc284ce3..73d17ac65a 100644 --- a/Code/Framework/AzCore/AzCore/Console/IConsole.h +++ b/Code/Framework/AzCore/AzCore/Console/IConsole.h @@ -31,7 +31,8 @@ namespace AZ using FunctorVisitor = AZStd::function; - inline static constexpr AZStd::string_view ConsoleRootCommandKey = "/Amazon/AzCore/Runtime/ConsoleCommands"; + inline static constexpr AZStd::string_view ConsoleRuntimeCommandKey = "/Amazon/AzCore/Runtime/ConsoleCommands"; + inline static constexpr AZStd::string_view ConsoleAutoexecCommandKey = "/O3DE/Autoexec/ConsoleCommands"; IConsole() = default; virtual ~IConsole() = default; From 70053f055a7dbbdd336d7027ca938ba2492f3e4f Mon Sep 17 00:00:00 2001 From: nggieber Date: Fri, 8 Oct 2021 16:52:58 -0700 Subject: [PATCH 086/169] More python PR feedback Signed-off-by: nggieber --- scripts/o3de/o3de/manifest.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/scripts/o3de/o3de/manifest.py b/scripts/o3de/o3de/manifest.py index 5d34c4bcf9..c5f6315474 100644 --- a/scripts/o3de/o3de/manifest.py +++ b/scripts/o3de/o3de/manifest.py @@ -423,11 +423,8 @@ def get_templates_for_generic_creation(): # temporary until we have a better wa def get_json_file_path(object_typename: str, object_path: str or pathlib.Path = None) -> pathlib.Path: - if not object_typename: - logger.error('Missing object typename.') - return None - - if not object_path: + if not object_typename or not object_path: + logger.error('Must specify an object typename and object path.') return None object_path = pathlib.Path(object_path).resolve() @@ -439,9 +436,11 @@ def get_json_data_file(object_json: pathlib.Path, object_validator = callable) -> dict or None: if not object_typename: logger.error('Missing object typename.') + return None if not object_json: - logger.error(f'No object_json provided for {object_typename}') + logger.error(f'No object json provided for {object_typename}') + return None if not object_json.is_file(): logger.error(f'{object_typename} json {object_json} is not present.') @@ -449,6 +448,7 @@ def get_json_data_file(object_json: pathlib.Path, if not object_validator: logger.error('Missing object validator.') + return None if not object_validator(object_json): logger.error(f'{object_typename} json {object_json} is not valid.') @@ -472,6 +472,7 @@ def get_json_data(object_typename: str = None, if not object_json and object_name: logger.error(f'{object_name} has not been registered.') + return None return get_json_data_file(object_json, object_typename, object_validator) From 7b1dd01d1d648b2e449dba283d051bcae2414483 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Fri, 8 Oct 2021 20:09:22 -0500 Subject: [PATCH 087/169] Implemented a deferred LoadLevel queue for the SpawnableLevelSystem (#4561) * Moved the SettingsRegistryTests.cpp and SettingsRegistryMergeUtilsTests.cpp to the Settings folder Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Implemented a deferred level load queue, that allows the SpawnableLevelSystem to re-run the last LoadLevel command that occured before it was constructed. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Added SettingsRegistryVisitorUtils to reduce Array and Object visitor boilerplate. The VisitArray and VisitObject functions allows iteration over each element of array and object respectively via a callback. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Removed the queuing logic for levels that attempt to load before the SpawnableLevelSystem is available Only the last level name that could not load is stored off and deferred until the SpawnableLevelsystem is created. Made the FieldVisitor AggregateTypes constructor protected and added a comment specifying the expected values. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Bring in the SettingsRegistry::Visitor::Visit functions into scope to fix MSVC compilation errors. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Changed the list of supported SettingsRegistry types to visit to an enum to constrain the values to Array and/or Object. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- .../AzCore/AzCore/Settings/SettingsRegistry.h | 4 +- .../Settings/SettingsRegistryVisitorUtils.cpp | 136 ++++++++++++ .../Settings/SettingsRegistryVisitorUtils.h | 83 ++++++++ .../AzCore/AzCore/azcore_files.cmake | 2 + .../SettingsRegistryMergeUtilsTests.cpp | 0 .../{ => Settings}/SettingsRegistryTests.cpp | 0 .../SettingsRegistryVisitorUtilsTests.cpp | 196 ++++++++++++++++++ .../AzCore/Tests/azcoretests_files.cmake | 5 +- .../LevelSystem/SpawnableLevelSystem.cpp | 35 +++- Registry/setregbuilder.assetprocessor.setreg | 3 +- 10 files changed, 456 insertions(+), 8 deletions(-) create mode 100644 Code/Framework/AzCore/AzCore/Settings/SettingsRegistryVisitorUtils.cpp create mode 100644 Code/Framework/AzCore/AzCore/Settings/SettingsRegistryVisitorUtils.h rename Code/Framework/AzCore/Tests/{ => Settings}/SettingsRegistryMergeUtilsTests.cpp (100%) rename Code/Framework/AzCore/Tests/{ => Settings}/SettingsRegistryTests.cpp (100%) create mode 100644 Code/Framework/AzCore/Tests/Settings/SettingsRegistryVisitorUtilsTests.cpp diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h index 3dc1be87c5..40022bdc04 100644 --- a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistry.h @@ -204,14 +204,14 @@ namespace AZ [[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent(const PreMergeEventCallback& callback) = 0; //! Register a function that will be called before a file is merged. //! @callback The function to call before a file is merged. - [[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent (PreMergeEventCallback&& callback) = 0; + [[nodiscard]] virtual PreMergeEventHandler RegisterPreMergeEvent(PreMergeEventCallback&& callback) = 0; //! Register a function that will be called after a file is merged. //! @callback The function to call after a file is merged. [[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent(const PostMergeEventCallback& callback) = 0; //! Register a function that will be called after a file is merged. //! @callback The function to call after a file is merged. - [[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent (PostMergeEventCallback&& callback) = 0; + [[nodiscard]] virtual PostMergeEventHandler RegisterPostMergeEvent(PostMergeEventCallback&& callback) = 0; //! Gets the boolean value at the provided path. //! @param result The target to write the result to. diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryVisitorUtils.cpp b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryVisitorUtils.cpp new file mode 100644 index 0000000000..9456616024 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryVisitorUtils.cpp @@ -0,0 +1,136 @@ +/* + * 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::SettingsRegistryVisitorUtils +{ + // Field Visitor implementation + FieldVisitor::FieldVisitor() = default; + FieldVisitor::FieldVisitor(VisitFieldType visitFieldType) + : m_visitFieldType{ visitFieldType } + { + } + + auto FieldVisitor::Traverse(AZStd::string_view path, AZStd::string_view valueName, + VisitAction action, Type type) -> VisitResponse + { + // A default response skip prevents visiting grand children(depth 2 or lower) + VisitResponse visitResponse = VisitResponse::Skip; + if (action == VisitAction::Begin) + { + // Invoke FieldVisitor override if the root path has been set + if (m_rootPath.has_value()) + { + Visit(path, valueName, type); + } + // To make sure only the direct children are visited(depth 1) + // set the root path once and set the VisitReponsoe + // to Continue to recurse into is fields + if (!m_rootPath.has_value()) + { + bool visitableFieldType{}; + switch (m_visitFieldType) + { + case VisitFieldType::Array: + visitableFieldType = type == Type::Array; + break; + case VisitFieldType::Object: + visitableFieldType = type == Type::Object; + break; + case VisitFieldType::ArrayOrObject: + visitableFieldType = type == Type::Array || type ==Type::Object; + break; + default: + AZ_Error("FieldVisitor", false, "The field visitation type value is invalid"); + break; + } + + if (visitableFieldType) + { + m_rootPath = path; + visitResponse = VisitResponse::Continue; + } + } + } + else if (action == VisitAction::Value) + { + // Invoke FieldVisitor override if the root path has been set + if (m_rootPath.has_value()) + { + Visit(path, valueName, type); + } + } + else if (action == VisitAction::End) + { + // Reset m_rootPath back to null when the root path has finished being visited + if (m_rootPath.has_value() && *m_rootPath == path) + { + m_rootPath = AZStd::nullopt; + } + } + + + return visitResponse; + } + + // Array Visitor implementation + ArrayVisitor::ArrayVisitor() + : FieldVisitor(VisitFieldType::Array) + { + } + + // Object Visitor implementation + ObjectVisitor::ObjectVisitor() + : FieldVisitor(VisitFieldType::Object) + { + } + + // Generic VisitField Callback implemention + template + bool VisitFieldCallback(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path) + { + struct VisitFieldVisitor + : BaseVisitor + { + using BaseVisitor::Visit; + VisitFieldVisitor(const VisitorCallback& visitCallback) + : m_visitCallback{ visitCallback } + {} + + void Visit(AZStd::string_view path, AZStd::string_view fieldIndex, typename BaseVisitor::Type type) override + { + m_visitCallback(path, fieldIndex, type); + } + + const VisitorCallback& m_visitCallback; + }; + + VisitFieldVisitor visitor{ visitCallback }; + return settingsRegistry.Visit(visitor, path); + } + + // VisitField implementation + bool VisitField(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path) + { + return VisitFieldCallback(settingsRegistry, visitCallback, path); + } + + // VisitArray implementation + bool VisitArray(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path) + { + return VisitFieldCallback(settingsRegistry, visitCallback, path); + } + + // VisitObject implementation + bool VisitObject(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path) + { + return VisitFieldCallback(settingsRegistry, visitCallback, path); + } +} diff --git a/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryVisitorUtils.h b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryVisitorUtils.h new file mode 100644 index 0000000000..a45712521f --- /dev/null +++ b/Code/Framework/AzCore/AzCore/Settings/SettingsRegistryVisitorUtils.h @@ -0,0 +1,83 @@ +/* + * 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::SettingsRegistryVisitorUtils +{ + //! Interface for visiting the fields of an array or object + //! To access the values, use the SettingsRegistryInterface Get/GetObject methods + struct FieldVisitor + : public AZ::SettingsRegistryInterface::Visitor + { + using VisitResponse = AZ::SettingsRegistryInterface::VisitResponse; + using VisitAction = AZ::SettingsRegistryInterface::VisitAction; + using Type = AZ::SettingsRegistryInterface::Type; + + FieldVisitor(); + + // Bring the base class visitor functions into scope + using AZ::SettingsRegistryInterface::Visitor::Visit; + virtual void Visit(AZStd::string_view path, AZStd::string_view arrayIndex, Type type) = 0; + + protected: + // VisitFieldType is used for filtering the type of referenced by the root path + enum class VisitFieldType + { + Array, + Object, + ArrayOrObject + }; + FieldVisitor(const VisitFieldType visitFieldType); + private: + VisitResponse Traverse(AZStd::string_view path, AZStd::string_view valueName, + VisitAction action, Type type) override; + + VisitFieldType m_visitFieldType{ VisitFieldType::ArrayOrObject }; + AZStd::optional m_rootPath; + }; + + //! Interface for visiting the fields of an array + //! To access the values, use the SettingsRegistryInterface Get/GetObject methods + struct ArrayVisitor + : public FieldVisitor + { + ArrayVisitor(); + }; + + //! Interface for visiting the fields of an object + //! To access the values, use the SettingsRegistryInterface Get/GetObject methods + struct ObjectVisitor + : public FieldVisitor + { + ObjectVisitor(); + }; + + //! Signature of callback funcition invoked when visiting an element of an array or object + using VisitorCallback = AZStd::function; + + //! Invokes the visitor callback for each element of either the array or object at @path + //! If @path is not an array or object, then no elements are visited + //! This function will not recurse into children of elements + //! @visitCallback functor that is invoked for each array or object element found + bool VisitField(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path); + //! Invokes the visitor callback for each element of the array at @path + //! If @path is not an array, then no elements are visited + //! This function will not recurse into children of elements + //! @visitCallback functor that is invoked for each array element found + bool VisitArray(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path); + //! Invokes the visitor callback for each element of the object at @path + //! If @path is not an object, then no elements are visited + //! This function will not recurse into children of elements + //! @visitCallback functor that is invoked for each object element found + bool VisitObject(AZ::SettingsRegistryInterface& settingsRegistry, const VisitorCallback& visitCallback, AZStd::string_view path); +} diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index 010c748402..6675958247 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -566,6 +566,8 @@ set(FILES Settings/SettingsRegistryMergeUtils.h Settings/SettingsRegistryScriptUtils.cpp Settings/SettingsRegistryScriptUtils.h + Settings/SettingsRegistryVisitorUtils.cpp + Settings/SettingsRegistryVisitorUtils.h State/HSM.cpp State/HSM.h Statistics/NamedRunningStatistic.h diff --git a/Code/Framework/AzCore/Tests/SettingsRegistryMergeUtilsTests.cpp b/Code/Framework/AzCore/Tests/Settings/SettingsRegistryMergeUtilsTests.cpp similarity index 100% rename from Code/Framework/AzCore/Tests/SettingsRegistryMergeUtilsTests.cpp rename to Code/Framework/AzCore/Tests/Settings/SettingsRegistryMergeUtilsTests.cpp diff --git a/Code/Framework/AzCore/Tests/SettingsRegistryTests.cpp b/Code/Framework/AzCore/Tests/Settings/SettingsRegistryTests.cpp similarity index 100% rename from Code/Framework/AzCore/Tests/SettingsRegistryTests.cpp rename to Code/Framework/AzCore/Tests/Settings/SettingsRegistryTests.cpp diff --git a/Code/Framework/AzCore/Tests/Settings/SettingsRegistryVisitorUtilsTests.cpp b/Code/Framework/AzCore/Tests/Settings/SettingsRegistryVisitorUtilsTests.cpp new file mode 100644 index 0000000000..15f346ee93 --- /dev/null +++ b/Code/Framework/AzCore/Tests/Settings/SettingsRegistryVisitorUtilsTests.cpp @@ -0,0 +1,196 @@ +/* + * 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 SettingsRegistryVisitorUtilsTests +{ + struct VisitCallbackParams + { + AZStd::string_view m_inputJsonDocument; + using VisitFieldFunction = bool(*)(AZ::SettingsRegistryInterface&, + const AZ::SettingsRegistryVisitorUtils::VisitorCallback&, + AZStd::string_view); + + static inline constexpr size_t MaxFieldCount = 10; + using ObjectFields = AZStd::fixed_vector, MaxFieldCount>; + using ArrayFields = AZStd::fixed_vector; + ObjectFields m_objectFields; + ArrayFields m_arrayFields; + }; + + template + class SettingsRegistryVisitorUtilsParamFixture + : public UnitTest::ScopedAllocatorSetupFixture + , public ::testing::WithParamInterface + { + public: + + void SetUp() override + { + m_registry = AZStd::make_unique(); + } + + void TearDown() override + { + m_registry.reset(); + } + + AZStd::unique_ptr m_registry; + }; + + using SettingsRegistryVisitCallbackFixture = SettingsRegistryVisitorUtilsParamFixture; + + TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitFieldsOfArrayType_ReturnsFields) + { + const VisitCallbackParams& visitParams = GetParam(); + + ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch)); + + AZStd::fixed_vector testArrayFields; + auto visitorCallback = [this, &testArrayFields](AZStd::string_view path, AZStd::string_view, AZ::SettingsRegistryInterface::Type) + { + AZStd::string fieldValue; + EXPECT_TRUE(m_registry->Get(fieldValue, path)); + testArrayFields.emplace_back(AZStd::move(fieldValue)); + }; + + AZ::SettingsRegistryVisitorUtils::VisitField(*m_registry, visitorCallback, "/Test/Array"); + + const AZStd::fixed_vector expectedFields{ + visitParams.m_arrayFields.begin(), visitParams.m_arrayFields.end() }; + EXPECT_THAT(testArrayFields, ::testing::ContainerEq(expectedFields)); + } + + TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitFieldsOfObjectType_ReturnsFields) + { + const VisitCallbackParams& visitParams = GetParam(); + + ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch)); + + AZStd::fixed_vector, VisitCallbackParams::MaxFieldCount> testObjectFields; + auto visitorCallback = [this, &testObjectFields](AZStd::string_view path, AZStd::string_view fieldName, AZ::SettingsRegistryInterface::Type) + { + AZStd::string fieldValue; + EXPECT_TRUE(m_registry->Get(fieldValue, path)); + testObjectFields.emplace_back(fieldName, AZStd::move(fieldValue)); + }; + + AZ::SettingsRegistryVisitorUtils::VisitField(*m_registry, visitorCallback, "/Test/Object"); + + const AZStd::fixed_vector, VisitCallbackParams::MaxFieldCount> expectedFields{ + visitParams.m_objectFields.begin(), visitParams.m_objectFields.end() }; + EXPECT_THAT(testObjectFields, ::testing::ContainerEq(expectedFields)); + } + + TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitArrayOfArrayType_ReturnsFields) + { + const VisitCallbackParams& visitParams = GetParam(); + + ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch)); + + AZStd::fixed_vector testArrayFields; + auto visitorCallback = [this, &testArrayFields](AZStd::string_view path, AZStd::string_view, AZ::SettingsRegistryInterface::Type) + { + AZStd::string fieldValue; + EXPECT_TRUE(m_registry->Get(fieldValue, path)); + testArrayFields.emplace_back(AZStd::move(fieldValue)); + }; + + AZ::SettingsRegistryVisitorUtils::VisitArray(*m_registry, visitorCallback, "/Test/Array"); + + const AZStd::fixed_vector expectedArrayFields{ + visitParams.m_arrayFields.begin(), visitParams.m_arrayFields.end() }; + EXPECT_THAT(testArrayFields, ::testing::ContainerEq(expectedArrayFields)); + } + + TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitArrayOfObjectType_ReturnsEmpty) + { + const VisitCallbackParams& visitParams = GetParam(); + + ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch)); + + AZStd::fixed_vector testArrayFields; + auto visitorCallback = [this, &testArrayFields](AZStd::string_view path, AZStd::string_view, AZ::SettingsRegistryInterface::Type) + { + AZStd::string fieldValue; + EXPECT_TRUE(m_registry->Get(fieldValue, path)); + testArrayFields.emplace_back(AZStd::move(fieldValue)); + }; + + AZ::SettingsRegistryVisitorUtils::VisitArray(*m_registry, visitorCallback, "/Test/Object"); + + EXPECT_TRUE(testArrayFields.empty()); + } + + TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitObjectOfArrayType_ReturnsEmpty) + { + const VisitCallbackParams& visitParams = GetParam(); + + ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch)); + + AZStd::fixed_vector, VisitCallbackParams::MaxFieldCount> testObjectFields; + auto visitorCallback = [this, &testObjectFields](AZStd::string_view path, AZStd::string_view fieldName, AZ::SettingsRegistryInterface::Type) + { + AZStd::string fieldValue; + EXPECT_TRUE(m_registry->Get(fieldValue, path)); + testObjectFields.emplace_back(fieldName, AZStd::move(fieldValue)); + }; + + AZ::SettingsRegistryVisitorUtils::VisitObject(*m_registry, visitorCallback, "/Test/Array"); + + EXPECT_TRUE(testObjectFields.empty()); + } + + TEST_P(SettingsRegistryVisitCallbackFixture, VisitFunction_VisitObjectOfObjectType_ReturnsFields) + { + const VisitCallbackParams& visitParams = GetParam(); + + ASSERT_TRUE(m_registry->MergeSettings(visitParams.m_inputJsonDocument, AZ::SettingsRegistryInterface::Format::JsonMergePatch)); + + AZStd::fixed_vector, VisitCallbackParams::MaxFieldCount> testObjectFields; + auto visitorCallback = [this, &testObjectFields](AZStd::string_view path, AZStd::string_view fieldName, AZ::SettingsRegistryInterface::Type) + { + AZStd::string fieldValue; + EXPECT_TRUE(m_registry->Get(fieldValue, path)); + testObjectFields.emplace_back(fieldName, AZStd::move(fieldValue)); + }; + + AZ::SettingsRegistryVisitorUtils::VisitObject(*m_registry, visitorCallback, "/Test/Object"); + + const AZStd::fixed_vector, VisitCallbackParams::MaxFieldCount> expectedObjectFields{ + visitParams.m_objectFields.begin(), visitParams.m_objectFields.end() }; + EXPECT_THAT(testObjectFields, ::testing::ContainerEq(expectedObjectFields)); + } + + + INSTANTIATE_TEST_CASE_P( + VisitField, + SettingsRegistryVisitCallbackFixture, + ::testing::Values( + VisitCallbackParams + { + R"({)" "\n" + R"( "Test":)" "\n" + R"( {)" "\n" + R"( "Array": [ "Hello", "World" ],)" "\n" + R"( "Object": { "Foo": "Hello", "Bar": "World"})" "\n" + R"( })" "\n" + R"(})" "\n", + VisitCallbackParams::ObjectFields{{"Foo", "Hello"}, {"Bar", "World"}}, + VisitCallbackParams::ArrayFields{"Hello", "World"} + } + ) + ); +} diff --git a/Code/Framework/AzCore/Tests/azcoretests_files.cmake b/Code/Framework/AzCore/Tests/azcoretests_files.cmake index e155594aa0..d738711a4f 100644 --- a/Code/Framework/AzCore/Tests/azcoretests_files.cmake +++ b/Code/Framework/AzCore/Tests/azcoretests_files.cmake @@ -75,11 +75,12 @@ set(FILES Name/NameJsonSerializerTests.cpp Name/NameTests.cpp RTTI/TypeSafeIntegralTests.cpp - SettingsRegistryTests.cpp - SettingsRegistryMergeUtilsTests.cpp Settings/CommandLineTests.cpp + Settings/SettingsRegistryTests.cpp Settings/SettingsRegistryConsoleUtilsTests.cpp + Settings/SettingsRegistryMergeUtilsTests.cpp Settings/SettingsRegistryScriptUtilsTests.cpp + Settings/SettingsRegistryVisitorUtilsTests.cpp Streamer/BlockCacheTests.cpp Streamer/DedicatedCacheTests.cpp Streamer/FullDecompressorTests.cpp diff --git a/Code/Legacy/CrySystem/LevelSystem/SpawnableLevelSystem.cpp b/Code/Legacy/CrySystem/LevelSystem/SpawnableLevelSystem.cpp index a82c4a6914..b2b67c3b75 100644 --- a/Code/Legacy/CrySystem/LevelSystem/SpawnableLevelSystem.cpp +++ b/Code/Legacy/CrySystem/LevelSystem/SpawnableLevelSystem.cpp @@ -22,22 +22,33 @@ #include #include #include +#include #include #include namespace LegacyLevelSystem { + constexpr AZStd::string_view DeferredLoadLevelKey = "/O3DE/Runtime/SpawnableLevelSystem/DeferredLoadLevel"; //------------------------------------------------------------------------ static void LoadLevel(const AZ::ConsoleCommandContainer& arguments) { AZ_Error("SpawnableLevelSystem", !arguments.empty(), "LoadLevel requires a level file name to be provided."); AZ_Error("SpawnableLevelSystem", arguments.size() == 1, "LoadLevel requires a single level file name to be provided."); - if (!arguments.empty() && gEnv->pSystem && gEnv->pSystem->GetILevelSystem() && !gEnv->IsEditor()) + if (!arguments.empty() && gEnv && gEnv->pSystem && gEnv->pSystem->GetILevelSystem() && !gEnv->IsEditor()) { gEnv->pSystem->GetILevelSystem()->LoadLevel(arguments[0].data()); } + else if (!arguments.empty()) + { + // The SpawnableLevelSystem isn't available yet. + // Defer the level load until later by storing it in the SettingsRegistry + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) + { + settingsRegistry->Set(DeferredLoadLevelKey, arguments.front()); + } + } } //------------------------------------------------------------------------ @@ -45,7 +56,7 @@ namespace LegacyLevelSystem { AZ_Warning("SpawnableLevelSystem", !arguments.empty(), "UnloadLevel doesn't use any arguments."); - if (gEnv->pSystem && gEnv->pSystem->GetILevelSystem() && !gEnv->IsEditor()) + if (gEnv && gEnv->pSystem && gEnv->pSystem->GetILevelSystem() && !gEnv->IsEditor()) { gEnv->pSystem->GetILevelSystem()->UnloadLevel(); } @@ -73,6 +84,24 @@ namespace LegacyLevelSystem } AzFramework::RootSpawnableNotificationBus::Handler::BusConnect(); + + // If there were LoadLevel command invocations before the creation of the level system + // then those invocations were queued. + // load the last level in the queue, since only one level can be loaded at a time + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) + { + if (AZ::SettingsRegistryInterface::FixedValueString deferredLevelName; + settingsRegistry->Get(deferredLevelName, DeferredLoadLevelKey) && !deferredLevelName.empty()) + { + // since this is the constructor any derived classes vtables aren't setup yet + // call this class LoadLevel function + AZ_TracePrintf("SpawnableLevelSystem", "The Level System is now available." + " Loading level %s which could not be loaded earlier\n", deferredLevelName.c_str()); + SpawnableLevelSystem::LoadLevel(deferredLevelName.c_str()); + // Delete the key with the deferred level name + settingsRegistry->Remove(DeferredLoadLevelKey); + } + } } //------------------------------------------------------------------------ @@ -173,7 +202,7 @@ namespace LegacyLevelSystem } // Make sure a spawnable level exists that matches levelname - AZStd::string validLevelName = ""; + AZStd::string validLevelName; AZ::Data::AssetId rootSpawnableAssetId; AZ::Data::AssetCatalogRequestBus::BroadcastResult( rootSpawnableAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, levelName, nullptr, false); diff --git a/Registry/setregbuilder.assetprocessor.setreg b/Registry/setregbuilder.assetprocessor.setreg index 25b51470bf..00e6e2f7f8 100644 --- a/Registry/setregbuilder.assetprocessor.setreg +++ b/Registry/setregbuilder.assetprocessor.setreg @@ -20,7 +20,8 @@ "Excludes": [ "/Amazon/AzCore/Runtime", - "/Amazon/AzCore/Bootstrap/project_path" + "/Amazon/AzCore/Bootstrap/project_path", + "/O3DE/Runtime", ] } } From afa8bb92264c2928ea40420267714c83c3d3b723 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Sat, 9 Oct 2021 21:10:08 -0700 Subject: [PATCH 088/169] chore: update intersect and improve documentation Signed-off-by: Michael Pollind --- .../AzCore/AzCore/Math/IntersectSegment.cpp | 33 +- .../AzCore/AzCore/Math/IntersectSegment.h | 648 ++++++++++-------- .../AzCore/AzCore/Math/IntersectSegment.inl | 102 +++ .../AzCore/AzCore/azcore_files.cmake | 1 + 4 files changed, 485 insertions(+), 299 deletions(-) create mode 100644 Code/Framework/AzCore/AzCore/Math/IntersectSegment.inl diff --git a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.cpp b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.cpp index a7a0d5197e..2a00412689 100644 --- a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.cpp +++ b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.cpp @@ -157,7 +157,7 @@ Intersect::IntersectSegmentTriangle( // TestSegmentAABBOrigin // [10/21/2009] //========================================================================= -int +bool AZ::Intersect::TestSegmentAABBOrigin(const Vector3& midPoint, const Vector3& halfVector, const Vector3& aabbExtends) { const Vector3 EPSILON(0.001f); // \todo this is slow load move to a const @@ -168,7 +168,7 @@ AZ::Intersect::TestSegmentAABBOrigin(const Vector3& midPoint, const Vector3& hal // Try world coordinate axes as separating axes if (!absMidpoint.IsLessEqualThan(absHalfMidpoint)) { - return 0; + return false; } // Add in an epsilon term to counteract arithmetic errors when segment is @@ -188,11 +188,11 @@ AZ::Intersect::TestSegmentAABBOrigin(const Vector3& midPoint, const Vector3& hal Vector3 ead(ey * adz + ez * ady, ex * adz + ez * adx, ex * ady + ey * adx); if (!absMDCross.IsLessEqualThan(ead)) { - return 0; + return false; } // No separating axis found; segment must be overlapping AABB - return 1; + return true; } @@ -200,7 +200,7 @@ AZ::Intersect::TestSegmentAABBOrigin(const Vector3& midPoint, const Vector3& hal // IntersectRayAABB // [10/21/2009] //========================================================================= -int +RayAABBIsectTypes AZ::Intersect::IntersectRayAABB( const Vector3& rayStart, const Vector3& dir, const Vector3& dirRCP, const Aabb& aabb, float& tStart, float& tEnd, Vector3& startNormal /*, Vector3& inter*/) @@ -352,11 +352,14 @@ AZ::Intersect::IntersectRayAABB( return ISECT_RAY_AABB_ISECT; } + + + //========================================================================= // IntersectRayAABB2 // [2/18/2011] //========================================================================= -int +RayAABBIsectTypes AZ::Intersect::IntersectRayAABB2(const Vector3& rayStart, const Vector3& dirRCP, const Aabb& aabb, float& start, float& end) { float tmin, tmax, tymin, tymax, tzmin, tzmax; @@ -1166,7 +1169,7 @@ int AZ::Intersect::IntersectRayObb(const Vector3& rayOrigin, const Vector3& rayD // IntersectSegmentCylinder // [10/21/2009] //========================================================================= -int +CylinderIsectTypes AZ::Intersect::IntersectSegmentCylinder( const Vector3& sa, const Vector3& dir, const Vector3& p, const Vector3& q, const float r, float& t) { @@ -1225,7 +1228,7 @@ AZ::Intersect::IntersectSegmentCylinder( return RR_ISECT_RAY_CYL_NONE; // No real roots; no intersection } t = (-b - Sqrt(discr)) / a; - int result = RR_ISECT_RAY_CYL_PQ; // default along the PQ segment + CylinderIsectTypes result = RR_ISECT_RAY_CYL_PQ; // default along the PQ segment if (md + t * nd < 0.0f) { @@ -1294,7 +1297,7 @@ AZ::Intersect::IntersectSegmentCylinder( // IntersectSegmentCapsule // [10/21/2009] //========================================================================= -int +CapsuleIsectTypes AZ::Intersect::IntersectSegmentCapsule(const Vector3& sa, const Vector3& dir, const Vector3& p, const Vector3& q, const float r, float& t) { int result = IntersectSegmentCylinder(sa, dir, p, q, r, t); @@ -1361,7 +1364,7 @@ AZ::Intersect::IntersectSegmentCapsule(const Vector3& sa, const Vector3& dir, co // IntersectSegmentPolyhedron // [10/21/2009] //========================================================================= -int +bool AZ::Intersect::IntersectSegmentPolyhedron( const Vector3& sa, const Vector3& sBA, const Plane p[], int numPlanes, float& tfirst, float& tlast, int& iFirstPlane, int& iLastPlane) @@ -1388,7 +1391,7 @@ AZ::Intersect::IntersectSegmentPolyhedron( // If so, return "no intersection" if segment lies outside plane if (dist < 0.0f) { - return 0; + return false; } } else @@ -1417,7 +1420,7 @@ AZ::Intersect::IntersectSegmentPolyhedron( // Exit with "no intersection" if intersection becomes empty if (tfirst > tlast) { - return 0; + return false; } } } @@ -1425,11 +1428,11 @@ AZ::Intersect::IntersectSegmentPolyhedron( //DBG_Assert(iFirstPlane!=-1&&iLastPlane!=-1,("We have some bad border case to have only one plane, fix this function!")); if (iFirstPlane == -1 && iLastPlane == -1) { - return 0; + return false; } // A nonzero logical intersection, so the segment intersects the polyhedron - return 1; + return true; } //========================================================================= @@ -1442,7 +1445,7 @@ AZ::Intersect::ClosestSegmentSegment( const Vector3& segment2Start, const Vector3& segment2End, float& segment1Proportion, float& segment2Proportion, Vector3& closestPointSegment1, Vector3& closestPointSegment2, - float epsilon /*= 1e-4f*/ ) + float epsilon) { const Vector3 segment1 = segment1End - segment1Start; const Vector3 segment2 = segment2End - segment2Start; diff --git a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h index df3d5e10fb..7be35c5ae6 100644 --- a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h +++ b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h @@ -5,257 +5,262 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#ifndef AZCORE_MATH_SEGMENT_INTERSECTION_H -#define AZCORE_MATH_SEGMENT_INTERSECTION_H +#pragma once -#include #include #include #include - -/// \file isect_segment.h +#include namespace AZ { namespace Intersect { - //! LineToPointDistanceTime computes the time of the shortest distance from point 'p' to segment (s1,s2). - //! To calculate the point of intersection: - //! P = s1 + u (s2 - s1) - //! @param s1 segment start point - //! @param s2 segment end point - //! @param p point to find the closest time to. - //! @return time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)] - inline float LineToPointDistanceTime(const Vector3& s1, const Vector3& s21, const Vector3& p) - { - // so u = (p.x - s1.x)*(s2.x - s1.x) + (p.y - s1.y)*(s2.y - s1.y) + (p.z-s1.z)*(s2.z-s1.z) / |s2-s1|^2 - return s21.Dot(p - s1) / s21.Dot(s21); - } + /** + * LineToPointDistanceTime computes the time of the shortest distance from point 'p' to segment (s1,s2). + * To calculate the point of intersection: + * P = s1 + u (s2 - s1) + * @param s1 segment start point + * @param s2 segment end point + * @param p point to find the closest time to. + * @return time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)] + */ + float LineToPointDistanceTime(const Vector3& s1, const Vector3& s21, const Vector3& p); - //! LineToPointDistance computes the closest point to 'p' from a segment (s1,s2). - //! @param s1 segment start point - //! @param s2 segment end point - //! @param p point to find the closest time to. - //! @param u time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)] - //! @return the closest point - inline Vector3 LineToPointDistance(const Vector3& s1, const Vector3& s2, const Vector3& p, float& u) - { - const Vector3 s21 = s2 - s1; - // we assume seg1 and seg2 are NOT coincident - AZ_MATH_ASSERT(!s21.IsClose(Vector3(0.0f), 1e-4f), "OK we agreed that we will pass valid segments! (s1 != s2)"); + /** + * LineToPointDistance computes the closest point to 'p' from a segment (s1,s2). + * @param s1 segment start point + * @param s2 segment end point + * @param p point to find the closest time to. + * @param u time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)] + * @return the closest point + */ + Vector3 LineToPointDistance(const Vector3& s1, const Vector3& s2, const Vector3& p, float& u); - u = LineToPointDistanceTime(s1, s21, p); - - return s1 + u * s21; - } - - //! Given segment pq and triangle abc (CCW), returns whether segment intersects - //! triangle and if so, also returns the barycentric coordinates (u,v,w) - //! of the intersection point. - //! @param p segment start point - //! @param q segment end point - //! @param a triangle point 1 - //! @param b triangle point 2 - //! @param c triangle point 3 - //! @param normal at the intersection point. - //! @param t time of intersection along the segment [0.0 (p), 1.0 (q)] - //! @return 1 if the segment intersects the triangle otherwise 0 + /** + * Given segment pq and triangle abc (CCW), returns whether segment intersects + * triangle and if so, also returns the barycentric coordinates (u,v,w) + * of the intersection point. + * + * @param p segment start point + * @param q segment end point + * @param a triangle point 1 + * @param b triangle point 2 + * @param c triangle point 3 + * @param normal at the intersection point. + * @param t time of intersection along the segment [0.0 (p), 1.0 (q)] + * @return true if the segments intersects the triangle otherwise false + */ int IntersectSegmentTriangleCCW( - const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c, - /*float &u, float &v, float &w,*/ Vector3& normal, float& t); + const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c, Vector3& normal, float& t); - //! Same as \ref IntersectSegmentTriangleCCW without respecting the triangle (a,b,c) vertex order (double sided). + /** + * Same as \ref IntersectSegmentTriangleCCW without respecting the triangle (a,b,c) vertex order (double sided). + * + * @param p segment start point + * @param q segment end point + * @param a triangle point 1 + * @param b triangle point 2 + * @param c triangle point 3 + * @param normal at the intersection point; + * @param t time of intersection along the segment [0.0 (p), 1.0 (q)] + * @return true if the segments intersects the triangle otherwise false + */ int IntersectSegmentTriangle( - const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c, - /*float &u, float &v, float &w,*/ Vector3& normal, float& t); + const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c, Vector3& normal, float& t); //! Ray aabb intersection result types. - enum RayAABBIsectTypes + enum RayAABBIsectTypes : AZ::s32 { - ISECT_RAY_AABB_NONE = 0, ///< no intersection - ISECT_RAY_AABB_SA_INSIDE, ///< the ray starts inside the aabb - ISECT_RAY_AABB_ISECT, ///< intersects along the PQ segment + ISECT_RAY_AABB_NONE = 0, ///< no intersection + ISECT_RAY_AABB_SA_INSIDE, ///< the ray starts inside the aabb + ISECT_RAY_AABB_ISECT, ///< intersects along the PQ segment }; - //! Intersect ray R(t) = rayStart + t*d against AABB a. When intersecting, - //! return intersection distance tmin and point q of intersection. - //! @param rayStart ray starting point - //! @param dir ray direction and length (dir = rayEnd - rayStart) - //! @param dirRCP 1/dir (reciprocal direction - we cache this result very often so we don't need to compute it multiple times, otherwise just use dir.GetReciprocal()) - //! @param aabb Axis aligned bounding box to intersect against - //! @param tStart time on ray of the first intersection [0,1] or 0 if the ray starts inside the aabb - check the return value - //! @param tEnd time of the of the second intersection [0,1] (it can be > 1 if intersects after the rayEnd) - //! @param startNormal normal at the start point. - //! @return \ref RayAABBIsectTypes - int IntersectRayAABB( - const Vector3& rayStart, const Vector3& dir, const Vector3& dirRCP, const Aabb& aabb, - float& tStart, float& tEnd, Vector3& startNormal /*, Vector3& inter*/); + /** + * Intersect ray R(t) = rayStart + t*d against AABB a. When intersecting, + * return intersection distance tmin and point q of intersection. + * @param rayStart ray starting point + * @param dir ray direction and length (dir = rayEnd - rayStart) + * @param dirRCP 1/dir (reciprocal direction - we cache this result very often so we don't need to compute it multiple times, + * otherwise just use dir.GetReciprocal()) + * @param aabb Axis aligned bounding box to intersect against + * @param tStart time on ray of the first intersection [0,1] or 0 if the ray starts inside the aabb - check the return value + * @param tEnd time of the of the second intersection [0,1] (it can be > 1 if intersects after the rayEnd) + * @param startNormal normal at the start point. + * @return \ref RayAABBIsectTypes + */ + RayAABBIsectTypes IntersectRayAABB( + const Vector3& rayStart, + const Vector3& dir, + const Vector3& dirRCP, + const Aabb& aabb, + float& tStart, + float& tEnd, + Vector3& startNormal /*, Vector3& inter*/); - //! Intersect ray against AABB. - //! @param rayStart ray starting point. - //! @param dir ray reciprocal direction. - //! @param aabb Axis aligned bounding box to intersect against. - //! @param start length on ray of the first intersection. - //! @param end length of the of the second intersection. - //! @return \ref RayAABBIsectTypes In this faster version than IntersectRayAABB we return only ISECT_RAY_AABB_NONE and ISECT_RAY_AABB_ISECT. - //! You can check yourself for that case. - int IntersectRayAABB2( - const Vector3& rayStart, const Vector3& dirRCP, const Aabb& aabb, - float& start, float& end); + /** + * Intersect ray against AABB. + * + * @param rayStart ray starting point. + * @param dir ray reciprocal direction. + * @param aabb Axis aligned bounding box to intersect against. + * @param start length on ray of the first intersection. + * @param end length of the of the second intersection. + * @return \ref RayAABBIsectTypes In this faster version than IntersectRayAABB we return only ISECT_RAY_AABB_NONE and ISECT_RAY_AABB_ISECT. You can check yourself for that case. + */ + RayAABBIsectTypes IntersectRayAABB2(const Vector3& rayStart, const Vector3& dirRCP, const Aabb& aabb, float& start, float& end); - //! Clip a ray to an aabb. return true if ray was clipped. The ray - //! can be inside so don't use the result if the ray intersect the box. - inline int ClipRayWithAabb( - const Aabb& aabb, Vector3& rayStart, Vector3& rayEnd, float& tClipStart, float& tClipEnd) - { - Vector3 startNormal; - float tStart, tEnd; - Vector3 dirLen = rayEnd - rayStart; - if (IntersectRayAABB(rayStart, dirLen, dirLen.GetReciprocal(), aabb, tStart, tEnd, startNormal) != ISECT_RAY_AABB_NONE) - { - // clip the ray with the box - if (tStart > 0.0f) - { - rayStart = rayStart + tStart * dirLen; - tClipStart = tStart; - } - if (tEnd < 1.0f) - { - rayEnd = rayStart + tEnd * dirLen; - tClipEnd = tEnd; - } + /** + * Clip a ray to an aabb. return true if ray was clipped. The ray + * can be inside so don't use the result if the ray intersect the box. + * + * @param aabb bounds + * @param rayStart the start of the ray + * @param rayEnd the end of the ray + * @param tClipStart[out] The proportion where the ray enterts the aabb + * @param tClipEnd[out] The proportion where the ray exits the aabb + * @return true ray was clipped else false + */ + bool ClipRayWithAabb(const Aabb& aabb, Vector3& rayStart, Vector3& rayEnd, float& tClipStart, float& tClipEnd); - return 1; - } + /** + * Test segment and aabb where the segment is defined by midpoint + * midPoint = (p1-p0) * 0.5f and half vector halfVector = p1 - midPoint. + * the aabb is at the origin and defined by half extents only. + * + * @param midPoint midpoint of a line segment + * @param halfVector half vector of an aabb + * @param aabbExtends the extends of a bounded box + * @return 1 if the intersect, otherwise 0. + */ + bool TestSegmentAABBOrigin(const Vector3& midPoint, const Vector3& halfVector, const Vector3& aabbExtends); - return 0; - } - - //! Test segment and aabb where the segment is defined by midpoint - //! midPoint = (p1-p0) * 0.5f and half vector halfVector = p1 - midPoint. - //! the aabb is at the origin and defined by half extents only. - //! @return 1 if the intersect, otherwise 0. - int TestSegmentAABBOrigin(const Vector3& midPoint, const Vector3& halfVector, const Vector3& aabbExtends); - - //! Test if segment specified by points p0 and p1 intersects AABB. \ref TestSegmentAABBOrigin - //! @return 1 if the segment and AABB intersect, otherwise 0. - inline int TestSegmentAABB(const Vector3& p0, const Vector3& p1, const Aabb& aabb) - { - Vector3 e = aabb.GetExtents(); - Vector3 d = p1 - p0; - Vector3 m = p0 + p1 - aabb.GetMin() - aabb.GetMax(); - - return TestSegmentAABBOrigin(m, d, e); - } + /** + * Test if segment specified by points p0 and p1 intersects AABB. \ref TestSegmentAABBOrigin + * + * @param p0 point 1 + * @param p1 point 2 + * @param aabb bounded box + * @return true if the segment and AABB intersect, otherwise false. + */ + bool TestSegmentAABB(const Vector3& p0, const Vector3& p1, const Aabb& aabb); //! Ray sphere intersection result types. - enum SphereIsectTypes + enum SphereIsectTypes : AZ::s32 { ISECT_RAY_SPHERE_SA_INSIDE = -1, // the ray starts inside the cylinder - ISECT_RAY_SPHERE_NONE, // no intersection - ISECT_RAY_SPHERE_ISECT, // along the PQ segment + ISECT_RAY_SPHERE_NONE, // no intersection + ISECT_RAY_SPHERE_ISECT, // along the PQ segment }; - //! IntersectRaySphereOrigin - //! return time t>=0 but not limited, so if you check a segment make sure - //! t <= segmentLen - //! @param rayStart ray start point - //! @param rayDirNormalized ray direction normalized. - //! @param shereRadius sphere radius - //! @param time of closest intersection [0,+INF] in relation to the normalized direction. - //! @return \ref SphereIsectTypes - AZ_INLINE int IntersectRaySphereOrigin( - const Vector3& rayStart, const Vector3& rayDirNormalized, - const float sphereRadius, float& t) - { - Vector3 m = rayStart; - float b = m.Dot(rayDirNormalized); - float c = m.Dot(m) - sphereRadius * sphereRadius; + /** + * IntersectRaySphereOrigin + * return time t>=0 but not limited, so if you check a segment make sure + * t <= segmentLen + * @param rayStart ray start point + * @param rayDirNormalized ray direction normalized. + * @param shereRadius sphere radius + * @param time of closest intersection [0,+INF] in relation to the normalized direction. + * @return \ref SphereIsectTypes + **/ + SphereIsectTypes IntersectRaySphereOrigin( + const Vector3& rayStart, const Vector3& rayDirNormalized, const float sphereRadius, float& t); - // Exit if r's origin outside s (c > 0)and r pointing away from s (b > 0) - if (c > 0.0f && b > 0.0f) - { - return ISECT_RAY_SPHERE_NONE; - } - float discr = b * b - c; - // A negative discriminant corresponds to ray missing sphere - if (discr < 0.0f) - { - return ISECT_RAY_SPHERE_NONE; - } + /** + * Intersect ray (rayStart,rayDirNormalized) and sphere (sphereCenter,sphereRadius) \ref IntersectRaySphereOrigin + * + * @param rayStart + * @param rayDirNormalized + * @param sphereCenter + * @param sphereRadius + * @param t + * @return int + */ + SphereIsectTypes IntersectRaySphere( + const Vector3& rayStart, const Vector3& rayDirNormalized, const Vector3& sphereCenter, const float sphereRadius, float& t); - // Ray now found to intersect sphere, compute smallest t value of intersection - t = -b - Sqrt(discr); - - // If t is negative, ray started inside sphere so clamp t to zero - if (t < 0.0f) - { - // t = 0.0f; - return ISECT_RAY_SPHERE_SA_INSIDE; // no hit if inside - } - //q = p + t * d; - return ISECT_RAY_SPHERE_ISECT; - } - - //! Intersect ray (rayStart,rayDirNormalized) and sphere (sphereCenter,sphereRadius) \ref IntersectRaySphereOrigin - inline int IntersectRaySphere( - const Vector3& rayStart, const Vector3& rayDirNormalized, const Vector3& sphereCenter, const float sphereRadius, float& t) - { - return IntersectRaySphereOrigin(rayStart - sphereCenter, rayDirNormalized, sphereRadius, t); - } - - //! @param rayOrigin The origin of the ray to test. - //! @param rayDir The direction of the ray to test. It has to be unit length. - //! @param diskCenter Center point of the disk - //! @param diskRadius Radius of the disk - //! @param diskNormal A normal perpendicular to the disk - //! @param[out] t If returning 1 (indicating a hit), this contains distance from rayOrigin along the normalized rayDir that the hit occured at. - //! @return The number of intersecting points. + /** + * @param rayOrigin The origin of the ray to test. + * @param rayDir The direction of the ray to test. It has to be unit length. + * @param diskCenter Center point of the disk + * @param diskRadius Radius of the disk + * @param diskNormal A normal perpendicular to the disk + * @param[out] t If returning 1 (indicating a hit), this contains distance from rayOrigin along the normalized rayDir + * that the hit occured at. + * @return The number of intersecting points. + **/ int IntersectRayDisk( - const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& diskCenter, const float diskRadius, const AZ::Vector3& diskNormal, float& t); + const Vector3& rayOrigin, + const Vector3& rayDir, + const Vector3& diskCenter, + const float diskRadius, + const AZ::Vector3& diskNormal, + float& t); - //! If there is only one intersecting point, the coefficient is stored in \ref t1. - //! @param rayOrigin The origin of the ray to test. - //! @param rayDir The direction of the ray to test. It has to be unit length. - //! @param cylinderEnd1 The center of the circle on one end of the cylinder. - //! @param cylinderDir The direction pointing from \ref cylinderEnd1 to the other end of the cylinder. It has to be unit length. - //! @param cylinderHeight The distance between two centers of the circles on two ends of the cylinder respectively. - //! @param[out] t1 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated as "rayOrigin + t1 * rayDir". - //! @param[out] t2 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated as "rayOrigin + t2 * rayDir". - //! @return The number of intersecting points. + /** + * If there is only one intersecting point, the coefficient is stored in \ref t1. + * @param rayOrigin The origin of the ray to test. + * @param rayDir The direction of the ray to test. It has to be unit length. + * @param cylinderEnd1 The center of the circle on one end of the cylinder. + * @param cylinderDir The direction pointing from \ref cylinderEnd1 to the other end of the cylinder. It has to be unit + * length. + * @param cylinderHeight The distance between two centers of the circles on two ends of the cylinder respectively. + * @param[out] t1 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated + * as "rayOrigin + t1 * rayDir". + * @param[out] t2 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated + * as "rayOrigin + t2 * rayDir". + * @return The number of intersecting points. + **/ int IntersectRayCappedCylinder( - const Vector3& rayOrigin, const Vector3& rayDir, - const Vector3& cylinderEnd1, const Vector3& cylinderDir, float cylinderHeight, float cylinderRadius, - float& t1, float& t2); + const Vector3& rayOrigin, + const Vector3& rayDir, + const Vector3& cylinderEnd1, + const Vector3& cylinderDir, + float cylinderHeight, + float cylinderRadius, + float& t1, + float& t2); - //! If there is only one intersecting point, the coefficient is stored in \ref t1. - //! @param rayOrigin The origin of the ray to test. - //! @param rayDir The direction of the ray to test. It has to be unit length. - //! @param coneApex The apex of the cone. - //! @param coneDir The unit-length direction from the apex to the base. - //! @param coneHeight The height of the cone, from the apex to the base. - //! @param coneBaseRadius The radius of the cone base circle. - //! @param[out] t1 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated as "rayOrigin + t1 * rayDir". - //! @param[out] t2 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated as "rayOrigin + t2 * rayDir". - //! @return The number of intersecting points. + /** + * If there is only one intersecting point, the coefficient is stored in \ref t1. + * @param rayOrigin The origin of the ray to test. + * @param rayDir The direction of the ray to test. It has to be unit length. + * @param coneApex The apex of the cone. + * @param coneDir The unit-length direction from the apex to the base. + * @param coneHeight The height of the cone, from the apex to the base. + * @param coneBaseRadius The radius of the cone base circle. + * @param[out] t1 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated + * as "rayOrigin + t1 * rayDir". + * @param[out] t2 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated + * as "rayOrigin + t2 * rayDir". + * @return The number of intersecting points. + **/ int IntersectRayCone( - const Vector3& rayOrigin, const Vector3& rayDir, - const Vector3& coneApex, const Vector3& coneDir, float coneHeight, float coneBaseRadius, - float& t1, float& t2); + const Vector3& rayOrigin, + const Vector3& rayDir, + const Vector3& coneApex, + const Vector3& coneDir, + float coneHeight, + float coneBaseRadius, + float& t1, + float& t2); - //! Test intersection between a ray and a plane in 3D. - //! @param rayOrigin The origin of the ray to test intersection with. - //! @param rayDir The direction of the ray to test intersection with. - //! @param planePos A point on the plane to test intersection with. - //! @param planeNormal The normal of the plane to test intersection with. - //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection". - //! @return The number of intersection point. + /** + * Test intersection between a ray and a plane in 3D. + * @param rayOrigin The origin of the ray to test intersection with. + * @param rayDir The direction of the ray to test intersection with. + * @param planePos A point on the plane to test intersection with. + * @param planeNormal The normal of the plane to test intersection with. + * @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + *+ t * rayDirection". + * @return The number of intersection point. + **/ int IntersectRayPlane( - const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& planePos, - const Vector3& planeNormal, float& t); + const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& planePos, const Vector3& planeNormal, float& t); //! Test intersection between a ray and a two-sided quadrilateral defined by four points in 3D. - //! The four points that define the quadrilateral could be passed in with either counter clock-wise + //! The four points that define the quadrilateral could be passed in with either counter clock-wise //! winding or clock-wise winding. //! @param rayOrigin The origin of the ray to test intersection with. //! @param rayDir The direction of the ray to test intersection with. @@ -263,105 +268,180 @@ namespace AZ //! @param vertexB One of the four points that define the quadrilateral. //! @param vertexC One of the four points that define the quadrilateral. //! @param vertexD One of the four points that define the quadrilateral. - //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection". + //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + + //! t * rayDirection". //! @return The number of intersection point. int IntersectRayQuad( - const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& vertexA, - const Vector3& vertexB, const Vector3& vertexC, const Vector3& vertexD, float& t); - - //! Test intersection between a ray and an oriented box in 3D. - //! @param rayOrigin The origin of the ray to test intersection with. - //! @param rayDir The direction of the ray to test intersection with. - //! @param boxCenter The position of the center of the box. - //! @param boxAxis1 An axis along one dimension of the oriented box. - //! @param boxAxis2 An axis along one dimension of the oriented box. - //! @param boxAxis3 An axis along one dimension of the oriented box. - //! @param boxHalfExtent1 The half extent of the box on the dimension of \ref boxAxis1. - //! @param boxHalfExtent2 The half extent of the box on the dimension of \ref boxAxis2. - //! @param boxHalfExtent3 The half extent of the box on the dimension of \ref boxAxis3. - //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection". - //! @return 1 if there is an intersection, 0 otherwise. - int IntersectRayBox( - const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& boxCenter, const Vector3& boxAxis1, - const Vector3& boxAxis2, const Vector3& boxAxis3, float boxHalfExtent1, float boxHalfExtent2, float boxHalfExtent3, + const Vector3& rayOrigin, + const Vector3& rayDir, + const Vector3& vertexA, + const Vector3& vertexB, + const Vector3& vertexC, + const Vector3& vertexD, float& t); - //! Test intersection between a ray and an OBB. - //! @param rayOrigin The origin of the ray to test intersection with. - //! @param rayDir The direction of the ray to test intersection with. - //! @param obb The OBB to test for intersection with the ray. - //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection". - //! @return 1 if there is an intersection, 0 otherwise. + /** Test intersection between a ray and an oriented box in 3D. + * @param rayOrigin The origin of the ray to test intersection with. + * @param rayDir The direction of the ray to test intersection with. + * @param boxCenter The position of the center of the box. + * @param boxAxis1 An axis along one dimension of the oriented box. + * @param boxAxis2 An axis along one dimension of the oriented box. + * @param boxAxis3 An axis along one dimension of the oriented box. + * @param boxHalfExtent1 The half extent of the box on the dimension of \ref boxAxis1. + * @param boxHalfExtent2 The half extent of the box on the dimension of \ref boxAxis2. + * @param boxHalfExtent3 The half extent of the box on the dimension of \ref boxAxis3. + * @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + + * t * rayDirection". + * @return 1 if there is an intersection, 0 otherwise. + **/ + int IntersectRayBox( + const Vector3& rayOrigin, + const Vector3& rayDir, + const Vector3& boxCenter, + const Vector3& boxAxis1, + const Vector3& boxAxis2, + const Vector3& boxAxis3, + float boxHalfExtent1, + float boxHalfExtent2, + float boxHalfExtent3, + float& t); + + /** + * Test intersection between a ray and an OBB. + * @param rayOrigin The origin of the ray to test intersection with. + * @param rayDir The direction of the ray to test intersection with. + * @param obb The OBB to test for intersection with the ray. + * @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * + * rayDirection". + * @return 1 if there is an intersection, 0 otherwise. + */ int IntersectRayObb(const Vector3& rayOrigin, const Vector3& rayDir, const Obb& obb, float& t); //! Ray cylinder intersection types. - enum CylinderIsectTypes + enum CylinderIsectTypes : AZ::s32 { RR_ISECT_RAY_CYL_SA_INSIDE = -1, // the ray starts inside the cylinder - RR_ISECT_RAY_CYL_NONE, // no intersection - RR_ISECT_RAY_CYL_PQ, // along the PQ segment - RR_ISECT_RAY_CYL_P_SIDE, // on the P side - RR_ISECT_RAY_CYL_Q_SIDE, // on the Q side + RR_ISECT_RAY_CYL_NONE, // no intersection + RR_ISECT_RAY_CYL_PQ, // along the PQ segment + RR_ISECT_RAY_CYL_P_SIDE, // on the P side + RR_ISECT_RAY_CYL_Q_SIDE, // on the Q side }; - //! Intersect segment S(t)=sa+t(dir), 0<=t<=1 against cylinder specified by p, q and r. - int IntersectSegmentCylinder( - const Vector3& sa, const Vector3& dir, const Vector3& p, const Vector3& q, - const float r, float& t); + /** + * Reference: Real-Time Collision Detection - 5.3.7 Intersecting Ray or Segment Against Cylinder + * Intersect segment S(t)=sa+t(dir), 0<=t<=1 against cylinder specified by p, q and r. + * + * @param sa point + * @param dir magnitude along sa + * @param p center point of side 1 cylinder + * @param q center point of side 2 cylinder + * @param r radius of cylinder + * @param t[out] proporition along line semgnet + * @return CylinderIsectTypes + */ + CylinderIsectTypes IntersectSegmentCylinder( + const Vector3& sa, const Vector3& dir, const Vector3& p, const Vector3& q, const float r, float& t); //! Capsule ray intersect types. enum CapsuleIsectTypes { ISECT_RAY_CAPSULE_SA_INSIDE = -1, // the ray starts inside the cylinder ISECT_RAY_CAPSULE_NONE, // no intersection - ISECT_RAY_CAPSULE_PQ, // along the PQ segment - ISECT_RAY_CAPSULE_P_SIDE, // on the P side - ISECT_RAY_CAPSULE_Q_SIDE, // on the Q side + ISECT_RAY_CAPSULE_PQ, // along the PQ segment + ISECT_RAY_CAPSULE_P_SIDE, // on the P side + ISECT_RAY_CAPSULE_Q_SIDE, // on the Q side }; - //! This is a quick implementation of segment capsule based on segment cylinder \ref IntersectSegmentCylinder - //! segment sphere intersection. We can optimize it a lot once we fix the ray - //! cylinder intersection. - int IntersectSegmentCapsule( - const Vector3& sa, const Vector3& dir, const Vector3& p, - const Vector3& q, const float r, float& t); + /** + * This is a quick implementation of segment capsule based on segment cylinder \ref IntersectSegmentCylinder + * segment sphere intersection. We can optimize it a lot once we fix the ray + * cylinder intersection. + */ + CapsuleIsectTypes IntersectSegmentCapsule( + const Vector3& sa, const Vector3& dir, const Vector3& p, const Vector3& q, const float r, float& t); - //! Intersect segment S(t)=A+t(B-A), 0<=t<=1 against convex polyhedron specified - //! by the n halfspaces defined by the planes p[]. On exit tfirst and tlast - //! define the intersection, if any. - int IntersectSegmentPolyhedron( - const Vector3& sa, const Vector3& sBA, const Plane p[], int numPlanes, - float& tfirst, float& tlast, int& iFirstPlane, int& iLastPlane); + /** + * Intersect segment S(t)=A+t(B-A), 0<=t<=1 against convex polyhedron specified + * by the n halfspaces defined by the planes p[]. On exit tfirst and tlast + * define the intersection, if any. + */ + bool IntersectSegmentPolyhedron( + const Vector3& sa, + const Vector3& sBA, + const Plane p[], + int numPlanes, + float& tfirst, + float& tlast, + int& iFirstPlane, + int& iLastPlane); - //! Calculate the line segment closestPointSegment1<->closestPointSegment2 that is the shortest route between - //! two segments segment1Start<->segment1End and segment2Start<->segment2End. Also calculate the values of segment1Proportion and segment2Proportion where - //! closestPointSegment1 = segment1Start + (segment1Proportion * (segment1End - segment1Start)) - //! closestPointSegment2 = segment2Start + (segment2Proportion * (segment2End - segment2Start)) - //! If segments are parallel returns a solution. + /** + * Calculate the line segment closestPointSegment1<->closestPointSegment2 that is the shortest route between + * two segments segment1Start<->segment1End and segment2Start<->segment2End. Also calculate the values of segment1Proportion and + * segment2Proportion where closestPointSegment1 = segment1Start + (segment1Proportion * (segment1End - segment1Start)) + * closestPointSegment2 = segment2Start + (segment2Proportion * (segment2End - segment2Start)) + * If segments are parallel returns a solution. + * @param segment1Start start of segment 1. + * @param segment1End end of segment 1. + * @param segment2Start start of segment 2. + * @param segment2End end of segment 2. + * @param segment1Proportion[out] the proporition along segment 1 [0..1] + * @param segment2Proportion[out] the proporition along segment 2 [0..1] + * @param closestPointSegment1[out] closest point on segment 1. + * @param closestPointSegment2[out] closest point on segment 2. + * @param epsilon the minimum square distance where a line segment can be treated as a single point. + */ void ClosestSegmentSegment( - const Vector3& segment1Start, const Vector3& segment1End, - const Vector3& segment2Start, const Vector3& segment2End, - float& segment1Proportion, float& segment2Proportion, - Vector3& closestPointSegment1, Vector3& closestPointSegment2, + const Vector3& segment1Start, + const Vector3& segment1End, + const Vector3& segment2Start, + const Vector3& segment2End, + float& segment1Proportion, + float& segment2Proportion, + Vector3& closestPointSegment1, + Vector3& closestPointSegment2, float epsilon = 1e-4f); - //! Calculate the line segment closestPointSegment1<->closestPointSegment2 that is the shortest route between - //! two segments segment1Start<->segment1End and segment2Start<->segment2End. - //! If segments are parallel returns a solution. + /** + * Calculate the line segment closestPointSegment1<->closestPointSegment2 that is the shortest route between + * two segments segment1Start<->segment1End and segment2Start<->segment2End. + * If segments are parallel returns a solution. + * + * @param segment1Start start of segment 1. + * @param segment1End end of segment 1. + * @param segment2Start start of segment 2. + * @param segment2End end of segment 2. + * @param closestPointSegment1[out] closest point on segment 1. + * @param closestPointSegment2[out] closest point on segment 2. + * @param epsilon the minimum square distance where a line segment can be treated as a single point. + */ void ClosestSegmentSegment( - const Vector3& segment1Start, const Vector3& segment1End, - const Vector3& segment2Start, const Vector3& segment2End, - Vector3& closestPointSegment1, Vector3& closestPointSegment2, + const Vector3& segment1Start, + const Vector3& segment1End, + const Vector3& segment2Start, + const Vector3& segment2End, + Vector3& closestPointSegment1, + Vector3& closestPointSegment2, float epsilon = 1e-4f); - //! Calculate the point (closestPointOnSegment) that is the closest point on - //! segment segmentStart/segmentEnd to point. Also calculate the value of proportion where - //! closestPointOnSegment = segmentStart + (proportion * (segmentEnd - segmentStart)) + /** + * Calculate the point (closestPointOnSegment) that is the closest point on + * segment segmentStart/segmentEnd to point. Also calculate the value of proportion where + * closestPointOnSegment = segmentStart + (proportion * (segmentEnd - segmentStart)) + * + * @param point the point to test + * @param segmentStart the start of the segment + * @param segmentEnd the end of the segment + * @param proportion[out] the proportion of the segment L(t) = (end - start) * t + * @param closestPointOnSegment[out] the point along the line segment + */ void ClosestPointSegment( - const Vector3& point, const Vector3& segmentStart, const Vector3& segmentEnd, - float& proportion, Vector3& closestPointOnSegment); - } -} + const Vector3& point, + const Vector3& segmentStart, + const Vector3& segmentEnd, + float& proportion, + Vector3& closestPointOnSegment); + } // namespace Intersect +} // namespace AZ -#endif // AZCORE_MATH_SEGMENT_INTERSECTION_H -#pragma once +#include diff --git a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.inl b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.inl new file mode 100644 index 0000000000..b9f5139923 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.inl @@ -0,0 +1,102 @@ +/* + * 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 + +namespace AZ +{ + namespace Intersect + { + AZ_MATH_INLINE bool ClipRayWithAabb(const Aabb& aabb, Vector3& rayStart, Vector3& rayEnd, float& tClipStart, float& tClipEnd) + { + Vector3 startNormal; + float tStart, tEnd; + Vector3 dirLen = rayEnd - rayStart; + if (IntersectRayAABB(rayStart, dirLen, dirLen.GetReciprocal(), aabb, tStart, tEnd, startNormal) != ISECT_RAY_AABB_NONE) + { + // clip the ray with the box + if (tStart > 0.0f) + { + rayStart = rayStart + tStart * dirLen; + tClipStart = tStart; + } + if (tEnd < 1.0f) + { + rayEnd = rayStart + tEnd * dirLen; + tClipEnd = tEnd; + } + + return true; + } + + return false; + } + + AZ_MATH_INLINE SphereIsectTypes + IntersectRaySphereOrigin(const Vector3& rayStart, const Vector3& rayDirNormalized, const float sphereRadius, float& t) + { + Vector3 m = rayStart; + float b = m.Dot(rayDirNormalized); + float c = m.Dot(m) - sphereRadius * sphereRadius; + + // Exit if r's origin outside s (c > 0)and r pointing away from s (b > 0) + if (c > 0.0f && b > 0.0f) + { + return ISECT_RAY_SPHERE_NONE; + } + float discr = b * b - c; + // A negative discriminant corresponds to ray missing sphere + if (discr < 0.0f) + { + return ISECT_RAY_SPHERE_NONE; + } + + // Ray now found to intersect sphere, compute smallest t value of intersection + t = -b - Sqrt(discr); + + // If t is negative, ray started inside sphere so clamp t to zero + if (t < 0.0f) + { + // t = 0.0f; + return ISECT_RAY_SPHERE_SA_INSIDE; // no hit if inside + } + // q = p + t * d; + return ISECT_RAY_SPHERE_ISECT; + } + + AZ_MATH_INLINE SphereIsectTypes IntersectRaySphere(const Vector3& rayStart, const Vector3& rayDirNormalized, const Vector3& sphereCenter, const float sphereRadius, float& t) + { + return IntersectRaySphereOrigin(rayStart - sphereCenter, rayDirNormalized, sphereRadius, t); + } + + AZ_MATH_INLINE Vector3 LineToPointDistance(const Vector3& s1, const Vector3& s2, const Vector3& p, float& u) + { + const Vector3 s21 = s2 - s1; + // we assume seg1 and seg2 are NOT coincident + AZ_MATH_ASSERT(!s21.IsClose(Vector3(0.0f), 1e-4f), "OK we agreed that we will pass valid segments! (s1 != s2)"); + + u = LineToPointDistanceTime(s1, s21, p); + + return s1 + u * s21; + } + + AZ_MATH_INLINE float LineToPointDistanceTime(const Vector3& s1, const Vector3& s21, const Vector3& p) + { + // so u = (p.x - s1.x)*(s2.x - s1.x) + (p.y - s1.y)*(s2.y - s1.y) + (p.z-s1.z)*(s2.z-s1.z) / |s2-s1|^2 + return s21.Dot(p - s1) / s21.Dot(s21); + } + + AZ_MATH_INLINE bool TestSegmentAABB(const Vector3& p0, const Vector3& p1, const Aabb& aabb) + { + Vector3 e = aabb.GetExtents(); + Vector3 d = p1 - p0; + Vector3 m = p0 + p1 - aabb.GetMin() - aabb.GetMax(); + + return TestSegmentAABBOrigin(m, d, e); + } + } // namespace Intersect +} // namespace AZ diff --git a/Code/Framework/AzCore/AzCore/azcore_files.cmake b/Code/Framework/AzCore/AzCore/azcore_files.cmake index 6675958247..4d95ddf098 100644 --- a/Code/Framework/AzCore/AzCore/azcore_files.cmake +++ b/Code/Framework/AzCore/AzCore/azcore_files.cmake @@ -282,6 +282,7 @@ set(FILES Math/Internal/VertexContainer.inl Math/InterpolationSample.h Math/IntersectPoint.h + Math/IntersectSegment.inl Math/IntersectSegment.cpp Math/IntersectSegment.h Math/MathIntrinsics.h From c3ff1e0cd3e6a3c9145a9972d2090d802d8bdba2 Mon Sep 17 00:00:00 2001 From: greerdv Date: Mon, 11 Oct 2021 11:15:55 +0100 Subject: [PATCH 089/169] feedback from PR Signed-off-by: greerdv --- Gems/PhysX/Code/Source/EditorColliderComponent.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp index 7cc69caeb7..f8d0adf156 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp @@ -826,9 +826,9 @@ namespace PhysX } m_componentWarnings.push_back(AZStd::string::format( - "The asset \"%s\" contains one or more triangle meshes, which are not compatible with non-kinematic dynamic " - "rigid bodies. To make the collider compatible, you can export the asset as a primitive or convex mesh, use mesh " - "decomposition when exporting the asset, or set the rigid body to kinematic. Learn more about " + "The physics asset \"%s\" was exported using triangle mesh geometry, which is not compatible with non-kinematic " + "dynamic rigid bodies. To make the collider compatible, you can export the asset using primitive or convex mesh " + "geometry, use mesh decomposition when exporting the asset, or set the rigid body to kinematic. Learn more about " "colliders.", assetPath.c_str())); From b91d503a824a18b14ad8e724cd11cb805aec7e44 Mon Sep 17 00:00:00 2001 From: Artur K <96597+nemerle@users.noreply.github.com> Date: Mon, 11 Oct 2021 12:55:24 +0200 Subject: [PATCH 090/169] Add AZStd::lerp math function, based on C++20 (#3468) * Add AZStd::lerp math function, based on c++20 Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * Add unit test for AZStd::lerp, based on libc++ ones Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * written a reduced set of lerp tests, but now the license is correct Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * Update Code/Framework/AzCore/AzCore/std/math.h Co-authored-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * Update Code/Framework/AzCore/Tests/AZStd/Math.cpp Co-authored-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * fix the github suggestion merge Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * Copy some AZ::Lerp tests to std::lerp test suite + clang-format Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * Cleanup lerp test cases Remove comments that suggested very heavy tests that required things like `for every t1..` Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * Fix unit test compilation issues Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * fix whitespace issue Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * Use `TypeParam` in TYPED_TEST Co-authored-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * Remove unneeded new-lines Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * remove unused infinity Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> Co-authored-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/std/math.h | 45 ++++++++++++++++++ Code/Framework/AzCore/Tests/AZStd/Math.cpp | 46 +++++++++++++++++++ .../AzCore/Tests/azcoretests_files.cmake | 1 + 3 files changed, 92 insertions(+) create mode 100644 Code/Framework/AzCore/Tests/AZStd/Math.cpp diff --git a/Code/Framework/AzCore/AzCore/std/math.h b/Code/Framework/AzCore/AzCore/std/math.h index 03f12e6e08..042dcca657 100644 --- a/Code/Framework/AzCore/AzCore/std/math.h +++ b/Code/Framework/AzCore/AzCore/std/math.h @@ -30,4 +30,49 @@ namespace AZStd using std::sqrt; using std::tan; using std::trunc; + +} // namespace AZStd + +// from c++20 standard +namespace AZStd::Internal +{ + template + constexpr T lerp(T a, T b, T t) noexcept + { + if ((a <= 0 && b >= 0) || (a >= 0 && b <= 0)) + { + return t * b + (1 - t) * a; + } + if (t == 1) + { + return b; + } + const T x = a + t * (b - a); + if ((t > 1) == (b > a)) + { + return b < x ? x : b; + } + else + { + return x < b ? x : b; + } + } +} // namespace AZStd::Internal + +namespace AZStd +{ + constexpr float lerp(float a, float b, float t) noexcept + { + return Internal::lerp(a, b, t); + } + + constexpr double lerp(double a, double b, double t) noexcept + { + return Internal::lerp(a, b, t); + } + + constexpr long double lerp(long double a, long double b, long double t) noexcept + { + return Internal::lerp(a, b, t); + } } // namespace AZStd diff --git a/Code/Framework/AzCore/Tests/AZStd/Math.cpp b/Code/Framework/AzCore/Tests/AZStd/Math.cpp new file mode 100644 index 0000000000..5379c9946b --- /dev/null +++ b/Code/Framework/AzCore/Tests/AZStd/Math.cpp @@ -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 + * + */ + +#include +#include + +namespace UnitTest +{ + template + class StdMathTest : public ::testing::Test + { + }; + + using MathTestConfigs = ::testing::Types; + TYPED_TEST_CASE(StdMathTest, MathTestConfigs); + + TYPED_TEST(StdMathTest, LerpOperations) + { + using AZStd::lerp; + using ::testing::Eq; + using T = TypeParam; + + constexpr T maxNumber = AZStd::numeric_limits::max(); + constexpr T eps = AZStd::numeric_limits::epsilon(); + constexpr T a{ 42 }; + + // exactness: lerp(a,b,0)==a && lerp(a,b,1)==b + EXPECT_THAT(lerp(eps, maxNumber, T(0)), Eq(eps)); + EXPECT_THAT(lerp(eps, maxNumber, T(1)), Eq(maxNumber)); + + // consistency: lerp(a,a,t)==a + EXPECT_THAT(lerp(a, a, T(0.5)), Eq(a)); + EXPECT_THAT(lerp(eps, eps, T(0.5)), Eq(eps)); + + // a few generic tests taken from MathUtilTests.cpp + EXPECT_EQ(T(2.5), lerp(T(2), T(4), T(0.25))); + EXPECT_EQ(T(6.0), lerp(T(2), T(4), T(2.0))); + EXPECT_EQ(T(3.5), lerp(T(2), T(4), T(0.75))); + EXPECT_EQ(T(0.0), lerp(T(2), T(4), T(-1.0))); + } +} // namespace UnitTest diff --git a/Code/Framework/AzCore/Tests/azcoretests_files.cmake b/Code/Framework/AzCore/Tests/azcoretests_files.cmake index d738711a4f..6ba9944f7d 100644 --- a/Code/Framework/AzCore/Tests/azcoretests_files.cmake +++ b/Code/Framework/AzCore/Tests/azcoretests_files.cmake @@ -195,6 +195,7 @@ set(FILES AZStd/LockFreeQueues.cpp AZStd/LockFreeStacks.cpp AZStd/LockTests.cpp + AZStd/Math.cpp AZStd/Numeric.cpp AZStd/Ordered.cpp AZStd/Optional.cpp From f84bd9829a82e2b131ae913fcf134cc35fe32ad3 Mon Sep 17 00:00:00 2001 From: amzn-sean <75276488+amzn-sean@users.noreply.github.com> Date: Mon, 11 Oct 2021 13:01:14 +0100 Subject: [PATCH 091/169] remove some flackyness in physx automated tests (#4547) Signed-off-by: amzn-sean <75276488+amzn-sean@users.noreply.github.com> --- .../PythonTests/Physics/TestSuite_Periodic.py | 4 - ...egion_SplineRegionWithModifiedTransform.py | 2 +- .../ForceRegion_ZeroPointForceDoesNothing.py | 2 +- .../Physics/tests/joints/JointsHelper.py | 11 +- .../joints/Joints_FixedLeadFollowerCollide.py | 92 ----- .../RigidBody_KinematicModeWorks.py | 30 +- .../Joints_FixedLeadFollowerCollide.ly | 3 - .../filelist.xml | 6 - .../Joints_FixedLeadFollowerCollide/level.pak | 3 - .../leveldata/Environment.xml | 14 - .../leveldata/TerrainTexture.xml | 7 - .../leveldata/TimeOfDay.xml | 356 ------------------ .../leveldata/VegetationMap.dat | 3 - .../Joints_FixedLeadFollowerCollide/tags.txt | 12 - .../terraintexture.pak | 3 - .../Joints_HingeNoLimitsConstrained.ly | 4 +- .../RigidBody_KinematicModeWorks.ly | 4 +- 17 files changed, 30 insertions(+), 526 deletions(-) delete mode 100644 AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_FixedLeadFollowerCollide.py delete mode 100644 AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/Joints_FixedLeadFollowerCollide.ly delete mode 100644 AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/filelist.xml delete mode 100644 AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/level.pak delete mode 100644 AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/Environment.xml delete mode 100644 AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/TerrainTexture.xml delete mode 100644 AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/TimeOfDay.xml delete mode 100644 AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/VegetationMap.dat delete mode 100644 AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/tags.txt delete mode 100644 AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/terraintexture.pak diff --git a/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Periodic.py b/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Periodic.py index da89316993..e5dd9adbb9 100755 --- a/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Periodic.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/TestSuite_Periodic.py @@ -525,10 +525,6 @@ class TestAutomation(TestAutomationBase): from .tests.joints import Joints_BallNoLimitsConstrained as test_module self._run_test(request, workspace, editor, test_module) - def test_Joints_FixedLeadFollowerCollide(self, request, workspace, editor, launcher_platform): - from .tests.joints import Joints_FixedLeadFollowerCollide as test_module - self._run_test(request, workspace, editor, test_module) - def test_Joints_GlobalFrameConstrained(self, request, workspace, editor, launcher_platform): from .tests.joints import Joints_GlobalFrameConstrained as test_module self._run_test(request, workspace, editor, test_module) diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py index abc58779a2..e949d2d8f9 100644 --- a/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_SplineRegionWithModifiedTransform.py @@ -82,7 +82,7 @@ def ForceRegion_SplineRegionWithModifiedTransform(): import azlmbr.bus as bus # region Constants - TIMEOUT = 5.0 + TIMEOUT = 10.0 MIN_TRIGGER_DISTANCE = 2.0 # endregion diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py index 91190f83e5..6582628ff9 100644 --- a/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/force_region/ForceRegion_ZeroPointForceDoesNothing.py @@ -77,7 +77,7 @@ def ForceRegion_ZeroPointForceDoesNothing(): helper.init_idle() - TIMEOUT_SECONDS = 3.0 + TIMEOUT_SECONDS = 5.0 X_Y_Z_TOLERANCE = 1.5 REGION_HEIGHT = 3.0 TERRAIN_HEIGHT = 32.0 diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/JointsHelper.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/JointsHelper.py index 6226f42534..a85e460659 100644 --- a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/JointsHelper.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/JointsHelper.py @@ -45,8 +45,13 @@ class JointEntity: # Entity class that sets a flag when an instance receives collision events. class JointEntityCollisionAware(JointEntity): def on_collision_begin(self, args): - if not self.collided: - self.collided = True + self.collided = True + + def on_collision_persist(self, args): + self.collided = True + + def on_collision_end(self, args): + self.collided = True def __init__(self, name): self.id = general.find_game_entity(name) @@ -58,3 +63,5 @@ class JointEntityCollisionAware(JointEntity): self.handler = azlmbr.physics.CollisionNotificationBusHandler() self.handler.connect(self.id) self.handler.add_callback("OnCollisionBegin", self.on_collision_begin) + self.handler.add_callback("OnCollisionPresist", self.on_collision_persist) + self.handler.add_callback("OnCollisionEnd", self.on_collision_end) diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_FixedLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_FixedLeadFollowerCollide.py deleted file mode 100644 index e142941c5a..0000000000 --- a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_FixedLeadFollowerCollide.py +++ /dev/null @@ -1,92 +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 -""" - -# Test case ID : C18243582 -# Test Case Title : Check that fixed joint allows lead-follower collision - - -# fmt: off -class Tests: - enter_game_mode = ("Entered game mode", "Failed to enter game mode") - exit_game_mode = ("Exited game mode", "Couldn't exit game mode") - lead_found = ("Found lead", "Did not find lead") - follower_found = ("Found follower", "Did not find follower") - check_collision_happened = ("Lead and follower collided", "Lead and follower did not collide") -# fmt: on - - -def Joints_FixedLeadFollowerCollide(): - """ - Summary: Check that fixed joint allows lead-follower collision - - Level Description: - lead - Starts above follower entity - follower - Starts below lead entity. Constrained to lead entity with fixed joint. Starts with initial velocity of (5, 0, 0) in positive X direction. - - Expected Behavior: - The follower entity moves in the positive X direction and the lead entity is dragged along towards the positive X direction. - The x position of the lead entity is incremented from its original. - The lead and follower entities are kept apart at a distance of approximately 1.0 due to collision. - - Test Steps: - 1) Open Level - 2) Enter Game Mode - 3) Create and Validate Entities - 4) Wait for several seconds - 5) Check to see if lead and follower behaved as expected. - 6) Exit Game Mode - 7) Close Editor - - Note: - - This test file must be called from the Open 3D Engine Editor command terminal - - Any passed and failed tests are written to the Editor.log file. - Parsing the file or running a log_monitor are required to observe the test results. - - :return: None - """ - import os - import sys - from editor_python_test_tools.utils import Report - from editor_python_test_tools.utils import TestHelper as helper - - import azlmbr.legacy.general as general - import azlmbr.bus - - from JointsHelper import JointEntityCollisionAware - - # Helper Entity class - self.collided flag is set when instance receives collision event. - class Entity(JointEntityCollisionAware): - def criticalEntityFound(self): # Override function to use local Test dictionary - Report.critical_result(Tests.__dict__[self.name + "_found"], self.id.isValid()) - - # Main Script - helper.init_idle() - - # 1) Open Level - helper.open_level("Physics", "Joints_FixedLeadFollowerCollide") - - # 2) Enter Game Mode - helper.enter_game_mode(Tests.enter_game_mode) - - # 3) Create and Validate Entities - lead = Entity("lead") - follower = Entity("follower") - - # 4) Wait for several seconds - general.idle_wait(2.0) # wait for lead and follower to move - - # 5) Check to see if lead entity and follower collided - Report.critical_result(Tests.check_collision_happened, lead.collided and follower.collided) - - # 6) Exit Game Mode - helper.exit_game_mode(Tests.exit_game_mode) - - - -if __name__ == "__main__": - from editor_python_test_tools.utils import Report - Report.start_test(Joints_FixedLeadFollowerCollide) diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_KinematicModeWorks.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_KinematicModeWorks.py index 1c53854bab..05671389c2 100644 --- a/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_KinematicModeWorks.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/rigid_body/RigidBody_KinematicModeWorks.py @@ -80,6 +80,20 @@ def RigidBody_KinematicModeWorks(): ramp_id = general.find_game_entity("Ramp") Report.result(Tests.find_ramp, ramp_id.IsValid()) + # 2.1) setup collision handler + class RampTouched: + value = False + + def on_collision_begin(args): + other_id = args[0] + if other_id.Equal(ramp_id): + Report.info("Box touched ramp") + RampTouched.value = True + + handler = azlmbr.physics.CollisionNotificationBusHandler() + handler.connect(box_id) + handler.add_callback("OnCollisionBegin", on_collision_begin) + # 3) Check for kinematic ramp and not kinematic box box_kinematic = azlmbr.physics.RigidBodyRequestBus(azlmbr.bus.Event, "IsKinematic", box_id) Report.result(Tests.box_is_not_kinematic, not box_kinematic) @@ -98,21 +112,7 @@ def RigidBody_KinematicModeWorks(): ramp_pos_start = azlmbr.components.TransformBus(azlmbr.bus.Event, "GetWorldTranslation", ramp_id) Report.info("Ramp's initial position: {}".format(ramp_pos_start)) - # 6) Check to see that the box hits the ramp - class RampTouched: - value = False - - def on_collision_begin(args): - other_id = args[0] - if other_id.Equal(ramp_id): - Report.info("Box touched ramp") - RampTouched.value = True - - handler = azlmbr.physics.CollisionNotificationBusHandler() - handler.connect(box_id) - handler.add_callback("OnCollisionBegin", on_collision_begin) - - # 6.5) Wait for the box to touch the ramp or timeout + # 6) Wait for the box to touch the ramp or timeout helper.wait_for_condition(lambda: RampTouched.value, TIME_OUT) Report.result(Tests.box_touched_ramp, RampTouched.value) diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/Joints_FixedLeadFollowerCollide.ly b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/Joints_FixedLeadFollowerCollide.ly deleted file mode 100644 index 0c3ac9e668..0000000000 --- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/Joints_FixedLeadFollowerCollide.ly +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3093fee5317ba6fb353a435c09f43f13c5e722421aae62a297f699c202d6129e -size 6699 diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/filelist.xml b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/filelist.xml deleted file mode 100644 index d0960f8154..0000000000 --- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/filelist.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/level.pak b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/level.pak deleted file mode 100644 index 532be2c1bd..0000000000 --- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/level.pak +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b1daa050e732ff0594601bbfca8ac9ed05972c2f9fa3e43dbc8645e802ed2730 -size 7959 diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/Environment.xml b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/Environment.xml deleted file mode 100644 index 4ba36f66ae..0000000000 --- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/Environment.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/TerrainTexture.xml b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/TerrainTexture.xml deleted file mode 100644 index f43df05b22..0000000000 --- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/TerrainTexture.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/TimeOfDay.xml b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/TimeOfDay.xml deleted file mode 100644 index 456d609b8a..0000000000 --- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/TimeOfDay.xml +++ /dev/null @@ -1,356 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/VegetationMap.dat b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/VegetationMap.dat deleted file mode 100644 index dce5631cd0..0000000000 --- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/leveldata/VegetationMap.dat +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0e6a5435c928079b27796f6b202bbc2623e7e454244ddc099a3cadf33b7cb9e9 -size 63 diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/tags.txt b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/tags.txt deleted file mode 100644 index 0d6c1880e7..0000000000 --- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/tags.txt +++ /dev/null @@ -1,12 +0,0 @@ -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 -0,0,0,0,0,0 diff --git a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/terraintexture.pak b/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/terraintexture.pak deleted file mode 100644 index fe3604a050..0000000000 --- a/AutomatedTesting/Levels/Physics/Joints_FixedLeadFollowerCollide/terraintexture.pak +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8739c76e681f900923b900c9df0ef75cf421d39cabb54650c4b9ad19b6a76d85 -size 22 diff --git a/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly b/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly index 3d17ae7ccc..86dd941423 100644 --- a/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly +++ b/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:012caffa9354f6253d2e626ba183b44eb02a74eba286fde0430227ef024411e2 -size 8961 +oid sha256:817bd8dd22e185136418b60fba5b3552993687515d3d5ae96791f2c3be907b92 +size 7233 diff --git a/AutomatedTesting/Levels/Physics/RigidBody_KinematicModeWorks/RigidBody_KinematicModeWorks.ly b/AutomatedTesting/Levels/Physics/RigidBody_KinematicModeWorks/RigidBody_KinematicModeWorks.ly index 92e6788bf0..d6052ffa7c 100644 --- a/AutomatedTesting/Levels/Physics/RigidBody_KinematicModeWorks/RigidBody_KinematicModeWorks.ly +++ b/AutomatedTesting/Levels/Physics/RigidBody_KinematicModeWorks/RigidBody_KinematicModeWorks.ly @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:619bcf0c2a2b08f4ffe05e60858c479828fe39d5530f4e488b9c0ec8a585ccb7 -size 7735 +oid sha256:cb97ada674d123c67d7a32eb65e81fa66472cf51f748054c4a4297649f2a0f40 +size 5568 From 9baf76beab35c190eee3044e2d57b4b70421e5a3 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 11 Oct 2021 13:28:33 +0100 Subject: [PATCH 092/169] Add missing header for non-unity builds on Linux. Signed-off-by: John --- Code/Editor/MainWindow.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Editor/MainWindow.cpp b/Code/Editor/MainWindow.cpp index 05477bb0c7..ed72cd9170 100644 --- a/Code/Editor/MainWindow.cpp +++ b/Code/Editor/MainWindow.cpp @@ -98,6 +98,7 @@ AZ_POP_DISABLE_WARNING #include "ActionManager.h" #include +#include #include using namespace AZ; From 6c8441713d91a0237fe002a687b43847d92c8ab0 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 11 Oct 2021 14:02:56 +0100 Subject: [PATCH 093/169] Fix another missing header for Linux non-unity. Signed-off-by: John --- Code/Editor/GameExporter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Editor/GameExporter.cpp b/Code/Editor/GameExporter.cpp index 9315505e08..0324629877 100644 --- a/Code/Editor/GameExporter.cpp +++ b/Code/Editor/GameExporter.cpp @@ -28,6 +28,7 @@ #include "Objects/EntityObject.h" #include +#include ////////////////////////////////////////////////////////////////////////// #define MUSIC_LEVEL_LIBRARY_FILE "Music.xml" From e26d1f9ec564d3eed9412d6e65d6345daada6bd9 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 11 Oct 2021 14:17:46 +0100 Subject: [PATCH 094/169] Linux non-unity header fix (again). Signed-off-by: John --- Code/Editor/Viewport.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Code/Editor/Viewport.cpp b/Code/Editor/Viewport.cpp index 5b4f4a4df3..44c41fef2f 100644 --- a/Code/Editor/Viewport.cpp +++ b/Code/Editor/Viewport.cpp @@ -18,6 +18,7 @@ #include #include +#include #include // Editor From 3ef24d3a05400dbf6a1ba8d964f9cc1c37d7968a Mon Sep 17 00:00:00 2001 From: John Date: Mon, 11 Oct 2021 14:28:27 +0100 Subject: [PATCH 095/169] Header fix. Signed-off-by: John --- Code/Editor/Viewport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Editor/Viewport.cpp b/Code/Editor/Viewport.cpp index 44c41fef2f..c8f2e268d9 100644 --- a/Code/Editor/Viewport.cpp +++ b/Code/Editor/Viewport.cpp @@ -18,8 +18,8 @@ #include #include -#include #include +#include // Editor #include "ViewManager.h" From 1c3b293cd36da71dd5c34fc71521d9a81446b885 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Mon, 11 Oct 2021 07:28:34 -0700 Subject: [PATCH 096/169] fix comments replace /** with //! Signed-off-by: Michael Pollind --- .../AzCore/AzCore/Math/IntersectSegment.h | 454 ++++++++---------- .../AzCore/AzCore/Math/IntersectSegment.inl | 1 - 2 files changed, 204 insertions(+), 251 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h index 7be35c5ae6..ecb0d7acc9 100644 --- a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h +++ b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h @@ -16,56 +16,47 @@ namespace AZ { namespace Intersect { - /** - * LineToPointDistanceTime computes the time of the shortest distance from point 'p' to segment (s1,s2). - * To calculate the point of intersection: - * P = s1 + u (s2 - s1) - * @param s1 segment start point - * @param s2 segment end point - * @param p point to find the closest time to. - * @return time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)] - */ + //! LineToPointDistanceTime computes the time of the shortest distance from point 'p' to segment (s1,s2). + //! To calculate the point of intersection: + //! P = s1 + u (s2 - s1) + //! @param s1 segment start point + //! @param s2 segment end point + //! @param p point to find the closest time to. + //! @return time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)] float LineToPointDistanceTime(const Vector3& s1, const Vector3& s21, const Vector3& p); - /** - * LineToPointDistance computes the closest point to 'p' from a segment (s1,s2). - * @param s1 segment start point - * @param s2 segment end point - * @param p point to find the closest time to. - * @param u time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)] - * @return the closest point - */ + //! LineToPointDistance computes the closest point to 'p' from a segment (s1,s2). + //! @param s1 segment start point + //! @param s2 segment end point + //! @param p point to find the closest time to. + //! @param u time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)] + //! @return the closest point Vector3 LineToPointDistance(const Vector3& s1, const Vector3& s2, const Vector3& p, float& u); - /** - * Given segment pq and triangle abc (CCW), returns whether segment intersects - * triangle and if so, also returns the barycentric coordinates (u,v,w) - * of the intersection point. - * - * @param p segment start point - * @param q segment end point - * @param a triangle point 1 - * @param b triangle point 2 - * @param c triangle point 3 - * @param normal at the intersection point. - * @param t time of intersection along the segment [0.0 (p), 1.0 (q)] - * @return true if the segments intersects the triangle otherwise false - */ + //! Given segment pq and triangle abc (CCW), returns whether segment intersects + //! triangle and if so, also returns the barycentric coordinates (u,v,w) + //! of the intersection point. + //! + //! @param p segment start point + //! @param q segment end point + //! @param a triangle point 1 + //! @param b triangle point 2 + //! @param c triangle point 3 + //! @param normal at the intersection point. + //! @param t time of intersection along the segment [0.0 (p), 1.0 (q)] + //! @return true if the segments intersects the triangle otherwise false int IntersectSegmentTriangleCCW( const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c, Vector3& normal, float& t); - /** - * Same as \ref IntersectSegmentTriangleCCW without respecting the triangle (a,b,c) vertex order (double sided). - * - * @param p segment start point - * @param q segment end point - * @param a triangle point 1 - * @param b triangle point 2 - * @param c triangle point 3 - * @param normal at the intersection point; - * @param t time of intersection along the segment [0.0 (p), 1.0 (q)] - * @return true if the segments intersects the triangle otherwise false - */ + //! Same as \ref IntersectSegmentTriangleCCW without respecting the triangle (a,b,c) vertex order (double sided). + //! //! @param p segment start point + //! @param q segment end point + //! @param a triangle point 1 + //! @param b triangle point 2 + //! @param c triangle point 3 + //! @param normal at the intersection point; + //! @param t time of intersection along the segment [0.0 (p), 1.0 (q)] + //! @return true if the segments intersects the triangle otherwise false int IntersectSegmentTriangle( const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c, Vector3& normal, float& t); @@ -77,19 +68,17 @@ namespace AZ ISECT_RAY_AABB_ISECT, ///< intersects along the PQ segment }; - /** - * Intersect ray R(t) = rayStart + t*d against AABB a. When intersecting, - * return intersection distance tmin and point q of intersection. - * @param rayStart ray starting point - * @param dir ray direction and length (dir = rayEnd - rayStart) - * @param dirRCP 1/dir (reciprocal direction - we cache this result very often so we don't need to compute it multiple times, - * otherwise just use dir.GetReciprocal()) - * @param aabb Axis aligned bounding box to intersect against - * @param tStart time on ray of the first intersection [0,1] or 0 if the ray starts inside the aabb - check the return value - * @param tEnd time of the of the second intersection [0,1] (it can be > 1 if intersects after the rayEnd) - * @param startNormal normal at the start point. - * @return \ref RayAABBIsectTypes - */ + //! Intersect ray R(t) = rayStart + t*d against AABB a. When intersecting, + //! return intersection distance tmin and point q of intersection. + //! @param rayStart ray starting point + //! @param dir ray direction and length (dir = rayEnd - rayStart) + //! @param dirRCP 1/dir (reciprocal direction - we cache this result very often so we don't need to compute it multiple times, + //! otherwise just use dir.GetReciprocal()) + //! @param aabb Axis aligned bounding box to intersect against + //! @param tStart time on ray of the first intersection [0,1] or 0 if the ray starts inside the aabb - check the return value + //! @param tEnd time of the of the second intersection [0,1] (it can be > 1 if intersects after the rayEnd) + //! @param startNormal normal at the start point. + //! @return \ref RayAABBIsectTypes RayAABBIsectTypes IntersectRayAABB( const Vector3& rayStart, const Vector3& dir, @@ -99,51 +88,43 @@ namespace AZ float& tEnd, Vector3& startNormal /*, Vector3& inter*/); - /** - * Intersect ray against AABB. - * - * @param rayStart ray starting point. - * @param dir ray reciprocal direction. - * @param aabb Axis aligned bounding box to intersect against. - * @param start length on ray of the first intersection. - * @param end length of the of the second intersection. - * @return \ref RayAABBIsectTypes In this faster version than IntersectRayAABB we return only ISECT_RAY_AABB_NONE and ISECT_RAY_AABB_ISECT. You can check yourself for that case. - */ + //! Intersect ray against AABB. + //! + //! @param rayStart ray starting point. + //! @param dir ray reciprocal direction. + //! @param aabb Axis aligned bounding box to intersect against. + //! @param start length on ray of the first intersection. + //! @param end length of the of the second intersection. + //! @return \ref RayAABBIsectTypes In this faster version than IntersectRayAABB we return only ISECT_RAY_AABB_NONE and ISECT_RAY_AABB_ISECT. You can check yourself for that case. RayAABBIsectTypes IntersectRayAABB2(const Vector3& rayStart, const Vector3& dirRCP, const Aabb& aabb, float& start, float& end); - /** - * Clip a ray to an aabb. return true if ray was clipped. The ray - * can be inside so don't use the result if the ray intersect the box. - * - * @param aabb bounds - * @param rayStart the start of the ray - * @param rayEnd the end of the ray - * @param tClipStart[out] The proportion where the ray enterts the aabb - * @param tClipEnd[out] The proportion where the ray exits the aabb - * @return true ray was clipped else false - */ + //! Clip a ray to an aabb. return true if ray was clipped. The ray + //! can be inside so don't use the result if the ray intersect the box. + //! + //! @param aabb bounds + //! @param rayStart the start of the ray + //! @param rayEnd the end of the ray + //! @param tClipStart[out] The proportion where the ray enterts the aabb + //! @param tClipEnd[out] The proportion where the ray exits the aabb + //! @return true ray was clipped else false bool ClipRayWithAabb(const Aabb& aabb, Vector3& rayStart, Vector3& rayEnd, float& tClipStart, float& tClipEnd); - /** - * Test segment and aabb where the segment is defined by midpoint - * midPoint = (p1-p0) * 0.5f and half vector halfVector = p1 - midPoint. - * the aabb is at the origin and defined by half extents only. - * - * @param midPoint midpoint of a line segment - * @param halfVector half vector of an aabb - * @param aabbExtends the extends of a bounded box - * @return 1 if the intersect, otherwise 0. - */ + //! Test segment and aabb where the segment is defined by midpoint + //! midPoint = (p1-p0) * 0.5f and half vector halfVector = p1 - midPoint. + //! the aabb is at the origin and defined by half extents only. + //! + //! @param midPoint midpoint of a line segment + //! @param halfVector half vector of an aabb + //! @param aabbExtends the extends of a bounded box + //! @return 1 if the intersect, otherwise 0. bool TestSegmentAABBOrigin(const Vector3& midPoint, const Vector3& halfVector, const Vector3& aabbExtends); - /** - * Test if segment specified by points p0 and p1 intersects AABB. \ref TestSegmentAABBOrigin - * - * @param p0 point 1 - * @param p1 point 2 - * @param aabb bounded box - * @return true if the segment and AABB intersect, otherwise false. - */ + //! Test if segment specified by points p0 and p1 intersects AABB. \ref TestSegmentAABBOrigin + //! + //! @param p0 point 1 + //! @param p1 point 2 + //! @param aabb bounded box + //! @return true if the segment and AABB intersect, otherwise false. bool TestSegmentAABB(const Vector3& p0, const Vector3& p1, const Aabb& aabb); //! Ray sphere intersection result types. @@ -154,42 +135,36 @@ namespace AZ ISECT_RAY_SPHERE_ISECT, // along the PQ segment }; - /** - * IntersectRaySphereOrigin - * return time t>=0 but not limited, so if you check a segment make sure - * t <= segmentLen - * @param rayStart ray start point - * @param rayDirNormalized ray direction normalized. - * @param shereRadius sphere radius - * @param time of closest intersection [0,+INF] in relation to the normalized direction. - * @return \ref SphereIsectTypes - **/ + //! IntersectRaySphereOrigin + //! return time t>=0 but not limited, so if you check a segment make sure + //! t <= segmentLen + //! @param rayStart ray start point + //! @param rayDirNormalized ray direction normalized. + //! @param shereRadius sphere radius + //! @param time of closest intersection [0,+INF] in relation to the normalized direction. + //! @return \ref SphereIsectTypes SphereIsectTypes IntersectRaySphereOrigin( const Vector3& rayStart, const Vector3& rayDirNormalized, const float sphereRadius, float& t); - /** - * Intersect ray (rayStart,rayDirNormalized) and sphere (sphereCenter,sphereRadius) \ref IntersectRaySphereOrigin - * - * @param rayStart - * @param rayDirNormalized - * @param sphereCenter - * @param sphereRadius - * @param t - * @return int - */ + //! Intersect ray (rayStart,rayDirNormalized) and sphere (sphereCenter,sphereRadius) \ref IntersectRaySphereOrigin + //! + //! @param rayStart + //! @param rayDirNormalized + //! @param sphereCenter + //! @param sphereRadius + //! @param t + //! @return SphereIsectTypes SphereIsectTypes IntersectRaySphere( const Vector3& rayStart, const Vector3& rayDirNormalized, const Vector3& sphereCenter, const float sphereRadius, float& t); - /** - * @param rayOrigin The origin of the ray to test. - * @param rayDir The direction of the ray to test. It has to be unit length. - * @param diskCenter Center point of the disk - * @param diskRadius Radius of the disk - * @param diskNormal A normal perpendicular to the disk - * @param[out] t If returning 1 (indicating a hit), this contains distance from rayOrigin along the normalized rayDir - * that the hit occured at. - * @return The number of intersecting points. - **/ + //! @param rayOrigin The origin of the ray to test. + //! @param rayDir The direction of the ray to test. It has to be unit length. + //! @param diskCenter Center point of the disk + //! @param diskRadius Radius of the disk + //! @param diskNormal A normal perpendicular to the disk + //! @param[out] t If returning 1 (indicating a hit), this contains distance from rayOrigin along the normalized rayDir + //! that the hit occured at. + //! @return The number of intersecting points. int IntersectRayDisk( const Vector3& rayOrigin, const Vector3& rayDir, @@ -198,20 +173,18 @@ namespace AZ const AZ::Vector3& diskNormal, float& t); - /** - * If there is only one intersecting point, the coefficient is stored in \ref t1. - * @param rayOrigin The origin of the ray to test. - * @param rayDir The direction of the ray to test. It has to be unit length. - * @param cylinderEnd1 The center of the circle on one end of the cylinder. - * @param cylinderDir The direction pointing from \ref cylinderEnd1 to the other end of the cylinder. It has to be unit - * length. - * @param cylinderHeight The distance between two centers of the circles on two ends of the cylinder respectively. - * @param[out] t1 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated - * as "rayOrigin + t1 * rayDir". - * @param[out] t2 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated - * as "rayOrigin + t2 * rayDir". - * @return The number of intersecting points. - **/ + //! If there is only one intersecting point, the coefficient is stored in \ref t1. + //! @param rayOrigin The origin of the ray to test. + //! @param rayDir The direction of the ray to test. It has to be unit length. + //! @param cylinderEnd1 The center of the circle on one end of the cylinder. + //! @param cylinderDir The direction pointing from \ref cylinderEnd1 to the other end of the cylinder. It has to be unit + //! length. + //! @param cylinderHeight The distance between two centers of the circles on two ends of the cylinder respectively. + //! @param[out] t1 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated + //! as "rayOrigin + t1 * rayDir". + //! @param[out] t2 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated + //! as "rayOrigin + t2 * rayDir". + //! @return The number of intersecting points. int IntersectRayCappedCylinder( const Vector3& rayOrigin, const Vector3& rayDir, @@ -222,20 +195,18 @@ namespace AZ float& t1, float& t2); - /** - * If there is only one intersecting point, the coefficient is stored in \ref t1. - * @param rayOrigin The origin of the ray to test. - * @param rayDir The direction of the ray to test. It has to be unit length. - * @param coneApex The apex of the cone. - * @param coneDir The unit-length direction from the apex to the base. - * @param coneHeight The height of the cone, from the apex to the base. - * @param coneBaseRadius The radius of the cone base circle. - * @param[out] t1 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated - * as "rayOrigin + t1 * rayDir". - * @param[out] t2 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated - * as "rayOrigin + t2 * rayDir". - * @return The number of intersecting points. - **/ + //! If there is only one intersecting point, the coefficient is stored in \ref t1. + //! @param rayOrigin The origin of the ray to test. + //! @param rayDir The direction of the ray to test. It has to be unit length. + //! @param coneApex The apex of the cone. + //! @param coneDir The unit-length direction from the apex to the base. + //! @param coneHeight The height of the cone, from the apex to the base. + //! @param coneBaseRadius The radius of the cone base circle. + //! @param[out] t1 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated + //! as "rayOrigin + t1 * rayDir". + //! @param[out] t2 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated + //! as "rayOrigin + t2 * rayDir". + //! @return The number of intersecting points. int IntersectRayCone( const Vector3& rayOrigin, const Vector3& rayDir, @@ -246,16 +217,13 @@ namespace AZ float& t1, float& t2); - /** - * Test intersection between a ray and a plane in 3D. - * @param rayOrigin The origin of the ray to test intersection with. - * @param rayDir The direction of the ray to test intersection with. - * @param planePos A point on the plane to test intersection with. - * @param planeNormal The normal of the plane to test intersection with. - * @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin - *+ t * rayDirection". - * @return The number of intersection point. - **/ + //! Test intersection between a ray and a plane in 3D. + //! @param rayOrigin The origin of the ray to test intersection with. + //! @param rayDir The direction of the ray to test intersection with. + //! @param planePos A point on the plane to test intersection with. + //! @param planeNormal The normal of the plane to test intersection with. + //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection". + //! @return The number of intersection point. int IntersectRayPlane( const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& planePos, const Vector3& planeNormal, float& t); @@ -268,8 +236,7 @@ namespace AZ //! @param vertexB One of the four points that define the quadrilateral. //! @param vertexC One of the four points that define the quadrilateral. //! @param vertexD One of the four points that define the quadrilateral. - //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + - //! t * rayDirection". + //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection". //! @return The number of intersection point. int IntersectRayQuad( const Vector3& rayOrigin, @@ -280,20 +247,19 @@ namespace AZ const Vector3& vertexD, float& t); - /** Test intersection between a ray and an oriented box in 3D. - * @param rayOrigin The origin of the ray to test intersection with. - * @param rayDir The direction of the ray to test intersection with. - * @param boxCenter The position of the center of the box. - * @param boxAxis1 An axis along one dimension of the oriented box. - * @param boxAxis2 An axis along one dimension of the oriented box. - * @param boxAxis3 An axis along one dimension of the oriented box. - * @param boxHalfExtent1 The half extent of the box on the dimension of \ref boxAxis1. - * @param boxHalfExtent2 The half extent of the box on the dimension of \ref boxAxis2. - * @param boxHalfExtent3 The half extent of the box on the dimension of \ref boxAxis3. - * @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + - * t * rayDirection". - * @return 1 if there is an intersection, 0 otherwise. - **/ + //! Test intersection between a ray and an oriented box in 3D. + //! + //! @param rayOrigin The origin of the ray to test intersection with. + //! @param rayDir The direction of the ray to test intersection with. + //! @param boxCenter The position of the center of the box. + //! @param boxAxis1 An axis along one dimension of the oriented box. + //! @param boxAxis2 An axis along one dimension of the oriented box. + //! @param boxAxis3 An axis along one dimension of the oriented box. + //! @param boxHalfExtent1 The half extent of the box on the dimension of \ref boxAxis1. + //! @param boxHalfExtent2 The half extent of the box on the dimension of \ref boxAxis2. + //! @param boxHalfExtent3 The half extent of the box on the dimension of \ref boxAxis3. + //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection". + //! @return 1 if there is an intersection, 0 otherwise. int IntersectRayBox( const Vector3& rayOrigin, const Vector3& rayDir, @@ -306,15 +272,14 @@ namespace AZ float boxHalfExtent3, float& t); - /** - * Test intersection between a ray and an OBB. - * @param rayOrigin The origin of the ray to test intersection with. - * @param rayDir The direction of the ray to test intersection with. - * @param obb The OBB to test for intersection with the ray. - * @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * - * rayDirection". - * @return 1 if there is an intersection, 0 otherwise. - */ + //! Test intersection between a ray and an OBB. + //! + //! @param rayOrigin The origin of the ray to test intersection with. + //! @param rayDir The direction of the ray to test intersection with. + //! @param obb The OBB to test for intersection with the ray. + //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * + //! rayDirection". + //! @return 1 if there is an intersection, 0 otherwise. int IntersectRayObb(const Vector3& rayOrigin, const Vector3& rayDir, const Obb& obb, float& t); //! Ray cylinder intersection types. @@ -327,18 +292,16 @@ namespace AZ RR_ISECT_RAY_CYL_Q_SIDE, // on the Q side }; - /** - * Reference: Real-Time Collision Detection - 5.3.7 Intersecting Ray or Segment Against Cylinder - * Intersect segment S(t)=sa+t(dir), 0<=t<=1 against cylinder specified by p, q and r. - * - * @param sa point - * @param dir magnitude along sa - * @param p center point of side 1 cylinder - * @param q center point of side 2 cylinder - * @param r radius of cylinder - * @param t[out] proporition along line semgnet - * @return CylinderIsectTypes - */ + //! Reference: Real-Time Collision Detection - 5.3.7 Intersecting Ray or Segment Against Cylinder + //! Intersect segment S(t)=sa+t(dir), 0<=t<=1 against cylinder specified by p, q and r. + //! + //! @param sa point + //! @param dir magnitude along sa + //! @param p center point of side 1 cylinder + //! @param q center point of side 2 cylinder + //! @param r radius of cylinder + //! @param t[out] proporition along line semgnet + //! @return CylinderIsectTypes CylinderIsectTypes IntersectSegmentCylinder( const Vector3& sa, const Vector3& dir, const Vector3& p, const Vector3& q, const float r, float& t); @@ -352,19 +315,16 @@ namespace AZ ISECT_RAY_CAPSULE_Q_SIDE, // on the Q side }; - /** - * This is a quick implementation of segment capsule based on segment cylinder \ref IntersectSegmentCylinder - * segment sphere intersection. We can optimize it a lot once we fix the ray - * cylinder intersection. - */ + //! This is a quick implementation of segment capsule based on segment cylinder \ref IntersectSegmentCylinder + //! segment sphere intersection. We can optimize it a lot once we fix the ray + //! cylinder intersection. + //! CapsuleIsectTypes IntersectSegmentCapsule( const Vector3& sa, const Vector3& dir, const Vector3& p, const Vector3& q, const float r, float& t); - /** - * Intersect segment S(t)=A+t(B-A), 0<=t<=1 against convex polyhedron specified - * by the n halfspaces defined by the planes p[]. On exit tfirst and tlast - * define the intersection, if any. - */ + //! Intersect segment S(t)=A+t(B-A), 0<=t<=1 against convex polyhedron specified + //! by the n halfspaces defined by the planes p[]. On exit tfirst and tlast + //! define the intersection, if any. bool IntersectSegmentPolyhedron( const Vector3& sa, const Vector3& sBA, @@ -375,22 +335,20 @@ namespace AZ int& iFirstPlane, int& iLastPlane); - /** - * Calculate the line segment closestPointSegment1<->closestPointSegment2 that is the shortest route between - * two segments segment1Start<->segment1End and segment2Start<->segment2End. Also calculate the values of segment1Proportion and - * segment2Proportion where closestPointSegment1 = segment1Start + (segment1Proportion * (segment1End - segment1Start)) - * closestPointSegment2 = segment2Start + (segment2Proportion * (segment2End - segment2Start)) - * If segments are parallel returns a solution. - * @param segment1Start start of segment 1. - * @param segment1End end of segment 1. - * @param segment2Start start of segment 2. - * @param segment2End end of segment 2. - * @param segment1Proportion[out] the proporition along segment 1 [0..1] - * @param segment2Proportion[out] the proporition along segment 2 [0..1] - * @param closestPointSegment1[out] closest point on segment 1. - * @param closestPointSegment2[out] closest point on segment 2. - * @param epsilon the minimum square distance where a line segment can be treated as a single point. - */ + //! Calculate the line segment closestPointSegment1<->closestPointSegment2 that is the shortest route between + //! two segments segment1Start<->segment1End and segment2Start<->segment2End. Also calculate the values of segment1Proportion and + //! segment2Proportion where closestPointSegment1 = segment1Start + (segment1Proportion * (segment1End - segment1Start)) + //! closestPointSegment2 = segment2Start + (segment2Proportion * (segment2End - segment2Start)) + //! If segments are parallel returns a solution. + //! @param segment1Start start of segment 1. + //! @param segment1End end of segment 1. + //! @param segment2Start start of segment 2. + //! @param segment2End end of segment 2. + //! @param segment1Proportion[out] the proporition along segment 1 [0..1] + //! @param segment2Proportion[out] the proporition along segment 2 [0..1] + //! @param closestPointSegment1[out] closest point on segment 1. + //! @param closestPointSegment2[out] closest point on segment 2. + //! @param epsilon the minimum square distance where a line segment can be treated as a single point. void ClosestSegmentSegment( const Vector3& segment1Start, const Vector3& segment1End, @@ -402,19 +360,17 @@ namespace AZ Vector3& closestPointSegment2, float epsilon = 1e-4f); - /** - * Calculate the line segment closestPointSegment1<->closestPointSegment2 that is the shortest route between - * two segments segment1Start<->segment1End and segment2Start<->segment2End. - * If segments are parallel returns a solution. - * - * @param segment1Start start of segment 1. - * @param segment1End end of segment 1. - * @param segment2Start start of segment 2. - * @param segment2End end of segment 2. - * @param closestPointSegment1[out] closest point on segment 1. - * @param closestPointSegment2[out] closest point on segment 2. - * @param epsilon the minimum square distance where a line segment can be treated as a single point. - */ + //! Calculate the line segment closestPointSegment1<->closestPointSegment2 that is the shortest route between + //! two segments segment1Start<->segment1End and segment2Start<->segment2End. + //! If segments are parallel returns a solution. + //! + //! @param segment1Start start of segment 1. + //! @param segment1End end of segment 1. + //! @param segment2Start start of segment 2. + //! @param segment2End end of segment 2. + //! @param closestPointSegment1[out] closest point on segment 1. + //! @param closestPointSegment2[out] closest point on segment 2. + //! @param epsilon the minimum square distance where a line segment can be treated as a single point. void ClosestSegmentSegment( const Vector3& segment1Start, const Vector3& segment1End, @@ -424,17 +380,15 @@ namespace AZ Vector3& closestPointSegment2, float epsilon = 1e-4f); - /** - * Calculate the point (closestPointOnSegment) that is the closest point on - * segment segmentStart/segmentEnd to point. Also calculate the value of proportion where - * closestPointOnSegment = segmentStart + (proportion * (segmentEnd - segmentStart)) - * - * @param point the point to test - * @param segmentStart the start of the segment - * @param segmentEnd the end of the segment - * @param proportion[out] the proportion of the segment L(t) = (end - start) * t - * @param closestPointOnSegment[out] the point along the line segment - */ + //! Calculate the point (closestPointOnSegment) that is the closest point on + //! segment segmentStart/segmentEnd to point. Also calculate the value of proportion where + //! closestPointOnSegment = segmentStart + (proportion * (segmentEnd - segmentStart)) + //! + //! @param point the point to test + //! @param segmentStart the start of the segment + //! @param segmentEnd the end of the segment + //! @param proportion[out] the proportion of the segment L(t) = (end - start) * t + //! @param closestPointOnSegment[out] the point along the line segment void ClosestPointSegment( const Vector3& point, const Vector3& segmentStart, diff --git a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.inl b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.inl index b9f5139923..b570b6a182 100644 --- a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.inl +++ b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.inl @@ -5,7 +5,6 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#pragma once namespace AZ { From 2d7dfe5047bef70e3dcf4fcf77a8fab080eb3516 Mon Sep 17 00:00:00 2001 From: bosnichd Date: Mon, 11 Oct 2021 08:36:07 -0600 Subject: [PATCH 097/169] Increase the max time in the iOS run loop from DBL_EPSILON to one millisecond to address issue where the virtual keyboard is sluggish. (#4580) Signed-off-by: bosnichd --- .../Platform/iOS/AzFramework/Application/Application_iOS.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Code/Framework/AzFramework/Platform/iOS/AzFramework/Application/Application_iOS.mm b/Code/Framework/AzFramework/Platform/iOS/AzFramework/Application/Application_iOS.mm index 41bba124c7..36d920085b 100644 --- a/Code/Framework/AzFramework/Platform/iOS/AzFramework/Application/Application_iOS.mm +++ b/Code/Framework/AzFramework/Platform/iOS/AzFramework/Application/Application_iOS.mm @@ -112,9 +112,10 @@ namespace AzFramework void ApplicationIos::PumpSystemEventLoopUntilEmpty() { SInt32 result; + const CFTimeInterval MaxSecondsInRunLoop = 0.001; // One millisecond do { - result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, DBL_EPSILON, TRUE); + result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, MaxSecondsInRunLoop, TRUE); } while (result == kCFRunLoopRunHandledSource); } From 3b89f7e1cd0c259642d6b70de5b96a4a734267f9 Mon Sep 17 00:00:00 2001 From: Allen Jackson <23512001+jackalbe@users.noreply.github.com> Date: Mon, 11 Oct 2021 09:55:28 -0500 Subject: [PATCH 098/169] {lyn7283} added test for assetHint Json Serialzier callback logic (#4586) * {lyn7283} adding unit test for the assetHint Json Serialzier callback logic AssetTracker_Callback_Works will regress the functionality Signed-off-by: jackalbe <23512001+jackalbe@users.noreply.github.com> * clean up of the jsonRegistrationContext Signed-off-by: jackalbe <23512001+jackalbe@users.noreply.github.com> --- .../AzCore/Tests/AssetJsonSerializerTests.cpp | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp b/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp index e04c5190f9..e3a2c5c23b 100644 --- a/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp +++ b/Code/Framework/AzCore/Tests/AssetJsonSerializerTests.cpp @@ -64,6 +64,91 @@ namespace JsonSerializationTests }; + class TestSerializedAssetTracker + : public BaseJsonSerializerFixture + { + public: + void SetUp() override + { + BaseJsonSerializerFixture::SetUp(); + + AZ::AllocatorInstance::Create(); + AZ::AllocatorInstance::Create(); + + // Set up the Job Manager with 1 thread so that the Asset Manager is able to load assets. + AZ::JobManagerDesc jobDesc; + AZ::JobManagerThreadDesc threadDesc; + jobDesc.m_workerThreads.push_back(threadDesc); + m_jobManager = aznew AZ::JobManager(jobDesc); + m_jobContext = aznew AZ::JobContext(*m_jobManager); + AZ::JobContext::SetGlobalContext(m_jobContext); + + AZ::Data::AssetManager::Descriptor descriptor; + AZ::Data::AssetManager::Create(descriptor); + AZ::Data::AssetManager::Instance().RegisterHandler(&m_assetHandler, azrtti_typeid()); + + m_serializeContext->RegisterGenericType>(); + m_jsonRegistrationContext->Serializer()->HandlesType(); + } + + void TearDown() override + { + m_jsonRegistrationContext->EnableRemoveReflection(); + m_jsonRegistrationContext->Serializer()->HandlesType(); + m_jsonRegistrationContext->DisableRemoveReflection(); + + AZ::Data::AssetManager::Instance().UnregisterHandler(&m_assetHandler); + AZ::Data::AssetManager::Destroy(); + + AZ::JobContext::SetGlobalContext(nullptr); + delete m_jobContext; + delete m_jobManager; + + AZ::AllocatorInstance::Destroy(); + AZ::AllocatorInstance::Destroy(); + + BaseJsonSerializerFixture::TearDown(); + } + + private: + TestAssetHandler m_assetHandler; + AZ::JobManager* m_jobManager{ nullptr }; + AZ::JobContext* m_jobContext{ nullptr }; + }; + + TEST_F(TestSerializedAssetTracker, AssetTracker_Callback_Works) + { + auto assetCallback = [](AZ::Data::Asset& asset) + { + if (!asset.GetId().IsValid() && !asset.GetHint().empty()) + { + if (asset.GetHint() == "test/path/foo.asset") + { + asset.SetHint("passed"); + } + } + }; + auto tracker = AZ::Data::SerializedAssetTracker{}; + tracker.SetAssetFixUp(assetCallback); + + AZ::JsonDeserializerSettings settings; + settings.m_metadata.Add(tracker); + settings.m_registrationContext = this->m_jsonRegistrationContext.get(); + settings.m_serializeContext = this->m_serializeContext.get(); + + AZStd::string_view assetHintOnlyTestAsset = R"( + { + "assetHint" : "test/path/foo.asset" + })"; + rapidjson::Document jsonDom; + jsonDom.Parse(assetHintOnlyTestAsset.data()); + + AZ::Data::Asset instance; + auto result = AZ::JsonSerialization::Load(instance, jsonDom, settings); + EXPECT_NE(result.GetProcessing(), AZ::JsonSerializationResult::Processing::Halted); + EXPECT_STREQ(instance.GetHint().c_str(), "passed"); + } + class AssetSerializerTestDescription final : public JsonSerializerConformityTestDescriptor> { From 5c859cb13493e0c4e42984099c342a7fb9c0b104 Mon Sep 17 00:00:00 2001 From: hultonha <82228511+hultonha@users.noreply.github.com> Date: Mon, 11 Oct 2021 16:23:24 +0100 Subject: [PATCH 099/169] Fix camera drift issues (#4576) * remove some unused code in RenderViewportWidget and make viewing devicePixelRatioF easier Signed-off-by: hultonha * updates to how cursor positions are calculate to handle the viewport widget moving Signed-off-by: hultonha * remove optional for previous position Signed-off-by: hultonha * add test to capture error with moving the widget Signed-off-by: hultonha * minor comment updates before publishing PR Signed-off-by: hultonha --- .../test_ModularViewportCameraController.cpp | 48 +++++++++++++++++++ .../Input/QtEventToAzInputManager.cpp | 20 ++++---- .../Input/QtEventToAzInputManager.h | 6 +-- .../Viewport/RenderViewportWidget.h | 15 +++--- .../Source/Viewport/RenderViewportWidget.cpp | 11 ++--- 5 files changed, 71 insertions(+), 29 deletions(-) diff --git a/Code/Editor/Lib/Tests/test_ModularViewportCameraController.cpp b/Code/Editor/Lib/Tests/test_ModularViewportCameraController.cpp index 157291cfc2..ea3653f663 100644 --- a/Code/Editor/Lib/Tests/test_ModularViewportCameraController.cpp +++ b/Code/Editor/Lib/Tests/test_ModularViewportCameraController.cpp @@ -69,6 +69,7 @@ namespace UnitTest m_rootWidget = AZStd::make_unique(); m_rootWidget->setFixedSize(WidgetSize); + m_rootWidget->move(0, 0); // explicitly set the widget to be in the upper left corner m_controllerList = AZStd::make_shared(); m_controllerList->RegisterViewportContext(TestViewportId); @@ -344,4 +345,51 @@ namespace UnitTest // Clean-up HaltCollaborators(); } + + // test to verify deltas and cursor positions are handled correctly when the widget is moved + TEST_F(ModularViewportCameraControllerFixture, CameraDoesNotStutterAfterWidgetIsMoved) + { + // Given + PrepareCollaborators(); + SandboxEditor::SetCameraCaptureCursorForLook(true); + + const float deltaTime = 1.0f / 60.0f; + + // When + // move cursor to the center of the screen + auto start = QPoint(WidgetSize.width() / 2, WidgetSize.height() / 2); + MouseMove(m_rootWidget.get(), start, QPoint(0, 0)); + m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(deltaTime), AZ::ScriptTimePoint() }); + + // move camera right + const auto mouseDelta = QPoint(200, 0); + MousePressAndMove(m_rootWidget.get(), start, mouseDelta, Qt::MouseButton::RightButton); + m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(deltaTime), AZ::ScriptTimePoint() }); + + QTest::mouseRelease(m_rootWidget.get(), Qt::MouseButton::RightButton, Qt::NoModifier, start + mouseDelta); + + // update the position of the widget + const auto offset = QPoint(500, 500); + m_rootWidget->move(offset); + + // move cursor back to widget center + MouseMove(m_rootWidget.get(), start, QPoint(0, 0)); + m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(deltaTime), AZ::ScriptTimePoint() }); + + // move camera left + MousePressAndMove(m_rootWidget.get(), start, -mouseDelta, Qt::MouseButton::RightButton); + m_controllerList->UpdateViewport({ TestViewportId, AzFramework::FloatSeconds(deltaTime), AZ::ScriptTimePoint() }); + + // Then + // ensure the camera rotation has returned to the identity + const AZ::Quaternion cameraRotation = m_cameraViewportContextView->GetCameraTransform().GetRotation(); + const auto eulerAngles = AzFramework::EulerAngles(AZ::Matrix3x3::CreateFromQuaternion(cameraRotation)); + + using ::testing::FloatNear; + EXPECT_THAT(eulerAngles.GetX(), FloatNear(0.0f, 0.001f)); + EXPECT_THAT(eulerAngles.GetZ(), FloatNear(0.0f, 0.001f)); + + // Clean-up + HaltCollaborators(); + } } // namespace UnitTest diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp index 5fcf7e11d3..18acccf049 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.cpp @@ -261,10 +261,10 @@ namespace AzToolsFramework // ensures cursor positions are refreshed correctly with context menu focus changes) if (eventType == QEvent::FocusIn) { - const auto widgetCursorPosition = m_sourceWidget->mapFromGlobal(QCursor::pos()); - if (m_sourceWidget->geometry().contains(widgetCursorPosition)) + const auto globalCursorPosition = QCursor::pos(); + if (m_sourceWidget->geometry().contains(globalCursorPosition)) { - HandleMouseMoveEvent(widgetCursorPosition); + HandleMouseMoveEvent(globalCursorPosition); } } } @@ -290,7 +290,7 @@ namespace AzToolsFramework else if (eventType == QEvent::Type::MouseMove) { auto mouseEvent = static_cast(event); - HandleMouseMoveEvent(mouseEvent->pos()); + HandleMouseMoveEvent(mouseEvent->globalPos()); } // Map wheel events to the mouse Z movement channel. else if (eventType == QEvent::Type::Wheel) @@ -370,11 +370,12 @@ namespace AzToolsFramework return QPoint{ denormalizedX, denormalizedY }; } - void QtEventToAzInputMapper::HandleMouseMoveEvent(const QPoint& cursorPosition) + void QtEventToAzInputMapper::HandleMouseMoveEvent(const QPoint& globalCursorPosition) { - const QPoint cursorDelta = cursorPosition - m_previousCursorPosition; + const QPoint cursorDelta = globalCursorPosition - m_previousGlobalCursorPosition; - m_mouseDevice->m_cursorPositionData2D->m_normalizedPosition = WidgetPositionToNormalizedPosition(cursorPosition); + m_mouseDevice->m_cursorPositionData2D->m_normalizedPosition = + WidgetPositionToNormalizedPosition(m_sourceWidget->mapFromGlobal(globalCursorPosition)); m_mouseDevice->m_cursorPositionData2D->m_normalizedPositionDelta = WidgetPositionToNormalizedPosition(cursorDelta); ProcessPendingMouseEvents(cursorDelta); @@ -382,12 +383,11 @@ namespace AzToolsFramework if (m_capturingCursor) { // Reset our cursor position to the previous point - const QPoint screenCursorPosition = m_sourceWidget->mapToGlobal(m_previousCursorPosition); - AzQtComponents::SetCursorPos(screenCursorPosition); + AzQtComponents::SetCursorPos(m_previousGlobalCursorPosition); } else { - m_previousCursorPosition = cursorPosition; + m_previousGlobalCursorPosition = globalCursorPosition; } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.h index aaf3fb6295..5add24ad84 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Input/QtEventToAzInputManager.h @@ -129,7 +129,7 @@ namespace AzToolsFramework // Handle mouse click events. void HandleMouseButtonEvent(QMouseEvent* mouseEvent); // Handle mouse move events. - void HandleMouseMoveEvent(const QPoint& cursorPosition); + void HandleMouseMoveEvent(const QPoint& globalCursorPosition); // Handles key press / release events (or ShortcutOverride events for keys listed in m_highPriorityKeys). void HandleKeyEvent(QKeyEvent* keyEvent); // Handles mouse wheel events. @@ -156,8 +156,8 @@ namespace AzToolsFramework AZStd::unordered_set m_highPriorityKeys; // A lookup table for AZ input channel ID -> physical input channel on our mouse or keyboard device. AZStd::unordered_map m_channels; - // Where the position of the mouse cursor was at the last cursor event. - QPoint m_previousCursorPosition; + // Where the mouse cursor was at the last cursor event. + QPoint m_previousGlobalCursorPosition; // The source widget to map events from, used to calculate the relative mouse position within the widget bounds. QWidget* m_sourceWidget; // Flags whether or not Qt events should currently be processed. 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 623d759c9f..b407aa2b4c 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Include/AtomToolsFramework/Viewport/RenderViewportWidget.h @@ -90,7 +90,7 @@ namespace AtomToolsFramework //! Input processing is enabled by default. void SetInputProcessingEnabled(bool enabled); - // AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler ... + // AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler overrides ... AzFramework::CameraState GetCameraState() override; AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition) override; AZStd::optional ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition, float depth) override; @@ -98,12 +98,12 @@ namespace AtomToolsFramework const AzFramework::ScreenPoint& screenPosition) override; float DeviceScalingFactor() override; - // AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Handler ... + // AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Handler overrides ... void BeginCursorCapture() override; void EndCursorCapture() override; bool IsMouseOver() const override; - // AzFramework::WindowRequestBus::Handler ... + // AzFramework::WindowRequestBus::Handler overrides ... void SetWindowTitle(const AZStd::string& title) override; AzFramework::WindowSize GetClientAreaSize() const override; void ResizeClientArea(AzFramework::WindowSize clientAreaSize) override; @@ -116,18 +116,17 @@ namespace AtomToolsFramework uint32_t GetDisplayRefreshRate() const override; protected: - // AzFramework::InputChannelEventListener ... + // AzFramework::InputChannelEventListener overrides ... bool OnInputChannelEventFiltered(const AzFramework::InputChannel& inputChannel) override; - // AZ::TickBus::Handler ... + // AZ::TickBus::Handler overrides ... void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; - // QWidget ... + // QWidget overrides ... void resizeEvent(QResizeEvent *event) override; bool event(QEvent* event) override; void enterEvent(QEvent* event) override; void leaveEvent(QEvent* event) override; - void mouseMoveEvent(QMouseEvent* event) override; private: void SendWindowResizeEvent(); @@ -143,8 +142,6 @@ namespace AtomToolsFramework AZ::RPI::AuxGeomDrawPtr m_auxGeom; // 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. - QPointF m_mousePosition; // Captures the time between our render events to give controllers a time delta. QElapsedTimer m_renderTimer; // The time of the last recorded tick event from the system tick bus. diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp index 7192afebf7..83926ecc79 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Viewport/RenderViewportWidget.cpp @@ -214,20 +214,17 @@ namespace AtomToolsFramework m_mouseOver = false; } - void RenderViewportWidget::mouseMoveEvent(QMouseEvent* event) - { - m_mousePosition = event->localPos(); - } - void RenderViewportWidget::SendWindowResizeEvent() { // Scale the size by the DPI of the platform to // get the proper size in pixels. + const auto pixelRatio = devicePixelRatioF(); const QSize uiWindowSize = size(); - const QSize windowSize = uiWindowSize * devicePixelRatioF(); + const QSize windowSize = uiWindowSize * pixelRatio; const AzFramework::NativeWindowHandle windowId = reinterpret_cast(winId()); - AzFramework::WindowNotificationBus::Event(windowId, &AzFramework::WindowNotifications::OnWindowResized, windowSize.width(), windowSize.height()); + AzFramework::WindowNotificationBus::Event( + windowId, &AzFramework::WindowNotifications::OnWindowResized, windowSize.width(), windowSize.height()); } AZ::Name RenderViewportWidget::GetCurrentContextName() const From 189aa5f3acc225a66763cece9bd5efc8dea37228 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Mon, 11 Oct 2021 08:50:05 -0700 Subject: [PATCH 100/169] Disable the creation of the UserSettings.xml file in Xcb tests (#4593) Signed-off-by: Chris Burel --- .../Tests/Platform/Common/Xcb/XcbInputDeviceKeyboardTests.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbInputDeviceKeyboardTests.cpp b/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbInputDeviceKeyboardTests.cpp index 3abbcdc564..2b1f21ede7 100644 --- a/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbInputDeviceKeyboardTests.cpp +++ b/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbInputDeviceKeyboardTests.cpp @@ -12,6 +12,7 @@ #include +#include #include #include #include @@ -196,6 +197,7 @@ namespace AzFramework Application application; application.Start({}, {}); + AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); const InputChannel* inputChannel = InputChannelRequests::FindInputChannel(InputDeviceKeyboard::Key::AlphanumericA); ASSERT_TRUE(inputChannel); @@ -420,6 +422,7 @@ namespace AzFramework Application application; application.Start({}, {}); + AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); for (int i = 0; i < 4; ++i) { From 091b729183fbcf7e0041aeb0b28cc8724d38e321 Mon Sep 17 00:00:00 2001 From: Tobias Alexander Franke Date: Mon, 11 Oct 2021 18:48:28 +0200 Subject: [PATCH 101/169] Do not run SSAO pass when disabled (#3826) * Define fallback slots when shader is disabled * Disable SSAO parent pass depending on the settings * Move SSAO modulation pass into SsaoParent pass so it can be disabled with the rest of SSAO * Enable SSAO by default Co-authored-by: Tobias Alexander Franke --- .../Common/Assets/Passes/OpaqueParent.pass | 29 ++------------- .../Common/Assets/Passes/SsaoCompute.pass | 8 +++- .../Common/Assets/Passes/SsaoParent.pass | 37 ++++++++++++++++++- .../Code/Source/PostProcessing/SsaoPasses.cpp | 27 +++++++++++++- 4 files changed, 72 insertions(+), 29 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass b/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass index f45f5c8b07..752d565234 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/OpaqueParent.pass @@ -472,36 +472,15 @@ "Pass": "Parent", "Attachment": "DepthLinear" } - } - ] - }, - { - "Name": "ModulateWithSsao", - "TemplateName": "ModulateTextureTemplate", - "Enabled": true, - "Connections": [ - { - "LocalSlot": "Input", - "AttachmentRef": { - "Pass": "Ssao", - "Attachment": "Output" - } }, { - "LocalSlot": "InputOutput", + "LocalSlot": "Modulate", "AttachmentRef": { "Pass": "SubsurfaceScatteringPass", "Attachment": "Output" } } - ], - "PassData": { - "$type": "ComputePassData", - "ShaderAsset": { - "FilePath": "Shaders/PostProcessing/ModulateTexture.shader" - }, - "Make Fullscreen Pass": true - } + ] }, { "Name": "DiffuseSpecularMergePass", @@ -510,8 +489,8 @@ { "LocalSlot": "InputDiffuse", "AttachmentRef": { - "Pass": "ModulateWithSsao", - "Attachment": "InputOutput" + "Pass": "Ssao", + "Attachment": "Output" } }, { diff --git a/Gems/Atom/Feature/Common/Assets/Passes/SsaoCompute.pass b/Gems/Atom/Feature/Common/Assets/Passes/SsaoCompute.pass index 034b4359b4..3c4a8c76f1 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/SsaoCompute.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/SsaoCompute.pass @@ -51,7 +51,13 @@ }, "Make Fullscreen Pass": true, "PipelineViewTag": "MainCamera" - } + }, + "FallbackConnections": [ + { + "Input": "LinearDepth", + "Output": "Output" + } + ] } } } diff --git a/Gems/Atom/Feature/Common/Assets/Passes/SsaoParent.pass b/Gems/Atom/Feature/Common/Assets/Passes/SsaoParent.pass index b94ca4ab38..111518706f 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/SsaoParent.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/SsaoParent.pass @@ -12,6 +12,11 @@ "SlotType": "Input", "ScopeAttachmentUsage": "Shader" }, + { + "Name": "Modulate", + "SlotType": "Input", + "ScopeAttachmentUsage": "Shader" + }, { "Name": "Output", "SlotType": "Output", @@ -22,8 +27,8 @@ { "LocalSlot": "Output", "AttachmentRef": { - "Pass": "Upsample", - "Attachment": "Output" + "Pass": "ModulateWithSsao", + "Attachment": "InputOutput" } } ], @@ -103,6 +108,34 @@ } } ] + }, + { + "Name": "ModulateWithSsao", + "TemplateName": "ModulateTextureTemplate", + "Enabled": true, + "Connections": [ + { + "LocalSlot": "Input", + "AttachmentRef": { + "Pass": "Upsample", + "Attachment": "Output" + } + }, + { + "LocalSlot": "InputOutput", + "AttachmentRef": { + "Pass": "Parent", + "Attachment": "Modulate" + } + } + ], + "PassData": { + "$type": "ComputePassData", + "ShaderAsset": { + "FilePath": "Shaders/PostProcessing/ModulateTexture.shader" + }, + "Make Fullscreen Pass": true + } } ] } diff --git a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/SsaoPasses.cpp b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/SsaoPasses.cpp index 5e6d4b2ad9..15f7f52338 100644 --- a/Gems/Atom/Feature/Common/Code/Source/PostProcessing/SsaoPasses.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/PostProcessing/SsaoPasses.cpp @@ -34,7 +34,32 @@ namespace AZ bool SsaoParentPass::IsEnabled() const { - return ParentPass::IsEnabled(); + if (!ParentPass::IsEnabled()) + { + return false; + } + const RPI::Scene* scene = GetScene(); + if (!scene) + { + return false; + } + PostProcessFeatureProcessor* fp = scene->GetFeatureProcessor(); + const RPI::ViewPtr view = GetRenderPipeline()->GetDefaultView(); + if (!fp) + { + return true; + } + PostProcessSettings* postProcessSettings = fp->GetLevelSettingsFromView(view); + if (!postProcessSettings) + { + return true; + } + const SsaoSettings* ssaoSettings = postProcessSettings->GetSsaoSettings(); + if (!ssaoSettings) + { + return true; + } + return ssaoSettings->GetEnabled(); } void SsaoParentPass::InitializeInternal() From c759bc9cd02e5a05fc418728ef5d023f4c79ef91 Mon Sep 17 00:00:00 2001 From: Junbo Liang <68558268+junbo75@users.noreply.github.com> Date: Mon, 11 Oct 2021 10:52:00 -0700 Subject: [PATCH 102/169] Update the Jenkins script to disable access log during AWSI deployment (#4579) Signed-off-by: Junbo Liang --- scripts/build/Platform/Windows/deploy_cdk_applications.cmd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build/Platform/Windows/deploy_cdk_applications.cmd b/scripts/build/Platform/Windows/deploy_cdk_applications.cmd index 54a2485360..006e0158c0 100644 --- a/scripts/build/Platform/Windows/deploy_cdk_applications.cmd +++ b/scripts/build/Platform/Windows/deploy_cdk_applications.cmd @@ -57,7 +57,7 @@ IF ERRORLEVEL 1 ( exit /b 1 ) -CALL :DeployCDKApplication AWSCore --all "-c disable_access_log=true" +CALL :DeployCDKApplication AWSCore "-c disable_access_log=true --all" IF ERRORLEVEL 1 ( exit /b 1 ) From 45def7440986934ed8cea07db62306506c262ad8 Mon Sep 17 00:00:00 2001 From: sweeneys Date: Mon, 11 Oct 2021 11:11:40 -0700 Subject: [PATCH 103/169] Fix extension ignoring between Windows and Linux Signed-off-by: sweeneys --- .../environment/process_utils.py | 88 ++++++++++++------- Tools/LyTestTools/tests/integ/sanity_tests.py | 4 +- .../tests/unit/test_process_utils.py | 51 +++++++++-- 3 files changed, 101 insertions(+), 42 deletions(-) diff --git a/Tools/LyTestTools/ly_test_tools/environment/process_utils.py b/Tools/LyTestTools/ly_test_tools/environment/process_utils.py index 79fc4f420a..f8245495fa 100755 --- a/Tools/LyTestTools/ly_test_tools/environment/process_utils.py +++ b/Tools/LyTestTools/ly_test_tools/environment/process_utils.py @@ -31,45 +31,59 @@ def kill_processes_named(names, ignore_extensions=False): Kills all processes with a given name :param names: string process name, or list of strings of process name - :param ignore_extensions: ignore trailing file extension + :param ignore_extensions: ignore trailing file extensions. By default 'abc.exe' will not match 'abc'. Note that + enabling this will cause 'abc.exe' to match 'abc', 'abc.bat', and 'abc.sh', though 'abc.GameLauncher.exe' + will not match 'abc.DedicatedServer' """ if not names: return - names = [names] if isinstance(names, str) else names + name_set = set() + if isinstance(names, str): + name_set.add(names) + else: + name_set.update(names) if ignore_extensions: - names = [_remove_extension(name) for name in names] + # both exact matches and extensionless + stripped_names = set() + for name in name_set: + stripped_names.add(_remove_extension(name)) + name_set.update(stripped_names) # remove any blank names, which may empty the list - names = list(filter(lambda x: not x.isspace(), names)) - if not names: + name_set = set(filter(lambda x: not x.isspace(), name_set)) + if not name_set: return - logger.info(f"Killing all processes named {names}") - process_list_to_kill = [] + logger.info(f"Killing all processes named {name_set}") + process_set_to_kill = set() for process in _safe_get_processes(['name', 'pid']): try: proc_name = process.name() except psutil.AccessDenied: - logger.info(f"Process {process} permissions error during kill_processes_named()", exc_info=True) + logger.warning(f"Process {process} permissions error during kill_processes_named()", exc_info=True) continue except psutil.ProcessLookupError: - logger.debug(f"Process {process} could not be killed during kill_processes_named() and was likely already stopped", exc_info=True) + logger.debug(f"Process {process} could not be killed during kill_processes_named() and was likely already " + f"stopped", exc_info=True) continue except psutil.NoSuchProcess: logger.debug(f"Process '{process}' was active when list of processes was requested but it was not found " f"during kill_processes_named()", exc_info=True) continue + if proc_name in name_set: + logger.debug(f"Found process with name {proc_name}.") + process_set_to_kill.add(process) + if ignore_extensions: - proc_name = _remove_extension(proc_name) + extensionless_name = _remove_extension(proc_name) + if extensionless_name in name_set: + process_set_to_kill.add(process) - if proc_name in names: - logger.debug(f"Found process with name {proc_name}. Attempting to kill...") - process_list_to_kill.append(process) - - _safe_kill_process_list(process_list_to_kill) + if process_set_to_kill: + _safe_kill_processes(process_set_to_kill) def kill_processes_started_from(path): @@ -90,7 +104,7 @@ def kill_processes_started_from(path): if process_path.lower().startswith(path.lower()): process_list.append(process) - _safe_kill_process_list(process_list) + _safe_kill_processes(process_list) else: logger.warning(f"Path:'{path}' not found") @@ -118,7 +132,7 @@ def kill_processes_with_name_not_started_from(name, path): logger.info("%s -> %s" % (os.path.dirname(process_path.lower()), path)) proccesses_to_kill.append(process) - _safe_kill_process_list(proccesses_to_kill) + _safe_kill_processes(proccesses_to_kill) else: logger.warning(f"Path:'{path}' not found") @@ -151,10 +165,12 @@ def process_exists(name, ignore_extensions=False): :return: A boolean determining whether the process is alive or not """ name = name.lower() - if ignore_extensions: - name = _remove_extension(name) if name.isspace(): return False + + if ignore_extensions: + name_extensionless = _remove_extension(name) + for process in _safe_get_processes(["name"]): try: proc_name = process.name().lower() @@ -165,10 +181,17 @@ def process_exists(name, ignore_extensions=False): except psutil.AccessDenied as e: logger.info(f"Permissions issue on {process} during process_exists check", exc_info=True) continue - if ignore_extensions: - proc_name = _remove_extension(proc_name) - if proc_name == name: + + if proc_name == name: # abc.exe matches abc.exe return True + if ignore_extensions: + proc_name_extensionless = _remove_extension(proc_name) + if proc_name_extensionless == name: # abc matches abc.exe + return True + if proc_name == name_extensionless: # abc.exe matches abc + return True + # don't check proc_name_extensionless against name_extensionless: abc.exe and abc.exe are already tested, + # however xyz.Gamelauncher should not match xyz.DedicatedServer return False @@ -341,17 +364,14 @@ def _safe_kill_process(proc): except Exception: # purposefully broad logger.warning("Unexpected exception while terminating process", exc_info=True) -def _safe_kill_process_list(proc_list): + +def _safe_kill_processes(processes): """ Kills a given process without raising an error - :param proc_list: The process list to kill + :param processes: An iterable of processes to kill """ - - def on_terminate(proc): - print(f"process '{proc.name()}' with id '{proc.pid}' terminated with exit code {proc.returncode}") - - for proc in proc_list: + for proc in processes: try: logger.info(f"Terminating process '{proc.name()}' with id '{proc.pid}'") proc.kill() @@ -360,12 +380,14 @@ def _safe_kill_process_list(proc_list): except psutil.NoSuchProcess: logger.debug("Termination request ignored, process was already terminated during iteration", exc_info=True) except Exception: # purposefully broad - logger.warning("Unexpected exception while terminating process", exc_info=True) + logger.warning("Unexpected exception ignored while terminating process", exc_info=True) + def on_terminate(proc): + logger.info(f"process '{proc.name()}' with id '{proc.pid}' terminated with exit code {proc.returncode}") try: - psutil.wait_procs(proc_list, timeout=30, callback=on_terminate) + psutil.wait_procs(processes, timeout=30, callback=on_terminate) except Exception: # purposefully broad - logger.warning("Unexpected exception while waiting for process to terminate", exc_info=True) + logger.warning("Unexpected exception while waiting for processes to terminate", exc_info=True) def _terminate_and_confirm_dead(proc): @@ -383,7 +405,7 @@ def _terminate_and_confirm_dead(proc): def _remove_extension(filename): """ - Returns a file name without its extension + Returns a file name without its extension, if any is present :param filename: The name of a file :return: The name of the file without the extension diff --git a/Tools/LyTestTools/tests/integ/sanity_tests.py b/Tools/LyTestTools/tests/integ/sanity_tests.py index ed77d7b8db..2e46d822c7 100755 --- a/Tools/LyTestTools/tests/integ/sanity_tests.py +++ b/Tools/LyTestTools/tests/integ/sanity_tests.py @@ -58,7 +58,7 @@ class TestAutomatedTestingProject(object): # Call the game client executable with launcher.start(): # Wait for the process to exist - waiter.wait_for(lambda: process_utils.process_exists(f"{project}.GameLauncher", ignore_extensions=True)) + waiter.wait_for(lambda: process_utils.process_exists(f"{project}.GameLauncher.exe", ignore_extensions=True)) finally: # Clean up processes after the test is finished process_utils.kill_processes_named(names=process_utils.LY_PROCESS_KILL_LIST, ignore_extensions=True) @@ -85,7 +85,7 @@ class TestAutomatedTestingProject(object): # Call the Editor executable with editor.start(): # Wait for the process to exist - waiter.wait_for(lambda: process_utils.process_exists("Editor", ignore_extensions=True)) + waiter.wait_for(lambda: process_utils.process_exists("Editor.exe", ignore_extensions=True)) finally: # Clean up processes after the test is finished process_utils.kill_processes_named(names=process_utils.LY_PROCESS_KILL_LIST, ignore_extensions=True) diff --git a/Tools/LyTestTools/tests/unit/test_process_utils.py b/Tools/LyTestTools/tests/unit/test_process_utils.py index de40fb8e34..bd6a79fb09 100755 --- a/Tools/LyTestTools/tests/unit/test_process_utils.py +++ b/Tools/LyTestTools/tests/unit/test_process_utils.py @@ -223,7 +223,7 @@ class TestCloseWindowsProcess(unittest.TestCase): mock_enum.assert_called_once() -class Test(unittest.TestCase): +class TestProcessMatching(unittest.TestCase): @mock.patch("ly_test_tools.environment.process_utils._safe_get_processes") def test_ProcExists_HasExtension_Found(self, mock_get_proc): @@ -261,18 +261,55 @@ class Test(unittest.TestCase): self.assertTrue(result) proc_mock.name.assert_called() - @mock.patch('ly_test_tools.environment.process_utils._safe_kill_process', mock.MagicMock) + @mock.patch('ly_test_tools.environment.process_utils._safe_kill_processes') @mock.patch('ly_test_tools.environment.process_utils._safe_get_processes') - def test_KillProcNamed_MockKill_SilentSuccess(self, mock_get_proc): + def test_KillProcNamed_ExactMatch_Killed(self, mock_get_proc, mock_kill_proc): + name = "dummy.exe" + proc_mock = mock.MagicMock() + proc_mock.name.return_value = name + mock_get_proc.return_value = [proc_mock] + + process_utils.kill_processes_named("dummy.exe", ignore_extensions=False) + mock_kill_proc.assert_called() + proc_mock.name.assert_called() + + @mock.patch('ly_test_tools.environment.process_utils._safe_kill_processes') + @mock.patch('ly_test_tools.environment.process_utils._safe_get_processes') + def test_KillProcNamed_NearMatch_Ignore(self, mock_get_proc, mock_kill_proc): + name = "dummy.exe" + proc_mock = mock.MagicMock() + proc_mock.name.return_value = name + mock_get_proc.return_value = [proc_mock] + + process_utils.kill_processes_named("dummy", ignore_extensions=False) + mock_kill_proc.assert_not_called() + proc_mock.name.assert_called() + + @mock.patch('ly_test_tools.environment.process_utils._safe_kill_processes') + @mock.patch('ly_test_tools.environment.process_utils._safe_get_processes') + def test_KillProcNamed_NearMatchIgnoreExtension_Kill(self, mock_get_proc, mock_kill_proc): name = "dummy.exe" proc_mock = mock.MagicMock() proc_mock.name.return_value = name mock_get_proc.return_value = [proc_mock] process_utils.kill_processes_named("dummy", ignore_extensions=True) + mock_kill_proc.assert_called() proc_mock.name.assert_called() - @mock.patch('ly_test_tools.environment.process_utils._safe_kill_process', mock.MagicMock) + @mock.patch('ly_test_tools.environment.process_utils._safe_kill_processes') + @mock.patch('ly_test_tools.environment.process_utils._safe_get_processes') + def test_KillProcNamed_ExactMatchIgnoreExtension_Killed(self, mock_get_proc, mock_kill_proc): + name = "dummy.exe" + proc_mock = mock.MagicMock() + proc_mock.name.return_value = name + mock_get_proc.return_value = [proc_mock] + + process_utils.kill_processes_named("dummy.exe", ignore_extensions=True) + mock_kill_proc.assert_called() + proc_mock.name.assert_called() + + @mock.patch('ly_test_tools.environment.process_utils._safe_kill_processes', mock.MagicMock) @mock.patch('ly_test_tools.environment.process_utils._safe_get_processes') @mock.patch('os.path.exists') def test_KillProcFrom_MockKill_SilentSuccess(self, mock_path, mock_get_proc): @@ -293,7 +330,7 @@ class Test(unittest.TestCase): mock_kill.assert_called() - @mock.patch('ly_test_tools.environment.process_utils._safe_kill_process', mock.MagicMock) + @mock.patch('ly_test_tools.environment.process_utils._safe_kill_processes', mock.MagicMock) @mock.patch('psutil.Process') def test_KillProcPid_NoProc_SilentPass(self, mock_psutil): mock_proc = mock.MagicMock() @@ -302,7 +339,7 @@ class Test(unittest.TestCase): process_utils.kill_process_with_pid(1) - @mock.patch('ly_test_tools.environment.process_utils._safe_kill_process', mock.MagicMock) + @mock.patch('ly_test_tools.environment.process_utils._safe_kill_processes', mock.MagicMock) @mock.patch('psutil.Process') def test_KillProcPidRaiseOnMissing_NoProc_Raises(self, mock_psutil): mock_proc = mock.MagicMock() @@ -339,7 +376,7 @@ class Test(unittest.TestCase): mock_wait_procs.side_effect = psutil.PermissionError() proc_mock = mock.MagicMock() - process_utils._safe_kill_process_list(proc_mock) + process_utils._safe_kill_processes(proc_mock) mock_wait_procs.assert_called() mock_log_warn.assert_called() From ef3470b0a91c1f0f11becc6dcad487d07addb2b1 Mon Sep 17 00:00:00 2001 From: Alex Peterson <26804013+AMZN-alexpete@users.noreply.github.com> Date: Mon, 11 Oct 2021 12:04:44 -0700 Subject: [PATCH 104/169] Dependency confirmation screen and URL display fix Signed-off-by: AMZN-alexpete <26804013+AMZN-alexpete@users.noreply.github.com> --- .../Resources/ProjectManager.qss | 23 +++- .../Source/CreateProjectCtrl.cpp | 6 +- .../Source/GemCatalog/GemCatalogScreen.cpp | 29 +++-- .../Source/GemCatalog/GemCatalogScreen.h | 9 +- .../GemCatalog/GemDependenciesDialog.cpp | 80 ++++++++++++++ .../Source/GemCatalog/GemDependenciesDialog.h | 27 +++++ .../Source/GemCatalog/GemItemDelegate.cpp | 102 +++++++++++++++--- .../Source/GemCatalog/GemItemDelegate.h | 3 + .../Source/GemCatalog/GemListView.cpp | 21 ---- .../Source/GemCatalog/GemModel.cpp | 14 +++ .../Source/GemCatalog/GemModel.h | 1 + .../GemCatalog/GemRequirementDelegate.cpp | 47 ++++++-- .../GemCatalog/GemRequirementDelegate.h | 3 + .../GemCatalog/GemRequirementDialog.cpp | 29 ++--- .../Source/GemCatalog/GemRequirementDialog.h | 12 +-- .../GemRequirementFilterProxyModel.cpp | 21 +--- .../GemRequirementFilterProxyModel.h | 5 +- .../GemCatalog/GemRequirementListView.cpp | 1 - .../Tools/ProjectManager/Source/TagWidget.cpp | 81 ++++---------- Code/Tools/ProjectManager/Source/TagWidget.h | 6 -- .../Source/UpdateProjectCtrl.cpp | 6 +- .../project_manager_files.cmake | 2 + 22 files changed, 343 insertions(+), 185 deletions(-) create mode 100644 Code/Tools/ProjectManager/Source/GemCatalog/GemDependenciesDialog.cpp create mode 100644 Code/Tools/ProjectManager/Source/GemCatalog/GemDependenciesDialog.h diff --git a/Code/Tools/ProjectManager/Resources/ProjectManager.qss b/Code/Tools/ProjectManager/Resources/ProjectManager.qss index f91a597481..5f7826dbac 100644 --- a/Code/Tools/ProjectManager/Resources/ProjectManager.qss +++ b/Code/Tools/ProjectManager/Resources/ProjectManager.qss @@ -496,13 +496,34 @@ QProgressBar::chunk { background-color: #333333; } -/************** Filter tag widget **************/ +#GemDependenciesDialog QLabel { + margin-bottom:10px; +} + +#GemDependenciesDialog QCheckBox { + background-color: #333333; + border-radius: 3px; + spacing:3px; + margin-right:5px; + padding:4px; + margin-top:5px; +} + +/************** Filter Tag widget **************/ #FilterTagWidgetTextLabel { color: #94D2FF; font-size: 10px; } +#TagWidget { + background-color: #333333; + padding:3px; + font-size:12px; + border-radius: 3px; + margin-right: 3px; +} + /************** Gems SubWidget **************/ #gemSubWidgetTitleLabel { diff --git a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp index f098518fd3..84b931cb30 100644 --- a/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/CreateProjectCtrl.cpp @@ -238,9 +238,13 @@ namespace O3DE::ProjectManager PythonBindingsInterface::Get()->AddProject(projectInfo.m_path); #ifdef TEMPLATE_GEM_CONFIGURATION_ENABLED - if (!m_gemCatalogScreen->EnableDisableGemsForProject(projectInfo.m_path)) + const GemCatalogScreen::EnableDisableGemsResult gemResult = m_gemCatalogScreen->EnableDisableGemsForProject(m_projectInfo.m_path); + if (gemResult == GemCatalogScreen::EnableDisableGemsResult::Failed) { QMessageBox::critical(this, tr("Failed to configure gems"), tr("Failed to configure gems for template.")); + } + if (gemResult != GemCatalogScreen::EnableDisableGemsResult::Success) + { return; } #endif // TEMPLATE_GEM_CONFIGURATION_ENABLED diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp index a41a81b448..945878768d 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -134,7 +135,7 @@ namespace O3DE::ProjectManager } } - bool GemCatalogScreen::EnableDisableGemsForProject(const QString& projectPath) + GemCatalogScreen::EnableDisableGemsResult GemCatalogScreen::EnableDisableGemsForProject(const QString& projectPath) { IPythonBindings* pythonBindings = PythonBindingsInterface::Get(); QVector toBeAdded = m_gemModel->GatherGemsToBeAdded(); @@ -142,15 +143,25 @@ namespace O3DE::ProjectManager if (m_gemModel->DoGemsToBeAddedHaveRequirements()) { - GemRequirementDialog* confirmRequirementsDialog = new GemRequirementDialog(m_gemModel, toBeAdded, this); - confirmRequirementsDialog->exec(); - - if (confirmRequirementsDialog->GetButtonResult() != QDialogButtonBox::ApplyRole) + GemRequirementDialog* confirmRequirementsDialog = new GemRequirementDialog(m_gemModel, this); + if(confirmRequirementsDialog->exec() == QDialog::Rejected) { - return false; + return EnableDisableGemsResult::Cancel; } } + if (m_gemModel->HasDependentGemsToRemove()) + { + GemDependenciesDialog* dependenciesDialog = new GemDependenciesDialog(m_gemModel, this); + if(dependenciesDialog->exec() == QDialog::Rejected) + { + return EnableDisableGemsResult::Cancel; + } + + toBeAdded = m_gemModel->GatherGemsToBeAdded(); + toBeRemoved = m_gemModel->GatherGemsToBeRemoved(); + } + for (const QModelIndex& modelIndex : toBeAdded) { const QString gemPath = GemModel::GetPath(modelIndex); @@ -160,7 +171,7 @@ namespace O3DE::ProjectManager QMessageBox::critical(nullptr, "Operation failed", QString("Cannot add gem %1 to project.\n\nError:\n%2").arg(GemModel::GetDisplayName(modelIndex), result.GetError().c_str())); - return false; + return EnableDisableGemsResult::Failed; } } @@ -173,11 +184,11 @@ namespace O3DE::ProjectManager QMessageBox::critical(nullptr, "Operation failed", QString("Cannot remove gem %1 from project.\n\nError:\n%2").arg(GemModel::GetDisplayName(modelIndex), result.GetError().c_str())); - return false; + return EnableDisableGemsResult::Failed; } } - return true; + return EnableDisableGemsResult::Success; } ProjectManagerScreen GemCatalogScreen::GetScreenEnum() diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h index 5b48b2f90e..72e8d44f65 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemCatalogScreen.h @@ -29,7 +29,14 @@ namespace O3DE::ProjectManager ProjectManagerScreen GetScreenEnum() override; void ReinitForProject(const QString& projectPath); - bool EnableDisableGemsForProject(const QString& projectPath); + + enum class EnableDisableGemsResult + { + Failed = 0, + Success, + Cancel + }; + EnableDisableGemsResult EnableDisableGemsForProject(const QString& projectPath); GemModel* GetGemModel() const { return m_gemModel; } diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemDependenciesDialog.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemDependenciesDialog.cpp new file mode 100644 index 0000000000..98aebd8fab --- /dev/null +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemDependenciesDialog.cpp @@ -0,0 +1,80 @@ +/* + * 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 O3DE::ProjectManager +{ + GemDependenciesDialog::GemDependenciesDialog(GemModel* gemModel, QWidget *parent) + : QDialog(parent) + { + setWindowTitle(tr("Dependent Gems")); + setObjectName("GemDependenciesDialog"); + setAttribute(Qt::WA_DeleteOnClose); + setModal(true); + + QVBoxLayout* layout = new QVBoxLayout(); + // layout margin/alignment cannot be set with qss + layout->setMargin(15); + layout->setAlignment(Qt::AlignTop); + setLayout(layout); + + // message + QLabel* instructionLabel = new QLabel( + tr("The following gem dependencies are no longer needed and will be deactivated.

" + "To keep these Gems enabled, select the checkbox next to it.")); + layout->addWidget(instructionLabel); + + // checkboxes + FlowLayout* flowLayout = new FlowLayout(); + QVector gemsToRemove = gemModel->GatherGemsToBeRemoved(/*includeDependencies=*/true); + for (const QModelIndex& gem : gemsToRemove) + { + if (GemModel::WasPreviouslyAddedDependency(gem)) + { + QCheckBox* checkBox = new QCheckBox(GemModel::GetName(gem)); + connect(checkBox, &QCheckBox::stateChanged, this, + [=](int state) + { + GemModel::SetIsAdded(*gemModel, gem, /*isAdded=*/state == Qt::Checked); + }); + flowLayout->addWidget(checkBox); + } + } + layout->addLayout(flowLayout); + + layout->addSpacing(10); + layout->addStretch(1); + + // buttons + QDialogButtonBox* dialogButtons = new QDialogButtonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Ok); + connect(dialogButtons, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(dialogButtons, &QDialogButtonBox::rejected, this, + [=]() + { + // de-select any Gems the user selected because they're canceling + for (const QModelIndex& gem : gemsToRemove) + { + if (GemModel::WasPreviouslyAddedDependency(gem) && GemModel::IsAdded(gem)) + { + GemModel::SetIsAdded(*gemModel, gem, /*isAdded=*/false); + } + } + + reject(); + }); + layout->addWidget(dialogButtons); + } +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemDependenciesDialog.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemDependenciesDialog.h new file mode 100644 index 0000000000..df8ca6f8a2 --- /dev/null +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemDependenciesDialog.h @@ -0,0 +1,27 @@ +/* + * 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 + +#if !defined(Q_MOC_RUN) +#include +#endif + +namespace O3DE::ProjectManager +{ + QT_FORWARD_DECLARE_CLASS(GemModel) + + class GemDependenciesDialog + : public QDialog + { + Q_OBJECT // AUTOMOC + public: + explicit GemDependenciesDialog(GemModel* gemModel, QWidget *parent = nullptr); + ~GemDependenciesDialog() = default; + }; +} // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp index dc24c13009..2c7f17db32 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -16,6 +17,9 @@ #include #include #include +#include +#include +#include namespace O3DE::ProjectManager { @@ -104,22 +108,11 @@ namespace O3DE::ProjectManager painter->drawText(gemCreatorRect, Qt::TextSingleLine, gemCreator); // Gem summary - - // In case there are feature tags displayed at the bottom, decrease the size of the summary text field. const QStringList featureTags = GemModel::GetFeatures(modelIndex); - const int featureTagAreaHeight = 30; - const int summaryHeight = contentRect.height() - (!featureTags.empty() * featureTagAreaHeight); - - const int additionalSummarySpacing = s_itemMargins.right() * 3; - const QSize summarySize = QSize(contentRect.width() - s_summaryStartX - s_buttonWidth - additionalSummarySpacing, - summaryHeight); - const QRect summaryRect = QRect(/*topLeft=*/QPoint(contentRect.left() + s_summaryStartX, contentRect.top()), summarySize); - - painter->setFont(standardFont); - painter->setPen(m_textColor); - + const bool hasTags = !featureTags.isEmpty(); const QString summary = GemModel::GetSummary(modelIndex); - painter->drawText(summaryRect, Qt::AlignLeft | Qt::TextWordWrap, summary); + const QRect summaryRect = CalcSummaryRect(contentRect, hasTags); + DrawText(summary, painter, summaryRect, standardFont); DrawButton(painter, contentRect, modelIndex); DrawPlatformIcons(painter, contentRect, modelIndex); @@ -128,6 +121,17 @@ namespace O3DE::ProjectManager painter->restore(); } + QRect GemItemDelegate::CalcSummaryRect(const QRect& contentRect, bool hasTags) const + { + const int featureTagAreaHeight = 30; + const int summaryHeight = contentRect.height() - (hasTags * featureTagAreaHeight); + + const int additionalSummarySpacing = s_itemMargins.right() * 3; + const QSize summarySize = QSize(contentRect.width() - s_summaryStartX - s_buttonWidth - additionalSummarySpacing, + summaryHeight); + return QRect(QPoint(contentRect.left() + s_summaryStartX, contentRect.top()), summarySize); + } + QSize GemItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const { QStyleOptionViewItem options(option); @@ -154,7 +158,7 @@ namespace O3DE::ProjectManager return true; } } - else if (event->type() == QEvent::MouseButtonPress ) + else if (event->type() == QEvent::MouseButtonPress) { QMouseEvent* mouseEvent = static_cast(event); @@ -168,6 +172,21 @@ namespace O3DE::ProjectManager GemModel::SetIsAdded(*model, modelIndex, !isAdded); return true; } + + // we must manually handle html links because we aren't using QLabels + const QStringList featureTags = GemModel::GetFeatures(modelIndex); + const bool hasTags = !featureTags.isEmpty(); + const QRect summaryRect = CalcSummaryRect(contentRect, hasTags); + if (summaryRect.contains(mouseEvent->pos())) + { + const QString html = GemModel::GetSummary(modelIndex); + QString anchor = anchorAt(html, mouseEvent->pos(), summaryRect); + if (!anchor.isEmpty()) + { + QDesktopServices::openUrl(QUrl(anchor)); + return true; + } + } } return QStyledItemDelegate::editorEvent(event, model, option, modelIndex); @@ -321,6 +340,44 @@ namespace O3DE::ProjectManager } } + AZStd::unique_ptr GetTextDocument(const QString& text, int width) + { + // using unique_ptr as a workaround for QTextDocument having a private copy constructor + auto doc = AZStd::make_unique(); + QTextOption textOption(doc->defaultTextOption()); + textOption.setWrapMode(QTextOption::WordWrap); + doc->setDefaultTextOption(textOption); + doc->setHtml(text); + doc->setTextWidth(width); + return doc; + } + + void GemItemDelegate::DrawText(const QString& text, QPainter* painter, const QRect& rect, const QFont& standardFont) const + { + painter->save(); + + if (text.contains('<')) + { + painter->translate(rect.topLeft()); + + // use QTextDocument because drawText does not support rich text or html + QAbstractTextDocumentLayout::PaintContext paintContext; + paintContext.clip = QRect(0, 0, rect.width(), rect.height()); + paintContext.palette.setColor(QPalette::Text, painter->pen().color()); + + AZStd::unique_ptr textDocument = GetTextDocument(text, rect.width()); + textDocument->documentLayout()->draw(painter, paintContext); + } + else + { + painter->setFont(standardFont); + painter->setPen(m_textColor); + painter->drawText(rect, Qt::AlignLeft | Qt::TextWordWrap, text); + } + + painter->restore(); + } + void GemItemDelegate::DrawButton(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const { painter->save(); @@ -355,4 +412,19 @@ namespace O3DE::ProjectManager painter->restore(); } + + QString GemItemDelegate::anchorAt(const QString& html, const QPoint& position, const QRect& rect) + { + if (!html.isEmpty()) + { + AZStd::unique_ptr doc = GetTextDocument(html, rect.width()); + QAbstractTextDocumentLayout* layout = doc->documentLayout(); + if (layout) + { + return layout->anchorAt(position - rect.topLeft()); + } + } + + return QString(); + } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h index d842f63ae7..52b5a4f58e 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h @@ -30,6 +30,7 @@ namespace O3DE::ProjectManager void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const override; QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const override; + virtual QString anchorAt(const QString& html, const QPoint& position, const QRect& rect); // Colors const QColor m_textColor = QColor("#FFFFFF"); @@ -71,9 +72,11 @@ namespace O3DE::ProjectManager void CalcRects(const QStyleOptionViewItem& option, QRect& outFullRect, QRect& outItemRect, QRect& outContentRect) const; QRect GetTextRect(QFont& font, const QString& text, qreal fontSize) const; QRect CalcButtonRect(const QRect& contentRect) const; + QRect CalcSummaryRect(const QRect& contentRect, bool hasTags) const; void DrawPlatformIcons(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const; void DrawButton(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const; void DrawFeatureTags(QPainter* painter, const QRect& contentRect, const QStringList& featureTags, const QFont& standardFont, const QRect& summaryRect) const; + void DrawText(const QString& text, QPainter* painter, const QRect& rect, const QFont& standardFont) const; QAbstractItemModel* m_model = nullptr; diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemListView.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemListView.cpp index afdb9697c9..f5b54a364b 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemListView.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemListView.cpp @@ -8,27 +8,9 @@ #include #include -#include -#include namespace O3DE::ProjectManager { - class GemListViewProxyStyle : public QProxyStyle - { - public: - using QProxyStyle::QProxyStyle; - int styleHint(StyleHint hint, const QStyleOption* option = nullptr, const QWidget* widget = nullptr, QStyleHintReturn* returnData = nullptr) const override - { - if (hint == QStyle::SH_ToolTip_WakeUpDelay || hint == QStyle::SH_ToolTip_FallAsleepDelay) - { - // no delay - return 0; - } - - return QProxyStyle::styleHint(hint, option, widget, returnData); - } - }; - GemListView::GemListView(QAbstractItemModel* model, QItemSelectionModel* selectionModel, QWidget* parent) : QListView(parent) { @@ -38,8 +20,5 @@ namespace O3DE::ProjectManager setModel(model); setSelectionModel(selectionModel); setItemDelegate(new GemItemDelegate(model, this)); - - // use a custom proxy style so we get immediate tooltips for gem radio buttons - setStyle(new GemListViewProxyStyle(this->style())); } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp index 0941541793..c8911de360 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp @@ -391,6 +391,20 @@ namespace O3DE::ProjectManager return false; } + bool GemModel::HasDependentGemsToRemove() const + { + for (int row = 0; row < rowCount(); ++row) + { + const QModelIndex modelIndex = index(row, 0); + if (GemModel::NeedsToBeRemoved(modelIndex, /*includeDependencies=*/true) && + GemModel::WasPreviouslyAddedDependency(modelIndex)) + { + return true; + } + } + return false; + } + QVector GemModel::GatherGemDependencies(const QModelIndex& modelIndex) const { QVector result; diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h index 0591094c11..ef2d1a903d 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h @@ -66,6 +66,7 @@ namespace O3DE::ProjectManager static void UpdateDependencies(QAbstractItemModel& model, const QModelIndex& modelIndex); bool DoGemsToBeAddedHaveRequirements() const; + bool HasDependentGemsToRemove() const; QVector GatherGemDependencies(const QModelIndex& modelIndex) const; QVector GatherDependentGems(const QModelIndex& modelIndex, bool addedOnly = false) const; diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDelegate.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDelegate.cpp index 0ca5ca836f..f4a7148d46 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDelegate.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDelegate.cpp @@ -10,6 +10,8 @@ #include #include +#include +#include namespace O3DE::ProjectManager { @@ -38,7 +40,6 @@ namespace O3DE::ProjectManager standardFont.setPixelSize(static_cast(s_fontSize)); QFontMetrics standardFontMetrics(standardFont); - painter->save(); painter->setClipping(true); painter->setClipRect(fullRect); painter->setFont(options.font); @@ -65,25 +66,51 @@ namespace O3DE::ProjectManager painter->drawText(gemNameRect, Qt::TextSingleLine, gemName); // Gem requirement - const QSize requirementSize = QSize(contentRect.width() - s_summaryStartX - s_itemMargins.right(), contentRect.height()); - const QRect requirementRect = QRect(QPoint(contentRect.left() + s_summaryStartX, contentRect.top()), requirementSize); - - painter->setFont(standardFont); - painter->setPen(m_textColor); - + const QRect requirementRect = CalcRequirementRect(contentRect); const QString requirement = GemModel::GetRequirement(modelIndex); - painter->drawText(requirementRect, Qt::AlignLeft | Qt::TextWordWrap, requirement); + DrawText(requirement, painter, requirementRect, standardFont); painter->restore(); } + QRect GemRequirementDelegate::CalcRequirementRect(const QRect& contentRect) const + { + const QSize requirementSize = QSize(contentRect.width() - s_summaryStartX - s_itemMargins.right(), contentRect.height()); + return QRect(QPoint(contentRect.left() + s_summaryStartX, contentRect.top()), requirementSize); + } + bool GemRequirementDelegate::editorEvent( [[maybe_unused]] QEvent* event, [[maybe_unused]] QAbstractItemModel* model, [[maybe_unused]] const QStyleOptionViewItem& option, [[maybe_unused]] const QModelIndex& modelIndex) { - // Do nothing here - return false; + if (!modelIndex.isValid()) + { + return false; + } + + if (event->type() == QEvent::MouseButtonPress) + { + QMouseEvent* mouseEvent = static_cast(event); + + QRect fullRect, itemRect, contentRect; + CalcRects(option, fullRect, itemRect, contentRect); + + const QRect requirementsRect = CalcRequirementRect(contentRect); + if (requirementsRect.contains(mouseEvent->pos())) + { + const QString html = GemModel::GetRequirement(modelIndex); + QString anchor = anchorAt(html, mouseEvent->pos(), requirementsRect); + if (!anchor.isEmpty()) + { + QDesktopServices::openUrl(QUrl(anchor)); + return true; + } + } + } + + return QStyledItemDelegate::editorEvent(event, model, option, modelIndex); } + } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDelegate.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDelegate.h index a23b999ca0..e9001df7fa 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDelegate.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDelegate.h @@ -29,5 +29,8 @@ namespace O3DE::ProjectManager const QColor m_backgroundColor = QColor("#444444"); // Outside of the actual gem item const QColor m_itemBackgroundColor = QColor("#393939"); // Background color of the gem item + + private: + QRect CalcRequirementRect(const QRect& contentRect) const; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDialog.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDialog.cpp index 4740d29344..23bb776c29 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDialog.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDialog.cpp @@ -19,11 +19,12 @@ namespace O3DE::ProjectManager { - GemRequirementDialog::GemRequirementDialog(GemModel* model, const QVector& gemsToAdd, QWidget* parent) + GemRequirementDialog::GemRequirementDialog(GemModel* model, QWidget* parent) : QDialog(parent) { setWindowTitle(tr("Manual setup is required")); setModal(true); + setAttribute(Qt::WA_DeleteOnClose); QVBoxLayout* vLayout = new QVBoxLayout(); vLayout->setMargin(0); @@ -51,7 +52,7 @@ namespace O3DE::ProjectManager vLayout->addSpacing(20); - GemRequirementFilterProxyModel* proxModel = new GemRequirementFilterProxyModel(model, gemsToAdd, this); + GemRequirementFilterProxyModel* proxModel = new GemRequirementFilterProxyModel(model, this); GemRequirementListView* m_gemListView = new GemRequirementListView(proxModel, proxModel->GetSelectionModel(), this); vLayout->addWidget(m_gemListView); @@ -62,27 +63,9 @@ namespace O3DE::ProjectManager QPushButton* cancelButton = dialogButtons->addButton(tr("Cancel"), QDialogButtonBox::RejectRole); cancelButton->setProperty("secondary", true); - QPushButton* continueButton = dialogButtons->addButton(tr("Continue"), QDialogButtonBox::ApplyRole); + QPushButton* continueButton = dialogButtons->addButton(tr("Continue"), QDialogButtonBox::AcceptRole); - connect(cancelButton, &QPushButton::clicked, this, &GemRequirementDialog::CancelButtonPressed); - connect(continueButton, &QPushButton::clicked, this, &GemRequirementDialog::ContinueButtonPressed); + connect(cancelButton, &QPushButton::clicked, this, &QDialog::reject); + connect(continueButton, &QPushButton::clicked, this, &QDialog::accept); } - - QDialogButtonBox::ButtonRole GemRequirementDialog::GetButtonResult() - { - return m_buttonResult; - } - - void GemRequirementDialog::CancelButtonPressed() - { - m_buttonResult = QDialogButtonBox::RejectRole; - close(); - } - - void GemRequirementDialog::ContinueButtonPressed() - { - m_buttonResult = QDialogButtonBox::ApplyRole; - close(); - } - } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDialog.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDialog.h index 22f6977332..af8b1e2cc9 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDialog.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementDialog.h @@ -10,8 +10,6 @@ #if !defined(Q_MOC_RUN) #include - -#include #endif namespace O3DE::ProjectManager @@ -23,15 +21,7 @@ namespace O3DE::ProjectManager { Q_OBJECT // AUTOMOC public: - explicit GemRequirementDialog(GemModel* model, const QVector& gemsToAdd, QWidget *parent = nullptr); + explicit GemRequirementDialog(GemModel* model, QWidget *parent = nullptr); ~GemRequirementDialog() = default; - - QDialogButtonBox::ButtonRole GetButtonResult(); - - private: - void CancelButtonPressed(); - void ContinueButtonPressed(); - - QDialogButtonBox::ButtonRole m_buttonResult = QDialogButtonBox::RejectRole; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementFilterProxyModel.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementFilterProxyModel.cpp index 50639b7936..e89de82c6c 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementFilterProxyModel.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementFilterProxyModel.cpp @@ -13,10 +13,8 @@ namespace O3DE::ProjectManager { - GemRequirementFilterProxyModel::GemRequirementFilterProxyModel(GemModel* sourceModel, const QVector& addedGems, QObject* parent) + GemRequirementFilterProxyModel::GemRequirementFilterProxyModel(GemModel* sourceModel, QObject* parent) : QSortFilterProxyModel(parent) - , m_sourceModel(sourceModel) - , m_addedGems(addedGems) { setSourceModel(sourceModel); m_selectionProxyModel = new AzQtComponents::SelectionProxyModel(sourceModel->GetSelectionModel(), this, parent); @@ -26,22 +24,7 @@ namespace O3DE::ProjectManager { // Do not use sourceParent->child because an invalid parent does not produce valid children (which our index function does) QModelIndex sourceIndex = sourceModel()->index(sourceRow, 0, sourceParent); - if (!sourceIndex.isValid()) - { - return false; - } - - if (!m_addedGems.contains(sourceIndex)) - { - return false; - } - - if (!m_sourceModel->HasRequirement(sourceIndex)) - { - return false; - } - - return true; + return GemModel::IsAdded(sourceIndex) && GemModel::HasRequirement(sourceIndex); } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementFilterProxyModel.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementFilterProxyModel.h index a40eed9fb4..7df75f7d94 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementFilterProxyModel.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementFilterProxyModel.h @@ -25,16 +25,13 @@ namespace O3DE::ProjectManager Q_OBJECT // AUTOMOC public: - GemRequirementFilterProxyModel(GemModel* sourceModel, const QVector& addedGems, QObject* parent = nullptr); + GemRequirementFilterProxyModel(GemModel* sourceModel, QObject* parent = nullptr); AzQtComponents::SelectionProxyModel* GetSelectionModel() const { return m_selectionProxyModel; } bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override; private: - GemModel* m_sourceModel = nullptr; AzQtComponents::SelectionProxyModel* m_selectionProxyModel = nullptr; - - QVector m_addedGems; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementListView.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementListView.cpp index daed5764ff..fd7d22cbfc 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementListView.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemRequirementListView.cpp @@ -8,7 +8,6 @@ #include #include -#include namespace O3DE::ProjectManager { diff --git a/Code/Tools/ProjectManager/Source/TagWidget.cpp b/Code/Tools/ProjectManager/Source/TagWidget.cpp index 8f433f420f..ace9d72d8f 100644 --- a/Code/Tools/ProjectManager/Source/TagWidget.cpp +++ b/Code/Tools/ProjectManager/Source/TagWidget.cpp @@ -8,87 +8,44 @@ #include #include +#include namespace O3DE::ProjectManager { TagWidget::TagWidget(const QString& text, QWidget* parent) : QLabel(text, parent) { - setFixedHeight(24); - setMargin(5); - setStyleSheet("font-size: 12px; background-color: #333333; border-radius: 3px;"); + setObjectName("TagWidget"); } TagContainerWidget::TagContainerWidget(QWidget* parent) : QWidget(parent) { - m_layout = new QVBoxLayout(); - m_layout->setAlignment(Qt::AlignTop); - m_layout->setMargin(0); - setLayout(m_layout); + setObjectName("TagWidgetContainer"); + setLayout(new FlowLayout(this)); + + // layout margins cannot be set via qss + constexpr int verticalMargin = 10; + constexpr int horizontalMargin = 0; + layout()->setContentsMargins(horizontalMargin, verticalMargin, horizontalMargin, verticalMargin); + + setAttribute(Qt::WA_StyledBackground, true); } void TagContainerWidget::Update(const QStringList& tags) { - QWidget* parentWidget = qobject_cast(parent()); - int width = 200; - if (parentWidget) + FlowLayout* flowLayout = static_cast(layout()); + + // remove old tags + QLayoutItem* layoutItem = nullptr; + while ((layoutItem = layout()->takeAt(0)) != nullptr) { - width = parentWidget->width(); + layoutItem->widget()->deleteLater(); } - if (m_widget) + foreach (const QString& tag, tags) { - // Hide the old widget and request deletion. - m_widget->hide(); - m_widget->deleteLater(); - } - - QVBoxLayout* vLayout = new QVBoxLayout(); - m_widget = new QWidget(this); - m_widget->setLayout(vLayout); - m_layout->addWidget(m_widget); - - vLayout->setAlignment(Qt::AlignTop); - vLayout->setMargin(0); - - QHBoxLayout* hLayout = nullptr; - int usedSpaceInRow = 0; - const int numTags = tags.count(); - - for (int i = 0; i < numTags; ++i) - { - // Create the new tag widget. - TagWidget* tagWidget = new TagWidget(tags[i]); - const int tagWidgetWidth = tagWidget->minimumSizeHint().width(); - - // Calculate the width we're currently using in the current row. Does the new tag still fit in the current row? - const bool isRowFull = width - usedSpaceInRow - tagWidgetWidth < 0; - if (isRowFull || i == 0) - { - // Add a spacer widget after the last tag widget in a row to push the tag widgets to the left. - if (i > 0) - { - QWidget* spacerWidget = new QWidget(); - spacerWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); - hLayout->addWidget(spacerWidget); - } - - // Add a new row for the current tag widget. - hLayout = new QHBoxLayout(); - hLayout->setAlignment(Qt::AlignLeft); - hLayout->setMargin(0); - vLayout->addLayout(hLayout); - - // Reset the used space in the row. - usedSpaceInRow = 0; - } - - // Calculate the width of the tag widgets including the spacing between them of the current row. - usedSpaceInRow += tagWidgetWidth + hLayout->spacing(); - - // Add the tag widget to the current row. - hLayout->addWidget(tagWidget); + flowLayout->addWidget(new TagWidget(tag)); } } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/TagWidget.h b/Code/Tools/ProjectManager/Source/TagWidget.h index 16eca28fc1..0dad7468eb 100644 --- a/Code/Tools/ProjectManager/Source/TagWidget.h +++ b/Code/Tools/ProjectManager/Source/TagWidget.h @@ -14,8 +14,6 @@ #include #endif -QT_FORWARD_DECLARE_CLASS(QVBoxLayout) - namespace O3DE::ProjectManager { // Single tag @@ -40,9 +38,5 @@ namespace O3DE::ProjectManager ~TagContainerWidget() = default; void Update(const QStringList& tags); - - private: - QVBoxLayout* m_layout = nullptr; - QWidget* m_widget = nullptr; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp index 08ad7f24d9..e952ada57a 100644 --- a/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp +++ b/Code/Tools/ProjectManager/Source/UpdateProjectCtrl.cpp @@ -137,9 +137,13 @@ namespace O3DE::ProjectManager else if (m_stack->currentIndex() == ScreenOrder::Gems && m_gemCatalogScreen) { // Enable or disable the gems that got adjusted in the gem catalog and apply them to the given project. - if (!m_gemCatalogScreen->EnableDisableGemsForProject(m_projectInfo.m_path)) + const GemCatalogScreen::EnableDisableGemsResult result = m_gemCatalogScreen->EnableDisableGemsForProject(m_projectInfo.m_path); + if (result == GemCatalogScreen::EnableDisableGemsResult::Failed) { QMessageBox::critical(this, tr("Failed to configure gems"), tr("Failed to configure gems for project.")); + } + if (result != GemCatalogScreen::EnableDisableGemsResult::Success) + { return; } diff --git a/Code/Tools/ProjectManager/project_manager_files.cmake b/Code/Tools/ProjectManager/project_manager_files.cmake index 544fa2537b..fd8389ca4f 100644 --- a/Code/Tools/ProjectManager/project_manager_files.cmake +++ b/Code/Tools/ProjectManager/project_manager_files.cmake @@ -92,6 +92,8 @@ set(FILES Source/GemCatalog/GemListHeaderWidget.cpp Source/GemCatalog/GemModel.h Source/GemCatalog/GemModel.cpp + Source/GemCatalog/GemDependenciesDialog.h + Source/GemCatalog/GemDependenciesDialog.cpp Source/GemCatalog/GemRequirementDialog.h Source/GemCatalog/GemRequirementDialog.cpp Source/GemCatalog/GemRequirementDelegate.h From 56de6064d2fa7755b9c34335d9a14f1afd934c08 Mon Sep 17 00:00:00 2001 From: nggieber Date: Mon, 11 Oct 2021 12:07:04 -0700 Subject: [PATCH 105/169] Hopefully final pass on PR comments Signed-off-by: nggieber --- scripts/o3de/o3de/manifest.py | 43 ++++++++++++----------------------- 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/scripts/o3de/o3de/manifest.py b/scripts/o3de/o3de/manifest.py index c5f6315474..b665727a4e 100644 --- a/scripts/o3de/o3de/manifest.py +++ b/scripts/o3de/o3de/manifest.py @@ -422,7 +422,7 @@ def get_templates_for_generic_creation(): # temporary until we have a better wa return list(filter(filter_project_and_gem_templates_out, get_all_templates())) def get_json_file_path(object_typename: str, - object_path: str or pathlib.Path = None) -> pathlib.Path: + object_path: str or pathlib.Path) -> pathlib.Path: if not object_typename or not object_path: logger.error('Must specify an object typename and object path.') return None @@ -432,26 +432,18 @@ def get_json_file_path(object_typename: str, def get_json_data_file(object_json: pathlib.Path, - object_typename: str = None, - object_validator = callable) -> dict or None: + object_typename: str, + object_validator: callable) -> dict or None: if not object_typename: logger.error('Missing object typename.') return None - if not object_json: - logger.error(f'No object json provided for {object_typename}') + if not object_json or not object_json.is_file(): + logger.error(f'Invalid {object_typename} json {object_json} supplied or file missing.') return None - if not object_json.is_file(): - logger.error(f'{object_typename} json {object_json} is not present.') - return None - - if not object_validator: - logger.error('Missing object validator.') - return None - - if not object_validator(object_json): - logger.error(f'{object_typename} json {object_json} is not valid.') + if not object_validator or not object_validator(object_json): + logger.error(f'{object_typename} json {object_json} is not valid or could not be validated.') return None with object_json.open('r') as f: @@ -464,16 +456,11 @@ def get_json_data_file(object_json: pathlib.Path, return None -def get_json_data(object_typename: str = None, - object_path: str or pathlib.Path = None, - object_validator = callable, - object_name: str = None) -> dict or None: +def get_json_data(object_typename: str, + object_path: str or pathlib.Path, + object_validator: callable) -> dict or None: object_json = get_json_file_path(object_typename, object_path) - if not object_json and object_name: - logger.error(f'{object_name} has not been registered.') - return None - return get_json_data_file(object_json, object_typename, object_validator) @@ -486,7 +473,7 @@ def get_engine_json_data(engine_name: str = None, if engine_name and not engine_path: engine_path = get_registered(engine_name=engine_name) - return get_json_data('engine', engine_path, validation.valid_o3de_engine_json, engine_name) + return get_json_data('engine', engine_path, validation.valid_o3de_engine_json) def get_project_json_data(project_name: str = None, @@ -498,7 +485,7 @@ def get_project_json_data(project_name: str = None, if project_name and not project_path: project_path = get_registered(project_name=project_name) - return get_json_data('project', project_path, validation.valid_o3de_project_json, project_name) + return get_json_data('project', project_path, validation.valid_o3de_project_json) def get_gem_json_data(gem_name: str = None, gem_path: str or pathlib.Path = None, @@ -510,7 +497,7 @@ def get_gem_json_data(gem_name: str = None, gem_path: str or pathlib.Path = None if gem_name and not gem_path: gem_path = get_registered(gem_name=gem_name, project_path=project_path) - return get_json_data('gem', gem_path, validation.valid_o3de_gem_json, gem_name) + return get_json_data('gem', gem_path, validation.valid_o3de_gem_json) def get_template_json_data(template_name: str = None, template_path: str or pathlib.Path = None, @@ -522,7 +509,7 @@ def get_template_json_data(template_name: str = None, template_path: str or path if template_name and not template_path: template_path = get_registered(template_name=template_name, project_path=project_path) - return get_json_data('template', template_path, validation.valid_o3de_template_json, template_name) + return get_json_data('template', template_path, validation.valid_o3de_template_json) def get_restricted_json_data(restricted_name: str = None, restricted_path: str or pathlib.Path = None, @@ -534,7 +521,7 @@ def get_restricted_json_data(restricted_name: str = None, restricted_path: str o if restricted_name and not restricted_path: restricted_path = get_registered(restricted_name=restricted_name, project_path=project_path) - return get_json_data('restricted', restricted_path, validation.valid_o3de_restricted_json, restricted_name) + return get_json_data('restricted', restricted_path, validation.valid_o3de_restricted_json) def get_repo_json_data(repo_uri: str) -> dict or None: if not repo_uri: From 843f993fc950c0324e303bbd1d03d2bf8c3b2624 Mon Sep 17 00:00:00 2001 From: Vincent Liu <5900509+onecent1101@users.noreply.github.com> Date: Mon, 11 Oct 2021 13:17:07 -0700 Subject: [PATCH 106/169] Improve ticket tracker workflow for testing (#4610) * Improve ticket tracker workflow for testing Signed-off-by: onecent1101 --- .../AWSGameLiftClientLocalTicketTracker.cpp | 16 +++++++++++++--- .../Source/AWSGameLiftClientLocalTicketTracker.h | 2 ++ .../AWSGameLiftClientLocalTicketTrackerTest.cpp | 2 +- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientLocalTicketTracker.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientLocalTicketTracker.cpp index 9ae168aea9..b619a10d4a 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientLocalTicketTracker.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientLocalTicketTracker.cpp @@ -47,6 +47,15 @@ namespace AWSGameLift AZ_TracePrintf(AWSGameLiftClientLocalTicketTrackerName, "Matchmaking ticket tracker is running."); return; } + + // Make sure thread and wait event are both in clean state before starting new one + m_waitEvent.release(); + if (m_trackerThread.joinable()) + { + m_trackerThread.join(); + } + m_waitEvent.acquire(); + m_status = TicketTrackerStatus::Running; m_trackerThread = AZStd::thread(AZStd::bind( &AWSGameLiftClientLocalTicketTracker::ProcessPolling, this, ticketId, playerId)); @@ -56,6 +65,7 @@ namespace AWSGameLift { AZStd::lock_guard lock(m_trackerMutex); m_status = TicketTrackerStatus::Idle; + m_waitEvent.release(); if (m_trackerThread.joinable()) { m_trackerThread.join(); @@ -81,19 +91,19 @@ namespace AWSGameLift auto ticket = describeMatchmakingOutcome.GetResult().GetTicketList().front(); if (ticket.GetStatus() == Aws::GameLift::Model::MatchmakingConfigurationStatus::COMPLETED) { - m_status = TicketTrackerStatus::Idle; AZ_TracePrintf(AWSGameLiftClientLocalTicketTrackerName, "Matchmaking ticket %s is complete.", ticket.GetTicketId().c_str()); RequestPlayerJoinMatch(ticket, playerId); + m_status = TicketTrackerStatus::Idle; return; } else if (ticket.GetStatus() == Aws::GameLift::Model::MatchmakingConfigurationStatus::TIMED_OUT || ticket.GetStatus() == Aws::GameLift::Model::MatchmakingConfigurationStatus::FAILED || ticket.GetStatus() == Aws::GameLift::Model::MatchmakingConfigurationStatus::CANCELLED) { - m_status = TicketTrackerStatus::Idle; AZ_Error(AWSGameLiftClientLocalTicketTrackerName, false, "Matchmaking ticket %s is not complete, %s", ticket.GetTicketId().c_str(), ticket.GetStatusReason().c_str()); + m_status = TicketTrackerStatus::Idle; return; } else if (ticket.GetStatus() == Aws::GameLift::Model::MatchmakingConfigurationStatus::REQUIRES_ACCEPTANCE) @@ -122,7 +132,7 @@ namespace AWSGameLift { AZ_Error(AWSGameLiftClientLocalTicketTrackerName, false, AWSGameLiftClientMissingErrorMessage); } - AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(m_pollingPeriodInMS)); + m_waitEvent.try_acquire_for(AZStd::chrono::milliseconds(m_pollingPeriodInMS)); } } diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientLocalTicketTracker.h b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientLocalTicketTracker.h index 7b317a0485..23083e9fd9 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientLocalTicketTracker.h +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientLocalTicketTracker.h @@ -8,6 +8,7 @@ #pragma once +#include #include #include @@ -58,5 +59,6 @@ namespace AWSGameLift AZStd::mutex m_trackerMutex; AZStd::thread m_trackerThread; + AZStd::binary_semaphore m_waitEvent; }; } // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientLocalTicketTrackerTest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientLocalTicketTrackerTest.cpp index 6e688b28e3..6506d70704 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientLocalTicketTrackerTest.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientLocalTicketTrackerTest.cpp @@ -16,7 +16,7 @@ using namespace AWSGameLift; -static constexpr const uint64_t TEST_RACKER_POLLING_PERIOD_MS = 100; +static constexpr const uint64_t TEST_RACKER_POLLING_PERIOD_MS = 1000; static constexpr const uint64_t TEST_WAIT_BUFFER_TIME_MS = 10; static constexpr const uint64_t TEST_WAIT_MAXIMUM_TIME_MS = 10000; From d3c2e288e92db7de43ab66676977f917648b42b3 Mon Sep 17 00:00:00 2001 From: jromnoa <80134229+jromnoa@users.noreply.github.com> Date: Mon, 11 Oct 2021 13:30:27 -0700 Subject: [PATCH 107/169] sandbox the Reflection Probe portion of the test, remove xfail marker - Reflection Probe will be re-added in the parallel test approach (#4584) Signed-off-by: jromnoa --- .../Gem/PythonTests/Atom/TestSuite_Main.py | 18 ------ .../Gem/PythonTests/Atom/TestSuite_Sandbox.py | 55 ++++++++++++++++++- 2 files changed, 53 insertions(+), 20 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py index b148ffdcdb..e4a77ca4ec 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.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 - -Main suite tests for the Atom renderer. """ import logging import os @@ -25,7 +23,6 @@ TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "tests") class TestAtomEditorComponentsMain(object): """Holds tests for Atom components.""" - @pytest.mark.xfail(reason="This test is being marked xfail as it failed during an unrelated development run. See LYN-7530 for more details.") def test_AtomEditorComponents_AddedToEntity(self, request, editor, level, workspace, project, launcher_platform): """ Please review the hydra script run by this test for more specific test info. @@ -162,21 +159,6 @@ class TestAtomEditorComponentsMain(object): "Display Mapper_test: Entity deleted: True", "Display Mapper_test: UNDO entity deletion works: True", "Display Mapper_test: REDO entity deletion works: True", - # Reflection Probe Component - "Reflection Probe Entity successfully created", - "Reflection Probe_test: Component added to the entity: True", - "Reflection Probe_test: Component removed after UNDO: True", - "Reflection Probe_test: Component added after REDO: True", - "Reflection Probe_test: Entered game mode: True", - "Reflection Probe_test: Exit game mode: True", - "Reflection Probe_test: Entity disabled initially: True", - "Reflection Probe_test: Entity enabled after adding required components: True", - "Reflection Probe_test: Cubemap is generated: True", - "Reflection Probe_test: Entity is hidden: True", - "Reflection Probe_test: Entity is shown: True", - "Reflection Probe_test: Entity deleted: True", - "Reflection Probe_test: UNDO entity deletion works: True", - "Reflection Probe_test: REDO entity deletion works: True", ] unexpected_lines = [ diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py index 05401c0059..79caf26784 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py @@ -3,12 +3,17 @@ 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 - -Sandbox suite tests for the Atom renderer. """ +import logging +import os import pytest +import editor_python_test_tools.hydra_test_utils as hydra + +logger = logging.getLogger(__name__) +TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "tests") + @pytest.mark.parametrize("project", ["AutomatedTesting"]) @pytest.mark.parametrize("launcher_platform", ['windows_editor']) @@ -18,3 +23,49 @@ class TestAtomEditorComponentsSandbox(object): # It requires at least one test def test_Dummy(self, request, editor, level, workspace, project, launcher_platform): pass + + @pytest.mark.parametrize("project", ["AutomatedTesting"]) + @pytest.mark.parametrize("launcher_platform", ['windows_editor']) + @pytest.mark.parametrize("level", ["auto_test"]) + class TestAtomEditorComponentsMain(object): + """Holds tests for Atom components.""" + + def test_AtomEditorComponents_ReflectionProbeAddedToEntity( + self, request, editor, level, workspace, project, launcher_platform): + """ + Please review the hydra script run by this test for more specific test info. + Tests the following Atom components and verifies all "expected_lines" appear in Editor.log: + 1. Reflection Probe + """ + cfg_args = [level] + + expected_lines = [ + # Reflection Probe Component + "Reflection Probe Entity successfully created", + "Reflection Probe_test: Component added to the entity: True", + "Reflection Probe_test: Component removed after UNDO: True", + "Reflection Probe_test: Component added after REDO: True", + "Reflection Probe_test: Entered game mode: True", + "Reflection Probe_test: Exit game mode: True", + "Reflection Probe_test: Entity disabled initially: True", + "Reflection Probe_test: Entity enabled after adding required components: True", + "Reflection Probe_test: Cubemap is generated: True", + "Reflection Probe_test: Entity is hidden: True", + "Reflection Probe_test: Entity is shown: True", + "Reflection Probe_test: Entity deleted: True", + "Reflection Probe_test: UNDO entity deletion works: True", + "Reflection Probe_test: REDO entity deletion works: True", + ] + + hydra.launch_and_validate_results( + request, + TEST_DIRECTORY, + editor, + "hydra_AtomEditorComponents_AddedToEntity.py", + timeout=120, + expected_lines=expected_lines, + unexpected_lines=[], + halt_on_unexpected=True, + null_renderer=True, + cfg_args=cfg_args, + ) From a95c609bd8e86c84226672f6ce4296cd443d60c4 Mon Sep 17 00:00:00 2001 From: Scott Romero <24445312+AMZN-ScottR@users.noreply.github.com> Date: Mon, 11 Oct 2021 14:00:42 -0700 Subject: [PATCH 108/169] [development] Migrate Atom CPU timing stats tracking to use global stats profiler (#4549) This change is a preparation for moving the CPU profiler/visualization system from Atom into its own Gem by removing the dependency on local time tracking object AZ::RHI::CpuTimingStatistics Full changes include: - Removed all usage of AZ::RHI::CpuTimingStatistics -- Replaced with pushing to AZ::Statistics::StatisticalProfilerProxy global instance - Promoted VariableTimer from AZ::RHI to AZ::Debug - Removed now unused CpuTimingStatistics.h Signed-off-by: AMZN-ScottR 24445312+AMZN-ScottR@users.noreply.github.com --- Code/Framework/AzCore/AzCore/Debug/Timer.h | 18 +++++ .../ProfilingCaptureSystemComponent.cpp | 14 +--- .../RHI/Code/Include/Atom/RHI.Reflect/Base.h | 1 + .../Atom/RHI.Reflect/CpuTimingStatistics.h | 77 ------------------- Gems/Atom/RHI/Code/Include/Atom/RHI/Device.h | 13 ++-- .../Code/Include/Atom/RHI/FrameScheduler.h | 6 +- .../RHI/Code/Include/Atom/RHI/RHISystem.h | 2 +- .../Include/Atom/RHI/RHISystemInterface.h | 3 +- .../Atom/RHI/Code/Source/RHI/CommandQueue.cpp | 17 ++++ .../RHI/Code/Source/RHI/CpuProfilerImpl.cpp | 6 ++ Gems/Atom/RHI/Code/Source/RHI/Device.cpp | 4 +- .../RHI/Code/Source/RHI/FrameScheduler.cpp | 34 ++++++-- Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp | 4 +- Gems/Atom/RHI/Code/Tests/Device.h | 2 +- .../RHI/Code/atom_rhi_reflect_files.cmake | 1 - .../RHI/DX12/Code/Source/RHI/CommandQueue.cpp | 8 +- .../Code/Source/RHI/CommandQueueContext.cpp | 22 +++--- .../Code/Source/RHI/CommandQueueContext.h | 7 +- Gems/Atom/RHI/DX12/Code/Source/RHI/Device.cpp | 4 +- Gems/Atom/RHI/DX12/Code/Source/RHI/Device.h | 2 +- .../Metal/Code/Source/RHI/CommandQueue.cpp | 9 ++- .../Code/Source/RHI/CommandQueueContext.cpp | 24 +++--- .../Code/Source/RHI/CommandQueueContext.h | 2 +- .../Atom/RHI/Metal/Code/Source/RHI/Device.cpp | 4 +- Gems/Atom/RHI/Metal/Code/Source/RHI/Device.h | 2 +- Gems/Atom/RHI/Null/Code/Source/RHI/Device.h | 2 +- .../Vulkan/Code/Source/RHI/CommandQueue.cpp | 9 ++- .../Code/Source/RHI/CommandQueueContext.cpp | 22 +++--- .../Code/Source/RHI/CommandQueueContext.h | 7 +- .../RHI/Vulkan/Code/Source/RHI/Device.cpp | 4 +- Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.h | 2 +- Gems/Atom/RPI/Code/Tests/Common/RHI/Stubs.h | 2 +- .../Viewport/PerformanceMonitorComponent.cpp | 7 +- .../Include/Atom/Utils/ImGuiCpuProfiler.h | 22 +++--- .../Include/Atom/Utils/ImGuiCpuProfiler.inl | 65 +++++++++++----- .../Source/AtomImGuiToolsSystemComponent.cpp | 6 +- 36 files changed, 213 insertions(+), 221 deletions(-) delete mode 100644 Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/CpuTimingStatistics.h diff --git a/Code/Framework/AzCore/AzCore/Debug/Timer.h b/Code/Framework/AzCore/AzCore/Debug/Timer.h index 47bd3e1b95..6585fe7468 100644 --- a/Code/Framework/AzCore/AzCore/Debug/Timer.h +++ b/Code/Framework/AzCore/AzCore/Debug/Timer.h @@ -46,5 +46,23 @@ namespace AZ private: AZStd::sys_time_t m_timeStamp; }; + + //! Utility type that updates the given variable with the lifetime of the object in cycles. + //! Useful for quick scope based timing. + struct ScopedTimer + { + explicit ScopedTimer(AZStd::sys_time_t& variable) + : m_variable(variable) + { + m_timer.Stamp(); + } + ~ScopedTimer() + { + m_variable = m_timer.GetDeltaTimeInTicks(); + } + + AZStd::sys_time_t& m_variable; + Timer m_timer; + }; } } diff --git a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp index a476b5b839..4accbf0bba 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ProfilingCaptureSystemComponent.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -457,17 +456,8 @@ namespace AZ JsonSerializerSettings serializationSettings; serializationSettings.m_keepDefaults = true; - double frameTime = 0.0; - const AZ::RHI::CpuTimingStatistics* stats = AZ::RHI::RHISystemInterface::Get()->GetCpuTimingStatistics(); - if (stats) - { - frameTime = stats->GetFrameToFrameTimeMilliseconds(); - } - else - { - AZStd::string warning = AZStd::string::format("Failed to get Cpu frame time"); - AZ_Warning("ProfilingCaptureSystemComponent", false, warning.c_str()); - } + double frameTime = AZ::RHI::RHISystemInterface::Get()->GetCpuFrameTime(); + AZ_Warning("ProfilingCaptureSystemComponent", frameTime > 0, "Failed to get Cpu frame time"); CpuFrameTimeSerializer serializer(frameTime); const auto saveResult = JsonSerializationUtils::SaveObjectToFile(&serializer, diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/Base.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/Base.h index 9e1ec4585e..977c2c9ce8 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/Base.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/Base.h @@ -16,6 +16,7 @@ #include AZ_DECLARE_BUDGET(RHI); +inline static constexpr AZ::Crc32 rhiMetricsId = AZ_CRC_CE("RHI"); namespace UnitTest { diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/CpuTimingStatistics.h b/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/CpuTimingStatistics.h deleted file mode 100644 index 2ab23def08..0000000000 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI.Reflect/CpuTimingStatistics.h +++ /dev/null @@ -1,77 +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 -#include - -namespace AZ -{ - namespace RHI - { - //! Container and helper type for storing per frame CPU timing data. - //! Users can queue up generic timings in Scopes or add to specific timing data. - struct CpuTimingStatistics - { - struct QueueStatistics - { - //! The display name of the queue the statistics are for. - Name m_queueName; - - //! Time spent executing queued work. - AZStd::sys_time_t m_executeDuration{}; - }; - - //! Statistics for each command queue. - AZStd::vector m_queueStatistics; - - //! The amount of time spent between two calls to EndFrame. - AZStd::sys_time_t m_frameToFrameTime{}; - - //! The amount of time spent presenting (vsync can affect this). - AZStd::sys_time_t m_presentDuration{}; - - void Reset() - { - m_queueStatistics.clear(); - } - - double GetFrameToFrameTimeMilliseconds() const - { - return (m_frameToFrameTime * 1000) / aznumeric_cast(AZStd::GetTimeTicksPerSecond()); - } - }; - - //! Utility type that updates the given variable with the lifetime of the object in cycles. - //! Useful for quick scope based timing. - struct VariableTimer - { - VariableTimer() = delete; - VariableTimer(AZStd::sys_time_t& variable) - : m_variable(variable) - { - m_timer.Stamp(); - } - ~VariableTimer() - { - m_variable = m_timer.GetDeltaTimeInTicks(); - } - - AZStd::sys_time_t& m_variable; - AZ::Debug::Timer m_timer; - }; - } -} - -//! Utility for timing a section of code and writing the timing (in cycles) to the given variable. -#define AZ_PROFILE_RHI_VARIABLE(variable) \ - AZ::RHI::VariableTimer AZ_JOIN(variableTimer, __LINE__)(variable); diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/Device.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/Device.h index fb4082bb25..358fdcb4c4 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/Device.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/Device.h @@ -27,9 +27,6 @@ namespace AZ { namespace RHI { - struct CpuTimingStatistics; - - //! The Device is a context for managing GPU state and memory on a physical device. The user creates //! a device instance from a PhysicalDevice. Each device has its own capabilities and limits, and can //! be configured to buffer a specific number of frames. @@ -91,10 +88,10 @@ namespace AZ //! scope. Otherwise, an error code is returned. ResultCode CompileMemoryStatistics(MemoryStatistics& memoryStatistics, MemoryStatisticsReportFlags reportFlags); - //! Fills the provided data structure with cpu timing statistics specific to this device. This - //! method can only be called on an initialized device, and outside of the BeginFrame / EndFrame - //! scope. Otherwise, an error code is returned. - ResultCode UpdateCpuTimingStatistics(CpuTimingStatistics& cpuTimingStatistics) const; + //! Pushes internally recorded timing statistics upwards into the global stats profiler, under the RHI section. + //! This method can only be called on an initialized device, and outside of the BeginFrame / EndFrame scope. + //! Otherwise, an error code is returned. + ResultCode UpdateCpuTimingStatistics() const; //! Returns the physical device associated with this device. const PhysicalDevice& GetPhysicalDevice() const; @@ -186,7 +183,7 @@ namespace AZ virtual void CompileMemoryStatisticsInternal(MemoryStatisticsBuilder& builder) = 0; //! Called when the device is reporting cpu timing statistics. - virtual void UpdateCpuTimingStatisticsInternal(CpuTimingStatistics& cpuTimingStatistics) const = 0; + virtual void UpdateCpuTimingStatisticsInternal() const = 0; //! Fills the capabilities for each format. virtual void FillFormatsCapabilitiesInternal(FormatCapabilitiesList& formatsCapabilities) = 0; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/FrameScheduler.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/FrameScheduler.h index 48e7e0f339..eb2b0b5b0c 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/FrameScheduler.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/FrameScheduler.h @@ -7,7 +7,6 @@ */ #pragma once -#include #include #include #include @@ -168,8 +167,8 @@ namespace AZ /// Returns the timing statistics for the previous frame. const TransientAttachmentStatistics* GetTransientAttachmentStatistics() const; - /// Returns cpu timing statistics for the previous frame. - const CpuTimingStatistics* GetCpuTimingStatistics() const; + /// Returns current CPU frame to frame time in milliseconds. + double GetCpuFrameTime() const; /// Returns memory statistics for the previous frame. const MemoryStatistics* GetMemoryStatistics() const; @@ -216,7 +215,6 @@ namespace AZ Ptr m_transientAttachmentPool; - CpuTimingStatistics m_cpuTimingStatistics; AZStd::sys_time_t m_lastFrameEndTime{}; MemoryStatistics m_memoryStatistics; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h index 599108654a..52a44c0903 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystem.h @@ -48,7 +48,7 @@ namespace AZ RHI::PipelineStateCache* GetPipelineStateCache() override; const RHI::FrameSchedulerCompileRequest& GetFrameSchedulerCompileRequest() const override; void ModifyFrameSchedulerStatisticsFlags(RHI::FrameSchedulerStatisticsFlags statisticsFlags, bool enableFlags) override; - const RHI::CpuTimingStatistics* GetCpuTimingStatistics() const override; + double GetCpuFrameTime() const override; const RHI::TransientAttachmentStatistics* GetTransientAttachmentStatistics() const override; const RHI::MemoryStatistics* GetMemoryStatistics() const override; const RHI::TransientAttachmentPoolDescriptor* GetTransientAttachmentPoolDescriptor() const override; diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystemInterface.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystemInterface.h index 6a9650e0a1..19ba1cb762 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystemInterface.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHISystemInterface.h @@ -27,7 +27,6 @@ namespace AZ class PipelineStateCache; class PlatformLimitsDescriptor; class RayTracingShaderTable; - struct CpuTimingStatistics; struct FrameSchedulerCompileRequest; struct TransientAttachmentStatistics; struct TransientAttachmentPoolDescriptor; @@ -55,7 +54,7 @@ namespace AZ virtual void ModifyFrameSchedulerStatisticsFlags(RHI::FrameSchedulerStatisticsFlags statisticsFlags, bool enableFlags) = 0; - virtual const RHI::CpuTimingStatistics* GetCpuTimingStatistics() const = 0; + virtual double GetCpuFrameTime() const = 0; virtual const RHI::TransientAttachmentStatistics* GetTransientAttachmentStatistics() const = 0; diff --git a/Gems/Atom/RHI/Code/Source/RHI/CommandQueue.cpp b/Gems/Atom/RHI/Code/Source/RHI/CommandQueue.cpp index f65c36f2ed..a365b23e94 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/CommandQueue.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/CommandQueue.cpp @@ -32,6 +32,23 @@ namespace AZ return ResultCode::InvalidOperation; } #endif + + if (auto statsProfiler = AZ::Interface::Get(); statsProfiler) + { + auto& rhiMetrics = statsProfiler->GetProfiler(rhiMetricsId); + + static constexpr AZStd::string_view presentStatName("Present"); + static constexpr AZ::Crc32 presentStatId(presentStatName); + rhiMetrics.GetStatsManager().AddStatistic(presentStatId, presentStatName, /*units=*/"clocks", /*failIfExist=*/false); + + if (!GetName().IsEmpty()) + { + const AZStd::string commandQueueName(GetName().GetCStr()); + const AZ::Crc32 commandQueueId(GetName().GetHash()); + rhiMetrics.GetStatsManager().AddStatistic(commandQueueId, commandQueueName, /*units=*/"clocks", /*failIfExist=*/false); + } + } + const ResultCode resultCode = InitInternal(device, descriptor); if (resultCode == ResultCode::Success) diff --git a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp index 1bc17adb22..826e0b6aa3 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/CpuProfilerImpl.cpp @@ -12,6 +12,7 @@ #include #include +#include #include namespace AZ @@ -73,6 +74,11 @@ namespace AZ m_initialized = true; SystemTickBus::Handler::BusConnect(); m_continuousCaptureData.set_capacity(10); + + if (auto statsProfiler = AZ::Interface::Get(); statsProfiler) + { + statsProfiler->ActivateProfiler(AZ_CRC_CE("RHI"), true); + } } void CpuProfilerImpl::Shutdown() diff --git a/Gems/Atom/RHI/Code/Source/RHI/Device.cpp b/Gems/Atom/RHI/Code/Source/RHI/Device.cpp index 2f4ca297a1..c8497cf7b1 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/Device.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/Device.cpp @@ -160,11 +160,11 @@ namespace AZ return ResultCode::InvalidOperation; } - ResultCode Device::UpdateCpuTimingStatistics(CpuTimingStatistics& cpuTimingStatistics) const + ResultCode Device::UpdateCpuTimingStatistics() const { if (ValidateIsNotInFrame()) { - UpdateCpuTimingStatisticsInternal(cpuTimingStatistics); + UpdateCpuTimingStatisticsInternal(); return ResultCode::Success; } return ResultCode::InvalidOperation; diff --git a/Gems/Atom/RHI/Code/Source/RHI/FrameScheduler.cpp b/Gems/Atom/RHI/Code/Source/RHI/FrameScheduler.cpp index 0d3ac8216b..a15db9e24b 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/FrameScheduler.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/FrameScheduler.cpp @@ -35,6 +35,9 @@ namespace AZ { namespace RHI { + static constexpr const char* frameTimeMetricName = "Frame to Frame Time"; + static constexpr AZ::Crc32 frameTimeMetricId = AZ_CRC_CE(frameTimeMetricName); + ResultCode FrameScheduler::Init(Device& device, const FrameSchedulerDescriptor& descriptor) { ResultCode resultCode = ResultCode::Success; @@ -81,6 +84,12 @@ namespace AZ m_taskGraphActive = AZ::Interface::Get(); + if (auto statsProfiler = AZ::Interface::Get(); statsProfiler) + { + auto& rhiMetrics = statsProfiler->GetProfiler(rhiMetricsId); + rhiMetrics.GetStatsManager().AddStatistic(frameTimeMetricId, frameTimeMetricName, /*units=*/"clocks", /*failIfExist=*/false); + } + m_lastFrameEndTime = AZStd::GetTimeNowTicks(); return ResultCode::Success; @@ -278,7 +287,7 @@ namespace AZ AZ::TaskDescriptor srgCompileEndDesc{"SrgCompileEnd", "Graphics"}; auto srgCompileEndTask = taskGraph.AddTask( - srgCompileEndDesc, + srgCompileEndDesc, [srgPool]() { srgPool->CompileGroupsEnd(); @@ -449,7 +458,7 @@ namespace AZ m_device->CompileMemoryStatistics(m_memoryStatistics, MemoryStatisticsReportFlags::Detail); } - m_device->UpdateCpuTimingStatistics(m_cpuTimingStatistics); + m_device->UpdateCpuTimingStatistics(); m_scopeProducers.clear(); m_scopeProducerLookup.clear(); @@ -460,7 +469,10 @@ namespace AZ } const AZStd::sys_time_t timeNowTicks = AZStd::GetTimeNowTicks(); - m_cpuTimingStatistics.m_frameToFrameTime = timeNowTicks - m_lastFrameEndTime; + if (auto statsProfiler = AZ::Interface::Get(); statsProfiler) + { + statsProfiler->PushSample(rhiMetricsId, frameTimeMetricId, static_cast(timeNowTicks - m_lastFrameEndTime)); + } m_lastFrameEndTime = timeNowTicks; return ResultCode::Success; @@ -588,12 +600,18 @@ namespace AZ : nullptr; } - const CpuTimingStatistics* FrameScheduler::GetCpuTimingStatistics() const + double FrameScheduler::GetCpuFrameTime() const { - return - CheckBitsAny(m_compileRequest.m_statisticsFlags, FrameSchedulerStatisticsFlags::GatherCpuTimingStatistics) - ? &m_cpuTimingStatistics - : nullptr; + if (CheckBitsAny(m_compileRequest.m_statisticsFlags, FrameSchedulerStatisticsFlags::GatherCpuTimingStatistics)) + { + if (auto statsProfiler = AZ::Interface::Get(); statsProfiler) + { + auto& rhiMetrics = statsProfiler->GetProfiler(rhiMetricsId); + const auto* frameTimeStat = rhiMetrics.GetStatistic(frameTimeMetricId); + return (frameTimeStat->GetMostRecentSample() * 1000) / aznumeric_cast(AZStd::GetTimeTicksPerSecond()); + } + } + return 0; } ScopeId FrameScheduler::GetRootScopeId() const diff --git a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp index 744b688c60..b40ad3e11a 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RHISystem.cpp @@ -254,9 +254,9 @@ namespace AZ : RHI::ResetBits(m_compileRequest.m_statisticsFlags, statisticsFlags); } - const RHI::CpuTimingStatistics* RHISystem::GetCpuTimingStatistics() const + double RHISystem::GetCpuFrameTime() const { - return m_frameScheduler.GetCpuTimingStatistics(); + return m_frameScheduler.GetCpuFrameTime(); } const RHI::TransientAttachmentStatistics* RHISystem::GetTransientAttachmentStatistics() const diff --git a/Gems/Atom/RHI/Code/Tests/Device.h b/Gems/Atom/RHI/Code/Tests/Device.h index d3177fc823..2b6a81face 100644 --- a/Gems/Atom/RHI/Code/Tests/Device.h +++ b/Gems/Atom/RHI/Code/Tests/Device.h @@ -47,7 +47,7 @@ namespace UnitTest void CompileMemoryStatisticsInternal(AZ::RHI::MemoryStatisticsBuilder&) override {} - void UpdateCpuTimingStatisticsInternal([[maybe_unused]] AZ::RHI::CpuTimingStatistics& cpuTimingStatistics) const override {} + void UpdateCpuTimingStatisticsInternal() const override {} AZStd::chrono::microseconds GpuTimestampToMicroseconds([[maybe_unused]] uint64_t gpuTimestamp, [[maybe_unused]] AZ::RHI::HardwareQueueClass queueClass) const override { diff --git a/Gems/Atom/RHI/Code/atom_rhi_reflect_files.cmake b/Gems/Atom/RHI/Code/atom_rhi_reflect_files.cmake index e211462eeb..9a2b6e8765 100644 --- a/Gems/Atom/RHI/Code/atom_rhi_reflect_files.cmake +++ b/Gems/Atom/RHI/Code/atom_rhi_reflect_files.cmake @@ -112,7 +112,6 @@ set(FILES Source/RHI.Reflect/ShaderResourceGroupLayout.cpp Source/RHI.Reflect/ShaderResourceGroupLayoutDescriptor.cpp Source/RHI.Reflect/ShaderResourceGroupPoolDescriptor.cpp - Include/Atom/RHI.Reflect/CpuTimingStatistics.h Include/Atom/RHI.Reflect/MemoryStatistics.h Include/Atom/RHI.Reflect/TransientAttachmentStatistics.h Include/Atom/RHI.Reflect/SwapChainDescriptor.h diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueue.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueue.cpp index 0cde6aeb09..7ab2b07b03 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueue.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueue.cpp @@ -10,8 +10,8 @@ #include #include #include -#include -#include + +#include namespace AZ { @@ -139,7 +139,7 @@ namespace AZ QueueCommand([=](void* commandQueue) { AZ_PROFILE_SCOPE(RHI, "ExecuteWork"); - AZ_PROFILE_RHI_VARIABLE(m_lastExecuteDuration); + AZ::Debug::ScopedTimer executionTimer(m_lastExecuteDuration); static const uint32_t CommandListCountMax = 128; ID3D12CommandQueue* dx12CommandQueue = static_cast(commandQueue); @@ -185,7 +185,7 @@ namespace AZ dx12CommandQueue->Signal(fence->Get(), fence->GetPendingValue()); } - AZ_PROFILE_RHI_VARIABLE(m_lastPresentDuration); + AZ::Debug::ScopedTimer presentTimer(m_lastPresentDuration); for (RHI::SwapChain* swapChain : request.m_swapChainsToPresent) { swapChain->Present(); diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.cpp index 012784d3fc..5692809443 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.cpp @@ -7,7 +7,6 @@ */ #include -#include #include #include #include @@ -183,17 +182,22 @@ namespace AZ return *m_commandQueues[static_cast(hardwareQueueClass)]; } - void CommandQueueContext::UpdateCpuTimingStatistics(RHI::CpuTimingStatistics& cpuTimingStatistics) const + void CommandQueueContext::UpdateCpuTimingStatistics() const { - cpuTimingStatistics.Reset(); - - AZStd::sys_time_t presentDuration = 0; - for (const RHI::Ptr& commandQueue : m_commandQueues) + if (auto statsProfiler = AZ::Interface::Get(); statsProfiler) { - cpuTimingStatistics.m_queueStatistics.push_back({ commandQueue->GetName(), commandQueue->GetLastExecuteDuration() }); - presentDuration += commandQueue->GetLastPresentDuration(); + auto& rhiMetrics = statsProfiler->GetProfiler(rhiMetricsId); + + AZStd::sys_time_t presentDuration = 0; + for (const RHI::Ptr& commandQueue : m_commandQueues) + { + const AZ::Crc32 commandQueueId(commandQueue->GetName().GetHash()); + rhiMetrics.PushSample(commandQueueId, static_cast(commandQueue->GetLastExecuteDuration())); + presentDuration += commandQueue->GetLastPresentDuration(); + } + + rhiMetrics.PushSample(AZ_CRC_CE("Present"), static_cast(presentDuration)); } - cpuTimingStatistics.m_presentDuration = presentDuration; } const FenceSet& CommandQueueContext::GetCompiledFences() diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.h b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.h index cf820026aa..dff1741109 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.h +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/CommandQueueContext.h @@ -14,11 +14,6 @@ namespace AZ { - namespace RHI - { - struct CpuTimingStatistics; - } - namespace DX12 { class CommandQueueContext @@ -49,7 +44,7 @@ namespace AZ RHI::HardwareQueueClass hardwareQueueClass, const ExecuteWorkRequest& request); - void UpdateCpuTimingStatistics(RHI::CpuTimingStatistics& cpuTimingStatistics) const; + void UpdateCpuTimingStatistics() const; // Fences across all queues that are compiled by the frame graph compilation phase const FenceSet& GetCompiledFences(); diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.cpp index 6f614499d2..3d44e56953 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.cpp @@ -184,9 +184,9 @@ namespace AZ m_stagingMemoryAllocator.ReportMemoryUsage(builder); } - void Device::UpdateCpuTimingStatisticsInternal(RHI::CpuTimingStatistics& cpuTimingStatistics) const + void Device::UpdateCpuTimingStatisticsInternal() const { - m_commandQueueContext.UpdateCpuTimingStatistics(cpuTimingStatistics); + m_commandQueueContext.UpdateCpuTimingStatistics(); } void Device::EndFrameInternal() diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.h b/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.h index 40e26db891..29e006fca0 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.h +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/Device.h @@ -147,7 +147,7 @@ namespace AZ void ShutdownInternal() override; void CompileMemoryStatisticsInternal(RHI::MemoryStatisticsBuilder& builder) override; - void UpdateCpuTimingStatisticsInternal(RHI::CpuTimingStatistics& cpuTimingStatistics) const override; + void UpdateCpuTimingStatisticsInternal() const override; void BeginFrameInternal() override; void EndFrameInternal() override; void WaitForIdleInternal() override; diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueue.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueue.cpp index d151a11ec1..a1f4616147 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueue.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueue.cpp @@ -5,14 +5,15 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#include -#include + #include #include #include #include #include +#include + namespace AZ { namespace Metal @@ -115,7 +116,7 @@ namespace AZ @autoreleasepool { AZ_PROFILE_SCOPE(RHI, "ExecuteWork"); - AZ_PROFILE_RHI_VARIABLE(m_lastExecuteDuration); + AZ::Debug::ScopedTimer executionTimer(m_lastExecuteDuration); if (request.m_signalFenceValue > 0) { @@ -128,7 +129,7 @@ namespace AZ } { - AZ_PROFILE_RHI_VARIABLE(m_lastPresentDuration); + AZ::Debug::ScopedTimer presentTimer(m_lastPresentDuration); for (RHI::SwapChain* swapChain : request.m_swapChainsToPresent) { diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueueContext.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueueContext.cpp index e4c651c2b1..37f8a8bab8 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueueContext.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueueContext.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include #include @@ -135,18 +134,23 @@ namespace AZ m_commandQueues[hardwareQueueIdx]->QueueGpuSignal(fence); } } - - void CommandQueueContext::UpdateCpuTimingStatistics(RHI::CpuTimingStatistics& cpuTimingStatistics) const - { - cpuTimingStatistics.Reset(); - AZStd::sys_time_t presentDuration = 0; - for (const RHI::Ptr& commandQueue : m_commandQueues) + void CommandQueueContext::UpdateCpuTimingStatistics() const + { + if (auto statsProfiler = AZ::Interface::Get(); statsProfiler) { - cpuTimingStatistics.m_queueStatistics.push_back({ commandQueue->GetName(), commandQueue->GetLastExecuteDuration() }); - presentDuration += commandQueue->GetLastPresentDuration(); + auto& rhiMetrics = statsProfiler->GetProfiler(rhiMetricsId); + + AZStd::sys_time_t presentDuration = 0; + for (const RHI::Ptr& commandQueue : m_commandQueues) + { + const AZ::Crc32 commandQueueId(commandQueue->GetName().GetHash()); + rhiMetrics.PushSample(commandQueueId, static_cast(commandQueue->GetLastExecuteDuration())); + presentDuration += commandQueue->GetLastPresentDuration(); + } + + rhiMetrics.PushSample(AZ_CRC_CE("Present"), static_cast(presentDuration)); } - cpuTimingStatistics.m_presentDuration = presentDuration; } } } diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueueContext.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueueContext.h index 747667e1a3..41c0f63189 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueueContext.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/CommandQueueContext.h @@ -40,7 +40,7 @@ namespace AZ /// Fences across all queues that are compiled by the frame graph compilation phase const FenceSet& GetCompiledFences(); - void UpdateCpuTimingStatistics(RHI::CpuTimingStatistics& cpuTimingStatistics) const; + void UpdateCpuTimingStatistics() const; private: AZStd::array, RHI::HardwareQueueClassCount> m_commandQueues; FenceSet m_compiledFences; diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.cpp index 782ea7174b..76af1ecab1 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.cpp @@ -245,9 +245,9 @@ namespace AZ { } - void Device::UpdateCpuTimingStatisticsInternal(RHI::CpuTimingStatistics& cpuTimingStatistics) const + void Device::UpdateCpuTimingStatisticsInternal() const { - m_commandQueueContext.UpdateCpuTimingStatistics(cpuTimingStatistics); + m_commandQueueContext.UpdateCpuTimingStatistics(); } void Device::FillFormatsCapabilitiesInternal(FormatCapabilitiesList& formatsCapabilities) diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.h b/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.h index 90dd4ff4a0..8a8ef662f9 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.h +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/Device.h @@ -161,7 +161,7 @@ namespace AZ RHI::ResultCode InitInternal(RHI::PhysicalDevice& physicalDevice) override; void ShutdownInternal() override; void CompileMemoryStatisticsInternal(RHI::MemoryStatisticsBuilder& builder) override; - void UpdateCpuTimingStatisticsInternal(RHI::CpuTimingStatistics& cpuTimingStatistics) const override; + void UpdateCpuTimingStatisticsInternal() const override; void BeginFrameInternal() override; void EndFrameInternal() override; void WaitForIdleInternal() override; diff --git a/Gems/Atom/RHI/Null/Code/Source/RHI/Device.h b/Gems/Atom/RHI/Null/Code/Source/RHI/Device.h index 27873887d4..73e1cd9119 100644 --- a/Gems/Atom/RHI/Null/Code/Source/RHI/Device.h +++ b/Gems/Atom/RHI/Null/Code/Source/RHI/Device.h @@ -32,7 +32,7 @@ namespace AZ RHI::ResultCode InitInternal([[maybe_unused]] RHI::PhysicalDevice& physicalDevice) override { return RHI::ResultCode::Success; } void ShutdownInternal() override {} void CompileMemoryStatisticsInternal([[maybe_unused]] RHI::MemoryStatisticsBuilder& builder) override {} - void UpdateCpuTimingStatisticsInternal([[maybe_unused]] RHI::CpuTimingStatistics& cpuTimingStatistics) const override {} + void UpdateCpuTimingStatisticsInternal() const override {} void BeginFrameInternal() override {} void EndFrameInternal() override {} void WaitForIdleInternal() override {} diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp index c712099172..6a43b66474 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueue.cpp @@ -5,13 +5,14 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ -#include + #include #include #include #include #include -#include + +#include namespace AZ { @@ -46,7 +47,7 @@ namespace AZ QueueCommand([=](void* queue) { AZ_PROFILE_SCOPE(RHI, "ExecuteWork"); - AZ_PROFILE_RHI_VARIABLE(m_lastExecuteDuration); + AZ::Debug::ScopedTimer executionTimer(m_lastExecuteDuration); Queue* vulkanQueue = static_cast(queue); @@ -80,7 +81,7 @@ namespace AZ } { - AZ_PROFILE_RHI_VARIABLE(m_lastPresentDuration); + AZ::Debug::ScopedTimer presentTimer(m_lastPresentDuration); // present the image of the current frame. for (RHI::SwapChain* swapChain : request.m_swapChainsToPresent) diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.cpp index ec7311cd6e..9cf6dce77b 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.cpp @@ -13,7 +13,6 @@ #include #include #include -#include namespace AZ { @@ -363,17 +362,22 @@ namespace AZ return queueSelection.m_familyIndex != InvalidFamilyIndex; } - void CommandQueueContext::UpdateCpuTimingStatistics(RHI::CpuTimingStatistics& cpuTimingStatistics) const + void CommandQueueContext::UpdateCpuTimingStatistics() const { - cpuTimingStatistics.Reset(); - - AZStd::sys_time_t presentDuration = 0; - for (const RHI::Ptr& commandQueue : m_commandQueues) + if (auto statsProfiler = AZ::Interface::Get(); statsProfiler) { - cpuTimingStatistics.m_queueStatistics.push_back({ commandQueue->GetName(), commandQueue->GetLastExecuteDuration() }); - presentDuration += commandQueue->GetLastPresentDuration(); + auto& rhiMetrics = statsProfiler->GetProfiler(rhiMetricsId); + + AZStd::sys_time_t presentDuration = 0; + for (const RHI::Ptr& commandQueue : m_commandQueues) + { + const AZ::Crc32 commandQueueId(commandQueue->GetName().GetHash()); + rhiMetrics.PushSample(commandQueueId, static_cast(commandQueue->GetLastExecuteDuration())); + presentDuration += commandQueue->GetLastPresentDuration(); + } + + rhiMetrics.PushSample(AZ_CRC_CE("Present"), static_cast(presentDuration)); } - cpuTimingStatistics.m_presentDuration = presentDuration; } } } diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.h b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.h index 8528185686..61e9b46d9f 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.h +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/CommandQueueContext.h @@ -16,11 +16,6 @@ namespace AZ { - namespace RHI - { - struct CpuTimingStatistics; - } - namespace Vulkan { class Device; @@ -62,7 +57,7 @@ namespace AZ AZStd::vector GetQueueFamilyIndices(const RHI::HardwareQueueClassMask hardwareQueueClassMask) const; VkPipelineStageFlags GetSupportedPipelineStages(uint32_t queueFamilyIndex) const; - void UpdateCpuTimingStatistics(RHI::CpuTimingStatistics& cpuTimingStatistics) const; + void UpdateCpuTimingStatistics() const; private: Descriptor m_descriptor; diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp index 35bc966d1d..132f9929c1 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.cpp @@ -547,9 +547,9 @@ namespace AZ physicalDevice.CompileMemoryStatistics(builder); } - void Device::UpdateCpuTimingStatisticsInternal(RHI::CpuTimingStatistics& cpuTimingStatistics) const + void Device::UpdateCpuTimingStatisticsInternal() const { - m_commandQueueContext.UpdateCpuTimingStatistics(cpuTimingStatistics); + m_commandQueueContext.UpdateCpuTimingStatistics(); } AZStd::vector Device::GetValidSwapChainImageFormats(const RHI::WindowHandle& windowHandle) const diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.h b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.h index 13ccf9367b..9c21103929 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.h +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Device.h @@ -126,7 +126,7 @@ namespace AZ void EndFrameInternal() override; void WaitForIdleInternal() override; void CompileMemoryStatisticsInternal(RHI::MemoryStatisticsBuilder& builder) override; - void UpdateCpuTimingStatisticsInternal(RHI::CpuTimingStatistics& cpuTimingStatistics) const override; + void UpdateCpuTimingStatisticsInternal() const override; AZStd::vector GetValidSwapChainImageFormats(const RHI::WindowHandle& windowHandle) const override; AZStd::chrono::microseconds GpuTimestampToMicroseconds(uint64_t gpuTimestamp, RHI::HardwareQueueClass queueClass) const override; void FillFormatsCapabilitiesInternal(FormatCapabilitiesList& formatsCapabilities) override; diff --git a/Gems/Atom/RPI/Code/Tests/Common/RHI/Stubs.h b/Gems/Atom/RPI/Code/Tests/Common/RHI/Stubs.h index 2ed2875cad..b8d1cfa050 100644 --- a/Gems/Atom/RPI/Code/Tests/Common/RHI/Stubs.h +++ b/Gems/Atom/RPI/Code/Tests/Common/RHI/Stubs.h @@ -61,7 +61,7 @@ namespace UnitTest void EndFrameInternal() override {} void WaitForIdleInternal() override {} void CompileMemoryStatisticsInternal(AZ::RHI::MemoryStatisticsBuilder&) override {} - void UpdateCpuTimingStatisticsInternal([[maybe_unused]] AZ::RHI::CpuTimingStatistics& cpuTimingStatistics) const override {} + void UpdateCpuTimingStatisticsInternal() const override {} AZStd::chrono::microseconds GpuTimestampToMicroseconds([[maybe_unused]] uint64_t gpuTimestamp, [[maybe_unused]] AZ::RHI::HardwareQueueClass queueClass) const override { return AZStd::chrono::microseconds(); diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/PerformanceMonitorComponent.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/PerformanceMonitorComponent.cpp index 5598d894ff..c3bb13d1d2 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/PerformanceMonitorComponent.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Viewport/PerformanceMonitorComponent.cpp @@ -9,7 +9,6 @@ #include #include -#include #include #include #include @@ -96,10 +95,10 @@ namespace MaterialEditor ResetStats(); } - const AZ::RHI::CpuTimingStatistics* stats = AZ::RHI::RHISystemInterface::Get()->GetCpuTimingStatistics(); - if (stats) + double frameTime = AZ::RHI::RHISystemInterface::Get()->GetCpuFrameTime(); + if (frameTime > 0) { - m_cpuFrameTimeMs.PushSample(stats->GetFrameToFrameTimeMilliseconds()); + m_cpuFrameTimeMs.PushSample(frameTime); } AZ::RHI::Ptr rootPass = AZ::RPI::PassSystemInterface::Get()->GetRootPass(); diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h index a649fcf0f7..4a326660dd 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.h @@ -12,17 +12,11 @@ #include #include -#include #include namespace AZ { - namespace RHI - { - struct CpuTimingStatistics; - } - namespace Render { //! Stores all the data associated with a row in the table. @@ -88,11 +82,17 @@ namespace AZ using GroupRegionName = AZ::RHI::CachedTimeRegion::GroupRegionName; public: + struct CpuTimingEntry + { + const AZStd::string& m_name; + double m_executeDuration; + }; + ImGuiCpuProfiler() = default; ~ImGuiCpuProfiler() = default; //! Draws the overall CPU profiling window, defaults to the statistical view - void Draw(bool& keepDrawing, const AZ::RHI::CpuTimingStatistics& cpuTimingStatistics); + void Draw(bool& keepDrawing); private: static constexpr float RowHeight = 35.0; @@ -121,11 +121,14 @@ namespace AZ // Sort the table by a given column, rearranges the pointers in m_tableData. void SortTable(ImGuiTableSortSpecs* sortSpecs); + // gather the latest timing statistics + void CacheCpuTimingStatistics(); + // Get the profiling data from the last frame, only called when the profiler is not paused. void CollectFrameData(); // Cull old data from internal storage, only called when profiler is not paused. - void CullFrameData(const AZ::RHI::CpuTimingStatistics& currentCpuTimingStatistics); + void CullFrameData(); // Draws a single block onto the timeline into the specified row void DrawBlock(const TimeRegion& block, u64 targetRow); @@ -204,7 +207,8 @@ namespace AZ bool m_enableVisualizer = false; // Last captured CPU timing statistics - AZ::RHI::CpuTimingStatistics m_cpuTimingStatisticsWhenPause; + AZStd::vector m_cpuTimingStatisticsWhenPause; + AZStd::sys_time_t m_frameToFrameTime{}; AZStd::string m_lastCapturedFilePath; diff --git a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl index a573e3019a..daf6eca5c0 100644 --- a/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl +++ b/Gems/Atom/Utils/Code/Include/Atom/Utils/ImGuiCpuProfiler.inl @@ -7,7 +7,6 @@ */ #include -#include #include #include #include @@ -16,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -31,7 +31,7 @@ namespace AZ { namespace CpuProfilerImGuiHelper { - inline float TicksToMs(AZStd::sys_time_t ticks) + inline float TicksToMs(double ticks) { // Note: converting to microseconds integer before converting to milliseconds float const AZStd::sys_time_t ticksPerSecond = AZStd::GetTimeTicksPerSecond(); @@ -39,6 +39,11 @@ namespace AZ return static_cast((ticks * 1000) / (ticksPerSecond / 1000)) / 1000.0f; } + inline float TicksToMs(AZStd::sys_time_t ticks) + { + return TicksToMs(static_cast(ticks)); + } + using DeserializedCpuData = AZStd::vector; inline Outcome LoadSavedCpuProfilingStatistics(const AZStd::string& capturePath) { @@ -108,7 +113,9 @@ namespace AZ } } // namespace CpuProfilerImGuiHelper - inline void ImGuiCpuProfiler::Draw(bool& keepDrawing, const AZ::RHI::CpuTimingStatistics& currentCpuTimingStatistics) + + + inline void ImGuiCpuProfiler::Draw(bool& keepDrawing) { // Cache the value to detect if it was changed by ImGui(user pressed 'x') const bool cachedShowCpuProfiler = keepDrawing; @@ -121,10 +128,10 @@ namespace AZ if (!m_paused) { // Update region map and cache the input cpu timing statistics when the profiling is not paused - m_cpuTimingStatisticsWhenPause = currentCpuTimingStatistics; + CacheCpuTimingStatistics(); CollectFrameData(); - CullFrameData(currentCpuTimingStatistics); + CullFrameData(); // Only listen to system ticks when the profiler is active if (!SystemTickBus::Handler::BusIsConnected()) @@ -354,19 +361,12 @@ namespace AZ { DrawCommonHeader(); - const AZ::RHI::CpuTimingStatistics& cpuTimingStatistics = m_cpuTimingStatisticsWhenPause; - - const auto ShowTimeInMs = [](AZStd::sys_time_t duration) - { - ImGui::Text("%.2f ms", CpuProfilerImGuiHelper::TicksToMs(duration)); - }; - - const auto ShowRow = [&ShowTimeInMs](const char* regionLabel, AZStd::sys_time_t duration) + const auto ShowRow = [](const char* regionLabel, double duration) { ImGui::Text("%s", regionLabel); ImGui::NextColumn(); - ShowTimeInMs(duration); + ImGui::Text("%.2f ms", CpuProfilerImGuiHelper::TicksToMs(duration)); ImGui::NextColumn(); }; @@ -377,11 +377,9 @@ namespace AZ ImGui::SetColumnWidth(0, 660.0f); ImGui::SetColumnWidth(1, 100.0f); - ShowRow("Frame to Frame Time", cpuTimingStatistics.m_frameToFrameTime); - ShowRow("Present Time", cpuTimingStatistics.m_presentDuration); - for (const auto& queueStatistics : cpuTimingStatistics.m_queueStatistics) + for (const auto& queueStatistics : m_cpuTimingStatisticsWhenPause) { - ShowRow(queueStatistics.m_queueName.GetCStr(), queueStatistics.m_executeDuration); + ShowRow(queueStatistics.m_name.c_str(), queueStatistics.m_executeDuration); } ImGui::Separator(); @@ -653,6 +651,32 @@ namespace AZ ImGui::EndChild(); } + inline void ImGuiCpuProfiler::CacheCpuTimingStatistics() + { + using namespace AZ::Statistics; + + m_cpuTimingStatisticsWhenPause.clear(); + if (auto statsProfiler = AZ::Interface::Get(); statsProfiler) + { + auto& rhiMetrics = statsProfiler->GetProfiler(AZ_CRC_CE("RHI")); + + const NamedRunningStatistic* frameTimeMetric = rhiMetrics.GetStatistic(AZ_CRC_CE("Frame to Frame Time")); + if (frameTimeMetric) + { + m_frameToFrameTime = static_cast(frameTimeMetric->GetMostRecentSample()); + } + + AZStd::vector statistics; + rhiMetrics.GetStatsManager().GetAllStatistics(statistics); + + for (NamedRunningStatistic* stat : statistics) + { + m_cpuTimingStatisticsWhenPause.push_back({ stat->GetName(), stat->GetMostRecentSample() }); + stat->Reset(); + } + } + } + inline void ImGuiCpuProfiler::CollectFrameData() { // We maintain separate datastores for the visualizer and the statistical view because they require different @@ -721,10 +745,9 @@ namespace AZ } } - inline void ImGuiCpuProfiler::CullFrameData(const AZ::RHI::CpuTimingStatistics& currentCpuTimingStatistics) + inline void ImGuiCpuProfiler::CullFrameData() { - const AZStd::sys_time_t frameToFrameTime = currentCpuTimingStatistics.m_frameToFrameTime; - const AZStd::sys_time_t deleteBeforeTick = AZStd::GetTimeNowTicks() - frameToFrameTime * m_framesToCollect; + const AZStd::sys_time_t deleteBeforeTick = AZStd::GetTimeNowTicks() - m_frameToFrameTime * m_framesToCollect; // Remove old frame boundary data auto firstBoundaryToKeepItr = AZStd::upper_bound(m_frameEndTicks.begin(), m_frameEndTicks.end(), deleteBeforeTick); diff --git a/Gems/AtomLyIntegration/AtomImGuiTools/Code/Source/AtomImGuiToolsSystemComponent.cpp b/Gems/AtomLyIntegration/AtomImGuiTools/Code/Source/AtomImGuiToolsSystemComponent.cpp index ec18997a01..b369ab2ee2 100644 --- a/Gems/AtomLyIntegration/AtomImGuiTools/Code/Source/AtomImGuiToolsSystemComponent.cpp +++ b/Gems/AtomLyIntegration/AtomImGuiTools/Code/Source/AtomImGuiToolsSystemComponent.cpp @@ -86,11 +86,7 @@ namespace AtomImGuiTools } if (m_showCpuProfiler) { - const AZ::RHI::CpuTimingStatistics* stats = AZ::RHI::RHISystemInterface::Get()->GetCpuTimingStatistics(); - if (stats) - { - m_imguiCpuProfiler.Draw(m_showCpuProfiler, *stats); - } + m_imguiCpuProfiler.Draw(m_showCpuProfiler); } if (m_showTransientAttachmentProfiler) { From 89e6df1c7fc6105ab6fac70964415af283768912 Mon Sep 17 00:00:00 2001 From: Qing Tao <55564570+VickyAtAZ@users.noreply.github.com> Date: Mon, 11 Oct 2021 15:18:39 -0700 Subject: [PATCH 109/169] ATOM-16575 clean up image builder presets files (#4611) ATOM-16575 clean up image builder presets files Removed unused image builder presets Deprecating preset UUID and use preset name as unique id Delete all .exportsettings file which were only used for legacy imageProcessing gem. Signed-off-by: Qing Tao --- .../Materials/Stripes.tif.exportsettings | 1 - .../Materials/voxel_editor.png.exportsettings | 1 - .../AverageMemoryUsage.TIF.exportsettings | 1 - .../Icons/HighMemoryUsage.TIF.exportsettings | 1 - .../LevelShaderCacheMiss.tif.exportsettings | 1 - .../Icons/LivePreview.TIF.exportsettings | 1 - .../Icons/LowMemoryUsage.TIF.exportsettings | 1 - .../NavigationProcessing.tif.exportsettings | 1 - .../Icons/NullSoundSystem.tif.exportsettings | 1 - .../Icons/ShaderCompiling.tif.exportsettings | 1 - .../Icons/Streaming.tif.exportsettings | 1 - .../Icons/StreamingTerrain.tif.exportsettings | 1 - .../textures/default_icon.png.exportsettings | 1 - .../grass_atlas_diff.tif.exportsettings | 1 - .../grass_atlas_sss.tif.exportsettings | 1 - ...est_texture_sequence000.png.exportsettings | 1 - .../ProxyGray_ddna.tif.exportsettings | 1 - .../lights/flare01.tif.exportsettings | 1 - .../milestone2/AMA_Grey_01.tif.exportsettings | 1 - .../milestone2/AMA_Grey_02.tif.exportsettings | 1 - .../milestone2/AMA_Grey_03.tif.exportsettings | 1 - ..._LauncherMuzzleFront_01.tif.exportsettings | 1 - ...X_LauncherMuzzleRing_01.tif.exportsettings | 1 - .../BuilderSettings/BuilderSettingManager.cpp | 78 +++++------ .../BuilderSettings/BuilderSettingManager.h | 24 ++-- .../Source/BuilderSettings/CubemapSettings.h | 8 +- .../BuilderSettings/ImageProcessingDefines.h | 4 +- .../Source/BuilderSettings/PresetSettings.h | 3 +- .../BuilderSettings/TextureSettings.cpp | 27 ++-- .../Source/BuilderSettings/TextureSettings.h | 7 +- .../Code/Source/Editor/EditorCommon.cpp | 25 ++-- .../Code/Source/Editor/EditorCommon.h | 2 +- .../Code/Source/Editor/PresetInfoPopup.cpp | 6 +- .../Editor/ResolutionSettingItemWidget.cpp | 2 +- .../Editor/ResolutionSettingItemWidget.h | 2 +- .../Editor/TexturePresetSelectionWidget.cpp | 20 +-- .../Editor/TexturePresetSelectionWidget.h | 2 +- .../Code/Source/ImageBuilderComponent.cpp | 8 +- .../Code/Source/Processing/ImageConvert.cpp | 18 ++- .../Code/Source/Processing/ImageConvert.h | 2 +- .../Code/Source/Processing/ImagePreview.cpp | 2 +- .../Code/Tests/ImageProcessing_Test.cpp | 11 +- .../1024x1024_24bit.tif.exportsettings | 1 - .../Config/AlbedoWithOpacity.preset | 104 --------------- .../Config/CloudShadows.preset | 44 ------ .../Config/ColorChart.preset | 64 --------- ...etail_MergedAlbedoNormalsSmoothness.preset | 79 ----------- ...gedAlbedoNormalsSmoothness_Lossless.preset | 74 ---------- .../Config/IBLGlobal.preset | 4 +- .../Config/IBLSkybox.preset | 20 +-- .../Config/ImageBuilder.settings | 42 +++--- .../Config/LensOptics.preset | 34 ----- .../Config/LightProjector.preset | 59 -------- .../Config/LoadingScreen.preset | 34 ----- .../ImageProcessingAtom/Config/Minimap.preset | 64 --------- .../Config/MuzzleFlash.preset | 59 -------- .../ImageProcessingAtom/Config/Normals.preset | 5 + .../Config/NormalsFromDisplacement.preset | 86 ------------ .../NormalsWithSmoothness_Legacy.preset | 101 -------------- .../ReflectanceWithSmoothness_Legacy.preset | 71 ---------- .../Config/Reflectance_Linear.preset | 81 ----------- .../ImageProcessingAtom/Config/SF_Font.preset | 49 ------- .../Config/SF_Gradient.preset | 49 ------- .../Config/SF_Image.preset | 54 -------- .../Config/SF_Image_nonpower2.preset | 49 ------- .../Config/Terrain_Albedo.preset | 69 ---------- .../Config/Terrain_Albedo_HighPassed.preset | 64 --------- .../Config/Uncompressed.preset | 54 -------- .../Actor/chicken_diff.png.imagesettings | 65 --------- .../Textures/Cowboy_01_ddna.tif.imagesettings | 126 ------------------ .../Textures/Cowboy_01_spec.tif.imagesettings | 126 ------------------ ...amepad_button_a_pressed.tif.exportsettings | 1 - ...epad_button_a_unpressed.tif.exportsettings | 1 - ...amepad_button_b_pressed.tif.exportsettings | 1 - ...epad_button_b_unpressed.tif.exportsettings | 1 - ...amepad_button_x_pressed.tif.exportsettings | 1 - ...epad_button_x_unpressed.tif.exportsettings | 1 - ...amepad_button_y_pressed.tif.exportsettings | 1 - ...epad_button_y_unpressed.tif.exportsettings | 1 - ...mepad_thumbstick_centre.tif.exportsettings | 1 - ...mepad_thumbstick_radial.tif.exportsettings | 1 - 81 files changed, 159 insertions(+), 1856 deletions(-) delete mode 100644 Assets/Editor/Materials/Stripes.tif.exportsettings delete mode 100644 Assets/Editor/Materials/voxel_editor.png.exportsettings delete mode 100644 Assets/Engine/EngineAssets/Icons/AverageMemoryUsage.TIF.exportsettings delete mode 100644 Assets/Engine/EngineAssets/Icons/HighMemoryUsage.TIF.exportsettings delete mode 100644 Assets/Engine/EngineAssets/Icons/LevelShaderCacheMiss.tif.exportsettings delete mode 100644 Assets/Engine/EngineAssets/Icons/LivePreview.TIF.exportsettings delete mode 100644 Assets/Engine/EngineAssets/Icons/LowMemoryUsage.TIF.exportsettings delete mode 100644 Assets/Engine/EngineAssets/Icons/NavigationProcessing.tif.exportsettings delete mode 100644 Assets/Engine/EngineAssets/Icons/NullSoundSystem.tif.exportsettings delete mode 100644 Assets/Engine/EngineAssets/Icons/ShaderCompiling.tif.exportsettings delete mode 100644 Assets/Engine/EngineAssets/Icons/Streaming.tif.exportsettings delete mode 100644 Assets/Engine/EngineAssets/Icons/StreamingTerrain.tif.exportsettings delete mode 100644 Assets/Engine/textures/default_icon.png.exportsettings delete mode 100644 AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_diff.tif.exportsettings delete mode 100644 AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_sss.tif.exportsettings delete mode 100644 AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/C30936451/test_texture_sequence000.png.exportsettings delete mode 100644 AutomatedTesting/Objects/LumberTank/ProxyGray_ddna.tif.exportsettings delete mode 100644 AutomatedTesting/textures/lights/flare01.tif.exportsettings delete mode 100644 AutomatedTesting/textures/milestone2/AMA_Grey_01.tif.exportsettings delete mode 100644 AutomatedTesting/textures/milestone2/AMA_Grey_02.tif.exportsettings delete mode 100644 AutomatedTesting/textures/milestone2/AMA_Grey_03.tif.exportsettings delete mode 100644 AutomatedTesting/textures/milestone2/particles/FX_LauncherMuzzleFront_01.tif.exportsettings delete mode 100644 AutomatedTesting/textures/milestone2/particles/FX_LauncherMuzzleRing_01.tif.exportsettings delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/1024x1024_24bit.tif.exportsettings delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithOpacity.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/CloudShadows.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/ColorChart.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness_Lossless.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/LensOptics.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/LightProjector.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/LoadingScreen.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/Minimap.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/MuzzleFlash.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsFromDisplacement.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsWithSmoothness_Legacy.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/ReflectanceWithSmoothness_Legacy.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance_Linear.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Font.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Gradient.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image_nonpower2.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo_HighPassed.preset delete mode 100644 Gems/Atom/Asset/ImageProcessingAtom/Config/Uncompressed.preset delete mode 100644 Gems/NvCloth/Assets/Objects/cloth/Chicken/Actor/chicken_diff.png.imagesettings delete mode 100644 Gems/PhysXSamples/Assets/Characters/Cowboy/Actor/Textures/Cowboy_01_ddna.tif.imagesettings delete mode 100644 Gems/PhysXSamples/Assets/Characters/Cowboy/Actor/Textures/Cowboy_01_spec.tif.imagesettings delete mode 100644 Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_a_pressed.tif.exportsettings delete mode 100644 Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_a_unpressed.tif.exportsettings delete mode 100644 Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_b_pressed.tif.exportsettings delete mode 100644 Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_b_unpressed.tif.exportsettings delete mode 100644 Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_x_pressed.tif.exportsettings delete mode 100644 Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_x_unpressed.tif.exportsettings delete mode 100644 Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_y_pressed.tif.exportsettings delete mode 100644 Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_y_unpressed.tif.exportsettings delete mode 100644 Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_thumbstick_centre.tif.exportsettings delete mode 100644 Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_thumbstick_radial.tif.exportsettings diff --git a/Assets/Editor/Materials/Stripes.tif.exportsettings b/Assets/Editor/Materials/Stripes.tif.exportsettings deleted file mode 100644 index 0653bb85eb..0000000000 --- a/Assets/Editor/Materials/Stripes.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Diffuse_lowQ \ No newline at end of file diff --git a/Assets/Editor/Materials/voxel_editor.png.exportsettings b/Assets/Editor/Materials/voxel_editor.png.exportsettings deleted file mode 100644 index d19ae00148..0000000000 --- a/Assets/Editor/Materials/voxel_editor.png.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /mipmaps=0 /preset=AlbedoWithGenericAlpha /reduce=-1 \ No newline at end of file diff --git a/Assets/Engine/EngineAssets/Icons/AverageMemoryUsage.TIF.exportsettings b/Assets/Engine/EngineAssets/Icons/AverageMemoryUsage.TIF.exportsettings deleted file mode 100644 index c48fb8632a..0000000000 --- a/Assets/Engine/EngineAssets/Icons/AverageMemoryUsage.TIF.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Uncompressed \ No newline at end of file diff --git a/Assets/Engine/EngineAssets/Icons/HighMemoryUsage.TIF.exportsettings b/Assets/Engine/EngineAssets/Icons/HighMemoryUsage.TIF.exportsettings deleted file mode 100644 index c48fb8632a..0000000000 --- a/Assets/Engine/EngineAssets/Icons/HighMemoryUsage.TIF.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Uncompressed \ No newline at end of file diff --git a/Assets/Engine/EngineAssets/Icons/LevelShaderCacheMiss.tif.exportsettings b/Assets/Engine/EngineAssets/Icons/LevelShaderCacheMiss.tif.exportsettings deleted file mode 100644 index c48fb8632a..0000000000 --- a/Assets/Engine/EngineAssets/Icons/LevelShaderCacheMiss.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Uncompressed \ No newline at end of file diff --git a/Assets/Engine/EngineAssets/Icons/LivePreview.TIF.exportsettings b/Assets/Engine/EngineAssets/Icons/LivePreview.TIF.exportsettings deleted file mode 100644 index 8da27c31a4..0000000000 --- a/Assets/Engine/EngineAssets/Icons/LivePreview.TIF.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=Uncompressed \ No newline at end of file diff --git a/Assets/Engine/EngineAssets/Icons/LowMemoryUsage.TIF.exportsettings b/Assets/Engine/EngineAssets/Icons/LowMemoryUsage.TIF.exportsettings deleted file mode 100644 index c48fb8632a..0000000000 --- a/Assets/Engine/EngineAssets/Icons/LowMemoryUsage.TIF.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Uncompressed \ No newline at end of file diff --git a/Assets/Engine/EngineAssets/Icons/NavigationProcessing.tif.exportsettings b/Assets/Engine/EngineAssets/Icons/NavigationProcessing.tif.exportsettings deleted file mode 100644 index 8da27c31a4..0000000000 --- a/Assets/Engine/EngineAssets/Icons/NavigationProcessing.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=Uncompressed \ No newline at end of file diff --git a/Assets/Engine/EngineAssets/Icons/NullSoundSystem.tif.exportsettings b/Assets/Engine/EngineAssets/Icons/NullSoundSystem.tif.exportsettings deleted file mode 100644 index 8da27c31a4..0000000000 --- a/Assets/Engine/EngineAssets/Icons/NullSoundSystem.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=Uncompressed \ No newline at end of file diff --git a/Assets/Engine/EngineAssets/Icons/ShaderCompiling.tif.exportsettings b/Assets/Engine/EngineAssets/Icons/ShaderCompiling.tif.exportsettings deleted file mode 100644 index 8da27c31a4..0000000000 --- a/Assets/Engine/EngineAssets/Icons/ShaderCompiling.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=Uncompressed \ No newline at end of file diff --git a/Assets/Engine/EngineAssets/Icons/Streaming.tif.exportsettings b/Assets/Engine/EngineAssets/Icons/Streaming.tif.exportsettings deleted file mode 100644 index 8da27c31a4..0000000000 --- a/Assets/Engine/EngineAssets/Icons/Streaming.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=Uncompressed \ No newline at end of file diff --git a/Assets/Engine/EngineAssets/Icons/StreamingTerrain.tif.exportsettings b/Assets/Engine/EngineAssets/Icons/StreamingTerrain.tif.exportsettings deleted file mode 100644 index 8da27c31a4..0000000000 --- a/Assets/Engine/EngineAssets/Icons/StreamingTerrain.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=Uncompressed \ No newline at end of file diff --git a/Assets/Engine/textures/default_icon.png.exportsettings b/Assets/Engine/textures/default_icon.png.exportsettings deleted file mode 100644 index 89ea1ac93f..0000000000 --- a/Assets/Engine/textures/default_icon.png.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /mipmaps=0 /preset=Albedo /reduce=-1 /ser=1 \ No newline at end of file diff --git a/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_diff.tif.exportsettings b/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_diff.tif.exportsettings deleted file mode 100644 index b65133fbb0..0000000000 --- a/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=AlbedoWithGenericAlpha /reduce="android:2,ios:2,mac:0,pc:0,provo:0" \ No newline at end of file diff --git a/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_sss.tif.exportsettings b/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_sss.tif.exportsettings deleted file mode 100644 index e8da408b36..0000000000 --- a/AutomatedTesting/Assets/Objects/Foliage/Textures/grass_atlas_sss.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Albedo /reduce="android:3,ios:3,mac:0,pc:0,provo:0" \ No newline at end of file diff --git a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/C30936451/test_texture_sequence000.png.exportsettings b/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/C30936451/test_texture_sequence000.png.exportsettings deleted file mode 100644 index a8fbf72992..0000000000 --- a/AutomatedTesting/Gem/PythonTests/assetpipeline/asset_processor_tests/assets/C30936451/test_texture_sequence000.png.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Terrain_Albedo_HighPassed /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/Objects/LumberTank/ProxyGray_ddna.tif.exportsettings b/AutomatedTesting/Objects/LumberTank/ProxyGray_ddna.tif.exportsettings deleted file mode 100644 index a4e1a9a3c5..0000000000 --- a/AutomatedTesting/Objects/LumberTank/ProxyGray_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="android:1,ios:1,mac:0,pc:0,provo:0" \ No newline at end of file diff --git a/AutomatedTesting/textures/lights/flare01.tif.exportsettings b/AutomatedTesting/textures/lights/flare01.tif.exportsettings deleted file mode 100644 index 4fee4cfc4b..0000000000 --- a/AutomatedTesting/textures/lights/flare01.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=LensOptics /reduce=-1 \ No newline at end of file diff --git a/AutomatedTesting/textures/milestone2/AMA_Grey_01.tif.exportsettings b/AutomatedTesting/textures/milestone2/AMA_Grey_01.tif.exportsettings deleted file mode 100644 index 2d1dccbf99..0000000000 --- a/AutomatedTesting/textures/milestone2/AMA_Grey_01.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Albedo /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/textures/milestone2/AMA_Grey_02.tif.exportsettings b/AutomatedTesting/textures/milestone2/AMA_Grey_02.tif.exportsettings deleted file mode 100644 index a8fbf72992..0000000000 --- a/AutomatedTesting/textures/milestone2/AMA_Grey_02.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Terrain_Albedo_HighPassed /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/textures/milestone2/AMA_Grey_03.tif.exportsettings b/AutomatedTesting/textures/milestone2/AMA_Grey_03.tif.exportsettings deleted file mode 100644 index a8fbf72992..0000000000 --- a/AutomatedTesting/textures/milestone2/AMA_Grey_03.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Terrain_Albedo_HighPassed /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/textures/milestone2/particles/FX_LauncherMuzzleFront_01.tif.exportsettings b/AutomatedTesting/textures/milestone2/particles/FX_LauncherMuzzleFront_01.tif.exportsettings deleted file mode 100644 index be29bd9bc0..0000000000 --- a/AutomatedTesting/textures/milestone2/particles/FX_LauncherMuzzleFront_01.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=AlbedoWithOpacity /reduce=0 \ No newline at end of file diff --git a/AutomatedTesting/textures/milestone2/particles/FX_LauncherMuzzleRing_01.tif.exportsettings b/AutomatedTesting/textures/milestone2/particles/FX_LauncherMuzzleRing_01.tif.exportsettings deleted file mode 100644 index be29bd9bc0..0000000000 --- a/AutomatedTesting/textures/milestone2/particles/FX_LauncherMuzzleRing_01.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=AlbedoWithOpacity /reduce=0 \ No newline at end of file diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.cpp index 924c01b916..a4ba846f1b 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.cpp @@ -137,25 +137,6 @@ namespace ImageProcessingAtom return nullptr; } - const PresetSettings* BuilderSettingManager::GetPreset(const AZ::Uuid presetId, const PlatformName& platform, AZStd::string_view* settingsFilePathOut) - { - AZStd::lock_guard lock(m_presetMapLock); - - for (const auto& namePreset : m_presets) - { - if (namePreset.second.m_multiPreset.GetPresetId() == presetId) - { - if (settingsFilePathOut) - { - *settingsFilePathOut = namePreset.second.m_presetFilePath; - } - return namePreset.second.m_multiPreset.GetPreset(platform); - } - } - - return nullptr; - } - const BuilderSettings* BuilderSettingManager::GetBuilderSetting(const PlatformName& platform) { if (m_builderSettings.find(platform) != m_builderSettings.end()) @@ -180,26 +161,12 @@ namespace ImageProcessingAtom return platforms; } - const AZStd::map >& BuilderSettingManager::GetPresetFilterMap() + const AZStd::map >& BuilderSettingManager::GetPresetFilterMap() { AZStd::lock_guard lock(m_presetMapLock); return m_presetFilterMap; } - const AZ::Uuid BuilderSettingManager::GetPresetIdFromName(const PresetName& presetName) - { - AZStd::lock_guard lock(m_presetMapLock); - - auto itr = m_presets.find(presetName); - - if (itr != m_presets.end()) - { - return itr->second.m_multiPreset.GetPresetId(); - } - - return AZ::Uuid::CreateNull(); - } - const PresetName BuilderSettingManager::GetPresetNameFromId(const AZ::Uuid& presetId) { AZStd::lock_guard lock(m_presetMapLock); @@ -212,7 +179,7 @@ namespace ImageProcessingAtom } } - return "Unknown"; + return {}; } void BuilderSettingManager::ClearSettings() @@ -296,7 +263,7 @@ namespace ImageProcessingAtom AZ_Warning("Image Processing", presetName == preset.GetPresetName(), "Preset file name '%s' is not" " same as preset name '%s'. Using preset file name as preset name", - filePath.toUtf8().data(), preset.GetPresetName().c_str()); + filePath.toUtf8().data(), preset.GetPresetName().GetCStr()); preset.SetPresetName(presetName); @@ -442,8 +409,20 @@ namespace ImageProcessingAtom return AZStd::string(); } - AZ::Uuid BuilderSettingManager::GetSuggestedPreset(AZStd::string_view imageFilePath, IImageObjectPtr imageFromFile) + bool BuilderSettingManager::IsValidPreset(PresetName presetName) const { + if (presetName.IsEmpty()) + { + return false; + } + + return m_presets.find(presetName) != m_presets.end(); + } + + PresetName BuilderSettingManager::GetSuggestedPreset(AZStd::string_view imageFilePath, IImageObjectPtr imageFromFile) + { + PresetName emptyPreset; + //load the image to get its size for later use IImageObjectPtr image = imageFromFile; //if the input image is empty we will try to load it from the path @@ -454,34 +433,37 @@ namespace ImageProcessingAtom if (image == nullptr) { - return AZ::Uuid::CreateNull(); + return emptyPreset; } //get file mask of this image file AZStd::string fileMask = GetFileMask(imageFilePath); - AZ::Uuid outPreset = AZ::Uuid::CreateNull(); + PresetName outPreset = emptyPreset; //check default presets for some file masks if (m_defaultPresetByFileMask.find(fileMask) != m_defaultPresetByFileMask.end()) { outPreset = m_defaultPresetByFileMask[fileMask]; + if (!IsValidPreset(outPreset)) + { + outPreset = emptyPreset; + } } //use the preset filter map to find - if (outPreset.IsNull() && !fileMask.empty()) + if (outPreset.IsEmpty() && !fileMask.empty()) { auto& presetFilterMap = GetPresetFilterMap(); if (presetFilterMap.find(fileMask) != presetFilterMap.end()) { - AZStd::string presetName = *(presetFilterMap.find(fileMask)->second.begin()); - outPreset = GetPresetIdFromName(presetName); + outPreset = *(presetFilterMap.find(fileMask)->second.begin()); } } const PresetSettings* presetInfo = nullptr; - if (!outPreset.IsNull()) + if (!outPreset.IsEmpty()) { presetInfo = GetPreset(outPreset); @@ -491,12 +473,12 @@ namespace ImageProcessingAtom // If it's not a latitude-longitude map or it doesn't match any cubemap layouts then reset its preset if (!IsValidLatLongMap(image) && CubemapLayout::GetCubemapLayoutInfo(image) == nullptr) { - outPreset = AZ::Uuid::CreateNull(); + outPreset = emptyPreset; } } } - if (outPreset.IsNull()) + if (outPreset == emptyPreset) { if (image->GetAlphaContent() == EAlphaContent::eAlphaContent_Absent) { @@ -521,7 +503,7 @@ namespace ImageProcessingAtom } else { - AZ_Warning("Image Processing", false, "Image dimensions are not compatible with preset '%s'. The default preset will be used.", presetInfo->m_name.c_str()); + AZ_Warning("Image Processing", false, "Image dimensions are not compatible with preset '%s'. The default preset will be used.", presetInfo->m_name.GetCStr()); } } @@ -540,7 +522,7 @@ namespace ImageProcessingAtom for (const auto& element : m_presets) { const PresetEntry& presetEntry = element.second; - AZStd::string fileName = AZStd::string::format("%s.preset", presetEntry.m_multiPreset.GetDefaultPreset().m_name.c_str()); + AZStd::string fileName = AZStd::string::format("%s.preset", presetEntry.m_multiPreset.GetDefaultPreset().m_name.GetCStr()); AZStd::string filePath; if (!AzFramework::StringFunc::Path::Join(outputFolder.data(), fileName.c_str(), filePath)) { @@ -552,7 +534,7 @@ namespace ImageProcessingAtom if (!result.IsSuccess()) { AZ_Warning("Image Processing", false, "Failed to save preset '%s' to file '%s'. Error: %s", - presetEntry.m_multiPreset.GetDefaultPreset().m_name.c_str(), filePath.c_str(), result.GetError().c_str()); + presetEntry.m_multiPreset.GetDefaultPreset().m_name.GetCStr(), filePath.c_str(), result.GetError().c_str()); } } } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.h index b0a7e103be..3bbb71ea43 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/BuilderSettingManager.h @@ -49,7 +49,6 @@ namespace ImageProcessingAtom static void DestroyInstance(); static void Reflect(AZ::ReflectContext* context); - const PresetSettings* GetPreset(const AZ::Uuid presetId, const PlatformName& platform = "", AZStd::string_view* settingsFilePathOut = nullptr); const PresetSettings* GetPreset(const PresetName& presetName, const PlatformName& platform = "", AZStd::string_view* settingsFilePathOut = nullptr); const BuilderSettings* GetBuilderSetting(const PlatformName& platform); @@ -60,10 +59,7 @@ namespace ImageProcessingAtom //! Return A map of preset settings based on their filemasks. //! @key filemask string, empty string means no filemask //! @value set of preset setting names supporting the specified filemask - const AZStd::map>& GetPresetFilterMap(); - - //!Find preset id list based on the preset name. - const AZ::Uuid GetPresetIdFromName(const PresetName& presetName); + const AZStd::map>& GetPresetFilterMap(); //! Find preset name based on the preset id. const PresetName GetPresetNameFromId(const AZ::Uuid& presetId); @@ -84,8 +80,10 @@ namespace ImageProcessingAtom //! Find a suitable preset a given image file. //! @param imageFilePath: Filepath string of the image file. The function may load the image from the path for better detection //! @param image: an optional image object which can be used for preset selection if there is no match based file mask. - //! @return suggested preset uuid. - AZ::Uuid GetSuggestedPreset(AZStd::string_view imageFilePath, IImageObjectPtr image = nullptr); + //! @return suggested preset name. + PresetName GetSuggestedPreset(AZStd::string_view imageFilePath, IImageObjectPtr image = nullptr); + + bool IsValidPreset(PresetName presetName) const; bool DoesSupportPlatform(AZStd::string_view platformId); @@ -131,27 +129,27 @@ namespace ImageProcessingAtom // Builder settings for each platform AZStd::map m_builderSettings; - AZStd::map m_presets; + AZStd::unordered_map m_presets; // Cached list of presets mapped by their file masks. // @Key file mask, use empty string to indicate all presets without filtering // @Value set of preset names that matches the file mask - AZStd::map > m_presetFilterMap; + AZStd::map > m_presetFilterMap; // A mutex to protect when modifying any map in this manager AZStd::recursive_mutex m_presetMapLock; // Default presets for certain file masks - AZStd::map m_defaultPresetByFileMask; + AZStd::map m_defaultPresetByFileMask; // Default preset for none power of two image - AZ::Uuid m_defaultPresetNonePOT; + PresetName m_defaultPresetNonePOT; // Default preset for power of two - AZ::Uuid m_defaultPreset; + PresetName m_defaultPreset; // Default preset for power of two with alpha - AZ::Uuid m_defaultPresetAlpha; + PresetName m_defaultPresetAlpha; // Image builder's version AZStd::string m_analysisFingerprint; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/CubemapSettings.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/CubemapSettings.h index 281075b80c..9135a0f4d1 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/CubemapSettings.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/CubemapSettings.h @@ -43,14 +43,14 @@ namespace ImageProcessingAtom // generate an IBL specular cubemap bool m_generateIBLSpecular = false; - // the UUID of the preset to be used for generating the IBL specular cubemap - AZ::Uuid m_iblSpecularPreset = AZ::Uuid::CreateNull(); + // the name of the preset to be used for generating the IBL specular cubemap + PresetName m_iblSpecularPreset; // generate an IBL diffuse cubemap bool m_generateIBLDiffuse = false; - // the UUID of the preset to be used for generating the IBL diffuse cubemap - AZ::Uuid m_iblDiffusePreset = AZ::Uuid::CreateNull(); + // the name of the preset to be used for generating the IBL diffuse cubemap + PresetName m_iblDiffusePreset; // "cm_requiresconvolve", convolve the cubemap mips bool m_requiresConvolve = true; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/ImageProcessingDefines.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/ImageProcessingDefines.h index d735608db5..e421715995 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/ImageProcessingDefines.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/ImageProcessingDefines.h @@ -8,6 +8,7 @@ #pragma once +#include #include #include #include @@ -38,7 +39,8 @@ namespace ImageProcessingAtom #define STRING_OUTCOME_ERROR(error) AZ::Failure(AZStd::string(error)) // Common typedefs (with dependent forward-declarations) - typedef AZStd::string PlatformName, PresetName, FileMask; + typedef AZStd::string PlatformName, FileMask; + typedef AZ::Name PresetName; typedef AZStd::vector PlatformNameVector; typedef AZStd::list PlatformNameList; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.h index b7ef72753e..941437bbf4 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/PresetSettings.h @@ -31,7 +31,8 @@ namespace ImageProcessingAtom bool operator== (const PresetSettings& other) const; static void Reflect(AZ::ReflectContext* context); - //unique id for the preset + // unique id for the preset + // this uuid will be deprecated. The preset name will be used as an unique id for the preset AZ::Uuid m_uuid = 0; PresetName m_name; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/TextureSettings.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/TextureSettings.cpp index 863b3358c5..29d9b21775 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/TextureSettings.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/TextureSettings.cpp @@ -23,7 +23,7 @@ namespace ImageProcessingAtom const char* TextureSettings::ExtensionName = ".assetinfo"; TextureSettings::TextureSettings() - : m_preset(0) + : m_presetId(0) , m_sizeReduceLevel(0) , m_suppressEngineReduce(false) , m_enableMipmap(true) @@ -45,8 +45,9 @@ namespace ImageProcessingAtom if (serialize) { serialize->Class() - ->Version(1) - ->Field("PresetID", &TextureSettings::m_preset) + ->Version(2) + ->Field("PresetID", &TextureSettings::m_presetId) + ->Field("Preset", &TextureSettings::m_preset) ->Field("SizeReduceLevel", &TextureSettings::m_sizeReduceLevel) ->Field("EngineReduce", &TextureSettings::m_suppressEngineReduce) ->Field("EnableMipmap", &TextureSettings::m_enableMipmap) @@ -169,9 +170,9 @@ namespace ImageProcessingAtom return 0.5f - fVal / 100.0f; } - void TextureSettings::ApplyPreset(AZ::Uuid presetId) + void TextureSettings::ApplyPreset(PresetName presetName) { - const PresetSettings* presetSetting = BuilderSettingManager::Instance()->GetPreset(presetId); + const PresetSettings* presetSetting = BuilderSettingManager::Instance()->GetPreset(presetName); if (presetSetting != nullptr) { m_sizeReduceLevel = presetSetting->m_sizeReduceLevel; @@ -181,11 +182,11 @@ namespace ImageProcessingAtom m_mipGenType = presetSetting->m_mipmapSetting->m_type; } - m_preset = presetId; + m_preset = presetName; } else { - AZ_Error("Image Processing", false, "Cannot set an invalid preset %s!", presetId.ToString().c_str()); + AZ_Error("Image Processing", false, "Cannot set an invalid preset %s!", presetName.GetCStr()); } } @@ -199,6 +200,14 @@ namespace ImageProcessingAtom } textureSettingPtrOut = *loadedTextureSettingPtr; + + // In old format, the preset name doesn't exist. Using preset id to get preset name + // We can remove this when we fully deprecate the preset uuid + if (textureSettingPtrOut.m_preset.IsEmpty()) + { + textureSettingPtrOut.m_preset = BuilderSettingManager::Instance()->GetPresetNameFromId(textureSettingPtrOut.m_presetId); + } + return AZ::Success(AZStd::string()); } @@ -216,7 +225,7 @@ namespace ImageProcessingAtom { MultiplatformTextureSettings settings; PlatformNameList platformsList = BuilderSettingManager::Instance()->GetPlatformList(); - AZ::Uuid suggestedPreset = BuilderSettingManager::Instance()->GetSuggestedPreset(imageFilepath); + PresetName suggestedPreset = BuilderSettingManager::Instance()->GetSuggestedPreset(imageFilepath); for (PlatformName& platform : platformsList) { TextureSettings textureSettings; @@ -234,7 +243,7 @@ namespace ImageProcessingAtom if (overrideIter == baseTextureSettings.m_platfromOverrides.end()) { return STRING_OUTCOME_ERROR(AZStd::string::format("TextureSettings preset [%s] does not have override for platform [%s]", - baseTextureSettings.m_preset.ToString().c_str(), platformName.c_str())); + baseTextureSettings.m_preset.GetCStr(), platformName.c_str())); } AZ::DataPatch& platformOverride = const_cast(overrideIter->second); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/TextureSettings.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/TextureSettings.h index 5bf4fa0d86..24a2f07bfb 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/TextureSettings.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/BuilderSettings/TextureSettings.h @@ -43,7 +43,7 @@ namespace ImageProcessingAtom /** * Apply value of some preset settings to this texture settings */ - void ApplyPreset(AZ::Uuid presetId); + void ApplyPreset(PresetName presetName); /** * Performs a comprehensive comparison between two TextureSettings instances. @@ -116,7 +116,10 @@ namespace ImageProcessingAtom static const size_t s_MaxMipMaps = 6; // uuid of selected preset for this texture - AZ::Uuid m_preset; + // We are deprecating preset UUID and switching to preset name as an unique id + AZ::Uuid m_presetId; + + PresetName m_preset; // texture size reduce level. the value of this variable will override the same variable in PresetSettings unsigned int m_sizeReduceLevel; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/EditorCommon.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/EditorCommon.cpp index c6f1398703..067faf3dab 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/EditorCommon.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/EditorCommon.cpp @@ -165,17 +165,17 @@ namespace ImageProcessingAtomEditor // Get the preset id from one platform. The preset id for each platform should always be same AZ_Assert(m_settingsMap.size() > 0, "There is no platform information"); - AZ::Uuid presetId = m_settingsMap.begin()->second.m_preset; - const PresetSettings* preset = BuilderSettingManager::Instance()->GetPreset(presetId); + PresetName presetName = m_settingsMap.begin()->second.m_preset; + const PresetSettings* preset = BuilderSettingManager::Instance()->GetPreset(presetName); if (!preset) { - AZ_Warning("Texture Editor", false, "Cannot find preset %s! Will assign a suggested one for the texture.", presetId.ToString().c_str()); - presetId = BuilderSettingManager::Instance()->GetSuggestedPreset(m_fullPath, m_img); + AZ_Warning("Texture Editor", false, "Cannot find preset %s! Will assign a suggested one for the texture.", presetName.GetCStr()); + presetName = BuilderSettingManager::Instance()->GetSuggestedPreset(m_fullPath, m_img); for (auto& settingIter : m_settingsMap) { - settingIter.second.ApplyPreset(presetId); + settingIter.second.ApplyPreset(presetName); } } } @@ -198,25 +198,18 @@ namespace ImageProcessingAtomEditor } else { - AZ_Error("Texture Editor", false, "Texture Preset %s is not found!", textureSetting.m_preset.ToString().c_str()); + AZ_Error("Texture Editor", false, "Texture Preset %s is not found!", textureSetting.m_preset.GetCStr()); } } } - void EditorTextureSetting::SetToPreset(const AZStd::string& presetName) + void EditorTextureSetting::SetToPreset(const PresetName& presetName) { m_overrideFromPreset = false; - AZ::Uuid presetId = BuilderSettingManager::Instance()->GetPresetIdFromName(presetName); - if (presetId.IsNull()) - { - AZ_Error("Texture Editor", false, "Texture Preset %s has no associated UUID.", presetName.c_str()); - return; - } - for (auto& settingIter : m_settingsMap) { - settingIter.second.ApplyPreset(presetId); + settingIter.second.ApplyPreset(presetName); } } @@ -305,7 +298,7 @@ namespace ImageProcessingAtomEditor { it.second.m_enableMipmap = false; enabled = false; - AZ_Error("Texture Editor", false, "Preset %s does not support mipmap!", preset->m_name.c_str()); + AZ_Error("Texture Editor", false, "Preset %s does not support mipmap!", preset->m_name.GetCStr()); } } else diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/EditorCommon.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/EditorCommon.h index 24efb7a70a..78bc403906 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/EditorCommon.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/EditorCommon.h @@ -62,7 +62,7 @@ namespace ImageProcessingAtomEditor void SetIsOverrided(); - void SetToPreset(const AZStd::string& presetName); + void SetToPreset(const ImageProcessingAtom::PresetName& presetName); //Get the texture setting on certain platform ImageProcessingAtom::TextureSettings& GetMultiplatformTextureSetting(const AZStd::string& platform = ""); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/PresetInfoPopup.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/PresetInfoPopup.cpp index 2d5c89e8f5..a5b942fa58 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/PresetInfoPopup.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/PresetInfoPopup.cpp @@ -66,7 +66,7 @@ namespace ImageProcessingAtomEditor } presetInfoText += QString("UUID: %1\n").arg(presetSettings->m_uuid.ToString().c_str()); - presetInfoText += QString("Name: %1\n").arg(presetSettings->m_name.c_str()); + presetInfoText += QString("Name: %1\n").arg(presetSettings->m_name.GetCStr()); presetInfoText += QString("Generate IBL Only: %1\n").arg(presetSettings->m_generateIBLOnly ? "True" : "False"); presetInfoText += QString("RGB Weight: %1\n").arg(RGBWeightToString(presetSettings->m_rgbWeight)); presetInfoText += QString("Source ColorSpace: %1\n").arg(ColorSpaceToString(presetSettings->m_srcColorSpace)); @@ -98,9 +98,9 @@ namespace ImageProcessingAtomEditor presetInfoText += QString("Mip Slope: %1\n").arg(presetSettings->m_cubemapSetting->m_mipSlope); presetInfoText += QString("Edge Fixup: %1\n").arg(presetSettings->m_cubemapSetting->m_edgeFixup); presetInfoText += QString("Generate IBL Specular: %1\n").arg(presetSettings->m_cubemapSetting->m_generateIBLSpecular ? "True" : "False"); - presetInfoText += QString("IBL Specular Preset: %1\n").arg(presetSettings->m_cubemapSetting->m_iblSpecularPreset.ToString().c_str()); + presetInfoText += QString("IBL Specular Preset: %1\n").arg(presetSettings->m_cubemapSetting->m_iblSpecularPreset.GetCStr()); presetInfoText += QString("Generate IBL Diffuse: %1\n").arg(presetSettings->m_cubemapSetting->m_generateIBLDiffuse ? "True" : "False"); - presetInfoText += QString("IBL Diffuse Preset: %1\n").arg(presetSettings->m_cubemapSetting->m_iblDiffusePreset.ToString().c_str()); + presetInfoText += QString("IBL Diffuse Preset: %1\n").arg(presetSettings->m_cubemapSetting->m_iblDiffusePreset.GetCStr()); presetInfoText += QString("Requires Convolve: %1\n").arg(presetSettings->m_cubemapSetting->m_requiresConvolve ? "True" : "False"); presetInfoText += QString("SubId: %1\n").arg(presetSettings->m_cubemapSetting->m_subId); } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/ResolutionSettingItemWidget.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/ResolutionSettingItemWidget.cpp index 6df7b8f3df..43f99c4b60 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/ResolutionSettingItemWidget.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/ResolutionSettingItemWidget.cpp @@ -104,7 +104,7 @@ namespace ImageProcessingAtomEditor } } - QString ResolutionSettingItemWidget::GetFinalFormat([[maybe_unused]] const AZ::Uuid& presetId) + QString ResolutionSettingItemWidget::GetFinalFormat([[maybe_unused]] const ImageProcessingAtom::PresetName& preset) { if (m_preset && m_preset->m_pixelFormat >= 0 && m_preset->m_pixelFormat < ePixelFormat_Count) { diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/ResolutionSettingItemWidget.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/ResolutionSettingItemWidget.h index dde3a0e32c..ce66ee1cd9 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/ResolutionSettingItemWidget.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/ResolutionSettingItemWidget.h @@ -60,7 +60,7 @@ namespace ImageProcessingAtomEditor void SetupFormatComboBox(); void SetupResolutionInfo(); void RefreshUI(); - QString GetFinalFormat(const AZ::Uuid& presetId); + QString GetFinalFormat(const ImageProcessingAtom::PresetName& preset); QScopedPointer m_ui; ResoultionWidgetType m_type; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/TexturePresetSelectionWidget.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/TexturePresetSelectionWidget.cpp index 5b34133f96..e50d95b907 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/TexturePresetSelectionWidget.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/TexturePresetSelectionWidget.cpp @@ -29,7 +29,7 @@ namespace ImageProcessingAtomEditor m_presetList.clear(); auto& presetFilterMap = BuilderSettingManager::Instance()->GetPresetFilterMap(); - AZStd::set noFilterPresetList; + AZStd::unordered_set noFilterPresetList; // Check if there is any filtered preset list first for(auto& presetFilter : presetFilterMap) @@ -40,7 +40,7 @@ namespace ImageProcessingAtomEditor } else if (IsMatchingWithFileMask(m_textureSetting->m_textureName, presetFilter.first)) { - for(const AZStd::string& presetName : presetFilter.second) + for(const auto& presetName : presetFilter.second) { m_presetList.insert(presetName); } @@ -52,18 +52,18 @@ namespace ImageProcessingAtomEditor m_presetList = noFilterPresetList; } - foreach (const AZStd::string& presetName, m_presetList) + foreach (const auto& presetName, m_presetList) { - m_ui->presetComboBox->addItem(QString(presetName.c_str())); + m_ui->presetComboBox->addItem(QString(presetName.GetCStr())); } // Set current preset - const AZ::Uuid& currPreset = m_textureSetting->GetMultiplatformTextureSetting().m_preset; + const auto& currPreset = m_textureSetting->GetMultiplatformTextureSetting().m_preset; const PresetSettings* presetSetting = BuilderSettingManager::Instance()->GetPreset(currPreset); if (presetSetting) { - m_ui->presetComboBox->setCurrentText(presetSetting->m_name.c_str()); + m_ui->presetComboBox->setCurrentText(presetSetting->m_name.GetCStr()); QObject::connect(m_ui->presetComboBox, static_cast(&QComboBox::currentIndexChanged), this, &TexturePresetSelectionWidget::OnChangePreset); // Suppress engine reduction checkbox @@ -109,20 +109,20 @@ namespace ImageProcessingAtomEditor void TexturePresetSelectionWidget::OnRestButton() { - m_textureSetting->SetToPreset(AZStd::string(m_ui->presetComboBox->currentText().toUtf8().data())); + m_textureSetting->SetToPreset(PresetName(m_ui->presetComboBox->currentText().toUtf8().data())); EditorInternalNotificationBus::Broadcast(&EditorInternalNotificationBus::Events::OnEditorSettingsChanged, true, BuilderSettingManager::s_defaultPlatform); } void TexturePresetSelectionWidget::OnChangePreset(int index) { QString text = m_ui->presetComboBox->itemText(index); - m_textureSetting->SetToPreset(AZStd::string(text.toUtf8().data())); + m_textureSetting->SetToPreset(PresetName(text.toUtf8().data())); EditorInternalNotificationBus::Broadcast(&EditorInternalNotificationBus::Events::OnEditorSettingsChanged, true, BuilderSettingManager::s_defaultPlatform); } void ImageProcessingAtomEditor::TexturePresetSelectionWidget::OnPresetInfoButton() { - const AZ::Uuid& currPreset = m_textureSetting->GetMultiplatformTextureSetting().m_preset; + const auto& currPreset = m_textureSetting->GetMultiplatformTextureSetting().m_preset; const PresetSettings* presetSetting = BuilderSettingManager::Instance()->GetPreset(currPreset); m_presetPopup.reset(new PresetInfoPopup(presetSetting, this)); m_presetPopup->installEventFilter(this); @@ -136,7 +136,7 @@ namespace ImageProcessingAtomEditor bool oldState = m_ui->serCheckBox->blockSignals(true); m_ui->serCheckBox->setChecked(m_textureSetting->GetMultiplatformTextureSetting().m_suppressEngineReduce); // If the preset's SER is true, texture setting should not override - const AZ::Uuid& currPreset = m_textureSetting->GetMultiplatformTextureSetting().m_preset; + const auto& currPreset = m_textureSetting->GetMultiplatformTextureSetting().m_preset; const PresetSettings* presetSetting = BuilderSettingManager::Instance()->GetPreset(currPreset); if (presetSetting) { diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/TexturePresetSelectionWidget.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/TexturePresetSelectionWidget.h index bbb6e6e7df..ad819840f9 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/TexturePresetSelectionWidget.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Editor/TexturePresetSelectionWidget.h @@ -49,7 +49,7 @@ namespace ImageProcessingAtomEditor private: QScopedPointer m_ui; - AZStd::set m_presetList; + AZStd::unordered_set m_presetList; EditorTextureSetting* m_textureSetting; QScopedPointer m_presetPopup; bool IsMatchingWithFileMask(const AZStd::string& filename, const AZStd::string& fileMask); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp index c688b0b20c..a489c8da5e 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageBuilderComponent.cpp @@ -74,7 +74,7 @@ namespace ImageProcessingAtom builderDescriptor.m_busId = azrtti_typeid(); builderDescriptor.m_createJobFunction = AZStd::bind(&ImageBuilderWorker::CreateJobs, &m_imageBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2); builderDescriptor.m_processJobFunction = AZStd::bind(&ImageBuilderWorker::ProcessJob, &m_imageBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2); - builderDescriptor.m_version = 24; // [SPEC-7821] + builderDescriptor.m_version = 25; // [ATOM-16575] builderDescriptor.m_analysisFingerprint = ImageProcessingAtom::BuilderSettingManager::Instance()->GetAnalysisFingerprint(); m_imageBuilder.BusConnect(builderDescriptor.m_busId); AssetBuilderSDK::AssetBuilderBus::Broadcast(&AssetBuilderSDK::AssetBuilderBusTraits::RegisterBuilderInformation, builderDescriptor); @@ -164,7 +164,7 @@ namespace ImageProcessingAtom AZStd::vector outProducts; AZStd::string_view presetFilePath; - const PresetSettings* preset = BuilderSettingManager::Instance()->GetPreset(presetName, platformName, &presetFilePath); + const PresetSettings* preset = BuilderSettingManager::Instance()->GetPreset(PresetName(presetName), platformName, &presetFilePath); if (preset == nullptr) { AZ_Assert(false, "Cannot find preset with name %s.", presetName.c_str()); @@ -173,7 +173,7 @@ namespace ImageProcessingAtom AZStd::unique_ptr desc = AZStd::make_unique(); TextureSettings& textureSettings = desc->m_textureSetting; - textureSettings.m_preset = preset->m_uuid; + textureSettings.m_preset = preset->m_name; desc->m_inputImage = imageObject; desc->m_presetSetting = *preset; desc->m_isPreview = false; @@ -204,7 +204,7 @@ namespace ImageProcessingAtom bool BuilderPluginComponent::IsPresetFormatSquarePow2(const AZStd::string& presetName, const AZStd::string& platformName) { AZStd::string_view filePath; - const PresetSettings* preset = BuilderSettingManager::Instance()->GetPreset(presetName, platformName, &filePath); + const PresetSettings* preset = BuilderSettingManager::Instance()->GetPreset(PresetName(presetName), platformName, &filePath); if (preset == nullptr) { AZ_Assert(false, "Cannot find preset with name %s.", presetName.c_str()); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp index 5995146c59..977359e4f6 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.cpp @@ -186,12 +186,12 @@ namespace ImageProcessingAtom { // check and generate IBL specular and diffuse, if necessary AZStd::unique_ptr& cubemapSettings = m_input->m_presetSetting.m_cubemapSetting; - if (cubemapSettings->m_generateIBLSpecular && !cubemapSettings->m_iblSpecularPreset.IsNull()) + if (cubemapSettings->m_generateIBLSpecular && !cubemapSettings->m_iblSpecularPreset.IsEmpty()) { CreateIBLCubemap(cubemapSettings->m_iblSpecularPreset, SpecularCubemapSuffix, m_iblSpecularCubemapImage); } - if (cubemapSettings->m_generateIBLDiffuse && !cubemapSettings->m_iblDiffusePreset.IsNull()) + if (cubemapSettings->m_generateIBLDiffuse && !cubemapSettings->m_iblDiffusePreset.IsEmpty()) { CreateIBLCubemap(cubemapSettings->m_iblDiffusePreset, DiffuseCubemapSuffix, m_iblDiffuseCubemapImage); } @@ -367,7 +367,7 @@ namespace ImageProcessingAtom else { AZ_TracePrintf("Image Processing", "Image converted with preset [%s] [%s] and saved to [%s] (%d bytes) taking %f seconds\n", - m_input->m_presetSetting.m_name.c_str(), + m_input->m_presetSetting.m_name.GetCStr(), m_input->m_filePath.c_str(), m_input->m_outputFolder.c_str(), sizeTotal, m_processTime); } @@ -834,7 +834,7 @@ namespace ImageProcessingAtom // if get textureSetting failed, use the default texture setting, and find suitable preset for this file // in very rare user case, an old texture setting file may not have a preset. We fix it over here too. - if (textureSettings.m_preset.IsNull()) + if (textureSettings.m_preset.IsEmpty()) { textureSettings.m_preset = BuilderSettingManager::Instance()->GetSuggestedPreset(imageFilePath, srcImage); } @@ -845,9 +845,7 @@ namespace ImageProcessingAtom if (preset == nullptr) { - AZStd::string uuidStr; - textureSettings.m_preset.ToString(uuidStr); - AZ_Assert(false, "%s cannot find image preset with ID %s.", imageFilePath.c_str(), uuidStr.c_str()); + AZ_Assert(false, "%s cannot find image preset %s.", imageFilePath.c_str(), textureSettings.m_preset.GetCStr()); return nullptr; } @@ -875,11 +873,11 @@ namespace ImageProcessingAtom return process; } - void ImageConvertProcess::CreateIBLCubemap(AZ::Uuid presetUUID, const char* fileNameSuffix, IImageObjectPtr& cubemapImage) + void ImageConvertProcess::CreateIBLCubemap(PresetName preset, const char* fileNameSuffix, IImageObjectPtr& cubemapImage) { const AZStd::string& platformId = m_input->m_platform; AZStd::string_view filePath; - const PresetSettings* presetSettings = BuilderSettingManager::Instance()->GetPreset(presetUUID, platformId, &filePath); + const PresetSettings* presetSettings = BuilderSettingManager::Instance()->GetPreset(preset, platformId, &filePath); if (presetSettings == nullptr) { AZ_Error("Image Processing", false, "Couldn't find preset for IBL cubemap generation"); @@ -900,7 +898,7 @@ namespace ImageProcessingAtom // the diffuse irradiance cubemap is generated with a separate ImageConvertProcess TextureSettings textureSettings = m_input->m_textureSetting; - textureSettings.m_preset = presetUUID; + textureSettings.m_preset = preset; AZStd::unique_ptr desc = AZStd::make_unique(); desc->m_presetSetting = *presetSettings; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.h index 6ab866ee09..eaf05c3280 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageConvert.h @@ -163,7 +163,7 @@ namespace ImageProcessingAtom bool FillCubemapMipmaps(); //IBL cubemap generation, this creates a separate ImageConvertProcess - void CreateIBLCubemap(AZ::Uuid presetUUID, const char* fileNameSuffix, IImageObjectPtr& cubemapImage); + void CreateIBLCubemap(PresetName preset, const char* fileNameSuffix, IImageObjectPtr& cubemapImage); //convert color space to linear with pixel format rgba32f bool ConvertToLinear(); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImagePreview.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImagePreview.cpp index b73157744c..f51741eba9 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImagePreview.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImagePreview.cpp @@ -43,7 +43,7 @@ namespace ImageProcessingAtom m_inputImage = IImageObjectPtr(LoadImageFromFile(m_imageFileName)); } // Get preset if the setting in texture is changed - if (m_presetSetting == nullptr || m_presetSetting->m_uuid != m_textureSetting->m_preset) + if (m_presetSetting == nullptr || m_presetSetting->m_name != m_textureSetting->m_preset) { m_presetSetting = BuilderSettingManager::Instance()->GetPreset(m_textureSetting->m_preset); } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp index 9e4aa83908..3e0bbd89eb 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/ImageProcessing_Test.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -145,6 +146,8 @@ namespace UnitTest AZ::Data::AssetManager::Descriptor desc; AZ::Data::AssetManager::Create(desc); + AZ::NameDictionary::Create(); + m_assetHandlers.emplace_back(AZ::RPI::MakeAssetHandler()); m_assetHandlers.emplace_back(AZ::RPI::MakeAssetHandler()); m_assetHandlers.emplace_back(AZ::RPI::MakeAssetHandler()); @@ -153,6 +156,7 @@ namespace UnitTest //prepare reflection m_context = AZStd::make_unique(); + AZ::Name::Reflect(m_context.get()); BuilderPluginComponent::Reflect(m_context.get()); AZ::DataPatch::Reflect(m_context.get()); AZ::RHI::ReflectSystemComponent::Reflect(m_context.get()); @@ -164,6 +168,7 @@ namespace UnitTest m_jsonRegistrationContext = AZStd::make_unique(); m_jsonSystemComponent = AZStd::make_unique(); m_jsonSystemComponent->Reflect(m_jsonRegistrationContext.get()); + AZ::Name::Reflect(m_jsonRegistrationContext.get()); BuilderPluginComponent::Reflect(m_jsonRegistrationContext.get()); // Setup job context for job system @@ -227,14 +232,18 @@ namespace UnitTest m_jsonRegistrationContext->EnableRemoveReflection(); m_jsonSystemComponent->Reflect(m_jsonRegistrationContext.get()); BuilderPluginComponent::Reflect(m_jsonRegistrationContext.get()); + AZ::Name::Reflect(m_jsonRegistrationContext.get()); m_jsonRegistrationContext->DisableRemoveReflection(); m_jsonRegistrationContext.reset(); m_jsonSystemComponent.reset(); m_context.reset(); BuilderSettingManager::DestroyInstance(); + CPixelFormats::DestroyInstance(); + AZ::NameDictionary::Destroy(); + AZ::Data::AssetManager::Destroy(); AZ::AllocatorInstance::Destroy(); @@ -1027,7 +1036,7 @@ namespace UnitTest // Fill-in structure with test data TextureSettings fakeTextureSettings; - fakeTextureSettings.m_preset = AZ::Uuid::CreateRandom(); + fakeTextureSettings.m_preset = "testPreset"; fakeTextureSettings.m_sizeReduceLevel = 0; fakeTextureSettings.m_suppressEngineReduce = true; fakeTextureSettings.m_enableMipmap = false; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/1024x1024_24bit.tif.exportsettings b/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/1024x1024_24bit.tif.exportsettings deleted file mode 100644 index 7bce3041b9..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Tests/TestAssets/1024x1024_24bit.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /bumptype=none /M=62,18,32,83,50,50 /preset=Diffuse_highQ /mipgentype=kaiser /reduce="android:0,ios:3,mac:0,pc:4,provo:1" /ser=0 diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithOpacity.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithOpacity.preset deleted file mode 100644 index 346f0f8cac..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/AlbedoWithOpacity.preset +++ /dev/null @@ -1,104 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{7BB7BC6C-D3DA-4184-AC42-BCD8C57DE565}", - "Name": "AlbedoWithOpacity", - "RGB_Weight": "CIEXYZ", - "FileMasks": [ - "_diff", - "_color", - "_albedo", - "_alb", - "_basecolor", - "_bc", - "_diffuse" - ], - "PixelFormat": "BC7t", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "PlatformsPresets": { - "android": { - "UUID": "{7BB7BC6C-D3DA-4184-AC42-BCD8C57DE565}", - "Name": "AlbedoWithOpacity", - "RGB_Weight": "CIEXYZ", - "FileMasks": [ - "_diff", - "_color", - "_albedo", - "_alb", - "_basecolor", - "_bc", - "_diffuse" - ], - "PixelFormat": "ASTC_6x6", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "ios": { - "UUID": "{7BB7BC6C-D3DA-4184-AC42-BCD8C57DE565}", - "Name": "AlbedoWithOpacity", - "RGB_Weight": "CIEXYZ", - "FileMasks": [ - "_diff", - "_color", - "_albedo", - "_alb", - "_basecolor", - "_bc", - "_diffuse" - ], - "PixelFormat": "ASTC_6x6", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "mac": { - "UUID": "{7BB7BC6C-D3DA-4184-AC42-BCD8C57DE565}", - "Name": "AlbedoWithOpacity", - "RGB_Weight": "CIEXYZ", - "FileMasks": [ - "_diff", - "_color", - "_albedo", - "_alb", - "_basecolor", - "_bc", - "_diffuse" - ], - "PixelFormat": "BC3", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "provo": { - "UUID": "{7BB7BC6C-D3DA-4184-AC42-BCD8C57DE565}", - "Name": "AlbedoWithOpacity", - "RGB_Weight": "CIEXYZ", - "FileMasks": [ - "_diff", - "_color", - "_albedo", - "_alb", - "_basecolor", - "_bc", - "_diffuse" - ], - "PixelFormat": "BC7t", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/CloudShadows.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/CloudShadows.preset deleted file mode 100644 index 8d1105cdfc..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/CloudShadows.preset +++ /dev/null @@ -1,44 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{884B5F7C-44AC-4E9E-8B8A-559D098BE2C7}", - "Name": "CloudShadows", - "DestColor": "Linear", - "PixelFormat": "BC4", - "IsPowerOf2": true - }, - "PlatformsPresets": { - "android": { - "UUID": "{884B5F7C-44AC-4E9E-8B8A-559D098BE2C7}", - "Name": "CloudShadows", - "DestColor": "Linear", - "PixelFormat": "ASTC_4x4", - "IsPowerOf2": true - }, - "ios": { - "UUID": "{884B5F7C-44AC-4E9E-8B8A-559D098BE2C7}", - "Name": "CloudShadows", - "DestColor": "Linear", - "PixelFormat": "ASTC_4x4", - "IsPowerOf2": true - }, - "mac": { - "UUID": "{884B5F7C-44AC-4E9E-8B8A-559D098BE2C7}", - "Name": "CloudShadows", - "DestColor": "Linear", - "PixelFormat": "BC4", - "IsPowerOf2": true - }, - "provo": { - "UUID": "{884B5F7C-44AC-4E9E-8B8A-559D098BE2C7}", - "Name": "CloudShadows", - "DestColor": "Linear", - "PixelFormat": "BC4", - "IsPowerOf2": true - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/ColorChart.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/ColorChart.preset deleted file mode 100644 index 5f0480cee7..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/ColorChart.preset +++ /dev/null @@ -1,64 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{0A17A85F-07EE-48A0-8BF8-D42F0A5E0B3C}", - "Name": "ColorChart", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_cch" - ], - "PixelFormat": "R8G8B8X8", - "IsColorChart": true - }, - "PlatformsPresets": { - "android": { - "UUID": "{0A17A85F-07EE-48A0-8BF8-D42F0A5E0B3C}", - "Name": "ColorChart", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_cch" - ], - "PixelFormat": "R8G8B8X8", - "IsColorChart": true - }, - "ios": { - "UUID": "{0A17A85F-07EE-48A0-8BF8-D42F0A5E0B3C}", - "Name": "ColorChart", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_cch" - ], - "PixelFormat": "R8G8B8X8", - "IsColorChart": true - }, - "mac": { - "UUID": "{0A17A85F-07EE-48A0-8BF8-D42F0A5E0B3C}", - "Name": "ColorChart", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_cch" - ], - "PixelFormat": "R8G8B8X8", - "IsColorChart": true - }, - "provo": { - "UUID": "{0A17A85F-07EE-48A0-8BF8-D42F0A5E0B3C}", - "Name": "ColorChart", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_cch" - ], - "PixelFormat": "R8G8B8X8", - "IsColorChart": true - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness.preset deleted file mode 100644 index 5bfea9a376..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness.preset +++ /dev/null @@ -1,79 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{5096FC7B-0B2D-4466-9943-AD59922968E8}", - "Name": "Detail_MergedAlbedoNormalsSmoothness", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_detail" - ], - "PixelFormat": "BC7", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "PlatformsPresets": { - "android": { - "UUID": "{5096FC7B-0B2D-4466-9943-AD59922968E8}", - "Name": "Detail_MergedAlbedoNormalsSmoothness", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_detail" - ], - "PixelFormat": "ASTC_4x4", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "ios": { - "UUID": "{5096FC7B-0B2D-4466-9943-AD59922968E8}", - "Name": "Detail_MergedAlbedoNormalsSmoothness", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_detail" - ], - "PixelFormat": "ASTC_4x4", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "mac": { - "UUID": "{5096FC7B-0B2D-4466-9943-AD59922968E8}", - "Name": "Detail_MergedAlbedoNormalsSmoothness", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_detail" - ], - "PixelFormat": "BC3", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "provo": { - "UUID": "{5096FC7B-0B2D-4466-9943-AD59922968E8}", - "Name": "Detail_MergedAlbedoNormalsSmoothness", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_detail" - ], - "PixelFormat": "BC7", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness_Lossless.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness_Lossless.preset deleted file mode 100644 index fec11218e8..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Detail_MergedAlbedoNormalsSmoothness_Lossless.preset +++ /dev/null @@ -1,74 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{B6FC1AEF-907C-4157-9A1A-D9960F0E5B9A}", - "Name": "Detail_MergedAlbedoNormalsSmoothness_Lossless", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_detail" - ], - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "PlatformsPresets": { - "android": { - "UUID": "{B6FC1AEF-907C-4157-9A1A-D9960F0E5B9A}", - "Name": "Detail_MergedAlbedoNormalsSmoothness_Lossless", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_detail" - ], - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "ios": { - "UUID": "{B6FC1AEF-907C-4157-9A1A-D9960F0E5B9A}", - "Name": "Detail_MergedAlbedoNormalsSmoothness_Lossless", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_detail" - ], - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "mac": { - "UUID": "{B6FC1AEF-907C-4157-9A1A-D9960F0E5B9A}", - "Name": "Detail_MergedAlbedoNormalsSmoothness_Lossless", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_detail" - ], - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "provo": { - "UUID": "{B6FC1AEF-907C-4157-9A1A-D9960F0E5B9A}", - "Name": "Detail_MergedAlbedoNormalsSmoothness_Lossless", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_detail" - ], - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLGlobal.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLGlobal.preset index eb829c3120..717157f2aa 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLGlobal.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLGlobal.preset @@ -15,9 +15,9 @@ ], "CubemapSettings": { "GenerateIBLSpecular": true, - "IBLSpecularPreset": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}", + "IBLSpecularPreset": "IBLSpecular", "GenerateIBLDiffuse": true, - "IBLDiffusePreset": "{E3706342-BF21-4D9C-AE28-9670EB3EF3C5}" + "IBLDiffusePreset": "IBLDiffuse" } } } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLSkybox.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLSkybox.preset index 402fc470eb..eee9af4cea 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLSkybox.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/IBLSkybox.preset @@ -20,9 +20,9 @@ "CubemapSettings": { "RequiresConvolve": false, "GenerateIBLSpecular": true, - "IBLSpecularPreset": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}", + "IBLSpecularPreset": "IBLSpecular", "GenerateIBLDiffuse": true, - "IBLDiffusePreset": "{E3706342-BF21-4D9C-AE28-9670EB3EF3C5}" + "IBLDiffusePreset": "IBLDiffuse" } }, "PlatformsPresets": { @@ -42,9 +42,9 @@ "CubemapSettings": { "RequiresConvolve": false, "GenerateIBLSpecular": true, - "IBLSpecularPreset": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}", + "IBLSpecularPreset": "IBLSpecular", "GenerateIBLDiffuse": true, - "IBLDiffusePreset": "{E3706342-BF21-4D9C-AE28-9670EB3EF3C5}" + "IBLDiffusePreset": "IBLDiffuse" } }, "ios": { @@ -63,9 +63,9 @@ "CubemapSettings": { "RequiresConvolve": false, "GenerateIBLSpecular": true, - "IBLSpecularPreset": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}", + "IBLSpecularPreset": "IBLSpecular", "GenerateIBLDiffuse": true, - "IBLDiffusePreset": "{E3706342-BF21-4D9C-AE28-9670EB3EF3C5}" + "IBLDiffusePreset": "IBLDiffuse" } }, "mac": { @@ -84,9 +84,9 @@ "CubemapSettings": { "RequiresConvolve": false, "GenerateIBLSpecular": true, - "IBLSpecularPreset": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}", + "IBLSpecularPreset": "IBLSpecular", "GenerateIBLDiffuse": true, - "IBLDiffusePreset": "{E3706342-BF21-4D9C-AE28-9670EB3EF3C5}" + "IBLDiffusePreset": "IBLDiffuse" } }, "provo": { @@ -105,9 +105,9 @@ "CubemapSettings": { "RequiresConvolve": false, "GenerateIBLSpecular": true, - "IBLSpecularPreset": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}", + "IBLSpecularPreset": "IBLSpecular", "GenerateIBLDiffuse": true, - "IBLDiffusePreset": "{E3706342-BF21-4D9C-AE28-9670EB3EF3C5}" + "IBLDiffusePreset": "IBLDiffuse" } } } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/ImageBuilder.settings b/Gems/Atom/Asset/ImageProcessingAtom/Config/ImageBuilder.settings index c513e05a97..466ac4b71d 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/ImageBuilder.settings +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/ImageBuilder.settings @@ -43,29 +43,25 @@ } }, "DefaultPresetsByFileMask": { - "_basecolor": "{08A95286-ADB2-41E4-96EB-DB48F4726D6A}", - "_cch": "{0A17A85F-07EE-48A0-8BF8-D42F0A5E0B3C}", - "_ccm": "{2174E04B-73BB-4DF1-8961-4900DC3C9D72}", - "_cm": "{A13B2FCE-2F6A-4634-B112-5A0A912B50CE}", - "_ddn": "{508B21D5-5250-4003-97EC-1CF28D571ACF}", - "_ddna": "{6EE749F4-846E-4F7A-878C-F211F85EA59F}", - "_diff": "{08A95286-ADB2-41E4-96EB-DB48F4726D6A}", - "_diffuse": "{08A95286-ADB2-41E4-96EB-DB48F4726D6A}", - "_glossness": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}", - "_ibldiffusecm": "{E3706342-BF21-4D9C-AE28-9670EB3EF3C5}", - "_iblskyboxcm": "{E6441EAC-9843-484B-8EFC-C03B2935B48D}", - "_iblglobalcm": "{A13B2FCE-2F6A-4634-B112-5A0A912B50CE}", - "_iblspecularcm": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}", - "_metallic": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}", - "_normal": "{508B21D5-5250-4003-97EC-1CF28D571ACF}", - "_refl": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}", - "_roughness": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}", - "_skyboxcm": "{F359CD3B-37E6-4627-B4F6-2DFC2C0E3C1C}", - "_spec": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}", - "_specular": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}" + "_basecolor": "Albedo", + "_diff": "Albedo", + "_diffuse": "Albedo", + "_ddn": "Normals", + "_normal": "Normals", + "_ddna": "NormalsWithSmoothness", + "_glossness": "Reflectance", + "_spec": "Reflectance", + "_specular": "Reflectance", + "_metallic": "Reflectance", + "_refl": "Reflectance", + "_roughness": "Reflectance", + "_ibldiffusecm": "IBLDiffuse", + "_iblskyboxcm": "IBLSkybox", + "_iblspecularcm": "IBLSpecular", + "_skyboxcm": "Skybox" }, - "DefaultPreset": "{08A95286-ADB2-41E4-96EB-DB48F4726D6A}", - "DefaultPresetAlpha": "{5D9ECB52-4CD9-4CB8-80E3-10CAE5EFB8A2}", - "DefaultPresetNonePOT": "{C659D222-F56B-4B61-A2F8-C1FA547F3C39}" + "DefaultPreset": "Albedo", + "DefaultPresetAlpha": "AlbedoWithGenericAlpha", + "DefaultPresetNonePOT": "ReferenceImage" } } diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LensOptics.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LensOptics.preset deleted file mode 100644 index d277785151..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/LensOptics.preset +++ /dev/null @@ -1,34 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{3000A993-0A04-4E08-A813-DFB1A47A0980}", - "Name": "LensOptics", - "PixelFormat": "BC1" - }, - "PlatformsPresets": { - "android": { - "UUID": "{3000A993-0A04-4E08-A813-DFB1A47A0980}", - "Name": "LensOptics", - "PixelFormat": "ASTC_4x4" - }, - "ios": { - "UUID": "{3000A993-0A04-4E08-A813-DFB1A47A0980}", - "Name": "LensOptics", - "PixelFormat": "ASTC_4x4" - }, - "mac": { - "UUID": "{3000A993-0A04-4E08-A813-DFB1A47A0980}", - "Name": "LensOptics", - "PixelFormat": "BC1" - }, - "provo": { - "UUID": "{3000A993-0A04-4E08-A813-DFB1A47A0980}", - "Name": "LensOptics", - "PixelFormat": "BC1" - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LightProjector.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LightProjector.preset deleted file mode 100644 index 4de95427d6..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/LightProjector.preset +++ /dev/null @@ -1,59 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{1DFEF41A-D97F-40FB-99D3-C142A3E5225E}", - "Name": "LightProjector", - "DestColor": "Linear", - "PixelFormat": "BC4", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "PlatformsPresets": { - "android": { - "UUID": "{1DFEF41A-D97F-40FB-99D3-C142A3E5225E}", - "Name": "LightProjector", - "DestColor": "Linear", - "PixelFormat": "ASTC_4x4", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "ios": { - "UUID": "{1DFEF41A-D97F-40FB-99D3-C142A3E5225E}", - "Name": "LightProjector", - "DestColor": "Linear", - "PixelFormat": "ASTC_4x4", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "mac": { - "UUID": "{1DFEF41A-D97F-40FB-99D3-C142A3E5225E}", - "Name": "LightProjector", - "DestColor": "Linear", - "PixelFormat": "BC4", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "provo": { - "UUID": "{1DFEF41A-D97F-40FB-99D3-C142A3E5225E}", - "Name": "LightProjector", - "DestColor": "Linear", - "PixelFormat": "BC4", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/LoadingScreen.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/LoadingScreen.preset deleted file mode 100644 index ad0e2ddf06..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/LoadingScreen.preset +++ /dev/null @@ -1,34 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{9ED87726-12AB-4BE0-9397-AD62AE56D9E2}", - "Name": "LoadingScreen", - "PixelFormat": "R8G8B8X8" - }, - "PlatformsPresets": { - "android": { - "UUID": "{9ED87726-12AB-4BE0-9397-AD62AE56D9E2}", - "Name": "LoadingScreen", - "PixelFormat": "R8G8B8X8" - }, - "ios": { - "UUID": "{9ED87726-12AB-4BE0-9397-AD62AE56D9E2}", - "Name": "LoadingScreen", - "PixelFormat": "R8G8B8X8" - }, - "mac": { - "UUID": "{9ED87726-12AB-4BE0-9397-AD62AE56D9E2}", - "Name": "LoadingScreen", - "PixelFormat": "R8G8B8X8" - }, - "provo": { - "UUID": "{9ED87726-12AB-4BE0-9397-AD62AE56D9E2}", - "Name": "LoadingScreen", - "PixelFormat": "R8G8B8X8" - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Minimap.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Minimap.preset deleted file mode 100644 index 79dda1977e..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Minimap.preset +++ /dev/null @@ -1,64 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{0D2F4C31-A665-4862-9C63-9E49A58E9A37}", - "Name": "Minimap", - "SuppressEngineReduce": true, - "PixelFormat": "BC1", - "IsPowerOf2": true, - "SizeReduceLevel": 1, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "PlatformsPresets": { - "android": { - "UUID": "{0D2F4C31-A665-4862-9C63-9E49A58E9A37}", - "Name": "Minimap", - "SuppressEngineReduce": true, - "PixelFormat": "ASTC_6x6", - "IsPowerOf2": true, - "SizeReduceLevel": 1, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "ios": { - "UUID": "{0D2F4C31-A665-4862-9C63-9E49A58E9A37}", - "Name": "Minimap", - "SuppressEngineReduce": true, - "PixelFormat": "ASTC_6x6", - "IsPowerOf2": true, - "SizeReduceLevel": 1, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "mac": { - "UUID": "{0D2F4C31-A665-4862-9C63-9E49A58E9A37}", - "Name": "Minimap", - "SuppressEngineReduce": true, - "PixelFormat": "BC1", - "IsPowerOf2": true, - "SizeReduceLevel": 1, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "provo": { - "UUID": "{0D2F4C31-A665-4862-9C63-9E49A58E9A37}", - "Name": "Minimap", - "SuppressEngineReduce": true, - "PixelFormat": "BC1", - "IsPowerOf2": true, - "SizeReduceLevel": 1, - "MipMapSetting": { - "MipGenType": "Box" - } - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/MuzzleFlash.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/MuzzleFlash.preset deleted file mode 100644 index b02227b454..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/MuzzleFlash.preset +++ /dev/null @@ -1,59 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{8BCC23A5-D08E-458E-B0B3-087C65FA1D31}", - "Name": "MuzzleFlash", - "SuppressEngineReduce": true, - "PixelFormat": "BC1", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "PlatformsPresets": { - "android": { - "UUID": "{8BCC23A5-D08E-458E-B0B3-087C65FA1D31}", - "Name": "MuzzleFlash", - "SuppressEngineReduce": true, - "PixelFormat": "ASTC_6x6", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "ios": { - "UUID": "{8BCC23A5-D08E-458E-B0B3-087C65FA1D31}", - "Name": "MuzzleFlash", - "SuppressEngineReduce": true, - "PixelFormat": "ASTC_6x6", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "mac": { - "UUID": "{8BCC23A5-D08E-458E-B0B3-087C65FA1D31}", - "Name": "MuzzleFlash", - "SuppressEngineReduce": true, - "PixelFormat": "BC1", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "provo": { - "UUID": "{8BCC23A5-D08E-458E-B0B3-087C65FA1D31}", - "Name": "MuzzleFlash", - "SuppressEngineReduce": true, - "PixelFormat": "BC1", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Normals.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Normals.preset index 04307eada4..eee0b88686 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Normals.preset +++ b/Gems/Atom/Asset/ImageProcessingAtom/Config/Normals.preset @@ -11,6 +11,7 @@ "FileMasks": [ "_ddn", "_normal", + "_normalmap", "_normals", "_norm", "_nor", @@ -35,6 +36,7 @@ "FileMasks": [ "_ddn", "_normal", + "_normalmap", "_normals", "_norm", "_nor", @@ -59,6 +61,7 @@ "FileMasks": [ "_ddn", "_normal", + "_normalmap", "_normals", "_norm", "_nor", @@ -83,6 +86,7 @@ "FileMasks": [ "_ddn", "_normal", + "_normalmap", "_normals", "_norm", "_nor", @@ -106,6 +110,7 @@ "FileMasks": [ "_ddn", "_normal", + "_normalmap", "_normals", "_norm", "_nor", diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsFromDisplacement.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsFromDisplacement.preset deleted file mode 100644 index a960ae41b2..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsFromDisplacement.preset +++ /dev/null @@ -1,86 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{8AE5D8D7-ECF8-4B7D-91DE-8F787E3B4210}", - "Name": "NormalsFromDisplacement", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_bump" - ], - "PixelFormat": "BC5s", - "IsPowerOf2": true, - "MipRenormalize": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "PlatformsPresets": { - "android": { - "UUID": "{8AE5D8D7-ECF8-4B7D-91DE-8F787E3B4210}", - "Name": "NormalsFromDisplacement", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_bump" - ], - "PixelFormat": "ASTC_4x4", - "MaxTextureSize": 2048, - "IsPowerOf2": true, - "MipRenormalize": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "ios": { - "UUID": "{8AE5D8D7-ECF8-4B7D-91DE-8F787E3B4210}", - "Name": "NormalsFromDisplacement", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_bump" - ], - "PixelFormat": "ASTC_4x4", - "MaxTextureSize": 2048, - "IsPowerOf2": true, - "MipRenormalize": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "mac": { - "UUID": "{8AE5D8D7-ECF8-4B7D-91DE-8F787E3B4210}", - "Name": "NormalsFromDisplacement", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_bump" - ], - "PixelFormat": "BC5s", - "IsPowerOf2": true, - "MipRenormalize": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "provo": { - "UUID": "{8AE5D8D7-ECF8-4B7D-91DE-8F787E3B4210}", - "Name": "NormalsFromDisplacement", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_bump" - ], - "PixelFormat": "BC5s", - "IsPowerOf2": true, - "MipRenormalize": true, - "MipMapSetting": { - "MipGenType": "Box" - } - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsWithSmoothness_Legacy.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsWithSmoothness_Legacy.preset deleted file mode 100644 index f7cba42886..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/NormalsWithSmoothness_Legacy.preset +++ /dev/null @@ -1,101 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{A92541B8-2E70-4EF1-BA88-1DC1EA2A2341}", - "Name": "NormalsWithSmoothness_Legacy", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_ddna" - ], - "PixelFormat": "BC5s", - "PixelFormatAlpha": "BC4", - "IsPowerOf2": true, - "GlossFromNormal": 1, - "UseLegacyGloss": true, - "MipRenormalize": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "PlatformsPresets": { - "android": { - "UUID": "{A92541B8-2E70-4EF1-BA88-1DC1EA2A2341}", - "Name": "NormalsWithSmoothness_Legacy", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_ddna" - ], - "PixelFormat": "ASTC_4x4", - "PixelFormatAlpha": "ASTC_4x4", - "MaxTextureSize": 2048, - "IsPowerOf2": true, - "GlossFromNormal": 1, - "UseLegacyGloss": true, - "MipRenormalize": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "ios": { - "UUID": "{A92541B8-2E70-4EF1-BA88-1DC1EA2A2341}", - "Name": "NormalsWithSmoothness_Legacy", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_ddna" - ], - "PixelFormat": "ASTC_4x4", - "PixelFormatAlpha": "ASTC_4x4", - "MaxTextureSize": 2048, - "IsPowerOf2": true, - "GlossFromNormal": 1, - "UseLegacyGloss": true, - "MipRenormalize": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "mac": { - "UUID": "{A92541B8-2E70-4EF1-BA88-1DC1EA2A2341}", - "Name": "NormalsWithSmoothness_Legacy", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_ddna" - ], - "PixelFormat": "BC5s", - "PixelFormatAlpha": "BC4", - "IsPowerOf2": true, - "GlossFromNormal": 1, - "UseLegacyGloss": true, - "MipRenormalize": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "provo": { - "UUID": "{A92541B8-2E70-4EF1-BA88-1DC1EA2A2341}", - "Name": "NormalsWithSmoothness_Legacy", - "SourceColor": "Linear", - "DestColor": "Linear", - "FileMasks": [ - "_ddna" - ], - "PixelFormat": "BC5s", - "PixelFormatAlpha": "BC4", - "IsPowerOf2": true, - "GlossFromNormal": 1, - "UseLegacyGloss": true, - "MipRenormalize": true, - "MipMapSetting": { - "MipGenType": "Box" - } - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/ReflectanceWithSmoothness_Legacy.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/ReflectanceWithSmoothness_Legacy.preset deleted file mode 100644 index 7a0c137f07..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/ReflectanceWithSmoothness_Legacy.preset +++ /dev/null @@ -1,71 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{851128B5-7454-42C4-83CE-FCFE071834C5}", - "Name": "ReflectanceWithSmoothness_Legacy", - "FileMasks": [ - "_spec" - ], - "PixelFormat": "BC7", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "PlatformsPresets": { - "android": { - "UUID": "{851128B5-7454-42C4-83CE-FCFE071834C5}", - "Name": "ReflectanceWithSmoothness_Legacy", - "FileMasks": [ - "_spec" - ], - "PixelFormat": "ASTC_4x4", - "MaxTextureSize": 2048, - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "ios": { - "UUID": "{851128B5-7454-42C4-83CE-FCFE071834C5}", - "Name": "ReflectanceWithSmoothness_Legacy", - "FileMasks": [ - "_spec" - ], - "PixelFormat": "ASTC_4x4", - "MaxTextureSize": 2048, - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "mac": { - "UUID": "{851128B5-7454-42C4-83CE-FCFE071834C5}", - "Name": "ReflectanceWithSmoothness_Legacy", - "FileMasks": [ - "_spec" - ], - "PixelFormat": "BC3", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "provo": { - "UUID": "{851128B5-7454-42C4-83CE-FCFE071834C5}", - "Name": "ReflectanceWithSmoothness_Legacy", - "FileMasks": [ - "_spec" - ], - "PixelFormat": "BC7", - "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 deleted file mode 100644 index f59fd594f4..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Reflectance_Linear.preset +++ /dev/null @@ -1,81 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{9B2114F5-118A-4B3A-9CFE-97FA01EC8CFE}", - "Name": "Reflectance_Linear", - "DestColor": "Linear", - "FileMasks": [ - "_spec", - "_refl" - ], - "PixelFormat": "BC1", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "PlatformsPresets": { - "android": { - "UUID": "{9B2114F5-118A-4B3A-9CFE-97FA01EC8CFE}", - "Name": "Reflectance_Linear", - "DestColor": "Linear", - "FileMasks": [ - "_spec", - "_refl" - ], - "PixelFormat": "ASTC_4x4", - "MaxTextureSize": 2048, - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "ios": { - "UUID": "{9B2114F5-118A-4B3A-9CFE-97FA01EC8CFE}", - "Name": "Reflectance_Linear", - "DestColor": "Linear", - "FileMasks": [ - "_spec", - "_refl" - ], - "PixelFormat": "ASTC_4x4", - "MaxTextureSize": 2048, - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "mac": { - "UUID": "{9B2114F5-118A-4B3A-9CFE-97FA01EC8CFE}", - "Name": "Reflectance_Linear", - "DestColor": "Linear", - "FileMasks": [ - "_spec", - "_refl" - ], - "PixelFormat": "BC1", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "provo": { - "UUID": "{9B2114F5-118A-4B3A-9CFE-97FA01EC8CFE}", - "Name": "Reflectance_Linear", - "DestColor": "Linear", - "FileMasks": [ - "_spec", - "_refl" - ], - "PixelFormat": "BC1", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Font.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Font.preset deleted file mode 100644 index f76741148c..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Font.preset +++ /dev/null @@ -1,49 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{F34E3711-5F34-4DBC-8F5D-6340D3989F4B}", - "Name": "SF_Font", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "IsPowerOf2": true - }, - "PlatformsPresets": { - "android": { - "UUID": "{F34E3711-5F34-4DBC-8F5D-6340D3989F4B}", - "Name": "SF_Font", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "IsPowerOf2": true - }, - "ios": { - "UUID": "{F34E3711-5F34-4DBC-8F5D-6340D3989F4B}", - "Name": "SF_Font", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "IsPowerOf2": true - }, - "mac": { - "UUID": "{F34E3711-5F34-4DBC-8F5D-6340D3989F4B}", - "Name": "SF_Font", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "IsPowerOf2": true - }, - "provo": { - "UUID": "{F34E3711-5F34-4DBC-8F5D-6340D3989F4B}", - "Name": "SF_Font", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "IsPowerOf2": true - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Gradient.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Gradient.preset deleted file mode 100644 index aff25dc83d..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Gradient.preset +++ /dev/null @@ -1,49 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{E7F9DF56-DCB0-4683-96EE-F04DA547BE24}", - "Name": "SF_Gradient", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "IsPowerOf2": true - }, - "PlatformsPresets": { - "android": { - "UUID": "{E7F9DF56-DCB0-4683-96EE-F04DA547BE24}", - "Name": "SF_Gradient", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "IsPowerOf2": true - }, - "ios": { - "UUID": "{E7F9DF56-DCB0-4683-96EE-F04DA547BE24}", - "Name": "SF_Gradient", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "IsPowerOf2": true - }, - "mac": { - "UUID": "{E7F9DF56-DCB0-4683-96EE-F04DA547BE24}", - "Name": "SF_Gradient", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "IsPowerOf2": true - }, - "provo": { - "UUID": "{E7F9DF56-DCB0-4683-96EE-F04DA547BE24}", - "Name": "SF_Gradient", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "IsPowerOf2": true - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image.preset deleted file mode 100644 index 191425bb92..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image.preset +++ /dev/null @@ -1,54 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{189A42CB-AEE3-4B80-B276-0FDB0ECA140C}", - "Name": "SF_Image", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "PixelFormat": "BC1", - "IsPowerOf2": true - }, - "PlatformsPresets": { - "android": { - "UUID": "{189A42CB-AEE3-4B80-B276-0FDB0ECA140C}", - "Name": "SF_Image", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "PixelFormat": "ASTC_4x4", - "IsPowerOf2": true - }, - "ios": { - "UUID": "{189A42CB-AEE3-4B80-B276-0FDB0ECA140C}", - "Name": "SF_Image", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "PixelFormat": "ASTC_4x4", - "IsPowerOf2": true - }, - "mac": { - "UUID": "{189A42CB-AEE3-4B80-B276-0FDB0ECA140C}", - "Name": "SF_Image", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "PixelFormat": "BC1", - "IsPowerOf2": true - }, - "provo": { - "UUID": "{189A42CB-AEE3-4B80-B276-0FDB0ECA140C}", - "Name": "SF_Image", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "PixelFormat": "BC1", - "IsPowerOf2": true - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image_nonpower2.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image_nonpower2.preset deleted file mode 100644 index 9b1a9c7c45..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/SF_Image_nonpower2.preset +++ /dev/null @@ -1,49 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{C456B8AB-C360-4822-BCDD-225252D0E697}", - "Name": "SF_Image_nonpower2", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "PixelFormat": "BC1" - }, - "PlatformsPresets": { - "android": { - "UUID": "{C456B8AB-C360-4822-BCDD-225252D0E697}", - "Name": "SF_Image_nonpower2", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "PixelFormat": "ASTC_4x4" - }, - "ios": { - "UUID": "{C456B8AB-C360-4822-BCDD-225252D0E697}", - "Name": "SF_Image_nonpower2", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "PixelFormat": "ASTC_4x4" - }, - "mac": { - "UUID": "{C456B8AB-C360-4822-BCDD-225252D0E697}", - "Name": "SF_Image_nonpower2", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "PixelFormat": "BC1" - }, - "provo": { - "UUID": "{C456B8AB-C360-4822-BCDD-225252D0E697}", - "Name": "SF_Image_nonpower2", - "SourceColor": "Linear", - "DestColor": "Linear", - "SuppressEngineReduce": true, - "PixelFormat": "BC1" - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo.preset deleted file mode 100644 index 8b12a08465..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo.preset +++ /dev/null @@ -1,69 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{88D07159-2FC0-4CBE-82CC-A9DC258C9351}", - "Name": "Terrain_Albedo", - "SourceColor": "Linear", - "DestColor": "Linear", - "PixelFormat": "BC1", - "IsPowerOf2": true, - "HighPassMip": 5, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "PlatformsPresets": { - "android": { - "UUID": "{88D07159-2FC0-4CBE-82CC-A9DC258C9351}", - "Name": "Terrain_Albedo", - "SourceColor": "Linear", - "DestColor": "Linear", - "PixelFormat": "ASTC_6x6", - "IsPowerOf2": true, - "HighPassMip": 5, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "ios": { - "UUID": "{88D07159-2FC0-4CBE-82CC-A9DC258C9351}", - "Name": "Terrain_Albedo", - "SourceColor": "Linear", - "DestColor": "Linear", - "PixelFormat": "ASTC_6x6", - "IsPowerOf2": true, - "HighPassMip": 5, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "mac": { - "UUID": "{88D07159-2FC0-4CBE-82CC-A9DC258C9351}", - "Name": "Terrain_Albedo", - "SourceColor": "Linear", - "DestColor": "Linear", - "PixelFormat": "BC1", - "IsPowerOf2": true, - "HighPassMip": 5, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "provo": { - "UUID": "{88D07159-2FC0-4CBE-82CC-A9DC258C9351}", - "Name": "Terrain_Albedo", - "SourceColor": "Linear", - "DestColor": "Linear", - "PixelFormat": "BC1", - "IsPowerOf2": true, - "HighPassMip": 5, - "MipMapSetting": { - "MipGenType": "Box" - } - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo_HighPassed.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo_HighPassed.preset deleted file mode 100644 index d24531858f..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Terrain_Albedo_HighPassed.preset +++ /dev/null @@ -1,64 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{7827AA52-0A7B-43E7-8CD4-55E0BC513AF1}", - "Name": "Terrain_Albedo_HighPassed", - "SourceColor": "Linear", - "DestColor": "Linear", - "PixelFormat": "BC1", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "PlatformsPresets": { - "android": { - "UUID": "{7827AA52-0A7B-43E7-8CD4-55E0BC513AF1}", - "Name": "Terrain_Albedo_HighPassed", - "SourceColor": "Linear", - "DestColor": "Linear", - "PixelFormat": "ASTC_6x6", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "ios": { - "UUID": "{7827AA52-0A7B-43E7-8CD4-55E0BC513AF1}", - "Name": "Terrain_Albedo_HighPassed", - "SourceColor": "Linear", - "DestColor": "Linear", - "PixelFormat": "ASTC_6x6", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "mac": { - "UUID": "{7827AA52-0A7B-43E7-8CD4-55E0BC513AF1}", - "Name": "Terrain_Albedo_HighPassed", - "SourceColor": "Linear", - "DestColor": "Linear", - "PixelFormat": "BC1", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "provo": { - "UUID": "{7827AA52-0A7B-43E7-8CD4-55E0BC513AF1}", - "Name": "Terrain_Albedo_HighPassed", - "SourceColor": "Linear", - "DestColor": "Linear", - "PixelFormat": "BC1", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - } - } - } -} diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Config/Uncompressed.preset b/Gems/Atom/Asset/ImageProcessingAtom/Config/Uncompressed.preset deleted file mode 100644 index 6e28cafe11..0000000000 --- a/Gems/Atom/Asset/ImageProcessingAtom/Config/Uncompressed.preset +++ /dev/null @@ -1,54 +0,0 @@ -{ - "Type": "JsonSerialization", - "Version": 1, - "ClassName": "MultiplatformPresetSettings", - "ClassData": { - "DefaultPreset": { - "UUID": "{E996A696-991C-4FFC-B270-F5AD408B0618}", - "Name": "Uncompressed", - "PixelFormat": "R8G8B8X8", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "PlatformsPresets": { - "android": { - "UUID": "{E996A696-991C-4FFC-B270-F5AD408B0618}", - "Name": "Uncompressed", - "PixelFormat": "R8G8B8X8", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "ios": { - "UUID": "{E996A696-991C-4FFC-B270-F5AD408B0618}", - "Name": "Uncompressed", - "PixelFormat": "R8G8B8X8", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "mac": { - "UUID": "{E996A696-991C-4FFC-B270-F5AD408B0618}", - "Name": "Uncompressed", - "PixelFormat": "R8G8B8X8", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - }, - "provo": { - "UUID": "{E996A696-991C-4FFC-B270-F5AD408B0618}", - "Name": "Uncompressed", - "PixelFormat": "R8G8B8X8", - "IsPowerOf2": true, - "MipMapSetting": { - "MipGenType": "Box" - } - } - } - } -} diff --git a/Gems/NvCloth/Assets/Objects/cloth/Chicken/Actor/chicken_diff.png.imagesettings b/Gems/NvCloth/Assets/Objects/cloth/Chicken/Actor/chicken_diff.png.imagesettings deleted file mode 100644 index adbf7d20f9..0000000000 --- a/Gems/NvCloth/Assets/Objects/cloth/Chicken/Actor/chicken_diff.png.imagesettings +++ /dev/null @@ -1,65 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Gems/PhysXSamples/Assets/Characters/Cowboy/Actor/Textures/Cowboy_01_ddna.tif.imagesettings b/Gems/PhysXSamples/Assets/Characters/Cowboy/Actor/Textures/Cowboy_01_ddna.tif.imagesettings deleted file mode 100644 index 9da169c456..0000000000 --- a/Gems/PhysXSamples/Assets/Characters/Cowboy/Actor/Textures/Cowboy_01_ddna.tif.imagesettings +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Gems/PhysXSamples/Assets/Characters/Cowboy/Actor/Textures/Cowboy_01_spec.tif.imagesettings b/Gems/PhysXSamples/Assets/Characters/Cowboy/Actor/Textures/Cowboy_01_spec.tif.imagesettings deleted file mode 100644 index 43410a50df..0000000000 --- a/Gems/PhysXSamples/Assets/Characters/Cowboy/Actor/Textures/Cowboy_01_spec.tif.imagesettings +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_a_pressed.tif.exportsettings b/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_a_pressed.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_a_pressed.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_a_unpressed.tif.exportsettings b/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_a_unpressed.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_a_unpressed.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_b_pressed.tif.exportsettings b/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_b_pressed.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_b_pressed.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_b_unpressed.tif.exportsettings b/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_b_unpressed.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_b_unpressed.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_x_pressed.tif.exportsettings b/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_x_pressed.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_x_pressed.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_x_unpressed.tif.exportsettings b/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_x_unpressed.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_x_unpressed.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_y_pressed.tif.exportsettings b/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_y_pressed.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_y_pressed.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_y_unpressed.tif.exportsettings b/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_y_unpressed.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_button_y_unpressed.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_thumbstick_centre.tif.exportsettings b/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_thumbstick_centre.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_thumbstick_centre.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 diff --git a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_thumbstick_radial.tif.exportsettings b/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_thumbstick_radial.tif.exportsettings deleted file mode 100644 index 1415bea891..0000000000 --- a/Gems/VirtualGamepad/Assets/UI/Textures/VirtualGamepad/virtual_gamepad_thumbstick_radial.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /dns=1 /preset=ReferenceImage_Linear /reduce=0 /ser=0 From 9dee92a7089a53e057e9a5c26700368dd6b6f479 Mon Sep 17 00:00:00 2001 From: smurly Date: Mon, 11 Oct 2021 16:09:11 -0700 Subject: [PATCH 110/169] Mateiral component P0 tests editor script (#4585) Signed-off-by: Scott Murray --- .../Atom/TestSuite_Main_Optimized.py | 4 + ...ydra_AtomEditorComponents_MaterialAdded.py | 205 ++++++++++++++++++ 2 files changed, 209 insertions(+) create mode 100644 AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_MaterialAdded.py diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py index 90436fbe27..ec3d76758c 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py @@ -59,5 +59,9 @@ class TestAutomation(EditorTestSuite): class AtomEditorComponents_MeshAdded(EditorSharedTest): from Atom.tests import hydra_AtomEditorComponents_MeshAdded as test_module + @pytest.mark.test_case_id("C32078123") + class AtomEditorComponents_MaterialAdded(EditorSharedTest): + from Atom.tests import hydra_AtomEditorComponents_MaterialAdded as test_module + class ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges(EditorSharedTest): from Atom.tests import hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges as test_module diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_MaterialAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_MaterialAdded.py new file mode 100644 index 0000000000..32cd5471f2 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_MaterialAdded.py @@ -0,0 +1,205 @@ +""" +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 +""" + +class Tests: + creation_undo = ( + "UNDO Entity creation success", + "UNDO Entity creation failed") + creation_redo = ( + "REDO Entity creation success", + "REDO Entity creation failed") + material_creation = ( + "Material Entity successfully created", + "Material Entity failed to be created") + material_component = ( + "Entity has a Material component", + "Entity failed to find Material component") + material_disabled = ( + "Material component disabled", + "Material component was not disabled.") + actor_component = ( + "Entity has an Actor component", + "Entity did not have an Actor component") + actor_undo = ( + "Entity Actor component gone", + "Entity Actor component add failed to undo") + mesh_component = ( + "Entity has a Mesh component", + "Entity did not have a Mesh component") + material_enabled = ( + "Material component enabled", + "Material component was not enabled.") + enter_game_mode = ( + "Entered game mode", + "Failed to enter game mode") + exit_game_mode = ( + "Exited game mode", + "Couldn't exit game mode") + is_visible = ( + "Entity is visible", + "Entity was not visible") + is_hidden = ( + "Entity is hidden", + "Entity was not hidden") + entity_deleted = ( + "Entity deleted", + "Entity was not deleted") + deletion_undo = ( + "UNDO deletion success", + "UNDO deletion failed") + deletion_redo = ( + "REDO deletion success", + "REDO deletion failed") + + +def AtomEditorComponents_Material_AddedToEntity(): + """ + Summary: + Tests the Material component can be added to an entity and has the expected functionality. + + Test setup: + - Wait for Editor idle loop. + - Open the "Base" level. + + Expected Behavior: + The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components. + Creation and deletion undo/redo should also work. + + Test Steps: + 1) Create a Material entity with no components. + 2) Add a Material component to Material entity. + 3) UNDO the entity creation and component addition. + 4) REDO the entity creation and component addition. + 5) Verify Material component not enabled. + 6) Add Actor component since it is required by the Material component. + 7) Verify Material component is enabled. + 8) UNDO add Actor component + 9) Verify Material component not enabled. + 10) Add Mesh component since it is required by the Material component. + 11) Verify Material component is enabled. + 12) Enter/Exit game mode. + 13) Test IsHidden. + 14) Test IsVisible. + 15) Delete Material entity. + 16) UNDO deletion. + 17) REDO deletion. + 18) Look for errors. + + :return: None + """ + + import azlmbr.legacy.general as general + + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report, Tracer, TestHelper + + with Tracer() as error_tracer: + # Test setup begins. + # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level. + TestHelper.init_idle() + TestHelper.open_level("", "Base") + + # Test steps begin. + # 1. Create a Material entity with no components. + material_name = "Material" + material_entity = EditorEntity.create_editor_entity(material_name) + Report.critical_result(Tests.material_creation, material_entity.exists()) + + # 2. Add a Material component to Material entity. + material_component = material_entity.add_component(material_name) + Report.critical_result( + Tests.material_component, + material_entity.has_component(material_name)) + + # 3. UNDO the entity creation and component addition. + # -> UNDO component addition. + general.undo() + # -> UNDO naming entity. + general.undo() + # -> UNDO selecting entity. + general.undo() + # -> UNDO entity creation. + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.creation_undo, not material_entity.exists()) + + # 4. REDO the entity creation and component addition. + # -> REDO entity creation. + general.redo() + # -> REDO selecting entity. + general.redo() + # -> REDO naming entity. + general.redo() + # -> REDO component addition. + general.redo() + general.idle_wait_frames(1) + Report.result(Tests.creation_redo, material_entity.exists()) + + # 5. Verify Material component not enabled. + Report.result(Tests.material_disabled, not material_component.is_enabled()) + + # 6. Add Actor component since it is required by the Material component. + actor_name = "Actor" + material_entity.add_component(actor_name) + Report.result(Tests.actor_component, material_entity.has_component(actor_name)) + + # 7. Verify Material component is enabled. + Report.result(Tests.material_enabled, material_component.is_enabled()) + + # 8. UNDO component addition. + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.actor_undo, not material_entity.has_component(actor_name)) + + # 9. Verify Material component not enabled. + Report.result(Tests.material_disabled, not material_component.is_enabled()) + + # 10. Add Mesh component since it is required by the Material component. + mesh_name = "Mesh" + material_entity.add_component(mesh_name) + Report.result(Tests.mesh_component, material_entity.has_component(mesh_name)) + + # 11. Verify Material component is enabled. + Report.result(Tests.material_enabled, material_component.is_enabled()) + + # 12. Enter/Exit game mode. + TestHelper.enter_game_mode(Tests.enter_game_mode) + general.idle_wait_frames(1) + TestHelper.exit_game_mode(Tests.exit_game_mode) + + # 13. Test IsHidden. + material_entity.set_visibility_state(False) + Report.result(Tests.is_hidden, material_entity.is_hidden() is True) + + # 14. Test IsVisible. + material_entity.set_visibility_state(True) + general.idle_wait_frames(1) + Report.result(Tests.is_visible, material_entity.is_visible() is True) + + # 15. Delete Material entity. + material_entity.delete() + Report.result(Tests.entity_deleted, not material_entity.exists()) + + # 16. UNDO deletion. + general.undo() + Report.result(Tests.deletion_undo, material_entity.exists()) + + # 17. REDO deletion. + general.redo() + Report.result(Tests.deletion_redo, not material_entity.exists()) + + # 18. Look for errors or asserts. + TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0) + for error_info in error_tracer.errors: + Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}") + for assert_info in error_tracer.asserts: + Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}") + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(AtomEditorComponents_Material_AddedToEntity) From 02d8596d875614316a720820e12db38e02661cfe Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Mon, 11 Oct 2021 20:24:41 -0700 Subject: [PATCH 111/169] chore: improject documentation for IntersectSegment - change return of IntersectRayDisk to bool - change return of IntersectRayBox to bool - move [out] after @param Signed-off-by: Michael Pollind --- .../AzCore/AzCore/Math/IntersectSegment.cpp | 31 ++- .../AzCore/AzCore/Math/IntersectSegment.h | 217 +++++++++--------- 2 files changed, 124 insertions(+), 124 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.cpp b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.cpp index 2a00412689..1bf1e41cb7 100644 --- a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.cpp +++ b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.cpp @@ -352,9 +352,6 @@ AZ::Intersect::IntersectRayAABB( return ISECT_RAY_AABB_ISECT; } - - - //========================================================================= // IntersectRayAABB2 // [2/18/2011] @@ -411,7 +408,7 @@ AZ::Intersect::IntersectRayAABB2(const Vector3& rayStart, const Vector3& dirRCP, return ISECT_RAY_AABB_ISECT; } -int AZ::Intersect::IntersectRayDisk( +bool AZ::Intersect::IntersectRayDisk( const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& diskCenter, const float diskRadius, const Vector3& diskNormal, float& t) { // First intersect with the plane of the disk @@ -424,10 +421,10 @@ int AZ::Intersect::IntersectRayDisk( if (pointOnPlane.GetDistance(diskCenter) < diskRadius) { t = planeIntersectionDistance; - return 1; + return true; } } - return 0; + return false; } // Reference: Real-Time Collision Detection - 5.3.7 Intersecting Ray or Segment Against Cylinder, and the book's errata. @@ -1015,7 +1012,7 @@ int AZ::Intersect::IntersectRayQuad( } // reference: Real-Time Collision Detection, 5.3.3 Intersecting Ray or Segment Against Box -int AZ::Intersect::IntersectRayBox( +bool AZ::Intersect::IntersectRayBox( const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& boxCenter, const Vector3& boxAxis1, const Vector3& boxAxis2, const Vector3& boxAxis3, float boxHalfExtent1, float boxHalfExtent2, float boxHalfExtent3, float& t) { @@ -1047,7 +1044,7 @@ int AZ::Intersect::IntersectRayBox( // If the ray is parallel to the slab and the ray origin is outside, return no intersection. if (tp < 0.0f || tn < 0.0f) { - return 0; + return false; } } else @@ -1068,7 +1065,7 @@ int AZ::Intersect::IntersectRayBox( tmax = AZ::GetMin(tmax, t2); if (tmin > tmax) { - return 0; + return false; } } @@ -1088,7 +1085,7 @@ int AZ::Intersect::IntersectRayBox( // If the ray is parallel to the slab and the ray origin is outside, return no intersection. if (tp < 0.0f || tn < 0.0f) { - return 0; + return false; } } else @@ -1109,7 +1106,7 @@ int AZ::Intersect::IntersectRayBox( tmax = AZ::GetMin(tmax, t2); if (tmin > tmax) { - return 0; + return false; } } @@ -1129,7 +1126,7 @@ int AZ::Intersect::IntersectRayBox( // If the ray is parallel to the slab and the ray origin is outside, return no intersection. if (tp < 0.0f || tn < 0.0f) { - return 0; + return false; } } else @@ -1150,15 +1147,15 @@ int AZ::Intersect::IntersectRayBox( tmax = AZ::GetMin(tmax, t2); if (tmin > tmax) { - return 0; + return false; } } t = (isRayOriginInsideBox ? tmax : tmin); - return 1; + return true; } -int AZ::Intersect::IntersectRayObb(const Vector3& rayOrigin, const Vector3& rayDir, const Obb& obb, float& t) +bool AZ::Intersect::IntersectRayObb(const Vector3& rayOrigin, const Vector3& rayDir, const Obb& obb, float& t) { return AZ::Intersect::IntersectRayBox(rayOrigin, rayDir, obb.GetPosition(), obb.GetAxisX(), obb.GetAxisY(), obb.GetAxisZ(), @@ -1366,11 +1363,11 @@ AZ::Intersect::IntersectSegmentCapsule(const Vector3& sa, const Vector3& dir, co //========================================================================= bool AZ::Intersect::IntersectSegmentPolyhedron( - const Vector3& sa, const Vector3& sBA, const Plane p[], int numPlanes, + const Vector3& sa, const Vector3& dir, const Plane p[], int numPlanes, float& tfirst, float& tlast, int& iFirstPlane, int& iLastPlane) { // Compute direction vector for the segment - Vector3 d = /*b - a*/ sBA; + Vector3 d = /*b - a*/ dir; // Set initial interval to being the whole segment. For a ray, tlast should be // set to +RR_FLT_MAX. For a line, additionally tfirst should be set to -RR_FLT_MAX tfirst = 0.0f; diff --git a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h index ecb0d7acc9..71c39fb53d 100644 --- a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h +++ b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h @@ -28,15 +28,14 @@ namespace AZ //! LineToPointDistance computes the closest point to 'p' from a segment (s1,s2). //! @param s1 segment start point //! @param s2 segment end point - //! @param p point to find the closest time to. - //! @param u time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)] + //! @param p point to find the closest time to. + //! @param u time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)] //! @return the closest point Vector3 LineToPointDistance(const Vector3& s1, const Vector3& s2, const Vector3& p, float& u); //! Given segment pq and triangle abc (CCW), returns whether segment intersects //! triangle and if so, also returns the barycentric coordinates (u,v,w) //! of the intersection point. - //! //! @param p segment start point //! @param q segment end point //! @param a triangle point 1 @@ -49,7 +48,7 @@ namespace AZ const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c, Vector3& normal, float& t); //! Same as \ref IntersectSegmentTriangleCCW without respecting the triangle (a,b,c) vertex order (double sided). - //! //! @param p segment start point + //! @param p segment start point //! @param q segment end point //! @param a triangle point 1 //! @param b triangle point 2 @@ -86,41 +85,38 @@ namespace AZ const Aabb& aabb, float& tStart, float& tEnd, - Vector3& startNormal /*, Vector3& inter*/); + Vector3& startNormal); //! Intersect ray against AABB. - //! //! @param rayStart ray starting point. //! @param dir ray reciprocal direction. //! @param aabb Axis aligned bounding box to intersect against. //! @param start length on ray of the first intersection. //! @param end length of the of the second intersection. - //! @return \ref RayAABBIsectTypes In this faster version than IntersectRayAABB we return only ISECT_RAY_AABB_NONE and ISECT_RAY_AABB_ISECT. You can check yourself for that case. + //! @return \ref RayAABBIsectTypes In this faster version than IntersectRayAABB we return only ISECT_RAY_AABB_NONE and + //! ISECT_RAY_AABB_ISECT. You can check yourself for that case. RayAABBIsectTypes IntersectRayAABB2(const Vector3& rayStart, const Vector3& dirRCP, const Aabb& aabb, float& start, float& end); //! Clip a ray to an aabb. return true if ray was clipped. The ray //! can be inside so don't use the result if the ray intersect the box. - //! //! @param aabb bounds //! @param rayStart the start of the ray //! @param rayEnd the end of the ray - //! @param tClipStart[out] The proportion where the ray enterts the aabb - //! @param tClipEnd[out] The proportion where the ray exits the aabb + //! @param[out] tClipStart The proportion where the ray enterts the aabb + //! @param[out] tClipEnd The proportion where the ray exits the aabb //! @return true ray was clipped else false bool ClipRayWithAabb(const Aabb& aabb, Vector3& rayStart, Vector3& rayEnd, float& tClipStart, float& tClipEnd); //! Test segment and aabb where the segment is defined by midpoint //! midPoint = (p1-p0) * 0.5f and half vector halfVector = p1 - midPoint. //! the aabb is at the origin and defined by half extents only. - //! //! @param midPoint midpoint of a line segment //! @param halfVector half vector of an aabb //! @param aabbExtends the extends of a bounded box - //! @return 1 if the intersect, otherwise 0. + //! @return true if the intersect, otherwise false. bool TestSegmentAABBOrigin(const Vector3& midPoint, const Vector3& halfVector, const Vector3& aabbExtends); //! Test if segment specified by points p0 and p1 intersects AABB. \ref TestSegmentAABBOrigin - //! //! @param p0 point 1 //! @param p1 point 2 //! @param aabb bounded box @@ -130,9 +126,9 @@ namespace AZ //! Ray sphere intersection result types. enum SphereIsectTypes : AZ::s32 { - ISECT_RAY_SPHERE_SA_INSIDE = -1, // the ray starts inside the cylinder - ISECT_RAY_SPHERE_NONE, // no intersection - ISECT_RAY_SPHERE_ISECT, // along the PQ segment + ISECT_RAY_SPHERE_SA_INSIDE = -1, //!< the ray starts inside the cylinder + ISECT_RAY_SPHERE_NONE, //!< no intersection + ISECT_RAY_SPHERE_ISECT, //!< along the PQ segment }; //! IntersectRaySphereOrigin @@ -147,25 +143,26 @@ namespace AZ const Vector3& rayStart, const Vector3& rayDirNormalized, const float sphereRadius, float& t); //! Intersect ray (rayStart,rayDirNormalized) and sphere (sphereCenter,sphereRadius) \ref IntersectRaySphereOrigin - //! - //! @param rayStart - //! @param rayDirNormalized - //! @param sphereCenter - //! @param sphereRadius - //! @param t - //! @return SphereIsectTypes + //! @param rayStart the start of the ray + //! @param rayDirNormalized the direction of the ray normalized + //! @param sphereCenter the center of the sphere + //! @param sphereRadius radius of the sphere + //! @param[out] t coefficient in the ray's explicit equation from which an + //! intersecting point is calculated as "rayOrigin + t1 * rayDir". + //! @return SphereIsectTypes SphereIsectTypes IntersectRaySphere( const Vector3& rayStart, const Vector3& rayDirNormalized, const Vector3& sphereCenter, const float sphereRadius, float& t); - //! @param rayOrigin The origin of the ray to test. - //! @param rayDir The direction of the ray to test. It has to be unit length. - //! @param diskCenter Center point of the disk - //! @param diskRadius Radius of the disk - //! @param diskNormal A normal perpendicular to the disk - //! @param[out] t If returning 1 (indicating a hit), this contains distance from rayOrigin along the normalized rayDir + //! Intersect ray (rayStarty, rayDirNormalized) and disk (center, radius, normal) + //! @param rayOrigin The origin of the ray to test. + //! @param rayDir The direction of the ray to test. It has to be unit length. + //! @param diskCenter Center point of the disk + //! @param diskRadius Radius of the disk + //! @param diskNormal A normal perpendicular to the disk + //! @param[out] t If returning 1 (indicating a hit), this contains distance from rayOrigin along the normalized rayDir //! that the hit occured at. - //! @return The number of intersecting points. - int IntersectRayDisk( + //! @return false if not interesecting and true if intersecting + bool IntersectRayDisk( const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& diskCenter, @@ -174,17 +171,14 @@ namespace AZ float& t); //! If there is only one intersecting point, the coefficient is stored in \ref t1. - //! @param rayOrigin The origin of the ray to test. - //! @param rayDir The direction of the ray to test. It has to be unit length. - //! @param cylinderEnd1 The center of the circle on one end of the cylinder. - //! @param cylinderDir The direction pointing from \ref cylinderEnd1 to the other end of the cylinder. It has to be unit - //! length. - //! @param cylinderHeight The distance between two centers of the circles on two ends of the cylinder respectively. - //! @param[out] t1 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated - //! as "rayOrigin + t1 * rayDir". - //! @param[out] t2 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated - //! as "rayOrigin + t2 * rayDir". - //! @return The number of intersecting points. + //! @param rayOrigin The origin of the ray to test. + //! @param rayDir The direction of the ray to test. It has to be unit length. + //! @param cylinderEnd1 The center of the circle on one end of the cylinder. + //! @param cylinderDir The direction pointing from \ref cylinderEnd1 to the other end of the cylinder. It has to be unit length. + //! @param cylinderHeight The distance between two centers of the circles on two ends of the cylinder respectively. + //! @param[out] t1 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated as "rayOrigin + t1 * rayDir". + //! @param[out] t2 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated as "rayOrigin + t2 * rayDir". + //! @return The number of intersecting points. int IntersectRayCappedCylinder( const Vector3& rayOrigin, const Vector3& rayDir, @@ -196,17 +190,15 @@ namespace AZ float& t2); //! If there is only one intersecting point, the coefficient is stored in \ref t1. - //! @param rayOrigin The origin of the ray to test. - //! @param rayDir The direction of the ray to test. It has to be unit length. - //! @param coneApex The apex of the cone. - //! @param coneDir The unit-length direction from the apex to the base. - //! @param coneHeight The height of the cone, from the apex to the base. - //! @param coneBaseRadius The radius of the cone base circle. - //! @param[out] t1 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated - //! as "rayOrigin + t1 * rayDir". - //! @param[out] t2 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated - //! as "rayOrigin + t2 * rayDir". - //! @return The number of intersecting points. + //! @param rayOrigin The origin of the ray to test. + //! @param rayDir The direction of the ray to test. It has to be unit length. + //! @param coneApex The apex of the cone. + //! @param coneDir The unit-length direction from the apex to the base. + //! @param coneHeight The height of the cone, from the apex to the base. + //! @param coneBaseRadius The radius of the cone base circle. + //! @param[out] t1 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated as "rayOrigin + t1 * rayDir". + //! @param[out] t2 A possible coefficient in the ray's explicit equation from which an intersecting point is calculated as "rayOrigin + t2 * rayDir". + //! @return The number of intersecting points. int IntersectRayCone( const Vector3& rayOrigin, const Vector3& rayDir, @@ -218,11 +210,11 @@ namespace AZ float& t2); //! Test intersection between a ray and a plane in 3D. - //! @param rayOrigin The origin of the ray to test intersection with. - //! @param rayDir The direction of the ray to test intersection with. - //! @param planePos A point on the plane to test intersection with. - //! @param planeNormal The normal of the plane to test intersection with. - //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection". + //! @param rayOrigin The origin of the ray to test intersection with. + //! @param rayDir The direction of the ray to test intersection with. + //! @param planePos A point on the plane to test intersection with. + //! @param planeNormal The normal of the plane to test intersection with. + //! @param[out] t The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection". //! @return The number of intersection point. int IntersectRayPlane( const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& planePos, const Vector3& planeNormal, float& t); @@ -230,13 +222,14 @@ namespace AZ //! Test intersection between a ray and a two-sided quadrilateral defined by four points in 3D. //! The four points that define the quadrilateral could be passed in with either counter clock-wise //! winding or clock-wise winding. - //! @param rayOrigin The origin of the ray to test intersection with. - //! @param rayDir The direction of the ray to test intersection with. - //! @param vertexA One of the four points that define the quadrilateral. - //! @param vertexB One of the four points that define the quadrilateral. - //! @param vertexC One of the four points that define the quadrilateral. - //! @param vertexD One of the four points that define the quadrilateral. - //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection". + //! @param rayOrigin The origin of the ray to test intersection with. + //! @param rayDir The direction of the ray to test intersection with. + //! @param vertexA One of the four points that define the quadrilateral. + //! @param vertexB One of the four points that define the quadrilateral. + //! @param vertexC One of the four points that define the quadrilateral. + //! @param vertexD One of the four points that define the quadrilateral. + //! @param[out] t The coefficient in the ray's explicit equation from which the + //! intersecting point is calculated as "rayOrigin + t * rayDirection". //! @return The number of intersection point. int IntersectRayQuad( const Vector3& rayOrigin, @@ -248,19 +241,18 @@ namespace AZ float& t); //! Test intersection between a ray and an oriented box in 3D. - //! - //! @param rayOrigin The origin of the ray to test intersection with. - //! @param rayDir The direction of the ray to test intersection with. - //! @param boxCenter The position of the center of the box. - //! @param boxAxis1 An axis along one dimension of the oriented box. - //! @param boxAxis2 An axis along one dimension of the oriented box. - //! @param boxAxis3 An axis along one dimension of the oriented box. - //! @param boxHalfExtent1 The half extent of the box on the dimension of \ref boxAxis1. - //! @param boxHalfExtent2 The half extent of the box on the dimension of \ref boxAxis2. - //! @param boxHalfExtent3 The half extent of the box on the dimension of \ref boxAxis3. - //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection". - //! @return 1 if there is an intersection, 0 otherwise. - int IntersectRayBox( + //! @param rayOrigin The origin of the ray to test intersection with. + //! @param rayDir The direction of the ray to test intersection with. + //! @param boxCenter The position of the center of the box. + //! @param boxAxis1 An axis along one dimension of the oriented box. + //! @param boxAxis2 An axis along one dimension of the oriented box. + //! @param boxAxis3 An axis along one dimension of the oriented box. + //! @param boxHalfExtent1 The half extent of the box on the dimension of \ref boxAxis1. + //! @param boxHalfExtent2 The half extent of the box on the dimension of \ref boxAxis2. + //! @param boxHalfExtent3 The half extent of the box on the dimension of \ref boxAxis3. + //! @param[out] t The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection". + //! @return true if there is an intersection, false otherwise. + bool IntersectRayBox( const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& boxCenter, @@ -273,23 +265,21 @@ namespace AZ float& t); //! Test intersection between a ray and an OBB. - //! //! @param rayOrigin The origin of the ray to test intersection with. //! @param rayDir The direction of the ray to test intersection with. //! @param obb The OBB to test for intersection with the ray. - //! @param t[out] The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * - //! rayDirection". - //! @return 1 if there is an intersection, 0 otherwise. - int IntersectRayObb(const Vector3& rayOrigin, const Vector3& rayDir, const Obb& obb, float& t); + //! @param[out] t The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection". + //! @return true if there is an intersection, false otherwise. + bool IntersectRayObb(const Vector3& rayOrigin, const Vector3& rayDir, const Obb& obb, float& t); //! Ray cylinder intersection types. enum CylinderIsectTypes : AZ::s32 { - RR_ISECT_RAY_CYL_SA_INSIDE = -1, // the ray starts inside the cylinder - RR_ISECT_RAY_CYL_NONE, // no intersection - RR_ISECT_RAY_CYL_PQ, // along the PQ segment - RR_ISECT_RAY_CYL_P_SIDE, // on the P side - RR_ISECT_RAY_CYL_Q_SIDE, // on the Q side + RR_ISECT_RAY_CYL_SA_INSIDE = -1, //!< the ray starts inside the cylinder + RR_ISECT_RAY_CYL_NONE, //!< no intersection + RR_ISECT_RAY_CYL_PQ, //!< along the PQ segment + RR_ISECT_RAY_CYL_P_SIDE, //!< on the P side + RR_ISECT_RAY_CYL_Q_SIDE, //!< on the Q side }; //! Reference: Real-Time Collision Detection - 5.3.7 Intersecting Ray or Segment Against Cylinder @@ -300,7 +290,7 @@ namespace AZ //! @param p center point of side 1 cylinder //! @param q center point of side 2 cylinder //! @param r radius of cylinder - //! @param t[out] proporition along line semgnet + //! @param[out] t proporition along line segment //! @return CylinderIsectTypes CylinderIsectTypes IntersectSegmentCylinder( const Vector3& sa, const Vector3& dir, const Vector3& p, const Vector3& q, const float r, float& t); @@ -308,26 +298,41 @@ namespace AZ //! Capsule ray intersect types. enum CapsuleIsectTypes { - ISECT_RAY_CAPSULE_SA_INSIDE = -1, // the ray starts inside the cylinder - ISECT_RAY_CAPSULE_NONE, // no intersection - ISECT_RAY_CAPSULE_PQ, // along the PQ segment - ISECT_RAY_CAPSULE_P_SIDE, // on the P side - ISECT_RAY_CAPSULE_Q_SIDE, // on the Q side + ISECT_RAY_CAPSULE_SA_INSIDE = -1, //!< the ray starts inside the cylinder + ISECT_RAY_CAPSULE_NONE, //!< no intersection + ISECT_RAY_CAPSULE_PQ, //!< along the PQ segment + ISECT_RAY_CAPSULE_P_SIDE, //!< on the P side + ISECT_RAY_CAPSULE_Q_SIDE, //!< on the Q side }; //! This is a quick implementation of segment capsule based on segment cylinder \ref IntersectSegmentCylinder //! segment sphere intersection. We can optimize it a lot once we fix the ray //! cylinder intersection. - //! + //! @param sa the beginning of the line segment + //! @param dir the direction and length of the segment + //! @param p center point of side 1 capsule + //! @param q center point of side 1 capsule + //! @param r the radius of the capsule + //! @param[out] t proporition along line segment + //! @return CapsuleIsectTypes CapsuleIsectTypes IntersectSegmentCapsule( const Vector3& sa, const Vector3& dir, const Vector3& p, const Vector3& q, const float r, float& t); //! Intersect segment S(t)=A+t(B-A), 0<=t<=1 against convex polyhedron specified //! by the n halfspaces defined by the planes p[]. On exit tfirst and tlast //! define the intersection, if any. + //! @param sa the beggining of the line segment + //! @param dir the direction and length of the segment + //! @param p planes that compose a convex ponvex polyhedron + //! @param numPlanes number of planes + //! @param[out] tfirst proportion along the line segment where the line enters + //! @param[out] tlast proportion along the line segment where the line exits + //! @param[out] iFirstPlane the plane where the line enters + //! @param[out] iLastPlane the plane where the line exits + //! @return true if intersects else false bool IntersectSegmentPolyhedron( const Vector3& sa, - const Vector3& sBA, + const Vector3& dir, const Plane p[], int numPlanes, float& tfirst, @@ -335,7 +340,7 @@ namespace AZ int& iFirstPlane, int& iLastPlane); - //! Calculate the line segment closestPointSegment1<->closestPointSegment2 that is the shortest route between + //! Calculate the line segment closestPointSegment1<->closestPointSegment2 that is the shortest route between //! two segments segment1Start<->segment1End and segment2Start<->segment2End. Also calculate the values of segment1Proportion and //! segment2Proportion where closestPointSegment1 = segment1Start + (segment1Proportion * (segment1End - segment1Start)) //! closestPointSegment2 = segment2Start + (segment2Proportion * (segment2End - segment2Start)) @@ -344,10 +349,10 @@ namespace AZ //! @param segment1End end of segment 1. //! @param segment2Start start of segment 2. //! @param segment2End end of segment 2. - //! @param segment1Proportion[out] the proporition along segment 1 [0..1] - //! @param segment2Proportion[out] the proporition along segment 2 [0..1] - //! @param closestPointSegment1[out] closest point on segment 1. - //! @param closestPointSegment2[out] closest point on segment 2. + //! @param[out] segment1Proportion the proporition along segment 1 [0..1] + //! @param[out] segment2Proportion the proporition along segment 2 [0..1] + //! @param[out] closestPointSegment1 closest point on segment 1. + //! @param[out] closestPointSegment2 closest point on segment 2. //! @param epsilon the minimum square distance where a line segment can be treated as a single point. void ClosestSegmentSegment( const Vector3& segment1Start, @@ -363,13 +368,12 @@ namespace AZ //! Calculate the line segment closestPointSegment1<->closestPointSegment2 that is the shortest route between //! two segments segment1Start<->segment1End and segment2Start<->segment2End. //! If segments are parallel returns a solution. - //! //! @param segment1Start start of segment 1. //! @param segment1End end of segment 1. //! @param segment2Start start of segment 2. //! @param segment2End end of segment 2. - //! @param closestPointSegment1[out] closest point on segment 1. - //! @param closestPointSegment2[out] closest point on segment 2. + //! @param[out] closestPointSegment1 closest point on segment 1. + //! @param[out] closestPointSegment2 closest point on segment 2. //! @param epsilon the minimum square distance where a line segment can be treated as a single point. void ClosestSegmentSegment( const Vector3& segment1Start, @@ -383,12 +387,11 @@ namespace AZ //! Calculate the point (closestPointOnSegment) that is the closest point on //! segment segmentStart/segmentEnd to point. Also calculate the value of proportion where //! closestPointOnSegment = segmentStart + (proportion * (segmentEnd - segmentStart)) - //! //! @param point the point to test //! @param segmentStart the start of the segment //! @param segmentEnd the end of the segment - //! @param proportion[out] the proportion of the segment L(t) = (end - start) * t - //! @param closestPointOnSegment[out] the point along the line segment + //! @param[out] proportion the proportion of the segment L(t) = (end - start) * t + //! @param[out] closestPointOnSegment the point along the line segment void ClosestPointSegment( const Vector3& point, const Vector3& segmentStart, From 7ca85460f752f74fc2fc111e2bcbe2ea78b41342 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Tue, 12 Oct 2021 01:41:11 -0700 Subject: [PATCH 112/169] Bug Fix: Improve display of Viewport UI (#4596) - always show controls on top of main ui - Tool window does not show visually in toolbar issue: https://github.com/o3de/o3de/issues/4380 Signed-off-by: Michael Pollind --- .../AzToolsFramework/ViewportUi/ViewportUiDisplay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiDisplay.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiDisplay.cpp index 80cc7941b0..e27627eab6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiDisplay.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiDisplay.cpp @@ -339,7 +339,7 @@ namespace AzToolsFramework::ViewportUi::Internal { // no background for the widget else each set of buttons/text-fields/etc would have a black box around them SetTransparentBackground(mainWindow); - mainWindow->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); + mainWindow->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); } void ViewportUiDisplay::InitializeUiOverlay() From ccb686b0fca55ff5e1510d61d665a8dd014c7f8c Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Tue, 12 Oct 2021 11:15:56 +0200 Subject: [PATCH 113/169] Bug report template improvement suggestions (#4478) Signed-off-by: Benjamin Jillich --- .github/ISSUE_TEMPLATE/bug_template.md | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_template.md b/.github/ISSUE_TEMPLATE/bug_template.md index d197ca1312..5a6275b394 100644 --- a/.github/ISSUE_TEMPLATE/bug_template.md +++ b/.github/ISSUE_TEMPLATE/bug_template.md @@ -7,20 +7,30 @@ labels: 'needs-triage,needs-sig,kind/bug' --- **Describe the bug** -A clear and concise description of what the bug is. +A clear and concise description of what the bug is. Try to isolate the issue to help the community to reproduce it easily and increase chances for a fast fix. -**To Reproduce** +**Steps to reproduce** Steps to reproduce the behavior: 1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error +2. Click on '...' +3. Select attached asset '...' +4. Scroll down to '...' +5. See error **Expected behavior** A clear and concise description of what you expected to happen. -**Screenshots** -If applicable, add screenshots to help explain your problem. +**Actual behavior** +A clear and concise description of what actually happened. + +**Assets required** +Provide sample assets needed to reproduce the issue. + +**Screenshots/Video** +If applicable, add screenshots and/or a video to help explain your problem. + +**Found in Branch** +Name of or link to the branch where the issue occurs. **Desktop/Device (please complete the following information):** - Device: [e.g. PC, Mac, iPhone, Samsung] From 129d249cb4aa3fdcc26e980f280fbb1b01aac61d Mon Sep 17 00:00:00 2001 From: Roman <69218254+amzn-rhhong@users.noreply.github.com> Date: Tue, 12 Oct 2021 08:53:30 -0700 Subject: [PATCH 114/169] Do not delete the actor instance if it's belong to an entity. (#4624) Signed-off-by: rhhong --- .../Code/Tools/EMStudio/AnimViewportRenderer.cpp | 4 ++++ .../Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp index ab54b1fa38..52f857551c 100644 --- a/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp +++ b/Gems/AtomLyIntegration/EMotionFXAtom/Code/Tools/EMStudio/AnimViewportRenderer.cpp @@ -92,6 +92,7 @@ namespace EMStudio m_postProcessEntity->CreateComponent(AZ::Render::PostFxLayerComponentTypeId); m_postProcessEntity->CreateComponent(AZ::Render::ExposureControlComponentTypeId); m_postProcessEntity->CreateComponent(azrtti_typeid()); + m_postProcessEntity->Init(); m_postProcessEntity->Activate(); // Init directional light processor @@ -112,6 +113,7 @@ namespace EMStudio m_iblEntity->CreateComponent(AZ::Render::ImageBasedLightComponentTypeId); m_iblEntity->CreateComponent(azrtti_typeid()); + m_iblEntity->Init(); m_iblEntity->Activate(); // Load light preset @@ -134,6 +136,7 @@ namespace EMStudio gridComponent->SetConfiguration(gridConfig); m_gridEntity->CreateComponent(azrtti_typeid()); + m_gridEntity->Init(); m_gridEntity->Activate(); Reinit(); @@ -251,6 +254,7 @@ namespace EMStudio actorEntity->CreateComponent(azrtti_typeid()); actorEntity->CreateComponent(AZ::Render::MaterialComponentTypeId); actorEntity->CreateComponent(azrtti_typeid()); + actorEntity->Init(); actorEntity->Activate(); EMotionFX::Integration::ActorComponent* actorComponent = actorEntity->FindComponent(); diff --git a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp index 57e206560a..ef573ab40c 100644 --- a/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/CommandSystem/Source/ActorCommands.cpp @@ -825,6 +825,11 @@ namespace CommandSystem { continue; } + // Ignore actor instances owned by entity + if (actorInstance->GetEntity()) + { + continue; + } // generate command to remove the actor instance const AZStd::string command = AZStd::string::format("RemoveActorInstance -actorInstanceID %i", actorInstance->GetID()); From 01448c5c49ef5e015fcd30f5ef869799fa042922 Mon Sep 17 00:00:00 2001 From: Qing Tao <55564570+VickyAtAZ@users.noreply.github.com> Date: Tue, 12 Oct 2021 09:11:50 -0700 Subject: [PATCH 115/169] ATOM-16658 Remove PBSreferenceMaterials gem which is a gem for legacy cry3dengine (#4616) Signed-off-by: Qing Tao --- .../Registry/assets_scan_folders.setreg | 7 ------- .../materials/pbs_reference/16_ddna.tif | 3 --- .../pbs_reference/anodized_metal.mtl | 10 ---------- .../pbs_reference/anodized_metal_diff.tif | 3 --- .../anodized_metal_diff.tif.exportsettings | 1 - .../pbs_reference/anodized_metal_spec.tif | 3 --- .../anodized_metal_spec.tif.exportsettings | 1 - .../materials/pbs_reference/brushed_steel.mtl | 10 ---------- .../materials/pbs_reference/brushed_steel.tif | 3 --- .../brushed_steel.tif.exportsettings | 1 - .../pbs_reference/brushed_steel2.mtl | 10 ---------- .../pbs_reference/brushed_steel_ddna.tif | 3 --- .../brushed_steel_ddna.tif.exportsettings | 1 - .../materials/pbs_reference/car_paint.mtl | 8 -------- .../pbs_reference/car_paint_diff.tif | 3 --- .../car_paint_diff.tif.exportsettings | 1 - .../pbs_reference/car_paint_spec.tif | 3 --- .../car_paint_spec.tif.exportsettings | 1 - .../Assets/materials/pbs_reference/coal.mtl | 9 --------- .../materials/pbs_reference/coal_ddna.tif | 3 --- .../coal_ddna.tif.exportsettings | 1 - .../materials/pbs_reference/coal_diff.tif | 3 --- .../coal_diff.tif.exportsettings | 1 - .../colorcharts/debug_contrast_high_cch.tif | 3 --- .../colorcharts/debug_contrast_low_cch.tif | 3 --- .../debug_contrast_veryhigh_cch.tif | 3 --- .../colorcharts/debug_saturation_0_cch.tif | 3 --- .../pbs_reference/concrete_stucco.mtl | 9 --------- .../pbs_reference/concrete_stucco_ddna.tif | 3 --- .../concrete_stucco_ddna.tif.exportsettings | 1 - .../pbs_reference/concrete_stucco_diff.tif | 3 --- .../concrete_stucco_diff.tif.exportsettings | 1 - .../pbs_reference/conductor_diff.tif | 3 --- .../conductor_diff.tif.exportsettings | 1 - .../materials/pbs_reference/copper_spec.tif | 3 --- .../copper_spec.tif.exportsettings | 1 - .../materials/pbs_reference/dark_leather.mtl | 9 --------- .../pbs_reference/dark_leather_diff.tif | 3 --- .../dark_leather_diff.tif.exportsettings | 1 - .../Assets/materials/pbs_reference/fabric.mtl | 9 --------- .../pbs_reference/galvanized_steel.mtl | 10 ---------- .../pbs_reference/galvanized_steel.tif | 3 --- .../galvanized_steel.tif.exportsettings | 1 - .../pbs_reference/galvanized_steel_ddna.tif | 3 --- .../galvanized_steel_ddna.tif.exportsettings | 1 - .../pbs_reference/galvanized_steel_spec.tif | 3 --- .../galvanized_steel_spec.tif.exportsettings | 1 - .../materials/pbs_reference/glazed_clay.mtl | 7 ------- .../pbs_reference/glazed_clay_ddna.tif | 3 --- .../glazed_clay_ddna.tif.exportsettings | 1 - .../pbs_reference/glazed_clay_diff.tif | 3 --- .../glazed_clay_diff.tif.exportsettings | 1 - .../Assets/materials/pbs_reference/gloss0.mtl | 7 ------- .../materials/pbs_reference/gloss0_ddna.tif | 3 --- .../gloss0_ddna.tif.exportsettings | 1 - .../materials/pbs_reference/gloss10.mtl | 7 ------- .../materials/pbs_reference/gloss100.mtl | 7 ------- .../materials/pbs_reference/gloss100_ddna.tif | 3 --- .../gloss100_ddna.tif.exportsettings | 1 - .../materials/pbs_reference/gloss10_ddna.tif | 3 --- .../gloss10_ddna.tif.exportsettings | 1 - .../materials/pbs_reference/gloss20.mtl | 7 ------- .../materials/pbs_reference/gloss20_ddna.tif | 3 --- .../gloss20_ddna.tif.exportsettings | 1 - .../materials/pbs_reference/gloss30.mtl | 7 ------- .../materials/pbs_reference/gloss30_ddna.tif | 3 --- .../gloss30_ddna.tif.exportsettings | 1 - .../materials/pbs_reference/gloss40.mtl | 7 ------- .../materials/pbs_reference/gloss40_ddna.tif | 3 --- .../gloss40_ddna.tif.exportsettings | 1 - .../materials/pbs_reference/gloss50.mtl | 7 ------- .../materials/pbs_reference/gloss50_ddna.tif | 3 --- .../gloss50_ddna.tif.exportsettings | 1 - .../materials/pbs_reference/gloss60.mtl | 7 ------- .../materials/pbs_reference/gloss60_ddna.tif | 3 --- .../gloss60_ddna.tif.exportsettings | 1 - .../materials/pbs_reference/gloss70.mtl | 7 ------- .../materials/pbs_reference/gloss70_ddna.tif | 3 --- .../gloss70_ddna.tif.exportsettings | 1 - .../materials/pbs_reference/gloss80.mtl | 7 ------- .../materials/pbs_reference/gloss80_ddna.tif | 3 --- .../gloss80_ddna.tif.exportsettings | 1 - .../materials/pbs_reference/gloss90.mtl | 7 ------- .../materials/pbs_reference/gloss90_ddna.tif | 3 --- .../gloss90_ddna.tif.exportsettings | 1 - .../materials/pbs_reference/gold_spec.tif | 3 --- .../gold_spec.tif.exportsettings | 1 - .../ground_mats/mixed_stones1.mtl | 7 ------- .../materials/pbs_reference/iron_spec.tif | 3 --- .../iron_spec.tif.exportsettings | 1 - .../materials/pbs_reference/leather_ddna.tif | 3 --- .../leather_ddna.tif.exportsettings | 1 - .../materials/pbs_reference/light_leather.mtl | 9 --------- .../pbs_reference/light_leather_diff.tif | 3 --- .../light_leather_diff.tif.exportsettings | 1 - .../materials/pbs_reference/mixed_stones.mtl | 9 --------- .../pbs_reference/mixed_stones_ddna.tif | 3 --- .../mixed_stones_ddna.tif.exportsettings | 1 - .../pbs_reference/mixed_stones_diff.tif | 3 --- .../mixed_stones_diff.tif.exportsettings | 1 - .../materials/pbs_reference/nickel_spec.tif | 3 --- .../nickel_spec.tif.exportsettings | 1 - .../pbs_reference/plain_fabric_ddna.tif | 3 --- .../plain_fabric_ddna.tif.exportsettings | 1 - .../pbs_reference/plain_fabric_diff.tif | 3 --- .../plain_fabric_diff.tif.exportsettings | 1 - .../materials/pbs_reference/platinum_spec.tif | 3 --- .../platinum_spec.tif.exportsettings | 1 - .../pbs_reference/polished_copper.mtl | 7 ------- .../materials/pbs_reference/polished_gold.mtl | 7 ------- .../materials/pbs_reference/polished_iron.mtl | 7 ------- .../pbs_reference/polished_nickel.mtl | 7 ------- .../pbs_reference/polished_silver.mtl | 7 ------- .../materials/pbs_reference/porcelain.mtl | 9 --------- .../pbs_reference/porcelain_diff.tif | 3 --- .../porcelain_diff.tif.exportsettings | 1 - .../materials/pbs_reference/red_diff.tif | 3 --- .../pbs_reference/red_diff.tif.exportsettings | 1 - .../rotary_brushed_steel_ddna.tif | 3 --- ...tary_brushed_steel_ddna.tif.exportsettings | 1 - .../Assets/materials/pbs_reference/rust.mtl | 9 --------- .../materials/pbs_reference/rust_blend.tif | 3 --- .../rust_blend.tif.exportsettings | 1 - .../materials/pbs_reference/rust_ddna.tif | 3 --- .../rust_ddna.tif.exportsettings | 1 - .../materials/pbs_reference/rust_diff.tif | 3 --- .../rust_diff.tif.exportsettings | 1 - .../materials/pbs_reference/rusted_metal.mtl | 13 ------------ .../materials/pbs_reference/shiny_plastic.mtl | 9 --------- .../materials/pbs_reference/silver_spec.tif | 3 --- .../silver_spec.tif.exportsettings | 1 - .../pbs_reference/skydomes/afternoon.tif | 3 --- .../pbs_reference/skydomes/evening.tif | 3 --- .../pbs_reference/skydomes/neutral.tif | 3 --- .../pbs_reference/skydomes/night.tif | 3 --- .../pbs_reference/skydomes/sky_afternoon.mtl | 6 ------ .../pbs_reference/skydomes/sky_evening.mtl | 6 ------ .../pbs_reference/skydomes/sky_neutral.mtl | 6 ------ .../pbs_reference/skydomes/sky_night.mtl | 7 ------- .../materials/pbs_reference/wood_planks.mtl | 10 ---------- .../pbs_reference/wood_planks_ddna.tif | 3 --- .../wood_planks_ddna.tif.exportsettings | 1 - .../pbs_reference/wood_planks_diff.tif | 3 --- .../wood_planks_diff.tif.exportsettings | 1 - .../pbs_reference/wood_planks_spec.tif | 3 --- .../wood_planks_spec.tif.exportsettings | 1 - .../materials/pbs_reference/worn_copper.mtl | 10 ---------- .../materials/pbs_reference/worn_gold.mtl | 10 ---------- .../materials/pbs_reference/worn_metal.mtl | 10 ---------- .../pbs_reference/worn_metal_ddna.tif | 3 --- .../worn_metal_ddna.tif.exportsettings | 1 - .../Assets/materials/test_reference/test.mtl | 12 ----------- .../materials/test_reference/test_AO.tif | 3 --- .../test_reference/test_AO.tif.exportsettings | 1 - .../materials/test_reference/test_H.tif | 3 --- .../test_reference/test_H.tif.exportsettings | 1 - .../materials/test_reference/test_albedo.tif | 3 --- .../test_albedo.tif.exportsettings | 1 - .../test_reference/test_normals_ddn.tif | 3 --- .../test_normals_ddn.tif.exportsettings | 1 - Gems/PBSreferenceMaterials/CMakeLists.txt | 12 ----------- .../Resources/test_source.psd | 3 --- Gems/PBSreferenceMaterials/gem.json | 20 ------------------- Gems/PBSreferenceMaterials/preview.png | 3 --- engine.json | 1 - 165 files changed, 634 deletions(-) delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/16_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_diff.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_diff.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_spec.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_spec.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel2.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint_diff.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint_diff.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint_spec.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint_spec.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal_diff.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal_diff.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/colorcharts/debug_contrast_high_cch.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/colorcharts/debug_contrast_low_cch.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/colorcharts/debug_contrast_veryhigh_cch.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/colorcharts/debug_saturation_0_cch.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco_diff.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco_diff.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/conductor_diff.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/conductor_diff.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/copper_spec.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/copper_spec.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/dark_leather.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/dark_leather_diff.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/dark_leather_diff.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/fabric.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_spec.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_spec.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay_diff.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay_diff.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss0.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss0_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss0_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss10.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss100.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss100_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss100_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss10_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss10_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss20.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss20_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss20_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss30.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss30_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss30_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss40.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss40_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss40_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss50.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss50_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss50_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss60.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss60_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss60_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss70.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss70_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss70_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss80.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss80_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss80_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss90.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss90_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss90_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gold_spec.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gold_spec.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/ground_mats/mixed_stones1.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/iron_spec.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/iron_spec.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/leather_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/leather_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/light_leather.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/light_leather_diff.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/light_leather_diff.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_diff.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_diff.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/nickel_spec.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/nickel_spec.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/plain_fabric_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/plain_fabric_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/plain_fabric_diff.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/plain_fabric_diff.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/platinum_spec.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/platinum_spec.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_copper.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_gold.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_iron.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_nickel.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_silver.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/porcelain.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/porcelain_diff.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/porcelain_diff.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/red_diff.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/red_diff.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rotary_brushed_steel_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rotary_brushed_steel_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_blend.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_blend.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_diff.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_diff.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rusted_metal.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/shiny_plastic.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/silver_spec.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/silver_spec.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/afternoon.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/evening.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/neutral.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/night.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/sky_afternoon.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/sky_evening.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/sky_neutral.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/sky_night.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_diff.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_diff.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_spec.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_spec.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_copper.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_gold.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_metal.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_metal_ddna.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_metal_ddna.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/test_reference/test.mtl delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_AO.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_AO.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_H.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_H.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_albedo.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_albedo.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_normals_ddn.tif delete mode 100644 Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_normals_ddn.tif.exportsettings delete mode 100644 Gems/PBSreferenceMaterials/CMakeLists.txt delete mode 100644 Gems/PBSreferenceMaterials/Resources/test_source.psd delete mode 100644 Gems/PBSreferenceMaterials/gem.json delete mode 100644 Gems/PBSreferenceMaterials/preview.png diff --git a/AutomatedTesting/Registry/assets_scan_folders.setreg b/AutomatedTesting/Registry/assets_scan_folders.setreg index c74ba6703e..3043533b59 100644 --- a/AutomatedTesting/Registry/assets_scan_folders.setreg +++ b/AutomatedTesting/Registry/assets_scan_folders.setreg @@ -10,13 +10,6 @@ "Gems/DevTextures" ] }, - "PBSreferenceMaterials": - { - "SourcePaths": - [ - "Gems/PBSreferenceMaterials" - ] - }, "PhysicsEntities": { "SourcePaths": diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/16_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/16_ddna.tif deleted file mode 100644 index 68edfab5e2..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/16_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:78394a1c8fc1e8bb260b27c5ae3fa040cbabcbc550fb33470316f9f38b2327f7 -size 2104742 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal.mtl deleted file mode 100644 index c27dfd5bc1..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal.mtl +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_diff.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_diff.tif deleted file mode 100644 index 7993c143a9..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ae4a72a26a2f232c6ffb42a391d81b4ca7396c73894ccb923ba2f7bc1c940f04 -size 12602810 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_diff.tif.exportsettings deleted file mode 100644 index e97c4e452c..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="android:0,ios:0,mac:0,pc:2,provo:0,wiiu:0" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_spec.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_spec.tif deleted file mode 100644 index 531bbe52b2..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_spec.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:73e215c80dcbde6b092b87aaed3532aa3e4447872a4c347248ada2e0c92b62c9 -size 12602768 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_spec.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_spec.tif.exportsettings deleted file mode 100644 index 0e4a4a080e..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/anodized_metal_spec.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Reflectance /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel.mtl deleted file mode 100644 index eab5de5a5b..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel.mtl +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel.tif deleted file mode 100644 index 9db133e2cd..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0801f5089dc5d984fc2c88bd1cb3e0160fc0eddacdb95492d8ee433d0dfe675b -size 12602752 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel.tif.exportsettings deleted file mode 100644 index fb61d0f55c..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce=1 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel2.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel2.mtl deleted file mode 100644 index dfadacee21..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel2.mtl +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel_ddna.tif deleted file mode 100644 index 5afabeeea2..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cb714bf17f4da5b74eb0fe8eb329533f1fe76c68a915f5240a30bf496d133b2a -size 33574354 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel_ddna.tif.exportsettings deleted file mode 100644 index a098bdcad9..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/brushed_steel_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint.mtl deleted file mode 100644 index c0f0399527..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint.mtl +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint_diff.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint_diff.tif deleted file mode 100644 index 207980ec50..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:cc61165bad7ff9a3f6bee23c47350bd4e69f7bce80a50acc4d353583d5a49ec2 -size 12602762 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint_diff.tif.exportsettings deleted file mode 100644 index d3713274e6..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint_spec.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint_spec.tif deleted file mode 100644 index 97738f104e..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint_spec.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8349c8ebe5b6b58f426bccd307778aeff674970b8b7761c78bf07460a51208d1 -size 12602764 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint_spec.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint_spec.tif.exportsettings deleted file mode 100644 index 0e4a4a080e..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/car_paint_spec.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Reflectance /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal.mtl deleted file mode 100644 index a5848a101c..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal.mtl +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal_ddna.tif deleted file mode 100644 index f0b243c4ba..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e8691f06e179e74b2035df0147b3792b28aded379fb8ca5c6a58694793bcfc7b -size 33574298 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal_ddna.tif.exportsettings deleted file mode 100644 index 4377d1bc2a..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=1 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal_diff.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal_diff.tif deleted file mode 100644 index 51afab3cae..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:51afb7f2b44b7249b7b560abd165cd07f55a8f622e7ce684aa70de0fe04fe457 -size 12602798 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal_diff.tif.exportsettings deleted file mode 100644 index 78867ef15c..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/coal_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /mipmaps=0 /preset=Albedo /reduce=-1 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/colorcharts/debug_contrast_high_cch.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/colorcharts/debug_contrast_high_cch.tif deleted file mode 100644 index 370a37320b..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/colorcharts/debug_contrast_high_cch.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:61b26a818df92997fe0336d7e4fcb84af10328be0f49bd23b28b20dd3d70dc94 -size 19460 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/colorcharts/debug_contrast_low_cch.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/colorcharts/debug_contrast_low_cch.tif deleted file mode 100644 index 57bb2a9eb6..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/colorcharts/debug_contrast_low_cch.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0c266cd36f1732dd6f0e86cee98d354f1301fa06c62dc8dc1d81f2dce64b589c -size 19460 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/colorcharts/debug_contrast_veryhigh_cch.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/colorcharts/debug_contrast_veryhigh_cch.tif deleted file mode 100644 index ac1f01f7a7..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/colorcharts/debug_contrast_veryhigh_cch.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:41360332648da3dc87d441d07efdbc9074e01de03e4752775f655299870adb84 -size 19462 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/colorcharts/debug_saturation_0_cch.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/colorcharts/debug_saturation_0_cch.tif deleted file mode 100644 index 5a5312dac8..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/colorcharts/debug_saturation_0_cch.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8b2d948c3edd823e3ce898cb0237d37088b7c09f7a6bc4f2d5a883a3785c7b92 -size 19416 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco.mtl deleted file mode 100644 index 0bc0563dc9..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco.mtl +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco_ddna.tif deleted file mode 100644 index 115848e63a..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f5e34cadedb6f04d7e2923ff39eb6aa26578f7fa66d55759a79fc8b2fc297a67 -size 33571726 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco_ddna.tif.exportsettings deleted file mode 100644 index 4377d1bc2a..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=1 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco_diff.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco_diff.tif deleted file mode 100644 index f73e9d8e29..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:f6fe115f07fabdf24effa6ccf510d7df0878338cf62ec725f99548f744d8d520 -size 25183118 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco_diff.tif.exportsettings deleted file mode 100644 index fb61d0f55c..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/concrete_stucco_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce=1 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/conductor_diff.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/conductor_diff.tif deleted file mode 100644 index 55869c6a65..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/conductor_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:1e83c754930c838b473d0388cb7eea6fc61f00d37756f288588706ef31fbc3e7 -size 793988 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/conductor_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/conductor_diff.tif.exportsettings deleted file mode 100644 index d3713274e6..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/conductor_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/copper_spec.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/copper_spec.tif deleted file mode 100644 index eff0d838ff..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/copper_spec.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:eb7bb72c37f57ae9f5c8be2239d24da91d635281ee6c5394f4cd4376260dd659 -size 1580448 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/copper_spec.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/copper_spec.tif.exportsettings deleted file mode 100644 index a6837b396f..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/copper_spec.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /mipgentype=average /preset=Reflectance /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/dark_leather.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/dark_leather.mtl deleted file mode 100644 index e1e04a218f..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/dark_leather.mtl +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/dark_leather_diff.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/dark_leather_diff.tif deleted file mode 100644 index 05a2366629..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/dark_leather_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:28e1269ebe4839f329879adf0faa908eef16a975a37e614f65c9337c8095c694 -size 12602796 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/dark_leather_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/dark_leather_diff.tif.exportsettings deleted file mode 100644 index 19e899701a..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/dark_leather_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/fabric.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/fabric.mtl deleted file mode 100644 index e25536921d..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/fabric.mtl +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel.mtl deleted file mode 100644 index a5becf3800..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel.mtl +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel.tif deleted file mode 100644 index 556be35401..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0b3d1f17036a544942d9b5ad753d9de4e77f2d72f264e75703c777a9ec36d0ff -size 16797130 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel.tif.exportsettings deleted file mode 100644 index 6a4cbb4a3f..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /mipmaps=0 /preset=NormalsWithSmoothness /reduce=-1 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_ddna.tif deleted file mode 100644 index b3310a7902..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ece9aed5ef96c2b677922f148ef03d6186b7eca9400e90956772bce5661ecc34 -size 33574310 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_ddna.tif.exportsettings deleted file mode 100644 index 0159b6ca02..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_spec.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_spec.tif deleted file mode 100644 index c8194ca629..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_spec.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9d6d9d3c1577efc9df9f9200d24d338cdca684239f0e793c217e1a7358ced6ff -size 25185726 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_spec.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_spec.tif.exportsettings deleted file mode 100644 index 08861692ea..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/galvanized_steel_spec.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Reflectance /reduce="android:0,ios:0,mac:0,pc:1,provo:0,wiiu:0" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay.mtl deleted file mode 100644 index 9b722cb5e6..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay_ddna.tif deleted file mode 100644 index 629475cdef..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:02fdb16917657d8af287dc03bbaef856d99570a26bd8d92d1766c221abb4ffd3 -size 33571149 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay_ddna.tif.exportsettings deleted file mode 100644 index 0159b6ca02..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay_diff.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay_diff.tif deleted file mode 100644 index 60698476a1..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:5001487368d53bba9def9ea772b129ee1e16e738b8940a0621d1822e87105ffc -size 25182520 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay_diff.tif.exportsettings deleted file mode 100644 index d3713274e6..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/glazed_clay_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss0.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss0.mtl deleted file mode 100644 index 217d3a979a..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss0.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss0_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss0_ddna.tif deleted file mode 100644 index 69bda20789..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss0_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:54c5b9d01385f9301ff5958c75ddf9f7128539dbdb8c12497ef12150fd7e3991 -size 2104738 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss0_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss0_ddna.tif.exportsettings deleted file mode 100644 index 0159b6ca02..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss0_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss10.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss10.mtl deleted file mode 100644 index 2d1be1df68..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss10.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss100.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss100.mtl deleted file mode 100644 index a8e096eead..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss100.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss100_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss100_ddna.tif deleted file mode 100644 index 9bb9eb9a2d..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss100_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:aab4381b123765d164d222ab8260977302a49d176f1c6b601a3236013eb93c71 -size 2104740 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss100_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss100_ddna.tif.exportsettings deleted file mode 100644 index 0159b6ca02..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss100_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss10_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss10_ddna.tif deleted file mode 100644 index c7b3884843..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss10_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6c84d169f7f305dde87039b113b144335239ded615ddc060fd7648e0c69c4ebd -size 2104738 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss10_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss10_ddna.tif.exportsettings deleted file mode 100644 index 0159b6ca02..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss10_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss20.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss20.mtl deleted file mode 100644 index b2b3c7643d..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss20.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss20_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss20_ddna.tif deleted file mode 100644 index 6b990d7545..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss20_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6bcd9dfe932714e63612023ea8dce2a9e2c377553e666b96771bb4f831387c7d -size 2104738 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss20_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss20_ddna.tif.exportsettings deleted file mode 100644 index 0159b6ca02..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss20_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss30.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss30.mtl deleted file mode 100644 index 661a8e3de2..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss30.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss30_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss30_ddna.tif deleted file mode 100644 index 64094acf29..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss30_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:500b16679345f981c68521e6021aea5ef0e07603beb52fdac6bbb46320af98cb -size 2104738 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss30_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss30_ddna.tif.exportsettings deleted file mode 100644 index 0159b6ca02..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss30_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss40.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss40.mtl deleted file mode 100644 index 70ee969fc0..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss40.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss40_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss40_ddna.tif deleted file mode 100644 index c166c9f8cc..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss40_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:36b57374a09c929f9bdec637483f3545b320a2fe18e3e33d483cd3d027b7a4cd -size 2104738 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss40_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss40_ddna.tif.exportsettings deleted file mode 100644 index 0159b6ca02..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss40_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss50.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss50.mtl deleted file mode 100644 index 4f00a19269..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss50.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss50_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss50_ddna.tif deleted file mode 100644 index e92493893f..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss50_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:09b976c732d3b456ebd75afc814cc74c8aaa2530118e2a54127c8ce8d24c63cd -size 2104746 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss50_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss50_ddna.tif.exportsettings deleted file mode 100644 index 0159b6ca02..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss50_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss60.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss60.mtl deleted file mode 100644 index c96632fe7b..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss60.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss60_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss60_ddna.tif deleted file mode 100644 index 1086d2a54d..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss60_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d733ad0c67d70aa2fbc31ac6edd1a50d99ed9f4659452707db1b107433668ef6 -size 2104746 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss60_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss60_ddna.tif.exportsettings deleted file mode 100644 index 0159b6ca02..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss60_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss70.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss70.mtl deleted file mode 100644 index e7afaff4cd..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss70.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss70_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss70_ddna.tif deleted file mode 100644 index 56f751a811..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss70_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:e8fe277c640d2f17b80322de1218cb9b8d3f979c76f735a9741fd253a639868f -size 2104746 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss70_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss70_ddna.tif.exportsettings deleted file mode 100644 index 0159b6ca02..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss70_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss80.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss80.mtl deleted file mode 100644 index 11bee418ea..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss80.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss80_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss80_ddna.tif deleted file mode 100644 index 096aa4f81f..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss80_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c2019143e287e449cfa544ca8d06be38332e6bad2d92f302482670d25c27ce93 -size 2104748 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss80_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss80_ddna.tif.exportsettings deleted file mode 100644 index 0159b6ca02..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss80_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss90.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss90.mtl deleted file mode 100644 index 295882a14d..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss90.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss90_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss90_ddna.tif deleted file mode 100644 index dd311c14f3..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss90_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:913e9594afce1753143c4a23ba63376844285e4cfa0353bec8c8fbb32fb55244 -size 2104748 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss90_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss90_ddna.tif.exportsettings deleted file mode 100644 index 0159b6ca02..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gloss90_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gold_spec.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gold_spec.tif deleted file mode 100644 index 7d053201a4..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gold_spec.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:60df2f9dd0c960135c590b6bbb085d8054d4f98a9349a3aaae2b69ef2c084afd -size 1580458 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gold_spec.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gold_spec.tif.exportsettings deleted file mode 100644 index a6837b396f..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/gold_spec.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /mipgentype=average /preset=Reflectance /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/ground_mats/mixed_stones1.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/ground_mats/mixed_stones1.mtl deleted file mode 100644 index 68bc825e99..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/ground_mats/mixed_stones1.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/iron_spec.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/iron_spec.tif deleted file mode 100644 index 69162c2479..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/iron_spec.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:0809fec4adb0ba0bd9143e599ae841b04bcfa924cdd55666e46c82771825e106 -size 794002 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/iron_spec.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/iron_spec.tif.exportsettings deleted file mode 100644 index 0e4a4a080e..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/iron_spec.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Reflectance /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/leather_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/leather_ddna.tif deleted file mode 100644 index ff7973839e..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/leather_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:44e38b77ed21dd6c4dbe506d7449440ae5edd734d8eaf9e3fc68b49f16890598 -size 16797150 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/leather_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/leather_ddna.tif.exportsettings deleted file mode 100644 index a098bdcad9..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/leather_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/light_leather.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/light_leather.mtl deleted file mode 100644 index fb58f3e7d3..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/light_leather.mtl +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/light_leather_diff.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/light_leather_diff.tif deleted file mode 100644 index 7efa3c5dc0..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/light_leather_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:7ec252b4e03cb18ae458c650c392cdcd2c3d077db54279665f7b8bf7b335ff80 -size 12602808 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/light_leather_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/light_leather_diff.tif.exportsettings deleted file mode 100644 index 19e899701a..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/light_leather_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones.mtl deleted file mode 100644 index f7572190ce..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones.mtl +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_ddna.tif deleted file mode 100644 index f65bd1efb8..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9b18ba8592261663e36608c74c763c7b80adc673f5857a605c7a1a261bb8dc3c -size 8400326 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_ddna.tif.exportsettings deleted file mode 100644 index a098bdcad9..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_diff.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_diff.tif deleted file mode 100644 index 57b058e334..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:54e57959423057d58ec5be9530669e613566eb1152919887b10f06ab81cf901d -size 6303154 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_diff.tif.exportsettings deleted file mode 100644 index 19e899701a..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/mixed_stones_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/nickel_spec.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/nickel_spec.tif deleted file mode 100644 index 538b6adf3a..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/nickel_spec.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:af459c0475bcf52150d818190480665ca0989f94a17cf979478e0bfd078cc0bf -size 793948 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/nickel_spec.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/nickel_spec.tif.exportsettings deleted file mode 100644 index 0e4a4a080e..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/nickel_spec.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Reflectance /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/plain_fabric_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/plain_fabric_ddna.tif deleted file mode 100644 index 28c888ac93..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/plain_fabric_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2c2b478231433a0d797bfe62bb087c8331a7edb32a150e2da6bd51fe55d4da60 -size 16797096 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/plain_fabric_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/plain_fabric_ddna.tif.exportsettings deleted file mode 100644 index 4377d1bc2a..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/plain_fabric_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=1 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/plain_fabric_diff.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/plain_fabric_diff.tif deleted file mode 100644 index 791d5a9068..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/plain_fabric_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d460e8b5c8c026cad1b20a71c3857c562051ccd4fc66d480357375276e41ab70 -size 12602770 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/plain_fabric_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/plain_fabric_diff.tif.exportsettings deleted file mode 100644 index d3713274e6..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/plain_fabric_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/platinum_spec.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/platinum_spec.tif deleted file mode 100644 index 293868dbcd..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/platinum_spec.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:a8a5517902429c5b518041cf13f09c0e68378ca0afcd53af487373bc23584953 -size 794002 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/platinum_spec.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/platinum_spec.tif.exportsettings deleted file mode 100644 index 2bec812694..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/platinum_spec.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Reflectance_Linear /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_copper.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_copper.mtl deleted file mode 100644 index e440e60c07..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_copper.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_gold.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_gold.mtl deleted file mode 100644 index ff61b723c1..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_gold.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_iron.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_iron.mtl deleted file mode 100644 index a2557c8cf5..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_iron.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_nickel.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_nickel.mtl deleted file mode 100644 index 383f132414..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_nickel.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_silver.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_silver.mtl deleted file mode 100644 index e6f78b0c92..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/polished_silver.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/porcelain.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/porcelain.mtl deleted file mode 100644 index b82aa09808..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/porcelain.mtl +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/porcelain_diff.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/porcelain_diff.tif deleted file mode 100644 index cc0ff9e1a1..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/porcelain_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:23383293c185f7801f466779a0f223dd3eb21a8cc2c69a742d58f699b32ac375 -size 3157400 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/porcelain_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/porcelain_diff.tif.exportsettings deleted file mode 100644 index 78867ef15c..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/porcelain_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /mipmaps=0 /preset=Albedo /reduce=-1 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/red_diff.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/red_diff.tif deleted file mode 100644 index 3532880e2d..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/red_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6c38541d104c3461b22f9bf8865308f5ea07895f3cebc1fd67c29647c76ed904 -size 794036 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/red_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/red_diff.tif.exportsettings deleted file mode 100644 index 48c18e1fe4..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/red_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="android:0,ios:0,mac:0,pc:3,provo:0,wiiu:0" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rotary_brushed_steel_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rotary_brushed_steel_ddna.tif deleted file mode 100644 index ac1ced5071..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rotary_brushed_steel_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:00928a4cbfc43bc3d13f407d8ea6d59499e658c0fdd92981b6124e999ca7d668 -size 33574298 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rotary_brushed_steel_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rotary_brushed_steel_ddna.tif.exportsettings deleted file mode 100644 index a098bdcad9..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rotary_brushed_steel_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust.mtl deleted file mode 100644 index 5861a12251..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust.mtl +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_blend.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_blend.tif deleted file mode 100644 index 7bd44ad5be..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_blend.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:d4fc3a6dc8729848be3fa54e544e146a324198c213d91031082f911f78c2a9df -size 3154182 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_blend.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_blend.tif.exportsettings deleted file mode 100644 index 8092b156b4..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_blend.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /mipgentype=box /preset=Albedo /reduce=1 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_ddna.tif deleted file mode 100644 index 3d13dc2fd6..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:3a673385f65153fdb1659a008229c333ccf972bf15268e051594abb97e129a20 -size 8397168 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_ddna.tif.exportsettings deleted file mode 100644 index a098bdcad9..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_diff.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_diff.tif deleted file mode 100644 index 9841bdb352..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:6170ca5d841592ca689316e268793094b8dde3705281ad7c9d942ed9dfd7343b -size 6299995 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_diff.tif.exportsettings deleted file mode 100644 index 19e899701a..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rust_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rusted_metal.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rusted_metal.mtl deleted file mode 100644 index 7ccf171972..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/rusted_metal.mtl +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/shiny_plastic.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/shiny_plastic.mtl deleted file mode 100644 index e62f3ca57b..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/shiny_plastic.mtl +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/silver_spec.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/silver_spec.tif deleted file mode 100644 index d50c32839a..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/silver_spec.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:9288cf57fb15fe106f335aa95910df01efa50eef2b69caf641c69640fc1f91e3 -size 793990 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/silver_spec.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/silver_spec.tif.exportsettings deleted file mode 100644 index 2bec812694..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/silver_spec.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Reflectance_Linear /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/afternoon.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/afternoon.tif deleted file mode 100644 index 9b8f9a20fb..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/afternoon.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ad6459c0fc86b2ef4f585505329a649eb30bc5940582b68d4dec0bf45aae3395 -size 6295912 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/evening.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/evening.tif deleted file mode 100644 index 9a637b17aa..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/evening.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:df24d58699c82f8581a8e787c12d3dadd6df97b165cb1d6f14fe68ed43ea31c0 -size 3150154 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/neutral.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/neutral.tif deleted file mode 100644 index 48ca954942..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/neutral.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4ddbd14843b551d8d4894fa85f4512c58505573ac0c8f14b1afe357abce21396 -size 3150190 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/night.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/night.tif deleted file mode 100644 index 8780f7fba0..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/night.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:2579027e45f1039a3b7cf253545aa166271556c2faf914cba9f5754577c49eaa -size 8393068 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/sky_afternoon.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/sky_afternoon.mtl deleted file mode 100644 index 76f9b83c9a..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/sky_afternoon.mtl +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/sky_evening.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/sky_evening.mtl deleted file mode 100644 index 4c72ff536f..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/sky_evening.mtl +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/sky_neutral.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/sky_neutral.mtl deleted file mode 100644 index 748c25929b..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/sky_neutral.mtl +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/sky_night.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/sky_night.mtl deleted file mode 100644 index d436db6ef2..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/skydomes/sky_night.mtl +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks.mtl deleted file mode 100644 index eb1dea0991..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks.mtl +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_ddna.tif deleted file mode 100644 index 0eaf9326d0..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bba137198cf4b87c822e12f0328dbc4ed9bc612521c7985913d6363f4e3291ab -size 33574348 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_ddna.tif.exportsettings deleted file mode 100644 index a098bdcad9..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce="android:1,ios:1,mac:1,pc:0,provo:1,wiiu:1" diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_diff.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_diff.tif deleted file mode 100644 index c919feeb0f..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_diff.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:76a8b871242fe618a5b5a11ddafa147890806759927606fe4dcc697c8e4d11d3 -size 25185676 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_diff.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_diff.tif.exportsettings deleted file mode 100644 index fb61d0f55c..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_diff.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Albedo /reduce=1 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_spec.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_spec.tif deleted file mode 100644 index 3dd863eb05..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_spec.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:bbd50f58c8e889272b5734f3eb63527a2a2d560ccacf69bb3326b6dc866aa01a -size 25185678 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_spec.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_spec.tif.exportsettings deleted file mode 100644 index c31be74648..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/wood_planks_spec.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=Reflectance /reduce=1 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_copper.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_copper.mtl deleted file mode 100644 index 1c522de4c3..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_copper.mtl +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_gold.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_gold.mtl deleted file mode 100644 index f81420b9aa..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_gold.mtl +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_metal.mtl b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_metal.mtl deleted file mode 100644 index d5300822cd..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_metal.mtl +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_metal_ddna.tif b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_metal_ddna.tif deleted file mode 100644 index 4d831687a4..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_metal_ddna.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:c84a16617421d986dbbd5c12393e6aef46de9d2898becfef6eb02d065b9d0bd0 -size 8400288 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_metal_ddna.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_metal_ddna.tif.exportsettings deleted file mode 100644 index 0159b6ca02..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/pbs_reference/worn_metal_ddna.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /M=50,50,0,50,50,50 /preset=NormalsWithSmoothness /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test.mtl b/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test.mtl deleted file mode 100644 index 25ea4b3171..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test.mtl +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_AO.tif b/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_AO.tif deleted file mode 100644 index ccebca85f8..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_AO.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:45358825d1fa0fed1a9fb7028d8361e58e5d96f1415d56aebe7c1ca0e410000a -size 12605680 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_AO.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_AO.tif.exportsettings deleted file mode 100644 index 25a6d5d697..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_AO.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Reflectance /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_H.tif b/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_H.tif deleted file mode 100644 index 5f89b4c33c..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_H.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:71d137d8fd428ae6191d7c97c9b48e92484975a8bc2b0e8704adab928eeb6650 -size 16798472 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_H.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_H.tif.exportsettings deleted file mode 100644 index 08f50cf38b..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_H.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /mipgentype=sigma-six /preset=Displacement /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_albedo.tif b/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_albedo.tif deleted file mode 100644 index 1e4fd75fd5..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_albedo.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:caf47b0db80678caa3673566150002420677e24e7e3bc77c9f3d95cac15433e3 -size 12609308 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_albedo.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_albedo.tif.exportsettings deleted file mode 100644 index 44cd6187b1..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_albedo.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Albedo /reduce=0 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_normals_ddn.tif b/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_normals_ddn.tif deleted file mode 100644 index c71f243adb..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_normals_ddn.tif +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:93a0842c8d0bb3ce1d5897e415820df48cf093ff9ea4369e2e9bfac5ea018259 -size 12602730 diff --git a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_normals_ddn.tif.exportsettings b/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_normals_ddn.tif.exportsettings deleted file mode 100644 index d1103c9959..0000000000 --- a/Gems/PBSreferenceMaterials/Assets/materials/test_reference/test_normals_ddn.tif.exportsettings +++ /dev/null @@ -1 +0,0 @@ -/autooptimizefile=0 /preset=Normals /reduce=0 diff --git a/Gems/PBSreferenceMaterials/CMakeLists.txt b/Gems/PBSreferenceMaterials/CMakeLists.txt deleted file mode 100644 index 76a911746c..0000000000 --- a/Gems/PBSreferenceMaterials/CMakeLists.txt +++ /dev/null @@ -1,12 +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 -# -# - -# This will export its "SourcePaths" to the generated "cmake_dependencies..assetbuilder.setreg" -if(PAL_TRAIT_BUILD_HOST_TOOLS) - ly_create_alias(NAME PBSreferenceMaterials.Builders NAMESPACE Gem) -endif() diff --git a/Gems/PBSreferenceMaterials/Resources/test_source.psd b/Gems/PBSreferenceMaterials/Resources/test_source.psd deleted file mode 100644 index 2f0ca41476..0000000000 --- a/Gems/PBSreferenceMaterials/Resources/test_source.psd +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:322e2360dd2a621fc733e171d676497d5351ade274df16d223ccf3b9df8c3382 -size 19277076 diff --git a/Gems/PBSreferenceMaterials/gem.json b/Gems/PBSreferenceMaterials/gem.json deleted file mode 100644 index feddc1e465..0000000000 --- a/Gems/PBSreferenceMaterials/gem.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "gem_name": "PBSreferenceMaterials", - "display_name": "PBS Reference Materials", - "license": "Apache-2.0 Or MIT", - "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" - ], - "icon_path": "preview.png", - "requirements": "", - "documentation_url": "https://o3de.org/docs/user-guide/gems/reference/rendering/pbs-reference-materials/", - "dependencies": [] -} diff --git a/Gems/PBSreferenceMaterials/preview.png b/Gems/PBSreferenceMaterials/preview.png deleted file mode 100644 index 51c277678f..0000000000 --- a/Gems/PBSreferenceMaterials/preview.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:097b03d36a65678b4e12e2c0830707480034fe31fe4efba9c848bb58440eb9fb -size 24928 diff --git a/engine.json b/engine.json index 63bddc9548..2b56e255fc 100644 --- a/engine.json +++ b/engine.json @@ -53,7 +53,6 @@ "Gems/Multiplayer", "Gems/MultiplayerCompression", "Gems/NvCloth", - "Gems/PBSreferenceMaterials", "Gems/PhysX", "Gems/PhysXDebug", "Gems/PhysXSamples", From 736c2fe27bab37239ccc0b29b55bbe918b35483a Mon Sep 17 00:00:00 2001 From: Junbo Liang <68558268+junbo75@users.noreply.github.com> Date: Tue, 12 Oct 2021 10:41:27 -0700 Subject: [PATCH 116/169] [O3DE][GameLift] Add client side change for starting and stopping matchmaking (#4536) * [O3DE][GameLift] Add client side change for starting and stopping matchmaking Signed-off-by: Junbo Liang --- .../Matchmaking/MatchmakingRequests.h | 1 + .../AWSGameLiftStartMatchmakingRequest.h | 3 + .../Source/AWSGameLiftClientManager.cpp | 109 +++++++- .../Source/AWSGameLiftClientManager.h | 4 + .../Activity/AWSGameLiftActivityUtils.cpp | 49 ++++ .../Activity/AWSGameLiftActivityUtils.h | 13 + .../AWSGameLiftStartMatchmakingActivity.cpp | 120 +++++++++ .../AWSGameLiftStartMatchmakingActivity.h | 34 +++ .../AWSGameLiftStopMatchmakingActivity.cpp | 61 +++++ .../AWSGameLiftStopMatchmakingActivity.h | 34 +++ .../Tests/AWSGameLiftClientManagerTest.cpp | 243 ++++++++++++++++++ .../Tests/AWSGameLiftClientMocks.h | 28 ++ ...WSGameLiftStartMatchmakingActivityTest.cpp | 152 +++++++++++ ...AWSGameLiftStopMatchmakingActivityTest.cpp | 38 +++ .../awsgamelift_client_files.cmake | 4 + .../awsgamelift_client_tests_files.cmake | 2 + 16 files changed, 890 insertions(+), 5 deletions(-) create mode 100644 Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.cpp create mode 100644 Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.h create mode 100644 Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStopMatchmakingActivity.cpp create mode 100644 Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStopMatchmakingActivity.h create mode 100644 Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStartMatchmakingActivityTest.cpp create mode 100644 Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStopMatchmakingActivityTest.cpp diff --git a/Code/Framework/AzFramework/AzFramework/Matchmaking/MatchmakingRequests.h b/Code/Framework/AzFramework/AzFramework/Matchmaking/MatchmakingRequests.h index 58e335696f..9169a83588 100644 --- a/Code/Framework/AzFramework/AzFramework/Matchmaking/MatchmakingRequests.h +++ b/Code/Framework/AzFramework/AzFramework/Matchmaking/MatchmakingRequests.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include namespace AZ diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Include/Request/AWSGameLiftStartMatchmakingRequest.h b/Gems/AWSGameLift/Code/AWSGameLiftClient/Include/Request/AWSGameLiftStartMatchmakingRequest.h index cd30bc45ab..d734daa808 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Include/Request/AWSGameLiftStartMatchmakingRequest.h +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Include/Request/AWSGameLiftStartMatchmakingRequest.h @@ -8,6 +8,9 @@ #pragma once +#include +#include + #include namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientManager.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientManager.cpp index ee731993aa..91e76380eb 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientManager.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientManager.cpp @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include @@ -43,10 +45,22 @@ namespace AWSGameLift AZ::Interface::Register(this); AWSGameLiftSessionRequestBus::Handler::BusConnect(); + + AZ::Interface::Register(this); + AWSGameLiftMatchmakingAsyncRequestBus::Handler::BusConnect(); + + AZ::Interface::Register(this); + AWSGameLiftMatchmakingRequestBus::Handler::BusConnect(); } void AWSGameLiftClientManager::DeactivateManager() { + AWSGameLiftMatchmakingRequestBus::Handler::BusDisconnect(); + AZ::Interface::Unregister(this); + + AWSGameLiftMatchmakingAsyncRequestBus::Handler::BusDisconnect(); + AZ::Interface::Unregister(this); + AWSGameLiftSessionRequestBus::Handler::BusDisconnect(); AZ::Interface::Unregister(this); @@ -357,23 +371,108 @@ namespace AWSGameLift AZStd::string AWSGameLiftClientManager::StartMatchmaking(const AzFramework::StartMatchmakingRequest& startMatchmakingRequest) { - AZ_UNUSED(startMatchmakingRequest); + AZStd::string response; + if (StartMatchmakingActivity::ValidateStartMatchmakingRequest(startMatchmakingRequest)) + { + const AWSGameLiftStartMatchmakingRequest& gameliftStartMatchmakingRequest = + static_cast(startMatchmakingRequest); + response = StartMatchmakingHelper(gameliftStartMatchmakingRequest); + } - return AZStd::string{}; + return response; } void AWSGameLiftClientManager::StartMatchmakingAsync(const AzFramework::StartMatchmakingRequest& startMatchmakingRequest) { - AZ_UNUSED(startMatchmakingRequest); + if (!StartMatchmakingActivity::ValidateStartMatchmakingRequest(startMatchmakingRequest)) + { + AzFramework::MatchmakingAsyncRequestNotificationBus::Broadcast( + &AzFramework::MatchmakingAsyncRequestNotifications::OnStartMatchmakingAsyncComplete, AZStd::string{}); + return; + } + + const AWSGameLiftStartMatchmakingRequest& gameliftStartMatchmakingRequest = + static_cast(startMatchmakingRequest); + + AZ::JobContext* jobContext = nullptr; + AWSCore::AWSCoreRequestBus::BroadcastResult(jobContext, &AWSCore::AWSCoreRequests::GetDefaultJobContext); + AZ::Job* startMatchmakingJob = AZ::CreateJobFunction( + [this, gameliftStartMatchmakingRequest]() + { + AZStd::string response = StartMatchmakingHelper(gameliftStartMatchmakingRequest); + + AzFramework::MatchmakingAsyncRequestNotificationBus::Broadcast( + &AzFramework::MatchmakingAsyncRequestNotifications::OnStartMatchmakingAsyncComplete, response); + }, + true, jobContext); + + startMatchmakingJob->Start(); + } + + AZStd::string AWSGameLiftClientManager::StartMatchmakingHelper(const AWSGameLiftStartMatchmakingRequest& startMatchmakingRequest) + { + auto gameliftClient = AZ::Interface::Get()->GetGameLiftClient(); + + AZStd::string response; + if (!gameliftClient) + { + AZ_Error(AWSGameLiftClientManagerName, false, AWSGameLiftClientMissingErrorMessage); + } + else + { + response = StartMatchmakingActivity::StartMatchmaking(*gameliftClient, startMatchmakingRequest); + } + return response; } void AWSGameLiftClientManager::StopMatchmaking(const AzFramework::StopMatchmakingRequest& stopMatchmakingRequest) { - AZ_UNUSED(stopMatchmakingRequest); + if (StopMatchmakingActivity::ValidateStopMatchmakingRequest(stopMatchmakingRequest)) + { + const AWSGameLiftStopMatchmakingRequest& gameliftStopMatchmakingRequest = + static_cast(stopMatchmakingRequest); + StopMatchmakingHelper(gameliftStopMatchmakingRequest); + } } void AWSGameLiftClientManager::StopMatchmakingAsync(const AzFramework::StopMatchmakingRequest& stopMatchmakingRequest) { - AZ_UNUSED(stopMatchmakingRequest); + if (!StopMatchmakingActivity::ValidateStopMatchmakingRequest(stopMatchmakingRequest)) + { + AzFramework::MatchmakingAsyncRequestNotificationBus::Broadcast( + &AzFramework::MatchmakingAsyncRequestNotifications::OnStopMatchmakingAsyncComplete); + return; + } + + const AWSGameLiftStopMatchmakingRequest& gameliftStopMatchmakingRequest = + static_cast(stopMatchmakingRequest); + + AZ::JobContext* jobContext = nullptr; + AWSCore::AWSCoreRequestBus::BroadcastResult(jobContext, &AWSCore::AWSCoreRequests::GetDefaultJobContext); + AZ::Job* stopMatchmakingJob = AZ::CreateJobFunction( + [this, gameliftStopMatchmakingRequest]() + { + StopMatchmakingHelper(gameliftStopMatchmakingRequest); + + AzFramework::MatchmakingAsyncRequestNotificationBus::Broadcast( + &AzFramework::MatchmakingAsyncRequestNotifications::OnStopMatchmakingAsyncComplete); + }, + true, jobContext); + + stopMatchmakingJob->Start(); + } + + void AWSGameLiftClientManager::StopMatchmakingHelper(const AWSGameLiftStopMatchmakingRequest& stopMatchmakingRequest) + { + auto gameliftClient = AZ::Interface::Get()->GetGameLiftClient(); + + if (!gameliftClient) + { + AZ_Error(AWSGameLiftClientManagerName, false, AWSGameLiftClientMissingErrorMessage); + } + else + { + StopMatchmakingActivity::StopMatchmaking(*gameliftClient, stopMatchmakingRequest); + } } } // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientManager.h b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientManager.h index fbdc1d6104..ba81196b07 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientManager.h +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientManager.h @@ -19,6 +19,8 @@ namespace AWSGameLift struct AWSGameLiftCreateSessionOnQueueRequest; struct AWSGameLiftJoinSessionRequest; struct AWSGameLiftSearchSessionsRequest; + struct AWSGameLiftStartMatchmakingRequest; + struct AWSGameLiftStopMatchmakingRequest; // MatchAcceptanceNotificationBus EBus handler for scripting class AWSGameLiftMatchAcceptanceNotificationBusHandler @@ -160,5 +162,7 @@ namespace AWSGameLift AZStd::string CreateSessionOnQueueHelper(const AWSGameLiftCreateSessionOnQueueRequest& createSessionOnQueueRequest); bool JoinSessionHelper(const AWSGameLiftJoinSessionRequest& joinSessionRequest); AzFramework::SearchSessionsResponse SearchSessionsHelper(const AWSGameLiftSearchSessionsRequest& searchSessionsRequest) const; + AZStd::string StartMatchmakingHelper(const AWSGameLiftStartMatchmakingRequest& startMatchmakingRequest); + void StopMatchmakingHelper(const AWSGameLiftStopMatchmakingRequest& stopMatchmakingRequest); }; } // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftActivityUtils.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftActivityUtils.cpp index 5bbd1d4654..f9968a7dd9 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftActivityUtils.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftActivityUtils.cpp @@ -6,6 +6,7 @@ * */ +#include #include namespace AWSGameLift @@ -31,5 +32,53 @@ namespace AWSGameLift outGamePropertiesOutput.substr(0, outGamePropertiesOutput.size() - 1); // Trim last comma to fit array format } } + + void ConvertPlayerAttributes( + const AZStd::unordered_map& playerAttributes, + Aws::Map& outPlayerAttributes) + { + outPlayerAttributes.clear(); + for (auto& playerAttribute : playerAttributes) + { + Aws::Utils::Json::JsonValue keyJsonValue(playerAttribute.second.c_str()); + Aws::GameLift::Model::AttributeValue attribute(keyJsonValue); + outPlayerAttributes[playerAttribute.first.c_str()] = attribute; + } + } + + void ConvertRegionToLatencyMap( + const AZStd::unordered_map& regionToLatencyMap, + Aws::Map& outRegionToLatencyMap) + { + outRegionToLatencyMap.clear(); + for (auto& regionToLatencyPair : regionToLatencyMap) + { + outRegionToLatencyMap[regionToLatencyPair.first.c_str()] = regionToLatencyPair.second; + } + } + + bool ValidatePlayerAttributes( + const AZStd::unordered_map& playerAttributes) + { + for (auto& playerAttribute : playerAttributes) + { + Aws::Utils::Json::JsonValue keyJsonValue(playerAttribute.second.c_str()); + Aws::GameLift::Model::AttributeValue attribute(keyJsonValue); + + // Each AttributeValue object can use only one of the available properties: + // 1) number values (N) + // 2) single string values (S) + // 3) string to double map (SDM) + // 4) array of strings (SL) + if (!attribute.SHasBeenSet() && + !attribute.NHasBeenSet() && + !attribute.SDMHasBeenSet() && + !attribute.SLHasBeenSet()) + { + return false; + } + } + return true; + } } // namespace AWSGameLiftActivityUtils } // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftActivityUtils.h b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftActivityUtils.h index 05ab2867d0..729f1deec6 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftActivityUtils.h +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftActivityUtils.h @@ -12,6 +12,7 @@ #include #include #include +#include namespace AWSGameLift { @@ -21,5 +22,17 @@ namespace AWSGameLift const AZStd::unordered_map& sessionProperties, Aws::Vector& outGameProperties, AZStd::string& outGamePropertiesOutput); + + void ConvertPlayerAttributes( + const AZStd::unordered_map& playerAttributes, + Aws::Map& outPlayerAttributes); + + void ConvertRegionToLatencyMap( + const AZStd::unordered_map& regionToLatencyMap, + Aws::Map& outRegionToLatencyMap); + + bool ValidatePlayerAttributes( + const AZStd::unordered_map& playerAttributes); + } // namespace AWSGameLiftActivityUtils } // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.cpp new file mode 100644 index 0000000000..2b2a32f74b --- /dev/null +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.cpp @@ -0,0 +1,120 @@ +/* + * 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 AWSGameLift +{ + namespace StartMatchmakingActivity + { + Aws::GameLift::Model::StartMatchmakingRequest BuildAWSGameLiftStartMatchmakingRequest( + const AWSGameLiftStartMatchmakingRequest& startMatchmakingRequest) + { + Aws::GameLift::Model::StartMatchmakingRequest request; + if (!startMatchmakingRequest.m_configurationName.empty()) + { + request.SetConfigurationName(startMatchmakingRequest.m_configurationName.c_str()); + } + + Aws::Vector players; + for (const AWSGameLiftPlayerInformation& playerInfo : startMatchmakingRequest.m_players) + { + Aws::GameLift::Model::Player player; + if (!playerInfo.m_playerId.empty()) + { + player.SetPlayerId(playerInfo.m_playerId.c_str()); + } + + // Optional attributes + if (!playerInfo.m_team.empty()) + { + player.SetTeam(playerInfo.m_team.c_str()); + } + if (playerInfo.m_latencyInMs.size() > 0) + { + Aws::Map regionToLatencyMap; + AWSGameLiftActivityUtils::ConvertRegionToLatencyMap(playerInfo.m_latencyInMs, regionToLatencyMap); + player.SetLatencyInMs(AZStd::move(regionToLatencyMap)); + } + if (playerInfo.m_playerAttributes.size() > 0) + { + Aws::Map playerAttributes; + AWSGameLiftActivityUtils::ConvertPlayerAttributes(playerInfo.m_playerAttributes, playerAttributes); + player.SetPlayerAttributes(AZStd::move(playerAttributes)); + } + players.emplace_back(player); + } + if (startMatchmakingRequest.m_players.size() > 0) + { + request.SetPlayers(players); + } + + // Optional attributes + if (!startMatchmakingRequest.m_ticketId.empty()) + { + request.SetTicketId(startMatchmakingRequest.m_ticketId.c_str()); + } + + AZ_TracePrintf(AWSGameLiftStartMatchmakingActivityName, + "Built StartMatchmakingRequest with TicketId=%s, ConfigurationName=%s and PlayersCount=%d", + request.GetTicketId().c_str(), + request.GetConfigurationName().c_str(), + request.GetPlayers().size()); + + return request; + } + + AZStd::string StartMatchmaking( + const Aws::GameLift::GameLiftClient& gameliftClient, + const AWSGameLiftStartMatchmakingRequest& startMatchmakingRequest) + { + AZ_TracePrintf(AWSGameLiftStartMatchmakingActivityName, "Requesting StartMatchmaking against Amazon GameLift service ..."); + + AZStd::string result = ""; + Aws::GameLift::Model::StartMatchmakingRequest request = BuildAWSGameLiftStartMatchmakingRequest(startMatchmakingRequest); + auto startMatchmakingOutcome = gameliftClient.StartMatchmaking(request); + if (startMatchmakingOutcome.IsSuccess()) + { + result = AZStd::string(startMatchmakingOutcome.GetResult().GetMatchmakingTicket().GetTicketId().c_str()); + + AZ_TracePrintf(AWSGameLiftStartMatchmakingActivityName, "StartMatchmaking request against Amazon GameLift service is complete"); + } + else + { + AZ_Error(AWSGameLiftStartMatchmakingActivityName, false, AWSGameLiftErrorMessageTemplate, + startMatchmakingOutcome.GetError().GetExceptionName().c_str(), startMatchmakingOutcome.GetError().GetMessage().c_str()); + } + + return result; + } + + bool ValidateStartMatchmakingRequest(const AzFramework::StartMatchmakingRequest& startMatchmakingRequest) + { + auto gameliftStartMatchmakingRequest = azrtti_cast(&startMatchmakingRequest); + bool isValid = gameliftStartMatchmakingRequest && + (!gameliftStartMatchmakingRequest->m_configurationName.empty()) && + gameliftStartMatchmakingRequest->m_players.size() > 0; + + if (isValid) + { + for (const AWSGameLiftPlayerInformation& playerInfo : gameliftStartMatchmakingRequest->m_players) + { + isValid &= !playerInfo.m_playerId.empty(); + isValid &= AWSGameLiftActivityUtils::ValidatePlayerAttributes(playerInfo.m_playerAttributes); + } + } + + AZ_Error(AWSGameLiftStartMatchmakingActivityName, isValid, AWSGameLiftStartMatchmakingRequestInvalidErrorMessage); + + return isValid; + } + } // namespace StartMatchmakingActivity +} // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.h b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.h new file mode 100644 index 0000000000..5f8c4558f4 --- /dev/null +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.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 + +#include +#include +#include + +namespace AWSGameLift +{ + namespace StartMatchmakingActivity + { + static constexpr const char AWSGameLiftStartMatchmakingActivityName[] = "AWSGameLiftStartMatchmakingActivity"; + static constexpr const char AWSGameLiftStartMatchmakingRequestInvalidErrorMessage[] = "Invalid GameLift StartMatchmaking request."; + + // Build AWS GameLift StartMatchmakingRequest by using AWSGameLiftStartMatchmakingRequest + Aws::GameLift::Model::StartMatchmakingRequest BuildAWSGameLiftStartMatchmakingRequest(const AWSGameLiftStartMatchmakingRequest& startMatchmakingRequest); + + // Create StartMatchmakingRequest and make a StartMatchmaking call through GameLift client + // Will also start polling the matchmaking ticket when get success outcome from GameLift client + AZStd::string StartMatchmaking(const Aws::GameLift::GameLiftClient& gameliftClient, const AWSGameLiftStartMatchmakingRequest& startMatchmakingRequest); + + // Validate StartMatchmakingRequest and check required request parameters + bool ValidateStartMatchmakingRequest(const AzFramework::StartMatchmakingRequest& startMatchmakingRequest); + } // namespace StartMatchmakingActivity +} // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStopMatchmakingActivity.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStopMatchmakingActivity.cpp new file mode 100644 index 0000000000..204923fc02 --- /dev/null +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStopMatchmakingActivity.cpp @@ -0,0 +1,61 @@ +/* + * 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.StopMatchmaking + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +#include +#include + +namespace AWSGameLift +{ + namespace StopMatchmakingActivity + { + Aws::GameLift::Model::StopMatchmakingRequest BuildAWSGameLiftStopMatchmakingRequest( + const AWSGameLiftStopMatchmakingRequest& stopMatchmakingRequest) + { + Aws::GameLift::Model::StopMatchmakingRequest request; + if (!stopMatchmakingRequest.m_ticketId.empty()) + { + request.SetTicketId(stopMatchmakingRequest.m_ticketId.c_str()); + } + + AZ_TracePrintf(AWSGameLiftStopMatchmakingActivityName, "Built StopMatchmakingRequest with TicketId=%s", request.GetTicketId().c_str()); + + return request; + } + + void StopMatchmaking(const Aws::GameLift::GameLiftClient& gameliftClient, + const AWSGameLiftStopMatchmakingRequest& stopMatchmakingRequest) + { + AZ_TracePrintf(AWSGameLiftStopMatchmakingActivityName, "Requesting StopMatchmaking against Amazon GameLift service ..."); + + Aws::GameLift::Model::StopMatchmakingRequest request = BuildAWSGameLiftStopMatchmakingRequest(stopMatchmakingRequest); + auto stopMatchmakingOutcome = gameliftClient.StopMatchmaking(request); + + if (stopMatchmakingOutcome.IsSuccess()) + { + AZ_TracePrintf(AWSGameLiftStopMatchmakingActivityName, "StopMatchmaking request against Amazon GameLift service is complete"); + } + else + { + AZ_Error(AWSGameLiftStopMatchmakingActivityName, false, AWSGameLiftErrorMessageTemplate, + stopMatchmakingOutcome.GetError().GetExceptionName().c_str(), stopMatchmakingOutcome.GetError().GetMessage().c_str()); + } + } + + bool ValidateStopMatchmakingRequest(const AzFramework::StopMatchmakingRequest& StopMatchmakingRequest) + { + auto gameliftStopMatchmakingRequest = azrtti_cast(&StopMatchmakingRequest); + bool isValid = gameliftStopMatchmakingRequest && (!gameliftStopMatchmakingRequest->m_ticketId.empty()); + + AZ_Error(AWSGameLiftStopMatchmakingActivityName, isValid, AWSGameLiftStopMatchmakingRequestInvalidErrorMessage); + + return isValid; + } + } // namespace StopMatchmakingActivity +} // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStopMatchmakingActivity.h b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStopMatchmakingActivity.h new file mode 100644 index 0000000000..9bfeb86343 --- /dev/null +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStopMatchmakingActivity.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 + +#include +#include +#include + +namespace AWSGameLift +{ + namespace StopMatchmakingActivity + { + static constexpr const char AWSGameLiftStopMatchmakingActivityName[] = "AWSGameLiftStopMatchmakingActivity"; + static constexpr const char AWSGameLiftStopMatchmakingRequestInvalidErrorMessage[] = "Invalid GameLift StopMatchmaking request."; + + // Build AWS GameLift StopMatchmakingRequest by using AWSGameLiftStopMatchmakingRequest + Aws::GameLift::Model::StopMatchmakingRequest BuildAWSGameLiftStopMatchmakingRequest(const AWSGameLiftStopMatchmakingRequest& stopMatchmakingRequest); + + // Create StopMatchmakingRequest and make a StopMatchmaking call through GameLift client + // Will also stop polling the matchmaking ticket when get success outcome from GameLift client + void StopMatchmaking(const Aws::GameLift::GameLiftClient& gameliftClient, const AWSGameLiftStopMatchmakingRequest& stopMatchmakingRequest); + + // Validate StopMatchmakingRequest and check required request parameters + bool ValidateStopMatchmakingRequest(const AzFramework::StopMatchmakingRequest& stopMatchmakingRequest); + } // namespace StopMatchmakingActivity +} // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientManagerTest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientManagerTest.cpp index e7612618ee..2fa332df72 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientManagerTest.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientManagerTest.cpp @@ -24,6 +24,8 @@ #include #include #include +#include +#include using namespace AWSGameLift; @@ -223,11 +225,43 @@ protected: return response; } + AWSGameLiftStartMatchmakingRequest GetValidStartMatchmakingRequest() + { + AWSGameLiftStartMatchmakingRequest request; + request.m_configurationName = "dummyConfiguration"; + request.m_ticketId = DummyMatchmakingTicketId; + + AWSGameLiftPlayerInformation player; + player.m_playerAttributes["dummy"] = "{\"N\": \"1\"}"; + player.m_playerId = DummyPlayerId; + player.m_latencyInMs["us-east-1"] = 10; + request.m_players.emplace_back(player); + + return request; + } + + Aws::GameLift::Model::StartMatchmakingOutcome GetValidStartMatchmakingResponse() + { + Aws::GameLift::Model::MatchmakingTicket ticket; + ticket.SetTicketId(DummyMatchmakingTicketId); + Aws::GameLift::Model::StartMatchmakingResult result; + result.SetMatchmakingTicket(ticket); + Aws::GameLift::Model::StartMatchmakingOutcome outcome(result); + + return outcome; + } + + static const char* const DummyMatchmakingTicketId; + static const char* const DummyPlayerId; + public: AZStd::unique_ptr m_gameliftClientManager; AZStd::shared_ptr m_gameliftClientMockPtr; }; +const char* const AWSGameLiftClientManagerTest::DummyMatchmakingTicketId = "dummyTicketId"; +const char* const AWSGameLiftClientManagerTest::DummyPlayerId = "dummyPlayerId"; + TEST_F(AWSGameLiftClientManagerTest, ConfigureGameLiftClient_CallWithoutRegion_GetFalseAsResult) { AZ_TEST_START_TRACE_SUPPRESSION; @@ -762,3 +796,212 @@ TEST_F(AWSGameLiftClientManagerTest, LeaveSessionAsync_CallWithInterfaceRegister m_gameliftClientManager->LeaveSessionAsync(); } + +TEST_F(AWSGameLiftClientManagerTest, StartMatchmaking_CallWithoutClientSetup_GetFalseResponse) +{ + AWSGameLiftStartMatchmakingRequest request = GetValidStartMatchmakingRequest(); + + AZ_TEST_START_TRACE_SUPPRESSION; + m_gameliftClientManager->ConfigureGameLiftClient(""); + AZStd::string response = m_gameliftClientManager->StartMatchmaking(request); + AZ_TEST_STOP_TRACE_SUPPRESSION(2); // capture 2 error message + EXPECT_TRUE(response.empty()); + +} +TEST_F(AWSGameLiftClientManagerTest, StartMatchmaking_CallWithInvalidRequest_GetErrorWithEmptyResponse) +{ + AWSGameLiftStartMatchmakingRequest request; + request.m_configurationName = "dummyConfiguration"; + AWSGameLiftPlayerInformation player; + player.m_playerAttributes["dummy"] = "{\"A\": \"1\"}"; + request.m_players.emplace_back(player); + + AZ_TEST_START_TRACE_SUPPRESSION; + AZStd::string response = m_gameliftClientManager->StartMatchmaking(request); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message + EXPECT_TRUE(response.empty()); +} + +TEST_F(AWSGameLiftClientManagerTest, StartMatchmaking_CallWithValidRequest_GetSuccessOutcome) +{ + AWSGameLiftStartMatchmakingRequest request = GetValidStartMatchmakingRequest(); + Aws::GameLift::Model::StartMatchmakingOutcome outcome = GetValidStartMatchmakingResponse(); + + EXPECT_CALL(*m_gameliftClientMockPtr, StartMatchmaking(::testing::_)) + .Times(1) + .WillOnce(::testing::Return(outcome)); + + AZStd::string response = m_gameliftClientManager->StartMatchmaking(request); + EXPECT_EQ(response, DummyMatchmakingTicketId); +} + +TEST_F(AWSGameLiftClientManagerTest, StartMatchmaking_CallWithValidRequest_GetErrorOutcome) +{ + AWSGameLiftStartMatchmakingRequest request = GetValidStartMatchmakingRequest(); + + Aws::Client::AWSError error; + Aws::GameLift::Model::StartMatchmakingOutcome outcome(error); + + EXPECT_CALL(*m_gameliftClientMockPtr, StartMatchmaking(::testing::_)) + .Times(1) + .WillOnce(::testing::Return(outcome)); + AZ_TEST_START_TRACE_SUPPRESSION; + m_gameliftClientManager->StartMatchmaking(request); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftClientManagerTest, StartMatchmakingAsync_CallWithInvalidRequest_GetNotificationWithErrorOutcome) +{ + AWSGameLiftStartMatchmakingRequest request; + request.m_configurationName = "dummyConfiguration"; + AWSGameLiftPlayerInformation player; + player.m_playerAttributes["dummy"] = "{\"A\": \"1\"}"; + request.m_players.emplace_back(player); + + MatchmakingAsyncRequestNotificationsHandlerMock matchmakingHandlerMock; + EXPECT_CALL(matchmakingHandlerMock, OnStartMatchmakingAsyncComplete(AZStd::string{})).Times(1); + + AZ_TEST_START_TRACE_SUPPRESSION; + m_gameliftClientManager->StartMatchmakingAsync(request); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftClientManagerTest, StartMatchmakingAsync_CallWithValidRequest_GetNotificationWithSuccessOutcome) +{ + AWSCoreRequestsHandlerMock handlerMock; + EXPECT_CALL(handlerMock, GetDefaultJobContext()).Times(1).WillOnce(::testing::Return(m_jobContext.get())); + + AWSGameLiftStartMatchmakingRequest request = GetValidStartMatchmakingRequest(); + Aws::GameLift::Model::StartMatchmakingOutcome outcome = GetValidStartMatchmakingResponse(); + + EXPECT_CALL(*m_gameliftClientMockPtr, StartMatchmaking(::testing::_)) + .Times(1) + .WillOnce(::testing::Return(outcome)); + + MatchmakingAsyncRequestNotificationsHandlerMock matchmakingHandlerMock; + EXPECT_CALL(matchmakingHandlerMock, OnStartMatchmakingAsyncComplete(AZStd::string(DummyMatchmakingTicketId))).Times(1); + + m_gameliftClientManager->StartMatchmakingAsync(request); +} + +TEST_F(AWSGameLiftClientManagerTest, StartMatchmakingAsync_CallWithValidRequest_GetNotificationWithErrorOutcome) +{ + AWSCoreRequestsHandlerMock handlerMock; + EXPECT_CALL(handlerMock, GetDefaultJobContext()).Times(1).WillOnce(::testing::Return(m_jobContext.get())); + + AWSGameLiftStartMatchmakingRequest request = GetValidStartMatchmakingRequest(); + + Aws::Client::AWSError error; + Aws::GameLift::Model::StartMatchmakingOutcome outcome(error); + EXPECT_CALL(*m_gameliftClientMockPtr, StartMatchmaking(::testing::_)) + .Times(1) + .WillOnce(::testing::Return(outcome)); + + MatchmakingAsyncRequestNotificationsHandlerMock matchmakingHandlerMock; + EXPECT_CALL(matchmakingHandlerMock, OnStartMatchmakingAsyncComplete(AZStd::string{})).Times(1); + + AZ_TEST_START_TRACE_SUPPRESSION; + m_gameliftClientManager->StartMatchmakingAsync(request); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftClientManagerTest, StopMatchmaking_CallWithoutClientSetup_GetError) +{ + AZ_TEST_START_TRACE_SUPPRESSION; + m_gameliftClientManager->ConfigureGameLiftClient(""); + AWSGameLiftStopMatchmakingRequest request; + request.m_ticketId = DummyMatchmakingTicketId; + + m_gameliftClientManager->StopMatchmaking(request); + AZ_TEST_STOP_TRACE_SUPPRESSION(2); // capture 2 error message +} +TEST_F(AWSGameLiftClientManagerTest, StopMatchmaking_CallWithInvalidRequest_GetError) +{ + AZ_TEST_START_TRACE_SUPPRESSION; + m_gameliftClientManager->StopMatchmaking(AzFramework::StopMatchmakingRequest()); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftClientManagerTest, StopMatchmaking_CallWithValidRequest_Success) +{ + AWSGameLiftStopMatchmakingRequest request; + request.m_ticketId = DummyMatchmakingTicketId; + + Aws::GameLift::Model::StopMatchmakingResult result; + Aws::GameLift::Model::StopMatchmakingResult outcome(result); + EXPECT_CALL(*m_gameliftClientMockPtr, StopMatchmaking(::testing::_)) + .Times(1) + .WillOnce(::testing::Return(outcome)); + + m_gameliftClientManager->StopMatchmaking(request); +} + +TEST_F(AWSGameLiftClientManagerTest, StopMatchmaking_CallWithValidRequest_GetError) +{ + AWSGameLiftStopMatchmakingRequest request; + request.m_ticketId = DummyMatchmakingTicketId; + + Aws::Client::AWSError error; + Aws::GameLift::Model::StopMatchmakingOutcome outcome(error); + + EXPECT_CALL(*m_gameliftClientMockPtr, StopMatchmaking(::testing::_)) + .Times(1) + .WillOnce(::testing::Return(outcome)); + AZ_TEST_START_TRACE_SUPPRESSION; + m_gameliftClientManager->StopMatchmaking(request); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftClientManagerTest, StopMatchmakingAsync_CallWithInvalidRequest_GetNotificationWithError) +{ + AWSGameLiftStopMatchmakingRequest request; + + MatchmakingAsyncRequestNotificationsHandlerMock matchmakingHandlerMock; + EXPECT_CALL(matchmakingHandlerMock, OnStopMatchmakingAsyncComplete()).Times(1); + + AZ_TEST_START_TRACE_SUPPRESSION; + m_gameliftClientManager->StopMatchmakingAsync(request); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftClientManagerTest, StopMatchmakingAsync_CallWithValidRequest_GetNotification) +{ + AWSCoreRequestsHandlerMock handlerMock; + EXPECT_CALL(handlerMock, GetDefaultJobContext()).Times(1).WillOnce(::testing::Return(m_jobContext.get())); + + AWSGameLiftStopMatchmakingRequest request; + request.m_ticketId = DummyMatchmakingTicketId; + + Aws::GameLift::Model::StopMatchmakingResult result; + Aws::GameLift::Model::StopMatchmakingOutcome outcome(result); + EXPECT_CALL(*m_gameliftClientMockPtr, StopMatchmaking(::testing::_)) + .Times(1) + .WillOnce(::testing::Return(outcome)); + + MatchmakingAsyncRequestNotificationsHandlerMock matchmakingHandlerMock; + EXPECT_CALL(matchmakingHandlerMock, OnStopMatchmakingAsyncComplete()).Times(1); + + m_gameliftClientManager->StopMatchmakingAsync(request); +} + +TEST_F(AWSGameLiftClientManagerTest, StopMatchmakingAsync_CallWithValidRequest_GetNotificationWithError) +{ + AWSCoreRequestsHandlerMock handlerMock; + EXPECT_CALL(handlerMock, GetDefaultJobContext()).Times(1).WillOnce(::testing::Return(m_jobContext.get())); + + AWSGameLiftStopMatchmakingRequest request; + request.m_ticketId = DummyMatchmakingTicketId; + + Aws::Client::AWSError error; + Aws::GameLift::Model::StopMatchmakingOutcome outcome(error); + EXPECT_CALL(*m_gameliftClientMockPtr, StopMatchmaking(::testing::_)) + .Times(1) + .WillOnce(::testing::Return(outcome)); + + MatchmakingAsyncRequestNotificationsHandlerMock matchmakingHandlerMock; + EXPECT_CALL(matchmakingHandlerMock, OnStopMatchmakingAsyncComplete()).Times(1); + + AZ_TEST_START_TRACE_SUPPRESSION; + m_gameliftClientManager->StopMatchmakingAsync(request); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientMocks.h b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientMocks.h index 5c09f43e08..964b6a21c2 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientMocks.h +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientMocks.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -27,6 +28,12 @@ #include #include #include +#include +#include +#include +#include + +#include using namespace Aws::GameLift; @@ -44,6 +51,27 @@ public: MOCK_CONST_METHOD1(DescribeMatchmaking, Model::DescribeMatchmakingOutcome(const Model::DescribeMatchmakingRequest&)); MOCK_CONST_METHOD1(SearchGameSessions, Model::SearchGameSessionsOutcome(const Model::SearchGameSessionsRequest&)); MOCK_CONST_METHOD1(StartGameSessionPlacement, Model::StartGameSessionPlacementOutcome(const Model::StartGameSessionPlacementRequest&)); + MOCK_CONST_METHOD1(StartMatchmaking, Model::StartMatchmakingOutcome(const Model::StartMatchmakingRequest&)); + MOCK_CONST_METHOD1(StopMatchmaking, Model::StopMatchmakingOutcome(const Model::StopMatchmakingRequest&)); +}; + +class MatchmakingAsyncRequestNotificationsHandlerMock + : public AzFramework::MatchmakingAsyncRequestNotificationBus::Handler +{ +public: + MatchmakingAsyncRequestNotificationsHandlerMock() + { + AzFramework::MatchmakingAsyncRequestNotificationBus::Handler::BusConnect(); + } + + ~MatchmakingAsyncRequestNotificationsHandlerMock() + { + AzFramework::MatchmakingAsyncRequestNotificationBus::Handler::BusDisconnect(); + } + + MOCK_METHOD0(OnAcceptMatchAsyncComplete, void()); + MOCK_METHOD1(OnStartMatchmakingAsyncComplete, void(const AZStd::string&)); + MOCK_METHOD0(OnStopMatchmakingAsyncComplete, void()); }; class SessionAsyncRequestNotificationsHandlerMock diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStartMatchmakingActivityTest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStartMatchmakingActivityTest.cpp new file mode 100644 index 0000000000..706aec04f2 --- /dev/null +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStartMatchmakingActivityTest.cpp @@ -0,0 +1,152 @@ +/* + * 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 + +using namespace AWSGameLift; + +using AWSGameLiftStartMatchmakingActivityTest = AWSGameLiftClientFixture; + +TEST_F(AWSGameLiftStartMatchmakingActivityTest, BuildAWSGameLiftStartMatchmakingRequest_Call_GetExpectedResult) +{ + AWSGameLiftStartMatchmakingRequest request; + request.m_configurationName = "dummyConfiguration"; + request.m_ticketId = "dummyTicketId"; + + AWSGameLiftPlayerInformation player; + player.m_playerAttributes["dummy"] = "{\"S\": \"test\"}"; + player.m_playerId = "dummyPlayerId"; + player.m_team = "dummyTeam"; + player.m_latencyInMs["us-east-1"] = 10; + request.m_players.emplace_back(player); + auto awsRequest = StartMatchmakingActivity::BuildAWSGameLiftStartMatchmakingRequest(request); + + EXPECT_TRUE(strcmp(awsRequest.GetConfigurationName().c_str(), request.m_configurationName.c_str()) == 0); + EXPECT_TRUE(strcmp(awsRequest.GetTicketId().c_str(), request.m_ticketId.c_str()) == 0); + + EXPECT_TRUE(awsRequest.GetPlayers().size() == request.m_players.size()); + EXPECT_TRUE(strcmp(awsRequest.GetPlayers()[0].GetPlayerId().c_str(), request.m_players[0].m_playerId.c_str()) == 0); + EXPECT_TRUE(strcmp(awsRequest.GetPlayers()[0].GetTeam().c_str(), request.m_players[0].m_team.c_str()) == 0); + + EXPECT_TRUE(awsRequest.GetPlayers()[0].GetLatencyInMs().size() == request.m_players[0].m_latencyInMs.size()); + EXPECT_TRUE(strcmp(awsRequest.GetPlayers()[0].GetLatencyInMs().begin()->first.c_str(), request.m_players[0].m_latencyInMs.begin()->first.c_str()) == 0); + EXPECT_TRUE(awsRequest.GetPlayers()[0].GetLatencyInMs().begin()->second == request.m_players[0].m_latencyInMs.begin()->second); + + EXPECT_TRUE(awsRequest.GetPlayers()[0].GetPlayerAttributes().size() == request.m_players[0].m_playerAttributes.size()); + EXPECT_TRUE(strcmp(awsRequest.GetPlayers()[0].GetPlayerAttributes().begin()->first.c_str(), request.m_players[0].m_playerAttributes.begin()->first.c_str()) == 0); + EXPECT_TRUE(strcmp(awsRequest.GetPlayers()[0].GetPlayerAttributes().begin()->second.GetS().c_str(), "test") == 0); +} + +TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_CallWithBaseType_GetFalseResult) +{ + AZ_TEST_START_TRACE_SUPPRESSION; + auto result = StartMatchmakingActivity::ValidateStartMatchmakingRequest(AzFramework::StartMatchmakingRequest()); + EXPECT_FALSE(result); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_CallWithoutConfigurationName_GetFalseResult) +{ + AWSGameLiftStartMatchmakingRequest request; + request.m_ticketId = "dummyTicketId"; + + AWSGameLiftPlayerInformation player; + player.m_playerAttributes["dummy"] = "{\"S\": \"test\"}"; + player.m_playerId = "dummyPlayerId"; + player.m_team = "dummyTeam"; + player.m_latencyInMs["us-east-1"] = 10; + request.m_players.emplace_back(player); + + AZ_TEST_START_TRACE_SUPPRESSION; + auto result = StartMatchmakingActivity::ValidateStartMatchmakingRequest(request); + EXPECT_FALSE(result); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_CallWithoutPlayers_GetFalseResult) +{ + AWSGameLiftStartMatchmakingRequest request; + request.m_configurationName = "dummyConfiguration"; + request.m_ticketId = "dummyTicketId"; + + AZ_TEST_START_TRACE_SUPPRESSION; + auto result = StartMatchmakingActivity::ValidateStartMatchmakingRequest(request); + EXPECT_FALSE(result); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_CallWithoutPlayerId_GetFalseResult) +{ + AWSGameLiftStartMatchmakingRequest request; + request.m_configurationName = "dummyConfiguration"; + request.m_ticketId = "dummyTicketId"; + + AWSGameLiftPlayerInformation player; + player.m_playerAttributes["dummy"] = "{\"S\": \"test\"}"; + player.m_team = "dummyTeam"; + player.m_latencyInMs["us-east-1"] = 10; + request.m_players.emplace_back(player); + + AZ_TEST_START_TRACE_SUPPRESSION; + auto result = StartMatchmakingActivity::ValidateStartMatchmakingRequest(request); + EXPECT_FALSE(result); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_CallWithInvalidPlayerAttribute_GetFalseResult) +{ + AWSGameLiftStartMatchmakingRequest request; + request.m_configurationName = "dummyConfiguration"; + request.m_ticketId = "dummyTicketId"; + + AWSGameLiftPlayerInformation player; + player.m_playerAttributes["dummy"] = "{\"A\": \"test\"}"; + player.m_playerId = "dummyPlayerId"; + player.m_team = "dummyTeam"; + player.m_latencyInMs["us-east-1"] = 10; + request.m_players.emplace_back(player); + + AZ_TEST_START_TRACE_SUPPRESSION; + auto result = StartMatchmakingActivity::ValidateStartMatchmakingRequest(request); + EXPECT_FALSE(result); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_CallWithoutTicketId_GetTrueResult) +{ + AWSGameLiftStartMatchmakingRequest request; + request.m_configurationName = "dummyConfiguration"; + + AWSGameLiftPlayerInformation player; + player.m_playerAttributes["dummy"] = "{\"S\": \"test\"}"; + player.m_playerId = "dummyPlayerId"; + player.m_team = "dummyTeam"; + player.m_latencyInMs["us-east-1"] = 10; + request.m_players.emplace_back(player); + + auto result = StartMatchmakingActivity::ValidateStartMatchmakingRequest(request); + EXPECT_TRUE(result); +} + +TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_CallWithValidParameters_GetTrueResult) +{ + AWSGameLiftStartMatchmakingRequest request; + request.m_ticketId = "dummyTicketId"; + request.m_configurationName = "dummyConfiguration"; + + AWSGameLiftPlayerInformation player; + player.m_playerAttributes["dummy"] = "{\"S\": \"test\"}"; + player.m_playerId = "dummyPlayerId"; + player.m_team = "dummyTeam"; + player.m_latencyInMs["us-east-1"] = 10; + request.m_players.emplace_back(player); + + auto result = StartMatchmakingActivity::ValidateStartMatchmakingRequest(request); + EXPECT_TRUE(result); +} diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStopMatchmakingActivityTest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStopMatchmakingActivityTest.cpp new file mode 100644 index 0000000000..6b53ed5055 --- /dev/null +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStopMatchmakingActivityTest.cpp @@ -0,0 +1,38 @@ +/* + * 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 + +using namespace AWSGameLift; + +using AWSGameLiftStopMatchmakingActivityTest = AWSGameLiftClientFixture; + +TEST_F(AWSGameLiftStopMatchmakingActivityTest, BuildAWSGameLiftStopMatchmakingRequest_Call_GetExpectedResult) +{ + AWSGameLiftStopMatchmakingRequest request; + request.m_ticketId = "dummyTicketId"; + auto awsRequest = StopMatchmakingActivity::BuildAWSGameLiftStopMatchmakingRequest(request); + EXPECT_TRUE(strcmp(awsRequest.GetTicketId().c_str(), request.m_ticketId.c_str()) == 0); +} + +TEST_F(AWSGameLiftStopMatchmakingActivityTest, ValidateStopMatchmakingRequest_CallWithoutTicketId_GetFalseResult) +{ + AZ_TEST_START_TRACE_SUPPRESSION; + auto result = StopMatchmakingActivity::ValidateStopMatchmakingRequest(AzFramework::StopMatchmakingRequest()); + EXPECT_FALSE(result); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftStopMatchmakingActivityTest, ValidateStopMatchmakingRequest_CallWithTicketId_GetTrueResult) +{ + AWSGameLiftStopMatchmakingRequest request; + request.m_ticketId = "dummyTicketId"; + auto result = StopMatchmakingActivity::ValidateStopMatchmakingRequest(request); + EXPECT_TRUE(result); +} diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_files.cmake b/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_files.cmake index d3b9d8d1b9..3122ff2261 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_files.cmake +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_files.cmake @@ -30,6 +30,10 @@ set(FILES Source/Activity/AWSGameLiftSearchSessionsActivity.h Source/AWSGameLiftClientLocalTicketTracker.cpp Source/AWSGameLiftClientLocalTicketTracker.h + Source/Activity/AWSGameLiftStartMatchmakingActivity.cpp + Source/Activity/AWSGameLiftStartMatchmakingActivity.h + Source/Activity/AWSGameLiftStopMatchmakingActivity.cpp + Source/Activity/AWSGameLiftStopMatchmakingActivity.h Source/AWSGameLiftClientManager.cpp Source/AWSGameLiftClientManager.h Source/AWSGameLiftClientSystemComponent.cpp diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_tests_files.cmake b/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_tests_files.cmake index 130ed28e4e..f8ef40d5df 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_tests_files.cmake +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_tests_files.cmake @@ -11,6 +11,8 @@ set(FILES Tests/Activity/AWSGameLiftCreateSessionOnQueueActivityTest.cpp Tests/Activity/AWSGameLiftJoinSessionActivityTest.cpp Tests/Activity/AWSGameLiftSearchSessionsActivityTest.cpp + Tests/Activity/AWSGameLiftStartMatchmakingActivityTest.cpp + Tests/Activity/AWSGameLiftStopMatchmakingActivityTest.cpp Tests/AWSGameLiftClientFixture.h Tests/AWSGameLiftClientLocalTicketTrackerTest.cpp Tests/AWSGameLiftClientManagerTest.cpp From 7fcaeb16c49d9c64ddc7b1874527de84b08dbea9 Mon Sep 17 00:00:00 2001 From: smurly Date: Tue, 12 Oct 2021 11:23:29 -0700 Subject: [PATCH 117/169] PostFX Layer component P0 parallel test (#4619) * PostFX Layer component P0 parallel test Signed-off-by: Scott Murray * removing an unused import Signed-off-by: Scott Murray --- .../Atom/TestSuite_Main_Optimized.py | 4 + ...a_AtomEditorComponents_PostFXLayerAdded.py | 156 ++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFXLayerAdded.py diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py index ec3d76758c..31b4cb687d 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py @@ -63,5 +63,9 @@ class TestAutomation(EditorTestSuite): class AtomEditorComponents_MaterialAdded(EditorSharedTest): from Atom.tests import hydra_AtomEditorComponents_MaterialAdded as test_module + @pytest.mark.test_case_id("C32078127") + class AtomEditorComponents_PostFXLayerAdded(EditorSharedTest): + from Atom.tests import hydra_AtomEditorComponents_PostFXLayerAdded as test_module + class ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges(EditorSharedTest): from Atom.tests import hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges as test_module diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFXLayerAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFXLayerAdded.py new file mode 100644 index 0000000000..8c2dee416b --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFXLayerAdded.py @@ -0,0 +1,156 @@ +""" +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 +""" + +class Tests: + creation_undo = ( + "UNDO Entity creation success", + "UNDO Entity creation failed") + creation_redo = ( + "REDO Entity creation success", + "REDO Entity creation failed") + postfx_layer_entity_creation = ( + "PostFX Layer Entity successfully created", + "PostFX Layer Entity failed to be created") + postfx_layer_component_added = ( + "Entity has a PostFX Layer component", + "Entity failed to find PostFX Layer component") + enter_game_mode = ( + "Entered game mode", + "Failed to enter game mode") + exit_game_mode = ( + "Exited game mode", + "Couldn't exit game mode") + is_visible = ( + "Entity is visible", + "Entity was not visible") + is_hidden = ( + "Entity is hidden", + "Entity was not hidden") + entity_deleted = ( + "Entity deleted", + "Entity was not deleted") + deletion_undo = ( + "UNDO deletion success", + "UNDO deletion failed") + deletion_redo = ( + "REDO deletion success", + "REDO deletion failed") + + +def AtomEditorComponents_postfx_layer_AddedToEntity(): + """ + Summary: + Tests the PostFX Layer component can be added to an entity and has the expected functionality. + + Test setup: + - Wait for Editor idle loop. + - Open the "Base" level. + + Expected Behavior: + The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components. + Creation and deletion undo/redo should also work. + + Test Steps: + 1) Create a PostFX Layer entity with no components. + 2) Add a PostFX Layer component to PostFX Layer entity. + 3) UNDO the entity creation and component addition. + 4) REDO the entity creation and component addition. + 5) Enter/Exit game mode. + 6) Test IsHidden. + 7) Test IsVisible. + 8) Delete PostFX Layer entity. + 9) UNDO deletion. + 10) REDO deletion. + 11) Look for errors. + + :return: None + """ + + import os + + import azlmbr.legacy.general as general + + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report, Tracer, TestHelper + + with Tracer() as error_tracer: + # Test setup begins. + # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level. + TestHelper.init_idle() + TestHelper.open_level("", "Base") + + # Test steps begin. + # 1. Create a PostFX Layer entity with no components. + postfx_layer_name = "PostFX Layer" + postfx_layer_entity = EditorEntity.create_editor_entity(postfx_layer_name) + Report.critical_result(Tests.postfx_layer_entity_creation, postfx_layer_entity.exists()) + + # 2. Add a PostFX Layer component to PostFX Layer entity. + postfx_layer_component = postfx_layer_entity.add_component(postfx_layer_name) + Report.critical_result(Tests.postfx_layer_component_added, postfx_layer_entity.has_component(postfx_layer_name)) + + # 3. UNDO the entity creation and component addition. + # -> UNDO component addition. + general.undo() + # -> UNDO naming entity. + general.undo() + # -> UNDO selecting entity. + general.undo() + # -> UNDO entity creation. + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.creation_undo, not postfx_layer_entity.exists()) + + # 4. REDO the entity creation and component addition. + # -> REDO entity creation. + general.redo() + # -> REDO selecting entity. + general.redo() + # -> REDO naming entity. + general.redo() + # -> REDO component addition. + general.redo() + general.idle_wait_frames(1) + Report.result(Tests.creation_redo, postfx_layer_entity.exists()) + + # 5. Enter/Exit game mode. + TestHelper.enter_game_mode(Tests.enter_game_mode) + general.idle_wait_frames(1) + TestHelper.exit_game_mode(Tests.exit_game_mode) + + # 6. Test IsHidden. + postfx_layer_entity.set_visibility_state(False) + Report.result(Tests.is_hidden, postfx_layer_entity.is_hidden() is True) + + # 7. Test IsVisible. + postfx_layer_entity.set_visibility_state(True) + general.idle_wait_frames(1) + Report.result(Tests.is_visible, postfx_layer_entity.is_visible() is True) + + # 8. Delete PostFX Layer entity. + postfx_layer_entity.delete() + Report.result(Tests.entity_deleted, not postfx_layer_entity.exists()) + + # 9. UNDO deletion. + general.undo() + Report.result(Tests.deletion_undo, postfx_layer_entity.exists()) + + # 10. REDO deletion. + general.redo() + Report.result(Tests.deletion_redo, not postfx_layer_entity.exists()) + + # 11. Look for errors or asserts. + TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0) + for error_info in error_tracer.errors: + Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}") + for assert_info in error_tracer.asserts: + Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}") + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(AtomEditorComponents_postfx_layer_AddedToEntity) From 94c938496eb3b78900000ded65fa3ab8696cd8ab Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Tue, 12 Oct 2021 13:46:54 -0500 Subject: [PATCH 118/169] Fixed logic error causing Python Scripts tree items to only show extension intead of filename. Signed-off-by: Chris Galvan --- Code/Editor/Controls/FolderTreeCtrl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Editor/Controls/FolderTreeCtrl.cpp b/Code/Editor/Controls/FolderTreeCtrl.cpp index 4088ab976f..1464580ffc 100644 --- a/Code/Editor/Controls/FolderTreeCtrl.cpp +++ b/Code/Editor/Controls/FolderTreeCtrl.cpp @@ -279,7 +279,7 @@ void CFolderTreeCtrl::LoadTreeRec(const QString& currentFolder) void CFolderTreeCtrl::AddItem(const QString& path) { AZ::IO::FixedMaxPath folder{ AZ::IO::PathView(path.toUtf8().constData()) }; - AZ::IO::FixedMaxPath fileNameWithoutExtension = folder.Extension(); + AZ::IO::FixedMaxPath fileNameWithoutExtension = folder.Stem(); folder = folder.ParentPath(); auto regex = QRegExp(m_fileNameSpec, Qt::CaseInsensitive, QRegExp::Wildcard); From 05767f2d2b89f456dca74e66d69e2c0c5f882431 Mon Sep 17 00:00:00 2001 From: Adi Bar-Lev <82479970+Adi-Amazon@users.noreply.github.com> Date: Tue, 12 Oct 2021 15:40:12 -0400 Subject: [PATCH 119/169] Atom Timer fix - changed milliseconds to seconds (#4631) * Atom Timer fix - changed milliseconds to seconds - Tested on both fog and EyeAdaptation animations - both are the only affected and were broken before - This is a small fix for pull #3969 that replaced the timer mechanism: https://github.com/o3de/o3de/pull/3969 Signed-off-by: Adi-Amazon * Atom Timer fix - using seconds to begin with and removing obsolete variable Signed-off-by: Adi-Amazon --- Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h | 3 --- Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp | 2 +- Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp | 4 +--- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h index 90389687de..fcf812cc38 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RenderPipeline.h @@ -228,9 +228,6 @@ namespace AZ PipelineViewMap m_pipelineViewsByTag; - /// The system time when the last time this pipeline render was started - float m_lastRenderStartTime = 0; - // RenderPipeline's name id, it will be used to identify the render pipeline when it's added to a Scene RenderPipelineId m_nameId; diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp index 5df1c655d6..eb74a81e3e 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp @@ -263,7 +263,7 @@ namespace AZ AZ::TickRequestBus::BroadcastResult(m_tickTime.m_gameDeltaTime, &AZ::TickRequestBus::Events::GetTickDeltaTime); ScriptTimePoint currentTime; AZ::TickRequestBus::BroadcastResult(currentTime, &AZ::TickRequestBus::Events::GetTimeAtCurrentTick); - m_tickTime.m_currentGameTime = static_cast(currentTime.GetMilliseconds()); + m_tickTime.m_currentGameTime = static_cast(currentTime.GetSeconds()); } void RPISystem::RenderTick() diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp index 1b99abae4e..6378a249a4 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/RenderPipeline.cpp @@ -375,12 +375,10 @@ namespace AZ m_scene->RemoveRenderPipeline(m_nameId); } - void RenderPipeline::OnStartFrame(const TickTimeInfo& tick) + void RenderPipeline::OnStartFrame([[maybe_unused]] const TickTimeInfo& tick) { AZ_PROFILE_SCOPE(RPI, "RenderPipeline: OnStartFrame"); - m_lastRenderStartTime = tick.m_currentGameTime; - OnPassModified(); for (auto& viewItr : m_pipelineViewsByTag) From 8487373b0cf1fe02210a083a9548cfc8ad4b7b79 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Tue, 12 Oct 2021 14:41:26 -0500 Subject: [PATCH 120/169] Updated thumbnail notification bus to use const QPixmap& Signed-off-by: Guthrie Adams --- .../AzToolsFramework/Thumbnails/ThumbnailerBus.h | 2 +- .../Code/Source/Thumbnail/ImageThumbnail.cpp | 2 +- .../ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.h | 2 +- .../CommonFeatures/Code/Source/Material/MaterialThumbnail.cpp | 2 +- .../CommonFeatures/Code/Source/Material/MaterialThumbnail.h | 2 +- .../CommonFeatures/Code/Source/Mesh/MeshThumbnail.cpp | 2 +- .../CommonFeatures/Code/Source/Mesh/MeshThumbnail.h | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h index 6f074da878..acd8ba3966 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Thumbnails/ThumbnailerBus.h @@ -90,7 +90,7 @@ namespace AzToolsFramework typedef SharedThumbnailKey BusIdType; //! notify product thumbnail that the data is ready - virtual void ThumbnailRendered(QPixmap& thumbnailImage) = 0; + virtual void ThumbnailRendered(const QPixmap& thumbnailImage) = 0; //! notify product thumbnail that the thumbnail failed to render virtual void ThumbnailFailedToRender() = 0; }; diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.cpp b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.cpp index 084e38a2db..cdd63dca18 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.cpp +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.cpp @@ -67,7 +67,7 @@ namespace ImageProcessingAtom m_renderWait.acquire(); } - void ImageThumbnail::ThumbnailRendered(QPixmap& thumbnailImage) + void ImageThumbnail::ThumbnailRendered(const QPixmap& thumbnailImage) { m_pixmap = thumbnailImage; m_renderWait.release(); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.h index 45fd178285..eadbfca945 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Thumbnail/ImageThumbnail.h @@ -34,7 +34,7 @@ namespace ImageProcessingAtom ~ImageThumbnail() override; //! AzToolsFramework::ThumbnailerRendererNotificationBus::Handler overrides... - void ThumbnailRendered(QPixmap& thumbnailImage) override; + void ThumbnailRendered(const QPixmap& thumbnailImage) override; void ThumbnailFailedToRender() override; protected: diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialThumbnail.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialThumbnail.cpp index 0723859ff5..2931b647e5 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialThumbnail.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialThumbnail.cpp @@ -54,7 +54,7 @@ namespace AZ AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); } - void MaterialThumbnail::ThumbnailRendered(QPixmap& thumbnailImage) + void MaterialThumbnail::ThumbnailRendered(const QPixmap& thumbnailImage) { m_pixmap = thumbnailImage; m_renderWait.release(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialThumbnail.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialThumbnail.h index dba922a1b2..8f2053ba67 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialThumbnail.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/MaterialThumbnail.h @@ -36,7 +36,7 @@ namespace AZ ~MaterialThumbnail() override; //! AzToolsFramework::ThumbnailerRendererNotificationBus::Handler overrides... - void ThumbnailRendered(QPixmap& thumbnailImage) override; + void ThumbnailRendered(const QPixmap& thumbnailImage) override; void ThumbnailFailedToRender() override; protected: diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshThumbnail.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshThumbnail.cpp index 658d420a16..845197d939 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshThumbnail.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshThumbnail.cpp @@ -55,7 +55,7 @@ namespace AZ AzFramework::AssetCatalogEventBus::Handler::BusDisconnect(); } - void MeshThumbnail::ThumbnailRendered(QPixmap& thumbnailImage) + void MeshThumbnail::ThumbnailRendered(const QPixmap& thumbnailImage) { m_pixmap = thumbnailImage; m_renderWait.release(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshThumbnail.h b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshThumbnail.h index 2975b6950c..872e1029d2 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshThumbnail.h +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/MeshThumbnail.h @@ -35,7 +35,7 @@ namespace AZ ~MeshThumbnail() override; //! AzToolsFramework::ThumbnailerRendererNotificationBus::Handler overrides... - void ThumbnailRendered(QPixmap& thumbnailImage) override; + void ThumbnailRendered(const QPixmap& thumbnailImage) override; void ThumbnailFailedToRender() override; protected: From 4c5906a8d46f0f69ed590407396368d47cd0d79b Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Tue, 12 Oct 2021 13:21:55 -0700 Subject: [PATCH 121/169] PostFX Shape Weight Modifier component P0 parallel test Signed-off-by: Scott Murray --- .../Atom/TestSuite_Main_Optimized.py | 4 + ...mponents_PostFxShapeWeightModifierAdded.py | 211 ++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py index 31b4cb687d..447a4ebac9 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_Optimized.py @@ -67,5 +67,9 @@ class TestAutomation(EditorTestSuite): class AtomEditorComponents_PostFXLayerAdded(EditorSharedTest): from Atom.tests import hydra_AtomEditorComponents_PostFXLayerAdded as test_module + @pytest.mark.test_case_id("C36525665") + class AtomEditorComponents_PostFXShapeWeightModifierAdded(EditorSharedTest): + from Atom.tests import hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded as test_module + class ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges(EditorSharedTest): from Atom.tests import hydra_ShaderAssetBuilder_RecompilesShaderAsChainOfDependenciesChanges as test_module diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py new file mode 100644 index 0000000000..be139f83b6 --- /dev/null +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py @@ -0,0 +1,211 @@ +""" +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 +""" + +class Tests: + creation_undo = ( + "UNDO Entity creation success", + "UNDO Entity creation failed") + creation_redo = ( + "REDO Entity creation success", + "REDO Entity creation failed") + postfx_shape_weight_creation = ( + "PostFx Shape Weight Modifier Entity successfully created", + "PostFx Shape Weight Modifier Entity failed to be created") + postfx_shape_weight_component = ( + "Entity has a PostFx Shape Weight Modifier component", + "Entity failed to find PostFx Shape Weight Modifier component") + postfx_shape_weight_disabled = ( + "PostFx Shape Weight Modifier component disabled", + "PostFx Shape Weight Modifier component was not disabled.") + postfx_layer_component = ( + "Entity has an Actor component", + "Entity did not have an Actor component") + shape_component = ( + "Entity has a Tube Shape component", + "Entity did not have a Tube Shape component") + shape_undo = ( + "Entity shape component add undone", + "Entity shape component undo failed to remove shape") + postfx_shape_weight_enabled = ( + "PostFx Shape Weight Modifier component enabled", + "PostFx Shape Weight Modifier component was not enabled.") + enter_game_mode = ( + "Entered game mode", + "Failed to enter game mode") + exit_game_mode = ( + "Exited game mode", + "Couldn't exit game mode") + is_visible = ( + "Entity is visible", + "Entity was not visible") + is_hidden = ( + "Entity is hidden", + "Entity was not hidden") + entity_deleted = ( + "Entity deleted", + "Entity was not deleted") + deletion_undo = ( + "UNDO deletion success", + "UNDO deletion failed") + deletion_redo = ( + "REDO deletion success", + "REDO deletion failed") + + +def AtomEditorComponents_postfx_shape_weight_AddedToEntity(): + """ + Summary: + Tests the PostFx Shape Weight Modifier component can be added to an entity and has the expected functionality. + + Test setup: + - Wait for Editor idle loop. + - Open the "Base" level. + + Expected Behavior: + The component can be added, used in game mode, hidden/shown, deleted, and has accurate required components. + Creation and deletion undo/redo should also work. + + Test Steps: + 1) Create a PostFx Shape Weight Modifier entity with no components. + 2) Add a PostFx Shape Weight Modifier component to PostFx Shape Weight Modifier entity. + 3) UNDO the entity creation and component addition. + 4) REDO the entity creation and component addition. + 5) Verify PostFx Shape Weight Modifier component not enabled. + 6) Add PostFX Layer component since it is required by the PostFx Shape Weight Modifier component. + 7) Verify PostFx Shape Weight Modifier component is NOT enabled since it also requires a shape. + 8) Add a required shape looping over a list and checking if it enables PostFX Shape Weight Modifier. + 9) Undo to remove each added shape and verify PostFX Shape Weight Modifier is not enabled + 10) Verify PostFx Shape Weight Modifier component is enabled by adding Spline and Tube Shape componen. + 11) Enter/Exit game mode. + 12) Test IsHidden. + 13) Test IsVisible. + 14) Delete PostFx Shape Weight Modifier entity. + 15) UNDO deletion. + 16) REDO deletion. + 17) Look for errors. + + :return: None + """ + + import azlmbr.legacy.general as general + + from editor_python_test_tools.editor_entity_utils import EditorEntity + from editor_python_test_tools.utils import Report, Tracer, TestHelper + + with Tracer() as error_tracer: + # Test setup begins. + # Setup: Wait for Editor idle loop before executing Python hydra scripts then open "Base" level. + TestHelper.init_idle() + TestHelper.open_level("", "Base") + + # Test steps begin. + # 1. Create a PostFx Shape Weight Modifier entity with no components. + postfx_shape_weight_name = "PostFX Shape Weight Modifier" + postfx_shape_weight_entity = EditorEntity.create_editor_entity(postfx_shape_weight_name) + Report.critical_result(Tests.postfx_shape_weight_creation, postfx_shape_weight_entity.exists()) + + # 2. Add a PostFx Shape Weight Modifier component to PostFx Shape Weight Modifier entity. + postfx_shape_weight_component = postfx_shape_weight_entity.add_component(postfx_shape_weight_name) + Report.critical_result( + Tests.postfx_shape_weight_component, + postfx_shape_weight_entity.has_component(postfx_shape_weight_name)) + + # 3. UNDO the entity creation and component addition. + # -> UNDO component addition. + general.undo() + # -> UNDO naming entity. + general.undo() + # -> UNDO selecting entity. + general.undo() + # -> UNDO entity creation. + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.creation_undo, not postfx_shape_weight_entity.exists()) + + # 4. REDO the entity creation and component addition. + # -> REDO entity creation. + general.redo() + # -> REDO selecting entity. + general.redo() + # -> REDO naming entity. + general.redo() + # -> REDO component addition. + general.redo() + general.idle_wait_frames(1) + Report.result(Tests.creation_redo, postfx_shape_weight_entity.exists()) + + # 5. Verify PostFx Shape Weight Modifier component not enabled. + Report.result(Tests.postfx_shape_weight_disabled, not postfx_shape_weight_component.is_enabled()) + + # 6. Add PostFX Layer component since it is required by the PostFx Shape Weight Modifier component. + postfx_layer_name = "PostFX Layer" + postfx_shape_weight_entity.add_component(postfx_layer_name) + Report.result(Tests.postfx_layer_component, postfx_shape_weight_entity.has_component(postfx_layer_name)) + + # 7. Verify PostFx Shape Weight Modifier component not enabled because shape is also required. + Report.result(Tests.postfx_shape_weight_disabled, not postfx_shape_weight_component.is_enabled()) + + # 8. Add remove each shape to test if the PostFX Shape Weight Modifier is enabled by having a required shape + for shape in ['Axis Aligned Box Shape', 'Box Shape', 'Capsule Shape', 'Compound Shape', 'Cylinder Shape', + 'Disk Shape', 'Polygon Prism Shape', 'Quad Shape', 'Sphere Shape', 'Vegetation Reference Shape']: + postfx_shape_weight_entity.add_component(shape) + test_shape = ( + f"Entity has a {shape} component", + f"Entity did not have a {shape} component") + Report.result(test_shape, postfx_shape_weight_entity.has_component(shape)) + + #Check if required shape allows PostFX Shape Weight Modifier to be enabled + Report.result(Tests.postfx_shape_weight_enabled, postfx_shape_weight_component.is_enabled()) + + # 9. UNDO component addition and check that PostFX Shape Weight Modifier is not enabled + general.undo() + general.idle_wait_frames(1) + Report.result(Tests.shape_undo, not postfx_shape_weight_entity.has_component(shape)) + Report.result(Tests.postfx_shape_weight_disabled, not postfx_shape_weight_component.is_enabled()) + + # 10. Add Tube Shape and Spline to fulfil the required shape component + postfx_shape_weight_entity.add_components(['Spline', 'Tube Shape']) + Report.result(Tests.shape_component, postfx_shape_weight_entity.has_component('Tube Shape')) + Report.result(Tests.postfx_shape_weight_enabled, postfx_shape_weight_component.is_enabled()) + + # 11. Enter/Exit game mode. + TestHelper.enter_game_mode(Tests.enter_game_mode) + general.idle_wait_frames(1) + TestHelper.exit_game_mode(Tests.exit_game_mode) + + # 12. Test IsHidden. + postfx_shape_weight_entity.set_visibility_state(False) + Report.result(Tests.is_hidden, postfx_shape_weight_entity.is_hidden() is True) + + # 13. Test IsVisible. + postfx_shape_weight_entity.set_visibility_state(True) + general.idle_wait_frames(1) + Report.result(Tests.is_visible, postfx_shape_weight_entity.is_visible() is True) + + # 14. Delete PostFx Shape Weight Modifier entity. + postfx_shape_weight_entity.delete() + Report.result(Tests.entity_deleted, not postfx_shape_weight_entity.exists()) + + # 15. UNDO deletion. + general.undo() + Report.result(Tests.deletion_undo, postfx_shape_weight_entity.exists()) + + # 16. REDO deletion. + general.redo() + Report.result(Tests.deletion_redo, not postfx_shape_weight_entity.exists()) + + # 17. Look for errors or asserts. + TestHelper.wait_for_condition(lambda: error_tracer.has_errors or error_tracer.has_asserts, 1.0) + for error_info in error_tracer.errors: + Report.info(f"Error: {error_info.filename} {error_info.function} | {error_info.message}") + for assert_info in error_tracer.asserts: + Report.info(f"Assert: {assert_info.filename} {assert_info.function} | {assert_info.message}") + + +if __name__ == "__main__": + from editor_python_test_tools.utils import Report + Report.start_test(AtomEditorComponents_postfx_shape_weight_AddedToEntity) From 5cefd552a64cd51826208b79a189b6593dd74848 Mon Sep 17 00:00:00 2001 From: moudgils <47460854+moudgils@users.noreply.github.com> Date: Tue, 12 Oct 2021 13:24:40 -0700 Subject: [PATCH 122/169] - Optimize SRG compilation to not update the whole SRG if not needed across all backends (#4499) - Each resource type is tracked and updated separately - Added caching ability for Raytracing srg to save ~2ms for a scene containing 100 x 50 vegetation patch Signed-off-by: moudgils --- .../RayTracing/RayTracingFeatureProcessor.cpp | 18 ++- .../RayTracing/RayTracingFeatureProcessor.h | 4 + .../Atom/RHI/ShaderResourceGroupData.h | 62 ++++++++++- .../Source/RHI/ShaderResourceGroupData.cpp | 58 ++++++++++ .../Source/RHI/ShaderResourceGroupPool.cpp | 22 +++- .../Source/RHI/ShaderResourceGroupPool.cpp | 65 +++++++---- .../Source/RHI/ShaderResourceGroupPool.cpp | 105 +++++++++++------- .../RPI.Public/Shader/ShaderResourceGroup.cpp | 4 + 8 files changed, 259 insertions(+), 79 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp index 042e934eb0..6e78d3170c 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.cpp @@ -507,8 +507,13 @@ namespace AZ } } - RHI::ShaderInputBufferUnboundedArrayIndex bufferUnboundedArrayIndex = srgLayout->FindShaderInputBufferUnboundedArrayIndex(AZ::Name("m_meshBuffers")); - m_rayTracingSceneSrg->SetBufferViewUnboundedArray(bufferUnboundedArrayIndex, meshBuffers); + //Check if buffer view data changed from previous frame. + if (m_meshBuffers.size() != meshBuffers.size() || m_meshBuffers != meshBuffers) + { + m_meshBuffers = meshBuffers; + RHI::ShaderInputBufferUnboundedArrayIndex bufferUnboundedArrayIndex = srgLayout->FindShaderInputBufferUnboundedArrayIndex(AZ::Name("m_meshBuffers")); + m_rayTracingSceneSrg->SetBufferViewUnboundedArray(bufferUnboundedArrayIndex, m_meshBuffers); + } } m_rayTracingSceneSrg->Compile(); @@ -554,8 +559,13 @@ namespace AZ } } - RHI::ShaderInputImageUnboundedArrayIndex textureUnboundedArrayIndex = srgLayout->FindShaderInputImageUnboundedArrayIndex(AZ::Name("m_materialTextures")); - m_rayTracingMaterialSrg->SetImageViewUnboundedArray(textureUnboundedArrayIndex, materialTextures); + // Check if image view data changed from previous frame. + if (m_materialTextures.size() != materialTextures.size() || m_materialTextures != materialTextures) + { + m_materialTextures = materialTextures; + RHI::ShaderInputImageUnboundedArrayIndex textureUnboundedArrayIndex = srgLayout->FindShaderInputImageUnboundedArrayIndex(AZ::Name("m_materialTextures")); + m_rayTracingMaterialSrg->SetImageViewUnboundedArray(textureUnboundedArrayIndex, materialTextures); + } } m_rayTracingMaterialSrg->Compile(); diff --git a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h index 52bb67f547..c0ebd6a4e7 100644 --- a/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/RayTracing/RayTracingFeatureProcessor.h @@ -281,6 +281,10 @@ namespace AZ using BlasInstanceMap = AZStd::unordered_map; BlasInstanceMap m_blasInstanceMap; + + // Cache view pointers so we dont need to update them if none changed from frame to frame. + AZStd::vector m_meshBuffers; + AZStd::vector m_materialTextures; }; } } diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupData.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupData.h index cbb0db53c8..ef4e734c01 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupData.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/ShaderResourceGroupData.h @@ -183,6 +183,42 @@ namespace AZ //! Returns the shader resource layout for this group. const ShaderResourceGroupLayout* GetLayout() const; + enum class ResourceType : uint32_t + { + ConstantData, + BufferView, + ImageView, + BufferViewUnboundedArray, + ImageViewUnboundedArray, + Sampler, + Count + }; + + enum class ResourceTypeMask : uint32_t + { + None = 0, + ConstantDataMask = AZ_BIT(static_cast(ResourceType::ConstantData)), + BufferViewMask = AZ_BIT(static_cast(ResourceType::BufferView)), + ImageViewMask = AZ_BIT(static_cast(ResourceType::ImageView)), + BufferViewUnboundedArrayMask = AZ_BIT(static_cast(ResourceType::BufferViewUnboundedArray)), + ImageViewUnboundedArrayMask = AZ_BIT(static_cast(ResourceType::ImageViewUnboundedArray)), + SamplerMask = AZ_BIT(static_cast(ResourceType::Sampler)) + }; + + //! Returns true if a resource type specified by resourceTypeMask is enabled for compilation + bool IsResourceTypeEnabledForCompilation(uint32_t resourceTypeMask) const; + + //! Disables all resource types for compilation after m_updateMaskResetLatency number of compiles + //! This allows higher level code to ensure that if SRG is multi-buffered it can compile multiple + //! times in order to ensure all SRG buffers are updated. + void DisableCompilationForAllResourceTypes(); + + //! Returns true if any of the resource type has been enabled for compilation. + bool IsAnyResourceTypeUpdated() const; + + //! Enable compilation for a resourceType specified by resourceType/resourceTypeMask + void EnableResourceTypeCompilation(ResourceTypeMask resourceTypeMask, ResourceType resourceType); + private: static const ConstPtr s_nullImageView; static const ConstPtr s_nullBufferView; @@ -207,23 +243,43 @@ namespace AZ //! The backing data store of constants for the shader resource group. ConstantsData m_constantsData; + + //! Mask used to check whether to compile a specific resource type + uint32_t m_updateMask = 0; + + //! Track iteration for each resource type in order to keep compiling it for m_updateMaskResetLatency number of times + uint32_t m_resourceTypeIteration[static_cast(ResourceType::Count)] = { 0 }; + uint32_t m_updateMaskResetLatency = RHI::Limits::Device::FrameCountMax; }; template bool ShaderResourceGroupData::SetConstant(ShaderInputConstantIndex inputIndex, const T& value) { + EnableResourceTypeCompilation(ResourceTypeMask::ConstantDataMask, ResourceType::ConstantData); return m_constantsData.SetConstant(inputIndex, value); } template bool ShaderResourceGroupData::SetConstant(ShaderInputConstantIndex inputIndex, const T& value, uint32_t arrayIndex) { + EnableResourceTypeCompilation(ResourceTypeMask::ConstantDataMask, ResourceType::ConstantData); return m_constantsData.SetConstant(inputIndex, value, arrayIndex); } + + template + bool ShaderResourceGroupData::SetConstantMatrixRows(ShaderInputConstantIndex inputIndex, const T& value, uint32_t rowCount) + { + EnableResourceTypeCompilation(ResourceTypeMask::ConstantDataMask, ResourceType::ConstantData); + return m_constantsData.SetConstantMatrixRows(inputIndex, value, rowCount); + } template bool ShaderResourceGroupData::SetConstantArray(ShaderInputConstantIndex inputIndex, AZStd::array_view values) { + if (!values.empty()) + { + EnableResourceTypeCompilation(ResourceTypeMask::ConstantDataMask, ResourceType::ConstantData); + } return m_constantsData.SetConstantArray(inputIndex, values); } @@ -245,12 +301,6 @@ namespace AZ return m_constantsData.GetConstant(inputIndex, arrayIndex); } - template - bool ShaderResourceGroupData::SetConstantMatrixRows(ShaderInputConstantIndex inputIndex, const T& value, uint32_t rowCount) - { - return m_constantsData.SetConstantMatrixRows(inputIndex, value, rowCount); - } - template bool ShaderResourceGroupData::ValidateImageViewAccess(TShaderInput inputIndex, const ImageView* imageView, [[maybe_unused]] uint32_t arrayIndex) const { diff --git a/Gems/Atom/RHI/Code/Source/RHI/ShaderResourceGroupData.cpp b/Gems/Atom/RHI/Code/Source/RHI/ShaderResourceGroupData.cpp index 18b292ac64..eed14b41b7 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/ShaderResourceGroupData.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/ShaderResourceGroupData.cpp @@ -7,6 +7,7 @@ */ #include #include +#include namespace AZ { @@ -126,6 +127,12 @@ namespace AZ } isValidAll &= isValid; } + + if(!imageViews.empty()) + { + EnableResourceTypeCompilation(ResourceTypeMask::ImageViewMask, ResourceType::ImageView); + } + return isValidAll; } return false; @@ -146,6 +153,11 @@ namespace AZ } isValidAll &= isValid; } + + if (!imageViews.empty()) + { + EnableResourceTypeCompilation(ResourceTypeMask::ImageViewUnboundedArrayMask, ResourceType::ImageViewUnboundedArray); + } return isValidAll; } return false; @@ -172,6 +184,11 @@ namespace AZ } isValidAll &= isValid; } + + if (!bufferViews.empty()) + { + EnableResourceTypeCompilation(ResourceTypeMask::BufferViewMask, ResourceType::BufferView); + } return isValidAll; } return false; @@ -192,6 +209,11 @@ namespace AZ } isValidAll &= isValid; } + + if (!bufferViews.empty()) + { + EnableResourceTypeCompilation(ResourceTypeMask::BufferViewUnboundedArrayMask, ResourceType::BufferViewUnboundedArray); + } return isValidAll; } return false; @@ -211,6 +233,11 @@ namespace AZ { m_samplers[interval.m_min + arrayIndex + i] = samplers[i]; } + + if (!samplers.empty()) + { + EnableResourceTypeCompilation(ResourceTypeMask::SamplerMask, ResourceType::Sampler); + } return true; } return false; @@ -223,16 +250,19 @@ namespace AZ bool ShaderResourceGroupData::SetConstantRaw(ShaderInputConstantIndex inputIndex, const void* bytes, uint32_t byteOffset, uint32_t byteCount) { + EnableResourceTypeCompilation(ResourceTypeMask::ConstantDataMask, ResourceType::ConstantData); return m_constantsData.SetConstantRaw(inputIndex, bytes, byteOffset, byteCount); } bool ShaderResourceGroupData::SetConstantData(const void* bytes, uint32_t byteCount) { + EnableResourceTypeCompilation(ResourceTypeMask::ConstantDataMask, ResourceType::ConstantData); return m_constantsData.SetConstantData(bytes, byteCount); } bool ShaderResourceGroupData::SetConstantData(const void* bytes, uint32_t byteOffset, uint32_t byteCount) { + EnableResourceTypeCompilation(ResourceTypeMask::ConstantDataMask, ResourceType::ConstantData); return m_constantsData.SetConstantData(bytes, byteOffset, byteCount); } @@ -348,5 +378,33 @@ namespace AZ return m_constantsData; } + bool ShaderResourceGroupData::IsResourceTypeEnabledForCompilation(uint32_t resourceTypeMask) const + { + return RHI::CheckBitsAny(m_updateMask, resourceTypeMask); + } + + bool ShaderResourceGroupData::IsAnyResourceTypeUpdated() const + { + return m_updateMask != 0; + } + + void ShaderResourceGroupData::EnableResourceTypeCompilation(ResourceTypeMask resourceTypeMask, ResourceType resourceType) + { + AZ_Assert(static_cast(resourceTypeMask) == AZ_BIT(static_cast(resourceType)), "resourceType and resourceTypeMask should point to the same ResourceType"); + m_updateMask = RHI::SetBits(m_updateMask, static_cast(resourceTypeMask)); + m_resourceTypeIteration[static_cast(resourceType)] = 0; + } + + void ShaderResourceGroupData::DisableCompilationForAllResourceTypes() + { + for (uint32_t i = 0; i < static_cast(ResourceType::Count); i++) + { + if (m_resourceTypeIteration[i] == m_updateMaskResetLatency) + { + m_updateMask = RHI::ResetBits(m_updateMask, AZ_BIT(i)); + } + m_resourceTypeIteration[i]++; + } + } } // namespace RHI } // namespace AZ diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI/ShaderResourceGroupPool.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI/ShaderResourceGroupPool.cpp index bd648cf535..087a36dc2f 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI/ShaderResourceGroupPool.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI/ShaderResourceGroupPool.cpp @@ -206,12 +206,21 @@ namespace AZ auto& device = static_cast(GetDevice()); group.m_compiledDataIndex = (group.m_compiledDataIndex + 1) % RHI::Limits::Device::FrameCountMax; - if (m_constantBufferSize) + if (!groupData.IsAnyResourceTypeUpdated()) + { + return RHI::ResultCode::Success; + } + + if (m_constantBufferSize && + groupData.IsResourceTypeEnabledForCompilation(static_cast(RHI::ShaderResourceGroupData::ResourceTypeMask::ConstantDataMask))) { memcpy(group.GetCompiledData().m_cpuConstantAddress, groupData.GetConstantData().data(), groupData.GetConstantData().size()); } - if (m_viewsDescriptorTableSize) + if (m_viewsDescriptorTableSize && + groupData.IsResourceTypeEnabledForCompilation( + static_cast(RHI::ShaderResourceGroupData::ResourceTypeMask::ImageViewMask) | + static_cast(RHI::ShaderResourceGroupData::ResourceTypeMask::BufferViewMask))) { //Lazy initialization for cbv/srv/uav Descriptor Tables if (!group.m_viewsDescriptorTable.IsValid()) @@ -236,12 +245,17 @@ namespace AZ UpdateViewsDescriptorTable(descriptorTable, groupData); } - if (m_unboundedArrayCount) + if (m_unboundedArrayCount && + groupData.IsResourceTypeEnabledForCompilation( + static_cast(RHI::ShaderResourceGroupData::ResourceTypeMask::ImageViewUnboundedArrayMask) | + static_cast(RHI::ShaderResourceGroupData::ResourceTypeMask::BufferViewUnboundedArrayMask))) { UpdateUnboundedArrayDescriptorTables(group, groupData); } - if (m_samplersDescriptorTableSize) + if (m_samplersDescriptorTableSize && + groupData.IsResourceTypeEnabledForCompilation( + static_cast(RHI::ShaderResourceGroupData::ResourceTypeMask::SamplerMask))) { const DescriptorTable descriptorTable( group.m_samplersDescriptorTable.GetOffset() + group.m_compiledDataIndex * m_samplersDescriptorTableSize, diff --git a/Gems/Atom/RHI/Metal/Code/Source/RHI/ShaderResourceGroupPool.cpp b/Gems/Atom/RHI/Metal/Code/Source/RHI/ShaderResourceGroupPool.cpp index 6be5ec7259..0a9c001868 100644 --- a/Gems/Atom/RHI/Metal/Code/Source/RHI/ShaderResourceGroupPool.cpp +++ b/Gems/Atom/RHI/Metal/Code/Source/RHI/ShaderResourceGroupPool.cpp @@ -63,39 +63,58 @@ namespace AZ { ShaderResourceGroup& group = static_cast(groupBase); group.UpdateCompiledDataIndex(); - + + if (!groupData.IsAnyResourceTypeUpdated()) + { + return RHI::ResultCode::Success; + } + ArgumentBuffer& argBuffer = *group.m_compiledArgBuffers[group.m_compiledDataIndex]; argBuffer.ClearResourceTracking(); - argBuffer.UpdateConstantBufferViews(groupData.GetConstantData()); - + + auto constantData = groupData.GetConstantData(); + if (!constantData.empty() && groupData.IsResourceTypeEnabledForCompilation(static_cast(RHI::ShaderResourceGroupData::ResourceTypeMask::ConstantDataMask))) + { + argBuffer.UpdateConstantBufferViews(groupData.GetConstantData()); + } + const RHI::ShaderResourceGroupLayout* layout = groupData.GetLayout(); uint32_t shaderInputIndex = 0; - for (const RHI::ShaderInputImageDescriptor& shaderInputImage : layout->GetShaderInputListForImages()) + if (groupData.IsResourceTypeEnabledForCompilation(static_cast(RHI::ShaderResourceGroupData::ResourceTypeMask::ImageViewMask))) { - const RHI::ShaderInputImageIndex imageInputIndex(shaderInputIndex); - AZStd::array_view> imageViews = groupData.GetImageViewArray(imageInputIndex); - argBuffer.UpdateImageViews(shaderInputImage, imageInputIndex, imageViews); - ++shaderInputIndex; + for (const RHI::ShaderInputImageDescriptor& shaderInputImage : layout->GetShaderInputListForImages()) + { + const RHI::ShaderInputImageIndex imageInputIndex(shaderInputIndex); + AZStd::array_view> imageViews = groupData.GetImageViewArray(imageInputIndex); + argBuffer.UpdateImageViews(shaderInputImage, imageInputIndex, imageViews); + ++shaderInputIndex; + } } - - shaderInputIndex = 0; - for (const RHI::ShaderInputSamplerDescriptor& shaderInputSampler : layout->GetShaderInputListForSamplers()) + + if (groupData.IsResourceTypeEnabledForCompilation(static_cast(RHI::ShaderResourceGroupData::ResourceTypeMask::SamplerMask))) { - const RHI::ShaderInputSamplerIndex samplerInputIndex(shaderInputIndex); - AZStd::array_view samplerStates= groupData.GetSamplerArray(samplerInputIndex); - argBuffer.UpdateSamplers(shaderInputSampler, samplerInputIndex, samplerStates); - ++shaderInputIndex; + shaderInputIndex = 0; + for (const RHI::ShaderInputSamplerDescriptor& shaderInputSampler : layout->GetShaderInputListForSamplers()) + { + const RHI::ShaderInputSamplerIndex samplerInputIndex(shaderInputIndex); + AZStd::array_view samplerStates = groupData.GetSamplerArray(samplerInputIndex); + argBuffer.UpdateSamplers(shaderInputSampler, samplerInputIndex, samplerStates); + ++shaderInputIndex; + } } - - shaderInputIndex = 0; - for (const RHI::ShaderInputBufferDescriptor& shaderInputBuffer : layout->GetShaderInputListForBuffers()) + + if (groupData.IsResourceTypeEnabledForCompilation(static_cast(RHI::ShaderResourceGroupData::ResourceTypeMask::BufferViewMask))) { - const RHI::ShaderInputBufferIndex bufferInputIndex(shaderInputIndex); - AZStd::array_view> bufferViews = groupData.GetBufferViewArray(bufferInputIndex); - argBuffer.UpdateBufferViews(shaderInputBuffer, bufferInputIndex, bufferViews); - ++shaderInputIndex; + shaderInputIndex = 0; + for (const RHI::ShaderInputBufferDescriptor& shaderInputBuffer : layout->GetShaderInputListForBuffers()) + { + const RHI::ShaderInputBufferIndex bufferInputIndex(shaderInputIndex); + AZStd::array_view> bufferViews = groupData.GetBufferViewArray(bufferInputIndex); + argBuffer.UpdateBufferViews(shaderInputBuffer, bufferInputIndex, bufferViews); + ++shaderInputIndex; + } } - + return RHI::ResultCode::Success; } diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ShaderResourceGroupPool.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ShaderResourceGroupPool.cpp index c5ca07eb27..59dbaf4377 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ShaderResourceGroupPool.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/ShaderResourceGroupPool.cpp @@ -105,66 +105,87 @@ namespace AZ { auto& group = static_cast(groupBase); group.UpdateCompiledDataIndex(m_currentIteration); + + if (!groupData.IsAnyResourceTypeUpdated()) + { + return RHI::ResultCode::Success; + } + DescriptorSet& descriptorSet = *group.m_compiledData[group.GetCompileDataIndex()]; const RHI::ShaderResourceGroupLayout* layout = groupData.GetLayout(); - for (uint32_t groupIndex = 0; groupIndex < static_cast(layout->GetShaderInputListForBuffers().size()); ++groupIndex) + if (groupData.IsResourceTypeEnabledForCompilation(static_cast(RHI::ShaderResourceGroupData::ResourceTypeMask::BufferViewMask))) { - const RHI::ShaderInputBufferIndex index(groupIndex); - auto bufViews = groupData.GetBufferViewArray(index); - uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::BufferView); - descriptorSet.UpdateBufferViews(layoutIndex, bufViews); - } - - auto const& shaderImageList = layout->GetShaderInputListForImages(); - for (uint32_t groupIndex = 0; groupIndex < static_cast(layout->GetShaderInputListForImages().size()); ++groupIndex) - { - const RHI::ShaderInputImageIndex index(groupIndex); - auto imgViews = groupData.GetImageViewArray(index); - uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::ImageView); - descriptorSet.UpdateImageViews(layoutIndex, imgViews, shaderImageList[groupIndex].m_type); - } - - for (uint32_t groupIndex = 0; groupIndex < static_cast(layout->GetShaderInputListForBufferUnboundedArrays().size()); ++groupIndex) - { - const RHI::ShaderInputBufferUnboundedArrayIndex index(groupIndex); - auto bufViews = groupData.GetBufferViewUnboundedArray(index); - if (bufViews.empty()) + for (uint32_t groupIndex = 0; groupIndex < static_cast(layout->GetShaderInputListForBuffers().size()); ++groupIndex) { - // skip empty unbounded arrays - continue; + const RHI::ShaderInputBufferIndex index(groupIndex); + auto bufViews = groupData.GetBufferViewArray(index); + uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::BufferView); + descriptorSet.UpdateBufferViews(layoutIndex, bufViews); } - - uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::BufferViewUnboundedArray); - descriptorSet.UpdateBufferViews(layoutIndex, bufViews); } - auto const& shaderImageUnboundeArrayList = layout->GetShaderInputListForImageUnboundedArrays(); - for (uint32_t groupIndex = 0; groupIndex < static_cast(layout->GetShaderInputListForImageUnboundedArrays().size()); ++groupIndex) + if (groupData.IsResourceTypeEnabledForCompilation(static_cast(RHI::ShaderResourceGroupData::ResourceTypeMask::ImageViewMask))) { - const RHI::ShaderInputImageUnboundedArrayIndex index(groupIndex); - auto imgViews = groupData.GetImageViewUnboundedArray(index); - if (imgViews.empty()) + auto const& shaderImageList = layout->GetShaderInputListForImages(); + for (uint32_t groupIndex = 0; groupIndex < static_cast(layout->GetShaderInputListForImages().size()); ++groupIndex) { - // skip empty unbounded arrays - continue; + const RHI::ShaderInputImageIndex index(groupIndex); + auto imgViews = groupData.GetImageViewArray(index); + uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::ImageView); + descriptorSet.UpdateImageViews(layoutIndex, imgViews, shaderImageList[groupIndex].m_type); } - - uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::ImageViewUnboundedArray); - descriptorSet.UpdateImageViews(layoutIndex, imgViews, shaderImageUnboundeArrayList[groupIndex].m_type); } - for (uint32_t groupIndex = 0; groupIndex < static_cast(layout->GetShaderInputListForSamplers().size()); ++groupIndex) + if (groupData.IsResourceTypeEnabledForCompilation(static_cast(RHI::ShaderResourceGroupData::ResourceTypeMask::BufferViewUnboundedArrayMask))) { - const RHI::ShaderInputSamplerIndex index(groupIndex); - auto samplerArray = groupData.GetSamplerArray(index); - uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::Sampler); - descriptorSet.UpdateSamplers(layoutIndex, samplerArray); + for (uint32_t groupIndex = 0; groupIndex < static_cast(layout->GetShaderInputListForBufferUnboundedArrays().size()); ++groupIndex) + { + const RHI::ShaderInputBufferUnboundedArrayIndex index(groupIndex); + auto bufViews = groupData.GetBufferViewUnboundedArray(index); + if (bufViews.empty()) + { + // skip empty unbounded arrays + continue; + } + + uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::BufferViewUnboundedArray); + descriptorSet.UpdateBufferViews(layoutIndex, bufViews); + } + } + + if (groupData.IsResourceTypeEnabledForCompilation(static_cast(RHI::ShaderResourceGroupData::ResourceTypeMask::ImageViewUnboundedArrayMask))) + { + auto const& shaderImageUnboundeArrayList = layout->GetShaderInputListForImageUnboundedArrays(); + for (uint32_t groupIndex = 0; groupIndex < static_cast(layout->GetShaderInputListForImageUnboundedArrays().size()); ++groupIndex) + { + const RHI::ShaderInputImageUnboundedArrayIndex index(groupIndex); + auto imgViews = groupData.GetImageViewUnboundedArray(index); + if (imgViews.empty()) + { + // skip empty unbounded arrays + continue; + } + + uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::ImageViewUnboundedArray); + descriptorSet.UpdateImageViews(layoutIndex, imgViews, shaderImageUnboundeArrayList[groupIndex].m_type); + } + } + + if (groupData.IsResourceTypeEnabledForCompilation(static_cast(RHI::ShaderResourceGroupData::ResourceTypeMask::SamplerMask))) + { + for (uint32_t groupIndex = 0; groupIndex < static_cast(layout->GetShaderInputListForSamplers().size()); ++groupIndex) + { + const RHI::ShaderInputSamplerIndex index(groupIndex); + auto samplerArray = groupData.GetSamplerArray(index); + uint32_t layoutIndex = m_descriptorSetLayout->GetLayoutIndexFromGroupIndex(groupIndex, DescriptorSetLayout::ResourceType::Sampler); + descriptorSet.UpdateSamplers(layoutIndex, samplerArray); + } } auto constantData = groupData.GetConstantData(); - if (!constantData.empty()) + if (!constantData.empty() && groupData.IsResourceTypeEnabledForCompilation(static_cast(RHI::ShaderResourceGroupData::ResourceTypeMask::ConstantDataMask))) { descriptorSet.UpdateConstantData(constantData); } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderResourceGroup.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderResourceGroup.cpp index f95c6abfcd..df16b5cd08 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderResourceGroup.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/ShaderResourceGroup.cpp @@ -114,6 +114,10 @@ namespace AZ void ShaderResourceGroup::Compile() { m_shaderResourceGroup->Compile(m_data); + + //Disable compilation for all resource types as a performance optimization + //No need to re-update SRG data on GPU timeline if nothing was updated. + m_data.DisableCompilationForAllResourceTypes(); } bool ShaderResourceGroup::IsQueuedForCompile() const From c38c9739da40e8613fefaf2b27f927cc1fad1adb Mon Sep 17 00:00:00 2001 From: mrieggeramzn <61609885+mrieggeramzn@users.noreply.github.com> Date: Tue, 12 Oct 2021 13:32:47 -0700 Subject: [PATCH 123/169] Adding vertexNormal to the Surface structure and using it for shadows (#4617) * Adding vertex shadow and using it for all shadows * Fixing small issue with it not being initialized * Adis recommendations for hair Signed-off-by: mrieggeramzn --- .../Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl | 2 +- Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl | 1 + .../Materials/Types/StandardMultilayerPBR_ForwardPass.azsl | 1 + .../Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl | 2 +- .../ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli | 2 +- .../Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli | 2 +- .../Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli | 2 +- .../ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli | 1 + .../ShaderLib/Atom/Features/PBR/Surfaces/SkinSurface.azsli | 1 + .../ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli | 1 + .../TestData/Materials/Types/AutoBrick_ForwardPass.azsl | 1 + .../TestData/Materials/Types/MinimalPBR_ForwardPass.azsl | 1 + Gems/AtomTressFX/Assets/Shaders/HairLightTypes.azsli | 3 ++- Gems/AtomTressFX/Assets/Shaders/HairLighting.azsli | 1 + Gems/AtomTressFX/Assets/Shaders/HairSurface.azsli | 1 + .../Terrain/Assets/Shaders/Terrain/TerrainPBR_ForwardPass.azsl | 1 + 16 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl index 26a7e21a6a..11859de7d6 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/EnhancedPBR_ForwardPass.azsl @@ -185,7 +185,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float float2 normalUv = IN.m_uv[MaterialSrg::m_normalMapUvIndex]; float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms. float detailLayerNormalFactor = MaterialSrg::m_detail_normal_factor * detailLayerBlendFactor; - + surface.vertexNormal = normalize(IN.m_normal); surface.normal = GetDetailedNormalInputWS( isFrontFace, IN.m_normal, tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_normalFactor, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, uvMatrix, o_normal_useTexture, diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl index 97cbfb2622..05059aba6f 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl @@ -237,6 +237,7 @@ PbrLightingOutput SkinPS_Common(VSOutput IN) normalMapSample = ApplyNormalWrinkleMap(o_wrinkleLayers_normal_useTexture4, normalMapSample, MaterialSrg::m_wrinkle_normal_texture4, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, IN.m_wrinkleBlendFactors.a); } + surface.vertexNormal = normalize(IN.m_normal); if(o_detail_normal_useTexture) { float3 normalTS = GetTangentSpaceNormal(normalMapSample, uvMatrix, MaterialSrg::m_normalFactor); diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl index 5d2aec063b..6a97c0e785 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardMultilayerPBR_ForwardPass.azsl @@ -445,6 +445,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float normalTS = ReorientTangentSpaceNormal(normalTS, lightingInputLayer3.m_normalTS); } // [GFX TODO][ATOM-14591]: This will only work if the normal maps all use the same UV stream. We would need to add support for having them in different UV streams. + surface.vertexNormal = normalize(IN.m_normal); surface.normal = normalize(TangentSpaceToWorld(normalTS, IN.m_normal, tangents[MaterialSrg::m_parallaxUvIndex], bitangents[MaterialSrg::m_parallaxUvIndex])); // ------- Combine Albedo, roughness, specular, roughness --------- diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl index 1fa5fc683c..8df5e1ba56 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/StandardPBR_ForwardPass.azsl @@ -146,7 +146,7 @@ PbrLightingOutput ForwardPassPS_Common(VSOutput IN, bool isFrontFace, out float float2 normalUv = IN.m_uv[MaterialSrg::m_normalMapUvIndex]; float3x3 uvMatrix = MaterialSrg::m_normalMapUvIndex == 0 ? MaterialSrg::m_uvMatrix : CreateIdentity3x3(); // By design, only UV0 is allowed to apply transforms. - + surface.vertexNormal = normalize(IN.m_normal); surface.normal = GetNormalInputWS(MaterialSrg::m_normalMap, MaterialSrg::m_sampler, normalUv, MaterialSrg::m_flipNormalX, MaterialSrg::m_flipNormalY, isFrontFace, IN.m_normal, tangents[MaterialSrg::m_normalMapUvIndex], bitangents[MaterialSrg::m_normalMapUvIndex], uvMatrix, o_normal_useTexture, MaterialSrg::m_normalFactor); diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli index 34c17e388c..1eee53a24f 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DirectionalLight.azsli @@ -24,7 +24,7 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) litRatio = DirectionalLightShadow::GetVisibility( shadowIndex, lightingData.shadowCoords, - surface.normal, + surface.vertexNormal, debugInfo); if (o_transmission_mode == TransmissionMode::ThickObject) diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli index ac9227f64a..63f671f021 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/DiskLight.azsli @@ -86,7 +86,7 @@ void ApplyDiskLight(ViewSrg::DiskLight light, Surface surface, inout LightingDat light.m_position, surface.position, -dirToConeTip, - surface.normal); + surface.vertexNormal); // Use backShadowRatio to carry thickness from shadow map for thick mode backShadowRatio = 1.0 - litRatio; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli index b88b6574a4..e6eea9728f 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Lights/PointLight.azsli @@ -83,7 +83,7 @@ void ApplyPointLight(ViewSrg::PointLight light, Surface surface, inout LightingD light.m_position, surface.position, lightDir, - surface.normal); + surface.vertexNormal); // Use backShadowRatio to carry thickness from shadow map for thick mode backShadowRatio = 1.0 - litRatio; diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli index 1b0ac3d76d..eb8c33cdce 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/EnhancedSurface.azsli @@ -23,6 +23,7 @@ class Surface float3 position; //!< Position in world-space float3 normal; //!< Normal in world-space + float3 vertexNormal; //!< Vertex normal in world-space float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value float3 specularF0; //!< Fresnel f0 spectral value of the surface float roughnessLinear; //!< Perceptually linear roughness value authored by artists. Must be remapped to roughnessA before use diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/SkinSurface.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/SkinSurface.azsli index 40f30d4f03..f82d80adee 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/SkinSurface.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/SkinSurface.azsli @@ -22,6 +22,7 @@ class Surface float3 position; //!< Position in world-space float3 normal; //!< Normal in world-space + float3 vertexNormal; //!< Vertex normal in world-space float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value float3 specularF0; //!< Fresnel f0 spectral value of the surface float roughnessLinear; //!< Perceptually linear roughness value authored by artists. Must be remapped to roughnessA before use diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli index 30e90323a5..084943bf38 100644 --- a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/PBR/Surfaces/StandardSurface.azsli @@ -22,6 +22,7 @@ class Surface float3 position; //!< Position in world-space float3 normal; //!< Normal in world-space + float3 vertexNormal; //!< Vertex normal in world-space float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value float3 specularF0; //!< Fresnel f0 spectral value of the surface float roughnessLinear; //!< Perceptually linear roughness value authored by artists. Must be remapped to roughnessA before use diff --git a/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl b/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl index 7be62c9343..2dbba46d8b 100644 --- a/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl +++ b/Gems/Atom/TestData/TestData/Materials/Types/AutoBrick_ForwardPass.azsl @@ -170,6 +170,7 @@ ForwardPassOutput AutoBrick_ForwardPassPS(VSOutput IN) // Position, Normal, Roughness surface.position = IN.m_worldPosition.xyz; surface.normal = normalize(normal); + surface.vertexNormal = surfaceNormal; surface.roughnessLinear = 1.0f; surface.CalculateRoughnessA(); diff --git a/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl b/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl index 6f73b63ad7..2f6f038e4b 100644 --- a/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl +++ b/Gems/Atom/TestData/TestData/Materials/Types/MinimalPBR_ForwardPass.azsl @@ -63,6 +63,7 @@ ForwardPassOutput MinimalPBR_MainPassPS(VSOutput IN) // Position, Normal, Roughness surface.position = IN.m_worldPosition.xyz; surface.normal = normalize(IN.m_normal); + surface.vertexNormal = normalize(IN.m_normal); surface.roughnessLinear = MinimalPBRSrg::m_roughness; surface.CalculateRoughnessA(); diff --git a/Gems/AtomTressFX/Assets/Shaders/HairLightTypes.azsli b/Gems/AtomTressFX/Assets/Shaders/HairLightTypes.azsli index 535d1380e7..4b0fa654e3 100644 --- a/Gems/AtomTressFX/Assets/Shaders/HairLightTypes.azsli +++ b/Gems/AtomTressFX/Assets/Shaders/HairLightTypes.azsli @@ -135,6 +135,7 @@ void SetNormalAndUpdateLightingParams( float3 projectedNormal = cross(biNormal, tangent); surface.normal = normalize(projectedNormal); // the normalization might be redundunt + surface.vertexNormal = surface.normal; // [To Do] - support proper vertex normals in the hair shader. // Next is important in order to set NdotV and other PBR settings - needs to be set once per light UpdateLightingParameters(lightingData, surface.position, surface.normal, surface.roughnessLinear); @@ -362,7 +363,7 @@ void ApplyDirectionalLights(Surface surface, inout LightingData lightingData) litRatio = DirectionalLightShadow::GetVisibility( shadowIndex, lightingData.shadowCoords, - surface.normal, + surface.vertexNormal, debugInfo); } diff --git a/Gems/AtomTressFX/Assets/Shaders/HairLighting.azsli b/Gems/AtomTressFX/Assets/Shaders/HairLighting.azsli index bf452e6ba8..dcdcf43243 100644 --- a/Gems/AtomTressFX/Assets/Shaders/HairLighting.azsli +++ b/Gems/AtomTressFX/Assets/Shaders/HairLighting.azsli @@ -197,6 +197,7 @@ float3 CalculateLighting( surface.position = vPositionWS; surface.tangent = vTangent; // Redundant - will be calculated per light surface.normal = float3(0, 0, 0); // Will fail lights that did not initialize properly. + surface.vertexNormal = float3(0,0,0); // [To Do] - vertex normals are not handled yet in the hair shader. surface.roughnessLinear = material.m_roughness; surface.cuticleTilt = material.m_cuticleTilt; surface.thickness = thickness; diff --git a/Gems/AtomTressFX/Assets/Shaders/HairSurface.azsli b/Gems/AtomTressFX/Assets/Shaders/HairSurface.azsli index 16496f0dcd..6ffd342734 100644 --- a/Gems/AtomTressFX/Assets/Shaders/HairSurface.azsli +++ b/Gems/AtomTressFX/Assets/Shaders/HairSurface.azsli @@ -18,6 +18,7 @@ class Surface // ------- BasePbrSurfaceData ------- float3 position; //!< Position in world-space float3 normal; //!< Normal in world-space + float3 vertexNormal; //!< Vertex normal in world-space float3 albedo; //!< Albedo color of the non-metallic material, will be multiplied against the diffuse lighting value float3 specularF0; //!< Fresnel f0 spectral value of the surface float roughnessLinear; //!< Perceptually linear roughness value authored by artists. Must be remapped to roughnessA before use diff --git a/Gems/Terrain/Assets/Shaders/Terrain/TerrainPBR_ForwardPass.azsl b/Gems/Terrain/Assets/Shaders/Terrain/TerrainPBR_ForwardPass.azsl index df2a801969..fedd19a498 100644 --- a/Gems/Terrain/Assets/Shaders/Terrain/TerrainPBR_ForwardPass.azsl +++ b/Gems/Terrain/Assets/Shaders/Terrain/TerrainPBR_ForwardPass.azsl @@ -95,6 +95,7 @@ ForwardPassOutput TerrainPBR_MainPassPS(VSOutput IN) detailNormal = ReorientTangentSpaceNormal(macroNormal, detailNormal); surface.normal = lerp(detailNormal, macroNormal, detailFactor); surface.normal = normalize(surface.normal); + surface.vertexNormal = normalize(IN.m_normal); // ------- Macro Color ------- float3 macroColor = GetBaseColorInput(TerrainMaterialSrg::m_macroColorMap, TerrainMaterialSrg::m_sampler, origUv, TerrainMaterialSrg::m_baseColor.rgb, o_baseColor_useTexture); From 6318247b3dc43d92f2825ed7afcc51e83aabda50 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 12 Oct 2021 13:34:51 -0700 Subject: [PATCH 124/169] LYN-7279 + LYN-7192 | Focus Mode - Container unit tests + Clear container entity open state on new level load (#4558) * Change SetContainerOpenState to SetContainerOpen. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Introduce Clear function to avoid retaining all lingering open states when switching contexts/loading a new level. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Minor FocusMode fixture refactors to support ContainerEntity tests Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Introduce tests for the ContainerEntity API Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Add include to fix issue with EntityContextId not being defined. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Minor comment fixes. Moved environment clear functions to TearDown function of test fixture. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Use default editor context id in ContainerEntitySystemComponent Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Revert previous change as the EditorEntityContextId would not be initialized correctly on ContainerEntitySystemComponent Activate. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../ContainerEntityInterface.h | 11 +- .../ContainerEntitySystemComponent.cpp | 39 ++- .../ContainerEntitySystemComponent.h | 8 +- .../Prefab/PrefabFocusHandler.cpp | 7 +- .../ContainerEntitySelectionTests.cpp | 99 ++++++ .../Tests/FocusMode/ContainerEntityTests.cpp | 293 ++++++++++++++++++ .../FocusMode/EditorFocusModeFixture.cpp | 37 ++- .../Tests/FocusMode/EditorFocusModeFixture.h | 10 +- .../EditorFocusModeSelectionFixture.h | 43 +++ .../EditorFocusModeSelectionTests.cpp | 82 +---- .../Tests/FocusMode/EditorFocusModeTests.cpp | 73 ++--- .../Tests/aztoolsframeworktests_files.cmake | 3 + 12 files changed, 575 insertions(+), 130 deletions(-) create mode 100644 Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntitySelectionTests.cpp create mode 100644 Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntityTests.cpp create mode 100644 Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionFixture.h diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h index 45da3a9d8f..95940e6dd6 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h @@ -11,6 +11,8 @@ #include #include +#include + namespace AzToolsFramework { //! Outcome object that returns an error message in case of failure to allow caller to handle internal errors. @@ -43,7 +45,7 @@ namespace AzToolsFramework //! @param entityId The entityId whose open state will be set. //! @param open True if the container should be opened, false if it should be closed. //! @return An error message if the operation was invalid, success otherwise. - virtual ContainerEntityOperationResult SetContainerOpenState(AZ::EntityId entityId, bool open) = 0; + virtual ContainerEntityOperationResult SetContainerOpen(AZ::EntityId entityId, bool open) = 0; //! If the entity id provided is registered as a container, it returns whether it's open. //! @note the default value for non-containers is true, so this function can be called without @@ -56,6 +58,13 @@ namespace AzToolsFramework //! @return The highest closed entity container id if any, or entityId otherwise. virtual AZ::EntityId FindHighestSelectableEntity(AZ::EntityId entityId) const = 0; + //! Clears all open state information for Container Entities for the EntityContextId provided. + //! Used when context is switched, for example in the case of a new root prefab being loaded + //! in place of an old one. + //! @note Clear is meant to be called when no container is registered for the context provided. + //! @return An error message if any container was registered for the context, success otherwise. + virtual ContainerEntityOperationResult Clear(AzFramework::EntityContextId entityContextId) = 0; + }; } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.cpp index 0ea2eeb5f6..c5649c56df 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.cpp @@ -10,16 +10,19 @@ #include #include +#include namespace AzToolsFramework { void ContainerEntitySystemComponent::Activate() { AZ::Interface::Register(this); + EditorEntityContextNotificationBus::Handler::BusConnect(); } void ContainerEntitySystemComponent::Deactivate() { + EditorEntityContextNotificationBus::Handler::BusDisconnect(); AZ::Interface::Unregister(this); } @@ -63,7 +66,7 @@ namespace AzToolsFramework return m_containers.contains(entityId); } - ContainerEntityOperationResult ContainerEntitySystemComponent::SetContainerOpenState(AZ::EntityId entityId, bool open) + ContainerEntityOperationResult ContainerEntitySystemComponent::SetContainerOpen(AZ::EntityId entityId, bool open) { if (!IsContainer(entityId)) { @@ -87,7 +90,7 @@ namespace AzToolsFramework bool ContainerEntitySystemComponent::IsContainerOpen(AZ::EntityId entityId) const { - // If the entity is not a container, it should behave as open. + // Non-container entities behave the same as open containers. This saves the caller an additional check. if(!m_containers.contains(entityId)) { return true; @@ -117,4 +120,36 @@ namespace AzToolsFramework return highestSelectableEntityId; } + void ContainerEntitySystemComponent::OnEntityStreamLoadSuccess() + { + // We don't yet support multiple entity contexts, so just use the default. + auto editorEntityContextId = AzFramework::EntityContextId::CreateNull(); + EditorEntityContextRequestBus::BroadcastResult(editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId); + + Clear(editorEntityContextId); + } + + ContainerEntityOperationResult ContainerEntitySystemComponent::Clear(AzFramework::EntityContextId entityContextId) + { + // We don't yet support multiple entity contexts, so only clear the default. + auto editorEntityContextId = AzFramework::EntityContextId::CreateNull(); + EditorEntityContextRequestBus::BroadcastResult(editorEntityContextId, &EditorEntityContextRequests::GetEditorEntityContextId); + + if (entityContextId != editorEntityContextId) + { + return AZ::Failure(AZStd::string( + "Error in ContainerEntitySystemComponent::Clear - cannot clear non-default Entity Context!")); + } + + if (!m_containers.empty()) + { + return AZ::Failure(AZStd::string( + "Error in ContainerEntitySystemComponent::Clear - cannot clear container states if entities are still registered!")); + } + + m_openContainers.clear(); + + return AZ::Success(); + } + } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h index 18c0fb70c6..44261979ef 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h @@ -12,6 +12,7 @@ #include #include +#include namespace AzToolsFramework { @@ -23,6 +24,7 @@ namespace AzToolsFramework class ContainerEntitySystemComponent final : public AZ::Component , private ContainerEntityInterface + , private EditorEntityContextNotificationBus::Handler { public: AZ_COMPONENT(ContainerEntitySystemComponent, "{74349759-B36B-44A6-B89F-F45D7111DD11}"); @@ -42,9 +44,13 @@ namespace AzToolsFramework ContainerEntityOperationResult RegisterEntityAsContainer(AZ::EntityId entityId) override; ContainerEntityOperationResult UnregisterEntityAsContainer(AZ::EntityId entityId) override; bool IsContainer(AZ::EntityId entityId) const override; - ContainerEntityOperationResult SetContainerOpenState(AZ::EntityId entityId, bool open) override; + ContainerEntityOperationResult SetContainerOpen(AZ::EntityId entityId, bool open) override; bool IsContainerOpen(AZ::EntityId entityId) const override; AZ::EntityId FindHighestSelectableEntity(AZ::EntityId entityId) const override; + ContainerEntityOperationResult Clear(AzFramework::EntityContextId entityContextId) override; + + // EditorEntityContextNotificationBus overrides ... + void OnEntityStreamLoadSuccess() override; private: AZStd::unordered_set m_containers; //!< All entities in this set are containers. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp index 9ffc18af5a..fcec1edd54 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp @@ -196,6 +196,9 @@ namespace AzToolsFramework::Prefab Initialize(); } + // Clear the old focus vector + m_instanceFocusVector.clear(); + // Focus on the root prefab (AZ::EntityId() will default to it) FocusOnOwningPrefab(AZ::EntityId()); } @@ -230,7 +233,7 @@ namespace AzToolsFramework::Prefab { if (instance.has_value()) { - m_containerEntityInterface->SetContainerOpenState(instance->get().GetContainerEntityId(), true); + m_containerEntityInterface->SetContainerOpen(instance->get().GetContainerEntityId(), true); } } } @@ -241,7 +244,7 @@ namespace AzToolsFramework::Prefab { if (instance.has_value()) { - m_containerEntityInterface->SetContainerOpenState(instance->get().GetContainerEntityId(), false); + m_containerEntityInterface->SetContainerOpen(instance->get().GetContainerEntityId(), false); } } } diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntitySelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntitySelectionTests.cpp new file mode 100644 index 0000000000..a47e41da42 --- /dev/null +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntitySelectionTests.cpp @@ -0,0 +1,99 @@ +/* + * 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 AzToolsFramework +{ + TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithNoContainers) + { + // When no containers are in the way, the function will just return the entityId of the entity that was clicked. + + // Click on Car Entity + ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + + // Verify the correct entity is selected + auto selectedEntitiesAfter = GetSelectedEntities(); + EXPECT_EQ(selectedEntitiesAfter.size(), 1); + EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]); + } + + TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithClosedContainer) + { + // If a closed container is an ancestor of the queried entity, the closed container is selected. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); // Containers are closed by default + + // Click on Car Entity + ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + + // Verify the correct entity is selected + auto selectedEntitiesAfter = GetSelectedEntities(); + EXPECT_EQ(selectedEntitiesAfter.size(), 1); + EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[StreetEntityName]); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]); + } + + TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithOpenContainer) + { + // If a closed container is an ancestor of the queried entity, the closed container is selected. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); + m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true); + + // Click on Car Entity + ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + + // Verify the correct entity is selected + auto selectedEntitiesAfter = GetSelectedEntities(); + EXPECT_EQ(selectedEntitiesAfter.size(), 1); + EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]); + } + + TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithMultipleClosedContainers) + { + // If multiple closed containers are ancestors of the queried entity, the highest closed container is selected. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]); + + // Click on Car Entity + ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + + // Verify the correct entity is selected + auto selectedEntitiesAfter = GetSelectedEntities(); + EXPECT_EQ(selectedEntitiesAfter.size(), 1); + EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CityEntityName]); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]); + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]); + } + + TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithMultipleContainers) + { + // If multiple containers are ancestors of the queried entity, the highest closed container is selected. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]); + m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], true); + + // Click on Car Entity + ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + + // Verify the correct entity is selected + auto selectedEntitiesAfter = GetSelectedEntities(); + EXPECT_EQ(selectedEntitiesAfter.size(), 1); + EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[StreetEntityName]); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]); + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]); + } +} diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntityTests.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntityTests.cpp new file mode 100644 index 0000000000..031062f027 --- /dev/null +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntityTests.cpp @@ -0,0 +1,293 @@ +/* + * 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 AzToolsFramework +{ + TEST_F(EditorFocusModeFixture, ContainerEntityTests_Register) + { + // Registering an entity is successful. + auto outcome = m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]); + EXPECT_TRUE(outcome.IsSuccess()); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_RegisterTwice) + { + // Registering an entity twice fails. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]); + auto outcome = m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]); + EXPECT_FALSE(outcome.IsSuccess()); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_Unregister) + { + // Unregistering a container entity is successful. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]); + auto outcome = m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]); + EXPECT_TRUE(outcome.IsSuccess()); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_UnregisterRegularEntity) + { + // Unregistering an entity that was not previously registered fails. + auto outcome = m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]); + EXPECT_FALSE(outcome.IsSuccess()); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_UnregisterTwice) + { + // Unregistering a container entity twice fails. + auto outcome = m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]); + EXPECT_FALSE(outcome.IsSuccess()); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOnRegularEntity) + { + // If a regular entity is passed, IsContainer returns false. + // Note that we use a different entity than the tests above to validate a completely new EntityId. + bool isContainer = m_containerEntityInterface->IsContainer(m_entityMap[SportsCarEntityName]); + EXPECT_FALSE(isContainer); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOnRegisteredContainer) + { + // If a container entity is passed, IsContainer returns true. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]); + bool isContainer = m_containerEntityInterface->IsContainer(m_entityMap[SportsCarEntityName]); + EXPECT_TRUE(isContainer); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOnUnRegisteredContainer) + { + // If an entity that was previously a container but was then unregistered is passed, IsContainer returns false. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]); + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]); + + bool isContainer = m_containerEntityInterface->IsContainer(m_entityMap[SportsCarEntityName]); + EXPECT_FALSE(isContainer); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_SetContainerOpenOnRegularEntity) + { + // Setting a regular entity to open should return a failure. + auto outcome = m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true); + EXPECT_FALSE(outcome.IsSuccess()); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_SetContainerOpen) + { + // Set a container entity to open, and verify the operation was successful. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); + auto outcome = m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true); + EXPECT_TRUE(outcome.IsSuccess()); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_SetContainerOpenTwice) + { + // Set a container entity to open twice, and verify that does not cause a failure (as intended). + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); + m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true); + auto outcome = m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true); + EXPECT_TRUE(outcome.IsSuccess()); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_SetContainerClosed) + { + // Set a container entity to closed, and verify the operation was successful. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); + auto outcome = m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true); + EXPECT_TRUE(outcome.IsSuccess()); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOpenOnRegularEntity) + { + // Query open state on a regular entity, and verify it returns true. + // Open containers behave exactly as regular entities, so this is the expected return value. + bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[CityEntityName]); + EXPECT_TRUE(isOpen); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOpenOnDefaultContainerEntity) + { + // Query open state on a newly registered container entity, and verify it returns false. + // Containers are registered closed by default. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]); + bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[CityEntityName]); + EXPECT_FALSE(isOpen); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOpenOnOpenContainerEntity) + { + // Query open state on a container entity that was opened, and verify it returns true. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]); + m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], true); + bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[CityEntityName]); + EXPECT_TRUE(isOpen); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOpenOnClosedContainerEntity) + { + // Query open state on a container entity that was opened and then closed, and verify it returns false. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]); + m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], true); + m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], false); + bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[CityEntityName]); + EXPECT_FALSE(isOpen); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_ContainerOpenStateIsPreserved) + { + // Register an entity as container, open it, then unregister it. + // When the entity is registered again, the open state should be preserved. + // This behavior is necessary for the system to work alongside Prefab propagation refreshes. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]); + m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], true); + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]); + + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]); + bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[CityEntityName]); + EXPECT_TRUE(isOpen); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_ClearSucceeds) + { + // The Clear function works if no container is registered. + auto outcome = m_containerEntityInterface->Clear(m_editorEntityContextId); + EXPECT_TRUE(outcome.IsSuccess()); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_ClearFailsIfContainersAreStillRegistered) + { + // The Clear function fails if a container is registered. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[Passenger1EntityName]); + auto outcome = m_containerEntityInterface->Clear(m_editorEntityContextId); + EXPECT_FALSE(outcome.IsSuccess()); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[Passenger1EntityName]); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_ClearSucceedsIfContainersAreUnregistered) + { + // The Clear function fails if a container is registered. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[Passenger1EntityName]); + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[Passenger1EntityName]); + auto outcome = m_containerEntityInterface->Clear(m_editorEntityContextId); + EXPECT_TRUE(outcome.IsSuccess()); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_ClearDeletesPreservedOpenStates) + { + // Register an entity as container, open it, unregister it, then call clear. + // When the entity is registered again, the open state should not be preserved. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[Passenger1EntityName]); + m_containerEntityInterface->SetContainerOpen(m_entityMap[Passenger1EntityName], true); + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[Passenger1EntityName]); + + m_containerEntityInterface->Clear(m_editorEntityContextId); + + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[Passenger1EntityName]); + bool isOpen = m_containerEntityInterface->IsContainerOpen(m_entityMap[Passenger1EntityName]); + EXPECT_FALSE(isOpen); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[Passenger1EntityName]); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithNoContainers) + { + // When no containers are in the way, the function will just return the entityId that was passed to it. + AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]); + EXPECT_EQ(selectedEntityId, m_entityMap[Passenger2EntityName]); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithClosedContainer) + { + // If a closed container is an ancestor of the queried entity, the closed container is selected. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]); // Containers are closed by default + AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]); + EXPECT_EQ(selectedEntityId, m_entityMap[SportsCarEntityName]); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithOpenContainer) + { + // If an open container is an ancestor of the queried entity, it is ignored. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]); + m_containerEntityInterface->SetContainerOpen(m_entityMap[SportsCarEntityName], true); + + AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]); + EXPECT_EQ(selectedEntityId, m_entityMap[Passenger2EntityName]); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithMultipleClosedContainers) + { + // If multiple closed containers are ancestors of the queried entity, the highest closed container is selected. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]); + + AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]); + EXPECT_EQ(selectedEntityId, m_entityMap[StreetEntityName]); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]); + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]); + } + + TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithMultipleContainers) + { + // If multiple containers are ancestors of the queried entity, the highest closed container is selected. + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); + m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]); + m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true); + + AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]); + EXPECT_EQ(selectedEntityId, m_entityMap[SportsCarEntityName]); + + // Restore default state for other tests. + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]); + m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]); + } + +} diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp index c309261a27..49bf7cee15 100644 --- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp @@ -14,6 +14,20 @@ namespace AzToolsFramework { + void ClearSelectedEntities() + { + AzToolsFramework::ToolsApplicationRequestBus::Broadcast( + &AzToolsFramework::ToolsApplicationRequestBus::Events::SetSelectedEntities, AzToolsFramework::EntityIdList()); + } + + AzToolsFramework::EntityIdList EditorFocusModeFixture::GetSelectedEntities() + { + AzToolsFramework::EntityIdList selectedEntities; + AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult( + selectedEntities, &AzToolsFramework::ToolsApplicationRequestBus::Events::GetSelectedEntities); + return selectedEntities; + } + void EditorFocusModeFixture::SetUpEditorFixtureImpl() { // Without this, the user settings component would attempt to save on finalize/shutdown. Since the file is @@ -21,6 +35,9 @@ namespace AzToolsFramework // in the unit tests. AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); + m_containerEntityInterface = AZ::Interface::Get(); + ASSERT_TRUE(m_containerEntityInterface != nullptr); + m_focusModeInterface = AZ::Interface::Get(); ASSERT_TRUE(m_focusModeInterface != nullptr); @@ -31,6 +48,24 @@ namespace AzToolsFramework m_editorEntityContextId, &AzToolsFramework::EditorEntityContextRequestBus::Events::GetEditorEntityContextId); GenerateTestHierarchy(); + + // Clear the focus, disabling focus mode + m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId); + + // Clear selection + ClearSelectedEntities(); + } + + void EditorFocusModeFixture::TearDownEditorFixtureImpl() + { + // Clear Container Entity preserved open states + m_containerEntityInterface->Clear(m_editorEntityContextId); + + // Clear the focus, disabling focus mode + m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId); + + // Clear selection + ClearSelectedEntities(); } void EditorFocusModeFixture::GenerateTestHierarchy() @@ -59,7 +94,7 @@ namespace AzToolsFramework entity->Activate(); // Move the CarEntity so it's out of the way. - AZ::TransformBus::Event(m_entityMap[CarEntityName], &AZ::TransformBus::Events::SetWorldTranslation, CarEntityPosition); + AZ::TransformBus::Event(m_entityMap[CarEntityName], &AZ::TransformBus::Events::SetWorldTranslation, WorldCarEntityPosition); // Setup the camera so the Car entity is in view. AzFramework::SetCameraTransform( diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h index f038408012..c48795a3a4 100644 --- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h @@ -14,6 +14,7 @@ #include +#include #include #include @@ -24,16 +25,20 @@ namespace AzToolsFramework { protected: void SetUpEditorFixtureImpl() override; + void TearDownEditorFixtureImpl() override; void GenerateTestHierarchy(); AZ::EntityId CreateEditorEntity(const char* name, AZ::EntityId parentId); AZStd::unordered_map m_entityMap; + + ContainerEntityInterface* m_containerEntityInterface = nullptr; FocusModeInterface* m_focusModeInterface = nullptr; public: - AzFramework::EntityContextId m_editorEntityContextId = AzFramework::EntityContextId::CreateNull(); + AzToolsFramework::EntityIdList GetSelectedEntities(); + AzFramework::EntityContextId m_editorEntityContextId = AzFramework::EntityContextId::CreateNull(); AzFramework::CameraState m_cameraState; inline static const AZ::Vector3 CameraPosition = AZ::Vector3(10.0f, 15.0f, 10.0f); @@ -45,6 +50,7 @@ namespace AzToolsFramework inline static const char* Passenger1EntityName = "Passenger1"; inline static const char* Passenger2EntityName = "Passenger2"; - inline static AZ::Vector3 CarEntityPosition = AZ::Vector3(5.0f, 15.0f, 0.0f); + inline static AZ::Vector3 WorldCarEntityPosition = AZ::Vector3(5.0f, 15.0f, 0.0f); }; + } diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionFixture.h b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionFixture.h new file mode 100644 index 0000000000..4c9369bc46 --- /dev/null +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionFixture.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace AzToolsFramework +{ + class EditorFocusModeSelectionFixture : public UnitTest::IndirectCallManipulatorViewportInteractionFixtureMixin + { + public: + void ClickAtWorldPositionOnViewport(const AZ::Vector3& worldPosition) + { + // Calculate the world position in screen space + const auto carScreenPosition = AzFramework::WorldToScreen(worldPosition, m_cameraState); + + // Click the entity in the viewport + m_actionDispatcher->CameraState(m_cameraState)->MousePosition(carScreenPosition)->MouseLButtonDown()->MouseLButtonUp(); + } + }; +} // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp index 968bb3f293..2f746c9d63 100644 --- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp @@ -6,64 +6,14 @@ * */ -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - +#include namespace AzToolsFramework { - class EditorFocusModeSelectionFixture - : public UnitTest::IndirectCallManipulatorViewportInteractionFixtureMixin - { - public: - void ClickAtWorldPositionOnViewport(const AZ::Vector3& worldPosition) - { - // Calculate the world position in screen space - const auto carScreenPosition = AzFramework::WorldToScreen(worldPosition, m_cameraState); - - // Click the entity in the viewport - m_actionDispatcher->CameraState(m_cameraState)->MousePosition(carScreenPosition)->MouseLButtonDown()->MouseLButtonUp(); - } - }; - - void ClearSelectedEntities() - { - AzToolsFramework::ToolsApplicationRequestBus::Broadcast( - &AzToolsFramework::ToolsApplicationRequestBus::Events::SetSelectedEntities, AzToolsFramework::EntityIdList()); - } - - AzToolsFramework::EntityIdList GetSelectedEntities() - { - AzToolsFramework::EntityIdList selectedEntities; - AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult( - selectedEntities, &AzToolsFramework::ToolsApplicationRequestBus::Events::GetSelectedEntities); - return selectedEntities; - } - TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnLevel) { - // Clear the focus, disabling focus mode - m_focusModeInterface->ClearFocusRoot(AzFramework::EntityContextId::CreateNull()); - // Clear selection - ClearSelectedEntities(); - // Click on Car Entity - ClickAtWorldPositionOnViewport(CarEntityPosition); + ClickAtWorldPositionOnViewport(WorldCarEntityPosition); // Verify entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -75,73 +25,53 @@ namespace AzToolsFramework { // Set the focus on the Street Entity (parent of the test entity) m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]); - // Clear selection - ClearSelectedEntities(); // Click on Car Entity - ClickAtWorldPositionOnViewport(CarEntityPosition); + ClickAtWorldPositionOnViewport(WorldCarEntityPosition); // Verify entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); EXPECT_EQ(selectedEntitiesAfter.size(), 1); EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]); - - // Clear the focus, disabling focus mode - m_focusModeInterface->ClearFocusRoot(AzFramework::EntityContextId::CreateNull()); } TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnItself) { // Set the focus on the Car Entity (test entity) m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]); - // Clear selection - ClearSelectedEntities(); // Click on Car Entity - ClickAtWorldPositionOnViewport(CarEntityPosition); + ClickAtWorldPositionOnViewport(WorldCarEntityPosition); // Verify entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); EXPECT_EQ(selectedEntitiesAfter.size(), 1); EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]); - - // Clear the focus, disabling focus mode - m_focusModeInterface->ClearFocusRoot(AzFramework::EntityContextId::CreateNull()); } TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnSibling) { // Set the focus on the SportsCar Entity (sibling of the test entity) m_focusModeInterface->SetFocusRoot(m_entityMap[SportsCarEntityName]); - // Clear selection - ClearSelectedEntities(); // Click on Car Entity - ClickAtWorldPositionOnViewport(CarEntityPosition); + ClickAtWorldPositionOnViewport(WorldCarEntityPosition); // Verify entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); EXPECT_EQ(selectedEntitiesAfter.size(), 0); - - // Clear the focus, disabling focus mode - m_focusModeInterface->ClearFocusRoot(AzFramework::EntityContextId::CreateNull()); } TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnDescendant) { // Set the focus on the Passenger1 Entity (child of the entity) m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger1EntityName]); - // Clear selection - ClearSelectedEntities(); // Click on Car Entity - ClickAtWorldPositionOnViewport(CarEntityPosition); + ClickAtWorldPositionOnViewport(WorldCarEntityPosition); // Verify entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); EXPECT_EQ(selectedEntitiesAfter.size(), 0); - - // Clear the focus, disabling focus mode - m_focusModeInterface->ClearFocusRoot(AzFramework::EntityContextId::CreateNull()); } } diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeTests.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeTests.cpp index 22bc7a494c..eec3902f99 100644 --- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeTests.cpp @@ -33,55 +33,40 @@ namespace AzToolsFramework TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_AncestorsDescendants) { // When the focus is set to an entity, all its descendants are in the focus subtree while the ancestors aren't. - { - m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]); + m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), true); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), true); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true); - } - - // Restore default expected focus. - m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true); } TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_Siblings) { // If the root entity has siblings, they are also outside of the focus subtree. - { - m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]); + m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), false); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), false); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), false); - } - - // Restore default expected focus. - m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), false); } TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_Leaf) { // If the root is a leaf, then the focus subtree will consists of just that entity. - { - m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger2EntityName]); + m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger2EntityName]); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), false); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), false); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), false); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), false); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true); - } - - // Restore default expected focus. - m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), false); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true); } TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_Clear) @@ -90,15 +75,13 @@ namespace AzToolsFramework m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]); // When the focus is cleared, the whole level is in the focus subtree; so we expect all entities to return true. - { - m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId); + m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), true); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), true); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), true); - EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true); - } + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CityEntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[StreetEntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[CarEntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger1EntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), true); + EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true); } } diff --git a/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake b/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake index 87d522c4a6..ef6774f620 100644 --- a/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake +++ b/Code/Framework/AzToolsFramework/Tests/aztoolsframeworktests_files.cmake @@ -37,8 +37,11 @@ set(FILES EntityTestbed.h FileFunc.cpp FingerprintingTests.cpp + FocusMode/ContainerEntitySelectionTests.cpp + FocusMode/ContainerEntityTests.cpp FocusMode/EditorFocusModeFixture.cpp FocusMode/EditorFocusModeFixture.h + FocusMode/EditorFocusModeSelectionFixture.h FocusMode/EditorFocusModeSelectionTests.cpp FocusMode/EditorFocusModeTests.cpp GenericComponentWrapperTest.cpp From f7e08d1c4bcfc983fc8d5f035b03a81673bf00a6 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Tue, 12 Oct 2021 15:36:19 -0500 Subject: [PATCH 125/169] =?UTF-8?q?PropertyAssetCtrl=20and=20ThumbnailProp?= =?UTF-8?q?ertyCtrl=20support=20custom=20thumbnail=20images=20=E2=80=A2=20?= =?UTF-8?q?PropertyAssetCtrl=20was=20previously=20extended=20with=20Thumbn?= =?UTF-8?q?ailPropertyCtrl=20to=20optionally=20display=20a=20thumbnail=20a?= =?UTF-8?q?nd=20floating=20zoomed=20in=20preview=20of=20the=20selected=20a?= =?UTF-8?q?sset.=20=E2=80=A2=20This=20change=20allows=20overriding=20the?= =?UTF-8?q?=20image=20that=20comes=20from=20the=20thumbnail=20system=20wit?= =?UTF-8?q?h=20a=20custom=20image=20provided=20as=20an=20attribute.=20The?= =?UTF-8?q?=20custom=20image=20can=20be=20specified=20as=20either=20a=20fi?= =?UTF-8?q?le=20path=20or=20a=20buffer=20containing=20a=20serialized=20QPi?= =?UTF-8?q?xmap.=20=E2=80=A2=20This=20will=20be=20used=20by=20the=20materi?= =?UTF-8?q?al=20system=20in=20the=20editor=20to=20provide=20a=20dynamicall?= =?UTF-8?q?y=20rendered=20image=20of=20the=20material=20with=20property=20?= =?UTF-8?q?overrides=20applied=20so=20that=20the=20image=20will=20update?= =?UTF-8?q?=20as=20the=20user=20customizes=20their=20material.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Guthrie Adams --- .../UI/PropertyEditor/PropertyAssetCtrl.cpp | 57 +++++++- .../UI/PropertyEditor/PropertyAssetCtrl.hxx | 5 + .../PropertyEditor/ThumbnailPropertyCtrl.cpp | 131 +++++++++++------- .../UI/PropertyEditor/ThumbnailPropertyCtrl.h | 25 +++- 4 files changed, 161 insertions(+), 57 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp index ba84e662c1..7f3b9e61fd 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp @@ -28,6 +28,9 @@ AZ_PUSH_DISABLE_WARNING(4244 4251, "-Wunknown-warning-option") #include #include #include +#include +#include +#include AZ_POP_DISABLE_WARNING #include @@ -1230,6 +1233,16 @@ namespace AzToolsFramework return m_showThumbnailDropDownButton; } + void PropertyAssetCtrl::SetCustomThumbnailEnabled(bool enabled) + { + m_thumbnail->SetCustomThumbnailEnabled(enabled); + } + + void PropertyAssetCtrl::SetCustomThumbnailPixmap(const QPixmap& pixmap) + { + m_thumbnail->SetCustomThumbnailPixmap(pixmap); + } + void PropertyAssetCtrl::SetThumbnailCallback(EditCallbackType* editNotifyCallback) { m_thumbnailCallback = editNotifyCallback; @@ -1356,15 +1369,27 @@ namespace AzToolsFramework GUI->SetClearNotifyCallback(nullptr); } } - else if (attrib == AZ_CRC("BrowseIcon", 0x507d7a4f)) + else if (attrib == AZ_CRC_CE("BrowseIcon")) { AZStd::string iconPath; - attrValue->Read(iconPath); - - if (!iconPath.empty()) + if (attrValue->Read(iconPath) && !iconPath.empty()) { GUI->SetBrowseButtonIcon(QIcon(iconPath.c_str())); } + else + { + // A QPixmap object can't be assigned directly via an attribute. + // This allows dynamic icon data to be supplied as a buffer containing a serialized QPixmap. + AZStd::vector pixmapBuffer; + if (attrValue->Read>(pixmapBuffer) && !pixmapBuffer.empty()) + { + QByteArray pixmapBytes(pixmapBuffer.data(), aznumeric_cast(pixmapBuffer.size())); + QDataStream stream(&pixmapBytes, QIODevice::ReadOnly); + QPixmap pixmap; + stream >> pixmap; + GUI->SetBrowseButtonIcon(pixmap); + } + } } else if (attrib == AZ_CRC_CE("BrowseButtonEnabled")) { @@ -1390,6 +1415,30 @@ namespace AzToolsFramework GUI->SetShowThumbnail(showThumbnail); } } + else if (attrib == AZ_CRC_CE("ThumbnailIcon")) + { + AZStd::string iconPath; + if (attrValue->Read(iconPath) && !iconPath.empty()) + { + GUI->SetCustomThumbnailEnabled(true); + GUI->SetCustomThumbnailPixmap(QPixmap::fromImage(QImage(iconPath.c_str()))); + } + else + { + // A QPixmap object can't be assigned directly via an attribute. + // This allows dynamic icon data to be supplied as a buffer containing a serialized QPixmap. + AZStd::vector pixmapBuffer; + if (attrValue->Read>(pixmapBuffer) && !pixmapBuffer.empty()) + { + QByteArray pixmapBytes(pixmapBuffer.data(), aznumeric_cast(pixmapBuffer.size())); + QDataStream stream(&pixmapBytes, QIODevice::ReadOnly); + QPixmap pixmap; + stream >> pixmap; + GUI->SetCustomThumbnailEnabled(true); + GUI->SetCustomThumbnailPixmap(pixmap); + } + } + } else if (attrib == AZ_CRC_CE("ThumbnailCallback")) { PropertyAssetCtrl::EditCallbackType* func = azdynamic_cast(attrValue->GetAttribute()); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx index cc4aff5649..0b98278bc5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx @@ -217,12 +217,17 @@ namespace AzToolsFramework void SetHideProductFilesInAssetPicker(bool hide); bool GetHideProductFilesInAssetPicker() const; + // Enable and configure a thumbnail widget that displays an asset preview and dropdown arrow for a dropdown menu void SetShowThumbnail(bool enable); bool GetShowThumbnail() const; void SetShowThumbnailDropDownButton(bool enable); bool GetShowThumbnailDropDownButton() const; void SetThumbnailCallback(EditCallbackType* editNotifyCallback); + // If enabled, replaces the thumbnail widget content with a custom pixmap + void SetCustomThumbnailEnabled(bool enabled); + void SetCustomThumbnailPixmap(const QPixmap& pixmap); + void SetSelectedAssetID(const AZ::Data::AssetId& newID); void SetCurrentAssetType(const AZ::Data::AssetType& newType); void SetSelectedAssetID(const AZ::Data::AssetId& newID, const AZ::Data::AssetType& newType); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.cpp index c458f7c47e..d8ddee6b76 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.cpp @@ -7,75 +7,117 @@ */ #include -AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") // 4251: 'QRawFont::d': class 'QExplicitlySharedDataPointer' needs to have dll-interface to be used by clients of class 'QRawFont' - // 4800: 'QTextEngine *const ': forcing value to bool 'true' or 'false' (performance warning) -#include -#include -#include -#include -#include -#include + +// 4251: 'QRawFont::d': class 'QExplicitlySharedDataPointer' needs to have dll-interface to be used by clients of class +// 'QRawFont' 4800: 'QTextEngine *const ': forcing value to bool 'true' or 'false' (performance warning) +AZ_PUSH_DISABLE_WARNING(4251 4800, "-Wunknown-warning-option") #include +#include +#include +#include +#include +#include +#include AZ_POP_DISABLE_WARNING #include "ThumbnailPropertyCtrl.h" namespace AzToolsFramework { - ThumbnailPropertyCtrl::ThumbnailPropertyCtrl(QWidget* parent) : QWidget(parent) { - QHBoxLayout* pLayout = new QHBoxLayout(); - pLayout->setContentsMargins(0, 0, 0, 0); - pLayout->setSpacing(0); - m_thumbnail = new Thumbnailer::ThumbnailWidget(this); m_thumbnail->setFixedSize(QSize(24, 24)); + m_thumbnailEnlarged = new Thumbnailer::ThumbnailWidget(this); + m_thumbnailEnlarged->setFixedSize(QSize(180, 180)); + m_thumbnailEnlarged->setWindowFlags(Qt::Window | Qt::FramelessWindowHint); + + m_customThumbnail = new QLabel(this); + m_customThumbnail->setFixedSize(QSize(24, 24)); + m_customThumbnail->setScaledContents(true); + + m_customThumbnailEnlarged = new QLabel(this); + m_customThumbnailEnlarged->setFixedSize(QSize(180, 180)); + m_customThumbnailEnlarged->setWindowFlags(Qt::Window | Qt::FramelessWindowHint); + m_customThumbnailEnlarged->setScaledContents(true); + m_dropDownArrow = new AspectRatioAwarePixmapWidget(this); m_dropDownArrow->setPixmap(QPixmap(":/stylesheet/img/triangle0.png")); m_dropDownArrow->setFixedSize(QSize(8, 24)); - ShowDropDownArrow(false); m_emptyThumbnail = new QLabel(this); m_emptyThumbnail->setPixmap(QPixmap(":/stylesheet/img/line.png")); m_emptyThumbnail->setFixedSize(QSize(24, 24)); - pLayout->addWidget(m_emptyThumbnail); + QHBoxLayout* pLayout = new QHBoxLayout(); + pLayout->setContentsMargins(0, 0, 0, 0); + pLayout->setSpacing(0); pLayout->addWidget(m_thumbnail); + pLayout->addWidget(m_customThumbnail); + pLayout->addWidget(m_emptyThumbnail); pLayout->addSpacing(4); pLayout->addWidget(m_dropDownArrow); pLayout->addSpacing(4); - setLayout(pLayout); + + ShowDropDownArrow(false); + UpdateVisibility(); } void ThumbnailPropertyCtrl::SetThumbnailKey(Thumbnailer::SharedThumbnailKey key, const char* contextName) { - m_key = key; - m_emptyThumbnail->setVisible(false); - m_thumbnail->SetThumbnailKey(key, contextName); + if (m_customThumbnailEnabled) + { + ClearThumbnail(); + } + else + { + m_key = key; + m_thumbnail->SetThumbnailKey(m_key, contextName); + m_thumbnailEnlarged->SetThumbnailKey(m_key, contextName); + } + UpdateVisibility(); } void ThumbnailPropertyCtrl::ClearThumbnail() { - m_emptyThumbnail->setVisible(true); + m_key.clear(); m_thumbnail->ClearThumbnail(); + m_thumbnailEnlarged->ClearThumbnail(); + UpdateVisibility(); } void ThumbnailPropertyCtrl::ShowDropDownArrow(bool visible) { - if (visible) - { - setFixedSize(QSize(40, 24)); - } - else - { - setFixedSize(QSize(24, 24)); - } + setFixedSize(QSize(visible ? 40 : 24, 24)); m_dropDownArrow->setVisible(visible); } + void ThumbnailPropertyCtrl::SetCustomThumbnailEnabled(bool enabled) + { + m_customThumbnailEnabled = enabled; + UpdateVisibility(); + } + + void ThumbnailPropertyCtrl::SetCustomThumbnailPixmap(const QPixmap& pixmap) + { + m_customThumbnail->setPixmap(pixmap); + m_customThumbnailEnlarged->setPixmap(pixmap); + UpdateVisibility(); + } + + void ThumbnailPropertyCtrl::UpdateVisibility() + { + m_thumbnail->setVisible(m_key && !m_customThumbnailEnabled); + m_thumbnailEnlarged->setVisible(false); + + m_customThumbnail->setVisible(m_customThumbnailEnabled); + m_customThumbnailEnlarged->setVisible(false); + + m_emptyThumbnail->setVisible(!m_key && !m_customThumbnailEnabled); + } + bool ThumbnailPropertyCtrl::event(QEvent* e) { if (isEnabled()) @@ -83,7 +125,7 @@ namespace AzToolsFramework if (e->type() == QEvent::MouseButtonPress) { emit clicked(); - return true; //ignore + return true; // ignore } } @@ -94,37 +136,32 @@ namespace AzToolsFramework { QPainter p(this); QRect targetRect(QPoint(), QSize(40, 24)); - p.fillRect(targetRect, QColor(17, 17, 17)); // #111111 + p.fillRect(targetRect, QColor("#111111")); QWidget::paintEvent(e); } void ThumbnailPropertyCtrl::enterEvent(QEvent* e) { m_dropDownArrow->setPixmap(QPixmap(":/stylesheet/img/triangle0_highlighted.png")); - if (!m_thumbnailEnlarged && m_key) - { - QPoint position = mapToGlobal(pos() - QPoint(185, 0)); - QSize size(180, 180); - m_thumbnailEnlarged.reset(new Thumbnailer::ThumbnailWidget()); - m_thumbnailEnlarged->setFixedSize(size); - m_thumbnailEnlarged->move(position); - m_thumbnailEnlarged->setWindowFlags(Qt::Window | Qt::FramelessWindowHint); - m_thumbnailEnlarged->SetThumbnailKey(m_key); - m_thumbnailEnlarged->raise(); - m_thumbnailEnlarged->show(); - } + const QPoint offset(-m_thumbnailEnlarged->width() - 5, -m_thumbnailEnlarged->height() / 2 + m_thumbnail->height() / 2); + + m_thumbnailEnlarged->move(mapToGlobal(pos()) + offset); + m_thumbnailEnlarged->raise(); + m_thumbnailEnlarged->setVisible(m_key && !m_customThumbnailEnabled); + + m_customThumbnailEnlarged->move(mapToGlobal(pos()) + offset); + m_customThumbnailEnlarged->raise(); + m_customThumbnailEnlarged->setVisible(m_customThumbnailEnabled); QWidget::enterEvent(e); } void ThumbnailPropertyCtrl::leaveEvent(QEvent* e) { m_dropDownArrow->setPixmap(QPixmap(":/stylesheet/img/triangle0.png")); - if (m_thumbnailEnlarged) - { - m_thumbnailEnlarged.reset(); - } + m_thumbnailEnlarged->setVisible(false); + m_customThumbnailEnlarged->setVisible(false); QWidget::leaveEvent(e); } -} +} // namespace AzToolsFramework #include "UI/PropertyEditor/moc_ThumbnailPropertyCtrl.cpp" diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.h index 93f703c4c5..b1ce78b601 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.h @@ -1,5 +1,3 @@ -#pragma once - /* * 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. @@ -8,6 +6,8 @@ * */ +#pragma once + #if !defined(Q_MOC_RUN) #include #include @@ -35,25 +35,38 @@ namespace AzToolsFramework //! Call this to set what thumbnail widget will display void SetThumbnailKey(Thumbnailer::SharedThumbnailKey key, const char* contextName = "Default"); + //! Remove current thumbnail void ClearThumbnail(); + //! Display a clickble dropdown arrow next to the thumbnail void ShowDropDownArrow(bool visible); - bool event(QEvent* e) override; + //! Override the thumbnail widget with a custom image + void SetCustomThumbnailEnabled(bool enabled); + + //! Assign a custom image to dispsy in place of thumbnail + void SetCustomThumbnailPixmap(const QPixmap& pixmap); Q_SIGNALS: void clicked(); - protected: + private: + void UpdateVisibility(); + + bool event(QEvent* e) override; void paintEvent(QPaintEvent* e) override; void enterEvent(QEvent* e) override; void leaveEvent(QEvent* e) override; - private: Thumbnailer::SharedThumbnailKey m_key; Thumbnailer::ThumbnailWidget* m_thumbnail = nullptr; - QScopedPointer m_thumbnailEnlarged; + Thumbnailer::ThumbnailWidget* m_thumbnailEnlarged = nullptr; + + QLabel* m_customThumbnail = nullptr; + QLabel* m_customThumbnailEnlarged = nullptr; + bool m_customThumbnailEnabled = false; + QLabel* m_emptyThumbnail = nullptr; AspectRatioAwarePixmapWidget* m_dropDownArrow = nullptr; }; From c35b0e5eface4f68c85190a2fd1d3c639e9ed8ed Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Tue, 12 Oct 2021 13:46:02 -0700 Subject: [PATCH 126/169] fix a test string to indicate PostFX Layer Signed-off-by: Scott Murray --- ...dra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py index be139f83b6..fe6362c9b7 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py @@ -22,8 +22,8 @@ class Tests: "PostFx Shape Weight Modifier component disabled", "PostFx Shape Weight Modifier component was not disabled.") postfx_layer_component = ( - "Entity has an Actor component", - "Entity did not have an Actor component") + "Entity has a PostFX Layer component", + "Entity did not have an PostFX Layer component") shape_component = ( "Entity has a Tube Shape component", "Entity did not have a Tube Shape component") From 4f539b0eb7c123bb4e35bbc144db14479ad52924 Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Tue, 12 Oct 2021 16:17:19 -0500 Subject: [PATCH 127/169] fixed comments Signed-off-by: Guthrie Adams --- .../UI/PropertyEditor/ThumbnailPropertyCtrl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.h index b1ce78b601..ffd8234190 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/ThumbnailPropertyCtrl.h @@ -39,13 +39,13 @@ namespace AzToolsFramework //! Remove current thumbnail void ClearThumbnail(); - //! Display a clickble dropdown arrow next to the thumbnail + //! Display a clickable dropdown arrow next to the thumbnail void ShowDropDownArrow(bool visible); //! Override the thumbnail widget with a custom image void SetCustomThumbnailEnabled(bool enabled); - //! Assign a custom image to dispsy in place of thumbnail + //! Assign a custom image to display in place of thumbnail void SetCustomThumbnailPixmap(const QPixmap& pixmap); Q_SIGNALS: From 80db67e90a1aa44c954d3814eaefd12c345db2b3 Mon Sep 17 00:00:00 2001 From: Artur K <96597+nemerle@users.noreply.github.com> Date: Wed, 13 Oct 2021 00:06:15 +0200 Subject: [PATCH 128/169] Remove many unused variables and unused setting files (#4607) * Remove many unused variables and unused setting files Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * Remove a few more dead config vars Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> * fix android test_ConfigureSettings_DefaultValues_SetsValues Signed-off-by: nemerle <96597+nemerle@users.noreply.github.com> --- Assets/Editor/MapScreenshotSettings.xml | 13 -- Assets/Editor/UserTools.xml | 2 - Assets/Engine/Config/AutoTestChain.cfg | 11 -- Assets/Engine/Config/AutoTestTimeDemo.cfg | 10 -- Assets/Engine/Config/AutotestPlaythrough.cfg | 9 +- .../Config/CVarGroups/sys_spec_Full.cfg | 97 ----------- .../CVarGroups/sys_spec_GameEffects.cfg | 8 - .../CVarGroups/sys_spec_ObjectDetail.cfg | 160 ------------------ .../Config/CVarGroups/sys_spec_Particles.cfg | 94 ---------- .../Config/CVarGroups/sys_spec_Physics.cfg | 100 ----------- .../CVarGroups/sys_spec_PostProcessing.cfg | 114 ------------- .../Config/CVarGroups/sys_spec_Quality.cfg | 98 ----------- .../Config/CVarGroups/sys_spec_Shading.cfg | 120 ------------- .../Config/CVarGroups/sys_spec_Shadows.cfg | 116 ------------- .../Config/CVarGroups/sys_spec_Sound.cfg | 17 -- .../Config/CVarGroups/sys_spec_Texture.cfg | 94 ---------- .../CVarGroups/sys_spec_TextureResolution.cfg | 52 ------ .../CVarGroups/sys_spec_VolumetricEffects.cfg | 26 --- .../Config/CVarGroups/sys_spec_Water.cfg | 81 --------- Assets/Engine/Config/aidebug.cfg | 3 - Assets/Engine/Config/artprof.cfg | 14 +- Assets/Engine/Config/artprof_user.cfg | 3 - Assets/Engine/Config/benchmark_cpu.cfg | 10 -- Assets/Engine/Config/benchmark_gpu.cfg | 12 +- Assets/Engine/Config/mgpu.cfg | 6 - Assets/Engine/Config/multiplayer.cfg | 77 --------- Assets/Engine/Config/multiplayer_console.cfg | 29 ---- Assets/Engine/Config/recording.cfg | 60 ------- Assets/Engine/Config/singleplayer.cfg | 15 -- Assets/Engine/Config/sketch_off.cfg | 24 --- Assets/Engine/Config/sketch_on.cfg | 24 --- .../Engine/Config/spec/android_MaliT760.cfg | 68 -------- Assets/Engine/Config/spec/android_high.cfg | 58 ------- .../Config/spec/android_high_nogmem.cfg | 53 ------ Assets/Engine/Config/spec/android_low.cfg | 69 -------- Assets/Engine/Config/spec/android_medium.cfg | 74 -------- .../Engine/Config/spec/android_veryhigh.cfg | 55 ------ Assets/Engine/Config/spec/ios_high.cfg | 90 ---------- Assets/Engine/Config/spec/ios_low.cfg | 93 ---------- Assets/Engine/Config/spec/ios_medium.cfg | 91 ---------- Assets/Engine/Config/spec/ios_veryhigh.cfg | 92 ---------- Assets/Engine/Config/spec/osx_metal_high.cfg | 38 ----- Assets/Engine/Config/spec/osx_metal_low.cfg | 37 ---- .../Engine/Config/spec/osx_metal_medium.cfg | 37 ---- .../Engine/Config/spec/osx_metal_veryhigh.cfg | 37 ---- Assets/Engine/Config/spec/pc_high.cfg | 1 - Assets/Engine/Config/spec/pc_low.cfg | 1 - Assets/Engine/Config/spec/pc_medium.cfg | 1 - Assets/Engine/Config/spec/pc_veryhigh.cfg | 1 - Assets/Engine/Config/statoscope.cfg | 9 - Assets/Engine/Config/vr.cfg | 26 --- Assets/Engine/SeedAssetList.seed | 152 ----------------- .../Atom/atom_utils/atom_component_helper.py | 1 - ...GPUTest_AtomFeatureIntegrationBenchmark.py | 1 - .../tests/hydra_GPUTest_BasicLevelSetup.py | 1 - .../editor_python_test_tools/utils.py | 1 - .../screenshot_utils.py | 4 - Code/Legacy/CrySystem/SystemInit.cpp | 21 --- .../Code/Source/Processing/ImageFlags.h | 2 +- .../Source/LYCommonMenu/ImGuiLYCommonMenu.cpp | 14 -- .../launchers/platforms/android/launcher.py | 7 - .../launchers/platforms/linux/launcher.py | 1 - .../launchers/platforms/win/launcher.py | 2 - .../tests/unit/test_launcher_android.py | 2 +- cmake/Tools/layout_tool.py | 39 ++--- editor.cfg | 21 --- system_android_android.cfg | 30 +--- system_ios_ios.cfg | 29 ---- system_linux_pc.cfg | 22 --- system_mac_mac.cfg | 21 --- system_windows_pc.cfg | 20 --- 71 files changed, 21 insertions(+), 2800 deletions(-) delete mode 100644 Assets/Engine/Config/CVarGroups/sys_spec_GameEffects.cfg delete mode 100644 Assets/Engine/Config/CVarGroups/sys_spec_ObjectDetail.cfg delete mode 100644 Assets/Engine/Config/CVarGroups/sys_spec_Particles.cfg delete mode 100644 Assets/Engine/Config/CVarGroups/sys_spec_Physics.cfg delete mode 100644 Assets/Engine/Config/CVarGroups/sys_spec_PostProcessing.cfg delete mode 100644 Assets/Engine/Config/CVarGroups/sys_spec_Quality.cfg delete mode 100644 Assets/Engine/Config/CVarGroups/sys_spec_Shading.cfg delete mode 100644 Assets/Engine/Config/CVarGroups/sys_spec_Shadows.cfg delete mode 100644 Assets/Engine/Config/CVarGroups/sys_spec_Sound.cfg delete mode 100644 Assets/Engine/Config/CVarGroups/sys_spec_Texture.cfg delete mode 100644 Assets/Engine/Config/CVarGroups/sys_spec_TextureResolution.cfg delete mode 100644 Assets/Engine/Config/CVarGroups/sys_spec_VolumetricEffects.cfg delete mode 100644 Assets/Engine/Config/CVarGroups/sys_spec_Water.cfg delete mode 100644 Assets/Engine/Config/sketch_off.cfg delete mode 100644 Assets/Engine/Config/sketch_on.cfg delete mode 100644 Assets/Engine/Config/spec/osx_metal_high.cfg delete mode 100644 Assets/Engine/Config/spec/osx_metal_low.cfg delete mode 100644 Assets/Engine/Config/spec/osx_metal_medium.cfg delete mode 100644 Assets/Engine/Config/spec/osx_metal_veryhigh.cfg diff --git a/Assets/Editor/MapScreenshotSettings.xml b/Assets/Editor/MapScreenshotSettings.xml index 01f90db4b3..88a8a49aef 100644 --- a/Assets/Editor/MapScreenshotSettings.xml +++ b/Assets/Editor/MapScreenshotSettings.xml @@ -1,18 +1,5 @@ - - - - - - - - - - - - - diff --git a/Assets/Editor/UserTools.xml b/Assets/Editor/UserTools.xml index 8f971cbd5c..4cc197afbe 100644 --- a/Assets/Editor/UserTools.xml +++ b/Assets/Editor/UserTools.xml @@ -7,8 +7,6 @@ - - diff --git a/Assets/Engine/Config/AutoTestChain.cfg b/Assets/Engine/Config/AutoTestChain.cfg index 8c6fae9020..4164acb271 100644 --- a/Assets/Engine/Config/AutoTestChain.cfg +++ b/Assets/Engine/Config/AutoTestChain.cfg @@ -1,16 +1,5 @@ ConsoleHide -g_godMode=1 sys_warnings=0 con_showonload=1 -i_forcefeedback=0 -g_infiniteammo=1 -e_ObjectLayersActivation=0 -e_ObjectLayersActivationPhysics=0 -g_flashrenderingduringloading=0 sys_maxfps=0 r_vsync=0 -p_max_substeps=1 -demo_file=autotest -demo_num_runs=0 -demo_quit=1 -demo_ai=1 diff --git a/Assets/Engine/Config/AutoTestTimeDemo.cfg b/Assets/Engine/Config/AutoTestTimeDemo.cfg index 687158eda9..664ea94939 100644 --- a/Assets/Engine/Config/AutoTestTimeDemo.cfg +++ b/Assets/Engine/Config/AutoTestTimeDemo.cfg @@ -1,15 +1,5 @@ ConsoleHide -g_godMode=1 -g_infiniteammo=1 r_displayinfo=1 s_profiling=1 sys_maxfps=0 -e_ObjectLayersActivation=0 -e_ObjectLayersActivationPhysics=0 - -demo_file=autotest -demo_num_runs=2 -demo_quit=1 -demo_savestats=1 -demo_profile=-1 demo diff --git a/Assets/Engine/Config/AutotestPlaythrough.cfg b/Assets/Engine/Config/AutotestPlaythrough.cfg index f453097972..664ea94939 100644 --- a/Assets/Engine/Config/AutotestPlaythrough.cfg +++ b/Assets/Engine/Config/AutotestPlaythrough.cfg @@ -1,12 +1,5 @@ ConsoleHide -g_godMode=1 -g_infiniteammo=1 r_displayinfo=1 s_profiling=1 sys_maxfps=0 -demo_file=playthru -demo_num_runs=2 -demo_quit=1 -demo_savestats=1 -demo_profile=-1 -demo \ No newline at end of file +demo diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Full.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Full.cfg index 626dce3ee4..04fb56f3ca 100644 --- a/Assets/Engine/Config/CVarGroups/sys_spec_Full.cfg +++ b/Assets/Engine/Config/CVarGroups/sys_spec_Full.cfg @@ -11,113 +11,16 @@ ; default of this CVarGroup = 7 -sys_spec_ObjectDetail=7 -sys_spec_Shading=7 -sys_spec_VolumetricEffects=7 -sys_spec_Shadows=7 -sys_spec_Texture=7 -sys_spec_Physics=7 -sys_spec_PostProcessing=7 -sys_spec_Particles=7 -sys_spec_Sound=7 -sys_spec_Water=7 -sys_spec_GameEffects=7 -sys_spec_light=7 - [1] -sys_spec_ObjectDetail=1 -sys_spec_Shading=1 -sys_spec_VolumetricEffects=1 -sys_spec_Shadows=1 -sys_spec_Texture=1 -sys_spec_Physics=1 -sys_spec_PostProcessing=1 -sys_spec_Particles=1 -sys_spec_Sound=1 -sys_spec_Water=1 -sys_spec_GameEffects=1 -sys_spec_light=1 [2] -sys_spec_ObjectDetail=2 -sys_spec_Shading=2 -sys_spec_VolumetricEffects=2 -sys_spec_Shadows=2 -sys_spec_Texture=2 -sys_spec_Physics=2 -sys_spec_PostProcessing=2 -sys_spec_Particles=2 -sys_spec_Sound=2 -sys_spec_Water=2 -sys_spec_GameEffects=2 -sys_spec_light=2 [3] -sys_spec_ObjectDetail=3 -sys_spec_Shading=3 -sys_spec_VolumetricEffects=3 -sys_spec_Shadows=3 -sys_spec_Texture=3 -sys_spec_Physics=3 -sys_spec_PostProcessing=3 -sys_spec_Particles=3 -sys_spec_Sound=3 -sys_spec_Water=3 -sys_spec_GameEffects=3 -sys_spec_light=3 [4] -sys_spec_ObjectDetail=4 -sys_spec_Shading=4 -sys_spec_VolumetricEffects=4 -sys_spec_Shadows=4 -sys_spec_Texture=4 -sys_spec_Physics=4 -sys_spec_PostProcessing=4 -sys_spec_Particles=4 -sys_spec_Sound=4 -sys_spec_Water=4 -sys_spec_GameEffects=4 -sys_spec_light=4 [5] -sys_spec_ObjectDetail=5 -sys_spec_Shading=5 -sys_spec_VolumetricEffects=5 -sys_spec_Shadows=5 -sys_spec_Texture=5 -sys_spec_Physics=5 -sys_spec_PostProcessing=5 -sys_spec_Particles=5 -sys_spec_Sound=5 -sys_spec_Water=5 -sys_spec_GameEffects=5 -sys_spec_light=5 [6] -sys_spec_ObjectDetail=6 -sys_spec_Shading=6 -sys_spec_VolumetricEffects=6 -sys_spec_Shadows=6 -sys_spec_Texture=6 -sys_spec_Physics=6 -sys_spec_PostProcessing=6 -sys_spec_Particles=6 -sys_spec_Sound=6 -sys_spec_Water=6 -sys_spec_GameEffects=6 -sys_spec_light=6 [8] -sys_spec_ObjectDetail=8 -sys_spec_Shading=8 -sys_spec_VolumetricEffects=8 -sys_spec_Shadows=8 -sys_spec_Texture=8 -sys_spec_Physics=8 -sys_spec_PostProcessing=8 -sys_spec_Particles=8 -sys_spec_Sound=8 -sys_spec_Water=8 -sys_spec_GameEffects=8 -sys_spec_light=8 diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_GameEffects.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_GameEffects.cfg deleted file mode 100644 index 34e058d47d..0000000000 --- a/Assets/Engine/Config/CVarGroups/sys_spec_GameEffects.cfg +++ /dev/null @@ -1,8 +0,0 @@ -[default] -; default of this CVarGroup -= 7 - -mfx_Timeout = 0.01 - - - diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_ObjectDetail.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_ObjectDetail.cfg deleted file mode 100644 index a2996f7ded..0000000000 --- a/Assets/Engine/Config/CVarGroups/sys_spec_ObjectDetail.cfg +++ /dev/null @@ -1,160 +0,0 @@ -[default] -; default of this CVarGroup -= 7 - -ca_AttachmentCullingRation=360 -es_DebrisLifetimeScale=1 -e_CoverageBufferReproj=6 -e_DecalsAllowGameDecals=1 -e_DecalsLifeTimeScale=2 -e_DecalsOverlapping=1 -e_Dissolve=2 -e_LightQuality=3 -e_LodMin=0 -e_LodRatio=20 -e_MaxViewDistSpecLerp=1 -e_MergedMeshesInstanceDist=1.0 -e_MergedMeshesPool=8192 -e_ObjQuality=3 -e_OcclusionCullingViewDistRatio=1 -e_ProcVegetation=1 -e_StatObjBufferRenderTasks=1 -e_StreamCgf=0 -e_TerrainLodRatio=1 -e_TerrainOcclusionCullingMaxDist=200 -e_Tessellation=0 -e_VegetationMinSize=0 -e_ViewDistMin=10 -e_ViewDistRatio=100 -e_ViewDistRatioCustom=100 -e_ViewDistRatioDetail=100 -e_ViewDistRatioLights=50 -e_ViewDistRatioVegetation=100 -r_DrawNearZRange=0.12 -r_FlaresTessellationRatio=1 -r_SilhouettePOM=0 -r_usezpass=2 - -[1] -ca_AttachmentCullingRation=145 -es_DebrisLifetimeScale=0.6 -e_DecalsLifeTimeScale=1 -e_Dissolve=0 -e_LightQuality=1 -e_LodRatio=10 -e_MaxViewDistSpecLerp=0.5 -e_ObjQuality=1 -e_TerrainOcclusionCullingMaxDist=130 -e_VegetationMinSize=0.5 -e_ViewDistRatioCustom=60 -e_ViewDistRatioDetail=25 -e_ViewDistRatioLights=25 -e_ViewDistRatioVegetation=21 -r_FlaresTessellationRatio=0.25 -r_usezpass=1 -e_ProcVegetation=0 -e_ViewDistRatio=50 - -[2] -ca_AttachmentCullingRation=145 -es_DebrisLifetimeScale=0.6 -e_DecalsLifeTimeScale=1 -e_Dissolve=0 -e_LightQuality=2 -e_LodRatio=10 -e_MaxViewDistSpecLerp=0.5 -e_ObjQuality=2 -e_TerrainOcclusionCullingMaxDist=130 -e_VegetationMinSize=0.5 -e_ViewDistRatioCustom=60 -e_ViewDistRatioDetail=25 -e_ViewDistRatioLights=25 -e_ViewDistRatioVegetation=50 -r_FlaresTessellationRatio=0.25 -r_usezpass=1 -e_ProcVegetation=1 -e_ViewDistRatio=50 - -[3] -ca_AttachmentCullingRation=145 -es_DebrisLifetimeScale=0.6 -e_DecalsLifeTimeScale=1 -e_Dissolve=0 -e_LightQuality=3 -e_LodRatio=10 -e_MaxViewDistSpecLerp=0.5 -e_ObjQuality=3 -e_TerrainOcclusionCullingMaxDist=130 -e_VegetationMinSize=0.5 -e_ViewDistRatioCustom=60 -e_ViewDistRatioDetail=25 -e_ViewDistRatioLights=25 -e_ViewDistRatioVegetation=50 -r_FlaresTessellationRatio=0.25 -r_usezpass=1 -e_ProcVegetation=1 -e_ViewDistRatio=75 - -[4] -ca_AttachmentCullingRation=145 -es_DebrisLifetimeScale=0.6 -e_DecalsLifeTimeScale=1 -e_Dissolve=0 -e_LightQuality=4 -e_LodRatio=10 -e_MaxViewDistSpecLerp=0.5 -e_ObjQuality=4 -e_TerrainOcclusionCullingMaxDist=130 -e_VegetationMinSize=0.5 -e_ViewDistRatioCustom=60 -e_ViewDistRatioDetail=25 -e_ViewDistRatioLights=25 -e_ViewDistRatioVegetation=50 -r_FlaresTessellationRatio=0.25 -r_usezpass=1 -e_ProcVegetation=1 -e_ViewDistRatio=75 - -[5] -ca_AttachmentCullingRation=145 -es_DebrisLifetimeScale=0.6 -e_DecalsLifeTimeScale=1 -e_LightQuality=1 -e_LodRatio=10 -e_MaxViewDistSpecLerp=0.5 -e_ObjQuality=1 -e_TerrainOcclusionCullingMaxDist=130 -e_VegetationMinSize=0.5 -e_ViewDistRatio=50 -e_ViewDistRatioCustom=60 -e_ViewDistRatioDetail=25 -e_ViewDistRatioLights=25 -e_ViewDistRatioVegetation=50 -r_FlaresTessellationRatio=0.25 - -[6] -ca_AttachmentCullingRation=300 -es_DebrisLifetimeScale=0.8 -e_LightQuality=2 -e_LodRatio=15 -e_ObjQuality=2 -e_ViewDistRatio=75 -e_ViewDistRatioDetail=35 -e_ViewDistRatioVegetation=75 - -[8] -ca_AttachmentCullingRation=400 -e_LightQuality=4 -e_LodRatio=40 -e_MergedMeshesInstanceDist=2.0 -e_MergedMeshesPool=16384 -e_ObjQuality=4 -e_TerrainLodRatio=0.5 -e_Tessellation=1 -e_ViewDistRatio=125 -e_ViewDistRatioCustom=125 -e_ViewDistRatioDetail=125 -e_ViewDistRatioLights=75 -e_ViewDistRatioVegetation=125 -r_DrawNearZRange = 0.08 -r_SilhouettePOM=1 \ No newline at end of file diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Particles.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Particles.cfg deleted file mode 100644 index 0a02170b97..0000000000 --- a/Assets/Engine/Config/CVarGroups/sys_spec_Particles.cfg +++ /dev/null @@ -1,94 +0,0 @@ -[default] -; default of this CVarGroup -= 7 - -e_ParticlesGI=1 -e_ParticlesPreload=0 -e_ParticlesMaxScreenFill=128 -e_ParticlesMinDrawPixels=1 -e_ParticlesMotionBlur=0 -e_ParticlesObjectCollisions=2 -e_ParticlesQuality=3 -e_ParticlesSortQuality=0 -e_ParticlesPoolSize=16384 -r_ParticlesHalfRes=0 -r_ParticlesTessellation=1 -r_ParticlesInstanceVertices=1 -r_ParticlesGpuMaxEmitCount=10000 - -[1] -e_ParticlesGI=0 -e_ParticlesPreload=1 -e_ParticlesMaxScreenFill=16 -e_ParticlesMinDrawPixels=2 -e_ParticlesObjectCollisions=1 -e_ParticlesQuality=2 -e_ParticlesPoolSize=4096 -r_ParticlesHalfRes=1 -r_ParticlesTessellation=0 -r_ParticlesInstanceVertices=0 -r_ParticlesGpuMaxEmitCount=10 - - -[2] -e_ParticlesGI=0 -e_ParticlesPreload=1 -e_ParticlesMaxScreenFill=16 -e_ParticlesMinDrawPixels=2 -e_ParticlesObjectCollisions=1 -e_ParticlesQuality=2 -e_ParticlesPoolSize=4096 -r_ParticlesHalfRes=1 -r_ParticlesTessellation=0 -r_ParticlesInstanceVertices=0 -r_ParticlesGpuMaxEmitCount=100 - - -[3] -e_ParticlesGI=0 -e_ParticlesPreload=1 -e_ParticlesMaxScreenFill=16 -e_ParticlesMinDrawPixels=2 -e_ParticlesObjectCollisions=1 -e_ParticlesQuality=2 -e_ParticlesPoolSize=4096 -r_ParticlesHalfRes=1 -r_ParticlesTessellation=0 -r_ParticlesInstanceVertices=0 -r_ParticlesGpuMaxEmitCount=500 - - -[4] -e_ParticlesGI=0 -e_ParticlesPreload=1 -e_ParticlesMaxScreenFill=16 -e_ParticlesMinDrawPixels=2 -e_ParticlesObjectCollisions=1 -e_ParticlesQuality=2 -e_ParticlesPoolSize=4096 -r_ParticlesHalfRes=1 -r_ParticlesTessellation=0 -r_ParticlesInstanceVertices=0 -r_ParticlesGpuMaxEmitCount=1000 - - -[5] -e_ParticlesMaxScreenFill=32 -e_ParticlesMinDrawPixels=1.5 -e_ParticlesObjectCollisions=1 -e_ParticlesQuality=1 -r_ParticlesHalfRes=1 -r_ParticlesTessellation=0 -r_ParticlesGpuMaxEmitCount=3000 - -[6] -e_ParticlesMaxScreenFill=64 -e_ParticlesObjectCollisions=1 -e_ParticlesQuality=2 -r_ParticlesGpuMaxEmitCount=5000 - -[8] -e_ParticlesMaxScreenFill=160 -e_ParticlesMotionBlur=1 -e_ParticlesQuality=4 -r_ParticlesGpuMaxEmitCount=1048576 \ No newline at end of file diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Physics.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Physics.cfg deleted file mode 100644 index 15d9fc61e3..0000000000 --- a/Assets/Engine/Config/CVarGroups/sys_spec_Physics.cfg +++ /dev/null @@ -1,100 +0,0 @@ -[default] -; default of this CVarGroup -= 7 - -es_MaxPhysDist=100 -es_MaxPhysDistInvisible=25 -e_CullVegActivation=50 -e_FoliageWindActivationDist=25 -e_PhysMinCellSize=4 -e_PhysOceanCell=0.5 -e_PhysProxyTriLimit=10000 -g_breakage_mem_limit=0 -g_breakage_particles_limit=160 -g_no_secondary_breaking=0 -g_tree_cut_reuse_dist=0 -p_gravity_z=-13 -p_max_entity_cells=300000 -p_max_MC_iters=6000 -p_max_object_splashes=3 -p_max_substeps=5 -p_max_substeps_large_group=5 -p_num_bodies_large_group=100 -p_splash_dist0=7 -p_splash_dist1=30 -p_splash_force0=10 -p_splash_force1=100 -p_splash_vel0=4.5 -p_splash_vel1=10 -v_vehicle_quality=4 - -[1] -es_MaxPhysDistInvisible=15 -e_CullVegActivation=30 -e_FoliageWindActivationDist=10 -e_PhysMinCellSize=16 -e_PhysOceanCell=1 -g_breakage_mem_limit=2000 -g_breakage_particles_limit=40 -g_no_secondary_breaking=1 -g_tree_cut_reuse_dist=1 -p_max_entity_cells=75000 -p_max_MC_iters=2000 -p_max_substeps=2 - -[2] -es_MaxPhysDistInvisible=15 -e_CullVegActivation=30 -e_FoliageWindActivationDist=10 -e_PhysMinCellSize=16 -e_PhysOceanCell=1 -g_breakage_mem_limit=2000 -g_breakage_particles_limit=40 -g_no_secondary_breaking=1 -g_tree_cut_reuse_dist=1 -p_max_entity_cells=75000 -p_max_MC_iters=2000 -p_max_substeps=2 - -[3] -es_MaxPhysDistInvisible=15 -e_CullVegActivation=30 -e_FoliageWindActivationDist=10 -e_PhysMinCellSize=16 -e_PhysOceanCell=1 -g_breakage_mem_limit=2000 -g_breakage_particles_limit=40 -g_no_secondary_breaking=1 -g_tree_cut_reuse_dist=1 -p_max_entity_cells=75000 -p_max_MC_iters=2000 -p_max_substeps=2 - -[4] -es_MaxPhysDistInvisible=15 -e_CullVegActivation=30 -e_FoliageWindActivationDist=10 -e_PhysMinCellSize=16 -e_PhysOceanCell=1 -g_breakage_mem_limit=2000 -g_breakage_particles_limit=40 -g_no_secondary_breaking=1 -g_tree_cut_reuse_dist=1 -p_max_entity_cells=75000 -p_max_MC_iters=2000 -p_max_substeps=2 - -[5] -es_MaxPhysDist=50 -es_MaxPhysDistInvisible=15 -e_CullVegActivation=30 -e_FoliageWindActivationDist=10 -e_PhysOceanCell=1 -g_breakage_particles_limit=80 -g_tree_cut_reuse_dist=0.35 -p_max_MC_iters=4000 -p_max_substeps=2 - -[6] - -[8] diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_PostProcessing.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_PostProcessing.cfg deleted file mode 100644 index 9d2cd3754d..0000000000 --- a/Assets/Engine/Config/CVarGroups/sys_spec_PostProcessing.cfg +++ /dev/null @@ -1,114 +0,0 @@ -[default] -; default of this CVarGroup -= 7 - -r_PostProcessEffects=1 -q_ShaderHDR=2 -q_ShaderPostProcess=2 -r_ChromaticAberration=0 -r_ColorGradingChartsCache=0 -r_DepthOfField=2 -r_Flares=1 -r_HDRBloomQuality=2 -r_MotionBlur=2 -r_MotionBlurMaxViewDist=100000 -r_MotionBlurQuality=1 -r_MotionBlurShutterSpeed=125 -r_Rain=2 -r_RainMaxViewDist_Deferred=150 -r_Sharpening=0 -r_Snow=2 -r_SunShafts=2 -r_TranspDepthFixup=1 -r_ToneMapTechnique=0 -r_ToneMapExposureType=0 -r_HDRBloom=1 -r_ColorGrading=1 -r_ColorSpace=0 - -[1] -q_ShaderHDR=1 -q_ShaderPostProcess=1 -r_ColorGrading=0 -r_DepthOfField=0 -r_Flares=0 -r_HDRBloom=0 -r_HDRBloomQuality=0 -r_MotionBlur=0 -r_MotionBlurMaxViewDist=16 -r_MotionBlurQuality=0 -r_Rain=1 -r_RainMaxViewDist_Deferred=40 -r_Snow=1 -r_SunShafts=0 -r_TranspDepthFixup=0 -r_ToneMapTechnique=3 -r_ToneMapExposureType=1 -r_ColorSpace=2 - - -[2] -q_ShaderHDR=1 -q_ShaderPostProcess=1 -r_ColorGradingChartsCache=4 -r_DepthOfField=1 -r_Flares=0 -r_HDRBloomQuality=0 -r_MotionBlur=0 -r_MotionBlurMaxViewDist=16 -r_MotionBlurQuality=0 -r_Rain=1 -r_RainMaxViewDist_Deferred=40 -r_Snow=1 -r_SunShafts=1 -r_TranspDepthFixup=0 - - -[3] -q_ShaderHDR=1 -q_ShaderPostProcess=2 -r_ColorGradingChartsCache=4 -r_DepthOfField=1 -r_HDRBloomQuality=1 -r_MotionBlur=0 -r_MotionBlurMaxViewDist=16 -r_MotionBlurQuality=0 -r_Rain=1 -r_RainMaxViewDist_Deferred=40 -r_Snow=1 -r_SunShafts=1 -r_TranspDepthFixup=0 - -[4] -q_ShaderHDR=1 -q_ShaderPostProcess=2 -r_ColorGradingChartsCache=4 -r_DepthOfField=1 -r_HDRBloomQuality=1 -r_MotionBlur=0 -r_MotionBlurMaxViewDist=16 -r_MotionBlurQuality=0 -r_Rain=1 -r_RainMaxViewDist_Deferred=40 -r_Snow=1 -r_SunShafts=1 -r_TranspDepthFixup=0 - -[5] -q_ShaderHDR=1 -q_ShaderPostProcess=1 -r_ColorGradingChartsCache=4 -r_MotionBlurMaxViewDist=16 -r_MotionBlurQuality=0 -r_RainMaxViewDist_Deferred=40 -r_TranspDepthFixup=0 - -[6] -q_ShaderHDR=1 -q_ShaderPostProcess=1 -r_RainMaxViewDist_Deferred=100 - -[8] -q_ShaderHDR=3 -q_ShaderPostProcess=3 -r_MotionBlurQuality=2 diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Quality.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Quality.cfg deleted file mode 100644 index cf1bdf5184..0000000000 --- a/Assets/Engine/Config/CVarGroups/sys_spec_Quality.cfg +++ /dev/null @@ -1,98 +0,0 @@ -[default] -; default of this CVarGroup -= 7 - -q_ShaderGeneral=2 -q_ShaderMetal=2 -q_ShaderGlass=2 -q_ShaderVegetation=2 -q_ShaderIce=2 -q_ShaderTerrain=2 -q_ShaderShadow=2 -q_ShaderFX=2 -q_ShaderSky=2 -q_Renderer=2 - -[1] -q_ShaderGeneral=1 -q_ShaderMetal=1 -q_ShaderGlass=1 -q_ShaderVegetation=1 -q_ShaderIce=1 -q_ShaderTerrain=1 -q_ShaderShadow=1 -q_ShaderFX=1 -q_ShaderSky=1 -q_Renderer=1 - -[2] -q_ShaderGeneral=1 -q_ShaderMetal=1 -q_ShaderGlass=1 -q_ShaderVegetation=1 -q_ShaderIce=1 -q_ShaderTerrain=1 -q_ShaderShadow=1 -q_ShaderFX=1 -q_ShaderSky=1 -q_Renderer=1 - -[3] -q_ShaderGeneral=1 -q_ShaderMetal=1 -q_ShaderGlass=1 -q_ShaderVegetation=1 -q_ShaderIce=1 -q_ShaderTerrain=1 -q_ShaderShadow=1 -q_ShaderFX=1 -q_ShaderSky=1 -q_Renderer=2 - -[4] -q_ShaderGeneral=1 -q_ShaderMetal=1 -q_ShaderGlass=1 -q_ShaderVegetation=1 -q_ShaderIce=1 -q_ShaderTerrain=1 -q_ShaderShadow=1 -q_ShaderFX=1 -q_ShaderSky=1 -q_Renderer=2 - -[5] -q_ShaderGeneral=1 -q_ShaderMetal=1 -q_ShaderGlass=1 -q_ShaderVegetation=1 -q_ShaderIce=1 -q_ShaderTerrain=1 -q_ShaderShadow=1 -q_ShaderFX=1 -q_ShaderSky=1 -q_Renderer=1 - -[6] -q_ShaderGeneral=1 -q_ShaderMetal=1 -q_ShaderGlass=1 -q_ShaderVegetation=1 -q_ShaderIce=1 -q_ShaderTerrain=1 -q_ShaderShadow=1 -q_ShaderFX=1 -q_ShaderSky=1 -q_Renderer=1 - -[8] -q_ShaderGeneral=3 -q_ShaderMetal=3 -q_ShaderGlass=3 -q_ShaderVegetation=3 -q_ShaderIce=3 -q_ShaderTerrain=3 -q_ShaderShadow=3 -q_ShaderFX=3 -q_ShaderSky=3 -q_Renderer=3 diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Shading.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Shading.cfg deleted file mode 100644 index eb379a8583..0000000000 --- a/Assets/Engine/Config/CVarGroups/sys_spec_Shading.cfg +++ /dev/null @@ -1,120 +0,0 @@ -[default] -; default of this CVarGroup -= 7 - -e_CacheNearestCubePicking=1 -e_DynamicLightsMaxEntityLights=16 -e_GI=1 -e_LightVolumes=1 -e_SkyUpdateRate=1 -e_TerrainAo=0 -e_VegetationUseTerrainColor=1 -r_DeferredShadingDepthBoundsTest=1 -r_DeferredShadingTiled=2 -r_DeferredShadingTiledHairQuality=1 -r_deferredShadingFilterGBuffer=0 -r_DeferredShadingSSS=1 -r_AntialiasingMode=3 -r_DetailDistance=8 -r_EnvTexUpdateInterval=0.05 -r_Refraction=1 -r_RefractionPartialResolves=2 -r_ssdo=1 -r_ssdoHalfRes=2 -r_ssdoColorBleeding=1 -r_SSReflections=1 -r_SSReflHalfRes=1 -r_VisAreaClipLightsPerPixel=1 -sys_spec_Quality=7 - -[1] -e_DynamicLightsMaxEntityLights=2 -e_GI=0 -e_SkyUpdateRate=0.5 -e_VegetationUseTerrainColor=0 -r_DeferredShadingTiled=0 -r_DeferredShadingTiledHairQuality=0 -r_DeferredShadingSSS=0 -r_AntialiasingMode=0 -r_DetailDistance=4 -r_EnvTexUpdateInterval=0.075 -r_Refraction=0 -r_RefractionPartialResolves=0 -r_ssdo=0 -r_ssdoHalfRes=1 -r_ssdoColorBleeding=0 -r_SSReflections=0 -sys_spec_Quality=1 - -[2] -e_DynamicLightsMaxEntityLights=2 -e_GI=0 -e_SkyUpdateRate=0.5 -e_VegetationUseTerrainColor=0 -r_DeferredShadingTiled=0 -r_DeferredShadingTiledHairQuality=0 -r_DeferredShadingSSS=0 -r_AntialiasingMode=0 -r_DetailDistance=4 -r_EnvTexUpdateInterval=0.075 -r_RefractionPartialResolves=0 -r_ssdo=0 -r_ssdoHalfRes=1 -r_ssdoColorBleeding=0 -r_SSReflections=0 -sys_spec_Quality=2 - -[3] -e_DynamicLightsMaxEntityLights=2 -e_GI=0 -e_SkyUpdateRate=0.5 -e_VegetationUseTerrainColor=0 -r_DeferredShadingTiled=0 -r_DeferredShadingTiledHairQuality=0 -r_DeferredShadingSSS=0 -r_AntialiasingMode=0 -r_DetailDistance=4 -r_EnvTexUpdateInterval=0.075 -r_RefractionPartialResolves=0 -r_ssdo=0 -r_ssdoColorBleeding=0 -r_SSReflections=0 -sys_spec_Quality=3 - -[4] -e_DynamicLightsMaxEntityLights=2 -e_GI=0 -e_SkyUpdateRate=0.5 -e_VegetationUseTerrainColor=0 -r_DeferredShadingTiled=0 -r_DeferredShadingTiledHairQuality=0 -r_DeferredShadingSSS=0 -r_AntialiasingMode=0 -r_DetailDistance=4 -r_EnvTexUpdateInterval=0.075 -r_RefractionPartialResolves=0 -r_ssdo=1 -r_ssdoHalfRes=1 -r_ssdoColorBleeding=0 -r_SSReflections=0 -sys_spec_Quality=4 - -[5] -e_DynamicLightsMaxEntityLights=7 -e_GI=0 -e_SkyUpdateRate=0.5 -r_DetailDistance=4 -r_EnvTexUpdateInterval=0.075 -r_SSReflections=0 -r_DeferredShadingTiledHairQuality=0 -r_DeferredShadingSSS=0 -sys_spec_Quality=5 - -[6] -e_DynamicLightsMaxEntityLights=11 -sys_spec_Quality=6 - -[8] -r_DeferredShadingTiledHairQuality=2 -r_SSReflHalfRes=0 -sys_spec_Quality=8 diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Shadows.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Shadows.cfg deleted file mode 100644 index d43c28c09d..0000000000 --- a/Assets/Engine/Config/CVarGroups/sys_spec_Shadows.cfg +++ /dev/null @@ -1,116 +0,0 @@ -[default] -; default of this CVarGroup -= 7 - -e_GsmLodsNum=5 -e_GsmRange=3 -e_ParticlesShadows=1 -e_Shadows=1 -e_ShadowsBlendCascades=1 -e_ShadowsClouds=1 -e_ShadowsCastViewDistRatio=1 -e_ShadowsLodBiasFixed=0 -e_ShadowsMaxTexRes=1024 -e_ShadowsOnAlphaBlend=0 -e_ShadowsPoolSize=4096 -e_ShadowsResScale=4 -e_ShadowsTessellateCascades=1 -e_ShadowsTessellateDLights=0 -e_ShadowsUpdateViewDistRatio=256 -r_DrawNearShadows=1 -r_FogShadows=2 -r_FogShadowsWater=0 -r_ShadowJittering=2.5 -r_ShadowPoolMaxFrames=30 -r_ShadowPoolMaxTimeslicedUpdatesPerFrame=100 -r_ShadowsPCFiltering=1 -r_ShadowsCache=4 -r_ShadowsCacheFormat=1 -r_ShadowsCacheResolutions=6324,4214 -r_ShadowsUseClipVolume=1 -e_ObjShadowCastSpec=3 - -[1] -e_GsmLodsNum=3 -e_ParticlesShadows=0 -e_ShadowsBlendCascades=0 -e_ShadowsCastViewDistRatio=0.8 -e_ShadowsLodBiasFixed=1 -e_ShadowsMaxTexRes=512 -r_DrawNearShadows=0 -r_FogShadows=0 -r_ShadowJittering=0 -r_ShadowsCacheFormat=0 -r_ShadowsCacheResolutions=3162,2107 -e_ObjShadowCastSpec=1 -e_ShadowsPoolSize=1024 - -[2] -e_GsmLodsNum=4 -e_ParticlesShadows=0 -e_ShadowsBlendCascades=0 -e_ShadowsCastViewDistRatio=0.8 -e_ShadowsLodBiasFixed=1 -e_ShadowsMaxTexRes=512 -r_DrawNearShadows=0 -r_FogShadows=0 -r_ShadowJittering=0 -r_ShadowsCacheFormat=0 -r_ShadowsCacheResolutions=3162,2107 -e_ObjShadowCastSpec=1 -e_ShadowsPoolSize=1024 - -[3] -e_GsmLodsNum=4 -e_ParticlesShadows=0 -e_ShadowsBlendCascades=0 -e_ShadowsCastViewDistRatio=0.8 -e_ShadowsLodBiasFixed=1 -e_ShadowsMaxTexRes=512 -r_DrawNearShadows=0 -r_FogShadows=0 -r_ShadowJittering=0 -r_ShadowsCacheFormat=0 -r_ShadowsCacheResolutions=3162,2107 -e_ObjShadowCastSpec=1 -e_ShadowsPoolSize=1024 - -[4] -e_GsmLodsNum=4 -e_ParticlesShadows=0 -e_ShadowsBlendCascades=0 -e_ShadowsCastViewDistRatio=0.8 -e_ShadowsLodBiasFixed=1 -e_ShadowsMaxTexRes=512 -r_DrawNearShadows=0 -r_FogShadows=0 -r_ShadowJittering=0 -r_ShadowsCacheFormat=0 -r_ShadowsCacheResolutions=3162,2107 -e_ObjShadowCastSpec=1 -e_ShadowsPoolSize=1024 - -[5] -e_GsmLodsNum=4 -e_ParticlesShadows=0 -e_ShadowsBlendCascades=0 -e_ShadowsCastViewDistRatio=0.8 -e_ShadowsLodBiasFixed=1 -e_ShadowsMaxTexRes=512 -r_FogShadows=0 -r_ShadowJittering=1 -e_ObjShadowCastSpec=1 -r_ShadowsCacheResolutions=3162,2107 - -[6] -r_ShadowJittering=1 -e_ObjShadowCastSpec=2 - -[8] -r_FogShadows=1 -r_FogShadowsWater=1 -r_ShadowPoolMaxFrames=0 -r_ShadowPoolMaxTimeslicedUpdatesPerFrame=100 -e_ObjShadowCastSpec=4 -r_ShadowsCache=5 -r_ShadowsCacheResolutions=4214 diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Sound.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Sound.cfg deleted file mode 100644 index 42bd4c7f02..0000000000 --- a/Assets/Engine/Config/CVarGroups/sys_spec_Sound.cfg +++ /dev/null @@ -1,17 +0,0 @@ -[default] -; default of this CVarGroup -= 7 - -[1] - -[2] - -[3] - -[4] - -[5] - -[6] - -[8] diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Texture.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Texture.cfg deleted file mode 100644 index 0e02c41ab2..0000000000 --- a/Assets/Engine/Config/CVarGroups/sys_spec_Texture.cfg +++ /dev/null @@ -1,94 +0,0 @@ -[default] -; default of this CVarGroup -= 7 - -e_TerrainTextureStreamingPoolItemsNum=64 -r_DynTexAtlasCloudsMaxSize=32 -r_DynTexAtlasSpritesMaxSize=32 -r_DynTexMaxSize=80 -r_EnvCMResolution=2 -r_EnvTexResolution=3 -r_ImposterRatio=1 -r_TexAtlasSize=2048 -r_TexMaxAnisotropy=4 -r_TexMinAnisotropy=4 -r_TexNoAnisoAlphaTest=0 - -[1] -e_TerrainTextureStreamingPoolItemsNum=16 -r_DynTexAtlasCloudsMaxSize=8 -r_DynTexAtlasSpritesMaxSize=8 -r_DynTexMaxSize=20 -r_EnvCMResolution=0 -r_EnvTexResolution=1 -r_ImposterRatio=2 -r_TexAtlasSize=512 -r_TexMaxAnisotropy=2 -r_TexMinAnisotropy=2 -r_TexNoAnisoAlphaTest=1 - -[2] -e_TerrainTextureStreamingPoolItemsNum=16 -r_DynTexAtlasCloudsMaxSize=8 -r_DynTexAtlasSpritesMaxSize=8 -r_DynTexMaxSize=20 -r_EnvCMResolution=0 -r_EnvTexResolution=1 -r_ImposterRatio=2 -r_TexAtlasSize=512 -r_TexMaxAnisotropy=2 -r_TexMinAnisotropy=2 -r_TexNoAnisoAlphaTest=1 - -[3] -e_TerrainTextureStreamingPoolItemsNum=16 -r_DynTexAtlasCloudsMaxSize=8 -r_DynTexAtlasSpritesMaxSize=8 -r_DynTexMaxSize=20 -r_EnvCMResolution=0 -r_EnvTexResolution=1 -r_ImposterRatio=2 -r_TexAtlasSize=512 -r_TexMaxAnisotropy=2 -r_TexMinAnisotropy=2 -r_TexNoAnisoAlphaTest=1 - -[4] -e_TerrainTextureStreamingPoolItemsNum=16 -r_DynTexAtlasCloudsMaxSize=8 -r_DynTexAtlasSpritesMaxSize=8 -r_DynTexMaxSize=20 -r_EnvCMResolution=0 -r_EnvTexResolution=1 -r_ImposterRatio=2 -r_TexAtlasSize=512 -r_TexMaxAnisotropy=2 -r_TexMinAnisotropy=2 -r_TexNoAnisoAlphaTest=1 - -[5] -r_DynTexAtlasCloudsMaxSize=24 -r_DynTexAtlasSpritesMaxSize=16 -r_DynTexMaxSize=50 -r_EnvCMResolution=0 -r_EnvTexResolution=1 -r_ImposterRatio=2 -r_TexAtlasSize=512 -r_TexMaxAnisotropy=2 -r_TexMinAnisotropy=2 -r_TexNoAnisoAlphaTest=1 - -[6] -r_DynTexAtlasCloudsMaxSize=24 -r_DynTexAtlasSpritesMaxSize=16 -r_DynTexMaxSize=60 -r_EnvCMResolution=1 -r_EnvTexResolution=2 -r_ImposterRatio=1.5 -r_TexMaxAnisotropy=8 -r_TexMinAnisotropy=8 -r_TexNoAnisoAlphaTest=1 - -[8] -r_TexMaxAnisotropy=16 -r_TexMinAnisotropy=16 diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_TextureResolution.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_TextureResolution.cfg deleted file mode 100644 index 6b6c11ddf6..0000000000 --- a/Assets/Engine/Config/CVarGroups/sys_spec_TextureResolution.cfg +++ /dev/null @@ -1,52 +0,0 @@ -[default] -; dummy default for this CVarGroup (will be auto initialized during streaming system init or overridden by user via system.cfg) -= 0 - -; VRAM 1.0 GB -r_TexturesStreaming=1 -r_TexturesStreamingMipBias=0 -r_TexturesstreamingMinUsableMips=8 -r_TexturesStreamingSkipMips=2 -r_TexturesStreamPoolSize=256 - -[1] -; VRAM 1.0 GB -r_TexturesStreaming=0 -r_TexturesStreamingSkipMips=0 -r_TexturesStreamPoolSize=384 - -[2] -; VRAM 1.0 GB -r_TexturesStreaming=0 -r_TexturesStreamingSkipMips=0 -r_TexturesStreamPoolSize=384 - -[3] -; VRAM 1.0 GB -r_TexturesStreaming=0 -r_TexturesStreamingSkipMips=0 -r_TexturesStreamPoolSize=384 - -[4] -; VRAM 1.0 GB -r_TexturesStreaming=0 -r_TexturesStreamingSkipMips=0 -r_TexturesStreamPoolSize=384 - -[5] -; VRAM 1.0 GB - -[6] -; VRAM 1.5 GB -r_TexturesStreamingSkipMips=1 -r_TexturesStreamPoolSize=512 - -[7] -; VRAM 2.0 GB -r_TexturesStreamingSkipMips=0 -r_TexturesStreamPoolSize=640 - -[8] -; VRAM 3.0 GB -r_TexturesStreamingSkipMips=0 -r_TexturesStreamPoolSize=1536 \ No newline at end of file diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_VolumetricEffects.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_VolumetricEffects.cfg deleted file mode 100644 index b6fdfec33c..0000000000 --- a/Assets/Engine/Config/CVarGroups/sys_spec_VolumetricEffects.cfg +++ /dev/null @@ -1,26 +0,0 @@ -[default] -; default of this CVarGroup -= 7 - -e_Clouds=1 -r_Beams=1 - -[1] -r_Beams=0 - -[2] -r_Beams=0 - -[3] -r_Beams=0 - -[4] -r_Beams=0 - -[5] -r_Beams=0 - -[6] -r_Beams=0 - -[8] diff --git a/Assets/Engine/Config/CVarGroups/sys_spec_Water.cfg b/Assets/Engine/Config/CVarGroups/sys_spec_Water.cfg deleted file mode 100644 index 720339dc98..0000000000 --- a/Assets/Engine/Config/CVarGroups/sys_spec_Water.cfg +++ /dev/null @@ -1,81 +0,0 @@ -[default] -; default of this CVarGroup -= 7 - -e_WaterOceanFFT=1 -e_WaterTessellationAmount=10 -e_WaterTessellationSwathWidth=10 -q_ShaderWater=2 -r_WaterCaustics=1 -r_WaterReflections=1 -r_WaterReflectionsQuality=4 -r_WaterReflectionsMinVisiblePixelsUpdate=0.05 -r_WaterTessellationHW=0 -r_WaterUpdateDistance=0.2 -r_WaterUpdateFactor=0.0 -r_WaterVolumeCaustics=0 -r_WaterVolumeCausticsDensity=256 -r_WaterVolumeCausticsMaxDist=35 -r_WaterVolumeCausticsRes=1024 -r_WaterVolumeCausticsSnapFactor=1 - -[1] -e_WaterTessellationAmount=20 -q_ShaderWater=1 -r_WaterReflectionsQuality=0 -r_WaterUpdateDistance=1 -r_WaterUpdateFactor=0.1 -r_WaterVolumeCausticsDensity=64 -r_WaterVolumeCausticsMaxDist=20 -r_WaterVolumeCausticsRes=384 - -[2] -e_WaterTessellationAmount=20 -q_ShaderWater=1 -r_WaterReflectionsQuality=0 -r_WaterUpdateDistance=1 -r_WaterUpdateFactor=0.1 -r_WaterVolumeCausticsDensity=64 -r_WaterVolumeCausticsMaxDist=20 -r_WaterVolumeCausticsRes=384 - -[3] -e_WaterTessellationAmount=20 -q_ShaderWater=1 -r_WaterReflectionsQuality=0 -r_WaterUpdateDistance=1 -r_WaterUpdateFactor=0.05 -r_WaterVolumeCausticsDensity=64 -r_WaterVolumeCausticsMaxDist=20 -r_WaterVolumeCausticsRes=384 - -[4] -e_WaterTessellationAmount=20 -q_ShaderWater=1 -r_WaterReflectionsQuality=4 -r_WaterUpdateDistance=1 -r_WaterUpdateFactor=0.01 -r_WaterVolumeCausticsDensity=64 -r_WaterVolumeCausticsMaxDist=20 -r_WaterVolumeCausticsRes=384 - -[5] -e_WaterTessellationAmount=20 -q_ShaderWater=1 -r_WaterUpdateDistance=1 -r_WaterUpdateFactor=0.1 -r_WaterVolumeCausticsDensity=64 -r_WaterVolumeCausticsMaxDist=20 -r_WaterVolumeCausticsRes=384 - -[6] -r_WaterUpdateDistance=1 -r_WaterUpdateFactor=0.05 -r_WaterVolumeCausticsDensity=128 -r_WaterVolumeCausticsMaxDist=25 -r_WaterVolumeCausticsRes=512 - -[8] -e_WaterTessellationAmount=85 -r_WaterTessellationHW=1 -r_WaterVolumeCaustics=1 diff --git a/Assets/Engine/Config/aidebug.cfg b/Assets/Engine/Config/aidebug.cfg index f8134c7461..b0eafaaa45 100644 --- a/Assets/Engine/Config/aidebug.cfg +++ b/Assets/Engine/Config/aidebug.cfg @@ -1,4 +1 @@ ai_DebugDraw = 1 -ai_DebugDrawNavigation = 1 -ai_DrawPath all -ai_debugMNMAgentType MediumSizedCharacters \ No newline at end of file diff --git a/Assets/Engine/Config/artprof.cfg b/Assets/Engine/Config/artprof.cfg index 2e1cf55a54..92b91623bf 100644 --- a/Assets/Engine/Config/artprof.cfg +++ b/Assets/Engine/Config/artprof.cfg @@ -1,7 +1,6 @@ ; Setup useful cvars for artists profiling GPU cost ; Once in level (e.g. map c3mp_rooftop_gardens from the frontend/cmdline), in the console: ; exec artprof.cfg -; Be sure also to set r_shadersAsyncActivation=0 in your user.cfg (or copy artprof_user.cfg -> user.cfg) ; used to allow loading of loose shaders sys_pakPriority=0 @@ -9,19 +8,8 @@ sys_pakPriority=0 ; because it's annoying and not relevant for artists sys_pakLogInvalidFileAccess=0 -; disable fog volumes and particles as they can be misleading with r_measureOverdraw 4 -e_fogVolumes=0 -e_particles=0 - ; for convenience -g_infiniteSuitEnergy=1 -g_infiniteAmmo=1 -g_timelimit=0 + bind o "r_measureOverdraw 0" bind p "r_measureOverdraw 4" -bind k "r_artProfile 0" -bind l "r_artProfile 1" - -; loading into an MP level with the map command stops you looking up and down unless you have a weapon -i_giveitem scar diff --git a/Assets/Engine/Config/artprof_user.cfg b/Assets/Engine/Config/artprof_user.cfg index 673436f6f3..265021e120 100644 --- a/Assets/Engine/Config/artprof_user.cfg +++ b/Assets/Engine/Config/artprof_user.cfg @@ -1,6 +1,3 @@ -; disable async shader activation as it crashes when r_shadersAllowCompilation=1 -r_shadersAsyncActivation=0 - ; enable shader compiliation for r_measureOverdraw 4 r_shadersAllowCompilation=1 diff --git a/Assets/Engine/Config/benchmark_cpu.cfg b/Assets/Engine/Config/benchmark_cpu.cfg index c75619107f..bbb3c9db95 100644 --- a/Assets/Engine/Config/benchmark_cpu.cfg +++ b/Assets/Engine/Config/benchmark_cpu.cfg @@ -1,13 +1,3 @@ -demo_restart_level = 2 -g_godMode=1 -g_infiniteammo=1 r_displayinfo=1 -demo_file = autotest -demo_ai = 1 -demo_num_runs = 4 -demo_quit = 1 -hud_startPaused=0 sys_maxfps=0 -e_ObjectLayersActivation=0 -sys_flash = 0 r_vsync = 0 diff --git a/Assets/Engine/Config/benchmark_gpu.cfg b/Assets/Engine/Config/benchmark_gpu.cfg index 7653b32d86..f0242d64d1 100644 --- a/Assets/Engine/Config/benchmark_gpu.cfg +++ b/Assets/Engine/Config/benchmark_gpu.cfg @@ -1,13 +1,3 @@ -demo_restart_level = 1 -g_godMode = 1 -g_infiniteammo = 1 r_displayinfo = 2 -demo_file = timedemo_short -demo_ai = 0 -demo_num_runs = 2 -demo_quit = 1 --- hud_startPaused = 0 sys_maxfps = -1 --- e_ObjectLayersActivation = 0 --- sys_flash = 0 -r_vsync = 0 \ No newline at end of file +r_vsync = 0 diff --git a/Assets/Engine/Config/mgpu.cfg b/Assets/Engine/Config/mgpu.cfg index 93da7fdfd0..e69de29bb2 100644 --- a/Assets/Engine/Config/mgpu.cfg +++ b/Assets/Engine/Config/mgpu.cfg @@ -1,6 +0,0 @@ -r_ColorGradingChartsCache = 0 -r_waterupdateFactor = 0 -r_PostProcessHUD3DCache = 0 -e_gsmcache = 0 -r_ConditionalRendering = 0 -e_gicache = 0 \ No newline at end of file diff --git a/Assets/Engine/Config/multiplayer.cfg b/Assets/Engine/Config/multiplayer.cfg index eafa434f8e..e69de29bb2 100644 --- a/Assets/Engine/Config/multiplayer.cfg +++ b/Assets/Engine/Config/multiplayer.cfg @@ -1,77 +0,0 @@ -ag_turnSpeedParamScale=0.0 -aim_assistFalloffDistance=200 -aim_assistInputForFullFollow_Ironsight=0.20 -aim_assistMaxDistance=255 -aim_assistMaxDistance_ironsight=255 -aim_assistMinTurnScale=0.5 -aim_assistMinTurnScale_ironsight=0.5 -aim_assistSlowDisableDistance=255 -aim_assistSlowFalloffStartDistance=200 -aim_assistSlowThresholdOuter=2.5 -aim_assiststrength=0.7 -aim_assiststrength_ironsight=0.75 -br_breakmaxworldsize=511 -cl_sensitivityControllerMP=0.6 -cl_shallowWaterSpeedMulPlayer=1.0 -controller_multiplier_x=3 -controller_multiplier_z=4 -g_actorViewDistRatio=255 - --- This forces broken trees to have spherical inertia, which makes them harder to rotate around their vertical axis. -g_breakageMinAxisInertia=1.0 -g_glassAutoShatterMinArea=0.5 - -g_distanceForceNoIk=35 -g_fpDbaManagementEnable=0 -g_godMode=0 -g_highlightingMaxDistanceToHighlightSquared=625 -g_hitDeathReactions_streaming=2 -g_mp_as_DefendersMaxHealth=150 -g_multiplayerDefault=1 - --- Overriden in GameSDK\Difficulty\*.cfg -g_playerLowHealthThreshold=20 -g_playerMidHealthThreshold=60 - -g_spawn_vistable_numLineTestsPerFrame=3 -g_telemetryConfig="MP" -g_telemetrySampleRateBandwidth=3 -g_telemetrySampleRateMemory=2 -g_telemetrySampleRatePerformance=1 -g_VTOLInsideBoundsScaleX=0.6 -g_VTOLInsideBoundsScaleY=1 -net_breakage_sync_entities=0 -net_enable_tfrc=0 -net_log=1 - --- Make consoles match the PC gravity -p_gravity_z="-13" - --- Sanity check for physics RepositionEntity -p_max_entity_cells=10000 - -pl_impulseEnabled=1 -pl_jump_maxTimerValue=0.0 -pl_jump_quickPressThresh=0.12 -pl_melee.angle_limit_from_behind=70 -pl_melee.impulses_enable=1 -pl_melee.melee_snap_angle_limit=45 -pl_melee.melee_snap_end_position_range=1.5 -pl_melee.melee_snap_move_speed_multiplier=10 -pl_melee.melee_snap_target_select_range=3.5 -pl_melee.mp_knockback_strength_hor=2 -pl_melee.mp_melee_system=1 -pl_melee.mp_victim_screenfx_blendout_duration=0.25 -pl_melee.mp_victim_screenfx_duration=0.1 -pl_nanovision_timetodrain=8 -pl_nanovision_timetorecharge=16 -pl_pickAndThrow.chargedThrowAutoAimConeSize=10 -pl_pickAndThrow.complexMelee_snap_angle_limit=25 -pl_sliding_control_mp.deceleration_speed=4 -pl_sliding_control_mp.max_downhill_acceleration=15 -pl_sliding_control_mp.min_speed=4 -pl_sliding_control_mp.min_speed_threshold=5 -pl_stealthKill_aimVsSpineLerp=0.65 -pl_stealthKill_useExtendedRange=1 -p_splash_vel0=0.5 -sv_bandwidth=2147483647 \ No newline at end of file diff --git a/Assets/Engine/Config/multiplayer_console.cfg b/Assets/Engine/Config/multiplayer_console.cfg index 0bed002497..e69de29bb2 100644 --- a/Assets/Engine/Config/multiplayer_console.cfg +++ b/Assets/Engine/Config/multiplayer_console.cfg @@ -1,29 +0,0 @@ -e_GI=0 -r_DeferredShadingIndexedAmbient=0 -e_ParticlesObjectCollisions=0 -g_distanceForceNoLegRaycasts=0.00001 -g_telemetryDisplaySessionId=1 -g_breakageNoDebrisCollisions=1 - -; Breakage throttling -; These are explained in ActionGame.cpp -; -g_glassAutoShatterOnExplosions=1 -g_glassNoDecals=1 -g_glassMaxPanesToBreakPerFrame=2 -g_breakageTreeMax=100 -g_breakageTreeInc=101 -g_breakageTreeDec=25 -g_breakageTreeIncGlass=51 - -sys_PakInMemoryPakSizeLimit=25 - -r_TexturesStreamPoolSecondarySize=35 -r_MotionBlur=1 - -e_CoverageBufferReproj=2 - -osm_enabled = 1 - -g_waterHitOnly = 1 -p_max_object_splashes=1 diff --git a/Assets/Engine/Config/recording.cfg b/Assets/Engine/Config/recording.cfg index 42a0dfd9bd..931dbf0858 100644 --- a/Assets/Engine/Config/recording.cfg +++ b/Assets/Engine/Config/recording.cfg @@ -1,63 +1,3 @@ --- added this lines for proper 360 deg panorama renderings - -e_ScreenShotFileFormat = jpg -demo_fixed_timestep = 60 -s_SoundEnable = 0 r_DisplayInfo = 0 -e_PanoramaScreenShotHeight = 720 -e_PanoramaScreenShotWidth = 10053 c_shakeMult = 0 -demo_ai = 1 -r_MotionBlur = 0 - --- enables full water reflection --- e_DebugMask = 2 -- e_DebugMask not allowed here - --- set weapong lighting effect to 0 to prevent flickering bug because of too much dynamic lights in the scene - - sys_spec = 2 -r_WaterRefractions = 1 -r_WaterReflections = 1 -r_WaterUpdateFactor = 0.01 -r_WaterReflections_ForceParticles = 0 - -r_EnvCMResolution = 2 -r_EnvTexResolution = 3 -r_EnvTexUpdateInterval = 0.05 -e_Decals = 1 -e_DecalsLifeTimeScale = 2 -ca_EnableDecals = 1 -e_LodRatio = 10 -e_ViewDistRatio = 55 -e_Lods = 1 -e_VegetationMinSize = 0 -r_CloudsUpdateAlways = 0 - -e_DynamicLightsMaxEntityLights = 3 -r_DepthOfField = 1 ---r_MotionBlur = 1 -r_Flares = 1 -r_checkSunVis = 1 -r_Coronas = 1 -r_CoronaFade = 0.1625 -r_UseEdgeAA = 1 -e_Clouds = 1 - -r_TexResolution = 0 -r_TexBumpResolution = 0 -r_DetailTextures = 1 -r_DetailNumLayers = 1 -r_DetailDistance = 8 - -e_ParticlesLod = 0.9 - -r_ShadowBlur = 3 -e_ShadowsMaxTexRes = 1024 -r_ShadowJittering = 1 -e_Shadows = 1 -e_VegetationBending = 1 -ai_UpdateAllAlways = 1 -r_refraction = 1 -r_sunshafts = 1 -r_ImposterRatio = 1 diff --git a/Assets/Engine/Config/singleplayer.cfg b/Assets/Engine/Config/singleplayer.cfg index fc7a4f4c05..e69de29bb2 100644 --- a/Assets/Engine/Config/singleplayer.cfg +++ b/Assets/Engine/Config/singleplayer.cfg @@ -1,15 +0,0 @@ -ai_CompatibilityMode=crysis2 -ai_BurstWhileMovingDestinationRange=9999.0 - -g_telemetryConfig=SP - -net_inactivitytimeout=3600 -net_inactivitytimeoutDevmode=3600 - -pl_movement.nonCombat_heavy_weapon_speed_scale=1.0 - --- BLM - Don't override game rules. The template project only has DummyRules. --- Furthermore, multiplayer.cfg doesn't set sv_gamerules, so the inconsistency --- is likely to create bugs. ---sv_gamerules=SinglePlayer -ca_StreamCHR=1 \ No newline at end of file diff --git a/Assets/Engine/Config/sketch_off.cfg b/Assets/Engine/Config/sketch_off.cfg deleted file mode 100644 index 6b0562daab..0000000000 --- a/Assets/Engine/Config/sketch_off.cfg +++ /dev/null @@ -1,24 +0,0 @@ -r_UseZPass = 1 -r_GeomInstancing = 1 - -e_Fog = 1 -e_Clouds = 1 -e_Decals = 1 -e_TerrainDetailMaterials = 1 -e_Dissolve = 1 -e_TerrainAo = 1 - -r_WaterReflections = 1 - -e_Shadows = 1 -e_VegetationBending = 1 - -r_PostProcessEffects = 1 -r_Flares = 1 -r_Beams = 1 -r_Glow = 1 - -r_DetailTextures = 1 - -r_refraction = 1 -r_sunshafts = 1 \ No newline at end of file diff --git a/Assets/Engine/Config/sketch_on.cfg b/Assets/Engine/Config/sketch_on.cfg deleted file mode 100644 index 6759b5d4c8..0000000000 --- a/Assets/Engine/Config/sketch_on.cfg +++ /dev/null @@ -1,24 +0,0 @@ -r_UseZPass = 0 -r_GeomInstancing = 0 - -e_Fog = 0 -e_Clouds = 0 -e_Decals = 0 -e_TerrainDetailMaterials = 0 -e_Dissolve = 0 -e_TerrainAo = 0 - -r_WaterReflections = 0 - -e_Shadows = 0 -e_VegetationBending = 0 - -r_PostProcessEffects = 0 -r_Flares = 0 -r_Beams = 0 -r_Glow = 0 - -r_DetailTextures = 0 - -r_refraction = 0 -r_sunshafts = 0 \ No newline at end of file diff --git a/Assets/Engine/Config/spec/android_MaliT760.cfg b/Assets/Engine/Config/spec/android_MaliT760.cfg index f951e61eef..fd7c0a349d 100644 --- a/Assets/Engine/Config/spec/android_MaliT760.cfg +++ b/Assets/Engine/Config/spec/android_MaliT760.cfg @@ -1,76 +1,8 @@ -sys_spec_Full=2 - -- Cap frame rate at 30fps sys_maxfps=30 r_vsync=0 --- Disable gmem for this device because it causes a crash -r_EnableGMEMPath=0 - --- Default of 3 allocates all shaders (potentially >150 MB) --- 1 is most memory efficient but definitely causes hitches when converting HLSL --- shaders. Recommend 1 during dev, and 3 with optimized caches for release. -r_ShadersPreactivate=1 - -sys_job_system_max_worker=2 sys_streaming_in_blocks=1 sys_streaming_memory_budget=512 --- This allows the generation of reflections for the ocean water. Without it, the water looks really dark. -e_recursion=1 -e_CheckOcclusion=1 - -r_Fur=0 -az_Asset_EnableAsyncMeshLoading=0 - ------------------------- --- Misc. memory buffers ------------------------- -e_GeomCacheBufferSize=0 -e_CheckOcclusionQueueSize=512 -e_CheckOcclusionOutputQueueSize=1024 - ------------------------- --- Animation ------------------------- -ca_MemoryDefragPoolSize=33554432 -ca_StreamCHR=1 - ------------------------- --- sys_spec_objectdetail ------------------------- -e_Dissolve=2 -e_LodRatio=5 -e_ViewDistRatioDetail=19 -e_ViewDistRatioVegetation=21 - - ------------------------- --- sys_spec_postprocessing ------------------------- -r_HDRBloom=0 -r_SunShafts=0 -r_ToneMapTechnique=3 -r_ToneMapExposureType=1 -r_ColorSpace=2 - ------------------------- --- sys_spec_shading ------------------------- -r_VisAreaClipLightsPerPixel=0 - ------------------------- --- sys_spec_textureresolution ------------------------- -r_TexturesstreamingMinUsableMips=7 - - - --- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame. --- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame. --- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps -e_ShadowsCacheRequireManualUpdate = 2 - ---Use an optimized pixel format for the lighting rendertargets during the lighting pass. -r_DeferredShadingLBuffersFmt = 2 \ No newline at end of file diff --git a/Assets/Engine/Config/spec/android_high.cfg b/Assets/Engine/Config/spec/android_high.cfg index fc46adc491..0ab8ebc37b 100644 --- a/Assets/Engine/Config/spec/android_high.cfg +++ b/Assets/Engine/Config/spec/android_high.cfg @@ -1,65 +1,7 @@ -sys_spec_Full=3 - -- Cap frame rate at 30fps sys_maxfps=30 r_vsync=0 --- Enable framebufferfetch(256bpp) or pls if applicable -r_EnableGMEMPath=2 - --- Skip the native upscale as a second upscale already occurs -r_SkipNativeUpscale=1 - --- Default of 3 allocates all shaders (potentially >150 MB) --- 1 is most memory efficient but definitely causes hitches when converting HLSL --- shaders. Recommend 1 during dev, and 3 with optimized caches for release. -r_ShadersPreactivate=1 - -sys_job_system_max_worker=2 sys_streaming_in_blocks=1 sys_streaming_memory_budget=512 - -e_CheckOcclusion=1 - -r_Fur=0 -az_Asset_EnableAsyncMeshLoading=0 - ------------------------- --- Misc. memory buffers ------------------------- -e_GeomCacheBufferSize=0 -e_CheckOcclusionQueueSize=512 -e_CheckOcclusionOutputQueueSize=1024 - ------------------------- --- Animation ------------------------- -ca_MemoryDefragPoolSize=33554432 -ca_StreamCHR=1 - ------------------------- --- sys_spec_objectdetail ------------------------- -e_Dissolve=2 -e_LodRatio=5 -e_ViewDistRatioDetail=19 - - ------------------------- --- sys_spec_shading ------------------------- -r_VisAreaClipLightsPerPixel=0 - --- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame. --- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame. --- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps -e_ShadowsCacheRequireManualUpdate = 2 - -r_ClearGMEMGBuffer=1 - --- Sort ligths since we have limited space in the shadowmap pool texture -r_DeferredShadingSortLights = 3 - ---Use an optimized pixel format for the lighting rendertargets during the lighting pass. -r_DeferredShadingLBuffersFmt = 2 \ No newline at end of file diff --git a/Assets/Engine/Config/spec/android_high_nogmem.cfg b/Assets/Engine/Config/spec/android_high_nogmem.cfg index ac718a57ee..fd7c0a349d 100644 --- a/Assets/Engine/Config/spec/android_high_nogmem.cfg +++ b/Assets/Engine/Config/spec/android_high_nogmem.cfg @@ -1,61 +1,8 @@ -sys_spec_Full=3 - -- Cap frame rate at 30fps sys_maxfps=30 r_vsync=0 --- Disabling gmem for this configuration -r_EnableGMEMPath=0 - --- Skip the native upscale as a second upscale already occurs -r_SkipNativeUpscale=1 - --- Default of 3 allocates all shaders (potentially >150 MB) --- 1 is most memory efficient but definitely causes hitches when converting HLSL --- shaders. Recommend 1 during dev, and 3 with optimized caches for release. -r_ShadersPreactivate=1 - -sys_job_system_max_worker=2 sys_streaming_in_blocks=1 sys_streaming_memory_budget=512 -e_CheckOcclusion=1 - -r_Fur=0 -az_Asset_EnableAsyncMeshLoading=0 - ------------------------- --- Misc. memory buffers ------------------------- -e_GeomCacheBufferSize=0 -e_CheckOcclusionQueueSize=512 -e_CheckOcclusionOutputQueueSize=1024 - ------------------------- --- Animation ------------------------- -ca_MemoryDefragPoolSize=33554432 -ca_StreamCHR=1 - ------------------------- --- sys_spec_objectdetail ------------------------- -e_Dissolve=2 -e_LodRatio=5 -e_ViewDistRatioDetail=19 - - ------------------------- --- sys_spec_shading ------------------------- -r_VisAreaClipLightsPerPixel=0 - --- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame. --- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame. --- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps -e_ShadowsCacheRequireManualUpdate = 2 - ---Use an optimized pixel format for the lighting rendertargets during the lighting pass. -r_DeferredShadingLBuffersFmt = 2 - diff --git a/Assets/Engine/Config/spec/android_low.cfg b/Assets/Engine/Config/spec/android_low.cfg index 6f2a876877..0ab8ebc37b 100644 --- a/Assets/Engine/Config/spec/android_low.cfg +++ b/Assets/Engine/Config/spec/android_low.cfg @@ -1,76 +1,7 @@ -sys_spec_Full=1 - -- Cap frame rate at 30fps sys_maxfps=30 r_vsync=0 --- Enable framebufferfetch(256bpp) or pls if applicable -r_EnableGMEMPath=1 - --- Skip the native upscale as a second upscale already occurs -r_SkipNativeUpscale=1 - --- Default of 3 allocates all shaders (potentially >150 MB) --- 1 is most memory efficient but definitely causes hitches when converting HLSL --- shaders. Recommend 1 during dev, and 3 with optimized caches for release. -r_ShadersPreactivate=1 - -sys_job_system_max_worker=2 sys_streaming_in_blocks=1 sys_streaming_memory_budget=512 - --- This allows the generation of reflections for the ocean water. Without it, the water looks really dark. -e_recursion=0 -e_CheckOcclusion=1 - -r_Fur=0 - --- Water occlusion queries crash in some OpenGL ES 3.0 devices -e_HwOcclusionCullingWater = 0 -az_Asset_EnableAsyncMeshLoading=0 - ------------------------- --- Misc. memory buffers ------------------------- -e_GeomCacheBufferSize=0 -e_CheckOcclusionQueueSize=512 -e_CheckOcclusionOutputQueueSize=1024 - ------------------------- --- Animation ------------------------- -ca_MemoryDefragPoolSize=33554432 -ca_StreamCHR=1 - ------------------------- --- sys_spec_objectdetail ------------------------- -e_Dissolve=2 -e_LodRatio=5 -e_ViewDistRatioDetail=19 - - ------------------------- --- sys_spec_shading ------------------------- -r_VisAreaClipLightsPerPixel=0 - - ------------------------- --- sys_spec_textureresolution ------------------------- -r_TexturesstreamingMinUsableMips=6 - - --- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame. --- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame. --- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps -e_ShadowsCacheRequireManualUpdate = 2 - --- Sort ligths since we have limited space in the shadowmap pool texture -r_DeferredShadingSortLights = 3 -r_ClearGMEMGBuffer=1 - ---Use an optimized pixel format for the lighting rendertargets during the lighting pass. -r_DeferredShadingLBuffersFmt = 2 \ No newline at end of file diff --git a/Assets/Engine/Config/spec/android_medium.cfg b/Assets/Engine/Config/spec/android_medium.cfg index f9d776efa7..0ab8ebc37b 100644 --- a/Assets/Engine/Config/spec/android_medium.cfg +++ b/Assets/Engine/Config/spec/android_medium.cfg @@ -1,81 +1,7 @@ -sys_spec_Full=2 - -- Cap frame rate at 30fps sys_maxfps=30 r_vsync=0 --- Enable framebufferfetch(256bpp) or pls if applicable -r_EnableGMEMPath=1 - --- Skip the native upscale as a second upscale already occurs -r_SkipNativeUpscale=1 - --- Default of 3 allocates all shaders (potentially >150 MB) --- 1 is most memory efficient but definitely causes hitches when converting HLSL --- shaders. Recommend 1 during dev, and 3 with optimized caches for release. -r_ShadersPreactivate=1 - -sys_job_system_max_worker=2 sys_streaming_in_blocks=1 sys_streaming_memory_budget=512 - --- This allows the generation of reflections for the ocean water. Without it, the water looks really dark. -e_recursion=1 -e_CheckOcclusion=1 - -r_Fur=0 -az_Asset_EnableAsyncMeshLoading=0 - ------------------------- --- Misc. memory buffers ------------------------- -e_GeomCacheBufferSize=0 -e_CheckOcclusionQueueSize=512 -e_CheckOcclusionOutputQueueSize=1024 - ------------------------- --- Animation ------------------------- -ca_MemoryDefragPoolSize=33554432 -ca_StreamCHR=1 - ------------------------- --- sys_spec_objectdetail ------------------------- -e_Dissolve=2 -e_LodRatio=5 -e_ViewDistRatioDetail=19 -e_ViewDistRatioVegetation=21 - - ------------------------- --- sys_spec_postprocessing ------------------------- -r_HDRBloom=0 -r_SunShafts=0 -r_ToneMapExposureType=1 -r_ColorSpace=2 - ------------------------- --- sys_spec_shading ------------------------- -r_VisAreaClipLightsPerPixel=0 - ------------------------- --- sys_spec_textureresolution ------------------------- -r_TexturesstreamingMinUsableMips=7 - --- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame. --- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame. --- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps -e_ShadowsCacheRequireManualUpdate = 2 - -r_ClearGMEMGBuffer=1 - --- Sort ligths since we have limited space in the shadowmap pool texture -r_DeferredShadingSortLights = 3 - ---Use an optimized pixel format for the lighting rendertargets during the lighting pass. -r_DeferredShadingLBuffersFmt = 2 \ No newline at end of file diff --git a/Assets/Engine/Config/spec/android_veryhigh.cfg b/Assets/Engine/Config/spec/android_veryhigh.cfg index d4f8e9cd47..d58e319706 100644 --- a/Assets/Engine/Config/spec/android_veryhigh.cfg +++ b/Assets/Engine/Config/spec/android_veryhigh.cfg @@ -1,60 +1,5 @@ -sys_spec_Full=4 - -- Cap frame rate at 30fps sys_maxfps=30 r_vsync=0 - --- Enable framebufferfetch(256bpp) or pls if applicable -r_EnableGMEMPath=1 - --- Skip the native upscale as a second upscale already occurs -r_SkipNativeUpscale=1 - --- Default of 3 allocates all shaders (potentially >150 MB) --- 1 is most memory efficient but definitely causes hitches when converting HLSL --- shaders. Recommend 1 during dev, and 3 with optimized caches for release. -r_ShadersPreactivate=1 - -sys_job_system_max_worker=2 sys_streaming_in_blocks=1 - sys_streaming_memory_budget=512 - -e_CheckOcclusion=1 - -r_Fur=0 -az_Asset_EnableAsyncMeshLoading=0 - ------------------------- --- Misc. memory buffers ------------------------- -e_GeomCacheBufferSize=0 -e_CheckOcclusionQueueSize=512 -e_CheckOcclusionOutputQueueSize=1024 - ------------------------- --- Animation ------------------------- -ca_MemoryDefragPoolSize=33554432 -ca_StreamCHR=1 - ------------------------- --- sys_spec_objectdetail ------------------------- -e_Dissolve=2 -e_LodRatio=5 -e_ViewDistRatioDetail=19 - - ------------------------- --- sys_spec_shading ------------------------- -r_VisAreaClipLightsPerPixel=0 - -r_ClearGMEMGBuffer=1 - --- Sort ligths since we have limited space in the shadowmap pool texture -r_DeferredShadingSortLights = 3 - ---Use an optimized pixel format for the lighting rendertargets during the lighting pass. -r_DeferredShadingLBuffersFmt = 2 \ No newline at end of file diff --git a/Assets/Engine/Config/spec/ios_high.cfg b/Assets/Engine/Config/spec/ios_high.cfg index 67fa99ca04..d0cf5b3bc5 100644 --- a/Assets/Engine/Config/spec/ios_high.cfg +++ b/Assets/Engine/Config/spec/ios_high.cfg @@ -1,100 +1,10 @@ -sys_spec_Full=3 - -- Cap frame rate at 30fps sys_maxfps=30 r_vsync=1 --- Enable framebufferfetch or pls if applicable -r_EnableGMEMPath=1 - --- Skip the native upscale as a second upscale occurs on Metal Present -r_SkipNativeUpscale=1 - --- Default of 3 allocates all shaders (potentially >150 MB) --- 1 is most memory efficient but definitely causes hitches when converting HLSL --- shaders. Recommend 1 during dev, and 3 with optimized caches for release. -r_ShadersPreactivate=1 - - ------------------------- --- Job System ------------------------- -sys_job_system_enable=0 -sys_job_system_max_worker=1 - ------------------------ -- Streaming ------------------------ sys_streaming_in_blocks=1 sys_streaming_memory_budget=512 ------------------------- --- General Rendering ------------------------- -r_Flush=0 --- Enabling this will clear the GMEM buffer before the z-pass -r_ClearGMEMGBuffer=2 -r_Fur=0 - ------------------------- --- VisArea / Portals ------------------------- -e_PortalsBlend=0 -r_GMEMVisAreasBlendWeight=0.5 - ------------------------- --- Misc. memory buffers ------------------------- -e_AutoPrecacheCgf=2 -e_AutoPrecacheTerrainAndProcVeget=1 -e_GeomCacheBufferSize=0 -e_CheckOcclusionQueueSize=512 -e_CheckOcclusionOutputQueueSize=2048 - ------------------------- --- Animation ------------------------- -ca_MemoryDefragPoolSize=32 -ca_StreamCHR=1 - ------------------------- --- sys_spec_water ------------------------- -e_WaterOcean=2 -e_WaterVolumes=2 -e_WaterOceanBottom=0 - ------------------------- --- batching ------------------------- -r_Batching = 1 -r_BatchType = 0 - ------------------------- --- geom instancing ------------------------- -r_GeomInstancing=1 -r_GeomInstancingThreshold=5 - ------------------------- --- Upscaling ------------------------- ---0 point, 1 bilinear, 2 bicubic, 3 lanczos -r_UpscalingQuality=1 - ------------------------- --- Geometry Cache ------------------------- -e_GeomCaches=0 - - --- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame. --- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame. --- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps -e_ShadowsCacheRequireManualUpdate = 2 - --- Sort ligths since we have limited space in the shadowmap pool texture -r_DeferredShadingSortLights = 3 - ---Use an optimized pixel format for the lighting rendertargets during the lighting pass. -r_DeferredShadingLBuffersFmt = 2 \ No newline at end of file diff --git a/Assets/Engine/Config/spec/ios_low.cfg b/Assets/Engine/Config/spec/ios_low.cfg index 7870d65bd5..d0cf5b3bc5 100644 --- a/Assets/Engine/Config/spec/ios_low.cfg +++ b/Assets/Engine/Config/spec/ios_low.cfg @@ -1,103 +1,10 @@ -sys_spec_Full=1 - -- Cap frame rate at 30fps sys_maxfps=30 r_vsync=1 --- Enable framebufferfetch or pls if applicable -r_EnableGMEMPath=1 - --- Skip the native upscale as a second upscale occurs on Metal Present -r_SkipNativeUpscale=1 - --- Default of 3 allocates all shaders (potentially >150 MB) --- 1 is most memory efficient but definitely causes hitches when converting HLSL --- shaders. Recommend 1 during dev, and 3 with optimized caches for release. -r_ShadersPreactivate=1 - - ------------------------- --- Job System ------------------------- -sys_job_system_enable=0 -sys_job_system_max_worker=1 - ------------------------ -- Streaming ------------------------ sys_streaming_in_blocks=1 sys_streaming_memory_budget=512 ------------------------- --- General Rendering ------------------------- -r_Flush=0 --- Enabling this will clear the GMEM buffer before the z-pass -r_ClearGMEMGBuffer=2 -r_Fur=0 - ------------------------- --- VisArea / Portals ------------------------- -e_PortalsBlend=0 -r_GMEMVisAreasBlendWeight=0.5 - ------------------------- --- Misc. memory buffers ------------------------- -e_AutoPrecacheCgf=2 -e_AutoPrecacheTerrainAndProcVeget=1 -e_GeomCacheBufferSize=0 -e_CheckOcclusionQueueSize=512 -e_CheckOcclusionOutputQueueSize=1024 - ------------------------- --- Animation ------------------------- -ca_MemoryDefragPoolSize=32 -ca_StreamCHR=1 - ------------------------- --- sys_spec_water ------------------------- -e_WaterOcean=2 -e_WaterVolumes=2 -e_WaterOceanBottom=0 - - ------------------------- --- batching ------------------------- -r_Batching = 1 -r_BatchType = 0 - ------------------------- --- geom instancing ------------------------- -r_GeomInstancing=1 -r_GeomInstancingThreshold=5 - ------------------------- --- Upscaling ------------------------- ---0 point, 1 bilinear, 2 bicubic, 3 lanczos -r_UpscalingQuality=1 - ------------------------- --- Geometry Cache ------------------------- -e_GeomCaches=0 - - - - --- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame. --- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame. --- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps -e_ShadowsCacheRequireManualUpdate = 2 - --- Sort ligths since we have limited space in the shadowmap pool texture -r_DeferredShadingSortLights = 3 - ---Use an optimized pixel format for the lighting rendertargets during the lighting pass. -r_DeferredShadingLBuffersFmt = 2 \ No newline at end of file diff --git a/Assets/Engine/Config/spec/ios_medium.cfg b/Assets/Engine/Config/spec/ios_medium.cfg index 2eaecdef16..d0cf5b3bc5 100644 --- a/Assets/Engine/Config/spec/ios_medium.cfg +++ b/Assets/Engine/Config/spec/ios_medium.cfg @@ -1,101 +1,10 @@ -sys_spec_Full=2 - -- Cap frame rate at 30fps sys_maxfps=30 r_vsync=1 --- Enable framebufferfetch or pls if applicable -r_EnableGMEMPath=1 - --- Skip the native upscale as a second upscale occurs on Metal Present -r_SkipNativeUpscale=1 - --- Default of 3 allocates all shaders (potentially >150 MB) --- 1 is most memory efficient but definitely causes hitches when converting HLSL --- shaders. Recommend 1 during dev, and 3 with optimized caches for release. -r_ShadersPreactivate=1 - - ------------------------- --- Job System ------------------------- -sys_job_system_enable=0 -sys_job_system_max_worker=1 - ------------------------ -- Streaming ------------------------ sys_streaming_in_blocks=1 sys_streaming_memory_budget=512 ------------------------- --- General Rendering ------------------------- -r_Flush=0 --- Enabling this will clear the GMEM buffer before the z-pass -r_ClearGMEMGBuffer=2 -r_Fur=0 - ------------------------- --- VisArea / Portals ------------------------- -e_PortalsBlend=0 -r_GMEMVisAreasBlendWeight=0.5 - ------------------------- --- Misc. memory buffers ------------------------- -e_AutoPrecacheCgf=2 -e_AutoPrecacheTerrainAndProcVeget=1 -e_GeomCacheBufferSize=0 -e_CheckOcclusionQueueSize=512 -e_CheckOcclusionOutputQueueSize=1024 - ------------------------- --- Animation ------------------------- -ca_MemoryDefragPoolSize=32 -ca_StreamCHR=1 - ------------------------- --- sys_spec_water ------------------------- -e_WaterOcean=2 -e_WaterVolumes=2 -e_WaterOceanBottom=0 - - ------------------------- --- batching ------------------------- -r_Batching = 1 -r_BatchType = 0 - ------------------------- --- geom instancing ------------------------- -r_GeomInstancing=1 -r_GeomInstancingThreshold=5 - ------------------------- --- Upscaling ------------------------- ---0 point, 1 bilinear, 2 bicubic, 3 lanczos -r_UpscalingQuality=1 - ------------------------- --- Geometry Cache ------------------------- -e_GeomCaches=0 - - --- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame. --- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame. --- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps -e_ShadowsCacheRequireManualUpdate = 2 - --- Sort ligths since we have limited space in the shadowmap pool texture -r_DeferredShadingSortLights = 3 - ---Use an optimized pixel format for the lighting rendertargets during the lighting pass. -r_DeferredShadingLBuffersFmt = 2 \ No newline at end of file diff --git a/Assets/Engine/Config/spec/ios_veryhigh.cfg b/Assets/Engine/Config/spec/ios_veryhigh.cfg index 53937a77bf..d0cf5b3bc5 100644 --- a/Assets/Engine/Config/spec/ios_veryhigh.cfg +++ b/Assets/Engine/Config/spec/ios_veryhigh.cfg @@ -1,102 +1,10 @@ -sys_spec_Full=4 - -- Cap frame rate at 30fps sys_maxfps=30 r_vsync=1 --- Enable framebufferfetch or pls if applicable -r_EnableGMEMPath=1 - --- Skip the native upscale as a second upscale occurs on Metal Present -r_SkipNativeUpscale=1 - --- Default of 3 allocates all shaders (potentially >150 MB) --- 1 is most memory efficient but definitely causes hitches when converting HLSL --- shaders. Recommend 1 during dev, and 3 with optimized caches for release. -r_ShadersPreactivate=1 - - ------------------------- --- Job System ------------------------- -sys_job_system_enable=0 -sys_job_system_max_worker=1 - ------------------------ -- Streaming ------------------------ sys_streaming_in_blocks=1 sys_streaming_memory_budget=512 ------------------------- --- General Rendering ------------------------- -r_Flush=0 --- Enabling this will clear the GMEM buffer before the z-pass -r_ClearGMEMGBuffer=2 -r_Fur=0 - ------------------------- --- VisArea / Portals ------------------------- -e_PortalsBlend=0 -r_GMEMVisAreasBlendWeight=0.5 - ------------------------- --- Misc. memory buffers ------------------------- -e_AutoPrecacheCgf=2 -e_AutoPrecacheTerrainAndProcVeget=1 -e_GeomCacheBufferSize=0 -e_CheckOcclusionQueueSize=512 -e_CheckOcclusionOutputQueueSize=2048 - ------------------------- --- Animation ------------------------- -ca_MemoryDefragPoolSize=32 -ca_StreamCHR=1 - ------------------------- --- sys_spec_water ------------------------- -e_WaterOcean=2 -e_WaterVolumes=2 -e_WaterOceanBottom=0 - - ------------------------- --- batching ------------------------- -r_Batching = 1 -r_BatchType = 0 - ------------------------- --- geom instancing ------------------------- -r_GeomInstancing=1 -r_GeomInstancingThreshold=5 - ------------------------- --- Upscaling ------------------------- ---0 point, 1 bilinear, 2 bicubic, 3 lanczos -r_UpscalingQuality=1 - ------------------------- --- Geometry Cache ------------------------- -e_GeomCaches=0 - - - --- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame. --- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame. --- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps -e_ShadowsCacheRequireManualUpdate = 2 - --- Sort ligths since we have limited space in the shadowmap pool texture -r_DeferredShadingSortLights = 3 - ---Use an optimized pixel format for the lighting rendertargets during the lighting pass. -r_DeferredShadingLBuffersFmt = 2 \ No newline at end of file diff --git a/Assets/Engine/Config/spec/osx_metal_high.cfg b/Assets/Engine/Config/spec/osx_metal_high.cfg deleted file mode 100644 index 8689e23c51..0000000000 --- a/Assets/Engine/Config/spec/osx_metal_high.cfg +++ /dev/null @@ -1,38 +0,0 @@ - -sys_spec_Full=7 -r_ShadersMETAL=1 - --- Default of 3 allocates all shaders (potentially >150 MB) --- 1 is most memory efficient but definitely causes hitches when converting HLSL --- shaders. Recommend 1 during dev, and 3 with optimized caches for release. -r_ShadersPreactivate=1 - --- Skip the native upscale as a second upscale occurs on Metal Present -r_SkipNativeUpscale=1 - ------------------------- --- sys_spec_postprocessing ------------------------- -r_SunShafts=1 - ------------------------- --- sys_spec_shading ------------------------- -r_DeferredShadingTiled=0 -r_RefractionPartialResolves=0 -e_GI = 0 - - -r_Fur=2 - - ------------------------- --- Upscaling ------------------------- ---0 point, 1 bilinear, 2 bicubic, 3 lanczos -r_UpscalingQuality=1 - --- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame. --- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame. --- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps -e_ShadowsCacheRequireManualUpdate = 2 diff --git a/Assets/Engine/Config/spec/osx_metal_low.cfg b/Assets/Engine/Config/spec/osx_metal_low.cfg deleted file mode 100644 index a3084d48c5..0000000000 --- a/Assets/Engine/Config/spec/osx_metal_low.cfg +++ /dev/null @@ -1,37 +0,0 @@ - -sys_spec_Full=5 -r_ShadersMETAL=1 - --- Default of 3 allocates all shaders (potentially >150 MB) --- 1 is most memory efficient but definitely causes hitches when converting HLSL --- shaders. Recommend 1 during dev, and 3 with optimized caches for release. -r_ShadersPreactivate=1 - --- Skip the native upscale as a second upscale occurs on Metal Present -r_SkipNativeUpscale=1 - ------------------------- --- sys_spec_postprocessing ------------------------- -r_SunShafts=1 - ------------------------- --- sys_spec_shading ------------------------- -r_DeferredShadingTiled=0 -r_RefractionPartialResolves=0 -e_GI=0 - -r_Fur=2 - - ------------------------- --- Upscaling ------------------------- ---0 point, 1 bilinear, 2 bicubic, 3 lanczos -r_UpscalingQuality=1 - --- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame. --- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame. --- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps -e_ShadowsCacheRequireManualUpdate = 2 diff --git a/Assets/Engine/Config/spec/osx_metal_medium.cfg b/Assets/Engine/Config/spec/osx_metal_medium.cfg deleted file mode 100644 index 6477bbb217..0000000000 --- a/Assets/Engine/Config/spec/osx_metal_medium.cfg +++ /dev/null @@ -1,37 +0,0 @@ - -sys_spec_Full=6 -r_ShadersMETAL=1 - --- Default of 3 allocates all shaders (potentially >150 MB) --- 1 is most memory efficient but definitely causes hitches when converting HLSL --- shaders. Recommend 1 during dev, and 3 with optimized caches for release. -r_ShadersPreactivate=1 - --- Skip the native upscale as a second upscale occurs on Metal Present -r_SkipNativeUpscale=1 - ------------------------- --- sys_spec_postprocessing ------------------------- -r_SunShafts=1 - ------------------------- --- sys_spec_shading ------------------------- -r_DeferredShadingTiled=0 -r_RefractionPartialResolves=0 -e_GI = 0 - -r_Fur=2 - - ------------------------- --- Upscaling ------------------------- ---0 point, 1 bilinear, 2 bicubic, 3 lanczos -r_UpscalingQuality=1 - --- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame. --- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame. --- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps -e_ShadowsCacheRequireManualUpdate = 2 diff --git a/Assets/Engine/Config/spec/osx_metal_veryhigh.cfg b/Assets/Engine/Config/spec/osx_metal_veryhigh.cfg deleted file mode 100644 index 899c198f31..0000000000 --- a/Assets/Engine/Config/spec/osx_metal_veryhigh.cfg +++ /dev/null @@ -1,37 +0,0 @@ - -sys_spec_Full=8 -r_ShadersMETAL=1 - --- Default of 3 allocates all shaders (potentially >150 MB) --- 1 is most memory efficient but definitely causes hitches when converting HLSL --- shaders. Recommend 1 during dev, and 3 with optimized caches for release. -r_ShadersPreactivate=1 - --- Skip the native upscale as a second upscale occurs on Metal Present -r_SkipNativeUpscale=1 - ------------------------- --- sys_spec_postprocessing ------------------------- -r_SunShafts=1 - ------------------------- --- sys_spec_shading ------------------------- -r_DeferredShadingTiled=0 -r_RefractionPartialResolves=0 -e_GI = 0 - -r_Fur=2 - - ------------------------- --- Upscaling ------------------------- ---0 point, 1 bilinear, 2 bicubic, 3 lanczos -r_UpscalingQuality=1 - --- Due to performance issues with incremental cached shadow map updates, enable this to prevent us from culling every object in the world vs each cached shadow map each frame. --- If no objects are present in the level this will eliminate the need to clear the massive cached textures each frame. --- Set to 2 to allow distance-based updates along with script-based updates for the cached shadow maps -e_ShadowsCacheRequireManualUpdate = 2 diff --git a/Assets/Engine/Config/spec/pc_high.cfg b/Assets/Engine/Config/spec/pc_high.cfg index a62ed25a6a..e69de29bb2 100644 --- a/Assets/Engine/Config/spec/pc_high.cfg +++ b/Assets/Engine/Config/spec/pc_high.cfg @@ -1 +0,0 @@ -sys_spec_Full = 7 \ No newline at end of file diff --git a/Assets/Engine/Config/spec/pc_low.cfg b/Assets/Engine/Config/spec/pc_low.cfg index 068446e151..e69de29bb2 100644 --- a/Assets/Engine/Config/spec/pc_low.cfg +++ b/Assets/Engine/Config/spec/pc_low.cfg @@ -1 +0,0 @@ -sys_spec_Full = 5 diff --git a/Assets/Engine/Config/spec/pc_medium.cfg b/Assets/Engine/Config/spec/pc_medium.cfg index 0d08b956b4..e69de29bb2 100644 --- a/Assets/Engine/Config/spec/pc_medium.cfg +++ b/Assets/Engine/Config/spec/pc_medium.cfg @@ -1 +0,0 @@ -sys_spec_Full = 6 \ No newline at end of file diff --git a/Assets/Engine/Config/spec/pc_veryhigh.cfg b/Assets/Engine/Config/spec/pc_veryhigh.cfg index 33959937e8..e69de29bb2 100644 --- a/Assets/Engine/Config/spec/pc_veryhigh.cfg +++ b/Assets/Engine/Config/spec/pc_veryhigh.cfg @@ -1 +0,0 @@ -sys_spec_Full = 8 diff --git a/Assets/Engine/Config/statoscope.cfg b/Assets/Engine/Config/statoscope.cfg index d1d18c813c..ed2089bd67 100644 --- a/Assets/Engine/Config/statoscope.cfg +++ b/Assets/Engine/Config/statoscope.cfg @@ -1,12 +1,3 @@ profile=-1 -profile_allthreads=1 -i_forcefeedback=0 -g_godmode=1 log_verbosity=-1 sys_pakLogInvalidFileAccess=1 -e_StatoscopeDataGroups=fgmrtudlipny -e_StatoscopeFilenameUseBuildInfo=0 -e_StatoscopeFilenameUseMap=1 -e_StatoscopeMinFuncLengthMs=0.1 -e_StatoscopeMaxNumFuncsPerFrame=60 -e_StatoscopeScreenshotCapturePeriod=5 diff --git a/Assets/Engine/Config/vr.cfg b/Assets/Engine/Config/vr.cfg index 989f55f345..80d4b7ce81 100644 --- a/Assets/Engine/Config/vr.cfg +++ b/Assets/Engine/Config/vr.cfg @@ -3,39 +3,13 @@ ----------------------------------------------- r_width = 960 r_height = 1080 -r_backbufferWidth = 1920 -r_backbufferHeight = 1080 - ------------------------------------------- -- Set the system Spec (Medium) ------------------------------------------- sys_spec = 2 - -------------------------------------------- --- HMD related -------------------------------------------- -r_overrideDXGIoutput = 0 -r_stereodevice = 100 -r_stereomode = 1 -r_stereooutput = 7 -r_minimizeLatency = 1 -hmd_low_persistence = 1 -r_stereoScaleCoefficient = 1 - - ------------------------------------------- -- Set some video optimisations ------------------------------------------- r_vsync = 0 -r_MotionBlur = 0 -r_ssdoHalfRes = 3 -r_Refraction = 0 -r_DeferredShadingTiled = 0 -r_CBufferUseNativeDepth = 0 - -------------------------------------------- --- Hide the hud -------------------------------------------- ---hud_hide = 1 diff --git a/Assets/Engine/SeedAssetList.seed b/Assets/Engine/SeedAssetList.seed index 579fd3c444..aafbffbe8f 100644 --- a/Assets/Engine/SeedAssetList.seed +++ b/Assets/Engine/SeedAssetList.seed @@ -48,22 +48,6 @@ - - - - - - - - - - - - - - - - @@ -432,110 +416,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -616,38 +496,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_component_helper.py b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_component_helper.py index 821e0acfdb..11832f8846 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_component_helper.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/atom_utils/atom_component_helper.py @@ -113,7 +113,6 @@ def create_basic_atom_level(level_name): general.close_pane("Error Log") general.idle_wait(1.0) general.run_console("r_displayInfo=0") - general.run_console("r_antialiasingmode=0") general.idle_wait(1.0) # Delete all existing entities & create default_level entity diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py index 92199bf196..fbd9f3459a 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_AtomFeatureIntegrationBenchmark.py @@ -66,7 +66,6 @@ def run(): general.close_pane("Error Log") general.idle_wait(1.0) general.run_console("r_displayInfo=0") - general.run_console("r_antialiasingmode=0") general.idle_wait(1.0) return True diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_BasicLevelSetup.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_BasicLevelSetup.py index ac28e67fa1..93e78a7c0a 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_BasicLevelSetup.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_GPUTest_BasicLevelSetup.py @@ -82,7 +82,6 @@ def run(): general.close_pane("Error Log") general.idle_wait(1.0) general.run_console("r_displayInfo=0") - general.run_console("r_antialiasingmode=0") general.idle_wait(1.0) return True diff --git a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py index ef3048d8d4..1b094b1cfa 100644 --- a/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py +++ b/AutomatedTesting/Gem/PythonTests/EditorPythonTestTools/editor_python_test_tools/utils.py @@ -149,7 +149,6 @@ class TestHelper: general.idle_wait(1.0) general.idle_wait(1.0) general.run_console("r_displayInfo=0") - general.run_console("r_antialiasingmode=0") general.idle_wait(1.0) diff --git a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/screenshot_utils.py b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/screenshot_utils.py index 49cf17855f..22fa3aca0d 100755 --- a/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/screenshot_utils.py +++ b/AutomatedTesting/Gem/PythonTests/automatedtesting_shared/screenshot_utils.py @@ -187,7 +187,3 @@ def prepare_for_screenshot_compare(remote_console_instance): """ wait_for(lambda: _retry_command(remote_console_instance, 'r_displayinfo 0', '$3r_DisplayInfo = $60 $5[DUMPTODISK, RESTRICTEDMODE]$4')) - wait_for(lambda: _retry_command(remote_console_instance, 'r_antialiasingmode 0', - '$3r_AntialiasingMode = $60 $5[]$4')) - wait_for(lambda: _retry_command(remote_console_instance, 'e_WaterOcean 0', - '$3e_WaterOcean = $60 $5[]$4')) diff --git a/Code/Legacy/CrySystem/SystemInit.cpp b/Code/Legacy/CrySystem/SystemInit.cpp index 6de10f3855..ee1c498a9a 100644 --- a/Code/Legacy/CrySystem/SystemInit.cpp +++ b/Code/Legacy/CrySystem/SystemInit.cpp @@ -1273,17 +1273,6 @@ AZ_POP_DISABLE_WARNING //Load config files ////////////////////////////////////////////////////////////////////////// - int curSpecVal = 0; - ICVar* pSysSpecCVar = gEnv->pConsole->GetCVar("r_GraphicsQuality"); - if (gEnv->pSystem->IsDevMode()) - { - if (pSysSpecCVar && pSysSpecCVar->GetFlags() & VF_WASINCONFIG) - { - curSpecVal = pSysSpecCVar->GetIVal(); - pSysSpecCVar->SetFlags(pSysSpecCVar->GetFlags() | VF_SYSSPEC_OVERWRITE); - } - } - // tools may not interact with @user@ if (!gEnv->IsInToolMode()) { @@ -1293,16 +1282,6 @@ AZ_POP_DISABLE_WARNING } } - // If sys spec variable was specified, is not 0, and we are in devmode restore the value from before loading game.cfg - // This enables setting of a specific sys_spec outside menu and game.cfg - if (gEnv->pSystem->IsDevMode()) - { - if (pSysSpecCVar && curSpecVal && curSpecVal != pSysSpecCVar->GetIVal()) - { - pSysSpecCVar->Set(curSpecVal); - } - } - { // We have to load this file again since first time we did it without devmode LoadConfiguration(m_systemConfigName.c_str()); diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageFlags.h b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageFlags.h index 96393f4a1f..99e752c90a 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageFlags.h +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/Source/Processing/ImageFlags.h @@ -22,7 +22,7 @@ namespace ImageProcessingAtom const static AZ::u32 EIF_UNUSED_BIT = 0x40; // Free to use const static AZ::u32 EIF_AttachedAlpha = 0x400; // info for the engine: it's a texture with attached alpha channel const static AZ::u32 EIF_SRGBRead = 0x800; // info for the engine: if gamma corrected rendering is on, this texture requires SRGBRead (it's not stored in linear) - const static AZ::u32 EIF_DontResize = 0x8000; // info for the engine: for dds textures that shouldn't be resized with r_TexResolution + const static AZ::u32 EIF_DontResize = 0x8000; // info for the engine: for dds textures that shouldn't be resized const static AZ::u32 EIF_RenormalizedTexture = 0x10000; // info for the engine: for dds textures that have renormalized color range const static AZ::u32 EIF_CafeNative = 0x20000; // info for the engine: native Cafe texture format const static AZ::u32 EIF_RestrictedPlatformONative = 0x40000; // native tiled texture for restrict platform O diff --git a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp index 28a5a30e9c..81ec4b17c8 100644 --- a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp +++ b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCommonMenu.cpp @@ -199,20 +199,6 @@ namespace ImGui } } - // Lod Min - static ICVar* eLodMinCVAR = gEnv->pConsole->GetCVar("e_LodMin"); - if (eLodMinCVAR) - { - int minLodValue = eLodMinCVAR->GetIVal(); - int dragIntVal = minLodValue; - ImGui::Text("e_LodMin: %d ( Force a lowest LOD level )", minLodValue); - ImGui::SliderInt("##LodMin", &dragIntVal, 0, 5); - if (dragIntVal != minLodValue) - { - eLodMinCVAR->Set(dragIntVal); - } - } - // Texel Density static ICVar* eTexelDensityCVAR = gEnv->pConsole->GetCVar("e_texeldensity"); if (eTexelDensityCVAR) diff --git a/Tools/LyTestTools/ly_test_tools/launchers/platforms/android/launcher.py b/Tools/LyTestTools/ly_test_tools/launchers/platforms/android/launcher.py index 42adee91ea..75eaa65e94 100755 --- a/Tools/LyTestTools/ly_test_tools/launchers/platforms/android/launcher.py +++ b/Tools/LyTestTools/ly_test_tools/launchers/platforms/android/launcher.py @@ -208,13 +208,6 @@ class AndroidLauncher(Launcher): with self.android_vfs_setreg_path.open('w') as android_vfs_setreg: json.dump(vfs_settings, android_vfs_setreg, indent=4) - self.workspace.settings.modify_platform_setting('r_AssetProcessorShaderCompiler', 1) - self.workspace.settings.modify_platform_setting('r_ShadersAsyncCompiling', 0) - self.workspace.settings.modify_platform_setting('r_ShadersRemoteCompiler', 1) - self.workspace.settings.modify_platform_setting('r_ShadersAllowCompilation', 1) - self.workspace.settings.modify_platform_setting('r_ShadersAsyncActivation', 0) - self.workspace.settings.modify_platform_setting('r_ShaderCompilerServer', '127.0.0.1') - self.workspace.settings.modify_platform_setting('r_ShaderCompilerPort', '61453') self.workspace.settings.modify_platform_setting("log_RemoteConsoleAllowedAddresses", '127.0.0.1') def launch(self): diff --git a/Tools/LyTestTools/ly_test_tools/launchers/platforms/linux/launcher.py b/Tools/LyTestTools/ly_test_tools/launchers/platforms/linux/launcher.py index 210519d197..047e4fdeef 100644 --- a/Tools/LyTestTools/ly_test_tools/launchers/platforms/linux/launcher.py +++ b/Tools/LyTestTools/ly_test_tools/launchers/platforms/linux/launcher.py @@ -172,7 +172,6 @@ class LinuxLauncher(Launcher): self.args.append('--regset="/Amazon/AzCore/Bootstrap/wait_for_connect=1"') self.args.append(f'--regset="/Amazon/AzCore/Bootstrap/allowed_list={host_ip}"') - self.workspace.settings.modify_platform_setting("r_AssetProcessorShaderCompiler", 1) self.workspace.settings.modify_platform_setting("r_ShaderCompilerServer", host_ip) self.workspace.settings.modify_platform_setting("log_RemoteConsoleAllowedAddresses", host_ip) diff --git a/Tools/LyTestTools/ly_test_tools/launchers/platforms/win/launcher.py b/Tools/LyTestTools/ly_test_tools/launchers/platforms/win/launcher.py index 4f904b0a40..d18431ba82 100755 --- a/Tools/LyTestTools/ly_test_tools/launchers/platforms/win/launcher.py +++ b/Tools/LyTestTools/ly_test_tools/launchers/platforms/win/launcher.py @@ -172,8 +172,6 @@ class WinLauncher(Launcher): self.args.append('--regset="/Amazon/AzCore/Bootstrap/wait_for_connect=1"') self.args.append(f'--regset="/Amazon/AzCore/Bootstrap/allowed_list={host_ip}"') - self.workspace.settings.modify_platform_setting("r_AssetProcessorShaderCompiler", 1) - self.workspace.settings.modify_platform_setting("r_ShaderCompilerServer", host_ip) self.workspace.settings.modify_platform_setting("log_RemoteConsoleAllowedAddresses", host_ip) diff --git a/Tools/LyTestTools/tests/unit/test_launcher_android.py b/Tools/LyTestTools/tests/unit/test_launcher_android.py index d2f700e35e..d1adccb096 100755 --- a/Tools/LyTestTools/tests/unit/test_launcher_android.py +++ b/Tools/LyTestTools/tests/unit/test_launcher_android.py @@ -238,7 +238,7 @@ class TestAndroidLauncher: launcher = ly_test_tools.launchers.AndroidLauncher(mock_workspace, ["dummy"]) launcher.configure_settings() - assert mock_workspace.settings.modify_platform_setting.call_count == 8 + assert mock_workspace.settings.modify_platform_setting.call_count == 1 @mock.patch('ly_test_tools.launchers.platforms.base.Launcher._config_ini_to_dict') @mock.patch('ly_test_tools.environment.process_utils.check_output') diff --git a/cmake/Tools/layout_tool.py b/cmake/Tools/layout_tool.py index 62e3922770..8093f72e44 100755 --- a/cmake/Tools/layout_tool.py +++ b/cmake/Tools/layout_tool.py @@ -120,10 +120,7 @@ def verify_layout(layout_dir, platform_name, project_path, asset_mode, asset_typ warning_count += _warn(f"'system_{platform_name_lower}_{asset_type}.cfg' is missing from {str(layout_path)}") system_config_values = None else: - system_config_values = common.get_config_file_values(str(platform_system_cfg_file), ['r_ShadersRemoteCompiler', - 'r_ShadersAllowCompilation', - 'r_AssetProcessorShaderCompiler', - 'r_ShaderCompilerServer']) + system_config_values = common.get_config_file_values(str(platform_system_cfg_file), []) if bootstrap_values: @@ -146,24 +143,23 @@ def verify_layout(layout_dir, platform_name, project_path, asset_mode, asset_typ elif system_config_values is not None: - shaders_remote_compiler = system_config_values.get('r_ShadersRemoteCompiler') or '0' + shaders_remote_compiler = '0' asset_processor_shader_compiler = system_config_values.get('r_AssetProcessorShaderCompiler') or '0' - shader_compiler_server = system_config_values.get('r_ShaderCompilerServer') or LOCAL_HOST + shader_compiler_server = LOCAL_HOST shaders_allow_compilation = system_config_values.get('r_ShadersAllowCompilation') def _validate_remote_shader_settings(): - if shader_compiler_server == LOCAL_HOST: - if asset_processor_shader_compiler != '1': - return _warn(f"Connection to the remote shader compiler (r_ShaderCompilerServer) is not properly " - f"set in system_{platform_name_lower}_{asset_type}.cfg. If it is set to {LOCAL_HOST}, then " - f"r_AssetProcessorShaderCompiler must be set to 1.") + if asset_processor_shader_compiler != '1': + return _warn(f"Connection to the remote shader compiler (r_ShaderCompilerServer) is not properly " + f"set in system_{platform_name_lower}_{asset_type}.cfg. If it is set to {LOCAL_HOST}, then " + f"r_AssetProcessorShaderCompiler must be set to 1.") - else: - if _validate_remote_ap(remote_ip, remote_connect, False) > 0: - return _warn(f"The system_{platform_name_lower}_{asset_type}.cfg file is configured to connect to the" - f" shader compiler server through the remote connection to the Asset Processor.") + else: + if _validate_remote_ap(remote_ip, remote_connect, False) > 0: + return _warn(f"The system_{platform_name_lower}_{asset_type}.cfg file is configured to connect to the" + f" shader compiler server through the remote connection to the Asset Processor.") return 0 # Validation steps based on the asset mode @@ -181,16 +177,9 @@ def verify_layout(layout_dir, platform_name, project_path, asset_mode, asset_typ warning_count += _warn("No pak files found for PAK mode deployment") # Check if the shader paks are set if has_shader_pak: - # If the shader paks are set, make sure that the remote shader compiler connection settings are set - # or that it is going through AP - if shaders_remote_compiler == '1': - warning_count += _warn(f"Shader paks are set for project {project_name} but remote shader compiling " - f"(r_ShadersRemoteCompiler) is still enabled " - f"for it in system_{platform_name_lower}_{asset_type}.cfg.") - else: - # Since we are not connecting to the shader compiler, also make sure bootstrap is not configured to - # connect to Asset Processor remotely - warning_count += _validate_remote_ap(remote_ip, remote_connect, False) + # Since we are not connecting to the shader compiler, also make sure bootstrap is not configured to + # connect to Asset Processor remotely + warning_count += _validate_remote_ap(remote_ip, remote_connect, False) if shaders_allow_compilation is not None and shaders_allow_compilation == '1': warning_count += _warn(f"Shader paks are set for project {project_name} but shader compiling " diff --git a/editor.cfg b/editor.cfg index 843a52824d..a8719590c5 100644 --- a/editor.cfg +++ b/editor.cfg @@ -1,33 +1,12 @@ -- Settings stored here are only used in the Editor --- Disable the Missing Asset Resolver by default -ed_MissingAssetResolver = 0 -e_ShadowsCache=0 -r_MotionBlur=0 -r_HDRVignetting=0 --- For feature-test compatibility -mn_FatalErrorOnInvalidEntity=0 - -- Do not warn on Pak file access issues sys_PakWarnOnPakAccessFailures=0 --- By default, disable any possible stereo output that might have been enabled via a GEM/other config file so that --- the editor does not startup in stereo mode (which prevents actually editing the environment) -r_StereoMode=0 -r_StereoOutput=0 - -- When editing terrain in the editor, the highest-detail octree nodes for any edited sector will be rendered until -- the level is exported and saved, which can cause an artificial increase in the number of nodes that can get -- queued for visibility checks. These numbers need to be set high enough to account for those increases. --- The CheckOcclusionQueueSize should be at least (terrain height * terrain width) / (32 * 32) in size. --- (Each queue entry is 64 bytes of RAM) -e_CheckOcclusionQueueSize=32768 - --- The CheckOcclusionOutputQueueSize should be at least double the above queue size for safety. --- (Each queue entry is 64 bytes of RAM) -e_CheckOcclusionOutputQueueSize=65536 - -- Enable warnings when asset loads take longer than the given millisecond threshold cl_assetLoadWarningEnable=true cl_assetLoadWarningMsThreshold=100 diff --git a/system_android_android.cfg b/system_android_android.cfg index d5bfddeb73..10ab95abc4 100644 --- a/system_android_android.cfg +++ b/system_android_android.cfg @@ -6,40 +6,14 @@ sys_PakLogInvalidFileAccess=1 r_WidthAndHeightAsFractionOfScreenSize=1.0 r_MaxWidth=1280 r_MaxHeight=1080 - r_fullscreen=0 +r_ShadersAllowCompilation=1 -- Enable to prevent log spam, can cause missed messages -- log_spamdelay=1 --- DXGL ---r_Batching=0 - --- Enabling aync shader compiling causes a hang on some Android devices. -r_ShadersAsyncCompiling=0 -r_ShadersRemoteCompiler=1 -r_ShadersAllowCompilation=1 -r_ShadersAsyncActivation=0 - --- Use the Asset Processor to route requests to compile shaders. This enables the Asset Processor --- to forward the request to the real shader compiler server. Your device is no --- longer required to be on the same network as the shader compiler server, as long as the device can contact the Asset Processor: -r_AssetProcessorShaderCompiler=1 - --- If you run your device locally on the same computer as the shader compiler server, you can use 127.0.0.1. --- To connect to a shader compiler server that runs on another computer, change localhost to the IP address of that computer (61453 is the default port): -r_ShaderCompilerServer=127.0.0.1 - --- For Shader Compiler server running on other machines - 61453 is the default port -r_ShaderCompilerPort=61453 - --- Spec level: 0 = auto, 1 = low, 2 = medium, 3 = high, 4 = very high. -r_GraphicsQuality = 2 - -s_FileCacheManagerSize=262144 - -- Remote console inclusion list log_RemoteConsoleAllowedAddresses=127.0.0.1 -- Localization Settings -sys_localization_format=0 \ No newline at end of file +sys_localization_format=0 diff --git a/system_ios_ios.cfg b/system_ios_ios.cfg index 190ad4a121..abf08d0209 100644 --- a/system_ios_ios.cfg +++ b/system_ios_ios.cfg @@ -3,26 +3,7 @@ ------------------------ r_FullScreen=1 - r_ShadersAllowCompilation=1 -r_ShadersAsyncActivation=0 -r_ShadersAsyncCompiling=0 -r_ShadersRemoteCompiler=1 -r_ShadersUseLLVMDirectXCompiler=1 - --- Spec level: 0 = auto, 1 = low, 2 = medium, 3 = high, 4 = very high. -r_GraphicsQuality = 0 - --- Use the Asset Processor to route requests to compile shaders. This enables the Asset Processor --- to forward the request to the real shader compiler server. Your device is no --- longer required to be on the same network as the shader compiler server, as long as the device can contact the Asset Processor: -r_AssetProcessorShaderCompiler=1 - --- If you run your device locally on the same computer as the shader compiler server, you can use 127.0.0.1. --- To connect to a shader compiler server that runs on another computer, change localhost to the IP address of that computer (61453 is the default port): -r_ShaderCompilerServer=127.0.0.1 - ---r_ShaderCompilerPort=61453 ------------------------ -- System @@ -39,16 +20,6 @@ sys_physics_CPU=0 -- log_spamdelay=1 log_IncludeTime=1 ------------------------- --- Audio ------------------------- -s_FileCacheManagerSize=262144 ------------------------- --- Auxiliary Geometry ------------------------- -r_enableAuxGeom=0 -r_auxGeom=0 - -- Remote console inclusion list log_RemoteConsoleAllowedAddresses=127.0.0.1 diff --git a/system_linux_pc.cfg b/system_linux_pc.cfg index 614bc44b49..5fec6b8dfd 100644 --- a/system_linux_pc.cfg +++ b/system_linux_pc.cfg @@ -10,8 +10,6 @@ sys_PakLogInvalidFileAccess = 0 -- Remote console inclusion list log_RemoteConsoleAllowedAddresses=127.0.0.1 -gm_disconnectDetection = 1 - -- Localization Settings sys_localization_format=0 @@ -20,27 +18,7 @@ r_width = 1280 r_height = 720 r_fullscreen = 0 -r_ShadersAsyncCompiling = 3 -r_ShadersAsyncActivation = 3 -r_ShadersAsyncMaxThreads = 16 -r_ShadersRemoteCompiler = 1 r_ShadersAllowCompilation = 1 --- Use the Asset Processor to route requests to compile shaders. This enables the Asset Processor --- to forward the request to the real shader compiler server. Your device is no --- longer required to be on the same network as the shader compiler server, as long as the device can contact the Asset Processor: -r_AssetProcessorShaderCompiler=0 - --- If you run your device locally on the same computer as the shader compiler server, you can use 127.0.0.1. --- To connect to a shader compiler server that runs on another computer, change localhost to the IP address of that computer (61453 is the default port): ---r_ShaderCompilerServer=127.0.0.1 ---r_ShaderCompilerPort = 61453 - --- Spec level: 0 = auto, 1 = low, 2 = medium, 3 = high, 4 = very high. Autodetection not yet implemented for this platform. -r_GraphicsQuality = 1 - --- Texture streaming not supported on opengl -r_TexturesStreaming=0 - -- Display FPS r_displayInfo = 3 diff --git a/system_mac_mac.cfg b/system_mac_mac.cfg index 22fbca6e1e..ef145c890e 100644 --- a/system_mac_mac.cfg +++ b/system_mac_mac.cfg @@ -3,9 +3,6 @@ sys_float_exceptions=0 log_IncludeTime=1 sys_PakLogInvalidFileAccess=0 --- Spec level: 0 = auto, 1 = low, 2 = medium, 3 = high, 4 = very high. Currently overwritten by hardcoded value for this platform. -r_GraphicsQuality = 0 - r_width=1280 r_height=720 r_fullscreen=0 @@ -13,25 +10,7 @@ r_fullscreen=0 -- Enable to prevent log spam, can cause missed messages -- log_spamdelay=1 --- DXGL -r_Batching=0 - -r_ShadersAsyncCompiling=0 -r_ShadersRemoteCompiler=1 r_ShadersAllowCompilation=1 -r_ShadersAsyncActivation=0 -r_ShadersUseLLVMDirectXCompiler=1 - --- Use the Asset Processor to route requests to compile shaders. This enables the Asset Processor --- to forward the request to the real shader compiler server. Your device is no --- longer required to be on the same network as the shader compiler server, as long as the device can contact the Asset Processor: -r_AssetProcessorShaderCompiler=1 - --- If you run your device locally on the same computer as the shader compiler server, you can use 127.0.0.1. --- To connect to a shader compiler server that runs on another computer, change localhost to the IP address of that computer (61453 is the default port): -r_ShaderCompilerServer=127.0.0.1 - ---r_ShaderCompilerPort=61453 -- Remote console inclusion list log_RemoteConsoleAllowedAddresses=127.0.0.1 diff --git a/system_windows_pc.cfg b/system_windows_pc.cfg index 05210e02e0..aa53ed9323 100644 --- a/system_windows_pc.cfg +++ b/system_windows_pc.cfg @@ -11,27 +11,7 @@ r_fullscreen = 0 -- Enable to prevent log spam, can cause missed messages -- log_spamdelay=1 -r_ShadersAsyncCompiling = 3 -r_ShadersAsyncActivation = 3 -r_ShadersAsyncMaxThreads = 16 -r_ShadersRemoteCompiler = 0 r_ShadersAllowCompilation = 1 --- Use the Asset Processor to route requests to compile shaders. This enables the Asset Processor --- to forward the request to the real shader compiler server. Your device is no --- longer required to be on the same network as the shader compiler server, as long as the device can contact the Asset Processor: -r_AssetProcessorShaderCompiler=0 - --- If you run your device locally on the same computer as the shader compiler server, you can use 127.0.0.1. --- To connect to a shader compiler server that runs on another computer, change localhost to the IP address of that computer (61453 is the default port): -r_ShaderCompilerServer=127.0.0.1 ---r_ShaderCompilerPort = 61453 - --- Spec level: 0 = auto, 1 = low, 2 = medium, 3 = high, 4 = very high. Autodetection not yet implemented for this platform. -r_GraphicsQuality = 4 - ---r_driver=GL ---r_ShadersGL4=1 - -- Localization Settings sys_localization_format=0 From 70636572ff259873a19dd6f8c384b3025c399df1 Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Tue, 12 Oct 2021 15:08:07 -0700 Subject: [PATCH 129/169] Fix casing of editor_xml filenames to match casing in .ly files (#4640) Signed-off-by: Steve Pham --- Code/Editor/CryEditDoc.cpp | 4 ++-- Code/Editor/Util/XmlArchive.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Editor/CryEditDoc.cpp b/Code/Editor/CryEditDoc.cpp index 75bd0ad270..4944c3bff5 100644 --- a/Code/Editor/CryEditDoc.cpp +++ b/Code/Editor/CryEditDoc.cpp @@ -1273,7 +1273,7 @@ bool CCryEditDoc::SaveLevel(const QString& filename) if (savedEntities) { AZ_PROFILE_SCOPE(AzToolsFramework, "CCryEditDoc::SaveLevel Updated PakFile levelEntities.editor_xml"); - pakFile.UpdateFile("LevelEntities.editor_xml", entitySaveBuffer.begin(), static_cast(entitySaveBuffer.size())); + pakFile.UpdateFile("levelentities.editor_xml", entitySaveBuffer.begin(), static_cast(entitySaveBuffer.size())); // Save XML archive to pak file. bool bSaved = xmlAr.SaveToPak(Path::GetPath(tempSaveFile), pakFile); @@ -1501,7 +1501,7 @@ bool CCryEditDoc::LoadEntitiesFromLevel(const QString& levelPakFile) bool pakOpened = pakSystem->OpenPack(levelPakFile.toUtf8().data()); if (pakOpened) { - const QString entityFilename = Path::GetPath(levelPakFile) + "LevelEntities.editor_xml"; + const QString entityFilename = Path::GetPath(levelPakFile) + "levelentities.editor_xml"; CCryFile entitiesFile; if (entitiesFile.Open(entityFilename.toUtf8().data(), "rt")) diff --git a/Code/Editor/Util/XmlArchive.cpp b/Code/Editor/Util/XmlArchive.cpp index 18c3fc8e63..3a965fb239 100644 --- a/Code/Editor/Util/XmlArchive.cpp +++ b/Code/Editor/Util/XmlArchive.cpp @@ -119,7 +119,7 @@ bool CXmlArchive::SaveToPak([[maybe_unused]] const QString& levelPath, CPakFile& _smart_ptr pXmlStrData = root->getXMLData(5000000); // Save xml file. - QString xmlFilename = "Level.editor_xml"; + QString xmlFilename = "level.editor_xml"; pakFile.UpdateFile(xmlFilename.toUtf8().data(), (void*)pXmlStrData->GetString(), static_cast(pXmlStrData->GetStringLength())); if (pakFile.GetArchive()) @@ -134,7 +134,7 @@ bool CXmlArchive::SaveToPak([[maybe_unused]] const QString& levelPath, CPakFile& ////////////////////////////////////////////////////////////////////////// bool CXmlArchive::LoadFromPak(const QString& levelPath, CPakFile& pakFile) { - QString xmlFilename = QDir(levelPath).absoluteFilePath("Level.editor_xml"); + QString xmlFilename = QDir(levelPath).absoluteFilePath("level.editor_xml"); root = XmlHelpers::LoadXmlFromFile(xmlFilename.toUtf8().data()); if (!root) { From 3b78132833f7537e7f5c107fa38b13987cd91f31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Semp=C3=A9?= <58790905+lsemp3d@users.noreply.github.com> Date: Tue, 12 Oct 2021 15:45:41 -0700 Subject: [PATCH 130/169] Split StyleHelper.h into a header and source file (#4614) * Split StyleHelper.h into a header and source file Signed-off-by: lsemp3d <58790905+lsemp3d@users.noreply.github.com> * Missing file from commit Signed-off-by: lsemp3d <58790905+lsemp3d@users.noreply.github.com> * Removed incorrect path Signed-off-by: lsemp3d <58790905+lsemp3d@users.noreply.github.com> * Fixed includes Signed-off-by: lsemp3d <58790905+lsemp3d@users.noreply.github.com> * Removed unnecessary comment Signed-off-by: lsemp3d <58790905+lsemp3d@users.noreply.github.com> * Missing include Signed-off-by: lsemp3d <58790905+lsemp3d@users.noreply.github.com> --- .../GraphCanvas/Styling/StyleHelper.cpp | 470 +++++++++++++++++ .../GraphCanvas/Styling/StyleHelper.h | 480 ++---------------- .../Code/graphcanvas_staticlib_files.cmake | 1 + .../ContainerWizard/ContainerWizard.cpp | 1 - .../Tools/UpgradeTool/UpgradeHelper.ui | 3 - 5 files changed, 510 insertions(+), 445 deletions(-) create mode 100644 Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/StyleHelper.cpp diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/StyleHelper.cpp b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/StyleHelper.cpp new file mode 100644 index 0000000000..6313d6ec17 --- /dev/null +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/StyleHelper.cpp @@ -0,0 +1,470 @@ +/* + * 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 GraphCanvas +{ + namespace Styling + { + + StyleHelper::StyleHelper(const AZ::EntityId& styledEntity) + { + SetStyle(styledEntity); + } + + StyleHelper::StyleHelper(const AZ::EntityId& realStyledEntity, const AZStd::string& virtualChildElement) + { + SetStyle(realStyledEntity, virtualChildElement); + } + + StyleHelper::~StyleHelper() + { + ReleaseStyle(); + } + + void StyleHelper::OnStylesUnloaded() + { + ReleaseStyle(); + } + + void StyleHelper::SetEditorId(const EditorId& editorId) + { + if (m_editorId != editorId) + { + ReleaseStyle(); + m_editorId = editorId; + + RegisterStyleSheetBus(m_editorId); + } + } + + void StyleHelper::SetScene(const AZ::EntityId& sceneId) + { + m_scene = sceneId; + + EditorId editorId; + SceneRequestBus::EventResult(editorId, m_scene, &SceneRequests::GetEditorId); + SetEditorId(editorId); + } + + void StyleHelper::SetStyle(const AZ::EntityId& styledEntity) + { + ReleaseStyle(); + + m_styledEntity = styledEntity; + + AZ::EntityId sceneId; + SceneMemberRequestBus::EventResult(sceneId, m_styledEntity, &SceneMemberRequests::GetScene); + if (!sceneId.IsValid()) + { + return; + } + + SetScene(sceneId); + + for (const auto& selector : m_styleSelectors) + { + StyledEntityRequestBus::Event(m_styledEntity, &StyledEntityRequests::AddSelectorState, selector.c_str()); + } + + UpdateStyle(); + } + + void StyleHelper::SetStyle(const AZStd::string& style) + { + ReleaseStyle(); + + m_deleteStyledEntity = true; + + PseudoElementFactoryRequestBus::BroadcastResult(m_styledEntity, &PseudoElementFactoryRequests::CreateStyleEntity, style); + + for (const auto& selector : m_styleSelectors) + { + StyledEntityRequestBus::Event(m_styledEntity, &StyledEntityRequests::AddSelectorState, selector.c_str()); + } + + // TODO: remove/replace OnSceneSet and fix any systems/components listening for that event. + SceneMemberNotificationBus::Event(m_styledEntity, &SceneMemberNotifications::OnSceneSet, m_scene); + + UpdateStyle(); + + static bool enableDiagnostic = false; + if (enableDiagnostic) + { + AZStd::string description; + StyleRequestBus::EventResult(description, m_style, &StyleRequests::GetDescription); + qDebug() << description.c_str(); + } + } + + void StyleHelper::SetStyle(const AZ::EntityId& parentStyledEntity, const AZStd::string& virtualChildElement) + { + ReleaseStyle(); + + m_deleteStyledEntity = true; + + AZ::EntityId sceneId; + SceneMemberRequestBus::EventResult(sceneId, parentStyledEntity, &SceneMemberRequests::GetScene); + + SetScene(sceneId); + + PseudoElementFactoryRequestBus::BroadcastResult(m_styledEntity, &PseudoElementFactoryRequests::CreateVirtualChild, parentStyledEntity, virtualChildElement); + + for (const auto& selector : m_styleSelectors) + { + StyledEntityRequestBus::Event(m_styledEntity, &StyledEntityRequests::AddSelectorState, selector.c_str()); + } + + UpdateStyle(); + + static bool enableDiagnostic = false; + if (enableDiagnostic) + { + AZStd::string description; + StyleRequestBus::EventResult(description, m_style, &StyleRequests::GetDescription); + qDebug() << description.c_str(); + } + + } + + void StyleHelper::RemoveAttributeOverride(Styling::Attribute attribute) + { + m_attributeOverride.erase(attribute); + } + + bool StyleHelper::HasAttribute(Styling::Attribute attribute) const + { + bool hasAttribute = (m_attributeOverride.find(attribute) != m_attributeOverride.end()); + + if (!hasAttribute) + { + StyleRequestBus::EventResult(hasAttribute, m_style, &StyleRequests::HasAttribute, static_cast(attribute)); + } + + return hasAttribute; + } + + QColor StyleHelper::GetColor(Styling::Attribute color, QColor defaultValue /*= QColor()*/) const + { + return GetAttribute(color, defaultValue); + } + + QFont StyleHelper::GetFont() const + { + QFont font; + QFontInfo info(font); + info.pixelSize(); + + font.setFamily(GetAttribute(Attribute::FontFamily, font.family())); + font.setPixelSize(GetAttribute(Attribute::FontSize, info.pixelSize())); + font.setWeight(GetAttribute(Attribute::FontWeight, font.weight())); + font.setStyle(GetAttribute(Attribute::FontStyle, font.style())); + font.setCapitalization(GetAttribute(Attribute::FontVariant, font.capitalization())); + + return font; + } + + QString StyleHelper::GetFontStyleSheet() const + { + QFont font = GetFont(); + QColor color = GetColor(Styling::Attribute::Color); + + QStringList fields; + + fields.push_back(QString("color: rgba(%1,%2,%3,%4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(color.alpha())); + + fields.push_back(QString("font-family: %1").arg(font.family())); + fields.push_back(QString("font-size: %1px").arg(font.pixelSize())); + + if (font.bold()) + { + fields.push_back("font-weight: bold"); + } + + switch (font.style()) + { + case QFont::StyleNormal: + break; + case QFont::StyleItalic: + fields.push_back("font-style: italic"); + break; + case QFont::StyleOblique: + fields.push_back("font-style: italic"); + break; + } + + const bool underline = font.underline(); + const bool strikeOut = font.strikeOut(); + + if (underline && strikeOut) + { + fields.push_back("text-decoration: underline line-through"); + } + else if (underline) + { + fields.push_back("text-decoration: underline"); + } + else if (strikeOut) + { + fields.push_back("text-decoration: line-through"); + } + + return fields.join("; "); + } + + QPen StyleHelper::GetPen(Styling::Attribute width, Styling::Attribute style, Styling::Attribute color, Styling::Attribute cap, bool cosmetic /*= false*/) const + { + QPen pen; + pen.setColor(GetAttribute(color, QColor(Qt::black))); + pen.setWidth(GetAttribute(width, 1)); + pen.setStyle(GetAttribute(style, Qt::SolidLine)); + pen.setCapStyle(GetAttribute(cap, Qt::SquareCap)); + pen.setCosmetic(cosmetic); + + return pen; + } + + QPen StyleHelper::GetBorder() const + { + return GetPen(Styling::Attribute::BorderWidth, Styling::Attribute::BorderStyle, Styling::Attribute::BorderColor, Styling::Attribute::CapStyle); + } + + QBrush StyleHelper::GetBrush(Styling::Attribute color, QBrush defaultValue /*= QBrush()*/) const + { + return GetAttribute(color, defaultValue); + } + + QSizeF StyleHelper::GetSize(QSizeF defaultSize) const + { + return{ + GetAttribute(Styling::Attribute::Width, defaultSize.width()), + GetAttribute(Styling::Attribute::Height, defaultSize.height()) + }; + } + + QSizeF StyleHelper::GetMinimumSize(QSizeF defaultSize /*= QSizeF(0,0)*/) const + { + return QSizeF(GetAttribute(Styling::Attribute::MinWidth, defaultSize.width()), GetAttribute(Styling::Attribute::MinHeight, defaultSize.height())); + } + + QSizeF StyleHelper::GetMaximumSize(QSizeF defaultSize /*= QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)*/) const + { + return QSizeF(GetAttribute(Styling::Attribute::MaxWidth, defaultSize.width()), GetAttribute(Styling::Attribute::MaxHeight, defaultSize.height())); + } + + QMarginsF StyleHelper::GetMargins(QMarginsF defaultMargins /*= QMarginsF()*/) const + { + bool hasMargin = false; + StyleRequestBus::EventResult(hasMargin, m_style, &StyleRequests::HasAttribute, static_cast(Styling::Attribute::Margin)); + + if (hasMargin) + { + qreal defaultMargin = GetAttribute(Styling::Attribute::Margin, 0); + defaultMargins = QMarginsF(defaultMargin, defaultMargin, defaultMargin, defaultMargin); + } + + return QMarginsF( + GetAttribute(Styling::Attribute::Margin/*TODO Left*/, defaultMargins.left()), + GetAttribute(Styling::Attribute::Margin/*TODO Top*/, defaultMargins.top()), + GetAttribute(Styling::Attribute::Margin/*TODO Right*/, defaultMargins.right()), + GetAttribute(Styling::Attribute::Margin/*TODO Bottom*/, defaultMargins.bottom()) + ); + } + + bool StyleHelper::HasTextAlignment() const + { + return HasAttribute(Styling::Attribute::TextAlignment) || HasAttribute(Styling::Attribute::TextVerticalAlignment); + } + + Qt::Alignment StyleHelper::GetTextAlignment(Qt::Alignment defaultAlignment) const + { + bool horizontalAlignment = HasAttribute(Styling::Attribute::TextAlignment); + bool verticalAlignment = HasAttribute(Styling::Attribute::TextVerticalAlignment); + + if (horizontalAlignment || verticalAlignment) + { + Qt::Alignment alignment = GetAttribute(Styling::Attribute::TextAlignment, Qt::AlignmentFlag::AlignLeft); + alignment = alignment | GetAttribute(Styling::Attribute::TextVerticalAlignment, Qt::AlignmentFlag::AlignTop); + + return alignment; + } + + return defaultAlignment; + } + + void StyleHelper::AddSelector(const AZStd::string_view& selector) + { + auto insertResult = m_styleSelectors.insert(AZStd::string(selector)); + + if (insertResult.second && m_styledEntity.IsValid()) + { + StyledEntityRequestBus::Event(m_styledEntity, &StyledEntityRequests::AddSelectorState, selector.data()); + + UpdateStyle(); + } + } + + void StyleHelper::RemoveSelector(const AZStd::string_view& selector) + { + AZStd::size_t elements = m_styleSelectors.erase(selector); + + if (elements > 0) + { + StyledEntityRequestBus::Event(m_styledEntity, &StyledEntityRequests::RemoveSelectorState, selector.data()); + + UpdateStyle(); + } + } + + GraphCanvas::CandyStripeConfiguration StyleHelper::GetCandyStripeConfiguration() const + { + CandyStripeConfiguration config; + + config.m_initialOffset = GetAttribute(Styling::Attribute::StripeOffset, 0); + config.m_maximumSize = GetAttribute(Styling::Attribute::MaximumStripeSize, 10); + + if (config.m_maximumSize <= 0) + { + config.m_maximumSize = 1; + } + + config.m_minStripes = GetAttribute(Styling::Attribute::MinimumStripes, 2); + + if (config.m_minStripes <= 0) + { + config.m_minStripes = 1; + } + + config.m_stripeAngle = GetAttribute(Styling::Attribute::StripeAngle, 60); + + if (config.m_stripeAngle > 90) + { + config.m_stripeAngle = 89; + } + else if (config.m_stripeAngle < -90) + { + config.m_stripeAngle = -89; + } + + if (!HasAttribute(Styling::Attribute::StripeColor)) + { + QColor backgroundColor = GetAttribute(Styling::Attribute::BackgroundColor, QColor(0, 0, 0)); + + config.m_stripeColor = backgroundColor.darker(); + + int totalDifference = 0; + + totalDifference += backgroundColor.red() - config.m_stripeColor.red(); + totalDifference += backgroundColor.green() - config.m_stripeColor.green(); + totalDifference += backgroundColor.blue() - config.m_stripeColor.blue(); + + if (totalDifference < 150) + { + config.m_stripeColor = backgroundColor.lighter(); + } + } + else + { + config.m_stripeColor = GetAttribute(Styling::Attribute::StripeColor, QColor(0, 0, 0)); + } + + return config; + } + + GraphCanvas::PatternedFillGenerator StyleHelper::GetPatternedFillGenerator() const + { + PatternedFillGenerator generator; + generator.m_editorId = m_editorId; + + generator.m_id = GetAttribute(Styling::Attribute::PatternTemplate, QString()).toUtf8().data(); + + if (HasAttribute(Styling::Attribute::PatternPalettes)) + { + AZStd::string paletteStrings = GetAttribute(Styling::Attribute::PatternPalettes, QString()).toUtf8().data(); + + AzFramework::StringFunc::Tokenize(paletteStrings.c_str(), generator.m_palettes, ','); + } + else + { + QColor backgroundColor = GetAttribute(Styling::Attribute::BackgroundColor, QColor(0, 0, 0)); + + QColor patternColor = backgroundColor.darker(); + + int totalDifference = 0; + + totalDifference += backgroundColor.red() - patternColor.red(); + totalDifference += backgroundColor.green() - patternColor.green(); + totalDifference += backgroundColor.blue() - patternColor.blue(); + + if (totalDifference < 150) + { + patternColor = backgroundColor.lighter(); + } + + generator.m_colors.push_back(patternColor); + } + + generator.m_configuration = GetPatternFillConfiguration(); + + return generator; + } + + GraphCanvas::PatternFillConfiguration StyleHelper::GetPatternFillConfiguration() const + { + PatternFillConfiguration configuration; + + configuration.m_minimumTileRepetitions = GetAttribute(Styling::Attribute::MinimumRepetitions, 1); + configuration.m_evenRowOffsetPercent = GetAttribute(Styling::Attribute::EvenOffsetPercent, 0.0f); + configuration.m_oddRowOffsetPercent = GetAttribute(Styling::Attribute::OddOffsetPercent, 0.0f); + + return configuration; + } + + void StyleHelper::PopulatePaletteConfiguration(PaletteIconConfiguration& configuration) const + { + AZStd::string stylePalette; + StyledEntityRequestBus::EventResult(stylePalette, m_styledEntity, &StyledEntityRequests::GetFullStyleElement); + + if (!stylePalette.empty()) + { + configuration.SetColorPalette(stylePalette); + } + } + + void StyleHelper::UpdateStyle() + { + ReleaseStyle(false); + StyleManagerRequestBus::EventResult(m_style, m_editorId, &StyleManagerRequests::ResolveStyles, m_styledEntity); + } + + void StyleHelper::ReleaseStyle(bool destroyChildElement /*= true*/) + { + if (m_style.IsValid()) + { + if (m_deleteStyledEntity && destroyChildElement) + { + m_deleteStyledEntity = false; + AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationRequests::DeleteEntity, m_styledEntity); + } + AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationRequests::DeleteEntity, m_style); + + m_style.SetInvalid(); + } + } + + void StyleHelper::RegisterStyleSheetBus(const EditorId& editorId) + { + StyleManagerNotificationBus::Handler::BusDisconnect(); + StyleManagerNotificationBus::Handler::BusConnect(editorId); + } + +} +} diff --git a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/StyleHelper.h b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/StyleHelper.h index cc7429f8fc..b500d4b197 100644 --- a/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/StyleHelper.h +++ b/Gems/GraphCanvas/Code/StaticLib/GraphCanvas/Styling/StyleHelper.h @@ -8,7 +8,8 @@ #pragma once -AZ_PUSH_DISABLE_WARNING(4251 4800 4244, "-Wunknown-warning-option") +#if !defined(Q_MOC_RUN) + #include #include #include @@ -16,7 +17,6 @@ AZ_PUSH_DISABLE_WARNING(4251 4800 4244, "-Wunknown-warning-option") #include #include #include -AZ_POP_DISABLE_WARNING #include #include @@ -32,6 +32,8 @@ AZ_POP_DISABLE_WARNING #include #include +#endif + namespace GraphCanvas { namespace Styling @@ -45,124 +47,49 @@ namespace GraphCanvas AZ_CLASS_ALLOCATOR(StyleHelper, AZ::SystemAllocator, 0); StyleHelper() = default; - - StyleHelper(const AZ::EntityId& styledEntity) - { - SetStyle(styledEntity); - } - - StyleHelper(const AZ::EntityId& realStyledEntity, const AZStd::string& virtualChildElement) - { - SetStyle(realStyledEntity, virtualChildElement); - } - - virtual ~StyleHelper() - { - ReleaseStyle(); - } + StyleHelper(const AZ::EntityId& styledEntity); + StyleHelper(const AZ::EntityId& realStyledEntity, const AZStd::string& virtualChildElement); + virtual ~StyleHelper(); // StyleManagerNotificationBus - void OnStylesUnloaded() override - { - ReleaseStyle(); - } + void OnStylesUnloaded() override; //// - void SetEditorId(const EditorId& editorId) - { - if (m_editorId != editorId) - { - ReleaseStyle(); - m_editorId = editorId; + void SetEditorId(const EditorId& editorId); + void SetScene(const AZ::EntityId& sceneId); - RegisterStyleSheetBus(m_editorId); - } - } + void SetStyle(const AZStd::string& style); + void SetStyle(const AZ::EntityId& styledEntity); + void SetStyle(const AZ::EntityId& parentStyledEntity, const AZStd::string& virtualChildElement); - // TODO: Get rid of this and m_scene once the OnSceneSet notification is removed (see below). - void SetScene(const AZ::EntityId& sceneId) - { - m_scene = sceneId; + bool HasAttribute(Styling::Attribute attribute) const; + void RemoveAttributeOverride(Styling::Attribute attribute); - EditorId editorId; - SceneRequestBus::EventResult(editorId, m_scene, &SceneRequests::GetEditorId); - SetEditorId(editorId); - } + QColor GetColor(Styling::Attribute color, QColor defaultValue = QColor()) const; + QFont GetFont() const; - void SetStyle(const AZ::EntityId& styledEntity) - { - ReleaseStyle(); + //! Helper method which constructs a stylesheet based on the calculated font style. + //! We need this too pass along to certain Qt widgets because we use our own custom style parsing system. + QString GetFontStyleSheet() const; - m_styledEntity = styledEntity; + QPen GetPen(Styling::Attribute width, Styling::Attribute style, Styling::Attribute color, Styling::Attribute cap, bool cosmetic = false) const; + QPen GetBorder() const; + QBrush GetBrush(Styling::Attribute color, QBrush defaultValue = QBrush()) const; + QSizeF GetSize(QSizeF defaultSize) const; + QSizeF GetMinimumSize(QSizeF defaultSize = QSizeF(0,0)) const; + QSizeF GetMaximumSize(QSizeF defaultSize = QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)) const; + QMarginsF GetMargins(QMarginsF defaultMargins = QMarginsF()) const; - AZ::EntityId sceneId; - SceneMemberRequestBus::EventResult(sceneId, m_styledEntity, &SceneMemberRequests::GetScene); - if (!sceneId.IsValid()) - { - return; - } + bool HasTextAlignment() const; + Qt::Alignment GetTextAlignment(Qt::Alignment defaultAlignment) const; - SetScene(sceneId); + void AddSelector(const AZStd::string_view& selector); + void RemoveSelector(const AZStd::string_view& selector); - for (const auto& selector : m_styleSelectors) - { - StyledEntityRequestBus::Event(m_styledEntity, &StyledEntityRequests::AddSelectorState, selector.c_str()); - } - - UpdateStyle(); - -#if 0 - AZStd::string description; - StyleRequestBus::EventResult(description, m_style, &StyleRequests::GetDescription); - qDebug() << description.c_str(); -#endif - } - - void SetStyle(const AZStd::string& style) - { - ReleaseStyle(); - - m_deleteStyledEntity = true; - - PseudoElementFactoryRequestBus::BroadcastResult(m_styledEntity, &PseudoElementFactoryRequests::CreateStyleEntity, style); - - for (const auto& selector : m_styleSelectors) - { - StyledEntityRequestBus::Event(m_styledEntity, &StyledEntityRequests::AddSelectorState, selector.c_str()); - } - - // TODO: remove/replace OnSceneSet and fix any systems/components listening for that event. - SceneMemberNotificationBus::Event(m_styledEntity, &SceneMemberNotifications::OnSceneSet, m_scene); - - UpdateStyle(); - } - - void SetStyle(const AZ::EntityId& parentStyledEntity, const AZStd::string& virtualChildElement) - { - ReleaseStyle(); - - m_deleteStyledEntity = true; - - AZ::EntityId sceneId; - SceneMemberRequestBus::EventResult(sceneId, parentStyledEntity, &SceneMemberRequests::GetScene); - - SetScene(sceneId); - - PseudoElementFactoryRequestBus::BroadcastResult(m_styledEntity, &PseudoElementFactoryRequests::CreateVirtualChild, parentStyledEntity, virtualChildElement); - - for (const auto& selector : m_styleSelectors) - { - StyledEntityRequestBus::Event(m_styledEntity, &StyledEntityRequests::AddSelectorState, selector.c_str()); - } - - UpdateStyle(); - -#if 0 - AZStd::string description; - StyleRequestBus::EventResult(description, m_style, &StyleRequests::GetDescription); - qDebug() << description.c_str(); -#endif - } + CandyStripeConfiguration GetCandyStripeConfiguration() const; + PatternedFillGenerator GetPatternedFillGenerator() const; + PatternFillConfiguration GetPatternFillConfiguration() const; + void PopulatePaletteConfiguration(PaletteIconConfiguration& configuration) const; template void AddAttributeOverride(Styling::Attribute attribute, const Value& defaultValue = Value()) @@ -170,23 +97,6 @@ namespace GraphCanvas m_attributeOverride[attribute] = QVariant(defaultValue); } - void RemoveAttributeOverride(Styling::Attribute attribute) - { - m_attributeOverride.erase(attribute); - } - - bool HasAttribute(Styling::Attribute attribute) const - { - bool hasAttribute = (m_attributeOverride.find(attribute) != m_attributeOverride.end()); - - if (!hasAttribute) - { - StyleRequestBus::EventResult(hasAttribute, m_style, &StyleRequests::HasAttribute, static_cast(attribute)); - } - - return hasAttribute; - } - template Value GetAttribute(Styling::Attribute attribute, const Value& defaultValue = Value()) const { @@ -202,7 +112,7 @@ namespace GraphCanvas { bool hasAttribute = false; auto rawAttribute = static_cast(attribute); - + StyleRequestBus::EventResult(hasAttribute, m_style, &StyleRequests::HasAttribute, rawAttribute); if (hasAttribute) @@ -217,323 +127,11 @@ namespace GraphCanvas return retVal; } - QColor GetColor(Styling::Attribute color, QColor defaultValue = QColor()) const - { - return GetAttribute(color, defaultValue); - } - - QFont GetFont() const - { - QFont font; - QFontInfo info(font); - info.pixelSize(); - - font.setFamily(GetAttribute(Attribute::FontFamily, font.family())); - font.setPixelSize(GetAttribute(Attribute::FontSize, info.pixelSize())); - font.setWeight(GetAttribute(Attribute::FontWeight, font.weight())); - font.setStyle(GetAttribute(Attribute::FontStyle, font.style())); - font.setCapitalization(GetAttribute(Attribute::FontVariant, font.capitalization())); - - return font; - } - - //! Helper method which constructs a stylesheet based on the calculated font style. - //! We need this too pass along to certain Qt widgets because we use our own custom style parsing system. - QString GetFontStyleSheet() const - { - QFont font = GetFont(); - QColor color = GetColor(Styling::Attribute::Color); - - QStringList fields; - - fields.push_back(QString("color: rgba(%1,%2,%3,%4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(color.alpha())); - - fields.push_back(QString("font-family: %1").arg(font.family())); - fields.push_back(QString("font-size: %1px").arg(font.pixelSize())); - - if (font.bold()) - { - fields.push_back("font-weight: bold"); - } - - switch (font.style()) - { - case QFont::StyleNormal: - break; - case QFont::StyleItalic: - fields.push_back("font-style: italic"); - break; - case QFont::StyleOblique: - fields.push_back("font-style: italic"); - break; - } - - const bool underline = font.underline(); - const bool strikeOut = font.strikeOut(); - - if (underline && strikeOut) - { - fields.push_back("text-decoration: underline line-through"); - } - else if (underline) - { - fields.push_back("text-decoration: underline"); - } - else if (strikeOut) - { - fields.push_back("text-decoration: line-through"); - } - - return fields.join("; "); - } - - QPen GetPen(Styling::Attribute width, Styling::Attribute style, Styling::Attribute color, Styling::Attribute cap, bool cosmetic = false) const - { - QPen pen; - pen.setColor(GetAttribute(color, QColor(Qt::black))); - pen.setWidth(GetAttribute(width, 1)); - pen.setStyle(GetAttribute(style, Qt::SolidLine)); - pen.setCapStyle(GetAttribute(cap, Qt::SquareCap)); - pen.setCosmetic(cosmetic); - - return pen; - } - - QPen GetBorder() const - { - return GetPen(Styling::Attribute::BorderWidth, Styling::Attribute::BorderStyle, Styling::Attribute::BorderColor, Styling::Attribute::CapStyle); - } - - QBrush GetBrush(Styling::Attribute color, QBrush defaultValue = QBrush()) const - { - return GetAttribute(color, defaultValue); - } - - QSizeF GetSize(QSizeF defaultSize) const - { - return{ - GetAttribute(Styling::Attribute::Width, defaultSize.width()), - GetAttribute(Styling::Attribute::Height, defaultSize.height()) - }; - } - - QSizeF GetMinimumSize(QSizeF defaultSize = QSizeF(0,0)) const - { - return QSizeF(GetAttribute(Styling::Attribute::MinWidth, defaultSize.width()), GetAttribute(Styling::Attribute::MinHeight, defaultSize.height())); - } - - QSizeF GetMaximumSize(QSizeF defaultSize = QSizeF(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)) const - { - return QSizeF(GetAttribute(Styling::Attribute::MaxWidth, defaultSize.width()), GetAttribute(Styling::Attribute::MaxHeight, defaultSize.height())); - } - - QMarginsF GetMargins(QMarginsF defaultMargins = QMarginsF()) const - { - bool hasMargin = false; - StyleRequestBus::EventResult(hasMargin, m_style, &StyleRequests::HasAttribute, static_cast(Styling::Attribute::Margin)); - - if (hasMargin) - { - qreal defaultMargin = GetAttribute(Styling::Attribute::Margin, 0); - defaultMargins = QMarginsF(defaultMargin, defaultMargin, defaultMargin, defaultMargin); - } - - return QMarginsF( - GetAttribute(Styling::Attribute::Margin/*TODO Left*/, defaultMargins.left()), - GetAttribute(Styling::Attribute::Margin/*TODO Top*/, defaultMargins.top()), - GetAttribute(Styling::Attribute::Margin/*TODO Right*/, defaultMargins.right()), - GetAttribute(Styling::Attribute::Margin/*TODO Bottom*/, defaultMargins.bottom()) - ); - } - - bool HasTextAlignment() const - { - return HasAttribute(Styling::Attribute::TextAlignment) || HasAttribute(Styling::Attribute::TextVerticalAlignment); - } - - Qt::Alignment GetTextAlignment(Qt::Alignment defaultAlignment) const - { - bool horizontalAlignment = HasAttribute(Styling::Attribute::TextAlignment); - bool verticalAlignment = HasAttribute(Styling::Attribute::TextVerticalAlignment); - - if (horizontalAlignment || verticalAlignment) - { - Qt::Alignment alignment = GetAttribute(Styling::Attribute::TextAlignment, Qt::AlignmentFlag::AlignLeft); - alignment = alignment | GetAttribute(Styling::Attribute::TextVerticalAlignment, Qt::AlignmentFlag::AlignTop); - - return alignment; - } - - return defaultAlignment; - } - - void AddSelector(const AZStd::string_view& selector) - { - auto insertResult = m_styleSelectors.insert(AZStd::string(selector)); - - if (insertResult.second && m_styledEntity.IsValid()) - { - StyledEntityRequestBus::Event(m_styledEntity, &StyledEntityRequests::AddSelectorState, selector.data()); - - UpdateStyle(); - } - } - - void RemoveSelector(const AZStd::string_view& selector) - { - AZStd::size_t elements = m_styleSelectors.erase(selector); - - if (elements > 0) - { - StyledEntityRequestBus::Event(m_styledEntity, &StyledEntityRequests::RemoveSelectorState, selector.data()); - - UpdateStyle(); - } - } - - CandyStripeConfiguration GetCandyStripeConfiguration() const - { - CandyStripeConfiguration config; - - config.m_initialOffset = GetAttribute(Styling::Attribute::StripeOffset, 0); - config.m_maximumSize = GetAttribute(Styling::Attribute::MaximumStripeSize, 10); - - if (config.m_maximumSize <= 0) - { - config.m_maximumSize = 1; - } - - config.m_minStripes = GetAttribute(Styling::Attribute::MinimumStripes, 2); - - if (config.m_minStripes <= 0) - { - config.m_minStripes = 1; - } - - config.m_stripeAngle = GetAttribute(Styling::Attribute::StripeAngle, 60); - - if (config.m_stripeAngle > 90) - { - config.m_stripeAngle = 89; - } - else if (config.m_stripeAngle < -90) - { - config.m_stripeAngle = -89; - } - - if (!HasAttribute(Styling::Attribute::StripeColor)) - { - QColor backgroundColor = GetAttribute(Styling::Attribute::BackgroundColor, QColor(0,0,0)); - - config.m_stripeColor = backgroundColor.darker(); - - int totalDifference = 0; - - totalDifference += backgroundColor.red() - config.m_stripeColor.red(); - totalDifference += backgroundColor.green() - config.m_stripeColor.green(); - totalDifference += backgroundColor.blue() - config.m_stripeColor.blue(); - - if (totalDifference < 150) - { - config.m_stripeColor = backgroundColor.lighter(); - } - } - else - { - config.m_stripeColor = GetAttribute(Styling::Attribute::StripeColor, QColor(0, 0, 0)); - } - - return config; - } - - PatternedFillGenerator GetPatternedFillGenerator() const - { - PatternedFillGenerator generator; - generator.m_editorId = m_editorId; - - generator.m_id = GetAttribute(Styling::Attribute::PatternTemplate, QString()).toUtf8().data(); - - if (HasAttribute(Styling::Attribute::PatternPalettes)) - { - AZStd::string paletteStrings = GetAttribute(Styling::Attribute::PatternPalettes, QString()).toUtf8().data(); - - AzFramework::StringFunc::Tokenize(paletteStrings.c_str(), generator.m_palettes, ','); - } - else - { - QColor backgroundColor = GetAttribute(Styling::Attribute::BackgroundColor, QColor(0, 0, 0)); - - QColor patternColor = backgroundColor.darker(); - - int totalDifference = 0; - - totalDifference += backgroundColor.red() - patternColor.red(); - totalDifference += backgroundColor.green() - patternColor.green(); - totalDifference += backgroundColor.blue() - patternColor.blue(); - - if (totalDifference < 150) - { - patternColor = backgroundColor.lighter(); - } - - generator.m_colors.push_back(patternColor); - } - - generator.m_configuration = GetPatternFillConfiguration(); - - return generator; - } - - PatternFillConfiguration GetPatternFillConfiguration() const - { - PatternFillConfiguration configuration; - - configuration.m_minimumTileRepetitions = GetAttribute(Styling::Attribute::MinimumRepetitions, 1); - configuration.m_evenRowOffsetPercent = GetAttribute(Styling::Attribute::EvenOffsetPercent, 0.0f); - configuration.m_oddRowOffsetPercent = GetAttribute(Styling::Attribute::OddOffsetPercent, 0.0f); - - return configuration; - } - - void PopulatePaletteConfiguration(PaletteIconConfiguration& configuration) const - { - AZStd::string stylePalette; - StyledEntityRequestBus::EventResult(stylePalette, m_styledEntity, &StyledEntityRequests::GetFullStyleElement); - - if (!stylePalette.empty()) - { - configuration.SetColorPalette(stylePalette); - } - } - private: - void UpdateStyle() - { - ReleaseStyle(false); - StyleManagerRequestBus::EventResult(m_style, m_editorId, &StyleManagerRequests::ResolveStyles, m_styledEntity); - } - - void ReleaseStyle(bool destroyChildElement = true) - { - if (m_style.IsValid()) - { - if (m_deleteStyledEntity && destroyChildElement) - { - m_deleteStyledEntity = false; - AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationRequests::DeleteEntity, m_styledEntity); - } - AZ::ComponentApplicationBus::Broadcast(&AZ::ComponentApplicationRequests::DeleteEntity, m_style); - - m_style.SetInvalid(); - } - } - - void RegisterStyleSheetBus(const EditorId& editorId) - { - StyleManagerNotificationBus::Handler::BusDisconnect(); - StyleManagerNotificationBus::Handler::BusConnect(editorId); - } + void UpdateStyle(); + void ReleaseStyle(bool destroyChildElement = true); + void RegisterStyleSheetBus(const EditorId& editorId); EditorId m_editorId; AZ::EntityId m_scene; diff --git a/Gems/GraphCanvas/Code/graphcanvas_staticlib_files.cmake b/Gems/GraphCanvas/Code/graphcanvas_staticlib_files.cmake index 58a28484f7..bedc6329d5 100644 --- a/Gems/GraphCanvas/Code/graphcanvas_staticlib_files.cmake +++ b/Gems/GraphCanvas/Code/graphcanvas_staticlib_files.cmake @@ -91,6 +91,7 @@ set(FILES StaticLib/GraphCanvas/Styling/Style.cpp StaticLib/GraphCanvas/Styling/Style.h StaticLib/GraphCanvas/Styling/StyleHelper.h + StaticLib/GraphCanvas/Styling/StyleHelper.cpp StaticLib/GraphCanvas/Styling/StyleManager.cpp StaticLib/GraphCanvas/Styling/StyleManager.h StaticLib/GraphCanvas/Types/ComponentSaveDataInterface.h diff --git a/Gems/ScriptCanvas/Code/Editor/View/Dialogs/ContainerWizard/ContainerWizard.cpp b/Gems/ScriptCanvas/Code/Editor/View/Dialogs/ContainerWizard/ContainerWizard.cpp index 940a2626f5..259efef392 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Dialogs/ContainerWizard/ContainerWizard.cpp +++ b/Gems/ScriptCanvas/Code/Editor/View/Dialogs/ContainerWizard/ContainerWizard.cpp @@ -226,7 +226,6 @@ namespace ScriptCanvasEditor auto dataTypeIter = m_containerDataTypeSets.find(workingCrc); if (dataTypeIter == m_containerDataTypeSets.end()) { - // No idea wtf do here we've managed to put ourselves into an invalid state AZ_Error("ScriptCanvas", false, "Unknown partial type found in Container Creation. Aborting."); close(); break; diff --git a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.ui b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.ui index 15998bd83b..b5965c9746 100644 --- a/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.ui +++ b/Gems/ScriptCanvas/Code/Editor/View/Windows/Tools/UpgradeTool/UpgradeHelper.ui @@ -184,8 +184,5 @@ - - - From 1cb26a31f8d51087ae586b356e6a3de72e6e1487 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 12 Oct 2021 15:53:38 -0700 Subject: [PATCH 131/169] LYN-7195 + LYN-7185 + LYN-5301 | Hide viewport helpers for entities out of focus + selection shortcut adjustments (#4615) * Light refactoring of selection logic. Only draw helpers for selectable entities according to Editor Focus Mode and Container Entity systems. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * When Escape is pressed, clear the Prefab Focus. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Alter Ctrl+A and Ctrl+Shift+I to take editor focus mode and container entity behaviors into account. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Remove redundant comments and reduce footprint of tests. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Introduce loop protection, as GetParentId is known to loop in some situations possibly causing timeouts. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../ContainerEntityInterface.h | 3 ++ .../ContainerEntitySystemComponent.cpp | 45 +++++++++++++++++++ .../ContainerEntitySystemComponent.h | 1 + .../Entity/EditorEntityHelpers.cpp | 35 +++++++++++++-- .../UI/Prefab/PrefabIntegrationManager.cpp | 7 +++ .../UI/Prefab/PrefabIntegrationManager.h | 12 +++-- .../ViewportSelection/EditorHelpers.cpp | 27 +++++++++-- .../ViewportSelection/EditorHelpers.h | 12 +++++ 8 files changed, 130 insertions(+), 12 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h index 95940e6dd6..2d7d9dc511 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntityInterface.h @@ -65,6 +65,9 @@ namespace AzToolsFramework //! @return An error message if any container was registered for the context, success otherwise. virtual ContainerEntityOperationResult Clear(AzFramework::EntityContextId entityContextId) = 0; + //! Returns true if one of the ancestors of entityId is a closed container entity. + virtual bool IsUnderClosedContainerEntity(AZ::EntityId entityId) const = 0; + }; } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.cpp index c5649c56df..61b257a189 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.cpp @@ -102,8 +102,17 @@ namespace AzToolsFramework AZ::EntityId ContainerEntitySystemComponent::FindHighestSelectableEntity(AZ::EntityId entityId) const { + if (!entityId.IsValid()) + { + return entityId; + } + + // Return the highest closed container, or the entity if none is found. AZ::EntityId highestSelectableEntityId = entityId; + // Skip the queried entity, as we only want to check its ancestors. + AZ::TransformBus::EventResult(entityId, entityId, &AZ::TransformBus::Events::GetParentId); + // Go up the hierarchy until you hit the root while (entityId.IsValid()) { @@ -152,4 +161,40 @@ namespace AzToolsFramework return AZ::Success(); } + bool ContainerEntitySystemComponent::IsUnderClosedContainerEntity(AZ::EntityId entityId) const + { + if (!entityId.IsValid()) + { + return false; + } + + // Skip the queried entity, as we only want to check its ancestors. + AZ::TransformBus::EventResult(entityId, entityId, &AZ::TransformBus::Events::GetParentId); + + // Go up the hierarchy until you hit the root. + while (entityId.IsValid()) + { + if (!IsContainerOpen(entityId)) + { + // One of the ancestors is a container and it's closed. + return true; + } + + AZ::EntityId parentId; + AZ::TransformBus::EventResult(parentId, entityId, &AZ::TransformBus::Events::GetParentId); + + if (parentId == entityId) + { + // In some circumstances, querying a root level entity with GetParentId will return + // the entity itself instead of an invalid entityId. + break; + } + + entityId = parentId; + } + + // All ancestors are either regular entities or open containers. + return false; + } + } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h index 44261979ef..7a11e05096 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ContainerEntity/ContainerEntitySystemComponent.h @@ -48,6 +48,7 @@ namespace AzToolsFramework bool IsContainerOpen(AZ::EntityId entityId) const override; AZ::EntityId FindHighestSelectableEntity(AZ::EntityId entityId) const override; ContainerEntityOperationResult Clear(AzFramework::EntityContextId entityContextId) override; + bool IsUnderClosedContainerEntity(AZ::EntityId entityId) const override; // EditorEntityContextNotificationBus overrides ... void OnEntityStreamLoadSuccess() override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp index 7789070209..8d40162f52 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Entity/EditorEntityHelpers.cpp @@ -16,9 +16,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -588,15 +590,40 @@ namespace AzToolsFramework { AZ_PROFILE_FUNCTION(AzToolsFramework); + // Detect if the Entity is Visible bool visible = false; EditorEntityInfoRequestBus::EventResult( visible, entityId, &EditorEntityInfoRequestBus::Events::IsVisible); - bool locked = false; - EditorEntityInfoRequestBus::EventResult( - locked, entityId, &EditorEntityInfoRequestBus::Events::IsLocked); + if (!visible) + { + return false; + } - return visible && !locked; + // Detect if the Entity is Locked + bool locked = false; + EditorEntityInfoRequestBus::EventResult(locked, entityId, &EditorEntityInfoRequestBus::Events::IsLocked); + + if (locked) + { + return false; + } + + // Detect if the Entity is part of the Editor Focus + if (auto focusModeInterface = AZ::Interface::Get(); + !focusModeInterface->IsInFocusSubTree(entityId)) + { + return false; + } + + // Detect if the Entity is a descendant of a closed container + if (auto containerEntityInterface = AZ::Interface::Get(); + containerEntityInterface->IsUnderClosedContainerEntity(entityId)) + { + return false; + } + + return true; } static void SetEntityLockStateRecursively( diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index d4b227c4ff..9bd377e3e9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -137,6 +137,7 @@ namespace AzToolsFramework } EditorContextMenuBus::Handler::BusConnect(); + EditorEventsBus::Handler::BusConnect(); PrefabInstanceContainerNotificationBus::Handler::BusConnect(); AZ::Interface::Register(this); AssetBrowser::AssetBrowserSourceDropBus::Handler::BusConnect(s_prefabFileExtension); @@ -147,6 +148,7 @@ namespace AzToolsFramework AssetBrowser::AssetBrowserSourceDropBus::Handler::BusDisconnect(); AZ::Interface::Unregister(this); PrefabInstanceContainerNotificationBus::Handler::BusDisconnect(); + EditorEventsBus::Handler::BusDisconnect(); EditorContextMenuBus::Handler::BusDisconnect(); } @@ -313,6 +315,11 @@ namespace AzToolsFramework } } + void PrefabIntegrationManager::OnEscape() + { + s_prefabFocusInterface->FocusOnOwningPrefab(AZ::EntityId()); + } + void PrefabIntegrationManager::HandleSourceFileType(AZStd::string_view sourceFilePath, AZ::EntityId parentId, AZ::Vector3 position) const { auto instantiatePrefabOutcome = s_prefabPublicInterface->InstantiatePrefab(sourceFilePath, parentId, position); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h index 696c05991c..6788af31e9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h @@ -51,6 +51,7 @@ namespace AzToolsFramework class PrefabIntegrationManager final : public EditorContextMenuBus::Handler + , public EditorEventsBus::Handler , public AssetBrowser::AssetBrowserSourceDropBus::Handler , public PrefabInstanceContainerNotificationBus::Handler , public PrefabIntegrationInterface @@ -64,19 +65,22 @@ namespace AzToolsFramework static void Reflect(AZ::ReflectContext* context); - // EditorContextMenuBus... + // EditorContextMenuBus overrides ... int GetMenuPosition() const override; AZStd::string GetMenuIdentifier() const override; void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override; - // EntityOutlinerSourceDropHandlingBus... + // EditorEventsBus overrides ... + void OnEscape(); + + // EntityOutlinerSourceDropHandlingBus overrides ... void HandleSourceFileType(AZStd::string_view sourceFilePath, AZ::EntityId parentId, AZ::Vector3 position) const override; - // PrefabInstanceContainerNotificationBus... + // PrefabInstanceContainerNotificationBus overrides ... void OnPrefabComponentActivate(AZ::EntityId entityId) override; void OnPrefabComponentDeactivate(AZ::EntityId entityId) override; - // PrefabIntegrationInterface... + // PrefabIntegrationInterface overrides ... AZ::EntityId CreateNewEntityAtPosition(const AZ::Vector3& position, AZ::EntityId parentId) override; int ExecuteClosePrefabDialog(TemplateId templateId) override; void ExecuteSavePrefabDialog(TemplateId templateId, bool useSaveAllPrefabsPreference) override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp index 3ce350287f..bb718d0dc9 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.cpp @@ -187,15 +187,14 @@ namespace AzToolsFramework } // Verify if the entity Id corresponds to an entity that is focused; if not, halt selection. - if (!m_focusModeInterface->IsInFocusSubTree(entityIdUnderCursor)) + if (!IsSelectableAccordingToFocusMode(entityIdUnderCursor)) { return AZ::EntityId(); } // Container Entity support - if the entity that is being selected is part of a closed container, // change the selection to the container instead. - ContainerEntityInterface* containerEntityInterface = AZ::Interface::Get(); - if (containerEntityInterface) + if (ContainerEntityInterface* containerEntityInterface = AZ::Interface::Get()) { return containerEntityInterface->FindHighestSelectableEntity(entityIdUnderCursor); } @@ -217,7 +216,7 @@ namespace AzToolsFramework { const AZ::EntityId entityId = m_entityDataCache->GetVisibleEntityId(entityCacheIndex); - if (!m_entityDataCache->IsVisibleEntityVisible(entityCacheIndex)) + if (!m_entityDataCache->IsVisibleEntityVisible(entityCacheIndex) || !IsSelectableInViewport(entityId)) { continue; } @@ -263,4 +262,24 @@ namespace AzToolsFramework } } } + + bool EditorHelpers::IsSelectableInViewport(AZ::EntityId entityId) + { + return IsSelectableAccordingToFocusMode(entityId) && IsSelectableAccordingToContainerEntities(entityId); + } + + bool EditorHelpers::IsSelectableAccordingToFocusMode(AZ::EntityId entityId) + { + return m_focusModeInterface->IsInFocusSubTree(entityId); + } + + bool EditorHelpers::IsSelectableAccordingToContainerEntities(AZ::EntityId entityId) + { + if (ContainerEntityInterface* containerEntityInterface = AZ::Interface::Get()) + { + return !containerEntityInterface->IsUnderClosedContainerEntity(entityId); + } + + return true; + } } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.h index a6a78a4e61..909a231635 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorHelpers.h @@ -58,7 +58,19 @@ namespace AzToolsFramework AzFramework::DebugDisplayRequests& debugDisplay, const AZStd::function& showIconCheck); + //! Returns whether the entityId can be selected in the viewport according + //! to the current Editor Focus Mode and Container Entity setup. + bool IsSelectableInViewport(AZ::EntityId entityId); + private: + //! Returns whether the entityId can be selected in the viewport according + //! to the current Editor Focus Mode setup. + bool IsSelectableAccordingToFocusMode(AZ::EntityId entityId); + + //! Returns whether the entityId can be selected in the viewport according + //! to the current Container Entityu setup. + bool IsSelectableAccordingToContainerEntities(AZ::EntityId entityId); + const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; //!< Entity Data queried by the EditorHelpers. const FocusModeInterface* m_focusModeInterface = nullptr; }; From ccd60513f1776231ba3dc1ed1fd512b3d29e972d Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Tue, 12 Oct 2021 18:34:55 -0700 Subject: [PATCH 132/169] Fix prefab close dialog Editor crash on Linux (#4623) Signed-off-by: Steve Pham --- .../AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index 9bd377e3e9..24cb71499e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -1400,7 +1400,7 @@ namespace AzToolsFramework AZStd::unique_ptr PrefabIntegrationManager::ConstructUnsavedPrefabsCard(TemplateId templateId) { - FlowLayout* unsavedPrefabsLayout = new FlowLayout(AzToolsFramework::GetActiveWindow()); + FlowLayout* unsavedPrefabsLayout = new FlowLayout(nullptr); AZStd::set dirtyTemplatePaths = s_prefabSystemComponentInterface->GetDirtyTemplatePaths(templateId); From 63da5847c105092ebe23d73aefbbfd4b4d1ea086 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Tue, 12 Oct 2021 20:15:29 -0700 Subject: [PATCH 133/169] chore: correct documentation and correct method return. - change return for IntersectSegmentTriangleCCW to bool - change return for IntersectSegmentTriangle to bool Signed-off-by: Michael Pollind --- .../AzCore/AzCore/Math/IntersectSegment.cpp | 24 +- .../AzCore/AzCore/Math/IntersectSegment.h | 238 +++++++++--------- 2 files changed, 130 insertions(+), 132 deletions(-) diff --git a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.cpp b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.cpp index 1bf1e41cb7..5d13acc34c 100644 --- a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.cpp +++ b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.cpp @@ -15,7 +15,7 @@ using namespace Intersect; // IntersectSegmentTriangleCCW // [10/21/2009] //========================================================================= -int Intersect::IntersectSegmentTriangleCCW( +bool Intersect::IntersectSegmentTriangleCCW( const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c, /*float &u, float &v, float &w,*/ Vector3& normal, float& t) { @@ -34,7 +34,7 @@ int Intersect::IntersectSegmentTriangleCCW( float d = qp.Dot(normal); if (d <= 0.0f) { - return 0; + return false; } // Compute intersection t value of pq with plane of triangle. A ray @@ -46,7 +46,7 @@ int Intersect::IntersectSegmentTriangleCCW( // range segment check t[0,1] (it this case [0,d]) if (t < 0.0f || t > d) { - return 0; + return false; } // Compute barycentric coordinate components and test if within bounds @@ -54,12 +54,12 @@ int Intersect::IntersectSegmentTriangleCCW( v = ac.Dot(e); if (v < 0.0f || v > d) { - return 0; + return false; } w = -ab.Dot(e); if (w < 0.0f || v + w > d) { - return 0; + return false; } // Segment/ray intersects triangle. Perform delayed division and @@ -72,14 +72,14 @@ int Intersect::IntersectSegmentTriangleCCW( normal.Normalize(); - return 1; + return true; } //========================================================================= // IntersectSegmentTriangle // [10/21/2009] //========================================================================= -int +bool Intersect::IntersectSegmentTriangle( const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c, /*float &u, float &v, float &w,*/ Vector3& normal, float& t) @@ -111,7 +111,7 @@ Intersect::IntersectSegmentTriangle( // so either have a parallel ray or our normal is flipped if (d >= -Constants::FloatEpsilon) { - return 0; // parallel + return false; // parallel } d = -d; e = ap.Cross(qp); @@ -125,19 +125,19 @@ Intersect::IntersectSegmentTriangle( // range segment check t[0,1] (it this case [0,d]) if (t < 0.0f || t > d) { - return 0; + return false; } // Compute barycentric coordinate components and test if within bounds v = ac.Dot(e); if (v < 0.0f || v > d) { - return 0; + return false; } w = -ab.Dot(e); if (w < 0.0f || v + w > d) { - return 0; + return false; } // Segment/ray intersects the triangle. Perform delayed division and @@ -150,7 +150,7 @@ Intersect::IntersectSegmentTriangle( normal.Normalize(); - return 1; + return true; } //========================================================================= diff --git a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h index 71c39fb53d..523069987f 100644 --- a/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h +++ b/Code/Framework/AzCore/AzCore/Math/IntersectSegment.h @@ -17,46 +17,45 @@ namespace AZ namespace Intersect { //! LineToPointDistanceTime computes the time of the shortest distance from point 'p' to segment (s1,s2). - //! To calculate the point of intersection: - //! P = s1 + u (s2 - s1) - //! @param s1 segment start point - //! @param s2 segment end point - //! @param p point to find the closest time to. - //! @return time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)] + //! To calculate the point of intersection: P = s1 + u (s2 - s1) + //! @param s1 Segment start point. + //! @param s2 Segment end point. + //! @param p Point to find the closest time to. + //! @return Time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)] float LineToPointDistanceTime(const Vector3& s1, const Vector3& s21, const Vector3& p); //! LineToPointDistance computes the closest point to 'p' from a segment (s1,s2). - //! @param s1 segment start point - //! @param s2 segment end point - //! @param p point to find the closest time to. - //! @param u time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)] - //! @return the closest point + //! @param s1 Segment start point + //! @param s2 Segment end point + //! @param p Point to find the closest time to. + //! @param u Time (on the segment) for the shortest distance from 'p' to (s1,s2) [0.0f (s1),1.0f (s2)] + //! @return The closest point Vector3 LineToPointDistance(const Vector3& s1, const Vector3& s2, const Vector3& p, float& u); //! Given segment pq and triangle abc (CCW), returns whether segment intersects //! triangle and if so, also returns the barycentric coordinates (u,v,w) //! of the intersection point. - //! @param p segment start point - //! @param q segment end point - //! @param a triangle point 1 - //! @param b triangle point 2 - //! @param c triangle point 3 - //! @param normal at the intersection point. - //! @param t time of intersection along the segment [0.0 (p), 1.0 (q)] - //! @return true if the segments intersects the triangle otherwise false - int IntersectSegmentTriangleCCW( + //! @param p Segment start point. + //! @param q Segment end point. + //! @param a Triangle point 1. + //! @param b Triangle point 2. + //! @param c Triangle point 3. + //! @param normal At the intersection point. + //! @param t Time of intersection along the segment [0.0 (p), 1.0 (q)]. + //! @return true if the segments intersects the triangle otherwise false. + bool IntersectSegmentTriangleCCW( const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c, Vector3& normal, float& t); //! Same as \ref IntersectSegmentTriangleCCW without respecting the triangle (a,b,c) vertex order (double sided). - //! @param p segment start point - //! @param q segment end point - //! @param a triangle point 1 - //! @param b triangle point 2 - //! @param c triangle point 3 - //! @param normal at the intersection point; - //! @param t time of intersection along the segment [0.0 (p), 1.0 (q)] - //! @return true if the segments intersects the triangle otherwise false - int IntersectSegmentTriangle( + //! @param p Segment start point. + //! @param q Segment end point. + //! @param a Triangle point 1. + //! @param b Triangle point 2. + //! @param c Triangle point 3. + //! @param normal At the intersection point. + //! @param t Time of intersection along the segment [0.0 (p), 1.0 (q)]. + //! @return True if the segments intersects the triangle otherwise false. + bool IntersectSegmentTriangle( const Vector3& p, const Vector3& q, const Vector3& a, const Vector3& b, const Vector3& c, Vector3& normal, float& t); //! Ray aabb intersection result types. @@ -69,14 +68,14 @@ namespace AZ //! Intersect ray R(t) = rayStart + t*d against AABB a. When intersecting, //! return intersection distance tmin and point q of intersection. - //! @param rayStart ray starting point - //! @param dir ray direction and length (dir = rayEnd - rayStart) + //! @param rayStart Ray starting point + //! @param dir Ray direction and length (dir = rayEnd - rayStart) //! @param dirRCP 1/dir (reciprocal direction - we cache this result very often so we don't need to compute it multiple times, //! otherwise just use dir.GetReciprocal()) //! @param aabb Axis aligned bounding box to intersect against - //! @param tStart time on ray of the first intersection [0,1] or 0 if the ray starts inside the aabb - check the return value - //! @param tEnd time of the of the second intersection [0,1] (it can be > 1 if intersects after the rayEnd) - //! @param startNormal normal at the start point. + //! @param tStart Time on ray of the first intersection [0,1] or 0 if the ray starts inside the aabb - check the return value + //! @param tEnd Time of the of the second intersection [0,1] (it can be > 1 if intersects after the rayEnd) + //! @param startNormal Normal at the start point. //! @return \ref RayAABBIsectTypes RayAABBIsectTypes IntersectRayAABB( const Vector3& rayStart, @@ -88,66 +87,66 @@ namespace AZ Vector3& startNormal); //! Intersect ray against AABB. - //! @param rayStart ray starting point. - //! @param dir ray reciprocal direction. + //! @param rayStart Ray starting point. + //! @param dir Ray reciprocal direction. //! @param aabb Axis aligned bounding box to intersect against. - //! @param start length on ray of the first intersection. - //! @param end length of the of the second intersection. + //! @param start Length on ray of the first intersection. + //! @param end Length of the of the second intersection. //! @return \ref RayAABBIsectTypes In this faster version than IntersectRayAABB we return only ISECT_RAY_AABB_NONE and //! ISECT_RAY_AABB_ISECT. You can check yourself for that case. RayAABBIsectTypes IntersectRayAABB2(const Vector3& rayStart, const Vector3& dirRCP, const Aabb& aabb, float& start, float& end); //! Clip a ray to an aabb. return true if ray was clipped. The ray //! can be inside so don't use the result if the ray intersect the box. - //! @param aabb bounds - //! @param rayStart the start of the ray - //! @param rayEnd the end of the ray - //! @param[out] tClipStart The proportion where the ray enterts the aabb - //! @param[out] tClipEnd The proportion where the ray exits the aabb - //! @return true ray was clipped else false + //! @param aabb Bounds to test against. + //! @param rayStart The start of the ray. + //! @param rayEnd The end of the ray. + //! @param[out] tClipStart The proportion where the ray enters the \ref Aabb. + //! @param[out] tClipEnd The proportion where the ray exits the \ref Aabb. + //! @return True if the ray was clipped, otherwise false. bool ClipRayWithAabb(const Aabb& aabb, Vector3& rayStart, Vector3& rayEnd, float& tClipStart, float& tClipEnd); //! Test segment and aabb where the segment is defined by midpoint //! midPoint = (p1-p0) * 0.5f and half vector halfVector = p1 - midPoint. //! the aabb is at the origin and defined by half extents only. - //! @param midPoint midpoint of a line segment - //! @param halfVector half vector of an aabb - //! @param aabbExtends the extends of a bounded box - //! @return true if the intersect, otherwise false. + //! @param midPoint Midpoint of a line segment. + //! @param halfVector Half vector of an aabb. + //! @param aabbExtends The extends of a bounded box. + //! @return True if the segment and AABB intersect, otherwise false bool TestSegmentAABBOrigin(const Vector3& midPoint, const Vector3& halfVector, const Vector3& aabbExtends); - //! Test if segment specified by points p0 and p1 intersects AABB. \ref TestSegmentAABBOrigin - //! @param p0 point 1 - //! @param p1 point 2 - //! @param aabb bounded box - //! @return true if the segment and AABB intersect, otherwise false. + //! Test if segment specified by points p0 and p1 intersects AABB. \ref TestSegmentAABBOrigin. + //! @param p0 Segment start point. + //! @param p1 Segment end point. + //! @param aabb Bounded box to test against. + //! @return True if the segment and AABB intersect, otherwise false. bool TestSegmentAABB(const Vector3& p0, const Vector3& p1, const Aabb& aabb); //! Ray sphere intersection result types. enum SphereIsectTypes : AZ::s32 { - ISECT_RAY_SPHERE_SA_INSIDE = -1, //!< the ray starts inside the cylinder - ISECT_RAY_SPHERE_NONE, //!< no intersection - ISECT_RAY_SPHERE_ISECT, //!< along the PQ segment + ISECT_RAY_SPHERE_SA_INSIDE = -1, //!< The ray starts inside the cylinder + ISECT_RAY_SPHERE_NONE, //!< No intersection + ISECT_RAY_SPHERE_ISECT, //!< Along the PQ segment }; //! IntersectRaySphereOrigin //! return time t>=0 but not limited, so if you check a segment make sure - //! t <= segmentLen - //! @param rayStart ray start point + //! t <= segmentLen. + //! @param rayStart ray start point. //! @param rayDirNormalized ray direction normalized. - //! @param shereRadius sphere radius + //! @param shereRadius Radius of sphere at origin. //! @param time of closest intersection [0,+INF] in relation to the normalized direction. - //! @return \ref SphereIsectTypes + //! @return \ref SphereIsectTypes. SphereIsectTypes IntersectRaySphereOrigin( const Vector3& rayStart, const Vector3& rayDirNormalized, const float sphereRadius, float& t); //! Intersect ray (rayStart,rayDirNormalized) and sphere (sphereCenter,sphereRadius) \ref IntersectRaySphereOrigin - //! @param rayStart the start of the ray - //! @param rayDirNormalized the direction of the ray normalized - //! @param sphereCenter the center of the sphere - //! @param sphereRadius radius of the sphere - //! @param[out] t coefficient in the ray's explicit equation from which an + //! @param rayStart The start of the ray. + //! @param rayDirNormalized The direction of the ray normalized. + //! @param sphereCenter The center of the sphere. + //! @param sphereRadius Radius of the sphere. + //! @param[out] t Coefficient in the ray's explicit equation from which an //! intersecting point is calculated as "rayOrigin + t1 * rayDir". //! @return SphereIsectTypes SphereIsectTypes IntersectRaySphere( @@ -156,12 +155,12 @@ namespace AZ //! Intersect ray (rayStarty, rayDirNormalized) and disk (center, radius, normal) //! @param rayOrigin The origin of the ray to test. //! @param rayDir The direction of the ray to test. It has to be unit length. - //! @param diskCenter Center point of the disk - //! @param diskRadius Radius of the disk - //! @param diskNormal A normal perpendicular to the disk + //! @param diskCenter Center point of the disk. + //! @param diskRadius Radius of the disk. + //! @param diskNormal A normal perpendicular to the disk. //! @param[out] t If returning 1 (indicating a hit), this contains distance from rayOrigin along the normalized rayDir //! that the hit occured at. - //! @return false if not interesecting and true if intersecting + //! @return False if not interesecting and true if intersecting bool IntersectRayDisk( const Vector3& rayOrigin, const Vector3& rayDir, @@ -215,7 +214,7 @@ namespace AZ //! @param planePos A point on the plane to test intersection with. //! @param planeNormal The normal of the plane to test intersection with. //! @param[out] t The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection". - //! @return The number of intersection point. + //! @return The number of intersection point. int IntersectRayPlane( const Vector3& rayOrigin, const Vector3& rayDir, const Vector3& planePos, const Vector3& planeNormal, float& t); @@ -230,7 +229,7 @@ namespace AZ //! @param vertexD One of the four points that define the quadrilateral. //! @param[out] t The coefficient in the ray's explicit equation from which the //! intersecting point is calculated as "rayOrigin + t * rayDirection". - //! @return The number of intersection point. + //! @return The number of intersection point. int IntersectRayQuad( const Vector3& rayOrigin, const Vector3& rayDir, @@ -269,7 +268,7 @@ namespace AZ //! @param rayDir The direction of the ray to test intersection with. //! @param obb The OBB to test for intersection with the ray. //! @param[out] t The coefficient in the ray's explicit equation from which the intersecting point is calculated as "rayOrigin + t * rayDirection". - //! @return true if there is an intersection, false otherwise. + //! @return True if there is an intersection, false otherwise. bool IntersectRayObb(const Vector3& rayOrigin, const Vector3& rayDir, const Obb& obb, float& t); //! Ray cylinder intersection types. @@ -284,13 +283,12 @@ namespace AZ //! Reference: Real-Time Collision Detection - 5.3.7 Intersecting Ray or Segment Against Cylinder //! Intersect segment S(t)=sa+t(dir), 0<=t<=1 against cylinder specified by p, q and r. - //! - //! @param sa point - //! @param dir magnitude along sa - //! @param p center point of side 1 cylinder - //! @param q center point of side 2 cylinder - //! @param r radius of cylinder - //! @param[out] t proporition along line segment + //! @param sa The initial point. + //! @param dir Magnitude and direction for sa. + //! @param p Center point of side 1 cylinder. + //! @param q Center point of side 2 cylinder. + //! @param r Radius of cylinder. + //! @param[out] t Proporition along line segment. //! @return CylinderIsectTypes CylinderIsectTypes IntersectSegmentCylinder( const Vector3& sa, const Vector3& dir, const Vector3& p, const Vector3& q, const float r, float& t); @@ -298,22 +296,22 @@ namespace AZ //! Capsule ray intersect types. enum CapsuleIsectTypes { - ISECT_RAY_CAPSULE_SA_INSIDE = -1, //!< the ray starts inside the cylinder - ISECT_RAY_CAPSULE_NONE, //!< no intersection - ISECT_RAY_CAPSULE_PQ, //!< along the PQ segment - ISECT_RAY_CAPSULE_P_SIDE, //!< on the P side - ISECT_RAY_CAPSULE_Q_SIDE, //!< on the Q side + ISECT_RAY_CAPSULE_SA_INSIDE = -1, //!< The ray starts inside the cylinder + ISECT_RAY_CAPSULE_NONE, //!< No intersection + ISECT_RAY_CAPSULE_PQ, //!< Along the PQ segment + ISECT_RAY_CAPSULE_P_SIDE, //!< On the P side + ISECT_RAY_CAPSULE_Q_SIDE, //!< On the Q side }; //! This is a quick implementation of segment capsule based on segment cylinder \ref IntersectSegmentCylinder //! segment sphere intersection. We can optimize it a lot once we fix the ray //! cylinder intersection. - //! @param sa the beginning of the line segment - //! @param dir the direction and length of the segment - //! @param p center point of side 1 capsule - //! @param q center point of side 1 capsule - //! @param r the radius of the capsule - //! @param[out] t proporition along line segment + //! @param sa The beginning of the line segment. + //! @param dir The direction and length of the segment. + //! @param p Center point of side 1 capsule. + //! @param q Center point of side 1 capsule. + //! @param r The radius of the capsule. + //! @param[out] t Proporition along line segment. //! @return CapsuleIsectTypes CapsuleIsectTypes IntersectSegmentCapsule( const Vector3& sa, const Vector3& dir, const Vector3& p, const Vector3& q, const float r, float& t); @@ -321,15 +319,15 @@ namespace AZ //! Intersect segment S(t)=A+t(B-A), 0<=t<=1 against convex polyhedron specified //! by the n halfspaces defined by the planes p[]. On exit tfirst and tlast //! define the intersection, if any. - //! @param sa the beggining of the line segment - //! @param dir the direction and length of the segment - //! @param p planes that compose a convex ponvex polyhedron - //! @param numPlanes number of planes - //! @param[out] tfirst proportion along the line segment where the line enters - //! @param[out] tlast proportion along the line segment where the line exits - //! @param[out] iFirstPlane the plane where the line enters - //! @param[out] iLastPlane the plane where the line exits - //! @return true if intersects else false + //! @param sa The beggining of the line segment. + //! @param dir The direction and length of the segment. + //! @param p Planes that compose a convex ponvex polyhedron. + //! @param numPlanes number of planes. + //! @param[out] tfirst Proportion along the line segment where the line enters. + //! @param[out] tlast Proportion along the line segment where the line exits. + //! @param[out] iFirstPlane The plane where the line enters. + //! @param[out] iLastPlane The plane where the line exits. + //! @return True if intersects else false. bool IntersectSegmentPolyhedron( const Vector3& sa, const Vector3& dir, @@ -345,15 +343,15 @@ namespace AZ //! segment2Proportion where closestPointSegment1 = segment1Start + (segment1Proportion * (segment1End - segment1Start)) //! closestPointSegment2 = segment2Start + (segment2Proportion * (segment2End - segment2Start)) //! If segments are parallel returns a solution. - //! @param segment1Start start of segment 1. - //! @param segment1End end of segment 1. - //! @param segment2Start start of segment 2. - //! @param segment2End end of segment 2. - //! @param[out] segment1Proportion the proporition along segment 1 [0..1] - //! @param[out] segment2Proportion the proporition along segment 2 [0..1] - //! @param[out] closestPointSegment1 closest point on segment 1. - //! @param[out] closestPointSegment2 closest point on segment 2. - //! @param epsilon the minimum square distance where a line segment can be treated as a single point. + //! @param segment1Start Start of segment 1. + //! @param segment1End End of segment 1. + //! @param segment2Start Start of segment 2. + //! @param segment2End End of segment 2. + //! @param[out] segment1Proportion The proporition along segment 1 [0..1] + //! @param[out] segment2Proportion The proporition along segment 2 [0..1] + //! @param[out] closestPointSegment1 Closest point on segment 1. + //! @param[out] closestPointSegment2 Closest point on segment 2. + //! @param epsilon The minimum square distance where a line segment can be treated as a single point. void ClosestSegmentSegment( const Vector3& segment1Start, const Vector3& segment1End, @@ -368,13 +366,13 @@ namespace AZ //! Calculate the line segment closestPointSegment1<->closestPointSegment2 that is the shortest route between //! two segments segment1Start<->segment1End and segment2Start<->segment2End. //! If segments are parallel returns a solution. - //! @param segment1Start start of segment 1. - //! @param segment1End end of segment 1. - //! @param segment2Start start of segment 2. - //! @param segment2End end of segment 2. - //! @param[out] closestPointSegment1 closest point on segment 1. - //! @param[out] closestPointSegment2 closest point on segment 2. - //! @param epsilon the minimum square distance where a line segment can be treated as a single point. + //! @param segment1Start Start of segment 1. + //! @param segment1End End of segment 1. + //! @param segment2Start Start of segment 2. + //! @param segment2End End of segment 2. + //! @param[out] closestPointSegment1 Closest point on segment 1. + //! @param[out] closestPointSegment2 Closest point on segment 2. + //! @param epsilon The minimum square distance where a line segment can be treated as a single point. void ClosestSegmentSegment( const Vector3& segment1Start, const Vector3& segment1End, @@ -387,11 +385,11 @@ namespace AZ //! Calculate the point (closestPointOnSegment) that is the closest point on //! segment segmentStart/segmentEnd to point. Also calculate the value of proportion where //! closestPointOnSegment = segmentStart + (proportion * (segmentEnd - segmentStart)) - //! @param point the point to test - //! @param segmentStart the start of the segment - //! @param segmentEnd the end of the segment - //! @param[out] proportion the proportion of the segment L(t) = (end - start) * t - //! @param[out] closestPointOnSegment the point along the line segment + //! @param point The point to test + //! @param segmentStart The start of the segment + //! @param segmentEnd The end of the segment + //! @param[out] proportion The proportion of the segment L(t) = (end - start) * t + //! @param[out] closestPointOnSegment The point along the line segment void ClosestPointSegment( const Vector3& point, const Vector3& segmentStart, From 2b79abb8c450fefa2932b4676d4b9fccf37156a1 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Wed, 13 Oct 2021 09:13:19 +0200 Subject: [PATCH 134/169] =?UTF-8?q?EMotion=20FX:=20A=20parameter=E2=80=99s?= =?UTF-8?q?=20text=20box=20of=20Blend=20Space=202D=20and=201D=20Motions=20?= =?UTF-8?q?only=20takes=20one=20numerical=20input=20value=20including=20fr?= =?UTF-8?q?actions=20(#4626)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The on value changed event was recevied too often - with every newly typed character. As we're updating elements outside of the value spinbox, we need to wait for the actual done editing signal. This can be achieved by not tracking the keyboard for the spinbox. Signed-off-by: Benjamin Jillich --- .../Editor/PropertyWidgets/BlendSpaceMotionContainerHandler.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/BlendSpaceMotionContainerHandler.cpp b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/BlendSpaceMotionContainerHandler.cpp index b534603be6..8cee46133e 100644 --- a/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/BlendSpaceMotionContainerHandler.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/PropertyWidgets/BlendSpaceMotionContainerHandler.cpp @@ -55,6 +55,7 @@ namespace EMotionFX m_spinboxX->setDecimals(4); m_spinboxX->setRange(-FLT_MAX, FLT_MAX); m_spinboxX->setProperty("motionId", motionId.c_str()); + m_spinboxX->setKeyboardTracking(false); layoutX->addWidget(m_spinboxX); layout->addLayout(layoutX, row, column); @@ -76,6 +77,7 @@ namespace EMotionFX m_spinboxY->setDecimals(4); m_spinboxY->setRange(-FLT_MAX, FLT_MAX); m_spinboxY->setProperty("motionId", motionId.c_str()); + m_spinboxX->setKeyboardTracking(false); layoutY->addWidget(m_spinboxY); layout->addLayout(layoutY, row, column); From da1fde8314e58641bcb21ca76987c29a754fc610 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Wed, 13 Oct 2021 09:57:15 +0200 Subject: [PATCH 135/169] ImGui histogram container improvements (#4630) * Added auto scale mode that uses a running average to expand and shrink the visible vertical range. * Added option to set the move direction and either push new values to the front of the buffer (left) and make the histogram move to the right or the inverse. * Changed the camera monitor to use auto scaling as well as the current one was not showing anything because of an outlier. * Pre-fill the histogram with zeros so that the first pushed sample moves in without horizontal scaling effects which made it hard to read out any information from the histogram. Signed-off-by: Benjamin Jillich --- .../Include/LYImGuiUtils/HistogramContainer.h | 40 +++++++-- .../LYCommonMenu/ImGuiLYCameraMonitor.cpp | 20 ++--- .../LYImGuiUtils/HistogramContainer.cpp | 90 ++++++++++++++++--- 3 files changed, 120 insertions(+), 30 deletions(-) diff --git a/Gems/ImGui/Code/Include/LYImGuiUtils/HistogramContainer.h b/Gems/ImGui/Code/Include/LYImGuiUtils/HistogramContainer.h index 101b123bb5..6129c3ec08 100644 --- a/Gems/ImGui/Code/Include/LYImGuiUtils/HistogramContainer.h +++ b/Gems/ImGui/Code/Include/LYImGuiUtils/HistogramContainer.h @@ -18,8 +18,7 @@ namespace ImGui namespace LYImGuiUtils { /** - * A small class to help manage values for an ImGui Histogram ( ImGui doesn't want to manage the values itself ). - * Nothing crazy, just helps reduce boiler plate if you are ImGui::PlotHistogram()'ing + * A small class to help manage values for an ImGui Histogram (ImGui is not managing values itself). */ class HistogramContainer { @@ -40,9 +39,24 @@ namespace ImGui // Static Type to String function static const char* ViewTypeToString(ViewType viewType); + //! Horizontal move direction of the histogram when pushing new values. + enum MoveDirection : AZ::u8 + { + PushLeftMoveRight = 0, //! Push new values to the front of the buffer, which corresponds to the left side, and make the histogram move to the right. + PushRightMoveLeft = 1, //! Push new values to the back of the buffer, which corresponds to the right side, and make the histogram move to the left. + }; + + //! Mode determining the min and max values for the visible range of the vertical axis for the histogram. + enum ScaleMode : AZ::u8 + { + NoAutoScale = 0, //! Use the min and max values given by Init() as visible range. + AutoExpand = 1, //! Expand scale in case a sample is out of the current bounds. Does only expand the scale but not decrease it back again. + AutoScale = 2, //! Use a running average to expand and shrink the visible range. + }; + // Do all of the set up via Init - void Init(const char* histogramName, int maxValueCountSize, ViewType viewType, bool displayOverlays, float minScale, float maxScale - , bool autoExpandScale, bool startCollapsed = false, bool drawMostRecentValue = true); + void Init(const char* histogramName, int maxValueCountSize, ViewType viewType, bool displayOverlays, float minScale, float maxScale, + ScaleMode scaleMode = AutoScale, bool startCollapsed = false, bool drawMostRecentValue = true); // How many values are in the container currently int GetSize() { return static_cast(m_values.size()); } @@ -50,9 +64,6 @@ namespace ImGui // What is the max size of the container int GetMaxSize() { return m_maxSize; } - // Set the Max Size and clear the container - void SetMaxSize(int size) { m_values.clear(); m_maxSize = size; } - // Push a value to this histogram container void PushValue(float val); @@ -65,7 +76,18 @@ namespace ImGui // Draw this histogram with ImGui void Draw(float histogramWidth, float histogramHeight); + //! Adjust the scale mode to determine the min and max values for the visible range of the vertical axis for the histogram. + void SetScaleMode(ScaleMode scaleMode) { m_scaleMode = scaleMode; } + + //! Adjust the horizontal move direction of the histogram when pushing new values. + void SetMoveDirection(MoveDirection moveDirection) { m_moveDirection = moveDirection; } + + //! Calculate the min and maximum values for the present samples. + void CalcMinMaxValues(float& outMin, float& outMax); + private: + // Set the Max Size and clear the container + void SetMaxSize(int size); AZStd::string m_histogramName; AZStd::deque m_values; @@ -73,8 +95,10 @@ namespace ImGui ViewType m_viewType = ViewType::Histogram; float m_minScale; float m_maxScale; + MoveDirection m_moveDirection = PushLeftMoveRight; //! Specify if values will be added on the left and the histogram moves right or the other way around. bool m_dispalyOverlays; - bool m_autoExpandScale; + ScaleMode m_scaleMode; //! Determines if the vertical range of the histogram will be manually specified, auto-expanded or automatically scaled based on the samples. + float m_autoScaleSpeed = 0.05f; //! Indicates how fast the min max values and the visible vertical range are adapting to new samples. bool m_collapsed; bool m_drawMostRecentValueText; }; diff --git a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCameraMonitor.cpp b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCameraMonitor.cpp index 1df74903e6..e079a01de1 100644 --- a/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCameraMonitor.cpp +++ b/Gems/ImGui/Code/Source/LYCommonMenu/ImGuiLYCameraMonitor.cpp @@ -34,13 +34,13 @@ namespace ImGui ImGuiCameraMonitorRequestBus::Handler::BusConnect(); // Init Histogram Containers - m_dofMinZHisto.Init( "DOF Min Z", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f, true); - m_dofMinZBlendMultHisto.Init( "DOF Min Z Blend Mult", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 50.0f, 50.0f, true); - m_dofMinZScaleHisto.Init( "DOF Min Z Scale", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 50.0f, 50.0f, true); + m_dofMinZHisto.Init( "DOF Min Z", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f); + m_dofMinZBlendMultHisto.Init( "DOF Min Z Blend Mult", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 50.0f, 50.0f); + m_dofMinZScaleHisto.Init( "DOF Min Z Scale", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 50.0f, 50.0f); - m_globalActiveCamInfo.m_fovHisto.Init( "FOV", 120, LYImGuiUtils::HistogramContainer::ViewType::Lines, true, 50.0f, 50.0f, true); - m_globalActiveCamInfo.m_facingVectorDeltaHisto.Init( "Facing Vec Frame Delta", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f, true); - m_globalActiveCamInfo.m_positionDeltaHisto.Init( "Position Frame Delta", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f, true); + m_globalActiveCamInfo.m_fovHisto.Init( "FOV", 120, LYImGuiUtils::HistogramContainer::ViewType::Lines, true, 50.0f, 50.0f); + m_globalActiveCamInfo.m_facingVectorDeltaHisto.Init( "Facing Vec Frame Delta", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f); + m_globalActiveCamInfo.m_positionDeltaHisto.Init( "Position Frame Delta", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f); } void ImGuiLYCameraMonitor::Shutdown() @@ -214,7 +214,7 @@ namespace ImGui } // save this cam off as the current one m_currentCamera = newCamId; - + // create a new empty CameraInfo in the queue m_cameraHistory.push_front(CameraInfo()); @@ -224,9 +224,9 @@ namespace ImGui AZ::ComponentApplicationBus::BroadcastResult(newCam.m_camName, &AZ::ComponentApplicationBus::Events::GetEntityName, m_currentCamera); newCam.m_activeTime = 0.0f; newCam.m_activeFrames = 0; - newCam.m_fovHisto.Init( "FOV", 120, LYImGuiUtils::HistogramContainer::ViewType::Lines, true, 50.0f, 50.0f, true); - newCam.m_facingVectorDeltaHisto.Init( "Facing Vec Frame Delta", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f, true); - newCam.m_positionDeltaHisto.Init( "Position Frame Delta", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f, true); + newCam.m_fovHisto.Init( "FOV", 120, LYImGuiUtils::HistogramContainer::ViewType::Lines, true, 50.0f, 50.0f); + newCam.m_facingVectorDeltaHisto.Init( "Facing Vec Frame Delta", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f); + newCam.m_positionDeltaHisto.Init( "Position Frame Delta", 120, LYImGuiUtils::HistogramContainer::ViewType::Histogram, true, 0.0f, 0.0f); // reset a few variables on the global camera info m_globalActiveCamInfo.m_camId = newCam.m_camId; diff --git a/Gems/ImGui/Code/Source/LYImGuiUtils/HistogramContainer.cpp b/Gems/ImGui/Code/Source/LYImGuiUtils/HistogramContainer.cpp index e3fd3f2054..1915cc3721 100644 --- a/Gems/ImGui/Code/Source/LYImGuiUtils/HistogramContainer.cpp +++ b/Gems/ImGui/Code/Source/LYImGuiUtils/HistogramContainer.cpp @@ -16,45 +16,92 @@ namespace ImGui { namespace LYImGuiUtils { - void HistogramContainer::Init(const char* histogramName, int maxValueCountSize, ViewType viewType, bool displayOverlays, float minScale, float maxScale - , bool autoExpandScale, bool startCollapsed/* = false*/, bool drawMostRecentValue/* = true*/) + void HistogramContainer::Init(const char* histogramName, int maxValueCountSize, ViewType viewType, bool displayOverlays, float minScale, float maxScale, + ScaleMode scaleMode, bool startCollapsed/* = false*/, bool drawMostRecentValue/* = true*/) { m_histogramName = histogramName; m_minScale = minScale; m_maxScale = maxScale; m_viewType = viewType; m_dispalyOverlays = displayOverlays; - m_autoExpandScale = autoExpandScale; + m_scaleMode = scaleMode; m_collapsed = startCollapsed; m_drawMostRecentValueText = drawMostRecentValue; SetMaxSize(maxValueCountSize); } - void HistogramContainer::PushValue(float val) + void HistogramContainer::SetMaxSize(int size) + { + m_values.resize(size); + m_maxSize = size; + + // Pre-fill the histogram with zeros so that the bars do not fill the space and + // scale horizontally when there are not enough samples yet. + for (float& value : m_values) + { + value = 0.0f; + } + } + + void HistogramContainer::PushValue(float value) { if (m_maxSize == 0) { return; } + if (m_values.size() == m_maxSize) { - m_values.pop_back(); + if (m_moveDirection == PushLeftMoveRight) + { + m_values.pop_back(); + } + else + { + m_values.pop_front(); + } } else if (m_values.size() > m_maxSize) { m_values.erase(m_values.begin() + (m_maxSize - 1), m_values.end()); } - m_values.push_front(val); - if (m_autoExpandScale) + if (m_moveDirection == PushLeftMoveRight) { - if (val < m_minScale) + m_values.push_front(value); + } + else + { + m_values.push_back(value); + } + + switch (m_scaleMode) + { + case AutoExpand: { - m_minScale = val; + if (value < m_minScale) + { + m_minScale = value; + } + else if (value > m_maxScale) + { + m_maxScale = value; + } + break; } - else if (val > m_maxScale) + case AutoScale: { - m_maxScale = val; + float min = 0.0f; + float max = 0.0f; + CalcMinMaxValues(min, max); + + m_minScale = AZ::Lerp(m_minScale, min, m_autoScaleSpeed); + m_maxScale = AZ::Lerp(m_maxScale, max, m_autoScaleSpeed); + break; + } + default: + { + break; } } } @@ -86,7 +133,6 @@ namespace ImGui ImGui::DragInt("History Size", &m_maxSize, 1, 1, 1000, "%f"); ImGui::DragFloat("Max Scale", &m_maxScale, 0.0001f, -100.0f, 100.0f); ImGui::DragFloat("Min Scale", &m_minScale, 0.0001f, -100.0f, 100.0f); - ImGui::Checkbox("Auto Expand Scale", &m_autoExpandScale); ImGui::EndPopup(); } @@ -157,6 +203,26 @@ namespace ImGui return "Lines"; } } + + void HistogramContainer::CalcMinMaxValues(float& outMin, float& outMax) + { + // Use the manually set min and max scale values in case there are no samples. + if (m_values.empty()) + { + outMin = m_minScale; + outMax = m_maxScale; + return; + } + + outMin = +AZ::Constants::FloatMax; + outMax = -AZ::Constants::FloatMax; + + for (const float x : m_values) + { + outMin = AZ::GetMin(outMin, x); + outMax = AZ::GetMax(outMax, x); + } + } } } #endif // #ifdef IMGUI_ENABLED From 48a74ca93d7df475a5ffbcfba45ad0fd95fa2604 Mon Sep 17 00:00:00 2001 From: hultonha <82228511+hultonha@users.noreply.github.com> Date: Wed, 13 Oct 2021 10:18:21 +0100 Subject: [PATCH 136/169] Remove clearFocus from EditorTransformComponentSelection duplicate Entity (#4571) * remove clearFocus from EditorTransformComponentSelection duplicate entity Signed-off-by: hultonha * remove extra unneeded calls to RequestWrite Signed-off-by: hultonha * update PrefabPublicHandler to use SetSelectedEntities Signed-off-by: hultonha --- .../Prefab/PrefabPublicHandler.cpp | 7 ++-- .../UI/PropertyEditor/PropertyIntCtrlCommon.h | 5 +-- .../UI/PropertyEditor/PropertyIntSpinCtrl.hxx | 5 --- .../EditorTransformComponentSelection.cpp | 41 ++++++++----------- 4 files changed, 23 insertions(+), 35 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp index 038f36eac9..b5f61b33bf 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabPublicHandler.cpp @@ -257,9 +257,10 @@ namespace AzToolsFramework // Select Container Entity { - auto selectionUndo = aznew SelectionCommand({ containerEntityId }, "Select Prefab Container Entity"); + const EntityIdList selectedEntities = EntityIdList{ containerEntityId }; + auto selectionUndo = aznew SelectionCommand(selectedEntities, "Select Prefab Container Entity"); selectionUndo->SetParent(undoBatch.GetUndoBatch()); - ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, selectionUndo); + ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::SetSelectedEntities, selectedEntities); } } @@ -1097,7 +1098,7 @@ namespace AzToolsFramework // Select the duplicated entities/instances auto selectionUndo = aznew SelectionCommand(duplicatedEntityAndInstanceIds, "Select Duplicated Entities/Instances"); selectionUndo->SetParent(undoBatch.GetUndoBatch()); - ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, selectionUndo); + ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::SetSelectedEntities, duplicatedEntityAndInstanceIds); } return AZ::Success(); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h index eda8b482a1..01675e0044 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntCtrlCommon.h @@ -38,7 +38,7 @@ namespace AzToolsFramework static bool UnsignedToolTip(QWidget* widget, QString& toolTipString); }; - //! Base class for integer widget handlers to provide functionality independant + //! Base class for integer widget handlers to provide functionality independent //! of widget type. //! @tparam ValueType The integer primitive type of the handler. //! @tparam PropertyControl The widget type of the handler. @@ -167,8 +167,7 @@ namespace AzToolsFramework PropertyControl* newCtrl = aznew PropertyControl(pParent); this->connect(newCtrl, &PropertyControl::valueChanged, this, [newCtrl]() { - EBUS_EVENT(PropertyEditorGUIMessages::Bus, RequestWrite, newCtrl); - AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&PropertyEditorGUIMessages::Bus::Handler::RequestWrite, newCtrl); + AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&PropertyEditorGUIMessages::Bus::Events::RequestWrite, newCtrl); }); // note: Qt automatically disconnects objects from each other when either end is destroyed, no need to worry about delete. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntSpinCtrl.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntSpinCtrl.hxx index 1e1e6a9592..fef4639a9f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntSpinCtrl.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyIntSpinCtrl.hxx @@ -98,11 +98,6 @@ namespace AzToolsFramework QWidget* IntSpinBoxHandler::CreateGUI(QWidget* parent) { PropertyIntSpinCtrl* newCtrl = static_cast(BaseHandler::CreateGUI(parent)); - this->connect(newCtrl, &PropertyIntSpinCtrl::valueChanged, [newCtrl]() - { - AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&PropertyEditorGUIMessages::Bus::Handler::RequestWrite, newCtrl); - }); - return newCtrl; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 7015a25ce1..6ee5c97636 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -1113,7 +1113,7 @@ namespace AzToolsFramework }); m_boxSelect.InstallLeftMouseUp( - [this, entityBoxSelectData]() + [this, entityBoxSelectData] { entityBoxSelectData->m_boxSelectSelectionCommand->UpdateSelection(EntityIdVectorFromContainer(m_selectedEntityIds)); @@ -2171,7 +2171,7 @@ namespace AzToolsFramework // lock selection AddAction( m_actions, { QKeySequence(Qt::Key_L) }, LockSelection, LockSelectionTitle, LockSelectionDesc, - [lockUnlock]() + [lockUnlock] { lockUnlock(true); }); @@ -2179,7 +2179,7 @@ namespace AzToolsFramework // unlock selection AddAction( m_actions, { QKeySequence(Qt::CTRL + Qt::Key_L) }, UnlockSelection, LockSelectionTitle, LockSelectionDesc, - [lockUnlock]() + [lockUnlock] { lockUnlock(false); }); @@ -2209,7 +2209,7 @@ namespace AzToolsFramework // hide selection AddAction( m_actions, { QKeySequence(Qt::Key_H) }, HideSelection, HideSelectionTitle, HideSelectionDesc, - [showHide]() + [showHide] { showHide(false); }); @@ -2217,7 +2217,7 @@ namespace AzToolsFramework // show selection AddAction( m_actions, { QKeySequence(Qt::CTRL + Qt::Key_H) }, ShowSelection, HideSelectionTitle, HideSelectionDesc, - [showHide]() + [showHide] { showHide(true); }); @@ -2225,7 +2225,7 @@ namespace AzToolsFramework // unlock all entities in the level/scene AddAction( m_actions, { QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_L) }, UnlockAll, UnlockAllTitle, UnlockAllDesc, - []() + [] { AZ_PROFILE_FUNCTION(AzToolsFramework); @@ -2242,14 +2242,14 @@ namespace AzToolsFramework // show all entities in the level/scene AddAction( m_actions, { QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_H) }, ShowAll, ShowAllTitle, ShowAllDesc, - []() + [] { AZ_PROFILE_FUNCTION(AzToolsFramework); ScopedUndoBatch undoBatch(ShowAllEntitiesUndoRedoDesc); EnumerateEditorEntities( - [](AZ::EntityId entityId) + [](const AZ::EntityId entityId) { ScopedUndoBatch::MarkEntityDirty(entityId); SetEntityVisibility(entityId, true); @@ -2259,7 +2259,7 @@ namespace AzToolsFramework // select all entities in the level/scene AddAction( m_actions, { QKeySequence(Qt::CTRL + Qt::Key_A) }, SelectAll, SelectAllTitle, SelectAllDesc, - [this]() + [this] { AZ_PROFILE_FUNCTION(AzToolsFramework); @@ -2299,7 +2299,7 @@ namespace AzToolsFramework // invert current selection AddAction( m_actions, { QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_I) }, InvertSelect, InvertSelectionTitle, InvertSelectionDesc, - [this]() + [this] { AZ_PROFILE_FUNCTION(AzToolsFramework); @@ -2346,17 +2346,10 @@ namespace AzToolsFramework // duplicate selection AddAction( m_actions, { QKeySequence(Qt::CTRL + Qt::Key_D) }, DuplicateSelect, DuplicateTitle, DuplicateDesc, - []() + [] { AZ_PROFILE_FUNCTION(AzToolsFramework); - // Clear Widget selection - Prevents issues caused by cloning entities while a property in the Reflected Property Editor - // is being edited. - if (QApplication::focusWidget()) - { - QApplication::focusWidget()->clearFocus(); - } - ScopedUndoBatch undoBatch(DuplicateUndoRedoDesc); auto selectionCommand = AZStd::make_unique(EntityIdList(), DuplicateUndoRedoDesc); selectionCommand->SetParent(undoBatch.GetUndoBatch()); @@ -2371,7 +2364,7 @@ namespace AzToolsFramework // delete selection AddAction( m_actions, { QKeySequence(Qt::Key_Delete) }, DeleteSelect, DeleteTitle, DeleteDesc, - [this]() + [this] { AZ_PROFILE_FUNCTION(AzToolsFramework); @@ -2388,21 +2381,21 @@ namespace AzToolsFramework AddAction( m_actions, { QKeySequence(Qt::Key_Space) }, EditEscaspe, "", "", - [this]() + [this] { DeselectEntities(); }); AddAction( m_actions, { QKeySequence(Qt::Key_P) }, EditPivot, TogglePivotTitleEditMenu, TogglePivotDesc, - [this]() + [this] { ToggleCenterPivotSelection(); }); AddAction( m_actions, { QKeySequence(Qt::Key_R) }, EditReset, ResetEntityTransformTitle, ResetEntityTransformDesc, - [this]() + [this] { switch (m_mode) { @@ -2427,7 +2420,7 @@ namespace AzToolsFramework AddAction( m_actions, { QKeySequence(Qt::Key_U) }, ViewportUiVisible, "Toggle Viewport UI", "Hide/Show Viewport UI", - [this]() + [this] { SetAllViewportUiVisible(!m_viewportUiVisible); }); @@ -3236,7 +3229,7 @@ namespace AzToolsFramework QAction* action = menu->addAction(QObject::tr(TogglePivotTitleRightClick)); QObject::connect( action, &QAction::triggered, action, - [this]() + [this] { ToggleCenterPivotSelection(); }); From 5bf7330f3505d4ac7837766317fa8ed7ab44ad96 Mon Sep 17 00:00:00 2001 From: amzn-sean <75276488+amzn-sean@users.noreply.github.com> Date: Wed, 13 Oct 2021 12:50:11 +0100 Subject: [PATCH 137/169] made some physX tests less flaky (#4632) Joints_BallLeadFollowerCollide - changed the idle_wait to a wait_for_condition of the lead and follower colliding with a 10 second timeout. It was a 2 second timeout which is on the edge of the time from start to collision (~1.5sec). Joints_HingeNoLimitsConstrained - now measures the angle the joint is at and waits for the follower to raise up and over the lead, or fail after a 10sec timeout. This use to 'catch' the follower joint in a force region and check the position of the follower to determine pass/fail. Signed-off-by: amzn-sean <75276488+amzn-sean@users.noreply.github.com> --- .../joints/Joints_BallLeadFollowerCollide.py | 14 +---- .../joints/Joints_HingeNoLimitsConstrained.py | 59 +++++++++++++++---- .../Joints_HingeNoLimitsConstrained.ly | 4 +- 3 files changed, 54 insertions(+), 23 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallLeadFollowerCollide.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallLeadFollowerCollide.py index 0e8d7ea255..1209cb6caf 100644 --- a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallLeadFollowerCollide.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_BallLeadFollowerCollide.py @@ -52,9 +52,6 @@ def Joints_BallLeadFollowerCollide(): from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper - import azlmbr.legacy.general as general - import azlmbr.bus - from JointsHelper import JointEntityCollisionAware # Helper Entity class - self.collided flag is set when instance receives collision event. @@ -75,17 +72,12 @@ def Joints_BallLeadFollowerCollide(): lead = Entity("lead") follower = Entity("follower") - # 4) Wait for several seconds - general.idle_wait(2.0) # wait for lead and follower to move + # 4) Wait for collision between lead and follower or timeout + Report.critical_result(Tests.check_collision_happened, helper.wait_for_condition(lambda: lead.collided and follower.collided, 10.0)) - # 5) Check to see if lead and follower behaved as expected - Report.critical_result(Tests.check_collision_happened, lead.collided and follower.collided) - - # 6) Exit Game Mode + # 5) Exit Game Mode helper.exit_game_mode(Tests.exit_game_mode) - - if __name__ == "__main__": from editor_python_test_tools.utils import Report Report.start_test(Joints_BallLeadFollowerCollide) diff --git a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeNoLimitsConstrained.py b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeNoLimitsConstrained.py index 0870a807fc..0b3f88b4f6 100644 --- a/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeNoLimitsConstrained.py +++ b/AutomatedTesting/Gem/PythonTests/Physics/tests/joints/Joints_HingeNoLimitsConstrained.py @@ -52,11 +52,13 @@ def Joints_HingeNoLimitsConstrained(): """ import os import sys + import math from editor_python_test_tools.utils import Report from editor_python_test_tools.utils import TestHelper as helper import azlmbr.legacy.general as general import azlmbr.bus + import azlmbr.math as azmath import JointsHelper from JointsHelper import JointEntity @@ -84,28 +86,65 @@ def Joints_HingeNoLimitsConstrained(): Report.info_vector3(lead.position, "lead initial position:") Report.info_vector3(follower.position, "follower initial position:") leadInitialPosition = lead.position - followerInitialPosition = follower.position - # 4) Wait for several seconds - general.idle_wait(4.0) # wait for lead and follower to move + # 4) Wait for the follower to move above and over the lead or Timeout + normalizedStartPos = JointsHelper.getRelativeVector(lead.position, follower.position) + normalizedStartPos = normalizedStartPos.GetNormalizedSafe() + + class WaitCondition: + ANGLE_CHECKPOINT_1 = math.radians(90) + ANGLE_CHECKPOINT_2 = math.radians(200) + + angleAchieved = 0.0 + followerMovedAbove90Deg = False #this is expected to be true to pass the test + followerMovedAbove200Deg = False #this is expected to be true to pass the test + + jointNormal = azmath.Vector3(0.0, -1.0, 0.0) # the joint rotates around the y axis + def checkConditionMet(self): + #calculate the current follower-lead vector + normalVec = JointsHelper.getRelativeVector(lead.position, follower.position) + normalVec = normalVec.GetNormalizedSafe() + + #triple product and get the angle + tripleProduct = normalizedStartPos.dot(normalVec.cross(self.jointNormal)) + currentAngle = math.acos(normalizedStartPos.Dot(normalVec)) + if tripleProduct < 0: + currentAngle = (2*math.pi) - currentAngle + + #if the angle is now less then last time, it is no longer rising, so end the test. + if currentAngle < self.angleAchieved: + return True + + #once we're passed the final check point, end the test + if currentAngle > self.ANGLE_CHECKPOINT_2: + self.followerMovedAbove200Deg = True + return True + + self.angleAchieved = currentAngle + self.followerMovedAbove90Deg = currentAngle > self.ANGLE_CHECKPOINT_1 + return False + + def isFollowerPositionCorrect(self): + return self.followerMovedAbove90Deg and self.followerMovedAbove200Deg + + waitCondition = WaitCondition() + + MAX_WAIT_TIME = 10.0 #seconds + conditionMet = helper.wait_for_condition(lambda: waitCondition.checkConditionMet(), MAX_WAIT_TIME) # 5) Check to see if lead and follower behaved as expected - Report.info_vector3(lead.position, "lead position after 1 second:") - Report.info_vector3(follower.position, "follower position after 1 second:") + Report.info_vector3(lead.position, "lead position after test run:") + Report.info_vector3(follower.position, "follower position after test run:") leadPositionDelta = lead.position.Subtract(leadInitialPosition) leadRemainedStill = JointsHelper.vector3SmallerThanScalar(leadPositionDelta, FLOAT_EPSILON) Report.critical_result(Tests.check_lead_position, leadRemainedStill) - followerSwingedOverLead = (follower.position.x < leadInitialPosition.x and - follower.position.z > leadInitialPosition.z) - Report.critical_result(Tests.check_follower_position, followerSwingedOverLead) + Report.critical_result(Tests.check_follower_position, conditionMet and waitCondition.isFollowerPositionCorrect()) # 6) Exit Game Mode helper.exit_game_mode(Tests.exit_game_mode) - - if __name__ == "__main__": from editor_python_test_tools.utils import Report Report.start_test(Joints_HingeNoLimitsConstrained) diff --git a/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly b/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly index 86dd941423..9babf84ba4 100644 --- a/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly +++ b/AutomatedTesting/Levels/Physics/Joints_HingeNoLimitsConstrained/Joints_HingeNoLimitsConstrained.ly @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:817bd8dd22e185136418b60fba5b3552993687515d3d5ae96791f2c3be907b92 -size 7233 +oid sha256:60276c07b45a734e4f71d695278167ea61e884f8b513906168c9642078ad5954 +size 6045 From 3af07e511764e7d617cfa9b13647405a6954e61f Mon Sep 17 00:00:00 2001 From: Adi Bar-Lev <82479970+Adi-Amazon@users.noreply.github.com> Date: Wed, 13 Oct 2021 09:37:47 -0400 Subject: [PATCH 138/169] Hair - creating parent class for raster pass as prep for ShortCut technique (#4560) Signed-off-by: Adi-Amazon --- .../Code/Passes/HairGeometryRasterPass.cpp | 301 ++++++++++++++++++ .../Code/Passes/HairGeometryRasterPass.h | 112 +++++++ .../Code/Passes/HairPPLLRasterPass.cpp | 269 +--------------- .../Code/Passes/HairPPLLRasterPass.h | 70 +--- Gems/AtomTressFX/Hair_files.cmake | 6 + 5 files changed, 434 insertions(+), 324 deletions(-) create mode 100644 Gems/AtomTressFX/Code/Passes/HairGeometryRasterPass.cpp create mode 100644 Gems/AtomTressFX/Code/Passes/HairGeometryRasterPass.h diff --git a/Gems/AtomTressFX/Code/Passes/HairGeometryRasterPass.cpp b/Gems/AtomTressFX/Code/Passes/HairGeometryRasterPass.cpp new file mode 100644 index 0000000000..7af5903cf3 --- /dev/null +++ b/Gems/AtomTressFX/Code/Passes/HairGeometryRasterPass.cpp @@ -0,0 +1,301 @@ +/* + * 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 + +#include +#include +#include + +namespace AZ +{ + namespace Render + { + namespace Hair + { + + // --- Creation & Initialization --- + RPI::Ptr HairGeometryRasterPass::Create(const RPI::PassDescriptor& descriptor) + { + RPI::Ptr pass = aznew HairGeometryRasterPass(descriptor); + return pass; + } + + HairGeometryRasterPass::HairGeometryRasterPass(const RPI::PassDescriptor& descriptor) + : RasterPass(descriptor), + m_passDescriptor(descriptor) + { + // For inherited classes, override this method and set the proper path. + // Example: "Shaders/hairrenderingfillppll.azshader" + SetShaderPath("dummyShaderPath"); + } + + bool HairGeometryRasterPass::AcquireFeatureProcessor() + { + if (m_featureProcessor) + { + return true; + } + + RPI::Scene* scene = GetScene(); + if (scene) + { + m_featureProcessor = scene->GetFeatureProcessor(); + } + else + { + return false; + } + + if (!m_featureProcessor) + { + AZ_Warning("Hair Gem", false, + "HairGeometryRasterPass [%s] - Failed to retrieve Hair feature processor from the scene", + GetName().GetCStr()); + return false; + } + return true; + } + + void HairGeometryRasterPass::InitializeInternal() + { + if (GetScene()) + { + RasterPass::InitializeInternal(); + } + } + + bool HairGeometryRasterPass::IsEnabled() const + { + return (RPI::RasterPass::IsEnabled() && m_initialized) ? true : false; + } + + bool HairGeometryRasterPass::LoadShaderAndPipelineState() + { + RPI::ShaderReloadNotificationBus::Handler::BusDisconnect(); + + const RPI::RasterPassData* passData = RPI::PassUtils::GetPassData(m_passDescriptor); + + // If we successfully retrieved our custom data, use it to set the DrawListTag + if (!passData) + { + AZ_Error("Hair Gem", false, "Missing pass raster data"); + return false; + } + + // Load Shader + const char* shaderFilePath = m_shaderPath.c_str(); + Data::Asset shaderAsset = + RPI::AssetUtils::LoadAssetByProductPath(shaderFilePath, RPI::AssetUtils::TraceLevel::Error); + + if (!shaderAsset.GetId().IsValid()) + { + AZ_Error("Hair Gem", false, "Invalid shader asset for shader '%s'!", shaderFilePath); + return false; + } + + m_shader = RPI::Shader::FindOrCreate(shaderAsset); + if (m_shader == nullptr) + { + AZ_Error("Hair Gem", false, "Pass failed to load shader '%s'!", shaderFilePath); + return false; + } + + // Per Pass Srg + { + // Using 'PerPass' naming since currently RasterPass assumes that the pass Srg is always named 'PassSrg' + // [To Do] - RasterPass should use srg slot index and not name - currently this will + // result in a crash in one of the Atom existing MSAA passes that requires further dive. + // m_shaderResourceGroup = UtilityClass::CreateShaderResourceGroup(m_shader, "HairPerPassSrg", "Hair Gem"); + m_shaderResourceGroup = UtilityClass::CreateShaderResourceGroup(m_shader, "PassSrg", "Hair Gem"); + if (!m_shaderResourceGroup) + { + AZ_Error("Hair Gem", false, "Failed to create the per pass srg"); + return false; + } + } + + const RPI::ShaderVariant& shaderVariant = m_shader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); + RHI::PipelineStateDescriptorForDraw pipelineStateDescriptor; + shaderVariant.ConfigurePipelineState(pipelineStateDescriptor); + + RPI::Scene* scene = GetScene(); + if (!scene) + { + AZ_Error("Hair Gem", false, "Scene could not be acquired" ); + return false; + } + RHI::DrawListTag drawListTag = m_shader->GetDrawListTag(); + scene->ConfigurePipelineState(drawListTag, pipelineStateDescriptor); + + pipelineStateDescriptor.m_renderAttachmentConfiguration = GetRenderAttachmentConfiguration(); + pipelineStateDescriptor.m_inputStreamLayout.SetTopology(AZ::RHI::PrimitiveTopology::TriangleList); + pipelineStateDescriptor.m_inputStreamLayout.Finalize(); + + m_pipelineState = m_shader->AcquirePipelineState(pipelineStateDescriptor); + if (!m_pipelineState) + { + AZ_Error("Hair Gem", false, "Pipeline state could not be acquired"); + return false; + } + + RPI::ShaderReloadNotificationBus::Handler::BusConnect(shaderAsset.GetId()); + + m_initialized = true; + return true; + } + + void HairGeometryRasterPass::SchedulePacketBuild(HairRenderObject* hairObject) + { + m_newRenderObjects.insert(hairObject); + } + + bool HairGeometryRasterPass::BuildDrawPacket(HairRenderObject* hairObject) + { + if (!m_initialized) + { + return false; + } + + RHI::DrawPacketBuilder::DrawRequest drawRequest; + drawRequest.m_listTag = m_drawListTag; + drawRequest.m_pipelineState = m_pipelineState; +// drawRequest.m_streamBufferViews = // no explicit vertex buffer. shader is using the srg buffers + drawRequest.m_stencilRef = 0; + drawRequest.m_sortKey = 0; + + // Seems that the PerView and PerScene are gathered through RenderPass::CollectSrgs() + // The PerPass is gathered through the RasterPass::m_shaderResourceGroup + AZStd::lock_guard lock(m_mutex); + + return hairObject->BuildPPLLDrawPacket(drawRequest); + } + + bool HairGeometryRasterPass::AddDrawPackets(AZStd::list>& hairRenderObjects) + { + bool overallSuccess = true; + + if (!m_currentView && + (!(m_currentView = GetView()) || !m_currentView->HasDrawListTag(m_drawListTag))) + { + m_currentView = nullptr; // set it to nullptr to prevent further attempts this frame + AZ_Warning("Hair Gem", false, "AddDrawPackets: failed to acquire or match the DrawListTag - check that your pass and shader tag name match"); + return false; + } + + for (auto& renderObject : hairRenderObjects) + { + const RHI::DrawPacket* drawPacket = renderObject->GetFillDrawPacket(); + if (!drawPacket) + { // might not be an error - the object might have just been added and the DrawPacket is + // scheduled to be built when the render frame begins + AZ_Warning("Hair Gem", !m_newRenderObjects.empty(), "HairGeometryRasterPass - DrawPacket wasn't built"); + overallSuccess = false; + continue; + } + + m_currentView->AddDrawPacket(drawPacket); + } + return overallSuccess; + } + + void HairGeometryRasterPass::FrameBeginInternal(FramePrepareParams params) + { + { + AZStd::lock_guard lock(m_mutex); + if (!m_initialized && AcquireFeatureProcessor()) + { + LoadShaderAndPipelineState(); + m_featureProcessor->ForceRebuildRenderData(); + } + } + + if (!m_initialized) + { + return; + } + + // Bind the Per Object resources and trigger the RHI validation that will use attachment + // for its validation. The attachments are invalidated outside the render begin/end frame. + for (HairRenderObject* newObject : m_newRenderObjects) + { + newObject->BindPerObjectSrgForRaster(); + BuildDrawPacket(newObject); + } + + // Clear the new added objects - BuildDrawPacket should only be carried out once per + // object/shader lifetime + m_newRenderObjects.clear(); + + // Refresh current view every frame + if (!(m_currentView = GetView()) || !m_currentView->HasDrawListTag(m_drawListTag)) + { + m_currentView = nullptr; // set it to null if view exists but no tag match + AZ_Warning("Hair Gem", false, "FrameBeginInternal: failed to acquire or match the DrawListTag - check that your pass and shader tag name match"); + return; + } + + RPI::RasterPass::FrameBeginInternal(params); + } + + void HairGeometryRasterPass::CompileResources(const RHI::FrameGraphCompileContext& context) + { + AZ_PROFILE_FUNCTION(AzRender); + + if (!m_featureProcessor) + { + return; + } + + // Compilation of remaining srgs will be done by the parent class + RPI::RasterPass::CompileResources(context); + } + + void HairGeometryRasterPass::BuildShaderAndRenderData() + { + AZStd::lock_guard lock(m_mutex); + m_initialized = false; // make sure we initialize it even if not in this frame + if (AcquireFeatureProcessor()) + { + LoadShaderAndPipelineState(); + m_featureProcessor->ForceRebuildRenderData(); + } + } + + void HairGeometryRasterPass::OnShaderReinitialized([[maybe_unused]] const RPI::Shader & shader) + { + BuildShaderAndRenderData(); + } + + void HairGeometryRasterPass::OnShaderAssetReinitialized([[maybe_unused]] const Data::Asset& shaderAsset) + { + BuildShaderAndRenderData(); + } + + void HairGeometryRasterPass::OnShaderVariantReinitialized([[maybe_unused]] const AZ::RPI::ShaderVariant& shaderVariant) + { + BuildShaderAndRenderData(); + } + } // namespace Hair + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomTressFX/Code/Passes/HairGeometryRasterPass.h b/Gems/AtomTressFX/Code/Passes/HairGeometryRasterPass.h new file mode 100644 index 0000000000..a226d2c294 --- /dev/null +++ b/Gems/AtomTressFX/Code/Passes/HairGeometryRasterPass.h @@ -0,0 +1,112 @@ +/* + * 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 RHI + { + struct DrawItem; + } + + namespace Render + { + namespace Hair + { + class HairRenderObject; + class HairFeatureProcessor; + + //! A HairGeometryRasterPass is used for the render of the hair geometries. This is the base + //! class that can be inherited - for example by the HiarPPLLRasterPass and have only the specific + //! class data handling added on top. + class HairGeometryRasterPass + : public RPI::RasterPass + , private RPI::ShaderReloadNotificationBus::Handler + { + AZ_RPI_PASS(HairGeometryRasterPass); + + public: + AZ_RTTI(HairGeometryRasterPass, "{0F07360A-A286-4060-8C62-137AFFA50561}", RasterPass); + AZ_CLASS_ALLOCATOR(HairGeometryRasterPass, SystemAllocator, 0); + + //! Creates a HairGeometryRasterPass + static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); + + bool AddDrawPackets(AZStd::list>& hairObjects); + + //! The following will be called when an object was added or shader has been compiled + void SchedulePacketBuild(HairRenderObject* hairObject); + + Data::Instance GetShader() { return m_shader; } + + void SetFeatureProcessor(HairFeatureProcessor* featureProcessor) + { + m_featureProcessor = featureProcessor; + } + + virtual bool IsEnabled() const override; + + protected: + explicit HairGeometryRasterPass(const RPI::PassDescriptor& descriptor); + + // ShaderReloadNotificationBus::Handler overrides... + void OnShaderReinitialized(const RPI::Shader& shader) override; + void OnShaderAssetReinitialized(const Data::Asset& shaderAsset) override; + void OnShaderVariantReinitialized(const AZ::RPI::ShaderVariant& shaderVariant) override; + + void SetShaderPath(const char* shaderPath) { m_shaderPath = shaderPath; } + bool LoadShaderAndPipelineState(); + bool AcquireFeatureProcessor(); + void BuildShaderAndRenderData(); + bool BuildDrawPacket(HairRenderObject* hairObject); + + // Pass behavior overrides + void InitializeInternal() override; +// void BuildInternal() override; + void FrameBeginInternal(FramePrepareParams params) override; + + // Scope producer functions... + void CompileResources(const RHI::FrameGraphCompileContext& context) override; + + protected: + HairFeatureProcessor* m_featureProcessor = nullptr; + + // The shader that will be used by the pass + Data::Instance m_shader = nullptr; + + // Override the following in the inherited class + AZStd::string m_shaderPath = "dummyShaderPath"; + + // To help create the pipeline state + RPI::PassDescriptor m_passDescriptor; + + const RHI::PipelineState* m_pipelineState = nullptr; + RPI::ViewPtr m_currentView = nullptr; + + AZStd::mutex m_mutex; + + //! List of new render objects introduced this frame so that their in order to identify + //! that their PerObject (dynamic) Srg needs binding to the resources. + //! Done once per every new object introduced / requires update. + AZStd::unordered_set m_newRenderObjects; + + bool m_initialized = false; + }; + + } // namespace Hair + } // namespace Render +} // namespace AZ diff --git a/Gems/AtomTressFX/Code/Passes/HairPPLLRasterPass.cpp b/Gems/AtomTressFX/Code/Passes/HairPPLLRasterPass.cpp index 746a3c2640..a677a929a2 100644 --- a/Gems/AtomTressFX/Code/Passes/HairPPLLRasterPass.cpp +++ b/Gems/AtomTressFX/Code/Passes/HairPPLLRasterPass.cpp @@ -34,61 +34,25 @@ namespace AZ namespace Hair { - // --- Creation & Initialization --- + HairPPLLRasterPass::HairPPLLRasterPass(const RPI::PassDescriptor& descriptor) + : HairGeometryRasterPass(descriptor) + { + SetShaderPath("Shaders/hairrenderingfillppll.azshader"); + } + RPI::Ptr HairPPLLRasterPass::Create(const RPI::PassDescriptor& descriptor) { RPI::Ptr pass = aznew HairPPLLRasterPass(descriptor); return pass; } - HairPPLLRasterPass::HairPPLLRasterPass(const RPI::PassDescriptor& descriptor) - : RasterPass(descriptor), - m_passDescriptor(descriptor) - { - } - - HairPPLLRasterPass::~HairPPLLRasterPass() - { - } - - bool HairPPLLRasterPass::AcquireFeatureProcessor() - { - if (m_featureProcessor) - { - return true; - } - - RPI::Scene* scene = GetScene(); - if (scene) - { - m_featureProcessor = scene->GetFeatureProcessor(); - } - else - { - return false; - } - - if (!m_featureProcessor) - { - AZ_Warning("Hair Gem", false, - "HairPPLLRasterPass [%s] - Failed to retrieve Hair feature processor from the scene", - GetName().GetCStr()); - return false; - } - return true; - } - - void HairPPLLRasterPass::InitializeInternal() - { - if (GetScene()) - { - RasterPass::InitializeInternal(); - } - } - + //! This method is used for attaching the PPLL data buffer which is a transient buffer. + //! It is done this ways because Atom doesn't support transient structured buffers declaration + //! via Pass yet. + //! Once supported, this will be done via data driven code and the method can be removed. void HairPPLLRasterPass::BuildInternal() { - RasterPass::BuildInternal(); + RasterPass::BuildInternal(); // change this to call parent if the method exists if (!AcquireFeatureProcessor()) { @@ -104,217 +68,6 @@ namespace AZ AttachBufferToSlot(Name{ "PerPixelLinkedList" }, m_featureProcessor->GetPerPixelListBuffer()); } - bool HairPPLLRasterPass::IsEnabled() const - { - return (RPI::RasterPass::IsEnabled() && m_initialized) ? true : false; - } - - bool HairPPLLRasterPass::LoadShaderAndPipelineState() - { - RPI::ShaderReloadNotificationBus::Handler::BusDisconnect(); - - const RPI::RasterPassData* passData = RPI::PassUtils::GetPassData(m_passDescriptor); - - // If we successfully retrieved our custom data, use it to set the DrawListTag - if (!passData) - { - AZ_Error("Hair Gem", false, "Missing pass raster data"); - return false; - } - - // Load Shader - const char* shaderFilePath = "Shaders/hairrenderingfillppll.azshader"; - Data::Asset shaderAsset = - RPI::AssetUtils::LoadAssetByProductPath(shaderFilePath, RPI::AssetUtils::TraceLevel::Error); - - if (!shaderAsset.GetId().IsValid()) - { - AZ_Error("Hair Gem", false, "Invalid shader asset for shader '%s'!", shaderFilePath); - return false; - } - - m_shader = RPI::Shader::FindOrCreate(shaderAsset); - if (m_shader == nullptr) - { - AZ_Error("Hair Gem", false, "Pass failed to load shader '%s'!", shaderFilePath); - return false; - } - - // Per Pass Srg - { - // Using 'PerPass' naming since currently RasterPass assumes that the pass Srg is always named 'PassSrg' - // [To Do] - RasterPass should use srg slot index and not name - currently this will - // result in a crash in one of the Atom existing MSAA passes that requires further dive. - // m_shaderResourceGroup = UtilityClass::CreateShaderResourceGroup(m_shader, "HairPerPassSrg", "Hair Gem"); - m_shaderResourceGroup = UtilityClass::CreateShaderResourceGroup(m_shader, "PassSrg", "Hair Gem"); - if (!m_shaderResourceGroup) - { - AZ_Error("Hair Gem", false, "Failed to create the per pass srg"); - return false; - } - } - - const RPI::ShaderVariant& shaderVariant = m_shader->GetVariant(RPI::ShaderAsset::RootShaderVariantStableId); - RHI::PipelineStateDescriptorForDraw pipelineStateDescriptor; - shaderVariant.ConfigurePipelineState(pipelineStateDescriptor); - - RPI::Scene* scene = GetScene(); - if (!scene) - { - AZ_Error("Hair Gem", false, "Scene could not be acquired" ); - return false; - } - RHI::DrawListTag drawListTag = m_shader->GetDrawListTag(); - scene->ConfigurePipelineState(drawListTag, pipelineStateDescriptor); - - pipelineStateDescriptor.m_renderAttachmentConfiguration = GetRenderAttachmentConfiguration(); - pipelineStateDescriptor.m_inputStreamLayout.SetTopology(AZ::RHI::PrimitiveTopology::TriangleList); - pipelineStateDescriptor.m_inputStreamLayout.Finalize(); - - m_pipelineState = m_shader->AcquirePipelineState(pipelineStateDescriptor); - if (!m_pipelineState) - { - AZ_Error("Hair Gem", false, "Pipeline state could not be acquired"); - return false; - } - - RPI::ShaderReloadNotificationBus::Handler::BusConnect(shaderAsset.GetId()); - - m_initialized = true; - return true; - } - - void HairPPLLRasterPass::SchedulePacketBuild(HairRenderObject* hairObject) - { - m_newRenderObjects.insert(hairObject); - } - - bool HairPPLLRasterPass::BuildDrawPacket(HairRenderObject* hairObject) - { - if (!m_initialized) - { - return false; - } - - RHI::DrawPacketBuilder::DrawRequest drawRequest; - drawRequest.m_listTag = m_drawListTag; - drawRequest.m_pipelineState = m_pipelineState; -// drawRequest.m_streamBufferViews = // no explicit vertex buffer. shader is using the srg buffers - drawRequest.m_stencilRef = 0; - drawRequest.m_sortKey = 0; - - // Seems that the PerView and PerScene are gathered through RenderPass::CollectSrgs() - // The PerPass is gathered through the RasterPass::m_shaderResourceGroup - AZStd::lock_guard lock(m_mutex); - - return hairObject->BuildPPLLDrawPacket(drawRequest); - } - - bool HairPPLLRasterPass::AddDrawPackets(AZStd::list>& hairRenderObjects) - { - bool overallSuccess = true; - - if (!m_currentView && - (!(m_currentView = GetView()) || !m_currentView->HasDrawListTag(m_drawListTag))) - { - m_currentView = nullptr; // set it to nullptr to prevent further attempts this frame - AZ_Warning("Hair Gem", false, "HairPPLLRasterPass failed to acquire or match the DrawListTag - check that your pass and shader tag name match"); - return false; - } - - for (auto& renderObject : hairRenderObjects) - { - const RHI::DrawPacket* drawPacket = renderObject->GetFillDrawPacket(); - if (!drawPacket) - { // might not be an error - the object might have just been added and the DrawPacket is - // scheduled to be built when the render frame begins - AZ_Warning("Hair Gem", !m_newRenderObjects.empty(), "HairPPLLRasterPass - DrawPacket wasn't built"); - overallSuccess = false; - continue; - } - - m_currentView->AddDrawPacket(drawPacket); - } - return overallSuccess; - } - - void HairPPLLRasterPass::FrameBeginInternal(FramePrepareParams params) - { - { - AZStd::lock_guard lock(m_mutex); - if (!m_initialized && AcquireFeatureProcessor()) - { - LoadShaderAndPipelineState(); - m_featureProcessor->ForceRebuildRenderData(); - } - } - - if (!m_initialized) - { - return; - } - - // Bind the Per Object resources and trigger the RHI validation that will use attachment - // for its validation. The attachments are invalidated outside the render begin/end frame. - for (HairRenderObject* newObject : m_newRenderObjects) - { - newObject->BindPerObjectSrgForRaster(); - BuildDrawPacket(newObject); - } - - // Clear the new added objects - BuildDrawPacket should only be carried out once per - // object/shader lifetime - m_newRenderObjects.clear(); - - // Refresh current view every frame - if (!(m_currentView = GetView()) || !m_currentView->HasDrawListTag(m_drawListTag)) - { - m_currentView = nullptr; // set it to null if view exists but no tag match - AZ_Warning("Hair Gem", false, "HairPPLLRasterPass failed to acquire or match the DrawListTag - check that your pass and shader tag name match"); - return; - } - - RPI::RasterPass::FrameBeginInternal(params); - } - - void HairPPLLRasterPass::CompileResources(const RHI::FrameGraphCompileContext& context) - { - AZ_PROFILE_FUNCTION(AzRender); - - if (!m_featureProcessor) - { - return; - } - - // Compilation of remaining srgs will be done by the parent class - RPI::RasterPass::CompileResources(context); - } - - void HairPPLLRasterPass::BuildShaderAndRenderData() - { - AZStd::lock_guard lock(m_mutex); - m_initialized = false; // make sure we initialize it even if not in this frame - if (AcquireFeatureProcessor()) - { - LoadShaderAndPipelineState(); - m_featureProcessor->ForceRebuildRenderData(); - } - } - - void HairPPLLRasterPass::OnShaderReinitialized([[maybe_unused]] const RPI::Shader & shader) - { - BuildShaderAndRenderData(); - } - - void HairPPLLRasterPass::OnShaderAssetReinitialized([[maybe_unused]] const Data::Asset& shaderAsset) - { - BuildShaderAndRenderData(); - } - - void HairPPLLRasterPass::OnShaderVariantReinitialized([[maybe_unused]] const AZ::RPI::ShaderVariant& shaderVariant) - { - BuildShaderAndRenderData(); - } } // namespace Hair } // namespace Render } // namespace AZ diff --git a/Gems/AtomTressFX/Code/Passes/HairPPLLRasterPass.h b/Gems/AtomTressFX/Code/Passes/HairPPLLRasterPass.h index ef7167897f..bf90fe0521 100644 --- a/Gems/AtomTressFX/Code/Passes/HairPPLLRasterPass.h +++ b/Gems/AtomTressFX/Code/Passes/HairPPLLRasterPass.h @@ -7,14 +7,7 @@ */ #pragma once -#include - -#include - -#include -#include -#include -#include +#include namespace AZ { @@ -27,11 +20,8 @@ namespace AZ { namespace Hair { - class HairRenderObject; - class HairFeatureProcessor; - //! A HairPPLLRasterPass is used for the hair fragments fill render after the data - //! went through the skinning and simulation passes. + //! went through the skinning and simulation passes. //! The output of this pass is the general list of fragment data that can now be //! traversed for depth resolve and lighting. //! The Fill pass uses the following Srgs: @@ -41,74 +31,22 @@ namespace AZ //! - HairDynamicDataSrg (PerObjectSrg) - shared buffers views for this hair object only. //! - PerViewSrg and PerSceneSrg - as per the data from Atom. class HairPPLLRasterPass - : public RPI::RasterPass - , private RPI::ShaderReloadNotificationBus::Handler + : public HairGeometryRasterPass { AZ_RPI_PASS(HairPPLLRasterPass); public: - AZ_RTTI(HairPPLLRasterPass, "{6614D7DD-24EE-4A2B-B314-7C035E2FB3C4}", RasterPass); + AZ_RTTI(HairPPLLRasterPass, "{6614D7DD-24EE-4A2B-B314-7C035E2FB3C4}", HairGeometryRasterPass); AZ_CLASS_ALLOCATOR(HairPPLLRasterPass, SystemAllocator, 0); - virtual ~HairPPLLRasterPass(); //! Creates a HairPPLLRasterPass static RPI::Ptr Create(const RPI::PassDescriptor& descriptor); - bool AddDrawPackets(AZStd::list>& hairObjects); - - //! The following will be called when an object was added or shader has been compiled - void SchedulePacketBuild(HairRenderObject* hairObject); - - Data::Instance GetShader() { return m_shader; } - - void SetFeatureProcessor(HairFeatureProcessor* featureProcessor) - { - m_featureProcessor = featureProcessor; - } - - virtual bool IsEnabled() const override; protected: - // ShaderReloadNotificationBus::Handler overrides... - void OnShaderReinitialized(const RPI::Shader& shader) override; - void OnShaderAssetReinitialized(const Data::Asset& shaderAsset) override; - void OnShaderVariantReinitialized(const AZ::RPI::ShaderVariant& shaderVariant) override; - - private: explicit HairPPLLRasterPass(const RPI::PassDescriptor& descriptor); - bool LoadShaderAndPipelineState(); - bool AcquireFeatureProcessor(); - void BuildShaderAndRenderData(); - bool BuildDrawPacket(HairRenderObject* hairObject); - // Pass behavior overrides - void InitializeInternal() override; void BuildInternal() override; - void FrameBeginInternal(FramePrepareParams params) override; - - // Scope producer functions... - void CompileResources(const RHI::FrameGraphCompileContext& context) override; - - private: - HairFeatureProcessor* m_featureProcessor = nullptr; - - // The shader that will be used by the pass - Data::Instance m_shader = nullptr; - - // To help create the pipeline state - RPI::PassDescriptor m_passDescriptor; - - const RHI::PipelineState* m_pipelineState = nullptr; - RPI::ViewPtr m_currentView = nullptr; - - AZStd::mutex m_mutex; - - //! List of new render objects introduced this frame so that their - //! Per Object (dynamic) Srg should be bound to the resources. - //! Done once per every new object introduced / requires update. - AZStd::unordered_set m_newRenderObjects; - - bool m_initialized = false; }; } // namespace Hair diff --git a/Gems/AtomTressFX/Hair_files.cmake b/Gems/AtomTressFX/Hair_files.cmake index c726d931f7..000abeb559 100644 --- a/Gems/AtomTressFX/Hair_files.cmake +++ b/Gems/AtomTressFX/Hair_files.cmake @@ -61,10 +61,16 @@ set(FILES #) # #set(atom_hair_passes + # The simulation pass class shared by all simulation / skinning compute passes Code/Passes/HairSkinningComputePass.h Code/Passes/HairSkinningComputePass.cpp + # Base class of all geometry raster passes + Code/Passes/HairGeometryRasterPass.h + Code/Passes/HairGeometryRasterPass.cpp + # PPLL rendering technique - geometry raster pass Code/Passes/HairPPLLRasterPass.h Code/Passes/HairPPLLRasterPass.cpp + # PP full screen resolve pass Code/Passes/HairPPLLResolvePass.h Code/Passes/HairPPLLResolvePass.cpp #) From 97e9f4dc7d7ce343c4a64547d30dc91d274c0277 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Wed, 13 Oct 2021 09:38:36 -0500 Subject: [PATCH 139/169] [LYN-6838] Various Monolithic shutdown fixes for the GameLauncher (#4564) * Added a stateless allocator which uses AZ_OS_MALLOC/AZ_OS_FREE to allocate memory for objects in static memory. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the Maestro and LyShine Anim Nodes to use the stateless_allocator for its static containers. This prevents crashes in static de-init due to the SystemAllocator being destroyed at that poitn Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Updated the EBus AllocatorType to use the EBusEnvironmentAllocator Because the EBus Context resides in static memory, the SystemAllocator lifetime is shorter than the EBus Context. This results in shutdown crashes in monolithic builds due to all of the gem modules being linked in as static libraries and the EBus context now destructing at the point of the executable static de-init, instead of the module de-init, where the SystemAllocator would still be around. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Fixed an assortment of shutdown issues due to deleting objects after AZ allocators are no longer available Fixed the NameDictionary IsReady() function to not assert when the dictionary when invoked after the environment variable it was stored in was destroyed. Updated the NameData destructor to check that the NameDictionary IsReady() before attempting to remove itself from the dictionary Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Fixed NameDictionary destory workflow, to reset the EnvironmentVariable instance Updated the EnvironmentVariable instance to store the NameDictionary as a value. Added a rvalue reference `Set` function overload to the EnvironmentVariable class to support move only types. Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> * Clang 6.0.0 build fixes The C++17 std::launder feature isn't available in that compiler version Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- Code/Framework/AzCore/AzCore/EBus/EBus.h | 6 +- .../AzCore/AzCore/Memory/AllocatorManager.h | 4 +- .../AzCore/AzCore/Module/Environment.h | 45 ++++----- .../AzCore/AzCore/Name/Internal/NameData.cpp | 5 +- .../AzCore/AzCore/Name/NameDictionary.cpp | 24 ++--- .../AzCore/AzCore/Name/NameDictionary.h | 21 +++-- .../AzCore/AzCore/std/allocator_stateless.cpp | 94 +++++++++++++++++++ .../AzCore/AzCore/std/allocator_stateless.h | 61 ++++++++++++ .../AzCore/AzCore/std/azstd_files.cmake | 2 + .../AzCore/AzCore/std/createdestroy.h | 6 +- Code/Legacy/CryCommon/IMovieSystem.h | 5 +- Code/Legacy/CryCommon/StlUtils.h | 8 ++ .../DecalTextureArrayFeatureProcessor.cpp | 4 +- .../ProjectedShadowFeatureProcessor.cpp | 2 +- .../RHI/Vulkan/Code/Source/RHI/Instance.cpp | 19 +++- .../RHI/Vulkan/Code/Source/RHI/Instance.h | 1 + .../Code/Source/RHI/SystemComponent.cpp | 1 + .../Source/AudioSystemGemSystemComponent.cpp | 3 + Gems/ImGui/Code/Source/ImGuiManager.cpp | 7 +- Gems/LyShine/Code/Source/Animation/AnimNode.h | 3 +- .../Source/Animation/UiAnimationSystem.cpp | 33 ++++--- .../Code/Source/Cinematics/AnimPostFXNode.cpp | 3 +- Gems/Maestro/Code/Source/Cinematics/Movie.cpp | 35 ++++--- 23 files changed, 302 insertions(+), 90 deletions(-) create mode 100644 Code/Framework/AzCore/AzCore/std/allocator_stateless.cpp create mode 100644 Code/Framework/AzCore/AzCore/std/allocator_stateless.h diff --git a/Code/Framework/AzCore/AzCore/EBus/EBus.h b/Code/Framework/AzCore/AzCore/EBus/EBus.h index a3dc10b103..67cffb4e41 100644 --- a/Code/Framework/AzCore/AzCore/EBus/EBus.h +++ b/Code/Framework/AzCore/AzCore/EBus/EBus.h @@ -77,9 +77,11 @@ namespace AZ public: /** * Allocator used by the EBus. - * The default setting is AZStd::allocator, which uses AZ::SystemAllocator. + * The default setting is Internal EBusEnvironmentAllocator + * EBus code stores their Context instances in static memory + * Therfore the configured allocator must last as long as the EBus in a module */ - using AllocatorType = AZStd::allocator; + using AllocatorType = AZ::Internal::EBusEnvironmentAllocator; /** * Defines how many handlers can connect to an address on the EBus diff --git a/Code/Framework/AzCore/AzCore/Memory/AllocatorManager.h b/Code/Framework/AzCore/AzCore/Memory/AllocatorManager.h index be0ab4a0a0..14dec68ad1 100644 --- a/Code/Framework/AzCore/AzCore/Memory/AllocatorManager.h +++ b/Code/Framework/AzCore/AzCore/Memory/AllocatorManager.h @@ -34,7 +34,9 @@ namespace AZ friend IAllocator; friend class AllocatorBase; friend class Debug::AllocationRecords; - friend class AZ::Internal::EnvironmentVariableHolder; + template friend constexpr auto AZStd::construct_at(T*, Args&&... args) + ->AZStd::enable_if_t()) T(AZStd::forward(args)...))>>, T*>; + template constexpr friend void AZStd::destroy_at(T*); public: typedef AZStd::function OutOfMemoryCBType; diff --git a/Code/Framework/AzCore/AzCore/Module/Environment.h b/Code/Framework/AzCore/AzCore/Module/Environment.h index e87ff81446..a2dcfbd8fa 100644 --- a/Code/Framework/AzCore/AzCore/Module/Environment.h +++ b/Code/Framework/AzCore/AzCore/Module/Environment.h @@ -251,16 +251,15 @@ namespace AZ class EnvironmentVariableHolder : public EnvironmentVariableHolderBase { - void ConstructImpl(const AZStd::true_type& /* AZStd::has_trivial_constructor */) - { - memset(&m_value, 0, sizeof(T)); - } - template - void ConstructImpl(const AZStd::false_type& /* AZStd::has_trivial_constructor */, Args&&... args) + void ConstructImpl(Args&&... args) { - // Construction of non-trivial types is left up to the type's constructor. - new(&m_value) T(AZStd::forward(args)...); + // Use std::launder to ensure that the compiler treats the T* reinterpret_cast as a new object + #if __cpp_lib_launder + AZStd::construct_at(std::launder(reinterpret_cast(&m_value)), AZStd::forward(args)...); + #else + AZStd::construct_at(reinterpret_cast(&m_value), AZStd::forward(args)...); + #endif } static void DestructDispatchNoLock(EnvironmentVariableHolderBase *base, DestroyTarget selfDestruct) { @@ -274,10 +273,12 @@ namespace AZ AZ_Assert(self->m_isConstructed, "Variable is not constructed. Please check your logic and guard if needed!"); self->m_isConstructed = false; self->m_moduleOwner = nullptr; - if constexpr(!AZStd::is_trivially_destructible_v) - { - reinterpret_cast(&self->m_value)->~T(); - } + // Use std::launder to ensure that the compiler treats the T* reinterpret_cast as a new object + #if __cpp_lib_launder + AZStd::destroy_at(std::launder(reinterpret_cast(&self->m_value))); + #else + AZStd::destroy_at(reinterpret_cast(&self->m_value)); + #endif } public: EnvironmentVariableHolder(u32 guid, bool isOwnershipTransfer, Environment::AllocatorInterface* allocator) @@ -303,24 +304,13 @@ namespace AZ UnregisterAndDestroy(DestructDispatchNoLock, moduleRelease); } - void Construct() - { - AZStd::lock_guard lock(m_mutex); - if (!m_isConstructed) - { - ConstructImpl(AZStd::is_trivially_constructible{}); - m_isConstructed = true; - m_moduleOwner = Environment::GetModuleId(); - } - } - template void Construct(Args&&... args) { AZStd::lock_guard lock(m_mutex); if (!m_isConstructed) { - ConstructImpl(typename AZStd::false_type(), AZStd::forward(args)...); + ConstructImpl(AZStd::forward(args)...); m_isConstructed = true; m_moduleOwner = Environment::GetModuleId(); } @@ -333,7 +323,7 @@ namespace AZ } // variable storage - typename AZStd::aligned_storage::value>::type m_value; + AZStd::aligned_storage_for_t m_value; static int s_moduleUseCount; }; @@ -468,6 +458,11 @@ namespace AZ Get() = value; } + void Set(T&& value) + { + Get() = AZStd::move(value); + } + explicit operator bool() const { return IsValid(); diff --git a/Code/Framework/AzCore/AzCore/Name/Internal/NameData.cpp b/Code/Framework/AzCore/AzCore/Name/Internal/NameData.cpp index 0086e68c6d..574b0bcc7e 100644 --- a/Code/Framework/AzCore/AzCore/Name/Internal/NameData.cpp +++ b/Code/Framework/AzCore/AzCore/Name/Internal/NameData.cpp @@ -42,7 +42,10 @@ namespace AZ AZ_Assert(m_useCount > 0, "m_useCount is already 0!"); if (m_useCount.fetch_sub(1) == 1) { - AZ::NameDictionary::Instance().TryReleaseName(hash); + if (AZ::NameDictionary::IsReady()) + { + AZ::NameDictionary::Instance().TryReleaseName(hash); + } } } } diff --git a/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp b/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp index 8e8011add9..3047a2894e 100644 --- a/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp +++ b/Code/Framework/AzCore/AzCore/Name/NameDictionary.cpp @@ -21,23 +21,18 @@ namespace AZ namespace NameDictionaryInternal { - static AZ::EnvironmentVariable s_instance = nullptr; + static AZ::EnvironmentVariable s_instance = nullptr; } void NameDictionary::Create() { using namespace NameDictionaryInternal; - AZ_Assert(!s_instance || !s_instance.Get(), "NameDictionary already created!"); + AZ_Assert(!s_instance, "NameDictionary already created!"); if (!s_instance) { - s_instance = AZ::Environment::CreateVariable(NameDictionaryInstanceName); - } - - if (!s_instance.Get()) - { - s_instance.Set(aznew NameDictionary()); + s_instance = AZ::Environment::CreateVariable(NameDictionaryInstanceName); } } @@ -46,8 +41,7 @@ namespace AZ using namespace NameDictionaryInternal; AZ_Assert(s_instance, "NameDictionary not created!"); - delete (*s_instance); - *s_instance = nullptr; + s_instance.Reset(); } bool NameDictionary::IsReady() @@ -56,10 +50,10 @@ namespace AZ if (!s_instance) { - s_instance = Environment::FindVariable(NameDictionaryInstanceName); + s_instance = Environment::FindVariable(NameDictionaryInstanceName); } - return s_instance && *s_instance; + return s_instance.IsConstructed(); } NameDictionary& NameDictionary::Instance() @@ -68,12 +62,12 @@ namespace AZ if (!s_instance) { - s_instance = Environment::FindVariable(NameDictionaryInstanceName); + s_instance = Environment::FindVariable(NameDictionaryInstanceName); } - AZ_Assert(s_instance && *s_instance, "NameDictionary has not been initialized yet."); + AZ_Assert(s_instance.IsConstructed(), "NameDictionary has not been initialized yet."); - return *(*s_instance); + return *s_instance; } NameDictionary::NameDictionary() diff --git a/Code/Framework/AzCore/AzCore/Name/NameDictionary.h b/Code/Framework/AzCore/AzCore/Name/NameDictionary.h index fa13dbd682..8f9af4be3a 100644 --- a/Code/Framework/AzCore/AzCore/Name/NameDictionary.h +++ b/Code/Framework/AzCore/AzCore/Name/NameDictionary.h @@ -16,7 +16,7 @@ #include #include -namespace MaterialEditor +namespace MaterialEditor { class MaterialEditorCoreComponent; } @@ -34,14 +34,14 @@ namespace AZ { class NameData; }; - + //! Maintains a list of unique strings for Name objects. //! The main benefit of the Name system is very fast string equality comparison, because every - //! unique name has a unique ID. The NameDictionary's purpose is to guarantee name IDs do not + //! unique name has a unique ID. The NameDictionary's purpose is to guarantee name IDs do not //! collide. It also saves memory by removing duplicate strings. //! - //! Benchmarks have shown that creating a new Name object can be quite slow when the name doesn't - //! already exist in the NameDictionary, but is comparable to creating an AZStd::string for names + //! Benchmarks have shown that creating a new Name object can be quite slow when the name doesn't + //! already exist in the NameDictionary, but is comparable to creating an AZStd::string for names //! that already exist. class NameDictionary final { @@ -51,7 +51,10 @@ namespace AZ friend Name; friend Internal::NameData; friend UnitTest::NameDictionaryTester; - + template friend constexpr auto AZStd::construct_at(T*, Args&&... args) + -> AZStd::enable_if_t()) T(AZStd::forward(args)...))>>, T*>; + template constexpr friend void AZStd::destroy_at(T*); + public: static void Create(); @@ -62,7 +65,7 @@ namespace AZ //! Makes a Name from the provided raw string. If an entry already exists in the dictionary, it is shared. //! Otherwise, it is added to the internal dictionary. - //! + //! //! @param name The name to resolve against the dictionary. //! @return A Name instance holding a dictionary entry associated with the provided raw string. Name MakeName(AZStd::string_view name); @@ -84,13 +87,13 @@ namespace AZ // Attempts to release the name from the dictionary, but checks to make sure // a reference wasn't taken by another thread. void TryReleaseName(Name::Hash hash); - + ////////////////////////////////////////////////////////////////////////// // Calculates a hash for the provided name string. // Does not attempt to resolve hash collisions; that is handled elsewhere. Name::Hash CalcHash(AZStd::string_view name); - + AZStd::unordered_map m_dictionary; mutable AZStd::shared_mutex m_sharedMutex; }; diff --git a/Code/Framework/AzCore/AzCore/std/allocator_stateless.cpp b/Code/Framework/AzCore/AzCore/std/allocator_stateless.cpp new file mode 100644 index 0000000000..5806cc485c --- /dev/null +++ b/Code/Framework/AzCore/AzCore/std/allocator_stateless.cpp @@ -0,0 +1,94 @@ +/* + * 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 AZStd +{ + stateless_allocator::stateless_allocator(const char* name) + : m_name(name) {} + + const char* stateless_allocator::get_name() const + { + return m_name; + } + + void stateless_allocator::set_name(const char* name) + { + m_name = name; + } + + auto stateless_allocator::allocate(size_type byteSize) -> pointer_type + { + return allocate(byteSize, AZ_DEFAULT_ALIGNMENT, 0); + } + + auto stateless_allocator::allocate(size_type byteSize, size_type alignment, int) -> pointer_type + { + pointer_type address = AZ_OS_MALLOC(byteSize, alignment); + + if (address == nullptr) + { + AZ_Error("Memory", false, "stateless_allocator ran out of system memory!\n"); + } + + return address; + } + + void stateless_allocator::deallocate(pointer_type ptr, size_type) + { + AZ_OS_FREE(ptr); + } + + void stateless_allocator::deallocate(pointer_type ptr, size_type, size_type) + { + AZ_OS_FREE(ptr); + } + + auto stateless_allocator::max_size() const -> size_type + { + return AZ_CORE_MAX_ALLOCATOR_SIZE; + } + + stateless_allocator stateless_allocator::select_on_container_copy_construction() const + { + return *this; + } + + auto stateless_allocator::resize(pointer_type, size_type) -> size_type + { + return 0; + } + + bool stateless_allocator::is_lock_free() + { + return false; + } + + bool stateless_allocator::is_stale_read_allowed() + { + return false; + } + + bool stateless_allocator::is_delayed_recycling() + { + return false; + } + + // comparison operators + bool operator==(const stateless_allocator&, const stateless_allocator&) + { + return true; + } + + bool operator!=(const stateless_allocator&, const stateless_allocator&) + { + return false; + } +} diff --git a/Code/Framework/AzCore/AzCore/std/allocator_stateless.h b/Code/Framework/AzCore/AzCore/std/allocator_stateless.h new file mode 100644 index 0000000000..b73c680c32 --- /dev/null +++ b/Code/Framework/AzCore/AzCore/std/allocator_stateless.h @@ -0,0 +1,61 @@ +/* + * 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 AZStd +{ + class stateless_allocator + { + public: + + AZ_TYPE_INFO(stateless_allocator, "{E4976C53-0B20-4F39-8D41-0A76F59A7D68}"); + + using value_type = uint8_t; + using pointer_type = void*; + using size_type = size_t; + using difference_type = ptrdiff_t; + using allow_memory_leaks = AZStd::true_type; + + stateless_allocator(const char* name = "AZStd::stateless_allocator"); + stateless_allocator(const stateless_allocator& rhs) = default; + + stateless_allocator& operator=(const stateless_allocator& rhs) = default; + + const char* get_name() const; + void set_name(const char* name); + + pointer_type allocate(size_type byteSize); + pointer_type allocate(size_type byteSize, size_type alignment, int flags = 0); + void deallocate(pointer_type ptr, size_type alignment); + void deallocate(pointer_type ptr, size_type byteSize, size_type alignment); + + // max_size actually returns the true maximum size of a single allocation + size_type max_size() const; + + // Returns a copy of the allocator + stateless_allocator select_on_container_copy_construction() const; + + //! extensions + size_type resize(pointer_type ptr, size_type newSize); + + bool is_lock_free(); + bool is_stale_read_allowed(); + bool is_delayed_recycling(); + + private: + const char* m_name; + }; + + bool operator==(const stateless_allocator& left, const stateless_allocator& right); + bool operator!=(const stateless_allocator& left, const stateless_allocator& right); +} diff --git a/Code/Framework/AzCore/AzCore/std/azstd_files.cmake b/Code/Framework/AzCore/AzCore/std/azstd_files.cmake index 08e72c5649..2746489f8c 100644 --- a/Code/Framework/AzCore/AzCore/std/azstd_files.cmake +++ b/Code/Framework/AzCore/AzCore/std/azstd_files.cmake @@ -12,6 +12,8 @@ set(FILES allocator.h allocator_ref.h allocator_stack.h + allocator_stateless.cpp + allocator_stateless.h allocator_static.h allocator_traits.h any.h diff --git a/Code/Framework/AzCore/AzCore/std/createdestroy.h b/Code/Framework/AzCore/AzCore/std/createdestroy.h index 0fa6e4ed40..355374a13a 100644 --- a/Code/Framework/AzCore/AzCore/std/createdestroy.h +++ b/Code/Framework/AzCore/AzCore/std/createdestroy.h @@ -20,7 +20,7 @@ namespace AZStd { - // alias std::pointer_traits into the AZStd::namespace + // alias std::pointer_traits into the AZStd::namespace using std::pointer_traits; //! Bring the names of uninitialized_default_construct and @@ -229,7 +229,7 @@ namespace AZStd //! `new (declval()) T(declval()...)` is well-formed template constexpr auto construct_at(T* ptr, Args&&... args) - -> enable_if_t()) T(AZStd::forward(args)...))>>, T*> + -> enable_if_t()) T(AZStd::forward(args)...))>>, T*> { return ::new (ptr) T(AZStd::forward(args)...); } @@ -487,7 +487,7 @@ namespace AZStd { //! Implements the C++17 uninitialized_move function //! The functions accepts two input iterators and an output iterator - //! It performs an AZStd::move on each in in the range of the input iterator + //! It performs an AZStd::move on each in in the range of the input iterator //! and stores the result in location pointed by the output iterator template ForwardIt uninitialized_move(InputIt first, InputIt last, ForwardIt result) diff --git a/Code/Legacy/CryCommon/IMovieSystem.h b/Code/Legacy/CryCommon/IMovieSystem.h index 6cc5a06c8f..4da08d3bbf 100644 --- a/Code/Legacy/CryCommon/IMovieSystem.h +++ b/Code/Legacy/CryCommon/IMovieSystem.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -181,7 +182,7 @@ public: private: AnimParamType m_type; - AZStd::string m_name; + AZStd::basic_string, AZStd::stateless_allocator> m_name; }; namespace AZStd @@ -617,7 +618,7 @@ public: , valueType(_valueType) , flags(_flags) {}; - AZStd::string name; // parameter name. + AZStd::basic_string, AZStd::stateless_allocator> name; // parameter name. CAnimParamType paramType; // parameter id. AnimValueType valueType; // value type, defines type of track to use for animating this parameter. ESupportedParamFlags flags; // combination of flags from ESupportedParamFlags. diff --git a/Code/Legacy/CryCommon/StlUtils.h b/Code/Legacy/CryCommon/StlUtils.h index 4aafd4dd0e..f5128a564f 100644 --- a/Code/Legacy/CryCommon/StlUtils.h +++ b/Code/Legacy/CryCommon/StlUtils.h @@ -13,6 +13,7 @@ #include #include +#include #include #include #include @@ -491,6 +492,13 @@ namespace stl return type; } + //! Specialization of string to const char cast. + template <> + inline const char* constchar_cast(const AZStd::basic_string, AZStd::stateless_allocator>& type) + { + return type.c_str(); + } + //! Specialization of string to const char cast. template <> inline const char* constchar_cast(const AZStd::string& type) diff --git a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.cpp index 472dbff5c8..e9bc1a1277 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Decals/DecalTextureArrayFeatureProcessor.cpp @@ -357,7 +357,7 @@ namespace AZ // Texture2DArray m_decalTextureArrayNormalMaps0; // Texture2DArray m_decalTextureArrayNormalMaps1; // Texture2DArray m_decalTextureArrayNormalMaps2; - static const AZStd::array ShaderNames = { "m_decalTextureArrayDiffuse", + static constexpr AZStd::array ShaderNames = { "m_decalTextureArrayDiffuse", "m_decalTextureArrayNormalMaps" }; for (int mapType = 0; mapType < DecalMapType_Num; ++mapType) @@ -365,7 +365,7 @@ namespace AZ for (int texArrayIdx = 0; texArrayIdx < NumTextureArrays; ++texArrayIdx) { const RHI::ShaderResourceGroupLayout* viewSrgLayout = RPI::RPISystemInterface::Get()->GetViewSrgLayout().get(); - const AZStd::string baseName = ShaderNames[mapType] + AZStd::to_string(texArrayIdx); + const AZStd::string baseName = AZStd::string(ShaderNames[mapType]) + AZStd::to_string(texArrayIdx); m_decalTextureArrayIndices[texArrayIdx][mapType] = viewSrgLayout->FindShaderInputImageIndex(Name(baseName.c_str())); AZ_Warning( diff --git a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp index c0202c7c74..6452b312c8 100644 --- a/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/Shadows/ProjectedShadowFeatureProcessor.cpp @@ -346,7 +346,7 @@ namespace AZ::Render void ProjectedShadowFeatureProcessor::CacheEsmShadowmapsPass(const AZStd::vector& validPipelineIds) { - static const Name LightTypeName = Name("projected"); + const Name LightTypeName = Name("projected"); const auto* passSystem = RPI::PassSystemInterface::Get(); const AZStd::vector passes = passSystem->GetPassesForTemplateName(Name("EsmShadowmapsTemplate")); diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Instance.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Instance.cpp index c2fe16b551..2dce5d85f3 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Instance.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Instance.cpp @@ -16,12 +16,27 @@ namespace AZ { static const uint32_t s_minVulkanSupportedVersion = VK_API_VERSION_1_0; + static EnvironmentVariable s_vulkanInstance; + static constexpr const char* s_vulkanInstanceKey = "VulkanInstance"; + Instance& Instance::GetInstance() { - static Instance s_instance; - return s_instance; + if (!s_vulkanInstance) + { + s_vulkanInstance = Environment::FindVariable(s_vulkanInstanceKey); + if (!s_vulkanInstance) + { + s_vulkanInstance = Environment::CreateVariable(s_vulkanInstanceKey); + } + } + + return s_vulkanInstance.Get(); } + void Instance::Reset() + { + s_vulkanInstance.Reset(); + } Instance::~Instance() { diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Instance.h b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Instance.h index 40a6951c2d..efa8d36d2b 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Instance.h +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/Instance.h @@ -34,6 +34,7 @@ namespace AZ }; static Instance& GetInstance(); + static void Reset(); ~Instance(); bool Init(const Descriptor& descriptor); void Shutdown(); diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SystemComponent.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SystemComponent.cpp index 36e0c2b2f5..0d401003d9 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SystemComponent.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI/SystemComponent.cpp @@ -101,6 +101,7 @@ namespace AZ RHI::FactoryManagerBus::Broadcast(&RHI::FactoryManagerRequest::UnregisterFactory, this); Instance::GetInstance().Shutdown(); + Instance::Reset(); } Name SystemComponent::GetName() diff --git a/Gems/AudioSystem/Code/Source/AudioSystemGemSystemComponent.cpp b/Gems/AudioSystem/Code/Source/AudioSystemGemSystemComponent.cpp index b1e7e3ac18..1af927a7e7 100644 --- a/Gems/AudioSystem/Code/Source/AudioSystemGemSystemComponent.cpp +++ b/Gems/AudioSystem/Code/Source/AudioSystemGemSystemComponent.cpp @@ -90,6 +90,9 @@ namespace AudioSystemGem AudioSystemGemSystemComponent::~AudioSystemGemSystemComponent() { + // The audio system uses the Audio::AudioSystemAllocator + // so it needs to be deleted before the allocator is shutdown + m_audioSystem.reset(); Audio::Platform::ShutdownAudioAllocators(); } diff --git a/Gems/ImGui/Code/Source/ImGuiManager.cpp b/Gems/ImGui/Code/Source/ImGuiManager.cpp index 6fc1ea8b71..d631e2f83e 100644 --- a/Gems/ImGui/Code/Source/ImGuiManager.cpp +++ b/Gems/ImGui/Code/Source/ImGuiManager.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -31,11 +32,11 @@ using namespace AzFramework; using namespace ImGui; // Wheel Delta const value. -const constexpr uint32_t IMGUI_WHEEL_DELTA = 120; // From WinUser.h, for Linux +static const constexpr uint32_t IMGUI_WHEEL_DELTA = 120; // From WinUser.h, for Linux // Typedef and local static map to hold LyInput->ImGui Nav mappings ( filled up in Initialize() ) -typedef AZStd::pair LyButtonImGuiNavIndexPair; -typedef AZStd::unordered_map LyButtonImGuiNavIndexMap; +using LyButtonImGuiNavIndexPair = AZStd::pair; +using LyButtonImGuiNavIndexMap = AZStd::fixed_unordered_map; static LyButtonImGuiNavIndexMap s_lyInputToImGuiNavIndexMap; /** diff --git a/Gems/LyShine/Code/Source/Animation/AnimNode.h b/Gems/LyShine/Code/Source/Animation/AnimNode.h index 0076276204..4d139e99ca 100644 --- a/Gems/LyShine/Code/Source/Animation/AnimNode.h +++ b/Gems/LyShine/Code/Source/Animation/AnimNode.h @@ -13,6 +13,7 @@ #include #include "UiAnimationSystem.h" +#include /*! @@ -39,7 +40,7 @@ public: , valueType(_valueType) , flags(_flags) {}; - AZStd::string name; // parameter name. + AZStd::basic_string, AZStd::stateless_allocator> name; // parameter name. CUiAnimParamType paramType; // parameter id. EUiAnimValue valueType; // value type, defines type of track to use for animating this parameter. ESupportedParamFlags flags; // combination of flags from ESupportedParamFlags. diff --git a/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp b/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp index 012eaacd1b..cab6ae3fa6 100644 --- a/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp +++ b/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp @@ -14,9 +14,11 @@ #include "UiAnimSerialize.h" #include +#include +#include +#include #include -#include #include #include #include @@ -25,22 +27,31 @@ #include ////////////////////////////////////////////////////////////////////////// -// Serialization for anim nodes & param types -#define REGISTER_NODE_TYPE(name) assert(g_animNodeEnumToStringMap.find(eUiAnimNodeType_ ## name) == g_animNodeEnumToStringMap.end()); \ - g_animNodeEnumToStringMap[eUiAnimNodeType_ ## name] = AZ_STRINGIZE(name); \ - g_animNodeStringToEnumMap[AZStd::string(AZ_STRINGIZE(name))] = eUiAnimNodeType_ ## name; +namespace +{ + using UiAnimParamSystemString = AZStd::basic_string, AZStd::stateless_allocator>; -#define REGISTER_PARAM_TYPE(name) assert(g_animParamEnumToStringMap.find(eUiAnimParamType_ ## name) == g_animParamEnumToStringMap.end()); \ + template > + using UiAnimSystemOrderedMap = AZStd::map; + template , typename EqualKey = AZStd::equal_to> + using UiAnimSystemUnorderedMap = AZStd::unordered_map; +} +// Serialization for anim nodes & param types +#define REGISTER_NODE_TYPE(name) assert(g_animNodeEnumToStringMap.contains(eUiAnimNodeType_ ## name)); \ + g_animNodeEnumToStringMap[eUiAnimNodeType_ ## name] = AZ_STRINGIZE(name); \ + g_animNodeStringToEnumMap[UiAnimParamSystemString(AZ_STRINGIZE(name))] = eUiAnimNodeType_ ## name; + +#define REGISTER_PARAM_TYPE(name) assert(g_animParamEnumToStringMap.contains(eUiAnimParamType_ ## name)); \ g_animParamEnumToStringMap[eUiAnimParamType_ ## name] = AZ_STRINGIZE(name); \ - g_animParamStringToEnumMap[AZStd::string(AZ_STRINGIZE(name))] = eUiAnimParamType_ ## name; + g_animParamStringToEnumMap[UiAnimParamSystemString(AZ_STRINGIZE(name))] = eUiAnimParamType_ ## name; namespace { - AZStd::unordered_map g_animNodeEnumToStringMap; - StaticInstance >> g_animNodeStringToEnumMap; + UiAnimSystemUnorderedMap g_animNodeEnumToStringMap; + UiAnimSystemOrderedMap> g_animNodeStringToEnumMap; - AZStd::unordered_map g_animParamEnumToStringMap; - StaticInstance >> g_animParamStringToEnumMap; + UiAnimSystemUnorderedMap g_animParamEnumToStringMap; + UiAnimSystemOrderedMap> g_animParamStringToEnumMap; // If you get an assert in this function, it means two node types have the same enum value. void RegisterNodeTypes() diff --git a/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp b/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp index 7e32301b71..b535033351 100644 --- a/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/AnimPostFXNode.cpp @@ -8,6 +8,7 @@ #include +#include #include "AnimPostFXNode.h" #include "AnimSplineTrack.h" #include "CompoundSplineTrack.h" @@ -38,7 +39,7 @@ public: virtual void GetDefault(bool& val) const = 0; virtual void GetDefault(Vec4& val) const = 0; - AZStd::string m_name; + AZStd::basic_string, AZStd::stateless_allocator> m_name; protected: virtual ~CControlParamBase(){} diff --git a/Gems/Maestro/Code/Source/Cinematics/Movie.cpp b/Gems/Maestro/Code/Source/Cinematics/Movie.cpp index 3654af52dd..9c4356560d 100644 --- a/Gems/Maestro/Code/Source/Cinematics/Movie.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/Movie.cpp @@ -8,6 +8,9 @@ #include +#include +#include +#include #include #include #include "Movie.h" @@ -73,22 +76,32 @@ static SMovieSequenceAutoComplete s_movieSequenceAutoComplete; #endif ////////////////////////////////////////////////////////////////////////// -// Serialization for anim nodes & param types -#define REGISTER_NODE_TYPE(name) assert(g_animNodeEnumToStringMap.find(AnimNodeType::name) == g_animNodeEnumToStringMap.end()); \ - g_animNodeEnumToStringMap[AnimNodeType::name] = AZ_STRINGIZE(name); \ - g_animNodeStringToEnumMap[AZStd::string(AZ_STRINGIZE(name))] = AnimNodeType::name; +namespace +{ + using AnimParamSystemString = AZStd::basic_string, AZStd::stateless_allocator>; -#define REGISTER_PARAM_TYPE(name) assert(g_animParamEnumToStringMap.find(AnimParamType::name) == g_animParamEnumToStringMap.end()); \ - g_animParamEnumToStringMap[AnimParamType::name] = AZ_STRINGIZE(name); \ - g_animParamStringToEnumMap[AZStd::string(AZ_STRINGIZE(name))] = AnimParamType::name; + template > + using AnimSystemOrderedMap = AZStd::map; + template , typename EqualKey = AZStd::equal_to> + using AnimSystemUnorderedMap = AZStd::unordered_map; +} + +// Serialization for anim nodes & param types +#define REGISTER_NODE_TYPE(name) assert(g_animNodeEnumToStringMap.contains(AnimNodeType::name)); \ + g_animNodeEnumToStringMap[AnimNodeType::name] = AZ_STRINGIZE(name); \ + g_animNodeStringToEnumMap[AnimParamSystemString(AZ_STRINGIZE(name))] = AnimNodeType::name; + +#define REGISTER_PARAM_TYPE(name) assert(g_animParamEnumToStringMap.contains(AnimParamType::name)); \ + g_animParamEnumToStringMap[AnimParamType::name] = AZ_STRINGIZE(name); \ + g_animParamStringToEnumMap[AnimParamSystemString(AZ_STRINGIZE(name))] = AnimParamType::name; namespace { - AZStd::unordered_map g_animNodeEnumToStringMap; - StaticInstance >> g_animNodeStringToEnumMap; + AnimSystemUnorderedMap g_animNodeEnumToStringMap; + AnimSystemOrderedMap> g_animNodeStringToEnumMap; - AZStd::unordered_map g_animParamEnumToStringMap; - StaticInstance >> g_animParamStringToEnumMap; + AnimSystemUnorderedMap g_animParamEnumToStringMap; + AnimSystemOrderedMap> g_animParamStringToEnumMap; // If you get an assert in this function, it means two node types have the same enum value. void RegisterNodeTypes() From b6a1f62dec2c248606905bdc931ee4d795c148c2 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Wed, 13 Oct 2021 18:20:48 +0200 Subject: [PATCH 140/169] EMotion FX: Fix for broken workspaces after asset path change (#4662) Some days ago an impactful change deprecated @assets@ and @root@ keywords from paths which our workspaces used. Some workspaces used these and were broken. This change makes them backward compatible and loads the assets correctly again. It also auto fixes broken paths that were present in some of the saved workspaces + making sure new workspaces are saved correctly. Signed-off-by: Benjamin Jillich --- .../EMotionStudio/EMStudioSDK/Source/Workspace.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Workspace.cpp b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Workspace.cpp index ea7c92b742..cada8c7f59 100644 --- a/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Workspace.cpp +++ b/Gems/EMotionFX/Code/EMotionFX/Tools/EMotionStudio/EMStudioSDK/Source/Workspace.cpp @@ -105,7 +105,9 @@ namespace EMStudio } } - commandString = AZStd::string::format("%s -filename \"%s\"", command, resultFileName.c_str()); + AZStd::string resultFilenameString = resultFileName.c_str(); + AzFramework::StringFunc::AssetDatabasePath::Normalize(resultFilenameString); + commandString = AZStd::string::format("%s -filename \"%s\"", command, resultFilenameString.c_str()); if (additionalParameters) { @@ -428,7 +430,13 @@ namespace EMStudio continue; } - AzFramework::StringFunc::Replace(commands[i], "@products@/", assetCacheFolder.c_str(), true /* case sensitive */); + AzFramework::StringFunc::Replace(commands[i], "@products@", assetCacheFolder.c_str()); + AzFramework::StringFunc::Replace(commands[i], "@assets@", assetCacheFolder.c_str()); + AzFramework::StringFunc::Replace(commands[i], "@root@", assetCacheFolder.c_str()); + AzFramework::StringFunc::Replace(commands[i], "@projectplatformcache@", assetCacheFolder.c_str()); + AzFramework::StringFunc::Replace(commands[i], "//", AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING); + AzFramework::StringFunc::Replace(commands[i], "\\\\", AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING); + AzFramework::StringFunc::Replace(commands[i], "/\\", AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING); // add the command to the command group commandGroup->AddCommandString(commands[i]); From 150060441eccb98318febe17d3915f0781823b19 Mon Sep 17 00:00:00 2001 From: jromnoa <80134229+jromnoa@users.noreply.github.com> Date: Wed, 13 Oct 2021 09:50:44 -0700 Subject: [PATCH 141/169] Re-add pytest.mark.test_case_id markers (#4621) * add some test case id markers Signed-off-by: jromnoa * re-added pytest.mark.test_case_id markers for test cases Signed-off-by: jromnoa * re-add directional light log lines that were missing and re-add directional light test case id Signed-off-by: jromnoa --- .../Gem/PythonTests/Atom/TestSuite_Main.py | 44 ++++++++++++++----- .../PythonTests/Atom/TestSuite_Main_GPU.py | 4 ++ .../Atom/TestSuite_Main_GPU_Optimized.py | 1 + .../Gem/PythonTests/Atom/TestSuite_Sandbox.py | 1 + 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py index e4a77ca4ec..3403c938a8 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main.py @@ -23,20 +23,20 @@ TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "tests") class TestAtomEditorComponentsMain(object): """Holds tests for Atom components.""" + @pytest.mark.test_case_id("C32078118") # Decal + @pytest.mark.test_case_id("C32078119") # DepthOfField + @pytest.mark.test_case_id("C32078120") # Directional Light + @pytest.mark.test_case_id("C32078121") # Exposure Control + @pytest.mark.test_case_id("C32078115") # Global Skylight (IBL) + @pytest.mark.test_case_id("C32078125") # Physical Sky + @pytest.mark.test_case_id("C32078127") # PostFX Layer + @pytest.mark.test_case_id("C32078131") # PostFX Radius Weight Modifier + @pytest.mark.test_case_id("C32078117") # Light + @pytest.mark.test_case_id("C36525660") # Display Mapper def test_AtomEditorComponents_AddedToEntity(self, request, editor, level, workspace, project, launcher_platform): """ Please review the hydra script run by this test for more specific test info. - Tests the following Atom components and verifies all "expected_lines" appear in Editor.log: - 1. Display Mapper - 2. Light - 3. PostFX Radius Weight Modifier - 4. PostFX Layer - 5. Physical Sky - 6. Global Skylight (IBL) - 7. Exposure Control - 8. Directional Light - 9. DepthOfField - 10. Decal + Tests the Atom components & verifies all "expected_lines" appear in Editor.log """ cfg_args = [level] @@ -69,6 +69,18 @@ class TestAtomEditorComponentsMain(object): "DepthOfField_test: Entity deleted: True", "DepthOfField_test: UNDO entity deletion works: True", "DepthOfField_test: REDO entity deletion works: True", + # Directional Light Component + "Directional Light Entity successfully created", + "Directional Light_test: Component added to the entity: True", + "Directional Light_test: Component removed after UNDO: True", + "Directional Light_test: Component added after REDO: True", + "Directional Light_test: Entered game mode: True", + "Directional Light_test: Exit game mode: True", + "Directional Light_test: Entity is hidden: True", + "Directional Light_test: Entity is shown: True", + "Directional Light_test: Entity deleted: True", + "Directional Light_test: UNDO entity deletion works: True", + "Directional Light_test: REDO entity deletion works: True", # Exposure Control Component "Exposure Control Entity successfully created", "Exposure Control_test: Component added to the entity: True", @@ -180,6 +192,7 @@ class TestAtomEditorComponentsMain(object): cfg_args=cfg_args, ) + @pytest.mark.test_case_id("C34525095") def test_AtomEditorComponents_LightComponent( self, request, editor, workspace, project, launcher_platform, level): """ @@ -266,6 +279,15 @@ class TestMaterialEditorBasicTests(object): request.addfinalizer(teardown) @pytest.mark.parametrize("exe_file_name", ["MaterialEditor"]) + @pytest.mark.test_case_id("C34448113") # Creating a New Asset. + @pytest.mark.test_case_id("C34448114") # Opening an Existing Asset. + @pytest.mark.test_case_id("C34448115") # Closing Selected Material. + @pytest.mark.test_case_id("C34448116") # Closing All Materials. + @pytest.mark.test_case_id("C34448117") # Closing all but Selected Material. + @pytest.mark.test_case_id("C34448118") # Saving Material. + @pytest.mark.test_case_id("C34448119") # Saving as a New Material. + @pytest.mark.test_case_id("C34448120") # Saving as a Child Material. + @pytest.mark.test_case_id("C34448121") # Saving all Open Materials. def test_MaterialEditorBasicTests( self, request, workspace, project, launcher_platform, generic_launcher, exe_file_name): diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py index 220623af8b..74b064a555 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py @@ -73,6 +73,7 @@ def create_screenshots_archive(screenshot_path): class TestAllComponentsIndepthTests(object): @pytest.mark.parametrize("screenshot_name", ["AtomBasicLevelSetup.ppm"]) + @pytest.mark.test_case_id("C34603773") def test_BasicLevelSetup_SetsUpLevel( self, request, editor, workspace, project, launcher_platform, level, screenshot_name): """ @@ -115,6 +116,7 @@ class TestAllComponentsIndepthTests(object): create_screenshots_archive(screenshot_directory) + @pytest.mark.test_case_id("C34525095") def test_LightComponent_ScreenshotMatchesGoldenImage( self, request, editor, workspace, project, launcher_platform, level): """ @@ -225,6 +227,8 @@ class TestMaterialEditor(object): pytest.param("-rhi=Vulkan", ["Registering vulkan RHI"]) ]) @pytest.mark.parametrize("exe_file_name", ["MaterialEditor"]) + @pytest.mark.test_case_id("C30973986") # Material Editor Launching in Dx12 + @pytest.mark.test_case_id("C30973987") # Material Editor Launching in Vulkan def test_MaterialEditorLaunch_AllRHIOptionsSucceed( self, request, workspace, project, launcher_platform, generic_launcher, exe_file_name, cfg_args, expected_lines): diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU_Optimized.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU_Optimized.py index ef572d6e5c..568768e12e 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU_Optimized.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU_Optimized.py @@ -23,6 +23,7 @@ class TestAutomation(EditorTestSuite): # Remove -autotest_mode from global_extra_cmdline_args since we need rendering for these tests. global_extra_cmdline_args = ["-BatchMode"] # Default is ["-BatchMode", "-autotest_mode"] + @pytest.mark.test_case_id("C34603773") class AtomGPU_BasicLevelSetup_SetsUpLevel(EditorSharedTest): use_null_renderer = False # Default is True screenshot_name = "AtomBasicLevelSetup.ppm" diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py index 79caf26784..58e5d00ff2 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Sandbox.py @@ -30,6 +30,7 @@ class TestAtomEditorComponentsSandbox(object): class TestAtomEditorComponentsMain(object): """Holds tests for Atom components.""" + @pytest.mark.test_case_id("C32078128") def test_AtomEditorComponents_ReflectionProbeAddedToEntity( self, request, editor, level, workspace, project, launcher_platform): """ From 56f0ea68a678ce7990ea616d31464da50d0a3e37 Mon Sep 17 00:00:00 2001 From: brianherrera Date: Wed, 13 Oct 2021 10:29:53 -0700 Subject: [PATCH 142/169] Add step to verify disk is in an offline state Some Windows configs will automatically set new drives as online causing diskpart setup script to fail. Signed-off-by: brianherrera --- .../build/bootstrap/incremental_build_util.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/scripts/build/bootstrap/incremental_build_util.py b/scripts/build/bootstrap/incremental_build_util.py index 5c77559085..a33eb2af80 100644 --- a/scripts/build/bootstrap/incremental_build_util.py +++ b/scripts/build/bootstrap/incremental_build_util.py @@ -252,6 +252,18 @@ def find_snapshot_id(ec2_client, snapshot_hint, repository_name, project, pipeli snapshot_id = snapshot['SnapshotId'] return snapshot_id + +def offline_drive(disk_number=1): + """Use diskpart to offline a Windows drive""" + with tempfile.NamedTemporaryFile(delete=False) as f: + f.write(f""" + select disk {disk_number} + offline disk + """.encode('utf-8')) + subprocess.run(['diskpart', '/s', f.name]) + os.unlink(f.name) + + def create_volume(ec2_client, availability_zone, snapshot_hint, repository_name, project, pipeline, branch, platform, build_type, disk_size, disk_type): # The actual EBS default calculation for IOps is a floating point number, the closest approxmiation is 4x of the disk size for simplicity mount_name = get_mount_name(repository_name, project, pipeline, branch, platform, build_type) @@ -310,6 +322,10 @@ def create_volume(ec2_client, availability_zone, snapshot_hint, repository_name, def mount_volume_to_device(created): print('Mounting volume...') if os.name == 'nt': + # Verify drive is in an offline state. + # Some Windows configs will automatically set new drives as online causing diskpart setup script to fail. + offline_drive() + f = tempfile.NamedTemporaryFile(delete=False) f.write(""" select disk 1 From ac8201a2faebfd361dadbfa96c527895426dfa2d Mon Sep 17 00:00:00 2001 From: brianherrera Date: Wed, 13 Oct 2021 10:34:03 -0700 Subject: [PATCH 143/169] Update disk setup step to use context manager Signed-off-by: brianherrera --- .../build/bootstrap/incremental_build_util.py | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/scripts/build/bootstrap/incremental_build_util.py b/scripts/build/bootstrap/incremental_build_util.py index a33eb2af80..493d8a9249 100644 --- a/scripts/build/bootstrap/incremental_build_util.py +++ b/scripts/build/bootstrap/incremental_build_util.py @@ -325,24 +325,22 @@ def mount_volume_to_device(created): # Verify drive is in an offline state. # Some Windows configs will automatically set new drives as online causing diskpart setup script to fail. offline_drive() - - f = tempfile.NamedTemporaryFile(delete=False) - f.write(""" - select disk 1 - online disk - attribute disk clear readonly - """.encode('utf-8')) # assume disk # for now + + with tempfile.NamedTemporaryFile(delete=False) as f: + f.write(""" + select disk 1 + online disk + attribute disk clear readonly + """.encode('utf-8')) # assume disk # for now if created: print('Creating filesystem on new volume') f.write("""create partition primary - select partition 1 - format quick fs=ntfs - assign - active - """.encode('utf-8')) - - f.close() + select partition 1 + format quick fs=ntfs + assign + active + """.encode('utf-8')) subprocess.call(['diskpart', '/s', f.name]) From 3c7357da479acd50fb19e0619a776c6ab00069fb Mon Sep 17 00:00:00 2001 From: brianherrera Date: Wed, 13 Oct 2021 10:35:42 -0700 Subject: [PATCH 144/169] Update existing unmount step to use new offline function Signed-off-by: brianherrera --- scripts/build/bootstrap/incremental_build_util.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/scripts/build/bootstrap/incremental_build_util.py b/scripts/build/bootstrap/incremental_build_util.py index 493d8a9249..6117fe0180 100644 --- a/scripts/build/bootstrap/incremental_build_util.py +++ b/scripts/build/bootstrap/incremental_build_util.py @@ -391,14 +391,7 @@ def unmount_volume_from_device(): print('Unmounting EBS volume from device...') if os.name == 'nt': kill_processes(MOUNT_PATH + 'workspace') - f = tempfile.NamedTemporaryFile(delete=False) - f.write(""" - select disk 1 - offline disk - """.encode('utf-8')) - f.close() - subprocess.call('diskpart /s %s' % f.name) - os.unlink(f.name) + offline_drive() else: kill_processes(MOUNT_PATH) subprocess.call(['umount', '-f', MOUNT_PATH]) From 26d53690b95dfec555b1caf8c6df6b3c239b6835 Mon Sep 17 00:00:00 2001 From: Junbo Liang <68558268+junbo75@users.noreply.github.com> Date: Wed, 13 Oct 2021 11:34:13 -0700 Subject: [PATCH 145/169] [GameLift][FlexMatch] Add client side change for match acceptance (#4634) * [GameLift][FlexMatch] Add client side change for match acceptance required Signed-off-by: Junbo Liang --- .../AWSGameLiftClientLocalTicketTracker.cpp | 2 + .../Source/AWSGameLiftClientManager.cpp | 46 +++++++- .../Source/AWSGameLiftClientManager.h | 2 + .../AWSGameLiftAcceptMatchActivity.cpp | 76 +++++++++++++ .../Activity/AWSGameLiftAcceptMatchActivity.h | 31 ++++++ .../AWSGameLiftStartMatchmakingActivity.cpp | 4 + .../AWSGameLiftStartMatchmakingActivity.h | 3 - .../AWSGameLiftStopMatchmakingActivity.cpp | 3 + .../AWSGameLiftStopMatchmakingActivity.h | 3 - ...WSGameLiftClientLocalTicketTrackerTest.cpp | 38 +++++++ .../Tests/AWSGameLiftClientManagerTest.cpp | 104 ++++++++++++++++++ .../Tests/AWSGameLiftClientMocks.h | 21 ++++ .../AWSGameLiftAcceptMatchActivityTest.cpp | 77 +++++++++++++ ...WSGameLiftStartMatchmakingActivityTest.cpp | 2 + ...AWSGameLiftStopMatchmakingActivityTest.cpp | 2 + .../awsgamelift_client_files.cmake | 2 + .../awsgamelift_client_tests_files.cmake | 1 + 17 files changed, 409 insertions(+), 8 deletions(-) create mode 100644 Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftAcceptMatchActivity.cpp create mode 100644 Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftAcceptMatchActivity.h create mode 100644 Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftAcceptMatchActivityTest.cpp diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientLocalTicketTracker.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientLocalTicketTracker.cpp index b619a10d4a..af0cf1c35c 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientLocalTicketTracker.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientLocalTicketTracker.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -109,6 +110,7 @@ namespace AWSGameLift else if (ticket.GetStatus() == Aws::GameLift::Model::MatchmakingConfigurationStatus::REQUIRES_ACCEPTANCE) { // broadcast acceptance requires to player + AzFramework::MatchAcceptanceNotificationBus::Broadcast(&AzFramework::MatchAcceptanceNotifications::OnMatchAcceptance); } else { diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientManager.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientManager.cpp index 91e76380eb..224f16481e 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientManager.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientManager.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -125,12 +126,53 @@ namespace AWSGameLift void AWSGameLiftClientManager::AcceptMatch(const AzFramework::AcceptMatchRequest& acceptMatchRequest) { - AZ_UNUSED(acceptMatchRequest); + if (AcceptMatchActivity::ValidateAcceptMatchRequest(acceptMatchRequest)) + { + const AWSGameLiftAcceptMatchRequest& gameliftStartMatchmakingRequest = + static_cast(acceptMatchRequest); + AcceptMatchHelper(gameliftStartMatchmakingRequest); + } } void AWSGameLiftClientManager::AcceptMatchAsync(const AzFramework::AcceptMatchRequest& acceptMatchRequest) { - AZ_UNUSED(acceptMatchRequest); + if (!AcceptMatchActivity::ValidateAcceptMatchRequest(acceptMatchRequest)) + { + AzFramework::MatchmakingAsyncRequestNotificationBus::Broadcast( + &AzFramework::MatchmakingAsyncRequestNotifications::OnAcceptMatchAsyncComplete); + return; + } + + const AWSGameLiftAcceptMatchRequest& gameliftStartMatchmakingRequest = static_cast(acceptMatchRequest); + + AZ::JobContext* jobContext = nullptr; + AWSCore::AWSCoreRequestBus::BroadcastResult(jobContext, &AWSCore::AWSCoreRequests::GetDefaultJobContext); + AZ::Job* acceptMatchJob = AZ::CreateJobFunction( + [this, gameliftStartMatchmakingRequest]() + { + AcceptMatchHelper(gameliftStartMatchmakingRequest); + + AzFramework::MatchmakingAsyncRequestNotificationBus::Broadcast( + &AzFramework::MatchmakingAsyncRequestNotifications::OnAcceptMatchAsyncComplete); + }, + true, jobContext); + + acceptMatchJob->Start(); + } + + void AWSGameLiftClientManager::AcceptMatchHelper(const AWSGameLiftAcceptMatchRequest& acceptMatchRequest) + { + auto gameliftClient = AZ::Interface::Get()->GetGameLiftClient(); + + AZStd::string response; + if (!gameliftClient) + { + AZ_Error(AWSGameLiftClientManagerName, false, AWSGameLiftClientMissingErrorMessage); + } + else + { + AcceptMatchActivity::AcceptMatch(*gameliftClient, acceptMatchRequest); + } } AZStd::string AWSGameLiftClientManager::CreateSession(const AzFramework::CreateSessionRequest& createSessionRequest) diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientManager.h b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientManager.h index ba81196b07..1f32b69f75 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientManager.h +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientManager.h @@ -15,6 +15,7 @@ namespace AWSGameLift { + struct AWSGameLiftAcceptMatchRequest; struct AWSGameLiftCreateSessionRequest; struct AWSGameLiftCreateSessionOnQueueRequest; struct AWSGameLiftJoinSessionRequest; @@ -158,6 +159,7 @@ namespace AWSGameLift void LeaveSession() override; private: + void AcceptMatchHelper(const AWSGameLiftAcceptMatchRequest& createSessionRequest); AZStd::string CreateSessionHelper(const AWSGameLiftCreateSessionRequest& createSessionRequest); AZStd::string CreateSessionOnQueueHelper(const AWSGameLiftCreateSessionOnQueueRequest& createSessionOnQueueRequest); bool JoinSessionHelper(const AWSGameLiftJoinSessionRequest& joinSessionRequest); diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftAcceptMatchActivity.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftAcceptMatchActivity.cpp new file mode 100644 index 0000000000..25ba328fd0 --- /dev/null +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftAcceptMatchActivity.cpp @@ -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.AcceptMatch + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include + +#include +#include + +#include +#include + +namespace AWSGameLift +{ + namespace AcceptMatchActivity + { + Aws::GameLift::Model::AcceptMatchRequest BuildAWSGameLiftAcceptMatchRequest( + const AWSGameLiftAcceptMatchRequest& acceptMatchRequest) + { + Aws::GameLift::Model::AcceptMatchRequest request; + request.SetAcceptanceType(acceptMatchRequest.m_acceptMatch ? + Aws::GameLift::Model::AcceptanceType::ACCEPT : Aws::GameLift::Model::AcceptanceType::REJECT); + + Aws::Vector playerIds; + for (const AZStd::string& playerId : acceptMatchRequest.m_playerIds) + { + playerIds.emplace_back(playerId.c_str()); + } + request.SetPlayerIds(playerIds); + + if (!acceptMatchRequest.m_ticketId.empty()) + { + request.SetTicketId(acceptMatchRequest.m_ticketId.c_str()); + } + + AZ_TracePrintf(AWSGameLiftAcceptMatchActivityName, "Built AcceptMatchRequest with TicketId=%s", request.GetTicketId().c_str()); + + return request; + } + + void AcceptMatch(const Aws::GameLift::GameLiftClient& gameliftClient, + const AWSGameLiftAcceptMatchRequest& AcceptMatchRequest) + { + AZ_TracePrintf(AWSGameLiftAcceptMatchActivityName, "Requesting AcceptMatch against Amazon GameLift service ..."); + + Aws::GameLift::Model::AcceptMatchRequest request = BuildAWSGameLiftAcceptMatchRequest(AcceptMatchRequest); + auto AcceptMatchOutcome = gameliftClient.AcceptMatch(request); + + if (AcceptMatchOutcome.IsSuccess()) + { + AZ_TracePrintf(AWSGameLiftAcceptMatchActivityName, "AcceptMatch request against Amazon GameLift service is complete"); + } + else + { + AZ_Error(AWSGameLiftAcceptMatchActivityName, false, AWSGameLiftErrorMessageTemplate, + AcceptMatchOutcome.GetError().GetExceptionName().c_str(), AcceptMatchOutcome.GetError().GetMessage().c_str()); + } + } + + bool ValidateAcceptMatchRequest(const AzFramework::AcceptMatchRequest& AcceptMatchRequest) + { + auto gameliftAcceptMatchRequest = azrtti_cast(&AcceptMatchRequest); + bool isValid = gameliftAcceptMatchRequest && + (gameliftAcceptMatchRequest->m_playerIds.size() > 0) && + (!gameliftAcceptMatchRequest->m_ticketId.empty()); + + AZ_Error(AWSGameLiftAcceptMatchActivityName, isValid, AWSGameLiftAcceptMatchRequestInvalidErrorMessage); + + return isValid; + } + } // namespace AcceptMatchActivity +} // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftAcceptMatchActivity.h b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftAcceptMatchActivity.h new file mode 100644 index 0000000000..d5f28f92e2 --- /dev/null +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftAcceptMatchActivity.h @@ -0,0 +1,31 @@ +/* + * 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 AWSGameLift +{ + namespace AcceptMatchActivity + { + static constexpr const char AWSGameLiftAcceptMatchActivityName[] = "AWSGameLiftAcceptMatchActivity"; + static constexpr const char AWSGameLiftAcceptMatchRequestInvalidErrorMessage[] = "Invalid GameLift AcceptMatch request."; + + // Build AWS GameLift AcceptMatchRequest by using AWSGameLiftAcceptMatchRequest + Aws::GameLift::Model::AcceptMatchRequest BuildAWSGameLiftAcceptMatchRequest(const AWSGameLiftAcceptMatchRequest& AcceptMatchRequest); + + // Create AcceptMatchRequest and make a AcceptMatch call through GameLift client + void AcceptMatch(const Aws::GameLift::GameLiftClient& gameliftClient, const AWSGameLiftAcceptMatchRequest& AcceptMatchRequest); + + // Validate AcceptMatchRequest and check required request parameters + bool ValidateAcceptMatchRequest(const AzFramework::AcceptMatchRequest& AcceptMatchRequest); + } // namespace AcceptMatchActivity +} // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.cpp index 2b2a32f74b..e535ea0c55 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.cpp @@ -5,12 +5,16 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ + #include #include #include #include +#include +#include + namespace AWSGameLift { namespace StartMatchmakingActivity diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.h b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.h index 5f8c4558f4..db814c14b2 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.h +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.h @@ -10,9 +10,7 @@ #include -#include #include -#include namespace AWSGameLift { @@ -25,7 +23,6 @@ namespace AWSGameLift Aws::GameLift::Model::StartMatchmakingRequest BuildAWSGameLiftStartMatchmakingRequest(const AWSGameLiftStartMatchmakingRequest& startMatchmakingRequest); // Create StartMatchmakingRequest and make a StartMatchmaking call through GameLift client - // Will also start polling the matchmaking ticket when get success outcome from GameLift client AZStd::string StartMatchmaking(const Aws::GameLift::GameLiftClient& gameliftClient, const AWSGameLiftStartMatchmakingRequest& startMatchmakingRequest); // Validate StartMatchmakingRequest and check required request parameters diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStopMatchmakingActivity.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStopMatchmakingActivity.cpp index 204923fc02..b427d0323a 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStopMatchmakingActivity.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStopMatchmakingActivity.cpp @@ -11,6 +11,9 @@ #include #include +#include +#include + namespace AWSGameLift { namespace StopMatchmakingActivity diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStopMatchmakingActivity.h b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStopMatchmakingActivity.h index 9bfeb86343..0820f2c05e 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStopMatchmakingActivity.h +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStopMatchmakingActivity.h @@ -10,9 +10,7 @@ #include -#include #include -#include namespace AWSGameLift { @@ -25,7 +23,6 @@ namespace AWSGameLift Aws::GameLift::Model::StopMatchmakingRequest BuildAWSGameLiftStopMatchmakingRequest(const AWSGameLiftStopMatchmakingRequest& stopMatchmakingRequest); // Create StopMatchmakingRequest and make a StopMatchmaking call through GameLift client - // Will also stop polling the matchmaking ticket when get success outcome from GameLift client void StopMatchmaking(const Aws::GameLift::GameLiftClient& gameliftClient, const AWSGameLiftStopMatchmakingRequest& stopMatchmakingRequest); // Validate StopMatchmakingRequest and check required request parameters diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientLocalTicketTrackerTest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientLocalTicketTrackerTest.cpp index 6506d70704..4dc4dd85f6 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientLocalTicketTrackerTest.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientLocalTicketTrackerTest.cpp @@ -351,3 +351,41 @@ TEST_F(AWSGameLiftClientLocalTicketTrackerTest, StartPolling_CallAndTicketComple WaitForProcessFinish(); ASSERT_TRUE(m_gameliftClientTicketTracker->IsTrackerIdle()); } + +TEST_F(AWSGameLiftClientLocalTicketTrackerTest, StartPolling_RequiresAcceptanceAndTicketCompleteAtLast_ProcessContinuesAndStop) +{ + Aws::GameLift::Model::MatchmakingTicket ticket1; + ticket1.SetStatus(Aws::GameLift::Model::MatchmakingConfigurationStatus::REQUIRES_ACCEPTANCE); + + Aws::GameLift::Model::DescribeMatchmakingResult result1; + result1.AddTicketList(ticket1); + Aws::GameLift::Model::DescribeMatchmakingOutcome outcome1(result1); + + Aws::GameLift::Model::GameSessionConnectionInfo connectionInfo; + connectionInfo.SetIpAddress("DummyIpAddress"); + connectionInfo.SetPort(123); + connectionInfo.AddMatchedPlayerSessions( + Aws::GameLift::Model::MatchedPlayerSession().WithPlayerId("player1").WithPlayerSessionId("playersession1")); + + Aws::GameLift::Model::MatchmakingTicket ticket2; + ticket2.SetStatus(Aws::GameLift::Model::MatchmakingConfigurationStatus::COMPLETED); + ticket2.SetGameSessionConnectionInfo(connectionInfo); + + Aws::GameLift::Model::DescribeMatchmakingResult result2; + result2.AddTicketList(ticket2); + Aws::GameLift::Model::DescribeMatchmakingOutcome outcome2(result2); + + EXPECT_CALL(*m_gameliftClientMockPtr, DescribeMatchmaking(::testing::_)) + .WillOnce(::testing::Return(outcome1)) + .WillOnce(::testing::Return(outcome2)); + + MatchAcceptanceNotificationsHandlerMock handlerMock1; + EXPECT_CALL(handlerMock1, OnMatchAcceptance()).Times(1); + + SessionHandlingClientRequestsMock handlerMock2; + EXPECT_CALL(handlerMock2, RequestPlayerJoinSession(::testing::_)).Times(1).WillOnce(::testing::Return(true)); + + m_gameliftClientTicketTracker->StartPolling("ticket1", "player1"); + WaitForProcessFinish(); + ASSERT_TRUE(m_gameliftClientTicketTracker->IsTrackerIdle()); +} diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientManagerTest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientManagerTest.cpp index 2fa332df72..3b7c7ee827 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientManagerTest.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientManagerTest.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -1005,3 +1006,106 @@ TEST_F(AWSGameLiftClientManagerTest, StopMatchmakingAsync_CallWithValidRequest_G m_gameliftClientManager->StopMatchmakingAsync(request); AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message } + +TEST_F(AWSGameLiftClientManagerTest, AcceptMatch_CallWithoutClientSetup_GetError) +{ + AZ_TEST_START_TRACE_SUPPRESSION; + m_gameliftClientManager->ConfigureGameLiftClient(""); + AWSGameLiftAcceptMatchRequest request; + request.m_acceptMatch = true; + request.m_playerIds = { DummyPlayerId }; + request.m_ticketId = DummyMatchmakingTicketId; + + m_gameliftClientManager->AcceptMatch(request); + AZ_TEST_STOP_TRACE_SUPPRESSION(2); // capture 2 error message +} +TEST_F(AWSGameLiftClientManagerTest, AcceptMatch_CallWithInvalidRequest_GetError) +{ + AZ_TEST_START_TRACE_SUPPRESSION; + m_gameliftClientManager->AcceptMatch(AzFramework::AcceptMatchRequest()); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftClientManagerTest, AcceptMatch_CallWithValidRequest_Success) +{ + AWSGameLiftAcceptMatchRequest request; + request.m_acceptMatch = true; + request.m_playerIds = { DummyPlayerId }; + request.m_ticketId = DummyMatchmakingTicketId; + + Aws::GameLift::Model::AcceptMatchResult result; + Aws::GameLift::Model::AcceptMatchResult outcome(result); + EXPECT_CALL(*m_gameliftClientMockPtr, AcceptMatch(::testing::_)).Times(1).WillOnce(::testing::Return(outcome)); + + m_gameliftClientManager->AcceptMatch(request); +} + +TEST_F(AWSGameLiftClientManagerTest, AcceptMatch_CallWithValidRequest_GetError) +{ + AWSGameLiftAcceptMatchRequest request; + request.m_acceptMatch = true; + request.m_playerIds = { DummyPlayerId }; + request.m_ticketId = DummyMatchmakingTicketId; + + Aws::Client::AWSError error; + Aws::GameLift::Model::AcceptMatchOutcome outcome(error); + + EXPECT_CALL(*m_gameliftClientMockPtr, AcceptMatch(::testing::_)).Times(1).WillOnce(::testing::Return(outcome)); + AZ_TEST_START_TRACE_SUPPRESSION; + m_gameliftClientManager->AcceptMatch(request); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftClientManagerTest, AcceptMatchAsync_CallWithInvalidRequest_GetNotificationWithError) +{ + AWSGameLiftAcceptMatchRequest request; + + MatchmakingAsyncRequestNotificationsHandlerMock matchmakingHandlerMock; + EXPECT_CALL(matchmakingHandlerMock, OnAcceptMatchAsyncComplete()).Times(1); + + AZ_TEST_START_TRACE_SUPPRESSION; + m_gameliftClientManager->AcceptMatchAsync(request); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftClientManagerTest, AcceptMatchAsync_CallWithValidRequest_GetNotification) +{ + AWSCoreRequestsHandlerMock handlerMock; + EXPECT_CALL(handlerMock, GetDefaultJobContext()).Times(1).WillOnce(::testing::Return(m_jobContext.get())); + + AWSGameLiftAcceptMatchRequest request; + request.m_acceptMatch = true; + request.m_playerIds = { DummyPlayerId }; + request.m_ticketId = DummyMatchmakingTicketId; + + Aws::GameLift::Model::AcceptMatchResult result; + Aws::GameLift::Model::AcceptMatchOutcome outcome(result); + EXPECT_CALL(*m_gameliftClientMockPtr, AcceptMatch(::testing::_)).Times(1).WillOnce(::testing::Return(outcome)); + + MatchmakingAsyncRequestNotificationsHandlerMock matchmakingHandlerMock; + EXPECT_CALL(matchmakingHandlerMock, OnAcceptMatchAsyncComplete()).Times(1); + + m_gameliftClientManager->AcceptMatchAsync(request); +} + +TEST_F(AWSGameLiftClientManagerTest, AcceptMatchAsync_CallWithValidRequest_GetNotificationWithError) +{ + AWSCoreRequestsHandlerMock handlerMock; + EXPECT_CALL(handlerMock, GetDefaultJobContext()).Times(1).WillOnce(::testing::Return(m_jobContext.get())); + + AWSGameLiftAcceptMatchRequest request; + request.m_acceptMatch = true; + request.m_playerIds = { DummyPlayerId }; + request.m_ticketId = DummyMatchmakingTicketId; + + Aws::Client::AWSError error; + Aws::GameLift::Model::AcceptMatchOutcome outcome(error); + EXPECT_CALL(*m_gameliftClientMockPtr, AcceptMatch(::testing::_)).Times(1).WillOnce(::testing::Return(outcome)); + + MatchmakingAsyncRequestNotificationsHandlerMock matchmakingHandlerMock; + EXPECT_CALL(matchmakingHandlerMock, OnAcceptMatchAsyncComplete()).Times(1); + + AZ_TEST_START_TRACE_SUPPRESSION; + m_gameliftClientManager->AcceptMatchAsync(request); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientMocks.h b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientMocks.h index 964b6a21c2..6ba05747aa 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientMocks.h +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientMocks.h @@ -9,6 +9,7 @@ #pragma once #include +#include #include #include #include @@ -18,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -46,6 +49,7 @@ public: { } + MOCK_CONST_METHOD1(AcceptMatch, Model::AcceptMatchOutcome(const Model::AcceptMatchRequest&)); MOCK_CONST_METHOD1(CreateGameSession, Model::CreateGameSessionOutcome(const Model::CreateGameSessionRequest&)); MOCK_CONST_METHOD1(CreatePlayerSession, Model::CreatePlayerSessionOutcome(const Model::CreatePlayerSessionRequest&)); MOCK_CONST_METHOD1(DescribeMatchmaking, Model::DescribeMatchmakingOutcome(const Model::DescribeMatchmakingRequest&)); @@ -74,6 +78,23 @@ public: MOCK_METHOD0(OnStopMatchmakingAsyncComplete, void()); }; +class MatchAcceptanceNotificationsHandlerMock + : public AzFramework::MatchAcceptanceNotificationBus::Handler +{ +public: + MatchAcceptanceNotificationsHandlerMock() + { + AzFramework::MatchAcceptanceNotificationBus::Handler::BusConnect(); + } + + ~MatchAcceptanceNotificationsHandlerMock() + { + AzFramework::MatchAcceptanceNotificationBus::Handler::BusDisconnect(); + } + + MOCK_METHOD0(OnMatchAcceptance, void()); +}; + class SessionAsyncRequestNotificationsHandlerMock : public AzFramework::SessionAsyncRequestNotificationBus::Handler { diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftAcceptMatchActivityTest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftAcceptMatchActivityTest.cpp new file mode 100644 index 0000000000..af78ca8c0c --- /dev/null +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftAcceptMatchActivityTest.cpp @@ -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 + * + */ + +#include + +#include +#include + +#include + +using namespace AWSGameLift; + +using AWSGameLiftAcceptMatchActivityTest = AWSGameLiftClientFixture; + +TEST_F(AWSGameLiftAcceptMatchActivityTest, BuildAWSGameLiftAcceptMatchRequest_Call_GetExpectedResult) +{ + AWSGameLiftAcceptMatchRequest request; + request.m_acceptMatch = true; + request.m_ticketId = "dummyTicketId"; + request.m_playerIds = { "dummyPlayerId" }; + + auto awsRequest = AcceptMatchActivity::BuildAWSGameLiftAcceptMatchRequest(request); + + EXPECT_EQ(awsRequest.GetAcceptanceType(), Aws::GameLift::Model::AcceptanceType::ACCEPT); + EXPECT_TRUE(strcmp(awsRequest.GetTicketId().c_str(), request.m_ticketId.c_str()) == 0); + EXPECT_EQ(awsRequest.GetPlayerIds().size(), request.m_playerIds.size()); + EXPECT_TRUE(strcmp(awsRequest.GetPlayerIds().begin()->c_str(), request.m_playerIds.begin()->c_str()) == 0); +} + +TEST_F(AWSGameLiftAcceptMatchActivityTest, ValidateAcceptMatchRequest_CallWithBaseType_GetFalseResult) +{ + AZ_TEST_START_TRACE_SUPPRESSION; + auto result = AcceptMatchActivity::ValidateAcceptMatchRequest(AzFramework::AcceptMatchRequest()); + EXPECT_FALSE(result); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftAcceptMatchActivityTest, ValidateAcceptMatchRequest_CallWithoutTicketId_GetFalseResult) +{ + AWSGameLiftAcceptMatchRequest request; + request.m_acceptMatch = true; + request.m_playerIds = { "dummyPlayerId" }; + + AZ_TEST_START_TRACE_SUPPRESSION; + auto result = AcceptMatchActivity::ValidateAcceptMatchRequest(request); + EXPECT_FALSE(result); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftAcceptMatchActivityTest, ValidateAcceptMatchRequest_CallWithoutPlayerIds_GetFalseResult) +{ + AWSGameLiftAcceptMatchRequest request; + request.m_acceptMatch = true; + request.m_playerIds = { "dummyPlayerId" }; + + AZ_TEST_START_TRACE_SUPPRESSION; + auto result = AcceptMatchActivity::ValidateAcceptMatchRequest(request); + EXPECT_FALSE(result); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); // capture 1 error message +} + +TEST_F(AWSGameLiftAcceptMatchActivityTest, ValidateAcceptMatchRequest_CallWithValidAttributes_GetTrueResult) +{ + + AWSGameLiftAcceptMatchRequest request; + request.m_acceptMatch = true; + request.m_ticketId = "dummyTicketId"; + request.m_playerIds = { "dummyPlayerId" }; + + auto result = AcceptMatchActivity::ValidateAcceptMatchRequest(request); + EXPECT_TRUE(result); +} diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStartMatchmakingActivityTest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStartMatchmakingActivityTest.cpp index 706aec04f2..3eed6b0448 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStartMatchmakingActivityTest.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStartMatchmakingActivityTest.cpp @@ -9,6 +9,8 @@ #include #include +#include + using namespace AWSGameLift; using AWSGameLiftStartMatchmakingActivityTest = AWSGameLiftClientFixture; diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStopMatchmakingActivityTest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStopMatchmakingActivityTest.cpp index 6b53ed5055..ba0e40c7e6 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStopMatchmakingActivityTest.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStopMatchmakingActivityTest.cpp @@ -9,6 +9,8 @@ #include #include +#include + using namespace AWSGameLift; using AWSGameLiftStopMatchmakingActivityTest = AWSGameLiftClientFixture; diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_files.cmake b/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_files.cmake index 3122ff2261..0930c42370 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_files.cmake +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_files.cmake @@ -18,6 +18,8 @@ set(FILES Include/Request/IAWSGameLiftRequests.h Source/Activity/AWSGameLiftActivityUtils.cpp Source/Activity/AWSGameLiftActivityUtils.h + Source/Activity/AWSGameLiftAcceptMatchActivity.cpp + Source/Activity/AWSGameLiftAcceptMatchActivity.h Source/Activity/AWSGameLiftCreateSessionActivity.cpp Source/Activity/AWSGameLiftCreateSessionActivity.h Source/Activity/AWSGameLiftCreateSessionOnQueueActivity.cpp diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_tests_files.cmake b/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_tests_files.cmake index f8ef40d5df..3e73dd8a0a 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_tests_files.cmake +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_tests_files.cmake @@ -7,6 +7,7 @@ # set(FILES + Tests/Activity/AWSGameLiftAcceptMatchActivityTest.cpp Tests/Activity/AWSGameLiftCreateSessionActivityTest.cpp Tests/Activity/AWSGameLiftCreateSessionOnQueueActivityTest.cpp Tests/Activity/AWSGameLiftJoinSessionActivityTest.cpp From afdf35a925d987c16d8399540f04d62212376d2c Mon Sep 17 00:00:00 2001 From: Guthrie Adams Date: Wed, 13 Oct 2021 13:41:31 -0500 Subject: [PATCH 146/169] updated material editor skybox and changed property icons Signed-off-by: Guthrie Adams --- .../Code/Source/Inspector/Icons/blank.png | 3 +++ .../Inspector/Icons/changed_property.svg | 5 +++++ .../Code/Source/Inspector/InspectorWidget.qrc | 2 ++ .../Code/Source/Window/Icons/skybox.svg | 21 ++++++------------- .../MaterialInspector/MaterialInspector.cpp | 4 ++-- .../Window/ToolBar/MaterialEditorToolBar.cpp | 12 +++++------ .../EditorMaterialComponentInspector.cpp | 4 ++-- 7 files changed, 26 insertions(+), 25 deletions(-) create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/Icons/blank.png create mode 100644 Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/Icons/changed_property.svg diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/Icons/blank.png b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/Icons/blank.png new file mode 100644 index 0000000000..d040fa2e14 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/Icons/blank.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:81b5fa1f978888c3be8a40fce20455668df2723a77587aeb7039f8bf74bdd0e3 +size 119 diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/Icons/changed_property.svg b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/Icons/changed_property.svg new file mode 100644 index 0000000000..c33e340a54 --- /dev/null +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/Icons/changed_property.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.qrc b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.qrc index 81a962801d..76733c52ed 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.qrc +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/Inspector/InspectorWidget.qrc @@ -2,5 +2,7 @@ Icons/group_closed.png Icons/group_open.png + Icons/blank.png + Icons/changed_property.svg diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/Icons/skybox.svg b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/Icons/skybox.svg index 83df996198..a79bebdd46 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/Icons/skybox.svg +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/Icons/skybox.svg @@ -1,15 +1,6 @@ - - - - icon / Environmental / Sky Highlight - Created with Sketch. - - - - - - - - - - \ No newline at end of file + + + + + + diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp index 025de21d31..e99f456653 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/MaterialInspector/MaterialInspector.cpp @@ -101,9 +101,9 @@ namespace MaterialEditor { if (IsInstanceNodePropertyModifed(node)) { - return ":/PropertyEditor/Resources/changed_data_item.png"; + return ":/Icons/changed_property.svg"; } - return ":/PropertyEditor/Resources/blank.png"; + return ":/Icons/blank.png"; } void MaterialInspector::AddOverviewGroup() diff --git a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.cpp b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.cpp index 1e189168da..10442e0c27 100644 --- a/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.cpp +++ b/Gems/Atom/Tools/MaterialEditor/Code/Source/Window/ToolBar/MaterialEditorToolBar.cpp @@ -88,18 +88,18 @@ namespace MaterialEditor toneMappingButton->setVisible(true); addWidget(toneMappingButton); - // Add model combo box - auto modelPresetComboBox = new ModelPresetComboBox(this); - modelPresetComboBox->setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy::AdjustToContents); - modelPresetComboBox->view()->setMinimumWidth(200); - addWidget(modelPresetComboBox); - // Add lighting preset combo box auto lightingPresetComboBox = new LightingPresetComboBox(this); lightingPresetComboBox->setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy::AdjustToContents); lightingPresetComboBox->view()->setMinimumWidth(200); addWidget(lightingPresetComboBox); + // Add model combo box + auto modelPresetComboBox = new ModelPresetComboBox(this); + modelPresetComboBox->setSizeAdjustPolicy(QComboBox::SizeAdjustPolicy::AdjustToContents); + modelPresetComboBox->view()->setMinimumWidth(200); + addWidget(modelPresetComboBox); + MaterialViewportNotificationBus::Handler::BusConnect(); } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp index 665adcd568..815f14aba7 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Material/EditorMaterialComponentInspector.cpp @@ -521,9 +521,9 @@ namespace AZ { if (IsInstanceNodePropertyModifed(node)) { - return ":/PropertyEditor/Resources/changed_data_item.png"; + return ":/Icons/changed_property.svg"; } - return ":/PropertyEditor/Resources/blank.png"; + return ":/Icons/blank.png"; } bool MaterialPropertyInspector::SaveMaterial() const From f1fa0acbb483cd7a917a2051a922c0d6bdac6e20 Mon Sep 17 00:00:00 2001 From: sweeneys Date: Wed, 13 Oct 2021 11:44:15 -0700 Subject: [PATCH 147/169] Stabilize asset processor immediately exiting Signed-off-by: sweeneys --- Tools/LyTestTools/ly_test_tools/o3de/asset_processor.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Tools/LyTestTools/ly_test_tools/o3de/asset_processor.py b/Tools/LyTestTools/ly_test_tools/o3de/asset_processor.py index 0623715350..682fcd3560 100644 --- a/Tools/LyTestTools/ly_test_tools/o3de/asset_processor.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/asset_processor.py @@ -488,6 +488,9 @@ class AssetProcessor(object): logger.info(f"Launching AP with command: {command}") try: self._ap_proc = subprocess.Popen(command, cwd=ap_exe_path, env=process_utils.get_display_env()) + time.sleep(1) + if self._ap_proc.poll() is not None: + raise AssetProcessorError(f"AssetProcessor immediately quit with errorcode {self._ap_proc.returncode}") if accept_input: self.connect_control() @@ -506,10 +509,11 @@ class AssetProcessor(object): logger.exception("Exception while starting Asset Processor", be) # clean up to avoid leaking open AP process to future tests try: - self._ap_proc.kill() + if self._ap_proc: + self._ap_proc.kill() except Exception as ex: logger.exception("Ignoring exception while trying to terminate Asset Processor", ex) - raise # raise whatever prompted us to clean up + raise be # raise whatever prompted us to clean up def connect_listen(self, timeout=DEFAULT_TIMEOUT_SECONDS): # Wait for the AP we launched to be ready to accept a connection From da3a39a6a040abddc6267a7750a65e20da4d878b Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Wed, 13 Oct 2021 12:37:07 -0700 Subject: [PATCH 148/169] LYN-7121 | Focus Mode - Make editing a prefab an undoable operation (#4582) * Refactor the PrefabFocusInterface to differentiate between Public and Internal functions. Introduce PrefabFocusUndo nodes to allow undoing Prefab Edit operations. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Fix selection code to avoid warning message Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Removed changed property from PrefabFocusUndo node Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Switch from size == 0 to empty in EntityOutlinerWidget::OnSelectionChanged Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * condense if check on Prefab Edit context menu item setup Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Correct interface usage in PrefabIntegrationManager (interface was renamed to public) Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Remove rej file that was included by mistake Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Fix missing interface initialization in PrefabFocusTests Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../Prefab/PrefabFocusHandler.cpp | 74 ++++++++++++++----- .../Prefab/PrefabFocusHandler.h | 10 ++- .../Prefab/PrefabFocusInterface.h | 20 +---- .../Prefab/PrefabFocusPublicInterface.h | 53 +++++++++++++ .../Prefab/PrefabFocusUndo.cpp | 52 +++++++++++++ .../AzToolsFramework/Prefab/PrefabFocusUndo.h | 39 ++++++++++ .../UI/Outliner/EntityOutlinerWidget.cpp | 3 +- .../UI/Prefab/PrefabIntegrationManager.cpp | 27 +++---- .../UI/Prefab/PrefabIntegrationManager.h | 4 +- .../UI/Prefab/PrefabUiHandler.cpp | 16 ++-- .../UI/Prefab/PrefabUiHandler.h | 4 +- .../Prefab/PrefabViewportFocusPathHandler.cpp | 14 ++-- .../Prefab/PrefabViewportFocusPathHandler.h | 4 +- .../aztoolsframework_files.cmake | 3 + .../Prefab/PrefabFocus/PrefabFocusTests.cpp | 43 ++++++----- 15 files changed, 268 insertions(+), 98 deletions(-) create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusUndo.cpp create mode 100644 Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusUndo.h diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp index fcec1edd54..a79b9eb73d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.cpp @@ -8,12 +8,14 @@ #include +#include #include #include #include #include #include #include +#include namespace AzToolsFramework::Prefab { @@ -28,10 +30,12 @@ namespace AzToolsFramework::Prefab EditorEntityContextNotificationBus::Handler::BusConnect(); AZ::Interface::Register(this); + AZ::Interface::Register(this); } PrefabFocusHandler::~PrefabFocusHandler() { + AZ::Interface::Unregister(this); AZ::Interface::Unregister(this); EditorEntityContextNotificationBus::Handler::BusDisconnect(); } @@ -61,6 +65,44 @@ namespace AzToolsFramework::Prefab } PrefabFocusOperationResult PrefabFocusHandler::FocusOnOwningPrefab(AZ::EntityId entityId) + { + // Initialize Undo Batch object + ScopedUndoBatch undoBatch("Edit Prefab"); + + // Clear selection + { + const EntityIdList selectedEntities = EntityIdList{}; + auto selectionUndo = aznew SelectionCommand(selectedEntities, "Clear Selection"); + selectionUndo->SetParent(undoBatch.GetUndoBatch()); + ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::SetSelectedEntities, selectedEntities); + } + + // Edit Prefab + { + auto editUndo = aznew PrefabFocusUndo("Edit Prefab"); + editUndo->Capture(entityId); + editUndo->SetParent(undoBatch.GetUndoBatch()); + ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, editUndo); + } + + return AZ::Success(); + } + + PrefabFocusOperationResult PrefabFocusHandler::FocusOnPathIndex([[maybe_unused]] AzFramework::EntityContextId entityContextId, int index) + { + if (index < 0 || index >= m_instanceFocusVector.size()) + { + return AZ::Failure(AZStd::string("Prefab Focus Handler: Invalid index on FocusOnPathIndex.")); + } + + InstanceOptionalReference focusedInstance = m_instanceFocusVector[index]; + + FocusOnOwningPrefab(focusedInstance->get().GetContainerEntityId()); + + return AZ::Success(); + } + + PrefabFocusOperationResult PrefabFocusHandler::FocusOnPrefabInstanceOwningEntityId(AZ::EntityId entityId) { InstanceOptionalReference focusedInstance; @@ -85,18 +127,6 @@ namespace AzToolsFramework::Prefab return FocusOnPrefabInstance(focusedInstance); } - PrefabFocusOperationResult PrefabFocusHandler::FocusOnPathIndex([[maybe_unused]] AzFramework::EntityContextId entityContextId, int index) - { - if (index < 0 || index >= m_instanceFocusVector.size()) - { - return AZ::Failure(AZStd::string("Prefab Focus Handler: Invalid index on FocusOnPathIndex.")); - } - - InstanceOptionalReference focusedInstance = m_instanceFocusVector[index]; - - return FocusOnPrefabInstance(focusedInstance); - } - PrefabFocusOperationResult PrefabFocusHandler::FocusOnPrefabInstance(InstanceOptionalReference focusedInstance) { if (!focusedInstance.has_value()) @@ -122,17 +152,10 @@ namespace AzToolsFramework::Prefab if (focusedInstance->get().GetParentInstance() != AZStd::nullopt) { containerEntityId = focusedInstance->get().GetContainerEntityId(); - - // Select the container entity - AzToolsFramework::SelectEntity(containerEntityId); } else { containerEntityId = AZ::EntityId(); - - // Clear the selection - AzToolsFramework::SelectEntities({}); - } // Focus on the descendants of the container entity @@ -161,6 +184,17 @@ namespace AzToolsFramework::Prefab return m_focusedInstance; } + AZ::EntityId PrefabFocusHandler::GetFocusedPrefabContainerEntityId([[maybe_unused]] AzFramework::EntityContextId entityContextId) const + { + if (!m_focusedInstance.has_value()) + { + // PrefabFocusHandler has not been initialized yet. + return AZ::EntityId(); + } + + return m_focusedInstance->get().GetContainerEntityId(); + } + bool PrefabFocusHandler::IsOwningPrefabBeingFocused(AZ::EntityId entityId) const { if (!m_focusedInstance.has_value()) @@ -200,7 +234,7 @@ namespace AzToolsFramework::Prefab m_instanceFocusVector.clear(); // Focus on the root prefab (AZ::EntityId() will default to it) - FocusOnOwningPrefab(AZ::EntityId()); + FocusOnPrefabInstanceOwningEntityId(AZ::EntityId()); } void PrefabFocusHandler::RefreshInstanceFocusList() diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h index 2f631f772d..80b7a6859c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusHandler.h @@ -13,6 +13,7 @@ #include #include #include +#include #include namespace AzToolsFramework @@ -28,6 +29,7 @@ namespace AzToolsFramework::Prefab //! Handles Prefab Focus mode, determining which prefab file entity changes will target. class PrefabFocusHandler final : private PrefabFocusInterface + , private PrefabFocusPublicInterface , private EditorEntityContextNotificationBus::Handler { public: @@ -39,10 +41,14 @@ namespace AzToolsFramework::Prefab void Initialize(); // PrefabFocusInterface overrides ... - PrefabFocusOperationResult FocusOnOwningPrefab(AZ::EntityId entityId) override; - PrefabFocusOperationResult FocusOnPathIndex(AzFramework::EntityContextId entityContextId, int index) override; + PrefabFocusOperationResult FocusOnPrefabInstanceOwningEntityId(AZ::EntityId entityId) override; TemplateId GetFocusedPrefabTemplateId(AzFramework::EntityContextId entityContextId) const override; InstanceOptionalReference GetFocusedPrefabInstance(AzFramework::EntityContextId entityContextId) const override; + + // PrefabFocusPublicInterface overrides ... + PrefabFocusOperationResult FocusOnOwningPrefab(AZ::EntityId entityId) override; + PrefabFocusOperationResult FocusOnPathIndex(AzFramework::EntityContextId entityContextId, int index) override; + AZ::EntityId GetFocusedPrefabContainerEntityId(AzFramework::EntityContextId entityContextId) const override; bool IsOwningPrefabBeingFocused(AZ::EntityId entityId) const override; const AZ::IO::Path& GetPrefabFocusPath(AzFramework::EntityContextId entityContextId) const override; const int GetPrefabFocusPathLength(AzFramework::EntityContextId entityContextId) const override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h index 1c0f4f85e9..25c83b89bc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusInterface.h @@ -20,7 +20,7 @@ namespace AzToolsFramework::Prefab { using PrefabFocusOperationResult = AZ::Outcome; - //! Interface to handle operations related to the Prefab Focus system. + //! Interface to handle internal operations related to the Prefab Focus system. class PrefabFocusInterface { public: @@ -28,29 +28,13 @@ namespace AzToolsFramework::Prefab //! 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; - - //! Set the focused prefab instance to the instance at position index of the current path. - //! @param index The index of the instance in the current path that we want the prefab system to focus on. - virtual PrefabFocusOperationResult FocusOnPathIndex(AzFramework::EntityContextId entityContextId, int index) = 0; + virtual PrefabFocusOperationResult FocusOnPrefabInstanceOwningEntityId(AZ::EntityId entityId) = 0; //! Returns the template id of the instance the prefab system is focusing on. virtual TemplateId GetFocusedPrefabTemplateId(AzFramework::EntityContextId entityContextId) const = 0; //! Returns a reference to the instance the prefab system is focusing on. virtual InstanceOptionalReference GetFocusedPrefabInstance(AzFramework::EntityContextId entityContextId) const = 0; - - //! 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) const = 0; - - //! Returns the path from the root instance to the currently focused instance. - //! @return A path composed from the names of the container entities for the instance path. - virtual const AZ::IO::Path& GetPrefabFocusPath(AzFramework::EntityContextId entityContextId) const = 0; - - //! Returns the size of the path to the currently focused instance. - virtual const int GetPrefabFocusPathLength(AzFramework::EntityContextId entityContextId) const = 0; }; } // namespace AzToolsFramework::Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h new file mode 100644 index 0000000000..86e476b56f --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusPublicInterface.h @@ -0,0 +1,53 @@ +/* + * 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 AzToolsFramework::Prefab +{ + using PrefabFocusOperationResult = AZ::Outcome; + + //! Public Interface for external systems to utilize the Prefab Focus system. + class PrefabFocusPublicInterface + { + public: + AZ_RTTI(PrefabFocusPublicInterface, "{53EE1D18-A41F-4DB1-9B73-9448F425722E}"); + + //! Set the focused prefab instance to the owning instance of the entityId provided. Supports undo/redo. + //! @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; + + //! Set the focused prefab instance to the instance at position index of the current path. Supports undo/redo. + //! @param index The index of the instance in the current path that we want the prefab system to focus on. + virtual PrefabFocusOperationResult FocusOnPathIndex(AzFramework::EntityContextId entityContextId, int index) = 0; + + //! Returns the entity id of the container entity for the instance the prefab system is focusing on. + virtual AZ::EntityId GetFocusedPrefabContainerEntityId(AzFramework::EntityContextId entityContextId) const = 0; + + //! 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) const = 0; + + //! Returns the path from the root instance to the currently focused instance. + //! @return A path composed from the names of the container entities for the instance path. + virtual const AZ::IO::Path& GetPrefabFocusPath(AzFramework::EntityContextId entityContextId) const = 0; + + //! Returns the size of the path to the currently focused instance. + virtual const int GetPrefabFocusPathLength(AzFramework::EntityContextId entityContextId) const = 0; + }; + +} // namespace AzToolsFramework::Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusUndo.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusUndo.cpp new file mode 100644 index 0000000000..e5f664ea38 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusUndo.cpp @@ -0,0 +1,52 @@ +/* + * 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 AzToolsFramework::Prefab +{ + PrefabFocusUndo::PrefabFocusUndo(const AZStd::string& undoOperationName) + : UndoSystem::URSequencePoint(undoOperationName) + { + m_prefabFocusInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabFocusInterface, "PrefabFocusUndo - Failed to grab prefab focus interface"); + + m_prefabFocusPublicInterface = AZ::Interface::Get(); + AZ_Assert(m_prefabFocusPublicInterface, "PrefabFocusUndo - Failed to grab prefab focus public interface"); + } + + bool PrefabFocusUndo::Changed() const + { + return true; + } + + void PrefabFocusUndo::Capture(AZ::EntityId entityId) + { + auto entityContextId = AzFramework::EntityContextId::CreateNull(); + EditorEntityContextRequestBus::BroadcastResult(entityContextId, &EditorEntityContextRequests::GetEditorEntityContextId); + + m_beforeEntityId = m_prefabFocusPublicInterface->GetFocusedPrefabContainerEntityId(entityContextId); + m_afterEntityId = entityId; + } + + void PrefabFocusUndo::Undo() + { + m_prefabFocusInterface->FocusOnPrefabInstanceOwningEntityId(m_beforeEntityId); + } + + void PrefabFocusUndo::Redo() + { + m_prefabFocusInterface->FocusOnPrefabInstanceOwningEntityId(m_afterEntityId); + } + +} // namespace AzToolsFramework::Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusUndo.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusUndo.h new file mode 100644 index 0000000000..3b257b6547 --- /dev/null +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Prefab/PrefabFocusUndo.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 AzToolsFramework::Prefab +{ + class PrefabFocusInterface; + class PrefabFocusPublicInterface; + + //! Undo node for prefab focus change operations. + class PrefabFocusUndo + : public UndoSystem::URSequencePoint + { + public: + explicit PrefabFocusUndo(const AZStd::string& undoOperationName); + + bool Changed() const override; + void Capture(AZ::EntityId entityId); + + void Undo() override; + void Redo() override; + + protected: + PrefabFocusInterface* m_prefabFocusInterface = nullptr; + PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr; + + AZ::EntityId m_beforeEntityId; + AZ::EntityId m_afterEntityId; + }; +} // namespace AzToolsFramework::Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp index 459b39a290..3b48cc4967 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp @@ -324,7 +324,8 @@ namespace AzToolsFramework // Currently, the first behavior is implemented. void EntityOutlinerWidget::OnSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) { - if (m_selectionChangeInProgress || !m_enableSelectionUpdates) + if (m_selectionChangeInProgress || !m_enableSelectionUpdates + || (selected.empty() && deselected.empty())) { return; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp index 24cb71499e..6ffa3aab69 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.cpp @@ -24,11 +24,11 @@ #include #include #include -#include +#include +#include +#include #include #include -#include -#include #include #include #include @@ -39,7 +39,6 @@ #include #include - #include #include #include @@ -56,14 +55,13 @@ #include #include - namespace AzToolsFramework { namespace Prefab { ContainerEntityInterface* PrefabIntegrationManager::s_containerEntityInterface = nullptr; EditorEntityUiInterface* PrefabIntegrationManager::s_editorEntityUiInterface = nullptr; - PrefabFocusInterface* PrefabIntegrationManager::s_prefabFocusInterface = nullptr; + PrefabFocusPublicInterface* PrefabIntegrationManager::s_prefabFocusPublicInterface = nullptr; PrefabLoaderInterface* PrefabIntegrationManager::s_prefabLoaderInterface = nullptr; PrefabPublicInterface* PrefabIntegrationManager::s_prefabPublicInterface = nullptr; PrefabSystemComponentInterface* PrefabIntegrationManager::s_prefabSystemComponentInterface = nullptr; @@ -129,10 +127,10 @@ namespace AzToolsFramework return; } - s_prefabFocusInterface = AZ::Interface::Get(); - if (s_prefabFocusInterface == nullptr) + s_prefabFocusPublicInterface = AZ::Interface::Get(); + if (s_prefabFocusPublicInterface == nullptr) { - AZ_Assert(false, "Prefab - could not get PrefabFocusInterface on PrefabIntegrationManager construction."); + AZ_Assert(false, "Prefab - could not get PrefabFocusPublicInterface on PrefabIntegrationManager construction."); return; } @@ -247,12 +245,8 @@ namespace AzToolsFramework if (s_prefabPublicInterface->IsInstanceContainerEntity(selectedEntity)) { // Edit Prefab - if (prefabWipFeaturesEnabled) + if (prefabWipFeaturesEnabled && !s_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(selectedEntity)) { - bool beingEdited = s_prefabFocusInterface->IsOwningPrefabBeingFocused(selectedEntity); - - if (!beingEdited) - { QAction* editAction = menu->addAction(QObject::tr("Edit Prefab")); editAction->setToolTip(QObject::tr("Edit the prefab in focus mode.")); @@ -261,7 +255,6 @@ namespace AzToolsFramework }); itemWasShown = true; - } } // Save Prefab @@ -317,7 +310,7 @@ namespace AzToolsFramework void PrefabIntegrationManager::OnEscape() { - s_prefabFocusInterface->FocusOnOwningPrefab(AZ::EntityId()); + s_prefabFocusPublicInterface->FocusOnOwningPrefab(AZ::EntityId()); } void PrefabIntegrationManager::HandleSourceFileType(AZStd::string_view sourceFilePath, AZ::EntityId parentId, AZ::Vector3 position) const @@ -490,7 +483,7 @@ namespace AzToolsFramework void PrefabIntegrationManager::ContextMenu_EditPrefab(AZ::EntityId containerEntity) { - s_prefabFocusInterface->FocusOnOwningPrefab(containerEntity); + s_prefabFocusPublicInterface->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 6788af31e9..e8c10c150a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabIntegrationManager.h @@ -30,7 +30,7 @@ namespace AzToolsFramework namespace Prefab { - class PrefabFocusInterface; + class PrefabFocusPublicInterface; class PrefabLoaderInterface; //! Structure for saving/retrieving user settings related to prefab workflows. @@ -144,7 +144,7 @@ namespace AzToolsFramework static ContainerEntityInterface* s_containerEntityInterface; static EditorEntityUiInterface* s_editorEntityUiInterface; - static PrefabFocusInterface* s_prefabFocusInterface; + static PrefabFocusPublicInterface* s_prefabFocusPublicInterface; 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 7d1f3485aa..00522b29dc 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp @@ -10,7 +10,7 @@ #include -#include +#include #include #include @@ -35,10 +35,10 @@ namespace AzToolsFramework return; } - m_prefabFocusInterface = AZ::Interface::Get(); - if (m_prefabFocusInterface == nullptr) + m_prefabFocusPublicInterface = AZ::Interface::Get(); + if (m_prefabFocusPublicInterface == nullptr) { - AZ_Assert(false, "PrefabUiHandler - could not get PrefabFocusInterface on PrefabUiHandler construction."); + AZ_Assert(false, "PrefabUiHandler - could not get PrefabFocusPublicInterface on PrefabUiHandler construction."); return; } } @@ -83,7 +83,7 @@ namespace AzToolsFramework QIcon PrefabUiHandler::GenerateItemIcon(AZ::EntityId entityId) const { - if (m_prefabFocusInterface->IsOwningPrefabBeingFocused(entityId)) + if (m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId)) { return QIcon(m_prefabEditIconPath); } @@ -105,7 +105,7 @@ namespace AzToolsFramework const bool hasVisibleChildren = index.data(EntityOutlinerListModel::ExpandedRole).value() && index.model()->hasChildren(index); QColor backgroundColor = m_prefabCapsuleColor; - if (m_prefabFocusInterface->IsOwningPrefabBeingFocused(entityId)) + if (m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId)) { backgroundColor = m_prefabCapsuleEditColor; } @@ -191,7 +191,7 @@ namespace AzToolsFramework const bool isLastColumn = descendantIndex.column() == EntityOutlinerListModel::ColumnLockToggle; QColor borderColor = m_prefabCapsuleColor; - if (m_prefabFocusInterface->IsOwningPrefabBeingFocused(entityId)) + if (m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId)) { borderColor = m_prefabCapsuleEditColor; } @@ -329,7 +329,7 @@ namespace AzToolsFramework if (prefabWipFeaturesEnabled) { // Focus on this prefab - m_prefabFocusInterface->FocusOnOwningPrefab(entityId); + m_prefabFocusPublicInterface->FocusOnOwningPrefab(entityId); } } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h index bb7168f409..7c68d9fd95 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h @@ -15,7 +15,7 @@ namespace AzToolsFramework namespace Prefab { - class PrefabFocusInterface; + class PrefabFocusPublicInterface; class PrefabPublicInterface; }; @@ -39,7 +39,7 @@ namespace AzToolsFramework void OnDoubleClick(AZ::EntityId entityId) const override; private: - Prefab::PrefabFocusInterface* m_prefabFocusInterface = nullptr; + Prefab::PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr; Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr; static bool IsLastVisibleChild(const QModelIndex& parent, const QModelIndex& child); diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp index 6b0de5dc53..21ada94184 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.cpp @@ -8,7 +8,7 @@ #include -#include +#include namespace AzToolsFramework::Prefab { @@ -31,8 +31,8 @@ namespace AzToolsFramework::Prefab void PrefabViewportFocusPathHandler::Initialize(AzQtComponents::BreadCrumbs* breadcrumbsWidget, QToolButton* backButton) { // Get reference to the PrefabFocusInterface handler - m_prefabFocusInterface = AZ::Interface::Get(); - if (m_prefabFocusInterface == nullptr) + m_prefabFocusPublicInterface = AZ::Interface::Get(); + if (m_prefabFocusPublicInterface == nullptr) { AZ_Assert(false, "Prefab - could not get PrefabFocusInterface on PrefabViewportFocusPathHandler construction."); return; @@ -46,7 +46,7 @@ namespace AzToolsFramework::Prefab connect(m_breadcrumbsWidget, &AzQtComponents::BreadCrumbs::linkClicked, this, [&](const QString&, int linkIndex) { - m_prefabFocusInterface->FocusOnPathIndex(m_editorEntityContextId, linkIndex); + m_prefabFocusPublicInterface->FocusOnPathIndex(m_editorEntityContextId, linkIndex); } ); @@ -54,9 +54,9 @@ namespace AzToolsFramework::Prefab connect(m_backButton, &QToolButton::clicked, this, [&]() { - if (int length = m_prefabFocusInterface->GetPrefabFocusPathLength(m_editorEntityContextId); length > 1) + if (int length = m_prefabFocusPublicInterface->GetPrefabFocusPathLength(m_editorEntityContextId); length > 1) { - m_prefabFocusInterface->FocusOnPathIndex(m_editorEntityContextId, length - 2); + m_prefabFocusPublicInterface->FocusOnPathIndex(m_editorEntityContextId, length - 2); } } ); @@ -65,7 +65,7 @@ namespace AzToolsFramework::Prefab void PrefabViewportFocusPathHandler::OnPrefabFocusChanged() { // Push new Path - m_breadcrumbsWidget->pushPath(m_prefabFocusInterface->GetPrefabFocusPath(m_editorEntityContextId).c_str()); + m_breadcrumbsWidget->pushPath(m_prefabFocusPublicInterface->GetPrefabFocusPath(m_editorEntityContextId).c_str()); } } // namespace AzToolsFramework::Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.h index ce7744fb1b..a97db60e34 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabViewportFocusPathHandler.h @@ -19,7 +19,7 @@ namespace AzToolsFramework::Prefab { - class PrefabFocusInterface; + class PrefabFocusPublicInterface; class PrefabViewportFocusPathHandler : public PrefabFocusNotificationBus::Handler @@ -40,6 +40,6 @@ namespace AzToolsFramework::Prefab AzFramework::EntityContextId m_editorEntityContextId = AzFramework::EntityContextId::CreateNull(); - PrefabFocusInterface* m_prefabFocusInterface = nullptr; + PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr; }; } // namespace AzToolsFramework::Prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake index 37559564db..8dec7ab611 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/aztoolsframework_files.cmake @@ -646,6 +646,9 @@ set(FILES Prefab/PrefabFocusHandler.cpp Prefab/PrefabFocusInterface.h Prefab/PrefabFocusNotificationBus.h + Prefab/PrefabFocusPublicInterface.h + Prefab/PrefabFocusUndo.h + Prefab/PrefabFocusUndo.cpp Prefab/PrefabIdTypes.h Prefab/PrefabLoader.h Prefab/PrefabLoader.cpp diff --git a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabFocus/PrefabFocusTests.cpp b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabFocus/PrefabFocusTests.cpp index 72489b07a1..86c73e72e5 100644 --- a/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabFocus/PrefabFocusTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/Prefab/PrefabFocus/PrefabFocusTests.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include namespace UnitTest @@ -72,6 +73,9 @@ namespace UnitTest m_prefabFocusInterface = AZ::Interface::Get(); ASSERT_TRUE(m_prefabFocusInterface != nullptr); + m_prefabFocusPublicInterface = AZ::Interface::Get(); + ASSERT_TRUE(m_prefabFocusPublicInterface != nullptr); + AzToolsFramework::EditorEntityContextRequestBus::BroadcastResult( m_editorEntityContextId, &AzToolsFramework::EditorEntityContextRequestBus::Events::GetEditorEntityContextId); @@ -91,6 +95,7 @@ namespace UnitTest AZStd::unique_ptr m_rootInstance; PrefabFocusInterface* m_prefabFocusInterface = nullptr; + PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr; AzFramework::EntityContextId m_editorEntityContextId = AzFramework::EntityContextId::CreateNull(); inline static const char* CityEntityName = "City"; @@ -105,7 +110,7 @@ namespace UnitTest { // Verify FocusOnOwningPrefab works when passing the container entity of the root prefab. { - m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[CityEntityName]->GetContainerEntityId()); + m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_instanceMap[CityEntityName]->GetContainerEntityId()); EXPECT_EQ( m_prefabFocusInterface->GetFocusedPrefabTemplateId(m_editorEntityContextId), m_instanceMap[CityEntityName]->GetTemplateId()); @@ -120,7 +125,7 @@ namespace UnitTest { // Verify FocusOnOwningPrefab works when passing a nested entity of the root prefab. { - m_prefabFocusInterface->FocusOnOwningPrefab(m_entityMap[CityEntityName]->GetId()); + m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_entityMap[CityEntityName]->GetId()); EXPECT_EQ( m_prefabFocusInterface->GetFocusedPrefabTemplateId(m_editorEntityContextId), m_instanceMap[CityEntityName]->GetTemplateId()); @@ -135,7 +140,7 @@ namespace UnitTest { // Verify FocusOnOwningPrefab works when passing the container entity of a nested prefab. { - m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[CarEntityName]->GetContainerEntityId()); + m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_instanceMap[CarEntityName]->GetContainerEntityId()); EXPECT_EQ( m_prefabFocusInterface->GetFocusedPrefabTemplateId(m_editorEntityContextId), m_instanceMap[CarEntityName]->GetTemplateId()); @@ -149,7 +154,7 @@ namespace UnitTest { // Verify FocusOnOwningPrefab works when passing a nested entity of the a nested prefab. { - m_prefabFocusInterface->FocusOnOwningPrefab(m_entityMap[Passenger1EntityName]->GetId()); + m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_entityMap[Passenger1EntityName]->GetId()); EXPECT_EQ( m_prefabFocusInterface->GetFocusedPrefabTemplateId(m_editorEntityContextId), m_instanceMap[CarEntityName]->GetTemplateId()); @@ -169,7 +174,7 @@ namespace UnitTest prefabEditorEntityOwnershipInterface->GetRootPrefabInstance(); EXPECT_TRUE(rootPrefabInstance.has_value()); - m_prefabFocusInterface->FocusOnOwningPrefab(AZ::EntityId()); + m_prefabFocusPublicInterface->FocusOnOwningPrefab(AZ::EntityId()); EXPECT_EQ( m_prefabFocusInterface->GetFocusedPrefabTemplateId(m_editorEntityContextId), rootPrefabInstance->get().GetTemplateId()); @@ -183,10 +188,10 @@ namespace UnitTest { // Verify IsOwningPrefabBeingFocused returns true for all entities in a focused prefab (container/nested) { - m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[CityEntityName]->GetContainerEntityId()); + m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_instanceMap[CityEntityName]->GetContainerEntityId()); - EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[CityEntityName]->GetContainerEntityId())); - EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[CityEntityName]->GetId())); + EXPECT_TRUE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[CityEntityName]->GetContainerEntityId())); + EXPECT_TRUE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_entityMap[CityEntityName]->GetId())); } } @@ -194,13 +199,13 @@ namespace UnitTest { // Verify IsOwningPrefabBeingFocused returns false for all entities not in a focused prefab (ancestors/descendants) { - m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[StreetEntityName]->GetContainerEntityId()); + m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_instanceMap[StreetEntityName]->GetContainerEntityId()); - EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[StreetEntityName]->GetContainerEntityId())); - EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[CityEntityName]->GetContainerEntityId())); - EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[CityEntityName]->GetId())); - EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[CarEntityName]->GetContainerEntityId())); - EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger1EntityName]->GetId())); + EXPECT_TRUE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[StreetEntityName]->GetContainerEntityId())); + EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[CityEntityName]->GetContainerEntityId())); + EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_entityMap[CityEntityName]->GetId())); + EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[CarEntityName]->GetContainerEntityId())); + EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger1EntityName]->GetId())); } } @@ -208,12 +213,12 @@ namespace UnitTest { // Verify IsOwningPrefabBeingFocused returns false for all entities not in a focused prefab (siblings) { - m_prefabFocusInterface->FocusOnOwningPrefab(m_instanceMap[SportsCarEntityName]->GetContainerEntityId()); + m_prefabFocusPublicInterface->FocusOnOwningPrefab(m_instanceMap[SportsCarEntityName]->GetContainerEntityId()); - EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[SportsCarEntityName]->GetContainerEntityId())); - EXPECT_TRUE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger2EntityName]->GetId())); - EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_instanceMap[CarEntityName]->GetContainerEntityId())); - EXPECT_FALSE(m_prefabFocusInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger1EntityName]->GetId())); + EXPECT_TRUE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[SportsCarEntityName]->GetContainerEntityId())); + EXPECT_TRUE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger2EntityName]->GetId())); + EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_instanceMap[CarEntityName]->GetContainerEntityId())); + EXPECT_FALSE(m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(m_entityMap[Passenger1EntityName]->GetId())); } } From 10ab1a369fed6767a371b6afa89371ba6cb9ef01 Mon Sep 17 00:00:00 2001 From: AMZN-nggieber <52797929+AMZN-nggieber@users.noreply.github.com> Date: Wed, 13 Oct 2021 12:52:44 -0700 Subject: [PATCH 149/169] Adds Download status info UI to Gem Catalog (#4602) * Adds Download status info UI to Gem Catalog Signed-off-by: nggieber * Removed test code Signed-off-by: nggieber * Remove unused variable Signed-off-by: nggieber * Addressed PR feedback Signed-off-by: nggieber * Fixed Open3DEngine spelling Signed-off-by: nggieber --- .../ProjectManager/Resources/Download.svg | 3 + .../Resources/ProjectManager.qrc | 4 +- .../Resources/{FeatureTagClose.svg => X.svg} | 0 .../ProjectManager/Resources/in_progress.gif | 3 + .../Source/GemCatalog/GemFilterTagWidget.cpp | 2 +- .../Source/GemCatalog/GemInfo.cpp | 48 ++++++++---- .../Source/GemCatalog/GemInfo.h | 15 +++- .../Source/GemCatalog/GemItemDelegate.cpp | 77 ++++++++++++++++++- .../Source/GemCatalog/GemItemDelegate.h | 23 ++++-- .../Source/GemCatalog/GemListHeaderWidget.cpp | 4 +- .../Source/GemCatalog/GemListView.cpp | 15 +++- .../Source/GemCatalog/GemModel.cpp | 11 +++ .../Source/GemCatalog/GemModel.h | 5 +- .../ProjectManager/Source/PythonBindings.cpp | 16 +++- 14 files changed, 194 insertions(+), 32 deletions(-) create mode 100644 Code/Tools/ProjectManager/Resources/Download.svg rename Code/Tools/ProjectManager/Resources/{FeatureTagClose.svg => X.svg} (100%) create mode 100644 Code/Tools/ProjectManager/Resources/in_progress.gif diff --git a/Code/Tools/ProjectManager/Resources/Download.svg b/Code/Tools/ProjectManager/Resources/Download.svg new file mode 100644 index 0000000000..c2b0c2ce3c --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/Download.svg @@ -0,0 +1,3 @@ + + + diff --git a/Code/Tools/ProjectManager/Resources/ProjectManager.qrc b/Code/Tools/ProjectManager/Resources/ProjectManager.qrc index 30bcc1ace5..aeaf9a9248 100644 --- a/Code/Tools/ProjectManager/Resources/ProjectManager.qrc +++ b/Code/Tools/ProjectManager/Resources/ProjectManager.qrc @@ -34,9 +34,11 @@ Warning.svg Backgrounds/DefaultBackground.jpg Backgrounds/FtueBackground.jpg - FeatureTagClose.svg + X.svg Refresh.svg Edit.svg Delete.svg + Download.svg + in_progress.gif diff --git a/Code/Tools/ProjectManager/Resources/FeatureTagClose.svg b/Code/Tools/ProjectManager/Resources/X.svg similarity index 100% rename from Code/Tools/ProjectManager/Resources/FeatureTagClose.svg rename to Code/Tools/ProjectManager/Resources/X.svg diff --git a/Code/Tools/ProjectManager/Resources/in_progress.gif b/Code/Tools/ProjectManager/Resources/in_progress.gif new file mode 100644 index 0000000000..eb392a9b89 --- /dev/null +++ b/Code/Tools/ProjectManager/Resources/in_progress.gif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:64985a78205da45f4bb92b040c348d96fe7cd7277549c1f79c430469a0d3bab7 +size 166393 diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterTagWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterTagWidget.cpp index 138880f44e..69a883d169 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterTagWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemFilterTagWidget.cpp @@ -33,7 +33,7 @@ namespace O3DE::ProjectManager m_closeButton = new QPushButton(); m_closeButton->setFlat(true); - m_closeButton->setIcon(QIcon(":/FeatureTagClose.svg")); + m_closeButton->setIcon(QIcon(":/X.svg")); m_closeButton->setIconSize(QSize(12, 12)); m_closeButton->setStyleSheet("QPushButton { background-color: transparent; border: 0px }"); layout->addWidget(m_closeButton); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.cpp index 771d644617..cbdcf64162 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.cpp @@ -8,6 +8,8 @@ #include "GemInfo.h" +#include + namespace O3DE::ProjectManager { GemInfo::GemInfo(const QString& name, const QString& creator, const QString& summary, Platforms platforms, bool isAdded) @@ -29,17 +31,17 @@ namespace O3DE::ProjectManager switch (platform) { case Android: - return "Android"; + return QObject::tr("Android"); case iOS: - return "iOS"; + return QObject::tr("iOS"); case Linux: - return "Linux"; + return QObject::tr("Linux"); case macOS: - return "macOS"; + return QObject::tr("macOS"); case Windows: - return "Windows"; + return QObject::tr("Windows"); default: - return ""; + return QObject::tr(""); } } @@ -48,13 +50,13 @@ namespace O3DE::ProjectManager switch (type) { case Asset: - return "Asset"; + return QObject::tr("Asset"); case Code: - return "Code"; + return QObject::tr("Code"); case Tool: - return "Tool"; + return QObject::tr("Tool"); default: - return ""; + return QObject::tr(""); } } @@ -62,15 +64,33 @@ namespace O3DE::ProjectManager { switch (origin) { - case Open3DEEngine: - return "Open 3D Engine"; + case Open3DEngine: + return QObject::tr("Open 3D Engine"); case Local: - return "Local"; + return QObject::tr("Local"); + case Remote: + return QObject::tr("Remote"); default: - return ""; + return QObject::tr(""); } } + QString GemInfo::GetDownloadStatusString(DownloadStatus status) + { + switch (status) + { + case NotDownloaded: + return QObject::tr("Not Downloaded"); + case Downloading: + return QObject::tr("Downloading"); + case Downloaded: + return QObject::tr("Downloaded"); + case UnknownDownloadStatus: + default: + return QObject::tr(""); + } + }; + bool GemInfo::IsPlatformSupported(Platform platform) const { return (m_platforms & platform); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h index 311eeb93f6..8c6d40505a 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemInfo.h @@ -44,13 +44,23 @@ namespace O3DE::ProjectManager enum GemOrigin { - Open3DEEngine = 1 << 0, + Open3DEngine = 1 << 0, Local = 1 << 1, - NumGemOrigins = 2 + Remote = 1 << 2, + NumGemOrigins = 3 }; Q_DECLARE_FLAGS(GemOrigins, GemOrigin) static QString GetGemOriginString(GemOrigin origin); + enum DownloadStatus + { + UnknownDownloadStatus = -1, + NotDownloaded, + Downloading, + Downloaded, + }; + static QString GetDownloadStatusString(DownloadStatus status); + GemInfo() = default; GemInfo(const QString& name, const QString& creator, const QString& summary, Platforms platforms, bool isAdded); bool IsPlatformSupported(Platform platform) const; @@ -68,6 +78,7 @@ namespace O3DE::ProjectManager QString m_summary = "No summary provided."; Platforms m_platforms; Types m_types; //! Asset and/or Code and/or Tool + DownloadStatus m_downloadStatus = UnknownDownloadStatus; QStringList m_features; QString m_requirement; QString m_directoryLink; diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp index 2c7f17db32..e15c4b3b39 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.cpp @@ -10,6 +10,7 @@ #include #include #include + #include #include #include @@ -20,6 +21,7 @@ #include #include #include +#include namespace O3DE::ProjectManager { @@ -32,6 +34,11 @@ namespace O3DE::ProjectManager AddPlatformIcon(GemInfo::Linux, ":/Linux.svg"); AddPlatformIcon(GemInfo::macOS, ":/macOS.svg"); AddPlatformIcon(GemInfo::Windows, ":/Windows.svg"); + + SetStatusIcon(m_notDownloadedPixmap, ":/Download.svg"); + SetStatusIcon(m_unknownStatusPixmap, ":/X.svg"); + + m_downloadingMovie = new QMovie(":/in_progress.gif"); } void GemItemDelegate::AddPlatformIcon(GemInfo::Platform platform, const QString& iconPath) @@ -41,6 +48,25 @@ namespace O3DE::ProjectManager m_platformIcons.insert(platform, QIcon(iconPath).pixmap(static_cast(static_cast(s_platformIconSize) * aspectRatio), s_platformIconSize)); } + void GemItemDelegate::SetStatusIcon(QPixmap& m_iconPixmap, const QString& iconPath) + { + QPixmap pixmap(iconPath); + float aspectRatio = static_cast(pixmap.width()) / pixmap.height(); + int xScaler = s_statusIconSize; + int yScaler = s_statusIconSize; + + if (aspectRatio > 1.0f) + { + yScaler = static_cast(1.0f / aspectRatio * s_statusIconSize); + } + else if (aspectRatio < 1.0f) + { + xScaler = static_cast(aspectRatio * s_statusIconSize); + } + + m_iconPixmap = QPixmap(QIcon(iconPath).pixmap(xScaler, yScaler)); + } + void GemItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) const { if (!modelIndex.isValid()) @@ -56,6 +82,8 @@ namespace O3DE::ProjectManager QRect fullRect, itemRect, contentRect; CalcRects(options, fullRect, itemRect, contentRect); + QRect buttonRect = CalcButtonRect(contentRect); + QFont standardFont(options.font); standardFont.setPixelSize(static_cast(s_fontSize)); QFontMetrics standardFontMetrics(standardFont); @@ -114,7 +142,8 @@ namespace O3DE::ProjectManager const QRect summaryRect = CalcSummaryRect(contentRect, hasTags); DrawText(summary, painter, summaryRect, standardFont); - DrawButton(painter, contentRect, modelIndex); + DrawDownloadStatusIcon(painter, contentRect, buttonRect, modelIndex); + DrawButton(painter, buttonRect, modelIndex); DrawPlatformIcons(painter, contentRect, modelIndex); DrawFeatureTags(painter, contentRect, featureTags, standardFont, summaryRect); @@ -270,7 +299,7 @@ namespace O3DE::ProjectManager QRect GemItemDelegate::CalcButtonRect(const QRect& contentRect) const { - const QPoint topLeft = QPoint(contentRect.right() - s_buttonWidth - s_itemMargins.right(), contentRect.top() + contentRect.height() / 2 - s_buttonHeight / 2); + const QPoint topLeft = QPoint(contentRect.right() - s_buttonWidth, contentRect.center().y() - s_buttonHeight / 2); const QSize size = QSize(s_buttonWidth, s_buttonHeight); return QRect(topLeft, size); } @@ -378,10 +407,9 @@ namespace O3DE::ProjectManager painter->restore(); } - void GemItemDelegate::DrawButton(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const + void GemItemDelegate::DrawButton(QPainter* painter, const QRect& buttonRect, const QModelIndex& modelIndex) const { painter->save(); - const QRect buttonRect = CalcButtonRect(contentRect); QPoint circleCenter; if (GemModel::IsAdded(modelIndex)) @@ -427,4 +455,45 @@ namespace O3DE::ProjectManager return QString(); } + + void GemItemDelegate::DrawDownloadStatusIcon(QPainter* painter, const QRect& contentRect, const QRect& buttonRect, const QModelIndex& modelIndex) const + { + const GemInfo::DownloadStatus downloadStatus = GemModel::GetDownloadStatus(modelIndex); + + // Show no icon if gem is already downloaded + if (downloadStatus == GemInfo::DownloadStatus::Downloaded) + { + return; + } + + QPixmap currentFrame; + const QPixmap* statusPixmap; + if (downloadStatus == GemInfo::DownloadStatus::Downloading) + { + if (m_downloadingMovie->state() != QMovie::Running) + { + m_downloadingMovie->start(); + emit MovieStartedPlaying(m_downloadingMovie); + } + + currentFrame = m_downloadingMovie->currentPixmap(); + currentFrame = currentFrame.scaled(s_statusIconSize, s_statusIconSize); + statusPixmap = ¤tFrame; + } + else if (downloadStatus == GemInfo::DownloadStatus::NotDownloaded) + { + statusPixmap = &m_notDownloadedPixmap; + } + else + { + statusPixmap = &m_unknownStatusPixmap; + } + + QSize statusSize = statusPixmap->size(); + + painter->drawPixmap( + buttonRect.left() - s_statusButtonSpacing - statusSize.width(), + contentRect.center().y() - statusSize.height() / 2, + *statusPixmap); + } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h index 52b5a4f58e..c013be0d9e 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemItemDelegate.h @@ -49,13 +49,13 @@ namespace O3DE::ProjectManager // Margin and borders inline constexpr static QMargins s_itemMargins = QMargins(/*left=*/16, /*top=*/8, /*right=*/16, /*bottom=*/8); // Item border distances - inline constexpr static QMargins s_contentMargins = QMargins(/*left=*/20, /*top=*/12, /*right=*/15, /*bottom=*/12); // Distances of the elements within an item to the item borders + inline constexpr static QMargins s_contentMargins = QMargins(/*left=*/20, /*top=*/12, /*right=*/20, /*bottom=*/12); // Distances of the elements within an item to the item borders inline constexpr static int s_borderWidth = 4; // Button - inline constexpr static int s_buttonWidth = 55; - inline constexpr static int s_buttonHeight = 18; - inline constexpr static int s_buttonBorderRadius = 9; + inline constexpr static int s_buttonWidth = 32; + inline constexpr static int s_buttonHeight = 16; + inline constexpr static int s_buttonBorderRadius = s_buttonHeight / 2; inline constexpr static int s_buttonCircleRadius = s_buttonBorderRadius - 2; inline constexpr static qreal s_buttonFontSize = 10.0; @@ -65,6 +65,9 @@ namespace O3DE::ProjectManager inline constexpr static int s_featureTagBorderMarginY = 3; inline constexpr static int s_featureTagSpacing = 7; + signals: + void MovieStartedPlaying(const QMovie* playingMovie) const; + protected: bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& modelIndex) override; bool helpEvent(QHelpEvent* event, QAbstractItemView* view, const QStyleOptionViewItem& option, const QModelIndex& index) override; @@ -74,9 +77,10 @@ namespace O3DE::ProjectManager QRect CalcButtonRect(const QRect& contentRect) const; QRect CalcSummaryRect(const QRect& contentRect, bool hasTags) const; void DrawPlatformIcons(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const; - void DrawButton(QPainter* painter, const QRect& contentRect, const QModelIndex& modelIndex) const; + void DrawButton(QPainter* painter, const QRect& buttonRect, const QModelIndex& modelIndex) const; void DrawFeatureTags(QPainter* painter, const QRect& contentRect, const QStringList& featureTags, const QFont& standardFont, const QRect& summaryRect) const; void DrawText(const QString& text, QPainter* painter, const QRect& rect, const QFont& standardFont) const; + void DrawDownloadStatusIcon(QPainter* painter, const QRect& contentRect, const QRect& buttonRect, const QModelIndex& modelIndex) const; QAbstractItemModel* m_model = nullptr; @@ -85,5 +89,14 @@ namespace O3DE::ProjectManager void AddPlatformIcon(GemInfo::Platform platform, const QString& iconPath); inline constexpr static int s_platformIconSize = 12; QHash m_platformIcons; + + // Status icons + void SetStatusIcon(QPixmap& m_iconPixmap, const QString& iconPath); + inline constexpr static int s_statusIconSize = 16; + inline constexpr static int s_statusButtonSpacing = 5; + + QPixmap m_unknownStatusPixmap; + QPixmap m_notDownloadedPixmap; + QMovie* m_downloadingMovie = nullptr; }; } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp index ab51c7511c..10ff31f33b 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemListHeaderWidget.cpp @@ -103,11 +103,11 @@ namespace O3DE::ProjectManager QSpacerItem* horizontalSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum); columnHeaderLayout->addSpacerItem(horizontalSpacer); - QLabel* gemSelectedLabel = new QLabel(tr("Selected")); + QLabel* gemSelectedLabel = new QLabel(tr("Status")); gemSelectedLabel->setObjectName("GemCatalogHeaderLabel"); columnHeaderLayout->addWidget(gemSelectedLabel); - columnHeaderLayout->addSpacing(65); + columnHeaderLayout->addSpacing(72); vLayout->addLayout(columnHeaderLayout); } diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemListView.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemListView.cpp index f5b54a364b..cfdf7fa5b3 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemListView.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemListView.cpp @@ -9,6 +9,8 @@ #include #include +#include + namespace O3DE::ProjectManager { GemListView::GemListView(QAbstractItemModel* model, QItemSelectionModel* selectionModel, QWidget* parent) @@ -19,6 +21,17 @@ namespace O3DE::ProjectManager setModel(model); setSelectionModel(selectionModel); - setItemDelegate(new GemItemDelegate(model, this)); + GemItemDelegate* itemDelegate = new GemItemDelegate(model, this); + + connect(itemDelegate, &GemItemDelegate::MovieStartedPlaying, [=](const QMovie* playingMovie) + { + // Force redraw when movie is playing so animation is smooth + connect(playingMovie, &QMovie::frameChanged, this, [=] + { + this->viewport()->repaint(); + }); + }); + + setItemDelegate(itemDelegate); } } // namespace O3DE::ProjectManager diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp index c8911de360..35491f4ddd 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.cpp @@ -48,6 +48,7 @@ namespace O3DE::ProjectManager item->setData(gemInfo.m_features, RoleFeatures); item->setData(gemInfo.m_path, RolePath); item->setData(gemInfo.m_requirement, RoleRequirement); + item->setData(gemInfo.m_downloadStatus, RoleDownloadStatus); appendRow(item); @@ -132,6 +133,11 @@ namespace O3DE::ProjectManager return static_cast(modelIndex.data(RoleTypes).toInt()); } + GemInfo::DownloadStatus GemModel::GetDownloadStatus(const QModelIndex& modelIndex) + { + return static_cast(modelIndex.data(RoleDownloadStatus).toInt()); + } + QString GemModel::GetSummary(const QModelIndex& modelIndex) { return modelIndex.data(RoleSummary).toString(); @@ -373,6 +379,11 @@ namespace O3DE::ProjectManager return previouslyAdded && !added; } + void GemModel::SetDownloadStatus(QAbstractItemModel& model, const QModelIndex& modelIndex, GemInfo::DownloadStatus status) + { + model.setData(modelIndex, status, RoleDownloadStatus); + } + bool GemModel::HasRequirement(const QModelIndex& modelIndex) { return !modelIndex.data(RoleRequirement).toString().isEmpty(); diff --git a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h index ef2d1a903d..0d1c225f74 100644 --- a/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h +++ b/Code/Tools/ProjectManager/Source/GemCatalog/GemModel.h @@ -40,6 +40,7 @@ namespace O3DE::ProjectManager static GemInfo::GemOrigin GetGemOrigin(const QModelIndex& modelIndex); static GemInfo::Platforms GetPlatforms(const QModelIndex& modelIndex); static GemInfo::Types GetTypes(const QModelIndex& modelIndex); + static GemInfo::DownloadStatus GetDownloadStatus(const QModelIndex& modelIndex); static QString GetSummary(const QModelIndex& modelIndex); static QString GetDirectoryLink(const QModelIndex& modelIndex); static QString GetDocLink(const QModelIndex& modelIndex); @@ -64,6 +65,7 @@ namespace O3DE::ProjectManager static bool NeedsToBeRemoved(const QModelIndex& modelIndex, bool includeDependencies = false); static bool HasRequirement(const QModelIndex& modelIndex); static void UpdateDependencies(QAbstractItemModel& model, const QModelIndex& modelIndex); + static void SetDownloadStatus(QAbstractItemModel& model, const QModelIndex& modelIndex, GemInfo::DownloadStatus status); bool DoGemsToBeAddedHaveRequirements() const; bool HasDependentGemsToRemove() const; @@ -101,7 +103,8 @@ namespace O3DE::ProjectManager RoleFeatures, RoleTypes, RolePath, - RoleRequirement + RoleRequirement, + RoleDownloadStatus }; QHash m_nameToIndexMap; diff --git a/Code/Tools/ProjectManager/Source/PythonBindings.cpp b/Code/Tools/ProjectManager/Source/PythonBindings.cpp index 83f93630ac..d91f08c73e 100644 --- a/Code/Tools/ProjectManager/Source/PythonBindings.cpp +++ b/Code/Tools/ProjectManager/Source/PythonBindings.cpp @@ -668,7 +668,21 @@ namespace O3DE::ProjectManager if (gemInfo.m_creator.contains("Open 3D Engine")) { - gemInfo.m_gemOrigin = GemInfo::GemOrigin::Open3DEEngine; + gemInfo.m_gemOrigin = GemInfo::GemOrigin::Open3DEngine; + } + else if (gemInfo.m_creator.contains("Amazon Web Services")) + { + gemInfo.m_gemOrigin = GemInfo::GemOrigin::Local; + } + else if (data.contains("origin")) + { + gemInfo.m_gemOrigin = GemInfo::GemOrigin::Remote; + } + + // As long Base Open3DEngine gems are installed before first startup non-remote gems will be downloaded + if (gemInfo.m_gemOrigin != GemInfo::GemOrigin::Remote) + { + gemInfo.m_downloadStatus = GemInfo::DownloadStatus::Downloaded; } if (data.contains("user_tags")) From 718fc97bb66d07a0f04c41c100783c5c8a6adbec Mon Sep 17 00:00:00 2001 From: Scott Murray Date: Wed, 13 Oct 2021 12:57:31 -0700 Subject: [PATCH 150/169] changes from review feedback Signed-off-by: Scott Murray --- ...mponents_PostFxShapeWeightModifierAdded.py | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py index fe6362c9b7..0ba7038c47 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/tests/hydra_AtomEditorComponents_PostFxShapeWeightModifierAdded.py @@ -24,12 +24,9 @@ class Tests: postfx_layer_component = ( "Entity has a PostFX Layer component", "Entity did not have an PostFX Layer component") - shape_component = ( + tube_shape_component = ( "Entity has a Tube Shape component", "Entity did not have a Tube Shape component") - shape_undo = ( - "Entity shape component add undone", - "Entity shape component undo failed to remove shape") postfx_shape_weight_enabled = ( "PostFx Shape Weight Modifier component enabled", "PostFx Shape Weight Modifier component was not enabled.") @@ -78,8 +75,8 @@ def AtomEditorComponents_postfx_shape_weight_AddedToEntity(): 6) Add PostFX Layer component since it is required by the PostFx Shape Weight Modifier component. 7) Verify PostFx Shape Weight Modifier component is NOT enabled since it also requires a shape. 8) Add a required shape looping over a list and checking if it enables PostFX Shape Weight Modifier. - 9) Undo to remove each added shape and verify PostFX Shape Weight Modifier is not enabled - 10) Verify PostFx Shape Weight Modifier component is enabled by adding Spline and Tube Shape componen. + 9) Undo to remove each added shape and verify PostFX Shape Weight Modifier is not enabled. + 10) Verify PostFx Shape Weight Modifier component is enabled by adding Spline and Tube Shape component. 11) Enter/Exit game mode. 12) Test IsHidden. 13) Test IsVisible. @@ -146,10 +143,10 @@ def AtomEditorComponents_postfx_shape_weight_AddedToEntity(): postfx_shape_weight_entity.add_component(postfx_layer_name) Report.result(Tests.postfx_layer_component, postfx_shape_weight_entity.has_component(postfx_layer_name)) - # 7. Verify PostFx Shape Weight Modifier component not enabled because shape is also required. + # 7. Verify PostFx Shape Weight Modifier component is NOT enabled since it also requires a shape. Report.result(Tests.postfx_shape_weight_disabled, not postfx_shape_weight_component.is_enabled()) - # 8. Add remove each shape to test if the PostFX Shape Weight Modifier is enabled by having a required shape + # 8. Add a required shape looping over a list and checking if it enables PostFX Shape Weight Modifier. for shape in ['Axis Aligned Box Shape', 'Box Shape', 'Capsule Shape', 'Compound Shape', 'Cylinder Shape', 'Disk Shape', 'Polygon Prism Shape', 'Quad Shape', 'Sphere Shape', 'Vegetation Reference Shape']: postfx_shape_weight_entity.add_component(shape) @@ -158,18 +155,16 @@ def AtomEditorComponents_postfx_shape_weight_AddedToEntity(): f"Entity did not have a {shape} component") Report.result(test_shape, postfx_shape_weight_entity.has_component(shape)) - #Check if required shape allows PostFX Shape Weight Modifier to be enabled + # Check if required shape allows PostFX Shape Weight Modifier to be enabled Report.result(Tests.postfx_shape_weight_enabled, postfx_shape_weight_component.is_enabled()) - # 9. UNDO component addition and check that PostFX Shape Weight Modifier is not enabled + # 9. Undo to remove each added shape and verify PostFX Shape Weight Modifier is not enabled. general.undo() - general.idle_wait_frames(1) - Report.result(Tests.shape_undo, not postfx_shape_weight_entity.has_component(shape)) Report.result(Tests.postfx_shape_weight_disabled, not postfx_shape_weight_component.is_enabled()) - # 10. Add Tube Shape and Spline to fulfil the required shape component + # 10. Verify PostFx Shape Weight Modifier component is enabled by adding Spline and Tube Shape component. postfx_shape_weight_entity.add_components(['Spline', 'Tube Shape']) - Report.result(Tests.shape_component, postfx_shape_weight_entity.has_component('Tube Shape')) + Report.result(Tests.tube_shape_component, postfx_shape_weight_entity.has_component('Tube Shape')) Report.result(Tests.postfx_shape_weight_enabled, postfx_shape_weight_component.is_enabled()) # 11. Enter/Exit game mode. From e7d7720d020104b169b19fb9bbe323bca8b5804c Mon Sep 17 00:00:00 2001 From: amzn-mike <80125227+amzn-mike@users.noreply.github.com> Date: Wed, 13 Oct 2021 15:14:14 -0500 Subject: [PATCH 151/169] Procedural Prefabs: Don't activate prefab when saving to manifest (#4663) * Generate prefab group dom without activating prefab Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> * Fix bad merge Signed-off-by: amzn-mike <80125227+amzn-mike@users.noreply.github.com> --- .../PrefabGroup/PrefabGroupBehavior.cpp | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/Gems/Prefab/PrefabBuilder/PrefabGroup/PrefabGroupBehavior.cpp b/Gems/Prefab/PrefabBuilder/PrefabGroup/PrefabGroupBehavior.cpp index 13828e5f8c..44a95c1b6b 100644 --- a/Gems/Prefab/PrefabBuilder/PrefabGroup/PrefabGroupBehavior.cpp +++ b/Gems/Prefab/PrefabBuilder/PrefabGroup/PrefabGroupBehavior.cpp @@ -124,24 +124,10 @@ namespace AZ::SceneAPI::Behaviors return {}; } - // create instance to update the asset hints - auto instance = prefabSystemComponentInterface->InstantiatePrefab(templateId); - if (!instance) - { - AZ_Error("prefab", false, "PrefabGroup(%s) Could not instantiate prefab", prefabGroup->GetName().c_str()); - return {}; - } - - auto* instanceToTemplateInterface = AZ::Interface::Get(); - if (!instanceToTemplateInterface) - { - AZ_Error("prefab", false, "Could not get InstanceToTemplateInterface"); - return {}; - } - - // fill out a JSON DOM + const rapidjson::Document& generatedInstanceDom = prefabSystemComponentInterface->FindTemplateDom(templateId); auto proceduralPrefab = AZStd::make_unique(rapidjson::kObjectType); - instanceToTemplateInterface->GenerateDomForInstance(*proceduralPrefab.get(), *instance.get()); + proceduralPrefab->CopyFrom(generatedInstanceDom, proceduralPrefab->GetAllocator(), true); + return proceduralPrefab; } From 29b62c7b842f77872ec9467aeabb14685e5d53cc Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Wed, 13 Oct 2021 15:22:25 -0500 Subject: [PATCH 152/169] Various updates to get pak builds working (#4552) * Various updates to get pak builds working -Fix basing config file merges off engine root. -Merge command-line in relelase to make sure they override defaults. -Fix nullptrs. -Exclude more paths from being sent to bootstrap setreg. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Reverting a change that caused some test failures. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Change tabs to spaces Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- .../AzGameFramework/Application/GameApplication.cpp | 2 ++ .../Code/Source/Grid/GridComponentController.cpp | 4 ++++ .../Code/Source/SkyBox/HDRiSkyboxComponentController.cpp | 2 +- Registry/setregbuilder.assetprocessor.setreg | 7 ++++++- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp index 462de43262..0cce93d751 100644 --- a/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp +++ b/Code/Framework/AzGameFramework/AzGameFramework/Application/GameApplication.cpp @@ -96,6 +96,8 @@ namespace AzGameFramework AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, false); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_ProjectUserRegistry(registry, AZ_TRAIT_OS_PLATFORM_CODENAME, specializations, &scratchBuffer); AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, true); +#else + AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_CommandLine(registry, m_commandLine, false); #endif // Update the Runtime file paths in case the "{BootstrapSettingsRootKey}/assets" key was overriden by a setting registry AZ::SettingsRegistryMergeUtils::MergeSettingsToRegistry_AddRuntimeFilePaths(registry); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Grid/GridComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Grid/GridComponentController.cpp index 52a4cd4343..b4131894f4 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Grid/GridComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Grid/GridComponentController.cpp @@ -175,6 +175,10 @@ namespace AZ void GridComponentController::OnBeginPrepareRender() { auto* auxGeomFP = AZ::RPI::Scene::GetFeatureProcessorForEntity(m_entityId); + if (!auxGeomFP) + { + return; + } if (auto auxGeom = auxGeomFP->GetDrawQueue()) { BuildGrid(); diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/HDRiSkyboxComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/HDRiSkyboxComponentController.cpp index b71ba1e148..171c5e417f 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/HDRiSkyboxComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/HDRiSkyboxComponentController.cpp @@ -65,7 +65,7 @@ namespace AZ m_featureProcessorInterface = RPI::Scene::GetFeatureProcessorForEntity(entityId); // only activate if there is no other skybox activate - if (!m_featureProcessorInterface->IsEnabled()) + if (m_featureProcessorInterface && !m_featureProcessorInterface->IsEnabled()) { m_featureProcessorInterface->SetSkyboxMode(SkyBoxMode::Cubemap); m_featureProcessorInterface->Enable(true); diff --git a/Registry/setregbuilder.assetprocessor.setreg b/Registry/setregbuilder.assetprocessor.setreg index 00e6e2f7f8..d67b6047f6 100644 --- a/Registry/setregbuilder.assetprocessor.setreg +++ b/Registry/setregbuilder.assetprocessor.setreg @@ -20,8 +20,13 @@ "Excludes": [ "/Amazon/AzCore/Runtime", + "/Amazon/AzCore/Bootstrap/engine_path", "/Amazon/AzCore/Bootstrap/project_path", - "/O3DE/Runtime", + "/Amazon/AzCore/Bootstrap/project_cache_path", + "/Amazon/AzCore/Bootstrap/project_user_path", + "/Amazon/AzCore/Bootstrap/project_log_path", + "/Amazon/Project/Settings/Build/project_build_path", + "/O3DE/Runtime" ] } } From 3934ac24e00135d79a01101c8f590ffac088e521 Mon Sep 17 00:00:00 2001 From: allisaurus <34254888+allisaurus@users.noreply.github.com> Date: Wed, 13 Oct 2021 13:25:19 -0700 Subject: [PATCH 153/169] Add field titles, tooltips to AWSClientAuth AWSCognitoUserManagementRequestBus nodes (#4613) Signed-off-by: Stanko --- .../Source/AWSClientAuthSystemComponent.cpp | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/Gems/AWSClientAuth/Code/Source/AWSClientAuthSystemComponent.cpp b/Gems/AWSClientAuth/Code/Source/AWSClientAuthSystemComponent.cpp index dbde19aad6..92c01dab19 100644 --- a/Gems/AWSClientAuth/Code/Source/AWSClientAuthSystemComponent.cpp +++ b/Gems/AWSClientAuth/Code/Source/AWSClientAuthSystemComponent.cpp @@ -33,7 +33,7 @@ namespace AWSClientAuth AZ::SerializeContext* serialize = azrtti_cast(context); if (serialize) { - serialize->Class()->Version(1); + serialize->Class()->Version(2); if (AZ::EditContext* ec = serialize->GetEditContext()) { @@ -105,12 +105,22 @@ namespace AWSClientAuth behaviorContext->EBus("AWSCognitoUserManagementRequestBus") ->Attribute(AZ::Script::Attributes::Category, SerializeComponentName) ->Event("Initialize", &AWSCognitoUserManagementRequestBus::Events::Initialize) - ->Event("EmailSignUpAsync", &AWSCognitoUserManagementRequestBus::Events::EmailSignUpAsync) - ->Event("PhoneSignUpAsync", &AWSCognitoUserManagementRequestBus::Events::PhoneSignUpAsync) - ->Event("ConfirmSignUpAsync", &AWSCognitoUserManagementRequestBus::Events::ConfirmSignUpAsync) - ->Event("ForgotPasswordAsync", &AWSCognitoUserManagementRequestBus::Events::ForgotPasswordAsync) - ->Event("ConfirmForgotPasswordAsync", &AWSCognitoUserManagementRequestBus::Events::ConfirmForgotPasswordAsync) - ->Event("EnableMFAAsync", &AWSCognitoUserManagementRequestBus::Events::EnableMFAAsync); + ->Event( + "EmailSignUpAsync", &AWSCognitoUserManagementRequestBus::Events::EmailSignUpAsync, + { { { "Username", "The client's username" }, { "Password", "The client's password" }, { "Email", "The email address used to sign up" } } }) + ->Event( + "PhoneSignUpAsync", &AWSCognitoUserManagementRequestBus::Events::PhoneSignUpAsync, + { { { "Username", "The client's username" }, { "Password", "The client's password" }, { "Phone number", "The phone number used to sign up" } } }) + ->Event( + "ConfirmSignUpAsync", &AWSCognitoUserManagementRequestBus::Events::ConfirmSignUpAsync, + { { { "Username", "The client's username" }, { "Confirmation code", "The client's confirmation code" } } }) + ->Event( + "ForgotPasswordAsync", &AWSCognitoUserManagementRequestBus::Events::ForgotPasswordAsync, + { { { "Username", "The client's username" } } }) + ->Event( + "ConfirmForgotPasswordAsync", &AWSCognitoUserManagementRequestBus::Events::ConfirmForgotPasswordAsync, + { { { "Username", "The client's username" }, { "Confirmation code", "The client's confirmation code" }, { "New password", "The new password for the client" } } }) + ->Event("EnableMFAAsync", &AWSCognitoUserManagementRequestBus::Events::EnableMFAAsync, { { { "Access token", "The MFA access token" } } }); behaviorContext->EBus("AuthenticationProviderNotificationBus") From 3c3cde99bed5f589c7522243b029e9f79baa949d Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Wed, 13 Oct 2021 13:33:59 -0700 Subject: [PATCH 154/169] LYN-7189 | Outliner - Disable context menu if right clicking on disabled entity (#4651) * Don't allow right clicking on a non selectable entity in the Outliner Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Also check that the index is valid to still allow the right click context menu to appear on empty areas of the widget. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Change if check to a more readable bool. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp index 3b48cc4967..4d53102edb 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp @@ -553,6 +553,13 @@ namespace AzToolsFramework return; } + // Do not display the context menu if the item under the mouse cursor is not selectable. + if (const QModelIndex& index = m_gui->m_objectTree->indexAt(pos); index.isValid() + && (index.flags() & Qt::ItemIsSelectable) == 0) + { + return; + } + QMenu* contextMenu = new QMenu(this); // Populate global context menu. From 4625e6d315fae6b343604d3e9654745bd352ee52 Mon Sep 17 00:00:00 2001 From: brianherrera Date: Wed, 13 Oct 2021 13:35:44 -0700 Subject: [PATCH 155/169] Fix indentation Signed-off-by: brianherrera --- .../build/bootstrap/incremental_build_util.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/build/bootstrap/incremental_build_util.py b/scripts/build/bootstrap/incremental_build_util.py index 6117fe0180..68e764e56f 100644 --- a/scripts/build/bootstrap/incremental_build_util.py +++ b/scripts/build/bootstrap/incremental_build_util.py @@ -333,14 +333,14 @@ def mount_volume_to_device(created): attribute disk clear readonly """.encode('utf-8')) # assume disk # for now - if created: - print('Creating filesystem on new volume') - f.write("""create partition primary - select partition 1 - format quick fs=ntfs - assign - active - """.encode('utf-8')) + if created: + print('Creating filesystem on new volume') + f.write("""create partition primary + select partition 1 + format quick fs=ntfs + assign + active + """.encode('utf-8')) subprocess.call(['diskpart', '/s', f.name]) From 5ba30f9a3746af4550ba4b0bcd89519e5375dfac Mon Sep 17 00:00:00 2001 From: Nicholas Lawson <70027408+lawsonamzn@users.noreply.github.com> Date: Wed, 13 Oct 2021 13:46:20 -0700 Subject: [PATCH 156/169] Update tiff to the new package revision (fixes IOS TIFF package) (#4638) The new tiff package works for all platforms, including android and IOS, which had issues before. Android - was missing tiff.h ios - wrong minimum ios revision --- Code/Editor/CMakeLists.txt | 2 +- Code/Legacy/CrySystem/CMakeLists.txt | 2 +- Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt | 2 +- cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake | 2 +- cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake | 2 +- cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake | 2 +- cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake | 2 +- cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Code/Editor/CMakeLists.txt b/Code/Editor/CMakeLists.txt index 2ea0aa1a74..bdfac373eb 100644 --- a/Code/Editor/CMakeLists.txt +++ b/Code/Editor/CMakeLists.txt @@ -102,7 +102,7 @@ ly_add_target( 3rdParty::Qt::Gui 3rdParty::Qt::Widgets 3rdParty::Qt::Concurrent - 3rdParty::tiff + 3rdParty::TIFF 3rdParty::squish-ccr 3rdParty::AWSNativeSDK::STS Legacy::CryCommon diff --git a/Code/Legacy/CrySystem/CMakeLists.txt b/Code/Legacy/CrySystem/CMakeLists.txt index 4c1f0d9b82..ebfc866f4a 100644 --- a/Code/Legacy/CrySystem/CMakeLists.txt +++ b/Code/Legacy/CrySystem/CMakeLists.txt @@ -27,7 +27,7 @@ ly_add_target( 3rdParty::expat 3rdParty::lz4 3rdParty::md5 - 3rdParty::tiff + 3rdParty::TIFF 3rdParty::zstd Legacy::CryCommon Legacy::CrySystem.XMLBinary diff --git a/Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt b/Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt index 836f173632..982ec43715 100644 --- a/Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt +++ b/Gems/Atom/Asset/ImageProcessingAtom/Code/CMakeLists.txt @@ -64,7 +64,7 @@ ly_add_target( 3rdParty::Qt::Gui 3rdParty::astc-encoder 3rdParty::squish-ccr - 3rdParty::tiff + 3rdParty::TIFF 3rdParty::ISPCTexComp 3rdParty::ilmbase AZ::AzFramework diff --git a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake index c1a770d1ff..9dbdbbd8aa 100644 --- a/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake +++ b/cmake/3rdParty/Platform/Android/BuiltInPackages_android.cmake @@ -16,7 +16,7 @@ ly_associate_package(PACKAGE_NAME zstd-1.35-multiplatform TARGETS zst ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS glad PACKAGE_HASH ff97ee9664e97d0854b52a3734c2289329d9f2b4cd69478df6d0ca1f1c9392ee) ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux_core PACKAGE_HASH c8c13cf7bc351643e1abd294d0841b24dee60e51647dff13db7aec396ad1e0b5) # platform-specific: -ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev2-android TARGETS tiff PACKAGE_HASH 252b99e5886ec59fdccf38603c1399dd3fc02d878641aba35a7f8d2504065a06) +ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev4-android TARGETS TIFF PACKAGE_HASH 2c62cdf34a8ee6c7eb091d05d98f60b4da7634c74054d4dbb8736886182f4589) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-android TARGETS freetype PACKAGE_HASH df9e4d559ea0f03b0666b48c79813b1cd4d9624429148a249865de9f5c2c11cd) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.9.50-rev1-android TARGETS AWSNativeSDK PACKAGE_HASH 33771499f9080cbaab613459927e52911e68f94fa356397885e85005efbd1490) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-android TARGETS Lua PACKAGE_HASH 1f638e94a17a87fe9e588ea456d5893876094b4db191234380e4c4eb9e06c300) diff --git a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake index 8e4a3ef828..d6fdc5cd9b 100644 --- a/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake +++ b/cmake/3rdParty/Platform/Linux/BuiltInPackages_linux.cmake @@ -23,7 +23,7 @@ ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform # platform-specific: ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-linux TARGETS AWSGameLiftServerSDK PACKAGE_HASH a8149a95bd100384af6ade97e2b21a56173740d921e6c3da8188cd51554d39af) -ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev2-linux TARGETS tiff PACKAGE_HASH 19791da0a370470a6c187199f97c2c46efcc2d89146e2013775fb3600fd7317d) +ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev3-linux TARGETS TIFF PACKAGE_HASH 2377f48b2ebc2d1628d9f65186c881544c92891312abe478a20d10b85877409a) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-linux TARGETS freetype PACKAGE_HASH 3f10c703d9001ecd2bb51a3bd003d3237c02d8f947ad0161c0252fdc54cbcf97) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev6-linux TARGETS AWSNativeSDK PACKAGE_HASH 490291e4c8057975c3ab86feb971b8a38871c58bac5e5d86abdd1aeb7141eec4) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-linux TARGETS Lua PACKAGE_HASH 1adc812abe3dd0dbb2ca9756f81d8f0e0ba45779ac85bf1d8455b25c531a38b0) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index 631c42784a..41df718b71 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -25,7 +25,7 @@ ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform # platform-specific: ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev3-mac TARGETS DirectXShaderCompilerDxc PACKAGE_HASH 3f77367dbb0342136ec4ebbd44bc1fedf7198089a0f83c5631248530769b2be6) ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-mac TARGETS SPIRVCross PACKAGE_HASH 78c6376ed2fd195b9b1f5fb2b56e5267a32c3aa21fb399e905308de470eb4515) -ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev2-mac TARGETS tiff PACKAGE_HASH b6f3040319f5bfe465d7e3f9b12ceed0dc951e66e05562beaac1c8da3b1b5d3f) +ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev3-mac TARGETS TIFF PACKAGE_HASH c2615ccdadcc0e1d6c5ed61e5965c4d3a82193d206591b79b805c3b3ff35a4bf) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-mac TARGETS freetype PACKAGE_HASH f159b346ac3251fb29cb8dd5f805c99b0015ed7fdb3887f656945ca701a61d0d) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev5-mac TARGETS AWSNativeSDK PACKAGE_HASH ffb890bd9cf23afb429b9214ad9bac1bf04696f07a0ebb93c42058c482ab2f01) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev6-mac TARGETS Lua PACKAGE_HASH b9079fd35634774c9269028447562c6b712dbc83b9c64975c095fd423ff04c08) diff --git a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake index 428e5e9526..cccd2591e8 100644 --- a/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake +++ b/cmake/3rdParty/Platform/Windows/BuiltInPackages_windows.cmake @@ -26,7 +26,7 @@ ly_associate_package(PACKAGE_NAME xxhash-0.7.4-rev1-multiplatform ly_associate_package(PACKAGE_NAME AWSGameLiftServerSDK-3.4.1-rev1-windows TARGETS AWSGameLiftServerSDK PACKAGE_HASH a0586b006e4def65cc25f388de17dc475e417dc1e6f9d96749777c88aa8271b0) ly_associate_package(PACKAGE_NAME DirectXShaderCompilerDxc-1.6.2104-o3de-rev3-windows TARGETS DirectXShaderCompilerDxc PACKAGE_HASH 803e10b94006b834cbbdd30f562a8ddf04174c2cb6956c8399ec164ef8418d1f) ly_associate_package(PACKAGE_NAME SPIRVCross-2021.04.29-rev1-windows TARGETS SPIRVCross PACKAGE_HASH 7d601ea9d625b1d509d38bd132a1f433d7e895b16adab76bac6103567a7a6817) -ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev2-windows TARGETS tiff PACKAGE_HASH ff03464ca460fc34a8406b2a0c548ad221b10e40480b0abb954f1e649c20bad0) +ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev3-windows TARGETS TIFF PACKAGE_HASH c6000a906e6d2a0816b652e93dfbeab41c9ed73cdd5a613acd53e553d0510b60) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-windows TARGETS freetype PACKAGE_HASH 9809255f1c59b07875097aa8d8c6c21c97c47a31fb35e30f2bb93188e99a85ff) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev4-windows TARGETS AWSNativeSDK PACKAGE_HASH a900e80f7259e43aed5c847afee2599ada37f29db70505481397675bcbb6c76c) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-windows TARGETS Lua PACKAGE_HASH 136faccf1f73891e3fa3b95f908523187792e56f5b92c63c6a6d7e72d1158d40) diff --git a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake index abfba29e5a..8042c888c7 100644 --- a/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake +++ b/cmake/3rdParty/Platform/iOS/BuiltInPackages_ios.cmake @@ -17,7 +17,7 @@ ly_associate_package(PACKAGE_NAME glad-2.0.0-beta-rev2-multiplatform TARGETS gla ly_associate_package(PACKAGE_NAME lux_core-2.2-rev5-multiplatform TARGETS lux_core PACKAGE_HASH c8c13cf7bc351643e1abd294d0841b24dee60e51647dff13db7aec396ad1e0b5) # platform-specific: -ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev2-ios TARGETS tiff PACKAGE_HASH d864beb0c955a55f28c2a993843afb2ecf6e01519ddfc857cedf34fc5db68d49) +ly_associate_package(PACKAGE_NAME tiff-4.2.0.15-rev3-ios TARGETS TIFF PACKAGE_HASH e9067e88649fb6e93a926d9ed38621a9fae360a2e6f6eb24ebca63c1bc7761ea) ly_associate_package(PACKAGE_NAME freetype-2.10.4.16-ios TARGETS freetype PACKAGE_HASH 3ac3c35e056ae4baec2e40caa023d76a7a3320895ef172b6655e9261b0dc2e29) ly_associate_package(PACKAGE_NAME AWSNativeSDK-1.7.167-rev4-ios TARGETS AWSNativeSDK PACKAGE_HASH d10e7496ca705577032821011beaf9f2507689f23817bfa0ed4d2a2758afcd02) ly_associate_package(PACKAGE_NAME Lua-5.3.5-rev5-ios TARGETS Lua PACKAGE_HASH c2d3c4e67046c293049292317a7d60fdb8f23effeea7136aefaef667163e5ffe) From b792ff3d33002c121e083562f476bacbb1c8fce0 Mon Sep 17 00:00:00 2001 From: brianherrera Date: Wed, 13 Oct 2021 14:12:18 -0700 Subject: [PATCH 157/169] Fix command formatting Signed-off-by: brianherrera --- scripts/build/bootstrap/incremental_build_util.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/build/bootstrap/incremental_build_util.py b/scripts/build/bootstrap/incremental_build_util.py index 68e764e56f..ff243ab02b 100644 --- a/scripts/build/bootstrap/incremental_build_util.py +++ b/scripts/build/bootstrap/incremental_build_util.py @@ -335,7 +335,8 @@ def mount_volume_to_device(created): if created: print('Creating filesystem on new volume') - f.write("""create partition primary + f.write(""" + create partition primary select partition 1 format quick fs=ntfs assign From 2b7262f566f3e27ee644c0c38de045bc93fcee6e Mon Sep 17 00:00:00 2001 From: sweeneys Date: Wed, 13 Oct 2021 14:14:01 -0700 Subject: [PATCH 158/169] Mock additional popen calls Signed-off-by: sweeneys --- Tools/LyTestTools/tests/unit/test_asset_processor.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Tools/LyTestTools/tests/unit/test_asset_processor.py b/Tools/LyTestTools/tests/unit/test_asset_processor.py index aabbf2f2f5..743ca9a2e4 100755 --- a/Tools/LyTestTools/tests/unit/test_asset_processor.py +++ b/Tools/LyTestTools/tests/unit/test_asset_processor.py @@ -45,6 +45,7 @@ class TestAssetProcessor(object): @mock.patch('subprocess.Popen') @mock.patch('ly_test_tools.o3de.asset_processor.AssetProcessor.connect_socket') @mock.patch('ly_test_tools.o3de.asset_processor.ASSET_PROCESSOR_PLATFORM_MAP', {'foo': 'bar'}) + @mock.patch('time.sleep', mock.MagicMock()) def test_Start_NoneRunning_ProcStarted(self, mock_connect, mock_popen, mock_workspace): mock_ap_path = 'mock_ap_path' mock_workspace.asset_processor_platform = 'foo' @@ -54,6 +55,9 @@ class TestAssetProcessor(object): under_test = ly_test_tools.o3de.asset_processor.AssetProcessor(mock_workspace) under_test.enable_asset_processor_platform = mock.MagicMock() under_test.wait_for_idle = mock.MagicMock() + mock_proc_object = mock.MagicMock() + mock_proc_object.poll.return_value = None + mock_popen.return_value = mock_proc_object under_test.start(connect_to_ap=True) From f7e2d07a4be6554141956246120d0a76f224b183 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Wed, 13 Oct 2021 14:17:09 -0700 Subject: [PATCH 159/169] LYN-7333 | Fix multiple selection by dragging to take focus mode and containers into account. (#4620) * Change FocusModeNotificationBus's OnEditorFocusChanged arguments to also pass the previous focus root entity id. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Add focus mode and container entity states to the visibility cache for the viewport. Use that data to correctly select entities when a rect is dragged on the viewport. Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Minor code adjustments Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> * Minor fixes and optimizations Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../FocusMode/FocusModeNotificationBus.h | 6 +- .../FocusMode/FocusModeSystemComponent.cpp | 3 +- .../UI/Outliner/EntityOutlinerTreeView.cpp | 3 +- .../UI/Outliner/EntityOutlinerTreeView.hxx | 2 +- .../EditorTransformComponentSelection.cpp | 2 +- .../EditorVisibleEntityDataCache.cpp | 112 +++++++++++++++++- .../EditorVisibleEntityDataCache.h | 24 ++-- 7 files changed, 136 insertions(+), 16 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeNotificationBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeNotificationBus.h index ab8629ac85..81f1f7bb3b 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeNotificationBus.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeNotificationBus.h @@ -28,8 +28,10 @@ namespace AzToolsFramework ////////////////////////////////////////////////////////////////////////// //! Triggered when the editor focus is changed to a different entity. - //! @param entityId The entity the focus has been moved to. - virtual void OnEditorFocusChanged(AZ::EntityId entityId) = 0; + //! @param previousFocusEntityId The entity the focus has been moved from. + //! @param newFocusEntityId The entity the focus has been moved to. + virtual void OnEditorFocusChanged( + [[maybe_unused]] AZ::EntityId previousFocusEntityId, [[maybe_unused]] AZ::EntityId newFocusEntityId) {} protected: ~FocusModeNotifications() = default; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp index af518afd66..f592c471d0 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/FocusMode/FocusModeSystemComponent.cpp @@ -71,8 +71,9 @@ namespace AzToolsFramework return; } + AZ::EntityId previousFocusEntityId = m_focusRoot; m_focusRoot = entityId; - FocusModeNotificationBus::Broadcast(&FocusModeNotifications::OnEditorFocusChanged, m_focusRoot); + FocusModeNotificationBus::Broadcast(&FocusModeNotifications::OnEditorFocusChanged, previousFocusEntityId, m_focusRoot); if (auto tracker = AZ::Interface::Get(); tracker != nullptr) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp index 4364ae1efc..d3138f5139 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.cpp @@ -313,7 +313,8 @@ namespace AzToolsFramework StyledTreeView::StartCustomDrag(indexListSorted, supportedActions); } - void EntityOutlinerTreeView::OnEditorFocusChanged([[maybe_unused]] AZ::EntityId entityId) + void EntityOutlinerTreeView::OnEditorFocusChanged( + [[maybe_unused]] AZ::EntityId previousFocusEntityId, [[maybe_unused]] AZ::EntityId newFocusEntityId) { viewport()->repaint(); } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx index 2ddbaaafa9..5d76ec6db2 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerTreeView.hxx @@ -64,7 +64,7 @@ namespace AzToolsFramework void leaveEvent(QEvent* event) override; // FocusModeNotificationBus overrides ... - void OnEditorFocusChanged(AZ::EntityId entityId) override; + void OnEditorFocusChanged(AZ::EntityId previousFocusEntityId, AZ::EntityId newFocusEntityId) override; //! Renders the left side of the item: appropriate background, branch lines, icons. void drawBranches(QPainter* painter, const QRect& rect, const QModelIndex& index) const override; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index 6ee5c97636..d5a0595049 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -407,7 +407,7 @@ namespace AzToolsFramework const AzFramework::CameraState cameraState = GetCameraState(viewportId); for (size_t entityCacheIndex = 0; entityCacheIndex < entityDataCache.VisibleEntityDataCount(); ++entityCacheIndex) { - if (entityDataCache.IsVisibleEntityLocked(entityCacheIndex) || !entityDataCache.IsVisibleEntityVisible(entityCacheIndex)) + if (!entityDataCache.IsVisibleEntitySelectableInViewport(entityCacheIndex)) { continue; } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.cpp index babc6f972c..328cfc3ae5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.cpp @@ -9,7 +9,9 @@ #include "EditorVisibleEntityDataCache.h" #include +#include #include +#include #include #include @@ -21,13 +23,23 @@ namespace AzToolsFramework using ComponentEntityAccentType = Components::EditorSelectionAccentSystemComponent::ComponentEntityAccentType; EntityData() = default; - EntityData(AZ::EntityId entityId, const AZ::Transform& worldFromLocal, bool locked, bool visible, bool selected, bool iconHidden); + EntityData( + AZ::EntityId entityId, + const AZ::Transform& worldFromLocal, + bool locked, + bool visible, + bool inFocus, + bool descendantOfClosedContainer, + bool selected, + bool iconHidden); AZ::Transform m_worldFromLocal; AZ::EntityId m_entityId; ComponentEntityAccentType m_accent = ComponentEntityAccentType::None; bool m_locked = false; bool m_visible = true; + bool m_inFocus = true; + bool m_descendantOfClosedContainer = false; bool m_selected = false; bool m_iconHidden = false; }; @@ -57,12 +69,16 @@ namespace AzToolsFramework const AZ::Transform& worldFromLocal, const bool locked, const bool visible, + const bool inFocus, + const bool descendantOfClosedContainer, const bool selected, const bool iconHidden) : m_worldFromLocal(worldFromLocal) , m_entityId(entityId) , m_locked(locked) , m_visible(visible) + , m_inFocus(inFocus) + , m_descendantOfClosedContainer(descendantOfClosedContainer) , m_selected(selected) , m_iconHidden(iconHidden) { @@ -106,6 +122,18 @@ namespace AzToolsFramework bool locked = false; EditorEntityInfoRequestBus::EventResult(locked, entityId, &EditorEntityInfoRequestBus::Events::IsLocked); + bool inFocus = false; + if (auto focusModeInterface = AZ::Interface::Get()) + { + inFocus = focusModeInterface->IsInFocusSubTree(entityId); + } + + bool descendantOfClosedContainer = false; + if (ContainerEntityInterface* containerEntityInterface = AZ::Interface::Get()) + { + descendantOfClosedContainer = containerEntityInterface->IsUnderClosedContainerEntity(entityId); + } + bool iconHidden = false; EditorEntityIconComponentRequestBus::EventResult( iconHidden, entityId, &EditorEntityIconComponentRequests::IsEntityIconHiddenInViewport); @@ -113,7 +141,7 @@ namespace AzToolsFramework AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity(); AZ::TransformBus::EventResult(worldFromLocal, entityId, &AZ::TransformBus::Events::GetWorldTM); - return { entityId, worldFromLocal, locked, visible, IsSelected(entityId), iconHidden }; + return { entityId, worldFromLocal, locked, visible, inFocus, descendantOfClosedContainer, IsSelected(entityId), iconHidden }; } EditorVisibleEntityDataCache::EditorVisibleEntityDataCache() @@ -126,10 +154,17 @@ namespace AzToolsFramework EntitySelectionEvents::Bus::Router::BusRouterConnect(); EditorEntityIconComponentNotificationBus::Router::BusRouterConnect(); ToolsApplicationNotificationBus::Handler::BusConnect(); + + AzFramework::EntityContextId editorEntityContextId = AzToolsFramework::GetEntityContextId(); + + ContainerEntityNotificationBus::Handler::BusConnect(editorEntityContextId); + FocusModeNotificationBus::Handler::BusConnect(editorEntityContextId); } EditorVisibleEntityDataCache::~EditorVisibleEntityDataCache() { + FocusModeNotificationBus::Handler::BusDisconnect(); + ContainerEntityNotificationBus::Handler::BusDisconnect(); ToolsApplicationNotificationBus::Handler::BusDisconnect(); EditorEntityIconComponentNotificationBus::Router::BusRouterDisconnect(); EntitySelectionEvents::Bus::Router::BusRouterDisconnect(); @@ -260,7 +295,10 @@ namespace AzToolsFramework bool EditorVisibleEntityDataCache::IsVisibleEntitySelectableInViewport(size_t index) const { - return m_impl->m_visibleEntityDatas[index].m_visible && !m_impl->m_visibleEntityDatas[index].m_locked; + return m_impl->m_visibleEntityDatas[index].m_visible + && !m_impl->m_visibleEntityDatas[index].m_locked + && m_impl->m_visibleEntityDatas[index].m_inFocus + && !m_impl->m_visibleEntityDatas[index].m_descendantOfClosedContainer; } AZStd::optional EditorVisibleEntityDataCache::GetVisibleEntityIndexFromId(const AZ::EntityId entityId) const @@ -371,4 +409,72 @@ namespace AzToolsFramework m_impl->m_visibleEntityDatas[entityIndex.value()].m_iconHidden = iconHidden; } } + + void EditorVisibleEntityDataCache::OnContainerEntityStatusChanged(AZ::EntityId entityId, [[maybe_unused]] bool open) + { + // Get container descendants + AzToolsFramework::EntityIdList descendantIds; + AZ::TransformBus::EventResult(descendantIds, entityId, &AZ::TransformBus::Events::GetAllDescendants); + + // Update cached values + if (auto containerEntityInterface = AZ::Interface::Get()) + { + for (AZ::EntityId descendantId : descendantIds) + { + if (AZStd::optional entityIndex = GetVisibleEntityIndexFromId(descendantId)) + { + m_impl->m_visibleEntityDatas[entityIndex.value()].m_descendantOfClosedContainer = + containerEntityInterface->IsUnderClosedContainerEntity(descendantId); + } + } + } + } + + void EditorVisibleEntityDataCache::OnEditorFocusChanged(AZ::EntityId previousFocusEntityId, AZ::EntityId newFocusEntityId) + { + if (previousFocusEntityId.IsValid() && newFocusEntityId.IsValid()) + { + // Get previous focus root descendants + AzToolsFramework::EntityIdList previousDescendantIds; + AZ::TransformBus::EventResult(previousDescendantIds, previousFocusEntityId, &AZ::TransformBus::Events::GetAllDescendants); + + // Get new focus root descendants + AzToolsFramework::EntityIdList newDescendantIds; + AZ::TransformBus::EventResult(newDescendantIds, newFocusEntityId, &AZ::TransformBus::Events::GetAllDescendants); + + // Merge EntityId Lists to avoid refreshing values twice + AzToolsFramework::EntityIdSet descendantsSet; + descendantsSet.insert(previousFocusEntityId); + descendantsSet.insert(newFocusEntityId); + descendantsSet.insert(previousDescendantIds.begin(), previousDescendantIds.end()); + descendantsSet.insert(newDescendantIds.begin(), newDescendantIds.end()); + + // Update cached values + if (auto focusModeInterface = AZ::Interface::Get()) + { + for (const AZ::EntityId& descendantId : descendantsSet) + { + if (AZStd::optional entityIndex = GetVisibleEntityIndexFromId(descendantId)) + { + m_impl->m_visibleEntityDatas[entityIndex.value()].m_inFocus = focusModeInterface->IsInFocusSubTree(descendantId); + } + } + } + } + else + { + // If either focus was the invalid entity, refresh all entities. + if (auto focusModeInterface = AZ::Interface::Get()) + { + for (size_t entityIndex = 0; entityIndex < m_impl->m_visibleEntityDatas.size(); ++entityIndex) + { + if (AZ::EntityId descendantId = GetVisibleEntityId(entityIndex); descendantId.IsValid()) + { + m_impl->m_visibleEntityDatas[entityIndex].m_inFocus = focusModeInterface->IsInFocusSubTree(descendantId); + } + } + } + } + } + } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h index b34defc25b..16fa1b6d14 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include #include #include #include @@ -28,6 +30,8 @@ namespace AzToolsFramework , private EntitySelectionEvents::Bus::Router , private EditorEntityIconComponentNotificationBus::Router , private ToolsApplicationNotificationBus::Handler + , private ContainerEntityNotificationBus::Handler + , private FocusModeNotificationBus::Handler { public: EditorVisibleEntityDataCache(); @@ -58,28 +62,34 @@ namespace AzToolsFramework void AddEntityIds(const EntityIdList& entityIds); private: - // ToolsApplicationNotificationBus + // ToolsApplicationNotificationBus overrides ... void AfterUndoRedo() override; - // EditorEntityVisibilityNotificationBus + // EditorEntityVisibilityNotificationBus overrides ... void OnEntityVisibilityChanged(bool visibility) override; - // EditorEntityLockComponentNotificationBus + // EditorEntityLockComponentNotificationBus overrides ... void OnEntityLockChanged(bool locked) override; - // TransformNotificationBus + // TransformNotificationBus overrides ... void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override; - // EditorComponentSelectionNotificationsBus + // EditorComponentSelectionNotificationsBus overrides ... void OnAccentTypeChanged(EntityAccentType accent) override; - // EntitySelectionEvents::Bus + // EntitySelectionEvents::Bus overrides ... void OnSelected() override; void OnDeselected() override; - // EditorEntityIconComponentNotificationBus + // EditorEntityIconComponentNotificationBus overrides ... void OnEntityIconChanged(const AZ::Data::AssetId& entityIconAssetId) override; + // ContainerEntityNotificationBus overrides ... + void OnContainerEntityStatusChanged(AZ::EntityId entityId, bool open) override; + + // FocusModeNotificationBus overrides ... + void OnEditorFocusChanged(AZ::EntityId previousFocusEntityId, AZ::EntityId newFocusEntityId) override; + class EditorVisibleEntityDataCacheImpl; AZStd::unique_ptr m_impl; //!< Internal representation of entity data cache. }; From 80dcc34e6fab19c89c6286b60668a81543009f14 Mon Sep 17 00:00:00 2001 From: amzn-phist <52085794+amzn-phist@users.noreply.github.com> Date: Wed, 13 Oct 2021 16:46:30 -0500 Subject: [PATCH 160/169] Add "Registry" folders as scan folders (#4583) * Add "Registry" folders as scan folders For projects, Gems, and Engine, add the "Registry" folder as scan folders. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Change params for adding scan folder Also add trailing newlines to setreg files. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Adjust the priority order for project templates Scan folder orders were way too high, they should be very low to become highest priority order. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Removes change of default assets folder to Assets Need to revert this change so it can be done separately. Renamed the scan folder to 'Project/Assets' to prep for Assets folder change later on. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> * Update platform configuration test to pass Adjusted expectation of scan folder count from 1 to 2 per Gem for 'Assets' and 'Registry' now. Signed-off-by: amzn-phist <52085794+amzn-phist@users.noreply.github.com> --- .../AzFramework/AzFramework/Gem/GemInfo.h | 4 +++ .../platformconfigurationtests.cpp | 14 +++++---- .../utilities/PlatformConfiguration.cpp | 18 ++++++++++++ Registry/AssetProcessorPlatformConfig.setreg | 7 ++++- .../Registry/assets_scan_folders.setreg | 29 ++++++++++++------- .../Registry/assets_scan_folders.setreg | 29 ++++++++++++------- 6 files changed, 72 insertions(+), 29 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/Gem/GemInfo.h b/Code/Framework/AzFramework/AzFramework/Gem/GemInfo.h index 1f300af770..3435d810fd 100644 --- a/Code/Framework/AzFramework/AzFramework/Gem/GemInfo.h +++ b/Code/Framework/AzFramework/AzFramework/Gem/GemInfo.h @@ -29,6 +29,10 @@ namespace AzFramework AZStd::vector m_absoluteSourcePaths; //!< Where the gem's source path folder are located(as an absolute path) static constexpr const char* GetGemAssetFolder() { return "Assets"; } + static constexpr const char* GetGemRegistryFolder() + { + return "Registry"; + } }; //! Returns a list of GemInfo of all the gems that are active for the for the specified game project. diff --git a/Code/Tools/AssetProcessor/native/tests/platformconfiguration/platformconfigurationtests.cpp b/Code/Tools/AssetProcessor/native/tests/platformconfiguration/platformconfigurationtests.cpp index 6f07901e27..69397745f1 100644 --- a/Code/Tools/AssetProcessor/native/tests/platformconfiguration/platformconfigurationtests.cpp +++ b/Code/Tools/AssetProcessor/native/tests/platformconfiguration/platformconfigurationtests.cpp @@ -590,20 +590,22 @@ TEST_F(PlatformConfigurationUnitTests, Test_GemHandling) AssetUtilities::ResetAssetRoot(); - ASSERT_EQ(2, config.GetScanFolderCount()); + ASSERT_EQ(4, config.GetScanFolderCount()); EXPECT_FALSE(config.GetScanFolderAt(0).IsRoot()); EXPECT_TRUE(config.GetScanFolderAt(0).RecurseSubFolders()); // the first one is a game gem, so its order should be above 1 but below 100. EXPECT_GE(config.GetScanFolderAt(0).GetOrder(), 100); EXPECT_EQ(0, config.GetScanFolderAt(0).ScanPath().compare(expectedScanFolder, Qt::CaseInsensitive)); - // for each gem, there are currently 1 scan folder, the gem assets folder, with no output prefix + // for each gem, there are currently 2 scan folders: + // The Gem's 'Assets' folder + // The Gem's 'Registry' folder expectedScanFolder = tempPath.absoluteFilePath("Gems/LmbrCentral/v2/Assets"); - EXPECT_FALSE(config.GetScanFolderAt(1).IsRoot() ); - EXPECT_TRUE(config.GetScanFolderAt(1).RecurseSubFolders()); - EXPECT_GT(config.GetScanFolderAt(1).GetOrder(), config.GetScanFolderAt(0).GetOrder()); - EXPECT_EQ(0, config.GetScanFolderAt(1).ScanPath().compare(expectedScanFolder, Qt::CaseInsensitive)); + EXPECT_FALSE(config.GetScanFolderAt(2).IsRoot() ); + EXPECT_TRUE(config.GetScanFolderAt(2).RecurseSubFolders()); + EXPECT_GT(config.GetScanFolderAt(2).GetOrder(), config.GetScanFolderAt(0).GetOrder()); + EXPECT_EQ(0, config.GetScanFolderAt(2).ScanPath().compare(expectedScanFolder, Qt::CaseInsensitive)); } TEST_F(PlatformConfigurationUnitTests, Test_MetaFileTypes) diff --git a/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp b/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp index 52df8e901d..4a033cf6ca 100644 --- a/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp +++ b/Code/Tools/AssetProcessor/native/utilities/PlatformConfiguration.cpp @@ -1582,6 +1582,24 @@ namespace AssetProcessor gemOrder, /*scanFolderId*/ 0, /*canSaveNewAssets*/ true)); // Users can create assets like slices in Gem asset folders. + + // Now add another scan folder on Gem/GemName/Registry... + gemFolder = gemDir.absoluteFilePath(AzFramework::GemInfo::GetGemRegistryFolder()); + gemFolder = AssetUtilities::NormalizeDirectoryPath(gemFolder); + + assetBrowserDisplayName = AzFramework::GemInfo::GetGemRegistryFolder(); + portableKey = QString("gemregistry-%1").arg(gemNameAsUuid); + gemOrder++; + + AZ_TracePrintf(AssetProcessor::DebugChannel, "Adding GEM registry folder for monitoring / scanning: %s.\n", gemFolder.toUtf8().data()); + AddScanFolder(ScanFolderInfo( + gemFolder, + assetBrowserDisplayName, + portableKey, + isRoot, + isRecursive, + platforms, + gemOrder)); } } } diff --git a/Registry/AssetProcessorPlatformConfig.setreg b/Registry/AssetProcessorPlatformConfig.setreg index 3e90b063b5..ddc465c201 100644 --- a/Registry/AssetProcessorPlatformConfig.setreg +++ b/Registry/AssetProcessorPlatformConfig.setreg @@ -106,7 +106,7 @@ // "exclude": "mac" // } - "ScanFolder Game": { + "ScanFolder Project/Assets": { "watch": "@PROJECTROOT@", "display": "@PROJECTNAME@", "recursive": 1, @@ -129,6 +129,11 @@ "order": 30000, "include": "tools,renderer" }, + "ScanFolder Engine/Registry": { + "watch": "@ENGINEROOT@/Registry", + "recursive": 1, + "order": 40000 + }, // Excludes files that match the pattern or glob // if you use a pattern, remember to escape your backslashes (\\) diff --git a/Templates/DefaultProject/Template/Registry/assets_scan_folders.setreg b/Templates/DefaultProject/Template/Registry/assets_scan_folders.setreg index a42f65efb4..05f6314da4 100644 --- a/Templates/DefaultProject/Template/Registry/assets_scan_folders.setreg +++ b/Templates/DefaultProject/Template/Registry/assets_scan_folders.setreg @@ -1,14 +1,21 @@ { - "Amazon": - { - "${Name}.Assets": - { - "SourcePaths": - [ - "Assets", - "ShaderLib", - "Shaders" - ] + "Amazon": { + "AssetProcessor": { + "ScanFolder Project/ShaderLib": { + "watch": "@PROJECTROOT@/ShaderLib", + "recursive": 1, + "order": 1 + }, + "ScanFolder Project/Shaders": { + "watch": "@PROJECTROOT@/Shaders", + "recurisve": 1, + "order": 2 + }, + "ScanFolder Project/Registry": { + "watch": "@PROJECTROOT@/Registry", + "recursive": 1, + "order": 3 + } } } -} \ No newline at end of file +} diff --git a/Templates/MinimalProject/Template/Registry/assets_scan_folders.setreg b/Templates/MinimalProject/Template/Registry/assets_scan_folders.setreg index a42f65efb4..05f6314da4 100644 --- a/Templates/MinimalProject/Template/Registry/assets_scan_folders.setreg +++ b/Templates/MinimalProject/Template/Registry/assets_scan_folders.setreg @@ -1,14 +1,21 @@ { - "Amazon": - { - "${Name}.Assets": - { - "SourcePaths": - [ - "Assets", - "ShaderLib", - "Shaders" - ] + "Amazon": { + "AssetProcessor": { + "ScanFolder Project/ShaderLib": { + "watch": "@PROJECTROOT@/ShaderLib", + "recursive": 1, + "order": 1 + }, + "ScanFolder Project/Shaders": { + "watch": "@PROJECTROOT@/Shaders", + "recurisve": 1, + "order": 2 + }, + "ScanFolder Project/Registry": { + "watch": "@PROJECTROOT@/Registry", + "recursive": 1, + "order": 3 + } } } -} \ No newline at end of file +} From 937c2b2e88c325046bc0e6933af1f169b55af406 Mon Sep 17 00:00:00 2001 From: Ken Pruiksma Date: Wed, 13 Oct 2021 16:58:23 -0500 Subject: [PATCH 161/169] Terrain FP supports macro material component (#4587) * Adding basic support for TerrainMacroMaterialNotificationBus. Tracking macro materials in list. Signed-off-by: Ken Pruiksma (cherry picked from commit b4773454334de940d730620ffff300b46d6c611d) * Adding bus connection Signed-off-by: Ken Pruiksma (cherry picked from commit 66c99f503adb24f4be4f81716b544202d8e237d9) * Additions to indexed data vector to allow for getting an index from the data or deleting data with a reference to the data itself instead of the index. Additions to the feature processor for tracking macro material indices in sectors. Signed-off-by: Ken Pruiksma (cherry picked from commit 06365dbde5454e18e5fdf941f03b17b0d632027c) * Macro materials updating which macro materials are used in which sectors. Correctly handling construction / destruction. Signed-off-by: Ken Pruiksma * Updating the terrain macro material type to have the correct properties and also not attempt to render. Refactored some of the update loop in the TerrainFP to only rebuild the sectors when necessary, otherwise just update the srgs. Signed-off-by: Ken Pruiksma * Fixed up macro material to not try to actually render anything with shaders or hook to any shader data Terrain FP now pulls data pulling from macro material instance to use in the terrain material Various bug fixes around when terrain sectors needed reprocessing Signed-off-by: Ken Pruiksma * Adding basic support for TerrainMacroMaterialNotificationBus. Tracking macro materials in list. Signed-off-by: Ken Pruiksma (cherry picked from commit b4773454334de940d730620ffff300b46d6c611d) * Adding bus connection Signed-off-by: Ken Pruiksma (cherry picked from commit 66c99f503adb24f4be4f81716b544202d8e237d9) * Additions to indexed data vector to allow for getting an index from the data or deleting data with a reference to the data itself instead of the index. Additions to the feature processor for tracking macro material indices in sectors. Signed-off-by: Ken Pruiksma (cherry picked from commit 06365dbde5454e18e5fdf941f03b17b0d632027c) * Macro materials updating which macro materials are used in which sectors. Correctly handling construction / destruction. Signed-off-by: Ken Pruiksma * Updating the terrain macro material type to have the correct properties and also not attempt to render. Refactored some of the update loop in the TerrainFP to only rebuild the sectors when necessary, otherwise just update the srgs. Signed-off-by: Ken Pruiksma * Fixed up macro material to not try to actually render anything with shaders or hook to any shader data Terrain FP now pulls data pulling from macro material instance to use in the terrain material Various bug fixes around when terrain sectors needed reprocessing Signed-off-by: Ken Pruiksma * Constify all the things Signed-off-by: Ken Pruiksma * Updates from PR review. Signed-off-by: Ken Pruiksma --- .../Atom/Feature/Utils/IndexedDataVector.h | 2 + .../Atom/Feature/Utils/IndexedDataVector.inl | 20 + .../Terrain/DefaultPbrTerrain.material | 6 - .../Materials/Terrain/PbrTerrain.materialtype | 77 --- .../Terrain/TerrainMacroMaterial.materialtype | 63 +- .../Shaders/Terrain/TerrainCommon.azsli | 26 +- .../Terrain/TerrainPBR_ForwardPass.azsl | 34 +- .../TerrainFeatureProcessor.cpp | 561 ++++++++++++++---- .../TerrainRenderer/TerrainFeatureProcessor.h | 83 ++- 9 files changed, 606 insertions(+), 266 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h index 37835bd6a8..82cc1e7d50 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.h @@ -30,6 +30,7 @@ namespace AZ::Render void Clear(); IndexType GetFreeSlotIndex(); void RemoveIndex(IndexType index); + void RemoveData(DataType* data); DataType& GetData(IndexType index); const DataType& GetData(IndexType index) const; @@ -42,6 +43,7 @@ namespace AZ::Render const AZStd::vector& GetIndexVector() const; IndexType GetRawIndex(IndexType index) const; + IndexType GetIndexForData(const DataType* data) const; private: constexpr static size_t InitialReservedSize = 128; diff --git a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl index 076caad7f4..581186dbcc 100644 --- a/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl +++ b/Gems/Atom/Feature/Common/Code/Include/Atom/Feature/Utils/IndexedDataVector.inl @@ -83,6 +83,16 @@ namespace AZ::Render m_indices.at(index) = m_firstFreeSlot; m_firstFreeSlot = index; } + + template + inline void IndexedDataVector::RemoveData(DataType* data) + { + IndexType indexForData = GetIndexForData(data); + if (indexForData != NoFreeSlot) + { + RemoveIndex(indexForData); + } + } template inline DataType& IndexedDataVector::GetData(IndexType index) @@ -131,4 +141,14 @@ namespace AZ::Render { return m_indices.at(index); } + + template + IndexType IndexedDataVector::GetIndexForData(const DataType* data) const + { + if (data >= &m_data.front() && data <= &m_data.back()) + { + return m_dataToIndices.at(data - &m_data.front()); + } + return NoFreeSlot; + } } // namespace AZ::Render diff --git a/Gems/Terrain/Assets/Materials/Terrain/DefaultPbrTerrain.material b/Gems/Terrain/Assets/Materials/Terrain/DefaultPbrTerrain.material index c0de5969b2..d2acc2516a 100644 --- a/Gems/Terrain/Assets/Materials/Terrain/DefaultPbrTerrain.material +++ b/Gems/Terrain/Assets/Materials/Terrain/DefaultPbrTerrain.material @@ -4,12 +4,6 @@ "parentMaterial": "", "propertyLayoutVersion": 1, "properties": { - "macroColor": { - "useTexture": false - }, - "macroNormal": { - "useTexture": false - }, "baseColor": { "color": [ 0.18, 0.18, 0.18 ], "useTexture": false diff --git a/Gems/Terrain/Assets/Materials/Terrain/PbrTerrain.materialtype b/Gems/Terrain/Assets/Materials/Terrain/PbrTerrain.materialtype index 191fa7a731..ec04412fe6 100644 --- a/Gems/Terrain/Assets/Materials/Terrain/PbrTerrain.materialtype +++ b/Gems/Terrain/Assets/Materials/Terrain/PbrTerrain.materialtype @@ -133,67 +133,6 @@ } } ], - "macroColor": [ - { - "id": "textureMap", - "displayName": "Texture", - "description": "Macro color texture map", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_macroColorMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture.", - "type": "Bool", - "defaultValue": true - } - - ], - "macroNormal": [ - { - "id": "textureMap", - "displayName": "Texture", - "description": "Macro normal texture map", - "type": "Image", - "connection": { - "type": "ShaderInput", - "id": "m_macroNormalMap" - } - }, - { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture.", - "type": "Bool", - "defaultValue": true - }, - { - "id": "flipX", - "displayName": "Flip X Channel", - "description": "Flip tangent direction for this normal map.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderInput", - "id": "m_flipMacroNormalX" - } - }, - { - "id": "flipY", - "displayName": "Flip Y Channel", - "description": "Flip bitangent direction for this normal map.", - "type": "Bool", - "defaultValue": false, - "connection": { - "type": "ShaderInput", - "id": "m_flipMacroNormalY" - } - } - ], "baseColor": [ { "id": "color", @@ -380,22 +319,6 @@ } ], "functors": [ - { - "type": "UseTexture", - "args": { - "textureProperty": "macroColor.textureMap", - "useTextureProperty": "macroColor.useTexture", - "shaderOption": "o_macroColor_useTexture" - } - }, - { - "type": "UseTexture", - "args": { - "textureProperty": "macroNormal.textureMap", - "useTextureProperty": "macroNormal.useTexture", - "shaderOption": "o_macroNormal_useTexture" - } - }, { "type": "UseTexture", "args": { diff --git a/Gems/Terrain/Assets/Materials/Terrain/TerrainMacroMaterial.materialtype b/Gems/Terrain/Assets/Materials/Terrain/TerrainMacroMaterial.materialtype index 0a4f6d0229..3cdab8da10 100644 --- a/Gems/Terrain/Assets/Materials/Terrain/TerrainMacroMaterial.materialtype +++ b/Gems/Terrain/Assets/Materials/Terrain/TerrainMacroMaterial.materialtype @@ -4,42 +4,59 @@ "version": 1, "groups": [ { - "id": "settings", - "displayName": "Settings" + "name": "baseColor", + "displayName": "Base Color", + "description": "Properties for configuring the surface reflected color for dielectrics or reflectance values for metals." + }, + { + "name": "normal", + "displayName": "Normal", + "description": "Properties related to configuring surface normal." } ], "properties": { - "macroColor": [ + "baseColor": [ { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture.", - "type": "Bool", - "defaultValue": true + "name": "textureMap", + "displayName": "Texture", + "description": "Base color of the macro material", + "type": "Image" } - ], - "macroNormal": [ + "normal": [ { - "id": "useTexture", - "displayName": "Use Texture", - "description": "Whether to use the texture.", + "name": "textureMap", + "displayName": "Texture", + "description": "Texture for defining surface normal direction. These will override normals generated from the geometry.", + "type": "Image" + }, + { + "name": "flipX", + "displayName": "Flip X Channel", + "description": "Flip tangent direction for this normal map.", "type": "Bool", - "defaultValue": true + "defaultValue": false + }, + { + "name": "flipY", + "displayName": "Flip Y Channel", + "description": "Flip bitangent direction for this normal map.", + "type": "Bool", + "defaultValue": false + }, + { + "name": "factor", + "displayName": "Factor", + "description": "Strength factor for scaling the values", + "type": "Float", + "defaultValue": 1.0, + "min": 0.0, + "softMax": 2.0 } ] } }, "shaders": [ - { - "file": "../../Shaders/Terrain/TerrainPBR_ForwardPass.shader" - }, - { - "file": "../../Shaders/Terrain/Terrain_Shadowmap.shader" - }, - { - "file": "../../Shaders/Terrain/Terrain_DepthPass.shader" - } ], "functors": [ ] diff --git a/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli b/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli index 95d1a73bbd..72c1af953c 100644 --- a/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli +++ b/Gems/Terrain/Assets/Shaders/Terrain/TerrainCommon.azsli @@ -26,8 +26,24 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject float m_heightScale; }; + struct MacroMaterialData + { + float2 m_uvMin; + float2 m_uvMax; + float m_normalFactor; + bool m_flipNormalX; + bool m_flipNormalY; + uint m_mapsInUse; + }; + TerrainData m_terrainData; + MacroMaterialData m_macroMaterialData[4]; + uint m_macroMaterialCount; + + Texture2D m_macroColorMap[4]; + Texture2D m_macroNormalMap[4]; + // The below shouldn't be in this SRG but needs to be for now because the lighting functions depend on them. //! Reflection Probe (smallest probe volume that overlaps the object position) @@ -101,14 +117,6 @@ ShaderResourceGroup TerrainMaterialSrg : SRG_PerMaterial MaxAnisotropy = 16; }; - // Macro Color - Texture2D m_macroColorMap; - - // Macro normal - Texture2D m_macroNormalMap; - bool m_flipMacroNormalX; - bool m_flipMacroNormalY; - // Base Color float3 m_baseColor; float m_baseColorFactor; @@ -130,8 +138,6 @@ ShaderResourceGroup TerrainMaterialSrg : SRG_PerMaterial } option bool o_useTerrainSmoothing = false; -option bool o_macroColor_useTexture = true; -option bool o_macroNormal_useTexture = true; option bool o_baseColor_useTexture = true; option bool o_specularF0_useTexture = true; option bool o_normal_useTexture = true; diff --git a/Gems/Terrain/Assets/Shaders/Terrain/TerrainPBR_ForwardPass.azsl b/Gems/Terrain/Assets/Shaders/Terrain/TerrainPBR_ForwardPass.azsl index fedd19a498..91e367500b 100644 --- a/Gems/Terrain/Assets/Shaders/Terrain/TerrainPBR_ForwardPass.azsl +++ b/Gems/Terrain/Assets/Shaders/Terrain/TerrainPBR_ForwardPass.azsl @@ -68,7 +68,6 @@ VSOutput TerrainPBR_MainPassVS(VertexInput IN) ForwardPassOutput TerrainPBR_MainPassPS(VSOutput IN) { // ------- Surface ------- - Surface surface; // Position @@ -83,12 +82,32 @@ ForwardPassOutput TerrainPBR_MainPassPS(VSOutput IN) // ------- Normal ------- float3 macroNormal = IN.m_normal; - if (o_macroNormal_useTexture) - { - macroNormal = GetNormalInputTS(TerrainMaterialSrg::m_macroNormalMap, TerrainMaterialSrg::m_sampler, - origUv, TerrainMaterialSrg::m_flipMacroNormalX, TerrainMaterialSrg::m_flipMacroNormalY, CreateIdentity3x3(), true, 1.0); - } + // ------- Macro Color / Normal ------- + float3 macroColor = TerrainMaterialSrg::m_baseColor.rgb; + [unroll] for (uint i = 0; i < 4; ++i) + { + float2 macroUvMin = ObjectSrg::m_macroMaterialData[i].m_uvMin; + float2 macroUvMax = ObjectSrg::m_macroMaterialData[i].m_uvMax; + float2 macroUv = lerp(macroUvMin, macroUvMax, IN.m_uv); + if (macroUv.x >= 0.0 && macroUv.x <= 1.0 && macroUv.y >= 0.0 && macroUv.y <= 1.0) + { + if ((ObjectSrg::m_macroMaterialData[i].m_mapsInUse & 1) > 0) + { + macroColor = GetBaseColorInput(ObjectSrg::m_macroColorMap[i], TerrainMaterialSrg::m_sampler, macroUv, macroColor, true); + } + if ((ObjectSrg::m_macroMaterialData[i].m_mapsInUse & 2) > 0) + { + bool flipX = ObjectSrg::m_macroMaterialData[i].m_flipNormalX; + bool flipY = ObjectSrg::m_macroMaterialData[i].m_flipNormalY; + bool factor = ObjectSrg::m_macroMaterialData[i].m_normalFactor; + macroNormal = GetNormalInputTS(ObjectSrg::m_macroNormalMap[i], TerrainMaterialSrg::m_sampler, + macroUv, flipX, flipY, CreateIdentity3x3(), true, factor); + } + break; + } + } + float3 detailNormal = GetNormalInputTS(TerrainMaterialSrg::m_normalMap, TerrainMaterialSrg::m_sampler, detailUv, TerrainMaterialSrg::m_flipNormalX, TerrainMaterialSrg::m_flipNormalY, CreateIdentity3x3(), o_normal_useTexture, TerrainMaterialSrg::m_normalFactor); @@ -97,9 +116,6 @@ ForwardPassOutput TerrainPBR_MainPassPS(VSOutput IN) surface.normal = normalize(surface.normal); surface.vertexNormal = normalize(IN.m_normal); - // ------- Macro Color ------- - float3 macroColor = GetBaseColorInput(TerrainMaterialSrg::m_macroColorMap, TerrainMaterialSrg::m_sampler, origUv, TerrainMaterialSrg::m_baseColor.rgb, o_baseColor_useTexture); - // ------- Base Color ------- float3 detailColor = GetBaseColorInput(TerrainMaterialSrg::m_baseColorMap, TerrainMaterialSrg::m_sampler, detailUv, TerrainMaterialSrg::m_baseColor.rgb, o_baseColor_useTexture); float3 blendedColor = BlendBaseColor(lerp(detailColor, TerrainMaterialSrg::m_baseColor.rgb, detailFactor), macroColor, TerrainMaterialSrg::m_baseColorFactor, o_baseColorTextureBlendMode, o_baseColor_useTexture); diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp index 560fe1eb60..d7300cdc48 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.cpp @@ -49,13 +49,25 @@ namespace Terrain namespace MaterialInputs { + // Terrain material static const char* const HeightmapImage("settings.heightmapImage"); + + // Macro material + static const char* const MacroColorTextureMap("baseColor.textureMap"); + static const char* const MacroNormalTextureMap("normal.textureMap"); + static const char* const MacroNormalFlipX("normal.flipX"); + static const char* const MacroNormalFlipY("normal.flipY"); + static const char* const MacroNormalFactor("normal.factor"); } namespace ShaderInputs { static const char* const ModelToWorld("m_modelToWorld"); static const char* const TerrainData("m_terrainData"); + static const char* const MacroMaterialData("m_macroMaterialData"); + static const char* const MacroMaterialCount("m_macroMaterialCount"); + static const char* const MacroColorMap("m_macroColorMap"); + static const char* const MacroNormalMap("m_macroNormalMap"); } @@ -71,8 +83,6 @@ namespace Terrain void TerrainFeatureProcessor::Activate() { - m_areaData = {}; - m_dirtyRegion = AZ::Aabb::CreateNull(); Initialize(); AzFramework::Terrain::TerrainDataNotificationBus::Handler::BusConnect(); } @@ -94,6 +104,10 @@ namespace Terrain { AZ_Error("TerrainFeatureProcessor", false, "No per-object ShaderResourceGroup found on terrain material."); } + else + { + PrepareMaterialData(); + } } } ); @@ -107,11 +121,17 @@ namespace Terrain void TerrainFeatureProcessor::Deactivate() { + TerrainMacroMaterialNotificationBus::Handler::BusDisconnect(); AzFramework::Terrain::TerrainDataNotificationBus::Handler::BusDisconnect(); AZ::RPI::MaterialReloadNotificationBus::Handler::BusDisconnect(); m_patchModel = {}; m_areaData = {}; + m_dirtyRegion = AZ::Aabb::CreateNull(); + m_sectorData.clear(); + m_macroMaterials.Clear(); + m_materialAssetLoader = {}; + m_materialInstance = {}; } void TerrainFeatureProcessor::Render(const AZ::RPI::FeatureProcessor::RenderPacket& packet) @@ -126,7 +146,7 @@ namespace Terrain void TerrainFeatureProcessor::OnTerrainDataChanged(const AZ::Aabb& dirtyRegion, TerrainDataChangedMask dataChangedMask) { - if (dataChangedMask != TerrainDataChangedMask::HeightData && dataChangedMask != TerrainDataChangedMask::Settings) + if ((dataChangedMask & (TerrainDataChangedMask::HeightData | TerrainDataChangedMask::Settings)) == 0) { return; } @@ -140,14 +160,21 @@ namespace Terrain m_dirtyRegion.AddAabb(regionToUpdate); m_dirtyRegion.Clamp(worldBounds); - AZ::Transform transform = AZ::Transform::CreateTranslation(worldBounds.GetCenter()); + const AZ::Transform transform = AZ::Transform::CreateTranslation(worldBounds.GetCenter()); AZ::Vector2 queryResolution = AZ::Vector2(1.0f); AzFramework::Terrain::TerrainDataRequestBus::BroadcastResult( queryResolution, &AzFramework::Terrain::TerrainDataRequests::GetTerrainHeightQueryResolution); + // Sectors need to be rebuilt if the world bounds change in the x/y, or the sample spacing changes. + m_areaData.m_rebuildSectors = m_areaData.m_rebuildSectors || + m_areaData.m_terrainBounds.GetMin().GetX() != worldBounds.GetMin().GetX() || + m_areaData.m_terrainBounds.GetMin().GetY() != worldBounds.GetMin().GetY() || + m_areaData.m_terrainBounds.GetMax().GetX() != worldBounds.GetMax().GetX() || + m_areaData.m_terrainBounds.GetMax().GetY() != worldBounds.GetMax().GetY() || + m_areaData.m_sampleSpacing != queryResolution.GetX(); + m_areaData.m_transform = transform; - m_areaData.m_heightScale = worldBounds.GetZExtent(); m_areaData.m_terrainBounds = worldBounds; m_areaData.m_heightmapImageWidth = aznumeric_cast(worldBounds.GetXExtent() / queryResolution.GetX()); m_areaData.m_heightmapImageHeight = aznumeric_cast(worldBounds.GetYExtent() / queryResolution.GetY()); @@ -155,7 +182,93 @@ namespace Terrain m_areaData.m_updateHeight = aznumeric_cast(m_dirtyRegion.GetYExtent() / queryResolution.GetY()); // Currently query resolution is multidimensional but the rendering system only supports this changing in one dimension. m_areaData.m_sampleSpacing = queryResolution.GetX(); - m_areaData.m_propertiesDirty = true; + m_areaData.m_heightmapUpdated = true; + } + + void TerrainFeatureProcessor::OnTerrainMacroMaterialCreated(AZ::EntityId entityId, MaterialInstance material, const AZ::Aabb& region) + { + MacroMaterialData& materialData = FindOrCreateMacroMaterial(entityId); + materialData.m_bounds = region; + + UpdateMacroMaterialData(materialData, material); + + // Update all sectors in region. + ForOverlappingSectors(materialData.m_bounds, + [&](SectorData& sectorData) { + if (sectorData.m_macroMaterials.size() < sectorData.m_macroMaterials.max_size()) + { + sectorData.m_macroMaterials.push_back(m_macroMaterials.GetIndexForData(&materialData)); + } + } + ); + } + + void TerrainFeatureProcessor::OnTerrainMacroMaterialChanged(AZ::EntityId entityId, MaterialInstance macroMaterial) + { + if (macroMaterial) + { + MacroMaterialData& data = FindOrCreateMacroMaterial(entityId); + UpdateMacroMaterialData(data, macroMaterial); + } + else + { + RemoveMacroMaterial(entityId); + } + } + + void TerrainFeatureProcessor::OnTerrainMacroMaterialRegionChanged(AZ::EntityId entityId, [[maybe_unused]] const AZ::Aabb& oldRegion, const AZ::Aabb& newRegion) + { + MacroMaterialData& materialData = FindOrCreateMacroMaterial(entityId); + for (SectorData& sectorData : m_sectorData) + { + bool overlapsOld = sectorData.m_aabb.Overlaps(materialData.m_bounds); + bool overlapsNew = sectorData.m_aabb.Overlaps(newRegion); + if (overlapsOld && !overlapsNew) + { + // Remove the macro material from this sector + for (uint16_t& idx : sectorData.m_macroMaterials) + { + if (m_macroMaterials.GetData(idx).m_entityId == entityId) + { + idx = sectorData.m_macroMaterials.back(); + sectorData.m_macroMaterials.pop_back(); + } + } + } + else if (overlapsNew && !overlapsOld) + { + // Add the macro material to this sector + if (sectorData.m_macroMaterials.size() < MaxMaterialsPerSector) + { + sectorData.m_macroMaterials.push_back(m_macroMaterials.GetIndexForData(&materialData)); + } + } + } + m_areaData.m_macroMaterialsUpdated = true; + materialData.m_bounds = newRegion; + } + + void TerrainFeatureProcessor::OnTerrainMacroMaterialDestroyed(AZ::EntityId entityId) + { + MacroMaterialData* materialData = FindMacroMaterial(entityId); + + if (materialData) + { + uint16_t destroyedMaterialIndex = m_macroMaterials.GetIndexForData(materialData); + ForOverlappingSectors(materialData->m_bounds, + [&](SectorData& sectorData) { + for (uint16_t& idx : sectorData.m_macroMaterials) + { + if (idx == destroyedMaterialIndex) + { + idx = sectorData.m_macroMaterials.back(); + sectorData.m_macroMaterials.pop_back(); + } + } + }); + } + + m_areaData.m_macroMaterialsUpdated = true; } void TerrainFeatureProcessor::UpdateTerrainData() @@ -165,9 +278,9 @@ namespace Terrain uint32_t width = m_areaData.m_updateWidth; uint32_t height = m_areaData.m_updateHeight; const AZ::Aabb& worldBounds = m_areaData.m_terrainBounds; - float queryResolution = m_areaData.m_sampleSpacing; + const float queryResolution = m_areaData.m_sampleSpacing; - AZ::RHI::Size worldSize = AZ::RHI::Size(m_areaData.m_heightmapImageWidth, m_areaData.m_heightmapImageHeight, 1); + const AZ::RHI::Size worldSize = AZ::RHI::Size(m_areaData.m_heightmapImageWidth, m_areaData.m_heightmapImageHeight, 1); if (!m_areaData.m_heightmapImage || m_areaData.m_heightmapImage->GetDescriptor().m_size != worldSize) { @@ -176,7 +289,7 @@ namespace Terrain height = worldSize.m_height; m_dirtyRegion = worldBounds; - AZ::Data::Instance imagePool = AZ::RPI::ImageSystemInterface::Get()->GetSystemAttachmentPool(); + const AZ::Data::Instance imagePool = AZ::RPI::ImageSystemInterface::Get()->GetSystemAttachmentPool(); AZ::RHI::ImageDescriptor imageDescriptor = AZ::RHI::ImageDescriptor::Create2D( AZ::RHI::ImageBindFlags::ShaderRead, width, height, AZ::RHI::Format::R16_UNORM ); @@ -210,9 +323,9 @@ namespace Terrain AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT, &terrainExists); - float clampedHeight = AZ::GetClamp((terrainHeight - worldBounds.GetMin().GetZ()) / worldBounds.GetExtents().GetZ(), 0.0f, 1.0f); - float expandedHeight = AZStd::roundf(clampedHeight * AZStd::numeric_limits::max()); - uint16_t uint16Height = aznumeric_cast(expandedHeight); + const float clampedHeight = AZ::GetClamp((terrainHeight - worldBounds.GetMin().GetZ()) / worldBounds.GetExtents().GetZ(), 0.0f, 1.0f); + const float expandedHeight = AZStd::roundf(clampedHeight * AZStd::numeric_limits::max()); + const uint16_t uint16Height = aznumeric_cast(expandedHeight); pixels.push_back(uint16Height); } @@ -241,118 +354,248 @@ namespace Terrain m_dirtyRegion = AZ::Aabb::CreateNull(); } + void TerrainFeatureProcessor::PrepareMaterialData() + { + const auto layout = m_materialInstance->GetAsset()->GetObjectSrgLayout(); + + m_modelToWorldIndex = layout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::ModelToWorld)); + AZ_Error(TerrainFPName, m_modelToWorldIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::ModelToWorld); + + m_terrainDataIndex = layout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::TerrainData)); + AZ_Error(TerrainFPName, m_terrainDataIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::TerrainData); + + m_macroMaterialDataIndex = layout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::MacroMaterialData)); + AZ_Error(TerrainFPName, m_macroMaterialDataIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::MacroMaterialData); + + m_macroMaterialCountIndex = layout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::MacroMaterialCount)); + AZ_Error(TerrainFPName, m_macroMaterialCountIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::MacroMaterialCount); + + m_macroColorMapIndex = layout->FindShaderInputImageIndex(AZ::Name(ShaderInputs::MacroColorMap)); + AZ_Error(TerrainFPName, m_macroColorMapIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::MacroColorMap); + + m_macroNormalMapIndex = layout->FindShaderInputImageIndex(AZ::Name(ShaderInputs::MacroNormalMap)); + AZ_Error(TerrainFPName, m_macroNormalMapIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::MacroNormalMap); + + m_heightmapPropertyIndex = m_materialInstance->GetMaterialPropertiesLayout()->FindPropertyIndex(AZ::Name(MaterialInputs::HeightmapImage)); + AZ_Error(TerrainFPName, m_heightmapPropertyIndex.IsValid(), "Failed to find material input constant %s.", MaterialInputs::HeightmapImage); + + TerrainMacroMaterialRequestBus::EnumerateHandlers( + [&](TerrainMacroMaterialRequests* handler) + { + MaterialInstance macroMaterial; + AZ::Aabb bounds; + handler->GetTerrainMacroMaterialData(macroMaterial, bounds); + AZ::EntityId entityId = *(Terrain::TerrainMacroMaterialRequestBus::GetCurrentBusId()); + OnTerrainMacroMaterialCreated(entityId, macroMaterial, bounds); + return true; + } + ); + TerrainMacroMaterialNotificationBus::Handler::BusConnect(); + } + + void TerrainFeatureProcessor::UpdateMacroMaterialData(MacroMaterialData& macroMaterialData, MaterialInstance material) + { + // Since we're using an actual macro material instance for now, get the values from it that we care about. + const auto materialLayout = material->GetMaterialPropertiesLayout(); + + const AZ::RPI::MaterialPropertyIndex macroColorTextureMapIndex = materialLayout->FindPropertyIndex(AZ::Name(MaterialInputs::MacroColorTextureMap)); + AZ_Error(TerrainFPName, macroColorTextureMapIndex.IsValid(), "Failed to find shader input constant %s.", MaterialInputs::MacroColorTextureMap); + + const AZ::RPI::MaterialPropertyIndex macroNormalTextureMapIndex = materialLayout->FindPropertyIndex(AZ::Name(MaterialInputs::MacroNormalTextureMap)); + AZ_Error(TerrainFPName, macroNormalTextureMapIndex.IsValid(), "Failed to find shader input constant %s.", MaterialInputs::MacroNormalTextureMap); + + const AZ::RPI::MaterialPropertyIndex macroNormalFlipXIndex = materialLayout->FindPropertyIndex(AZ::Name(MaterialInputs::MacroNormalFlipX)); + AZ_Error(TerrainFPName, macroNormalFlipXIndex.IsValid(), "Failed to find shader input constant %s.", MaterialInputs::MacroNormalFlipX); + + const AZ::RPI::MaterialPropertyIndex macroNormalFlipYIndex = materialLayout->FindPropertyIndex(AZ::Name(MaterialInputs::MacroNormalFlipY)); + AZ_Error(TerrainFPName, macroNormalFlipYIndex.IsValid(), "Failed to find shader input constant %s.", MaterialInputs::MacroNormalFlipY); + + const AZ::RPI::MaterialPropertyIndex macroNormalFactorIndex = materialLayout->FindPropertyIndex(AZ::Name(MaterialInputs::MacroNormalFactor)); + AZ_Error(TerrainFPName, macroNormalFactorIndex.IsValid(), "Failed to find shader input constant %s.", MaterialInputs::MacroNormalFactor); + + macroMaterialData.m_colorImage = material->GetPropertyValue(macroColorTextureMapIndex).GetValue>(); + macroMaterialData.m_normalImage = material->GetPropertyValue(macroNormalTextureMapIndex).GetValue>(); + macroMaterialData.m_normalFlipX = material->GetPropertyValue(macroNormalFlipXIndex).GetValue(); + macroMaterialData.m_normalFlipY = material->GetPropertyValue(macroNormalFlipYIndex).GetValue(); + macroMaterialData.m_normalFactor = material->GetPropertyValue(macroNormalFactorIndex).GetValue(); + + if (macroMaterialData.m_bounds.IsValid()) + { + m_areaData.m_macroMaterialsUpdated = true; + } + } + void TerrainFeatureProcessor::ProcessSurfaces(const FeatureProcessor::RenderPacket& process) { AZ_PROFILE_FUNCTION(AzRender); + + const AZ::Aabb& terrainBounds = m_areaData.m_terrainBounds; - if (!m_areaData.m_terrainBounds.IsValid()) + if (!terrainBounds.IsValid()) { return; } - - if (m_areaData.m_propertiesDirty && m_materialInstance && m_materialInstance->CanCompile()) + + if (m_materialInstance && m_materialInstance->CanCompile()) { - UpdateTerrainData(); - - m_areaData.m_propertiesDirty = false; - m_sectorData.clear(); - - AZ::RPI::MaterialPropertyIndex heightmapPropertyIndex = - m_materialInstance->GetMaterialPropertiesLayout()->FindPropertyIndex(AZ::Name(MaterialInputs::HeightmapImage)); - AZ_Error(TerrainFPName, heightmapPropertyIndex.IsValid(), "Failed to find material input constant %s.", MaterialInputs::HeightmapImage); - AZ::Data::Instance heightmapImage = m_areaData.m_heightmapImage; - m_materialInstance->SetPropertyValue(heightmapPropertyIndex, heightmapImage); - m_materialInstance->Compile(); - - const auto layout = m_materialInstance->GetAsset()->GetObjectSrgLayout(); - - m_modelToWorldIndex = layout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::ModelToWorld)); - AZ_Error(TerrainFPName, m_modelToWorldIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::ModelToWorld); - - m_terrainDataIndex = layout->FindShaderInputConstantIndex(AZ::Name(ShaderInputs::TerrainData)); - AZ_Error(TerrainFPName, m_terrainDataIndex.IsValid(), "Failed to find shader input constant %s.", ShaderInputs::TerrainData); - - float xFirstPatchStart = - m_areaData.m_terrainBounds.GetMin().GetX() - fmod(m_areaData.m_terrainBounds.GetMin().GetX(), GridMeters); - float xLastPatchStart = m_areaData.m_terrainBounds.GetMax().GetX() - fmod(m_areaData.m_terrainBounds.GetMax().GetX(), GridMeters); - float yFirstPatchStart = - m_areaData.m_terrainBounds.GetMin().GetY() - fmod(m_areaData.m_terrainBounds.GetMin().GetY(), GridMeters); - float yLastPatchStart = m_areaData.m_terrainBounds.GetMax().GetY() - fmod(m_areaData.m_terrainBounds.GetMax().GetY(), GridMeters); - - for (float yPatch = yFirstPatchStart; yPatch <= yLastPatchStart; yPatch += GridMeters) + if (m_areaData.m_rebuildSectors) { - for (float xPatch = xFirstPatchStart; xPatch <= xLastPatchStart; xPatch += GridMeters) + // Something about the whole world changed, so the sectors need to be rebuilt + + m_areaData.m_rebuildSectors = false; + + m_sectorData.clear(); + const float xFirstPatchStart = terrainBounds.GetMin().GetX() - fmod(terrainBounds.GetMin().GetX(), GridMeters); + const float xLastPatchStart = terrainBounds.GetMax().GetX() - fmod(terrainBounds.GetMax().GetX(), GridMeters); + const float yFirstPatchStart = terrainBounds.GetMin().GetY() - fmod(terrainBounds.GetMin().GetY(), GridMeters); + const float yLastPatchStart = terrainBounds.GetMax().GetY() - fmod(terrainBounds.GetMax().GetY(), GridMeters); + + const auto& materialAsset = m_materialInstance->GetAsset(); + const auto& shaderAsset = materialAsset->GetMaterialTypeAsset()->GetShaderAssetForObjectSrg(); + + for (float yPatch = yFirstPatchStart; yPatch <= yLastPatchStart; yPatch += GridMeters) { - const auto& materialAsset = m_materialInstance->GetAsset(); - auto& shaderAsset = materialAsset->GetMaterialTypeAsset()->GetShaderAssetForObjectSrg(); - auto objectSrg = AZ::RPI::ShaderResourceGroup::Create(shaderAsset, materialAsset->GetObjectSrgLayout()->GetName()); - if (!objectSrg) + for (float xPatch = xFirstPatchStart; xPatch <= xLastPatchStart; xPatch += GridMeters) { - AZ_Warning("TerrainFeatureProcessor", false, "Failed to create a new shader resource group, skipping."); - continue; - } - - { // Update SRG - - AZStd::array uvMin = { 0.0f, 0.0f }; - AZStd::array uvMax = { 1.0f, 1.0f }; - - uvMin[0] = (float)((xPatch - m_areaData.m_terrainBounds.GetMin().GetX()) / m_areaData.m_terrainBounds.GetXExtent()); - uvMin[1] = (float)((yPatch - m_areaData.m_terrainBounds.GetMin().GetY()) / m_areaData.m_terrainBounds.GetYExtent()); - - uvMax[0] = - (float)(((xPatch + GridMeters) - m_areaData.m_terrainBounds.GetMin().GetX()) / m_areaData.m_terrainBounds.GetXExtent()); - uvMax[1] = - (float)(((yPatch + GridMeters) - m_areaData.m_terrainBounds.GetMin().GetY()) / m_areaData.m_terrainBounds.GetYExtent()); - - AZStd::array uvStep = + auto objectSrg = AZ::RPI::ShaderResourceGroup::Create(shaderAsset, materialAsset->GetObjectSrgLayout()->GetName()); + if (!objectSrg) { - 1.0f / m_areaData.m_heightmapImageWidth, 1.0f / m_areaData.m_heightmapImageHeight, - }; - - AZ::Transform transform = m_areaData.m_transform; - transform.SetTranslation(xPatch, yPatch, m_areaData.m_transform.GetTranslation().GetZ()); - - AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromTransform(transform); - - objectSrg->SetConstant(m_modelToWorldIndex, matrix3x4); - - ShaderTerrainData terrainDataForSrg; - terrainDataForSrg.m_sampleSpacing = m_areaData.m_sampleSpacing; - terrainDataForSrg.m_heightScale = m_areaData.m_heightScale; - terrainDataForSrg.m_uvMin = uvMin; - terrainDataForSrg.m_uvMax = uvMax; - terrainDataForSrg.m_uvStep = uvStep; - objectSrg->SetConstant(m_terrainDataIndex, terrainDataForSrg); - - objectSrg->Compile(); - } - - m_sectorData.push_back(); - SectorData& sectorData = m_sectorData.back(); - - for (auto& lod : m_patchModel->GetLods()) - { - AZ::RPI::ModelLod& modelLod = *lod.get(); - sectorData.m_drawPackets.emplace_back(modelLod, 0, m_materialInstance, objectSrg); - AZ::RPI::MeshDrawPacket& drawPacket = sectorData.m_drawPackets.back(); - - // set the shader option to select forward pass IBL specular if necessary - if (!drawPacket.SetShaderOption(AZ::Name("o_meshUseForwardPassIBLSpecular"), AZ::RPI::ShaderOptionValue{ false })) - { - AZ_Warning("MeshDrawPacket", false, "Failed to set o_meshUseForwardPassIBLSpecular on mesh draw packet"); + AZ_Warning("TerrainFeatureProcessor", false, "Failed to create a new shader resource group, skipping."); + continue; } - uint8_t stencilRef = AZ::Render::StencilRefs::UseDiffuseGIPass | AZ::Render::StencilRefs::UseIBLSpecularPass; - drawPacket.SetStencilRef(stencilRef); - drawPacket.Update(*GetParentScene(), true); + + m_sectorData.push_back(); + SectorData& sectorData = m_sectorData.back(); + + for (auto& lod : m_patchModel->GetLods()) + { + AZ::RPI::ModelLod& modelLod = *lod.get(); + sectorData.m_drawPackets.emplace_back(modelLod, 0, m_materialInstance, objectSrg); + AZ::RPI::MeshDrawPacket& drawPacket = sectorData.m_drawPackets.back(); + + // set the shader option to select forward pass IBL specular if necessary + if (!drawPacket.SetShaderOption(AZ::Name("o_meshUseForwardPassIBLSpecular"), AZ::RPI::ShaderOptionValue{ false })) + { + AZ_Warning("MeshDrawPacket", false, "Failed to set o_meshUseForwardPassIBLSpecular on mesh draw packet"); + } + const uint8_t stencilRef = AZ::Render::StencilRefs::UseDiffuseGIPass | AZ::Render::StencilRefs::UseIBLSpecularPass; + drawPacket.SetStencilRef(stencilRef); + drawPacket.Update(*GetParentScene(), true); + } + + sectorData.m_aabb = + AZ::Aabb::CreateFromMinMax( + AZ::Vector3(xPatch, yPatch, terrainBounds.GetMin().GetZ()), + AZ::Vector3(xPatch + GridMeters, yPatch + GridMeters, terrainBounds.GetMax().GetZ()) + ); + sectorData.m_srg = objectSrg; + } + } + + if (m_areaData.m_macroMaterialsUpdated) + { + // sectors were rebuilt, so any cached macro material data needs to be regenerated + for (SectorData& sectorData : m_sectorData) + { + for (MacroMaterialData& macroMaterialData : m_macroMaterials.GetDataVector()) + { + if (macroMaterialData.m_bounds.Overlaps(sectorData.m_aabb)) + { + sectorData.m_macroMaterials.push_back(m_macroMaterials.GetIndexForData(¯oMaterialData)); + if (sectorData.m_macroMaterials.size() == MaxMaterialsPerSector) + { + break; + } + } + } + } + } + } + + if (m_areaData.m_heightmapUpdated) + { + UpdateTerrainData(); + + const AZ::Data::Instance heightmapImage = m_areaData.m_heightmapImage; + m_materialInstance->SetPropertyValue(m_heightmapPropertyIndex, heightmapImage); + m_materialInstance->Compile(); + } + + if (m_areaData.m_heightmapUpdated || m_areaData.m_macroMaterialsUpdated) + { + // Currently when anything in the heightmap changes we're updating all the srgs, but this could probably + // be optimized to only update the srgs that changed. + + m_areaData.m_heightmapUpdated = false; + m_areaData.m_macroMaterialsUpdated = false; + + for (SectorData& sectorData : m_sectorData) + { + ShaderTerrainData terrainDataForSrg; + + const float xPatch = sectorData.m_aabb.GetMin().GetX(); + const float yPatch = sectorData.m_aabb.GetMin().GetY(); + + terrainDataForSrg.m_uvMin = { + (xPatch - terrainBounds.GetMin().GetX()) / terrainBounds.GetXExtent(), + (yPatch - terrainBounds.GetMin().GetY()) / terrainBounds.GetYExtent() + }; + + terrainDataForSrg.m_uvMax = { + ((xPatch + GridMeters) - terrainBounds.GetMin().GetX()) / terrainBounds.GetXExtent(), + ((yPatch + GridMeters) - terrainBounds.GetMin().GetY()) / terrainBounds.GetYExtent() + }; + + terrainDataForSrg.m_uvStep = + { + 1.0f / m_areaData.m_heightmapImageWidth, + 1.0f / m_areaData.m_heightmapImageHeight, + }; + + AZ::Transform transform = m_areaData.m_transform; + transform.SetTranslation(xPatch, yPatch, m_areaData.m_transform.GetTranslation().GetZ()); + + terrainDataForSrg.m_sampleSpacing = m_areaData.m_sampleSpacing; + terrainDataForSrg.m_heightScale = terrainBounds.GetZExtent(); + + sectorData.m_srg->SetConstant(m_terrainDataIndex, terrainDataForSrg); + + AZStd::array macroMaterialData; + for (uint32_t i = 0; i < sectorData.m_macroMaterials.size(); ++i) + { + const MacroMaterialData& materialData = m_macroMaterials.GetData(sectorData.m_macroMaterials.at(i)); + ShaderMacroMaterialData& shaderData = macroMaterialData.at(i); + const AZ::Aabb& materialBounds = materialData.m_bounds; + + shaderData.m_uvMin = { + (xPatch - materialBounds.GetMin().GetX()) / materialBounds.GetXExtent(), + (yPatch - materialBounds.GetMin().GetY()) / materialBounds.GetYExtent() + }; + shaderData.m_uvMax = { + ((xPatch + GridMeters) - materialBounds.GetMin().GetX()) / materialBounds.GetXExtent(), + ((yPatch + GridMeters) - materialBounds.GetMin().GetY()) / materialBounds.GetYExtent() + }; + shaderData.m_normalFactor = materialData.m_normalFactor; + shaderData.m_flipNormalX = materialData.m_normalFlipX; + shaderData.m_flipNormalY = materialData.m_normalFlipY; + + const AZ::RHI::ImageView* colorImageView = materialData.m_colorImage ? materialData.m_colorImage->GetImageView() : nullptr; + sectorData.m_srg->SetImageView(m_macroColorMapIndex, colorImageView, i); + + const AZ::RHI::ImageView* normalImageView = materialData.m_normalImage ? materialData.m_normalImage->GetImageView() : nullptr; + sectorData.m_srg->SetImageView(m_macroNormalMapIndex, normalImageView, i); + + // set flags for which images are used. + shaderData.m_mapsInUse = (colorImageView ? ColorImageUsed : 0) | (normalImageView ? NormalImageUsed : 0); } - sectorData.m_aabb = - AZ::Aabb::CreateFromMinMax( - AZ::Vector3(xPatch, yPatch, m_areaData.m_terrainBounds.GetMin().GetZ()), - AZ::Vector3(xPatch + GridMeters, yPatch + GridMeters, m_areaData.m_terrainBounds.GetMax().GetZ()) - ); - sectorData.m_srg = objectSrg; + sectorData.m_srg->SetConstantArray(m_macroMaterialDataIndex, macroMaterialData); + sectorData.m_srg->SetConstant(m_macroMaterialCountIndex, aznumeric_cast(sectorData.m_macroMaterials.size())); + + const AZ::Matrix3x4 matrix3x4 = AZ::Matrix3x4::CreateFromTransform(transform); + sectorData.m_srg->SetConstant(m_modelToWorldIndex, matrix3x4); + + sectorData.m_srg->Compile(); } } } @@ -366,12 +609,20 @@ namespace Terrain { if ((view->GetUsageFlags() & AZ::RPI::View::UsageFlags::UsageCamera) > 0) { - AZ::Vector3 cameraPosition = view->GetCameraTransform().GetTranslation(); - AZ::Vector2 cameraPositionXY = AZ::Vector2(cameraPosition.GetX(), cameraPosition.GetY()); - AZ::Vector2 sectorCenterXY = AZ::Vector2(sectorData.m_aabb.GetCenter().GetX(), sectorData.m_aabb.GetCenter().GetY()); + const AZ::Vector3 cameraPosition = view->GetCameraTransform().GetTranslation(); + const AZ::Vector2 cameraPositionXY = AZ::Vector2(cameraPosition.GetX(), cameraPosition.GetY()); + const AZ::Vector2 sectorCenterXY = AZ::Vector2(sectorData.m_aabb.GetCenter().GetX(), sectorData.m_aabb.GetCenter().GetY()); - float sectorDistance = sectorCenterXY.GetDistance(cameraPositionXY); - float lodForCamera = floorf(AZ::GetMax(0.0f, log2f(sectorDistance / (GridMeters * 4.0f)))); + const float sectorDistance = sectorCenterXY.GetDistance(cameraPositionXY); + + // This will be configurable later + const float minDistanceForLod0 = (GridMeters * 4.0f); + + // For every distance doubling beyond a minDistanceForLod0, we only need half the mesh density. Each LOD + // is exactly half the resolution of the last. + const float lodForCamera = floorf(AZ::GetMax(0.0f, log2f(sectorDistance / minDistanceForLod0))); + + // All cameras should render the same LOD so effects like shadows are consistent. lodChoice = AZ::GetMin(lodChoice, aznumeric_cast(lodForCamera)); } } @@ -382,7 +633,7 @@ namespace Terrain AZ::Frustum viewFrustum = AZ::Frustum::CreateFromMatrixColumnMajor(view->GetWorldToClipMatrix()); if (viewFrustum.IntersectAabb(sectorData.m_aabb) != AZ::IntersectResult::Exterior) { - uint8_t lodToRender = AZ::GetMin(lodChoice, aznumeric_cast(sectorData.m_drawPackets.size() - 1)); + const uint8_t lodToRender = AZ::GetMin(lodChoice, aznumeric_cast(sectorData.m_drawPackets.size() - 1)); view->AddDrawPacket(sectorData.m_drawPackets.at(lodToRender).GetRHIDrawPacket()); } } @@ -395,9 +646,8 @@ namespace Terrain patchdata.m_uvs.clear(); patchdata.m_indices.clear(); - uint16_t gridVertices = gridSize + 1; // For m_gridSize quads, (m_gridSize + 1) vertices are needed. - size_t size = gridVertices * gridVertices; - size *= size; + const uint16_t gridVertices = gridSize + 1; // For m_gridSize quads, (m_gridSize + 1) vertices are needed. + const size_t size = gridVertices * gridVertices; patchdata.m_positions.reserve(size); patchdata.m_uvs.reserve(size); @@ -417,10 +667,10 @@ namespace Terrain { for (uint16_t x = 0; x < gridSize; ++x) { - uint16_t topLeft = y * gridVertices + x; - uint16_t topRight = topLeft + 1; - uint16_t bottomLeft = (y + 1) * gridVertices + x; - uint16_t bottomRight = bottomLeft + 1; + const uint16_t topLeft = y * gridVertices + x; + const uint16_t topRight = topLeft + 1; + const uint16_t bottomLeft = (y + 1) * gridVertices + x; + const uint16_t bottomRight = bottomLeft + 1; patchdata.m_indices.emplace_back(topLeft); patchdata.m_indices.emplace_back(topRight); @@ -469,14 +719,14 @@ namespace Terrain PatchData patchData; InitializeTerrainPatch(gridSize, gridSpacing, patchData); - auto positionBufferViewDesc = AZ::RHI::BufferViewDescriptor::CreateTyped(0, aznumeric_cast(patchData.m_positions.size()), AZ::RHI::Format::R32G32_FLOAT); - auto positionsOutcome = CreateBufferAsset(patchData.m_positions.data(), positionBufferViewDesc, "TerrainPatchPositions"); + const auto positionBufferViewDesc = AZ::RHI::BufferViewDescriptor::CreateTyped(0, aznumeric_cast(patchData.m_positions.size()), AZ::RHI::Format::R32G32_FLOAT); + const auto positionsOutcome = CreateBufferAsset(patchData.m_positions.data(), positionBufferViewDesc, "TerrainPatchPositions"); - auto uvBufferViewDesc = AZ::RHI::BufferViewDescriptor::CreateTyped(0, aznumeric_cast(patchData.m_uvs.size()), AZ::RHI::Format::R32G32_FLOAT); - auto uvsOutcome = CreateBufferAsset(patchData.m_uvs.data(), uvBufferViewDesc, "TerrainPatchUvs"); + const auto uvBufferViewDesc = AZ::RHI::BufferViewDescriptor::CreateTyped(0, aznumeric_cast(patchData.m_uvs.size()), AZ::RHI::Format::R32G32_FLOAT); + const auto uvsOutcome = CreateBufferAsset(patchData.m_uvs.data(), uvBufferViewDesc, "TerrainPatchUvs"); - auto indexBufferViewDesc = AZ::RHI::BufferViewDescriptor::CreateTyped(0, aznumeric_cast(patchData.m_indices.size()), AZ::RHI::Format::R16_UINT); - auto indicesOutcome = CreateBufferAsset(patchData.m_indices.data(), indexBufferViewDesc, "TerrainPatchIndices"); + const auto indexBufferViewDesc = AZ::RHI::BufferViewDescriptor::CreateTyped(0, aznumeric_cast(patchData.m_indices.size()), AZ::RHI::Format::R16_UINT); + const auto indicesOutcome = CreateBufferAsset(patchData.m_indices.data(), indexBufferViewDesc, "TerrainPatchIndices"); if (!positionsOutcome.IsSuccess() || !uvsOutcome.IsSuccess() || !indicesOutcome.IsSuccess()) { @@ -514,7 +764,7 @@ namespace Terrain return success; } - void TerrainFeatureProcessor::OnMaterialReinitialized([[maybe_unused]] const AZ::Data::Instance& material) + void TerrainFeatureProcessor::OnMaterialReinitialized([[maybe_unused]] const MaterialInstance& material) { for (auto& sectorData : m_sectorData) { @@ -530,4 +780,57 @@ namespace Terrain // This will control the max rendering size. Actual terrain size can be much // larger but this will limit how much is rendered. } + + TerrainFeatureProcessor::MacroMaterialData* TerrainFeatureProcessor::FindMacroMaterial(AZ::EntityId entityId) + { + for (MacroMaterialData& data : m_macroMaterials.GetDataVector()) + { + if (data.m_entityId == entityId) + { + return &data; + } + } + return nullptr; + } + + TerrainFeatureProcessor::MacroMaterialData& TerrainFeatureProcessor::FindOrCreateMacroMaterial(AZ::EntityId entityId) + { + MacroMaterialData* dataPtr = FindMacroMaterial(entityId); + if (dataPtr != nullptr) + { + return *dataPtr; + } + + const uint16_t slotId = m_macroMaterials.GetFreeSlotIndex(); + AZ_Assert(slotId != m_macroMaterials.NoFreeSlot, "Ran out of indices for macro materials"); + + MacroMaterialData& data = m_macroMaterials.GetData(slotId); + data.m_entityId = entityId; + return data; + } + + void TerrainFeatureProcessor::RemoveMacroMaterial(AZ::EntityId entityId) + { + for (MacroMaterialData& data : m_macroMaterials.GetDataVector()) + { + if (data.m_entityId == entityId) + { + m_macroMaterials.RemoveData(&data); + return; + } + } + AZ_Assert(false, "Entity Id not found in m_macroMaterials.") + } + + template + void TerrainFeatureProcessor::ForOverlappingSectors(const AZ::Aabb& bounds, Callback callback) + { + for (SectorData& sectorData : m_sectorData) + { + if (sectorData.m_aabb.Overlaps(bounds)) + { + callback(sectorData); + } + } + } } diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.h b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.h index d8df9b328c..d9f15f2d47 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.h +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainFeatureProcessor.h @@ -11,11 +11,13 @@ #include #include +#include #include #include #include #include +#include namespace AZ::RPI { @@ -25,6 +27,7 @@ namespace AZ::RPI } class Material; class Model; + class StreamingImage; } namespace Terrain @@ -33,6 +36,7 @@ namespace Terrain : public AZ::RPI::FeatureProcessor , private AZ::RPI::MaterialReloadNotificationBus::Handler , private AzFramework::Terrain::TerrainDataNotificationBus::Handler + , private TerrainMacroMaterialNotificationBus::Handler { public: AZ_RTTI(TerrainFeatureProcessor, "{D7DAC1F9-4A9F-4D3C-80AE-99579BF8AB1C}", AZ::RPI::FeatureProcessor); @@ -52,6 +56,15 @@ namespace Terrain void SetWorldSize(AZ::Vector2 sizeInMeters); private: + + using MaterialInstance = AZ::Data::Instance; + static constexpr uint32_t MaxMaterialsPerSector = 4; + + enum MacroMaterialFlags + { + ColorImageUsed = 0b01, + NormalImageUsed = 0b10, + }; struct ShaderTerrainData // Must align with struct in Object Srg { @@ -61,7 +74,17 @@ namespace Terrain float m_sampleSpacing; float m_heightScale; }; - + + struct ShaderMacroMaterialData + { + AZStd::array m_uvMin; + AZStd::array m_uvMax; + float m_normalFactor; + uint32_t m_flipNormalX{ 0 }; // bool in shader + uint32_t m_flipNormalY{ 0 }; // bool in shader + uint32_t m_mapsInUse{ 0b00 }; // 0b01 = color, 0b10 = normal + }; + struct VertexPosition { float m_posx; @@ -81,21 +104,56 @@ namespace Terrain AZStd::vector m_indices; }; + struct SectorData + { + AZ::Data::Instance m_srg; // Hold on to ref so it's not dropped + AZ::Aabb m_aabb; + AZStd::fixed_vector m_drawPackets; + AZStd::fixed_vector m_macroMaterials; + }; + + struct MacroMaterialData + { + AZ::EntityId m_entityId; + AZ::Aabb m_bounds = AZ::Aabb::CreateNull(); + + AZ::Data::Instance m_colorImage; + AZ::Data::Instance m_normalImage; + bool m_normalFlipX{ false }; + bool m_normalFlipY{ false }; + float m_normalFactor{ 0.0f }; + }; + // AZ::RPI::MaterialReloadNotificationBus::Handler overrides... - void OnMaterialReinitialized(const AZ::Data::Instance& material) override; + void OnMaterialReinitialized(const MaterialInstance& material) override; // AzFramework::Terrain::TerrainDataNotificationBus overrides... void OnTerrainDataDestroyBegin() override; void OnTerrainDataChanged(const AZ::Aabb& dirtyRegion, TerrainDataChangedMask dataChangedMask) override; + // TerrainMacroMaterialNotificationBus overrides... + void OnTerrainMacroMaterialCreated(AZ::EntityId entityId, MaterialInstance material, const AZ::Aabb& region) override; + void OnTerrainMacroMaterialChanged(AZ::EntityId entityId, MaterialInstance material) override; + void OnTerrainMacroMaterialRegionChanged(AZ::EntityId entityId, const AZ::Aabb& oldRegion, const AZ::Aabb& newRegion) override; + void OnTerrainMacroMaterialDestroyed(AZ::EntityId entityId) override; + void Initialize(); void InitializeTerrainPatch(uint16_t gridSize, float gridSpacing, PatchData& patchdata); bool InitializePatchModel(); void UpdateTerrainData(); + void PrepareMaterialData(); + void UpdateMacroMaterialData(MacroMaterialData& macroMaterialData, MaterialInstance material); void ProcessSurfaces(const FeatureProcessor::RenderPacket& process); + MacroMaterialData* FindMacroMaterial(AZ::EntityId entityId); + MacroMaterialData& FindOrCreateMacroMaterial(AZ::EntityId entityId); + void RemoveMacroMaterial(AZ::EntityId entityId); + + template + void ForOverlappingSectors(const AZ::Aabb& bounds, Callback callback); + AZ::Outcome> CreateBufferAsset( const void* data, const AZ::RHI::BufferViewDescriptor& bufferViewDescriptor, const AZStd::string& bufferName); @@ -105,10 +163,15 @@ namespace Terrain static constexpr float GridMeters{ GridSpacing * GridSize }; AZStd::unique_ptr m_materialAssetLoader; - AZ::Data::Instance m_materialInstance; + MaterialInstance m_materialInstance; AZ::RHI::ShaderInputConstantIndex m_modelToWorldIndex; AZ::RHI::ShaderInputConstantIndex m_terrainDataIndex; + AZ::RHI::ShaderInputConstantIndex m_macroMaterialDataIndex; + AZ::RHI::ShaderInputConstantIndex m_macroMaterialCountIndex; + AZ::RHI::ShaderInputImageIndex m_macroColorMapIndex; + AZ::RHI::ShaderInputImageIndex m_macroNormalMapIndex; + AZ::RPI::MaterialPropertyIndex m_heightmapPropertyIndex; AZ::Data::Instance m_patchModel; @@ -117,26 +180,22 @@ namespace Terrain { AZ::Transform m_transform{ AZ::Transform::CreateIdentity() }; AZ::Aabb m_terrainBounds{ AZ::Aabb::CreateNull() }; - float m_heightScale{ 0.0f }; AZ::Data::Instance m_heightmapImage; uint32_t m_heightmapImageWidth{ 0 }; uint32_t m_heightmapImageHeight{ 0 }; uint32_t m_updateWidth{ 0 }; uint32_t m_updateHeight{ 0 }; - bool m_propertiesDirty{ true }; float m_sampleSpacing{ 0.0f }; + bool m_heightmapUpdated{ true }; + bool m_macroMaterialsUpdated{ true }; + bool m_rebuildSectors{ true }; }; TerrainAreaData m_areaData; AZ::Aabb m_dirtyRegion{ AZ::Aabb::CreateNull() }; - struct SectorData - { - AZ::Data::Instance m_srg; // Hold on to ref so it's not dropped - AZ::Aabb m_aabb; - AZStd::fixed_vector m_drawPackets; - }; - AZStd::vector m_sectorData; + + AZ::Render::IndexedDataVector m_macroMaterials; }; } From 2474ffc5a1fb7ed5a6d5df753034e196fc9732f0 Mon Sep 17 00:00:00 2001 From: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> Date: Wed, 13 Oct 2021 16:59:46 -0500 Subject: [PATCH 162/169] Fixed contains check in the Global AnimNode Map macros (#4674) Signed-off-by: lumberyard-employee-dm <56135373+lumberyard-employee-dm@users.noreply.github.com> --- Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp | 4 ++-- Gems/Maestro/Code/Source/Cinematics/Movie.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp b/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp index cab6ae3fa6..ab45042b4c 100644 --- a/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp +++ b/Gems/LyShine/Code/Source/Animation/UiAnimationSystem.cpp @@ -37,11 +37,11 @@ namespace using UiAnimSystemUnorderedMap = AZStd::unordered_map; } // Serialization for anim nodes & param types -#define REGISTER_NODE_TYPE(name) assert(g_animNodeEnumToStringMap.contains(eUiAnimNodeType_ ## name)); \ +#define REGISTER_NODE_TYPE(name) assert(!g_animNodeEnumToStringMap.contains(eUiAnimNodeType_ ## name)); \ g_animNodeEnumToStringMap[eUiAnimNodeType_ ## name] = AZ_STRINGIZE(name); \ g_animNodeStringToEnumMap[UiAnimParamSystemString(AZ_STRINGIZE(name))] = eUiAnimNodeType_ ## name; -#define REGISTER_PARAM_TYPE(name) assert(g_animParamEnumToStringMap.contains(eUiAnimParamType_ ## name)); \ +#define REGISTER_PARAM_TYPE(name) assert(!g_animParamEnumToStringMap.contains(eUiAnimParamType_ ## name)); \ g_animParamEnumToStringMap[eUiAnimParamType_ ## name] = AZ_STRINGIZE(name); \ g_animParamStringToEnumMap[UiAnimParamSystemString(AZ_STRINGIZE(name))] = eUiAnimParamType_ ## name; diff --git a/Gems/Maestro/Code/Source/Cinematics/Movie.cpp b/Gems/Maestro/Code/Source/Cinematics/Movie.cpp index 9c4356560d..2a9a231177 100644 --- a/Gems/Maestro/Code/Source/Cinematics/Movie.cpp +++ b/Gems/Maestro/Code/Source/Cinematics/Movie.cpp @@ -87,11 +87,11 @@ namespace } // Serialization for anim nodes & param types -#define REGISTER_NODE_TYPE(name) assert(g_animNodeEnumToStringMap.contains(AnimNodeType::name)); \ +#define REGISTER_NODE_TYPE(name) assert(!g_animNodeEnumToStringMap.contains(AnimNodeType::name)); \ g_animNodeEnumToStringMap[AnimNodeType::name] = AZ_STRINGIZE(name); \ g_animNodeStringToEnumMap[AnimParamSystemString(AZ_STRINGIZE(name))] = AnimNodeType::name; -#define REGISTER_PARAM_TYPE(name) assert(g_animParamEnumToStringMap.contains(AnimParamType::name)); \ +#define REGISTER_PARAM_TYPE(name) assert(!g_animParamEnumToStringMap.contains(AnimParamType::name)); \ g_animParamEnumToStringMap[AnimParamType::name] = AZ_STRINGIZE(name); \ g_animParamStringToEnumMap[AnimParamSystemString(AZ_STRINGIZE(name))] = AnimParamType::name; From 6823ea22740e8c26b5d417772cdf75db2c8e4fed Mon Sep 17 00:00:00 2001 From: Vincent Liu <5900509+onecent1101@users.noreply.github.com> Date: Wed, 13 Oct 2021 16:59:37 -0700 Subject: [PATCH 163/169] Add GameLift matchmaking backfill server support (#4622) * Add GameLift matchmaking backfill server support Signed-off-by: onecent1101 --- .../AzFramework/Session/SessionConfig.cpp | 3 + .../AzFramework/Session/SessionConfig.h | 3 + .../Session/SessionNotifications.h | 5 + .../Code/AWSGameLiftClient/CMakeLists.txt | 6 +- .../AWSGameLiftStartMatchmakingRequest.h | 30 +- .../AWSGameLiftClientSystemComponent.cpp | 1 + .../AWSGameLiftSearchSessionsActivity.cpp | 1 + .../AWSGameLiftStartMatchmakingActivity.cpp | 5 +- .../AWSGameLiftStartMatchmakingRequest.cpp | 45 +- .../Tests/AWSGameLiftClientManagerTest.cpp | 7 +- ...WSGameLiftStartMatchmakingActivityTest.cpp | 13 +- .../awsgamelift_client_files.cmake | 2 + .../Include/AWSGameLiftPlayer.h | 44 ++ .../Source/AWSGameLiftPlayer.cpp | 58 ++ .../Code/AWSGameLiftServer/CMakeLists.txt | 3 + .../Request/IAWSGameLiftServerRequests.h | 21 +- .../Source/AWSGameLiftServerManager.cpp | 378 ++++++++++++- .../Source/AWSGameLiftServerManager.h | 75 ++- .../Source/GameLiftServerSDKWrapper.cpp | 19 + .../Source/GameLiftServerSDKWrapper.h | 19 + .../Tests/AWSGameLiftServerManagerTest.cpp | 516 ++++++++++++++++++ .../Tests/AWSGameLiftServerMocks.h | 23 + .../awsgamelift_server_files.cmake | 2 + .../Source/MultiplayerSystemComponent.cpp | 6 + .../Code/Source/MultiplayerSystemComponent.h | 1 + 25 files changed, 1194 insertions(+), 92 deletions(-) create mode 100644 Gems/AWSGameLift/Code/AWSGameLiftCommon/Include/AWSGameLiftPlayer.h create mode 100644 Gems/AWSGameLift/Code/AWSGameLiftCommon/Source/AWSGameLiftPlayer.cpp diff --git a/Code/Framework/AzFramework/AzFramework/Session/SessionConfig.cpp b/Code/Framework/AzFramework/AzFramework/Session/SessionConfig.cpp index 0c879a930f..0856ddeed6 100644 --- a/Code/Framework/AzFramework/AzFramework/Session/SessionConfig.cpp +++ b/Code/Framework/AzFramework/AzFramework/Session/SessionConfig.cpp @@ -22,6 +22,7 @@ namespace AzFramework ->Field("terminationTime", &SessionConfig::m_terminationTime) ->Field("creatorId", &SessionConfig::m_creatorId) ->Field("sessionProperties", &SessionConfig::m_sessionProperties) + ->Field("matchmakingData", &SessionConfig::m_matchmakingData) ->Field("sessionId", &SessionConfig::m_sessionId) ->Field("sessionName", &SessionConfig::m_sessionName) ->Field("dnsName", &SessionConfig::m_dnsName) @@ -46,6 +47,8 @@ namespace AzFramework "CreatorId", "A unique identifier for a player or entity creating the session.") ->DataElement(AZ::Edit::UIHandlers::Default, &AzFramework::SessionConfig::m_sessionProperties, "SessionProperties", "A collection of custom properties for a session.") + ->DataElement(AZ::Edit::UIHandlers::Default, &AzFramework::SessionConfig::m_matchmakingData, + "MatchmakingData", "The matchmaking process information that was used to create the session.") ->DataElement(AZ::Edit::UIHandlers::Default, &AzFramework::SessionConfig::m_sessionId, "SessionId", "A unique identifier for the session.") ->DataElement(AZ::Edit::UIHandlers::Default, &AzFramework::SessionConfig::m_sessionName, diff --git a/Code/Framework/AzFramework/AzFramework/Session/SessionConfig.h b/Code/Framework/AzFramework/AzFramework/Session/SessionConfig.h index cfd6aa7c8b..45e40c2f29 100644 --- a/Code/Framework/AzFramework/AzFramework/Session/SessionConfig.h +++ b/Code/Framework/AzFramework/AzFramework/Session/SessionConfig.h @@ -35,6 +35,9 @@ namespace AzFramework // A collection of custom properties for a session. AZStd::unordered_map m_sessionProperties; + + // The matchmaking process information that was used to create the session. + AZStd::string m_matchmakingData; // A unique identifier for the session. AZStd::string m_sessionId; diff --git a/Code/Framework/AzFramework/AzFramework/Session/SessionNotifications.h b/Code/Framework/AzFramework/AzFramework/Session/SessionNotifications.h index 7788c2d030..902500fe9a 100644 --- a/Code/Framework/AzFramework/AzFramework/Session/SessionNotifications.h +++ b/Code/Framework/AzFramework/AzFramework/Session/SessionNotifications.h @@ -41,6 +41,11 @@ namespace AzFramework // OnDestroySessionBegin is fired at the beginning of session termination // @return The result of all OnDestroySessionBegin notifications virtual bool OnDestroySessionBegin() = 0; + + // OnUpdateSessionBegin is fired at the beginning of session update + // @param sessionConfig The properties to describe a session + // @param updateReason The reason for session update + virtual void OnUpdateSessionBegin(const SessionConfig& sessionConfig, const AZStd::string& updateReason) = 0; }; using SessionNotificationBus = AZ::EBus; } // namespace AzFramework diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/CMakeLists.txt b/Gems/AWSGameLift/Code/AWSGameLiftClient/CMakeLists.txt index 3eb5eafab0..1fab09e9f4 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/CMakeLists.txt +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/CMakeLists.txt @@ -15,10 +15,11 @@ ly_add_target( awsgamelift_client_files.cmake INCLUDE_DIRECTORIES PUBLIC + ../AWSGameLiftCommon/Include Include PRIVATE - Source ../AWSGameLiftCommon/Source + Source COMPILE_DEFINITIONS PRIVATE ${awsgameliftclient_compile_definition} @@ -78,10 +79,11 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) awsgamelift_client_tests_files.cmake INCLUDE_DIRECTORIES PRIVATE + ../AWSGameLiftCommon/Include + ../AWSGameLiftCommon/Source Include Tests Source - ../AWSGameLiftCommon/Source BUILD_DEPENDENCIES PRIVATE AZ::AzCore diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Include/Request/AWSGameLiftStartMatchmakingRequest.h b/Gems/AWSGameLift/Code/AWSGameLiftClient/Include/Request/AWSGameLiftStartMatchmakingRequest.h index d734daa808..ec3719c6d3 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Include/Request/AWSGameLiftStartMatchmakingRequest.h +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Include/Request/AWSGameLiftStartMatchmakingRequest.h @@ -10,36 +10,12 @@ #include #include - #include +#include + namespace AWSGameLift { - //! AWSGameLiftPlayerInformation - //! Information on each player to be matched - //! This information must include a player ID, and may contain player attributes and latency data to be used in the matchmaking process - //! After a successful match, Player objects contain the name of the team the player is assigned to - struct AWSGameLiftPlayerInformation - { - AZ_RTTI(AWSGameLiftPlayerInformation, "{B62C118E-C55D-4903-8ECB-E58E8CA613C4}"); - static void Reflect(AZ::ReflectContext* context); - - AWSGameLiftPlayerInformation() = default; - virtual ~AWSGameLiftPlayerInformation() = default; - - // A map of region names to latencies in millseconds, that indicates - // the amount of latency that a player experiences when connected to AWS Regions - AZStd::unordered_map m_latencyInMs; - // A collection of key:value pairs containing player information for use in matchmaking - // Player attribute keys must match the playerAttributes used in a matchmaking rule set - // Example: {"skill": "{\"N\": \"23\"}", "gameMode": "{\"S\": \"deathmatch\"}"} - AZStd::unordered_map m_playerAttributes; - // A unique identifier for a player - AZStd::string m_playerId; - // Name of the team that the player is assigned to in a match - AZStd::string m_team; - }; - //! AWSGameLiftStartMatchmakingRequest //! GameLift start matchmaking request which corresponds to Amazon GameLift //! Uses FlexMatch to create a game match for a group of players based on custom matchmaking rules @@ -57,6 +33,6 @@ namespace AWSGameLift // Name of the matchmaking configuration to use for this request AZStd::string m_configurationName; // Information on each player to be matched - AZStd::vector m_players; + AZStd::vector m_players; }; } // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientSystemComponent.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientSystemComponent.cpp index ea5fff99a3..ed7830ce57 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientSystemComponent.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/AWSGameLiftClientSystemComponent.cpp @@ -210,6 +210,7 @@ namespace AWSGameLift ->Property("SessionId", BehaviorValueProperty(&AzFramework::SessionConfig::m_sessionId)) ->Property("SessionName", BehaviorValueProperty(&AzFramework::SessionConfig::m_sessionName)) ->Property("SessionProperties", BehaviorValueProperty(&AzFramework::SessionConfig::m_sessionProperties)) + ->Property("MatchmakingData", BehaviorValueProperty(&AzFramework::SessionConfig::m_matchmakingData)) ->Property("Status", BehaviorValueProperty(&AzFramework::SessionConfig::m_status)) ->Property("StatusReason", BehaviorValueProperty(&AzFramework::SessionConfig::m_statusReason)) ->Property("TerminationTime", BehaviorValueProperty(&AzFramework::SessionConfig::m_terminationTime)) diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftSearchSessionsActivity.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftSearchSessionsActivity.cpp index 3d29fa2b71..5f0b6fd012 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftSearchSessionsActivity.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftSearchSessionsActivity.cpp @@ -105,6 +105,7 @@ namespace AWSGameLift session.m_status = AWSGameLiftSessionStatusNames[(int)gameSession.GetStatus()]; session.m_statusReason = AWSGameLiftSessionStatusReasons[(int)gameSession.GetStatusReason()]; session.m_terminationTime = gameSession.GetTerminationTime().Millis(); + session.m_matchmakingData = gameSession.GetMatchmakerData().c_str(); // TODO: Update the AWS Native SDK to get the new game session attributes. //session.m_dnsName = gameSession.GetDnsName(); diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.cpp index e535ea0c55..00a7773491 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Activity/AWSGameLiftStartMatchmakingActivity.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -29,7 +30,7 @@ namespace AWSGameLift } Aws::Vector players; - for (const AWSGameLiftPlayerInformation& playerInfo : startMatchmakingRequest.m_players) + for (const AWSGameLiftPlayer& playerInfo : startMatchmakingRequest.m_players) { Aws::GameLift::Model::Player player; if (!playerInfo.m_playerId.empty()) @@ -109,7 +110,7 @@ namespace AWSGameLift if (isValid) { - for (const AWSGameLiftPlayerInformation& playerInfo : gameliftStartMatchmakingRequest->m_players) + for (const AWSGameLiftPlayer& playerInfo : gameliftStartMatchmakingRequest->m_players) { isValid &= !playerInfo.m_playerId.empty(); isValid &= AWSGameLiftActivityUtils::ValidatePlayerAttributes(playerInfo.m_playerAttributes); diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Request/AWSGameLiftStartMatchmakingRequest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Request/AWSGameLiftStartMatchmakingRequest.cpp index 03d802fd36..31e9c5eff7 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Request/AWSGameLiftStartMatchmakingRequest.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Source/Request/AWSGameLiftStartMatchmakingRequest.cpp @@ -14,53 +14,10 @@ namespace AWSGameLift { - void AWSGameLiftPlayerInformation::Reflect(AZ::ReflectContext* context) - { - if (auto serializeContext = azrtti_cast(context)) - { - serializeContext->Class() - ->Version(0) - ->Field("latencyInMs", &AWSGameLiftPlayerInformation::m_latencyInMs) - ->Field("playerAttributes", &AWSGameLiftPlayerInformation::m_playerAttributes) - ->Field("playerId", &AWSGameLiftPlayerInformation::m_playerId) - ->Field("team", &AWSGameLiftPlayerInformation::m_team); - - if (AZ::EditContext* editContext = serializeContext->GetEditContext()) - { - editContext->Class("AWSGameLiftPlayerInformation", "") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->DataElement( - AZ::Edit::UIHandlers::Default, &AWSGameLiftPlayerInformation::m_latencyInMs, "LatencyInMs", - "A set of values, expressed in milliseconds, that indicates the amount of latency that" - "a player experiences when connected to AWS Regions") - ->DataElement( - AZ::Edit::UIHandlers::Default, &AWSGameLiftPlayerInformation::m_playerAttributes, "PlayerAttributes", - "A collection of key:value pairs containing player information for use in matchmaking") - ->DataElement( - AZ::Edit::UIHandlers::Default, &AWSGameLiftPlayerInformation::m_playerId, "PlayerId", - "A unique identifier for a player") - ->DataElement( - AZ::Edit::UIHandlers::Default, &AWSGameLiftPlayerInformation::m_team, "Team", - "Name of the team that the player is assigned to in a match"); - } - } - - if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) - { - behaviorContext->Class("AWSGameLiftPlayerInformation") - ->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value) - ->Property("LatencyInMs", BehaviorValueProperty(&AWSGameLiftPlayerInformation::m_latencyInMs)) - ->Property("PlayerAttributes", BehaviorValueProperty(&AWSGameLiftPlayerInformation::m_playerAttributes)) - ->Property("PlayerId", BehaviorValueProperty(&AWSGameLiftPlayerInformation::m_playerId)) - ->Property("Team", BehaviorValueProperty(&AWSGameLiftPlayerInformation::m_team)); - } - } - void AWSGameLiftStartMatchmakingRequest::Reflect(AZ::ReflectContext* context) { AzFramework::StartMatchmakingRequest::Reflect(context); - AWSGameLiftPlayerInformation::Reflect(context); + AWSGameLiftPlayer::Reflect(context); if (auto serializeContext = azrtti_cast(context)) { diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientManagerTest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientManagerTest.cpp index 3b7c7ee827..1c3e8726fd 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientManagerTest.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/AWSGameLiftClientManagerTest.cpp @@ -208,6 +208,7 @@ protected: sessionConfig.m_terminationTime = 0; sessionConfig.m_creatorId = "dummyCreatorId"; sessionConfig.m_sessionProperties["dummyKey"] = "dummyValue"; + sessionConfig.m_matchmakingData = "dummyMatchmakingData"; sessionConfig.m_sessionId = "dummyGameSessionId"; sessionConfig.m_sessionName = "dummyGameSessionName"; sessionConfig.m_ipAddress = "dummyIpAddress"; @@ -232,7 +233,7 @@ protected: request.m_configurationName = "dummyConfiguration"; request.m_ticketId = DummyMatchmakingTicketId; - AWSGameLiftPlayerInformation player; + AWSGameLiftPlayer player; player.m_playerAttributes["dummy"] = "{\"N\": \"1\"}"; player.m_playerId = DummyPlayerId; player.m_latencyInMs["us-east-1"] = 10; @@ -813,7 +814,7 @@ TEST_F(AWSGameLiftClientManagerTest, StartMatchmaking_CallWithInvalidRequest_Get { AWSGameLiftStartMatchmakingRequest request; request.m_configurationName = "dummyConfiguration"; - AWSGameLiftPlayerInformation player; + AWSGameLiftPlayer player; player.m_playerAttributes["dummy"] = "{\"A\": \"1\"}"; request.m_players.emplace_back(player); @@ -855,7 +856,7 @@ TEST_F(AWSGameLiftClientManagerTest, StartMatchmakingAsync_CallWithInvalidReques { AWSGameLiftStartMatchmakingRequest request; request.m_configurationName = "dummyConfiguration"; - AWSGameLiftPlayerInformation player; + AWSGameLiftPlayer player; player.m_playerAttributes["dummy"] = "{\"A\": \"1\"}"; request.m_players.emplace_back(player); diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStartMatchmakingActivityTest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStartMatchmakingActivityTest.cpp index 3eed6b0448..6da932828c 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStartMatchmakingActivityTest.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/Tests/Activity/AWSGameLiftStartMatchmakingActivityTest.cpp @@ -8,6 +8,7 @@ #include #include +#include #include @@ -21,7 +22,7 @@ TEST_F(AWSGameLiftStartMatchmakingActivityTest, BuildAWSGameLiftStartMatchmaking request.m_configurationName = "dummyConfiguration"; request.m_ticketId = "dummyTicketId"; - AWSGameLiftPlayerInformation player; + AWSGameLiftPlayer player; player.m_playerAttributes["dummy"] = "{\"S\": \"test\"}"; player.m_playerId = "dummyPlayerId"; player.m_team = "dummyTeam"; @@ -58,7 +59,7 @@ TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_ AWSGameLiftStartMatchmakingRequest request; request.m_ticketId = "dummyTicketId"; - AWSGameLiftPlayerInformation player; + AWSGameLiftPlayer player; player.m_playerAttributes["dummy"] = "{\"S\": \"test\"}"; player.m_playerId = "dummyPlayerId"; player.m_team = "dummyTeam"; @@ -89,7 +90,7 @@ TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_ request.m_configurationName = "dummyConfiguration"; request.m_ticketId = "dummyTicketId"; - AWSGameLiftPlayerInformation player; + AWSGameLiftPlayer player; player.m_playerAttributes["dummy"] = "{\"S\": \"test\"}"; player.m_team = "dummyTeam"; player.m_latencyInMs["us-east-1"] = 10; @@ -107,7 +108,7 @@ TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_ request.m_configurationName = "dummyConfiguration"; request.m_ticketId = "dummyTicketId"; - AWSGameLiftPlayerInformation player; + AWSGameLiftPlayer player; player.m_playerAttributes["dummy"] = "{\"A\": \"test\"}"; player.m_playerId = "dummyPlayerId"; player.m_team = "dummyTeam"; @@ -125,7 +126,7 @@ TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_ AWSGameLiftStartMatchmakingRequest request; request.m_configurationName = "dummyConfiguration"; - AWSGameLiftPlayerInformation player; + AWSGameLiftPlayer player; player.m_playerAttributes["dummy"] = "{\"S\": \"test\"}"; player.m_playerId = "dummyPlayerId"; player.m_team = "dummyTeam"; @@ -142,7 +143,7 @@ TEST_F(AWSGameLiftStartMatchmakingActivityTest, ValidateStartMatchmakingRequest_ request.m_ticketId = "dummyTicketId"; request.m_configurationName = "dummyConfiguration"; - AWSGameLiftPlayerInformation player; + AWSGameLiftPlayer player; player.m_playerAttributes["dummy"] = "{\"S\": \"test\"}"; player.m_playerId = "dummyPlayerId"; player.m_team = "dummyTeam"; diff --git a/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_files.cmake b/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_files.cmake index 0930c42370..cd54414cc1 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_files.cmake +++ b/Gems/AWSGameLift/Code/AWSGameLiftClient/awsgamelift_client_files.cmake @@ -7,6 +7,8 @@ # set(FILES + ../AWSGameLiftCommon/Include/AWSGameLiftPlayer.h + ../AWSGameLiftCommon/Source/AWSGameLiftPlayer.cpp ../AWSGameLiftCommon/Source/AWSGameLiftSessionConstants.h Include/Request/AWSGameLiftAcceptMatchRequest.h Include/Request/AWSGameLiftCreateSessionOnQueueRequest.h diff --git a/Gems/AWSGameLift/Code/AWSGameLiftCommon/Include/AWSGameLiftPlayer.h b/Gems/AWSGameLift/Code/AWSGameLiftCommon/Include/AWSGameLiftPlayer.h new file mode 100644 index 0000000000..1fbdadc8bf --- /dev/null +++ b/Gems/AWSGameLift/Code/AWSGameLiftCommon/Include/AWSGameLiftPlayer.h @@ -0,0 +1,44 @@ +/* + * 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 AWSGameLift +{ + //! AWSGameLiftPlayer + //! Information on each player to be matched + //! This information must include a player ID, and may contain player attributes and latency data to be used in the matchmaking process + //! After a successful match, Player objects contain the name of the team the player is assigned to + struct AWSGameLiftPlayer + { + AZ_RTTI(AWSGameLiftPlayer, "{B62C118E-C55D-4903-8ECB-E58E8CA613C4}"); + static void Reflect(AZ::ReflectContext* context); + + AWSGameLiftPlayer() = default; + virtual ~AWSGameLiftPlayer() = default; + + // A map of region names to latencies in millseconds, that indicates + // the amount of latency that a player experiences when connected to AWS Regions + AZStd::unordered_map m_latencyInMs; + + // A collection of key:value pairs containing player information for use in matchmaking + // Player attribute keys must match the playerAttributes used in a matchmaking rule set + // Example: {"skill": "{\"N\": 23}", "gameMode": "{\"S\": \"deathmatch\"}"} + AZStd::unordered_map m_playerAttributes; + + // A unique identifier for a player + AZStd::string m_playerId; + + // Name of the team that the player is assigned to in a match + AZStd::string m_team; + }; +} // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftCommon/Source/AWSGameLiftPlayer.cpp b/Gems/AWSGameLift/Code/AWSGameLiftCommon/Source/AWSGameLiftPlayer.cpp new file mode 100644 index 0000000000..80a3915a6b --- /dev/null +++ b/Gems/AWSGameLift/Code/AWSGameLiftCommon/Source/AWSGameLiftPlayer.cpp @@ -0,0 +1,58 @@ +/* + * 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 AWSGameLift +{ + void AWSGameLiftPlayer::Reflect(AZ::ReflectContext* context) + { + if (auto serializeContext = azrtti_cast(context)) + { + serializeContext->Class() + ->Version(0) + ->Field("latencyInMs", &AWSGameLiftPlayer::m_latencyInMs) + ->Field("playerAttributes", &AWSGameLiftPlayer::m_playerAttributes) + ->Field("playerId", &AWSGameLiftPlayer::m_playerId) + ->Field("team", &AWSGameLiftPlayer::m_team); + + if (AZ::EditContext* editContext = serializeContext->GetEditContext()) + { + editContext->Class("AWSGameLiftPlayer", "") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) + ->DataElement( + AZ::Edit::UIHandlers::Default, &AWSGameLiftPlayer::m_latencyInMs, "LatencyInMs", + "A set of values, expressed in milliseconds, that indicates the amount of latency that" + "a player experiences when connected to AWS Regions") + ->DataElement( + AZ::Edit::UIHandlers::Default, &AWSGameLiftPlayer::m_playerAttributes, "PlayerAttributes", + "A collection of key:value pairs containing player information for use in matchmaking") + ->DataElement( + AZ::Edit::UIHandlers::Default, &AWSGameLiftPlayer::m_playerId, "PlayerId", + "A unique identifier for a player") + ->DataElement( + AZ::Edit::UIHandlers::Default, &AWSGameLiftPlayer::m_team, "Team", + "Name of the team that the player is assigned to in a match"); + } + } + + if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) + { + behaviorContext->Class("AWSGameLiftPlayer") + ->Attribute(AZ::Script::Attributes::Storage, AZ::Script::Attributes::StorageType::Value) + ->Property("LatencyInMs", BehaviorValueProperty(&AWSGameLiftPlayer::m_latencyInMs)) + ->Property("PlayerAttributes", BehaviorValueProperty(&AWSGameLiftPlayer::m_playerAttributes)) + ->Property("PlayerId", BehaviorValueProperty(&AWSGameLiftPlayer::m_playerId)) + ->Property("Team", BehaviorValueProperty(&AWSGameLiftPlayer::m_team)); + } + } +} // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/CMakeLists.txt b/Gems/AWSGameLift/Code/AWSGameLiftServer/CMakeLists.txt index 798c6a6a25..d05ec46b52 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/CMakeLists.txt +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/CMakeLists.txt @@ -17,6 +17,7 @@ ly_add_target( awsgamelift_server_files.cmake INCLUDE_DIRECTORIES PUBLIC + ../AWSGameLiftCommon/Include Include PRIVATE ../AWSGameLiftCommon/Source @@ -54,6 +55,8 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) awsgamelift_server_tests_files.cmake INCLUDE_DIRECTORIES PRIVATE + ../AWSGameLiftCommon/Include + ../AWSGameLiftCommon/Source Tests Source BUILD_DEPENDENCIES diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Include/Request/IAWSGameLiftServerRequests.h b/Gems/AWSGameLift/Code/AWSGameLiftServer/Include/Request/IAWSGameLiftServerRequests.h index e5b14319a8..777086e633 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Include/Request/IAWSGameLiftServerRequests.h +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Include/Request/IAWSGameLiftServerRequests.h @@ -9,9 +9,11 @@ #pragma once #include -#include +#include +#include #include -#include + +#include namespace AWSGameLift { @@ -26,8 +28,21 @@ namespace AWSGameLift virtual ~IAWSGameLiftServerRequests() = default; //! Notify GameLift that the server process is ready to host a game session. - //! @return Whether the ProcessReady notification is sent to GameLift. + //! @return True if the ProcessReady notification is sent to GameLift successfully, false otherwise virtual bool NotifyGameLiftProcessReady() = 0; + + //! Sends a request to find new players for open slots in a game session created with FlexMatch. + //! @param ticketId Unique identifier for match backfill request ticket + //! @param players A set of data representing all players who are currently in the game session, + //! if not provided, system will use lazy loaded game session data which is not guaranteed to + //! be accurate (no latency data either) + //! @return True if StartMatchBackfill succeeds, false otherwise + virtual bool StartMatchBackfill(const AZStd::string& ticketId, const AZStd::vector& players) = 0; + + //! Cancels an active match backfill request that was created with StartMatchBackfill + //! @param ticketId Unique identifier of the backfill request ticket to be canceled + //! @return True if StopMatchBackfill succeeds, false otherwise + virtual bool StopMatchBackfill(const AZStd::string& ticketId) = 0; }; // IAWSGameLiftServerRequests EBus wrapper for scripting diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.cpp b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.cpp index e739933ab2..70d0063b61 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.cpp @@ -17,6 +17,9 @@ #include #include #include +#include +#include +#include #include #include @@ -112,6 +115,7 @@ namespace AWSGameLift { propertiesOutput = propertiesOutput.substr(0, propertiesOutput.size() - 1); // Trim last comma to fit array format } + sessionConfig.m_matchmakingData = gameSession.GetMatchmakerData().c_str(); sessionConfig.m_sessionId = gameSession.GetGameSessionId().c_str(); sessionConfig.m_ipAddress = gameSession.GetIpAddress().c_str(); sessionConfig.m_maxPlayer = gameSession.GetMaximumPlayerSessionCount(); @@ -133,6 +137,276 @@ namespace AWSGameLift return sessionConfig; } + bool AWSGameLiftServerManager::BuildServerMatchBackfillPlayer( + const AWSGameLiftPlayer& player, Aws::GameLift::Server::Model::Player& outBackfillPlayer) + { + outBackfillPlayer.SetPlayerId(player.m_playerId.c_str()); + outBackfillPlayer.SetTeam(player.m_team.c_str()); + for (auto latencyPair : player.m_latencyInMs) + { + outBackfillPlayer.AddLatencyInMs(latencyPair.first.c_str(), latencyPair.second); + } + + for (auto attributePair : player.m_playerAttributes) + { + Aws::GameLift::Server::Model::AttributeValue playerAttribute; + rapidjson::Document attributeDocument; + rapidjson::ParseResult parseResult = attributeDocument.Parse(attributePair.second.c_str()); + // player attribute json content should always be a single member object + if (parseResult && attributeDocument.IsObject() && attributeDocument.MemberCount() == 1) + { + if ((attributeDocument.HasMember(AWSGameLiftMatchmakingPlayerAttributeSTypeName) || + attributeDocument.HasMember(AWSGameLiftMatchmakingPlayerAttributeSServerTypeName)) && + attributeDocument.MemberBegin()->value.IsString()) + { + playerAttribute = Aws::GameLift::Server::Model::AttributeValue( + attributeDocument.MemberBegin()->value.GetString()); + } + else if ((attributeDocument.HasMember(AWSGameLiftMatchmakingPlayerAttributeNTypeName) || + attributeDocument.HasMember(AWSGameLiftMatchmakingPlayerAttributeNServerTypeName)) && + attributeDocument.MemberBegin()->value.IsNumber()) + { + playerAttribute = Aws::GameLift::Server::Model::AttributeValue( + attributeDocument.MemberBegin()->value.GetDouble()); + } + else if ((attributeDocument.HasMember(AWSGameLiftMatchmakingPlayerAttributeSDMTypeName) || + attributeDocument.HasMember(AWSGameLiftMatchmakingPlayerAttributeSDMServerTypeName)) && + attributeDocument.MemberBegin()->value.IsObject()) + { + playerAttribute = Aws::GameLift::Server::Model::AttributeValue::ConstructStringDoubleMap(); + for (auto iter = attributeDocument.MemberBegin()->value.MemberBegin(); + iter != attributeDocument.MemberBegin()->value.MemberEnd(); iter++) + { + if (iter->name.IsString() && iter->value.IsNumber()) + { + playerAttribute.AddStringAndDouble(iter->name.GetString(), iter->value.GetDouble()); + } + else + { + AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftMatchmakingPlayerAttributeInvalidErrorMessage, + player.m_playerId.c_str(), "String double map key must be string type and value must be number type"); + return false; + } + } + } + else if ((attributeDocument.HasMember(AWSGameLiftMatchmakingPlayerAttributeSLTypeName) || + attributeDocument.HasMember(AWSGameLiftMatchmakingPlayerAttributeSLServerTypeName)) && + attributeDocument.MemberBegin()->value.IsArray()) + { + playerAttribute = Aws::GameLift::Server::Model::AttributeValue::ConstructStringList(); + for (auto iter = attributeDocument.MemberBegin()->value.Begin(); + iter != attributeDocument.MemberBegin()->value.End(); iter++) + { + if (iter->IsString()) + { + playerAttribute.AddString(iter->GetString()); + } + else + { + AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftMatchmakingPlayerAttributeInvalidErrorMessage, + player.m_playerId.c_str(), "String list element must be string type"); + return false; + } + } + } + else + { + AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftMatchmakingPlayerAttributeInvalidErrorMessage, + player.m_playerId.c_str(), "S, N, SDM or SLM is expected as attribute type."); + return false; + } + } + else + { + AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftMatchmakingPlayerAttributeInvalidErrorMessage, + player.m_playerId.c_str(), rapidjson::GetParseError_En(parseResult.Code())); + return false; + } + outBackfillPlayer.AddPlayerAttribute(attributePair.first.c_str(), playerAttribute); + } + return true; + } + + AZStd::vector AWSGameLiftServerManager::GetActiveServerMatchBackfillPlayers() + { + AZStd::vector activePlayers; + // Keep processing only when game session has matchmaking data + if (IsMatchmakingDataValid()) + { + auto activePlayerSessions = GetActivePlayerSessions(); + for (auto playerSession : activePlayerSessions) + { + AWSGameLiftPlayer player; + if (BuildActiveServerMatchBackfillPlayer(playerSession.GetPlayerId().c_str(), player)) + { + activePlayers.push_back(player); + } + } + } + return activePlayers; + } + + bool AWSGameLiftServerManager::IsMatchmakingDataValid() + { + return m_matchmakingData.IsObject() && + m_matchmakingData.HasMember(AWSGameLiftMatchmakingConfigurationKeyName) && + m_matchmakingData.HasMember(AWSGameLiftMatchmakingTeamsKeyName); + } + + AZStd::vector AWSGameLiftServerManager::GetActivePlayerSessions() + { + Aws::GameLift::Server::Model::DescribePlayerSessionsRequest describeRequest; + describeRequest.SetGameSessionId(m_gameSession.GetGameSessionId()); + describeRequest.SetPlayerSessionStatusFilter( + Aws::GameLift::Server::Model::PlayerSessionStatusMapper::GetNameForPlayerSessionStatus( + Aws::GameLift::Server::Model::PlayerSessionStatus::ACTIVE)); + int maxPlayerSession = m_gameSession.GetMaximumPlayerSessionCount(); + + AZStd::vector activePlayerSessions; + if (maxPlayerSession <= AWSGameLiftDescribePlayerSessionsPageSize) + { + describeRequest.SetLimit(maxPlayerSession); + auto outcome = m_gameLiftServerSDKWrapper->DescribePlayerSessions(describeRequest); + if (outcome.IsSuccess()) + { + for (auto playerSession : outcome.GetResult().GetPlayerSessions()) + { + activePlayerSessions.push_back(playerSession); + } + } + else + { + AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftDescribePlayerSessionsErrorMessage, + outcome.GetError().GetErrorMessage().c_str()); + } + } + else + { + describeRequest.SetLimit(AWSGameLiftDescribePlayerSessionsPageSize); + while (true) + { + auto outcome = m_gameLiftServerSDKWrapper->DescribePlayerSessions(describeRequest); + if (outcome.IsSuccess()) + { + for (auto playerSession : outcome.GetResult().GetPlayerSessions()) + { + activePlayerSessions.push_back(playerSession); + } + if (outcome.GetResult().GetNextToken().empty()) + { + break; + } + else + { + describeRequest.SetNextToken(outcome.GetResult().GetNextToken()); + } + } + else + { + activePlayerSessions.clear(); + AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftDescribePlayerSessionsErrorMessage, + outcome.GetError().GetErrorMessage().c_str()); + break; + } + } + } + return activePlayerSessions; + } + + bool AWSGameLiftServerManager::BuildActiveServerMatchBackfillPlayer(const AZStd::string& playerId, AWSGameLiftPlayer& outPlayer) + { + // As data is from GameLift service, assume it is always in correct format + rapidjson::Value& teams = m_matchmakingData[AWSGameLiftMatchmakingTeamsKeyName]; + + // Iterate through teams to find target player + for (rapidjson::SizeType teamIndex = 0; teamIndex < teams.Size(); ++teamIndex) + { + rapidjson::Value& players = teams[teamIndex][AWSGameLiftMatchmakingPlayersKeyName]; + + // Iterate through players under the team to find target player + for (rapidjson::SizeType playerIndex = 0; playerIndex < players.Size(); ++playerIndex) + { + if (std::strcmp(players[playerIndex][AWSGameLiftMatchmakingPlayerIdKeyName].GetString(), playerId.c_str()) == 0) + { + outPlayer.m_playerId = playerId; + outPlayer.m_team = teams[teamIndex][AWSGameLiftMatchmakingTeamNameKeyName].GetString(); + // Get player attributes if target player has + if (players[playerIndex].HasMember(AWSGameLiftMatchmakingPlayerAttributesKeyName)) + { + BuildServerMatchBackfillPlayerAttributes( + players[playerIndex][AWSGameLiftMatchmakingPlayerAttributesKeyName], outPlayer); + } + } + else + { + return false; + } + } + } + return true; + } + + void AWSGameLiftServerManager::BuildServerMatchBackfillPlayerAttributes( + const rapidjson::Value& playerAttributes, AWSGameLiftPlayer& outPlayer) + { + for (auto iter = playerAttributes.MemberBegin(); iter != playerAttributes.MemberEnd(); iter++) + { + AZStd::string attributeName = iter->name.GetString(); + + rapidjson::StringBuffer jsonStringBuffer; + rapidjson::Writer writer(jsonStringBuffer); + iter->value[AWSGameLiftMatchmakingPlayerAttributeValueKeyName].Accept(writer); + AZStd::string attributeType = iter->value[AWSGameLiftMatchmakingPlayerAttributeTypeKeyName].GetString(); + AZStd::string attributeValue = AZStd::string::format("{\"%s\": %s}", + attributeType.c_str(), jsonStringBuffer.GetString()); + + outPlayer.m_playerAttributes.emplace(attributeName, attributeValue); + } + } + + bool AWSGameLiftServerManager::BuildStartMatchBackfillRequest( + const AZStd::string& ticketId, + const AZStd::vector& players, + Aws::GameLift::Server::Model::StartMatchBackfillRequest& outRequest) + { + outRequest.SetGameSessionArn(m_gameSession.GetGameSessionId()); + outRequest.SetMatchmakingConfigurationArn(m_matchmakingData[AWSGameLiftMatchmakingConfigurationKeyName].GetString()); + if (!ticketId.empty()) + { + outRequest.SetTicketId(ticketId.c_str()); + } + + AZStd::vector requestPlayers(players); + if (players.size() == 0) + { + requestPlayers = GetActiveServerMatchBackfillPlayers(); + } + for (auto player : requestPlayers) + { + Aws::GameLift::Server::Model::Player backfillPlayer; + if (BuildServerMatchBackfillPlayer(player, backfillPlayer)) + { + outRequest.AddPlayer(backfillPlayer); + } + else + { + return false; + } + } + return true; + } + + void AWSGameLiftServerManager::BuildStopMatchBackfillRequest( + const AZStd::string& ticketId, Aws::GameLift::Server::Model::StopMatchBackfillRequest& outRequest) + { + outRequest.SetGameSessionArn(m_gameSession.GetGameSessionId()); + outRequest.SetMatchmakingConfigurationArn(m_matchmakingData[AWSGameLiftMatchmakingConfigurationKeyName].GetString()); + if (!ticketId.empty()) + { + outRequest.SetTicketId(ticketId.c_str()); + } + } + AZ::IO::Path AWSGameLiftServerManager::GetExternalSessionCertificate() { // TODO: Add support to get TLS cert file path @@ -238,7 +512,7 @@ namespace AWSGameLift Aws::GameLift::Server::ProcessParameters processReadyParameter = Aws::GameLift::Server::ProcessParameters( AZStd::bind(&AWSGameLiftServerManager::OnStartGameSession, this, AZStd::placeholders::_1), - AZStd::bind(&AWSGameLiftServerManager::OnUpdateGameSession, this), + AZStd::bind(&AWSGameLiftServerManager::OnUpdateGameSession, this, AZStd::placeholders::_1), AZStd::bind(&AWSGameLiftServerManager::OnProcessTerminate, this), AZStd::bind(&AWSGameLiftServerManager::OnHealthCheck, this), desc.m_port, Aws::GameLift::Server::LogParameters(logPaths)); @@ -260,6 +534,7 @@ namespace AWSGameLift void AWSGameLiftServerManager::OnStartGameSession(const Aws::GameLift::Server::Model::GameSession& gameSession) { + UpdateGameSessionData(gameSession); AzFramework::SessionConfig sessionConfig = BuildSessionConfig(gameSession); bool createSessionResult = true; @@ -311,10 +586,19 @@ namespace AWSGameLift return m_serverSDKInitialized && healthCheckResult; } - void AWSGameLiftServerManager::OnUpdateGameSession() + void AWSGameLiftServerManager::OnUpdateGameSession(const Aws::GameLift::Server::Model::UpdateGameSession& updateGameSession) { - // TODO: Perform game-specific tasks to prep for newly matched players - return; + Aws::GameLift::Server::Model::UpdateReason updateReason = updateGameSession.GetUpdateReason(); + if (updateReason == Aws::GameLift::Server::Model::UpdateReason::MATCHMAKING_DATA_UPDATED) + { + UpdateGameSessionData(updateGameSession.GetGameSession()); + } + AzFramework::SessionConfig sessionConfig = BuildSessionConfig(updateGameSession.GetGameSession()); + + AzFramework::SessionNotificationBus::Broadcast( + &AzFramework::SessionNotifications::OnUpdateSessionBegin, + sessionConfig, + Aws::GameLift::Server::Model::UpdateReasonMapper::GetNameForUpdateReason(updateReason).c_str()); } bool AWSGameLiftServerManager::RemoveConnectedPlayer(uint32_t playerConnectionId, AZStd::string& outPlayerSessionId) @@ -340,6 +624,92 @@ namespace AWSGameLift m_gameLiftServerSDKWrapper = AZStd::move(gameLiftServerSDKWrapper); } + bool AWSGameLiftServerManager::StartMatchBackfill(const AZStd::string& ticketId, const AZStd::vector& players) + { + if (!m_serverSDKInitialized) + { + AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftServerSDKNotInitErrorMessage); + return false; + } + + if (!IsMatchmakingDataValid()) + { + AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftMatchmakingDataMissingErrorMessage); + return false; + } + + Aws::GameLift::Server::Model::StartMatchBackfillRequest request; + if (!BuildStartMatchBackfillRequest(ticketId, players, request)) + { + return false; + } + + AZ_TracePrintf(AWSGameLiftServerManagerName, "Starting match backfill %s ...", ticketId.c_str()); + auto outcome = m_gameLiftServerSDKWrapper->StartMatchBackfill(request); + if (!outcome.IsSuccess()) + { + AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftStartMatchBackfillErrorMessage, + outcome.GetError().GetErrorMessage().c_str()); + return false; + } + else + { + AZ_TracePrintf(AWSGameLiftServerManagerName, "StartMatchBackfill request against Amazon GameLift service is complete."); + return true; + } + } + + bool AWSGameLiftServerManager::StopMatchBackfill(const AZStd::string& ticketId) + { + if (!m_serverSDKInitialized) + { + AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftServerSDKNotInitErrorMessage); + return false; + } + + if (!IsMatchmakingDataValid()) + { + AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftMatchmakingDataMissingErrorMessage); + return false; + } + + Aws::GameLift::Server::Model::StopMatchBackfillRequest request; + BuildStopMatchBackfillRequest(ticketId, request); + + AZ_TracePrintf(AWSGameLiftServerManagerName, "Stopping match backfill %s ...", ticketId.c_str()); + auto outcome = m_gameLiftServerSDKWrapper->StopMatchBackfill(request); + if (!outcome.IsSuccess()) + { + AZ_Error(AWSGameLiftServerManagerName, false, AWSGameLiftStopMatchBackfillErrorMessage, + outcome.GetError().GetErrorMessage().c_str()); + return false; + } + else + { + AZ_TracePrintf(AWSGameLiftServerManagerName, "StopMatchBackfill request against Amazon GameLift service is complete."); + return true; + } + } + + void AWSGameLiftServerManager::UpdateGameSessionData(const Aws::GameLift::Server::Model::GameSession& gameSession) + { + AZ_TracePrintf(AWSGameLiftServerManagerName, "Lazy loading game session and matchmaking data from Amazon GameLift service ..."); + m_gameSession = Aws::GameLift::Server::Model::GameSession(gameSession); + if (m_gameSession.GetMatchmakerData().empty()) + { + m_matchmakingData.Parse("{}"); + } + else + { + rapidjson::ParseResult parseResult = m_matchmakingData.Parse(m_gameSession.GetMatchmakerData().c_str()); + if (!parseResult) + { + AZ_Error(AWSGameLiftServerManagerName, false, + AWSGameLiftMatchmakingDataInvalidErrorMessage, rapidjson::GetParseError_En(parseResult.Code())); + } + } + } + bool AWSGameLiftServerManager::ValidatePlayerJoinSession(const AzFramework::PlayerConnectionConfig& playerConnectionConfig) { uint32_t playerConnectionId = playerConnectionConfig.m_playerConnectionId; diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.h b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.h index c0f1c00bea..fa2f783eca 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.h +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/AWSGameLiftServerManager.h @@ -11,11 +11,15 @@ #include #include +#include +#include #include #include #include #include #include + +#include #include namespace AWSGameLift @@ -66,6 +70,36 @@ namespace AWSGameLift "Invalid player connection config, player connection id: %d, player session id: %s"; static constexpr const char AWSGameLiftServerRemovePlayerSessionErrorMessage[] = "Failed to notify GameLift that the player with the player session id %s has disconnected from the server process. ErrorMessage: %s"; + static constexpr const char AWSGameLiftMatchmakingDataInvalidErrorMessage[] = + "Failed to parse GameLift matchmaking data. ErrorMessage: %s"; + static constexpr const char AWSGameLiftMatchmakingDataMissingErrorMessage[] = + "GameLift matchmaking data is missing or invalid to parse."; + static constexpr const char AWSGameLiftMatchmakingPlayerAttributeInvalidErrorMessage[] = + "Failed to build player %s attributes. ErrorMessage: %s"; + static constexpr const char AWSGameLiftDescribePlayerSessionsErrorMessage[] = + "Failed to describe player sessions. ErrorMessage: %s"; + static constexpr const char AWSGameLiftStartMatchBackfillErrorMessage[] = + "Failed to start match backfill. ErrorMessage: %s"; + static constexpr const char AWSGameLiftStopMatchBackfillErrorMessage[] = + "Failed to stop match backfill. ErrorMessage: %s"; + + static constexpr const char AWSGameLiftMatchmakingConfigurationKeyName[] = "matchmakingConfigurationArn"; + static constexpr const char AWSGameLiftMatchmakingTeamsKeyName[] = "teams"; + static constexpr const char AWSGameLiftMatchmakingTeamNameKeyName[] = "name"; + static constexpr const char AWSGameLiftMatchmakingPlayersKeyName[] = "players"; + static constexpr const char AWSGameLiftMatchmakingPlayerIdKeyName[] = "playerId"; + static constexpr const char AWSGameLiftMatchmakingPlayerAttributesKeyName[] = "attributes"; + static constexpr const char AWSGameLiftMatchmakingPlayerAttributeTypeKeyName[] = "attributeType"; + static constexpr const char AWSGameLiftMatchmakingPlayerAttributeValueKeyName[] = "valueAttribute"; + static constexpr const char AWSGameLiftMatchmakingPlayerAttributeSTypeName[] = "S"; + static constexpr const char AWSGameLiftMatchmakingPlayerAttributeSServerTypeName[] = "STRING"; + static constexpr const char AWSGameLiftMatchmakingPlayerAttributeNTypeName[] = "N"; + static constexpr const char AWSGameLiftMatchmakingPlayerAttributeNServerTypeName[] = "NUMBER"; + static constexpr const char AWSGameLiftMatchmakingPlayerAttributeSLTypeName[] = "SL"; + static constexpr const char AWSGameLiftMatchmakingPlayerAttributeSLServerTypeName[] = "STRING_LIST"; + static constexpr const char AWSGameLiftMatchmakingPlayerAttributeSDMTypeName[] = "SDM"; + static constexpr const char AWSGameLiftMatchmakingPlayerAttributeSDMServerTypeName[] = "STRING_DOUBLE_MAP"; + static constexpr const uint16_t AWSGameLiftDescribePlayerSessionsPageSize = 30; AWSGameLiftServerManager(); virtual ~AWSGameLiftServerManager(); @@ -78,6 +112,8 @@ namespace AWSGameLift // AWSGameLiftServerRequestBus interface implementation bool NotifyGameLiftProcessReady() override; + bool StartMatchBackfill(const AZStd::string& ticketId, const AZStd::vector& players) override; + bool StopMatchBackfill(const AZStd::string& ticketId) override; // ISessionHandlingProviderRequests interface implementation void HandleDestroySession() override; @@ -92,18 +128,48 @@ namespace AWSGameLift //! Add connected player session id. bool AddConnectedPlayer(const AzFramework::PlayerConnectionConfig& playerConnectionConfig); + //! Get active server player data from lazy loaded game session for server match backfill + AZStd::vector GetActiveServerMatchBackfillPlayers(); + + //! Update local game session data to latest one + void UpdateGameSessionData(const Aws::GameLift::Server::Model::GameSession& gameSession); + private: //! Build the serverProcessDesc with appropriate server port number and log paths. GameLiftServerProcessDesc BuildGameLiftServerProcessDesc(); + //! Build active server player data from lazy loaded game session based on player id + bool BuildActiveServerMatchBackfillPlayer(const AZStd::string& playerId, AWSGameLiftPlayer& outPlayer); + + //! Build server player attribute data from lazy load matchmaking data + void BuildServerMatchBackfillPlayerAttributes(const rapidjson::Value& playerAttributes, AWSGameLiftPlayer& outPlayer); + + //! Build server player data for server match backfill + bool BuildServerMatchBackfillPlayer(const AWSGameLiftPlayer& player, Aws::GameLift::Server::Model::Player& outBackfillPlayer); + + //! Build start match backfill request for StartMatchBackfill operation + bool BuildStartMatchBackfillRequest( + const AZStd::string& ticketId, + const AZStd::vector& players, + Aws::GameLift::Server::Model::StartMatchBackfillRequest& outRequest); + + //! Build stop match backfill request for StopMatchBackfill operation + void BuildStopMatchBackfillRequest(const AZStd::string& ticketId, Aws::GameLift::Server::Model::StopMatchBackfillRequest& outRequest); + //! Build session config by using AWS GameLift Server GameSession Model. AzFramework::SessionConfig BuildSessionConfig(const Aws::GameLift::Server::Model::GameSession& gameSession); + //! Check whether matchmaking data is in proper format + bool IsMatchmakingDataValid(); + + //! Fetch active player sessions in game session. + AZStd::vector GetActivePlayerSessions(); + //! Callback function that the GameLift service invokes to activate a new game session. void OnStartGameSession(const Aws::GameLift::Server::Model::GameSession& gameSession); //! Callback function that the GameLift service invokes to pass an updated game session object to the server process. - void OnUpdateGameSession(); + void OnUpdateGameSession(const Aws::GameLift::Server::Model::UpdateGameSession& updateGameSession); //! Callback function that the server process or GameLift service invokes to force the server process to shut down. void OnProcessTerminate(); @@ -125,5 +191,12 @@ namespace AWSGameLift using PlayerConnectionId = uint32_t; using PlayerSessionId = AZStd::string; AZStd::unordered_map m_connectedPlayers; + + // Lazy loaded game session and matchmaking data + Aws::GameLift::Server::Model::GameSession m_gameSession; + // Matchmaking data contains a unique match ID, it identifies the matchmaker that created the match + // and describes the teams, team assignments, and players. + // Reference https://docs.aws.amazon.com/gamelift/latest/flexmatchguide/match-server.html#match-server-data + rapidjson::Document m_matchmakingData; }; } // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/GameLiftServerSDKWrapper.cpp b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/GameLiftServerSDKWrapper.cpp index 7e216f33be..d51c8eb8cb 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/GameLiftServerSDKWrapper.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/GameLiftServerSDKWrapper.cpp @@ -22,6 +22,12 @@ namespace AWSGameLift return Aws::GameLift::Server::ActivateGameSession(); } + Aws::GameLift::DescribePlayerSessionsOutcome GameLiftServerSDKWrapper::DescribePlayerSessions( + const Aws::GameLift::Server::Model::DescribePlayerSessionsRequest& describePlayerSessionsRequest) + { + return Aws::GameLift::Server::DescribePlayerSessions(describePlayerSessionsRequest); + } + Aws::GameLift::Server::InitSDKOutcome GameLiftServerSDKWrapper::InitSDK() { return Aws::GameLift::Server::InitSDK(); @@ -69,4 +75,17 @@ namespace AWSGameLift { return Aws::GameLift::Server::RemovePlayerSession(playerSessionId.c_str()); } + + Aws::GameLift::StartMatchBackfillOutcome GameLiftServerSDKWrapper::StartMatchBackfill( + const Aws::GameLift::Server::Model::StartMatchBackfillRequest& startMatchBackfillRequest) + { + return Aws::GameLift::Server::StartMatchBackfill(startMatchBackfillRequest); + } + + Aws::GameLift::GenericOutcome GameLiftServerSDKWrapper::StopMatchBackfill( + const Aws::GameLift::Server::Model::StopMatchBackfillRequest& stopMatchBackfillRequest) + { + return Aws::GameLift::Server::StopMatchBackfill(stopMatchBackfillRequest); + } + } // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/GameLiftServerSDKWrapper.h b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/GameLiftServerSDKWrapper.h index a656087206..e56366d75a 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/GameLiftServerSDKWrapper.h +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Source/GameLiftServerSDKWrapper.h @@ -33,6 +33,14 @@ namespace AWSGameLift //! @return Returns a generic outcome consisting of success or failure with an error message. virtual Aws::GameLift::GenericOutcome ActivateGameSession(); + //! Retrieves player session data, including settings, session metadata, and player data. + //! Use this action to get information for a single player session, + //! for all player sessions in a game session, or for all player sessions associated with a single player ID. + //! @param describePlayerSessionsRequest The request object describing which player sessions to retrieve. + //! @return If successful, returns a DescribePlayerSessionsOutcome object containing a set of player session objects that fit the request parameters. + virtual Aws::GameLift::DescribePlayerSessionsOutcome DescribePlayerSessions( + const Aws::GameLift::Server::Model::DescribePlayerSessionsRequest& describePlayerSessionsRequest); + //! Initializes the GameLift SDK. //! Should be called when the server starts, before any GameLift-dependent initialization happens. //! @return If successful, returns an InitSdkOutcome object indicating that the server process is ready to call ProcessReady(). @@ -56,5 +64,16 @@ namespace AWSGameLift //! @param playerSessionId Unique ID issued by the Amazon GameLift service in response to a call to the AWS SDK Amazon GameLift API action CreatePlayerSession. //! @return Returns a generic outcome consisting of success or failure with an error message. virtual Aws::GameLift::GenericOutcome RemovePlayerSession(const AZStd::string& playerSessionId); + + //! Sends a request to find new players for open slots in a game session created with FlexMatch. + //! When the match has been successfully, backfilled updated matchmaker data will be sent to the OnUpdateGameSession callback. + //! @param startMatchBackfillRequest This data type is used to send a matchmaking backfill request. + //! @return Returns a StartMatchBackfillOutcome object with the match backfill ticket or failure with an error message. + virtual Aws::GameLift::StartMatchBackfillOutcome StartMatchBackfill(const Aws::GameLift::Server::Model::StartMatchBackfillRequest& startMatchBackfillRequest); + + //! Cancels an active match backfill request that was created with StartMatchBackfill + //! @param stopMatchBackfillRequest This data type is used to cancel a matchmaking backfill request. + //! @return Returns a generic outcome consisting of success or failure with an error message. + virtual Aws::GameLift::GenericOutcome StopMatchBackfill(const Aws::GameLift::Server::Model::StopMatchBackfillRequest& stopMatchBackfillRequest); }; } // namespace AWSGameLift diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Tests/AWSGameLiftServerManagerTest.cpp b/Gems/AWSGameLift/Code/AWSGameLiftServer/Tests/AWSGameLiftServerManagerTest.cpp index 2c8929b297..d172734ec0 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Tests/AWSGameLiftServerManagerTest.cpp +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Tests/AWSGameLiftServerManagerTest.cpp @@ -16,6 +16,136 @@ namespace UnitTest { + static constexpr const char TEST_SERVER_MATCHMAKING_DATA[] = +R"({ + "matchId":"testmatchid", + "matchmakingConfigurationArn":"testmatchconfig", + "teams":[ + {"name":"testteam", + "players":[ + {"playerId":"testplayer", + "attributes":{ + "skills":{ + "attributeType":"STRING_DOUBLE_MAP", + "valueAttribute":{"test1":10.0,"test2":20.0,"test3":30.0,"test4":40.0} + }, + "mode":{ + "attributeType":"STRING", + "valueAttribute":"testmode" + }, + "level":{ + "attributeType":"NUMBER", + "valueAttribute":10.0 + }, + "items":{ + "attributeType":"STRING_LIST", + "valueAttribute":["test1","test2","test3"] + } + }} + ]} + ] +})"; + + Aws::GameLift::Server::Model::StartMatchBackfillRequest GetTestStartMatchBackfillRequest() + { + Aws::GameLift::Server::Model::StartMatchBackfillRequest request; + request.SetMatchmakingConfigurationArn("testmatchconfig"); + Aws::GameLift::Server::Model::Player player; + player.SetPlayerId("testplayer"); + player.SetTeam("testteam"); + player.AddPlayerAttribute("mode", Aws::GameLift::Server::Model::AttributeValue("testmode")); + player.AddPlayerAttribute("level", Aws::GameLift::Server::Model::AttributeValue(10.0)); + auto sdmValue = Aws::GameLift::Server::Model::AttributeValue::ConstructStringDoubleMap(); + sdmValue.AddStringAndDouble("test1", 10.0); + player.AddPlayerAttribute("skills", sdmValue); + auto slValue = Aws::GameLift::Server::Model::AttributeValue::ConstructStringList(); + slValue.AddString("test1"); + player.AddPlayerAttribute("items", slValue); + player.AddLatencyInMs("testregion", 10); + request.AddPlayer(player); + request.SetTicketId("testticket"); + return request; + } + + AWSGameLiftPlayer GetTestGameLiftPlayer() + { + AWSGameLiftPlayer player; + player.m_team = "testteam"; + player.m_playerId = "testplayer"; + player.m_playerAttributes.emplace("mode", "{\"S\": \"testmode\"}"); + player.m_playerAttributes.emplace("level", "{\"N\": 10.0}"); + player.m_playerAttributes.emplace("skills", "{\"SDM\": {\"test1\":10.0}}"); + player.m_playerAttributes.emplace("items", "{\"SL\": [\"test1\"]}"); + player.m_latencyInMs.emplace("testregion", 10); + return player; + } + + MATCHER_P(StartMatchBackfillRequestMatcher, expectedRequest, "") + { + // Custome matcher for checking the SearchSessionsResponse type argument. + AZ_UNUSED(result_listener); + if (strcmp(arg.GetGameSessionArn().c_str(), expectedRequest.GetGameSessionArn().c_str()) != 0) + { + return false; + } + if (strcmp(arg.GetMatchmakingConfigurationArn().c_str(), expectedRequest.GetMatchmakingConfigurationArn().c_str()) != 0) + { + return false; + } + if (strcmp(arg.GetTicketId().c_str(), expectedRequest.GetTicketId().c_str()) != 0) + { + return false; + } + if (arg.GetPlayers().size() != expectedRequest.GetPlayers().size()) + { + return false; + } + for (int playerIndex = 0; playerIndex < expectedRequest.GetPlayers().size(); playerIndex++) + { + auto actualPlayerAttributes = arg.GetPlayers()[playerIndex].GetPlayerAttributes(); + auto expectedPlayerAttributes = expectedRequest.GetPlayers()[playerIndex].GetPlayerAttributes(); + if (actualPlayerAttributes.size() != expectedPlayerAttributes.size()) + { + return false; + } + for (auto attributePair : expectedPlayerAttributes) + { + if (actualPlayerAttributes.find(attributePair.first) == actualPlayerAttributes.end()) + { + return false; + } + if (!(attributePair.second.GetType() == actualPlayerAttributes[attributePair.first].GetType() && + (attributePair.second.GetS() == actualPlayerAttributes[attributePair.first].GetS() || + attributePair.second.GetN() == actualPlayerAttributes[attributePair.first].GetN() || + attributePair.second.GetSL() == actualPlayerAttributes[attributePair.first].GetSL() || + attributePair.second.GetSDM() == actualPlayerAttributes[attributePair.first].GetSDM()))) + { + return false; + } + } + + auto actualLatencies = arg.GetPlayers()[playerIndex].GetLatencyInMs(); + auto expectedLatencies = expectedRequest.GetPlayers()[playerIndex].GetLatencyInMs(); + if (actualLatencies.size() != expectedLatencies.size()) + { + return false; + } + for (auto latencyPair : expectedLatencies) + { + if (actualLatencies.find(latencyPair.first) == actualLatencies.end()) + { + return false; + } + if (latencyPair.second != actualLatencies[latencyPair.first]) + { + return false; + } + } + } + + return true; + } + class SessionNotificationsHandlerMock : public AzFramework::SessionNotificationBus::Handler { @@ -33,6 +163,7 @@ namespace UnitTest MOCK_METHOD0(OnSessionHealthCheck, bool()); MOCK_METHOD1(OnCreateSessionBegin, bool(const AzFramework::SessionConfig&)); MOCK_METHOD0(OnDestroySessionBegin, bool()); + MOCK_METHOD2(OnUpdateSessionBegin, void(const AzFramework::SessionConfig&, const AZStd::string&)); }; class GameLiftServerManagerTest @@ -228,6 +359,64 @@ namespace UnitTest AZ_TEST_STOP_TRACE_SUPPRESSION(1); } + TEST_F(GameLiftServerManagerTest, OnUpdateGameSession_TriggerWithUnknownReason_OnUpdateSessionBeginGetCalledOnce) + { + m_serverManager->InitializeGameLiftServerSDK(); + m_serverManager->NotifyGameLiftProcessReady(); + SessionNotificationsHandlerMock handlerMock; + EXPECT_CALL(handlerMock, OnUpdateSessionBegin(testing::_, testing::_)).Times(1); + + m_serverManager->m_gameLiftServerSDKWrapperMockPtr->m_onUpdateGameSessionFunc( + Aws::GameLift::Server::Model::UpdateGameSession( + Aws::GameLift::Server::Model::GameSession(), + Aws::GameLift::Server::Model::UpdateReason::UNKNOWN, + "testticket")); + } + + TEST_F(GameLiftServerManagerTest, OnUpdateGameSession_TriggerWithEmptyMatchmakingData_OnUpdateSessionBeginGetCalledOnce) + { + m_serverManager->InitializeGameLiftServerSDK(); + m_serverManager->NotifyGameLiftProcessReady(); + SessionNotificationsHandlerMock handlerMock; + EXPECT_CALL(handlerMock, OnUpdateSessionBegin(testing::_, testing::_)).Times(1); + + m_serverManager->m_gameLiftServerSDKWrapperMockPtr->m_onUpdateGameSessionFunc( + Aws::GameLift::Server::Model::UpdateGameSession( + Aws::GameLift::Server::Model::GameSession(), + Aws::GameLift::Server::Model::UpdateReason::MATCHMAKING_DATA_UPDATED, + "testticket")); + } + + TEST_F(GameLiftServerManagerTest, OnUpdateGameSession_TriggerWithValidMatchmakingData_OnUpdateSessionBeginGetCalledOnce) + { + m_serverManager->InitializeGameLiftServerSDK(); + m_serverManager->NotifyGameLiftProcessReady(); + SessionNotificationsHandlerMock handlerMock; + EXPECT_CALL(handlerMock, OnUpdateSessionBegin(testing::_, testing::_)).Times(1); + + Aws::GameLift::Server::Model::GameSession gameSession; + gameSession.SetMatchmakerData(TEST_SERVER_MATCHMAKING_DATA); + m_serverManager->m_gameLiftServerSDKWrapperMockPtr->m_onUpdateGameSessionFunc( + Aws::GameLift::Server::Model::UpdateGameSession( + gameSession, Aws::GameLift::Server::Model::UpdateReason::MATCHMAKING_DATA_UPDATED, "testticket")); + } + + TEST_F(GameLiftServerManagerTest, OnUpdateGameSession_TriggerWithInvalidMatchmakingData_OnUpdateSessionBeginGetCalledOnce) + { + m_serverManager->InitializeGameLiftServerSDK(); + m_serverManager->NotifyGameLiftProcessReady(); + SessionNotificationsHandlerMock handlerMock; + EXPECT_CALL(handlerMock, OnUpdateSessionBegin(testing::_, testing::_)).Times(1); + + Aws::GameLift::Server::Model::GameSession gameSession; + gameSession.SetMatchmakerData("{invalid}"); + AZ_TEST_START_TRACE_SUPPRESSION; + m_serverManager->m_gameLiftServerSDKWrapperMockPtr->m_onUpdateGameSessionFunc( + Aws::GameLift::Server::Model::UpdateGameSession( + gameSession, Aws::GameLift::Server::Model::UpdateReason::MATCHMAKING_DATA_UPDATED, "testticket")); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + } + TEST_F(GameLiftServerManagerTest, ValidatePlayerJoinSession_CallWithInvalidConnectionConfig_GetFalseResultAndExpectedErrorLog) { AZ_TEST_START_TRACE_SUPPRESSION; @@ -425,4 +614,331 @@ namespace UnitTest } AZ_TEST_STOP_TRACE_SUPPRESSION(testThreadNumber - 1); // The player is only disconnected once. } + + TEST_F(GameLiftServerManagerTest, UpdateGameSessionData_CallWithInvalidMatchmakingData_GetExpectedError) + { + AZ_TEST_START_TRACE_SUPPRESSION; + m_serverManager->SetupTestMatchmakingData("{invalid}"); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + } + + TEST_F(GameLiftServerManagerTest, GetActiveServerMatchBackfillPlayers_CallWithInvalidMatchmakingData_GetEmptyResult) + { + AZ_TEST_START_TRACE_SUPPRESSION; + m_serverManager->SetupTestMatchmakingData("{invalid}"); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + + auto actualResult = m_serverManager->GetTestServerMatchBackfillPlayers(); + EXPECT_TRUE(actualResult.empty()); + } + + TEST_F(GameLiftServerManagerTest, GetActiveServerMatchBackfillPlayers_CallWithEmptyMatchmakingData_GetEmptyResult) + { + m_serverManager->SetupTestMatchmakingData(""); + + auto actualResult = m_serverManager->GetTestServerMatchBackfillPlayers(); + EXPECT_TRUE(actualResult.empty()); + } + + TEST_F(GameLiftServerManagerTest, GetActiveServerMatchBackfillPlayers_CallButDescribePlayerError_GetEmptyResult) + { + m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA); + + Aws::GameLift::GameLiftError error; + Aws::GameLift::DescribePlayerSessionsOutcome errorOutcome(error); + EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), DescribePlayerSessions(testing::_)) + .Times(1) + .WillOnce(Return(errorOutcome)); + + AZ_TEST_START_TRACE_SUPPRESSION; + auto actualResult = m_serverManager->GetTestServerMatchBackfillPlayers(); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + EXPECT_TRUE(actualResult.empty()); + } + + TEST_F(GameLiftServerManagerTest, GetActiveServerMatchBackfillPlayers_CallButNoActivePlayer_GetEmptyResult) + { + m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA); + + Aws::GameLift::Server::Model::DescribePlayerSessionsResult result; + Aws::GameLift::DescribePlayerSessionsOutcome successOutcome(result); + EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), DescribePlayerSessions(testing::_)) + .Times(1) + .WillOnce(Return(successOutcome)); + + auto actualResult = m_serverManager->GetTestServerMatchBackfillPlayers(); + EXPECT_TRUE(actualResult.empty()); + } + + TEST_F(GameLiftServerManagerTest, GetActiveServerMatchBackfillPlayers_CallWithValidMatchmakingData_GetExpectedResult) + { + m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA); + + Aws::GameLift::Server::Model::PlayerSession playerSession; + playerSession.SetPlayerId("testplayer"); + Aws::GameLift::Server::Model::DescribePlayerSessionsResult result; + result.AddPlayerSessions(playerSession); + Aws::GameLift::DescribePlayerSessionsOutcome successOutcome(result); + EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), DescribePlayerSessions(testing::_)) + .Times(1) + .WillOnce(Return(successOutcome)); + + auto actualResult = m_serverManager->GetTestServerMatchBackfillPlayers(); + EXPECT_TRUE(actualResult.size() == 1); + EXPECT_TRUE(actualResult[0].m_team == "testteam"); + EXPECT_TRUE(actualResult[0].m_playerId == "testplayer"); + EXPECT_TRUE(actualResult[0].m_playerAttributes.size() == 4); + } + + TEST_F(GameLiftServerManagerTest, GetActiveServerMatchBackfillPlayers_CallWithMultiDescribePlayerButError_GetEmptyResult) + { + m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA, 50); + + Aws::GameLift::GameLiftError error; + Aws::GameLift::DescribePlayerSessionsOutcome errorOutcome(error); + EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), DescribePlayerSessions(testing::_)) + .Times(1) + .WillOnce(Return(errorOutcome)); + + AZ_TEST_START_TRACE_SUPPRESSION; + auto actualResult = m_serverManager->GetTestServerMatchBackfillPlayers(); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + EXPECT_TRUE(actualResult.empty()); + } + + TEST_F(GameLiftServerManagerTest, GetActiveServerMatchBackfillPlayers_CallWithMultiDescribePlayer_GetExpectedResult) + { + m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA, 50); + + Aws::GameLift::Server::Model::PlayerSession playerSession1; + playerSession1.SetPlayerId("testplayer"); + Aws::GameLift::Server::Model::DescribePlayerSessionsResult result1; + result1.AddPlayerSessions(playerSession1); + result1.SetNextToken("testtoken"); + Aws::GameLift::DescribePlayerSessionsOutcome successOutcome1(result1); + + Aws::GameLift::Server::Model::PlayerSession playerSession2; + playerSession2.SetPlayerId("playernotinmatch"); + Aws::GameLift::Server::Model::DescribePlayerSessionsResult result2; + result2.AddPlayerSessions(playerSession2); + Aws::GameLift::DescribePlayerSessionsOutcome successOutcome2(result2); + EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), DescribePlayerSessions(testing::_)) + .WillOnce(Return(successOutcome1)) + .WillOnce(Return(successOutcome2)); + + auto actualResult = m_serverManager->GetTestServerMatchBackfillPlayers(); + EXPECT_TRUE(actualResult.size() == 1); + EXPECT_TRUE(actualResult[0].m_team == "testteam"); + EXPECT_TRUE(actualResult[0].m_playerId == "testplayer"); + EXPECT_TRUE(actualResult[0].m_playerAttributes.size() == 4); + } + + TEST_F(GameLiftServerManagerTest, StartMatchBackfill_SDKNotInitialized_GetExpectedError) + { + AZ_TEST_START_TRACE_SUPPRESSION; + auto actualResult = m_serverManager->StartMatchBackfill("testticket", {}); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + EXPECT_FALSE(actualResult); + } + + TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallWithEmptyMatchmakingData_GetExpectedError) + { + m_serverManager->InitializeGameLiftServerSDK(); + m_serverManager->SetupTestMatchmakingData(""); + + AZ_TEST_START_TRACE_SUPPRESSION; + auto actualResult = m_serverManager->StartMatchBackfill("testticket", {}); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + EXPECT_FALSE(actualResult); + } + + TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallWithInvalidPlayerAttribute_GetExpectedError) + { + m_serverManager->InitializeGameLiftServerSDK(); + m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA); + + AWSGameLiftPlayer testPlayer = GetTestGameLiftPlayer(); + testPlayer.m_playerAttributes.clear(); + testPlayer.m_playerAttributes.emplace("invalidattribute", "{invalid}"); + + AZ_TEST_START_TRACE_SUPPRESSION; + auto actualResult = m_serverManager->StartMatchBackfill("testticket", { testPlayer }); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + EXPECT_FALSE(actualResult); + } + + TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallWithWrongPlayerAttributeType_GetExpectedError) + { + m_serverManager->InitializeGameLiftServerSDK(); + m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA); + + AWSGameLiftPlayer testPlayer = GetTestGameLiftPlayer(); + testPlayer.m_playerAttributes.clear(); + testPlayer.m_playerAttributes.emplace("invalidattribute", "{\"SDM\": [\"test1\"]}"); + + AZ_TEST_START_TRACE_SUPPRESSION; + auto actualResult = m_serverManager->StartMatchBackfill("testticket", { testPlayer }); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + EXPECT_FALSE(actualResult); + } + + TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallWithUnexpectedPlayerAttributeType_GetExpectedError) + { + m_serverManager->InitializeGameLiftServerSDK(); + m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA); + + AWSGameLiftPlayer testPlayer = GetTestGameLiftPlayer(); + testPlayer.m_playerAttributes.clear(); + testPlayer.m_playerAttributes.emplace("invalidattribute", "{\"UNEXPECTED\": [\"test1\"]}"); + + AZ_TEST_START_TRACE_SUPPRESSION; + auto actualResult = m_serverManager->StartMatchBackfill("testticket", { testPlayer }); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + EXPECT_FALSE(actualResult); + } + + TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallWithWrongSLPlayerAttributeValue_GetExpectedError) + { + m_serverManager->InitializeGameLiftServerSDK(); + m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA); + + AWSGameLiftPlayer testPlayer = GetTestGameLiftPlayer(); + testPlayer.m_playerAttributes.clear(); + testPlayer.m_playerAttributes.emplace("invalidattribute", "{\"SL\": [10.0]}"); + + AZ_TEST_START_TRACE_SUPPRESSION; + auto actualResult = m_serverManager->StartMatchBackfill("testticket", { testPlayer }); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + EXPECT_FALSE(actualResult); + } + + TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallWithWrongSDMPlayerAttributeValue_GetExpectedError) + { + m_serverManager->InitializeGameLiftServerSDK(); + m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA); + + AWSGameLiftPlayer testPlayer = GetTestGameLiftPlayer(); + testPlayer.m_playerAttributes.clear(); + testPlayer.m_playerAttributes.emplace("invalidattribute", "{\"SDM\": {10.0: \"test1\"}}"); + + AZ_TEST_START_TRACE_SUPPRESSION; + auto actualResult = m_serverManager->StartMatchBackfill("testticket", { testPlayer }); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + EXPECT_FALSE(actualResult); + } + + TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallWithValidPlayersData_GetExpectedResult) + { + m_serverManager->InitializeGameLiftServerSDK(); + m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA); + + Aws::GameLift::Server::Model::StartMatchBackfillResult backfillResult; + Aws::GameLift::StartMatchBackfillOutcome backfillSuccessOutcome(backfillResult); + Aws::GameLift::Server::Model::StartMatchBackfillRequest request = GetTestStartMatchBackfillRequest(); + + EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), StartMatchBackfill(StartMatchBackfillRequestMatcher(request))) + .Times(1) + .WillOnce(Return(backfillSuccessOutcome)); + + AWSGameLiftPlayer testPlayer = GetTestGameLiftPlayer(); + auto actualResult = m_serverManager->StartMatchBackfill("testticket", {testPlayer}); + EXPECT_TRUE(actualResult); + } + + TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallWithoutGivingPlayersData_GetExpectedResult) + { + m_serverManager->InitializeGameLiftServerSDK(); + m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA); + + Aws::GameLift::Server::Model::PlayerSession playerSession; + playerSession.SetPlayerId("testplayer"); + Aws::GameLift::Server::Model::DescribePlayerSessionsResult result; + result.AddPlayerSessions(playerSession); + Aws::GameLift::DescribePlayerSessionsOutcome successOutcome(result); + EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), DescribePlayerSessions(testing::_)) + .Times(1) + .WillOnce(Return(successOutcome)); + + Aws::GameLift::Server::Model::StartMatchBackfillResult backfillResult; + Aws::GameLift::StartMatchBackfillOutcome backfillSuccessOutcome(backfillResult); + EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), StartMatchBackfill(testing::_)) + .Times(1) + .WillOnce(Return(backfillSuccessOutcome)); + + auto actualResult = m_serverManager->StartMatchBackfill("testticket", {}); + EXPECT_TRUE(actualResult); + } + + TEST_F(GameLiftServerManagerTest, StartMatchBackfill_CallButStartBackfillFail_GetExpectedError) + { + m_serverManager->InitializeGameLiftServerSDK(); + m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA); + + Aws::GameLift::Server::Model::PlayerSession playerSession; + playerSession.SetPlayerId("testplayer"); + Aws::GameLift::Server::Model::DescribePlayerSessionsResult result; + result.AddPlayerSessions(playerSession); + Aws::GameLift::DescribePlayerSessionsOutcome successOutcome(result); + EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), DescribePlayerSessions(testing::_)) + .Times(1) + .WillOnce(Return(successOutcome)); + + Aws::GameLift::GameLiftError error; + Aws::GameLift::StartMatchBackfillOutcome errorOutcome(error); + EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), StartMatchBackfill(testing::_)) + .Times(1) + .WillOnce(Return(errorOutcome)); + + AZ_TEST_START_TRACE_SUPPRESSION; + auto actualResult = m_serverManager->StartMatchBackfill("testticket", {}); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + EXPECT_FALSE(actualResult); + } + + TEST_F(GameLiftServerManagerTest, StopMatchBackfill_SDKNotInitialized_GetExpectedError) + { + AZ_TEST_START_TRACE_SUPPRESSION; + auto actualResult = m_serverManager->StopMatchBackfill("testticket"); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + EXPECT_FALSE(actualResult); + } + + TEST_F(GameLiftServerManagerTest, StopMatchBackfill_CallWithEmptyMatchmakingData_GetExpectedError) + { + m_serverManager->InitializeGameLiftServerSDK(); + m_serverManager->SetupTestMatchmakingData(""); + + AZ_TEST_START_TRACE_SUPPRESSION; + auto actualResult = m_serverManager->StopMatchBackfill("testticket"); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + EXPECT_FALSE(actualResult); + } + + TEST_F(GameLiftServerManagerTest, StopMatchBackfill_CallAndSuccessOutcome_GetExpectedResult) + { + m_serverManager->InitializeGameLiftServerSDK(); + m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA); + + EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), StopMatchBackfill(testing::_)) + .Times(1) + .WillOnce(Return(Aws::GameLift::GenericOutcome(nullptr))); + + auto actualResult = m_serverManager->StopMatchBackfill("testticket"); + EXPECT_TRUE(actualResult); + } + + TEST_F(GameLiftServerManagerTest, StopMatchBackfill_CallButErrorOutcome_GetExpectedError) + { + m_serverManager->InitializeGameLiftServerSDK(); + m_serverManager->SetupTestMatchmakingData(TEST_SERVER_MATCHMAKING_DATA); + + EXPECT_CALL(*(m_serverManager->m_gameLiftServerSDKWrapperMockPtr), StopMatchBackfill(testing::_)) + .Times(1) + .WillOnce(Return(Aws::GameLift::GenericOutcome())); + + AZ_TEST_START_TRACE_SUPPRESSION; + auto actualResult = m_serverManager->StopMatchBackfill("testticket"); + AZ_TEST_STOP_TRACE_SUPPRESSION(1); + EXPECT_FALSE(actualResult); + } } // namespace UnitTest diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/Tests/AWSGameLiftServerMocks.h b/Gems/AWSGameLift/Code/AWSGameLiftServer/Tests/AWSGameLiftServerMocks.h index 24336680b0..7ab9c51cd1 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/Tests/AWSGameLiftServerMocks.h +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/Tests/AWSGameLiftServerMocks.h @@ -8,6 +8,7 @@ #pragma once +#include #include #include #include @@ -40,17 +41,25 @@ namespace UnitTest MOCK_METHOD1(AcceptPlayerSession, GenericOutcome(const std::string&)); MOCK_METHOD0(ActivateGameSession, GenericOutcome()); + MOCK_METHOD1(DescribePlayerSessions, DescribePlayerSessionsOutcome( + const Aws::GameLift::Server::Model::DescribePlayerSessionsRequest&)); MOCK_METHOD0(InitSDK, Server::InitSDKOutcome()); MOCK_METHOD1(ProcessReady, GenericOutcome(const Server::ProcessParameters& processParameters)); MOCK_METHOD0(ProcessEnding, GenericOutcome()); MOCK_METHOD1(RemovePlayerSession, GenericOutcome(const AZStd::string& playerSessionId)); MOCK_METHOD0(GetTerminationTime, AZStd::string()); + MOCK_METHOD1(StartMatchBackfill, StartMatchBackfillOutcome( + const Aws::GameLift::Server::Model::StartMatchBackfillRequest&)); + MOCK_METHOD1(StopMatchBackfill, GenericOutcome( + const Aws::GameLift::Server::Model::StopMatchBackfillRequest&)); + GenericOutcome ProcessReadyMock(const Server::ProcessParameters& processParameters) { m_healthCheckFunc = processParameters.getOnHealthCheck(); m_onStartGameSessionFunc = processParameters.getOnStartGameSession(); m_onProcessTerminateFunc = processParameters.getOnProcessTerminate(); + m_onUpdateGameSessionFunc = processParameters.getOnUpdateGameSession(); GenericOutcome successOutcome(nullptr); return successOutcome; @@ -59,6 +68,7 @@ namespace UnitTest AZStd::function m_healthCheckFunc; AZStd::function m_onProcessTerminateFunc; AZStd::function m_onStartGameSessionFunc; + AZStd::function m_onUpdateGameSessionFunc; }; class AWSGameLiftServerManagerMock @@ -78,12 +88,25 @@ namespace UnitTest m_gameLiftServerSDKWrapperMockPtr = nullptr; } + void SetupTestMatchmakingData(const AZStd::string& matchmakingData, int maxPlayer = 10) + { + m_testGameSession.SetMatchmakerData(matchmakingData.c_str()); + m_testGameSession.SetMaximumPlayerSessionCount(maxPlayer); + UpdateGameSessionData(m_testGameSession); + } + bool AddConnectedTestPlayer(const AzFramework::PlayerConnectionConfig& playerConnectionConfig) { return AddConnectedPlayer(playerConnectionConfig); } + AZStd::vector GetTestServerMatchBackfillPlayers() + { + return GetActiveServerMatchBackfillPlayers(); + } + NiceMock* m_gameLiftServerSDKWrapperMockPtr; + Aws::GameLift::Server::Model::GameSession m_testGameSession; }; class AWSGameLiftServerSystemComponentMock diff --git a/Gems/AWSGameLift/Code/AWSGameLiftServer/awsgamelift_server_files.cmake b/Gems/AWSGameLift/Code/AWSGameLiftServer/awsgamelift_server_files.cmake index 95b5e1d2d2..9039c9943e 100644 --- a/Gems/AWSGameLift/Code/AWSGameLiftServer/awsgamelift_server_files.cmake +++ b/Gems/AWSGameLift/Code/AWSGameLiftServer/awsgamelift_server_files.cmake @@ -7,6 +7,8 @@ # set(FILES + ../AWSGameLiftCommon/Include/AWSGameLiftPlayer.h + ../AWSGameLiftCommon/Source/AWSGameLiftPlayer.cpp ../AWSGameLiftCommon/Source/AWSGameLiftSessionConstants.h Include/Request/IAWSGameLiftServerRequests.h Source/AWSGameLiftServerManager.cpp diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp index 35174e31fb..4fad5697c7 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.cpp @@ -308,6 +308,12 @@ namespace Multiplayer return true; } + void MultiplayerSystemComponent::OnUpdateSessionBegin(const AzFramework::SessionConfig& sessionConfig, const AZStd::string& updateReason) + { + AZ_UNUSED(sessionConfig); + AZ_UNUSED(updateReason); + } + void MultiplayerSystemComponent::OnTick(float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time) { const AZ::TimeMs deltaTimeMs = aznumeric_cast(static_cast(deltaTime * 1000.0f)); diff --git a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h index e46bbb59bc..ef1fb0da5b 100644 --- a/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h +++ b/Gems/Multiplayer/Code/Source/MultiplayerSystemComponent.h @@ -70,6 +70,7 @@ namespace Multiplayer bool OnSessionHealthCheck() override; bool OnCreateSessionBegin(const AzFramework::SessionConfig& sessionConfig) override; bool OnDestroySessionBegin() override; + void OnUpdateSessionBegin(const AzFramework::SessionConfig& sessionConfig, const AZStd::string& updateReason) override; //! @} //! AZ::TickBus::Handler overrides. From 922a9914438b55464984c330c6ac8a8496a5febf Mon Sep 17 00:00:00 2001 From: jromnoa <80134229+jromnoa@users.noreply.github.com> Date: Wed, 13 Oct 2021 21:15:29 -0700 Subject: [PATCH 164/169] change expected_lines to something that appears in both AR + locally (#4680) Signed-off-by: jromnoa --- AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py index 74b064a555..381f266fab 100644 --- a/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py +++ b/AutomatedTesting/Gem/PythonTests/Atom/TestSuite_Main_GPU.py @@ -148,7 +148,7 @@ class TestAllComponentsIndepthTests(object): golden_image_path = os.path.join(golden_images_directory(), golden_image) golden_images.append(golden_image_path) - expected_lines = ["Light component tests completed."] + expected_lines = ["spot_light Controller|Configuration|Shadows|Shadowmap size: SUCCESS"] unexpected_lines = [ "Trace::Assert", "Trace::Error", From 5a204dc80b65c322be7fb038cd9c5783cadf4533 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Wed, 13 Oct 2021 21:26:03 -0700 Subject: [PATCH 165/169] chore: remove equality from boolean expression Signed-off-by: Michael Pollind --- .../AzToolsFramework/Picking/Manipulators/ManipulatorBounds.cpp | 2 +- Gems/LmbrCentral/Code/Source/Shape/BoxShape.cpp | 2 +- Gems/LmbrCentral/Code/Source/Shape/DiskShape.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Picking/Manipulators/ManipulatorBounds.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/Picking/Manipulators/ManipulatorBounds.cpp index 3a7fffb3be..4c7afa2275 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Picking/Manipulators/ManipulatorBounds.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Picking/Manipulators/ManipulatorBounds.cpp @@ -116,7 +116,7 @@ namespace AzToolsFramework { return AZ::Intersect::IntersectRayBox( rayOrigin, rayDirection, m_center, m_axis1, m_axis2, m_axis3, m_halfExtents.GetX(), m_halfExtents.GetY(), - m_halfExtents.GetZ(), rayIntersectionDistance) > 0; + m_halfExtents.GetZ(), rayIntersectionDistance); } void ManipulatorBoundBox::SetShapeData(const BoundRequestShapeBase& shapeData) diff --git a/Gems/LmbrCentral/Code/Source/Shape/BoxShape.cpp b/Gems/LmbrCentral/Code/Source/Shape/BoxShape.cpp index a776a01ccc..4f6089ba16 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/BoxShape.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/BoxShape.cpp @@ -166,7 +166,7 @@ namespace LmbrCentral return intersection; } - const bool intersection = AZ::Intersect::IntersectRayObb(src, dir, m_intersectionDataCache.m_obb, distance) > 0; + const bool intersection = AZ::Intersect::IntersectRayObb(src, dir, m_intersectionDataCache.m_obb, distance); return intersection; } diff --git a/Gems/LmbrCentral/Code/Source/Shape/DiskShape.cpp b/Gems/LmbrCentral/Code/Source/Shape/DiskShape.cpp index 8eaf03457f..1c4a94ced3 100644 --- a/Gems/LmbrCentral/Code/Source/Shape/DiskShape.cpp +++ b/Gems/LmbrCentral/Code/Source/Shape/DiskShape.cpp @@ -153,7 +153,7 @@ namespace LmbrCentral m_intersectionDataCache.UpdateIntersectionParams(m_currentTransform, m_diskShapeConfig); return AZ::Intersect::IntersectRayDisk( - src, dir, m_intersectionDataCache.m_position, m_intersectionDataCache.m_radius, m_intersectionDataCache.m_normal, distance) > 0; + src, dir, m_intersectionDataCache.m_position, m_intersectionDataCache.m_radius, m_intersectionDataCache.m_normal, distance); } void DiskShape::DiskIntersectionDataCache::UpdateIntersectionParamsImpl( From 5967b419a29805c1db276eb33704fff9ca4a3a67 Mon Sep 17 00:00:00 2001 From: Chris Burel Date: Thu, 14 Oct 2021 07:45:44 -0700 Subject: [PATCH 166/169] Only enable the Keyboard device in the XcbKeyboard unit tests (#4682) This prevents other input devices from interfering with the expected calls that the Keyboard tests should make. Signed-off-by: Chris Burel --- .../Input/System/InputSystemComponent.cpp | 20 +++++++++ .../Xcb/AzFramework/XcbNativeWindow.cpp | 1 + .../Xcb/XcbInputDeviceKeyboardTests.cpp | 42 ++++++++++--------- .../Platform/Common/Xcb/XcbTestApplication.h | 38 +++++++++++++++++ .../Xcb/azframework_xcb_tests_files.cmake | 1 + 5 files changed, 82 insertions(+), 20 deletions(-) create mode 100644 Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbTestApplication.h diff --git a/Code/Framework/AzFramework/AzFramework/Input/System/InputSystemComponent.cpp b/Code/Framework/AzFramework/AzFramework/Input/System/InputSystemComponent.cpp index 33690f2246..14fb7ea5eb 100644 --- a/Code/Framework/AzFramework/AzFramework/Input/System/InputSystemComponent.cpp +++ b/Code/Framework/AzFramework/AzFramework/Input/System/InputSystemComponent.cpp @@ -20,6 +20,7 @@ #include #include #include +#include //////////////////////////////////////////////////////////////////////////////////////////////////// namespace AzFramework @@ -190,6 +191,25 @@ namespace AzFramework //////////////////////////////////////////////////////////////////////////////////////////////// void InputSystemComponent::Activate() { + const auto* settingsRegistry = AZ::SettingsRegistry::Get(); + if (settingsRegistry) + { + AZ::u64 value = 0; + if (settingsRegistry->Get(value, "/O3DE/InputSystem/MouseMovementSampleRateHertz")) + { + m_mouseMovementSampleRateHertz = aznumeric_caster(value); + } + if (settingsRegistry->Get(value, "/O3DE/InputSystem/GamepadsEnabled")) + { + m_gamepadsEnabled = aznumeric_caster(value); + } + settingsRegistry->Get(m_keyboardEnabled, "/O3DE/InputSystem/KeyboardEnabled"); + settingsRegistry->Get(m_motionEnabled, "/O3DE/InputSystem/MotionEnabled"); + settingsRegistry->Get(m_mouseEnabled, "/O3DE/InputSystem/MouseEnabled"); + settingsRegistry->Get(m_touchEnabled, "/O3DE/InputSystem/TouchEnabled"); + settingsRegistry->Get(m_virtualKeyboardEnabled, "/O3DE/InputSystem/VirtualKeyboardEnabled"); + } + // Create all enabled input devices CreateEnabledInputDevices(); diff --git a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbNativeWindow.cpp b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbNativeWindow.cpp index 6ab97fd616..43f7e7140f 100644 --- a/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbNativeWindow.cpp +++ b/Code/Framework/AzFramework/Platform/Common/Xcb/AzFramework/XcbNativeWindow.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include diff --git a/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbInputDeviceKeyboardTests.cpp b/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbInputDeviceKeyboardTests.cpp index 2b1f21ede7..76d00eda50 100644 --- a/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbInputDeviceKeyboardTests.cpp +++ b/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbInputDeviceKeyboardTests.cpp @@ -12,7 +12,6 @@ #include -#include #include #include #include @@ -20,6 +19,7 @@ #include "Matchers.h" #include "Actions.h" #include "XcbBaseTestFixture.h" +#include "XcbTestApplication.h" template xcb_generic_event_t MakeEvent(T event) @@ -33,6 +33,7 @@ namespace AzFramework class XcbInputDeviceKeyboardTests : public XcbBaseTestFixture { + public: void SetUp() override { using testing::Return; @@ -123,6 +124,15 @@ namespace AzFramework static constexpr xcb_keycode_t s_keycodeForAKey{38}; static constexpr xcb_keycode_t s_keycodeForShiftLKey{50}; + + XcbTestApplication m_application{ + /*enabledGamepadsCount=*/0, + /*keyboardEnabled=*/true, + /*motionEnabled=*/false, + /*mouseEnabled=*/false, + /*touchEnabled=*/false, + /*virtualKeyboardEnabled=*/false + }; }; class InputTextNotificationListener @@ -195,27 +205,23 @@ namespace AzFramework EXPECT_CALL(m_interface, xkb_state_key_get_one_sym(&m_xkbState, s_keycodeForAKey)) .Times(2); - Application application; - application.Start({}, {}); - AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); + m_application.Start(); const InputChannel* inputChannel = InputChannelRequests::FindInputChannel(InputDeviceKeyboard::Key::AlphanumericA); ASSERT_TRUE(inputChannel); EXPECT_THAT(inputChannel->GetState(), Eq(InputChannel::State::Idle)); - application.PumpSystemEventLoopUntilEmpty(); - application.TickSystem(); - application.Tick(); + m_application.PumpSystemEventLoopUntilEmpty(); + m_application.TickSystem(); + m_application.Tick(); EXPECT_THAT(inputChannel->GetState(), Eq(InputChannel::State::Began)); - application.PumpSystemEventLoopUntilEmpty(); - application.TickSystem(); - application.Tick(); + m_application.PumpSystemEventLoopUntilEmpty(); + m_application.TickSystem(); + m_application.Tick(); EXPECT_THAT(inputChannel->GetState(), Eq(InputChannel::State::Ended)); - - application.Stop(); } TEST_F(XcbInputDeviceKeyboardTests, TextEnteredFromXcbKeyPressEvents) @@ -420,17 +426,13 @@ namespace AzFramework EXPECT_CALL(textListener, OnInputTextEvent(StrEq("a"), _)).Times(1); EXPECT_CALL(textListener, OnInputTextEvent(StrEq("A"), _)).Times(1); - Application application; - application.Start({}, {}); - AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); + m_application.Start(); for (int i = 0; i < 4; ++i) { - application.PumpSystemEventLoopUntilEmpty(); - application.TickSystem(); - application.Tick(); + m_application.PumpSystemEventLoopUntilEmpty(); + m_application.TickSystem(); + m_application.Tick(); } - - application.Stop(); } } // namespace AzFramework diff --git a/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbTestApplication.h b/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbTestApplication.h new file mode 100644 index 0000000000..3035a9de74 --- /dev/null +++ b/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/XcbTestApplication.h @@ -0,0 +1,38 @@ +/* + * 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 AzFramework +{ + class XcbTestApplication + : public Application + { + public: + XcbTestApplication(AZ::u64 enabledGamepadsCount, bool keyboardEnabled, bool motionEnabled, bool mouseEnabled, bool touchEnabled, bool virtualKeyboardEnabled) + { + auto* settingsRegistry = AZ::SettingsRegistry::Get(); + settingsRegistry->Set("/O3DE/InputSystem/GamepadsEnabled", enabledGamepadsCount); + settingsRegistry->Set("/O3DE/InputSystem/KeyboardEnabled", keyboardEnabled); + settingsRegistry->Set("/O3DE/InputSystem/MotionEnabled", motionEnabled); + settingsRegistry->Set("/O3DE/InputSystem/MouseEnabled", mouseEnabled); + settingsRegistry->Set("/O3DE/InputSystem/TouchEnabled", touchEnabled); + settingsRegistry->Set("/O3DE/InputSystem/VirtualKeyboardEnabled", virtualKeyboardEnabled); + } + + void Start(const Descriptor& descriptor = {}, const StartupParameters& startupParameters = {}) override + { + Application::Start(descriptor, startupParameters); + AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); + } + }; +} // namespace AzFramework diff --git a/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/azframework_xcb_tests_files.cmake b/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/azframework_xcb_tests_files.cmake index 762d5d74fe..147fd2bfe1 100644 --- a/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/azframework_xcb_tests_files.cmake +++ b/Code/Framework/AzFramework/Tests/Platform/Common/Xcb/azframework_xcb_tests_files.cmake @@ -17,4 +17,5 @@ set(FILES XcbBaseTestFixture.cpp XcbBaseTestFixture.h XcbInputDeviceKeyboardTests.cpp + XcbTestApplication.h ) From 8d7b03c8592ccc219f4de0629f8bed2386ba4774 Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Thu, 14 Oct 2021 08:27:43 -0700 Subject: [PATCH 167/169] Implement open in file browser for Linux (#4677) * Add support to open folder browser for Linux * PAL'ified DesktopUtilities.cpp Signed-off-by: Steve Pham --- .../Platform/Linux/platform_linux_files.cmake | 1 + .../Platform/Mac/platform_mac_files.cmake | 1 + .../Windows/platform_windows_files.cmake | 1 + .../AzQtComponents/azqtcomponents_files.cmake | 1 - .../Utilities/DesktopUtilities_Linux.cpp | 49 +++++++++++++++++++ .../Utilities/DesktopUtilities_Mac.cpp} | 23 --------- .../Utilities/DesktopUtilities_Windows.cpp | 35 +++++++++++++ 7 files changed, 87 insertions(+), 24 deletions(-) create mode 100644 Code/Framework/AzQtComponents/Platform/Linux/AzQtComponents/Utilities/DesktopUtilities_Linux.cpp rename Code/Framework/AzQtComponents/{AzQtComponents/Utilities/DesktopUtilities.cpp => Platform/Mac/AzQtComponents/Utilities/DesktopUtilities_Mac.cpp} (67%) create mode 100644 Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/Utilities/DesktopUtilities_Windows.cpp diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Linux/platform_linux_files.cmake b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Linux/platform_linux_files.cmake index ec71d7b508..f292c29c3c 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Linux/platform_linux_files.cmake +++ b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Linux/platform_linux_files.cmake @@ -12,6 +12,7 @@ set(FILES ../../Utilities/QtWindowUtilities_linux.cpp ../../Utilities/ScreenGrabber_linux.cpp ../../../Platform/Linux/AzQtComponents/Components/StyledDockWidget_Linux.cpp + ../../../Platform/Linux/AzQtComponents/Utilities/DesktopUtilities_Linux.cpp ../../../Platform/Linux/AzQtComponents/AzQtComponents_Traits_Linux.h ../../../Platform/Linux/AzQtComponents/AzQtComponents_Traits_Platform.h ) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Mac/platform_mac_files.cmake b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Mac/platform_mac_files.cmake index 18f9479289..4addf53599 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Mac/platform_mac_files.cmake +++ b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Mac/platform_mac_files.cmake @@ -12,6 +12,7 @@ set(FILES ../../Utilities/QtWindowUtilities_mac.mm ../../Utilities/ScreenGrabber_mac.mm ../../../Platform/Mac/AzQtComponents/Components/StyledDockWidget_Mac.cpp + ../../../Platform/Mac/AzQtComponents/Utilities/DesktopUtilities_Mac.cpp ../../../Platform/Mac/AzQtComponents/AzQtComponents_Traits_Mac.h ../../../Platform/Mac/AzQtComponents/AzQtComponents_Traits_Platform.h ) diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Windows/platform_windows_files.cmake b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Windows/platform_windows_files.cmake index ca4145ef35..bf0d0bb785 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Platform/Windows/platform_windows_files.cmake +++ b/Code/Framework/AzQtComponents/AzQtComponents/Platform/Windows/platform_windows_files.cmake @@ -9,6 +9,7 @@ set(FILES ../../natvis/qt.natvis ../../../Platform/Windows/AzQtComponents/Utilities/HandleDpiAwareness_Windows.cpp + ../../../Platform/Windows/AzQtComponents/Utilities/DesktopUtilities_Windows.cpp ../../Utilities/MouseHider_win.cpp ../../Utilities/QtWindowUtilities_win.cpp ../../Utilities/ScreenGrabber_win.cpp diff --git a/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_files.cmake b/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_files.cmake index 8219ab04b2..4c343b852c 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_files.cmake +++ b/Code/Framework/AzQtComponents/AzQtComponents/azqtcomponents_files.cmake @@ -271,7 +271,6 @@ set(FILES Utilities/ColorUtilities.h Utilities/Conversions.h Utilities/Conversions.cpp - Utilities/DesktopUtilities.cpp Utilities/DesktopUtilities.h Utilities/HandleDpiAwareness.cpp Utilities/HandleDpiAwareness.h diff --git a/Code/Framework/AzQtComponents/Platform/Linux/AzQtComponents/Utilities/DesktopUtilities_Linux.cpp b/Code/Framework/AzQtComponents/Platform/Linux/AzQtComponents/Utilities/DesktopUtilities_Linux.cpp new file mode 100644 index 0000000000..e4ddaceec7 --- /dev/null +++ b/Code/Framework/AzQtComponents/Platform/Linux/AzQtComponents/Utilities/DesktopUtilities_Linux.cpp @@ -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 + * + */ + +#include + +#include +#include + +namespace AzQtComponents +{ + void ShowFileOnDesktop(const QString& path) + { + const char* defaultNautilusPath = "/usr/bin/nautilus"; + const char* defaultXdgOpenPath = "/usr/bin/xdg-open"; + + // Determine if Nautilus (for Gnome Desktops) is available because it supports opening the file manager + // and selecting a specific file + bool nautilusAvailable = QFileInfo(defaultNautilusPath).exists(); + + QFileInfo pathInfo(path); + if (pathInfo.isDir()) + { + QProcess::startDetached(defaultXdgOpenPath, { path }); + } + else + { + if (nautilusAvailable) + { + QProcess::startDetached(defaultNautilusPath, { "--select", path }); + } + else + { + QDir parentDir { pathInfo.dir() }; + QProcess::startDetached(defaultXdgOpenPath, { parentDir.path() }); + } + } + } + + QString fileBrowserActionName() + { + const char* exploreActionName = "Open in file browser"; + return QObject::tr(exploreActionName); + } +} diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Utilities/DesktopUtilities.cpp b/Code/Framework/AzQtComponents/Platform/Mac/AzQtComponents/Utilities/DesktopUtilities_Mac.cpp similarity index 67% rename from Code/Framework/AzQtComponents/AzQtComponents/Utilities/DesktopUtilities.cpp rename to Code/Framework/AzQtComponents/Platform/Mac/AzQtComponents/Utilities/DesktopUtilities_Mac.cpp index c210f17136..5920dc76c6 100644 --- a/Code/Framework/AzQtComponents/AzQtComponents/Utilities/DesktopUtilities.cpp +++ b/Code/Framework/AzQtComponents/Platform/Mac/AzQtComponents/Utilities/DesktopUtilities_Mac.cpp @@ -15,21 +15,6 @@ namespace AzQtComponents { void ShowFileOnDesktop(const QString& path) { -#if defined(AZ_PLATFORM_WINDOWS) - - // Launch explorer at the path provided - QStringList args; - if (!QFileInfo(path).isDir()) - { - // Folders are just opened, files are selected - args << "/select,"; - } - args << QDir::toNativeSeparators(path); - - QProcess::startDetached("explorer", args); - -#else - if (QFileInfo(path).isDir()) { QProcess::startDetached("/usr/bin/osascript", { "-e", @@ -43,19 +28,11 @@ namespace AzQtComponents QProcess::startDetached("/usr/bin/osascript", { "-e", QStringLiteral("tell application \"Finder\" to activate") }); - -#endif } QString fileBrowserActionName() { -#ifdef AZ_PLATFORM_WINDOWS - const char* exploreActionName = "Open in Explorer"; -#elif defined(AZ_PLATFORM_MAC) const char* exploreActionName = "Open in Finder"; -#else - const char* exploreActionName = "Open in file browser"; -#endif return QObject::tr(exploreActionName); } } diff --git a/Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/Utilities/DesktopUtilities_Windows.cpp b/Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/Utilities/DesktopUtilities_Windows.cpp new file mode 100644 index 0000000000..796e2c0ccf --- /dev/null +++ b/Code/Framework/AzQtComponents/Platform/Windows/AzQtComponents/Utilities/DesktopUtilities_Windows.cpp @@ -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 + * + */ + +#include + +#include +#include + +namespace AzQtComponents +{ + void ShowFileOnDesktop(const QString& path) + { + // Launch explorer at the path provided + QStringList args; + if (!QFileInfo(path).isDir()) + { + // Folders are just opened, files are selected + args << "/select,"; + } + args << QDir::toNativeSeparators(path); + + QProcess::startDetached("explorer", args); + } + + QString fileBrowserActionName() + { + const char* exploreActionName = "Open in Explorer"; + return QObject::tr(exploreActionName); + } +} From 999ec261c9dcf060ed99555a740e7566f4701df6 Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Thu, 14 Oct 2021 08:28:36 -0700 Subject: [PATCH 168/169] Update linux AP connection settings to connect to remote AP and wait for the connection (#4685) Signed-off-by: Steve Pham --- Registry/bootstrap.setreg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Registry/bootstrap.setreg b/Registry/bootstrap.setreg index 3a15d59450..b2bcdd7f3f 100644 --- a/Registry/bootstrap.setreg +++ b/Registry/bootstrap.setreg @@ -17,7 +17,7 @@ "remote_port": 45643, "connect_to_remote": 0, "windows_connect_to_remote": 1, - "linux_connect_to_remote": 0, + "linux_connect_to_remote": 1, "provo_connect_to_remote": 1, "salem_connect_to_remote": 0, "jasper_connect_to_remote": 0, @@ -29,7 +29,7 @@ "salem_wait_for_connect": 0, "jasper_wait_for_connect": 0, "windows_wait_for_connect": 1, - "linux_wait_for_connect": 0, + "linux_wait_for_connect": 1, "android_wait_for_connect": 0, "ios_wait_for_connect": 0, "mac_wait_for_connect": 0, From 2dd00e298313b58c4ec9d4e3c023e4aa44ed5152 Mon Sep 17 00:00:00 2001 From: Tommy Walton <82672795+amzn-tommy@users.noreply.github.com> Date: Thu, 14 Oct 2021 08:58:50 -0700 Subject: [PATCH 169/169] Move wrinkle mask data out of default object srg (#4578) * Refactored depth, shadow, and motion vector shaders to support custom object srgs. Added a new skin object srg and moved wrinklemask data out of the default object srg. Added a new minimal morph target asset for testing wrinkle masks to AutomatedTesting. Signed-off-by: Tommy Walton * Fix copyright header Signed-off-by: Tommy Walton --- .../DisplayWrinkleMaskBlendValues.material | 13 +++ .../Objects/MorphTargets/morphActor.fbx | 3 + .../Morph1_wrinklemask.tif | 3 + .../Morph2_wriklemask.tif | 3 + .../Morph3_wrinklemask.tif | 3 + .../Objects/MorphTargets/morphAnimation.fbx | 3 + .../Common/Assets/Materials/Types/Skin.azsl | 2 +- .../Assets/Materials/Types/Skin.materialtype | 6 +- .../Atom/Features/PBR/DefaultObjectSrg.azsli | 10 --- .../Atom/Features/Skin/SkinObjectSrg.azsli | 81 ++++++++++++++++++ .../Assets/Shaders/Depth/DepthPass.azsl | 27 +----- .../Shaders/Depth/DepthPassCommon.azsli | 36 ++++++++ .../Assets/Shaders/Depth/DepthPassSkin.azsl | 12 +++ .../Assets/Shaders/Depth/DepthPassSkin.shader | 24 ++++++ .../MotionVector/MeshMotionVector.azsl | 74 +---------------- .../MotionVector/MeshMotionVectorCommon.azsli | 83 +++++++++++++++++++ .../MotionVector/MeshMotionVectorSkin.azsl | 12 +++ .../MotionVector/MeshMotionVectorSkin.shader | 24 ++++++ .../Assets/Shaders/Shadow/Shadowmap.azsl | 24 +----- .../Shaders/Shadow/ShadowmapCommon.azsli | 33 ++++++++ .../Assets/Shaders/Shadow/ShadowmapSkin.azsl | 12 +++ .../Shaders/Shadow/ShadowmapSkin.shader | 26 ++++++ 22 files changed, 381 insertions(+), 133 deletions(-) create mode 100644 AutomatedTesting/Objects/MorphTargets/DisplayWrinkleMaskBlendValues.material create mode 100644 AutomatedTesting/Objects/MorphTargets/morphActor.fbx create mode 100644 AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph1_wrinklemask.tif create mode 100644 AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph2_wriklemask.tif create mode 100644 AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph3_wrinklemask.tif create mode 100644 AutomatedTesting/Objects/MorphTargets/morphAnimation.fbx create mode 100644 Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Skin/SkinObjectSrg.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassCommon.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassSkin.azsl create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassSkin.shader create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVectorCommon.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVectorSkin.azsl create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVectorSkin.shader create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/Shadow/ShadowmapCommon.azsli create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/Shadow/ShadowmapSkin.azsl create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/Shadow/ShadowmapSkin.shader diff --git a/AutomatedTesting/Objects/MorphTargets/DisplayWrinkleMaskBlendValues.material b/AutomatedTesting/Objects/MorphTargets/DisplayWrinkleMaskBlendValues.material new file mode 100644 index 0000000000..878b3ac39f --- /dev/null +++ b/AutomatedTesting/Objects/MorphTargets/DisplayWrinkleMaskBlendValues.material @@ -0,0 +1,13 @@ +{ + "description": "", + "materialType": "Materials/Types/Skin.materialtype", + "parentMaterial": "", + "propertyLayoutVersion": 3, + "properties": { + "wrinkleLayers": { + "count": 3, + "enable": true, + "showBlendValues": true + } + } +} diff --git a/AutomatedTesting/Objects/MorphTargets/morphActor.fbx b/AutomatedTesting/Objects/MorphTargets/morphActor.fbx new file mode 100644 index 0000000000..ffb75e680e --- /dev/null +++ b/AutomatedTesting/Objects/MorphTargets/morphActor.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:53e17ec8155911c8b42e85436130f600bd6dddd8931a8ccb1b2f8a9f8674cc85 +size 45104 diff --git a/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph1_wrinklemask.tif b/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph1_wrinklemask.tif new file mode 100644 index 0000000000..3bc18cf450 --- /dev/null +++ b/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph1_wrinklemask.tif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0da56a05daa0ec1c476cfe25ca6d3b65267c98886cf33408f6e852fb325a8e2c +size 198084 diff --git a/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph2_wriklemask.tif b/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph2_wriklemask.tif new file mode 100644 index 0000000000..39e70f5acf --- /dev/null +++ b/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph2_wriklemask.tif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3537fbe9205731a242251c525a67bbb5f3b8f5307537f1dc0c318b5b885ce52 +size 198112 diff --git a/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph3_wrinklemask.tif b/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph3_wrinklemask.tif new file mode 100644 index 0000000000..43e19f0d5f --- /dev/null +++ b/AutomatedTesting/Objects/MorphTargets/morphActor_wrinklemasks/Morph3_wrinklemask.tif @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bd794d5dd4b749c3275bfab79b9b5ae3f8e007d3e6741c0566c9c2d3931123bf +size 198112 diff --git a/AutomatedTesting/Objects/MorphTargets/morphAnimation.fbx b/AutomatedTesting/Objects/MorphTargets/morphAnimation.fbx new file mode 100644 index 0000000000..c0dcc007dc --- /dev/null +++ b/AutomatedTesting/Objects/MorphTargets/morphAnimation.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:45ded862987a64061deffd8e4c9aa1dff4eec3bcff5f7b505679f1959e8ae137 +size 51440 diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl index 05059aba6f..523353f8fa 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.azsl @@ -9,7 +9,7 @@ #include "Skin_Common.azsli" // SRGs -#include +#include #include // Pass Output diff --git a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype index 0969cc36e8..e4da9c6022 100644 --- a/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype +++ b/Gems/Atom/Feature/Common/Assets/Materials/Types/Skin.materialtype @@ -973,15 +973,15 @@ "tag": "ForwardPass" }, { - "file": "Shaders/Shadow/Shadowmap.shader", + "file": "Shaders/Shadow/ShadowmapSkin.shader", "tag": "Shadowmap" }, { - "file": "Shaders/Depth/DepthPass.shader", + "file": "Shaders/Depth/DepthPassSkin.shader", "tag": "DepthPass" }, { - "file": "Shaders/MotionVector/MeshMotionVector.shader", + "file": "Shaders/MotionVector/MeshMotionVectorSkin.shader", "tag": "MeshMotionVector" } ], 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 7a2d2ee428..10526597cb 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 @@ -27,16 +27,6 @@ ShaderResourceGroup ObjectSrg : SRG_PerObject return SceneSrg::GetObjectToWorldInverseTransposeMatrix(m_objectId); } - //[GFX TODO][ATOM-15280] Move wrinkle mask data from the default object srg into something specific to the Skin shader - uint m_wrinkle_mask_count; - float4 m_wrinkle_mask_weights[4]; - Texture2D m_wrinkle_masks[16]; - - float GetWrinkleMaskWeight(uint index) - { - return m_wrinkle_mask_weights[index / 4][index % 4]; - } - //! Reflection Probe (smallest probe volume that overlaps the object position) struct ReflectionProbeData { diff --git a/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Skin/SkinObjectSrg.azsli b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Skin/SkinObjectSrg.azsli new file mode 100644 index 0000000000..d0766c295d --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/ShaderLib/Atom/Features/Skin/SkinObjectSrg.azsli @@ -0,0 +1,81 @@ +/* + * 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 + +ShaderResourceGroup ObjectSrg : SRG_PerObject +{ + uint m_objectId; + + //! Returns the matrix for transforming points from Object Space to World Space. + float4x4 GetWorldMatrix() + { + return SceneSrg::GetObjectToWorldMatrix(m_objectId); + } + + //! Returns the inverse-transpose of the world matrix. + //! Commonly used to transform normals while supporting non-uniform scale. + float3x3 GetWorldMatrixInverseTranspose() + { + return SceneSrg::GetObjectToWorldInverseTransposeMatrix(m_objectId); + } + + uint m_wrinkle_mask_count; + float4 m_wrinkle_mask_weights[4]; + Texture2D m_wrinkle_masks[16]; + + float GetWrinkleMaskWeight(uint index) + { + return m_wrinkle_mask_weights[index / 4][index % 4]; + } + + //! Reflection Probe (smallest probe volume that overlaps the object position) + struct ReflectionProbeData + { + 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; + }; + + 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/Shaders/Depth/DepthPass.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPass.azsl index 8eb657f8f5..876f4b1a61 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPass.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPass.azsl @@ -6,30 +6,7 @@ * */ -#include #include +#include -struct VSInput -{ - float3 m_position : POSITION; -}; - -struct VSDepthOutput -{ - float4 m_position : SV_Position; -}; - -VSDepthOutput DepthPassVS(VSInput IN) -{ - VSDepthOutput OUT; - - float4x4 objectToWorld = ObjectSrg::GetWorldMatrix(); - float4 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)); - OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, worldPosition); - - return OUT; -} - - - - +// Use the depth pass shader with the default object srg diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassCommon.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassCommon.azsli new file mode 100644 index 0000000000..f658dd13da --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassCommon.azsli @@ -0,0 +1,36 @@ +/* + * 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 + +struct VSInput +{ + float3 m_position : POSITION; +}; + +struct VSDepthOutput +{ + float4 m_position : SV_Position; +}; + +VSDepthOutput DepthPassVS(VSInput IN) +{ + VSDepthOutput OUT; + + float4x4 objectToWorld = ObjectSrg::GetWorldMatrix(); + float4 worldPosition = mul(objectToWorld, float4(IN.m_position, 1.0)); + OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, worldPosition); + + return OUT; +} + + + + diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassSkin.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassSkin.azsl new file mode 100644 index 0000000000..0947be6cf8 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassSkin.azsl @@ -0,0 +1,12 @@ +/* + * 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 + +// Use the depth pass shader with the skin object srg diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassSkin.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassSkin.shader new file mode 100644 index 0000000000..de6c989223 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Depth/DepthPassSkin.shader @@ -0,0 +1,24 @@ +{ + "Source" : "DepthPassSkin", + + "DepthStencilState" : { + "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } + }, + + "CompilerHints" : { + "DisableOptimizations" : false + }, + + "ProgramSettings" : + { + "EntryPoints": + [ + { + "name": "DepthPassVS", + "type" : "Vertex" + } + ] + }, + + "DrawList" : "depth" +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVector.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVector.azsl index 11cf20dcaf..a14d07194f 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVector.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVector.azsl @@ -6,77 +6,7 @@ * */ -#include -#include - #include -#include +#include -struct VSInput -{ - float3 m_position : POSITION; - - // This gets set automatically by the system at runtime only if it's available. - // There is a soft naming convention that associates this with o_prevPosition_isBound, which will be set to true whenever m_optional_prevPosition is available. - // (search "m_optional_" in ShaderVariantAssetBuilder for details on the naming convention). - // [GFX TODO][ATOM-14475]: Come up with a more elegant way to associate the isBound flag with the input stream. - // Vertex position of last frame to capture small scale motion due to vertex animation - float3 m_optional_prevPosition : POSITIONT; -}; - -struct VSOutput -{ - float4 m_position : SV_Position; - float3 m_worldPos : TEXCOORD0; - float3 m_worldPosPrev: TEXCOORD1; -}; - -struct PSOutput -{ - float2 m_motion : SV_Target0; -}; - -// Indicates whether the vertex input struct's "m_optional_prevPosition" is bound. If false, it is not safe to read from m_optional_prevPosition. -// This option gets set automatically by the system at runtime; there is a soft naming convention that associates it with m_optional_prevPosition. -// (search "m_optional_" in ShaderVariantAssetBuilder for details on the naming convention). -// [GFX TODO][ATOM-14475]: Come up with a more elegant way to associate the isBound flag with the input stream. -option bool o_prevPosition_isBound; - -VSOutput MainVS(VSInput IN) -{ - VSOutput OUT; - - OUT.m_worldPos = mul(SceneSrg::GetObjectToWorldMatrix(ObjectSrg::m_objectId), float4(IN.m_position, 1.0)).xyz; - OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(OUT.m_worldPos, 1.0)); - - if (o_prevPosition_isBound) - { - OUT.m_worldPosPrev = mul(SceneSrg::GetObjectToWorldMatrixPrev(ObjectSrg::m_objectId), float4(IN.m_optional_prevPosition, 1.0)).xyz; - } - else - { - OUT.m_worldPosPrev = mul(SceneSrg::GetObjectToWorldMatrixPrev(ObjectSrg::m_objectId), float4(IN.m_position, 1.0)).xyz; - } - - return OUT; -} - -PSOutput MainPS(VSOutput IN) -{ - PSOutput OUT; - - // Current clip position - float4 clipPos = mul(ViewSrg::m_viewProjectionMatrix, float4(IN.m_worldPos, 1.0)); - - // Reprojected last frame's clip position, for skinned mesh it also implies last key frame - float4 clipPosPrev = mul(ViewSrg::m_viewProjectionPrevMatrix, float4(IN.m_worldPosPrev, 1.0)); - - float2 motion = (clipPos.xy / clipPos.w - clipPosPrev.xy / clipPosPrev.w) * 0.5; - - OUT.m_motion = motion; - - // Flip y to line up with uv coordinates - OUT.m_motion.y = -OUT.m_motion.y; - - return OUT; -} +// Use the mesh motion vector with the default object srg diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVectorCommon.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVectorCommon.azsli new file mode 100644 index 0000000000..c934b056db --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVectorCommon.azsli @@ -0,0 +1,83 @@ +/* + * 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 + +struct VSInput +{ + float3 m_position : POSITION; + + // This gets set automatically by the system at runtime only if it's available. + // There is a soft naming convention that associates this with o_prevPosition_isBound, which will be set to true whenever m_optional_prevPosition is available. + // (search "m_optional_" in ShaderVariantAssetBuilder for details on the naming convention). + // [GFX TODO][ATOM-14475]: Come up with a more elegant way to associate the isBound flag with the input stream. + // Vertex position of last frame to capture small scale motion due to vertex animation + float3 m_optional_prevPosition : POSITIONT; +}; + +struct VSOutput +{ + float4 m_position : SV_Position; + float3 m_worldPos : TEXCOORD0; + float3 m_worldPosPrev: TEXCOORD1; +}; + +struct PSOutput +{ + float2 m_motion : SV_Target0; +}; + +// Indicates whether the vertex input struct's "m_optional_prevPosition" is bound. If false, it is not safe to read from m_optional_prevPosition. +// This option gets set automatically by the system at runtime; there is a soft naming convention that associates it with m_optional_prevPosition. +// (search "m_optional_" in ShaderVariantAssetBuilder for details on the naming convention). +// [GFX TODO][ATOM-14475]: Come up with a more elegant way to associate the isBound flag with the input stream. +option bool o_prevPosition_isBound; + +VSOutput MainVS(VSInput IN) +{ + VSOutput OUT; + + OUT.m_worldPos = mul(SceneSrg::GetObjectToWorldMatrix(ObjectSrg::m_objectId), float4(IN.m_position, 1.0)).xyz; + OUT.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(OUT.m_worldPos, 1.0)); + + if (o_prevPosition_isBound) + { + OUT.m_worldPosPrev = mul(SceneSrg::GetObjectToWorldMatrixPrev(ObjectSrg::m_objectId), float4(IN.m_optional_prevPosition, 1.0)).xyz; + } + else + { + OUT.m_worldPosPrev = mul(SceneSrg::GetObjectToWorldMatrixPrev(ObjectSrg::m_objectId), float4(IN.m_position, 1.0)).xyz; + } + + return OUT; +} + +PSOutput MainPS(VSOutput IN) +{ + PSOutput OUT; + + // Current clip position + float4 clipPos = mul(ViewSrg::m_viewProjectionMatrix, float4(IN.m_worldPos, 1.0)); + + // Reprojected last frame's clip position, for skinned mesh it also implies last key frame + float4 clipPosPrev = mul(ViewSrg::m_viewProjectionPrevMatrix, float4(IN.m_worldPosPrev, 1.0)); + + float2 motion = (clipPos.xy / clipPos.w - clipPosPrev.xy / clipPosPrev.w) * 0.5; + + OUT.m_motion = motion; + + // Flip y to line up with uv coordinates + OUT.m_motion.y = -OUT.m_motion.y; + + return OUT; +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVectorSkin.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVectorSkin.azsl new file mode 100644 index 0000000000..fc089ac7a3 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVectorSkin.azsl @@ -0,0 +1,12 @@ +/* + * 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 + +// Use the mesh motion vector with the skin object srg diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVectorSkin.shader b/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVectorSkin.shader new file mode 100644 index 0000000000..9a50e4e2cf --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/MotionVector/MeshMotionVectorSkin.shader @@ -0,0 +1,24 @@ +{ + "Source" : "MeshMotionVectorSkin", + + "DepthStencilState" : { + "Depth" : { "Enable" : true, "CompareFunc" : "GreaterEqual" } + }, + + "DrawList" : "motion", + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MainVS", + "type": "Vertex" + }, + { + "name": "MainPS", + "type": "Fragment" + } + ] + } +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/Shadowmap.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/Shadowmap.azsl index 713ff7c393..7a958a73ca 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/Shadowmap.azsl +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/Shadowmap.azsl @@ -6,27 +6,7 @@ * */ -#include -#include #include +#include -struct VertexInput -{ - float3 m_position : POSITION; -}; - -struct VertexOutput -{ - float4 m_position : SV_Position; -}; - -VertexOutput MainVS(VertexInput input) -{ - const float4x4 worldMatrix = ObjectSrg::GetWorldMatrix(); - VertexOutput output; - - const float3 worldPosition = mul(worldMatrix, float4(input.m_position, 1.0)).xyz; - output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0)); - - return output; -} +// Use the shadowmap shader with the default object srg diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/ShadowmapCommon.azsli b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/ShadowmapCommon.azsli new file mode 100644 index 0000000000..213fb18dc4 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/ShadowmapCommon.azsli @@ -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 + +struct VertexInput +{ + float3 m_position : POSITION; +}; + +struct VertexOutput +{ + float4 m_position : SV_Position; +}; + +VertexOutput MainVS(VertexInput input) +{ + const float4x4 worldMatrix = ObjectSrg::GetWorldMatrix(); + VertexOutput output; + + const float3 worldPosition = mul(worldMatrix, float4(input.m_position, 1.0)).xyz; + output.m_position = mul(ViewSrg::m_viewProjectionMatrix, float4(worldPosition, 1.0)); + + return output; +} diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/ShadowmapSkin.azsl b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/ShadowmapSkin.azsl new file mode 100644 index 0000000000..6f0d8e1a31 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/ShadowmapSkin.azsl @@ -0,0 +1,12 @@ +/* + * 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 + +// Use the shadowmap shader with the skin object srg diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/ShadowmapSkin.shader b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/ShadowmapSkin.shader new file mode 100644 index 0000000000..14c1352c08 --- /dev/null +++ b/Gems/Atom/Feature/Common/Assets/Shaders/Shadow/ShadowmapSkin.shader @@ -0,0 +1,26 @@ +{ + "Source" : "ShadowmapSkin", + + "DepthStencilState" : { + "Depth" : { "Enable" : true, "CompareFunc" : "LessEqual" } + }, + + "DrawList" : "shadow", + + "RasterState" : + { + "depthBias" : "10", + "depthBiasSlopeScale" : "4" + }, + + "ProgramSettings": + { + "EntryPoints": + [ + { + "name": "MainVS", + "type": "Vertex" + } + ] + } +}