Initial improvements to fix viewport icon selection and draw order (#6284)

* wip fixes for entity viewport icons displaying in the correct order and handling selection correctly

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* add additional comment about z value

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* move manual sorting and some small tidy-up

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* update comment

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* updates following initial round of PR feedback

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* additional changes to support tests for entity icon intersection

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* add support to enable/disable icons separately from helpers

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* final tests added and small tidy-up to display EntityId correctly

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* update some manipulator test framework calls after utility functions were moved

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* fix for implicit cast

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* move icon scale values to AZ_CVARS

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* fix failing tests caught in AR and update some naming conventions for tests

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* update naming convention for members of ProjectedViewportRay

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* update other references to ProjectedViewportRay

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* update more references to ProjectedViewportRay change

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>

* update menus for python tests

Signed-off-by: Tom Hulton-Harrop <82228511+hultonha@users.noreply.github.com>
monroegm-disable-blank-issue-2
Tom Hulton-Harrop 4 years ago committed by GitHub
parent df8326a1b0
commit d065eb9498
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -40,11 +40,12 @@ def Menus_EditMenuOptions_Work():
("Toggle Pivot Location",), ("Toggle Pivot Location",),
("Reset Entity Transform",), ("Reset Entity Transform",),
("Reset Manipulator",), ("Reset Manipulator",),
("Reset Transform (Local)",),
("Reset Transform (World)",),
("Hide Selection",), ("Hide Selection",),
("Show All",), ("Show All",),
("Modify", "Snap", "Snap angle"), ("Lock Selection",),
("Unlock All Entities",),
("Modify", "Snap", "Angle snapping"),
("Modify", "Snap", "Grid snapping"),
("Modify", "Transform Mode", "Move"), ("Modify", "Transform Mode", "Move"),
("Modify", "Transform Mode", "Rotate"), ("Modify", "Transform Mode", "Rotate"),
("Modify", "Transform Mode", "Scale"), ("Modify", "Transform Mode", "Scale"),

@ -39,7 +39,8 @@ def Menus_ViewMenuOptions_Work():
("Viewport", "Go to Location"), ("Viewport", "Go to Location"),
("Viewport", "Remember Location"), ("Viewport", "Remember Location"),
("Viewport", "Switch Camera"), ("Viewport", "Switch Camera"),
("Viewport", "Show/Hide Helpers"), ("Viewport", "Show Helpers"),
("Viewport", "Show Icons"),
("Refresh Style",), ("Refresh Style",),
] ]

@ -538,6 +538,7 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe
auto snapMenu = modifyMenu.AddMenu(tr("Snap")); auto snapMenu = modifyMenu.AddMenu(tr("Snap"));
snapMenu.AddAction(AzToolsFramework::SnapAngle); snapMenu.AddAction(AzToolsFramework::SnapAngle);
snapMenu.AddAction(AzToolsFramework::SnapToGrid);
auto transformModeMenu = modifyMenu.AddMenu(tr("Transform Mode")); auto transformModeMenu = modifyMenu.AddMenu(tr("Transform Mode"));
transformModeMenu.AddAction(AzToolsFramework::EditModeMove); transformModeMenu.AddAction(AzToolsFramework::EditModeMove);
@ -723,7 +724,8 @@ QMenu* LevelEditorMenuHandler::CreateViewMenu()
// MISSING AVIRECORDER // MISSING AVIRECORDER
viewportViewsMenuWrapper.AddSeparator(); viewportViewsMenuWrapper.AddSeparator();
viewportViewsMenuWrapper.AddAction(ID_DISPLAY_SHOWHELPERS); viewportViewsMenuWrapper.AddAction(AzToolsFramework::Helpers);
viewportViewsMenuWrapper.AddAction(AzToolsFramework::Icons);
// Refresh Style // Refresh Style
viewMenu.AddAction(ID_SKINS_REFRESH); viewMenu.AddAction(ID_SKINS_REFRESH);

@ -445,7 +445,6 @@ void CCryEditApp::RegisterActionHandlers()
ON_COMMAND(ID_OPEN_ASSET_BROWSER, OnOpenAssetBrowserView) ON_COMMAND(ID_OPEN_ASSET_BROWSER, OnOpenAssetBrowserView)
ON_COMMAND(ID_OPEN_AUDIO_CONTROLS_BROWSER, OnOpenAudioControlsEditor) ON_COMMAND(ID_OPEN_AUDIO_CONTROLS_BROWSER, OnOpenAudioControlsEditor)
ON_COMMAND(ID_DISPLAY_SHOWHELPERS, OnShowHelpers)
ON_COMMAND(ID_OPEN_TRACKVIEW, OnOpenTrackView) ON_COMMAND(ID_OPEN_TRACKVIEW, OnOpenTrackView)
ON_COMMAND(ID_OPEN_UICANVASEDITOR, OnOpenUICanvasEditor) ON_COMMAND(ID_OPEN_UICANVASEDITOR, OnOpenUICanvasEditor)
@ -2617,12 +2616,6 @@ void CCryEditApp::OnUpdateSelected(QAction* action)
action->setEnabled(!GetIEditor()->GetSelection()->IsEmpty()); action->setEnabled(!GetIEditor()->GetSelection()->IsEmpty());
} }
void CCryEditApp::OnShowHelpers()
{
GetIEditor()->GetDisplaySettings()->DisplayHelpers(!GetIEditor()->GetDisplaySettings()->IsDisplayHelpers());
GetIEditor()->Notify(eNotify_OnDisplayRenderUpdate);
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void CCryEditApp::OnEditLevelData() void CCryEditApp::OnEditLevelData()
{ {

@ -237,7 +237,6 @@ public:
void OnSyncPlayerUpdate(QAction* action); void OnSyncPlayerUpdate(QAction* action);
void OnResourcesReduceworkingset(); void OnResourcesReduceworkingset();
void OnDummyCommand() {}; void OnDummyCommand() {};
void OnShowHelpers();
void OnFileSave(); void OnFileSave();
void OnUpdateDocumentReady(QAction* action); void OnUpdateDocumentReady(QAction* action);
void OnUpdateFileOpen(QAction* action); void OnUpdateFileOpen(QAction* action);

@ -68,8 +68,6 @@ void CDisplaySettings::SetObjectHideMask(int hideMask)
m_objectHideMask = hideMask; m_objectHideMask = hideMask;
gSettings.objectHideMask = m_objectHideMask; gSettings.objectHideMask = m_objectHideMask;
GetIEditor()->Notify(eNotify_OnDisplayRenderUpdate);
}; };
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

@ -46,6 +46,7 @@
#include <AzToolsFramework/API/EditorCameraBus.h> #include <AzToolsFramework/API/EditorCameraBus.h>
#include <AzToolsFramework/API/ViewportEditorModeTrackerInterface.h> #include <AzToolsFramework/API/ViewportEditorModeTrackerInterface.h>
#include <AzToolsFramework/Manipulators/ManipulatorManager.h> #include <AzToolsFramework/Manipulators/ManipulatorManager.h>
#include <AzToolsFramework/Viewport/ViewportSettings.h>
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h> #include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
#include <AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h> #include <AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h>
@ -1621,14 +1622,14 @@ Vec3 EditorViewportWidget::ViewToWorld(
auto ray = m_renderViewport->ViewportScreenToWorldRay(AzToolsFramework::ViewportInteraction::ScreenPointFromQPoint(vp)); auto ray = m_renderViewport->ViewportScreenToWorldRay(AzToolsFramework::ViewportInteraction::ScreenPointFromQPoint(vp));
const float maxDistance = 10000.f; const float maxDistance = 10000.f;
Vec3 v = AZVec3ToLYVec3(ray.direction) * maxDistance; Vec3 v = AZVec3ToLYVec3(ray.m_direction) * maxDistance;
if (!_finite(v.x) || !_finite(v.y) || !_finite(v.z)) if (!_finite(v.x) || !_finite(v.y) || !_finite(v.z))
{ {
return Vec3(0, 0, 0); return Vec3(0, 0, 0);
} }
Vec3 colp = AZVec3ToLYVec3(ray.origin) + 0.002f * v; Vec3 colp = AZVec3ToLYVec3(ray.m_origin) + 0.002f * v;
return colp; return colp;
} }
@ -2420,6 +2421,16 @@ AZ::Vector3 EditorViewportSettings::DefaultEditorCameraPosition() const
return SandboxEditor::CameraDefaultEditorPosition(); return SandboxEditor::CameraDefaultEditorPosition();
} }
bool EditorViewportSettings::IconsVisible() const
{
return AzToolsFramework::IconsVisible();
}
bool EditorViewportSettings::HelpersVisible() const
{
return AzToolsFramework::HelpersVisible();
}
AZ_CVAR_EXTERNED(bool, ed_previewGameInFullscreen_once); AZ_CVAR_EXTERNED(bool, ed_previewGameInFullscreen_once);
bool EditorViewportWidget::ShouldPreviewFullscreen() const bool EditorViewportWidget::ShouldPreviewFullscreen() const

@ -79,6 +79,8 @@ struct EditorViewportSettings : public AzToolsFramework::ViewportInteraction::Vi
float ManipulatorCircleBoundWidth() const override; float ManipulatorCircleBoundWidth() const override;
bool StickySelectEnabled() const override; bool StickySelectEnabled() const override;
AZ::Vector3 DefaultEditorCameraPosition() const override; AZ::Vector3 DefaultEditorCameraPosition() const override;
bool IconsVisible() const override;
bool HelpersVisible() const override;
}; };
// EditorViewportWidget window // EditorViewportWidget window

@ -168,8 +168,6 @@ enum EEditorNotifyEvent
eNotify_OnVegetationObjectSelection, // When vegetation objects selection change. eNotify_OnVegetationObjectSelection, // When vegetation objects selection change.
eNotify_OnVegetationPanelUpdate, // When vegetation objects selection change. eNotify_OnVegetationPanelUpdate, // When vegetation objects selection change.
eNotify_OnDisplayRenderUpdate, // Sent when editor finish terrain texture generation.
eNotify_OnDataBaseUpdate, // DataBase Library was modified. eNotify_OnDataBaseUpdate, // DataBase Library was modified.
eNotify_OnLayerImportBegin, //layer import was started eNotify_OnLayerImportBegin, //layer import was started

@ -47,6 +47,7 @@ AZ_POP_DISABLE_WARNING
#include <AzToolsFramework/API/EditorAnimationSystemRequestBus.h> #include <AzToolsFramework/API/EditorAnimationSystemRequestBus.h>
#include <AzToolsFramework/SourceControl/QtSourceControlNotificationHandler.h> #include <AzToolsFramework/SourceControl/QtSourceControlNotificationHandler.h>
#include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h> #include <AzToolsFramework/PythonTerminal/ScriptTermDialog.h>
#include <AzToolsFramework/Viewport/ViewportSettings.h>
#include <AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h> #include <AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h>
// AzQtComponents // AzQtComponents
@ -445,11 +446,11 @@ void MainWindow::Initialize()
{ {
m_viewPaneManager->SetMainWindow(m_viewPaneHost, &m_settings, /*unused*/ QByteArray()); m_viewPaneManager->SetMainWindow(m_viewPaneHost, &m_settings, /*unused*/ QByteArray());
InitActions();
RegisterStdViewClasses(); RegisterStdViewClasses();
InitCentralWidget(); InitCentralWidget();
InitActions();
// load toolbars ("shelves") and macros // load toolbars ("shelves") and macros
GetIEditor()->GetToolBoxManager()->Load(m_actionManager); GetIEditor()->GetToolBoxManager()->Load(m_actionManager);
@ -798,27 +799,40 @@ void MainWindow::InitActions()
EditorTransformComponentSelectionRequests::Mode::Scale); EditorTransformComponentSelectionRequests::Mode::Scale);
}); });
am->AddAction(AzToolsFramework::SnapToGrid, tr("Snap to grid")) am->AddAction(AzToolsFramework::SnapToGrid, tr("Grid snapping"))
.SetIcon(Style::icon("Grid")) .SetIcon(Style::icon("Grid"))
.SetStatusTip(tr("Toggle grid snapping"))
.SetShortcut(tr("G")) .SetShortcut(tr("G"))
.SetToolTip(tr("Snap to grid (G)"))
.SetStatusTip(tr("Toggles snap to grid"))
.SetCheckable(true) .SetCheckable(true)
.RegisterUpdateCallback([](QAction* action) { .RegisterUpdateCallback(
[](QAction* action)
{
Q_ASSERT(action->isCheckable()); Q_ASSERT(action->isCheckable());
action->setChecked(SandboxEditor::GridSnappingEnabled()); action->setChecked(SandboxEditor::GridSnappingEnabled());
}) })
.Connect(&QAction::triggered, []() { SandboxEditor::SetGridSnapping(!SandboxEditor::GridSnappingEnabled()); }); .Connect(
&QAction::triggered,
[]
{
SandboxEditor::SetGridSnapping(!SandboxEditor::GridSnappingEnabled());
});
am->AddAction(AzToolsFramework::SnapAngle, tr("Snap angle")) am->AddAction(AzToolsFramework::SnapAngle, tr("Angle snapping"))
.SetIcon(Style::icon("Angle")) .SetIcon(Style::icon("Angle"))
.SetStatusTip(tr("Snap angle")) .SetStatusTip(tr("Toggle angle snapping"))
.SetCheckable(true) .SetCheckable(true)
.RegisterUpdateCallback([](QAction* action) { .RegisterUpdateCallback(
[](QAction* action)
{
Q_ASSERT(action->isCheckable()); Q_ASSERT(action->isCheckable());
action->setChecked(SandboxEditor::AngleSnappingEnabled()); action->setChecked(SandboxEditor::AngleSnappingEnabled());
}) })
.Connect(&QAction::triggered, []() { SandboxEditor::SetAngleSnapping(!SandboxEditor::AngleSnappingEnabled()); }); .Connect(
&QAction::triggered,
[]
{
SandboxEditor::SetAngleSnapping(!SandboxEditor::AngleSnappingEnabled());
});
// Display actions // Display actions
am->AddAction(ID_SWITCHCAMERA_DEFAULTCAMERA, tr("Default Camera")).SetCheckable(true) am->AddAction(ID_SWITCHCAMERA_DEFAULTCAMERA, tr("Default Camera")).SetCheckable(true)
@ -918,9 +932,41 @@ void MainWindow::InitActions()
.SetStatusTip(tr("Cycle 2D Viewport")) .SetStatusTip(tr("Cycle 2D Viewport"))
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateNonGameMode); .RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateNonGameMode);
#endif #endif
am->AddAction(ID_DISPLAY_SHOWHELPERS, tr("Show/Hide Helpers")) am->AddAction(AzToolsFramework::Helpers, tr("Show Helpers"))
.SetShortcut(tr("Shift+Space")) .SetShortcut(tr("Shift+Space"))
.SetToolTip(tr("Show/Hide Helpers (Shift+Space)")); .SetToolTip(tr("Show/Hide Helpers (Shift+Space)"))
.SetCheckable(true)
.RegisterUpdateCallback(
[](QAction* action)
{
Q_ASSERT(action->isCheckable());
action->setChecked(AzToolsFramework::HelpersVisible());
})
.Connect(
&QAction::triggered,
[]()
{
AzToolsFramework::SetHelpersVisible(!AzToolsFramework::HelpersVisible());
AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Broadcast(
&AzToolsFramework::ViewportInteraction::ViewportSettingNotifications::OnDrawHelpersChanged,
AzToolsFramework::HelpersVisible());
});
am->AddAction(AzToolsFramework::Icons, tr("Show Icons"))
.SetShortcut(tr("Ctrl+Space"))
.SetToolTip(tr("Show/Hide Icons (Ctrl+Space)"))
.SetCheckable(true)
.RegisterUpdateCallback(
[](QAction* action)
{
Q_ASSERT(action->isCheckable());
action->setChecked(AzToolsFramework::IconsVisible());
})
.Connect(
&QAction::triggered,
[]()
{
AzToolsFramework::SetIconsVisible(!AzToolsFramework::IconsVisible());
});
// Audio actions // Audio actions
am->AddAction(ID_SOUND_STOPALLSOUNDS, tr("Stop All Sounds")) am->AddAction(ID_SOUND_STOPALLSOUNDS, tr("Stop All Sounds"))

@ -1986,8 +1986,3 @@ void SandboxIntegrationManager::BrowseForAssets(AssetSelectionModel& selection)
{ {
AssetBrowserComponentRequestBus::Broadcast(&AssetBrowserComponentRequests::PickAssets, selection, GetMainWindow()); AssetBrowserComponentRequestBus::Broadcast(&AssetBrowserComponentRequests::PickAssets, selection, GetMainWindow());
} }
bool SandboxIntegrationManager::DisplayHelpersVisible()
{
return GetIEditor()->GetDisplaySettings()->IsDisplayHelpers();
}

@ -165,7 +165,6 @@ private:
void InstantiateSliceFromAssetId(const AZ::Data::AssetId& assetId) override; void InstantiateSliceFromAssetId(const AZ::Data::AssetId& assetId) override;
void ClearRedoStack() override; void ClearRedoStack() override;
int GetIconTextureIdFromEntityIconPath(const AZStd::string& entityIconPath) override; int GetIconTextureIdFromEntityIconPath(const AZStd::string& entityIconPath) override;
bool DisplayHelpersVisible() override;
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

@ -191,7 +191,6 @@
#define ID_BRUSH_CSGSUBSTRUCT 33837 #define ID_BRUSH_CSGSUBSTRUCT 33837
#define ID_MATERIAL_PICKTOOL 33842 #define ID_MATERIAL_PICKTOOL 33842
#define ID_MODIFY_AIPOINT_PICKIMPASSLINK 33865 #define ID_MODIFY_AIPOINT_PICKIMPASSLINK 33865
#define ID_DISPLAY_SHOWHELPERS 33871
#define ID_FILE_EXPORTSELECTION 33875 #define ID_FILE_EXPORTSELECTION 33875
#define ID_EDIT_PASTE_WITH_LINKS 33893 #define ID_EDIT_PASTE_WITH_LINKS 33893
#define ID_FILE_EXPORT_TERRAINAREA 33904 #define ID_FILE_EXPORT_TERRAINAREA 33904

@ -129,8 +129,8 @@ namespace SandboxEditor
ViewportInteractionRequestBus::EventResult( ViewportInteractionRequestBus::EventResult(
ray, GetViewportId(), &ViewportInteractionRequestBus::Events::ViewportScreenToWorldRay, screenPoint); ray, GetViewportId(), &ViewportInteractionRequestBus::Events::ViewportScreenToWorldRay, screenPoint);
m_mouseInteraction.m_mousePick.m_rayOrigin = ray.origin; m_mouseInteraction.m_mousePick.m_rayOrigin = ray.m_origin;
m_mouseInteraction.m_mousePick.m_rayDirection = ray.direction; m_mouseInteraction.m_mousePick.m_rayDirection = ray.m_direction;
m_mouseInteraction.m_mousePick.m_screenCoordinates = screenPoint; m_mouseInteraction.m_mousePick.m_screenCoordinates = screenPoint;
} }

@ -6,7 +6,6 @@
* *
*/ */
// Description : CViewportTitleDlg implementation file // Description : CViewportTitleDlg implementation file
#if !defined(Q_MOC_RUN) #if !defined(Q_MOC_RUN)
@ -42,6 +41,8 @@
#include <AzCore/std/algorithm.h> #include <AzCore/std/algorithm.h>
#include <AzFramework/API/ApplicationAPI.h> #include <AzFramework/API/ApplicationAPI.h>
#include <AzToolsFramework/Viewport/ViewportMessages.h> #include <AzToolsFramework/Viewport/ViewportMessages.h>
#include <AzToolsFramework/Viewport/ViewportSettings.h>
#include <AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h>
#include <LmbrCentral/Audio/AudioSystemComponentBus.h> #include <LmbrCentral/Audio/AudioSystemComponentBus.h>
@ -52,28 +53,6 @@ AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
// CViewportTitleDlg dialog // CViewportTitleDlg dialog
inline namespace Helpers
{
void ToggleHelpers()
{
const bool newValue = !GetIEditor()->GetDisplaySettings()->IsDisplayHelpers();
GetIEditor()->GetDisplaySettings()->DisplayHelpers(newValue);
GetIEditor()->Notify(eNotify_OnDisplayRenderUpdate);
if (newValue == false)
{
GetIEditor()->GetObjectManager()->SendEvent(EVENT_HIDE_HELPER);
}
AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Broadcast(
&AzToolsFramework::ViewportInteraction::ViewportSettingNotifications::OnDrawHelpersChanged, newValue);
}
bool IsHelpersShown()
{
return GetIEditor()->GetDisplaySettings()->IsDisplayHelpers();
}
}
namespace namespace
{ {
class CViewportTitleDlgDisplayInfoHelper class CViewportTitleDlgDisplayInfoHelper
@ -215,13 +194,65 @@ void CViewportTitleDlg::SetupViewportInformationMenu()
m_ui->m_debugInformationMenu->setMenu(GetViewportInformationMenu()); m_ui->m_debugInformationMenu->setMenu(GetViewportInformationMenu());
connect(m_ui->m_debugInformationMenu, &QToolButton::clicked, this, &CViewportTitleDlg::OnToggleDisplayInfo); connect(m_ui->m_debugInformationMenu, &QToolButton::clicked, this, &CViewportTitleDlg::OnToggleDisplayInfo);
m_ui->m_debugInformationMenu->setPopupMode(QToolButton::MenuButtonPopup); m_ui->m_debugInformationMenu->setPopupMode(QToolButton::MenuButtonPopup);
} }
void CViewportTitleDlg::SetupHelpersButton() void CViewportTitleDlg::SetupHelpersButton()
{ {
connect(m_ui->m_helpers, &QToolButton::clicked, this, &CViewportTitleDlg::OnToggleHelpers); if (m_helpersMenu == nullptr)
m_ui->m_helpers->setChecked(Helpers::IsHelpersShown()); {
m_helpersMenu = new QMenu("Helpers State", this);
auto helperAction = MainWindow::instance()->GetActionManager()->GetAction(AzToolsFramework::Helpers);
connect(
helperAction, &QAction::triggered, this,
[this]
{
m_ui->m_helpers->setChecked(AzToolsFramework::HelpersVisible() || AzToolsFramework::IconsVisible());
});
auto iconAction = MainWindow::instance()->GetActionManager()->GetAction(AzToolsFramework::Icons);
connect(
iconAction, &QAction::triggered, this,
[this]
{
m_ui->m_helpers->setChecked(AzToolsFramework::HelpersVisible() || AzToolsFramework::IconsVisible());
});
m_helpersAction = new QAction(tr("Helpers"), m_helpersMenu);
m_helpersAction->setCheckable(true);
connect(
m_helpersAction, &QAction::triggered, this,
[helperAction]
{
helperAction->trigger();
});
m_iconsAction = new QAction(tr("Icons"), m_helpersMenu);
m_iconsAction->setCheckable(true);
connect(
m_iconsAction, &QAction::triggered, this,
[iconAction]
{
iconAction->trigger();
});
m_helpersMenu->addAction(m_helpersAction);
m_helpersMenu->addAction(m_iconsAction);
connect(
m_helpersMenu, &QMenu::aboutToShow, this,
[this]
{
m_helpersAction->setChecked(AzToolsFramework::HelpersVisible());
m_iconsAction->setChecked(AzToolsFramework::IconsVisible());
});
m_ui->m_helpers->setCheckable(true);
m_ui->m_helpers->setMenu(m_helpersMenu);
m_ui->m_helpers->setPopupMode(QToolButton::InstantPopup);
}
m_ui->m_helpers->setChecked(AzToolsFramework::HelpersVisible() || AzToolsFramework::IconsVisible());
} }
void CViewportTitleDlg::SetupOverflowMenu() void CViewportTitleDlg::SetupOverflowMenu()
@ -279,16 +310,21 @@ void CViewportTitleDlg::SetupOverflowMenu()
UpdateMuteActionText(); UpdateMuteActionText();
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void CViewportTitleDlg::SetViewPane(CLayoutViewPane* pViewPane) void CViewportTitleDlg::SetViewPane(CLayoutViewPane* pViewPane)
{ {
if (m_pViewPane) if (m_pViewPane)
{
m_pViewPane->disconnect(this); m_pViewPane->disconnect(this);
}
m_pViewPane = pViewPane; m_pViewPane = pViewPane;
if (m_pViewPane) if (m_pViewPane)
{
connect(this, &QWidget::customContextMenuRequested, m_pViewPane, &CLayoutViewPane::ShowTitleMenu); connect(this, &QWidget::customContextMenuRequested, m_pViewPane, &CLayoutViewPane::ShowTitleMenu);
} }
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void CViewportTitleDlg::OnInitDialog() void CViewportTitleDlg::OnInitDialog()
@ -318,7 +354,6 @@ void CViewportTitleDlg::OnInitDialog()
m_ui->m_prefabFocusPath->hide(); m_ui->m_prefabFocusPath->hide();
m_ui->m_prefabFocusBackButton->hide(); m_ui->m_prefabFocusBackButton->hide();
} }
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@ -336,13 +371,6 @@ void CViewportTitleDlg::OnMaximize()
} }
} }
//////////////////////////////////////////////////////////////////////////
void CViewportTitleDlg::OnToggleHelpers()
{
Helpers::ToggleHelpers();
m_ui->m_helpers->setChecked(Helpers::IsHelpersShown());
}
void CViewportTitleDlg::SetNoViewportInfo() void CViewportTitleDlg::SetNoViewportInfo()
{ {
AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Broadcast( AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Broadcast(
@ -367,7 +395,6 @@ void CViewportTitleDlg::SetCompactViewportInfo()
&AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::SetDisplayState, AZ::AtomBridge::ViewportInfoDisplayState::CompactInfo); &AZ::AtomBridge::AtomViewportInfoDisplayRequestBus::Events::SetDisplayState, AZ::AtomBridge::ViewportInfoDisplayState::CompactInfo);
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void CViewportTitleDlg::UpdateDisplayInfo() void CViewportTitleDlg::UpdateDisplayInfo()
{ {
@ -783,9 +810,6 @@ void CViewportTitleDlg::OnEditorNotifyEvent(EEditorNotifyEvent event)
{ {
switch (event) switch (event)
{ {
case eNotify_OnDisplayRenderUpdate:
m_ui->m_helpers->setChecked(Helpers::IsHelpersShown());
break;
case eNotify_OnBeginGameMode: case eNotify_OnBeginGameMode:
case eNotify_OnEndGameMode: case eNotify_OnEndGameMode:
UpdateMuteActionText(); UpdateMuteActionText();
@ -1001,20 +1025,14 @@ namespace
{ {
void PyToggleHelpers() void PyToggleHelpers()
{ {
GetIEditor()->GetDisplaySettings()->DisplayHelpers(!GetIEditor()->GetDisplaySettings()->IsDisplayHelpers()); AzToolsFramework::SetHelpersVisible(!AzToolsFramework::HelpersVisible());
GetIEditor()->Notify(eNotify_OnDisplayRenderUpdate);
if (GetIEditor()->GetDisplaySettings()->IsDisplayHelpers() == false)
{
GetIEditor()->GetObjectManager()->SendEvent(EVENT_HIDE_HELPER);
}
} }
bool PyIsHelpersShown() bool PyIsHelpersShown()
{ {
return GetIEditor()->GetDisplaySettings()->IsDisplayHelpers(); return AzToolsFramework::HelpersVisible();
}
} }
} // namespace
namespace AzToolsFramework namespace AzToolsFramework
{ {
@ -1029,11 +1047,12 @@ namespace AzToolsFramework
->Attribute(AZ::Script::Attributes::Category, "Legacy/Editor") ->Attribute(AZ::Script::Attributes::Category, "Legacy/Editor")
->Attribute(AZ::Script::Attributes::Module, "legacy.general"); ->Attribute(AZ::Script::Attributes::Module, "legacy.general");
}; };
addLegacyGeneral(behaviorContext->Method("toggle_helpers", PyToggleHelpers, nullptr, "Toggles the display of helpers.")); addLegacyGeneral(behaviorContext->Method("toggle_helpers", PyToggleHelpers, nullptr, "Toggles the display of helpers."));
addLegacyGeneral(behaviorContext->Method("is_helpers_shown", PyIsHelpersShown, nullptr, "Gets the display state of helpers.")); addLegacyGeneral(behaviorContext->Method("is_helpers_shown", PyIsHelpersShown, nullptr, "Gets the display state of helpers."));
} }
} }
} } // namespace AzToolsFramework
#include "ViewportTitleDlg.moc" #include "ViewportTitleDlg.moc"
#include <moc_ViewportTitleDlg.cpp> #include <moc_ViewportTitleDlg.cpp>

@ -80,7 +80,6 @@ protected:
void OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam) override; void OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam) override;
void OnMaximize(); void OnMaximize();
void OnToggleHelpers();
void UpdateDisplayInfo(); void UpdateDisplayInfo();
void SetupCameraDropdownMenu(); void SetupCameraDropdownMenu();
@ -153,6 +152,9 @@ protected:
QMenu* m_aspectMenu = nullptr; QMenu* m_aspectMenu = nullptr;
QMenu* m_resolutionMenu = nullptr; QMenu* m_resolutionMenu = nullptr;
QMenu* m_viewportInformationMenu = nullptr; QMenu* m_viewportInformationMenu = nullptr;
QMenu* m_helpersMenu = nullptr;
QAction* m_helpersAction = nullptr;
QAction* m_iconsAction = nullptr;
QAction* m_noInformationAction = nullptr; QAction* m_noInformationAction = nullptr;
QAction* m_normalInformationAction = nullptr; QAction* m_normalInformationAction = nullptr;
QAction* m_fullInformationAction = nullptr; QAction* m_fullInformationAction = nullptr;

@ -10,6 +10,7 @@
#include <AzCore/Casting/numeric_cast.h> #include <AzCore/Casting/numeric_cast.h>
#include <AzCore/Math/Vector2.h> #include <AzCore/Math/Vector2.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/RTTI/TypeInfoSimple.h> #include <AzCore/RTTI/TypeInfoSimple.h>
#include <AzCore/base.h> #include <AzCore/base.h>
@ -203,6 +204,12 @@ namespace AzFramework
return AZ::Vector2(aznumeric_cast<float>(screenPoint.m_x), aznumeric_cast<float>(screenPoint.m_y)); return AZ::Vector2(aznumeric_cast<float>(screenPoint.m_x), aznumeric_cast<float>(screenPoint.m_y));
} }
//! Return an AZ::Vector3 from a ScreenPoint (including z/depth value, defaulting to 0.0f).
inline AZ::Vector3 Vector3FromScreenPoint(const ScreenPoint& screenPoint, const float z = 0.0f)
{
return AZ::Vector3(aznumeric_cast<float>(screenPoint.m_x), aznumeric_cast<float>(screenPoint.m_y), z);
}
//! Return an AZ::Vector2 from a ScreenVector. //! Return an AZ::Vector2 from a ScreenVector.
inline AZ::Vector2 Vector2FromScreenVector(const ScreenVector& screenVector) inline AZ::Vector2 Vector2FromScreenVector(const ScreenVector& screenVector)
{ {

@ -26,29 +26,33 @@ namespace AzManipulatorTestFramework
{ {
public: public:
virtual ~ViewportInteractionInterface() = default; virtual ~ViewportInteractionInterface() = default;
//! Return the camera state. //! Returns the camera state.
virtual AzFramework::CameraState GetCameraState() = 0; virtual AzFramework::CameraState GetCameraState() = 0;
//! Set the camera state. //! Sets the camera state.
virtual void SetCameraState(const AzFramework::CameraState& cameraState) = 0; virtual void SetCameraState(const AzFramework::CameraState& cameraState) = 0;
//! Retrieve the debug display. //! Retrieves the debug display.
virtual AzFramework::DebugDisplayRequests& GetDebugDisplay() = 0; virtual AzFramework::DebugDisplayRequests& GetDebugDisplay() = 0;
//! Set if grid snapping is enabled or not. //! Sets if grid snapping is enabled or not.
virtual void SetGridSnapping(bool enabled) = 0; virtual void SetGridSnapping(bool enabled) = 0;
//! Set if angular snapping is enabled or not. //! Sets if angular snapping is enabled or not.
virtual void SetAngularSnapping(bool enabled) = 0; virtual void SetAngularSnapping(bool enabled) = 0;
//! Set the grid size. //! Sets the grid size.
virtual void SetGridSize(float size) = 0; virtual void SetGridSize(float size) = 0;
//! Set the angular step. //! Sets the angular step.
virtual void SetAngularStep(float step) = 0; virtual void SetAngularStep(float step) = 0;
//! Get the viewport id. //! Gets the viewport id.
virtual AzFramework::ViewportId GetViewportId() const = 0; virtual AzFramework::ViewportId GetViewportId() const = 0;
//! Updates the visibility state. //! Updates the visibility state.
//! Updates which entities are currently visible given the current camera state. //! Updates which entities are currently visible given the current camera state.
virtual void UpdateVisibility() = 0; virtual void UpdateVisibility() = 0;
//! Set if sticky select is enabled or not. //! Sets if sticky select is enabled or not.
virtual void SetStickySelect(bool enabled) = 0; virtual void SetStickySelect(bool enabled) = 0;
//! Get default Editor Camera Position. //! Gets default Editor Camera Position.
virtual AZ::Vector3 DefaultEditorCameraPosition() const = 0; virtual AZ::Vector3 DefaultEditorCameraPosition() const = 0;
//! Sets if icons are visible in the viewport.
virtual void SetIconsVisible(bool visible) = 0;
//! Sets if helpers are visible in the viewport.
virtual void SetHelpersVisible(bool visible) = 0;
}; };
//! This interface is used to simulate the manipulator manager while the manipulators are under test. //! This interface is used to simulate the manipulator manager while the manipulators are under test.

@ -26,6 +26,7 @@ namespace UnitTest
using IndirectCallManipulatorViewportInteraction = AzManipulatorTestFramework::IndirectCallManipulatorViewportInteraction; using IndirectCallManipulatorViewportInteraction = AzManipulatorTestFramework::IndirectCallManipulatorViewportInteraction;
using ImmediateModeActionDispatcher = AzManipulatorTestFramework::ImmediateModeActionDispatcher; using ImmediateModeActionDispatcher = AzManipulatorTestFramework::ImmediateModeActionDispatcher;
public:
void SetUpEditorFixtureImpl() override void SetUpEditorFixtureImpl() override
{ {
ToolsApplicationFixtureT::SetUpEditorFixtureImpl(); ToolsApplicationFixtureT::SetUpEditorFixtureImpl();
@ -43,7 +44,6 @@ namespace UnitTest
ToolsApplicationFixtureT::TearDownEditorFixtureImpl(); ToolsApplicationFixtureT::TearDownEditorFixtureImpl();
} }
public:
AzFramework::CameraState m_cameraState; AzFramework::CameraState m_cameraState;
AZStd::unique_ptr<ImmediateModeActionDispatcher> m_actionDispatcher; AZStd::unique_ptr<ImmediateModeActionDispatcher> m_actionDispatcher;
AZStd::unique_ptr<IndirectCallManipulatorViewportInteraction> m_viewportManipulatorInteraction; AZStd::unique_ptr<IndirectCallManipulatorViewportInteraction> m_viewportManipulatorInteraction;

@ -27,29 +27,6 @@ namespace AzManipulatorTestFramework
const AZ::Vector3& position = AZ::Vector3::CreateZero(), const AZ::Vector3& position = AZ::Vector3::CreateZero(),
float radius = 1.0f); float radius = 1.0f);
//! Create a mouse pick from the specified ray and screen point.
AzToolsFramework::ViewportInteraction::MousePick CreateMousePick(
const AZ::Vector3& origin, const AZ::Vector3& direction, const AzFramework::ScreenPoint& screenPoint);
//! Build a mouse pick from the specified mouse position and camera state.
AzToolsFramework::ViewportInteraction::MousePick BuildMousePick(
const AzFramework::ScreenPoint& screenPoint, const AzFramework::CameraState& cameraState);
//! Create a mouse interaction from the specified pick, buttons, interaction id and keyboard modifiers.
AzToolsFramework::ViewportInteraction::MouseInteraction CreateMouseInteraction(
const AzToolsFramework::ViewportInteraction::MousePick& mousePick,
AzToolsFramework::ViewportInteraction::MouseButtons buttons,
AzToolsFramework::ViewportInteraction::InteractionId interactionId,
AzToolsFramework::ViewportInteraction::KeyboardModifiers modifiers);
//! Create a mouse buttons from the specified mouse button.
AzToolsFramework::ViewportInteraction::MouseButtons CreateMouseButtons(AzToolsFramework::ViewportInteraction::MouseButton button);
//! Create a mouse interaction event from the specified interaction and event.
AzToolsFramework::ViewportInteraction::MouseInteractionEvent CreateMouseInteractionEvent(
const AzToolsFramework::ViewportInteraction::MouseInteraction& mouseInteraction,
AzToolsFramework::ViewportInteraction::MouseEvent event);
//! Dispatch a mouse event to the main manipulator manager via a bus call. //! Dispatch a mouse event to the main manipulator manager via a bus call.
void DispatchMouseInteractionEvent(const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& event); void DispatchMouseInteractionEvent(const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& event);

@ -24,9 +24,12 @@ namespace AzManipulatorTestFramework
explicit IndirectCallManipulatorViewportInteraction(AZStd::shared_ptr<AzFramework::DebugDisplayRequests> debugDisplayRequests); explicit IndirectCallManipulatorViewportInteraction(AZStd::shared_ptr<AzFramework::DebugDisplayRequests> debugDisplayRequests);
~IndirectCallManipulatorViewportInteraction(); ~IndirectCallManipulatorViewportInteraction();
// ManipulatorViewportInteractionInterface ... // ManipulatorViewportInteraction overrides ...
const ViewportInteractionInterface& GetViewportInteraction() const override; const ViewportInteractionInterface& GetViewportInteraction() const override;
const ManipulatorManagerInterface& GetManipulatorManager() const override; const ManipulatorManagerInterface& GetManipulatorManager() const override;
// make non-const overloads visible
using ManipulatorViewportInteraction::GetViewportInteraction;
using ManipulatorViewportInteraction::GetManipulatorManager;
private: private:
AZStd::unique_ptr<ViewportInteraction> m_viewportInteraction; AZStd::unique_ptr<ViewportInteraction> m_viewportInteraction;

@ -39,7 +39,8 @@ namespace AzManipulatorTestFramework
AzFramework::ViewportId GetViewportId() const override; AzFramework::ViewportId GetViewportId() const override;
void UpdateVisibility() override; void UpdateVisibility() override;
void SetStickySelect(bool enabled) override; void SetStickySelect(bool enabled) override;
AZ::Vector3 DefaultEditorCameraPosition() const override; void SetIconsVisible(bool visible) override;
void SetHelpersVisible(bool visible) override;
// ViewportInteractionRequestBus overrides ... // ViewportInteractionRequestBus overrides ...
AzFramework::CameraState GetCameraState() override; AzFramework::CameraState GetCameraState() override;
@ -58,6 +59,9 @@ namespace AzManipulatorTestFramework
float ManipulatorLineBoundWidth() const override; float ManipulatorLineBoundWidth() const override;
float ManipulatorCircleBoundWidth() const override; float ManipulatorCircleBoundWidth() const override;
bool StickySelectEnabled() const override; bool StickySelectEnabled() const override;
AZ::Vector3 DefaultEditorCameraPosition() const override;
bool IconsVisible() const override;
bool HelpersVisible() const override;
// EditorEntityViewportInteractionRequestBus overrides ... // EditorEntityViewportInteractionRequestBus overrides ...
void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntities) override; void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntities) override;
@ -68,10 +72,12 @@ namespace AzManipulatorTestFramework
AzFramework::EntityVisibilityQuery m_entityVisibilityQuery; AzFramework::EntityVisibilityQuery m_entityVisibilityQuery;
AZStd::shared_ptr<AzFramework::DebugDisplayRequests> m_debugDisplayRequests; AZStd::shared_ptr<AzFramework::DebugDisplayRequests> m_debugDisplayRequests;
AzFramework::CameraState m_cameraState; AzFramework::CameraState m_cameraState;
float m_gridSize = 1.0f;
float m_angularStep = 0.0f;
bool m_gridSnapping = false; bool m_gridSnapping = false;
bool m_angularSnapping = false; bool m_angularSnapping = false;
bool m_stickySelect = true; bool m_stickySelect = true;
float m_gridSize = 1.0f; bool m_iconsVisible = true;
float m_angularStep = 0.0f; bool m_helpersVisible = true;
}; };
} // namespace AzManipulatorTestFramework } // namespace AzManipulatorTestFramework

@ -82,49 +82,6 @@ namespace AzManipulatorTestFramework
return manipulator; return manipulator;
} }
AzToolsFramework::ViewportInteraction::MousePick CreateMousePick(
const AZ::Vector3& origin, const AZ::Vector3& direction, const AzFramework::ScreenPoint& screenPoint)
{
return { origin, direction, screenPoint };
}
AzToolsFramework::ViewportInteraction::MousePick BuildMousePick(
const AzFramework::ScreenPoint& screenPoint, const AzFramework::CameraState& cameraState)
{
const auto nearPlaneWorldPosition = AzFramework::ScreenToWorld(screenPoint, cameraState);
AzToolsFramework::ViewportInteraction::MousePick mousePick;
mousePick.m_screenCoordinates = screenPoint;
mousePick.m_rayOrigin = nearPlaneWorldPosition;
mousePick.m_rayDirection = (nearPlaneWorldPosition - cameraState.m_position).GetNormalized();
return mousePick;
}
MouseInteraction CreateMouseInteraction(
const MousePick& mousePick, MouseButtons buttons, InteractionId interactionId, KeyboardModifiers modifiers)
{
AzToolsFramework::ViewportInteraction::MouseInteraction interaction;
interaction.m_mousePick = mousePick;
interaction.m_mouseButtons = buttons;
interaction.m_interactionId = interactionId;
interaction.m_keyboardModifiers = modifiers;
return interaction;
}
MouseButtons CreateMouseButtons(MouseButton button)
{
MouseButtons buttons;
buttons.m_mouseButtons = static_cast<AZ::u32>(button);
return buttons;
}
MouseInteractionEvent CreateMouseInteractionEvent(const MouseInteraction& mouseInteraction, MouseEvent event)
{
return MouseInteractionEvent(mouseInteraction, event, /*captured=*/false);
}
void DispatchMouseInteractionEvent(const MouseInteractionEvent& event) void DispatchMouseInteractionEvent(const MouseInteractionEvent& event)
{ {
AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Event( AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Event(

@ -120,7 +120,8 @@ namespace AzManipulatorTestFramework
void ImmediateModeActionDispatcher::MousePositionImpl(const AzFramework::ScreenPoint& position) void ImmediateModeActionDispatcher::MousePositionImpl(const AzFramework::ScreenPoint& position)
{ {
const auto cameraState = m_manipulatorViewportInteraction.GetViewportInteraction().GetCameraState(); const auto cameraState = m_manipulatorViewportInteraction.GetViewportInteraction().GetCameraState();
GetMouseInteractionEvent()->m_mouseInteraction.m_mousePick = BuildMousePick(position, cameraState); GetMouseInteractionEvent()->m_mouseInteraction.m_mousePick =
AzToolsFramework::ViewportInteraction::BuildMousePick(cameraState, position);
GetMouseInteractionEvent()->m_mouseEvent = AzToolsFramework::ViewportInteraction::MouseEvent::Move; GetMouseInteractionEvent()->m_mouseEvent = AzToolsFramework::ViewportInteraction::MouseEvent::Move;
m_manipulatorViewportInteraction.GetManipulatorManager().ConsumeMouseInteractionEvent(*m_event); m_manipulatorViewportInteraction.GetManipulatorManager().ConsumeMouseInteractionEvent(*m_event);
} }

@ -10,6 +10,7 @@
#include <AzFramework/Viewport/ViewportScreen.h> #include <AzFramework/Viewport/ViewportScreen.h>
#include <AzManipulatorTestFramework/ViewportInteraction.h> #include <AzManipulatorTestFramework/ViewportInteraction.h>
#include <AzToolsFramework/Manipulators/ManipulatorBus.h> #include <AzToolsFramework/Manipulators/ManipulatorBus.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h>
namespace AzManipulatorTestFramework namespace AzManipulatorTestFramework
{ {
@ -19,6 +20,9 @@ namespace AzManipulatorTestFramework
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusConnect(m_viewportId); AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler::BusConnect(m_viewportId);
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler::BusConnect(m_viewportId); AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler::BusConnect(m_viewportId);
AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusConnect(m_viewportId); AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler::BusConnect(m_viewportId);
m_cameraState =
AzFramework::CreateIdentityDefaultCamera(AZ::Vector3::CreateZero(), AzManipulatorTestFramework::DefaultViewportSize);
} }
ViewportInteraction::~ViewportInteraction() ViewportInteraction::~ViewportInteraction()
@ -113,6 +117,16 @@ namespace AzManipulatorTestFramework
m_stickySelect = enabled; m_stickySelect = enabled;
} }
void ViewportInteraction::SetIconsVisible(const bool visible)
{
m_iconsVisible = visible;
}
void ViewportInteraction::SetHelpersVisible(const bool visible)
{
m_helpersVisible = visible;
}
AZ::Vector3 ViewportInteraction::DefaultEditorCameraPosition() const AZ::Vector3 ViewportInteraction::DefaultEditorCameraPosition() const
{ {
return {}; return {};
@ -148,4 +162,14 @@ namespace AzManipulatorTestFramework
{ {
return 1.0f; return 1.0f;
} }
bool ViewportInteraction::IconsVisible() const
{
return m_iconsVisible;
}
bool ViewportInteraction::HelpersVisible() const
{
return m_helpersVisible;
}
} // namespace AzManipulatorTestFramework } // namespace AzManipulatorTestFramework

@ -8,18 +8,19 @@
#pragma once #pragma once
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h>
#include <AzTest/AzTest.h> #include <AzTest/AzTest.h>
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h> #include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h>
namespace UnitTest namespace UnitTest
{ {
class LinearManipulatorTestFixture class LinearManipulatorTestFixture : public ToolsApplicationFixture
: public ToolsApplicationFixture
{ {
protected: protected:
LinearManipulatorTestFixture(const AzToolsFramework::ManipulatorManagerId& manipulatorManagerId) LinearManipulatorTestFixture(const AzToolsFramework::ManipulatorManagerId& manipulatorManagerId)
: m_manipulatorManagerId(manipulatorManagerId) {} : m_manipulatorManagerId(manipulatorManagerId)
{
}
void SetUpEditorFixtureImpl() override void SetUpEditorFixtureImpl() override
{ {
@ -63,16 +64,16 @@ namespace UnitTest
bool m_receivedLeftMouseUp = false; bool m_receivedLeftMouseUp = false;
// initial world space starting position for mouse interaction // initial world space starting position for mouse interaction
const AzToolsFramework::ViewportInteraction::MousePick m_mouseStartingPositionRay = const AzToolsFramework::ViewportInteraction::MousePick m_mouseStartingPositionRay{ AZ::Vector3(0.0f, -2.0f, 0.0f),
AzManipulatorTestFramework::CreateMousePick( AZ::Vector3(0.0f, 1.0f, 0.0f),
AZ::Vector3(0.0f, -2.0f, 0.0f), AZ::Vector3(0.0f, 1.0f, 0.0f), AzFramework::ScreenPoint( 0,0 )); AzFramework::ScreenPoint(0, 0) };
// left mouse down ray in world space 2 units back from origin looking down +y axis with a null interaction // left mouse down ray in world space 2 units back from origin looking down +y axis with a null interaction
// id and no keyboard modifiers // id and no keyboard modifiers
AzToolsFramework::ViewportInteraction::MouseInteraction m_interaction = AzToolsFramework::ViewportInteraction::MouseInteraction m_interaction =
AzManipulatorTestFramework::CreateMouseInteraction( AzToolsFramework::ViewportInteraction::BuildMouseInteraction(
m_mouseStartingPositionRay, m_mouseStartingPositionRay,
AzManipulatorTestFramework::CreateMouseButtons(AzToolsFramework::ViewportInteraction::MouseButton::Left), AzToolsFramework::ViewportInteraction::BuildMouseButtons(AzToolsFramework::ViewportInteraction::MouseButton::Left),
AzToolsFramework::ViewportInteraction::InteractionId(AZ::EntityId(0), 0), AzToolsFramework::ViewportInteraction::InteractionId(AZ::EntityId(0), 0),
AzToolsFramework::ViewportInteraction::KeyboardModifiers(0)); AzToolsFramework::ViewportInteraction::KeyboardModifiers(0));
}; };

@ -7,6 +7,8 @@
*/ */
#include "AzManipulatorTestFrameworkTestFixtures.h" #include "AzManipulatorTestFrameworkTestFixtures.h"
#include <AzToolsFramework/Viewport/ViewportTypes.h>
#include <AzToolsFramework/ViewportSelection/EditorDefaultSelection.h> #include <AzToolsFramework/ViewportSelection/EditorDefaultSelection.h>
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h> #include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
@ -34,8 +36,8 @@ namespace UnitTest
TEST_F(AzManipulatorTestFrameworkBusCallTestFixture, ConsumeViewportLeftMouseClick) TEST_F(AzManipulatorTestFrameworkBusCallTestFixture, ConsumeViewportLeftMouseClick)
{ {
// given a left mouse down ray in world space // given a left mouse down ray in world space
auto event = auto event = AzToolsFramework::ViewportInteraction::BuildMouseInteractionEvent(
AzManipulatorTestFramework::CreateMouseInteractionEvent(m_interaction, AzToolsFramework::ViewportInteraction::MouseEvent::Down); m_interaction, AzToolsFramework::ViewportInteraction::MouseEvent::Down);
// consume the mouse down and up events // consume the mouse down and up events
AzManipulatorTestFramework::DispatchMouseInteractionEvent(event); AzManipulatorTestFramework::DispatchMouseInteractionEvent(event);
@ -53,8 +55,8 @@ namespace UnitTest
TEST_F(AzManipulatorTestFrameworkBusCallTestFixture, ConsumeViewportMouseMoveHover) TEST_F(AzManipulatorTestFrameworkBusCallTestFixture, ConsumeViewportMouseMoveHover)
{ {
// given a left mouse down ray in world space // given a left mouse down ray in world space
const auto event = const auto event = AzToolsFramework::ViewportInteraction::BuildMouseInteractionEvent(
AzManipulatorTestFramework::CreateMouseInteractionEvent(m_interaction, AzToolsFramework::ViewportInteraction::MouseEvent::Move); m_interaction, AzToolsFramework::ViewportInteraction::MouseEvent::Move);
// consume the mouse move event // consume the mouse move event
AzManipulatorTestFramework::DispatchMouseInteractionEvent(event); AzManipulatorTestFramework::DispatchMouseInteractionEvent(event);
@ -72,8 +74,8 @@ namespace UnitTest
TEST_F(AzManipulatorTestFrameworkBusCallTestFixture, ConsumeViewportMouseMoveActive) TEST_F(AzManipulatorTestFrameworkBusCallTestFixture, ConsumeViewportMouseMoveActive)
{ {
// given a left mouse down ray in world space // given a left mouse down ray in world space
auto event = auto event = AzToolsFramework::ViewportInteraction::BuildMouseInteractionEvent(
AzManipulatorTestFramework::CreateMouseInteractionEvent(m_interaction, AzToolsFramework::ViewportInteraction::MouseEvent::Down); m_interaction, AzToolsFramework::ViewportInteraction::MouseEvent::Down);
// consume the mouse down event // consume the mouse down event
AzManipulatorTestFramework::DispatchMouseInteractionEvent(event); AzManipulatorTestFramework::DispatchMouseInteractionEvent(event);
@ -113,8 +115,8 @@ namespace UnitTest
}); });
// given a left mouse down ray in world space // given a left mouse down ray in world space
auto event = auto event = AzToolsFramework::ViewportInteraction::BuildMouseInteractionEvent(
AzManipulatorTestFramework::CreateMouseInteractionEvent(m_interaction, AzToolsFramework::ViewportInteraction::MouseEvent::Down); m_interaction, AzToolsFramework::ViewportInteraction::MouseEvent::Down);
// consume the mouse down event // consume the mouse down event
AzManipulatorTestFramework::DispatchMouseInteractionEvent(event); AzManipulatorTestFramework::DispatchMouseInteractionEvent(event);

@ -5,9 +5,12 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
#include <ostream>
#include <AzCore/Component/EntityId.h>
#include <AzCore/IO/Path/Path.h> #include <AzCore/IO/Path/Path.h>
#include <ostream>
namespace AZ::IO namespace AZ::IO
{ {
void PrintTo(const AZ::IO::PathView& path, ::std::ostream* os) void PrintTo(const AZ::IO::PathView& path, ::std::ostream* os)
@ -24,4 +27,12 @@ namespace AZ::IO
{ {
*os << "path: " << AZ::IO::FixedMaxPath(path.Native(), AZ::IO::PosixPathSeparator).MakePreferred().c_str(); *os << "path: " << AZ::IO::FixedMaxPath(path.Native(), AZ::IO::PosixPathSeparator).MakePreferred().c_str();
} }
} // namespace AZ::IO
namespace AZ
{
void PrintTo(const AZ::EntityId entityId, ::std::ostream* os)
{
*os << entityId.ToString().c_str();
} }
} // namespace AZ

@ -5,6 +5,7 @@
* SPDX-License-Identifier: Apache-2.0 OR MIT * SPDX-License-Identifier: Apache-2.0 OR MIT
* *
*/ */
#pragma once #pragma once
#include <iosfwd> #include <iosfwd>
@ -37,4 +38,11 @@ namespace AZ::IO
void PrintTo(const AZ::IO::FixedMaxPath& path, ::std::ostream* os); void PrintTo(const AZ::IO::FixedMaxPath& path, ::std::ostream* os);
} }
namespace AZ
{
class EntityId;
void PrintTo(AZ::EntityId entityId, ::std::ostream* os);
}
#include <AzTest/Printers.inl> #include <AzTest/Printers.inl>

@ -878,9 +878,6 @@ namespace AzToolsFramework
/// Return the icon texture id (from internal IconManager) for a given entity icon path. /// Return the icon texture id (from internal IconManager) for a given entity icon path.
/// This can be passed to DrawTextureLabel to draw an entity icon. /// This can be passed to DrawTextureLabel to draw an entity icon.
virtual int GetIconTextureIdFromEntityIconPath(const AZStd::string& entityIconPath) = 0; virtual int GetIconTextureIdFromEntityIconPath(const AZStd::string& entityIconPath) = 0;
/// Returns if the Display Helpers option is toggled on in the Editor.
virtual bool DisplayHelpersVisible() = 0;
}; };
using EditorRequestBus = AZ::EBus<EditorRequests>; using EditorRequestBus = AZ::EBus<EditorRequests>;

@ -89,8 +89,8 @@ namespace AzToolsFramework
const float rayLength) const float rayLength)
{ {
AZ_Assert(rayLength > 0.0f, "Invalid ray length passed to RefreshRayRequest"); AZ_Assert(rayLength > 0.0f, "Invalid ray length passed to RefreshRayRequest");
rayRequest.m_startWorldPosition = viewportRay.origin; rayRequest.m_startWorldPosition = viewportRay.m_origin;
rayRequest.m_endWorldPosition = viewportRay.origin + viewportRay.direction * rayLength; rayRequest.m_endWorldPosition = viewportRay.m_origin + viewportRay.m_direction * rayLength;
} }
AZ::Vector3 FindClosestPickIntersection( AZ::Vector3 FindClosestPickIntersection(

@ -15,7 +15,6 @@
#include <AzFramework/Viewport/CameraState.h> #include <AzFramework/Viewport/CameraState.h>
#include <AzFramework/Viewport/ClickDetector.h> #include <AzFramework/Viewport/ClickDetector.h>
#include <AzFramework/Viewport/ViewportId.h> #include <AzFramework/Viewport/ViewportId.h>
#include <AzFramework/Viewport/ViewportScreen.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h> #include <AzToolsFramework/Entity/EditorEntityContextBus.h>
#include <AzToolsFramework/Viewport/ViewportTypes.h> #include <AzToolsFramework/Viewport/ViewportTypes.h>
@ -151,13 +150,6 @@ namespace AzToolsFramework
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single; static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
}; };
//! A ray projection, originating from a point and extending in a direction specified as a normal.
struct ProjectedViewportRay
{
AZ::Vector3 origin;
AZ::Vector3 direction;
};
//! Requests that can be made to the viewport to query and modify its state. //! Requests that can be made to the viewport to query and modify its state.
class ViewportInteractionRequests class ViewportInteractionRequests
{ {
@ -183,15 +175,6 @@ namespace AzToolsFramework
//! Type to inherit to implement ViewportInteractionRequests. //! Type to inherit to implement ViewportInteractionRequests.
using ViewportInteractionRequestBus = AZ::EBus<ViewportInteractionRequests, ViewportEBusTraits>; using ViewportInteractionRequestBus = AZ::EBus<ViewportInteractionRequests, ViewportEBusTraits>;
//! Utility function to return a viewport ray.
inline ProjectedViewportRay ViewportScreenToWorldRay(
const AzFramework::CameraState& cameraState, const AzFramework::ScreenPoint& screenPoint)
{
const AZ::Vector3 rayOrigin = AzFramework::ScreenToWorld(screenPoint, cameraState);
const AZ::Vector3 rayDirection = (rayOrigin - cameraState.m_position).GetNormalized();
return AzToolsFramework::ViewportInteraction::ProjectedViewportRay{ rayOrigin, rayDirection };
}
//! Utility function to return a viewport ray using the ViewportInteractionRequestBus. //! Utility function to return a viewport ray using the ViewportInteractionRequestBus.
inline ProjectedViewportRay ViewportScreenToWorldRay( inline ProjectedViewportRay ViewportScreenToWorldRay(
const AzFramework::ViewportId viewportId, const AzFramework::ScreenPoint& screenPoint) const AzFramework::ViewportId viewportId, const AzFramework::ScreenPoint& screenPoint)
@ -225,6 +208,10 @@ namespace AzToolsFramework
virtual bool StickySelectEnabled() const = 0; virtual bool StickySelectEnabled() const = 0;
//! Returns the default viewport camera position. //! Returns the default viewport camera position.
virtual AZ::Vector3 DefaultEditorCameraPosition() const = 0; virtual AZ::Vector3 DefaultEditorCameraPosition() const = 0;
//! Returns if icons are visible in the viewport.
virtual bool IconsVisible() const = 0;
//! Returns if viewport helpers (additional debug drawing) are visible in the viewport.
virtual bool HelpersVisible() const = 0;
protected: protected:
~ViewportSettingsRequests() = default; ~ViewportSettingsRequests() = default;

@ -20,6 +20,8 @@ namespace AzToolsFramework
constexpr AZStd::string_view ScaleManipulatorBoxHalfExtentSetting = "/Amazon/Preferences/Editor/Manipulator/ScaleManipulatorBoxHalfExtent"; constexpr AZStd::string_view ScaleManipulatorBoxHalfExtentSetting = "/Amazon/Preferences/Editor/Manipulator/ScaleManipulatorBoxHalfExtent";
constexpr AZStd::string_view RotationManipulatorRadiusSetting = "/Amazon/Preferences/Editor/Manipulator/RotationManipulatorRadius"; constexpr AZStd::string_view RotationManipulatorRadiusSetting = "/Amazon/Preferences/Editor/Manipulator/RotationManipulatorRadius";
constexpr AZStd::string_view ManipulatorViewBaseScaleSetting = "/Amazon/Preferences/Editor/Manipulator/ViewBaseScale"; constexpr AZStd::string_view ManipulatorViewBaseScaleSetting = "/Amazon/Preferences/Editor/Manipulator/ViewBaseScale";
constexpr AZStd::string_view IconsVisibleSetting = "/Amazon/Preferences/Editor/IconsVisible";
constexpr AZStd::string_view HelpersVisibleSetting = "/Amazon/Preferences/Editor/HelpersVisible";
bool FlipManipulatorAxesTowardsView() bool FlipManipulatorAxesTowardsView()
{ {
@ -120,4 +122,24 @@ namespace AzToolsFramework
{ {
SetRegistry(ManipulatorViewBaseScaleSetting, scale); SetRegistry(ManipulatorViewBaseScaleSetting, scale);
} }
bool IconsVisible()
{
return GetRegistry(IconsVisibleSetting, true);
}
void SetIconsVisible(const bool visible)
{
SetRegistry(IconsVisibleSetting, visible);
}
bool HelpersVisible()
{
return GetRegistry(HelpersVisibleSetting, true);
}
void SetHelpersVisible(const bool visible)
{
SetRegistry(HelpersVisibleSetting, visible);
}
} // namespace AzToolsFramework } // namespace AzToolsFramework

@ -66,4 +66,10 @@ namespace AzToolsFramework
float ManipulatorViewBaseScale(); float ManipulatorViewBaseScale();
void SetManipulatorViewBaseScale(float scale); void SetManipulatorViewBaseScale(float scale);
bool IconsVisible();
void SetIconsVisible(bool visible);
bool HelpersVisible();
void SetHelpersVisible(bool visible);
} // namespace AzToolsFramework } // namespace AzToolsFramework

@ -49,5 +49,22 @@ namespace AzToolsFramework
->Field("MouseEvent", &MouseInteractionEvent::m_mouseEvent) ->Field("MouseEvent", &MouseInteractionEvent::m_mouseEvent)
->Field("WheelDelta", &MouseInteractionEvent::m_wheelDelta); ->Field("WheelDelta", &MouseInteractionEvent::m_wheelDelta);
} }
MouseInteraction BuildMouseInteraction(
const MousePick& mousePick, const MouseButtons buttons, const InteractionId interactionId, const KeyboardModifiers modifiers)
{
MouseInteraction interaction;
interaction.m_mousePick = mousePick;
interaction.m_mouseButtons = buttons;
interaction.m_interactionId = interactionId;
interaction.m_keyboardModifiers = modifiers;
return interaction;
}
MouseInteractionEvent BuildMouseInteractionEvent(
const MouseInteraction& mouseInteraction, const MouseEvent event, const bool cursorCaptured /*= false*/)
{
return MouseInteractionEvent(mouseInteraction, event, cursorCaptured);
}
} // namespace ViewportInteraction } // namespace ViewportInteraction
} // namespace AzToolsFramework } // namespace AzToolsFramework

@ -8,11 +8,11 @@
#pragma once #pragma once
#include "AzFramework/Viewport/ScreenGeometry.h"
#include <AzCore/Component/EntityId.h> #include <AzCore/Component/EntityId.h>
#include <AzCore/Math/Vector2.h> #include <AzCore/Math/Vector2.h>
#include <AzCore/Math/Vector3.h> #include <AzCore/Math/Vector3.h>
#include <AzFramework/Viewport/CameraState.h>
#include <AzFramework/Viewport/ViewportScreen.h>
#include <QPoint> #include <QPoint>
@ -20,7 +20,7 @@ namespace AZ
{ {
class ReflectContext; class ReflectContext;
class SerializeContext; class SerializeContext;
} } // namespace AZ
namespace AzToolsFramework namespace AzToolsFramework
{ {
@ -178,6 +178,12 @@ namespace AzToolsFramework
//! @cond //! @cond
AZ_TYPE_INFO(MousePick, "{A69B9562-FC8C-4DE7-9137-0FF867B1513D}"); AZ_TYPE_INFO(MousePick, "{A69B9562-FC8C-4DE7-9137-0FF867B1513D}");
MousePick() = default; MousePick() = default;
MousePick(const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection, const AzFramework::ScreenPoint& screenPoint)
: m_rayOrigin(rayOrigin)
, m_rayDirection(rayDirection)
, m_screenCoordinates(screenPoint)
{
}
//! @endcond //! @endcond
AZ::Vector3 m_rayOrigin = AZ::Vector3::CreateZero(); //!< World space. AZ::Vector3 m_rayOrigin = AZ::Vector3::CreateZero(); //!< World space.
@ -249,6 +255,22 @@ namespace AzToolsFramework
return mouseInteractionEvent.m_wheelDelta; return mouseInteractionEvent.m_wheelDelta;
} }
//! A ray projection, originating from a point and extending in a direction specified as a normal.
struct ProjectedViewportRay
{
AZ::Vector3 m_origin;
AZ::Vector3 m_direction;
};
//! Utility function to return a viewport ray.
inline ProjectedViewportRay ViewportScreenToWorldRay(
const AzFramework::CameraState& cameraState, const AzFramework::ScreenPoint& screenPoint)
{
const AZ::Vector3 rayOrigin = AzFramework::ScreenToWorld(screenPoint, cameraState);
const AZ::Vector3 rayDirection = (rayOrigin - cameraState.m_position).GetNormalized();
return ProjectedViewportRay{ rayOrigin, rayDirection };
}
//! Return QPoint from AzFramework::ScreenPoint. //! Return QPoint from AzFramework::ScreenPoint.
inline QPoint QPointFromScreenPoint(const AzFramework::ScreenPoint& screenPoint) inline QPoint QPointFromScreenPoint(const AzFramework::ScreenPoint& screenPoint)
{ {
@ -301,6 +323,27 @@ namespace AzToolsFramework
return mouseButtons; return mouseButtons;
} }
//! Build a mouse pick from the specified mouse position and camera state.
inline MousePick BuildMousePick(const AzFramework::CameraState& cameraState, const AzFramework::ScreenPoint& screenPoint)
{
const auto ray = ViewportScreenToWorldRay(cameraState, screenPoint);
return MousePick(ray.m_origin, ray.m_direction, screenPoint);
}
//! Create a mouse interaction from the specified pick, buttons, interaction id and keyboard modifiers.
MouseInteraction BuildMouseInteraction(
const MousePick& mousePick, MouseButtons buttons, InteractionId interactionId, KeyboardModifiers modifiers);
//! Create a mouse buttons from the specified mouse button.
inline MouseButtons BuildMouseButtons(const MouseButton button)
{
return MouseButtons(aznumeric_cast<AZ::u32>(button));
}
//! Create a mouse interaction event from the specified interaction and event.
MouseInteractionEvent BuildMouseInteractionEvent(
const MouseInteraction& mouseInteraction, MouseEvent event, bool cursorCaptured = false);
//! Reflect all viewport related types. //! Reflect all viewport related types.
void ViewportInteractionReflect(AZ::ReflectContext* context); void ViewportInteractionReflect(AZ::ReflectContext* context);
} // namespace ViewportInteraction } // namespace ViewportInteraction

@ -52,34 +52,45 @@ AZ_CVAR(
AZ::ConsoleFunctorFlags::Null, AZ::ConsoleFunctorFlags::Null,
"Use a lock icon when the cursor is over entities that cannot be interacted with"); "Use a lock icon when the cursor is over entities that cannot be interacted with");
AZ_CVAR(float, ed_iconMinScale, 0.1f, nullptr, AZ::ConsoleFunctorFlags::Null, "Minimum scale for icons in the distance");
AZ_CVAR(float, ed_iconMaxScale, 1.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "Maximum scale for icons near the camera");
AZ_CVAR(float, ed_iconCloseDist, 3.0f, nullptr, AZ::ConsoleFunctorFlags::Null, "Distance at which icons are at maximum scale");
AZ_CVAR(float, ed_iconFarDist, 40.f, nullptr, AZ::ConsoleFunctorFlags::Null, "Distance at which icons are at minimum scale");
namespace AzToolsFramework namespace AzToolsFramework
{ {
AZ_CLASS_ALLOCATOR_IMPL(EditorHelpers, AZ::SystemAllocator, 0) AZ_CLASS_ALLOCATOR_IMPL(EditorHelpers, AZ::SystemAllocator, 0)
static const int s_iconSize = 36; // icon display size (in pixels) static const int IconSize = 36; // icon display size (in pixels)
static const float s_iconMinScale = 0.1f; // minimum scale for icons in the distance
static const float s_iconMaxScale = 1.0f; // maximum scale for icons near the camera
static const float s_iconCloseDist = 3.f; // distance at which icons are at maximum scale
static const float s_iconFarDist = 40.f; // distance at which icons are at minimum scale
// helper function to wrap EBus call to check if helpers are being displayed // helper function to wrap EBus call to check if helpers are being displayed
// note: the ['?'] icon in the top right of the editor static bool HelpersVisible(const AzFramework::ViewportId viewportId)
static bool HelpersVisible()
{ {
bool helpersVisible = false; bool helpersVisible = false;
EditorRequestBus::BroadcastResult(helpersVisible, &EditorRequests::DisplayHelpersVisible); ViewportInteraction::ViewportSettingsRequestBus::EventResult(
helpersVisible, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::HelpersVisible);
return helpersVisible; return helpersVisible;
} }
// calculate the icon scale based on how far away it is (distanceSq) from a given point // helper function to wrap EBus call to check if icons are being displayed
// note: this is mostly likely distance from the camera static bool IconsVisible(const AzFramework::ViewportId viewportId)
static float GetIconScale(const float distSq)
{ {
AZ_PROFILE_FUNCTION(AzToolsFramework); bool iconsVisible = false;
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
iconsVisible, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::IconsVisible);
return iconsVisible;
}
return s_iconMinScale + float GetIconScale(const float distance)
(s_iconMaxScale - s_iconMinScale) * {
(1.0f - AZ::GetClamp(AZ::GetMax(0.0f, sqrtf(distSq) - s_iconCloseDist) / s_iconFarDist, 0.0f, 1.0f)); return ed_iconMinScale +
(ed_iconMaxScale - ed_iconMinScale) *
(1.0f - AZ::GetClamp(AZ::GetMax(0.0f, distance - ed_iconCloseDist) / (ed_iconFarDist - ed_iconCloseDist), 0.0f, 1.0f));
}
float GetIconSize(const float distance)
{
return GetIconScale(distance) * IconSize;
} }
static void DisplayComponents( static void DisplayComponents(
@ -171,11 +182,14 @@ namespace AzToolsFramework
const int viewportId = mouseInteraction.m_mouseInteraction.m_interactionId.m_viewportId; const int viewportId = mouseInteraction.m_mouseInteraction.m_interactionId.m_viewportId;
const bool helpersVisible = HelpersVisible(); const bool iconsVisible = IconsVisible(viewportId);
const AZ::Matrix3x4 cameraView = AzFramework::CameraView(cameraState);
const AZ::Matrix4x4 cameraProjection = AzFramework::CameraProjection(cameraState);
// selecting new entities // selecting new entities
AZ::EntityId entityIdUnderCursor; AZ::EntityId entityIdUnderCursor;
float closestDistance = std::numeric_limits<float>::max(); float closestDistance = AZStd::numeric_limits<float>::max();
for (size_t entityCacheIndex = 0; entityCacheIndex < m_entityDataCache->VisibleEntityDataCount(); ++entityCacheIndex) for (size_t entityCacheIndex = 0; entityCacheIndex < m_entityDataCache->VisibleEntityDataCount(); ++entityCacheIndex)
{ {
const AZ::EntityId entityId = m_entityDataCache->GetVisibleEntityId(entityCacheIndex); const AZ::EntityId entityId = m_entityDataCache->GetVisibleEntityId(entityCacheIndex);
@ -185,8 +199,7 @@ namespace AzToolsFramework
continue; continue;
} }
// 2d screen space selection - did we click an icon if (iconsVisible)
if (helpersVisible)
{ {
// some components choose to hide their icons (e.g. meshes) // some components choose to hide their icons (e.g. meshes)
// we also do not want to test against icons that may not be showing as they're inside a 'closed' entity container // we also do not want to test against icons that may not be showing as they're inside a 'closed' entity container
@ -197,17 +210,23 @@ namespace AzToolsFramework
const AZ::Vector3& entityPosition = m_entityDataCache->GetVisibleEntityPosition(entityCacheIndex); const AZ::Vector3& entityPosition = m_entityDataCache->GetVisibleEntityPosition(entityCacheIndex);
// selecting based on 2d icon - should only do it when visible and not selected // selecting based on 2d icon - should only do it when visible and not selected
const AzFramework::ScreenPoint screenPosition = AzFramework::WorldToScreen(entityPosition, cameraState); const AZ::Vector3 ndcPoint = AzFramework::WorldToScreenNdc(entityPosition, cameraView, cameraProjection);
const AzFramework::ScreenPoint screenPosition =
AzFramework::ScreenPointFromNdc(AZ::Vector3ToVector2(ndcPoint), cameraState.m_viewportSize);
const float distSqFromCamera = cameraState.m_position.GetDistanceSq(entityPosition); const float distanceFromCamera = cameraState.m_position.GetDistance(entityPosition);
const auto iconRange = static_cast<float>(GetIconScale(distSqFromCamera) * s_iconSize * 0.5f); const auto iconRange = GetIconSize(distanceFromCamera) * 0.5f;
const auto screenCoords = mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates; const auto screenCoords = mouseInteraction.m_mouseInteraction.m_mousePick.m_screenCoordinates;
// 2d screen space selection - did we click an icon
if (screenCoords.m_x >= screenPosition.m_x - iconRange && screenCoords.m_x <= screenPosition.m_x + iconRange && if (screenCoords.m_x >= screenPosition.m_x - iconRange && screenCoords.m_x <= screenPosition.m_x + iconRange &&
screenCoords.m_y >= screenPosition.m_y - iconRange && screenCoords.m_y <= screenPosition.m_y + iconRange) screenCoords.m_y >= screenPosition.m_y - iconRange && screenCoords.m_y <= screenPosition.m_y + iconRange &&
ndcPoint.GetZ() < closestDistance)
{ {
// use ndc z value for distance here which is in 0-1 range so will most likely 'win' when it comes to the
// distance check (this is what we want as the cursor should always favor icons if they are hovered)
closestDistance = ndcPoint.GetZ();
entityIdUnderCursor = entityId; entityIdUnderCursor = entityId;
break;
} }
} }
} }
@ -220,13 +239,18 @@ namespace AzToolsFramework
if (AabbIntersectMouseRay(mouseInteraction.m_mouseInteraction, aabb)) if (AabbIntersectMouseRay(mouseInteraction.m_mouseInteraction, aabb))
{ {
// if success, pick against specific component // if success, pick against specific component
if (PickEntity(entityId, mouseInteraction.m_mouseInteraction, closestDistance, viewportId)) float closestBoundDifference = AZStd::numeric_limits<float>::max();
if (PickEntity(entityId, mouseInteraction.m_mouseInteraction, closestBoundDifference, viewportId))
{ {
if (closestBoundDifference < closestDistance)
{
closestDistance = closestBoundDifference;
entityIdUnderCursor = entityId; entityIdUnderCursor = entityId;
} }
} }
} }
} }
}
// verify if the entity Id corresponds to an entity that is focused; if not, halt selection. // verify if the entity Id corresponds to an entity that is focused; if not, halt selection.
if (entityIdUnderCursor.IsValid() && !IsSelectableAccordingToFocusMode(entityIdUnderCursor)) if (entityIdUnderCursor.IsValid() && !IsSelectableAccordingToFocusMode(entityIdUnderCursor))
@ -276,20 +300,44 @@ namespace AzToolsFramework
{ {
AZ_PROFILE_FUNCTION(AzToolsFramework); AZ_PROFILE_FUNCTION(AzToolsFramework);
if (HelpersVisible()) const bool iconsVisible = IconsVisible(viewportInfo.m_viewportId);
{ const bool helpersVisible = HelpersVisible(viewportInfo.m_viewportId);
for (size_t entityCacheIndex = 0; entityCacheIndex < m_entityDataCache->VisibleEntityDataCount(); ++entityCacheIndex)
{
const AZ::EntityId entityId = m_entityDataCache->GetVisibleEntityId(entityCacheIndex);
auto displayCheck = [this](const size_t entityCacheIndex, const AZ::EntityId entityId)
{
if (!m_entityDataCache->IsVisibleEntityVisible(entityCacheIndex) || !IsSelectableInViewport(entityId)) if (!m_entityDataCache->IsVisibleEntityVisible(entityCacheIndex) || !IsSelectableInViewport(entityId))
{ {
continue; return false;
} }
return true;
};
if (helpersVisible)
{
for (size_t entityCacheIndex = 0; entityCacheIndex < m_entityDataCache->VisibleEntityDataCount(); ++entityCacheIndex)
{
if (const AZ::EntityId entityId = m_entityDataCache->GetVisibleEntityId(entityCacheIndex);
displayCheck(entityCacheIndex, entityId))
{
// notify components to display // notify components to display
DisplayComponents(entityId, viewportInfo, debugDisplay); DisplayComponents(entityId, viewportInfo, debugDisplay);
}
}
}
if (iconsVisible)
{
auto editorViewportIconDisplay = EditorViewportIconDisplay::Get();
if (!editorViewportIconDisplay)
{
return;
}
for (size_t entityCacheIndex = 0; entityCacheIndex < m_entityDataCache->VisibleEntityDataCount(); ++entityCacheIndex)
{
if (const AZ::EntityId entityId = m_entityDataCache->GetVisibleEntityId(entityCacheIndex);
displayCheck(entityCacheIndex, entityId))
{
if (m_entityDataCache->IsVisibleEntityIconHidden(entityCacheIndex) || if (m_entityDataCache->IsVisibleEntityIconHidden(entityCacheIndex) ||
(m_entityDataCache->IsVisibleEntitySelected(entityCacheIndex) && !showIconCheck(entityId))) (m_entityDataCache->IsVisibleEntitySelected(entityCacheIndex) && !showIconCheck(entityId)))
{ {
@ -300,12 +348,6 @@ namespace AzToolsFramework
EditorEntityIconComponentRequestBus::EventResult( EditorEntityIconComponentRequestBus::EventResult(
iconTextureId, entityId, &EditorEntityIconComponentRequests::GetEntityIconTextureId); iconTextureId, entityId, &EditorEntityIconComponentRequests::GetEntityIconTextureId);
const AZ::Vector3& entityPosition = m_entityDataCache->GetVisibleEntityPosition(entityCacheIndex);
const float distSqFromCamera = cameraState.m_position.GetDistanceSq(entityPosition);
const float iconScale = GetIconScale(distSqFromCamera);
const float iconSize = s_iconSize * iconScale;
using ComponentEntityAccentType = Components::EditorSelectionAccentSystemComponent::ComponentEntityAccentType; using ComponentEntityAccentType = Components::EditorSelectionAccentSystemComponent::ComponentEntityAccentType;
const AZ::Color iconHighlight = [this, entityCacheIndex]() const AZ::Color iconHighlight = [this, entityCacheIndex]()
{ {
@ -322,12 +364,17 @@ namespace AzToolsFramework
return AZ::Color(1.0f, 1.0f, 1.0f, 1.0f); return AZ::Color(1.0f, 1.0f, 1.0f, 1.0f);
}(); }();
EditorViewportIconDisplay::Get()->DrawIcon({ viewportInfo.m_viewportId, iconTextureId, iconHighlight, entityPosition, const AZ::Vector3& entityPosition = m_entityDataCache->GetVisibleEntityPosition(entityCacheIndex);
const float distanceFromCamera = cameraState.m_position.GetDistance(entityPosition);
const float iconSize = GetIconSize(distanceFromCamera);
editorViewportIconDisplay->DrawIcon({ viewportInfo.m_viewportId, iconTextureId, iconHighlight, entityPosition,
EditorViewportIconDisplayInterface::CoordinateSpace::WorldSpace, EditorViewportIconDisplayInterface::CoordinateSpace::WorldSpace,
AZ::Vector2{ iconSize, iconSize } }); AZ::Vector2{ iconSize, iconSize } });
} }
} }
} }
}
bool EditorHelpers::IsSelectableInViewport(const AZ::EntityId entityId) const bool EditorHelpers::IsSelectableInViewport(const AZ::EntityId entityId) const
{ {

@ -106,4 +106,12 @@ namespace AzToolsFramework
const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; //!< Entity Data queried by the EditorHelpers. const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; //!< Entity Data queried by the EditorHelpers.
const FocusModeInterface* m_focusModeInterface = nullptr; //!< API to interact with focus mode functionality. const FocusModeInterface* m_focusModeInterface = nullptr; //!< API to interact with focus mode functionality.
}; };
//! Calculate the icon scale based on how far away it is from a given point.
//! @note This is mostly likely distance from the camera.
float GetIconScale(float distance);
//! Calculate the icon size based on how far away it is from a given point.
//! @note This is the base icon size multiplied by the icon scale to give a final viewport size.
float GetIconSize(float distance);
} // namespace AzToolsFramework } // namespace AzToolsFramework

@ -2523,8 +2523,7 @@ namespace AzToolsFramework
[readOnlyEntityPublicInterface](auto entityId) [readOnlyEntityPublicInterface](auto entityId)
{ {
return readOnlyEntityPublicInterface->IsReadOnly(entityId); return readOnlyEntityPublicInterface->IsReadOnly(entityId);
} });
);
} }
// note: create/destroy pattern to be addressed // note: create/destroy pattern to be addressed

@ -32,6 +32,8 @@ namespace AzToolsFramework
constexpr inline AZ::Crc32 EditReset = AZ_CRC_CE("com.o3de.action.editortransform.editreset"); constexpr inline AZ::Crc32 EditReset = AZ_CRC_CE("com.o3de.action.editortransform.editreset");
constexpr inline AZ::Crc32 EditResetManipulator = AZ_CRC_CE("com.o3de.action.editortransform.editresetmanipulator"); constexpr inline AZ::Crc32 EditResetManipulator = AZ_CRC_CE("com.o3de.action.editortransform.editresetmanipulator");
constexpr inline AZ::Crc32 ViewportUiVisible = AZ_CRC_CE("com.o3de.action.editortransform.viewportuivisible"); constexpr inline AZ::Crc32 ViewportUiVisible = AZ_CRC_CE("com.o3de.action.editortransform.viewportuivisible");
constexpr inline AZ::Crc32 Helpers = AZ_CRC_CE("com.o3de.action.editor.helpers");
constexpr inline AZ::Crc32 Icons = AZ_CRC_CE("com.o3de.action.editor.icons");
//@} //@}
//! Provide interface for EditorTransformComponentSelection requests. //! Provide interface for EditorTransformComponentSelection requests.

@ -40,16 +40,12 @@
#include <Tests/BoundsTestComponent.h> #include <Tests/BoundsTestComponent.h>
namespace AZ
{
std::ostream& operator<<(std::ostream& os, const EntityId entityId)
{
return os << entityId.ToString().c_str();
}
} // namespace AZ
namespace UnitTest namespace UnitTest
{ {
using AzToolsFramework::ViewportInteraction::BuildMouseButtons;
using AzToolsFramework::ViewportInteraction::BuildMouseInteraction;
using AzToolsFramework::ViewportInteraction::BuildMousePick;
AzToolsFramework::EntityIdList SelectedEntities() AzToolsFramework::EntityIdList SelectedEntities()
{ {
AzToolsFramework::EntityIdList selectedEntitiesBefore; AzToolsFramework::EntityIdList selectedEntitiesBefore;
@ -137,16 +133,7 @@ namespace UnitTest
AzToolsFramework::EntityIdList m_entityIds; AzToolsFramework::EntityIdList m_entityIds;
}; };
class EditorTransformComponentSelectionViewportPickingFixture : public ToolsApplicationFixture AZ::EntityId CreateEntityWithBounds(const char* entityName)
{
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::Entity* entity = nullptr;
AZ::EntityId entityId = CreateDefaultEditorEntity(entityName, &entity); AZ::EntityId entityId = CreateDefaultEditorEntity(entityName, &entity);
@ -156,11 +143,20 @@ namespace UnitTest
entity->Activate(); entity->Activate();
return entityId; return entityId;
}; }
m_entityId1 = createEntityWithBoundsFn("Entity1"); class EditorTransformComponentSelectionViewportPickingFixture : public ToolsApplicationFixture
m_entityId2 = createEntityWithBoundsFn("Entity2"); {
m_entityId3 = createEntityWithBoundsFn("Entity3"); public:
void SetUpEditorFixtureImpl() override
{
auto* app = GetApplication();
// register a simple component implementing BoundsRequestBus and EditorComponentSelectionRequestsBus
app->RegisterComponentDescriptor(BoundsTestComponent::CreateDescriptor());
m_entityId1 = CreateEntityWithBounds("Entity1");
m_entityId2 = CreateEntityWithBounds("Entity2");
m_entityId3 = CreateEntityWithBounds("Entity3");
} }
void PositionEntities() void PositionEntities()
@ -959,6 +955,9 @@ namespace UnitTest
const auto entity2ScreenPosition = AzFramework::WorldToScreen(AzToolsFramework::GetWorldTranslation(m_entityId2), m_cameraState); const auto entity2ScreenPosition = AzFramework::WorldToScreen(AzToolsFramework::GetWorldTranslation(m_entityId2), m_cameraState);
// ensure icons are not enabled to avoid them interfering with bound detection
m_viewportManipulatorInteraction->GetViewportInteraction().SetIconsVisible(false);
// click the entity in the viewport // click the entity in the viewport
m_actionDispatcher->SetStickySelect(true) m_actionDispatcher->SetStickySelect(true)
->CameraState(m_cameraState) ->CameraState(m_cameraState)
@ -974,6 +973,137 @@ namespace UnitTest
EXPECT_THAT(selectedEntities, UnorderedElementsAreArray(expectedSelectedEntities)); EXPECT_THAT(selectedEntities, UnorderedElementsAreArray(expectedSelectedEntities));
} }
// entity can be selected using icon
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, CursorOverEntityIconReturnsThatEntityId)
{
const AZ::EntityId boundlessEntityId = CreateDefaultEditorEntity("BoundlessEntity");
// camera (go to position format) -5.00, -8.00, 5.00, 0.00, 0.00
AzFramework::SetCameraTransform(m_cameraState, AZ::Transform::CreateTranslation(AZ::Vector3(-5.0f, -8.0f, 5.0f)));
// position entity in the world
AZ::TransformBus::Event(boundlessEntityId, &AZ::TransformBus::Events::SetWorldTranslation, AZ::Vector3(-5.0f, -1.0f, 5.0f));
const float distanceFromCamera = m_cameraState.m_position.GetDistance(AzToolsFramework::GetWorldTranslation(boundlessEntityId));
const auto quaterIconSize = AzToolsFramework::GetIconSize(distanceFromCamera) * 0.25f;
const auto entity1ScreenPosition =
AzFramework::WorldToScreen(AzToolsFramework::GetWorldTranslation(boundlessEntityId), m_cameraState) +
AzFramework::ScreenVectorFromVector2(AZ::Vector2(quaterIconSize));
AzToolsFramework::EditorVisibleEntityDataCache editorVisibleEntityDataCache;
AzToolsFramework::EditorHelpers editorHelpers(&editorVisibleEntityDataCache);
const auto viewportId = m_viewportManipulatorInteraction->GetViewportInteraction().GetViewportId();
const auto mousePick = BuildMousePick(m_cameraState, entity1ScreenPosition);
const auto mouseInteraction = BuildMouseInteraction(
mousePick, BuildMouseButtons(AzToolsFramework::ViewportInteraction::MouseButton::None),
AzToolsFramework::ViewportInteraction::InteractionId(AZ::EntityId(), viewportId),
AzToolsFramework::ViewportInteraction::KeyboardModifiers());
const auto mouseInteractionEvent = AzToolsFramework::ViewportInteraction::BuildMouseInteractionEvent(
mouseInteraction, AzToolsFramework::ViewportInteraction::MouseEvent::Move, false);
// mimic mouse move
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity1ScreenPosition);
// simulate hovering over an icon in the viewport
editorVisibleEntityDataCache.CalculateVisibleEntityDatas(AzFramework::ViewportInfo{ viewportId });
auto entityIdUnderCursor = editorHelpers.FindEntityIdUnderCursor(m_cameraState, mouseInteractionEvent);
using ::testing::Eq;
EXPECT_THAT(entityIdUnderCursor.EntityIdUnderCursor(), Eq(boundlessEntityId));
}
// overlapping icons, nearest is detected
TEST_F(EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, CursorOverOverlappingEntityIconsReturnsClosestEntityId)
{
const AZ::EntityId boundlessEntityId1 = CreateDefaultEditorEntity("BoundlessEntity1");
const AZ::EntityId boundlessEntityId2 = CreateDefaultEditorEntity("BoundlessEntity2");
// camera (go to position format) -5.00, -8.00, 5.00, 0.00, 0.00
AzFramework::SetCameraTransform(m_cameraState, AZ::Transform::CreateTranslation(AZ::Vector3(-5.0f, -8.0f, 5.0f)));
// position entities in the world
AZ::TransformBus::Event(boundlessEntityId1, &AZ::TransformBus::Events::SetWorldTranslation, AZ::Vector3(-5.0f, -1.0f, 5.0f));
// note: boundlessEntityId2 is closer to the camera
AZ::TransformBus::Event(boundlessEntityId2, &AZ::TransformBus::Events::SetWorldTranslation, AZ::Vector3(-5.0f, -3.0f, 5.0f));
const float distanceFromCamera = m_cameraState.m_position.GetDistance(AzToolsFramework::GetWorldTranslation(boundlessEntityId2));
const auto quaterIconSize = AzToolsFramework::GetIconSize(distanceFromCamera) * 0.25f;
const auto entity2ScreenPosition =
AzFramework::WorldToScreen(AzToolsFramework::GetWorldTranslation(boundlessEntityId2), m_cameraState) +
AzFramework::ScreenVectorFromVector2(AZ::Vector2(quaterIconSize));
AzToolsFramework::EditorVisibleEntityDataCache editorVisibleEntityDataCache;
AzToolsFramework::EditorHelpers editorHelpers(&editorVisibleEntityDataCache);
const auto viewportId = m_viewportManipulatorInteraction->GetViewportInteraction().GetViewportId();
const auto mousePick = BuildMousePick(m_cameraState, entity2ScreenPosition);
const auto mouseInteraction = BuildMouseInteraction(
mousePick, BuildMouseButtons(AzToolsFramework::ViewportInteraction::MouseButton::None),
AzToolsFramework::ViewportInteraction::InteractionId(AZ::EntityId(), viewportId),
AzToolsFramework::ViewportInteraction::KeyboardModifiers());
const auto mouseInteractionEvent = AzToolsFramework::ViewportInteraction::BuildMouseInteractionEvent(
mouseInteraction, AzToolsFramework::ViewportInteraction::MouseEvent::Move, false);
// mimic mouse move
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity2ScreenPosition);
// simulate hovering over an icon in the viewport
editorVisibleEntityDataCache.CalculateVisibleEntityDatas(AzFramework::ViewportInfo{ viewportId });
auto entityIdUnderCursor = editorHelpers.FindEntityIdUnderCursor(m_cameraState, mouseInteractionEvent);
using ::testing::Eq;
EXPECT_THAT(entityIdUnderCursor.EntityIdUnderCursor(), Eq(boundlessEntityId2));
}
// if an entity with an icon is behind an entity with a bound, the entity with the icon will be selected
// even if the bound is closer (this is because icons are treated as if they are on the near clip plane)
TEST_F(
EditorTransformComponentSelectionViewportPickingManipulatorTestFixture, FurtherAwayEntityWithIconReturnedWhenBoundEntityIsInFront)
{
const AZ::EntityId boundEntityId = CreateEntityWithBounds("BoundEntity");
const AZ::EntityId boundlessEntityId = CreateDefaultEditorEntity("BoundlessEntity");
auto* boundTestComponent = AzToolsFramework::GetEntityById(boundEntityId)->FindComponent<BoundsTestComponent>();
boundTestComponent->m_localBounds = AZ::Aabb::CreateFromMinMax(AZ::Vector3(-1.5f, -0.5f, -0.5f), AZ::Vector3(1.5f, 0.5, 0.5f));
// camera (go to position format) -5.00, -8.00, 5.00, 0.00, 0.00
AzFramework::SetCameraTransform(m_cameraState, AZ::Transform::CreateTranslation(AZ::Vector3(-5.0f, -8.0f, 5.0f)));
// position entities in the world
AZ::TransformBus::Event(boundEntityId, &AZ::TransformBus::Events::SetWorldTranslation, AZ::Vector3(-4.0f, -3.0f, 5.0f));
// note: boundlessEntityId2 is closer to the camera
AZ::TransformBus::Event(boundlessEntityId, &AZ::TransformBus::Events::SetWorldTranslation, AZ::Vector3(-5.0f, -1.0f, 5.0f));
const float distanceFromCamera = m_cameraState.m_position.GetDistance(AzToolsFramework::GetWorldTranslation(boundlessEntityId));
const auto quaterIconSize = AzToolsFramework::GetIconSize(distanceFromCamera) * 0.25f;
const auto entity2ScreenPosition =
AzFramework::WorldToScreen(AzToolsFramework::GetWorldTranslation(boundlessEntityId), m_cameraState) +
AzFramework::ScreenVectorFromVector2(AZ::Vector2(quaterIconSize));
AzToolsFramework::EditorVisibleEntityDataCache editorVisibleEntityDataCache;
AzToolsFramework::EditorHelpers editorHelpers(&editorVisibleEntityDataCache);
const auto viewportId = m_viewportManipulatorInteraction->GetViewportInteraction().GetViewportId();
const auto mousePick = BuildMousePick(m_cameraState, entity2ScreenPosition);
const auto mouseInteraction = BuildMouseInteraction(
mousePick, BuildMouseButtons(AzToolsFramework::ViewportInteraction::MouseButton::None),
AzToolsFramework::ViewportInteraction::InteractionId(AZ::EntityId(), viewportId),
AzToolsFramework::ViewportInteraction::KeyboardModifiers());
const auto mouseInteractionEvent = AzToolsFramework::ViewportInteraction::BuildMouseInteractionEvent(
mouseInteraction, AzToolsFramework::ViewportInteraction::MouseEvent::Move, false);
// mimic mouse move
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(entity2ScreenPosition);
// simulate hovering over an icon in the viewport
editorVisibleEntityDataCache.CalculateVisibleEntityDatas(AzFramework::ViewportInfo{ viewportId });
auto entityIdUnderCursor = editorHelpers.FindEntityIdUnderCursor(m_cameraState, mouseInteractionEvent);
using ::testing::Eq;
EXPECT_THAT(entityIdUnderCursor.EntityIdUnderCursor(), Eq(boundlessEntityId));
}
class EditorTransformComponentSelectionViewportPickingManipulatorTestFixtureParam class EditorTransformComponentSelectionViewportPickingManipulatorTestFixtureParam
: public EditorTransformComponentSelectionViewportPickingManipulatorTestFixture : public EditorTransformComponentSelectionViewportPickingManipulatorTestFixture
, public ::testing::WithParamInterface<bool> , public ::testing::WithParamInterface<bool>
@ -1709,8 +1839,9 @@ namespace UnitTest
using MouseInteractionResult = AzToolsFramework::ViewportInteraction::MouseInteractionResult; using MouseInteractionResult = AzToolsFramework::ViewportInteraction::MouseInteractionResult;
public: public:
WheelEventWidget(QWidget* parent = nullptr) WheelEventWidget(const AzFramework::ViewportId viewportId, QWidget* parent = nullptr)
: QWidget(parent) : QWidget(parent)
, m_viewportId(viewportId)
{ {
} }
@ -1719,7 +1850,7 @@ namespace UnitTest
namespace vi = AzToolsFramework::ViewportInteraction; namespace vi = AzToolsFramework::ViewportInteraction;
vi::MouseInteraction mouseInteraction; vi::MouseInteraction mouseInteraction;
mouseInteraction.m_interactionId.m_cameraId = AZ::EntityId(); mouseInteraction.m_interactionId.m_cameraId = AZ::EntityId();
mouseInteraction.m_interactionId.m_viewportId = 0; mouseInteraction.m_interactionId.m_viewportId = m_viewportId;
mouseInteraction.m_mouseButtons = vi::BuildMouseButtons(ev->buttons()); mouseInteraction.m_mouseButtons = vi::BuildMouseButtons(ev->buttons());
mouseInteraction.m_mousePick = vi::MousePick(); mouseInteraction.m_mousePick = vi::MousePick();
mouseInteraction.m_keyboardModifiers = vi::BuildKeyboardModifiers(ev->modifiers()); mouseInteraction.m_keyboardModifiers = vi::BuildKeyboardModifiers(ev->modifiers());
@ -1731,15 +1862,15 @@ namespace UnitTest
} }
MouseInteractionResult m_mouseInteractionResult; MouseInteractionResult m_mouseInteractionResult;
AzFramework::ViewportId m_viewportId;
}; };
TEST_F(EditorTransformComponentSelectionFixture, MouseScrollWheelSwitchesTransformMode) TEST_F(EditorTransformComponentSelectionManipulatorTestFixture, MouseScrollWheelSwitchesTransformMode)
{ {
using ::testing::Eq;
namespace vi = AzToolsFramework::ViewportInteraction; namespace vi = AzToolsFramework::ViewportInteraction;
using AzToolsFramework::EditorTransformComponentSelectionRequestBus; using AzToolsFramework::EditorTransformComponentSelectionRequestBus;
const auto transformMode = []() const auto transformMode = []
{ {
EditorTransformComponentSelectionRequestBus::Events::Mode transformMode; EditorTransformComponentSelectionRequestBus::Events::Mode transformMode;
EditorTransformComponentSelectionRequestBus::EventResult( EditorTransformComponentSelectionRequestBus::EventResult(
@ -1752,7 +1883,7 @@ namespace UnitTest
// preconditions // preconditions
EXPECT_THAT(transformMode(), EditorTransformComponentSelectionRequestBus::Events::Mode::Translation); EXPECT_THAT(transformMode(), EditorTransformComponentSelectionRequestBus::Events::Mode::Translation);
auto wheelEventWidget = WheelEventWidget(); auto wheelEventWidget = WheelEventWidget(m_viewportManipulatorInteraction->GetViewportInteraction().GetViewportId());
// attach the global event filter to the placeholder widget // attach the global event filter to the placeholder widget
AzQtComponents::GlobalEventFilter globalEventFilter(QApplication::instance()); AzQtComponents::GlobalEventFilter globalEventFilter(QApplication::instance());
wheelEventWidget.installEventFilter(&globalEventFilter); wheelEventWidget.installEventFilter(&globalEventFilter);
@ -1768,6 +1899,7 @@ namespace UnitTest
// then // then
// transform mode has changed and mouse event was handled // transform mode has changed and mouse event was handled
using ::testing::Eq;
EXPECT_THAT(transformMode(), Eq(EditorTransformComponentSelectionRequestBus::Events::Mode::Rotation)); EXPECT_THAT(transformMode(), Eq(EditorTransformComponentSelectionRequestBus::Events::Mode::Rotation));
EXPECT_THAT(wheelEventWidget.m_mouseInteractionResult, Eq(vi::MouseInteractionResult::Viewport)); EXPECT_THAT(wheelEventWidget.m_mouseInteractionResult, Eq(vi::MouseInteractionResult::Viewport));
} }
@ -3100,7 +3232,7 @@ namespace UnitTest
const AZ::Transform finalEntityTransform = AzToolsFramework::GetWorldTransform(m_entityIdBox); const AZ::Transform finalEntityTransform = AzToolsFramework::GetWorldTransform(m_entityIdBox);
const auto viewportRay = AzToolsFramework::ViewportInteraction::ViewportScreenToWorldRay(m_cameraState, initialPositionScreen); const auto viewportRay = AzToolsFramework::ViewportInteraction::ViewportScreenToWorldRay(m_cameraState, initialPositionScreen);
const auto distanceAway = (finalEntityTransform.GetTranslation() - viewportRay.origin).GetLength(); const auto distanceAway = (finalEntityTransform.GetTranslation() - viewportRay.m_origin).GetLength();
// ensure final world positions match // ensure final world positions match
EXPECT_THAT(finalEntityTransform, IsCloseTolerance(finalTransformWorld, 0.01f)); EXPECT_THAT(finalEntityTransform, IsCloseTolerance(finalTransformWorld, 0.01f));

@ -62,7 +62,6 @@ namespace UnitTest
void BrowseForAssets(AssetBrowser::AssetSelectionModel& /*selection*/) override {} void BrowseForAssets(AssetBrowser::AssetSelectionModel& /*selection*/) override {}
int GetIconTextureIdFromEntityIconPath(const AZStd::string& entityIconPath) override { AZ_UNUSED(entityIconPath); return 0; } int GetIconTextureIdFromEntityIconPath(const AZStd::string& entityIconPath) override { AZ_UNUSED(entityIconPath); return 0; }
bool DisplayHelpersVisible() override { return false; }
void GoToSelectedEntitiesInViewports() override void GoToSelectedEntitiesInViewports() override
{ {

@ -8,9 +8,9 @@
#include <Tests/FocusMode/EditorFocusModeSelectionFixture.h> #include <Tests/FocusMode/EditorFocusModeSelectionFixture.h>
namespace AzToolsFramework namespace UnitTest
{ {
TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithNoContainers) TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionFindHighestSelectableEntityWithNoContainers)
{ {
// When no containers are in the way, the function will just return the entityId of the entity that was clicked. // When no containers are in the way, the function will just return the entityId of the entity that was clicked.
@ -23,7 +23,7 @@ namespace AzToolsFramework
EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]); EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]);
} }
TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithClosedContainer) TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionFindHighestSelectableEntityWithClosedContainer)
{ {
// If a closed container is an ancestor of the queried entity, the closed container is selected. // If a closed container is an ancestor of the queried entity, the closed container is selected.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); // Containers are closed by default m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); // Containers are closed by default
@ -40,7 +40,7 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
} }
TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithOpenContainer) TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionFindHighestSelectableEntityWithOpenContainer)
{ {
// If a closed container is an ancestor of the queried entity, the closed container is selected. // If a closed container is an ancestor of the queried entity, the closed container is selected.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
@ -58,7 +58,7 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
} }
TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithMultipleClosedContainers) TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionFindHighestSelectableEntityWithMultipleClosedContainers)
{ {
// If multiple closed containers are ancestors of the queried entity, the highest closed container is selected. // If multiple closed containers are ancestors of the queried entity, the highest closed container is selected.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
@ -77,7 +77,7 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
} }
TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionTests_FindHighestSelectableEntityWithMultipleContainers) TEST_F(EditorFocusModeSelectionFixture, ContainerEntitySelectionFindHighestSelectableEntityWithMultipleContainers)
{ {
// If multiple containers are ancestors of the queried entity, the highest closed container is selected. // If multiple containers are ancestors of the queried entity, the highest closed container is selected.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
@ -96,4 +96,4 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
} }
} } // namespace UnitTest

@ -8,9 +8,9 @@
#include <Tests/FocusMode/EditorFocusModeFixture.h> #include <Tests/FocusMode/EditorFocusModeFixture.h>
namespace AzToolsFramework namespace UnitTest
{ {
TEST_F(EditorFocusModeFixture, ContainerEntityTests_Register) TEST_F(EditorFocusModeFixture, ContainerEntityRegister)
{ {
// Registering an entity is successful. // Registering an entity is successful.
auto outcome = m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]); auto outcome = m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]);
@ -20,7 +20,7 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_RegisterTwice) TEST_F(EditorFocusModeFixture, ContainerEntityRegisterTwice)
{ {
// Registering an entity twice fails. // Registering an entity twice fails.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]);
@ -31,7 +31,7 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_Unregister) TEST_F(EditorFocusModeFixture, ContainerEntityUnregister)
{ {
// Unregistering a container entity is successful. // Unregistering a container entity is successful.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CarEntityName]);
@ -39,21 +39,21 @@ namespace AzToolsFramework
EXPECT_TRUE(outcome.IsSuccess()); EXPECT_TRUE(outcome.IsSuccess());
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_UnregisterRegularEntity) TEST_F(EditorFocusModeFixture, ContainerEntityUnregisterRegularEntity)
{ {
// Unregistering an entity that was not previously registered fails. // Unregistering an entity that was not previously registered fails.
auto outcome = m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]); auto outcome = m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]);
EXPECT_FALSE(outcome.IsSuccess()); EXPECT_FALSE(outcome.IsSuccess());
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_UnregisterTwice) TEST_F(EditorFocusModeFixture, ContainerEntityUnregisterTwice)
{ {
// Unregistering a container entity twice fails. // Unregistering a container entity twice fails.
auto outcome = m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]); auto outcome = m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CarEntityName]);
EXPECT_FALSE(outcome.IsSuccess()); EXPECT_FALSE(outcome.IsSuccess());
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOnRegularEntity) TEST_F(EditorFocusModeFixture, ContainerEntityIsContainerOnRegularEntity)
{ {
// If a regular entity is passed, IsContainer returns false. // If a regular entity is passed, IsContainer returns false.
// Note that we use a different entity than the tests above to validate a completely new EntityId. // Note that we use a different entity than the tests above to validate a completely new EntityId.
@ -61,7 +61,7 @@ namespace AzToolsFramework
EXPECT_FALSE(isContainer); EXPECT_FALSE(isContainer);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOnRegisteredContainer) TEST_F(EditorFocusModeFixture, ContainerEntityIsContainerOnRegisteredContainer)
{ {
// If a container entity is passed, IsContainer returns true. // If a container entity is passed, IsContainer returns true.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
@ -72,7 +72,7 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOnUnRegisteredContainer) TEST_F(EditorFocusModeFixture, ContainerEntityIsContainerOnUnRegisteredContainer)
{ {
// If an entity that was previously a container but was then unregistered is passed, IsContainer returns false. // If an entity that was previously a container but was then unregistered is passed, IsContainer returns false.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
@ -82,14 +82,14 @@ namespace AzToolsFramework
EXPECT_FALSE(isContainer); EXPECT_FALSE(isContainer);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_SetContainerOpenOnRegularEntity) TEST_F(EditorFocusModeFixture, ContainerEntitySetContainerOpenOnRegularEntity)
{ {
// Setting a regular entity to open should return a failure. // Setting a regular entity to open should return a failure.
auto outcome = m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true); auto outcome = m_containerEntityInterface->SetContainerOpen(m_entityMap[StreetEntityName], true);
EXPECT_FALSE(outcome.IsSuccess()); EXPECT_FALSE(outcome.IsSuccess());
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_SetContainerOpen) TEST_F(EditorFocusModeFixture, ContainerEntitySetContainerOpen)
{ {
// Set a container entity to open, and verify the operation was successful. // Set a container entity to open, and verify the operation was successful.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
@ -100,7 +100,7 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_SetContainerOpenTwice) TEST_F(EditorFocusModeFixture, ContainerEntitySetContainerOpenTwice)
{ {
// Set a container entity to open twice, and verify that does not cause a failure (as intended). // Set a container entity to open twice, and verify that does not cause a failure (as intended).
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
@ -112,7 +112,7 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_SetContainerClosed) TEST_F(EditorFocusModeFixture, ContainerEntitySetContainerClosed)
{ {
// Set a container entity to closed, and verify the operation was successful. // Set a container entity to closed, and verify the operation was successful.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
@ -123,7 +123,7 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOpenOnRegularEntity) TEST_F(EditorFocusModeFixture, ContainerEntityIsContainerOpenOnRegularEntity)
{ {
// Query open state on a regular entity, and verify it returns true. // Query open state on a regular entity, and verify it returns true.
// Open containers behave exactly as regular entities, so this is the expected return value. // Open containers behave exactly as regular entities, so this is the expected return value.
@ -131,7 +131,7 @@ namespace AzToolsFramework
EXPECT_TRUE(isOpen); EXPECT_TRUE(isOpen);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOpenOnDefaultContainerEntity) TEST_F(EditorFocusModeFixture, ContainerEntityIsContainerOpenOnDefaultContainerEntity)
{ {
// Query open state on a newly registered container entity, and verify it returns false. // Query open state on a newly registered container entity, and verify it returns false.
// Containers are registered closed by default. // Containers are registered closed by default.
@ -143,7 +143,7 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOpenOnOpenContainerEntity) TEST_F(EditorFocusModeFixture, ContainerEntityIsContainerOpenOnOpenContainerEntity)
{ {
// Query open state on a container entity that was opened, and verify it returns true. // Query open state on a container entity that was opened, and verify it returns true.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
@ -155,7 +155,7 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_IsContainerOpenOnClosedContainerEntity) TEST_F(EditorFocusModeFixture, ContainerEntityIsContainerOpenOnClosedContainerEntity)
{ {
// Query open state on a container entity that was opened and then closed, and verify it returns false. // Query open state on a container entity that was opened and then closed, and verify it returns false.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[CityEntityName]);
@ -168,7 +168,7 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_ContainerOpenStateIsPreserved) TEST_F(EditorFocusModeFixture, ContainerEntityContainerOpenStateIsPreserved)
{ {
// Register an entity as container, open it, then unregister it. // Register an entity as container, open it, then unregister it.
// When the entity is registered again, the open state should be preserved. // When the entity is registered again, the open state should be preserved.
@ -185,14 +185,14 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[CityEntityName]);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_ClearSucceeds) TEST_F(EditorFocusModeFixture, ContainerEntityClearSucceeds)
{ {
// The Clear function works if no container is registered. // The Clear function works if no container is registered.
auto outcome = m_containerEntityInterface->Clear(m_editorEntityContextId); auto outcome = m_containerEntityInterface->Clear(m_editorEntityContextId);
EXPECT_TRUE(outcome.IsSuccess()); EXPECT_TRUE(outcome.IsSuccess());
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_ClearFailsIfContainersAreStillRegistered) TEST_F(EditorFocusModeFixture, ContainerEntityClearFailsIfContainersAreStillRegistered)
{ {
// The Clear function fails if a container is registered. // The Clear function fails if a container is registered.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[Passenger1EntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
@ -203,7 +203,7 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[Passenger1EntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_ClearSucceedsIfContainersAreUnregistered) TEST_F(EditorFocusModeFixture, ContainerEntityClearSucceedsIfContainersAreUnregistered)
{ {
// The Clear function fails if a container is registered. // The Clear function fails if a container is registered.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[Passenger1EntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
@ -212,7 +212,7 @@ namespace AzToolsFramework
EXPECT_TRUE(outcome.IsSuccess()); EXPECT_TRUE(outcome.IsSuccess());
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_ClearDeletesPreservedOpenStates) TEST_F(EditorFocusModeFixture, ContainerEntityClearDeletesPreservedOpenStates)
{ {
// Register an entity as container, open it, unregister it, then call clear. // Register an entity as container, open it, unregister it, then call clear.
// When the entity is registered again, the open state should not be preserved. // When the entity is registered again, the open state should not be preserved.
@ -230,14 +230,14 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[Passenger1EntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[Passenger1EntityName]);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithNoContainers) TEST_F(EditorFocusModeFixture, ContainerEntityFindHighestSelectableEntityWithNoContainers)
{ {
// When no containers are in the way, the function will just return the entityId that was passed to it. // When no containers are in the way, the function will just return the entityId that was passed to it.
AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]); AZ::EntityId selectedEntityId = m_containerEntityInterface->FindHighestSelectableEntity(m_entityMap[Passenger2EntityName]);
EXPECT_EQ(selectedEntityId, m_entityMap[Passenger2EntityName]); EXPECT_EQ(selectedEntityId, m_entityMap[Passenger2EntityName]);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithClosedContainer) TEST_F(EditorFocusModeFixture, ContainerEntityFindHighestSelectableEntityWithClosedContainer)
{ {
// If a closed container is an ancestor of the queried entity, the closed container is selected. // If a closed container is an ancestor of the queried entity, the closed container is selected.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]); // Containers are closed by default m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]); // Containers are closed by default
@ -248,7 +248,7 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithOpenContainer) TEST_F(EditorFocusModeFixture, ContainerEntityFindHighestSelectableEntityWithOpenContainer)
{ {
// If an open container is an ancestor of the queried entity, it is ignored. // If an open container is an ancestor of the queried entity, it is ignored.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
@ -261,7 +261,7 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithMultipleClosedContainers) TEST_F(EditorFocusModeFixture, ContainerEntityFindHighestSelectableEntityWithMultipleClosedContainers)
{ {
// If multiple closed containers are ancestors of the queried entity, the highest closed container is selected. // If multiple closed containers are ancestors of the queried entity, the highest closed container is selected.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
@ -275,7 +275,7 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
} }
TEST_F(EditorFocusModeFixture, ContainerEntityTests_FindHighestSelectableEntityWithMultipleContainers) TEST_F(EditorFocusModeFixture, ContainerEntityFindHighestSelectableEntityWithMultipleContainers)
{ {
// If multiple containers are ancestors of the queried entity, the highest closed container is selected. // If multiple containers are ancestors of the queried entity, the highest closed container is selected.
m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]); m_containerEntityInterface->RegisterEntityAsContainer(m_entityMap[StreetEntityName]);
@ -289,5 +289,4 @@ namespace AzToolsFramework
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[StreetEntityName]);
m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]); m_containerEntityInterface->UnregisterEntityAsContainer(m_entityMap[SportsCarEntityName]);
} }
} // namespace UnitTest
}

@ -12,7 +12,7 @@
#include <Tests/BoundsTestComponent.h> #include <Tests/BoundsTestComponent.h>
namespace AzToolsFramework namespace UnitTest
{ {
void ClearSelectedEntities() void ClearSelectedEntities()
{ {
@ -35,10 +35,10 @@ namespace AzToolsFramework
// in the unit tests. // in the unit tests.
AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize); AZ::UserSettingsComponentRequestBus::Broadcast(&AZ::UserSettingsComponentRequests::DisableSaveOnFinalize);
m_containerEntityInterface = AZ::Interface<ContainerEntityInterface>::Get(); m_containerEntityInterface = AZ::Interface<AzToolsFramework::ContainerEntityInterface>::Get();
ASSERT_TRUE(m_containerEntityInterface != nullptr); ASSERT_TRUE(m_containerEntityInterface != nullptr);
m_focusModeInterface = AZ::Interface<FocusModeInterface>::Get(); m_focusModeInterface = AZ::Interface<AzToolsFramework::FocusModeInterface>::Get();
ASSERT_TRUE(m_focusModeInterface != nullptr); ASSERT_TRUE(m_focusModeInterface != nullptr);
// register a simple component implementing BoundsRequestBus and EditorComponentSelectionRequestsBus // register a simple component implementing BoundsRequestBus and EditorComponentSelectionRequestsBus
@ -87,7 +87,7 @@ namespace AzToolsFramework
m_entityMap[Passenger2EntityName] = CreateEditorEntity(Passenger2EntityName, m_entityMap[SportsCarEntityName]); m_entityMap[Passenger2EntityName] = CreateEditorEntity(Passenger2EntityName, m_entityMap[SportsCarEntityName]);
// Add a BoundsTestComponent to the Car entity. // Add a BoundsTestComponent to the Car entity.
AZ::Entity* entity = GetEntityById(m_entityMap[CarEntityName]); AZ::Entity* entity = AzToolsFramework::GetEntityById(m_entityMap[CarEntityName]);
entity->Deactivate(); entity->Deactivate();
entity->CreateComponent<UnitTest::BoundsTestComponent>(); entity->CreateComponent<UnitTest::BoundsTestComponent>();
@ -113,4 +113,4 @@ namespace AzToolsFramework
return entity->GetId(); return entity->GetId();
} }
} } // namespace UnitTest

@ -18,10 +18,9 @@
#include <AzToolsFramework/FocusMode/FocusModeInterface.h> #include <AzToolsFramework/FocusMode/FocusModeInterface.h>
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h> #include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
namespace AzToolsFramework namespace UnitTest
{ {
class EditorFocusModeFixture class EditorFocusModeFixture : public ToolsApplicationFixture
: public UnitTest::ToolsApplicationFixture
{ {
protected: protected:
void SetUpEditorFixtureImpl() override; void SetUpEditorFixtureImpl() override;
@ -32,8 +31,8 @@ namespace AzToolsFramework
AZStd::unordered_map<AZStd::string, AZ::EntityId> m_entityMap; AZStd::unordered_map<AZStd::string, AZ::EntityId> m_entityMap;
ContainerEntityInterface* m_containerEntityInterface = nullptr; AzToolsFramework::ContainerEntityInterface* m_containerEntityInterface = nullptr;
FocusModeInterface* m_focusModeInterface = nullptr; AzToolsFramework::FocusModeInterface* m_focusModeInterface = nullptr;
public: public:
AzToolsFramework::EntityIdList GetSelectedEntities(); AzToolsFramework::EntityIdList GetSelectedEntities();
@ -53,4 +52,4 @@ namespace AzToolsFramework
inline static AZ::Vector3 WorldCarEntityPosition = AZ::Vector3(5.0f, 15.0f, 0.0f); inline static AZ::Vector3 WorldCarEntityPosition = AZ::Vector3(5.0f, 15.0f, 0.0f);
}; };
} } // namespace UnitTest

@ -26,11 +26,17 @@
#include <AzToolsFramework/Manipulators/ManipulatorManager.h> #include <AzToolsFramework/Manipulators/ManipulatorManager.h>
#include <AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h> #include <AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h>
namespace AzToolsFramework namespace UnitTest
{ {
class EditorFocusModeSelectionFixture : public UnitTest::IndirectCallManipulatorViewportInteractionFixtureMixin<EditorFocusModeFixture> class EditorFocusModeSelectionFixture : public IndirectCallManipulatorViewportInteractionFixtureMixin<EditorFocusModeFixture>
{ {
public: public:
void SetUpEditorFixtureImpl() override
{
IndirectCallManipulatorViewportInteractionFixtureMixin<EditorFocusModeFixture>::SetUpEditorFixtureImpl();
m_viewportManipulatorInteraction->GetViewportInteraction().SetIconsVisible(false);
}
void ClickAtWorldPositionOnViewport(const AZ::Vector3& worldPosition) void ClickAtWorldPositionOnViewport(const AZ::Vector3& worldPosition)
{ {
// Calculate the world position in screen space // Calculate the world position in screen space
@ -40,4 +46,4 @@ namespace AzToolsFramework
m_actionDispatcher->CameraState(m_cameraState)->MousePosition(carScreenPosition)->MouseLButtonDown()->MouseLButtonUp(); m_actionDispatcher->CameraState(m_cameraState)->MousePosition(carScreenPosition)->MouseLButtonDown()->MouseLButtonUp();
} }
}; };
} // namespace AzToolsFramework } // namespace UnitTest

@ -8,9 +8,9 @@
#include <Tests/FocusMode/EditorFocusModeSelectionFixture.h> #include <Tests/FocusMode/EditorFocusModeSelectionFixture.h>
namespace AzToolsFramework namespace UnitTest
{ {
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnLevel) TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionSelectEntityWithFocusOnLevel)
{ {
// Click on Car Entity // Click on Car Entity
ClickAtWorldPositionOnViewport(WorldCarEntityPosition); ClickAtWorldPositionOnViewport(WorldCarEntityPosition);
@ -21,7 +21,7 @@ namespace AzToolsFramework
EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]); EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]);
} }
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnAncestor) TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionSelectEntityWithFocusOnAncestor)
{ {
// Set the focus on the Street Entity (parent of the test entity) // Set the focus on the Street Entity (parent of the test entity)
m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]); m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]);
@ -35,7 +35,7 @@ namespace AzToolsFramework
EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]); EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]);
} }
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnItself) TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionSelectEntityWithFocusOnItself)
{ {
// Set the focus on the Car Entity (test entity) // Set the focus on the Car Entity (test entity)
m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]); m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]);
@ -49,7 +49,7 @@ namespace AzToolsFramework
EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]); EXPECT_EQ(selectedEntitiesAfter.front(), m_entityMap[CarEntityName]);
} }
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnSibling) TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionSelectEntityWithFocusOnSibling)
{ {
// Set the focus on the SportsCar Entity (sibling of the test entity) // Set the focus on the SportsCar Entity (sibling of the test entity)
m_focusModeInterface->SetFocusRoot(m_entityMap[SportsCarEntityName]); m_focusModeInterface->SetFocusRoot(m_entityMap[SportsCarEntityName]);
@ -62,7 +62,7 @@ namespace AzToolsFramework
EXPECT_EQ(selectedEntitiesAfter.size(), 0); EXPECT_EQ(selectedEntitiesAfter.size(), 0);
} }
TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionTests_SelectEntityWithFocusOnDescendant) TEST_F(EditorFocusModeSelectionFixture, EditorFocusModeSelectionSelectEntityWithFocusOnDescendant)
{ {
// Set the focus on the Passenger1 Entity (child of the entity) // Set the focus on the Passenger1 Entity (child of the entity)
m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger1EntityName]); m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger1EntityName]);
@ -74,4 +74,4 @@ namespace AzToolsFramework
auto selectedEntitiesAfter = GetSelectedEntities(); auto selectedEntitiesAfter = GetSelectedEntities();
EXPECT_EQ(selectedEntitiesAfter.size(), 0); EXPECT_EQ(selectedEntitiesAfter.size(), 0);
} }
} } // namespace UnitTest

@ -8,9 +8,9 @@
#include <Tests/FocusMode/EditorFocusModeFixture.h> #include <Tests/FocusMode/EditorFocusModeFixture.h>
namespace AzToolsFramework namespace UnitTest
{ {
TEST_F(EditorFocusModeFixture, EditorFocusModeTests_SetFocus) TEST_F(EditorFocusModeFixture, SetFocus)
{ {
// When an entity is set as the focus root, GetFocusRoot should return its EntityId. // When an entity is set as the focus root, GetFocusRoot should return its EntityId.
m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]); m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]);
@ -20,7 +20,7 @@ namespace AzToolsFramework
m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId); m_focusModeInterface->ClearFocusRoot(m_editorEntityContextId);
} }
TEST_F(EditorFocusModeFixture, EditorFocusModeTests_ClearFocus) TEST_F(EditorFocusModeFixture, ClearFocus)
{ {
// Change the value from the default. // Change the value from the default.
m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]); m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]);
@ -30,7 +30,7 @@ namespace AzToolsFramework
EXPECT_EQ(m_focusModeInterface->GetFocusRoot(m_editorEntityContextId), AZ::EntityId()); EXPECT_EQ(m_focusModeInterface->GetFocusRoot(m_editorEntityContextId), AZ::EntityId());
} }
TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_AncestorsDescendants) TEST_F(EditorFocusModeFixture, IsInFocusSubTreeAncestorsDescendants)
{ {
// When the focus is set to an entity, all its descendants are in the focus subtree while the ancestors aren't. // When the focus is set to an entity, all its descendants are in the focus subtree while the ancestors aren't.
m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]); m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]);
@ -43,7 +43,7 @@ namespace AzToolsFramework
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true); EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true);
} }
TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_Siblings) TEST_F(EditorFocusModeFixture, IsInFocusSubTreeSiblings)
{ {
// If the root entity has siblings, they are also outside of the focus subtree. // If the root entity has siblings, they are also outside of the focus subtree.
m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]); m_focusModeInterface->SetFocusRoot(m_entityMap[CarEntityName]);
@ -56,7 +56,7 @@ namespace AzToolsFramework
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), false); EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), false);
} }
TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_Leaf) TEST_F(EditorFocusModeFixture, IsInFocusSubTreeLeaf)
{ {
// If the root is a leaf, then the focus subtree will consists of just that entity. // If the root is a leaf, then the focus subtree will consists of just that entity.
m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger2EntityName]); m_focusModeInterface->SetFocusRoot(m_entityMap[Passenger2EntityName]);
@ -69,7 +69,7 @@ namespace AzToolsFramework
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true); EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true);
} }
TEST_F(EditorFocusModeFixture, EditorFocusModeTests_IsInFocusSubTree_Clear) TEST_F(EditorFocusModeFixture, IsInFocusSubTreeClear)
{ {
// Change the value from the default. // Change the value from the default.
m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]); m_focusModeInterface->SetFocusRoot(m_entityMap[StreetEntityName]);
@ -84,4 +84,4 @@ namespace AzToolsFramework
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), true); EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[SportsCarEntityName]), true);
EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true); EXPECT_EQ(m_focusModeInterface->IsInFocusSubTree(m_entityMap[Passenger2EntityName]), true);
} }
} } // namespace UnitTest

@ -137,7 +137,6 @@ namespace UnitTest
void CreateEditorRepresentation(AZ::Entity* entity) override; void CreateEditorRepresentation(AZ::Entity* entity) override;
void BrowseForAssets(AzToolsFramework::AssetBrowser::AssetSelectionModel& selection) override { AZ_UNUSED(selection); } void BrowseForAssets(AzToolsFramework::AssetBrowser::AssetSelectionModel& selection) override { AZ_UNUSED(selection); }
int GetIconTextureIdFromEntityIconPath(const AZStd::string& entityIconPath) override { AZ_UNUSED(entityIconPath); return 0; } int GetIconTextureIdFromEntityIconPath(const AZStd::string& entityIconPath) override { AZ_UNUSED(entityIconPath); return 0; }
bool DisplayHelpersVisible() override { return false; }
/* /*
* AssetSystemRequestBus * AssetSystemRequestBus

@ -243,7 +243,6 @@ namespace UnitTest
// These are required by implementing the EditorRequestBus // These are required by implementing the EditorRequestBus
void BrowseForAssets(AssetBrowser::AssetSelectionModel& /*selection*/) override {} void BrowseForAssets(AssetBrowser::AssetSelectionModel& /*selection*/) override {}
int GetIconTextureIdFromEntityIconPath([[maybe_unused]] const AZStd::string& entityIconPath) override { return 0; } int GetIconTextureIdFromEntityIconPath([[maybe_unused]] const AZStd::string& entityIconPath) override { return 0; }
bool DisplayHelpersVisible() override { return false; }
public: public:
EntityPropertyEditor* m_levelEditor; EntityPropertyEditor* m_levelEditor;

@ -41,7 +41,8 @@
"PassData": { "PassData": {
"$type": "RasterPassData", "$type": "RasterPassData",
"DrawListTag": "2dpass", "DrawListTag": "2dpass",
"PipelineViewTag": "MainCamera" "PipelineViewTag": "MainCamera",
"DrawListSortType": "KeyThenReverseDepth"
} }
}, },
{ {

@ -167,7 +167,8 @@ namespace UnitTest
const auto ray = m_viewportInteractionImpl->ViewportScreenToWorldRay(ScreenPoint(832, 226)); const auto ray = m_viewportInteractionImpl->ViewportScreenToWorldRay(ScreenPoint(832, 226));
float unused; float unused;
auto intersection = AZ::Intersect::IntersectRaySphere(ray.origin, ray.direction, AZ::Vector3(-14.0f, 5.7f, 0.75f), 0.5f, unused); auto intersection =
AZ::Intersect::IntersectRaySphere(ray.m_origin, ray.m_direction, AZ::Vector3(-14.0f, 5.7f, 0.75f), 0.5f, unused);
EXPECT_EQ(intersection, AZ::Intersect::SphereIsectTypes::ISECT_RAY_SPHERE_ISECT); EXPECT_EQ(intersection, AZ::Intersect::SphereIsectTypes::ISECT_RAY_SPHERE_ISECT);
} }

@ -8,6 +8,7 @@
#include "AtomViewportDisplayIconsSystemComponent.h" #include "AtomViewportDisplayIconsSystemComponent.h"
#include <AzCore/Math/VectorConversions.h>
#include <AzCore/Serialization/SerializeContext.h> #include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h> #include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/EditContextConstants.inl> #include <AzCore/Serialization/EditContextConstants.inl>
@ -117,8 +118,7 @@ namespace AZ::Render
return; return;
} }
auto perViewportDynamicDrawInterface = auto perViewportDynamicDrawInterface = AtomBridge::PerViewportDynamicDraw::Get();
AtomBridge::PerViewportDynamicDraw::Get();
if (!perViewportDynamicDrawInterface) if (!perViewportDynamicDrawInterface)
{ {
return; return;
@ -131,7 +131,7 @@ namespace AZ::Render
return; return;
} }
// Find our icon, falling back on a grey placeholder if its image is unavailable // Find our icon, falling back on a gray placeholder if its image is unavailable
AZ::Data::Instance<AZ::RPI::Image> image = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::Grey); AZ::Data::Instance<AZ::RPI::Image> image = AZ::RPI::ImageSystemInterface::Get()->GetSystemImage(AZ::RPI::SystemImage::Grey);
if (auto iconIt = m_iconData.find(drawParameters.m_icon); iconIt != m_iconData.end()) if (auto iconIt = m_iconData.find(drawParameters.m_icon); iconIt != m_iconData.end())
{ {
@ -172,13 +172,16 @@ namespace AZ::Render
} }
else if (drawParameters.m_positionSpace == CoordinateSpace::WorldSpace) else if (drawParameters.m_positionSpace == CoordinateSpace::WorldSpace)
{ {
// Calculate the ndc point (0.0-1.0 range) including depth
const AZ::Vector3 ndcPoint = AzFramework::WorldToScreenNdc(
drawParameters.m_position, viewportContext->GetCameraViewMatrixAsMatrix3x4(),
viewportContext->GetCameraProjectionMatrix());
// Calculate our screen space position using the viewport size // Calculate our screen space position using the viewport size
// We want this instead of RenderViewportWidget::WorldToScreen which works in QWidget virtual coordinate space // We want this instead of RenderViewportWidget::WorldToScreen which works in QWidget virtual coordinate space
const AzFramework::ScreenPoint position = AzFramework::WorldToScreen( const AzFramework::ScreenPoint screenPoint = AzFramework::ScreenPointFromNdc(AZ::Vector3ToVector2(ndcPoint), viewportSize);
drawParameters.m_position, viewportContext->GetCameraViewMatrixAsMatrix3x4(),
viewportContext->GetCameraProjectionMatrix(), viewportSize); screenPosition = AzFramework::Vector3FromScreenPoint(screenPoint, ndcPoint.GetZ());
screenPosition.SetX(aznumeric_cast<float>(position.m_x));
screenPosition.SetY(aznumeric_cast<float>(position.m_y));
} }
struct Vertex struct Vertex
@ -210,7 +213,12 @@ namespace AZ::Render
createVertex(-0.5f, 0.5f, 0.f, 1.f) createVertex(-0.5f, 0.5f, 0.f, 1.f)
}; };
AZStd::array<Indice, 6> indices = {0, 1, 2, 0, 2, 3}; AZStd::array<Indice, 6> indices = {0, 1, 2, 0, 2, 3};
dynamicDraw->DrawIndexed(&vertices, static_cast<uint32_t>(vertices.size()), &indices, static_cast<uint32_t>(indices.size()), RHI::IndexFormat::Uint16, drawSrg);
dynamicDraw->SetSortKey(
aznumeric_cast<int64_t>(screenPosition.GetZ() * aznumeric_cast<float>(AZStd::numeric_limits<int64_t>::max())));
dynamicDraw->DrawIndexed(
&vertices, static_cast<uint32_t>(vertices.size()), &indices, static_cast<uint32_t>(indices.size()), RHI::IndexFormat::Uint16,
drawSrg);
} }
QString AtomViewportDisplayIconsSystemComponent::FindAssetPath(const QString& path) const QString AtomViewportDisplayIconsSystemComponent::FindAssetPath(const QString& path) const
@ -354,7 +362,7 @@ namespace AZ::Render
{ {
// Once the shader is loaded, register it with the dynamic draw context // Once the shader is loaded, register it with the dynamic draw context
Data::Asset<RPI::ShaderAsset> shaderAsset = asset; Data::Asset<RPI::ShaderAsset> shaderAsset = asset;
AtomBridge::PerViewportDynamicDraw::Get()->RegisterDynamicDrawContext(m_drawContextName, [shaderAsset](RPI::Ptr<RPI::DynamicDrawContext> drawContext) AtomBridge::PerViewportDynamicDraw::Get()->RegisterDynamicDrawContext(m_drawContextName, [shaderAsset](RPI::Ptr<RPI::DynamicDrawContext> dynamicDraw)
{ {
AZ_Assert(shaderAsset->IsReady(), "Attempting to register the AtomViewportDisplayIconsSystemComponent" AZ_Assert(shaderAsset->IsReady(), "Attempting to register the AtomViewportDisplayIconsSystemComponent"
" dynamic draw context before the shader asset is loaded. The shader should be loaded first" " dynamic draw context before the shader asset is loaded. The shader should be loaded first"
@ -362,12 +370,11 @@ namespace AZ::Render
" will be executed during scene processing and there may be multiple scenes executing in parallel."); " will be executed during scene processing and there may be multiple scenes executing in parallel.");
Data::Instance<RPI::Shader> shader = RPI::Shader::FindOrCreate(shaderAsset); Data::Instance<RPI::Shader> shader = RPI::Shader::FindOrCreate(shaderAsset);
drawContext->InitShader(shader); dynamicDraw->InitShader(shader);
drawContext->InitVertexFormat( dynamicDraw->InitVertexFormat({ { "POSITION", RHI::Format::R32G32B32_FLOAT },
{ {"POSITION", RHI::Format::R32G32B32_FLOAT},
{ "COLOR", RHI::Format::R8G8B8A8_UNORM }, { "COLOR", RHI::Format::R8G8B8A8_UNORM },
{ "TEXCOORD", RHI::Format::R32G32_FLOAT } }); { "TEXCOORD", RHI::Format::R32G32_FLOAT } });
drawContext->EndInit(); dynamicDraw->EndInit();
}); });
m_drawContextRegistered = true; m_drawContextRegistered = true;

@ -56,9 +56,9 @@ namespace PhysX
bool IsDrawColliderReadOnly() bool IsDrawColliderReadOnly()
{ {
bool helpersVisible = false; bool helpersVisible = false;
AzToolsFramework::EditorRequestBus::BroadcastResult(helpersVisible, AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::BroadcastResult(
&AzToolsFramework::EditorRequests::DisplayHelpersVisible); helpersVisible, &AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Events::HelpersVisible);
// if helpers are visible, draw colliders is NOT read only and can be changed. // if helpers are visible, draw colliders is not read only and can be changed
return !helpersVisible; return !helpersVisible;
} }

@ -720,7 +720,6 @@ namespace WhiteBox
// must have at least one triangle // must have at least one triangle
if (m_faces->empty()) if (m_faces->empty())
{ {
distance = std::numeric_limits<float>::max();
return false; return false;
} }
@ -735,7 +734,6 @@ namespace WhiteBox
const AZ::Vector3 localRayEnd = localRayOrigin + localRayDirection * rayLength; const AZ::Vector3 localRayEnd = localRayOrigin + localRayDirection * rayLength;
bool intersection = false; bool intersection = false;
distance = std::numeric_limits<float>::max();
for (const auto& face : m_faces.value()) for (const auto& face : m_faces.value())
{ {
float t; float t;

Loading…
Cancel
Save