LayerSpawnerTests.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzTest/AzTest.h>
  9. #include <AzCore/Component/ComponentApplication.h>
  10. #include <AzCore/Component/TransformBus.h>
  11. #include <Components/TerrainLayerSpawnerComponent.h>
  12. #include <Terrain/MockTerrain.h>
  13. #include <TerrainTestFixtures.h>
  14. using ::testing::NiceMock;
  15. using ::testing::AtLeast;
  16. using ::testing::_;
  17. class LayerSpawnerComponentTest
  18. : public UnitTest::TerrainTestFixture
  19. {
  20. protected:
  21. constexpr static inline float TestBoxHalfBounds = 128.0f;
  22. };
  23. TEST_F(LayerSpawnerComponentTest, ActivateEntityWithoutShapeFails)
  24. {
  25. auto entity = CreateEntity();
  26. entity->CreateComponent<Terrain::TerrainLayerSpawnerComponent>(Terrain::TerrainLayerSpawnerConfig());
  27. const AZ::Entity::DependencySortOutcome sortOutcome = entity->EvaluateDependenciesGetDetails();
  28. EXPECT_FALSE(sortOutcome.IsSuccess());
  29. entity.reset();
  30. }
  31. TEST_F(LayerSpawnerComponentTest, ActivateEntityActivateSuccess)
  32. {
  33. auto entity = CreateTestBoxEntity(TestBoxHalfBounds);
  34. entity->CreateComponent<Terrain::TerrainLayerSpawnerComponent>(Terrain::TerrainLayerSpawnerConfig());
  35. ActivateEntity(entity.get());
  36. EXPECT_EQ(entity->GetState(), AZ::Entity::State::Active);
  37. entity.reset();
  38. }
  39. TEST_F(LayerSpawnerComponentTest, LayerSpawnerDefaultValuesCorrect)
  40. {
  41. auto entity = CreateTestBoxEntity(TestBoxHalfBounds);
  42. entity->CreateComponent<Terrain::TerrainLayerSpawnerComponent>(Terrain::TerrainLayerSpawnerConfig());
  43. ActivateEntity(entity.get());
  44. int32_t priority = 999;
  45. uint32_t layer = 999;
  46. Terrain::TerrainSpawnerRequestBus::Event(entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer, priority);
  47. EXPECT_EQ(0, priority);
  48. EXPECT_EQ(1, layer);
  49. bool useGroundPlane = false;
  50. Terrain::TerrainSpawnerRequestBus::EventResult(
  51. useGroundPlane, entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane);
  52. EXPECT_TRUE(useGroundPlane);
  53. entity.reset();
  54. }
  55. TEST_F(LayerSpawnerComponentTest, LayerSpawnerConfigValuesCorrect)
  56. {
  57. auto entity = CreateTestBoxEntity(TestBoxHalfBounds);
  58. constexpr static AZ::u32 testPriority = 15;
  59. constexpr static AZ::u32 testLayer = 0;
  60. Terrain::TerrainLayerSpawnerConfig config;
  61. config.m_layer = testLayer;
  62. config.m_priority = testPriority;
  63. config.m_useGroundPlane = false;
  64. entity->CreateComponent<Terrain::TerrainLayerSpawnerComponent>(config);
  65. ActivateEntity(entity.get());
  66. int32_t priority = 999;
  67. uint32_t layer = 999;
  68. Terrain::TerrainSpawnerRequestBus::Event(entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetPriority, layer, priority);
  69. EXPECT_EQ(testPriority, priority);
  70. EXPECT_EQ(testLayer, layer);
  71. bool useGroundPlane = true;
  72. Terrain::TerrainSpawnerRequestBus::EventResult(
  73. useGroundPlane, entity->GetId(), &Terrain::TerrainSpawnerRequestBus::Events::GetUseGroundPlane);
  74. EXPECT_FALSE(useGroundPlane);
  75. entity.reset();
  76. }
  77. TEST_F(LayerSpawnerComponentTest, LayerSpawnerRegisterAreaUpdatesTerrainSystem)
  78. {
  79. auto entity = CreateTestBoxEntity(TestBoxHalfBounds);
  80. NiceMock<UnitTest::MockTerrainSystemService> terrainSystem;
  81. // The Activate call should register the area.
  82. EXPECT_CALL(terrainSystem, RegisterArea(_)).Times(1);
  83. entity->CreateComponent<Terrain::TerrainLayerSpawnerComponent>(Terrain::TerrainLayerSpawnerConfig());
  84. ActivateEntity(entity.get());
  85. entity.reset();
  86. }
  87. TEST_F(LayerSpawnerComponentTest, LayerSpawnerUnregisterAreaUpdatesTerrainSystem)
  88. {
  89. auto entity = CreateTestBoxEntity(TestBoxHalfBounds);
  90. NiceMock<UnitTest::MockTerrainSystemService> terrainSystem;
  91. // The Deactivate call should unregister the area.
  92. EXPECT_CALL(terrainSystem, UnregisterArea(_)).Times(1);
  93. entity->CreateComponent<Terrain::TerrainLayerSpawnerComponent>(Terrain::TerrainLayerSpawnerConfig());
  94. ActivateEntity(entity.get());
  95. entity.reset();
  96. }
  97. TEST_F(LayerSpawnerComponentTest, LayerSpawnerTransformChangedUpdatesTerrainSystem)
  98. {
  99. auto entity = CreateTestBoxEntity(TestBoxHalfBounds);
  100. NiceMock<UnitTest::MockTerrainSystemService> terrainSystem;
  101. // The TransformChanged call should refresh the area.
  102. EXPECT_CALL(terrainSystem, RefreshArea(_, _)).Times(1);
  103. entity->CreateComponent<Terrain::TerrainLayerSpawnerComponent>(Terrain::TerrainLayerSpawnerConfig());
  104. ActivateEntity(entity.get());
  105. // The component gets transform change notifications via the shape bus.
  106. LmbrCentral::ShapeComponentNotificationsBus::Event(
  107. entity->GetId(), &LmbrCentral::ShapeComponentNotificationsBus::Events::OnShapeChanged,
  108. LmbrCentral::ShapeComponentNotifications::ShapeChangeReasons::TransformChanged);
  109. entity.reset();
  110. }
  111. TEST_F(LayerSpawnerComponentTest, LayerSpawnerShapeChangedUpdatesTerrainSystem)
  112. {
  113. auto entity = CreateTestBoxEntity(TestBoxHalfBounds);
  114. NiceMock<UnitTest::MockTerrainSystemService> terrainSystem;
  115. // The ShapeChanged call should refresh the area.
  116. EXPECT_CALL(terrainSystem, RefreshArea(_, _)).Times(1);
  117. entity->CreateComponent<Terrain::TerrainLayerSpawnerComponent>(Terrain::TerrainLayerSpawnerConfig());
  118. ActivateEntity(entity.get());
  119. LmbrCentral::ShapeComponentNotificationsBus::Event(
  120. entity->GetId(), &LmbrCentral::ShapeComponentNotificationsBus::Events::OnShapeChanged,
  121. LmbrCentral::ShapeComponentNotifications::ShapeChangeReasons::ShapeChanged);
  122. entity.reset();
  123. }
  124. TEST_F(LayerSpawnerComponentTest, LayerSpawnerCreatesGroundPlaneWhenUseGroundPlaneSet)
  125. {
  126. // Create a terrain world with height bounds from -128 to 128.
  127. const float queryResolution = 1.0f;
  128. const AzFramework::Terrain::FloatRange heightBounds = { -128.0f, 128.0f };
  129. auto terrainSystem = CreateAndActivateTerrainSystem(queryResolution, heightBounds);
  130. // Create a terrain spawner with useGroundPlane enabled and a box from 0 to 32.
  131. Terrain::TerrainLayerSpawnerConfig config;
  132. config.m_useGroundPlane = true;
  133. const float SpawnerBoxHalfBounds = 16.0f;
  134. auto entity = CreateTestBoxEntity(SpawnerBoxHalfBounds);
  135. entity->CreateComponent<Terrain::TerrainLayerSpawnerComponent>(config);
  136. ActivateEntity(entity.get());
  137. // Querying for terrain heights at the center of the spawner box should give us a valid point with a height equal to the min
  138. // height of the spawner box, not the min height of the terrain world.
  139. bool terrainExists = false;
  140. AZStd::array<AZ::Vector3, 1> positionList = { AZ::Vector3(16.0f, 16.0f, 16.0f) };
  141. float height = terrainSystem->GetHeight(
  142. positionList[0], AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT, &terrainExists);
  143. EXPECT_TRUE(terrainExists);
  144. EXPECT_EQ(height, 0.0f);
  145. // Verify that the results from QueryList also use the "useGroundPlane" setting.
  146. terrainSystem->QueryList(
  147. positionList,
  148. AzFramework::Terrain::TerrainDataRequests::TerrainDataMask::Heights,
  149. [](const AzFramework::SurfaceData::SurfacePoint& surfacePoint, bool terrainExists)
  150. {
  151. EXPECT_TRUE(terrainExists);
  152. EXPECT_EQ(surfacePoint.m_position.GetZ(), 0.0f);
  153. },
  154. AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT);
  155. entity.reset();
  156. terrainSystem.reset();
  157. }
  158. TEST_F(LayerSpawnerComponentTest, LayerSpawnerDoesNotCreateGroundPlaneWhenUseGroundPlaneNotSet)
  159. {
  160. // Create a terrain world with height bounds from -128 to 128.
  161. const float queryResolution = 1.0f;
  162. const AzFramework::Terrain::FloatRange heightBounds = { -128.0f, 128.0f };
  163. auto terrainSystem = CreateAndActivateTerrainSystem(queryResolution, heightBounds);
  164. // Create a terrain spawner with useGroundPlane disabled and a box from 0 to 32.
  165. Terrain::TerrainLayerSpawnerConfig config;
  166. config.m_useGroundPlane = false;
  167. const float SpawnerBoxHalfBounds = 16.0f;
  168. auto entity = CreateTestBoxEntity(SpawnerBoxHalfBounds);
  169. entity->CreateComponent<Terrain::TerrainLayerSpawnerComponent>(config);
  170. ActivateEntity(entity.get());
  171. // Querying for terrain heights at the center of the spawner box should give us a invalid point because useGroundPlane isn't enabled.
  172. bool terrainExists = false;
  173. AZStd::array<AZ::Vector3, 1> positionList = { AZ::Vector3(16.0f, 16.0f, 16.0f) };
  174. float height = terrainSystem->GetHeight(positionList[0], AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT, &terrainExists);
  175. EXPECT_FALSE(terrainExists);
  176. EXPECT_EQ(height, -128.0f);
  177. // Verify that the results from QueryList also use the "useGroundPlane" setting.
  178. terrainSystem->QueryList(
  179. positionList,
  180. AzFramework::Terrain::TerrainDataRequests::TerrainDataMask::Heights,
  181. [](const AzFramework::SurfaceData::SurfacePoint& surfacePoint, bool terrainExists)
  182. {
  183. EXPECT_FALSE(terrainExists);
  184. EXPECT_EQ(surfacePoint.m_position.GetZ(), -128.0f);
  185. },
  186. AzFramework::Terrain::TerrainDataRequests::Sampler::EXACT);
  187. entity.reset();
  188. terrainSystem.reset();
  189. }