Terrain/sphrose/layer spawner (#3980)
* #3326 Get layer priorities to work. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Refresh terrain when layer settings change Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Removed dependency notification handling: it isn't needed due to deactivate/activate cycle caused by editor redrawing. Moved layer registering to ordered map sorted by priority. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Remove unused code, add extra sort condition. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Fix copy/paste error. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Change erase method. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Review suggestions. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Fix bus disconnect order, change GetUseGroundPlane to return bool. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Create unit tests for Terrain Spawning component #3224 Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Remove unintended commit. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * Remove blank line. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com> * PR changes. Signed-off-by: sphrose <82213493+sphrose@users.noreply.github.com>
This commit is contained in:
@@ -105,17 +105,19 @@ namespace Terrain
|
||||
AZ::TransformNotificationBus::Handler::BusConnect(GetEntityId());
|
||||
LmbrCentral::ShapeComponentNotificationsBus::Handler::BusConnect(GetEntityId());
|
||||
TerrainAreaRequestBus::Handler::BusConnect(GetEntityId());
|
||||
TerrainSpawnerRequestBus::Handler::BusConnect(GetEntityId());
|
||||
|
||||
TerrainSystemServiceRequestBus::Broadcast(&TerrainSystemServiceRequestBus::Events::RegisterArea, GetEntityId());
|
||||
}
|
||||
|
||||
void TerrainLayerSpawnerComponent::Deactivate()
|
||||
{
|
||||
TerrainAreaRequestBus::Handler::BusDisconnect();
|
||||
TerrainSystemServiceRequestBus::Broadcast(&TerrainSystemServiceRequestBus::Events::UnregisterArea, GetEntityId());
|
||||
|
||||
AZ::TransformNotificationBus::Handler::BusDisconnect();
|
||||
TerrainSpawnerRequestBus::Handler::BusDisconnect();
|
||||
TerrainAreaRequestBus::Handler::BusDisconnect();
|
||||
LmbrCentral::ShapeComponentNotificationsBus::Handler::BusDisconnect();
|
||||
AZ::TransformNotificationBus::Handler::BusDisconnect();
|
||||
|
||||
}
|
||||
|
||||
bool TerrainLayerSpawnerComponent::ReadInConfig(const AZ::ComponentConfig* baseConfig)
|
||||
@@ -147,6 +149,17 @@ namespace Terrain
|
||||
{
|
||||
RefreshArea();
|
||||
}
|
||||
|
||||
void TerrainLayerSpawnerComponent::GetPriority(AZ::u32& outLayer, AZ::u32& outPriority)
|
||||
{
|
||||
outLayer = m_configuration.m_layer;
|
||||
outPriority = m_configuration.m_priority;
|
||||
}
|
||||
|
||||
bool TerrainLayerSpawnerComponent::GetUseGroundPlane()
|
||||
{
|
||||
return m_configuration.m_useGroundPlane;
|
||||
}
|
||||
|
||||
void TerrainLayerSpawnerComponent::RegisterArea()
|
||||
{
|
||||
|
||||
@@ -59,6 +59,7 @@ namespace Terrain
|
||||
, private AZ::TransformNotificationBus::Handler
|
||||
, private LmbrCentral::ShapeComponentNotificationsBus::Handler
|
||||
, private Terrain::TerrainAreaRequestBus::Handler
|
||||
, private Terrain::TerrainSpawnerRequestBus::Handler
|
||||
{
|
||||
public:
|
||||
template<typename, typename>
|
||||
@@ -80,7 +81,6 @@ namespace Terrain
|
||||
bool ReadInConfig(const AZ::ComponentConfig* baseConfig) override;
|
||||
bool WriteOutConfig(AZ::ComponentConfig* outBaseConfig) const override;
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AZ::TransformNotificationBus::Handler
|
||||
void OnTransformChanged(const AZ::Transform& local, const AZ::Transform& world) override;
|
||||
@@ -88,6 +88,10 @@ namespace Terrain
|
||||
// ShapeComponentNotificationsBus
|
||||
void OnShapeChanged(ShapeChangeReasons changeReason) override;
|
||||
|
||||
// TerrainSpawnerRequestBus
|
||||
void GetPriority(AZ::u32& outLayer, AZ::u32& outPriority) override;
|
||||
bool GetUseGroundPlane() override;
|
||||
|
||||
void RegisterArea() override;
|
||||
void RefreshArea() override;
|
||||
|
||||
|
||||
@@ -17,6 +17,33 @@
|
||||
|
||||
using namespace Terrain;
|
||||
|
||||
bool TerrainLayerPriorityComparator::operator()(const AZ::EntityId& layer1id, const AZ::EntityId& layer2id) const
|
||||
{
|
||||
// Comparator for insertion/keylookup.
|
||||
// Sorts into layer/priority order, highest priority first.
|
||||
AZ::u32 priority1, layer1;
|
||||
Terrain::TerrainSpawnerRequestBus::Event(layer1id, &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer1, priority1);
|
||||
|
||||
AZ::u32 priority2, layer2;
|
||||
Terrain::TerrainSpawnerRequestBus::Event(layer2id, &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer2, priority2);
|
||||
|
||||
if (layer1 < layer2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (layer1 > layer2)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (priority1 != priority2)
|
||||
{
|
||||
return priority1 > priority2;
|
||||
}
|
||||
|
||||
return layer1id > layer2id;
|
||||
}
|
||||
|
||||
TerrainSystem::TerrainSystem()
|
||||
{
|
||||
Terrain::TerrainSystemServiceRequestBus::Handler::BusConnect();
|
||||
@@ -78,17 +105,14 @@ float TerrainSystem::GetHeightSynchronous(float x, float y) const
|
||||
|
||||
AZStd::shared_lock<AZStd::shared_mutex> lock(m_areaMutex);
|
||||
|
||||
if (!m_registeredAreas.empty())
|
||||
for (auto& [areaId, areaBounds] : m_registeredAreas)
|
||||
{
|
||||
for (auto& [areaId, areaBounds] : m_registeredAreas)
|
||||
inPosition.SetZ(areaBounds.GetMin().GetZ());
|
||||
if (areaBounds.Contains(inPosition))
|
||||
{
|
||||
inPosition.SetZ(areaBounds.GetMin().GetZ());
|
||||
if (areaBounds.Contains(inPosition))
|
||||
{
|
||||
Terrain::TerrainAreaHeightRequestBus::Event(
|
||||
areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition,
|
||||
Terrain::TerrainAreaHeightRequestBus::Events::Sampler::DEFAULT);
|
||||
}
|
||||
Terrain::TerrainAreaHeightRequestBus::Event(
|
||||
areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition,
|
||||
Terrain::TerrainAreaHeightRequestBus::Events::Sampler::DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,26 +329,34 @@ void TerrainSystem::SystemDeactivate()
|
||||
|
||||
void TerrainSystem::RegisterArea(AZ::EntityId areaId)
|
||||
{
|
||||
{
|
||||
AZStd::unique_lock<AZStd::shared_mutex> lock(m_areaMutex);
|
||||
AZ::Aabb aabb = AZ::Aabb::CreateNull();
|
||||
LmbrCentral::ShapeComponentRequestsBus::EventResult(aabb, areaId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb);
|
||||
m_registeredAreas[areaId] = aabb;
|
||||
}
|
||||
|
||||
RefreshArea(areaId);
|
||||
AZStd::unique_lock<AZStd::shared_mutex> lock(m_areaMutex);
|
||||
AZ::Aabb aabb = AZ::Aabb::CreateNull();
|
||||
LmbrCentral::ShapeComponentRequestsBus::EventResult(aabb, areaId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb);
|
||||
m_registeredAreas[areaId] = aabb;
|
||||
m_dirtyRegion.AddAabb(aabb);
|
||||
m_terrainHeightDirty = true;
|
||||
}
|
||||
|
||||
void TerrainSystem::UnregisterArea(AZ::EntityId areaId)
|
||||
{
|
||||
{
|
||||
AZStd::unique_lock<AZStd::shared_mutex> lock(m_areaMutex);
|
||||
AZ::Aabb aabb = AZ::Aabb::CreateNull();
|
||||
LmbrCentral::ShapeComponentRequestsBus::EventResult(aabb, areaId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb);
|
||||
m_registeredAreas.erase(areaId);
|
||||
}
|
||||
AZStd::unique_lock<AZStd::shared_mutex> lock(m_areaMutex);
|
||||
|
||||
RefreshArea(areaId);
|
||||
// Remove the data for this entity from the registered areas.
|
||||
// Erase_if is used as erase would use the comparator to lookup the entity id in the map.
|
||||
// As the comparator will get the new layer/priority data for the entity, the id lookup will fail.
|
||||
AZStd::erase_if(
|
||||
m_registeredAreas,
|
||||
[areaId, this](const auto& item)
|
||||
{
|
||||
auto const& [entityId, aabb] = item;
|
||||
if (areaId == entityId)
|
||||
{
|
||||
m_dirtyRegion.AddAabb(aabb);
|
||||
m_terrainHeightDirty = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
void TerrainSystem::RefreshArea(AZ::EntityId areaId)
|
||||
@@ -336,7 +368,6 @@ void TerrainSystem::RefreshArea(AZ::EntityId areaId)
|
||||
AZ::Aabb oldAabb = (areaAabb != m_registeredAreas.end()) ? areaAabb->second : AZ::Aabb::CreateNull();
|
||||
AZ::Aabb newAabb = AZ::Aabb::CreateNull();
|
||||
LmbrCentral::ShapeComponentRequestsBus::EventResult(newAabb, areaId, &LmbrCentral::ShapeComponentRequestsBus::Events::GetEncompassingAabb);
|
||||
|
||||
m_registeredAreas[areaId] = newAabb;
|
||||
|
||||
AZ::Aabb expandedAabb = oldAabb;
|
||||
@@ -400,31 +431,37 @@ void TerrainSystem::OnTick(float /*deltaTime*/, AZ::ScriptTimePoint /*time*/)
|
||||
const uint32_t pixelDataSize = width * height * sizeof(float);
|
||||
memset(pixels.data(), 0, pixelDataSize);
|
||||
|
||||
for (auto& [areaId, areaBounds] : m_registeredAreas)
|
||||
for (uint32_t y = 0; y < height; y++)
|
||||
{
|
||||
for (uint32_t y = 0; y < height; y++)
|
||||
for (uint32_t x = 0; x < width; x++)
|
||||
{
|
||||
for (uint32_t x = 0; x < width; x++)
|
||||
// Find the first terrain layer that covers this position. This will be the highest priority, so others can be ignored.
|
||||
for (auto& [areaId, areaBounds] : m_registeredAreas)
|
||||
{
|
||||
AZ::Vector3 inPosition(
|
||||
(x * m_currentSettings.m_heightQueryResolution.GetX()) + m_currentSettings.m_worldBounds.GetMin().GetX(),
|
||||
(y * m_currentSettings.m_heightQueryResolution.GetY()) + m_currentSettings.m_worldBounds.GetMin().GetY(),
|
||||
areaBounds.GetMin().GetZ());
|
||||
if (areaBounds.Contains(inPosition))
|
||||
|
||||
if (!areaBounds.Contains(inPosition))
|
||||
{
|
||||
AZ::Vector3 outPosition;
|
||||
const Terrain::TerrainAreaHeightRequests::Sampler sampleFilter =
|
||||
Terrain::TerrainAreaHeightRequests::Sampler::DEFAULT;
|
||||
|
||||
Terrain::TerrainAreaHeightRequestBus::Event(
|
||||
areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, sampleFilter);
|
||||
|
||||
pixels[(y * width) + x] = (outPosition.GetZ() - m_currentSettings.m_worldBounds.GetMin().GetZ()) /
|
||||
m_currentSettings.m_worldBounds.GetExtents().GetZ();
|
||||
continue;
|
||||
}
|
||||
|
||||
AZ::Vector3 outPosition;
|
||||
const Terrain::TerrainAreaHeightRequests::Sampler sampleFilter = Terrain::TerrainAreaHeightRequests::Sampler::DEFAULT;
|
||||
|
||||
Terrain::TerrainAreaHeightRequestBus::Event(
|
||||
areaId, &Terrain::TerrainAreaHeightRequestBus::Events::GetHeight, inPosition, outPosition, sampleFilter);
|
||||
|
||||
pixels[(y * width) + x] = (outPosition.GetZ() - m_currentSettings.m_worldBounds.GetMin().GetZ()) /
|
||||
m_currentSettings.m_worldBounds.GetExtents().GetZ();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const AZ::RPI::Scene* scene = AZ::RPI::RPISystemInterface::Get()->GetDefaultScene().get();
|
||||
auto terrainFeatureProcessor = scene->GetFeatureProcessor<TerrainFeatureProcessor>();
|
||||
|
||||
@@ -25,6 +25,11 @@
|
||||
|
||||
namespace Terrain
|
||||
{
|
||||
struct TerrainLayerPriorityComparator
|
||||
{
|
||||
bool operator()(const AZ::EntityId& layer1id, const AZ::EntityId& layer2id) const;
|
||||
};
|
||||
|
||||
class TerrainSystem
|
||||
: public AzFramework::Terrain::TerrainDataRequestBus::Handler
|
||||
, private Terrain::TerrainSystemServiceRequestBus::Handler
|
||||
@@ -112,6 +117,6 @@ namespace Terrain
|
||||
AZ::Aabb m_dirtyRegion;
|
||||
|
||||
mutable AZStd::shared_mutex m_areaMutex;
|
||||
AZStd::unordered_map<AZ::EntityId, AZ::Aabb> m_registeredAreas;
|
||||
AZStd::map<AZ::EntityId, AZ::Aabb, TerrainLayerPriorityComparator> m_registeredAreas;
|
||||
};
|
||||
} // namespace Terrain
|
||||
|
||||
@@ -112,5 +112,26 @@ namespace Terrain
|
||||
};
|
||||
|
||||
using TerrainAreaHeightRequestBus = AZ::EBus<TerrainAreaHeightRequests>;
|
||||
|
||||
/**
|
||||
* A bus for the TerrainSystem to interrogate TerrainLayerSpawners.
|
||||
*/
|
||||
class TerrainSpawnerRequests
|
||||
: public AZ::ComponentBus
|
||||
{
|
||||
public:
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// EBusTraits
|
||||
using MutexType = AZStd::recursive_mutex;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
virtual ~TerrainSpawnerRequests() = default;
|
||||
|
||||
virtual void GetPriority(AZ::u32& outLayer, AZ::u32& outPriority) = 0;
|
||||
virtual bool GetUseGroundPlane() = 0;
|
||||
|
||||
};
|
||||
|
||||
using TerrainSpawnerRequestBus = AZ::EBus<TerrainSpawnerRequests>;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* 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 <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzCore/Memory/MemoryComponent.h>
|
||||
|
||||
#include <AzFramework/Terrain/TerrainDataRequestBus.h>
|
||||
|
||||
#include <Components/TerrainLayerSpawnerComponent.h>
|
||||
#include <LmbrCentral/Shape/BoxShapeComponentBus.h>
|
||||
#include <AzTest/AzTest.h>
|
||||
|
||||
#include <TerrainMocks.h>
|
||||
|
||||
class LayerSpawnerComponentTest
|
||||
: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
AZ::ComponentApplication m_app;
|
||||
|
||||
AZStd::unique_ptr<AZ::Entity> m_entity;
|
||||
Terrain::TerrainLayerSpawnerComponent* m_layerSpawnerComponent;
|
||||
UnitTest::MockBoxShapeComponent* m_shapeComponent;
|
||||
AZStd::unique_ptr<UnitTest::MockTerrainSystem> m_terrainSystem;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
if (m_terrainSystem)
|
||||
{
|
||||
m_terrainSystem->Deactivate();
|
||||
}
|
||||
m_app.Destroy();
|
||||
}
|
||||
|
||||
void CreateEntity()
|
||||
{
|
||||
m_entity = AZStd::make_unique<AZ::Entity>();
|
||||
m_entity->Init();
|
||||
|
||||
ASSERT_TRUE(m_entity);
|
||||
}
|
||||
|
||||
void AddLayerSpawnerAndShapeComponentToEntity()
|
||||
{
|
||||
AddLayerSpawnerAndShapeComponentToEntity(Terrain::TerrainLayerSpawnerConfig());
|
||||
}
|
||||
|
||||
void AddLayerSpawnerAndShapeComponentToEntity(const Terrain::TerrainLayerSpawnerConfig& config)
|
||||
{
|
||||
m_layerSpawnerComponent = m_entity->CreateComponent<Terrain::TerrainLayerSpawnerComponent>(config);
|
||||
m_app.RegisterComponentDescriptor(m_layerSpawnerComponent->CreateDescriptor());
|
||||
|
||||
m_shapeComponent = m_entity->CreateComponent<UnitTest::MockBoxShapeComponent>();
|
||||
m_app.RegisterComponentDescriptor(m_shapeComponent->CreateDescriptor());
|
||||
|
||||
ASSERT_TRUE(m_layerSpawnerComponent);
|
||||
ASSERT_TRUE(m_shapeComponent);
|
||||
}
|
||||
|
||||
void ResetEntity()
|
||||
{
|
||||
m_entity->Deactivate();
|
||||
m_entity->Reset();
|
||||
}
|
||||
|
||||
void CreateMockTerrainSystem()
|
||||
{
|
||||
m_terrainSystem = AZStd::make_unique<UnitTest::MockTerrainSystem>();
|
||||
m_terrainSystem->Activate();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(LayerSpawnerComponentTest, ActivatEntityActivateSuccess)
|
||||
{
|
||||
CreateEntity();
|
||||
AddLayerSpawnerAndShapeComponentToEntity();
|
||||
|
||||
m_entity->Activate();
|
||||
EXPECT_EQ(m_entity->GetState(), AZ::Entity::State::Active);
|
||||
|
||||
ResetEntity();
|
||||
}
|
||||
|
||||
TEST_F(LayerSpawnerComponentTest, LayerSpawnerDefaultValuesCorrect)
|
||||
{
|
||||
CreateEntity();
|
||||
AddLayerSpawnerAndShapeComponentToEntity();
|
||||
|
||||
m_entity->Activate();
|
||||
|
||||
AZ::u32 priority = 999, layer = 999;
|
||||
Terrain::TerrainSpawnerRequestBus::Event(m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer, priority);
|
||||
|
||||
EXPECT_EQ(0, priority);
|
||||
EXPECT_EQ(1, layer);
|
||||
|
||||
bool useGroundPlane = false;
|
||||
|
||||
Terrain::TerrainSpawnerRequestBus::EventResult(useGroundPlane, m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane);
|
||||
|
||||
EXPECT_TRUE(useGroundPlane);
|
||||
|
||||
ResetEntity();
|
||||
}
|
||||
|
||||
TEST_F(LayerSpawnerComponentTest, LayerSpawnerConfigValuesCorrect)
|
||||
{
|
||||
CreateEntity();
|
||||
|
||||
constexpr static AZ::u32 testPriority = 15;
|
||||
constexpr static AZ::u32 testLayer = 0;
|
||||
|
||||
Terrain::TerrainLayerSpawnerConfig config;
|
||||
config.m_layer = testLayer;
|
||||
config.m_priority = testPriority;
|
||||
config.m_useGroundPlane = false;
|
||||
|
||||
AddLayerSpawnerAndShapeComponentToEntity(config);
|
||||
|
||||
m_entity->Activate();
|
||||
|
||||
AZ::u32 priority = 999, layer = 999;
|
||||
Terrain::TerrainSpawnerRequestBus::Event(m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer, priority);
|
||||
|
||||
EXPECT_EQ(testPriority, priority);
|
||||
EXPECT_EQ(testLayer, layer);
|
||||
|
||||
bool useGroundPlane = true;
|
||||
|
||||
Terrain::TerrainSpawnerRequestBus::EventResult(
|
||||
useGroundPlane, m_entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane);
|
||||
|
||||
EXPECT_FALSE(useGroundPlane);
|
||||
|
||||
ResetEntity();
|
||||
}
|
||||
|
||||
TEST_F(LayerSpawnerComponentTest, LayerSpawnerRegisterAreaUpdatesTerrainSystem)
|
||||
{
|
||||
CreateEntity();
|
||||
|
||||
CreateMockTerrainSystem();
|
||||
|
||||
AddLayerSpawnerAndShapeComponentToEntity();
|
||||
|
||||
m_entity->Activate();
|
||||
|
||||
// The Activate call should have registered the area.
|
||||
EXPECT_EQ(1, m_terrainSystem->m_registerAreaCalledCount);
|
||||
|
||||
ResetEntity();
|
||||
}
|
||||
|
||||
TEST_F(LayerSpawnerComponentTest, LayerSpawnerUnregisterAreaUpdatesTerrainSystem)
|
||||
{
|
||||
CreateEntity();
|
||||
|
||||
CreateMockTerrainSystem();
|
||||
|
||||
AddLayerSpawnerAndShapeComponentToEntity();
|
||||
|
||||
m_entity->Activate();
|
||||
|
||||
m_layerSpawnerComponent->Deactivate();
|
||||
|
||||
// The Deactivate call should have unregistered the area.
|
||||
EXPECT_EQ(1, m_terrainSystem->m_unregisterAreaCalledCount);
|
||||
|
||||
ResetEntity();
|
||||
}
|
||||
|
||||
TEST_F(LayerSpawnerComponentTest, LayerSpawnerTransformChangedUpdatesTerrainSystem)
|
||||
{
|
||||
CreateEntity();
|
||||
|
||||
CreateMockTerrainSystem();
|
||||
|
||||
AddLayerSpawnerAndShapeComponentToEntity();
|
||||
|
||||
m_entity->Activate();
|
||||
|
||||
AZ::TransformNotificationBus::Event(
|
||||
m_entity->GetId(), &AZ::TransformNotificationBus::Events::OnTransformChanged, AZ::Transform(), AZ::Transform());
|
||||
|
||||
EXPECT_EQ(1, m_terrainSystem->m_refreshAreaCalledCount);
|
||||
|
||||
ResetEntity();
|
||||
}
|
||||
|
||||
TEST_F(LayerSpawnerComponentTest, LayerSpawnerShapeChangedUpdatesTerrainSystem)
|
||||
{
|
||||
CreateEntity();
|
||||
|
||||
CreateMockTerrainSystem();
|
||||
|
||||
AddLayerSpawnerAndShapeComponentToEntity();
|
||||
|
||||
m_entity->Activate();
|
||||
|
||||
LmbrCentral::ShapeComponentNotificationsBus::Event(
|
||||
m_entity->GetId(), &LmbrCentral::ShapeComponentNotificationsBus::Events::OnShapeChanged,
|
||||
LmbrCentral::ShapeComponentNotifications::ShapeChangeReasons::ShapeChanged);
|
||||
|
||||
EXPECT_EQ(1, m_terrainSystem->m_refreshAreaCalledCount);
|
||||
|
||||
ResetEntity();
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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/ComponentApplication.h>
|
||||
#include <LmbrCentral/Shape/ShapeComponentBus.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
static const AZ::Uuid BoxShapeComponentTypeId = "{5EDF4B9E-0D3D-40B8-8C91-5142BCFC30A6}";
|
||||
|
||||
class MockBoxShapeComponent
|
||||
: public AZ::Component
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(MockBoxShapeComponent, BoxShapeComponentTypeId)
|
||||
static void Reflect([[maybe_unused]] AZ::ReflectContext* context)
|
||||
{
|
||||
}
|
||||
|
||||
void Activate() override
|
||||
{
|
||||
}
|
||||
|
||||
void Deactivate() override
|
||||
{
|
||||
}
|
||||
|
||||
bool ReadInConfig([[maybe_unused]] const AZ::ComponentConfig* baseConfig) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteOutConfig([[maybe_unused]] AZ::ComponentConfig* outBaseConfig) const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
static void GetProvidedServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
{
|
||||
provided.push_back(AZ_CRC("ShapeService", 0xe86aa5fe));
|
||||
provided.push_back(AZ_CRC("BoxShapeService", 0x946a0032));
|
||||
}
|
||||
|
||||
static void GetIncompatibleServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
{
|
||||
}
|
||||
|
||||
static void GetRequiredServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
{
|
||||
}
|
||||
|
||||
static void GetDependentServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& dependent)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
class MockTerrainSystem : private Terrain::TerrainSystemServiceRequestBus::Handler
|
||||
{
|
||||
public:
|
||||
void Activate() override
|
||||
{
|
||||
Terrain::TerrainSystemServiceRequestBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
void Deactivate() override
|
||||
{
|
||||
Terrain::TerrainSystemServiceRequestBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void SetWorldBounds(const AZ::Aabb& worldBounds) override
|
||||
{
|
||||
}
|
||||
|
||||
void SetHeightQueryResolution([[maybe_unused]] AZ::Vector2 queryResolution) override
|
||||
{
|
||||
}
|
||||
|
||||
void RegisterArea([[maybe_unused]] AZ::EntityId areaId) override
|
||||
{
|
||||
m_registerAreaCalledCount++;
|
||||
}
|
||||
|
||||
void UnregisterArea([[maybe_unused]] AZ::EntityId areaId) override
|
||||
{
|
||||
m_unregisterAreaCalledCount++;
|
||||
}
|
||||
|
||||
void RefreshArea([[maybe_unused]] AZ::EntityId areaId) override
|
||||
{
|
||||
m_refreshAreaCalledCount++;
|
||||
}
|
||||
|
||||
int m_registerAreaCalledCount = 0;
|
||||
int m_refreshAreaCalledCount = 0;
|
||||
int m_unregisterAreaCalledCount = 0;
|
||||
};
|
||||
}
|
||||
@@ -7,5 +7,7 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
Tests/TerrainMocks.h
|
||||
Tests/TerrainTest.cpp
|
||||
Tests/LayerSpawnerTests.cpp
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user