Merge branch 'development' into Prefab/IncreaseReadFileSizeLimit

Signed-off-by: srikappa-amzn <srikappa@amazon.com>
This commit is contained in:
srikappa-amzn
2021-09-09 09:09:04 -07:00
49 changed files with 5126 additions and 6360 deletions
@@ -40,6 +40,12 @@ namespace AzManipulatorTestFramework
{
m_viewportInteraction.UpdateVisibility();
// ensure we call display viewport 2d to simulate this update step (some state may be
// updated here, e.g. box select)
AzFramework::ViewportDebugDisplayEventBus::Event(
AzToolsFramework::GetEntityContextId(), &AzFramework::ViewportDebugDisplayEvents::DisplayViewport2d,
AzFramework::ViewportInfo{ m_viewportInteraction.GetViewportId() }, m_viewportInteraction.GetDebugDisplay());
DrawManipulators();
AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Event(
AzToolsFramework::GetEntityContextId(),
@@ -44,7 +44,7 @@ namespace AzToolsFramework
const char AssetBundleSettingsFileExtension[] = "bundlesettings";
const char BundleFileExtension[] = "pak";
const char ComparisonRulesFileExtension[] = "rules";
const char ErrorWindowName[] = "AssetBundler";
[[maybe_unused]] const char ErrorWindowName[] = "AssetBundler";
const char* AssetFileInfoListComparison::ComparisonTypeNames[] = { "delta", "union", "intersection", "complement", "filepattern", "intersectioncount" };
const char* AssetFileInfoListComparison::FilePatternTypeNames[] = { "wildcard", "regex" };
const char DefaultTypeName[] = "default";
@@ -9,8 +9,8 @@
#include "EditorBoxSelect.h"
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
#include <QApplication>
@@ -19,11 +19,15 @@ 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;
void EditorBoxSelect::HandleMouseInteraction(
const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
void EditorBoxSelect::HandleMouseInteraction(const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down)
{
m_cursorPositionAtDownEvent = mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates;
}
m_cursorState.SetCurrentPosition(mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates);
const auto selectClickEvent = ClickDetectorEventFromViewportInteraction(mouseInteraction);
@@ -35,12 +39,7 @@ namespace AzToolsFramework
m_leftMouseDown(mouseInteraction);
}
m_boxSelectRegion = QRect
{
ViewportInteraction::QPointFromScreenPoint(
mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates),
QSize { 0, 0 }
};
m_boxSelectRegion = QRect{ ViewportInteraction::QPointFromScreenPoint(m_cursorPositionAtDownEvent), QSize{ 0, 0 } };
}
if (m_boxSelectRegion)
@@ -87,11 +86,11 @@ namespace AzToolsFramework
AZ::Vector2 viewportSize = AzToolsFramework::GetCameraState(viewportInfo.m_viewportId).m_viewportSize;
debugDisplay.DrawWireQuad2d(
AZ::Vector2(
aznumeric_cast<float>(m_boxSelectRegion->x()), aznumeric_cast<float>(m_boxSelectRegion->y())) / viewportSize,
AZ::Vector2(aznumeric_cast<float>(m_boxSelectRegion->x()), aznumeric_cast<float>(m_boxSelectRegion->y())) / viewportSize,
AZ::Vector2(
aznumeric_cast<float>(m_boxSelectRegion->x()) + aznumeric_cast<float>(m_boxSelectRegion->width()),
aznumeric_cast<float>(m_boxSelectRegion->y()) + aznumeric_cast<float>(m_boxSelectRegion->height())) / viewportSize,
aznumeric_cast<float>(m_boxSelectRegion->y()) + aznumeric_cast<float>(m_boxSelectRegion->height())) /
viewportSize,
0.f);
debugDisplay.DepthTestOn();
@@ -101,8 +100,7 @@ namespace AzToolsFramework
}
}
void EditorBoxSelect::DisplayScene(
const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
void EditorBoxSelect::DisplayScene(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
{
if (m_displayScene)
{
@@ -122,15 +120,14 @@ namespace AzToolsFramework
m_mouseMove = mouseMove;
}
void EditorBoxSelect::InstallLeftMouseUp(
const AZStd::function<void()>& leftMouseUp)
void EditorBoxSelect::InstallLeftMouseUp(const AZStd::function<void()>& leftMouseUp)
{
m_leftMouseUp = leftMouseUp;
}
void EditorBoxSelect::InstallDisplayScene(
const AZStd::function<void(const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay)>& displayScene)
const AZStd::function<void(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)>&
displayScene)
{
m_displayScene = displayScene;
}
@@ -81,5 +81,6 @@ namespace AzToolsFramework
ViewportInteraction::KeyboardModifiers m_previousModifiers; //!< Modifier keys active on the previous frame.
AzFramework::ClickDetector m_clickDetector; //!< Utility type to detect if a mouse click or move has occurred.
AzFramework::CursorState m_cursorState; //!< Utility type to track the current cursor position (and movement/delta).
AzFramework::ScreenPoint m_cursorPositionAtDownEvent; //!< The position of the cursor when first potentially starting a box select.
};
} // namespace AzToolsFramework
@@ -44,39 +44,46 @@ namespace AzToolsFramework
AZ_CVAR(
float,
cl_viewportGizmoAxisLineWidth,
ed_viewportGizmoAxisLineWidth,
4.0f,
nullptr,
AZ::ConsoleFunctorFlags::Null,
"The width of the line for the viewport axis gizmo");
AZ_CVAR(
float,
cl_viewportGizmoAxisLineLength,
ed_viewportGizmoAxisLineLength,
0.7f,
nullptr,
AZ::ConsoleFunctorFlags::Null,
"The length of the line for the viewport axis gizmo");
AZ_CVAR(
float,
cl_viewportGizmoAxisLabelOffset,
ed_viewportGizmoAxisLabelOffset,
1.15f,
nullptr,
AZ::ConsoleFunctorFlags::Null,
"The offset of the label for the viewport axis gizmo");
AZ_CVAR(
float,
cl_viewportGizmoAxisLabelSize,
ed_viewportGizmoAxisLabelSize,
1.0f,
nullptr,
AZ::ConsoleFunctorFlags::Null,
"The size of each label for the viewport axis gizmo");
AZ_CVAR(
AZ::Vector2,
cl_viewportGizmoAxisScreenPosition,
ed_viewportGizmoAxisScreenPosition,
AZ::Vector2(0.045f, 0.9f),
nullptr,
AZ::ConsoleFunctorFlags::Null,
"The screen position of the gizmo in normalized (0-1) ndc space");
AZ_CVAR(
bool,
ed_viewportStickySelect,
true,
nullptr,
AZ::ConsoleFunctorFlags::Null,
"Sticky select implies a single click will not change selection with an entity already selected");
// strings related to new viewport interaction model (EditorTransformComponentSelection)
static const char* const s_togglePivotTitleRightClick = "Toggle pivot";
@@ -991,14 +998,19 @@ namespace AzToolsFramework
// ask the visible entity data cache if the entity is selectable in the viewport
// (useful in the context of drawing when we only care about entities we can see)
static bool SelectableInVisibleViewportCache(const EditorVisibleEntityDataCache& entityDataCache, const AZ::EntityId entityId)
// note: return the index if it is selectable, nullopt otherwise
static AZStd::optional<size_t> SelectableInVisibleViewportCache(
const EditorVisibleEntityDataCache& entityDataCache, const AZ::EntityId entityId)
{
if (auto entityIndex = entityDataCache.GetVisibleEntityIndexFromId(entityId))
{
return entityDataCache.IsVisibleEntitySelectableInViewport(*entityIndex);
if (entityDataCache.IsVisibleEntitySelectableInViewport(*entityIndex))
{
return *entityIndex;
}
}
return false;
return AZStd::nullopt;
}
static AZ::ComponentId GetTransformComponentId(const AZ::EntityId entityId)
@@ -1709,17 +1721,17 @@ namespace AzToolsFramework
m_pivotOverrideFrame.Reset();
}
bool EditorTransformComponentSelection::SelectDeselect(const AZ::EntityId entityIdUnderCursor)
bool EditorTransformComponentSelection::SelectDeselect(const AZ::EntityId entityId)
{
AZ_PROFILE_FUNCTION(AzToolsFramework);
if (entityIdUnderCursor.IsValid())
if (entityId.IsValid())
{
if (IsEntitySelectedInternal(entityIdUnderCursor, m_selectedEntityIds))
if (IsEntitySelectedInternal(entityId, m_selectedEntityIds))
{
if (!UndoRedoOperationInProgress())
{
RemoveEntityFromSelection(entityIdUnderCursor);
RemoveEntityFromSelection(entityId);
const auto nextEntityIds = EntityIdVectorFromContainer(m_selectedEntityIds);
@@ -1742,7 +1754,7 @@ namespace AzToolsFramework
{
if (!UndoRedoOperationInProgress())
{
AddEntityToSelection(entityIdUnderCursor);
AddEntityToSelection(entityId);
const auto nextEntityIds = EntityIdVectorFromContainer(m_selectedEntityIds);
@@ -1783,25 +1795,21 @@ namespace AzToolsFramework
// for entities selected with no bounds of their own (just TransformComponent)
// check selection against the selection indicator aabb
for (AZ::EntityId entityId : m_selectedEntityIds)
for (const AZ::EntityId& entityId : m_selectedEntityIds)
{
if (!SelectableInVisibleViewportCache(*m_entityDataCache, entityId))
if (const auto entityIndex = SelectableInVisibleViewportCache(*m_entityDataCache, entityId); entityIndex.has_value())
{
continue;
}
const AZ::Transform& worldFromLocal = m_entityDataCache->GetVisibleEntityTransform(*entityIndex);
const AZ::Vector3 boxPosition = worldFromLocal.TransformPoint(CalculateCenterOffset(entityId, m_pivotMode));
const AZ::Vector3 scaledSize =
AZ::Vector3(s_pivotSize) * CalculateScreenToWorldMultiplier(worldFromLocal.GetTranslation(), cameraState);
AZ::Transform worldFromLocal;
AZ::TransformBus::EventResult(worldFromLocal, entityId, &AZ::TransformBus::Events::GetWorldTM);
const AZ::Vector3 boxPosition = worldFromLocal.TransformPoint(CalculateCenterOffset(entityId, m_pivotMode));
const AZ::Vector3 scaledSize =
AZ::Vector3(s_pivotSize) * CalculateScreenToWorldMultiplier(worldFromLocal.GetTranslation(), cameraState);
if (AabbIntersectMouseRay(
mouseInteraction.m_mouseInteraction, AZ::Aabb::CreateFromMinMax(boxPosition - scaledSize, boxPosition + scaledSize)))
{
m_cachedEntityIdUnderCursor = entityId;
if (AabbIntersectMouseRay(
mouseInteraction.m_mouseInteraction,
AZ::Aabb::CreateFromMinMax(boxPosition - scaledSize, boxPosition + scaledSize)))
{
m_cachedEntityIdUnderCursor = entityId;
}
}
}
@@ -3490,7 +3498,7 @@ namespace AzToolsFramework
const auto cameraProjection = AzFramework::CameraProjection(gizmoCameraState);
// screen space offset to move the 2d gizmo around
const AZ::Vector2 screenOffset = AZ::Vector2(cl_viewportGizmoAxisScreenPosition) - AZ::Vector2(0.5f, 0.5f);
const AZ::Vector2 screenOffset = AZ::Vector2(ed_viewportGizmoAxisScreenPosition) - AZ::Vector2(0.5f, 0.5f);
// map from a position in world space (relative to the the gizmo camera near the origin) to a position in
// screen space
@@ -3502,7 +3510,7 @@ namespace AzToolsFramework
};
// get all important axis positions in screen space
const float lineLength = cl_viewportGizmoAxisLineLength;
const float lineLength = ed_viewportGizmoAxisLineLength;
const auto gizmoStart = calculateGizmoAxis(AZ::Vector3::CreateZero());
const auto gizmoEndAxisX = calculateGizmoAxis(-AZ::Vector3::CreateAxisX() * lineLength);
const auto gizmoEndAxisY = calculateGizmoAxis(-AZ::Vector3::CreateAxisY() * lineLength);
@@ -3513,7 +3521,7 @@ namespace AzToolsFramework
const AZ::Vector2 gizmoAxisZ = gizmoEndAxisZ - gizmoStart;
// draw the axes of the gizmo
debugDisplay.SetLineWidth(cl_viewportGizmoAxisLineWidth);
debugDisplay.SetLineWidth(ed_viewportGizmoAxisLineWidth);
debugDisplay.SetColor(AZ::Colors::Red);
debugDisplay.DrawLine2d(gizmoStart, gizmoEndAxisX, 1.0f);
debugDisplay.SetColor(AZ::Colors::Lime);
@@ -3522,14 +3530,14 @@ namespace AzToolsFramework
debugDisplay.DrawLine2d(gizmoStart, gizmoEndAxisZ, 1.0f);
debugDisplay.SetLineWidth(1.0f);
const float labelOffset = cl_viewportGizmoAxisLabelOffset;
const float labelOffset = ed_viewportGizmoAxisLabelOffset;
const float screenScale = GetScreenDisplayScaling(viewportId);
const auto labelXScreenPosition = (gizmoStart + (gizmoAxisX * labelOffset)) * editorCameraState.m_viewportSize * screenScale;
const auto labelYScreenPosition = (gizmoStart + (gizmoAxisY * labelOffset)) * editorCameraState.m_viewportSize * screenScale;
const auto labelZScreenPosition = (gizmoStart + (gizmoAxisZ * labelOffset)) * editorCameraState.m_viewportSize * screenScale;
// draw the label of of each axis for the gizmo
const float labelSize = cl_viewportGizmoAxisLabelSize;
const float labelSize = ed_viewportGizmoAxisLabelSize;
debugDisplay.SetColor(AZ::Colors::White);
debugDisplay.Draw2dTextLabel(labelXScreenPosition.GetX(), labelXScreenPosition.GetY(), labelSize, "X", true);
debugDisplay.Draw2dTextLabel(labelYScreenPosition.GetX(), labelYScreenPosition.GetY(), labelSize, "Y", true);
@@ -9,6 +9,7 @@
#pragma once
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Console/IConsole.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/optional.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
@@ -32,6 +33,8 @@
namespace AzToolsFramework
{
AZ_CVAR_EXTERNED(bool, ed_viewportStickySelect);
class EditorVisibleEntityDataCache;
using EntityIdSet = AZStd::unordered_set<AZ::EntityId>; //!< Alias for unordered_set of EntityIds.
@@ -170,14 +173,11 @@ namespace AzToolsFramework
//! ViewportInteraction::ViewportSelectionRequests
//! Intercept all viewport mouse events and respond to inputs.
bool HandleMouseInteraction(
const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
bool HandleMouseInteraction(const ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
void DisplayViewportSelection(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay) override;
const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
void DisplayViewportSelection2d(
const AzFramework::ViewportInfo& viewportInfo,
AzFramework::DebugDisplayRequests& debugDisplay) override;
const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
//! Add an entity to the current selection
void AddEntityToSelection(AZ::EntityId entityId);
@@ -206,7 +206,7 @@ namespace AzToolsFramework
bool IsEntitySelected(AZ::EntityId entityId) const;
void SetSelectedEntities(const EntityIdList& entityIds);
void DeselectEntities();
bool SelectDeselect(AZ::EntityId entityIdUnderCursor);
bool SelectDeselect(AZ::EntityId entityId);
void RefreshSelectedEntityIds();
void RefreshSelectedEntityIds(const EntityIdList& selectedEntityIds);
@@ -253,11 +253,10 @@ namespace AzToolsFramework
void SnapSelectedEntitiesToWorldGrid(float gridSize) override;
// EditorManipulatorCommandUndoRedoRequestBus ...
void UndoRedoEntityManipulatorCommand(
AZ::u8 pivotOverride, const AZ::Transform& transform, AZ::EntityId entityId) override;
void UndoRedoEntityManipulatorCommand(AZ::u8 pivotOverride, const AZ::Transform& transform, AZ::EntityId entityId) override;
// EditorContextMenuBus...
void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2 & point, int flags) override;
void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override;
int GetMenuPosition() const override;
AZStd::string GetMenuIdentifier() const override;
@@ -266,8 +265,7 @@ namespace AzToolsFramework
// ToolsApplicationNotificationBus ...
void BeforeEntitySelectionChanged() override;
void AfterEntitySelectionChanged(
const EntityIdList& newlySelectedEntities, const EntityIdList& newlyDeselectedEntities) override;
void AfterEntitySelectionChanged(const EntityIdList& newlySelectedEntities, const EntityIdList& newlyDeselectedEntities) override;
// TransformNotificationBus ...
void OnTransformChanged(const AZ::Transform& localTM, const AZ::Transform& worldTM) override;
@@ -318,7 +316,8 @@ namespace AzToolsFramework
EntityIdManipulators m_entityIdManipulators; //!< Mapping from a Manipulator to potentially many EntityIds.
EditorBoxSelect m_boxSelect; //!< Type responsible for handling box select.
AZStd::unique_ptr<EntityManipulatorCommand> m_manipulatorMoveCommand; //!< Track adjustments to manipulator translation and orientation (during mouse press/move).
//! Track adjustments to manipulator translation and orientation (during mouse press/move).
AZStd::unique_ptr<EntityManipulatorCommand> m_manipulatorMoveCommand;
AZStd::vector<AZStd::unique_ptr<QAction>> m_actions; //!< What actions are tied to this handler.
ViewportInteraction::KeyboardModifiers m_previousModifiers; //!< What modifiers were held last frame.
EditorContextMenu m_contextMenu; //!< Viewport right click context menu.
@@ -328,8 +327,10 @@ namespace AzToolsFramework
ReferenceFrame m_referenceFrame = ReferenceFrame::Parent; //!< What reference frame is the Manipulator currently operating in.
Frame m_axisPreview; //!< Axes of entity at the time of mouse down to indicate delta of translation.
bool m_triedToRefresh = false; //!< Did a refresh event occur to recalculate the current Manipulator transform.
bool m_didSetSelectedEntities = false; //!< Was EditorTransformComponentSelection responsible for the most recent entity selection change.
bool m_selectedEntityIdsAndManipulatorsDirty = false; //!< Do the active manipulators need to recalculated after a modification (lock/visibility etc).
//! Was EditorTransformComponentSelection responsible for the most recent entity selection change.
bool m_didSetSelectedEntities = false;
//! Do the active manipulators need to recalculated after a modification (lock/visibility etc).
bool m_selectedEntityIdsAndManipulatorsDirty = false;
bool m_transformChangedInternally = false; //!< Was an OnTransformChanged event triggered internally or not.
ViewportUi::ClusterId m_transformModeClusterId; //!< Id of the Viewport UI cluster for changing transform mode.
ViewportUi::ButtonId m_translateButtonId; //!< Id of the Viewport UI button for translate mode.
@@ -363,15 +364,13 @@ namespace AzToolsFramework
//! Calculate the orientation for a group of entities based on the incoming reference frame.
template<typename EntityIdMap>
PivotOrientationResult CalculatePivotOrientationForEntityIds(
const EntityIdMap& entityIdMap, const ReferenceFrame referenceFrame);
PivotOrientationResult CalculatePivotOrientationForEntityIds(const EntityIdMap& entityIdMap, const ReferenceFrame referenceFrame);
//! Calculate the orientation for a group of entities based on the incoming
//! reference frame with possible pivot override.
template<typename EntityIdMap>
PivotOrientationResult CalculateSelectionPivotOrientation(
const EntityIdMap& entityIdMap, const OptionalFrame& pivotOverrideFrame,
const ReferenceFrame referenceFrame);
const EntityIdMap& entityIdMap, const OptionalFrame& pivotOverrideFrame, const ReferenceFrame referenceFrame);
void SetEntityWorldTranslation(AZ::EntityId entityId, const AZ::Vector3& worldTranslation, bool& internal);
void SetEntityLocalTranslation(AZ::EntityId entityId, const AZ::Vector3& localTranslation, bool& internal);
@@ -15,7 +15,7 @@ namespace AzToolsFramework
{
namespace Platform
{
static const char ErrorChannel[] = "ArchiveComponent_Linux";
[[maybe_unused]] static const char ErrorChannel[] = "ArchiveComponent_Linux";
static const char ZipExePath[] = R"(/usr/bin/zip)";
static const char UnzipExePath[] = R"(/usr/bin/unzip)";
@@ -6,12 +6,14 @@
*
*/
#include <AzCore/Math/IntersectSegment.h>
#include <AzCore/Math/ToString.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/UnitTest/TestTypes.h>
#include <AzFramework/Components/TransformComponent.h>
#include <AzFramework/Entity/EntityContext.h>
#include <AzFramework/Viewport/ViewportScreen.h>
#include <AzFramework/Visibility/BoundsBus.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h>
@@ -20,10 +22,12 @@
#include <AzManipulatorTestFramework/ViewportInteraction.h>
#include <AzQtComponents/Components/GlobalEventFilter.h>
#include <AzTest/AzTest.h>
#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
#include <AzToolsFramework/Application/ToolsApplication.h>
#include <AzToolsFramework/Entity/EditorEntityActionComponent.h>
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
#include <AzToolsFramework/Entity/EditorEntityModel.h>
#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
#include <AzToolsFramework/ToolsComponents/EditorLockComponent.h>
#include <AzToolsFramework/ToolsComponents/EditorVisibilityComponent.h>
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
@@ -32,6 +36,7 @@
#include <AzToolsFramework/ViewportSelection/EditorDefaultSelection.h>
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
#include <AzToolsFramework/ViewportSelection/EditorPickEntitySelection.h>
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
#include <AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h>
#include <AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h>
#include <AzToolsFramework/ViewportUi/ViewportUiManager.h>
@@ -46,6 +51,14 @@ namespace AZ
namespace UnitTest
{
AzToolsFramework::EntityIdList SelectedEntities()
{
AzToolsFramework::EntityIdList selectedEntitiesBefore;
AzToolsFramework::ToolsApplicationRequestBus::BroadcastResult(
selectedEntitiesBefore, &AzToolsFramework::ToolsApplicationRequestBus::Events::GetSelectedEntities);
return selectedEntitiesBefore;
}
class EditorEntityVisibilityCacheFixture : public ToolsApplicationFixture
{
public:
@@ -110,6 +123,80 @@ namespace UnitTest
EXPECT_FALSE(m_cache.IsVisibleEntityVisible(m_cache.GetVisibleEntityIndexFromId(m_entityIds[2]).value()));
}
//! Basic component that implements BoundsRequestBus and EditorComponentSelectionRequestsBus to be compatible
//! with the Editor visibility system.
//! Note: Used for simulating selection (picking) in the viewport.
class BoundsTestComponent
: public AzToolsFramework::Components::EditorComponentBase
, public AzFramework::BoundsRequestBus::Handler
, public AzToolsFramework::EditorComponentSelectionRequestsBus::Handler
{
public:
AZ_EDITOR_COMPONENT(
BoundsTestComponent, "{E6312E9D-8489-4677-9980-C93C328BC92C}", AzToolsFramework::Components::EditorComponentBase);
static void Reflect(AZ::ReflectContext* context);
// AZ::Component overrides ...
void Activate() override;
void Deactivate() override;
// EditorComponentSelectionRequestsBus overrides ...
AZ::Aabb GetEditorSelectionBoundsViewport(const AzFramework::ViewportInfo& viewportInfo) override;
bool EditorSelectionIntersectRayViewport(
const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, const AZ::Vector3& dir, float& distance) override;
bool SupportsEditorRayIntersect() override;
// BoundsRequestBus overrides ...
AZ::Aabb GetWorldBounds() override;
AZ::Aabb GetLocalBounds() override;
};
AZ::Aabb BoundsTestComponent::GetEditorSelectionBoundsViewport([[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo)
{
return GetWorldBounds();
}
bool BoundsTestComponent::EditorSelectionIntersectRayViewport(
[[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, const AZ::Vector3& src, const AZ::Vector3& dir, float& distance)
{
return AzToolsFramework::AabbIntersectRay(src, dir, GetWorldBounds(), distance);
}
bool BoundsTestComponent::SupportsEditorRayIntersect()
{
return true;
}
void BoundsTestComponent::Reflect([[maybe_unused]] AZ::ReflectContext* context)
{
// noop
}
void BoundsTestComponent::Activate()
{
AzFramework::BoundsRequestBus::Handler::BusConnect(GetEntityId());
AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(GetEntityId());
}
void BoundsTestComponent::Deactivate()
{
AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect();
AzFramework::BoundsRequestBus::Handler::BusDisconnect();
}
AZ::Aabb BoundsTestComponent::GetWorldBounds()
{
AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(worldFromLocal, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
return GetLocalBounds().GetTransformedAabb(worldFromLocal);
}
AZ::Aabb BoundsTestComponent::GetLocalBounds()
{
return AZ::Aabb::CreateFromMinMax(AZ::Vector3(-0.5f), AZ::Vector3(0.5f));
}
// Fixture to support testing EditorTransformComponentSelection functionality on an Entity selection.
class EditorTransformComponentSelectionFixture : public ToolsApplicationFixture
{
@@ -120,27 +207,52 @@ namespace UnitTest
m_entityIds.push_back(m_entityId1);
}
void ArrangeIndividualRotatedEntitySelection(const AZ::Quaternion& orientation);
AZStd::optional<AZ::Transform> GetManipulatorTransform() const;
void RefreshManipulators(AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::RefreshType refreshType);
void SetTransformMode(AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::Mode transformMode);
void OverrideManipulatorOrientation(const AZ::Quaternion& orientation);
void OverrideManipulatorTranslation(const AZ::Vector3& translation);
public:
AZ::EntityId m_entityId1;
AzToolsFramework::EntityIdList m_entityIds;
};
void EditorTransformComponentSelectionFixture::ArrangeIndividualRotatedEntitySelection(const AZ::Quaternion& orientation)
class EditorTransformComponentSelectionViewportPickingFixture : public ToolsApplicationFixture
{
for (auto entityId : m_entityIds)
public:
void SetUpEditorFixtureImpl() override
{
auto* app = GetApplication();
// register a simple component implementing BoundsRequestBus and EditorComponentSelectionRequestsBus
app->RegisterComponentDescriptor(BoundsTestComponent::CreateDescriptor());
auto createEntityWithBoundsFn = [](const char* entityName)
{
AZ::Entity* entity = nullptr;
AZ::EntityId entityId = CreateDefaultEditorEntity(entityName, &entity);
entity->Deactivate();
entity->CreateComponent<BoundsTestComponent>();
entity->Activate();
return entityId;
};
m_entityId1 = createEntityWithBoundsFn("Entity1");
m_entityId2 = createEntityWithBoundsFn("Entity2");
m_entityId3 = createEntityWithBoundsFn("Entity3");
}
public:
AZ::EntityId m_entityId1;
AZ::EntityId m_entityId2;
AZ::EntityId m_entityId3;
};
void ArrangeIndividualRotatedEntitySelection(const AzToolsFramework::EntityIdList& entityIds, const AZ::Quaternion& orientation)
{
for (auto entityId : entityIds)
{
AZ::TransformBus::Event(entityId, &AZ::TransformBus::Events::SetLocalRotationQuaternion, orientation);
}
}
AZStd::optional<AZ::Transform> EditorTransformComponentSelectionFixture::GetManipulatorTransform() const
AZStd::optional<AZ::Transform> GetManipulatorTransform()
{
using AzToolsFramework::EditorTransformComponentSelectionRequestBus;
@@ -151,8 +263,7 @@ namespace UnitTest
return manipulatorTransform;
}
void EditorTransformComponentSelectionFixture::RefreshManipulators(
AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::RefreshType refreshType)
void RefreshManipulators(const AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::RefreshType refreshType)
{
using AzToolsFramework::EditorTransformComponentSelectionRequestBus;
@@ -160,8 +271,7 @@ namespace UnitTest
AzToolsFramework::GetEntityContextId(), &EditorTransformComponentSelectionRequestBus::Events::RefreshManipulators, refreshType);
}
void EditorTransformComponentSelectionFixture::SetTransformMode(
AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::Mode transformMode)
void SetTransformMode(const AzToolsFramework::EditorTransformComponentSelectionRequestBus::Events::Mode transformMode)
{
using AzToolsFramework::EditorTransformComponentSelectionRequestBus;
@@ -169,7 +279,7 @@ namespace UnitTest
AzToolsFramework::GetEntityContextId(), &EditorTransformComponentSelectionRequestBus::Events::SetTransformMode, transformMode);
}
void EditorTransformComponentSelectionFixture::OverrideManipulatorOrientation(const AZ::Quaternion& orientation)
void OverrideManipulatorOrientation(const AZ::Quaternion& orientation)
{
using AzToolsFramework::EditorTransformComponentSelectionRequestBus;
@@ -178,7 +288,7 @@ namespace UnitTest
orientation);
}
void EditorTransformComponentSelectionFixture::OverrideManipulatorTranslation(const AZ::Vector3& translation)
void OverrideManipulatorTranslation(const AZ::Vector3& translation)
{
using AzToolsFramework::EditorTransformComponentSelectionRequestBus;
@@ -190,7 +300,7 @@ namespace UnitTest
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// EditorTransformComponentSelection Tests
TEST_F(EditorTransformComponentSelectionFixture, Focus_is_not_changed_while_switching_viewport_interaction_request_instance)
TEST_F(EditorTransformComponentSelectionFixture, FocusIsNotChangedWhileSwitchingViewportInteractionRequestInstance)
{
// setup a dummy widget and make it the active window to ensure focus in/out events are fired
auto dummyWidget = AZStd::make_unique<QWidget>();
@@ -239,7 +349,7 @@ namespace UnitTest
// Given
AzToolsFramework::SelectEntity(m_entityId1);
ArrangeIndividualRotatedEntitySelection(AZ::Quaternion::CreateRotationX(AZ::DegToRad(90.0f)));
ArrangeIndividualRotatedEntitySelection(m_entityIds, AZ::Quaternion::CreateRotationX(AZ::DegToRad(90.0f)));
RefreshManipulators(EditorTransformComponentSelectionRequestBus::Events::RefreshType::All);
SetTransformMode(EditorTransformComponentSelectionRequestBus::Events::Mode::Rotation);
@@ -286,7 +396,7 @@ namespace UnitTest
AzToolsFramework::SelectEntity(m_entityId1);
const AZ::Quaternion initialEntityOrientation = AZ::Quaternion::CreateRotationX(AZ::DegToRad(90.0f));
ArrangeIndividualRotatedEntitySelection(initialEntityOrientation);
ArrangeIndividualRotatedEntitySelection(m_entityIds, initialEntityOrientation);
// assign new orientation to manipulator which does not match entity orientation
OverrideManipulatorOrientation(AZ::Quaternion::CreateRotationZ(AZ::DegToRad(90.0f)));
@@ -478,6 +588,227 @@ namespace UnitTest
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
}
// fixture for use with the indirect manipulator test framework
using EditorTransformComponentSelectionViewportPickingManipulatorTestFixture =
IndirectCallManipulatorViewportInteractionFixtureMixin<EditorTransformComponentSelectionViewportPickingFixture>;
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, SingleClickWithNoSelectionWillSelectEntity)
{
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)));
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);
// click the entity in the viewport
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(initialPositionScreen)->MouseLButtonDown()->MouseLButtonUp();
// entity is selected
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_THAT(selectedEntitiesAfter.size(), Eq(1));
EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId1));
}
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, SingleClickOffEntityWithSelectionWillNotDeselectEntity)
{
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)));
// 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
const auto clickOffPositionScreen = AzFramework::WorldToScreen(clickOffPositionWorld, m_cameraState);
// click the empty space in the viewport
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(clickOffPositionScreen)->MouseLButtonDown()->MouseLButtonUp();
// entity was not deselected
using ::testing::Eq;
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_THAT(selectedEntitiesAfter.size(), Eq(1));
EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId1));
}
TEST_F(
EditorTransformComponentSelectionViewportPickingManipulatorTestFixture,
SingleClickOnNewEntityWithSelectionWillNotChangeSelectedEntity)
{
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)));
AzToolsFramework::SelectEntity(m_entityId1);
// calculate the position in screen space of the second entity
const auto initialPositionScreenSecondEntity =
AzFramework::WorldToScreen(initialTransformWorldSecondEntity.GetTranslation(), m_cameraState);
// click the entity in the viewport
m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(initialPositionScreenSecondEntity)
->MouseLButtonDown()
->MouseLButtonUp();
// entity selection was not changed
using ::testing::Eq;
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_THAT(selectedEntitiesAfter.size(), Eq(1));
EXPECT_THAT(selectedEntitiesAfter.front(), Eq(m_entityId1));
}
TEST_F(
EditorTransformComponentSelectionViewportPickingManipulatorTestFixture,
CtrlSingleClickOnNewEntityWithSelectionWillAppendSelectedEntityToSelection)
{
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)));
AzToolsFramework::SelectEntity(m_entityId1);
// calculate the position in screen space of the second entity
const auto initialPositionScreenSecondEntity =
AzFramework::WorldToScreen(initialTransformWorldSecondEntity.GetTranslation(), m_cameraState);
// click the entity in the viewport
m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(initialPositionScreenSecondEntity)
->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control)
->MouseLButtonDown()
->MouseLButtonUp();
// entity selection was changed (one entity selected to two)
using ::testing::UnorderedElementsAre;
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1, m_entityId2));
}
TEST_F(
EditorTransformComponentSelectionViewportPickingManipulatorTestFixture,
CtrlSingleClickOnEntityInSelectionWillRemoveEntityFromSelection)
{
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)));
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);
// click the entity in the viewport
m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(initialPositionScreenSecondEntity)
->KeyboardModifierDown(AzToolsFramework::ViewportInteraction::KeyboardModifier::Control)
->MouseLButtonDown()
->MouseLButtonUp();
// entity selection was changed (entity2 was deselected)
using ::testing::UnorderedElementsAre;
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1));
}
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, DISABLED_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)));
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);
// perform a box select in the viewport
m_actionDispatcher->CameraState(m_cameraState)
->MousePosition(beginningPositionWorldBoxSelectStart)
->MouseLButtonDown()
->MousePosition(middlePositionWorldBoxSelectStart)
->MousePosition(endingPositionWorldBoxSelectStart)
->MouseLButtonUp();
// entities are selected
using ::testing::UnorderedElementsAre;
auto selectedEntitiesAfter = SelectedEntities();
EXPECT_THAT(selectedEntitiesAfter, UnorderedElementsAre(m_entityId1, m_entityId2, m_entityId3));
}
using EditorTransformComponentSelectionManipulatorTestFixture =
IndirectCallManipulatorViewportInteractionFixtureMixin<EditorTransformComponentSelectionFixture>;