diff --git a/Gems/LmbrCentral/Code/CMakeLists.txt b/Gems/LmbrCentral/Code/CMakeLists.txt index eb1d56bf27..38e80fb03b 100644 --- a/Gems/LmbrCentral/Code/CMakeLists.txt +++ b/Gems/LmbrCentral/Code/CMakeLists.txt @@ -161,6 +161,7 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED) AZ::AzToolsFramework AZ::AzToolsFrameworkTestCommon AZ::AssetBuilderSDK + AZ::AzManipulatorTestFramework.Static Gem::LmbrCentral.Static Gem::LmbrCentral.Editor.Static ) diff --git a/Gems/LmbrCentral/Code/Tests/EditorPolygonPrismShapeComponentTests.cpp b/Gems/LmbrCentral/Code/Tests/EditorPolygonPrismShapeComponentTests.cpp index 1206c81450..e1bd240e13 100644 --- a/Gems/LmbrCentral/Code/Tests/EditorPolygonPrismShapeComponentTests.cpp +++ b/Gems/LmbrCentral/Code/Tests/EditorPolygonPrismShapeComponentTests.cpp @@ -1,12 +1,26 @@ /* * Copyright (c) Contributors to the Open 3D Engine Project - * + * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #include "LmbrCentral_precompiled.h" #include "LmbrCentralReflectionTest.h" #include "Shape/EditorPolygonPrismShapeComponent.h" +#include "Shape/EditorSphereShapeComponent.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace LmbrCentral { @@ -37,11 +51,13 @@ namespace LmbrCentral )DELIMITER"; - class LoadEditorPolygonPrismShapeComponentFromVersion1 - : public LoadEditorComponentTest + class LoadEditorPolygonPrismShapeComponentFromVersion1 : public LoadEditorComponentTest { protected: - const char* GetSourceDataBuffer() const override { return kEditorPolygonPrismComponentVersion1; } + const char* GetSourceDataBuffer() const override + { + return kEditorPolygonPrismComponentVersion1; + } }; TEST_F(LoadEditorPolygonPrismShapeComponentFromVersion1, Application_IsRunning) @@ -63,7 +79,8 @@ namespace LmbrCentral TEST_F(LoadEditorPolygonPrismShapeComponentFromVersion1, Height_MatchesSourceData) { AZ::ConstPolygonPrismPtr polygonPrism; - PolygonPrismShapeComponentRequestBus::EventResult(polygonPrism, m_entity->GetId(), &PolygonPrismShapeComponentRequestBus::Events::GetPolygonPrism); + PolygonPrismShapeComponentRequestBus::EventResult( + polygonPrism, m_entity->GetId(), &PolygonPrismShapeComponentRequestBus::Events::GetPolygonPrism); EXPECT_FLOAT_EQ(polygonPrism->GetHeight(), 1.57f); } @@ -71,16 +88,133 @@ namespace LmbrCentral TEST_F(LoadEditorPolygonPrismShapeComponentFromVersion1, Vertices_MatchesSourceData) { AZ::ConstPolygonPrismPtr polygonPrism; - PolygonPrismShapeComponentRequestBus::EventResult(polygonPrism, m_entity->GetId(), &PolygonPrismShapeComponentRequestBus::Events::GetPolygonPrism); + PolygonPrismShapeComponentRequestBus::EventResult( + polygonPrism, m_entity->GetId(), &PolygonPrismShapeComponentRequestBus::Events::GetPolygonPrism); - AZStd::vector sourceVertices = - { - AZ::Vector2(-0.57f, -0.57f), - AZ::Vector2(0.57f, -0.57f), - AZ::Vector2(0.57f, 0.57f), - AZ::Vector2(-0.57f, 0.57f) - }; + AZStd::vector sourceVertices = { AZ::Vector2(-0.57f, -0.57f), AZ::Vector2(0.57f, -0.57f), AZ::Vector2(0.57f, 0.57f), + AZ::Vector2(-0.57f, 0.57f) }; EXPECT_EQ(polygonPrism->m_vertexContainer.GetVertices(), sourceVertices); } -} + using EditorPolygonPrismShapeComponentManipulatorTestFixture = UnitTest::IndirectCallManipulatorViewportInteractionFixture; + + class EditorPolygonPrismShapeComponentFixture : public UnitTest::ToolsApplicationFixture + { + public: + void SetUpEditorFixtureImpl() override; + void TearDownEditorFixtureImpl() override; + + AZStd::unique_ptr m_editorPolygonPrismShapeComponentDescriptor; + AZStd::unique_ptr m_editorSphereShapeComponentDescriptor; + + AZ::Entity* m_entity = nullptr; + }; + + void EditorPolygonPrismShapeComponentFixture::SetUpEditorFixtureImpl() + { + AZ::SerializeContext* serializeContext = nullptr; + AZ::ComponentApplicationBus::BroadcastResult( + serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext); + + // need to reflect EditorSphereShapeComponent in order for EditorBaseShapeComponent to be reflected + m_editorSphereShapeComponentDescriptor = + AZStd::unique_ptr(EditorSphereShapeComponent::CreateDescriptor()); + + m_editorPolygonPrismShapeComponentDescriptor = + AZStd::unique_ptr(EditorPolygonPrismShapeComponent::CreateDescriptor()); + + ShapeComponentConfig::Reflect(serializeContext); + PolygonPrismShape::Reflect(serializeContext); + m_editorSphereShapeComponentDescriptor->Reflect(serializeContext); + m_editorPolygonPrismShapeComponentDescriptor->Reflect(serializeContext); + + UnitTest::CreateDefaultEditorEntity("PolygonPrismShapeComponentEntity", &m_entity); + m_entity->Deactivate(); + m_entity->CreateComponent(AzToolsFramework::Components::EditorNonUniformScaleComponent::RTTI_Type()); + m_entity->CreateComponent(EditorPolygonPrismShapeComponentTypeId); + m_entity->Activate(); + } + + void EditorPolygonPrismShapeComponentFixture::TearDownEditorFixtureImpl() + { + AzToolsFramework::EditorEntityContextRequestBus::Broadcast( + &AzToolsFramework::EditorEntityContextRequestBus::Events::DestroyEditorEntity, m_entity->GetId()); + m_entity = nullptr; + + m_editorPolygonPrismShapeComponentDescriptor.reset(); + m_editorSphereShapeComponentDescriptor.reset(); + } + + using EditorPolygonPrismShapeComponentManipulatorFixture = + UnitTest::IndirectCallManipulatorViewportInteractionFixtureMixin; + + TEST_F(EditorPolygonPrismShapeComponentManipulatorFixture, PolygonPrismNonUniformScale_ManipulatorsScaleCorrectly) + { + // set the non-uniform scale and enter the polygon prism shape component's component mode + const AZ::Vector3 nonUniformScale(2.0f, 3.0f, 4.0f); + AZ::NonUniformScaleRequestBus::Event(m_entity->GetId(), &AZ::NonUniformScaleRequests::SetScale, nonUniformScale); + + AzToolsFramework::SelectEntity(m_entity->GetId()); + + AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast( + &AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Events::AddSelectedComponentModesOfType, + EditorPolygonPrismShapeComponentTypeId); + + // position the camera so it is looking down at the polygon prism + AzFramework::SetCameraTransform( + m_cameraState, + AZ::Transform::CreateFromQuaternionAndTranslation( + AZ::Quaternion::CreateRotationX(-AZ::Constants::HalfPi), AZ::Vector3(0.0f, 0.0f, 20.0f))); + + // the first vertex of the polygon prism should be at (-2, -2, 0) in its local space + // because of the non-uniform scale, that should be (-4, -6, 0) in world space + const AZ::Vector3 worldStart(-4.0f, -6.0f, 0.0f); + + // position in world space to drag the vertex to + const AZ::Vector3 worldEnd(-8.0f, -9.0f, 0.0f); + + const auto screenStart = AzFramework::WorldToScreen(worldStart, m_cameraState); + const auto screenEnd = AzFramework::WorldToScreen(worldEnd, m_cameraState); + + // small diagonal offset to ensure we interact with the planar manipulator and not one of the linear manipulators + const AzFramework::ScreenVector offset(5, -5); + + m_actionDispatcher + ->CameraState(m_cameraState) + // move the mouse to the first vertex of the polygon prism + ->MousePosition(screenStart) + // click to activate the manipulator + ->MouseLButtonDown() + ->MouseLButtonUp() + // offset the mouse position slightly to ensure we get the planar manipulator and not one of the linear manipulators + ->MousePosition(screenStart + offset) + // drag to move the manipulator + ->MouseLButtonDown() + ->MousePosition(screenEnd + offset) + ->MouseLButtonUp(); + + AZ::PolygonPrismPtr polygonPrism = nullptr; + PolygonPrismShapeComponentRequestBus::EventResult( + polygonPrism, m_entity->GetId(), &PolygonPrismShapeComponentRequests::GetPolygonPrism); + + AZ::Vector2 vertex; + polygonPrism->m_vertexContainer.GetVertex(0, vertex); + + // dragging the vertex to (-8, -9, 0) in world space should move its local translation to (-4, -3, 0) + AZ::Vector2 expectedVertex(-4.0f, -3.0f); + EXPECT_THAT(vertex, UnitTest::IsCloseTolerance(expectedVertex, 1e-2f)); + + // now check the manipulator is still in the correct position relative to the vertex + // by starting a drag from the new vertex world position + m_actionDispatcher + ->CameraState(m_cameraState) + ->MousePosition(screenEnd + offset) + ->MouseLButtonDown() + ->MousePosition(screenStart + offset) + ->MouseLButtonUp(); + + polygonPrism->m_vertexContainer.GetVertex(0, vertex); + expectedVertex = AZ::Vector2(-2.0f, -2.0f); + EXPECT_THAT(vertex, UnitTest::IsCloseTolerance(expectedVertex, 1e-2f)); + } +} // namespace LmbrCentral diff --git a/Gems/LmbrCentral/Code/Tests/LmbrCentralEditorTest.cpp b/Gems/LmbrCentral/Code/Tests/LmbrCentralEditorTest.cpp new file mode 100644 index 0000000000..33527b39b1 --- /dev/null +++ b/Gems/LmbrCentral/Code/Tests/LmbrCentralEditorTest.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) Contributors to the Open 3D Engine Project + * + * SPDX-License-Identifier: Apache-2.0 OR MIT + * + */ + +#include +#include +#include + +// Required to support running integration tests with Qt +AZTEST_EXPORT int AZ_UNIT_TEST_HOOK_NAME(int argc, char** argv) +{ + ::testing::InitGoogleMock(&argc, argv); + AzQtComponents::PrepareQtPaths(); + QApplication app(argc, argv); + AZ::Test::printUnusedParametersWarning(argc, argv); + AZ::Test::addTestEnvironments({ DEFAULT_UNIT_TEST_ENV }); + int result = RUN_ALL_TESTS(); + return result; +} + +IMPLEMENT_TEST_EXECUTABLE_MAIN(); diff --git a/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake b/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake index 20cf106a26..f8b6429938 100644 --- a/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake +++ b/Gems/LmbrCentral/Code/lmbrcentral_editor_tests_files.cmake @@ -6,7 +6,7 @@ # set(FILES - Tests/LmbrCentralTest.cpp + Tests/LmbrCentralEditorTest.cpp Tests/LmbrCentralReflectionTest.h Tests/LmbrCentralReflectionTest.cpp Tests/EditorBoxShapeComponentTests.cpp