Merge pull request #7439 from aws-lumberyard-dev/TerrainMaterialsFix

LYN-8403 Prevent the same Surface Tag from getting reused
This commit is contained in:
SergeyAMZN
2022-02-10 15:59:24 +00:00
committed by GitHub
15 changed files with 327 additions and 83 deletions
@@ -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
@@ -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);
}
}
}
@@ -66,6 +66,12 @@ namespace AzToolsFramework
class GenericEnumPropertyComboBoxHandler
: public GenericComboBoxHandler<ValueType>
{
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;
@@ -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<AZStd::pair<AZ::u32, AZStd::string>> GetRegisteredTags();
private:
@@ -54,8 +57,6 @@ namespace SurfaceData
AZStd::vector<AZStd::pair<AZ::u32, AZStd::string>> BuildSelectableTagList() const;
AZStd::string GetDisplayName() const;
AZ::u32 m_surfaceTagCrc;
};
@@ -22,6 +22,7 @@
#include <AzFramework/Physics/PhysicsSystem.h>
#include <AzFramework/Terrain/TerrainDataRequestBus.h>
namespace Terrain
{
void TerrainPhysicsSurfaceMaterialMapping::Reflect(AZ::ReflectContext* context)
@@ -32,27 +33,10 @@ namespace Terrain
->Version(1)
->Field("Surface", &TerrainPhysicsSurfaceMaterialMapping::m_surfaceTag)
->Field("Material", &TerrainPhysicsSurfaceMaterialMapping::m_materialId);
if (auto edit = serialize->GetEditContext())
{
edit->Class<TerrainPhysicsSurfaceMaterialMapping>(
"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.")
->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);
}
}
}
AZ::Data::AssetId TerrainPhysicsSurfaceMaterialMapping::GetMaterialLibraryId()
{
if (const auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
@@ -76,22 +60,6 @@ namespace Terrain
->Field("DefaultMaterial", &TerrainPhysicsColliderConfig::m_defaultMaterialSelection)
->Field("Mappings", &TerrainPhysicsColliderConfig::m_surfaceMaterialMappings)
;
if (auto edit = serialize->GetEditContext())
{
edit->Class<TerrainPhysicsColliderConfig>(
"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")
;
}
}
}
@@ -25,6 +25,8 @@ namespace LmbrCentral
namespace Terrain
{
class EditorSurfaceTagListProvider;
static const uint8_t InvalidSurfaceTagIndex = 0xFF;
struct TerrainPhysicsSurfaceMaterialMapping final
@@ -33,12 +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<AZStd::pair<AZ::u32, AZStd::string>> BuildSelectableTagList() const;
void SetTagListProvider(const EditorSurfaceTagListProvider* tagListProvider);
SurfaceData::SurfaceTag m_surfaceTag;
Physics::MaterialId m_materialId;
private:
static AZ::Data::AssetId GetMaterialLibraryId();
const EditorSurfaceTagListProvider* m_tagListProvider = nullptr;
};
class TerrainPhysicsColliderConfig
@@ -48,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<TerrainPhysicsSurfaceMaterialMapping> m_surfaceMaterialMappings;
};
@@ -26,26 +26,6 @@ namespace Terrain
->Field("Gradient Entity", &TerrainSurfaceGradientMapping::m_gradientEntityId)
->Field("Surface Tag", &TerrainSurfaceGradientMapping::m_surfaceTag)
;
if (auto edit = serialize->GetEditContext())
{
edit->Class<TerrainSurfaceGradientMapping>("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.")
;
}
}
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
@@ -71,21 +51,6 @@ namespace Terrain
->Version(1)
->Field("Mappings", &TerrainSurfaceGradientListConfig::m_gradientSurfaceMappings)
;
AZ::EditContext* edit = serialize->GetEditContext();
if (edit)
{
edit->Class<TerrainSurfaceGradientListConfig>(
"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.")
;
}
}
}
@@ -25,6 +25,8 @@ namespace LmbrCentral
namespace Terrain
{
class EditorSurfaceTagListProvider;
class TerrainSurfaceGradientMapping final
{
public:
@@ -39,8 +41,14 @@ namespace Terrain
{
}
AZStd::vector<AZStd::pair<AZ::u32, AZStd::string>> BuildSelectableTagList() const;
void SetTagListProvider(const EditorSurfaceTagListProvider* tagListProvider);
AZ::EntityId m_gradientEntityId;
SurfaceData::SurfaceTag m_surfaceTag;
private:
const EditorSurfaceTagListProvider* m_tagListProvider = nullptr;
};
class TerrainSurfaceGradientListConfig : public AZ::ComponentConfig
@@ -20,5 +20,85 @@ namespace Terrain
&LmbrCentral::EditorWrappedComponentBaseVersionConverter<typename BaseClassType::WrappedComponentType,
typename BaseClassType::WrappedConfigType, 1>
);
if (auto serialize = azrtti_cast<AZ::SerializeContext*>(context))
{
if (auto edit = serialize->GetEditContext())
{
edit->Class<TerrainPhysicsSurfaceMaterialMapping>(
"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<TerrainPhysicsColliderConfig>(
"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()
{
UpdateConfigurationTagProvider();
BaseClassType::Activate();
}
AZStd::unordered_set<SurfaceData::SurfaceTag> EditorTerrainPhysicsColliderComponent::GetSurfaceTagsInUse() const
{
AZStd::unordered_set<SurfaceData::SurfaceTag> tagsInUse;
for (const TerrainPhysicsSurfaceMaterialMapping& mapping : m_configuration.m_surfaceMaterialMappings)
{
tagsInUse.insert(mapping.m_surfaceTag);
}
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);
}
}
AZStd::vector<AZStd::pair<AZ::u32, AZStd::string>> 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;
}
}
@@ -11,22 +11,34 @@
#include <Components/TerrainPhysicsColliderComponent.h>
#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
#include <LmbrCentral/Component/EditorWrappedComponentBase.h>
#include <EditorSurfaceTagListProvider.h>
namespace Terrain
{
class EditorTerrainPhysicsColliderComponent
: public LmbrCentral::EditorWrappedComponentBase<TerrainPhysicsColliderComponent, TerrainPhysicsColliderConfig>
, public EditorSurfaceTagListProvider
{
public:
using BaseClassType = LmbrCentral::EditorWrappedComponentBase<TerrainPhysicsColliderComponent, TerrainPhysicsColliderConfig>;
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:
// EditorSurfaceTagListProvider interface implementation
AZStd::unordered_set<SurfaceData::SurfaceTag> GetSurfaceTagsInUse() const override;
AZ::u32 ConfigurationChanged() override;
void UpdateConfigurationTagProvider();
};
}
@@ -19,5 +19,83 @@ namespace Terrain
&LmbrCentral::EditorWrappedComponentBaseVersionConverter<typename BaseClassType::WrappedComponentType,
typename BaseClassType::WrappedConfigType, 1>
);
if (auto serialize = azrtti_cast<AZ::SerializeContext*>(context))
{
if (auto edit = serialize->GetEditContext())
{
edit->Class<TerrainSurfaceGradientMapping>("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<TerrainSurfaceGradientListConfig>(
"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()
{
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<SurfaceData::SurfaceTag> EditorTerrainSurfaceGradientListComponent::GetSurfaceTagsInUse() const
{
AZStd::unordered_set<SurfaceData::SurfaceTag> tagsInUse;
for (const TerrainSurfaceGradientMapping& mapping : m_configuration.m_gradientSurfaceMappings)
{
tagsInUse.insert(mapping.m_surfaceTag);
}
return AZStd::move(tagsInUse);
}
AZStd::vector<AZStd::pair<AZ::u32, AZStd::string>> 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;
}
}
@@ -11,22 +11,34 @@
#include <Components/TerrainSurfaceGradientListComponent.h>
#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
#include <LmbrCentral/Component/EditorWrappedComponentBase.h>
#include <EditorSurfaceTagListProvider.h>
namespace Terrain
{
class EditorTerrainSurfaceGradientListComponent
: public LmbrCentral::EditorWrappedComponentBase<TerrainSurfaceGradientListComponent, TerrainSurfaceGradientListConfig>
, public EditorSurfaceTagListProvider
{
public:
using BaseClassType = LmbrCentral::EditorWrappedComponentBase<TerrainSurfaceGradientListComponent, TerrainSurfaceGradientListConfig>;
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:
// EditorSurfaceTagListProvider interface implementation
AZStd::unordered_set<SurfaceData::SurfaceTag> GetSurfaceTagsInUse() const override;
AZ::u32 ConfigurationChanged() override;
void UpdateConfigurationTagProvider();
};
}
@@ -0,0 +1,41 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <EditorSurfaceTagListProvider.h>
#include <AzCore/std/sort.h>
namespace Terrain
{
AZStd::vector<AZStd::pair<AZ::u32, AZStd::string>> BuildSelectableTagList(const EditorSurfaceTagListProvider* tagListProvider,
const SurfaceData::SurfaceTag& currentTag)
{
AZStd::vector<AZStd::pair<AZ::u32, AZStd::string>> availableTags = SurfaceData::SurfaceTag::GetRegisteredTags();
AZStd::unordered_set<SurfaceData::SurfaceTag> 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);
}
}
@@ -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 <AzCore/std/containers/vector.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/containers/unordered_set.h>
#include <SurfaceData/SurfaceTag.h>
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<SurfaceData::SurfaceTag> GetSurfaceTagsInUse() const = 0;
};
//! Returns a list of available tags to be selected in the component.
AZStd::vector<AZStd::pair<AZ::u32, AZStd::string>> BuildSelectableTagList(
const EditorSurfaceTagListProvider* tagListProvider,
const SurfaceData::SurfaceTag& currentTag);
}
@@ -25,6 +25,8 @@ set(FILES
Source/EditorComponents/EditorTerrainSystemComponent.h
Source/EditorTerrainModule.cpp
Source/EditorTerrainModule.h
Source/EditorSurfaceTagListProvider.h
Source/EditorSurfaceTagListProvider.cpp
Source/TerrainModule.cpp
Source/TerrainModule.h
Source/TerrainRenderer/EditorComponents/EditorTerrainSurfaceMaterialsListComponent.cpp