Terrain/sphrose/surface materials component (#4541)
* wip Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * wip Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Terrain Surface Materials List Component. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * fix erroneous commit Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Added some comments. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Review changes. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Surface Materials list unit tests Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Missing shape test Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * review changes. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Compile fix. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Fix case issue in include path. Signed-off-by: Ken Pruiksma <pruiksma@amazon.com> * replaced reverted test. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> Co-authored-by: Ken Pruiksma <pruiksma@amazon.com>
This commit is contained in:
@@ -22,9 +22,12 @@ ly_add_target(
|
||||
Gem::Atom_RPI.Public
|
||||
Gem::Atom_Utils.Static
|
||||
Gem::Atom_Feature_Common
|
||||
Gem::AtomLyIntegration_CommonFeatures.Static
|
||||
Gem::GradientSignal
|
||||
Gem::SurfaceData
|
||||
Gem::LmbrCentral
|
||||
|
||||
|
||||
)
|
||||
|
||||
ly_add_target(
|
||||
|
||||
+2
-1
@@ -14,7 +14,8 @@ namespace Terrain
|
||||
{
|
||||
void EditorTerrainSurfaceGradientListComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
BaseClassType::ReflectSubClass<EditorTerrainSurfaceGradientListComponent, BaseClassType>(context, 1,
|
||||
BaseClassType::ReflectSubClass<EditorTerrainSurfaceGradientListComponent, BaseClassType>(
|
||||
context, 1,
|
||||
&LmbrCentral::EditorWrappedComponentBaseVersionConverter<typename BaseClassType::WrappedComponentType,
|
||||
typename BaseClassType::WrappedConfigType, 1>
|
||||
);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <EditorComponents/EditorTerrainWorldComponent.h>
|
||||
#include <EditorComponents/EditorTerrainWorldDebuggerComponent.h>
|
||||
#include <EditorComponents/EditorTerrainWorldRendererComponent.h>
|
||||
#include <TerrainRenderer/EditorComponents/EditorTerrainSurfaceMaterialsListComponent.h>
|
||||
#include <TerrainRenderer/EditorComponents/EditorTerrainMacroMaterialComponent.h>
|
||||
|
||||
namespace Terrain
|
||||
@@ -28,6 +29,7 @@ namespace Terrain
|
||||
Terrain::EditorTerrainMacroMaterialComponent::CreateDescriptor(),
|
||||
Terrain::EditorTerrainSurfaceGradientListComponent::CreateDescriptor(),
|
||||
Terrain::EditorTerrainSystemComponent::CreateDescriptor(),
|
||||
Terrain::EditorTerrainSurfaceMaterialsListComponent::CreateDescriptor(),
|
||||
Terrain::EditorTerrainWorldComponent::CreateDescriptor(),
|
||||
Terrain::EditorTerrainWorldDebuggerComponent::CreateDescriptor(),
|
||||
Terrain::EditorTerrainWorldRendererComponent::CreateDescriptor(),
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <Components/TerrainLayerSpawnerComponent.h>
|
||||
#include <Components/TerrainSurfaceGradientListComponent.h>
|
||||
#include <Components/TerrainSurfaceDataSystemComponent.h>
|
||||
#include <TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h>
|
||||
#include <TerrainRenderer/Components/TerrainMacroMaterialComponent.h>
|
||||
|
||||
namespace Terrain
|
||||
@@ -26,6 +27,7 @@ namespace Terrain
|
||||
: AZ::Module()
|
||||
{
|
||||
m_descriptors.insert(m_descriptors.end(), {
|
||||
TerrainSurfaceMaterialsListComponent::CreateDescriptor(),
|
||||
TerrainSystemComponent::CreateDescriptor(),
|
||||
TerrainWorldComponent::CreateDescriptor(),
|
||||
TerrainWorldDebuggerComponent::CreateDescriptor(),
|
||||
|
||||
+305
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* 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 <TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h>
|
||||
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
#include <AzCore/Component/Entity.h>
|
||||
#include <AzCore/Asset/AssetManager.h>
|
||||
#include <AzCore/Asset/AssetSerializer.h>
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Math/Aabb.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
|
||||
#include <GradientSignal/Ebuses/GradientRequestBus.h>
|
||||
#include <SurfaceData/SurfaceDataProviderRequestBus.h>
|
||||
|
||||
#include <AtomLyIntegration/CommonFeatures/Material/MaterialComponentBus.h>
|
||||
|
||||
#include <TerrainSystem/TerrainSystemBus.h>
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
void TerrainSurfaceMaterialMapping::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serialize = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serialize->Class<TerrainSurfaceMaterialMapping>()
|
||||
->Version(1)
|
||||
->Field("Surface", &TerrainSurfaceMaterialMapping::m_surfaceTag)
|
||||
->Field("MaterialAsset", &TerrainSurfaceMaterialMapping::m_materialAsset);
|
||||
|
||||
if (auto edit = serialize->GetEditContext())
|
||||
{
|
||||
edit->Class<TerrainSurfaceMaterialMapping>("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)
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainSurfaceMaterialsListConfig::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
TerrainSurfaceMaterialMapping::Reflect(context);
|
||||
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<TerrainSurfaceMaterialsListConfig, AZ::ComponentConfig>()
|
||||
->Version(1)
|
||||
->Field("Mappings", &TerrainSurfaceMaterialsListConfig::m_surfaceMaterials);
|
||||
|
||||
AZ::EditContext* edit = serialize->GetEditContext();
|
||||
if (edit)
|
||||
{
|
||||
edit->Class<TerrainSurfaceMaterialsListConfig>(
|
||||
"Terrain Surface Material List Component", "Provide mapping between surfaces and render materials.")
|
||||
->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, &TerrainSurfaceMaterialsListConfig::m_surfaceMaterials,
|
||||
"Gradient to Material Mappings", "Maps surfaces to materials.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainSurfaceMaterialsListComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& services)
|
||||
{
|
||||
services.push_back(AZ_CRC_CE("TerrainMaterialProviderService"));
|
||||
}
|
||||
|
||||
void TerrainSurfaceMaterialsListComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& services)
|
||||
{
|
||||
services.push_back(AZ_CRC_CE("TerrainMaterialProviderService"));
|
||||
}
|
||||
|
||||
void TerrainSurfaceMaterialsListComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& services)
|
||||
{
|
||||
services.push_back(AZ_CRC_CE("AxisAlignedBoxShapeService"));
|
||||
}
|
||||
|
||||
void TerrainSurfaceMaterialsListComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
TerrainSurfaceMaterialsListConfig::Reflect(context);
|
||||
|
||||
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
if (serialize)
|
||||
{
|
||||
serialize->Class<TerrainSurfaceMaterialsListComponent, AZ::Component>()
|
||||
->Version(0)
|
||||
->Field("Configuration", &TerrainSurfaceMaterialsListComponent::m_configuration);
|
||||
}
|
||||
}
|
||||
|
||||
TerrainSurfaceMaterialsListComponent::TerrainSurfaceMaterialsListComponent(const TerrainSurfaceMaterialsListConfig& configuration)
|
||||
: m_configuration(configuration)
|
||||
{
|
||||
}
|
||||
|
||||
void TerrainSurfaceMaterialsListComponent::Activate()
|
||||
{
|
||||
m_cachedAabb = AZ::Aabb::CreateNull();
|
||||
|
||||
// Set all the materials as inactive and start loading.
|
||||
for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials)
|
||||
{
|
||||
if (surfaceMaterialMapping.m_materialAsset.GetId().IsValid())
|
||||
{
|
||||
surfaceMaterialMapping.m_active = false;
|
||||
surfaceMaterialMapping.m_materialAsset.QueueLoad();
|
||||
AZ::Data::AssetBus::Handler::BusConnect(surfaceMaterialMapping.m_materialAsset.GetId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TerrainSurfaceMaterialsListComponent::Deactivate()
|
||||
{
|
||||
TerrainAreaMaterialRequestBus::Handler::BusDisconnect();
|
||||
|
||||
for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials)
|
||||
{
|
||||
if (surfaceMaterialMapping.m_materialAsset.GetId().IsValid())
|
||||
{
|
||||
AZ::Data::AssetBus::Handler::BusDisconnect(surfaceMaterialMapping.m_materialAsset.GetId());
|
||||
surfaceMaterialMapping.m_materialAsset.Release();
|
||||
surfaceMaterialMapping.m_materialInstance.reset();
|
||||
surfaceMaterialMapping.m_activeMaterialAssetId = AZ::Data::AssetId();
|
||||
}
|
||||
}
|
||||
|
||||
HandleMaterialStateChanges();
|
||||
}
|
||||
|
||||
int TerrainSurfaceMaterialsListComponent::CountMaterialIDInstances(AZ::Data::AssetId id) const
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (const auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials)
|
||||
{
|
||||
if (surfaceMaterialMapping.m_activeMaterialAssetId == id)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void TerrainSurfaceMaterialsListComponent::HandleMaterialStateChanges()
|
||||
{
|
||||
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);
|
||||
|
||||
if (wasPreviouslyActive)
|
||||
{
|
||||
anyMaterialWasAlreadyActive = true;
|
||||
}
|
||||
|
||||
if (isNowActive)
|
||||
{
|
||||
anyMaterialIsActive = true;
|
||||
}
|
||||
|
||||
surfaceMaterialMapping.m_active = isNowActive;
|
||||
|
||||
if (!wasPreviouslyActive && !isNowActive)
|
||||
{
|
||||
// A material has been assigned but has not yet completed loading.
|
||||
}
|
||||
else if (!wasPreviouslyActive && isNowActive)
|
||||
{
|
||||
// Remember the asset id so we can disconnect from the AssetBus if the material asset is removed.
|
||||
surfaceMaterialMapping.m_activeMaterialAssetId = surfaceMaterialMapping.m_materialAsset.GetId();
|
||||
|
||||
TerrainAreaMaterialNotificationBus::Broadcast(
|
||||
&TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingCreated, GetEntityId(),
|
||||
surfaceMaterialMapping.m_surfaceTag,
|
||||
surfaceMaterialMapping.m_materialInstance);
|
||||
}
|
||||
else if (wasPreviouslyActive && !isNowActive)
|
||||
{
|
||||
// Don't disconnect from the AssetBus if this material is mapped more than once.
|
||||
if (CountMaterialIDInstances(surfaceMaterialMapping.m_activeMaterialAssetId) == 1)
|
||||
{
|
||||
AZ::Data::AssetBus::Handler::BusDisconnect(surfaceMaterialMapping.m_activeMaterialAssetId);
|
||||
}
|
||||
|
||||
surfaceMaterialMapping.m_activeMaterialAssetId = AZ::Data::AssetId();
|
||||
|
||||
TerrainAreaMaterialNotificationBus::Broadcast(
|
||||
&TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingDestroyed, GetEntityId(),
|
||||
surfaceMaterialMapping.m_surfaceTag);
|
||||
}
|
||||
else
|
||||
{
|
||||
TerrainAreaMaterialNotificationBus::Broadcast(
|
||||
&TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingChanged, GetEntityId(),
|
||||
surfaceMaterialMapping.m_surfaceTag,
|
||||
surfaceMaterialMapping.m_materialInstance);
|
||||
}
|
||||
}
|
||||
|
||||
if (!anyMaterialWasAlreadyActive && anyMaterialIsActive)
|
||||
{
|
||||
// Cache the current shape bounds.
|
||||
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
||||
m_cachedAabb, GetEntityId(), &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb);
|
||||
|
||||
// Start listening for data requests.
|
||||
TerrainAreaMaterialRequestBus::Handler::BusConnect(GetEntityId());
|
||||
|
||||
// Start listening for shape changes.
|
||||
LmbrCentral::ShapeComponentNotificationsBus::Handler::BusConnect(GetEntityId());
|
||||
|
||||
}
|
||||
else if (anyMaterialWasAlreadyActive && !anyMaterialIsActive)
|
||||
{
|
||||
// All materials have been deactivated, stop listening for requests and notifications.
|
||||
m_cachedAabb = AZ::Aabb::CreateNull();
|
||||
LmbrCentral::ShapeComponentNotificationsBus::Handler::BusDisconnect();
|
||||
TerrainAreaMaterialRequestBus::Handler::BusConnect(GetEntityId());
|
||||
}
|
||||
}
|
||||
|
||||
bool TerrainSurfaceMaterialsListComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig)
|
||||
{
|
||||
if (auto config = azrtti_cast<const TerrainSurfaceMaterialsListConfig*>(baseConfig))
|
||||
{
|
||||
m_configuration = *config;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TerrainSurfaceMaterialsListComponent::WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const
|
||||
{
|
||||
if (auto config = azrtti_cast<TerrainSurfaceMaterialsListConfig*>(outBaseConfig))
|
||||
{
|
||||
*config = m_configuration;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TerrainSurfaceMaterialsListComponent::OnShapeChanged([[maybe_unused]] ShapeComponentNotifications::ShapeChangeReasons reasons)
|
||||
{
|
||||
AZ::Aabb oldAabb = m_cachedAabb;
|
||||
|
||||
LmbrCentral::ShapeComponentRequestsBus::EventResult(
|
||||
m_cachedAabb, GetEntityId(), &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb);
|
||||
|
||||
TerrainAreaMaterialNotificationBus::Broadcast(
|
||||
&TerrainAreaMaterialNotificationBus::Events::OnTerrainSurfaceMaterialMappingRegionChanged, GetEntityId(), oldAabb,
|
||||
m_cachedAabb);
|
||||
}
|
||||
|
||||
const AZStd::vector<TerrainSurfaceMaterialMapping>& TerrainSurfaceMaterialsListComponent::GetSurfaceMaterialMappings(
|
||||
AZ::Aabb& region) const
|
||||
{
|
||||
region = m_cachedAabb;
|
||||
|
||||
return m_configuration.m_surfaceMaterials;
|
||||
}
|
||||
|
||||
void TerrainSurfaceMaterialsListComponent::OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset)
|
||||
{
|
||||
// Find the missing material instance with the correct id.
|
||||
for (auto& surfaceMaterialMapping : m_configuration.m_surfaceMaterials)
|
||||
{
|
||||
if (surfaceMaterialMapping.m_materialAsset.GetId() == asset.GetId() &&
|
||||
(!surfaceMaterialMapping.m_materialInstance ||
|
||||
surfaceMaterialMapping.m_materialInstance->GetAssetId() != surfaceMaterialMapping.m_materialAsset.GetId()))
|
||||
{
|
||||
surfaceMaterialMapping.m_materialInstance = AZ::RPI::Material::FindOrCreate(surfaceMaterialMapping.m_materialAsset);
|
||||
surfaceMaterialMapping.m_materialAsset.Release();
|
||||
}
|
||||
}
|
||||
HandleMaterialStateChanges();
|
||||
}
|
||||
|
||||
void TerrainSurfaceMaterialsListComponent::OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset)
|
||||
{
|
||||
OnAssetReady(asset);
|
||||
}
|
||||
} // namespace Terrain
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* 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 <Atom/Feature/Material/MaterialAssignment.h>
|
||||
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/Material/EditorMaterialSystemComponentRequestBus.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <LmbrCentral/Shape/ShapeComponentBus.h>
|
||||
#include <SurfaceData/SurfaceDataTypes.h>
|
||||
#include <TerrainRenderer/TerrainAreaMaterialRequestBus.h>
|
||||
|
||||
|
||||
namespace LmbrCentral
|
||||
{
|
||||
template<typename, typename>
|
||||
class EditorWrappedComponentBase;
|
||||
}
|
||||
|
||||
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<AZ::RPI::MaterialAsset> m_materialAsset;
|
||||
AZ::Data::Instance<AZ::RPI::Material> m_materialInstance;
|
||||
|
||||
bool m_active = false;
|
||||
};
|
||||
|
||||
class TerrainSurfaceMaterialsListConfig : public AZ::ComponentConfig
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(TerrainSurfaceMaterialsListConfig, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(TerrainSurfaceMaterialsListConfig, "{68A1CB1B-C835-4C3A-8D1C-08692E07711A}", AZ::ComponentConfig);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
AZStd::vector<TerrainSurfaceMaterialMapping> m_surfaceMaterials;
|
||||
};
|
||||
|
||||
class TerrainSurfaceMaterialsListComponent
|
||||
: public AZ::Component
|
||||
, private TerrainAreaMaterialRequestBus::Handler
|
||||
, private AZ::Data::AssetBus::Handler
|
||||
, private LmbrCentral::ShapeComponentNotificationsBus::Handler
|
||||
{
|
||||
public:
|
||||
template<typename, typename>
|
||||
friend class LmbrCentral::EditorWrappedComponentBase;
|
||||
AZ_COMPONENT(TerrainSurfaceMaterialsListComponent, "{93CF3938-FBC3-4E55-B825-27BA94A5CD35}");
|
||||
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);
|
||||
|
||||
TerrainSurfaceMaterialsListComponent(const TerrainSurfaceMaterialsListConfig& configuration);
|
||||
TerrainSurfaceMaterialsListComponent() = default;
|
||||
~TerrainSurfaceMaterialsListComponent() = 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;
|
||||
|
||||
private:
|
||||
void HandleMaterialStateChanges();
|
||||
int CountMaterialIDInstances(AZ::Data::AssetId id) const;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// ShapeComponentNotificationsBus
|
||||
void OnShapeChanged(ShapeComponentNotifications::ShapeChangeReasons reasons) override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// TerrainAreaMaterialRequestBus
|
||||
const AZStd::vector<TerrainSurfaceMaterialMapping>& GetSurfaceMaterialMappings(AZ::Aabb& region) const override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AZ::Data::AssetBus::Handler
|
||||
void OnAssetReady(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
|
||||
void OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
|
||||
|
||||
TerrainSurfaceMaterialsListConfig m_configuration;
|
||||
|
||||
AZ::Aabb m_cachedAabb;
|
||||
};
|
||||
} // namespace Terrain
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include <TerrainRenderer/EditorComponents/EditorTerrainSurfaceMaterialsListComponent.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/EditContext.h>
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
void EditorTerrainSurfaceMaterialsListComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
BaseClassType::ReflectSubClass<EditorTerrainSurfaceMaterialsListComponent, BaseClassType>(context, 1,
|
||||
&LmbrCentral::EditorWrappedComponentBaseVersionConverter<typename BaseClassType::WrappedComponentType,
|
||||
typename BaseClassType::WrappedConfigType, 1>
|
||||
);
|
||||
}
|
||||
}
|
||||
+32
@@ -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 <TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
|
||||
#include <LmbrCentral/Component/EditorWrappedComponentBase.h>
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
class EditorTerrainSurfaceMaterialsListComponent
|
||||
: public LmbrCentral::EditorWrappedComponentBase<TerrainSurfaceMaterialsListComponent, TerrainSurfaceMaterialsListConfig>
|
||||
{
|
||||
public:
|
||||
using BaseClassType = LmbrCentral::EditorWrappedComponentBase<TerrainSurfaceMaterialsListComponent, TerrainSurfaceMaterialsListConfig>;
|
||||
AZ_EDITOR_COMPONENT(EditorTerrainSurfaceMaterialsListComponent, "{335CDED5-2E76-4342-8675-A60F66C471BF}", BaseClassType);
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
static constexpr const char* const s_categoryName = "Terrain";
|
||||
static constexpr const char* const s_componentName = "Terrain Surface Materials List";
|
||||
static constexpr const char* const s_componentDescription = "Provides a mapping between surface tags and render materials.";
|
||||
static constexpr const char* const s_icon = "Editor/Icons/Components/TerrainHeight.svg";
|
||||
static constexpr const char* const s_viewportIcon = "Editor/Icons/Components/Viewport/TerrainHeight.svg";
|
||||
static constexpr const char* const s_helpUrl = "";
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) Contributors to the Open 3D Engine Project.
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/ComponentBus.h>
|
||||
|
||||
#include <SurfaceData/SurfaceDataTypes.h>
|
||||
|
||||
#include <Atom/RPI.Public/Material/Material.h>
|
||||
|
||||
#include <TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h>
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
//! This bus provides retrieval of information from Terrain Surfaces.
|
||||
class TerrainAreaMaterialRequests
|
||||
: public AZ::ComponentBus
|
||||
{
|
||||
public:
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ~TerrainAreaMaterialRequests() = default;
|
||||
|
||||
//! Get the Material asset assigned to a particular surface tag.
|
||||
virtual const AZStd::vector<struct TerrainSurfaceMaterialMapping>& GetSurfaceMaterialMappings(AZ::Aabb& region) const = 0;
|
||||
};
|
||||
|
||||
using TerrainAreaMaterialRequestBus = AZ::EBus<TerrainAreaMaterialRequests>;
|
||||
|
||||
//! Notifications for when the surface -> material mapping changes..
|
||||
class TerrainAreaMaterialNotifications : public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits overrides
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual void OnTerrainSurfaceMaterialMappingCreated(
|
||||
[[maybe_unused]] AZ::EntityId entityId,
|
||||
[[maybe_unused]] SurfaceData::SurfaceTag surface,
|
||||
[[maybe_unused]] AZ::Data::Instance<AZ::RPI::Material> material)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void OnTerrainSurfaceMaterialMappingDestroyed(
|
||||
[[maybe_unused]] AZ::EntityId entityId,
|
||||
[[maybe_unused]] SurfaceData::SurfaceTag surface)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void OnTerrainSurfaceMaterialMappingChanged(
|
||||
[[maybe_unused]] AZ::EntityId entityId,
|
||||
[[maybe_unused]] SurfaceData::SurfaceTag surface,
|
||||
[[maybe_unused]] AZ::Data::Instance<AZ::RPI::Material> material)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void OnTerrainSurfaceMaterialMappingRegionChanged(
|
||||
[[maybe_unused]] AZ::EntityId entityId,
|
||||
[[maybe_unused]] const AZ::Aabb& oldRegion,
|
||||
[[maybe_unused]] const AZ::Aabb& newRegion)
|
||||
{
|
||||
}
|
||||
};
|
||||
using TerrainAreaMaterialNotificationBus = AZ::EBus<TerrainAreaMaterialNotifications>;
|
||||
} // namespace Terrain
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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 <AzTest/AzTest.h>
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h>
|
||||
#include <MockAxisAlignedBoxShapeComponent.h>
|
||||
|
||||
using ::testing::NiceMock;
|
||||
using ::testing::AtLeast;
|
||||
using ::testing::_;
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
class TerrainSurfaceMaterialsListTest : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
AZ::ComponentApplication m_app;
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
AZ::ComponentApplication::Descriptor appDesc;
|
||||
appDesc.m_memoryBlocksByteSize = 20 * 1024 * 1024;
|
||||
appDesc.m_recordingMode = AZ::Debug::AllocationRecords::RECORD_NO_RECORDS;
|
||||
appDesc.m_stackRecordLevels = 20;
|
||||
|
||||
m_app.Create(appDesc);
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> CreateEntity()
|
||||
{
|
||||
auto entity = AZStd::make_unique<AZ::Entity>();
|
||||
entity->Init();
|
||||
return entity;
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> CreateEntityWithShapeComponents()
|
||||
{
|
||||
auto entity = CreateEntity();
|
||||
|
||||
auto shapeComponent = entity->CreateComponent<UnitTest::MockAxisAlignedBoxShapeComponent>();
|
||||
m_app.RegisterComponentDescriptor(shapeComponent->CreateDescriptor());
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
Terrain::TerrainSurfaceMaterialsListComponent* AddSurfaceMaterialListComponent(AZ::Entity* entity)
|
||||
{
|
||||
auto surfaceMaterialsListComponent = entity->CreateComponent<Terrain::TerrainSurfaceMaterialsListComponent>();
|
||||
m_app.RegisterComponentDescriptor(surfaceMaterialsListComponent->CreateDescriptor());
|
||||
|
||||
return surfaceMaterialsListComponent;
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
m_app.Destroy();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(TerrainSurfaceMaterialsListTest, SurfaceGradientListRequiresShapeToActivate)
|
||||
{
|
||||
auto entity = CreateEntity();
|
||||
|
||||
AddSurfaceMaterialListComponent(entity.get());
|
||||
|
||||
const AZ::Entity::DependencySortOutcome sortOutcome = entity->EvaluateDependenciesGetDetails();
|
||||
EXPECT_FALSE(sortOutcome.IsSuccess());
|
||||
|
||||
entity.reset();
|
||||
}
|
||||
|
||||
TEST_F(TerrainSurfaceMaterialsListTest, SurfaceGradientListActivatesSuccessfully)
|
||||
{
|
||||
auto entity = CreateEntityWithShapeComponents();
|
||||
|
||||
AddSurfaceMaterialListComponent(entity.get());
|
||||
|
||||
entity->Activate();
|
||||
|
||||
EXPECT_EQ(entity->GetState(), AZ::Entity::State::Active);
|
||||
|
||||
entity.reset();
|
||||
}
|
||||
} // namespace UnitTest
|
||||
@@ -25,6 +25,8 @@ set(FILES
|
||||
Source/EditorTerrainModule.h
|
||||
Source/TerrainModule.cpp
|
||||
Source/TerrainModule.h
|
||||
Source/TerrainRenderer/EditorComponents/EditorTerrainSurfaceMaterialsListComponent.cpp
|
||||
Source/TerrainRenderer/EditorComponents/EditorTerrainSurfaceMaterialsListComponent.h
|
||||
Source/TerrainRenderer/EditorComponents/EditorTerrainMacroMaterialComponent.cpp
|
||||
Source/TerrainRenderer/EditorComponents/EditorTerrainMacroMaterialComponent.h
|
||||
)
|
||||
|
||||
@@ -24,10 +24,13 @@ set(FILES
|
||||
Source/Components/TerrainWorldDebuggerComponent.h
|
||||
Source/Components/TerrainWorldRendererComponent.cpp
|
||||
Source/Components/TerrainWorldRendererComponent.h
|
||||
Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.cpp
|
||||
Source/TerrainRenderer/Components/TerrainSurfaceMaterialsListComponent.h
|
||||
Source/TerrainRenderer/Components/TerrainMacroMaterialComponent.cpp
|
||||
Source/TerrainRenderer/Components/TerrainMacroMaterialComponent.h
|
||||
Source/TerrainRenderer/TerrainFeatureProcessor.cpp
|
||||
Source/TerrainRenderer/TerrainFeatureProcessor.h
|
||||
Source/TerrainRenderer/TerrainAreaMaterialRequestBus.h
|
||||
Source/TerrainRenderer/TerrainMacroMaterialBus.h
|
||||
Source/TerrainSystem/TerrainSystem.cpp
|
||||
Source/TerrainSystem/TerrainSystem.h
|
||||
|
||||
@@ -10,5 +10,6 @@ set(FILES
|
||||
Tests/TerrainTest.cpp
|
||||
Tests/TerrainSystemTest.cpp
|
||||
Tests/LayerSpawnerTests.cpp
|
||||
Tests/SurfaceMaterialsListTest.cpp
|
||||
Tests/MockAxisAlignedBoxShapeComponent.h
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user