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.
215 lines
10 KiB
C++
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
|