EditorBoxShapeComponentTests.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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 "LmbrCentralReflectionTest.h"
  9. #include "Shape/EditorBoxShapeComponent.h"
  10. #include "Shape/EditorSphereShapeComponent.h"
  11. #include <AZTestShared/Utils/Utils.h>
  12. #include <AzCore/Component/NonUniformScaleBus.h>
  13. #include <AzToolsFramework/ComponentModes/ShapeComponentModeBus.h>
  14. #include <AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.h>
  15. #include <AzToolsFramework/Viewport/ViewportSettings.h>
  16. #include <EditorShapeTestUtils.h>
  17. namespace LmbrCentral
  18. {
  19. // Serialized legacy EditorBoxShapeComponent v1.
  20. const char kEditorBoxComponentVersion1[] =
  21. R"DELIMITER(<ObjectStream version="1">
  22. <Class name="EditorBoxShapeComponent" field="element" version="1" type="{2ADD9043-48E8-4263-859A-72E0024372BF}">
  23. <Class name="EditorComponentBase" field="BaseClass1" version="1" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}">
  24. <Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
  25. <Class name="AZ::u64" field="Id" value="7702953324769442676" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
  26. </Class>
  27. </Class>
  28. <Class name="BoxShapeConfig" field="Configuration" version="1" type="{F034FBA2-AC2F-4E66-8152-14DFB90D6283}">
  29. <Class name="Vector3" field="Dimensions" value="0.3700000 0.5700000 0.6600000" type="{8379EB7D-01FA-4538-B64B-A6543B4BE73D}"/>
  30. </Class>
  31. </Class>
  32. </ObjectStream>)DELIMITER";
  33. class LoadEditorBoxShapeComponentFromVersion1
  34. : public LoadEditorComponentTest<EditorBoxShapeComponent>
  35. {
  36. protected:
  37. const char* GetSourceDataBuffer() const override { return kEditorBoxComponentVersion1; }
  38. };
  39. TEST_F(LoadEditorBoxShapeComponentFromVersion1, Application_IsRunning)
  40. {
  41. ASSERT_NE(GetApplication(), nullptr);
  42. }
  43. TEST_F(LoadEditorBoxShapeComponentFromVersion1, Components_Load)
  44. {
  45. EXPECT_NE(m_object.get(), nullptr);
  46. }
  47. TEST_F(LoadEditorBoxShapeComponentFromVersion1, EditorComponent_Found)
  48. {
  49. EXPECT_EQ(m_entity->GetComponents().size(), 2);
  50. EXPECT_NE(m_entity->FindComponent(m_object->GetId()), nullptr);
  51. }
  52. TEST_F(LoadEditorBoxShapeComponentFromVersion1, Dimensions_MatchesSourceData)
  53. {
  54. AZ::Vector3 dimensions = AZ::Vector3::CreateZero();
  55. BoxShapeComponentRequestsBus::EventResult(
  56. dimensions, m_entity->GetId(), &BoxShapeComponentRequests::GetBoxDimensions);
  57. EXPECT_EQ(dimensions, AZ::Vector3(0.37f, 0.57f, 0.66f));
  58. }
  59. class EditorBoxShapeComponentFixture
  60. : public UnitTest::ToolsApplicationFixture<>
  61. {
  62. public:
  63. void SetUpEditorFixtureImpl() override;
  64. void TearDownEditorFixtureImpl() override;
  65. AZStd::unique_ptr<AZ::ComponentDescriptor> m_editorBoxShapeComponentDescriptor;
  66. AZStd::unique_ptr<AZ::ComponentDescriptor> m_editorSphereShapeComponentDescriptor;
  67. AZ::Entity* m_entity = nullptr;
  68. AZ::EntityId m_entityId;
  69. AZ::EntityComponentIdPair m_entityComponentIdPair;
  70. };
  71. void EditorBoxShapeComponentFixture::SetUpEditorFixtureImpl()
  72. {
  73. AZ::SerializeContext* serializeContext = nullptr;
  74. AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
  75. // need to reflect EditorSphereShapeComponent in order for EditorBaseShapeComponent to be reflected
  76. m_editorSphereShapeComponentDescriptor = AZStd::unique_ptr<AZ::ComponentDescriptor>(EditorSphereShapeComponent::CreateDescriptor());
  77. m_editorBoxShapeComponentDescriptor =
  78. AZStd::unique_ptr<AZ::ComponentDescriptor>(EditorBoxShapeComponent::CreateDescriptor());
  79. ShapeComponentConfig::Reflect(serializeContext);
  80. BoxShape::Reflect(serializeContext);
  81. m_editorSphereShapeComponentDescriptor->Reflect(serializeContext);
  82. m_editorBoxShapeComponentDescriptor->Reflect(serializeContext);
  83. UnitTest::CreateDefaultEditorEntity("BoxShapeComponentEntity", &m_entity);
  84. m_entityId = m_entity->GetId();
  85. m_entity->Deactivate();
  86. m_entity->CreateComponent(AzToolsFramework::Components::EditorNonUniformScaleComponent::RTTI_Type());
  87. m_entityComponentIdPair =
  88. AZ::EntityComponentIdPair(m_entityId, m_entity->CreateComponent(EditorBoxShapeComponentTypeId)->GetId());
  89. m_entity->Activate();
  90. }
  91. void EditorBoxShapeComponentFixture::TearDownEditorFixtureImpl()
  92. {
  93. AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
  94. &AzToolsFramework::EditorEntityContextRequestBus::Events::DestroyEditorEntity, m_entityId);
  95. m_entity = nullptr;
  96. m_entityId.SetInvalid();
  97. m_editorBoxShapeComponentDescriptor.reset();
  98. m_editorSphereShapeComponentDescriptor.reset();
  99. }
  100. using EditorBoxShapeComponentManipulatorFixture =
  101. UnitTest::IndirectCallManipulatorViewportInteractionFixtureMixin<EditorBoxShapeComponentFixture>;
  102. void SetUpBoxShapeComponent(
  103. AZ::EntityId entityId,
  104. const AZ::Transform& transform,
  105. const AZ::Vector3& nonUniformScale,
  106. const AZ::Vector3& translationOffset,
  107. const AZ::Vector3& boxDimensions)
  108. {
  109. AZ::TransformBus::Event(entityId, &AZ::TransformBus::Events::SetWorldTM, transform);
  110. AZ::NonUniformScaleRequestBus::Event(entityId, &AZ::NonUniformScaleRequests::SetScale, nonUniformScale);
  111. ShapeComponentRequestsBus::Event(entityId, &ShapeComponentRequests::SetTranslationOffset, translationOffset);
  112. BoxShapeComponentRequestsBus::Event(entityId, &BoxShapeComponentRequests::SetBoxDimensions, boxDimensions);
  113. }
  114. TEST_F(EditorBoxShapeComponentManipulatorFixture, BoxShapeNonUniformScaleSymmetricalDimensionManipulatorsScaleCorrectly)
  115. {
  116. // a rotation which rotates the x-axis to (0.8, 0.6, 0)
  117. const AZ::Quaternion boxRotation(0.0f, 0.0f, 0.316228f, 0.948683f);
  118. AZ::Transform boxTransform(AZ::Vector3(2.0f, 3.0f, 4.0f), boxRotation, 1.5f);
  119. const AZ::Vector3 nonUniformScale(4.0f, 1.5f, 2.0f);
  120. const AZ::Vector3 boxDimensions(1.0f, 2.0f, 2.5f);
  121. const AZ::Vector3 translationOffset = AZ::Vector3::CreateZero();
  122. SetUpBoxShapeComponent(m_entity->GetId(), boxTransform, nonUniformScale, translationOffset, boxDimensions);
  123. EnterComponentMode(m_entityId, EditorBoxShapeComponentTypeId);
  124. // position the camera so it is looking down at the box
  125. AzFramework::SetCameraTransform(
  126. m_cameraState,
  127. AZ::Transform::CreateFromQuaternionAndTranslation(
  128. AZ::Quaternion::CreateRotationX(-AZ::Constants::HalfPi), AZ::Vector3(2.0f, 3.0f, 20.0f)));
  129. // position in world space which should allow grabbing the box's x scale manipulator
  130. // the unscaled position of the x scale manipulator in the box's local frame should be (0.5f, 0.0f, 0.0f)
  131. // after non-uniform scale, the manipulator position should be (2.0f, 0.0f, 0.0f)
  132. // after the scale of the entity transform, the manipulator position should be (3.0f, 0.0f, 0.0f)
  133. // after the rotation of the entity transform, the manipulator position should be (2.4f, 1.8f, 0.0f)
  134. // after the translation of the entity transform, the manipulator position should be (4.4f, 4.8f, 4.0f)
  135. const AZ::Vector3 worldStart(4.4f, 4.8f, 4.0f);
  136. // position in world space to move to
  137. const AZ::Vector3 worldEnd(6.8f, 6.6f, 4.0f);
  138. DragMouse(m_cameraState, m_actionDispatcher.get(), worldStart, worldEnd, AzToolsFramework::DefaultSymmetricalEditingModifier);
  139. ExpectBoxDimensions(m_entityId, AZ::Vector3(2.0f, 2.0f, 2.5f));
  140. }
  141. TEST_F(EditorBoxShapeComponentManipulatorFixture, BoxShapeNonUniformScaleAsymmetricalDimensionManipulatorsScaleCorrectly)
  142. {
  143. const AZ::Quaternion boxRotation(0.2f, 0.4f, -0.4f, 0.8f);
  144. AZ::Transform boxTransform(AZ::Vector3(4.0f, -6.0f, -5.0f), boxRotation, 0.5f);
  145. const AZ::Vector3 nonUniformScale(2.0f, 0.5f, 1.5f);
  146. const AZ::Vector3 boxDimensions(3.0f, 6.0f, 2.0f);
  147. const AZ::Vector3 translationOffset(2.0f, -5.0f, 4.0f);
  148. SetUpBoxShapeComponent(m_entityId, boxTransform, nonUniformScale, translationOffset, boxDimensions);
  149. EnterComponentMode(m_entityId, EditorBoxShapeComponentTypeId);
  150. // position the camera so it is looking down at the box
  151. AzFramework::SetCameraTransform(
  152. m_cameraState,
  153. AZ::Transform::CreateFromQuaternionAndTranslation(
  154. AZ::Quaternion::CreateRotationX(-AZ::Constants::HalfPi), AZ::Vector3(5.0f, -10.0f, 15.0f)));
  155. // position in world space which should allow grabbing the box's -y scale manipulator
  156. const AZ::Vector3 worldStart(4.56f, -10.08f, -4.8f);
  157. // position in world space to move to
  158. const AZ::Vector3 worldEnd(3.96f, -10.53f, -4.8f);
  159. DragMouse(m_cameraState, m_actionDispatcher.get(), worldStart, worldEnd);
  160. ExpectBoxDimensions(m_entityId, AZ::Vector3(3.0f, 9.0f, 2.0f));
  161. // the offset should have changed because the editing was asymmetrical
  162. ExpectTranslationOffset(m_entityId, translationOffset - AZ::Vector3::CreateAxisY(1.5f));
  163. }
  164. TEST_F(EditorBoxShapeComponentManipulatorFixture, BoxShapeNonUniformScaleTranslationOffsetManipulatorsScaleCorrectly)
  165. {
  166. const AZ::Quaternion boxRotation(0.7f, 0.1f, -0.7f, 0.1f);
  167. AZ::Transform boxTransform(AZ::Vector3(-3.0f, 5.0f, 2.0f), boxRotation, 2.5f);
  168. const AZ::Vector3 nonUniformScale(0.5f, 2.0f, 3.0f);
  169. const AZ::Vector3 boxDimensions(6.0f, 2.0f, 5.0f);
  170. const AZ::Vector3 translationOffset(4.0f, 5.0f, -3.0f);
  171. SetUpBoxShapeComponent(m_entityId, boxTransform, nonUniformScale, translationOffset, boxDimensions);
  172. EnterComponentMode(m_entityId, EditorBoxShapeComponentTypeId);
  173. SetComponentSubMode(m_entityComponentIdPair, AzToolsFramework::ShapeComponentModeRequests::SubMode::TranslationOffset);
  174. // position the camera so it is looking horizontally at the box
  175. AzFramework::SetCameraTransform(
  176. m_cameraState,
  177. AZ::Transform::CreateTranslation(AZ::Vector3(25.0f, -25.0f, -4.0f)));
  178. // position in world space which should allow grabbing the box's x translation offset manipulator
  179. const AZ::Vector3 worldStart(25.6f, -12.7f, -3.5f);
  180. // position in world space to move to
  181. const AZ::Vector3 worldEnd(25.6f, -12.7f, -4.75f);
  182. DragMouse(m_cameraState, m_actionDispatcher.get(), worldStart, worldEnd);
  183. ExpectTranslationOffset(m_entityId, translationOffset + AZ::Vector3::CreateAxisX());
  184. }
  185. } // namespace LmbrCentral