You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/Framework/AzManipulatorTestFramework/Tests/WorldSpaceBuilderTest.cpp

215 lines
10 KiB
C++

/*
* 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 <AzFramework/Viewport/ViewportScreen.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h>
#include <AzManipulatorTestFramework/DirectManipulatorViewportInteraction.h>
#include <AzManipulatorTestFramework/ImmediateModeActionDispatcher.h>
#include <AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h>
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
namespace UnitTest
{
class AzManipulatorTestFrameworkWorldSpaceBuilderTestFixture : public ToolsApplicationFixture
{
protected:
struct State
{
State(AZStd::unique_ptr<AzManipulatorTestFramework::ManipulatorViewportInteraction> viewportManipulatorInteraction)
: m_viewportManipulatorInteraction(viewportManipulatorInteraction.release())
, m_actionDispatcher(
AZStd::make_unique<AzManipulatorTestFramework::ImmediateModeActionDispatcher>(*m_viewportManipulatorInteraction))
, m_linearManipulator(AzManipulatorTestFramework::CreateLinearManipulator(
m_viewportManipulatorInteraction->GetManipulatorManager().GetId(),
/*position=*/AZ::Vector3(0.0f, 50.0f, 0.0f),
/*radius=*/m_boundsRadius))
{
// default sanity check call backs
m_linearManipulator->InstallLeftMouseDownCallback(
[this]([[maybe_unused]] const AzToolsFramework::LinearManipulator::Action& action)
{
m_receivedLeftMouseDown = true;
});
m_linearManipulator->InstallMouseMoveCallback(
[this]([[maybe_unused]] const AzToolsFramework::LinearManipulator::Action& action)
{
m_receivedMouseMove = true;
});
m_linearManipulator->InstallLeftMouseUpCallback(
[this]([[maybe_unused]] const AzToolsFramework::LinearManipulator::Action& action)
{
m_receivedLeftMouseUp = true;
});
}
~State() = default;
// sanity flags for manipulator mouse callbacks
bool m_receivedLeftMouseDown = false;
bool m_receivedMouseMove = false;
bool m_receivedLeftMouseUp = false;
private:
AZStd::unique_ptr<AzManipulatorTestFramework::ManipulatorViewportInteraction> m_viewportManipulatorInteraction;
public:
AZStd::unique_ptr<AzManipulatorTestFramework::ImmediateModeActionDispatcher> m_actionDispatcher;
AZStd::shared_ptr<AzToolsFramework::LinearManipulator> m_linearManipulator;
};
void ConsumeViewportLeftMouseClick(State& state);
void ConsumeViewportMouseMoveHover(State& state);
void ConsumeViewportMouseMoveActive(State& state);
void MoveManipulatorAlongAxis(State& state);
protected:
void SetUpEditorFixtureImpl() override
{
m_directState =
AZStd::make_unique<State>(AZStd::make_unique<AzManipulatorTestFramework::DirectCallManipulatorViewportInteraction>());
m_busState =
AZStd::make_unique<State>(AZStd::make_unique<AzManipulatorTestFramework::IndirectCallManipulatorViewportInteraction>());
m_cameraState =
AzFramework::CreateIdentityDefaultCamera(AZ::Vector3::CreateZero(), AzManipulatorTestFramework::DefaultViewportSize);
}
void TearDownEditorFixtureImpl() override
{
m_directState.reset();
m_busState.reset();
}
public:
AZStd::unique_ptr<State> m_directState;
AZStd::unique_ptr<State> m_busState;
AzFramework::CameraState m_cameraState;
static constexpr float m_boundsRadius = 2.0f;
};
void AzManipulatorTestFrameworkWorldSpaceBuilderTestFixture::ConsumeViewportLeftMouseClick(State& state)
{
// given a left mouse down ray in world space
// consume the mouse down and up events
state.m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(AzManipulatorTestFramework::GetCameraStateViewportCenter(m_cameraState))
->MouseLButtonDown()
->Trace("Expecting left mouse button down")
->ExpectTrue(state.m_receivedLeftMouseDown)
->Trace("Not expecting left mouse button up")
->ExpectFalse(state.m_receivedLeftMouseUp)
->Trace("Expecting mouse move")
// note: a zero delta mouse move is generated after every mouse up event in the
// editor application - the manipulator test framework simulates this event to
// ensure the tests are representative of what actually happens in the editor
// therefore we do expect m_receivedMouseMove to be true after MouseLButtonDown
->ExpectTrue(state.m_receivedMouseMove)
->ExpectManipulatorBeingInteracted()
->MouseLButtonUp()
->Trace("Expecting left mouse button up")
->ExpectTrue(state.m_receivedLeftMouseDown)
->ExpectTrue(state.m_receivedLeftMouseUp)
->ExpectTrue(state.m_receivedMouseMove)
->ExpectFalse(state.m_linearManipulator->PerformingAction())
->ExpectManipulatorNotBeingInteracted();
}
void AzManipulatorTestFrameworkWorldSpaceBuilderTestFixture::ConsumeViewportMouseMoveHover(State& state)
{
// given a left mouse down ray in world space
// consume the mouse move event
state.m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(AzManipulatorTestFramework::GetCameraStateViewportCenter(m_cameraState))
->ExpectFalse(state.m_linearManipulator->PerformingAction())
->ExpectManipulatorNotBeingInteracted()
->ExpectFalse(state.m_receivedLeftMouseDown)
->ExpectFalse(state.m_receivedMouseMove)
->ExpectFalse(state.m_receivedLeftMouseUp);
}
void AzManipulatorTestFrameworkWorldSpaceBuilderTestFixture::ConsumeViewportMouseMoveActive(State& state)
{
// given a left mouse down ray in world space
// consume the mouse move event
state.m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(AzManipulatorTestFramework::GetCameraStateViewportCenter(m_cameraState))
->MouseLButtonDown()
->ExpectTrue(state.m_linearManipulator->PerformingAction())
->ExpectManipulatorBeingInteracted()
->MouseLButtonUp()
->ExpectTrue(state.m_receivedLeftMouseDown)
->ExpectTrue(state.m_receivedMouseMove)
->ExpectTrue(state.m_receivedLeftMouseUp);
}
void AzManipulatorTestFrameworkWorldSpaceBuilderTestFixture::MoveManipulatorAlongAxis(State& state)
{
// the initial starting position of the manipulator (in front of the camera)
const auto initialPositionWorld = state.m_linearManipulator->GetLocalPosition();
// where the manipulator should end up (in front and to the left of the camera)
const auto finalPositionWorld = AZ::Vector3(-10.0f, 50.0f, 0.0f);
// perspective scale factor for manipulator distance to camera
const auto scaledRadiusBound =
AzToolsFramework::CalculateScreenToWorldMultiplier(initialPositionWorld, m_cameraState) * m_boundsRadius;
// vector from camera to manipulator
const auto vectorToInitialPositionWorld = (initialPositionWorld - m_cameraState.m_position).GetNormalized();
// adjusted final world position taking into account the manipulator position relative to the camera
const auto finalPositionWorldAdjusted = finalPositionWorld - (vectorToInitialPositionWorld * scaledRadiusBound);
// calculate the position in screen space of the initial position of the manipulator
const auto initialPositionScreen = AzFramework::WorldToScreen(initialPositionWorld, m_cameraState);
// calculate the position in screen space of the final position of the manipulator
const auto finalPositionScreen = AzFramework::WorldToScreen(finalPositionWorldAdjusted, m_cameraState);
AZ::Vector3 movementAlongAxis = AZ::Vector3::CreateZero();
state.m_linearManipulator->InstallMouseMoveCallback(
[&movementAlongAxis](const AzToolsFramework::LinearManipulator::Action& action)
{
movementAlongAxis = action.LocalPosition();
});
state.m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(initialPositionScreen)
->MouseLButtonDown()
->ExpectTrue(state.m_linearManipulator->PerformingAction())
->ExpectManipulatorBeingInteracted()
->MousePosition(finalPositionScreen)
->MouseLButtonUp()
->ExpectTrue(state.m_receivedLeftMouseDown)
->ExpectTrue(state.m_receivedLeftMouseUp)
->ExpectTrue(movementAlongAxis.IsClose(finalPositionWorld, 0.01f));
}
TEST_F(AzManipulatorTestFrameworkWorldSpaceBuilderTestFixture, ConsumeViewportLeftMouseClick)
{
ConsumeViewportLeftMouseClick(*m_directState);
ConsumeViewportLeftMouseClick(*m_busState);
}
TEST_F(AzManipulatorTestFrameworkWorldSpaceBuilderTestFixture, ConsumeViewportMouseMoveHover)
{
ConsumeViewportMouseMoveHover(*m_directState);
ConsumeViewportMouseMoveHover(*m_busState);
}
TEST_F(AzManipulatorTestFrameworkWorldSpaceBuilderTestFixture, ConsumeViewportMouseMoveActive)
{
ConsumeViewportMouseMoveActive(*m_directState);
ConsumeViewportMouseMoveActive(*m_busState);
}
TEST_F(AzManipulatorTestFrameworkWorldSpaceBuilderTestFixture, MoveManipulatorAlongAxis)
{
MoveManipulatorAlongAxis(*m_directState);
MoveManipulatorAlongAxis(*m_busState);
}
} // namespace UnitTest