diff --git a/Gems/Terrain/Assets/Materials/Terrain/DefaultTerrainMacroMaterial.material b/Gems/Terrain/Assets/Materials/Terrain/DefaultTerrainMacroMaterial.material new file mode 100644 index 0000000000..afaf7e1947 --- /dev/null +++ b/Gems/Terrain/Assets/Materials/Terrain/DefaultTerrainMacroMaterial.material @@ -0,0 +1,8 @@ +{ + "description": "", + "materialType": "TerrainMacroMaterial.materialtype", + "parentMaterial": "", + "propertyLayoutVersion": 1, + "properties": { + } +} diff --git a/Gems/Terrain/Assets/Materials/Terrain/TerrainMacroMaterial.materialtype b/Gems/Terrain/Assets/Materials/Terrain/TerrainMacroMaterial.materialtype new file mode 100644 index 0000000000..0a4f6d0229 --- /dev/null +++ b/Gems/Terrain/Assets/Materials/Terrain/TerrainMacroMaterial.materialtype @@ -0,0 +1,46 @@ +{ + "description": "A material for providing terrain with low-fidelity color and normals. This material will get blended with surface detail materials.", + "propertyLayout": { + "version": 1, + "groups": [ + { + "id": "settings", + "displayName": "Settings" + } + ], + "properties": { + "macroColor": [ + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture.", + "type": "Bool", + "defaultValue": true + } + + ], + "macroNormal": [ + { + "id": "useTexture", + "displayName": "Use Texture", + "description": "Whether to use the texture.", + "type": "Bool", + "defaultValue": true + } + ] + } + }, + "shaders": [ + { + "file": "../../Shaders/Terrain/TerrainPBR_ForwardPass.shader" + }, + { + "file": "../../Shaders/Terrain/Terrain_Shadowmap.shader" + }, + { + "file": "../../Shaders/Terrain/Terrain_DepthPass.shader" + } + ], + "functors": [ + ] +} diff --git a/Gems/Terrain/Code/Source/EditorTerrainModule.cpp b/Gems/Terrain/Code/Source/EditorTerrainModule.cpp index 9107ea8541..94c6f5c3c6 100644 --- a/Gems/Terrain/Code/Source/EditorTerrainModule.cpp +++ b/Gems/Terrain/Code/Source/EditorTerrainModule.cpp @@ -14,6 +14,7 @@ #include #include #include +#include namespace Terrain { @@ -24,6 +25,7 @@ namespace Terrain { Terrain::EditorTerrainHeightGradientListComponent::CreateDescriptor(), Terrain::EditorTerrainLayerSpawnerComponent::CreateDescriptor(), + Terrain::EditorTerrainMacroMaterialComponent::CreateDescriptor(), Terrain::EditorTerrainSurfaceGradientListComponent::CreateDescriptor(), Terrain::EditorTerrainSystemComponent::CreateDescriptor(), Terrain::EditorTerrainWorldComponent::CreateDescriptor(), diff --git a/Gems/Terrain/Code/Source/TerrainModule.cpp b/Gems/Terrain/Code/Source/TerrainModule.cpp index 6aeddc3cd5..878c6b44c8 100644 --- a/Gems/Terrain/Code/Source/TerrainModule.cpp +++ b/Gems/Terrain/Code/Source/TerrainModule.cpp @@ -18,6 +18,7 @@ #include #include #include +#include namespace Terrain { @@ -31,6 +32,7 @@ namespace Terrain TerrainWorldRendererComponent::CreateDescriptor(), TerrainHeightGradientListComponent::CreateDescriptor(), TerrainLayerSpawnerComponent::CreateDescriptor(), + TerrainMacroMaterialComponent::CreateDescriptor(), TerrainSurfaceGradientListComponent::CreateDescriptor(), TerrainSurfaceDataSystemComponent::CreateDescriptor(), }); diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainMacroMaterialComponent.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainMacroMaterialComponent.cpp new file mode 100644 index 0000000000..55653c64fa --- /dev/null +++ b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainMacroMaterialComponent.cpp @@ -0,0 +1,287 @@ +/* + * 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 Terrain +{ + AZ::Data::AssetId TerrainMacroMaterialConfig::s_macroMaterialTypeAssetId{}; + + void TerrainMacroMaterialConfig::Reflect(AZ::ReflectContext* context) + { + AZ::SerializeContext* serialize = azrtti_cast(context); + if (serialize) + { + serialize->Class() + ->Version(1) + ->Field("MacroMaterial", &TerrainMacroMaterialConfig::m_materialAsset) + ; + + // The edit context for this appears in EditorTerrainMacroMaterialComponent.cpp. + } + } + + AZ::Data::AssetId TerrainMacroMaterialConfig::GetTerrainMacroMaterialTypeAssetId() + { + // Get the Asset ID for the TerrainMacroMaterial material type and store it in a class static so that we don't have to look it + // up again. + if (!s_macroMaterialTypeAssetId.IsValid()) + { + AZ::Data::AssetCatalogRequestBus::BroadcastResult( + s_macroMaterialTypeAssetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, TerrainMacroMaterialTypeAsset, + azrtti_typeid(), false); + AZ_Assert(s_macroMaterialTypeAssetId.IsValid(), "The asset '%s' couldn't be found.", TerrainMacroMaterialTypeAsset); + } + + return s_macroMaterialTypeAssetId; + } + + bool TerrainMacroMaterialConfig::IsMaterialTypeCorrect(const AZ::Data::AssetId& assetId) + { + // We'll verify that whatever material we try to load has this material type as a dependency, as a way to implicitly detect + // that we're only trying to use terrain macro materials even before we load the asset. + auto macroMaterialTypeAssetId = GetTerrainMacroMaterialTypeAssetId(); + + // Get the dependencies for the requested asset. + AZ::Outcome, AZStd::string> result; + AZ::Data::AssetCatalogRequestBus::BroadcastResult( + result, &AZ::Data::AssetCatalogRequestBus::Events::GetDirectProductDependencies, assetId); + + // If any of the dependencies match the TerrainMacroMaterial materialtype asset, then this should be the correct type of material. + if (result) + { + for (auto& dependency : result.GetValue()) + { + if (dependency.m_assetId == macroMaterialTypeAssetId) + { + return true; + } + } + } + + // Didn't have the expected dependency, so it must not be the right material type. + return false; + } + + AZ::Outcome TerrainMacroMaterialConfig::ValidateMaterialAsset(void* newValue, const AZ::Uuid& valueType) + { + if (azrtti_typeid>() != valueType) + { + AZ_Assert(false, "Unexpected value type"); + return AZ::Failure(AZStd::string("Unexpectedly received something other than a material asset for the MacroMaterial!")); + } + + auto newMaterialAsset = *static_cast*>(newValue); + + if (!IsMaterialTypeCorrect(newMaterialAsset.GetId())) + { + return AZ::Failure(AZStd::string::format( + "The selected MacroMaterial ('%s') needs to use the TerrainMacroMaterial material type.", + newMaterialAsset.GetHint().c_str())); + } + + return AZ::Success(); + } + + + void TerrainMacroMaterialComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services) + { + services.push_back(AZ_CRC_CE("TerrainMacroMaterialProviderService")); + } + + void TerrainMacroMaterialComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services) + { + services.push_back(AZ_CRC_CE("TerrainMacroMaterialProviderService")); + } + + void TerrainMacroMaterialComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& services) + { + services.push_back(AZ_CRC_CE("AxisAlignedBoxShapeService")); + } + + void TerrainMacroMaterialComponent::Reflect(AZ::ReflectContext* context) + { + TerrainMacroMaterialConfig::Reflect(context); + + AZ::SerializeContext* serialize = azrtti_cast(context); + if (serialize) + { + serialize->Class() + ->Version(0) + ->Field("Configuration", &TerrainMacroMaterialComponent::m_configuration) + ; + } + } + + TerrainMacroMaterialComponent::TerrainMacroMaterialComponent(const TerrainMacroMaterialConfig& configuration) + : m_configuration(configuration) + { + } + + void TerrainMacroMaterialComponent::Activate() + { + // Clear out our shape bounds and make sure the material is queued to load. + m_cachedShapeBounds = AZ::Aabb::CreateNull(); + m_configuration.m_materialAsset.QueueLoad(); + + // Don't mark our material as active until it's finished loading and is valid. + m_macroMaterialActive = false; + + // Listen for the material asset to complete loading. + AZ::Data::AssetBus::Handler::BusConnect(m_configuration.m_materialAsset.GetId()); + } + + void TerrainMacroMaterialComponent::Deactivate() + { + TerrainMacroMaterialRequestBus::Handler::BusDisconnect(); + + AZ::Data::AssetBus::Handler::BusDisconnect(); + m_configuration.m_materialAsset.Release(); + + m_macroMaterialInstance.reset(); + + // Send out any notifications as appropriate based on the macro material destruction. + HandleMaterialStateChange(); + } + + bool TerrainMacroMaterialComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig) + { + if (auto config = azrtti_cast(baseConfig)) + { + m_configuration = *config; + return true; + } + return false; + } + + bool TerrainMacroMaterialComponent::WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const + { + if (auto config = azrtti_cast(outBaseConfig)) + { + *config = m_configuration; + return true; + } + return false; + } + + void TerrainMacroMaterialComponent::OnShapeChanged([[maybe_unused]] ShapeComponentNotifications::ShapeChangeReasons reasons) + { + // This should only get called while the macro material is active. If it gets called while the macro material isn't active, + // we've got a bug where we haven't managed the bus connections properly. + AZ_Assert(m_macroMaterialActive, "The ShapeComponentNotificationBus connection is out of sync with the material load."); + + AZ::Aabb oldShapeBounds = m_cachedShapeBounds; + + LmbrCentral::ShapeComponentRequestsBus::EventResult( + m_cachedShapeBounds, GetEntityId(), &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb); + + TerrainMacroMaterialNotificationBus::Broadcast( + &TerrainMacroMaterialNotificationBus::Events::OnTerrainMacroMaterialRegionChanged, + GetEntityId(), oldShapeBounds, m_cachedShapeBounds); + } + + void TerrainMacroMaterialComponent::HandleMaterialStateChange() + { + // We only want our component to appear active during the time that the macro material is loaded and valid. The logic below + // will handle all transition possibilities to notify if we've become active, inactive, or just changed. We'll also only + // keep a valid up-to-date copy of the shape bounds while the material is valid, since we don't need it any other time. + + bool wasPreviouslyActive = m_macroMaterialActive; + bool isNowActive = (m_macroMaterialInstance != nullptr); + + // Set our state to active or inactive, based on whether or not the macro material instance is now valid. + m_macroMaterialActive = isNowActive; + + // Handle the different inactive/active transition possibilities. + + if (!wasPreviouslyActive && !isNowActive) + { + // Do nothing, we haven't yet successfully loaded a valid material. + } + else if (!wasPreviouslyActive && isNowActive) + { + // We've transitioned from inactive to active, so send out a message saying that we've been created and start tracking the + // overall shape bounds. + + // Get the current shape bounds. + LmbrCentral::ShapeComponentRequestsBus::EventResult( + m_cachedShapeBounds, GetEntityId(), &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb); + + // Start listening for terrain macro material requests. + TerrainMacroMaterialRequestBus::Handler::BusConnect(GetEntityId()); + + // Start listening for shape changes. + LmbrCentral::ShapeComponentNotificationsBus::Handler::BusConnect(GetEntityId()); + + TerrainMacroMaterialNotificationBus::Broadcast( + &TerrainMacroMaterialNotificationBus::Events::OnTerrainMacroMaterialCreated, GetEntityId(), m_macroMaterialInstance, + m_cachedShapeBounds); + } + else if (wasPreviouslyActive && !isNowActive) + { + // Stop listening to macro material requests or shape changes, and send out a notification that we no longer have a valid + // macro material. + + TerrainMacroMaterialRequestBus::Handler::BusDisconnect(); + LmbrCentral::ShapeComponentNotificationsBus::Handler::BusDisconnect(); + + m_cachedShapeBounds = AZ::Aabb::CreateNull(); + + TerrainMacroMaterialNotificationBus::Broadcast( + &TerrainMacroMaterialNotificationBus::Events::OnTerrainMacroMaterialDestroyed, GetEntityId()); + } + else + { + // We were active both before and after, so just send out a material changed event. + + TerrainMacroMaterialNotificationBus::Broadcast( + &TerrainMacroMaterialNotificationBus::Events::OnTerrainMacroMaterialChanged, GetEntityId(), m_macroMaterialInstance); + } + } + + void TerrainMacroMaterialComponent::OnAssetReady(AZ::Data::Asset asset) + { + m_configuration.m_materialAsset = asset; + + if (m_configuration.m_materialAsset.Get()->GetMaterialTypeAsset().GetId() == + TerrainMacroMaterialConfig::GetTerrainMacroMaterialTypeAssetId()) + { + m_macroMaterialInstance = AZ::RPI::Material::FindOrCreate(m_configuration.m_materialAsset); + } + else + { + AZ_Error("Terrain", false, "Material '%s' has the wrong material type.", m_configuration.m_materialAsset.GetHint().c_str()); + m_macroMaterialInstance.reset(); + } + + // Clear the material asset reference to make sure we don't prevent hot-reloading. + m_configuration.m_materialAsset.Release(); + + HandleMaterialStateChange(); + } + + void TerrainMacroMaterialComponent::OnAssetReloaded(AZ::Data::Asset asset) + { + OnAssetReady(asset); + } + + void TerrainMacroMaterialComponent::GetTerrainMacroMaterialData( + AZ::Data::Instance& macroMaterial, AZ::Aabb& macroMaterialRegion) + { + macroMaterial = m_macroMaterialInstance; + macroMaterialRegion = m_cachedShapeBounds; + } +} diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainMacroMaterialComponent.h b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainMacroMaterialComponent.h new file mode 100644 index 0000000000..b60f6b2a94 --- /dev/null +++ b/Gems/Terrain/Code/Source/TerrainRenderer/Components/TerrainMacroMaterialComponent.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + + +namespace LmbrCentral +{ + template + class EditorWrappedComponentBase; +} + +namespace Terrain +{ + class TerrainMacroMaterialConfig + : public AZ::ComponentConfig + { + public: + AZ_CLASS_ALLOCATOR(TerrainMacroMaterialConfig, AZ::SystemAllocator, 0); + AZ_RTTI(TerrainMacroMaterialConfig, "{9DBAFFF0-FD20-4594-8884-E3266D8CCAC8}", AZ::ComponentConfig); + static void Reflect(AZ::ReflectContext* context); + + AZ::Data::Asset m_materialAsset = { AZ::Data::AssetLoadBehavior::QueueLoad }; + + static AZ::Data::AssetId GetTerrainMacroMaterialTypeAssetId(); + static bool IsMaterialTypeCorrect(const AZ::Data::AssetId&); + AZ::Outcome ValidateMaterialAsset(void* newValue, const AZ::Uuid& valueType); + + private: + static inline constexpr const char* TerrainMacroMaterialTypeAsset = "materials/terrain/terrainmacromaterial.azmaterialtype"; + static AZ::Data::AssetId s_macroMaterialTypeAssetId; + + }; + + class TerrainMacroMaterialComponent + : public AZ::Component + , public TerrainMacroMaterialRequestBus::Handler + , private LmbrCentral::ShapeComponentNotificationsBus::Handler + , private AZ::Data::AssetBus::Handler + { + public: + template + friend class LmbrCentral::EditorWrappedComponentBase; + AZ_COMPONENT(TerrainMacroMaterialComponent, "{F82379FB-E2AE-4F75-A6F4-1AE5F5DA42E8}"); + static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services); + static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services); + static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& services); + static void Reflect(AZ::ReflectContext* context); + + TerrainMacroMaterialComponent(const TerrainMacroMaterialConfig& configuration); + TerrainMacroMaterialComponent() = default; + ~TerrainMacroMaterialComponent() = default; + + ////////////////////////////////////////////////////////////////////////// + // AZ::Component interface implementation + void Activate() override; + void Deactivate() override; + bool ReadInConfig(const AZ::ComponentConfig* baseConfig) override; + bool WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const override; + + void GetTerrainMacroMaterialData(AZ::Data::Instance& macroMaterial, AZ::Aabb& macroMaterialRegion) override; + + private: + //////////////////////////////////////////////////////////////////////// + // ShapeComponentNotificationsBus + void OnShapeChanged(ShapeComponentNotifications::ShapeChangeReasons reasons) override; + + ////////////////////////////////////////////////////////////////////////// + // AZ::Data::AssetBus::Handler + void OnAssetReady(AZ::Data::Asset asset) override; + void OnAssetReloaded(AZ::Data::Asset asset) override; + + void HandleMaterialStateChange(); + + TerrainMacroMaterialConfig m_configuration; + AZ::Aabb m_cachedShapeBounds; + AZ::Data::Instance m_macroMaterialInstance; + bool m_macroMaterialActive{ false }; + }; +} diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/EditorComponents/EditorTerrainMacroMaterialComponent.cpp b/Gems/Terrain/Code/Source/TerrainRenderer/EditorComponents/EditorTerrainMacroMaterialComponent.cpp new file mode 100644 index 0000000000..07472d1b85 --- /dev/null +++ b/Gems/Terrain/Code/Source/TerrainRenderer/EditorComponents/EditorTerrainMacroMaterialComponent.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include +#include + +namespace Terrain +{ + void EditorTerrainMacroMaterialComponent::Reflect(AZ::ReflectContext* context) + { + BaseClassType::ReflectSubClass( + context, 1, + &LmbrCentral::EditorWrappedComponentBaseVersionConverter + ); + + AZ::SerializeContext* serializeContext = azrtti_cast(context); + + if (serializeContext) + { + AZ::EditContext* editContext = serializeContext->GetEditContext(); + + // The edit context for TerrainMacroMaterialConfig is specified here to make it easier to add custom filtering to the + // asset picker for the material asset so that we can eventually only display materials that inherit from the proper + // material type. + if (editContext) + { + editContext + ->Class( + "Terrain Macro Material Component", "Provide a terrain macro material for a region of the world") + ->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, &TerrainMacroMaterialConfig::m_materialAsset, "Macro Material", + "Terrain macro material for use by any terrain inside the bounding box on this entity.") + // This is disabled until ChangeValidate can support the Asset type. :( + //->Attribute(AZ::Edit::Attributes::ChangeValidate, &TerrainMacroMaterialConfig::ValidateMaterialAsset) + ; + } + } + + } +} diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/EditorComponents/EditorTerrainMacroMaterialComponent.h b/Gems/Terrain/Code/Source/TerrainRenderer/EditorComponents/EditorTerrainMacroMaterialComponent.h new file mode 100644 index 0000000000..a2fddf5768 --- /dev/null +++ b/Gems/Terrain/Code/Source/TerrainRenderer/EditorComponents/EditorTerrainMacroMaterialComponent.h @@ -0,0 +1,32 @@ +/* + * 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 +{ + class EditorTerrainMacroMaterialComponent + : public LmbrCentral::EditorWrappedComponentBase + { + public: + using BaseClassType = LmbrCentral::EditorWrappedComponentBase; + AZ_EDITOR_COMPONENT(EditorTerrainMacroMaterialComponent, "{24D87D5F-6845-4F1F-81DC-05B4CEBA3EF4}", BaseClassType); + static void Reflect(AZ::ReflectContext* context); + + static constexpr const char* const s_categoryName = "Terrain"; + static constexpr const char* const s_componentName = "Terrain Macro Material"; + static constexpr const char* const s_componentDescription = "Provides a macro material for a region to the terrain renderer"; + static constexpr const char* const s_icon = "Editor/Icons/Components/TerrainLayerRenderer.svg"; + static constexpr const char* const s_viewportIcon = "Editor/Icons/Components/Viewport/TerrainLayerRenderer.svg"; + static constexpr const char* const s_helpUrl = ""; + }; +} diff --git a/Gems/Terrain/Code/Source/TerrainRenderer/TerrainMacroMaterialBus.h b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainMacroMaterialBus.h new file mode 100644 index 0000000000..c0618a7f66 --- /dev/null +++ b/Gems/Terrain/Code/Source/TerrainRenderer/TerrainMacroMaterialBus.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project. + * For complete copyright and license terms please see the LICENSE at the root of this distribution. + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#pragma once + +#include +#include +#include +#include + +#include + +namespace Terrain +{ + /** + * Request terrain macro material data. + */ + class TerrainMacroMaterialRequests + : public AZ::ComponentBus + { + public: + //////////////////////////////////////////////////////////////////////// + // EBusTraits + using MutexType = AZStd::recursive_mutex; + //////////////////////////////////////////////////////////////////////// + + virtual ~TerrainMacroMaterialRequests() = default; + + // Get the terrain macro material and the region that it covers. + virtual void GetTerrainMacroMaterialData(AZ::Data::Instance& macroMaterial, AZ::Aabb& macroMaterialRegion) = 0; + }; + + using TerrainMacroMaterialRequestBus = AZ::EBus; + + /** + * Notifications for when the terrain macro material data changes. + */ + class TerrainMacroMaterialNotifications : public AZ::EBusTraits + { + public: + ////////////////////////////////////////////////////////////////////////// + // EBusTraits overrides + static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; + static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; + ////////////////////////////////////////////////////////////////////////// + + virtual void OnTerrainMacroMaterialCreated( + [[maybe_unused]] AZ::EntityId macroMaterialEntity, + [[maybe_unused]] AZ::Data::Instance macroMaterial, + [[maybe_unused]] const AZ::Aabb& macroMaterialRegion) + { + } + + virtual void OnTerrainMacroMaterialChanged( + [[maybe_unused]] AZ::EntityId macroMaterialEntity, + [[maybe_unused]] AZ::Data::Instance macroMaterial) + { + } + + virtual void OnTerrainMacroMaterialRegionChanged( + [[maybe_unused]] AZ::EntityId macroMaterialEntity, + [[maybe_unused]] const AZ::Aabb& oldRegion, + [[maybe_unused]] const AZ::Aabb& newRegion) + { + } + + virtual void OnTerrainMacroMaterialDestroyed([[maybe_unused]] AZ::EntityId macroMaterialEntity) + { + } + }; + using TerrainMacroMaterialNotificationBus = AZ::EBus; + +} diff --git a/Gems/Terrain/Code/terrain_editor_shared_files.cmake b/Gems/Terrain/Code/terrain_editor_shared_files.cmake index efb68eca31..2db46dc264 100644 --- a/Gems/Terrain/Code/terrain_editor_shared_files.cmake +++ b/Gems/Terrain/Code/terrain_editor_shared_files.cmake @@ -25,4 +25,6 @@ set(FILES Source/EditorTerrainModule.h Source/TerrainModule.cpp Source/TerrainModule.h + Source/TerrainRenderer/EditorComponents/EditorTerrainMacroMaterialComponent.cpp + Source/TerrainRenderer/EditorComponents/EditorTerrainMacroMaterialComponent.h ) diff --git a/Gems/Terrain/Code/terrain_files.cmake b/Gems/Terrain/Code/terrain_files.cmake index 6d190b7d5e..5739ed6079 100644 --- a/Gems/Terrain/Code/terrain_files.cmake +++ b/Gems/Terrain/Code/terrain_files.cmake @@ -24,8 +24,11 @@ set(FILES Source/Components/TerrainWorldDebuggerComponent.h Source/Components/TerrainWorldRendererComponent.cpp Source/Components/TerrainWorldRendererComponent.h + Source/TerrainRenderer/Components/TerrainMacroMaterialComponent.cpp + Source/TerrainRenderer/Components/TerrainMacroMaterialComponent.h Source/TerrainRenderer/TerrainFeatureProcessor.cpp Source/TerrainRenderer/TerrainFeatureProcessor.h + Source/TerrainRenderer/TerrainMacroMaterialBus.h Source/TerrainSystem/TerrainSystem.cpp Source/TerrainSystem/TerrainSystem.h Source/TerrainSystem/TerrainSystemBus.h