Add remaining integration tests for viewport selection (box select) (#4075)

* updates to viewport box select tests

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

* add interface for querying keyboard modifiers

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

* remove redundant casts

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

* update formatting options for trace functions in ActionDispatcher

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

* remove redundant GetKeyboardModifiers call

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

* update how trace/log functions have been fixed to output during tests

Signed-off-by: hultonha <hultonha@amazon.co.uk>
This commit is contained in:
hultonha
2021-09-13 15:19:46 +01:00
committed by GitHub
parent fd627af003
commit 7a58b72f15
15 changed files with 256 additions and 172 deletions
@@ -657,8 +657,7 @@ namespace AzToolsFramework
m_editorBoxSelect.InstallDisplayScene(
[this, vertexBoxSelectData](const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& /*debugDisplay*/)
{
const auto keyboardModifiers = ViewportInteraction::KeyboardModifiers(
ViewportInteraction::TranslateKeyboardModifiers(QApplication::queryKeyboardModifiers()));
const auto keyboardModifiers = AzToolsFramework::ViewportInteraction::QueryKeyboardModifiers();
// when modifiers change ensure we refresh box selection for immediate update
if (keyboardModifiers != m_editorBoxSelect.PreviousModifiers())
@@ -275,6 +275,29 @@ namespace AzToolsFramework
using EditorEntityViewportInteractionRequestBus = AZ::EBus<EditorEntityViewportInteractionRequests, ViewportEBusTraits>;
//! An interface to query editor modifier keys.
class EditorModifierKeyRequests : public AZ::EBusTraits
{
public:
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
//! Returns the current state of the keyboard modifier keys.
virtual KeyboardModifiers QueryKeyboardModifiers() = 0;
protected:
~EditorModifierKeyRequests() = default;
};
using EditorModifierKeyRequestBus = AZ::EBus<EditorModifierKeyRequests>;
inline KeyboardModifiers QueryKeyboardModifiers()
{
KeyboardModifiers keyboardModifiers;
EditorModifierKeyRequestBus::BroadcastResult(keyboardModifiers, &EditorModifierKeyRequestBus::Events::QueryKeyboardModifiers);
return keyboardModifiers;
}
//! Viewport requests for managing the viewport cursor state.
class ViewportMouseCursorRequests
{
@@ -19,6 +19,13 @@ namespace AzToolsFramework
static const AZ::Color s_boxSelectColor = AZ::Color(1.0f, 1.0f, 1.0f, 0.4f);
static const float s_boxSelectLineWidth = 2.0f;
EditorBoxSelect::EditorBoxSelect()
{
// discard double click interval as box select is only interested in 'move' detection
// note: this also simplifies integration tests that do not have delays between presses
m_clickDetector.SetDoubleClickInterval(0.0f);
}
void EditorBoxSelect::HandleMouseInteraction(const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
@@ -95,8 +102,7 @@ namespace AzToolsFramework
debugDisplay.DepthTestOn();
m_previousModifiers = ViewportInteraction::KeyboardModifiers(
ViewportInteraction::TranslateKeyboardModifiers(QApplication::queryKeyboardModifiers()));
m_previousModifiers = AzToolsFramework::ViewportInteraction::QueryKeyboardModifiers();
}
}
@@ -29,7 +29,7 @@ namespace AzToolsFramework
class EditorBoxSelect
{
public:
EditorBoxSelect() = default;
EditorBoxSelect();
//! Return if a box select action is currently taking place.
bool Active() const { return m_boxSelectRegion.has_value(); }
@@ -293,8 +293,8 @@ namespace AzToolsFramework
}
// poll and set the keyboard modifiers to ensure the mouse interaction is up to date
m_currentInteraction.m_keyboardModifiers =
AzToolsFramework::ViewportInteraction::BuildKeyboardModifiers(QGuiApplication::queryKeyboardModifiers());
m_currentInteraction.m_keyboardModifiers = AzToolsFramework::ViewportInteraction::QueryKeyboardModifiers();
// draw the manipulators
const AzFramework::CameraState cameraState = GetCameraState(viewportInfo.m_viewportId);
debugDisplay.DepthTestOff();
@@ -399,16 +399,18 @@ namespace AzToolsFramework
// modifier has changed - swapped from additive to subtractive box select (or vice versa)
if (previousKeyboardModifiers != currentKeyboardModifiers)
{
for (AZ::EntityId entityId : potentialDeselectedEntityIds)
for (const AZ::EntityId& entityId : potentialDeselectedEntityIds)
{
editorTransformComponentSelection.AddEntityToSelection(entityId);
}
potentialDeselectedEntityIds.clear();
for (AZ::EntityId entityId : potentialSelectedEntityIds)
for (const AZ::EntityId& entityId : potentialSelectedEntityIds)
{
editorTransformComponentSelection.RemoveEntityFromSelection(entityId);
}
potentialSelectedEntityIds.clear();
}
@@ -1162,15 +1164,13 @@ namespace AzToolsFramework
m_boxSelect.InstallDisplayScene(
[this, entityBoxSelectData](const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
{
const auto modifiers = ViewportInteraction::KeyboardModifiers(
ViewportInteraction::TranslateKeyboardModifiers(QApplication::queryKeyboardModifiers()));
if (m_boxSelect.PreviousModifiers() != modifiers)
if (const auto keyboardModifiers = AzToolsFramework::ViewportInteraction::QueryKeyboardModifiers();
m_boxSelect.PreviousModifiers() != keyboardModifiers)
{
EntityBoxSelectUpdateGeneral(
m_boxSelect.BoxRegion(), *this, m_selectedEntityIds, entityBoxSelectData->m_selectedEntityIdsBeforeBoxSelect,
entityBoxSelectData->m_potentialSelectedEntityIds, entityBoxSelectData->m_potentialDeselectedEntityIds,
*m_entityDataCache, viewportInfo.m_viewportId, modifiers, m_boxSelect.PreviousModifiers());
*m_entityDataCache, viewportInfo.m_viewportId, keyboardModifiers, m_boxSelect.PreviousModifiers());
}
debugDisplay.DepthTestOff();
@@ -3324,16 +3324,15 @@ namespace AzToolsFramework
CheckDirtyEntityIds();
const auto modifiers =
ViewportInteraction::KeyboardModifiers(ViewportInteraction::TranslateKeyboardModifiers(QApplication::queryKeyboardModifiers()));
const auto keyboardModifiers = AzToolsFramework::ViewportInteraction::QueryKeyboardModifiers();
m_cursorState.Update();
HandleAccents(
!m_selectedEntityIds.empty(), m_cachedEntityIdUnderCursor, modifiers.Ctrl(), m_hoveredEntityId,
!m_selectedEntityIds.empty(), m_cachedEntityIdUnderCursor, keyboardModifiers.Ctrl(), m_hoveredEntityId,
ViewportInteraction::BuildMouseButtons(QGuiApplication::mouseButtons()), m_boxSelect.Active());
const ReferenceFrame referenceFrame = m_spaceCluster.m_spaceLock.value_or(ReferenceFrameFromModifiers(modifiers));
const ReferenceFrame referenceFrame = m_spaceCluster.m_spaceLock.value_or(ReferenceFrameFromModifiers(keyboardModifiers));
UpdateSpaceCluster(referenceFrame);
@@ -235,7 +235,7 @@ namespace AzToolsFramework
// can be returned to its previous state after an undo/redo operation
void CreateEntityManipulatorDeselectCommand(ScopedUndoBatch& undoBatch);
// EditorTransformComponentSelectionRequestBus ...
// EditorTransformComponentSelectionRequestBus overrides ...
Mode GetTransformMode() override;
void SetTransformMode(Mode mode) override;
void RefreshManipulators(RefreshType refreshType) override;
@@ -252,34 +252,34 @@ namespace AzToolsFramework
void CopyScaleToSelectedEntitiesIndividualWorld(float scale) override;
void SnapSelectedEntitiesToWorldGrid(float gridSize) override;
// EditorManipulatorCommandUndoRedoRequestBus ...
// EditorManipulatorCommandUndoRedoRequestBus overrides ...
void UndoRedoEntityManipulatorCommand(AZ::u8 pivotOverride, const AZ::Transform& transform, AZ::EntityId entityId) override;
// EditorContextMenuBus...
// EditorContextMenuBus overrides ...
void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override;
int GetMenuPosition() const override;
AZStd::string GetMenuIdentifier() const override;
// EditorEventsBus ...
// EditorEventsBus overrides ...
void OnEscape() override;
// ToolsApplicationNotificationBus ...
// ToolsApplicationNotificationBus overrides ...
void BeforeEntitySelectionChanged() override;
void AfterEntitySelectionChanged(const EntityIdList& newlySelectedEntities, const EntityIdList& newlyDeselectedEntities) override;
// TransformNotificationBus ...
// TransformNotificationBus overrides ...
void OnTransformChanged(const AZ::Transform& localTM, const AZ::Transform& worldTM) override;
// Camera::EditorCameraNotificationBus ...
// Camera::EditorCameraNotificationBus overrides ...
void OnViewportViewEntityChanged(const AZ::EntityId& newViewId) override;
// EditorContextVisibilityNotificationBus ...
// EditorContextVisibilityNotificationBus overrides ...
void OnEntityVisibilityChanged(bool visibility) override;
// EditorContextLockComponentNotificationBus ...
// EditorContextLockComponentNotificationBus overrides ...
void OnEntityLockChanged(bool locked) override;
// EditorComponentModeNotificationBus ...
// EditorComponentModeNotificationBus overrides ...
void EnteredComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
void LeftComponentMode(const AZStd::vector<AZ::Uuid>& componentModeTypes) override;
@@ -301,7 +301,7 @@ namespace AzToolsFramework
//! Responsible for keeping the space cluster in sync with the current reference frame.
void UpdateSpaceCluster(ReferenceFrame referenceFrame);
//! Hides/Shows all viewportUi toolbars.
//! Hides/Shows all viewportUi tool bars.
void SetAllViewportUiVisible(bool visible);
AZ::EntityId m_hoveredEntityId; //!< What EntityId is the mouse currently hovering over (if any).
@@ -238,10 +238,32 @@ namespace UnitTest
m_entityId3 = createEntityWithBoundsFn("Entity3");
}
public:
void PositionEntities()
{
// the initial starting position of the entities
AZ::TransformBus::Event(
m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(m_entity1WorldTranslation));
AZ::TransformBus::Event(
m_entityId2, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(m_entity2WorldTranslation));
AZ::TransformBus::Event(
m_entityId3, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(m_entity3WorldTranslation));
}
static void PositionCamera(AzFramework::CameraState& cameraState)
{
// initial camera position (looking down the negative x-axis)
AzFramework::SetCameraTransform(
cameraState,
AZ::Transform::CreateFromQuaternionAndTranslation(
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f)));
}
AZ::EntityId m_entityId1;
AZ::EntityId m_entityId2;
AZ::EntityId m_entityId3;
AZ::Vector3 m_entity1WorldTranslation = AZ::Vector3(5.0f, 15.0f, 10.0f);
AZ::Vector3 m_entity2WorldTranslation = AZ::Vector3(5.0f, 14.0f, 10.0f);
AZ::Vector3 m_entity3WorldTranslation = AZ::Vector3(5.0f, 16.0f, 10.0f);
};
void ArrangeIndividualRotatedEntitySelection(const AzToolsFramework::EntityIdList& entityIds, const AZ::Quaternion& orientation)
@@ -596,25 +618,18 @@ namespace UnitTest
{
AzToolsFramework::ed_viewportStickySelect = true;
// the initial starting position of the entity
const auto initialTransformWorld = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f));
AZ::TransformBus::Event(m_entityId1, &AZ::TransformBus::Events::SetWorldTM, initialTransformWorld);
// initial camera position (looking down the negative x-axis)
AzFramework::SetCameraTransform(
m_cameraState,
AZ::Transform::CreateFromQuaternionAndTranslation(
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f)));
PositionEntities();
PositionCamera(m_cameraState);
using ::testing::Eq;
auto selectedEntitiesBefore = SelectedEntities();
EXPECT_TRUE(selectedEntitiesBefore.empty());
// calculate the position in screen space of the initial entity position
const auto initialPositionScreen = AzFramework::WorldToScreen(initialTransformWorld.GetTranslation(), m_cameraState);
const auto entity1ScreenPosition = AzFramework::WorldToScreen(m_entity1WorldTranslation, m_cameraState);
// click the entity in the viewport
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(initialPositionScreen)->MouseLButtonDown()->MouseLButtonUp();
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity1ScreenPosition)->MouseLButtonDown()->MouseLButtonUp();
// entity is selected
auto selectedEntitiesAfter = SelectedEntities();
@@ -626,19 +641,12 @@ namespace UnitTest
{
AzToolsFramework::ed_viewportStickySelect = true;
// the initial starting position of the entity
AZ::TransformBus::Event(
m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f)));
PositionEntities();
PositionCamera(m_cameraState);
// position in space above the entity
const auto clickOffPositionWorld = AZ::Vector3(5.0f, 15.0f, 12.0f);
// initial camera position (looking down the negative x-axis)
AzFramework::SetCameraTransform(
m_cameraState,
AZ::Transform::CreateFromQuaternionAndTranslation(
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f)));
AzToolsFramework::SelectEntity(m_entityId1);
// calculate the position in screen space of the initial position of the entity
@@ -660,30 +668,16 @@ namespace UnitTest
{
AzToolsFramework::ed_viewportStickySelect = true;
// the initial starting position of the entity
AZ::TransformBus::Event(
m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f)));
const auto initialTransformWorldSecondEntity = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 10.0f, 10.0f));
AZ::TransformBus::Event(m_entityId2, &AZ::TransformBus::Events::SetWorldTM, initialTransformWorldSecondEntity);
// initial camera position (looking down the negative x-axis)
AzFramework::SetCameraTransform(
m_cameraState,
AZ::Transform::CreateFromQuaternionAndTranslation(
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f)));
PositionEntities();
PositionCamera(m_cameraState);
AzToolsFramework::SelectEntity(m_entityId1);
// calculate the position in screen space of the second entity
const auto initialPositionScreenSecondEntity =
AzFramework::WorldToScreen(initialTransformWorldSecondEntity.GetTranslation(), m_cameraState);
const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState);
// click the entity in the viewport
m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(initialPositionScreenSecondEntity)
->MouseLButtonDown()
->MouseLButtonUp();
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity2ScreenPosition)->MouseLButtonDown()->MouseLButtonUp();
// entity selection was not changed
using ::testing::Eq;
@@ -698,28 +692,17 @@ namespace UnitTest
{
AzToolsFramework::ed_viewportStickySelect = true;
// the initial starting position of the entity
AZ::TransformBus::Event(
m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f)));
const auto initialTransformWorldSecondEntity = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 10.0f, 10.0f));
AZ::TransformBus::Event(m_entityId2, &AZ::TransformBus::Events::SetWorldTM, initialTransformWorldSecondEntity);
// initial camera position (looking down the negative x-axis)
AzFramework::SetCameraTransform(
m_cameraState,
AZ::Transform::CreateFromQuaternionAndTranslation(
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f)));
PositionEntities();
PositionCamera(m_cameraState);
AzToolsFramework::SelectEntity(m_entityId1);
// calculate the position in screen space of the second entity
const auto initialPositionScreenSecondEntity =
AzFramework::WorldToScreen(initialTransformWorldSecondEntity.GetTranslation(), m_cameraState);
const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState);
// click the entity in the viewport
m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(initialPositionScreenSecondEntity)
->MousePosition(entity2ScreenPosition)
->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control)
->MouseLButtonDown()
->MouseLButtonUp();
@@ -736,28 +719,17 @@ namespace UnitTest
{
AzToolsFramework::ed_viewportStickySelect = true;
// the initial starting position of the entity
AZ::TransformBus::Event(
m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f)));
const auto initialTransformWorldSecondEntity = AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 10.0f, 10.0f));
AZ::TransformBus::Event(m_entityId2, &AZ::TransformBus::Events::SetWorldTM, initialTransformWorldSecondEntity);
// initial camera position (looking down the negative x-axis)
AzFramework::SetCameraTransform(
m_cameraState,
AZ::Transform::CreateFromQuaternionAndTranslation(
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f)));
PositionEntities();
PositionCamera(m_cameraState);
AzToolsFramework::SelectEntities({ m_entityId1, m_entityId2 });
// calculate the position in screen space of the second entity
const auto initialPositionScreenSecondEntity =
AzFramework::WorldToScreen(initialTransformWorldSecondEntity.GetTranslation(), m_cameraState);
const auto entity2ScreenPosition = AzFramework::WorldToScreen(m_entity2WorldTranslation, m_cameraState);
// click the entity in the viewport
m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(initialPositionScreenSecondEntity)
->MousePosition(entity2ScreenPosition)
->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control)
->MouseLButtonDown()
->MouseLButtonUp();
@@ -768,39 +740,26 @@ namespace UnitTest
EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1));
}
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, DISABLED_BoxSelectWithNoInitialSelectionAddsEntitiesToSelection)
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, BoxSelectWithNoInitialSelectionAddsEntitiesToSelection)
{
AzToolsFramework::ed_viewportStickySelect = true;
// the initial starting position of the entities
AZ::TransformBus::Event(
m_entityId1, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 15.0f, 10.0f)));
AZ::TransformBus::Event(
m_entityId2, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 14.0f, 10.0f)));
AZ::TransformBus::Event(
m_entityId3, &AZ::TransformBus::Events::SetWorldTM, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 16.0f, 10.0f)));
// initial camera position (looking down the negative x-axis)
AzFramework::SetCameraTransform(
m_cameraState,
AZ::Transform::CreateFromQuaternionAndTranslation(
AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(0.0f, 0.0f, 90.0f)), AZ::Vector3(10.0f, 15.0f, 10.0f)));
PositionEntities();
PositionCamera(m_cameraState);
using ::testing::Eq;
auto selectedEntitiesBefore = SelectedEntities();
EXPECT_THAT(selectedEntitiesBefore.size(), Eq(0));
// calculate the position in screen space of where to begin and end the box select action
const auto beginningPositionWorldBoxSelectStart = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 13.5f, 10.5f), m_cameraState);
const auto middlePositionWorldBoxSelectStart = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 15.0f, 10.0f), m_cameraState);
const auto endingPositionWorldBoxSelectStart = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 16.5f, 9.5f), m_cameraState);
const auto beginningPositionWorldBoxSelect = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 13.5f, 10.5f), m_cameraState);
const auto endingPositionWorldBoxSelect = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 16.5f, 9.5f), m_cameraState);
// perform a box select in the viewport
m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(beginningPositionWorldBoxSelectStart)
->MousePosition(beginningPositionWorldBoxSelect)
->MouseLButtonDown()
->MousePosition(middlePositionWorldBoxSelectStart)
->MousePosition(endingPositionWorldBoxSelectStart)
->MousePosition(endingPositionWorldBoxSelect)
->MouseLButtonUp();
// entities are selected
@@ -809,6 +768,73 @@ namespace UnitTest
EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1, m_entityId2, m_entityId3));
}
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, BoxSelectWithSelectionAppendsEntitiesToSelection)
{
AzToolsFramework::ed_viewportStickySelect = true;
PositionEntities();
PositionCamera(m_cameraState);
AzToolsFramework::SelectEntity(m_entityId1);
using ::testing::UnorderedElementsAre;
auto selectedEntitiesBefore = SelectedEntities();
EXPECT_THAT(selectedEntitiesBefore, UnorderedElementsAre(m_entityId1));
// calculate the position in screen space of where to begin and end the box select action
const auto beginningPositionWorldBoxSelect1 = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 14.5f, 10.5f), m_cameraState);
const auto endingPositionWorldBoxSelect1 = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 13.5f, 9.5f), m_cameraState);
const auto beginningPositionWorldBoxSelect2 = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 15.5f, 10.5f), m_cameraState);
const auto endingPositionWorldBoxSelect2 = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 16.5f, 9.5f), m_cameraState);
// perform a box select in the viewport (going left and right)
m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(beginningPositionWorldBoxSelect1)
->MouseLButtonDown()
->MousePosition(endingPositionWorldBoxSelect1)
->MouseLButtonUp()
->MousePosition(beginningPositionWorldBoxSelect2)
->MouseLButtonDown()
->MousePosition(endingPositionWorldBoxSelect2)
->MouseLButtonUp();
// entities are selected
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1, m_entityId2, m_entityId3));
}
TEST_F(
EditorTransformComponentSelectionViewportPickingManipulatorTestFixture,
BoxSelectHoldingCtrlWithSelectionRemovesEntitiesFromSelection)
{
AzToolsFramework::ed_viewportStickySelect = true;
PositionEntities();
PositionCamera(m_cameraState);
AzToolsFramework::SelectEntities({ m_entityId1, m_entityId2, m_entityId3 });
using ::testing::UnorderedElementsAre;
auto selectedEntitiesBefore = SelectedEntities();
EXPECT_THAT(selectedEntitiesBefore, UnorderedElementsAre(m_entityId1, m_entityId2, m_entityId3));
// calculate the position in screen space of where to begin and end the box select action
const auto beginningPositionWorldBoxSelect = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 13.5f, 10.5f), m_cameraState);
const auto endingPositionWorldBoxSelect = AzFramework::WorldToScreen(AZ::Vector3(5.0f, 16.5f, 9.5f), m_cameraState);
// perform a box select in the viewport
m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(beginningPositionWorldBoxSelect)
->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control)
->MouseLButtonDown()
->MousePosition(endingPositionWorldBoxSelect)
->MouseLButtonUp();
// entities are selected
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_TRUE(selectedEntitiesAfter.empty());
}
using EditorTransformComponentSelectionManipulatorTestFixture =
IndirectCallManipulatorViewportInteractionFixtureMixin<EditorTransformComponentSelectionFixture>;