Additional test support for Manipulator Ditto commands (#4191)

* additional test support for manipulator ditto

Signed-off-by: hultonha <hultonha@amazon.co.uk>

* tidy-up to changes

Signed-off-by: hultonha <hultonha@amazon.co.uk>

* fix for non-unity build compile error

Signed-off-by: hultonha <hultonha@amazon.co.uk>
This commit is contained in:
hultonha
2021-09-20 09:49:01 +01:00
committed by GitHub
parent 22e43c9122
commit de9a27597b
11 changed files with 220 additions and 27 deletions
@@ -282,6 +282,24 @@ namespace AzToolsFramework
return keyboardModifiers;
}
//! An interface to deal with time requests relating to viewports.
//! @note The bus is global and not per viewport.
class EditorViewportInputTimeNowRequests : public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
//! Returns the current time in seconds.
//! This interface can be overridden for the purposes of testing to simplify viewport input requests.
virtual AZStd::chrono::milliseconds EditorViewportInputTimeNow() = 0;
protected:
~EditorViewportInputTimeNowRequests() = default;
};
using EditorViewportInputTimeNowRequestBus = AZ::EBus<EditorViewportInputTimeNowRequests>;
//! Viewport requests for managing the viewport cursor state.
class ViewportMouseCursorRequests
{
@@ -253,10 +253,10 @@ namespace AzToolsFramework
mouseInteraction.m_mouseInteraction.m_keyboardModifiers.Ctrl());
}
static bool ManipulatorDitto(const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
static bool ManipulatorDitto(
const AzFramework::ClickDetector::ClickOutcome clickOutcome, const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
{
return mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down &&
mouseInteraction.m_mouseInteraction.m_mouseButtons.Left() &&
return clickOutcome == AzFramework::ClickDetector::ClickOutcome::Click &&
mouseInteraction.m_mouseInteraction.m_keyboardModifiers.Ctrl() &&
mouseInteraction.m_mouseInteraction.m_keyboardModifiers.Alt();
}
@@ -1054,6 +1054,17 @@ namespace AzToolsFramework
RegisterActions();
SetupBoxSelect();
RefreshSelectedEntityIdsAndRegenerateManipulators();
// ensure the click detector uses the EditorViewportInputTimeNowRequests interface to retrieve elapsed time
// note: this is to facilitate overriding this functionality for purposes such as testing
m_clickDetector.OverrideTimeNowFn(
[]
{
AZStd::chrono::milliseconds timeNow;
AzToolsFramework::ViewportInteraction::EditorViewportInputTimeNowRequestBus::BroadcastResult(
timeNow, &AzToolsFramework::ViewportInteraction::EditorViewportInputTimeNowRequestBus::Events::EditorViewportInputTimeNow);
return timeNow;
});
}
EditorTransformComponentSelection::~EditorTransformComponentSelection()
@@ -1883,7 +1894,7 @@ namespace AzToolsFramework
}
// set manipulator pivot override translation or orientation (update manipulators)
if (Input::ManipulatorDitto(mouseInteraction))
if (Input::ManipulatorDitto(clickOutcome, mouseInteraction))
{
PerformManipulatorDitto(entityIdUnderCursor);
return false;
@@ -783,7 +783,8 @@ namespace UnitTest
const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState);
// click the entity in the viewport
m_actionDispatcher->SetStickySelect(true)->CameraState(m_cameraState)
m_actionDispatcher->SetStickySelect(true)
->CameraState(m_cameraState)
->MousePosition(entity2ScreenPosition)
->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control)
->MouseLButtonDown()
@@ -1018,6 +1019,105 @@ namespace UnitTest
EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1));
}
class EditorTransformComponentSelectionViewportPickingManipulatorTestFixtureParam
: public EditorTransformComponentSelectionViewportPickingManipulatorTestFixture
, public ::testing::WithParamInterface<bool>
{
};
TEST_P(
EditorTransformComponentSelectionViewportPickingManipulatorTestFixtureParam,
StickyAndUnstickyDittoManipulatorToOtherEntityChangesManipulatorAndDoesNotChangeSelection)
{
PositionEntities();
PositionCamera(m_cameraState);
AzToolsFramework::SelectEntity(m_entityId1);
// calculate the position in screen space of the second entity
const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState);
// single click select entity2
m_actionDispatcher->SetStickySelect(GetParam())
->CameraState(m_cameraState)
->MousePosition(entity2ScreenPosition)
->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control)
->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Alt)
->MouseLButtonDown()
->MouseLButtonUp();
// entity1 is still selected
using ::testing::UnorderedElementsAre;
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1));
AZStd::optional<AZ::Transform> manipulatorTransform;
AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
manipulatorTransform, AzToolsFramework::GetEntityContextId(),
&AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
EXPECT_THAT(manipulatorTransform->GetTranslation(), IsClose(m_entity2WorldTranslation));
}
TEST_P(
EditorTransformComponentSelectionViewportPickingManipulatorTestFixtureParam,
StickyAndUnstickyDittoManipulatorToOtherEntityChangesManipulatorAndClickOffResetsManipulator)
{
PositionEntities();
PositionCamera(m_cameraState);
AzToolsFramework::SelectEntity(m_entityId1);
// calculate the position in screen space of the second entity
const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState);
// position in space above the entities
const auto clickOffPositionWorld = AZ::Vector3(5.0f, 15.0f, 12.0f);
// calculate the screen space position of the click
const auto clickOffPositionScreen = AzFramework::WorldToScreen(clickOffPositionWorld, m_cameraState);
using ::testing::UnorderedElementsAre;
// single click select entity2, then click off
m_actionDispatcher->SetStickySelect(GetParam())
->CameraState(m_cameraState)
->MousePosition(entity2ScreenPosition)
->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control)
->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Alt)
->MouseLButtonDown()
->MouseLButtonUp()
->ExecuteBlock(
[this]()
{
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1));
AZStd::optional<AZ::Transform> manipulatorTransform;
AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
manipulatorTransform, AzToolsFramework::GetEntityContextId(),
&AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
EXPECT_THAT(manipulatorTransform->GetTranslation(), IsClose(m_entity2WorldTranslation));
})
->MousePosition(clickOffPositionScreen)
->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control)
->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Alt)
->MouseLButtonDown()
->MouseLButtonUp();
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1));
AZStd::optional<AZ::Transform> manipulatorTransform;
AzToolsFramework::EditorTransformComponentSelectionRequestBus::EventResult(
manipulatorTransform, AzToolsFramework::GetEntityContextId(),
&AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::GetManipulatorTransform);
// manipulator transform is reset
EXPECT_THAT(manipulatorTransform->GetTranslation(), IsClose(m_entity1WorldTranslation));
}
INSTANTIATE_TEST_CASE_P(All, EditorTransformComponentSelectionViewportPickingManipulatorTestFixtureParam, testing::Values(true, false));
using EditorTransformComponentSelectionManipulatorTestFixture =
IndirectCallManipulatorViewportInteractionFixtureMixin<EditorTransformComponentSelectionFixture>;