From 9aece3e84bcc5cc48c5af5177942b4f274c5d558 Mon Sep 17 00:00:00 2001 From: Sergey Pereslavtsev Date: Fri, 4 Feb 2022 19:57:29 +0000 Subject: [PATCH 01/27] LYN-8403 Prevent the same Surface Tag from getting reused Signed-off-by: Sergey Pereslavtsev --- .../PropertyEditorAPI_Internals.h | 10 +++++ .../PropertyEditorAPI_Internals_Impl.h | 45 ++++++++++++++----- .../PropertyEnumComboBoxCtrl.hxx | 6 +++ .../Code/Include/SurfaceData/SurfaceTag.h | 7 +-- .../TerrainPhysicsColliderComponent.cpp | 29 ++++++++++++ .../TerrainPhysicsColliderComponent.h | 5 +++ .../TerrainSurfaceGradientListComponent.cpp | 27 +++++++++++ .../TerrainSurfaceGradientListComponent.h | 8 ++++ .../EditorTerrainPhysicsColliderComponent.cpp | 34 ++++++++++++++ .../EditorTerrainPhysicsColliderComponent.h | 12 +++++ ...torTerrainSurfaceGradientListComponent.cpp | 33 ++++++++++++++ ...ditorTerrainSurfaceGradientListComponent.h | 12 +++++ .../EditorSelectableTagListProvider.cpp | 31 +++++++++++++ .../Source/EditorSelectableTagListProvider.h | 26 +++++++++++ .../Code/terrain_editor_shared_files.cmake | 2 + 15 files changed, 274 insertions(+), 13 deletions(-) create mode 100644 Gems/Terrain/Code/Source/EditorSelectableTagListProvider.cpp create mode 100644 Gems/Terrain/Code/Source/EditorSelectableTagListProvider.h diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals.h index ecd27baed4..f1ddc2268d 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals.h @@ -154,6 +154,16 @@ namespace AzToolsFramework (void)debugName; } + // provides an option to specify reading parent element attributes. + // This allows parent elements to override attributes of their children if needed. + virtual void ConsumeParentAttribute(WidgetType* widget, AZ::u32 attrib, PropertyAttributeReader* attrValue, const char* debugName) + { + (void)widget; + (void)attrib; + (void)attrValue; + (void)debugName; + } + // override GetFirstInTabOrder, GetLastInTabOrder in your base class to define which widget gets focus first when pressing tab, // and also what widget is last. // for example, if your widget is a compound widget and contains, say, 5 buttons diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals_Impl.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals_Impl.h index 2ebacfa558..ec428de951 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals_Impl.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI_Internals_Impl.h @@ -40,7 +40,14 @@ namespace AzToolsFramework } void* classInstance = parent->FirstInstance(); // pointer to the owner class so we can read member variables and functions - auto consumeAttributes = [&](const auto& attributes, const char* name) + + void* parentClassInstance = nullptr; + if (InstanceDataNode* parentInstanceDataNode = parent->GetParent()) + { + parentClassInstance = parentInstanceDataNode->FirstInstance(); + } + + auto consumeAttributes = [this, classInstance, wid](const auto& attributes, const char* name) { for (size_t i = 0; i < attributes.size(); ++i) { @@ -50,25 +57,43 @@ namespace AzToolsFramework } }; + auto consumeParentAttributes = [this, parentClassInstance, wid](const auto& attributes, const char* name) + { + if (parentClassInstance) + { + for (size_t i = 0; i < attributes.size(); ++i) + { + const auto& attrPair = attributes[i]; + PropertyAttributeReader reader(parentClassInstance, &*attrPair.second); + ConsumeParentAttribute(wid, attrPair.first, &reader, name); + } + } + }; + const AZ::SerializeContext::ClassElement* element = dataNode->GetElementMetadata(); if (element) { consumeAttributes(element->m_attributes, element->m_name); - const AZ::Edit::ElementData* elementEdit = dataNode->GetElementEditMetadata(); - if (elementEdit) + + if (const AZ::Edit::ElementData* elementEdit = dataNode->GetElementEditMetadata(); + elementEdit != nullptr) { consumeAttributes(elementEdit->m_attributes, elementEdit->m_name); } - } - if (dataNode->GetClassMetadata()) - { - const AZ::Edit::ClassData* classEditData = dataNode->GetClassMetadata()->m_editData; - if (classEditData) + const AZ::SerializeContext::ClassElement* parentElement = parent != dataNode ? + dataNode->GetElementMetadata() : + nullptr; + + if (parentElement != nullptr) { - for (auto it = classEditData->m_elements.begin(); it != classEditData->m_elements.end(); ++it) + // Reuse the current instance element name for the debug name + consumeParentAttributes(parentElement->m_attributes, element->m_name); + + if (const AZ::Edit::ElementData* elementEdit = parent->GetElementEditMetadata(); + elementEdit != nullptr) { - consumeAttributes(it->m_attributes, it->m_name); + consumeParentAttributes(elementEdit->m_attributes, elementEdit->m_name); } } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEnumComboBoxCtrl.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEnumComboBoxCtrl.hxx index 206b972b37..fc1d24b7a5 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEnumComboBoxCtrl.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyEnumComboBoxCtrl.hxx @@ -66,6 +66,12 @@ namespace AzToolsFramework class GenericEnumPropertyComboBoxHandler : public GenericComboBoxHandler { + virtual void ConsumeParentAttribute(GenericComboBoxCtrlBase* GUI, AZ::u32 attrib, PropertyAttributeReader* attrValue, const char* debugName) override + { + // Simply re-route to ConsumeAttribute since no special logic is needed. + ConsumeAttribute(GUI, attrib, attrValue, debugName); + } + virtual void ConsumeAttribute(GenericComboBoxCtrlBase* GUI, AZ::u32 attrib, PropertyAttributeReader* attrValue, const char* debugName) override { (void)debugName; diff --git a/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceTag.h b/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceTag.h index d16856995d..ab24ba09f0 100644 --- a/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceTag.h +++ b/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceTag.h @@ -19,7 +19,8 @@ namespace SurfaceData { public: AZ_CLASS_ALLOCATOR(SurfaceTag, AZ::SystemAllocator, 0); - AZ_RTTI(SurfaceTag, "{67C8C6ED-F32A-443E-A777-1CAE48B22CD7}"); + AZ_TYPE_INFO(SurfaceTag, "{67C8C6ED-F32A-443E-A777-1CAE48B22CD7}"); + static void Reflect(AZ::ReflectContext* context); SurfaceTag() @@ -47,6 +48,8 @@ namespace SurfaceData m_surfaceTagCrc = AZ::Crc32(value.data()); } + AZStd::string GetDisplayName() const; + static AZStd::vector> GetRegisteredTags(); private: @@ -54,8 +57,6 @@ namespace SurfaceData AZStd::vector> BuildSelectableTagList() const; - AZStd::string GetDisplayName() const; - AZ::u32 m_surfaceTagCrc; }; diff --git a/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.cpp index d70915a861..23134e663d 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.cpp @@ -17,11 +17,14 @@ #include #include #include +#include #include #include #include +#include + namespace Terrain { void TerrainPhysicsSurfaceMaterialMapping::Reflect(AZ::ReflectContext* context) @@ -45,6 +48,8 @@ namespace Terrain ->DataElement( AZ::Edit::UIHandlers::ComboBox, &TerrainPhysicsSurfaceMaterialMapping::m_surfaceTag, "Surface Tag", "Surface type to map to a physics material.") + ->Attribute(AZ::Edit::Attributes::EnumValues, &TerrainPhysicsSurfaceMaterialMapping::BuildSelectableTagList) + ->DataElement(AZ::Edit::UIHandlers::Default, &TerrainPhysicsSurfaceMaterialMapping::m_materialId, "Material ID", "") ->ElementAttribute(Physics::Attributes::MaterialLibraryAssetId, &TerrainPhysicsSurfaceMaterialMapping::GetMaterialLibraryId) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) @@ -53,6 +58,30 @@ namespace Terrain } } + AZStd::vector> TerrainPhysicsSurfaceMaterialMapping::BuildSelectableTagList() const + { + AZ_PROFILE_FUNCTION(Entity); + + if (m_tagListProvider) + { + AZStd::vector> selectableTags = AZStd::move(m_tagListProvider->BuildSelectableTagList()); + + // Insert the tag currently in use by this mapping + selectableTags.push_back({ m_surfaceTag, m_surfaceTag.GetDisplayName() }); + + // Sorting for consistency + AZStd::sort(selectableTags.begin(), selectableTags.end(), [](const auto& lhs, const auto& rhs) {return lhs.second < rhs.second; }); + return selectableTags; + } + + return SurfaceData::SurfaceTag::GetRegisteredTags(); + } + + void TerrainPhysicsSurfaceMaterialMapping::SetTagListProvider(const EditorSelectableTagListProvider* tagListProvider) + { + m_tagListProvider = tagListProvider; + } + AZ::Data::AssetId TerrainPhysicsSurfaceMaterialMapping::GetMaterialLibraryId() { if (const auto* physicsSystem = AZ::Interface::Get()) diff --git a/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.h b/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.h index 5f79fa9103..97b5e49fca 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.h +++ b/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.h @@ -25,6 +25,8 @@ namespace LmbrCentral namespace Terrain { + class EditorSelectableTagListProvider; + static const uint8_t InvalidSurfaceTagIndex = 0xFF; struct TerrainPhysicsSurfaceMaterialMapping final @@ -33,12 +35,15 @@ namespace Terrain AZ_CLASS_ALLOCATOR(TerrainPhysicsSurfaceMaterialMapping, AZ::SystemAllocator, 0); AZ_RTTI(TerrainPhysicsSurfaceMaterialMapping, "{A88B5289-DFCD-4564-8395-E2177DFE5B18}"); static void Reflect(AZ::ReflectContext* context); + AZStd::vector> BuildSelectableTagList() const; + void SetTagListProvider(const EditorSelectableTagListProvider* tagListProvider); SurfaceData::SurfaceTag m_surfaceTag; Physics::MaterialId m_materialId; private: static AZ::Data::AssetId GetMaterialLibraryId(); + const EditorSelectableTagListProvider* m_tagListProvider = nullptr; }; class TerrainPhysicsColliderConfig diff --git a/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.cpp index 7d41b829c1..64b5d36a8f 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.cpp @@ -11,9 +11,11 @@ #include #include #include +#include #include #include +#include namespace Terrain { @@ -44,6 +46,7 @@ namespace Terrain ->DataElement( AZ::Edit::UIHandlers::Default, &TerrainSurfaceGradientMapping::m_surfaceTag, "Surface Tag", "Surface type to map to this gradient.") + ->Attribute(AZ::Edit::Attributes::EnumValues, &TerrainSurfaceGradientMapping::BuildSelectableTagList) ; } } @@ -60,6 +63,30 @@ namespace Terrain } } + AZStd::vector> TerrainSurfaceGradientMapping::BuildSelectableTagList() const + { + AZ_PROFILE_FUNCTION(Entity); + + if (m_tagListProvider) + { + AZStd::vector> selectableTags = AZStd::move(m_tagListProvider->BuildSelectableTagList()); + + // Insert the tag currently in use by this mapping + selectableTags.push_back({ m_surfaceTag, m_surfaceTag.GetDisplayName() }); + + // Sorting for consistency + AZStd::sort(selectableTags.begin(), selectableTags.end(), [](const auto& lhs, const auto& rhs) {return lhs.second < rhs.second; }); + return selectableTags; + } + + return SurfaceData::SurfaceTag::GetRegisteredTags(); + } + + void TerrainSurfaceGradientMapping::SetTagListProvider(const EditorSelectableTagListProvider* tagListProvider) + { + m_tagListProvider = tagListProvider; + } + void TerrainSurfaceGradientListConfig::Reflect(AZ::ReflectContext* context) { TerrainSurfaceGradientMapping::Reflect(context); diff --git a/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.h b/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.h index 36c16bed8f..b2f41fae88 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.h +++ b/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.h @@ -25,6 +25,8 @@ namespace LmbrCentral namespace Terrain { + class EditorSelectableTagListProvider; + class TerrainSurfaceGradientMapping final { public: @@ -39,8 +41,14 @@ namespace Terrain { } + AZStd::vector> BuildSelectableTagList() const; + void SetTagListProvider(const EditorSelectableTagListProvider* tagListProvider); + AZ::EntityId m_gradientEntityId; SurfaceData::SurfaceTag m_surfaceTag; + + private: + const EditorSelectableTagListProvider* m_tagListProvider = nullptr; }; class TerrainSurfaceGradientListConfig : public AZ::ComponentConfig diff --git a/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainPhysicsColliderComponent.cpp b/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainPhysicsColliderComponent.cpp index 6df6c3b440..09f99fd7fe 100644 --- a/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainPhysicsColliderComponent.cpp +++ b/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainPhysicsColliderComponent.cpp @@ -21,4 +21,38 @@ namespace Terrain typename BaseClassType::WrappedConfigType, 1> ); } + + void EditorTerrainPhysicsColliderComponent::Activate() + { + UpdateConfigurationTagProvider(); + BaseClassType::Activate(); + } + + AZStd::unordered_set EditorTerrainPhysicsColliderComponent::GetSurfaceTagsInUse() const + { + AZStd::unordered_set tagsInUse; + + for (const TerrainPhysicsSurfaceMaterialMapping& mapping : m_configuration.m_surfaceMaterialMappings) + { + AZ::u32 crc = mapping.m_surfaceTag; + tagsInUse.insert(crc); + } + + return AZStd::move(tagsInUse); + } + + AZ::u32 EditorTerrainPhysicsColliderComponent::ConfigurationChanged() + { + UpdateConfigurationTagProvider(); + return BaseClassType::ConfigurationChanged(); + } + + void EditorTerrainPhysicsColliderComponent::UpdateConfigurationTagProvider() + { + for (TerrainPhysicsSurfaceMaterialMapping& mapping : m_configuration.m_surfaceMaterialMappings) + { + mapping.SetTagListProvider(this); + } + } + } diff --git a/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainPhysicsColliderComponent.h b/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainPhysicsColliderComponent.h index 924426c262..fb724507d6 100644 --- a/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainPhysicsColliderComponent.h +++ b/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainPhysicsColliderComponent.h @@ -11,22 +11,34 @@ #include #include #include +#include namespace Terrain { class EditorTerrainPhysicsColliderComponent : public LmbrCentral::EditorWrappedComponentBase + , public EditorSelectableTagListProvider { public: using BaseClassType = LmbrCentral::EditorWrappedComponentBase; AZ_EDITOR_COMPONENT(EditorTerrainPhysicsColliderComponent, "{C43FAB8F-3968-46A6-920E-E84AEDED3DF5}", BaseClassType); static void Reflect(AZ::ReflectContext* context); + // AZ::Component interface implementation + void Activate() override; + static constexpr auto s_categoryName = "Terrain"; static constexpr auto s_componentName = "Terrain Physics Heightfield Collider"; static constexpr auto s_componentDescription = "Provides terrain data to a physics collider in the form of a heightfield and surface->material mapping."; static constexpr auto s_icon = "Editor/Icons/Components/TerrainPhysicsCollider.svg"; static constexpr auto s_viewportIcon = "Editor/Icons/Components/Viewport/TerrainPhysicsCollider.svg"; static constexpr auto s_helpUrl = ""; + + private: + // EditorSelectableTagListProvider interface implementation + AZStd::unordered_set GetSurfaceTagsInUse() const override; + + AZ::u32 ConfigurationChanged() override; + void UpdateConfigurationTagProvider(); }; } diff --git a/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainSurfaceGradientListComponent.cpp b/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainSurfaceGradientListComponent.cpp index bc823734b4..50d45d6cf0 100644 --- a/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainSurfaceGradientListComponent.cpp +++ b/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainSurfaceGradientListComponent.cpp @@ -20,4 +20,37 @@ namespace Terrain typename BaseClassType::WrappedConfigType, 1> ); } + + void EditorTerrainSurfaceGradientListComponent::Activate() + { + UpdateConfigurationTagProvider(); + BaseClassType::Activate(); + } + + AZ::u32 EditorTerrainSurfaceGradientListComponent::ConfigurationChanged() + { + UpdateConfigurationTagProvider(); + return BaseClassType::ConfigurationChanged(); + } + + void EditorTerrainSurfaceGradientListComponent::UpdateConfigurationTagProvider() + { + for (TerrainSurfaceGradientMapping& mapping : m_configuration.m_gradientSurfaceMappings) + { + mapping.SetTagListProvider(this); + } + } + + AZStd::unordered_set EditorTerrainSurfaceGradientListComponent::GetSurfaceTagsInUse() const + { + AZStd::unordered_set tagsInUse; + + for (const TerrainSurfaceGradientMapping& mapping : m_configuration.m_gradientSurfaceMappings) + { + AZ::u32 crc = mapping.m_surfaceTag; + tagsInUse.insert(crc); + } + + return AZStd::move(tagsInUse); + } } diff --git a/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainSurfaceGradientListComponent.h b/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainSurfaceGradientListComponent.h index 58cb776823..37fafdc0a9 100644 --- a/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainSurfaceGradientListComponent.h +++ b/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainSurfaceGradientListComponent.h @@ -11,22 +11,34 @@ #include #include #include +#include namespace Terrain { class EditorTerrainSurfaceGradientListComponent : public LmbrCentral::EditorWrappedComponentBase + , public EditorSelectableTagListProvider { public: using BaseClassType = LmbrCentral::EditorWrappedComponentBase; AZ_EDITOR_COMPONENT(EditorTerrainSurfaceGradientListComponent, "{49831E91-A11F-4EFF-A824-6D85C284B934}", BaseClassType); static void Reflect(AZ::ReflectContext* context); + // AZ::Component interface implementation + void Activate() override; + static constexpr const char* const s_categoryName = "Terrain"; static constexpr const char* const s_componentName = "Terrain Surface Gradient List"; static constexpr const char* const s_componentDescription = "Provides a mapping between gradients and surface tags for use by the terrain system."; static constexpr const char* const s_icon = "Editor/Icons/Components/TerrainSurfaceGradientList.svg"; static constexpr const char* const s_viewportIcon = "Editor/Icons/Components/Viewport/TerrainSurfaceGradientList.svg"; static constexpr const char* const s_helpUrl = "https://o3de.org/docs/user-guide/components/reference/terrain/surface-gradient-list/"; + + private: + // EditorSelectableTagListProvider interface implementation + AZStd::unordered_set GetSurfaceTagsInUse() const override; + + AZ::u32 ConfigurationChanged() override; + void UpdateConfigurationTagProvider(); }; } diff --git a/Gems/Terrain/Code/Source/EditorSelectableTagListProvider.cpp b/Gems/Terrain/Code/Source/EditorSelectableTagListProvider.cpp new file mode 100644 index 0000000000..82ea70158c --- /dev/null +++ b/Gems/Terrain/Code/Source/EditorSelectableTagListProvider.cpp @@ -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 Terrain +{ + AZStd::vector> EditorSelectableTagListProvider::BuildSelectableTagList() const + { + AZStd::vector> availableTags = SurfaceData::SurfaceTag::GetRegisteredTags(); + + AZStd::unordered_set tagsInUse = AZStd::move(GetSurfaceTagsInUse()); + + // Filter out all tags in use from the list of registered tags + availableTags.erase(std::remove_if(availableTags.begin(), availableTags.end(), + [&tagsInUse](const auto& tag)-> bool + { + return tagsInUse.contains(tag.first); + }), availableTags.end()); + + return AZStd::move(availableTags); + } +} diff --git a/Gems/Terrain/Code/Source/EditorSelectableTagListProvider.h b/Gems/Terrain/Code/Source/EditorSelectableTagListProvider.h new file mode 100644 index 0000000000..d8640bd73f --- /dev/null +++ b/Gems/Terrain/Code/Source/EditorSelectableTagListProvider.h @@ -0,0 +1,26 @@ +/* + * 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 Terrain +{ + //! Interface for a class providing information about surface tags available for selecting in Editor components. + class EditorSelectableTagListProvider + { + public: + //! Returns a list of available tags to be selected in the component. + virtual AZStd::vector> BuildSelectableTagList() const; + + //! Returns a set of CRC of all surface tags currently in use and not available for selecting. + virtual AZStd::unordered_set GetSurfaceTagsInUse() const = 0; + }; +} diff --git a/Gems/Terrain/Code/terrain_editor_shared_files.cmake b/Gems/Terrain/Code/terrain_editor_shared_files.cmake index 09724751a9..deb70ba566 100644 --- a/Gems/Terrain/Code/terrain_editor_shared_files.cmake +++ b/Gems/Terrain/Code/terrain_editor_shared_files.cmake @@ -25,6 +25,8 @@ set(FILES Source/EditorComponents/EditorTerrainSystemComponent.h Source/EditorTerrainModule.cpp Source/EditorTerrainModule.h + Source/EditorSelectableTagListProvider.h + Source/EditorSelectableTagListProvider.cpp Source/TerrainModule.cpp Source/TerrainModule.h Source/TerrainRenderer/EditorComponents/EditorTerrainSurfaceMaterialsListComponent.cpp From 701b7a55e6e308b15c4ec258efc21d774e666d4b Mon Sep 17 00:00:00 2001 From: Sergey Pereslavtsev Date: Tue, 8 Feb 2022 12:43:40 +0000 Subject: [PATCH 02/27] PR feedback addressing Signed-off-by: Sergey Pereslavtsev --- .../TerrainPhysicsColliderComponent.cpp | 61 ------------------ .../TerrainPhysicsColliderComponent.h | 10 +-- .../TerrainSurfaceGradientListComponent.cpp | 62 ------------------- .../TerrainSurfaceGradientListComponent.h | 6 +- .../EditorTerrainPhysicsColliderComponent.cpp | 54 ++++++++++++++-- .../EditorTerrainPhysicsColliderComponent.h | 8 +-- ...torTerrainSurfaceGradientListComponent.cpp | 53 ++++++++++++++-- ...ditorTerrainSurfaceGradientListComponent.h | 8 +-- .../EditorSelectableTagListProvider.cpp | 31 ---------- .../Source/EditorSelectableTagListProvider.h | 26 -------- .../Source/EditorSurfaceTagListProvider.cpp | 43 +++++++++++++ .../Source/EditorSurfaceTagListProvider.h | 29 +++++++++ .../Code/terrain_editor_shared_files.cmake | 4 +- 13 files changed, 190 insertions(+), 205 deletions(-) delete mode 100644 Gems/Terrain/Code/Source/EditorSelectableTagListProvider.cpp delete mode 100644 Gems/Terrain/Code/Source/EditorSelectableTagListProvider.h create mode 100644 Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.cpp create mode 100644 Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.h diff --git a/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.cpp index ecc91d06ff..a0689ec23a 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.cpp @@ -17,13 +17,11 @@ #include #include #include -#include #include #include #include -#include namespace Terrain { @@ -35,52 +33,9 @@ namespace Terrain ->Version(1) ->Field("Surface", &TerrainPhysicsSurfaceMaterialMapping::m_surfaceTag) ->Field("Material", &TerrainPhysicsSurfaceMaterialMapping::m_materialId); - - if (auto edit = serialize->GetEditContext()) - { - edit->Class( - "Terrain Surface Material Mapping", "Mapping between a surface and a physics material.") - - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show) - - ->DataElement( - AZ::Edit::UIHandlers::ComboBox, &TerrainPhysicsSurfaceMaterialMapping::m_surfaceTag, "Surface Tag", - "Surface type to map to a physics material.") - ->Attribute(AZ::Edit::Attributes::EnumValues, &TerrainPhysicsSurfaceMaterialMapping::BuildSelectableTagList) - - ->DataElement(AZ::Edit::UIHandlers::Default, &TerrainPhysicsSurfaceMaterialMapping::m_materialId, "Material ID", "") - ->ElementAttribute(Physics::Attributes::MaterialLibraryAssetId, &TerrainPhysicsSurfaceMaterialMapping::GetMaterialLibraryId) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::ShowProductAssetFileName, true); - } } } - AZStd::vector> TerrainPhysicsSurfaceMaterialMapping::BuildSelectableTagList() const - { - AZ_PROFILE_FUNCTION(Entity); - - if (m_tagListProvider) - { - AZStd::vector> selectableTags = AZStd::move(m_tagListProvider->BuildSelectableTagList()); - - // Insert the tag currently in use by this mapping - selectableTags.push_back({ m_surfaceTag, m_surfaceTag.GetDisplayName() }); - - // Sorting for consistency - AZStd::sort(selectableTags.begin(), selectableTags.end(), [](const auto& lhs, const auto& rhs) {return lhs.second < rhs.second; }); - return selectableTags; - } - - return SurfaceData::SurfaceTag::GetRegisteredTags(); - } - - void TerrainPhysicsSurfaceMaterialMapping::SetTagListProvider(const EditorSelectableTagListProvider* tagListProvider) - { - m_tagListProvider = tagListProvider; - } AZ::Data::AssetId TerrainPhysicsSurfaceMaterialMapping::GetMaterialLibraryId() { @@ -105,22 +60,6 @@ namespace Terrain ->Field("DefaultMaterial", &TerrainPhysicsColliderConfig::m_defaultMaterialSelection) ->Field("Mappings", &TerrainPhysicsColliderConfig::m_surfaceMaterialMappings) ; - - if (auto edit = serialize->GetEditContext()) - { - edit->Class( - "Terrain Physics Collider Component", - "Provides terrain data to a physics collider with configurable surface mappings.") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->DataElement(AZ::Edit::UIHandlers::Default, &TerrainPhysicsColliderConfig::m_defaultMaterialSelection, - "Default Surface Physics Material", "Select a material to be used by unmapped surfaces by default") - ->DataElement( - AZ::Edit::UIHandlers::Default, &TerrainPhysicsColliderConfig::m_surfaceMaterialMappings, - "Surface to Material Mappings", "Maps surfaces to physics materials") - ; - } } } diff --git a/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.h b/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.h index 97b5e49fca..2bd0e95769 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.h +++ b/Gems/Terrain/Code/Source/Components/TerrainPhysicsColliderComponent.h @@ -25,7 +25,7 @@ namespace LmbrCentral namespace Terrain { - class EditorSelectableTagListProvider; + class EditorSurfaceTagListProvider; static const uint8_t InvalidSurfaceTagIndex = 0xFF; @@ -35,15 +35,16 @@ namespace Terrain AZ_CLASS_ALLOCATOR(TerrainPhysicsSurfaceMaterialMapping, AZ::SystemAllocator, 0); AZ_RTTI(TerrainPhysicsSurfaceMaterialMapping, "{A88B5289-DFCD-4564-8395-E2177DFE5B18}"); static void Reflect(AZ::ReflectContext* context); + static AZ::Data::AssetId GetMaterialLibraryId(); + AZStd::vector> BuildSelectableTagList() const; - void SetTagListProvider(const EditorSelectableTagListProvider* tagListProvider); + void SetTagListProvider(const EditorSurfaceTagListProvider* tagListProvider); SurfaceData::SurfaceTag m_surfaceTag; Physics::MaterialId m_materialId; private: - static AZ::Data::AssetId GetMaterialLibraryId(); - const EditorSelectableTagListProvider* m_tagListProvider = nullptr; + const EditorSurfaceTagListProvider* m_tagListProvider = nullptr; }; class TerrainPhysicsColliderConfig @@ -53,6 +54,7 @@ namespace Terrain AZ_CLASS_ALLOCATOR(TerrainPhysicsColliderConfig, AZ::SystemAllocator, 0); AZ_RTTI(TerrainPhysicsColliderConfig, "{E9EADB8F-C3A5-4B9C-A62D-2DBC86B4CE59}", AZ::ComponentConfig); static void Reflect(AZ::ReflectContext* context); + Physics::MaterialSelection m_defaultMaterialSelection; AZStd::vector m_surfaceMaterialMappings; }; diff --git a/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.cpp b/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.cpp index 64b5d36a8f..a93bda1872 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.cpp +++ b/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.cpp @@ -11,11 +11,9 @@ #include #include #include -#include #include #include -#include namespace Terrain { @@ -28,27 +26,6 @@ namespace Terrain ->Field("Gradient Entity", &TerrainSurfaceGradientMapping::m_gradientEntityId) ->Field("Surface Tag", &TerrainSurfaceGradientMapping::m_surfaceTag) ; - - if (auto edit = serialize->GetEditContext()) - { - edit->Class("Terrain Surface Gradient Mapping", "Mapping between a gradient and a surface.") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - - ->DataElement( - AZ::Edit::UIHandlers::Default, &TerrainSurfaceGradientMapping::m_gradientEntityId, - "Gradient Entity", "ID of Entity providing a gradient.") - ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues) - ->UIElement("GradientPreviewer", "Previewer") - ->Attribute(AZ::Edit::Attributes::NameLabelOverride, "") - ->Attribute(AZ_CRC_CE("GradientEntity"), &TerrainSurfaceGradientMapping::m_gradientEntityId) - ->DataElement( - AZ::Edit::UIHandlers::Default, &TerrainSurfaceGradientMapping::m_surfaceTag, "Surface Tag", - "Surface type to map to this gradient.") - ->Attribute(AZ::Edit::Attributes::EnumValues, &TerrainSurfaceGradientMapping::BuildSelectableTagList) - ; - } } if (auto behaviorContext = azrtti_cast(context)) @@ -63,30 +40,6 @@ namespace Terrain } } - AZStd::vector> TerrainSurfaceGradientMapping::BuildSelectableTagList() const - { - AZ_PROFILE_FUNCTION(Entity); - - if (m_tagListProvider) - { - AZStd::vector> selectableTags = AZStd::move(m_tagListProvider->BuildSelectableTagList()); - - // Insert the tag currently in use by this mapping - selectableTags.push_back({ m_surfaceTag, m_surfaceTag.GetDisplayName() }); - - // Sorting for consistency - AZStd::sort(selectableTags.begin(), selectableTags.end(), [](const auto& lhs, const auto& rhs) {return lhs.second < rhs.second; }); - return selectableTags; - } - - return SurfaceData::SurfaceTag::GetRegisteredTags(); - } - - void TerrainSurfaceGradientMapping::SetTagListProvider(const EditorSelectableTagListProvider* tagListProvider) - { - m_tagListProvider = tagListProvider; - } - void TerrainSurfaceGradientListConfig::Reflect(AZ::ReflectContext* context) { TerrainSurfaceGradientMapping::Reflect(context); @@ -98,21 +51,6 @@ namespace Terrain ->Version(1) ->Field("Mappings", &TerrainSurfaceGradientListConfig::m_gradientSurfaceMappings) ; - - AZ::EditContext* edit = serialize->GetEditContext(); - if (edit) - { - edit->Class( - "Terrain Surface Gradient List Component", "Provide mapping between gradients and surfaces.") - ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - - ->DataElement( - AZ::Edit::UIHandlers::Default, &TerrainSurfaceGradientListConfig::m_gradientSurfaceMappings, - "Gradient to Surface Mappings", "Maps Gradient Entities to Surfaces.") - ; - } } } diff --git a/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.h b/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.h index b2f41fae88..fd6c16d30d 100644 --- a/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.h +++ b/Gems/Terrain/Code/Source/Components/TerrainSurfaceGradientListComponent.h @@ -25,7 +25,7 @@ namespace LmbrCentral namespace Terrain { - class EditorSelectableTagListProvider; + class EditorSurfaceTagListProvider; class TerrainSurfaceGradientMapping final { @@ -42,13 +42,13 @@ namespace Terrain } AZStd::vector> BuildSelectableTagList() const; - void SetTagListProvider(const EditorSelectableTagListProvider* tagListProvider); + void SetTagListProvider(const EditorSurfaceTagListProvider* tagListProvider); AZ::EntityId m_gradientEntityId; SurfaceData::SurfaceTag m_surfaceTag; private: - const EditorSelectableTagListProvider* m_tagListProvider = nullptr; + const EditorSurfaceTagListProvider* m_tagListProvider = nullptr; }; class TerrainSurfaceGradientListConfig : public AZ::ComponentConfig diff --git a/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainPhysicsColliderComponent.cpp b/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainPhysicsColliderComponent.cpp index 09f99fd7fe..5f76b7de6a 100644 --- a/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainPhysicsColliderComponent.cpp +++ b/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainPhysicsColliderComponent.cpp @@ -20,6 +20,43 @@ namespace Terrain &LmbrCentral::EditorWrappedComponentBaseVersionConverter ); + + if (auto serialize = azrtti_cast(context)) + { + if (auto edit = serialize->GetEditContext()) + { + edit->Class( + "Terrain Surface Material Mapping", "Mapping between a surface and a physics material.") + + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show) + + ->DataElement( + AZ::Edit::UIHandlers::ComboBox, &TerrainPhysicsSurfaceMaterialMapping::m_surfaceTag, "Surface Tag", + "Surface type to map to a physics material.") + ->Attribute(AZ::Edit::Attributes::EnumValues, &TerrainPhysicsSurfaceMaterialMapping::BuildSelectableTagList) + + ->DataElement(AZ::Edit::UIHandlers::Default, &TerrainPhysicsSurfaceMaterialMapping::m_materialId, "Material ID", "") + ->ElementAttribute(Physics::Attributes::MaterialLibraryAssetId, &TerrainPhysicsSurfaceMaterialMapping::GetMaterialLibraryId) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute(AZ::Edit::Attributes::ShowProductAssetFileName, true) + ; + + edit->Class( + "Terrain Physics Collider Component", + "Provides terrain data to a physics collider with configurable surface mappings.") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::Default, &TerrainPhysicsColliderConfig::m_defaultMaterialSelection, + "Default Surface Physics Material", "Select a material to be used by unmapped surfaces by default") + ->DataElement( + AZ::Edit::UIHandlers::Default, &TerrainPhysicsColliderConfig::m_surfaceMaterialMappings, + "Surface to Material Mappings", "Maps surfaces to physics materials") + ; + } + } } void EditorTerrainPhysicsColliderComponent::Activate() @@ -28,14 +65,13 @@ namespace Terrain BaseClassType::Activate(); } - AZStd::unordered_set EditorTerrainPhysicsColliderComponent::GetSurfaceTagsInUse() const + AZStd::unordered_set EditorTerrainPhysicsColliderComponent::GetSurfaceTagsInUse() const { - AZStd::unordered_set tagsInUse; + AZStd::unordered_set tagsInUse; for (const TerrainPhysicsSurfaceMaterialMapping& mapping : m_configuration.m_surfaceMaterialMappings) { - AZ::u32 crc = mapping.m_surfaceTag; - tagsInUse.insert(crc); + tagsInUse.insert(mapping.m_surfaceTag); } return AZStd::move(tagsInUse); @@ -55,4 +91,14 @@ namespace Terrain } } + AZStd::vector> TerrainPhysicsSurfaceMaterialMapping::BuildSelectableTagList() const + { + AZ_PROFILE_FUNCTION(Entity); + return AZStd::move(Terrain::BuildSelectableTagList(m_tagListProvider, m_surfaceTag)); + } + + void TerrainPhysicsSurfaceMaterialMapping::SetTagListProvider(const EditorSurfaceTagListProvider* tagListProvider) + { + m_tagListProvider = tagListProvider; + } } diff --git a/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainPhysicsColliderComponent.h b/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainPhysicsColliderComponent.h index fb724507d6..fca8e52246 100644 --- a/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainPhysicsColliderComponent.h +++ b/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainPhysicsColliderComponent.h @@ -11,13 +11,13 @@ #include #include #include -#include +#include namespace Terrain { class EditorTerrainPhysicsColliderComponent : public LmbrCentral::EditorWrappedComponentBase - , public EditorSelectableTagListProvider + , public EditorSurfaceTagListProvider { public: using BaseClassType = LmbrCentral::EditorWrappedComponentBase; @@ -35,8 +35,8 @@ namespace Terrain static constexpr auto s_helpUrl = ""; private: - // EditorSelectableTagListProvider interface implementation - AZStd::unordered_set GetSurfaceTagsInUse() const override; + // EditorSurfaceTagListProvider interface implementation + AZStd::unordered_set GetSurfaceTagsInUse() const override; AZ::u32 ConfigurationChanged() override; void UpdateConfigurationTagProvider(); diff --git a/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainSurfaceGradientListComponent.cpp b/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainSurfaceGradientListComponent.cpp index 50d45d6cf0..0ea51f282b 100644 --- a/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainSurfaceGradientListComponent.cpp +++ b/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainSurfaceGradientListComponent.cpp @@ -19,6 +19,41 @@ namespace Terrain &LmbrCentral::EditorWrappedComponentBaseVersionConverter ); + + if (auto serialize = azrtti_cast(context)) + { + if (auto edit = serialize->GetEditContext()) + { + edit->Class("Terrain Surface Gradient Mapping", "Mapping between a gradient and a surface.") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + + ->DataElement( + AZ::Edit::UIHandlers::Default, &TerrainSurfaceGradientMapping::m_gradientEntityId, + "Gradient Entity", "ID of Entity providing a gradient.") + ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::AttributesAndValues) + ->UIElement("GradientPreviewer", "Previewer") + ->Attribute(AZ::Edit::Attributes::NameLabelOverride, "") + ->Attribute(AZ_CRC_CE("GradientEntity"), &TerrainSurfaceGradientMapping::m_gradientEntityId) + ->DataElement( + AZ::Edit::UIHandlers::Default, &TerrainSurfaceGradientMapping::m_surfaceTag, "Surface Tag", + "Surface type to map to this gradient.") + ->Attribute(AZ::Edit::Attributes::EnumValues, &TerrainSurfaceGradientMapping::BuildSelectableTagList) + ; + + edit->Class( + "Terrain Surface Gradient List Component", "Provide mapping between gradients and surfaces.") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + + ->DataElement( + AZ::Edit::UIHandlers::Default, &TerrainSurfaceGradientListConfig::m_gradientSurfaceMappings, + "Gradient to Surface Mappings", "Maps Gradient Entities to Surfaces.") + ; + } + } } void EditorTerrainSurfaceGradientListComponent::Activate() @@ -41,16 +76,26 @@ namespace Terrain } } - AZStd::unordered_set EditorTerrainSurfaceGradientListComponent::GetSurfaceTagsInUse() const + AZStd::unordered_set EditorTerrainSurfaceGradientListComponent::GetSurfaceTagsInUse() const { - AZStd::unordered_set tagsInUse; + AZStd::unordered_set tagsInUse; for (const TerrainSurfaceGradientMapping& mapping : m_configuration.m_gradientSurfaceMappings) { - AZ::u32 crc = mapping.m_surfaceTag; - tagsInUse.insert(crc); + tagsInUse.insert(mapping.m_surfaceTag); } return AZStd::move(tagsInUse); } + + AZStd::vector> TerrainSurfaceGradientMapping::BuildSelectableTagList() const + { + AZ_PROFILE_FUNCTION(Entity); + return AZStd::move(Terrain::BuildSelectableTagList(m_tagListProvider, m_surfaceTag)); + } + + void TerrainSurfaceGradientMapping::SetTagListProvider(const EditorSurfaceTagListProvider* tagListProvider) + { + m_tagListProvider = tagListProvider; + } } diff --git a/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainSurfaceGradientListComponent.h b/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainSurfaceGradientListComponent.h index 37fafdc0a9..bcd5d84c38 100644 --- a/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainSurfaceGradientListComponent.h +++ b/Gems/Terrain/Code/Source/EditorComponents/EditorTerrainSurfaceGradientListComponent.h @@ -11,13 +11,13 @@ #include #include #include -#include +#include namespace Terrain { class EditorTerrainSurfaceGradientListComponent : public LmbrCentral::EditorWrappedComponentBase - , public EditorSelectableTagListProvider + , public EditorSurfaceTagListProvider { public: using BaseClassType = LmbrCentral::EditorWrappedComponentBase; @@ -35,8 +35,8 @@ namespace Terrain static constexpr const char* const s_helpUrl = "https://o3de.org/docs/user-guide/components/reference/terrain/surface-gradient-list/"; private: - // EditorSelectableTagListProvider interface implementation - AZStd::unordered_set GetSurfaceTagsInUse() const override; + // EditorSurfaceTagListProvider interface implementation + AZStd::unordered_set GetSurfaceTagsInUse() const override; AZ::u32 ConfigurationChanged() override; void UpdateConfigurationTagProvider(); diff --git a/Gems/Terrain/Code/Source/EditorSelectableTagListProvider.cpp b/Gems/Terrain/Code/Source/EditorSelectableTagListProvider.cpp deleted file mode 100644 index 82ea70158c..0000000000 --- a/Gems/Terrain/Code/Source/EditorSelectableTagListProvider.cpp +++ /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 -#include - -namespace Terrain -{ - AZStd::vector> EditorSelectableTagListProvider::BuildSelectableTagList() const - { - AZStd::vector> availableTags = SurfaceData::SurfaceTag::GetRegisteredTags(); - - AZStd::unordered_set tagsInUse = AZStd::move(GetSurfaceTagsInUse()); - - // Filter out all tags in use from the list of registered tags - availableTags.erase(std::remove_if(availableTags.begin(), availableTags.end(), - [&tagsInUse](const auto& tag)-> bool - { - return tagsInUse.contains(tag.first); - }), availableTags.end()); - - return AZStd::move(availableTags); - } -} diff --git a/Gems/Terrain/Code/Source/EditorSelectableTagListProvider.h b/Gems/Terrain/Code/Source/EditorSelectableTagListProvider.h deleted file mode 100644 index d8640bd73f..0000000000 --- a/Gems/Terrain/Code/Source/EditorSelectableTagListProvider.h +++ /dev/null @@ -1,26 +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 Terrain -{ - //! Interface for a class providing information about surface tags available for selecting in Editor components. - class EditorSelectableTagListProvider - { - public: - //! Returns a list of available tags to be selected in the component. - virtual AZStd::vector> BuildSelectableTagList() const; - - //! Returns a set of CRC of all surface tags currently in use and not available for selecting. - virtual AZStd::unordered_set GetSurfaceTagsInUse() const = 0; - }; -} diff --git a/Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.cpp b/Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.cpp new file mode 100644 index 0000000000..aa4a666d1b --- /dev/null +++ b/Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.cpp @@ -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 + + +namespace Terrain +{ + AZStd::vector> BuildSelectableTagList(const EditorSurfaceTagListProvider* tagListProvider, + const SurfaceData::SurfaceTag& currentTag) + { + AZStd::vector> availableTags = SurfaceData::SurfaceTag::GetRegisteredTags(); + + AZStd::unordered_set tagsInUse; + + if (tagListProvider) + { + tagsInUse = AZStd::move(tagListProvider->GetSurfaceTagsInUse()); + + // Filter out all tags in use from the list of registered tags + AZStd::erase_if(availableTags, [&tagsInUse](const auto& tag)-> bool + { + return tagsInUse.contains(SurfaceData::SurfaceTag(tag.first)); + }); + } + + // Insert the current tag back if it was removed via tagsInUse + availableTags.emplace_back({ AZ::u32(currentTag), currentTag.GetDisplayName() }); + + // Sorting for consistency + AZStd::sort(availableTags.begin(), availableTags.end(), [](const auto& lhs, const auto& rhs) {return lhs.second < rhs.second; }); + + return AZStd::move(availableTags); + } +} diff --git a/Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.h b/Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.h new file mode 100644 index 0000000000..ed5a5c1c0a --- /dev/null +++ b/Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once +#include +#include +#include +#include + +namespace Terrain +{ + //! Interface for a class providing information about surface tags available for selecting in Editor components. + class EditorSurfaceTagListProvider + { + public: + //! Returns a set of all surface tags currently in use that won't be available for selecting. + virtual AZStd::unordered_set GetSurfaceTagsInUse() const = 0; + }; + + //! Returns a list of available tags to be selected in the component. + AZStd::vector> BuildSelectableTagList( + const EditorSurfaceTagListProvider* tagListProvider, + const SurfaceData::SurfaceTag& currentTag); +} diff --git a/Gems/Terrain/Code/terrain_editor_shared_files.cmake b/Gems/Terrain/Code/terrain_editor_shared_files.cmake index deb70ba566..ed64b7c4fc 100644 --- a/Gems/Terrain/Code/terrain_editor_shared_files.cmake +++ b/Gems/Terrain/Code/terrain_editor_shared_files.cmake @@ -25,8 +25,8 @@ set(FILES Source/EditorComponents/EditorTerrainSystemComponent.h Source/EditorTerrainModule.cpp Source/EditorTerrainModule.h - Source/EditorSelectableTagListProvider.h - Source/EditorSelectableTagListProvider.cpp + Source/EditorSurfaceTagListProvider.h + Source/EditorSurfaceTagListProvider.cpp Source/TerrainModule.cpp Source/TerrainModule.h Source/TerrainRenderer/EditorComponents/EditorTerrainSurfaceMaterialsListComponent.cpp From 5dfbddd0cf21e982072a83f84d28cd326e8c4af8 Mon Sep 17 00:00:00 2001 From: Sergey Pereslavtsev Date: Tue, 8 Feb 2022 14:48:52 +0000 Subject: [PATCH 03/27] Build fix Signed-off-by: Sergey Pereslavtsev --- Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.cpp b/Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.cpp index aa4a666d1b..12a371fc49 100644 --- a/Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.cpp +++ b/Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.cpp @@ -33,7 +33,7 @@ namespace Terrain } // Insert the current tag back if it was removed via tagsInUse - availableTags.emplace_back({ AZ::u32(currentTag), currentTag.GetDisplayName() }); + availableTags.emplace_back(AZ::u32(currentTag), currentTag.GetDisplayName()); // Sorting for consistency AZStd::sort(availableTags.begin(), availableTags.end(), [](const auto& lhs, const auto& rhs) {return lhs.second < rhs.second; }); From 8c545138673c7b8fdc249cff6a4c2d780279f35f Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Tue, 8 Feb 2022 16:59:25 -0800 Subject: [PATCH 04/27] Add box selection tests for Editor Focus Mode Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../ContainerEntitySelectionTests.cpp | 10 +-- .../FocusMode/EditorFocusModeFixture.cpp | 11 ++- .../Tests/FocusMode/EditorFocusModeFixture.h | 10 +-- .../EditorFocusModeSelectionFixture.h | 15 ++++ .../EditorFocusModeSelectionTests.cpp | 71 +++++++++++++++++-- 5 files changed, 99 insertions(+), 18 deletions(-) diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntitySelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntitySelectionTests.cpp index 0ad61b924b..483db4076e 100644 --- a/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntitySelectionTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/ContainerEntitySelectionTests.cpp @@ -15,7 +15,7 @@ namespace UnitTest // 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); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify the correct entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -29,7 +29,7 @@ namespace UnitTest m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); // Containers are closed by default // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify the correct entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -47,7 +47,7 @@ namespace UnitTest m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true); // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify the correct entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -65,7 +65,7 @@ namespace UnitTest m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]); // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify the correct entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -85,7 +85,7 @@ namespace UnitTest m_containerEntityInterface->SetContainerOpen(m_entityMap[CityEntityName], true); // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify the correct entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp index 90becfa46f..374b85c01d 100644 --- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.cpp @@ -8,6 +8,7 @@ #include +#include #include #include @@ -93,10 +94,13 @@ namespace UnitTest entity->CreateComponent(); entity->Activate(); - // Move the CarEntity so it's out of the way. - AZ::TransformBus::Event(m_entityMap[CarEntityName], &AZ::TransformBus::Events::SetWorldTranslation, WorldCarEntityPosition); + // Move the City so that it is in view + AZ::TransformBus::Event(m_entityMap[CityEntityName], &AZ::TransformBus::Events::SetWorldTranslation, s_worldCityEntityPosition); - // Setup the camera so the Car entity is in view. + // Move the CarEntity so that it's not overlapping with the rest + AZ::TransformBus::Event(m_entityMap[CarEntityName], &AZ::TransformBus::Events::SetWorldTranslation, s_worldCarEntityPosition); + + // Setup the camera so the entities is in view. AzFramework::SetCameraTransform( m_cameraState, AZ::Transform::CreateFromQuaternionAndTranslation( @@ -113,4 +117,5 @@ namespace UnitTest return entity->GetId(); } + } // namespace UnitTest diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h index 0cf1be6ffd..88cc5ac921 100644 --- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeFixture.h @@ -8,7 +8,6 @@ #pragma once -#include #include #include @@ -38,9 +37,6 @@ namespace UnitTest 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); inline static const char* CityEntityName = "City"; inline static const char* StreetEntityName = "Street"; @@ -49,7 +45,11 @@ namespace UnitTest inline static const char* Passenger1EntityName = "Passenger1"; inline static const char* Passenger2EntityName = "Passenger2"; - inline static AZ::Vector3 WorldCarEntityPosition = AZ::Vector3(5.0f, 15.0f, 0.0f); + AzFramework::CameraState m_cameraState; + + inline static const AZ::Vector3 CameraPosition = AZ::Vector3(10.0f, 15.0f, 10.0f); + inline static AZ::Vector3 s_worldCityEntityPosition = AZ::Vector3(5.0f, 10.0f, 0.0f); + inline static AZ::Vector3 s_worldCarEntityPosition = AZ::Vector3(5.0f, 15.0f, 0.0f); }; } // namespace UnitTest diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionFixture.h b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionFixture.h index fe1de9b122..5dc323dd8c 100644 --- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionFixture.h +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionFixture.h @@ -45,5 +45,20 @@ namespace UnitTest // Click the entity in the viewport m_actionDispatcher->CameraState(m_cameraState)->MousePosition(carScreenPosition)->MouseLButtonDown()->MouseLButtonUp(); } + + void BoxSelectOnViewport() + { + // Calculate the position in screen space of where to begin and end the box select action + const auto beginningPositionWorldBoxSelect = AzFramework::WorldToScreen(AZ::Vector3(-10.0f, 15.0f, 5.0f), m_cameraState); + const auto endingPositionWorldBoxSelect = AzFramework::WorldToScreen(AZ::Vector3(10.0f, 15.0f, -5.0f), m_cameraState); + + // Perform a box select in the viewport + m_actionDispatcher->SetStickySelect(true) + ->CameraState(m_cameraState) + ->MousePosition(beginningPositionWorldBoxSelect) + ->MouseLButtonDown() + ->MousePosition(endingPositionWorldBoxSelect) + ->MouseLButtonUp(); + } }; } // namespace UnitTest diff --git a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp index 1efcb15b30..ee338539a8 100644 --- a/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp +++ b/Code/Framework/AzToolsFramework/Tests/FocusMode/EditorFocusModeSelectionTests.cpp @@ -13,7 +13,7 @@ namespace UnitTest TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionSelectEntityWithFocusOnLevel) { // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -27,7 +27,7 @@ namespace UnitTest m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]); // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -41,7 +41,7 @@ namespace UnitTest m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]); // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -55,7 +55,7 @@ namespace UnitTest m_focusModeInterface->SetFocusRoot(m_entityMap[SportsCarEntityName]); // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); @@ -68,10 +68,71 @@ namespace UnitTest m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger1EntityName]); // Click on Car Entity - ClickAtWorldPositionOnViewport(WorldCarEntityPosition); + ClickAtWorldPositionOnViewport(s_worldCarEntityPosition); // Verify entity is selected auto selectedEntitiesAfter = GetSelectedEntities(); EXPECT_EQ(selectedEntitiesAfter.size(), 0); } + + TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionBoxSelectWithFocusOnLevel) + { + // Do a box select that includes all entities in the fixture + BoxSelectOnViewport(); + + // Entities are selected + using ::testing::UnorderedElementsAre; + auto selectedEntitiesAfter = GetSelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter, + UnorderedElementsAre( + m_entityMap[CityEntityName], + m_entityMap[StreetEntityName], + m_entityMap[CarEntityName], + m_entityMap[Passenger1EntityName], + m_entityMap[SportsCarEntityName], + m_entityMap[Passenger2EntityName] + ) + ); + } + + TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionBoxSelectWithFocusOnChild) + { + // Set the focus on the Passenger1 Entity (child of the entity) + m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]); + + // Do a box select that includes all entities in the fixture + BoxSelectOnViewport(); + + // Entities are selected + using ::testing::UnorderedElementsAre; + auto selectedEntitiesAfter = GetSelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter, + UnorderedElementsAre( + m_entityMap[StreetEntityName], + m_entityMap[CarEntityName], + m_entityMap[Passenger1EntityName], + m_entityMap[SportsCarEntityName], + m_entityMap[Passenger2EntityName] + ) + ); + } + + TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionBoxSelectWithFocusOnLeaf) + { + // Set the focus on the Passenger1 Entity (child of the entity) + m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger1EntityName]); + + // Do a box select that includes all entities in the fixture + BoxSelectOnViewport(); + + // Entities are selected + using ::testing::UnorderedElementsAre; + auto selectedEntitiesAfter = GetSelectedEntities(); + EXPECT_THAT(selectedEntitiesAfter, + UnorderedElementsAre( + m_entityMap[Passenger1EntityName] + ) + ); + } + } // namespace UnitTest From 08a9f908a2a2e3bcf72ac5fa3aa770638e2971f4 Mon Sep 17 00:00:00 2001 From: lsemp3d <58790905+lsemp3d@users.noreply.github.com> Date: Wed, 9 Feb 2022 09:16:21 -0800 Subject: [PATCH 05/27] Disabled tests that are reported failing on nightly builds Signed-off-by: lsemp3d <58790905+lsemp3d@users.noreply.github.com> --- .../Gem/PythonTests/scripting/TestSuite_Periodic.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py b/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py index 27af63ddbc..85714b84a9 100755 --- a/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py +++ b/AutomatedTesting/Gem/PythonTests/scripting/TestSuite_Periodic.py @@ -61,6 +61,7 @@ class TestAutomation(TestAutomationBase): from . import Graph_HappyPath_ZoomInZoomOut as test_module self._run_test(request, workspace, editor, test_module, enable_prefab_system=False) + @pytest.mark.xfail(reason="Test fails on nightly build builds, it needs to be fixed.") def test_NodePalette_HappyPath_CanSelectNode(self, request, workspace, editor, launcher_platform): from . import NodePalette_HappyPath_CanSelectNode as test_module self._run_test(request, workspace, editor, test_module, enable_prefab_system=False) @@ -113,6 +114,7 @@ class TestAutomation(TestAutomationBase): from . import Debugger_HappyPath_TargetMultipleGraphs as test_module self._run_test(request, workspace, editor, test_module, enable_prefab_system=False) + @pytest.mark.xfail(reason="Test fails on nightly build builds, it needs to be fixed.") @pytest.mark.parametrize("level", ["tmp_level"]) def test_Debugger_HappyPath_TargetMultipleEntities(self, request, workspace, editor, launcher_platform, project, level): def teardown(): @@ -174,6 +176,7 @@ class TestAutomation(TestAutomationBase): from . import ScriptEvents_ReturnSetType_Successfully as test_module self._run_test(request, workspace, editor, test_module, enable_prefab_system=False) + @pytest.mark.xfail(reason="Test fails on nightly build builds, it needs to be fixed.") def test_NodeCategory_ExpandOnClick(self, request, workspace, editor, launcher_platform): from . import NodeCategory_ExpandOnClick as test_module self._run_test(request, workspace, editor, test_module, enable_prefab_system=False) @@ -187,6 +190,7 @@ class TestAutomation(TestAutomationBase): from . import VariableManager_UnpinVariableType_Works as test_module self._run_test(request, workspace, editor, test_module, enable_prefab_system=False) + @pytest.mark.xfail(reason="Test fails on nightly build builds, it needs to be fixed.") def test_Node_HappyPath_DuplicateNode(self, request, workspace, editor, launcher_platform): from . import Node_HappyPath_DuplicateNode as test_module self._run_test(request, workspace, editor, test_module, enable_prefab_system=False) @@ -266,6 +270,7 @@ class TestScriptCanvasTests(object): enable_prefab_system=False, ) + @pytest.mark.xfail(reason="Test fails on nightly build builds, it needs to be fixed.") def test_VariableManager_Default_CreateDeleteVars(self, request, editor, launcher_platform): var_types = ["Boolean", "Color", "EntityID", "Number", "String", "Transform", "Vector2", "Vector3", "Vector4"] expected_lines = [f"Success: {var_type} variable is created" for var_type in var_types] From 2f3c4d37dfc77485041b79358c9683a3860574cd Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Wed, 9 Feb 2022 12:22:38 -0600 Subject: [PATCH 06/27] Improved image gradient GetValue(s) performance by using cached image data Signed-off-by: Chris Galvan --- .../Code/Include/Atom/RPI.Public/RPIUtils.h | 5 ++ .../RPI/Code/Source/RPI.Public/RPIUtils.cpp | 74 +++++++++++++------ .../Components/ImageGradientComponent.h | 3 + .../Code/Include/GradientSignal/ImageAsset.h | 2 +- .../Components/ImageGradientComponent.cpp | 49 +++++++++++- .../GradientSignal/Code/Source/ImageAsset.cpp | 7 +- 6 files changed, 109 insertions(+), 31 deletions(-) diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h index 546089ab1e..6516407265 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPIUtils.h @@ -60,6 +60,11 @@ namespace AZ //! Same as above. Provided as a convenience when all arguments of the 'numthreads' attributes should be assigned to RHI::DispatchDirect::m_threadsPerGroup* variables. AZ::Outcome GetComputeShaderNumThreads(const Data::Asset& shaderAsset, RHI::DispatchDirect& dispatchDirect); + //! Get single image pixel value from raw image data + //! This assumes the imageData is not empty + template + T GetImageDataPixelValue(AZStd::span imageData, const AZ::RHI::ImageDescriptor& imageDescriptor, uint32_t x, uint32_t y, uint32_t componentIndex = 0); + //! Get single image pixel value for specified mip and slice template T GetSubImagePixelValue(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex = 0, uint32_t mip = 0, uint32_t slice = 0); diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp index 9ff26f0d3a..8a6cc80cfe 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/RPIUtils.cpp @@ -232,16 +232,12 @@ namespace AZ } } - template - T GetSubImagePixelValueInternal(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) + size_t GetImageDataIndex(const AZ::RHI::ImageDescriptor& imageDescriptor, uint32_t x, uint32_t y, uint32_t componentIndex) { - AZStd::array values{ aznumeric_cast(0) }; + auto width = imageDescriptor.m_size.m_width; + const uint32_t numComponents = AZ::RHI::GetFormatComponentCount(imageDescriptor.m_format); - auto topLeft = AZStd::make_pair(x, y); - auto bottomRight = AZStd::make_pair(x + 1, y + 1); - GetSubImagePixelValues(imageAsset, topLeft, bottomRight, AZStd::span(values), componentIndex, mip, slice); - - return values[0]; + return (y * width + x) * numComponents + componentIndex; } } @@ -447,22 +443,60 @@ namespace AZ return GetComputeShaderNumThreads(shaderAsset, &dispatchDirect.m_threadsPerGroupX, &dispatchDirect.m_threadsPerGroupY, &dispatchDirect.m_threadsPerGroupZ); } + template<> + float GetImageDataPixelValue(AZStd::span imageData, const AZ::RHI::ImageDescriptor& imageDescriptor, uint32_t x, uint32_t y, uint32_t componentIndex) + { + size_t imageDataIndex = Internal::GetImageDataIndex(imageDescriptor, x, y, componentIndex); + return Internal::RetrieveFloatValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); + } + + template<> + AZ::u32 GetImageDataPixelValue(AZStd::span imageData, const AZ::RHI::ImageDescriptor& imageDescriptor, uint32_t x, uint32_t y, uint32_t componentIndex) + { + size_t imageDataIndex = Internal::GetImageDataIndex(imageDescriptor, x, y, componentIndex); + return Internal::RetrieveUintValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); + } + + template<> + AZ::s32 GetImageDataPixelValue(AZStd::span imageData, const AZ::RHI::ImageDescriptor& imageDescriptor, uint32_t x, uint32_t y, uint32_t componentIndex) + { + size_t imageDataIndex = Internal::GetImageDataIndex(imageDescriptor, x, y, componentIndex); + return Internal::RetrieveIntValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); + } + + template + T GetSubImagePixelValueInternal(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) + { + if (!imageAsset.IsReady()) + { + return aznumeric_cast(0); + } + + auto imageData = imageAsset->GetSubImageData(mip, slice); + if (imageData.empty()) + { + return aznumeric_cast(0); + } + + return GetImageDataPixelValue(imageData, imageAsset->GetImageDescriptor(), x, y, componentIndex); + } + template<> float GetSubImagePixelValue(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) { - return Internal::GetSubImagePixelValueInternal(imageAsset, x, y, componentIndex, mip, slice); + return GetSubImagePixelValueInternal(imageAsset, x, y, componentIndex, mip, slice); } template<> AZ::u32 GetSubImagePixelValue(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) { - return Internal::GetSubImagePixelValueInternal(imageAsset, x, y, componentIndex, mip, slice); + return GetSubImagePixelValueInternal(imageAsset, x, y, componentIndex, mip, slice); } template<> AZ::s32 GetSubImagePixelValue(const AZ::Data::Asset& imageAsset, uint32_t x, uint32_t y, uint32_t componentIndex, uint32_t mip, uint32_t slice) { - return Internal::GetSubImagePixelValueInternal(imageAsset, x, y, componentIndex, mip, slice); + return GetSubImagePixelValueInternal(imageAsset, x, y, componentIndex, mip, slice); } bool GetSubImagePixelValues(const AZ::Data::Asset& imageAsset, AZStd::pair topLeft, AZStd::pair bottomRight, AZStd::span outValues, uint32_t componentIndex, uint32_t mip, uint32_t slice) @@ -478,16 +512,14 @@ namespace AZ return false; } - const AZ::RHI::ImageDescriptor imageDescriptor = imageAsset->GetImageDescriptor(); - auto width = imageDescriptor.m_size.m_width; - const uint32_t numComponents = AZ::RHI::GetFormatComponentCount(imageDescriptor.m_format); + const AZ::RHI::ImageDescriptor& imageDescriptor = imageAsset->GetImageDescriptor(); size_t outValuesIndex = 0; for (uint32_t y = topLeft.second; y < bottomRight.second; ++y) { for (uint32_t x = topLeft.first; x < bottomRight.first; ++x) { - size_t imageDataIndex = (y * width + x) * numComponents + componentIndex; + size_t imageDataIndex = Internal::GetImageDataIndex(imageDescriptor, x, y, componentIndex); auto& outValue = outValues[outValuesIndex++]; outValue = Internal::RetrieveFloatValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); @@ -510,16 +542,14 @@ namespace AZ return false; } - const AZ::RHI::ImageDescriptor imageDescriptor = imageAsset->GetImageDescriptor(); - auto width = imageDescriptor.m_size.m_width; - const uint32_t numComponents = AZ::RHI::GetFormatComponentCount(imageDescriptor.m_format); + const AZ::RHI::ImageDescriptor& imageDescriptor = imageAsset->GetImageDescriptor(); size_t outValuesIndex = 0; for (uint32_t y = topLeft.second; y < bottomRight.second; ++y) { for (uint32_t x = topLeft.first; x < bottomRight.first; ++x) { - size_t imageDataIndex = (y * width + x) * numComponents + componentIndex; + size_t imageDataIndex = Internal::GetImageDataIndex(imageDescriptor, x, y, componentIndex); auto& outValue = outValues[outValuesIndex++]; outValue = Internal::RetrieveUintValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); @@ -542,16 +572,14 @@ namespace AZ return false; } - const AZ::RHI::ImageDescriptor imageDescriptor = imageAsset->GetImageDescriptor(); - auto width = imageDescriptor.m_size.m_width; - const uint32_t numComponents = AZ::RHI::GetFormatComponentCount(imageDescriptor.m_format); + const AZ::RHI::ImageDescriptor& imageDescriptor = imageAsset->GetImageDescriptor(); size_t outValuesIndex = 0; for (uint32_t y = topLeft.second; y < bottomRight.second; ++y) { for (uint32_t x = topLeft.first; x < bottomRight.first; ++x) { - size_t imageDataIndex = (y * width + x) * numComponents + componentIndex; + size_t imageDataIndex = Internal::GetImageDataIndex(imageDescriptor, x, y, componentIndex); auto& outValue = outValues[outValuesIndex++]; outValue = Internal::RetrieveIntValue(imageData.data(), imageDataIndex, imageDescriptor.m_format); diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h index 0cbd8bd4c7..7ec1c785e5 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/Components/ImageGradientComponent.h @@ -98,6 +98,8 @@ namespace GradientSignal void SetupDependencies(); + void GetSubImageData(); + // ImageGradientRequestBus overrides... AZStd::string GetImageAssetPath() const override; void SetImageAssetPath(const AZStd::string& assetPath) override; @@ -113,5 +115,6 @@ namespace GradientSignal LmbrCentral::DependencyMonitor m_dependencyMonitor; mutable AZStd::shared_mutex m_imageMutex; GradientTransform m_gradientTransform; + AZStd::span m_imageData; }; } diff --git a/Gems/GradientSignal/Code/Include/GradientSignal/ImageAsset.h b/Gems/GradientSignal/Code/Include/GradientSignal/ImageAsset.h index 811d74082d..500251d924 100644 --- a/Gems/GradientSignal/Code/Include/GradientSignal/ImageAsset.h +++ b/Gems/GradientSignal/Code/Include/GradientSignal/ImageAsset.h @@ -62,6 +62,6 @@ namespace GradientSignal } }; - float GetValueFromImageAsset(const AZ::Data::Asset& imageAsset, const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue); + float GetValueFromImageAsset(AZStd::span imageData, const AZ::RHI::ImageDescriptor& imageDescriptor, const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue); } // namespace GradientSignal diff --git a/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp index 468b96e5ad..39a456a277 100644 --- a/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp @@ -215,6 +215,16 @@ namespace GradientSignal m_dependencyMonitor.ConnectDependency(m_configuration.m_imageAsset.GetId()); } + void ImageGradientComponent::GetSubImageData() + { + if (!m_configuration.m_imageAsset || !m_configuration.m_imageAsset.IsReady()) + { + return; + } + + m_imageData = m_configuration.m_imageAsset->GetSubImageData(0, 0); + } + void ImageGradientComponent::Activate() { // This will immediately call OnGradientTransformChanged and initialize m_gradientTransform. @@ -226,8 +236,19 @@ namespace GradientSignal GradientRequestBus::Handler::BusConnect(GetEntityId()); AZ::Data::AssetBus::Handler::BusConnect(m_configuration.m_imageAsset.GetId()); + // If the image asset is already ready (e.g. constructed in a unit test), + // then go ahead and retrieve the image data now AZStd::unique_lock imageLock(m_imageMutex); - m_configuration.m_imageAsset.QueueLoad(); + if (m_configuration.m_imageAsset.IsReady()) + { + GetSubImageData(); + } + // Otherwise for normal use-case, we queue the asset to be loaded now + else + { + m_imageData = AZStd::span(); + m_configuration.m_imageAsset.QueueLoad(); + } } void ImageGradientComponent::Deactivate() @@ -267,18 +288,24 @@ namespace GradientSignal { AZStd::unique_lock imageLock(m_imageMutex); m_configuration.m_imageAsset = asset; + + GetSubImageData(); } void ImageGradientComponent::OnAssetMoved(AZ::Data::Asset asset, [[maybe_unused]] void* oldDataPointer) { AZStd::unique_lock imageLock(m_imageMutex); m_configuration.m_imageAsset = asset; + + GetSubImageData(); } void ImageGradientComponent::OnAssetReloaded(AZ::Data::Asset asset) { AZStd::unique_lock imageLock(m_imageMutex); m_configuration.m_imageAsset = asset; + + GetSubImageData(); } void ImageGradientComponent::OnGradientTransformChanged(const GradientTransform& newTransform) @@ -292,6 +319,12 @@ namespace GradientSignal AZ::Vector3 uvw = sampleParams.m_position; bool wasPointRejected = false; + // Return immediately if our cached image data hasn't been retrieved yet + if (m_imageData.empty()) + { + return 0.0f; + } + { AZStd::shared_lock imageLock(m_imageMutex); @@ -300,7 +333,7 @@ namespace GradientSignal if (!wasPointRejected) { return GetValueFromImageAsset( - m_configuration.m_imageAsset, uvw, m_configuration.m_tilingX, m_configuration.m_tilingY, 0.0f); + m_imageData, m_configuration.m_imageAsset->GetImageDescriptor(), uvw, m_configuration.m_tilingX, m_configuration.m_tilingY, 0.0f); } } @@ -315,6 +348,12 @@ namespace GradientSignal return; } + // Return immediately if our cached image data hasn't been retrieved yet + if (m_imageData.empty()) + { + return; + } + AZ::Vector3 uvw; bool wasPointRejected = false; @@ -327,7 +366,7 @@ namespace GradientSignal if (!wasPointRejected) { outValues[index] = GetValueFromImageAsset( - m_configuration.m_imageAsset, uvw, m_configuration.m_tilingX, m_configuration.m_tilingY, 0.0f); + m_imageData, m_configuration.m_imageAsset->GetImageDescriptor(), uvw, m_configuration.m_tilingX, m_configuration.m_tilingY, 0.0f); } else { @@ -353,6 +392,10 @@ namespace GradientSignal { AZStd::unique_lock imageLock(m_imageMutex); + + // Clear our cached image data + m_imageData = AZStd::span(); + m_configuration.m_imageAsset = AZ::Data::AssetManager::Instance().FindOrCreateAsset(assetId, azrtti_typeid(), m_configuration.m_imageAsset.GetAutoLoadBehavior()); } diff --git a/Gems/GradientSignal/Code/Source/ImageAsset.cpp b/Gems/GradientSignal/Code/Source/ImageAsset.cpp index 0f91a3ea08..05ad13d193 100644 --- a/Gems/GradientSignal/Code/Source/ImageAsset.cpp +++ b/Gems/GradientSignal/Code/Source/ImageAsset.cpp @@ -78,11 +78,10 @@ namespace GradientSignal return true; } - float GetValueFromImageAsset(const AZ::Data::Asset& imageAsset, const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue) + float GetValueFromImageAsset(AZStd::span imageData, const AZ::RHI::ImageDescriptor& imageDescriptor, const AZ::Vector3& uvw, float tilingX, float tilingY, float defaultValue) { - if (imageAsset.IsReady()) + if (!imageData.empty()) { - auto imageDescriptor = imageAsset->GetImageDescriptor(); auto width = imageDescriptor.m_size.m_width; auto height = imageDescriptor.m_size.m_height; @@ -125,7 +124,7 @@ namespace GradientSignal // Flip the y because images are stored in reverse of our world axes y = (height - 1) - y; - return AZ::RPI::GetSubImagePixelValue(imageAsset, x, y); + return AZ::RPI::GetImageDataPixelValue(imageData, imageDescriptor, x, y); } } From 2e762ba0eb2c916b0acdb9a5fa29537922190cc6 Mon Sep 17 00:00:00 2001 From: Chris Galvan Date: Wed, 9 Feb 2022 14:35:34 -0600 Subject: [PATCH 07/27] Modified activate logic from PR feedback Signed-off-by: Chris Galvan --- .../Components/ImageGradientComponent.cpp | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp b/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp index 39a456a277..0bf914fea3 100644 --- a/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Components/ImageGradientComponent.cpp @@ -234,21 +234,13 @@ namespace GradientSignal ImageGradientRequestBus::Handler::BusConnect(GetEntityId()); GradientRequestBus::Handler::BusConnect(GetEntityId()); - AZ::Data::AssetBus::Handler::BusConnect(m_configuration.m_imageAsset.GetId()); - // If the image asset is already ready (e.g. constructed in a unit test), - // then go ahead and retrieve the image data now - AZStd::unique_lock imageLock(m_imageMutex); - if (m_configuration.m_imageAsset.IsReady()) - { - GetSubImageData(); - } - // Otherwise for normal use-case, we queue the asset to be loaded now - else - { - m_imageData = AZStd::span(); - m_configuration.m_imageAsset.QueueLoad(); - } + // Invoke the QueueLoad before connecting to the AssetBus, so that + // if the asset is already ready, then OnAssetReady will be triggered immediately + m_imageData = AZStd::span(); + m_configuration.m_imageAsset.QueueLoad(); + + AZ::Data::AssetBus::Handler::BusConnect(m_configuration.m_imageAsset.GetId()); } void ImageGradientComponent::Deactivate() From f79fa57b4a350385b148230ef99628eb908f8ee8 Mon Sep 17 00:00:00 2001 From: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> Date: Wed, 9 Feb 2022 16:09:08 -0600 Subject: [PATCH 08/27] Fix race condition crash with the gradient preview. (#7530) When duplicating an entity with a Gradient SurfaceData Component, it's possible to get a hang/crash due to a race condition between entity deactivation and the gradient preview job refresh. This change ensures that the preview job is canceled on deactivation. Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> --- .../Source/Editor/EditorGradientSurfaceDataComponent.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Gems/GradientSignal/Code/Source/Editor/EditorGradientSurfaceDataComponent.cpp b/Gems/GradientSignal/Code/Source/Editor/EditorGradientSurfaceDataComponent.cpp index e318e0fdf6..692576b3b3 100644 --- a/Gems/GradientSignal/Code/Source/Editor/EditorGradientSurfaceDataComponent.cpp +++ b/Gems/GradientSignal/Code/Source/Editor/EditorGradientSurfaceDataComponent.cpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace GradientSignal { @@ -61,6 +62,12 @@ namespace GradientSignal void EditorGradientSurfaceDataComponent::Deactivate() { + // Make sure any previews for this entity aren't currently trying to refresh. Otherwise, the preview job could call + // back into our FilterFunc lambda below after the entity has already been destroyed. + AZ::EntityId canceledEntity; + GradientSignal::GradientPreviewRequestBus::EventResult( + canceledEntity, GetEntityId(), &GradientSignal::GradientPreviewRequestBus::Events::CancelRefresh); + // If the preview shouldn't be active, use an invalid entityId m_gradientEntityId = AZ::EntityId(); AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); From caae0b0ec383a533423e3ebbc46c2e4cd05ad683 Mon Sep 17 00:00:00 2001 From: Benjamin Jillich <43751992+amzn-jillich@users.noreply.github.com> Date: Wed, 9 Feb 2022 23:18:19 +0100 Subject: [PATCH 09/27] Motion Matching: Fix for test build on nightly linux builds (#7522) Signed-off-by: Benjamin Jillich --- Gems/MotionMatching/Code/CMakeLists.txt | 42 ++++++++++++------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/Gems/MotionMatching/Code/CMakeLists.txt b/Gems/MotionMatching/Code/CMakeLists.txt index ae613f5d7f..22d2f28f3b 100644 --- a/Gems/MotionMatching/Code/CMakeLists.txt +++ b/Gems/MotionMatching/Code/CMakeLists.txt @@ -121,27 +121,27 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) ly_add_googletest( NAME Gem::MotionMatching.Tests ) -endif() -# If we are a host platform we want to add tools test like editor tests here -if(PAL_TRAIT_BUILD_HOST_TOOLS) - ly_add_target( - NAME MotionMatching.Editor.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} - NAMESPACE Gem - FILES_CMAKE - motionmatching_editor_tests_files.cmake - INCLUDE_DIRECTORIES - PRIVATE - Tests - Source - BUILD_DEPENDENCIES - PRIVATE - AZ::AzTest - Gem::MotionMatching.Editor - ) + # If we are a host platform we want to add tools test like editor tests here + if(PAL_TRAIT_BUILD_HOST_TOOLS) + ly_add_target( + NAME MotionMatching.Editor.Tests ${PAL_TRAIT_TEST_TARGET_TYPE} + NAMESPACE Gem + FILES_CMAKE + motionmatching_editor_tests_files.cmake + INCLUDE_DIRECTORIES + PRIVATE + Tests + Source + BUILD_DEPENDENCIES + PRIVATE + AZ::AzTest + Gem::MotionMatching.Editor + ) - # Add MotionMatching.Editor.Tests to googletest - ly_add_googletest( - NAME Gem::MotionMatching.Editor.Tests - ) + # Add MotionMatching.Editor.Tests to googletest + ly_add_googletest( + NAME Gem::MotionMatching.Editor.Tests + ) + endif() endif() From 51bac9a6c01426a5bd27904e3e9e8bfcd1622903 Mon Sep 17 00:00:00 2001 From: carlitosan <82187351+carlitosan@users.noreply.github.com> Date: Wed, 9 Feb 2022 14:45:56 -0800 Subject: [PATCH 10/27] remove code that loads member variables on SC editor component twice (#7506) * remove code that loads member variables on SC editor component twice Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> * fix unused variable release build error Signed-off-by: carlitosan <82187351+carlitosan@users.noreply.github.com> --- .../Components/EditorScriptCanvasComponentSerializer.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponentSerializer.cpp b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponentSerializer.cpp index 596c2d9dbf..069b7a5f48 100644 --- a/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponentSerializer.cpp +++ b/Gems/ScriptCanvas/Code/Editor/Include/ScriptCanvas/Components/EditorScriptCanvasComponentSerializer.cpp @@ -5,7 +5,7 @@ * SPDX-License-Identifier: Apache-2.0 OR MIT * */ - + #include #include #include @@ -17,7 +17,7 @@ namespace AZ JsonSerializationResult::Result EditorScriptCanvasComponentSerializer::Load ( void* outputValue - , const Uuid& outputValueTypeId + , [[maybe_unused]] const Uuid& outputValueTypeId , const rapidjson::Value& inputValue , JsonDeserializerContext& context) { @@ -32,9 +32,7 @@ namespace AZ JsonSerializationResult::ResultCode result = BaseJsonSerializer::Load(outputValue , azrtti_typeid(), inputValue, context); - // load child data one by one... - result.Combine(BaseJsonSerializer::Load(outputValue, outputValueTypeId, inputValue, context)); - + // load child data one by one if (result.GetProcessing() != JSR::Processing::Halted) { result.Combine(ContinueLoadingFromJsonObjectField From 4f06be88f61c6f0c1f22339d4b50dcf938ec1e3e Mon Sep 17 00:00:00 2001 From: puvvadar Date: Wed, 9 Feb 2022 15:11:32 -0800 Subject: [PATCH 11/27] Fix Rewindable volume bounds and missing component notification Signed-off-by: puvvadar --- Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp index 59dddf5652..899640895d 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp @@ -113,7 +113,7 @@ namespace Multiplayer NetworkEntityTracker* networkEntityTracker = GetNetworkEntityTracker(); AzFramework::IEntityBoundsUnion* entityBoundsUnion = AZ::Interface::Get(); AZ::Interface::Get()->GetDefaultVisibilityScene()->Enumerate(expandedVolume, - [this, debugDisplay, networkEntityTracker, entityBoundsUnion, rewindVolume](const AzFramework::IVisibilityScene::NodeData& nodeData) + [this, debugDisplay, networkEntityTracker, entityBoundsUnion, expandedVolume](const AzFramework::IVisibilityScene::NodeData& nodeData) { m_rewoundEntities.reserve(m_rewoundEntities.size() + nodeData.m_entries.size()); for (AzFramework::VisibilityEntry* visEntry : nodeData.m_entries) @@ -156,9 +156,10 @@ namespace Multiplayer debugDisplay->DrawWireBox(rewoundAabb.GetMin(), rewoundAabb.GetMax()); } - if (AZ::ShapeIntersection::Overlaps(rewoundAabb, rewindVolume)) // Validate the rewound aabb intersects our rewind volume + if (AZ::ShapeIntersection::Overlaps(rewoundAabb, expandedVolume)) // Validate the rewound aabb intersects our rewind volume { m_rewoundEntities.push_back(entityHandle); + entityHandle.GetNetBindComponent()->NotifySyncRewindState(); } } } From 9d6062d96fb80d5fbed7550aecc909c278b585ba Mon Sep 17 00:00:00 2001 From: dmcdiarmid-ly <63674186+dmcdiarmid-ly@users.noreply.github.com> Date: Wed, 9 Feb 2022 16:18:43 -0700 Subject: [PATCH 12/27] Added an RPISystemInterface method to set the application-wide MSAA state The Editor will now properly apply the MSAA state from MainRenderPipeline.azasset Corrected a race condition with the cubemap baking pipeline Signed-off-by: dmcdiarmid-ly <63674186+dmcdiarmid-ly@users.noreply.github.com> --- .../Code/Source/BootstrapSystemComponent.cpp | 6 ++--- .../Passes/EnvironmentCubeMapDepthMSAA.pass | 6 ++--- .../DiffuseProbeGridRender.precompiledshader | 18 +++++++++++++ ...begridrender-nomsaa_dx12_0.azshadervariant | Bin 0 -> 29668 bytes ...begridrender-nomsaa_null_0.azshadervariant | Bin 0 -> 589 bytes ...gridrender-nomsaa_vulkan_0.azshadervariant | Bin 0 -> 24013 bytes .../diffuseprobegridrender.azshader | Bin 219075 -> 436794 bytes ...fuseprobegridrender_dx12_0.azshadervariant | Bin 30575 -> 30575 bytes ...fuseprobegridrender_null_0.azshadervariant | Bin 589 -> 589 bytes ...seprobegridrender_vulkan_0.azshadervariant | Bin 24081 -> 24081 bytes .../ReflectionProbe/ReflectionProbe.cpp | 16 ++++++++---- .../Source/ReflectionProbe/ReflectionProbe.h | 1 + .../ReflectionProbeFeatureProcessor.cpp | 12 +++++++++ .../ReflectionProbeFeatureProcessor.h | 1 + .../Code/Include/Atom/RPI.Public/RPISystem.h | 5 ++++ .../Atom/RPI.Public/RPISystemInterface.h | 4 +++ .../RPI/Code/Source/RPI.Public/RPISystem.cpp | 24 ++++++++++++++++++ .../PreviewRenderer/PreviewRenderer.cpp | 4 +-- 18 files changed, 82 insertions(+), 15 deletions(-) create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender-nomsaa_dx12_0.azshadervariant create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender-nomsaa_null_0.azshadervariant create mode 100644 Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender-nomsaa_vulkan_0.azshadervariant diff --git a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp index ef03a839d7..60ca6ff429 100644 --- a/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp +++ b/Gems/Atom/Bootstrap/Code/Source/BootstrapSystemComponent.cpp @@ -318,10 +318,8 @@ namespace AZ RPI::RenderPipelineDescriptor renderPipelineDescriptor = *RPI::GetDataFromAnyAsset(pipelineAsset); renderPipelineDescriptor.m_name = AZStd::string::format("%s_%i", renderPipelineDescriptor.m_name.c_str(), viewportContext->GetId()); - // Make sure non-msaa super variant is used for non-msaa pipeline - bool isNonMsaaPipeline = (renderPipelineDescriptor.m_renderSettings.m_multisampleState.m_samples == 1); - const char* supervariantName = isNonMsaaPipeline ? AZ::RPI::NoMsaaSupervariantName : ""; - AZ::RPI::ShaderSystemInterface::Get()->SetSupervariantName(AZ::Name(supervariantName)); + // The default pipeline determines the initial MSAA state for the application + AZ::RPI::RPISystemInterface::Get()->SetApplicationMultisampleState(renderPipelineDescriptor.m_renderSettings.m_multisampleState); if (!scene->GetRenderPipeline(AZ::Name(renderPipelineDescriptor.m_name))) { diff --git a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapDepthMSAA.pass b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapDepthMSAA.pass index 5abbe7d62d..cb94e75389 100644 --- a/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapDepthMSAA.pass +++ b/Gems/Atom/Feature/Common/Assets/Passes/EnvironmentCubeMapDepthMSAA.pass @@ -34,11 +34,11 @@ "Attachment": "Output" } }, + "MultisampleSource": { + "Pass": "Pipeline" + }, "ImageDescriptor": { "Format": "D32_FLOAT_S8X24_UINT", - "MultisampleState": { - "samples": 4 - }, "SharedQueueMask": "Graphics" } } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRender.precompiledshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRender.precompiledshader index 97c58091a2..613714b0b6 100644 --- a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRender.precompiledshader +++ b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/DiffuseProbeGridRender.precompiledshader @@ -29,6 +29,24 @@ "RootShaderVariantAssetFileName": "diffuseprobegridrender_null_0.azshadervariant" } ] + }, + { + "Name": "NoMSAA", + "RootShaderVariantAssets": + [ + { + "APIName": "dx12", + "RootShaderVariantAssetFileName": "diffuseprobegridrender-nomsaa_dx12_0.azshadervariant" + }, + { + "APIName": "vulkan", + "RootShaderVariantAssetFileName": "diffuseprobegridrender-nomsaa_vulkan_0.azshadervariant" + }, + { + "APIName": "null", + "RootShaderVariantAssetFileName": "diffuseprobegridrender-nomsaa_null_0.azshadervariant" + } + ] } ] } diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender-nomsaa_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender-nomsaa_dx12_0.azshadervariant new file mode 100644 index 0000000000000000000000000000000000000000..31ca52ba02b7f81f6bbe2fbb57f4f21bf897008b GIT binary patch literal 29668 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 z zv_vP&z+9>E;BEjffbNFV;Qp7*5MCf%uJ?9~OXfj7_<=%nn?`EVR66n(c*gbWG!>NJ zI4Hl()pGFp2P-V_Rp&ZIC%2bzur0`T6fL5i55u%rA{(N`k2VA>o|fT&0w|7grDdc> z$X^cjykgV!anJYxvdl`~MW+AeEm}w;ZB)BB4%wJdmZ<*M??J7A9ttlQB z#<}(~q}I(Jf1iJL`5_8Ar#(f!CaGS=;ji$Uzrs(W(wgnl@!`|)6yn>&N#ms6Fe$*M zF&oEjRbQ- literal 0 HcmV?d00001 diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender-nomsaa_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender-nomsaa_null_0.azshadervariant new file mode 100644 index 0000000000000000000000000000000000000000..299490c1bd28c50ad68e8f24e11146bb75b6f6f3 GIT binary patch literal 589 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 Lqv`BVDEI#XoPY6L literal 0 HcmV?d00001 diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender.azshader b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender.azshader index 4676c42e8da1743b54f491e17ccc3347aa0fb277..16db49af1ba018c19dc432a74e38029272a65a5a 100644 GIT binary patch delta 996 zcmX@So_E(3sSR2zEZb6=syFMgRJyT+d8ZbZmu_C`wTc7Ajt!P?fU(zlad2$zx_yEP zCJ-Aesk8l$8q+amjwS4ye`hF3E!}R<$Ji${c|MC6W8CDx0ueU9eBWS4$IYi$?z+OX zt@Y|-nl2#DTr*krCfD?HtxOUip5Nq#0G3VH>sUB~id>#(=-x`0yfJ7QOb@C%h||Aa z@CV}=Y>wsnci>vP__0kO$EFA|I!vD$&aA!tyaHn~EDW~ueqiL_nC_6zxCrWk=|BnSNjmqv-SiQ6`Sb{~xn%3YntLu_knRgy#AqzjhJ+udVr9$h zyB|+)W!P@x#vCp>w@}kb;p^PY`DTN;u=S0`6VQ3(~W6GH1#_z01S^ zjRSuhCU_i7Uh5@0y+DjvW&0j(=9BD`w+6*e&u?OKhK4IhdOJ}1pZ50F?MxqFVUMC~ zA}kVMijU}XeA=?aslwQ97AT;b1hIwjG{)`Oc1-RrNEX4};g2`vZc(v)$u)h-L12(4 jlj>IDOy1ro%nVP{NWN<76*uhFS?>VyRfHfUN$UXsAzyR5 delta 336 zcmdmWMe6W+-VItTELok8Pi@v?sdQsYDU66JtK9xDjj@kuv%s|~*2!Cg7QsX(<}=DS zz&J1^P8={1ptPjUb^~YTW6T_H@?|Hl$>{#J-JXxJPiXq8Viu?E&bCa-a2p(Xm^nC* z44)1Zu-|?mpYf~q_JAEsuY+Nx0>v+IK{;?mx3r=5_}p?@v%K^5yX|$_Oc8?9!y=fq zw*xIph1oOx;ayh8?FCm^{XyQzW1TL1h-DqjXrLT7%s=P~w_o#Oy~2c~Qd(#G=}K0h d*H*eKC*1b?`e=K-HdDCZ^bdWk+N=y9005llg7p9Z diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_dx12_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_dx12_0.azshadervariant index 9bf8e7f53fcde322f5ff225146544c70979e16c0..23b0c807bf9bc68cb6ac3b7e255aea8829905ac4 100644 GIT binary patch delta 17 YcmaF=j`96F#tj+e?AubBsu>s<08`=zY5)KL delta 17 ZcmaF=j`96F#tj+e>{*?UPcbks0033Z2lD^` diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_null_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_null_0.azshadervariant index 98402384db1e019e435ea7756543150375580091..299490c1bd28c50ad68e8f24e11146bb75b6f6f3 100644 GIT binary patch delta 15 WcmX@ha+YO-8x#Asl%{G11_l5vK?Jz~ delta 15 WcmX@ha+YO-8xwn0=i^fh3=9A-ECoUU diff --git a/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_vulkan_0.azshadervariant b/Gems/Atom/Feature/Common/Assets/Shaders/DiffuseGlobalIllumination/diffuseprobegridrender_vulkan_0.azshadervariant index 5caf3084766a8bd2be7d63394f0257af6e304dd6..447f0712d32462d676490ea7496c0233fd1b1b3c 100644 GIT binary patch delta 17 YcmbQZhjHQ_#tmF??AubBsu>s<06s|t(*OVf delta 17 ZcmbQZhjHQ_#tmF?>{*?UPcbks002NV23!CD diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp index f5aaec4faa..539531b5a0 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.cpp @@ -115,10 +115,6 @@ namespace AZ // all faces of the cubemap have been rendered, invoke the callback m_callback(m_environmentCubeMapPass->GetTextureData(), m_environmentCubeMapPass->GetTextureFormat()); - // remove the pipeline - m_scene->RemoveRenderPipeline(m_environmentCubeMapPipelineId); - m_environmentCubeMapPass = nullptr; - // restore exposures sceneSrg->SetConstant(m_globalIblExposureConstantIndex, m_previousGlobalIblExposure); sceneSrg->SetConstant(m_skyBoxExposureConstantIndex, m_previousSkyBoxExposure); @@ -223,6 +219,16 @@ namespace AZ } } + void ReflectionProbe::OnRenderEnd() + { + if (m_environmentCubeMapPass && m_environmentCubeMapPass->IsFinished()) + { + // remove the cubemap pipeline + // Note: this must be done here (not in Simulate) to avoid a race condition with other feature processors + m_scene->RemoveRenderPipeline(m_environmentCubeMapPipelineId); + m_environmentCubeMapPass = nullptr; + } + } void ReflectionProbe::SetTransform(const AZ::Transform& transform) { @@ -282,7 +288,7 @@ namespace AZ AZ::RPI::RenderPipelineDescriptor environmentCubeMapPipelineDesc; environmentCubeMapPipelineDesc.m_mainViewTagName = "MainCamera"; - environmentCubeMapPipelineDesc.m_renderSettings.m_multisampleState.m_samples = 4; + environmentCubeMapPipelineDesc.m_renderSettings.m_multisampleState = RPI::RPISystemInterface::Get()->GetApplicationMultisampleState(); environmentCubeMapPipelineDesc.m_renderSettings.m_size.m_width = RPI::EnvironmentCubeMapPass::CubeMapFaceSize; environmentCubeMapPipelineDesc.m_renderSettings.m_size.m_height = RPI::EnvironmentCubeMapPass::CubeMapFaceSize; diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h index 17ef54367b..6ec9368167 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbe.h @@ -75,6 +75,7 @@ namespace AZ void Init(RPI::Scene* scene, ReflectionRenderData* reflectionRenderData); void Simulate(uint32_t probeIndex); + void OnRenderEnd(); const Vector3& GetPosition() const { return m_transform.GetTranslation(); } const AZ::Transform& GetTransform() const { return m_transform; } diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp index 155a159447..cfe807610b 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.cpp @@ -166,6 +166,18 @@ namespace AZ } } + void ReflectionProbeFeatureProcessor::OnRenderEnd() + { + // call OnRenderEnd on all reflection probes + for (uint32_t probeIndex = 0; probeIndex < m_reflectionProbes.size(); ++probeIndex) + { + AZStd::shared_ptr& reflectionProbe = m_reflectionProbes[probeIndex]; + AZ_Assert(reflectionProbe.use_count() > 1, "ReflectionProbe found with no corresponding owner, ensure that RemoveProbe() is called before releasing probe handles"); + + reflectionProbe->OnRenderEnd(); + } + } + ReflectionProbeHandle ReflectionProbeFeatureProcessor::AddProbe(const AZ::Transform& transform, bool useParallaxCorrection) { AZStd::shared_ptr reflectionProbe = AZStd::make_shared(); diff --git a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.h b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.h index ded36f5496..92fb3fe604 100644 --- a/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.h +++ b/Gems/Atom/Feature/Common/Code/Source/ReflectionProbe/ReflectionProbeFeatureProcessor.h @@ -46,6 +46,7 @@ namespace AZ void Activate() override; void Deactivate() override; void Simulate(const FeatureProcessor::SimulatePacket& packet) override; + void OnRenderEnd() override; // find the reflection probe volumes that contain the position using ReflectionProbeVector = AZStd::vector>; diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystem.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystem.h index 57f595ccba..dbf70fb0cc 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystem.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystem.h @@ -86,6 +86,8 @@ namespace AZ const RPISystemDescriptor& GetDescriptor() const override; Name GetRenderApiName() const override; uint64_t GetCurrentTick() const override; + void SetApplicationMultisampleState(const RHI::MultisampleState& multisampleState) override; + const RHI::MultisampleState& GetApplicationMultisampleState() const override; // AZ::Debug::TraceMessageBus::Handler overrides... bool OnPreAssert(const char* fileName, int line, const char* func, const char* message) override; @@ -136,6 +138,9 @@ namespace AZ bool m_systemAssetsInitialized = false; uint64_t m_renderTick = 0; + + // Application multisample state + RHI::MultisampleState m_multisampleState; }; } // namespace RPI diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystemInterface.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystemInterface.h index 693185b6d2..7853e8f51e 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystemInterface.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Public/RPISystemInterface.h @@ -90,6 +90,10 @@ namespace AZ //! Get the index of current render tick virtual uint64_t GetCurrentTick() const = 0; + + //! Application multisample state + virtual void SetApplicationMultisampleState(const RHI::MultisampleState& multisampleState) = 0; + virtual const RHI::MultisampleState& GetApplicationMultisampleState() const = 0; }; } // namespace RPI diff --git a/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp b/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp index 3416b2895d..57bef2c7e5 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Public/RPISystem.cpp @@ -434,5 +434,29 @@ namespace AZ return m_renderTick; } + void RPISystem::SetApplicationMultisampleState(const RHI::MultisampleState& multisampleState) + { + m_multisampleState = multisampleState; + + bool isNonMsaaPipeline = (m_multisampleState.m_samples == 1); + const char* supervariantName = isNonMsaaPipeline ? AZ::RPI::NoMsaaSupervariantName : ""; + AZ::RPI::ShaderSystemInterface::Get()->SetSupervariantName(AZ::Name(supervariantName)); + + // reinitialize pipelines for all scenes + for (auto& scene : m_scenes) + { + for (auto& renderPipeline : scene->GetRenderPipelines()) + { + renderPipeline->GetRenderSettings().m_multisampleState = multisampleState; + renderPipeline->SetPassNeedsRecreate(); + } + } + } + + const RHI::MultisampleState& RPISystem::GetApplicationMultisampleState() const + { + return m_multisampleState; + } + } //namespace RPI } //namespace AZ diff --git a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/PreviewRenderer/PreviewRenderer.cpp b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/PreviewRenderer/PreviewRenderer.cpp index 27d468e64b..638e8da87c 100644 --- a/Gems/Atom/Tools/AtomToolsFramework/Code/Source/PreviewRenderer/PreviewRenderer.cpp +++ b/Gems/Atom/Tools/AtomToolsFramework/Code/Source/PreviewRenderer/PreviewRenderer.cpp @@ -63,10 +63,8 @@ namespace AtomToolsFramework pipelineDesc.m_mainViewTagName = "MainCamera"; pipelineDesc.m_name = pipelineName; pipelineDesc.m_rootPassTemplate = "ToolsPipelineRenderToTexture"; + pipelineDesc.m_renderSettings.m_multisampleState = AZ::RPI::RPISystemInterface::Get()->GetApplicationMultisampleState(); - // We have to set the samples to 4 to match the pipeline passes' setting, otherwise it may lead to device lost issue - // [GFX TODO] [ATOM-13551] Default value sand validation required to prevent pipeline crash and device lost - pipelineDesc.m_renderSettings.m_multisampleState.m_samples = 4; m_renderPipeline = AZ::RPI::RenderPipeline::CreateRenderPipeline(pipelineDesc); m_scene->AddRenderPipeline(m_renderPipeline); m_scene->Activate(); From e5800d738a34a2ed2358cef381d3b9b94954cabd Mon Sep 17 00:00:00 2001 From: michabr <82236305+michabr@users.noreply.github.com> Date: Wed, 9 Feb 2022 15:27:53 -0800 Subject: [PATCH 13/27] Fix position of newly created UI element (#7510) Signed-off-by: abrmich --- Gems/LyShine/Code/Editor/HierarchyMenu.cpp | 8 ++++++-- Gems/LyShine/Code/Editor/HierarchyWidget.cpp | 6 ++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Gems/LyShine/Code/Editor/HierarchyMenu.cpp b/Gems/LyShine/Code/Editor/HierarchyMenu.cpp index 004fe53354..4fb09ea1f8 100644 --- a/Gems/LyShine/Code/Editor/HierarchyMenu.cpp +++ b/Gems/LyShine/Code/Editor/HierarchyMenu.cpp @@ -387,7 +387,9 @@ void HierarchyMenu::New_ElementFromSlice(HierarchyWidget* hierarchy, AZ::Vector2 viewportPosition(-1.0f,-1.0f); // indicates no viewport position specified if (optionalPos) { - viewportPosition = QtHelpers::QPointFToVector2(*optionalPos); + // Convert position to render viewport coords + QPointF scaledPosition = *optionalPos * hierarchy->GetEditorWindow()->GetViewport()->WidgetToViewportFactor(); + viewportPosition = QtHelpers::QPointFToVector2(scaledPosition); } SliceMenuHelpers::CreateInstantiateSliceMenu(hierarchy, @@ -405,7 +407,9 @@ void HierarchyMenu::New_ElementFromSlice(HierarchyWidget* hierarchy, AZ::Vector2 viewportPosition(-1.0f,-1.0f); // indicates no viewport position specified if (optionalPos) { - viewportPosition = QtHelpers::QPointFToVector2(*optionalPos); + // Convert position to render viewport coords + QPointF scaledPosition = *optionalPos * hierarchy->GetEditorWindow()->GetViewport()->WidgetToViewportFactor(); + viewportPosition = QtHelpers::QPointFToVector2(scaledPosition); } hierarchy->GetEditorWindow()->GetSliceManager()->InstantiateSliceUsingBrowser(hierarchy, viewportPosition); } diff --git a/Gems/LyShine/Code/Editor/HierarchyWidget.cpp b/Gems/LyShine/Code/Editor/HierarchyWidget.cpp index 30cb7e51dc..cd80e5a278 100644 --- a/Gems/LyShine/Code/Editor/HierarchyWidget.cpp +++ b/Gems/LyShine/Code/Editor/HierarchyWidget.cpp @@ -1239,11 +1239,13 @@ void HierarchyWidget::AddElement(const QTreeWidgetItemRawPtrQList& selectedItems this, selectedItems, childIndex, - [optionalPos](AZ::Entity* element) + [this, optionalPos](AZ::Entity* element) { if (optionalPos) { - EntityHelpers::MoveElementToGlobalPosition(element, *optionalPos); + // Convert position to render viewport coords + QPoint scaledPosition = *optionalPos * GetEditorWindow()->GetViewport()->WidgetToViewportFactor(); + EntityHelpers::MoveElementToGlobalPosition(element, scaledPosition); } }); } From dc5d50a4ce163af54f0547bdf8f223ded1297f6c Mon Sep 17 00:00:00 2001 From: Ken Pruiksma Date: Wed, 9 Feb 2022 17:41:38 -0600 Subject: [PATCH 14/27] Terrain default surface material (#7481) Terrain default surface material This adds the ability to set a default material on detail material regions as a fallback material for when there are no materials for an assigned surface tag, or there's only one surface tag but its weight is less than 1.0. This also fixes some issues - The terrain surface list component now correctly sends notifications on tag changes. - The terrain area material notifications bus now has two separate change notifications - one for material, the other for tag - The terrain renderer will now only consider a single region per point queried instead of any region that might have a matching surface tag. --- .../TerrainSurfaceMaterialsListComponent.cpp | 233 ++++++++++++----- .../TerrainSurfaceMaterialsListComponent.h | 27 +- .../TerrainAreaMaterialRequestBus.h | 34 ++- .../TerrainDetailMaterialManager.cpp | 245 +++++++++++++----- .../TerrainDetailMaterialManager.h | 34 ++- 5 files changed, 437 insertions(+), 136 deletions(-) diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp index 5f2a50f903..fc4b821578 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp +++ b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp @@ -8,21 +8,19 @@ #include -#include -#include #include +#include #include -#include -#include -#include +#include #include +#include +#include #include -#include -#include - #include +#include +#include #include namespace Terrain @@ -38,15 +36,14 @@ namespace Terrain if (auto edit = serialize->GetEditContext()) { - edit->Class("Terrain Surface Gradient Mapping", "Mapping between a surface and a material.") + edit->Class("Terrain surface gradient mapping", "Mapping between a surface and a material.") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show) - - ->DataElement(AZ::Edit::UIHandlers::ComboBox, &TerrainSurfaceMaterialMapping::m_surfaceTag, "Surface Tag", "Surface type to map to a material.") - ->DataElement(AZ::Edit::UIHandlers::Default, &TerrainSurfaceMaterialMapping::m_materialAsset, "Material Asset", "") - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) - ->Attribute(AZ::Edit::Attributes::ShowProductAssetFileName, true) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + + ->DataElement(AZ::Edit::UIHandlers::ComboBox, &TerrainSurfaceMaterialMapping::m_surfaceTag, "Surface tag", "Surface type to map to a material.") + ->DataElement(AZ::Edit::UIHandlers::Default, &TerrainSurfaceMaterialMapping::m_materialAsset, "Material asset", "") + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute(AZ::Edit::Attributes::ShowProductAssetFileName, true) ; } } @@ -60,7 +57,8 @@ namespace Terrain if (serialize) { serialize->Class() - ->Version(1) + ->Version(2) + ->Field("DefaultMaterial", &TerrainSurfaceMaterialsListConfig::m_defaultSurfaceMaterial) ->Field("Mappings", &TerrainSurfaceMaterialsListConfig::m_surfaceMaterials); AZ::EditContext* edit = serialize->GetEditContext(); @@ -68,10 +66,13 @@ namespace Terrain { edit->Class( "Terrain Surface Material List Component", "Provide mapping between surfaces and render materials.") + ->SetDynamicEditDataProvider(&TerrainSurfaceMaterialsListConfig::GetDynamicData) ->ClassElement(AZ::Edit::ClassElements::EditorData, "") - ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show) - ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::Show) + ->Attribute(AZ::Edit::Attributes::AutoExpand, true) + ->DataElement(AZ::Edit::UIHandlers::Default, &TerrainSurfaceMaterialsListConfig::m_defaultSurfaceMaterial, + "Default Material", "The default material to fall back to where no other material surface mappings exist.") ->DataElement( AZ::Edit::UIHandlers::Default, &TerrainSurfaceMaterialsListConfig::m_surfaceMaterials, "Material Mappings", "Maps surfaces to materials."); @@ -79,6 +80,26 @@ namespace Terrain } } + TerrainSurfaceMaterialsListConfig::TerrainSurfaceMaterialsListConfig() + { + m_hideSurfaceTagData.m_attributes.push_back( + { + AZ::Edit::Attributes::Visibility, + aznew AZ::Edit::AttributeData(AZ::Edit::PropertyVisibility::Hide) + } + ); + } + + const AZ::Edit::ElementData* TerrainSurfaceMaterialsListConfig::GetDynamicData(const void* handlerPtr, const void* elementPtr, const AZ::Uuid& ) + { + const TerrainSurfaceMaterialsListConfig* owner = reinterpret_cast(handlerPtr); + if (elementPtr == &owner->m_defaultSurfaceMaterial.m_surfaceTag) + { + return &owner->m_hideSurfaceTagData; + } + return nullptr; + } + void TerrainSurfaceMaterialsListComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services) { services.push_back(AZ_CRC_CE("TerrainMaterialProviderService")); @@ -116,15 +137,21 @@ namespace Terrain { m_cachedAabb = AZ::Aabb::CreateNull(); + auto checkLoadMaterial = [&](TerrainSurfaceMaterialMapping& material) + { + if (material.m_materialAsset.GetId().IsValid()) + { + material.m_active = false; + material.m_materialAsset.QueueLoad(); + AZ::Data::AssetBus::MultiHandler::BusConnect(material.m_materialAsset.GetId()); + } + }; + // Set all the materials as inactive and start loading. + checkLoadMaterial(m_configuration.m_defaultSurfaceMaterial); for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials) { - if (surfaceMaterialMapping.m_materialAsset.GetId().IsValid()) - { - surfaceMaterialMapping.m_active = false; - surfaceMaterialMapping.m_materialAsset.QueueLoad(); - AZ::Data::AssetBus::MultiHandler::BusConnect(surfaceMaterialMapping.m_materialAsset.GetId()); - } + checkLoadMaterial(surfaceMaterialMapping); } // Announce initial shape using OnShapeChanged @@ -135,24 +162,35 @@ namespace Terrain { TerrainAreaMaterialRequestBus::Handler::BusDisconnect(); + auto checkResetMaterial = [&](TerrainSurfaceMaterialMapping& material) + { + if (material.m_materialAsset.GetId().IsValid()) + { + AZ::Data::AssetBus::MultiHandler::BusDisconnect(material.m_materialAsset.GetId()); + material.m_materialAsset.Release(); + material.m_materialInstance.reset(); + material.m_activeMaterialAssetId = AZ::Data::AssetId(); + } + }; + + checkResetMaterial(m_configuration.m_defaultSurfaceMaterial); for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials) { - if (surfaceMaterialMapping.m_materialAsset.GetId().IsValid()) - { - AZ::Data::AssetBus::MultiHandler::BusDisconnect(surfaceMaterialMapping.m_materialAsset.GetId()); - surfaceMaterialMapping.m_materialAsset.Release(); - surfaceMaterialMapping.m_materialInstance.reset(); - surfaceMaterialMapping.m_activeMaterialAssetId = AZ::Data::AssetId(); - } + checkResetMaterial(surfaceMaterialMapping); } HandleMaterialStateChanges(); } - int TerrainSurfaceMaterialsListComponent::CountMaterialIDInstances(AZ::Data::AssetId id) const + int TerrainSurfaceMaterialsListComponent::CountMaterialIdInstances(AZ::Data::AssetId id) const { int count = 0; + if (m_configuration.m_defaultSurfaceMaterial.m_activeMaterialAssetId == id) + { + count++; + } + for (const auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials) { if (surfaceMaterialMapping.m_activeMaterialAssetId == id) @@ -169,28 +207,63 @@ namespace Terrain bool anyMaterialIsActive = false; bool anyMaterialWasAlreadyActive = false; - for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials) { - const bool wasPreviouslyActive = surfaceMaterialMapping.m_active; - const bool isNowActive = (surfaceMaterialMapping.m_materialInstance != nullptr); + // Handle default material first + auto& defaultMaterial = m_configuration.m_defaultSurfaceMaterial; - if (wasPreviouslyActive) - { - anyMaterialWasAlreadyActive = true; - } + const bool wasPreviouslyActive = defaultMaterial.m_active; + defaultMaterial.m_active = (defaultMaterial.m_materialInstance != nullptr); - if (isNowActive) - { - anyMaterialIsActive = true; - } - - surfaceMaterialMapping.m_active = isNowActive; - - if (!wasPreviouslyActive && !isNowActive) + anyMaterialWasAlreadyActive = wasPreviouslyActive; + anyMaterialIsActive = defaultMaterial.m_active; + + if (!wasPreviouslyActive && !defaultMaterial.m_active) { // A material has been assigned but has not yet completed loading. } - else if (!wasPreviouslyActive && isNowActive) + else if (!wasPreviouslyActive && defaultMaterial.m_active) + { + TerrainAreaMaterialNotificationBus::Broadcast( + &TerrainAreaMaterialNotificationBus::Events::OnTerrainDefaultSurfaceMaterialCreated, GetEntityId(), + defaultMaterial.m_materialInstance); + defaultMaterial.m_previousChangeId = defaultMaterial.m_materialInstance->GetCurrentChangeId(); + } + else if (wasPreviouslyActive && !defaultMaterial.m_active) + { + // Don't disconnect from the AssetBus if this material is mapped more than once. + if (CountMaterialIdInstances(defaultMaterial.m_activeMaterialAssetId) == 1) + { + AZ::Data::AssetBus::MultiHandler::BusDisconnect(defaultMaterial.m_activeMaterialAssetId); + } + defaultMaterial = {}; + + TerrainAreaMaterialNotificationBus::Broadcast( + &TerrainAreaMaterialNotificationBus::Events::OnTerrainDefaultSurfaceMaterialDestroyed, GetEntityId()); + } + else if (defaultMaterial.m_materialInstance->GetAssetId() != defaultMaterial.m_activeMaterialAssetId || + defaultMaterial.m_materialInstance->GetCurrentChangeId() != defaultMaterial.m_previousChangeId) + { + defaultMaterial.m_previousChangeId = defaultMaterial.m_materialInstance->GetCurrentChangeId(); + defaultMaterial.m_activeMaterialAssetId = defaultMaterial.m_materialInstance->GetAssetId(); + + TerrainAreaMaterialNotificationBus::Broadcast( + &TerrainAreaMaterialNotificationBus::Events::OnTerrainDefaultSurfaceMaterialChanged, GetEntityId(), defaultMaterial.m_materialInstance); + } + } + + for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials) + { + const bool wasPreviouslyActive = surfaceMaterialMapping.m_active; + surfaceMaterialMapping.m_active = surfaceMaterialMapping.m_materialInstance != nullptr; + + anyMaterialWasAlreadyActive = anyMaterialWasAlreadyActive || wasPreviouslyActive; + anyMaterialIsActive = anyMaterialIsActive || surfaceMaterialMapping.m_active; + + if (!wasPreviouslyActive && !surfaceMaterialMapping.m_active) + { + // A material has been assigned but has not yet completed loading. + } + else if (!wasPreviouslyActive && surfaceMaterialMapping.m_active) { // Remember the asset id so we can disconnect from the AssetBus if the material asset is removed. surfaceMaterialMapping.m_activeMaterialAssetId = surfaceMaterialMapping.m_materialAsset.GetId(); @@ -199,27 +272,47 @@ namespace Terrain &TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingCreated, GetEntityId(), surfaceMaterialMapping.m_surfaceTag, surfaceMaterialMapping.m_materialInstance); + + surfaceMaterialMapping.m_previousChangeId = surfaceMaterialMapping.m_materialInstance->GetCurrentChangeId(); + surfaceMaterialMapping.m_previousTag = surfaceMaterialMapping.m_surfaceTag; } - else if (wasPreviouslyActive && !isNowActive) + else if (wasPreviouslyActive && !surfaceMaterialMapping.m_active) { // Don't disconnect from the AssetBus if this material is mapped more than once. - if (CountMaterialIDInstances(surfaceMaterialMapping.m_activeMaterialAssetId) == 1) + if (CountMaterialIdInstances(surfaceMaterialMapping.m_activeMaterialAssetId) == 1) { AZ::Data::AssetBus::MultiHandler::BusDisconnect(surfaceMaterialMapping.m_activeMaterialAssetId); } - surfaceMaterialMapping.m_activeMaterialAssetId = AZ::Data::AssetId(); + surfaceMaterialMapping.m_activeMaterialAssetId = {}; + surfaceMaterialMapping.m_previousChangeId = AZ::RPI::Material::DEFAULT_CHANGE_ID; + surfaceMaterialMapping.m_previousTag = {}; TerrainAreaMaterialNotificationBus::Broadcast( &TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingDestroyed, GetEntityId(), surfaceMaterialMapping.m_surfaceTag); } - else + else { - TerrainAreaMaterialNotificationBus::Broadcast( - &TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingChanged, GetEntityId(), - surfaceMaterialMapping.m_surfaceTag, - surfaceMaterialMapping.m_materialInstance); + if (surfaceMaterialMapping.m_previousTag != surfaceMaterialMapping.m_surfaceTag) + { + TerrainAreaMaterialNotificationBus::Broadcast( + &TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingTagChanged, GetEntityId(), + surfaceMaterialMapping.m_previousTag, + surfaceMaterialMapping.m_surfaceTag); + surfaceMaterialMapping.m_previousTag = surfaceMaterialMapping.m_surfaceTag; + } + if (surfaceMaterialMapping.m_materialInstance->GetAssetId() != surfaceMaterialMapping.m_activeMaterialAssetId || + surfaceMaterialMapping.m_materialInstance->GetCurrentChangeId() != surfaceMaterialMapping.m_previousChangeId) + { + surfaceMaterialMapping.m_previousChangeId = surfaceMaterialMapping.m_materialInstance->GetCurrentChangeId(); + surfaceMaterialMapping.m_activeMaterialAssetId = surfaceMaterialMapping.m_materialInstance->GetAssetId(); + + TerrainAreaMaterialNotificationBus::Broadcast( + &TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingMaterialChanged, GetEntityId(), + surfaceMaterialMapping.m_surfaceTag, + surfaceMaterialMapping.m_materialInstance); + } } } @@ -290,14 +383,28 @@ namespace Terrain void TerrainSurfaceMaterialsListComponent::OnAssetReady(AZ::Data::Asset asset) { // Find the missing material instance with the correct id. - for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials) + auto checkUpdateMaterialAsset = [](TerrainSurfaceMaterialMapping& mapping, const AZ::Data::Asset& asset) -> bool { - if (surfaceMaterialMapping.m_materialAsset.GetId() == asset.GetId() && - (!surfaceMaterialMapping.m_materialInstance || - surfaceMaterialMapping.m_materialInstance->GetAssetId() != surfaceMaterialMapping.m_materialAsset.GetId())) + if (mapping.m_materialAsset.GetId() == asset.GetId() && + (!mapping.m_materialInstance || mapping.m_materialInstance->GetAssetId() != mapping.m_materialAsset.GetId())) { - surfaceMaterialMapping.m_materialInstance = AZ::RPI::Material::FindOrCreate(surfaceMaterialMapping.m_materialAsset); - surfaceMaterialMapping.m_materialAsset.Release(); + mapping.m_materialInstance = AZ::RPI::Material::FindOrCreate(mapping.m_materialAsset); + mapping.m_materialAsset.Release(); + return true; + } + return false; + }; + + // First check the default material + if (!checkUpdateMaterialAsset(m_configuration.m_defaultSurfaceMaterial, asset)) + { + // If the default materail wasn't updated, then check all the surface material mappings. + for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials) + { + if (checkUpdateMaterialAsset(surfaceMaterialMapping, asset)) + { + break; + } } } HandleMaterialStateChanges(); diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h index 0e32cb12c0..96a7da60de 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h +++ b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h @@ -8,15 +8,18 @@ #pragma once -#include -#include #include #include +#include + +#include +#include + #include + #include #include - namespace LmbrCentral { template @@ -27,16 +30,20 @@ namespace Terrain { struct TerrainSurfaceMaterialMapping final { - public: AZ_CLASS_ALLOCATOR(TerrainSurfaceMaterialMapping, AZ::SystemAllocator, 0); AZ_RTTI(TerrainSurfaceMaterialMapping, "{37D2A586-CDDD-4FB7-A7D6-0B4CC575AB8C}"); static void Reflect(AZ::ReflectContext* context); - SurfaceData::SurfaceTag m_surfaceTag; - AZ::Data::AssetId m_activeMaterialAssetId; AZ::Data::Asset m_materialAsset; AZ::Data::Instance m_materialInstance; + AZ::Data::AssetId m_activeMaterialAssetId; + AZ::RPI::Material::ChangeId m_previousChangeId = AZ::RPI::Material::DEFAULT_CHANGE_ID; + + // Surface tags not used by default material + SurfaceData::SurfaceTag m_surfaceTag; + SurfaceData::SurfaceTag m_previousTag; + bool m_active = false; }; @@ -47,7 +54,13 @@ namespace Terrain AZ_RTTI(TerrainSurfaceMaterialsListConfig, "{68A1CB1B-C835-4C3A-8D1C-08692E07711A}", AZ::ComponentConfig); static void Reflect(AZ::ReflectContext* context); + TerrainSurfaceMaterialsListConfig(); + + TerrainSurfaceMaterialMapping m_defaultSurfaceMaterial; AZStd::vector m_surfaceMaterials; + private: + static const AZ::Edit::ElementData* GetDynamicData(const void* handlerPtr, const void* elementPtr, const AZ::Uuid& elementType); + AZ::Edit::ElementData m_hideSurfaceTagData; }; class TerrainSurfaceMaterialsListComponent @@ -78,7 +91,7 @@ namespace Terrain private: void HandleMaterialStateChanges(); - int CountMaterialIDInstances(AZ::Data::AssetId id) const; + int CountMaterialIdInstances(AZ::Data::AssetId id) const; //////////////////////////////////////////////////////////////////////// // ShapeComponentNotificationsBus diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainAreaMaterialRequestBus.h b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainAreaMaterialRequestBus.h index ae36a2639e..a2225702ef 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainAreaMaterialRequestBus.h +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainAreaMaterialRequestBus.h @@ -45,6 +45,27 @@ namespace Terrain static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; ////////////////////////////////////////////////////////////////////////// + //! The default surface material has been assigned and loaded + virtual void OnTerrainDefaultSurfaceMaterialCreated( + [[maybe_unused]] AZ::EntityId entityId, + [[maybe_unused]] AZ::Data::Instance material) + { + } + + //! The default surface material has been unassigned + virtual void OnTerrainDefaultSurfaceMaterialDestroyed( + [[maybe_unused]] AZ::EntityId entityId) + { + } + + //! The default surface material has been changed to a different material + virtual void OnTerrainDefaultSurfaceMaterialChanged( + [[maybe_unused]] AZ::EntityId entityId, + [[maybe_unused]] AZ::Data::Instance newMaterial) + { + } + + //! A loaded material mapped to a valid surface tag has been created virtual void OnTerrainSurfaceMaterialMappingCreated( [[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] SurfaceData::SurfaceTag surface, @@ -52,19 +73,30 @@ namespace Terrain { } + //! Either the material or surface tag was unassigned, making this mapping invalid virtual void OnTerrainSurfaceMaterialMappingDestroyed( [[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] SurfaceData::SurfaceTag surface) { } - virtual void OnTerrainSurfaceMaterialMappingChanged( + //! The surface tag has changed to tag for an existing material + virtual void OnTerrainSurfaceMaterialMappingTagChanged( + [[maybe_unused]] AZ::EntityId entityId, + [[maybe_unused]] SurfaceData::SurfaceTag oldSurface, + [[maybe_unused]] SurfaceData::SurfaceTag newSurface) + { + } + + //! The material has changed for an existing surface tag + virtual void OnTerrainSurfaceMaterialMappingMaterialChanged( [[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] SurfaceData::SurfaceTag surface, [[maybe_unused]] AZ::Data::Instance material) { } + //! The bounds of this set of surface material mappings has changed virtual void OnTerrainSurfaceMaterialMappingRegionChanged( [[maybe_unused]] AZ::EntityId entityId, [[maybe_unused]] const AZ::Aabb& oldRegion, diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.cpp index a00d2efe59..f817c138a7 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.cpp +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.cpp @@ -106,6 +106,8 @@ namespace Terrain return; } + InitializePassthroughDetailMaterial(); + ClipmapBoundsDescriptor desc; desc.m_clipmapUpdateMultiple = 1; desc.m_clipToWorldScale = DetailTextureScale; @@ -260,20 +262,73 @@ namespace Terrain m_dirtyDetailRegion.AddAabb(dirtyRegion); } } + + bool TerrainDetailMaterialManager::ForSurfaceTag(DetailMaterialListRegion& materialRegion, + SurfaceData::SurfaceTag surfaceTag, DefaultMaterialSurfaceCallback callback) + { + for (DetailMaterialSurface& surface : materialRegion.m_materialsForSurfaces) + { + if (surface.m_surfaceTag == surfaceTag) + { + callback(surface); + return true; + } + } + return false; + } + void TerrainDetailMaterialManager::OnTerrainDefaultSurfaceMaterialCreated(AZ::EntityId entityId, MaterialInstance material) + { + DetailMaterialListRegion& materialRegion = FindOrCreateByEntityId(entityId, m_detailMaterialRegions); + AZ_Error("TerrainDetailMaterialManager", materialRegion.m_defaultDetailMaterialId == InvalidDetailMaterailId, + "Default detail material created but was already set for this region."); + + materialRegion.m_defaultDetailMaterialId = CreateOrUpdateDetailMaterial(material); + m_detailMaterials.GetData(materialRegion.m_defaultDetailMaterialId).refCount++; + m_dirtyDetailRegion.AddAabb(materialRegion.m_region); + } + + void TerrainDetailMaterialManager::OnTerrainDefaultSurfaceMaterialDestroyed(AZ::EntityId entityId) + { + DetailMaterialListRegion* materialRegion = FindByEntityId(entityId, m_detailMaterialRegions); + if (materialRegion == nullptr) + { + AZ_Assert(false, "OnTerrainDefaultSurfaceMaterialDestroyed() called for region that doesn't exist."); + return; + } + + CheckDetailMaterialForDeletion(materialRegion->m_defaultDetailMaterialId); + materialRegion->m_defaultDetailMaterialId = InvalidDetailMaterailId; + } + + void TerrainDetailMaterialManager::OnTerrainDefaultSurfaceMaterialChanged(AZ::EntityId entityId, MaterialInstance newMaterial) + { + DetailMaterialListRegion* materialRegion = FindByEntityId(entityId, m_detailMaterialRegions); + if (materialRegion == nullptr) + { + AZ_Assert(false, "OnTerrainDefaultSurfaceMaterialChanged() called for region that doesn't exist."); + return; + } + + // Update existing entry or create a new material entry + uint16_t materialId = CreateOrUpdateDetailMaterial(newMaterial); + if (materialRegion->m_defaultDetailMaterialId != materialId) + { + ++m_detailMaterials.GetData(materialId).refCount; + CheckDetailMaterialForDeletion(materialRegion->m_defaultDetailMaterialId); + materialRegion->m_defaultDetailMaterialId = materialId; + } + } + void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingCreated(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material) { DetailMaterialListRegion& materialRegion = FindOrCreateByEntityId(entityId, m_detailMaterialRegions); // Validate that the surface tag is new - for (DetailMaterialSurface& surface : materialRegion.m_materialsForSurfaces) + ForSurfaceTag(materialRegion, surfaceTag, [](DetailMaterialSurface&) { - if (surface.m_surfaceTag == surfaceTag) - { - AZ_Error(TerrainDetailMaterialManagerName, false, "Already have a surface material mapping for this surface tag."); - return; - } - } + AZ_Error(TerrainDetailMaterialManagerName, false, "Already have a surface material mapping for this surface tag."); + }); uint16_t detailMaterialId = CreateOrUpdateDetailMaterial(material); materialRegion.m_materialsForSurfaces.push_back({ surfaceTag, detailMaterialId }); @@ -284,52 +339,71 @@ namespace Terrain void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingDestroyed(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag) { DetailMaterialListRegion& materialRegion = FindOrCreateByEntityId(entityId, m_detailMaterialRegions); - - for (DetailMaterialSurface& surface : materialRegion.m_materialsForSurfaces) + + [[maybe_unused]] bool found = ForSurfaceTag(materialRegion, surfaceTag, + [&](DetailMaterialSurface& surface) { - if (surface.m_surfaceTag == surfaceTag) - { - CheckDetailMaterialForDeletion(surface.m_detailMaterialId); + CheckDetailMaterialForDeletion(surface.m_detailMaterialId); - if (surface.m_surfaceTag != materialRegion.m_materialsForSurfaces.back().m_surfaceTag) - { - AZStd::swap(surface, materialRegion.m_materialsForSurfaces.back()); - } - materialRegion.m_materialsForSurfaces.pop_back(); - m_dirtyDetailRegion.AddAabb(materialRegion.m_region); - return; + if (surface.m_surfaceTag != materialRegion.m_materialsForSurfaces.back().m_surfaceTag) + { + AZStd::swap(surface, materialRegion.m_materialsForSurfaces.back()); } + materialRegion.m_materialsForSurfaces.pop_back(); + m_dirtyDetailRegion.AddAabb(materialRegion.m_region); + return; + }); + + AZ_Error(TerrainDetailMaterialManagerName, found, "Could not find surface tag to destroy for OnTerrainSurfaceMaterialMappingDestroyed()."); + } + + void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingMaterialChanged( + AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material) + { + DetailMaterialListRegion* materialRegion = FindByEntityId(entityId, m_detailMaterialRegions); + if (materialRegion == nullptr) + { + AZ_Assert(false, "OnTerrainSurfaceMaterialMappingMaterialChanged() called for region that doesn't exist."); + return; } - AZ_Error(TerrainDetailMaterialManagerName, false, "Could not find surface tag to destroy for OnTerrainSurfaceMaterialMappingDestroyed()."); + + // Update existing entry or create a new material entry + uint16_t materialId = CreateOrUpdateDetailMaterial(material); + + [[maybe_unused]] bool found = ForSurfaceTag(*materialRegion, surfaceTag, + [&](DetailMaterialSurface& surface) + { + if (surface.m_detailMaterialId != materialId) + { + // Updated material was a different asset than the old material, decrement ref count and + // delete if no other surface tags are using it. + ++m_detailMaterials.GetData(materialId).refCount; + CheckDetailMaterialForDeletion(surface.m_detailMaterialId); + surface.m_detailMaterialId = materialId; + } + m_dirtyDetailRegion.AddAabb(materialRegion->m_region); + }); + + AZ_Assert(found, "OnTerrainSurfaceMaterialMappingMaterialChanged() called for tag that doesn't exist."); } - void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingChanged(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material) + void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingTagChanged( + AZ::EntityId entityId, SurfaceData::SurfaceTag oldTag, SurfaceData::SurfaceTag newTag) { - DetailMaterialListRegion& materialRegion = FindOrCreateByEntityId(entityId, m_detailMaterialRegions); - - bool found = false; - uint16_t materialId = CreateOrUpdateDetailMaterial(material); - for (DetailMaterialSurface& surface : materialRegion.m_materialsForSurfaces) + DetailMaterialListRegion* materialRegion = FindByEntityId(entityId, m_detailMaterialRegions); + if (materialRegion == nullptr) { - if (surface.m_surfaceTag == surfaceTag) - { - found = true; - if (surface.m_detailMaterialId != materialId) - { - ++m_detailMaterials.GetData(materialId).refCount; - CheckDetailMaterialForDeletion(surface.m_detailMaterialId); - surface.m_detailMaterialId = materialId; - } - break; - } + AZ_Assert(false, "OnTerrainSurfaceMaterialMappingTagChanged() called for region that doesn't exist."); + return; } - - if (!found) + + [[maybe_unused]] bool found = ForSurfaceTag(*materialRegion, oldTag, + [&](DetailMaterialSurface& surface) { - ++m_detailMaterials.GetData(materialId).refCount; - materialRegion.m_materialsForSurfaces.push_back({ surfaceTag, materialId }); - } - m_dirtyDetailRegion.AddAabb(materialRegion.m_region); + surface.m_surfaceTag = newTag; + m_dirtyDetailRegion.AddAabb(materialRegion->m_region); + }); + AZ_Assert(found, "OnTerrainSurfaceMaterialMappingTagChanged() called for tag that doesn't exist."); } void TerrainDetailMaterialManager::OnTerrainSurfaceMaterialMappingRegionChanged(AZ::EntityId entityId, const AZ::Aabb& oldRegion, const AZ::Aabb& newRegion) @@ -667,23 +741,38 @@ namespace Terrain bool isFirstMaterial = true; float firstWeight = 0.0f; AZ::Vector2 position(surfacePoint.m_position.GetX(), surfacePoint.m_position.GetY()); + const DetailMaterialListRegion* region = FindRegionForPosition(position); + + if (region == nullptr) + { + pixels.at(index).m_material1 = m_passthroughMaterialId; + ++index; + return; + } + for (const auto& surfaceTagWeight : surfacePoint.m_surfaceTags) { if (surfaceTagWeight.m_weight > 0.0f) { AZ::Crc32 surfaceType = surfaceTagWeight.m_surfaceType; - uint16_t materialId = GetDetailMaterialForSurfaceTypeAndPosition(surfaceType, position); - if (materialId != m_detailMaterials.NoFreeSlot && materialId < 255) + uint16_t materialId = GetDetailMaterialForSurfaceType(*region, surfaceType); + if (materialId < 255) { if (isFirstMaterial) { + // First material is valid. Save its weight to calculate blend later pixels.at(index).m_material1 = aznumeric_cast(materialId); firstWeight = surfaceTagWeight.m_weight; - // m_blend only needs to be calculated is material 2 is found, otherwise the initial value of 0 is correct. isFirstMaterial = false; + static constexpr float MaxValueBeforeRounding = 254.5f / 255.0f; + if (firstWeight >= MaxValueBeforeRounding) + { + break; + } } else { + // Second material is valid, weight is relative based on first material's weight. pixels.at(index).m_material2 = aznumeric_cast(materialId); float totalWeight = firstWeight + surfaceTagWeight.m_weight; float blendWeight = 1.0f - (firstWeight / totalWeight); @@ -691,11 +780,37 @@ namespace Terrain break; } } + continue; // search for second material } else { - break; // since the list is ordered, no other materials are in the list with positive weights. + // No more valid materials in list since surfaceTagWeight is ordered. + + uint8_t defaultMaterial = region->m_defaultDetailMaterialId == InvalidDetailMaterailId ? m_passthroughMaterialId : + aznumeric_cast(m_detailMaterials.GetData(region->m_defaultDetailMaterialId).m_detailMaterialBufferIndex); + + if (isFirstMaterial) + { + // Only one material and it's the default material. + pixels.at(index).m_material1 = defaultMaterial; + } + else + { + // Second material is default, weight is exactly what the first material requested + pixels.at(index).m_material2 = defaultMaterial; + float blendWeight = 1.0f - AZStd::clamp(firstWeight, 0.0f, 1.0f); + pixels.at(index).m_blend = aznumeric_cast(AZStd::round(blendWeight * 255.0f)); + } } + + if (pixels.at(index).m_material1 == pixels.at(index).m_material2) + { + // If the materials are the same, then make the blend 100% on the first id so the shader + // doesn't blend identical materials + pixels.at(index).m_blend = 0; + } + + break; } ++index; }; @@ -723,23 +838,37 @@ namespace Terrain m_detailTextureImage->UpdateImageContents(imageUpdateRequest); } - - uint16_t TerrainDetailMaterialManager::GetDetailMaterialForSurfaceTypeAndPosition(AZ::Crc32 surfaceType, const AZ::Vector2& position) + + uint16_t TerrainDetailMaterialManager::GetDetailMaterialForSurfaceType(const DetailMaterialListRegion& materialRegion, AZ::Crc32 surfaceType) const + { + for (const auto& materialSurface : materialRegion.m_materialsForSurfaces) + { + if (materialSurface.m_surfaceTag == surfaceType) + { + return m_detailMaterials.GetData(materialSurface.m_detailMaterialId).m_detailMaterialBufferIndex; + } + } + return InvalidDetailMaterailId; + } + + auto TerrainDetailMaterialManager::FindRegionForPosition(const AZ::Vector2& position) const -> const DetailMaterialListRegion* { for (const auto& materialRegion : m_detailMaterialRegions.GetDataVector()) { if (materialRegion.m_region.Contains(AZ::Vector3(position.GetX(), position.GetY(), 0.0f))) { - for (const auto& materialSurface : materialRegion.m_materialsForSurfaces) - { - if (materialSurface.m_surfaceTag == surfaceType) - { - return m_detailMaterials.GetData(materialSurface.m_detailMaterialId).m_detailMaterialBufferIndex; - } - } + return &materialRegion; } } - return m_detailMaterials.NoFreeSlot; + return nullptr; + } + + void TerrainDetailMaterialManager::InitializePassthroughDetailMaterial() + { + m_passthroughMaterialId = aznumeric_cast(m_detailMaterialShaderData.Reserve()); + DetailMaterialShaderData& materialShaderData = m_detailMaterialShaderData.GetElement(m_passthroughMaterialId); + // Material defaults to white (1.0, 1.0, 1.0), set the blend mode to multiply so it passes through to the macro material. + materialShaderData.m_flags = DetailTextureFlags::BlendModeMultiply; } auto TerrainDetailMaterialManager::FindByEntityId(AZ::EntityId entityId, AZ::Render::IndexedDataVector& container) @@ -784,5 +913,5 @@ namespace Terrain } AZ_Assert(false, "Entity Id not found in container.") } - + } diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.h b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.h index 3f63812e47..16423251ec 100644 --- a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.h +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainDetailMaterialManager.h @@ -11,6 +11,7 @@ #include #include #include +#include #include @@ -151,7 +152,11 @@ namespace Terrain AZ::EntityId m_entityId; AZ::Aabb m_region{AZ::Aabb::CreateNull()}; AZStd::vector m_materialsForSurfaces; + uint16_t m_defaultDetailMaterialId; }; + + using DetailMaterialContainer = AZ::Render::IndexedDataVector; + static constexpr auto InvalidDetailMaterailId = DetailMaterialContainer::NoFreeSlot; // System-level parameters static constexpr int32_t DetailTextureSize{ 1024 }; @@ -162,9 +167,14 @@ namespace Terrain void OnTerrainDataChanged(const AZ::Aabb& dirtyRegion, TerrainDataChangedMask dataChangedMask) override; // TerrainAreaMaterialNotificationBus overrides... + void OnTerrainDefaultSurfaceMaterialCreated(AZ::EntityId entityId, AZ::Data::Instance material) override; + void OnTerrainDefaultSurfaceMaterialDestroyed(AZ::EntityId entityId) override; + void OnTerrainDefaultSurfaceMaterialChanged(AZ::EntityId entityId, AZ::Data::Instance newMaterial) override; void OnTerrainSurfaceMaterialMappingCreated(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material) override; void OnTerrainSurfaceMaterialMappingDestroyed(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag) override; - void OnTerrainSurfaceMaterialMappingChanged(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material) override; + void OnTerrainSurfaceMaterialMappingMaterialChanged(AZ::EntityId entityId, SurfaceData::SurfaceTag surfaceTag, MaterialInstance material) override; + void OnTerrainSurfaceMaterialMappingTagChanged( + AZ::EntityId entityId, SurfaceData::SurfaceTag oldSurfaceTag, SurfaceData::SurfaceTag newSurfaceTag) override; void OnTerrainSurfaceMaterialMappingRegionChanged(AZ::EntityId entityId, const AZ::Aabb& oldRegion, const AZ::Aabb& newRegion) override; //! Removes all images from all detail materials from the bindless image array @@ -186,22 +196,32 @@ namespace Terrain //! Updates the detail texture in a given area void UpdateDetailTexture(const AZ::Aabb& worldUpdateAabb, const Aabb2i& textureUpdateAabb); - //! Finds the detail material Id for a surface type and position - uint16_t GetDetailMaterialForSurfaceTypeAndPosition(AZ::Crc32 surfaceType, const AZ::Vector2& position); + //! Finds the detail material Id for a region and surface type + uint16_t GetDetailMaterialForSurfaceType(const DetailMaterialListRegion& materialRegion, AZ::Crc32 surfaceType) const; + //! Finds a region for a position. Returns nullptr if none found. + const DetailMaterialListRegion* FindRegionForPosition(const AZ::Vector2& position) const; + + //! Initializes shader data for the default passthrough material which is used when no other detail material is found. + void InitializePassthroughDetailMaterial(); + + using DefaultMaterialSurfaceCallback = AZStd::function; + bool ForSurfaceTag(DetailMaterialListRegion& materialRegion, + SurfaceData::SurfaceTag surfaceTag, DefaultMaterialSurfaceCallback callback); DetailMaterialListRegion* FindByEntityId(AZ::EntityId entityId, AZ::Render::IndexedDataVector& container); DetailMaterialListRegion& FindOrCreateByEntityId(AZ::EntityId entityId, AZ::Render::IndexedDataVector& container); void RemoveByEntityId(AZ::EntityId entityId, AZ::Render::IndexedDataVector& container); - + AZStd::shared_ptr m_bindlessImageHandler; AZ::Data::Instance m_detailTextureImage; - AZ::Render::IndexedDataVector m_detailMaterials; + DetailMaterialContainer m_detailMaterials; AZ::Render::IndexedDataVector m_detailMaterialRegions; AZ::Render::SparseVector m_detailMaterialShaderData; AZ::Render::GpuBufferHandler m_detailMaterialDataBuffer; - + uint8_t m_passthroughMaterialId = 0; + AZ::Aabb m_dirtyDetailRegion{ AZ::Aabb::CreateNull() }; ClipmapBounds m_detailMaterialIdBounds; @@ -212,6 +232,6 @@ namespace Terrain bool m_isInitialized{ false }; bool m_detailMaterialBufferNeedsUpdate{ false }; bool m_detailImageNeedsUpdate{ false }; - + }; } From 5ef2b12dca45b5ca396cf55de747c5ad4b27fe65 Mon Sep 17 00:00:00 2001 From: evanchia-ly-sdets <80914607+evanchia-ly-sdets@users.noreply.github.com> Date: Wed, 9 Feb 2022 18:13:01 -0800 Subject: [PATCH 15/27] Collects failed assets on LyTestTools test failures (#7368) * Collects failed assets on LyTestTools test failures Signed-off-by: evanchia * Changed query to all lines because of current asset logging bug Signed-off-by: evanchia * fixes per pr feedback Signed-off-by: evanchia * testing removing change for AR failure Signed-off-by: evanchia * Moved asset log artifact collection to after the results have been collected Signed-off-by: evanchia * Adding debug line to help debug AR failure Signed-off-by: evanchia * Made asset log collection non failing Signed-off-by: evanchia * moved asset log collection after test result collection Signed-off-by: evanchia * changed asset saving to non failing Signed-off-by: evanchia * improved logging and comments Signed-off-by: evanchia --- .../managers/abstract_resource_locator.py | 9 ++- .../ly_test_tools/o3de/editor_test.py | 24 +++++++- .../ly_test_tools/o3de/editor_test_utils.py | 39 +++++++++++++ .../tests/unit/test_editor_test_utils.py | 56 +++++++++++++++++++ .../tests/unit/test_o3de_editor_test.py | 7 +++ 5 files changed, 132 insertions(+), 3 deletions(-) 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 4514e5d812..6e0923b916 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 @@ -175,13 +175,20 @@ class AbstractResourceLocator(object): return os.path.join(self.build_directory(), 'AssetProcessor') def asset_processor_batch(self): - """" + """ Return path for the AssetProcessorBatch compatible with this build platform and configuration ex. engine_root/dev/mac/bin/profile/AssetProcessorBatch :return: path to AssetProcessorBatch """ return os.path.join(self.build_directory(), 'AssetProcessorBatch') + def ap_job_logs(self): + """ + Return path to the Asset Processor JobLogs directory. + :return: path to /user/log/JobLogs + """ + return os.path.join(self.project_log(), 'JobLogs') + def editor(self): """ Return path to the editor executable compatible with the current build. diff --git a/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py b/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py index f363689066..3c4e2b49a4 100644 --- a/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/editor_test.py @@ -851,11 +851,11 @@ class EditorTestSuite(): workspace.artifact_manager.save_artifact(os.path.join(editor_utils.retrieve_log_path(run_id, workspace), log_name), f'({run_id}){log_name}') if return_code == 0: - # No need to scrap the output, as all the tests have passed + # No need to scrape the output, as all the tests have passed for test_spec in test_spec_list: results[test_spec.__name__] = Result.Pass.create(test_spec, output, editor_log_content) else: - # Scrap the output to attempt to find out which tests failed. + # Scrape the output to attempt to find out which tests failed. # This function should always populate the result list, if it didn't find it, it will have "Unknown" type of result results = self._get_results_using_output(test_spec_list, output, editor_log_content) assert len(results) == len(test_spec_list), "bug in _get_results_using_output(), the number of results don't match the tests ran" @@ -940,6 +940,9 @@ class EditorTestSuite(): editor_test_data.results.update(results) test_name, test_result = next(iter(results.items())) self._report_result(test_name, test_result) + # If test did not pass, save assets with errors and warnings + if not isinstance(test_result, Result.Pass): + editor_utils.save_failed_asset_joblogs(workspace) def _run_batched_tests(self, request: Request, workspace: AbstractWorkspace, editor: Editor, editor_test_data: TestData, test_spec_list: list[EditorSharedTest], extra_cmdline_args: list[str] = []) -> None: @@ -961,6 +964,11 @@ class EditorTestSuite(): extra_cmdline_args) assert results is not None editor_test_data.results.update(results) + # If at least one test did not pass, save assets with errors and warnings + for result in results: + if not isinstance(result, Result.Pass): + editor_utils.save_failed_asset_joblogs(workspace) + return def _run_parallel_tests(self, request: Request, workspace: AbstractWorkspace, editor: Editor, editor_test_data: TestData, test_spec_list: list[EditorSharedTest], extra_cmdline_args: list[str] = []) -> None: @@ -1007,8 +1015,14 @@ class EditorTestSuite(): for t in threads: t.join() + save_asset_logs = False for result in results_per_thread: editor_test_data.results.update(result) + if not isinstance(result, Result.Pass): + save_asset_logs = True + # If at least one test did not pass, save assets with errors and warnings + if save_asset_logs: + editor_utils.save_failed_asset_joblogs(workspace) def _run_parallel_batched_tests(self, request: Request, workspace: AbstractWorkspace, editor: Editor, editor_test_data: TestData, test_spec_list: list[EditorSharedTest], extra_cmdline_args: list[str] = []) -> None: @@ -1056,8 +1070,14 @@ class EditorTestSuite(): for t in threads: t.join() + save_asset_logs = False for result in results_per_thread: editor_test_data.results.update(result) + if not isinstance(result, Result.Pass): + save_asset_logs = True + # If at least one test did not pass, save assets with errors and warnings + if save_asset_logs: + editor_utils.save_failed_asset_joblogs(workspace) def _get_number_parallel_editors(self, request: Request) -> int: """ diff --git a/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py b/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py index 7b36a82c07..4e678151bd 100644 --- a/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py +++ b/Tools/LyTestTools/ly_test_tools/o3de/editor_test_utils.py @@ -10,6 +10,7 @@ from __future__ import annotations import os import time import logging +import re import ly_test_tools.environment.process_utils as process_utils import ly_test_tools.environment.waiter as waiter @@ -151,3 +152,41 @@ def retrieve_last_run_test_index_from_output(test_spec_list: list[EditorTestBase else: index += 1 return index + +def save_failed_asset_joblogs(workspace: AbstractWorkspace) -> None: + """ + Checks all asset logs in the JobLogs directory to see if the asset has any warnings or errors. If so, the asset is + saved via ArtifactManager. + + :param workspace: The AbstractWorkspace to access the JobLogs path + :return: None + """ + for walk_tuple in os.walk(workspace.paths.ap_job_logs()): + for log_file in walk_tuple[2]: + full_log_path = os.path.join(walk_tuple[0], log_file) + # Only save asset logs that contain errors or warnings + if _check_log_errors_warnings(full_log_path): + try: + workspace.artifact_manager.save_artifact(full_log_path) + except Exception as e: # Purposefully broad + logger.warning(f"Error when saving log at path:{full_log_path}\n{e}") + +def _check_log_errors_warnings(log_path: str) -> bool: + """ + Checks to see if the asset log contains any errors or warnings. Also returns True is no regex is found because + something probably went wrong. + Example log lines: ~~1643759303647~~1~~00000000000009E0~~AssetBuilder~~S: 0 errors, 1 warnings + + :param log_path: The full path to the asset log file to read + :return: True if the regex finds an error or warning, else False + """ + log_regex = "(\\d+) errors, (\\d+) warnings" + with open(log_path, 'r') as opened_asset_log: + for log_line in opened_asset_log: + regex_match = re.search(log_regex, log_line) + if regex_match is not None: + break + # If we match any non zero numbers in: n error, n warnings + if regex_match is None or (int)(regex_match.group(1)) != 0 or (int)(regex_match.group(2)) != 0: + return True + return False diff --git a/Tools/LyTestTools/tests/unit/test_editor_test_utils.py b/Tools/LyTestTools/tests/unit/test_editor_test_utils.py index f81d2fd8e6..cca9a161c8 100644 --- a/Tools/LyTestTools/tests/unit/test_editor_test_utils.py +++ b/Tools/LyTestTools/tests/unit/test_editor_test_utils.py @@ -170,3 +170,59 @@ class TestEditorTestUtils(unittest.TestCase): mock_test_list.append(mock_test) assert 0 == editor_test_utils.retrieve_last_run_test_index_from_output(mock_test_list, mock_editor_output) + + @mock.patch('ly_test_tools.o3de.editor_test_utils._check_log_errors_warnings') + @mock.patch('os.walk') + def test_SaveFailedAssetJoblogs_ManyValidLogs_SavesCorrectly(self, mock_walk, mock_check_log): + mock_workspace = mock.MagicMock() + mock_walk.return_value = [['MockDirectory', None, ['mock_log.log']], + ['MockDirectory2', None, ['mock_log2.log']]] + mock_check_log.return_value = True + + editor_test_utils.save_failed_asset_joblogs(mock_workspace) + + assert mock_workspace.artifact_manager.save_artifact.call_count == 2 + + @mock.patch('ly_test_tools.o3de.editor_test_utils._check_log_errors_warnings') + @mock.patch('os.walk') + def test_SaveFailedAssetJoblogs_ManyInvalidLogs_NoSaves(self, mock_walk, mock_check_log): + mock_workspace = mock.MagicMock() + mock_walk.return_value = [['MockDirectory', None, ['mock_log.log']], + ['MockDirectory2', None, ['mock_log2.log']]] + mock_check_log.return_value = False + + editor_test_utils.save_failed_asset_joblogs(mock_workspace) + + assert mock_workspace.artifact_manager.save_artifact.call_count == 0 + + def test_CheckLogErrorWarnings_ValidLine_ReturnsTrue(self): + mock_log = '~~1643759303647~~1~~00000000000009E0~~AssetBuilder~~S: 0 errors, 1 warnings' + mock_log_path = mock.MagicMock() + + with mock.patch('builtins.open', mock.mock_open(read_data=mock_log)) as mock_file: + expected = editor_test_utils._check_log_errors_warnings(mock_log_path) + assert expected + + def test_CheckLogErrorWarnings_MultipleValidLine_ReturnsTrue(self): + mock_log = 'foo\nfoo\n~~1643759303647~~1~~00000000000009E0~~AssetBuilder~~S: 1 errors, 1 warnings' + mock_log_path = mock.MagicMock() + + with mock.patch('builtins.open', mock.mock_open(read_data=mock_log)) as mock_file: + expected = editor_test_utils._check_log_errors_warnings(mock_log_path) + assert expected + + def test_CheckLogErrorWarnings_InvalidLine_ReturnsFalse(self): + mock_log = 'foo\n~~1643759303647~~1~~00000000000009E0~~AssetBuilder~~S: 0 errors, 0 warnings' + mock_log_path = mock.MagicMock() + + with mock.patch('builtins.open', mock.mock_open(read_data=mock_log)) as mock_file: + expected = editor_test_utils._check_log_errors_warnings(mock_log_path) + assert not expected + + def test_CheckLogErrorWarnings_InvalidRegex_ReturnsTrue(self): + mock_log = 'Invalid last line' + mock_log_path = mock.MagicMock() + + with mock.patch('builtins.open', mock.mock_open(read_data=mock_log)) as mock_file: + expected = editor_test_utils._check_log_errors_warnings(mock_log_path) + assert expected diff --git a/Tools/LyTestTools/tests/unit/test_o3de_editor_test.py b/Tools/LyTestTools/tests/unit/test_o3de_editor_test.py index 973366aa94..f63ec315eb 100644 --- a/Tools/LyTestTools/tests/unit/test_o3de_editor_test.py +++ b/Tools/LyTestTools/tests/unit/test_o3de_editor_test.py @@ -871,6 +871,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._report_result') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._exec_editor_test') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._setup_editor_test') + @mock.patch('ly_test_tools.o3de.editor_test_utils.save_failed_asset_joblogs', mock.MagicMock()) def test_RunSingleTest_ValidTest_ReportsResults(self, mock_setup_test, mock_exec_editor_test, mock_report_result): mock_test_suite = ly_test_tools.o3de.editor_test.EditorTestSuite() mock_test_data = mock.MagicMock() @@ -903,6 +904,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('threading.Thread') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._get_number_parallel_editors') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._setup_editor_test') + @mock.patch('ly_test_tools.o3de.editor_test_utils.save_failed_asset_joblogs', mock.MagicMock()) def test_RunParallelTests_TwoTestsAndEditors_TwoThreads(self, mock_setup_test, mock_get_num_editors, mock_thread): mock_test_suite = ly_test_tools.o3de.editor_test.EditorTestSuite() mock_get_num_editors.return_value = 2 @@ -919,6 +921,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('threading.Thread') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._get_number_parallel_editors') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._setup_editor_test') + @mock.patch('ly_test_tools.o3de.editor_test_utils.save_failed_asset_joblogs', mock.MagicMock()) def test_RunParallelTests_TenTestsAndTwoEditors_TenThreads(self, mock_setup_test, mock_get_num_editors, mock_thread): mock_test_suite = ly_test_tools.o3de.editor_test.EditorTestSuite() mock_get_num_editors.return_value = 2 @@ -937,6 +940,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('threading.Thread') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._get_number_parallel_editors') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._setup_editor_test') + @mock.patch('ly_test_tools.o3de.editor_test_utils.save_failed_asset_joblogs', mock.MagicMock()) def test_RunParallelTests_TenTestsAndThreeEditors_TenThreads(self, mock_setup_test, mock_get_num_editors, mock_thread): mock_test_suite = ly_test_tools.o3de.editor_test.EditorTestSuite() @@ -956,6 +960,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('threading.Thread') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._get_number_parallel_editors') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._setup_editor_test') + @mock.patch('ly_test_tools.o3de.editor_test_utils.save_failed_asset_joblogs', mock.MagicMock()) def test_RunParallelBatchedTests_TwoTestsAndEditors_TwoThreads(self, mock_setup_test, mock_get_num_editors, mock_thread): mock_test_suite = ly_test_tools.o3de.editor_test.EditorTestSuite() @@ -973,6 +978,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('threading.Thread') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._get_number_parallel_editors') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._setup_editor_test') + @mock.patch('ly_test_tools.o3de.editor_test_utils.save_failed_asset_joblogs', mock.MagicMock()) def test_RunParallelBatchedTests_TenTestsAndTwoEditors_2Threads(self, mock_setup_test, mock_get_num_editors, mock_thread): mock_test_suite = ly_test_tools.o3de.editor_test.EditorTestSuite() @@ -992,6 +998,7 @@ class TestRunningTests(unittest.TestCase): @mock.patch('threading.Thread') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._get_number_parallel_editors') @mock.patch('ly_test_tools.o3de.editor_test.EditorTestSuite._setup_editor_test') + @mock.patch('ly_test_tools.o3de.editor_test_utils.save_failed_asset_joblogs', mock.MagicMock()) def test_RunParallelBatchedTests_TenTestsAndThreeEditors_ThreeThreads(self, mock_setup_test, mock_get_num_editors, mock_thread): mock_test_suite = ly_test_tools.o3de.editor_test.EditorTestSuite() From 1c3a61983acf001cf0380c8dcd92eb5244475d17 Mon Sep 17 00:00:00 2001 From: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> Date: Wed, 9 Feb 2022 20:50:32 -0800 Subject: [PATCH 16/27] Refactor EditorEntityUiHandlerBaseto be explicitly Outliner-focused. This lays the groundwork for multiple widget-based handlers in the future. (#7443) Signed-off-by: Danilo Aimini <82231674+AMZN-daimini@users.noreply.github.com> --- .../EditorEntityUiHandlerBase.cpp | 10 +++++++++- .../EditorEntityUiHandlerBase.h | 20 +++++++++++-------- .../UI/Outliner/EntityOutlinerWidget.cpp | 2 +- .../UI/Prefab/LevelRootUiHandler.cpp | 13 +++++++----- .../UI/Prefab/LevelRootUiHandler.h | 2 +- .../UI/Prefab/PrefabUiHandler.cpp | 14 +++++++------ .../UI/Prefab/PrefabUiHandler.h | 2 +- 7 files changed, 40 insertions(+), 23 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.cpp index 866080a83f..4896a5af49 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.cpp @@ -7,6 +7,7 @@ */ #include +#include #include @@ -117,9 +118,16 @@ namespace AzToolsFramework { } - bool EditorEntityUiHandlerBase::OnEntityDoubleClick([[maybe_unused]] AZ::EntityId entityId) const + bool EditorEntityUiHandlerBase::OnOutlinerItemDoubleClick([[maybe_unused]] const QModelIndex& index) const { return false; } + AZ::EntityId EditorEntityUiHandlerBase::GetEntityIdFromIndex(const QModelIndex& index) + { + QModelIndex firstColumnIndex = index.siblingAtColumn(EntityOutlinerListModel::ColumnName); + + return AZ::EntityId(firstColumnIndex.data(EntityOutlinerListModel::EntityIdRole).value()); + } + } // namespace AzToolsFramework diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h index 96d393efa1..948c26d710 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/EditorEntityUi/EditorEntityUiHandlerBase.h @@ -21,7 +21,6 @@ class QTreeView; namespace AzToolsFramework { //! Defines a handler that can customize entity UI appearance and behavior in the Entity Outliner. - //! This class is meant to be abstract, entities do not have a handler by default. class EditorEntityUiHandlerBase { protected: @@ -33,7 +32,7 @@ namespace AzToolsFramework public: EditorEntityUiHandlerId GetHandlerId(); - // # Entity Outliner + // # Entity Outliner Item //! Returns the item info string that is appended to the item name in the Outliner. virtual QString GenerateItemInfoString(AZ::EntityId entityId) const; @@ -41,10 +40,12 @@ namespace AzToolsFramework virtual QString GenerateItemTooltip(AZ::EntityId entityId) const; //! Returns the item icon pixmap to display in the Outliner. virtual QIcon GenerateItemIcon(AZ::EntityId entityId) const; - //! Returns whether the element's lock and visibility state should be accessible in the Outliner - virtual bool CanToggleLockVisibility(AZ::EntityId entityId) const; //! Returns whether the element's name should be editable virtual bool CanRename(AZ::EntityId entityId) const; + //! Returns whether the element's lock and visibility state should be accessible in the Outliner + virtual bool CanToggleLockVisibility(AZ::EntityId entityId) const; + + // Qt-specific painting functions //! Paints the background of the item in the Outliner. virtual void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; @@ -54,24 +55,27 @@ namespace AzToolsFramework //! Paints the background of the descendant branches of the item in the Outliner. virtual void PaintDescendantBranchBackground(QPainter* painter, const QTreeView* view, const QRect& rect, const QModelIndex& index, const QModelIndex& descendantIndex) const; - //! Paints visual elements on the foreground of the item in the Outliner. virtual void PaintItemForeground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; //! Paints visual elements on the foreground of the descendants of the item in the Outliner. virtual void PaintDescendantForeground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index, const QModelIndex& descendantIndex) const; + // Outliner-specific interactions + //! Triggered when the entity is clicked in the Outliner. //! @return True if the click has been handled and should not be propagated, false otherwise. virtual bool OnOutlinerItemClick(const QPoint& position, const QStyleOptionViewItem& option, const QModelIndex& index) const; + //! Triggered when the entity is double-clicked in the Outliner. + //! @return True if the double-click has been handled and should not be propagated, false otherwise. + virtual bool OnOutlinerItemDoubleClick(const QModelIndex& index) const; //! Triggered when an entity's children are expanded in the Outliner. virtual void OnOutlinerItemExpand(const QModelIndex& index) const; //! Triggered when an entity's children are collapsed in the Outliner. virtual void OnOutlinerItemCollapse(const QModelIndex& index) const; - //! Triggered when the entity is double clicked in the Outliner or in the Viewport. - //! @return True if the double click has been handled and should not be propagated, false otherwise. - virtual bool OnEntityDoubleClick(AZ::EntityId entityId) const; + protected: + static AZ::EntityId GetEntityIdFromIndex(const QModelIndex& index); private: EditorEntityUiHandlerId m_handlerId = 0; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp index 52b688543a..f4855cb715 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Outliner/EntityOutlinerWidget.cpp @@ -945,7 +945,7 @@ namespace AzToolsFramework { if (AZ::EntityId entityId = GetEntityIdFromIndex(index); auto entityUiHandler = m_editorEntityUiInterface->GetHandler(entityId)) { - entityUiHandler->OnEntityDoubleClick(entityId); + entityUiHandler->OnOutlinerItemDoubleClick(index); } } diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp index b34bbff298..9c5c478a2f 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.cpp @@ -33,7 +33,7 @@ namespace AzToolsFramework } } - QIcon LevelRootUiHandler::GenerateItemIcon(AZ::EntityId /*entityId*/) const + QIcon LevelRootUiHandler::GenerateItemIcon([[maybe_unused]] AZ::EntityId entityId) const { return QIcon(m_levelRootIconPath); } @@ -62,17 +62,18 @@ namespace AzToolsFramework return infoString; } - bool LevelRootUiHandler::CanToggleLockVisibility(AZ::EntityId /*entityId*/) const + bool LevelRootUiHandler::CanToggleLockVisibility([[maybe_unused]] AZ::EntityId entityId) const { return false; } - bool LevelRootUiHandler::CanRename(AZ::EntityId /*entityId*/) const + bool LevelRootUiHandler::CanRename([[maybe_unused]] AZ::EntityId entityId) const { return false; } - void LevelRootUiHandler::PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& /*index*/) const + void LevelRootUiHandler::PaintItemBackground( + QPainter* painter, const QStyleOptionViewItem& option, [[maybe_unused]] const QModelIndex& index) const { if (!painter) { @@ -94,8 +95,10 @@ namespace AzToolsFramework painter->restore(); } - bool LevelRootUiHandler::OnEntityDoubleClick(AZ::EntityId entityId) const + bool LevelRootUiHandler::OnOutlinerItemDoubleClick(const QModelIndex& index) const { + AZ::EntityId entityId = GetEntityIdFromIndex(index); + if (auto prefabFocusPublicInterface = AZ::Interface::Get(); !prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId)) { diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.h index 3f7f56670e..a43aa0606a 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/LevelRootUiHandler.h @@ -33,7 +33,7 @@ namespace AzToolsFramework bool CanToggleLockVisibility(AZ::EntityId entityId) const override; bool CanRename(AZ::EntityId entityId) const override; void PaintItemBackground(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override; - bool OnEntityDoubleClick(AZ::EntityId entityId) const override; + bool OnOutlinerItemDoubleClick(const QModelIndex& index) const override; private: Prefab::PrefabPublicInterface* m_prefabPublicInterface = nullptr; diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp index 69d6ae82ca..f3579c223c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.cpp @@ -99,7 +99,7 @@ namespace AzToolsFramework return; } - AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value()); + AZ::EntityId entityId = GetEntityIdFromIndex(index); const bool isFirstColumn = index.column() == EntityOutlinerListModel::ColumnName; const bool isLastColumn = index.column() == EntityOutlinerListModel::ColumnLockToggle; QModelIndex firstColumnIndex = index.siblingAtColumn(EntityOutlinerListModel::ColumnName); @@ -183,7 +183,7 @@ namespace AzToolsFramework return; } - AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value()); + AZ::EntityId entityId = GetEntityIdFromIndex(index); const QTreeView* outlinerTreeView(qobject_cast(option.widget)); const int ancestorLeft = outlinerTreeView->visualRect(index).left() + (m_prefabBorderThickness / 2) - 1; @@ -283,7 +283,7 @@ namespace AzToolsFramework void PrefabUiHandler::PaintItemForeground(QPainter* painter, const QStyleOptionViewItem& option, [[maybe_unused]] const QModelIndex& index) const { - AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value()); + AZ::EntityId entityId = GetEntityIdFromIndex(index); const QPoint offset = QPoint(-18, 3); QModelIndex firstColumnIndex = index.siblingAtColumn(EntityOutlinerListModel::ColumnName); const int iconSize = 16; @@ -385,7 +385,7 @@ namespace AzToolsFramework bool PrefabUiHandler::OnOutlinerItemClick(const QPoint& position, const QStyleOptionViewItem& option, const QModelIndex& index) const { - AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value()); + AZ::EntityId entityId = GetEntityIdFromIndex(index); const QPoint offset = QPoint(-18, 3); if (m_prefabFocusPublicInterface->IsOwningPrefabInFocusHierarchy(entityId)) @@ -411,7 +411,7 @@ namespace AzToolsFramework void PrefabUiHandler::OnOutlinerItemCollapse(const QModelIndex& index) const { - AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value()); + AZ::EntityId entityId = GetEntityIdFromIndex(index); if (m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId)) { @@ -420,8 +420,10 @@ namespace AzToolsFramework } } - bool PrefabUiHandler::OnEntityDoubleClick(AZ::EntityId entityId) const + bool PrefabUiHandler::OnOutlinerItemDoubleClick(const QModelIndex& index) const { + AZ::EntityId entityId = GetEntityIdFromIndex(index); + if (!m_prefabFocusPublicInterface->IsOwningPrefabBeingFocused(entityId)) { // Focus on this prefab diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h index a1c624f85a..7166629cf3 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/Prefab/PrefabUiHandler.h @@ -43,8 +43,8 @@ namespace AzToolsFramework const QModelIndex& index, const QModelIndex& descendantIndex) const override; bool OnOutlinerItemClick(const QPoint& position, const QStyleOptionViewItem& option, const QModelIndex& index) const override; + bool OnOutlinerItemDoubleClick(const QModelIndex& index) const override; void OnOutlinerItemCollapse(const QModelIndex& index) const override; - bool OnEntityDoubleClick(AZ::EntityId entityId) const override; protected: Prefab::PrefabFocusPublicInterface* m_prefabFocusPublicInterface = nullptr; From 3ad78881076240204bc8adb9bf0baeafba330cd7 Mon Sep 17 00:00:00 2001 From: dmcdiarmid-ly <63674186+dmcdiarmid-ly@users.noreply.github.com> Date: Wed, 9 Feb 2022 22:11:43 -0700 Subject: [PATCH 17/27] Checked the device raytracing feature flag before initializing the visualization raytracing objects Signed-off-by: dmcdiarmid-ly <63674186+dmcdiarmid-ly@users.noreply.github.com> --- .../DiffuseProbeGridFeatureProcessor.cpp | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp index 84c066604a..5e85c3b247 100644 --- a/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp +++ b/Gems/Atom/Feature/Common/Code/Source/DiffuseGlobalIllumination/DiffuseProbeGridFeatureProcessor.cpp @@ -92,21 +92,24 @@ namespace AZ AZ_Error("DiffuseProbeGridFeatureProcessor", m_probeGridRenderData.m_srgLayout != nullptr, "Failed to find ObjectSrg layout"); } - // initialize the buffer pools for the DiffuseProbeGrid visualization - m_visualizationBufferPools = RHI::RayTracingBufferPools::CreateRHIRayTracingBufferPools(); - m_visualizationBufferPools->Init(device); - - // load probe visualization model, the BLAS will be created in OnAssetReady() - m_visualizationModelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath( - "Models/DiffuseProbeSphere.azmodel", - AZ::RPI::AssetUtils::TraceLevel::Assert); - - if (!m_visualizationModelAsset.IsReady()) + if (device->GetFeatures().m_rayTracing) { - m_visualizationModelAsset.QueueLoad(); - } + // initialize the buffer pools for the DiffuseProbeGrid visualization + m_visualizationBufferPools = RHI::RayTracingBufferPools::CreateRHIRayTracingBufferPools(); + m_visualizationBufferPools->Init(device); - Data::AssetBus::MultiHandler::BusConnect(m_visualizationModelAsset.GetId()); + // load probe visualization model, the BLAS will be created in OnAssetReady() + m_visualizationModelAsset = AZ::RPI::AssetUtils::GetAssetByProductPath( + "Models/DiffuseProbeSphere.azmodel", + AZ::RPI::AssetUtils::TraceLevel::Assert); + + if (!m_visualizationModelAsset.IsReady()) + { + m_visualizationModelAsset.QueueLoad(); + } + + Data::AssetBus::MultiHandler::BusConnect(m_visualizationModelAsset.GetId()); + } EnableSceneNotification(); } From aec7b58c39d369ccce23e28742989c1ef16575f5 Mon Sep 17 00:00:00 2001 From: Jeremy Ong Date: Thu, 10 Feb 2022 02:27:49 -0700 Subject: [PATCH 18/27] Introduce Atom/GraphicsDevMode settings registry key When `"Atom": {"GraphicsDevMode": true}` is found in a `.setreg` file, PDBs for all shaders will be emitted to their corresponding output locations. This allows global PDB generation without needing to explicitly modify each `.shader` file to include the `GenerateDebugInfo` compilation option. Signed-off-by: Jeremy Ong --- .../Editor/AzslShaderBuilderSystemComponent.cpp | 2 +- Gems/Atom/RHI/Code/Include/Atom/RHI/RHIUtils.h | 3 +++ Gems/Atom/RHI/Code/Source/RHI/RHIUtils.cpp | 14 ++++++++++++++ .../RHI.Builders/ShaderPlatformInterface.cpp | 10 ++++++---- .../RHI.Builders/ShaderPlatformInterface.cpp | 7 +++++-- 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp index 7e510e2e3a..43d67cc95c 100644 --- a/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp +++ b/Gems/Atom/Asset/Shader/Code/Source/Editor/AzslShaderBuilderSystemComponent.cpp @@ -82,7 +82,7 @@ namespace AZ // Register Shader Asset Builder AssetBuilderSDK::AssetBuilderDesc shaderAssetBuilderDescriptor; shaderAssetBuilderDescriptor.m_name = "Shader Asset Builder"; - shaderAssetBuilderDescriptor.m_version = 110; // Add "Definitions" field to shader asset to support convenient addition of preprocessor definitions + shaderAssetBuilderDescriptor.m_version = 111; // Enable shader PDB generation globally if Atom/GraphicsDevMode settings registry key is set shaderAssetBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern( AZStd::string::format("*.%s", RPI::ShaderSourceData::Extension), AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard)); shaderAssetBuilderDescriptor.m_busId = azrtti_typeid(); shaderAssetBuilderDescriptor.m_createJobFunction = AZStd::bind(&ShaderAssetBuilder::CreateJobs, &m_shaderAssetBuilder, AZStd::placeholders::_1, AZStd::placeholders::_2); diff --git a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHIUtils.h b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHIUtils.h index 73e8e1ad56..48a041ad7d 100644 --- a/Gems/Atom/RHI/Code/Include/Atom/RHI/RHIUtils.h +++ b/Gems/Atom/RHI/Code/Include/Atom/RHI/RHIUtils.h @@ -42,6 +42,9 @@ namespace AZ //! Returns if the current bakcend is a null renderer bool IsNullRenderer(); + + //! Returns true if the Atom/GraphicsDevMode settings registry key is set + bool IsGraphicsDevModeEnabled(); } } diff --git a/Gems/Atom/RHI/Code/Source/RHI/RHIUtils.cpp b/Gems/Atom/RHI/Code/Source/RHI/RHIUtils.cpp index bc4cde9406..de27f4ce18 100644 --- a/Gems/Atom/RHI/Code/Source/RHI/RHIUtils.cpp +++ b/Gems/Atom/RHI/Code/Source/RHI/RHIUtils.cpp @@ -9,9 +9,12 @@ #include #include #include +#include #include #include +static constexpr char GraphicsDevModeSetting[] = "/Atom/GraphicsDevMode"; + namespace AZ { namespace RHI @@ -134,5 +137,16 @@ namespace AZ } return false; } + + bool IsGraphicsDevModeEnabled() + { + AZ::SettingsRegistryInterface* settingsRegistry = AZ::SettingsRegistry::Get(); + bool graphicsDevMode = false; + if (settingsRegistry) + { + settingsRegistry->Get(graphicsDevMode, GraphicsDevModeSetting); + } + return graphicsDevMode; + } } } diff --git a/Gems/Atom/RHI/DX12/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp b/Gems/Atom/RHI/DX12/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp index ee293292e1..287c8e4fd5 100644 --- a/Gems/Atom/RHI/DX12/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp +++ b/Gems/Atom/RHI/DX12/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp @@ -12,10 +12,10 @@ #include #include #include +#include #include #include - #include namespace AZ @@ -253,9 +253,11 @@ namespace AZ return false; } + const bool graphicsDevMode = RHI::IsGraphicsDevModeEnabled(); + // Compilation parameters AZStd::string params = shaderCompilerArguments.MakeAdditionalDxcCommandLineString(); - if (BuildHasDebugInfo(shaderCompilerArguments)) + if (graphicsDevMode || BuildHasDebugInfo(shaderCompilerArguments)) { params += " -Zi"; // Generate debug information params += " -Zss"; // Compute Shader Hash considering source information @@ -284,7 +286,7 @@ namespace AZ // If we use the auto-name (hash), there is no way we can retrieve that name apart from listing the directory. // Instead, let's just generate that hash ourselves. AZStd::string symbolDatabaseFileCliArgument{" "}; // when not debug: still insert a space between 5.dxil and 7.hlsl-in - if (BuildHasDebugInfo(shaderCompilerArguments)) + if (graphicsDevMode || BuildHasDebugInfo(shaderCompilerArguments)) { // prepare .pdb filename: AZStd::string md5hex = RHI::ByteToHexString(md5); @@ -353,7 +355,7 @@ namespace AZ byProducts.m_dynamicBranchCount = ByProducts::UnknownDynamicBranchCount; } - if (BuildHasDebugInfo(shaderCompilerArguments)) + if (graphicsDevMode || BuildHasDebugInfo(shaderCompilerArguments)) { byProducts.m_intermediatePaths.emplace(AZStd::move(objectCodeOutputFile)); } diff --git a/Gems/Atom/RHI/Vulkan/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp b/Gems/Atom/RHI/Vulkan/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp index c5f1060ca3..f5716f384f 100644 --- a/Gems/Atom/RHI/Vulkan/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp +++ b/Gems/Atom/RHI/Vulkan/Code/Source/RHI.Builders/ShaderPlatformInterface.cpp @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -281,7 +282,9 @@ namespace AZ args.m_destinationFolder = tempFolder.c_str(); const auto dxcInputFile = RHI::PrependFile(args); // Prepend header - if (BuildHasDebugInfo(shaderCompilerArguments)) + const bool graphicsDevMode = RHI::IsGraphicsDevModeEnabled(); + + if (graphicsDevMode || BuildHasDebugInfo(shaderCompilerArguments)) { // dump intermediate "true final HLSL" file (shadername.vulkan.shadersource.prepend) byProducts.m_intermediatePaths.insert(dxcInputFile); @@ -334,7 +337,7 @@ namespace AZ byProducts.m_dynamicBranchCount = ByProducts::UnknownDynamicBranchCount; } - if (BuildHasDebugInfo(shaderCompilerArguments)) + if (graphicsDevMode || BuildHasDebugInfo(shaderCompilerArguments)) { byProducts.m_intermediatePaths.emplace(AZStd::move(objectCodeOutputFile)); } From c964d2085f4d0732d9b23cc5bbedc0181bc551be Mon Sep 17 00:00:00 2001 From: Sergey Pereslavtsev Date: Thu, 10 Feb 2022 10:45:25 +0000 Subject: [PATCH 19/27] Removed pragma once from cpp Signed-off-by: Sergey Pereslavtsev --- Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.cpp b/Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.cpp index 12a371fc49..bb4dcb6afe 100644 --- a/Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.cpp +++ b/Gems/Terrain/Code/Source/EditorSurfaceTagListProvider.cpp @@ -6,8 +6,6 @@ * */ -#pragma once - #include #include From dac3bc4ba62c34c47ab1513a42f0e415bbcacc49 Mon Sep 17 00:00:00 2001 From: moraaar Date: Thu, 10 Feb 2022 12:23:38 +0000 Subject: [PATCH 20/27] Added option to disable edit button in asset widgets when there are no asset selected. (#7521) Added new attribute "DisableEditButtonWheNoAssetSelected" to PropertyAssetCtrl. By default it's false, keeping the original behavior of leaving the edit button enabled and if it's clicked while there is no asset assigned it'll try to create a new one. PhysX mesh asset property uses now this new feature. Signed-off-by: moraaar moraaar@amazon.com --- .../UI/PropertyEditor/PropertyAssetCtrl.cpp | 42 ++++++++++++++++++- .../UI/PropertyEditor/PropertyAssetCtrl.hxx | 8 ++++ .../Code/Source/EditorColliderComponent.cpp | 1 + 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp index bd0cb3844a..e4a1a35b2c 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.cpp @@ -102,7 +102,7 @@ namespace AzToolsFramework m_editButton->setAutoRaise(true); m_editButton->setIcon(QIcon(":/stylesheet/img/UI20/open-in-internal-app.svg")); m_editButton->setToolTip("Edit asset"); - m_editButton->setVisible(false); + SetEditButtonVisible(false); connect(m_editButton, &QToolButton::clicked, this, &PropertyAssetCtrl::OnEditButtonClicked); @@ -961,12 +961,16 @@ namespace AzToolsFramework AzFramework::StringFunc::Path::GetFileName(assetPath.c_str(), m_defaultAssetHint); } m_browseEdit->setPlaceholderText((m_defaultAssetHint + m_DefaultSuffix).c_str()); + + UpdateEditButton(); } void PropertyAssetCtrl::UpdateAssetDisplay() { UpdateThumbnail(); + UpdateEditButton(); + if (m_currentAssetType == AZ::Data::s_invalidAssetType) { return; @@ -1109,7 +1113,9 @@ namespace AzToolsFramework void PropertyAssetCtrl::SetEditButtonVisible(bool visible) { - m_editButton->setVisible(visible); + m_showEditButton = visible; + m_editButton->setVisible(m_showEditButton); + UpdateEditButton(); } void PropertyAssetCtrl::SetEditButtonIcon(const QIcon& icon) @@ -1205,6 +1211,15 @@ namespace AzToolsFramework m_thumbnail->ClearThumbnail(); } + void PropertyAssetCtrl::UpdateEditButton() + { + // if Edit button is in use (shown), enable/disable it depending on the current asset id. + if (m_showEditButton && m_disableEditButtonWhenNoAssetSelected) + { + m_editButton->setEnabled(GetCurrentAssetID().IsValid()); + } + } + void PropertyAssetCtrl::SetClearButtonEnabled(bool enable) { m_browseEdit->setClearButtonEnabled(enable); @@ -1236,6 +1251,17 @@ namespace AzToolsFramework return m_hideProductFilesInAssetPicker; } + void PropertyAssetCtrl::SetDisableEditButtonWhenNoAssetSelected(bool disableEditButtonWhenNoAssetSelected) + { + m_disableEditButtonWhenNoAssetSelected = disableEditButtonWhenNoAssetSelected; + UpdateEditButton(); + } + + bool PropertyAssetCtrl::GetDisableEditButtonWhenNoAssetSelected() const + { + return m_disableEditButtonWhenNoAssetSelected; + } + void PropertyAssetCtrl::SetShowThumbnail(bool enable) { m_showThumbnail = enable; @@ -1349,6 +1375,12 @@ namespace AzToolsFramework GUI->SetEditButtonTooltip(tr(buttonTooltip.c_str())); } } + else if (attrib == AZ_CRC_CE("DisableEditButtonWhenNoAssetSelected")) + { + bool disableEditButtonWhenNoAssetSelected = false; + attrValue->Read(disableEditButtonWhenNoAssetSelected); + GUI->SetDisableEditButtonWhenNoAssetSelected(disableEditButtonWhenNoAssetSelected); + } else if (attrib == AZ::Edit::Attributes::DefaultAsset) { AZ::Data::AssetId assetId; @@ -1597,6 +1629,12 @@ namespace AzToolsFramework GUI->SetEditButtonTooltip(tr(buttonTooltip.c_str())); } } + else if (attrib == AZ_CRC_CE("DisableEditButtonWhenNoAssetSelected")) + { + bool disableEditButtonWhenNoAssetSelected = false; + attrValue->Read(disableEditButtonWhenNoAssetSelected); + GUI->SetDisableEditButtonWhenNoAssetSelected(disableEditButtonWhenNoAssetSelected); + } } void SimpleAssetPropertyHandlerDefault::WriteGUIValuesIntoProperty(size_t index, PropertyAssetCtrl* GUI, property_t& instance, InstanceDataNode* node) diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx index d6ff1b8de6..87fd691b20 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/UI/PropertyEditor/PropertyAssetCtrl.hxx @@ -159,6 +159,10 @@ namespace AzToolsFramework //! By default the asset picker shows both on an AZ::Asset<> property. You can hide product assets with this flag. bool m_hideProductFilesInAssetPicker = false; + //! True to disable the edit button when there is no asset currently selected. + bool m_disableEditButtonWhenNoAssetSelected = false; + + bool m_showEditButton = false; bool m_showThumbnail = false; bool m_showThumbnailDropDownButton = false; EditCallbackType* m_thumbnailCallback = nullptr; @@ -220,6 +224,9 @@ namespace AzToolsFramework void SetHideProductFilesInAssetPicker(bool hide); bool GetHideProductFilesInAssetPicker() const; + void SetDisableEditButtonWhenNoAssetSelected(bool disableEditButtonWhenNoAssetSelected); + bool GetDisableEditButtonWhenNoAssetSelected() 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; @@ -250,6 +257,7 @@ namespace AzToolsFramework private: void UpdateThumbnail(); + void UpdateEditButton(); }; class AssetPropertyHandlerDefault diff --git a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp index 7e1d1c341f..69ae037e07 100644 --- a/Gems/PhysX/Code/Source/EditorColliderComponent.cpp +++ b/Gems/PhysX/Code/Source/EditorColliderComponent.cpp @@ -60,6 +60,7 @@ namespace PhysX "Specifies the PhysX mesh collider asset for this PhysX collider component.") ->Attribute(AZ_CRC_CE("EditButton"), "") ->Attribute(AZ_CRC_CE("EditDescription"), "Open in Scene Settings") + ->Attribute(AZ_CRC_CE("DisableEditButtonWhenNoAssetSelected"), true) ->DataElement(AZ::Edit::UIHandlers::Default, &EditorProxyAssetShapeConfig::m_configuration, "Configuration", "PhysX mesh asset collider configuration.") ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly); From 396ec8a247526754eb434f890b47d02c2a13f62f Mon Sep 17 00:00:00 2001 From: amzn-sj Date: Thu, 10 Feb 2022 05:53:21 -0800 Subject: [PATCH 21/27] [Terrain] Optimize bulk queries to the Terrain System to retrieve height, surface weights, and normals (#7357) --- .../AzFramework/SurfaceData/SurfaceData.cpp | 2 + .../AzFramework/SurfaceData/SurfaceData.h | 10 +- .../Include/SurfaceData/SurfaceDataTypes.h | 12 +- .../Code/Source/SurfaceDataTypes.cpp | 2 +- .../Code/Tests/SurfaceDataBenchmarks.cpp | 4 +- .../Source/TerrainSystem/TerrainSystem.cpp | 410 +++++++++++++++--- .../Code/Source/TerrainSystem/TerrainSystem.h | 32 ++ Gems/Terrain/Code/Tests/TerrainSystemTest.cpp | 28 +- 8 files changed, 427 insertions(+), 73 deletions(-) diff --git a/Code/Framework/AzFramework/AzFramework/SurfaceData/SurfaceData.cpp b/Code/Framework/AzFramework/AzFramework/SurfaceData/SurfaceData.cpp index 55fec57bb6..e287c8d948 100644 --- a/Code/Framework/AzFramework/AzFramework/SurfaceData/SurfaceData.cpp +++ b/Code/Framework/AzFramework/AzFramework/SurfaceData/SurfaceData.cpp @@ -37,6 +37,7 @@ namespace AzFramework::SurfaceData { if (AZ::SerializeContext* serializeContext = azrtti_cast(context)) { + serializeContext->Class>(); serializeContext->Class() ->Field("m_position", &SurfacePoint::m_position) ->Field("m_normal", &SurfacePoint::m_normal) @@ -46,6 +47,7 @@ namespace AzFramework::SurfaceData if (AZ::BehaviorContext* behaviorContext = azrtti_cast(context)) { + behaviorContext->Class>(); behaviorContext->Class("AzFramework::SurfaceData::SurfacePoint") ->Attribute(AZ::Script::Attributes::Category, "SurfaceData") ->Constructor() diff --git a/Code/Framework/AzFramework/AzFramework/SurfaceData/SurfaceData.h b/Code/Framework/AzFramework/AzFramework/SurfaceData/SurfaceData.h index 9faa03f921..45e2ad3abb 100644 --- a/Code/Framework/AzFramework/AzFramework/SurfaceData/SurfaceData.h +++ b/Code/Framework/AzFramework/AzFramework/SurfaceData/SurfaceData.h @@ -10,13 +10,19 @@ #include #include #include -#include +#include namespace AzFramework::SurfaceData { namespace Constants { static constexpr const char* s_unassignedTagName = "(unassigned)"; + + //! The maximum number of surface weights that we can store. + //! For performance reasons, we want to limit this so that we can preallocate the max size in advance. + //! The current number is chosen to be higher than expected needs, but small enough to avoid being excessively wasteful. + //! (Dynamic structures would end up taking more memory than what we're preallocating) + static constexpr size_t MaxSurfaceWeights = 16; } struct SurfaceTagWeight @@ -70,7 +76,7 @@ namespace AzFramework::SurfaceData } }; - using SurfaceTagWeightList = AZStd::vector; + using SurfaceTagWeightList = AZStd::fixed_vector; struct SurfacePoint final { diff --git a/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataTypes.h b/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataTypes.h index 943c45bb6a..1d49fff3dc 100644 --- a/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataTypes.h +++ b/Gems/SurfaceData/Code/Include/SurfaceData/SurfaceDataTypes.h @@ -29,12 +29,6 @@ namespace SurfaceData class SurfaceTagWeights { public: - //! The maximum number of surface weights that we can store. - //! For performance reasons, we want to limit this so that we can preallocate the max size in advance. - //! The current number is chosen to be higher than expected needs, but small enough to avoid being excessively wasteful. - //! (Dynamic structures would end up taking more memory than what we're preallocating) - static inline constexpr size_t MaxSurfaceWeights = 16; - SurfaceTagWeights() = default; //! Construct a collection of SurfaceTagWeights from the given SurfaceTagWeightList. @@ -65,7 +59,7 @@ namespace SurfaceData // early-out once we pass the location for the entry instead of always searching every entry. if (weightItr->m_surfaceType > tag) { - if (m_weights.size() != MaxSurfaceWeights) + if (m_weights.size() != AzFramework::SurfaceData::Constants::MaxSurfaceWeights) { // We didn't find the surface type, so add the new entry in sorted order. m_weights.insert(weightItr, { tag, weight }); @@ -85,7 +79,7 @@ namespace SurfaceData } // We didn't find the surface weight, and the sort order for it is at the end, so add it to the back of the list. - if (m_weights.size() != MaxSurfaceWeights) + if (m_weights.size() != AzFramework::SurfaceData::Constants::MaxSurfaceWeights) { m_weights.emplace_back(tag, weight); } @@ -188,7 +182,7 @@ namespace SurfaceData //! @return The pointer to the tag that's found, or end() if it wasn't found. const AzFramework::SurfaceData::SurfaceTagWeight* FindTag(AZ::Crc32 tag) const; - AZStd::fixed_vector m_weights; + AZStd::fixed_vector m_weights; }; //! SurfacePointList stores a collection of surface point data, which consists of positions, normals, and surface tag weights. diff --git a/Gems/SurfaceData/Code/Source/SurfaceDataTypes.cpp b/Gems/SurfaceData/Code/Source/SurfaceDataTypes.cpp index a25273896e..3d6378aa7c 100644 --- a/Gems/SurfaceData/Code/Source/SurfaceDataTypes.cpp +++ b/Gems/SurfaceData/Code/Source/SurfaceDataTypes.cpp @@ -42,7 +42,7 @@ namespace SurfaceData AzFramework::SurfaceData::SurfaceTagWeightList SurfaceTagWeights::GetSurfaceTagWeightList() const { AzFramework::SurfaceData::SurfaceTagWeightList weights; - weights.reserve(m_weights.size()); + for (auto& weight : m_weights) { weights.emplace_back(weight); diff --git a/Gems/SurfaceData/Code/Tests/SurfaceDataBenchmarks.cpp b/Gems/SurfaceData/Code/Tests/SurfaceDataBenchmarks.cpp index df011113da..becb91f0ce 100644 --- a/Gems/SurfaceData/Code/Tests/SurfaceDataBenchmarks.cpp +++ b/Gems/SurfaceData/Code/Tests/SurfaceDataBenchmarks.cpp @@ -275,7 +275,7 @@ namespace UnitTest { AZ_PROFILE_FUNCTION(Entity); - AZ::Crc32 tags[SurfaceData::SurfaceTagWeights::MaxSurfaceWeights]; + AZ::Crc32 tags[AzFramework::SurfaceData::Constants::MaxSurfaceWeights]; AZ::SimpleLcgRandom randomGenerator(1234567); // Declare this outside the loop so that we aren't benchmarking creation and destruction. @@ -316,7 +316,7 @@ namespace UnitTest { AZ_PROFILE_FUNCTION(Entity); - AZ::Crc32 tags[SurfaceData::SurfaceTagWeights::MaxSurfaceWeights]; + AZ::Crc32 tags[AzFramework::SurfaceData::Constants::MaxSurfaceWeights]; AZ::SimpleLcgRandom randomGenerator(1234567); // Declare this outside the loop so that we aren't benchmarking creation and destruction. diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp index 8976faadac..6ce83094e4 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.cpp @@ -177,6 +177,193 @@ bool TerrainSystem::InWorldBounds(float x, float y) const return false; } +// Generate positions to be queried based on the sampler type. +void TerrainSystem::GenerateQueryPositions(const AZStd::span& inPositions, + AZStd::vector& outPositions, + Sampler sampler) const +{ + const float minHeight = m_currentSettings.m_worldBounds.GetMin().GetZ(); + for (auto& position : inPositions) + { + switch(sampler) + { + case AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR: + { + AZ::Vector2 normalizedDelta; + AZ::Vector2 pos0; + ClampPosition(position.GetX(), position.GetY(), pos0, normalizedDelta); + const AZ::Vector2 pos1(pos0.GetX() + m_currentSettings.m_heightQueryResolution, + pos0.GetY() + m_currentSettings.m_heightQueryResolution); + outPositions.emplace_back(AZ::Vector3(pos0.GetX(), pos0.GetY(), minHeight)); + outPositions.emplace_back(AZ::Vector3(pos1.GetX(), pos0.GetY(), minHeight)); + outPositions.emplace_back(AZ::Vector3(pos0.GetX(), pos1.GetY(), minHeight)); + outPositions.emplace_back(AZ::Vector3(pos1.GetX(), pos1.GetY(), minHeight)); + } + break; + case AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP: + { + AZ::Vector2 normalizedDelta; + AZ::Vector2 clampedPosition; + ClampPosition(position.GetX(), position.GetY(), clampedPosition, normalizedDelta); + outPositions.emplace_back(AZ::Vector3(clampedPosition.GetX(), clampedPosition.GetY(), minHeight)); + } + break; + case AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT: + [[fallthrough]]; + default: + outPositions.emplace_back(AZ::Vector3(position.GetX(), position.GetY(), minHeight)); + break; + } + } +} + +AZStd::vector TerrainSystem::GenerateInputPositionsFromRegion( + const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize) const +{ + AZStd::vector inPositions; + const auto [numSamplesX, numSamplesY] = GetNumSamplesFromRegion(inRegion, stepSize); + inPositions.reserve(numSamplesX * numSamplesY); + + for (size_t y = 0; y < numSamplesY; y++) + { + float fy = aznumeric_cast(inRegion.GetMin().GetY() + (y * stepSize.GetY())); + for (size_t x = 0; x < numSamplesX; x++) + { + float fx = aznumeric_cast(inRegion.GetMin().GetX() + (x * stepSize.GetX())); + inPositions.emplace_back(AZ::Vector3(fx, fy, 0.0f)); + } + } + + return inPositions; +} + +void TerrainSystem::MakeBulkQueries( + const AZStd::span inPositions, + AZStd::span outPositions, + AZStd::span outTerrainExists, + AZStd::span outSurfaceWeights, + BulkQueriesCallback queryCallback) const +{ + AZ::Aabb bounds; + AZ::EntityId prevAreaId = FindBestAreaEntityAtPosition(inPositions[0].GetX(), inPositions[0].GetY(), bounds); + + // We use a sliding window here and update the window end for each + // position that falls in the same area as the previous positions. This consumes lesser memory + // than sorting the points into separate lists and handling putting them back together. + // This may be sub optimal if the points are randomly distributed in the list as opposed + // to points in the same area id being close to each other. + size_t windowStart = 0; + size_t windowEnd = 0; + const size_t numPositions = inPositions.size(); + for(int i = 1; i < numPositions; i++) + { + AZ::EntityId areaId = FindBestAreaEntityAtPosition(inPositions[i].GetX(), inPositions[i].GetY(), bounds); + bool queryHeights = false; + if (areaId == prevAreaId) + { + // Update window end to current position. + // If it's the last position, submit the query. + windowEnd = i; + if (windowEnd == numPositions - 1) + { + queryHeights = true; + } + } + else + { + queryHeights = true; + } + + if (queryHeights) + { + // If the area id is a default entity id, it usually means the + // position is outside world bounds. + if (prevAreaId != AZ::EntityId()) + { + size_t spanLength = (windowEnd - windowStart) + 1; + queryCallback(AZStd::span(inPositions.begin() + windowStart, spanLength), + AZStd::span(outPositions.begin() + windowStart, spanLength), + AZStd::span(outTerrainExists.begin() + windowStart, spanLength), + AZStd::span(outSurfaceWeights.begin() + windowStart, spanLength), + prevAreaId); + } + + // Reset the window to start at the current position. Set the new area + // id on which to run the next query. + windowStart = windowEnd = i; + prevAreaId = areaId; + } + } +} + +void TerrainSystem::GetHeightsSynchronous(const AZStd::span& inPositions, Sampler sampler, + AZStd::span heights, AZStd::span terrainExists) const +{ + AZStd::shared_lock lock(m_areaMutex); + + AZStd::vector outPositions; + AZStd::vector outTerrainExists; + + // outPositions holds the iterators to results of the bulk queries. + // In the case of the bilinear sampler, we'll be making 4 queries per + // input position. + size_t indexStepSize = (sampler == AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR) ? 4 : 1; + outPositions.reserve(inPositions.size() * indexStepSize); + outTerrainExists.resize(inPositions.size() * indexStepSize); + + GenerateQueryPositions(inPositions, outPositions, sampler); + + auto callback = []([[maybe_unused]] const AZStd::span inPositions, + AZStd::span outPositions, + AZStd::span outTerrainExists, + [[maybe_unused]] AZStd::span outSurfaceWeights, + AZ::EntityId areaId) + { + AZ_Assert((inPositions.size() == outPositions.size() && inPositions.size() == outTerrainExists.size()), + "The sizes of the terrain exists list and in/out positions list should match."); + Terrain::TerrainAreaHeightRequestBus::Event(areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeights, + outPositions, outTerrainExists); + }; + + // This will be unused for heights. It's fine if it's empty. + AZStd::vector outSurfaceWeights; + MakeBulkQueries(outPositions, outPositions, outTerrainExists, outSurfaceWeights, callback); + + // Compute/store the final result + for (size_t i = 0, iteratorIndex = 0; i < inPositions.size(); i++, iteratorIndex += indexStepSize) + { + switch(sampler) + { + case AzFramework::Terrain::TerrainDataRequests::Sampler::BILINEAR: + { + // We now need to compute the final height after all the bulk queries are done. + AZ::Vector2 normalizedDelta; + AZ::Vector2 clampedPosition; + ClampPosition(inPositions[i].GetX(), inPositions[i].GetY(), clampedPosition, normalizedDelta); + const float heightX0Y0 = outPositions[iteratorIndex].GetZ(); + const float heightX1Y0 = outPositions[iteratorIndex + 1].GetZ(); + const float heightX0Y1 = outPositions[iteratorIndex + 2].GetZ(); + const float heightX1Y1 = outPositions[iteratorIndex + 3].GetZ(); + const float heightXY0 = AZ::Lerp(heightX0Y0, heightX1Y0, normalizedDelta.GetX()); + const float heightXY1 = AZ::Lerp(heightX0Y1, heightX1Y1, normalizedDelta.GetX()); + heights[i] = AZ::Lerp(heightXY0, heightXY1, normalizedDelta.GetY()); + terrainExists[i] = outTerrainExists[iteratorIndex]; + } + break; + case AzFramework::Terrain::TerrainDataRequests::Sampler::CLAMP: + [[fallthrough]]; + case AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT: + [[fallthrough]]; + default: + // For clamp and exact, we just need to store the results of the bulk query. + heights[i] = outPositions[iteratorIndex].GetZ(); + terrainExists[i] = outTerrainExists[iteratorIndex]; + break; + } + } +} + float TerrainSystem::GetHeightSynchronous(float x, float y, Sampler sampler, bool* terrainExistsPtr) const { bool terrainExists = false; @@ -315,6 +502,39 @@ bool TerrainSystem::GetIsHoleFromFloats(float x, float y, Sampler sampler) const return !terrainExists; } +void TerrainSystem::GetNormalsSynchronous(const AZStd::span& inPositions, Sampler sampler, + AZStd::span normals, AZStd::span terrainExists) const +{ + AZStd::vector directionVectors; + directionVectors.reserve(inPositions.size() * 4); + const AZ::Vector2 range(m_currentSettings.m_heightQueryResolution / 2.0f, m_currentSettings.m_heightQueryResolution / 2.0f); + size_t indexStepSize = 4; + for (auto& position : inPositions) + { + directionVectors.emplace_back(position.GetX(), position.GetY() - range.GetY(), 0.0f); + directionVectors.emplace_back(position.GetX() - range.GetX(), position.GetY(), 0.0f); + directionVectors.emplace_back(position.GetX() + range.GetX(), position.GetY(), 0.0f); + directionVectors.emplace_back(position.GetX(), position.GetY() + range.GetY(), 0.0f); + } + + AZStd::vector heights(directionVectors.size()); + AZStd::vector exists(directionVectors.size()); + GetHeightsSynchronous(directionVectors, sampler, heights, exists); + + for (size_t i = 0, iteratorIndex = 0; i < inPositions.size(); i++, iteratorIndex += indexStepSize) + { + directionVectors[iteratorIndex].SetZ(heights[iteratorIndex]); + directionVectors[iteratorIndex + 1].SetZ(heights[iteratorIndex + 1]); + directionVectors[iteratorIndex + 2].SetZ(heights[iteratorIndex + 2]); + directionVectors[iteratorIndex + 3].SetZ(heights[iteratorIndex + 3]); + + normals[i] = (directionVectors[iteratorIndex + 2] - directionVectors[iteratorIndex + 1]). + Cross(directionVectors[iteratorIndex + 3] - directionVectors[iteratorIndex]).GetNormalized(); + + terrainExists[i] = exists[iteratorIndex]; + } +} + AZ::Vector3 TerrainSystem::GetNormalSynchronous(float x, float y, Sampler sampler, bool* terrainExistsPtr) const { AZStd::shared_lock lock(m_areaMutex); @@ -471,6 +691,35 @@ AZ::EntityId TerrainSystem::FindBestAreaEntityAtPosition(float x, float y, AZ::A return AZ::EntityId(); } +void TerrainSystem::GetOrderedSurfaceWeightsFromList( + const AZStd::span& inPositions, + [[maybe_unused]] Sampler sampler, + AZStd::span outSurfaceWeightsList, + AZStd::span terrainExists) const +{ + if (terrainExists.size() == outSurfaceWeightsList.size()) + { + AZStd::vector heights(inPositions.size()); + GetHeightsSynchronous(inPositions, AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT, heights, terrainExists); + } + + auto callback = [](const AZStd::span inPositions, + [[maybe_unused]] AZStd::span outPositions, + [[maybe_unused]] AZStd::span outTerrainExists, + AZStd::span outSurfaceWeights, + AZ::EntityId areaId) + { + AZ_Assert(inPositions.size() == outSurfaceWeights.size(), + "The sizes of the surface weights list and in/out positions list should match."); + Terrain::TerrainAreaSurfaceRequestBus::Event(areaId, &Terrain::TerrainAreaSurfaceRequestBus::Events::GetSurfaceWeightsFromList, + inPositions, outSurfaceWeights); + }; + + // This will be unused for surface weights. It's fine if it's empty. + AZStd::vector outPositions; + MakeBulkQueries(inPositions, outPositions, terrainExists, outSurfaceWeightsList, callback); +} + void TerrainSystem::GetOrderedSurfaceWeights( const float x, const float y, @@ -551,13 +800,17 @@ void TerrainSystem::ProcessHeightsFromList( return; } + AZStd::vector terrainExists(inPositions.size()); + AZStd::vector heights(inPositions.size()); + + GetHeightsSynchronous(inPositions, sampleFilter, heights, terrainExists); + AzFramework::SurfaceData::SurfacePoint surfacePoint; - for (const auto& position : inPositions) + for (size_t i = 0; i < inPositions.size(); i++) { - bool terrainExists = false; - surfacePoint.m_position = position; - surfacePoint.m_position.SetZ(GetHeight(position, sampleFilter, &terrainExists)); - perPositionCallback(surfacePoint, terrainExists); + surfacePoint.m_position = inPositions[i]; + surfacePoint.m_position.SetZ(heights[i]); + perPositionCallback(surfacePoint, terrainExists[i]); } } @@ -571,13 +824,17 @@ void TerrainSystem::ProcessNormalsFromList( return; } + AZStd::vector terrainExists(inPositions.size()); + AZStd::vector normals(inPositions.size()); + + GetNormalsSynchronous(inPositions, sampleFilter, normals, terrainExists); + AzFramework::SurfaceData::SurfacePoint surfacePoint; - for (const auto& position : inPositions) + for (size_t i = 0; i < inPositions.size(); i++) { - bool terrainExists = false; - surfacePoint.m_position = position; - surfacePoint.m_normal = GetNormal(position, sampleFilter, &terrainExists); - perPositionCallback(surfacePoint, terrainExists); + surfacePoint.m_position = inPositions[i]; + surfacePoint.m_normal = AZStd::move(normals[i]); + perPositionCallback(surfacePoint, terrainExists[i]); } } @@ -591,13 +848,17 @@ void TerrainSystem::ProcessSurfaceWeightsFromList( return; } + AZStd::vector outSurfaceWeightsList(inPositions.size()); + AZStd::vector terrainExists(inPositions.size()); + + GetOrderedSurfaceWeightsFromList(inPositions, sampleFilter, outSurfaceWeightsList, terrainExists); + AzFramework::SurfaceData::SurfacePoint surfacePoint; - for (const auto& position : inPositions) + for (size_t i = 0; i < inPositions.size(); i++) { - bool terrainExists = false; - surfacePoint.m_position = position; - GetSurfaceWeights(position, surfacePoint.m_surfaceTags, sampleFilter, &terrainExists); - perPositionCallback(surfacePoint, terrainExists); + surfacePoint.m_position = inPositions[i]; + surfacePoint.m_surfaceTags = AZStd::move(outSurfaceWeightsList[i]); + perPositionCallback(surfacePoint, terrainExists[i]); } } @@ -611,13 +872,26 @@ void TerrainSystem::ProcessSurfacePointsFromList( return; } + AZStd::vector heights(inPositions.size()); + AZStd::vector normals(inPositions.size()); + AZStd::vector outSurfaceWeightsList(inPositions.size()); + AZStd::vector terrainExists(inPositions.size()); + + GetHeightsSynchronous(inPositions, sampleFilter, heights, terrainExists); + GetNormalsSynchronous(inPositions, sampleFilter, normals, terrainExists); + + // We can skip the unnecessary call to GetHeights since we already + // got the terrain exists flags in the earlier call to GetHeights + AZStd::vector terrainExistsEmpty; + GetOrderedSurfaceWeightsFromList(inPositions, sampleFilter, outSurfaceWeightsList, terrainExistsEmpty); + AzFramework::SurfaceData::SurfacePoint surfacePoint; - for (const auto& position : inPositions) + for (size_t i = 0; i < inPositions.size(); i++) { - bool terrainExists = false; - surfacePoint.m_position = position; - GetSurfacePoint(position, surfacePoint, sampleFilter, &terrainExists); - perPositionCallback(surfacePoint, terrainExists); + surfacePoint.m_position.Set(inPositions[i].GetX(), inPositions[i].GetY(), heights[i]); + surfacePoint.m_normal = AZStd::move(normals[i]); + surfacePoint.m_surfaceTags = AZStd::move(outSurfaceWeightsList[i]); + perPositionCallback(surfacePoint, terrainExists[i]); } } @@ -723,20 +997,23 @@ void TerrainSystem::ProcessHeightsFromRegion( return; } - const size_t numSamplesX = aznumeric_cast(ceil(inRegion.GetExtents().GetX() / stepSize.GetX())); - const size_t numSamplesY = aznumeric_cast(ceil(inRegion.GetExtents().GetY() / stepSize.GetY())); + const auto [numSamplesX, numSamplesY] = GetNumSamplesFromRegion(inRegion, stepSize); + + AZStd::vector inPositions = GenerateInputPositionsFromRegion(inRegion, stepSize); + + AZStd::vector terrainExists(inPositions.size()); + AZStd::vector heights(inPositions.size()); + + GetHeightsSynchronous(inPositions, sampleFilter, heights, terrainExists); AzFramework::SurfaceData::SurfacePoint surfacePoint; - for (size_t y = 0; y < numSamplesY; y++) + for (size_t y = 0, i = 0; y < numSamplesY; y++) { - float fy = aznumeric_cast(inRegion.GetMin().GetY() + (y * stepSize.GetY())); for (size_t x = 0; x < numSamplesX; x++) { - bool terrainExists = false; - float fx = aznumeric_cast(inRegion.GetMin().GetX() + (x * stepSize.GetX())); - surfacePoint.m_position.Set(fx, fy, 0.0f); - surfacePoint.m_position.SetZ(GetHeight(surfacePoint.m_position, sampleFilter, &terrainExists)); - perPositionCallback(x, y, surfacePoint, terrainExists); + surfacePoint.m_position.Set(inPositions[i].GetX(), inPositions[i].GetY(), heights[i]); + perPositionCallback(x, y, surfacePoint, terrainExists[i]); + i++; } } } @@ -753,20 +1030,24 @@ void TerrainSystem::ProcessNormalsFromRegion( return; } - const size_t numSamplesX = aznumeric_cast(ceil(inRegion.GetExtents().GetX() / stepSize.GetX())); - const size_t numSamplesY = aznumeric_cast(ceil(inRegion.GetExtents().GetY() / stepSize.GetY())); + const auto [numSamplesX, numSamplesY] = GetNumSamplesFromRegion(inRegion, stepSize); + + AZStd::vector inPositions = GenerateInputPositionsFromRegion(inRegion, stepSize); + + AZStd::vector terrainExists(inPositions.size()); + AZStd::vector normals(inPositions.size()); + + GetNormalsSynchronous(inPositions, sampleFilter, normals, terrainExists); AzFramework::SurfaceData::SurfacePoint surfacePoint; - for (size_t y = 0; y < numSamplesY; y++) + for (size_t y = 0, i = 0; y < numSamplesY; y++) { - float fy = aznumeric_cast(inRegion.GetMin().GetY() + (y * stepSize.GetY())); for (size_t x = 0; x < numSamplesX; x++) { - bool terrainExists = false; - float fx = aznumeric_cast(inRegion.GetMin().GetX() + (x * stepSize.GetX())); - surfacePoint.m_position.Set(fx, fy, 0.0f); - surfacePoint.m_normal = GetNormal(surfacePoint.m_position, sampleFilter, &terrainExists); - perPositionCallback(x, y, surfacePoint, terrainExists); + surfacePoint.m_position.Set(inPositions[i].GetX(), inPositions[i].GetY(), 0.0f); + surfacePoint.m_normal = AZStd::move(normals[i]); + perPositionCallback(x, y, surfacePoint, terrainExists[i]); + i++; } } } @@ -783,20 +1064,24 @@ void TerrainSystem::ProcessSurfaceWeightsFromRegion( return; } - const size_t numSamplesX = aznumeric_cast(ceil(inRegion.GetExtents().GetX() / stepSize.GetX())); - const size_t numSamplesY = aznumeric_cast(ceil(inRegion.GetExtents().GetY() / stepSize.GetY())); + const auto [numSamplesX, numSamplesY] = GetNumSamplesFromRegion(inRegion, stepSize); + + AZStd::vector inPositions = GenerateInputPositionsFromRegion(inRegion, stepSize); + + AZStd::vector outSurfaceWeightsList(inPositions.size()); + AZStd::vector terrainExists(inPositions.size()); + + GetOrderedSurfaceWeightsFromList(inPositions, sampleFilter, outSurfaceWeightsList, terrainExists); AzFramework::SurfaceData::SurfacePoint surfacePoint; - for (size_t y = 0; y < numSamplesY; y++) + for (size_t y = 0, i = 0; y < numSamplesY; y++) { - float fy = aznumeric_cast(inRegion.GetMin().GetY() + (y * stepSize.GetY())); for (size_t x = 0; x < numSamplesX; x++) { - bool terrainExists = false; - float fx = aznumeric_cast(inRegion.GetMin().GetX() + (x * stepSize.GetX())); - surfacePoint.m_position.Set(fx, fy, 0.0f); - GetSurfaceWeights(surfacePoint.m_position, surfacePoint.m_surfaceTags, sampleFilter, &terrainExists); - perPositionCallback(x, y, surfacePoint, terrainExists); + surfacePoint.m_position.Set(inPositions[i].GetX(), inPositions[i].GetY(), 0.0f); + surfacePoint.m_surfaceTags = AZStd::move(outSurfaceWeightsList[i]); + perPositionCallback(x, y, surfacePoint, terrainExists[i]); + i++; } } } @@ -813,20 +1098,33 @@ void TerrainSystem::ProcessSurfacePointsFromRegion( return; } - const size_t numSamplesX = aznumeric_cast(ceil(inRegion.GetExtents().GetX() / stepSize.GetX())); - const size_t numSamplesY = aznumeric_cast(ceil(inRegion.GetExtents().GetY() / stepSize.GetY())); + const auto [numSamplesX, numSamplesY] = GetNumSamplesFromRegion(inRegion, stepSize); + + AZStd::vector inPositions = GenerateInputPositionsFromRegion(inRegion, stepSize); + + AZStd::vector heights(inPositions.size()); + AZStd::vector normals(inPositions.size()); + AZStd::vector outSurfaceWeightsList(inPositions.size()); + AZStd::vector terrainExists(inPositions.size()); + + GetHeightsSynchronous(inPositions, sampleFilter, heights, terrainExists); + GetNormalsSynchronous(inPositions, sampleFilter, normals, terrainExists); + + // We can skip the unnecessary call to GetHeights since we already + // got the terrain exists flags in the earlier call to GetHeights + AZStd::vector terrainExistsEmpty; + GetOrderedSurfaceWeightsFromList(inPositions, sampleFilter, outSurfaceWeightsList, terrainExistsEmpty); AzFramework::SurfaceData::SurfacePoint surfacePoint; - for (size_t y = 0; y < numSamplesY; y++) + for (size_t y = 0, i = 0; y < numSamplesY; y++) { - float fy = aznumeric_cast(inRegion.GetMin().GetY() + (y * stepSize.GetY())); for (size_t x = 0; x < numSamplesX; x++) { - bool terrainExists = false; - float fx = aznumeric_cast(inRegion.GetMin().GetX() + (x * stepSize.GetX())); - surfacePoint.m_position.Set(fx, fy, 0.0f); - GetSurfacePoint(surfacePoint.m_position, surfacePoint, sampleFilter, &terrainExists); - perPositionCallback(x, y, surfacePoint, terrainExists); + surfacePoint.m_position.Set(inPositions[i].GetX(), inPositions[i].GetY(), heights[i]); + surfacePoint.m_normal = AZStd::move(normals[i]); + surfacePoint.m_surfaceTags = AZStd::move(outSurfaceWeightsList[i]); + perPositionCallback(x, y, surfacePoint, terrainExists[i]); + i++; } } } diff --git a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h index e0457b80af..7895ab96cc 100644 --- a/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h +++ b/Gems/Terrain/Code/Source/TerrainSystem/TerrainSystem.h @@ -207,6 +207,38 @@ namespace Terrain float GetTerrainAreaHeight(float x, float y, bool& terrainExists) const; AZ::Vector3 GetNormalSynchronous(float x, float y, Sampler sampler, bool* terrainExistsPtr) const; + typedef AZStd::function inPositions, + AZStd::span outPositions, + AZStd::span outTerrainExists, + AZStd::span outSurfaceWeights, + AZ::EntityId areaId)> BulkQueriesCallback; + + void GetHeightsSynchronous( + const AZStd::span& inPositions, + Sampler sampler, AZStd::span heights, + AZStd::span terrainExists) const; + void GetNormalsSynchronous( + const AZStd::span& inPositions, + Sampler sampler, AZStd::span normals, + AZStd::span terrainExists) const; + void GetOrderedSurfaceWeightsFromList( + const AZStd::span& inPositions, Sampler sampler, + AZStd::span outSurfaceWeightsList, + AZStd::span terrainExists) const; + void MakeBulkQueries( + const AZStd::span inPositions, + AZStd::span outPositions, + AZStd::span outTerrainExists, + AZStd::span outSurfaceWieghts, + BulkQueriesCallback queryCallback) const; + void GenerateQueryPositions(const AZStd::span& inPositions, + AZStd::vector& outPositions, + Sampler sampler) const; + AZStd::vector GenerateInputPositionsFromRegion( + const AZ::Aabb& inRegion, + const AZ::Vector2& stepSize) const; + // AZ::TickBus::Handler overrides ... void OnTick(float deltaTime, AZ::ScriptTimePoint time) override; diff --git a/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp b/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp index 2c01a3d455..1277e9ed20 100644 --- a/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp +++ b/Gems/Terrain/Code/Tests/TerrainSystemTest.cpp @@ -158,6 +158,15 @@ namespace UnitTest // Let the test function modify these values based on the needs of the specific test. mockHeights(outPosition, terrainExists); }); + ON_CALL(*m_terrainAreaHeightRequests, GetHeights) + .WillByDefault( + [mockHeights](AZStd::span inOutPositionList, AZStd::span terrainExistsList) + { + for (int i = 0; i < inOutPositionList.size(); i++) + { + mockHeights(inOutPositionList[i], terrainExistsList[i]); + } + }); ActivateEntity(entity.get()); return entity; @@ -184,9 +193,9 @@ namespace UnitTest tagWeight3.m_weight = 0.3f; expectedTags.push_back(tagWeight3); - m_terrainAreaSurfaceRequests = AZStd::make_unique>(entity->GetId()); - ON_CALL(*m_terrainAreaSurfaceRequests, GetSurfaceWeights).WillByDefault( - [tagWeight1, tagWeight2, tagWeight3](const AZ::Vector3& position, AzFramework::SurfaceData::SurfaceTagWeightList& surfaceWeights) + auto mockGetSurfaceWeights = [tagWeight1, tagWeight2, tagWeight3]( + const AZ::Vector3& position, + AzFramework::SurfaceData::SurfaceTagWeightList& surfaceWeights) { surfaceWeights.clear(); float absYPos = fabsf(position.GetY()); @@ -202,6 +211,19 @@ namespace UnitTest { surfaceWeights.push_back(tagWeight3); } + }; + + m_terrainAreaSurfaceRequests = AZStd::make_unique>(entity->GetId()); + ON_CALL(*m_terrainAreaSurfaceRequests, GetSurfaceWeights).WillByDefault(mockGetSurfaceWeights); + ON_CALL(*m_terrainAreaSurfaceRequests, GetSurfaceWeightsFromList).WillByDefault( + [mockGetSurfaceWeights]( + AZStd::span inPositionList, + AZStd::span outSurfaceWeightsList) + { + for (size_t i = 0; i < inPositionList.size(); i++) + { + mockGetSurfaceWeights(inPositionList[i], outSurfaceWeightsList[i]); + } } ); } From 6791b652cc3a544ad3650ec69b99a594a4b39caf Mon Sep 17 00:00:00 2001 From: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> Date: Thu, 10 Feb 2022 10:17:01 -0600 Subject: [PATCH 22/27] Fix memory allocation that caused benchmark runs to crash. (#7535) Signed-off-by: Mike Balfour <82224783+mbalfour-amzn@users.noreply.github.com> --- Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h b/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h index c45af43ad9..4d2233528b 100644 --- a/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h +++ b/Gems/GradientSignal/Code/Tests/GradientSignalTestFixtures.h @@ -90,7 +90,7 @@ namespace UnitTest AZStd::unique_ptr BuildTestSurfaceMaskGradient(float shapeHalfBounds); AZStd::unique_ptr BuildTestSurfaceSlopeGradient(float shapeHalfBounds); - AZ::RPI::AssetHandlerPtrList m_assetHandlers; + AZStd::fixed_vector, 2> m_assetHandlers; }; struct GradientSignalTest From 27abad7564ca607900d6d7d6ca42b5dbf6832699 Mon Sep 17 00:00:00 2001 From: Steve Pham <82231385+spham-amzn@users.noreply.github.com> Date: Thu, 10 Feb 2022 13:32:22 -0800 Subject: [PATCH 23/27] Fix Mac SQL Package (#7538) * Update mac SQLite3 package to fix bad version Signed-off-by: spham <82231385+spham-amzn@users.noreply.github.com> --- cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake index ae51076857..c0bc9060d4 100644 --- a/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake +++ b/cmake/3rdParty/Platform/Mac/BuiltInPackages_mac.cmake @@ -42,5 +42,5 @@ ly_associate_package(PACKAGE_NAME astc-encoder-3.2-rev5-mac ly_associate_package(PACKAGE_NAME ISPCTexComp-36b80aa-rev1-mac TARGETS ISPCTexComp PACKAGE_HASH 8a4e93277b8face6ea2fd57c6d017bdb55643ed3d6387110bc5f6b3b884dd169) ly_associate_package(PACKAGE_NAME lz4-1.9.3-vcpkg-rev4-mac TARGETS lz4 PACKAGE_HASH 891ff630bf34f7ab1d8eaee2ea0a8f1fca89dbdc63fca41ee592703dd488a73b) ly_associate_package(PACKAGE_NAME azslc-1.7.35-rev1-mac TARGETS azslc PACKAGE_HASH 03cb1ea8c47d4c80c893e2e88767272d5d377838f5ba94b777a45902dd85052e) -ly_associate_package(PACKAGE_NAME SQLite-3.37.2-rev1-mac TARGETS SQLite PACKAGE_HASH f9101023f99cf32fc5867284ceb28c0761c23d2c5a4b1748349c69f976a2fbea) +ly_associate_package(PACKAGE_NAME SQLite-3.37.2-rev2-mac TARGETS SQLite PACKAGE_HASH b7d9abdb68045003e030e1a9a805db1aefa5e8fde6dccfbb4fab3a06249a41fc) ly_associate_package(PACKAGE_NAME AwsIotDeviceSdkCpp-1.15.2-rev2-mac TARGETS AwsIotDeviceSdkCpp PACKAGE_HASH 4854edb7b88fa6437b4e69e87d0ee111a25313ac2a2db5bb2f8b674ba0974f95) From 1865e3085e31443a10bce97d1e11b81957ab2dcc Mon Sep 17 00:00:00 2001 From: puvvadar Date: Thu, 10 Feb 2022 14:17:39 -0800 Subject: [PATCH 24/27] Fix improper early out skipping valid entities Signed-off-by: puvvadar --- .../Code/Source/NetworkTime/NetworkTime.cpp | 63 +++--- .../Source/NetworkTime/NetworkTime.cpp.orig | 187 ++++++++++++++++++ 2 files changed, 217 insertions(+), 33 deletions(-) create mode 100644 Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp.orig diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp index 899640895d..c6b6385845 100644 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp @@ -113,7 +113,7 @@ namespace Multiplayer NetworkEntityTracker* networkEntityTracker = GetNetworkEntityTracker(); AzFramework::IEntityBoundsUnion* entityBoundsUnion = AZ::Interface::Get(); AZ::Interface::Get()->GetDefaultVisibilityScene()->Enumerate(expandedVolume, - [this, debugDisplay, networkEntityTracker, entityBoundsUnion, expandedVolume](const AzFramework::IVisibilityScene::NodeData& nodeData) + [this, debugDisplay, networkEntityTracker, entityBoundsUnion, rewindVolume](const AzFramework::IVisibilityScene::NodeData& nodeData) { m_rewoundEntities.reserve(m_rewoundEntities.size() + nodeData.m_entries.size()); for (AzFramework::VisibilityEntry* visEntry : nodeData.m_entries) @@ -122,44 +122,41 @@ namespace Multiplayer { AZ::Entity* entity = static_cast(visEntry->m_userData); NetworkEntityHandle entityHandle(entity, networkEntityTracker); - if (entityHandle.GetNetBindComponent() == nullptr) + if (entityHandle.GetNetBindComponent() != nullptr) { - // Not a net-bound entity, terminate processing of this entity - return; - } - - const AZ::Aabb currentBounds = entityBoundsUnion->GetEntityWorldBoundsUnion(entity->GetId()); - const AZ::Vector3 currentCenter = currentBounds.GetCenter(); - NetworkTransformComponent* networkTransform = entity->template FindComponent(); - if (debugDisplay) - { - debugDisplay->SetColor(AZ::Colors::White); - debugDisplay->DrawWireBox(currentBounds.GetMin(), currentBounds.GetMax()); - } - - if (networkTransform != nullptr) - { - // Get the rewound position for target host frame ID plus the one preceding it for potential lerp - AZ::Vector3 rewindCenter = networkTransform->GetTranslation(); - const AZ::Vector3 rewindCenterPrevious = networkTransform->GetTranslationPrevious(); - const float blendFactor = GetNetworkTime()->GetHostBlendFactor(); - if (!AZ::IsClose(blendFactor, 1.0f) && !rewindCenter.IsClose(rewindCenterPrevious)) - { - // If we have a blend factor, lerp the translation for accuracy - rewindCenter = rewindCenterPrevious.Lerp(rewindCenter, blendFactor); - } - const AZ::Vector3 rewindOffset = rewindCenter - currentCenter; // Compute offset between rewound and current positions - const AZ::Aabb rewoundAabb = currentBounds.GetTranslated(rewindOffset); // Apply offset to the entity aabb + const AZ::Aabb currentBounds = entityBoundsUnion->GetEntityWorldBoundsUnion(entity->GetId()); + const AZ::Vector3 currentCenter = currentBounds.GetCenter(); + NetworkTransformComponent* networkTransform = entity->template FindComponent(); if (debugDisplay) { - debugDisplay->SetColor(AZ::Colors::Grey); - debugDisplay->DrawWireBox(rewoundAabb.GetMin(), rewoundAabb.GetMax()); + debugDisplay->SetColor(AZ::Colors::White); + debugDisplay->DrawWireBox(currentBounds.GetMin(), currentBounds.GetMax()); } - if (AZ::ShapeIntersection::Overlaps(rewoundAabb, expandedVolume)) // Validate the rewound aabb intersects our rewind volume + if (networkTransform != nullptr) { - m_rewoundEntities.push_back(entityHandle); - entityHandle.GetNetBindComponent()->NotifySyncRewindState(); + // Get the rewound position for target host frame ID plus the one preceding it for potential lerp + AZ::Vector3 rewindCenter = networkTransform->GetTranslation(); + const AZ::Vector3 rewindCenterPrevious = networkTransform->GetTranslationPrevious(); + const float blendFactor = GetNetworkTime()->GetHostBlendFactor(); + if (!AZ::IsClose(blendFactor, 1.0f) && !rewindCenter.IsClose(rewindCenterPrevious)) + { + // If we have a blend factor, lerp the translation for accuracy + rewindCenter = rewindCenterPrevious.Lerp(rewindCenter, blendFactor); + } + const AZ::Vector3 rewindOffset = rewindCenter - currentCenter; // Compute offset between rewound and current positions + const AZ::Aabb rewoundAabb = currentBounds.GetTranslated(rewindOffset); // Apply offset to the entity aabb + if (debugDisplay) + { + debugDisplay->SetColor(AZ::Colors::Grey); + debugDisplay->DrawWireBox(rewoundAabb.GetMin(), rewoundAabb.GetMax()); + } + + if (AZ::ShapeIntersection::Overlaps(rewoundAabb, rewindVolume)) // Validate the rewound aabb intersects our rewind volume + { + m_rewoundEntities.push_back(entityHandle); + entityHandle.GetNetBindComponent()->NotifySyncRewindState(); + } } } } diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp.orig b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp.orig new file mode 100644 index 0000000000..26d53a50e1 --- /dev/null +++ b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp.orig @@ -0,0 +1,187 @@ +/* + * 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 Multiplayer +{ + AZ_CVAR(float, sv_RewindVolumeExtrudeDistance, 50.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "The amount to increase rewind volume checks to account for fast moving entities"); + AZ_CVAR(bool, bg_RewindDebugDraw, false, nullptr, AZ::ConsoleFunctorFlags::Null, "If true enables debug draw of rewind operations"); + + NetworkTime::NetworkTime() + { + AZ::Interface::Register(this); + } + + NetworkTime::~NetworkTime() + { + AZ::Interface::Unregister(this); + } + + bool NetworkTime::IsTimeRewound() const + { + return m_rewindingConnectionId != AzNetworking::InvalidConnectionId; + } + + HostFrameId NetworkTime::GetHostFrameId() const + { + return m_hostFrameId; + } + + HostFrameId NetworkTime::GetUnalteredHostFrameId() const + { + return m_unalteredFrameId; + } + + void NetworkTime::IncrementHostFrameId() + { + AZ_Assert(!IsTimeRewound(), "Incrementing the global application frameId is unsupported under a rewound time scope"); + ++m_unalteredFrameId; + m_hostFrameId = m_unalteredFrameId; + } + + AZ::TimeMs NetworkTime::GetHostTimeMs() const + { + return m_hostTimeMs; + } + + float NetworkTime::GetHostBlendFactor() const + { + return m_hostBlendFactor; + } + + AzNetworking::ConnectionId NetworkTime::GetRewindingConnectionId() const + { + return m_rewindingConnectionId; + } + + void NetworkTime::ForceSetTime(HostFrameId frameId, AZ::TimeMs timeMs) + { + AZ_Assert(!IsTimeRewound(), "Forcibly setting network time is unsupported under a rewound time scope"); + m_unalteredFrameId = frameId; + m_hostFrameId = frameId; + m_hostTimeMs = timeMs; + m_rewindingConnectionId = AzNetworking::InvalidConnectionId; + } + + void NetworkTime::AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, float blendFactor, AzNetworking::ConnectionId rewindConnectionId) + { + m_hostFrameId = frameId; + m_hostTimeMs = timeMs; + m_hostBlendFactor = blendFactor; + m_rewindingConnectionId = rewindConnectionId; + } + + void NetworkTime::SyncEntitiesToRewindState(const AZ::Aabb& rewindVolume) + { + if (!IsTimeRewound()) + { + // If we're not inside a rewind scope then reset any rewound state and exit + ClearRewoundEntities(); + return; + } + + // Since the vis system doesn't support rewound queries, first query with an expanded volume to catch any fast moving entities + const AZ::Aabb expandedVolume = rewindVolume.GetExpanded(AZ::Vector3(sv_RewindVolumeExtrudeDistance)); + + AzFramework::DebugDisplayRequests* debugDisplay = nullptr; + if (bg_RewindDebugDraw) + { + AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus; + AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId); + debugDisplay = AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus); + } + + if (debugDisplay) + { + debugDisplay->SetColor(AZ::Colors::Red); + debugDisplay->DrawWireBox(expandedVolume.GetMin(), expandedVolume.GetMax()); + } + + NetworkEntityTracker* networkEntityTracker = GetNetworkEntityTracker(); + AzFramework::IEntityBoundsUnion* entityBoundsUnion = AZ::Interface::Get(); + AZ::Interface::Get()->GetDefaultVisibilityScene()->Enumerate(expandedVolume, + [this, debugDisplay, networkEntityTracker, entityBoundsUnion, expandedVolume](const AzFramework::IVisibilityScene::NodeData& nodeData) + { + m_rewoundEntities.reserve(m_rewoundEntities.size() + nodeData.m_entries.size()); + for (AzFramework::VisibilityEntry* visEntry : nodeData.m_entries) + { + if (visEntry->m_typeFlags & AzFramework::VisibilityEntry::TypeFlags::TYPE_Entity) + { + AZ::Entity* entity = static_cast(visEntry->m_userData); + NetworkEntityHandle entityHandle(entity, networkEntityTracker); + if (entityHandle.GetNetBindComponent() != nullptr) + { + const AZ::Aabb currentBounds = entityBoundsUnion->GetEntityWorldBoundsUnion(entity->GetId()); + const AZ::Vector3 currentCenter = currentBounds.GetCenter(); + NetworkTransformComponent* networkTransform = entity->template FindComponent(); + if (debugDisplay) + { + debugDisplay->SetColor(AZ::Colors::White); + debugDisplay->DrawWireBox(currentBounds.GetMin(), currentBounds.GetMax()); + } + +<<<<<<< Updated upstream + if (AZ::ShapeIntersection::Overlaps(rewoundAabb, expandedVolume)) // Validate the rewound aabb intersects our rewind volume + { + m_rewoundEntities.push_back(entityHandle); + entityHandle.GetNetBindComponent()->NotifySyncRewindState(); +======= + if (networkTransform != nullptr) + { + // Get the rewound position for target host frame ID plus the one preceding it for potential lerp + AZ::Vector3 rewindCenter = networkTransform->GetTranslation(); + const AZ::Vector3 rewindCenterPrevious = networkTransform->GetTranslationPrevious(); + const float blendFactor = GetNetworkTime()->GetHostBlendFactor(); + if (!AZ::IsClose(blendFactor, 1.0f) && !rewindCenter.IsClose(rewindCenterPrevious)) + { + // If we have a blend factor, lerp the translation for accuracy + rewindCenter = rewindCenterPrevious.Lerp(rewindCenter, blendFactor); + } + const AZ::Vector3 rewindOffset = rewindCenter - currentCenter; // Compute offset between rewound and current positions + const AZ::Aabb rewoundAabb = currentBounds.GetTranslated(rewindOffset); // Apply offset to the entity aabb + if (debugDisplay) + { + debugDisplay->SetColor(AZ::Colors::Grey); + debugDisplay->DrawWireBox(rewoundAabb.GetMin(), rewoundAabb.GetMax()); + } + + if (AZ::ShapeIntersection::Overlaps(rewoundAabb, rewindVolume)) // Validate the rewound aabb intersects our rewind volume + { + m_rewoundEntities.push_back(entityHandle); + entityHandle.GetNetBindComponent()->NotifySyncRewindState(); + } +>>>>>>> Stashed changes + } + } + } + } + }); + } + + void NetworkTime::ClearRewoundEntities() + { + AZ_Assert(!IsTimeRewound(), "Cannot clear rewound entity state while still within scoped rewind"); + + for (NetworkEntityHandle entityHandle : m_rewoundEntities) + { + if (NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent()) + { + netBindComponent->NotifySyncRewindState(); + } + } + m_rewoundEntities.clear(); + } +} From 1adfd4e3f9b8a3062c424dbe354572af427fc8c5 Mon Sep 17 00:00:00 2001 From: puvvadar Date: Thu, 10 Feb 2022 14:24:00 -0800 Subject: [PATCH 25/27] Delete merge artifact that snuck in Signed-off-by: puvvadar --- .../Source/NetworkTime/NetworkTime.cpp.orig | 187 ------------------ 1 file changed, 187 deletions(-) delete mode 100644 Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp.orig diff --git a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp.orig b/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp.orig deleted file mode 100644 index 26d53a50e1..0000000000 --- a/Gems/Multiplayer/Code/Source/NetworkTime/NetworkTime.cpp.orig +++ /dev/null @@ -1,187 +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 Multiplayer -{ - AZ_CVAR(float, sv_RewindVolumeExtrudeDistance, 50.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "The amount to increase rewind volume checks to account for fast moving entities"); - AZ_CVAR(bool, bg_RewindDebugDraw, false, nullptr, AZ::ConsoleFunctorFlags::Null, "If true enables debug draw of rewind operations"); - - NetworkTime::NetworkTime() - { - AZ::Interface::Register(this); - } - - NetworkTime::~NetworkTime() - { - AZ::Interface::Unregister(this); - } - - bool NetworkTime::IsTimeRewound() const - { - return m_rewindingConnectionId != AzNetworking::InvalidConnectionId; - } - - HostFrameId NetworkTime::GetHostFrameId() const - { - return m_hostFrameId; - } - - HostFrameId NetworkTime::GetUnalteredHostFrameId() const - { - return m_unalteredFrameId; - } - - void NetworkTime::IncrementHostFrameId() - { - AZ_Assert(!IsTimeRewound(), "Incrementing the global application frameId is unsupported under a rewound time scope"); - ++m_unalteredFrameId; - m_hostFrameId = m_unalteredFrameId; - } - - AZ::TimeMs NetworkTime::GetHostTimeMs() const - { - return m_hostTimeMs; - } - - float NetworkTime::GetHostBlendFactor() const - { - return m_hostBlendFactor; - } - - AzNetworking::ConnectionId NetworkTime::GetRewindingConnectionId() const - { - return m_rewindingConnectionId; - } - - void NetworkTime::ForceSetTime(HostFrameId frameId, AZ::TimeMs timeMs) - { - AZ_Assert(!IsTimeRewound(), "Forcibly setting network time is unsupported under a rewound time scope"); - m_unalteredFrameId = frameId; - m_hostFrameId = frameId; - m_hostTimeMs = timeMs; - m_rewindingConnectionId = AzNetworking::InvalidConnectionId; - } - - void NetworkTime::AlterTime(HostFrameId frameId, AZ::TimeMs timeMs, float blendFactor, AzNetworking::ConnectionId rewindConnectionId) - { - m_hostFrameId = frameId; - m_hostTimeMs = timeMs; - m_hostBlendFactor = blendFactor; - m_rewindingConnectionId = rewindConnectionId; - } - - void NetworkTime::SyncEntitiesToRewindState(const AZ::Aabb& rewindVolume) - { - if (!IsTimeRewound()) - { - // If we're not inside a rewind scope then reset any rewound state and exit - ClearRewoundEntities(); - return; - } - - // Since the vis system doesn't support rewound queries, first query with an expanded volume to catch any fast moving entities - const AZ::Aabb expandedVolume = rewindVolume.GetExpanded(AZ::Vector3(sv_RewindVolumeExtrudeDistance)); - - AzFramework::DebugDisplayRequests* debugDisplay = nullptr; - if (bg_RewindDebugDraw) - { - AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus; - AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, AzFramework::g_defaultSceneEntityDebugDisplayId); - debugDisplay = AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus); - } - - if (debugDisplay) - { - debugDisplay->SetColor(AZ::Colors::Red); - debugDisplay->DrawWireBox(expandedVolume.GetMin(), expandedVolume.GetMax()); - } - - NetworkEntityTracker* networkEntityTracker = GetNetworkEntityTracker(); - AzFramework::IEntityBoundsUnion* entityBoundsUnion = AZ::Interface::Get(); - AZ::Interface::Get()->GetDefaultVisibilityScene()->Enumerate(expandedVolume, - [this, debugDisplay, networkEntityTracker, entityBoundsUnion, expandedVolume](const AzFramework::IVisibilityScene::NodeData& nodeData) - { - m_rewoundEntities.reserve(m_rewoundEntities.size() + nodeData.m_entries.size()); - for (AzFramework::VisibilityEntry* visEntry : nodeData.m_entries) - { - if (visEntry->m_typeFlags & AzFramework::VisibilityEntry::TypeFlags::TYPE_Entity) - { - AZ::Entity* entity = static_cast(visEntry->m_userData); - NetworkEntityHandle entityHandle(entity, networkEntityTracker); - if (entityHandle.GetNetBindComponent() != nullptr) - { - const AZ::Aabb currentBounds = entityBoundsUnion->GetEntityWorldBoundsUnion(entity->GetId()); - const AZ::Vector3 currentCenter = currentBounds.GetCenter(); - NetworkTransformComponent* networkTransform = entity->template FindComponent(); - if (debugDisplay) - { - debugDisplay->SetColor(AZ::Colors::White); - debugDisplay->DrawWireBox(currentBounds.GetMin(), currentBounds.GetMax()); - } - -<<<<<<< Updated upstream - if (AZ::ShapeIntersection::Overlaps(rewoundAabb, expandedVolume)) // Validate the rewound aabb intersects our rewind volume - { - m_rewoundEntities.push_back(entityHandle); - entityHandle.GetNetBindComponent()->NotifySyncRewindState(); -======= - if (networkTransform != nullptr) - { - // Get the rewound position for target host frame ID plus the one preceding it for potential lerp - AZ::Vector3 rewindCenter = networkTransform->GetTranslation(); - const AZ::Vector3 rewindCenterPrevious = networkTransform->GetTranslationPrevious(); - const float blendFactor = GetNetworkTime()->GetHostBlendFactor(); - if (!AZ::IsClose(blendFactor, 1.0f) && !rewindCenter.IsClose(rewindCenterPrevious)) - { - // If we have a blend factor, lerp the translation for accuracy - rewindCenter = rewindCenterPrevious.Lerp(rewindCenter, blendFactor); - } - const AZ::Vector3 rewindOffset = rewindCenter - currentCenter; // Compute offset between rewound and current positions - const AZ::Aabb rewoundAabb = currentBounds.GetTranslated(rewindOffset); // Apply offset to the entity aabb - if (debugDisplay) - { - debugDisplay->SetColor(AZ::Colors::Grey); - debugDisplay->DrawWireBox(rewoundAabb.GetMin(), rewoundAabb.GetMax()); - } - - if (AZ::ShapeIntersection::Overlaps(rewoundAabb, rewindVolume)) // Validate the rewound aabb intersects our rewind volume - { - m_rewoundEntities.push_back(entityHandle); - entityHandle.GetNetBindComponent()->NotifySyncRewindState(); - } ->>>>>>> Stashed changes - } - } - } - } - }); - } - - void NetworkTime::ClearRewoundEntities() - { - AZ_Assert(!IsTimeRewound(), "Cannot clear rewound entity state while still within scoped rewind"); - - for (NetworkEntityHandle entityHandle : m_rewoundEntities) - { - if (NetBindComponent* netBindComponent = entityHandle.GetNetBindComponent()) - { - netBindComponent->NotifySyncRewindState(); - } - } - m_rewoundEntities.clear(); - } -} From 7150a28ed6050bd27e5a8fc97d556080f7d45c48 Mon Sep 17 00:00:00 2001 From: moraaar Date: Fri, 11 Feb 2022 09:08:33 +0000 Subject: [PATCH 26/27] Mesh Component: Add button to the Mesh Asset field to open mesh FBX settings (#7547) This is an UX improvement for Mesh Component as the user can quickly access FBX settings of the mesh to modify it if they so desire. Video https://user-images.githubusercontent.com/27999040/153414278-f7996b9a-8a28-49d4-92a8-daeb9924b148.mp4 Signed-off-by: moraaar moraaar@amazon.com --- .../RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp | 10 ++++++++++ .../Code/Source/Mesh/EditorMeshComponent.cpp | 3 +++ 2 files changed, 13 insertions(+) diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp index 6780763d7c..5685dfece2 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Model/ModelAsset.cpp @@ -15,6 +15,7 @@ #include #include +#include namespace AZ { @@ -35,6 +36,15 @@ namespace AZ ->Field("MaterialSlots", &ModelAsset::m_materialSlots) ->Field("LodAssets", &ModelAsset::m_lodAssets) ; + + // Note: This class needs to have edit context reflection so PropertyAssetCtrl::OnEditButtonClicked + // can open the asset with the preferred asset editor (Scene Settings). + if (auto* editContext = serializeContext->GetEditContext()) + { + editContext->Class("Model Asset", "") + ->ClassElement(AZ::Edit::ClassElements::EditorData, "") + ; + } } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp index 255f639cd7..0d6b87e795 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/Mesh/EditorMeshComponent.cpp @@ -72,6 +72,9 @@ namespace AZ ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentConfig::m_modelAsset, "Mesh Asset", "Mesh asset reference") + ->Attribute(AZ_CRC_CE("EditButton"), "") + ->Attribute(AZ_CRC_CE("EditDescription"), "Open in Scene Settings") + ->Attribute(AZ_CRC_CE("DisableEditButtonWhenNoAssetSelected"), true) ->DataElement(AZ::Edit::UIHandlers::Default, &MeshComponentConfig::m_sortKey, "Sort Key", "Transparent meshes are drawn by sort key then depth. Used this to force certain transparent meshes to draw before or after others.") ->Attribute(AZ::Edit::Attributes::Visibility, &MeshComponentConfig::IsAssetSet) ->DataElement(AZ::Edit::UIHandlers::CheckBox, &MeshComponentConfig::m_excludeFromReflectionCubeMaps, "Exclude from reflection cubemaps", "Mesh will not be visible in baked reflection probe cubemaps") From dbb4e76a3da883f4b0c196798cbf234294e7f602 Mon Sep 17 00:00:00 2001 From: evanchia-ly-sdets <80914607+evanchia-ly-sdets@users.noreply.github.com> Date: Fri, 11 Feb 2022 09:02:22 -0800 Subject: [PATCH 27/27] updating python packages py, pillow, and urllib3 (#7155) * updating python packages py, pillow, and urllib3 Signed-off-by: evanchia * updating dependencies versions as well Signed-off-by: evanchia --- python/requirements.txt | 105 +++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 45 deletions(-) diff --git a/python/requirements.txt b/python/requirements.txt index 9648a20ba0..c000be48de 100644 --- a/python/requirements.txt +++ b/python/requirements.txt @@ -6,13 +6,13 @@ attrs==20.1.0 \ --hash=sha256:0ef97238856430dcf9228e07f316aefc17e8939fc8507e18c6501b761ef1a42a \ --hash=sha256:2867b7b9f8326499ab5b0e2d12801fa5c98842d2cbd22b35112ae04bf85b4dff # via -r .\requirements.txt -boto3==1.12.21 \ - --hash=sha256:50105a25e301e20b361b2b8fafee196a425a4758e51f400a0f381d42e4bd909e \ - --hash=sha256:5fe70e656f92e4e649dc4cf05786f57d180e5d491bcb22c80411512ec2b27c15 \ +boto3==1.20.44 \ + --hash=sha256:26f18ca7411615f33d8d1bf60cc8efe5b331a57b3013d5f8f3587cd5350c27cb \ + --hash=sha256:4470f64e4af609ff678055338c96a6f7cbe601d1fb06a4ea7dc8d9223c2e527a \ # via -r .\requirements.txt -botocore==1.15.21 \ - --hash=sha256:4aaf6c94bcaace260138d32eae144be1b5d2ddce9ef0f395da32c68e106ff20f \ - --hash=sha256:86f7f1c489887f9e3c2ede598e2a30f8bd259c11e8ebe25e897e40231b3f4bc8 \ +botocore==1.23.44 \ + --hash=sha256:11483a493de4a76ef218d8cd3980c63550d006a0d082c10d53c0954184ca542a \ + --hash=sha256:8e5317f84fc1118bff58fa6fa79a9b62083e75a2a9c62feb3ea73694c550b99d \ # via -r .\requirements.txt, boto3, s3transfer certifi==2019.11.28 \ --hash=sha256:017c25db2a153ce562900032d5bc68e9f191e44e9a0f762f373977de9df1fbb3 \ @@ -22,6 +22,11 @@ chardet==3.0.4 \ --hash=sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae \ --hash=sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691 \ # via -r .\requirements.txt, requests +charset-normalizer==2.0.10 \ + --hash=sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd \ + --hash=sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455 \ + # via + # -r requirements.txt, requests colorama==0.4.3 \ --hash=sha256:7d73d2a99753107a36ac6b455ee49046802e59d9d076ef8e47b61499fa29afff \ --hash=sha256:e96da0d330793e2cb9485e9ddfd918d456036c7149416295932478192f4436a1 \ @@ -129,30 +134,40 @@ packaging==20.4 \ --hash=sha256:4357f74f47b9c12db93624a82154e9b120fa8293699949152b22065d556079f8 \ --hash=sha256:998416ba6962ae7fbd6596850b80e17859a5753ba17c32284f67bfff33784181 \ # pytest -pillow==7.0.0 \ - --hash=sha256:0a628977ac2e01ca96aaae247ec2bd38e729631ddf2221b4b715446fd45505be \ - --hash=sha256:4d9ed9a64095e031435af120d3c910148067087541131e82b3e8db302f4c8946 \ - --hash=sha256:54ebae163e8412aff0b9df1e88adab65788f5f5b58e625dc5c7f51eaf14a6837 \ - --hash=sha256:5bfef0b1cdde9f33881c913af14e43db69815c7e8df429ceda4c70a5e529210f \ - --hash=sha256:5f3546ceb08089cedb9e8ff7e3f6a7042bb5b37c2a95d392fb027c3e53a2da00 \ - --hash=sha256:5f7ae9126d16194f114435ebb79cc536b5682002a4fa57fa7bb2cbcde65f2f4d \ - --hash=sha256:62a889aeb0a79e50ecf5af272e9e3c164148f4bd9636cc6bcfa182a52c8b0533 \ - --hash=sha256:7406f5a9b2fd966e79e6abdaf700585a4522e98d6559ce37fc52e5c955fade0a \ - --hash=sha256:8453f914f4e5a3d828281a6628cf517832abfa13ff50679a4848926dac7c0358 \ - --hash=sha256:87269cc6ce1e3dee11f23fa515e4249ae678dbbe2704598a51cee76c52e19cda \ - --hash=sha256:875358310ed7abd5320f21dd97351d62de4929b0426cdb1eaa904b64ac36b435 \ - --hash=sha256:8ac6ce7ff3892e5deaab7abaec763538ffd011f74dc1801d93d3c5fc541feee2 \ - --hash=sha256:91b710e3353aea6fc758cdb7136d9bbdcb26b53cefe43e2cba953ac3ee1d3313 \ - --hash=sha256:9d2ba4ed13af381233e2d810ff3bab84ef9f18430a9b336ab69eaf3cd24299ff \ - --hash=sha256:a62ec5e13e227399be73303ff301f2865bf68657d15ea50b038d25fc41097317 \ - --hash=sha256:ab76e5580b0ed647a8d8d2d2daee170e8e9f8aad225ede314f684e297e3643c2 \ - --hash=sha256:bf4003aa538af3f4205c5fac56eacaa67a6dd81e454ffd9e9f055fff9f1bc614 \ - --hash=sha256:bf598d2e37cf8edb1a2f26ed3fb255191f5232badea4003c16301cb94ac5bdd0 \ - --hash=sha256:c18f70dc27cc5d236f10e7834236aff60aadc71346a5bc1f4f83a4b3abee6386 \ - --hash=sha256:c5ed816632204a2fc9486d784d8e0d0ae754347aba99c811458d69fcdfd2a2f9 \ - --hash=sha256:dc058b7833184970d1248135b8b0ab702e6daa833be14035179f2acb78ff5636 \ - --hash=sha256:ff3797f2f16bf9d17d53257612da84dd0758db33935777149b3334c01ff68865 \ - # via requirements.txt, imageio +pillow==9.0.0 \ + --hash=sha256:03b27b197deb4ee400ed57d8d4e572d2d8d80f825b6634daf6e2c18c3c6ccfa6 \ + --hash=sha256:0b281fcadbb688607ea6ece7649c5d59d4bbd574e90db6cd030e9e85bde9fecc \ + --hash=sha256:0ebd8b9137630a7bbbff8c4b31e774ff05bbb90f7911d93ea2c9371e41039b52 \ + --hash=sha256:113723312215b25c22df1fdf0e2da7a3b9c357a7d24a93ebbe80bfda4f37a8d4 \ + --hash=sha256:2d16b6196fb7a54aff6b5e3ecd00f7c0bab1b56eee39214b2b223a9d938c50af \ + --hash=sha256:2fd8053e1f8ff1844419842fd474fc359676b2e2a2b66b11cc59f4fa0a301315 \ + --hash=sha256:31b265496e603985fad54d52d11970383e317d11e18e856971bdbb86af7242a4 \ + --hash=sha256:3586e12d874ce2f1bc875a3ffba98732ebb12e18fb6d97be482bd62b56803281 \ + --hash=sha256:47f5cf60bcb9fbc46011f75c9b45a8b5ad077ca352a78185bd3e7f1d294b98bb \ + --hash=sha256:490e52e99224858f154975db61c060686df8a6b3f0212a678e5d2e2ce24675c9 \ + --hash=sha256:500d397ddf4bbf2ca42e198399ac13e7841956c72645513e8ddf243b31ad2128 \ + --hash=sha256:52abae4c96b5da630a8b4247de5428f593465291e5b239f3f843a911a3cf0105 \ + --hash=sha256:6579f9ba84a3d4f1807c4aab4be06f373017fc65fff43498885ac50a9b47a553 \ + --hash=sha256:68e06f8b2248f6dc8b899c3e7ecf02c9f413aab622f4d6190df53a78b93d97a5 \ + --hash=sha256:6c5439bfb35a89cac50e81c751317faea647b9a3ec11c039900cd6915831064d \ + --hash=sha256:72c3110228944019e5f27232296c5923398496b28be42535e3b2dc7297b6e8b6 \ + --hash=sha256:72f649d93d4cc4d8cf79c91ebc25137c358718ad75f99e99e043325ea7d56100 \ + --hash=sha256:7aaf07085c756f6cb1c692ee0d5a86c531703b6e8c9cae581b31b562c16b98ce \ + --hash=sha256:80fe92813d208ce8aa7d76da878bdc84b90809f79ccbad2a288e9bcbeac1d9bd \ + --hash=sha256:95545137fc56ce8c10de646074d242001a112a92de169986abd8c88c27566a05 \ + --hash=sha256:97b6d21771da41497b81652d44191489296555b761684f82b7b544c49989110f \ + --hash=sha256:98cb63ca63cb61f594511c06218ab4394bf80388b3d66cd61d0b1f63ee0ea69f \ + --hash=sha256:9f3b4522148586d35e78313db4db0df4b759ddd7649ef70002b6c3767d0fdeb7 \ + --hash=sha256:a09a9d4ec2b7887f7a088bbaacfd5c07160e746e3d47ec5e8050ae3b2a229e9f \ + --hash=sha256:b5050d681bcf5c9f2570b93bee5d3ec8ae4cf23158812f91ed57f7126df91762 \ + --hash=sha256:bb47a548cea95b86494a26c89d153fd31122ed65255db5dcbc421a2d28eb3379 \ + --hash=sha256:bc462d24500ba707e9cbdef436c16e5c8cbf29908278af053008d9f689f56dee \ + --hash=sha256:c2067b3bb0781f14059b112c9da5a91c80a600a97915b4f48b37f197895dd925 \ + --hash=sha256:d154ed971a4cc04b93a6d5b47f37948d1f621f25de3e8fa0c26b2d44f24e3e8f \ + --hash=sha256:d5dcea1387331c905405b09cdbfb34611050cc52c865d71f2362f354faee1e9f \ + --hash=sha256:ee6e2963e92762923956fe5d3479b1fdc3b76c83f290aad131a2f98c3df0593e \ + --hash=sha256:fd0e5062f11cb3e730450a7d9f323f4051b532781026395c4323b8ad055523c4 \ + # via -r requirements.txt pluggy==0.13.1 \ --hash=sha256:15b2acde666561e1298d71b523007ed7364de07029219b604cf808bfa1c765b0 \ --hash=sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d \ @@ -191,10 +206,10 @@ psutil==5.8.0 \ --hash=sha256:f4634b033faf0d968bb9220dd1c793b897ab7f1189956e1aa9eae752527127d3 \ --hash=sha256:fcc01e900c1d7bee2a37e5d6e4f9194760a93597c97fee89c4ae51701de03563 # via requirements.txt -py==1.9.0 \ - --hash=sha256:366389d1db726cd2fcfc79732e75410e5fe4d31db13692115529d34069a043c2 \ - --hash=sha256:9ca6883ce56b4e8da7e79ac18787889fa5206c79dcc67fb065376cd2fe03f342 \ - # via -r .\requirements.txt, pytest +py==1.11.0 \ + --hash=sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719 \ + --hash=sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378 \ + # via -r requirements.txt pyparsing==2.4.7 \ --hash=sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1 \ --hash=sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b \ @@ -246,13 +261,13 @@ PyYAML==5.4.1 \ --hash=sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df \ --hash=sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc \ # via requirements.txt -requests==2.23.0 \ - --hash=sha256:43999036bfa82904b6af1d99e4882b560e5e2c68e5c4b0aa03b655f3d7d73fee \ - --hash=sha256:b3f43d496c6daba4493e7c431722aeb7dbc6288f52a6e04e7b6023b0247817e6 \ - # via -r .\requirements.txt -s3transfer==0.3.3 \ - --hash=sha256:2482b4259524933a022d59da830f51bd746db62f047d6eb213f2f8855dcb8a13 \ - --hash=sha256:921a37e2aefc64145e7b73d50c71bb4f26f46e4c9f414dc648c6245ff92cf7db \ +requests==2.27.1 \ + --hash=sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61 \ + --hash=sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d \ + # via -r requirements.txt +s3transfer==0.5.0 \ + --hash=sha256:50ed823e1dc5868ad40c8dc92072f757aa0e653a192845c94a3b676f4a62da4c \ + --hash=sha256:9c1dc369814391a6bda20ebbf4b70a0f34630592c9aa520856bf384916af2803 \ # boto3 scipy==1.4.1 \ --hash=sha256:00af72998a46c25bdb5824d2b729e7dabec0c765f9deb0b504f928591f5ff9d4 \ @@ -290,10 +305,10 @@ smmap==3.0.5 \ --hash=sha256:7bfcf367828031dc893530a29cb35eb8c8f2d7c8f2d0989354d75d24c8573714 \ --hash=sha256:84c2751ef3072d4f6b2785ec7ee40244c6f45eb934d9e543e2c51f1bd3d54c50 \ # via smmap2 -urllib3==1.25.8 \ - --hash=sha256:2f3db8b19923a873b3e5256dc9c2dedfa883e33d87c690d9c7913e1f40673cdc \ - --hash=sha256:87716c2d2a7121198ebcb7ce7cccf6ce5e9ba539041cfbaeecfb641dc0bf6acc \ - # via -r .\requirements.txt, botocore, requests +urllib3==1.26.8 \ + --hash=sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed \ + --hash=sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c \ + # via -r requirements.txt wcwidth==0.2.5 \ --hash=sha256:beb4802a9cebb9144e99086eff703a642a13d6a0052920003a230f3294bbe784 \ --hash=sha256:c4d647b99872929fdb7bdcaa4fbe7f01413ed3d98077df798530e5b04f116c83 \