EditorAxisAlignedBoxShapeComponentTests.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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 "Shape/EditorAxisAlignedBoxShapeComponent.h"
  9. #include "Shape/EditorSphereShapeComponent.h"
  10. #include <AZTestShared/Utils/Utils.h>
  11. #include <AzToolsFramework/Viewport/ViewportSettings.h>
  12. #include <EditorShapeTestUtils.h>
  13. namespace LmbrCentral
  14. {
  15. class EditorAxisAlignedBoxShapeComponentFixture
  16. : public UnitTest::ToolsApplicationFixture<>
  17. {
  18. public:
  19. void SetUpEditorFixtureImpl() override;
  20. void TearDownEditorFixtureImpl() override;
  21. AZStd::unique_ptr<AZ::ComponentDescriptor> m_editorAxisAlignedBoxShapeComponentDescriptor;
  22. AZStd::unique_ptr<AZ::ComponentDescriptor> m_editorSphereShapeComponentDescriptor;
  23. AZ::Entity* m_entity = nullptr;
  24. AZ::EntityId m_entityId;
  25. AZ::EntityComponentIdPair m_entityComponentIdPair;
  26. };
  27. void EditorAxisAlignedBoxShapeComponentFixture::SetUpEditorFixtureImpl()
  28. {
  29. AZ::SerializeContext* serializeContext = nullptr;
  30. AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
  31. // need to reflect EditorSphereShapeComponent in order for EditorBaseShapeComponent to be reflected
  32. m_editorSphereShapeComponentDescriptor = AZStd::unique_ptr<AZ::ComponentDescriptor>(EditorSphereShapeComponent::CreateDescriptor());
  33. m_editorAxisAlignedBoxShapeComponentDescriptor =
  34. AZStd::unique_ptr<AZ::ComponentDescriptor>(EditorAxisAlignedBoxShapeComponent::CreateDescriptor());
  35. ShapeComponentConfig::Reflect(serializeContext);
  36. AxisAlignedBoxShape::Reflect(serializeContext);
  37. m_editorSphereShapeComponentDescriptor->Reflect(serializeContext);
  38. m_editorAxisAlignedBoxShapeComponentDescriptor->Reflect(serializeContext);
  39. UnitTest::CreateDefaultEditorEntity("AxisAlignedBoxShapeComponentEntity", &m_entity);
  40. m_entityId = m_entity->GetId();
  41. m_entity->Deactivate();
  42. m_entityComponentIdPair =
  43. AZ::EntityComponentIdPair(m_entityId, m_entity->CreateComponent(EditorAxisAlignedBoxShapeComponentTypeId)->GetId());
  44. m_entity->Activate();
  45. }
  46. void EditorAxisAlignedBoxShapeComponentFixture::TearDownEditorFixtureImpl()
  47. {
  48. AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
  49. &AzToolsFramework::EditorEntityContextRequestBus::Events::DestroyEditorEntity, m_entityId);
  50. m_entity = nullptr;
  51. m_entityId.SetInvalid();
  52. m_editorAxisAlignedBoxShapeComponentDescriptor.reset();
  53. m_editorSphereShapeComponentDescriptor.reset();
  54. }
  55. using EditorAxisAlignedBoxShapeComponentManipulatorFixture =
  56. UnitTest::IndirectCallManipulatorViewportInteractionFixtureMixin<EditorAxisAlignedBoxShapeComponentFixture>;
  57. void SetUpAxisAlignedBoxShapeComponent(
  58. AZ::EntityId entityId, const AZ::Transform& transform, const AZ::Vector3& translationOffset, const AZ::Vector3& boxDimensions)
  59. {
  60. AZ::TransformBus::Event(entityId, &AZ::TransformBus::Events::SetWorldTM, transform);
  61. ShapeComponentRequestsBus::Event(entityId, &ShapeComponentRequests::SetTranslationOffset, translationOffset);
  62. BoxShapeComponentRequestsBus::Event(entityId, &BoxShapeComponentRequests::SetBoxDimensions, boxDimensions);
  63. }
  64. TEST_F(EditorAxisAlignedBoxShapeComponentManipulatorFixture, AxisAlignedBoxShapeSymmetricalDimensionManipulatorsScaleCorrectly)
  65. {
  66. const AZ::Transform transform(AZ::Vector3(7.0f, 5.0f, -2.0f), AZ::Quaternion::CreateIdentity(), 0.5f);
  67. const AZ::Vector3 translationOffset(-4.0f, -4.0f, 3.0f);
  68. const AZ::Vector3 boxDimensions(4.0f, 2.0f, 3.0f);
  69. SetUpAxisAlignedBoxShapeComponent(m_entityId, transform, translationOffset, boxDimensions);
  70. EnterComponentMode(m_entityId, EditorAxisAlignedBoxShapeComponentTypeId);
  71. // position the camera so it is looking down at the box
  72. AzFramework::SetCameraTransform(
  73. m_cameraState,
  74. AZ::Transform::CreateFromQuaternionAndTranslation(
  75. AZ::Quaternion::CreateRotationX(-AZ::Constants::HalfPi), AZ::Vector3(5.0f, 4.0f, 10.0f)));
  76. // position in world space which should allow grabbing the box's y scale manipulator
  77. const AZ::Vector3 worldStart(5.0f, 3.5f, -0.5f);
  78. const AZ::Vector3 worldEnd(5.0f, 4.0f, -0.5f);
  79. DragMouse(m_cameraState, m_actionDispatcher.get(), worldStart, worldEnd, AzToolsFramework::DefaultSymmetricalEditingModifier);
  80. ExpectBoxDimensions(m_entityId, AZ::Vector3(4.0f, 4.0f, 3.0f));
  81. }
  82. TEST_F(EditorAxisAlignedBoxShapeComponentManipulatorFixture, AxisAlignedBoxShapeAsymmetricalDimensionManipulatorsScaleCorrectly)
  83. {
  84. const AZ::Transform transform(AZ::Vector3(2.0f, 4.0f, -7.0f), AZ::Quaternion::CreateIdentity(), 1.5f);
  85. const AZ::Vector3 translationOffset(-5.0f, 3.0f, 1.0f);
  86. const AZ::Vector3 boxDimensions(2.0f, 6.0f, 4.0f);
  87. SetUpAxisAlignedBoxShapeComponent(m_entityId, transform, translationOffset, boxDimensions);
  88. EnterComponentMode(m_entityId, EditorAxisAlignedBoxShapeComponentTypeId);
  89. // position the camera so it is looking down at the box
  90. AzFramework::SetCameraTransform(
  91. m_cameraState,
  92. AZ::Transform::CreateFromQuaternionAndTranslation(
  93. AZ::Quaternion::CreateRotationX(-AZ::Constants::HalfPi), AZ::Vector3(-5.5f, 8.5f, 5.0f)));
  94. // position in world space which should allow grabbing the box's -x scale manipulator
  95. const AZ::Vector3 worldStart(-7.0f, 8.5f, -5.5f);
  96. const AZ::Vector3 worldEnd(-8.5f, 8.5f, -5.5f);
  97. DragMouse(m_cameraState, m_actionDispatcher.get(), worldStart, worldEnd);
  98. ExpectBoxDimensions(m_entityId, AZ::Vector3(3.0f, 6.0f, 4.0f));
  99. // the offset should have changed because the editing was asymmetrical
  100. ExpectTranslationOffset(m_entityId, translationOffset - AZ::Vector3::CreateAxisX(0.5f));
  101. }
  102. TEST_F(EditorAxisAlignedBoxShapeComponentManipulatorFixture, AxisAlignedBoxShapeRotatedEntityManipulatorSpaceCorrect)
  103. {
  104. const AZ::Transform transform(AZ::Vector3(7.0f, -6.0f, -2.0f), AZ::Quaternion(0.7f, 0.1f, -0.1f, 0.7f), 2.0f);
  105. const AZ::Vector3 translationOffset(-4.0f, 4.0f, 2.0f);
  106. const AZ::Vector3 boxDimensions(2.0f, 3.0f, 4.0f);
  107. SetUpAxisAlignedBoxShapeComponent(m_entityId, transform, translationOffset, boxDimensions);
  108. EnterComponentMode(m_entityId, EditorAxisAlignedBoxShapeComponentTypeId);
  109. // position the camera so it is looking down at the box
  110. AzFramework::SetCameraTransform(
  111. m_cameraState,
  112. AZ::Transform::CreateFromQuaternionAndTranslation(
  113. AZ::Quaternion::CreateRotationX(-AZ::Constants::HalfPi), AZ::Vector3(-1.0f, 2.0f, 15.0f)));
  114. // position in world space which should allow grabbing the box's x scale manipulator
  115. // the entity is rotated, but the box (and the manipulator space) should act as if it is not rotated
  116. const AZ::Vector3 worldStart(1.0f, 2.0f, 2.0f);
  117. const AZ::Vector3 worldEnd(3.0f, 2.0f, 2.0f);
  118. DragMouse(m_cameraState, m_actionDispatcher.get(), worldStart, worldEnd);
  119. ExpectBoxDimensions(m_entityId, AZ::Vector3(3.0f, 3.0f, 4.0f));
  120. // the offset should have changed because the editing was asymmetrical
  121. ExpectTranslationOffset(m_entityId, translationOffset + AZ::Vector3::CreateAxisX(0.5f));
  122. }
  123. TEST_F(EditorAxisAlignedBoxShapeComponentManipulatorFixture, AxisAlignedBoxShapeTranslationOffsetManipulatorsScaleCorrectly)
  124. {
  125. const AZ::Transform boxTransform(AZ::Vector3(-5.0f, 2.0f, 2.0f), AZ::Quaternion(0.3f, 0.3f, 0.1f, 0.9f), 1.5f);
  126. const AZ::Vector3 translationOffset(3.0f, 1.0f, -4.0f);
  127. const AZ::Vector3 boxDimensions(1.0f, 4.0f, 2.0f);
  128. SetUpAxisAlignedBoxShapeComponent(m_entityId, boxTransform, translationOffset, boxDimensions);
  129. EnterComponentMode(m_entityId, EditorAxisAlignedBoxShapeComponentTypeId);
  130. SetComponentSubMode(m_entityComponentIdPair, AzToolsFramework::ShapeComponentModeRequests::SubMode::TranslationOffset);
  131. // position the camera so it is looking horizontally at the box
  132. AzFramework::SetCameraTransform(
  133. m_cameraState,
  134. AZ::Transform::CreateTranslation(AZ::Vector3(0.0f, -10.0f, -3.0f)));
  135. // position in world space which should allow grabbing the box's z translation offset manipulator
  136. const AZ::Vector3 worldStart(-0.5f, 3.5f, -3.0f);
  137. // position in world space to move to
  138. const AZ::Vector3 worldEnd(-0.5f, 3.5f, -1.5f);
  139. DragMouse(m_cameraState, m_actionDispatcher.get(), worldStart, worldEnd);
  140. ExpectTranslationOffset(m_entityId, translationOffset + AZ::Vector3::CreateAxisZ());
  141. }
  142. TEST_F(EditorAxisAlignedBoxShapeComponentManipulatorFixture, PressingKey1ShouldSetDimensionMode)
  143. {
  144. EnterComponentMode(m_entityId, EditorAxisAlignedBoxShapeComponentTypeId);
  145. SetComponentSubMode(m_entityComponentIdPair, AzToolsFramework::ShapeComponentModeRequests::SubMode::TranslationOffset);
  146. ExpectSubMode(m_entityComponentIdPair, AzToolsFramework::ShapeComponentModeRequests::SubMode::TranslationOffset);
  147. QTest::keyPress(&m_editorActions.m_componentModeWidget, Qt::Key_1);
  148. ExpectSubMode(m_entityComponentIdPair, AzToolsFramework::ShapeComponentModeRequests::SubMode::Dimensions);
  149. }
  150. TEST_F(EditorAxisAlignedBoxShapeComponentManipulatorFixture, PressingKey2ShouldSetTranslationOffsetMode)
  151. {
  152. EnterComponentMode(m_entityId, EditorAxisAlignedBoxShapeComponentTypeId);
  153. ExpectSubMode(m_entityComponentIdPair, AzToolsFramework::ShapeComponentModeRequests::SubMode::Dimensions);
  154. QTest::keyPress(&m_editorActions.m_componentModeWidget, Qt::Key_2);
  155. ExpectSubMode(m_entityComponentIdPair, AzToolsFramework::ShapeComponentModeRequests::SubMode::TranslationOffset);
  156. }
  157. TEST_F(EditorAxisAlignedBoxShapeComponentManipulatorFixture, PressingKeyRInDimensionModeShouldResetBoxDimensions)
  158. {
  159. const AZ::Vector3 boxDimensions(2.0f, 2.0f, 2.0f);
  160. BoxShapeComponentRequestsBus::Event(m_entityId, &BoxShapeComponentRequests::SetBoxDimensions, boxDimensions);
  161. EnterComponentMode(m_entityId, EditorAxisAlignedBoxShapeComponentTypeId);
  162. ExpectBoxDimensions(m_entityId, boxDimensions);
  163. QTest::keyPress(&m_editorActions.m_componentModeWidget, Qt::Key_R);
  164. ExpectBoxDimensions(m_entityId, AZ::Vector3::CreateOne());
  165. }
  166. TEST_F(EditorAxisAlignedBoxShapeComponentManipulatorFixture, PressingKeyRInTranslationOffsetModeShouldResetTranslationOffset)
  167. {
  168. const AZ::Vector3 translationOffset(3.0f, 4.0f, 5.0f);
  169. ShapeComponentRequestsBus::Event(m_entityId, &ShapeComponentRequests::SetTranslationOffset, translationOffset);
  170. EnterComponentMode(m_entityId, EditorAxisAlignedBoxShapeComponentTypeId);
  171. SetComponentSubMode(m_entityComponentIdPair, AzToolsFramework::ShapeComponentModeRequests::SubMode::TranslationOffset);
  172. ExpectTranslationOffset(m_entityId, translationOffset);
  173. QTest::keyPress(&m_editorActions.m_componentModeWidget, Qt::Key_R);
  174. ExpectTranslationOffset(m_entityId, AZ::Vector3::CreateZero());
  175. }
  176. TEST_F(EditorAxisAlignedBoxShapeComponentManipulatorFixture, CtrlMouseWheelUpShouldSetNextMode)
  177. {
  178. EnterComponentMode(m_entityId, EditorAxisAlignedBoxShapeComponentTypeId);
  179. ExpectSubMode(m_entityComponentIdPair, AzToolsFramework::ShapeComponentModeRequests::SubMode::Dimensions);
  180. const auto handled = CtrlScroll(1.0f);
  181. EXPECT_EQ(handled, AzToolsFramework::ViewportInteraction::MouseInteractionResult::Viewport);
  182. ExpectSubMode(m_entityComponentIdPair, AzToolsFramework::ShapeComponentModeRequests::SubMode::TranslationOffset);
  183. }
  184. TEST_F(EditorAxisAlignedBoxShapeComponentManipulatorFixture, CtrlMouseWheelDownShouldSetNextMode)
  185. {
  186. EnterComponentMode(m_entityId, EditorAxisAlignedBoxShapeComponentTypeId);
  187. SetComponentSubMode(m_entityComponentIdPair, AzToolsFramework::ShapeComponentModeRequests::SubMode::TranslationOffset);
  188. ExpectSubMode(m_entityComponentIdPair, AzToolsFramework::ShapeComponentModeRequests::SubMode::TranslationOffset);
  189. const auto handled = CtrlScroll(-1.0f);
  190. EXPECT_EQ(handled, AzToolsFramework::ViewportInteraction::MouseInteractionResult::Viewport);
  191. ExpectSubMode(m_entityComponentIdPair, AzToolsFramework::ShapeComponentModeRequests::SubMode::Dimensions);
  192. }
  193. }