Fix incorrect icon rendering (#6454)

* fix incorrect icon rendering

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

* add redundant parens

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

* add tests for icon display fixes

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

* update references to EditorVisibleEntityDataCache to EditorVisibleEntityDataCacheInterface

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

* updates following review feedback and remaining updates for EditorVisibleEntityDataCacheInterface

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 f5fcab75d6
commit dd0f21b460
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -47,8 +47,6 @@ namespace AzManipulatorTestFramework
virtual void UpdateVisibility() = 0;
//! Sets if sticky select is enabled or not.
virtual void SetStickySelect(bool enabled) = 0;
//! Gets default Editor Camera Position.
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.

@ -10,6 +10,7 @@
#include <AzFramework/Visibility/EntityVisibilityQuery.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
namespace AzFramework
{
@ -22,7 +23,7 @@ namespace AzManipulatorTestFramework
class ViewportInteraction
: public ViewportInteractionInterface
, public AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler
, public AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler
, public UnitTest::ViewportSettingsTestImpl
, private AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler
{
public:
@ -50,19 +51,6 @@ namespace AzManipulatorTestFramework
const AzFramework::ScreenPoint& screenPosition) override;
float DeviceScalingFactor() override;
// ViewportSettingsRequestBus overrides ...
bool GridSnappingEnabled() const override;
float GridSize() const override;
bool ShowGrid() const override;
bool AngleSnappingEnabled() const override;
float AngleStep() const override;
float ManipulatorLineBoundWidth() const override;
float ManipulatorCircleBoundWidth() const override;
bool StickySelectEnabled() const override;
AZ::Vector3 DefaultEditorCameraPosition() const override;
bool IconsVisible() const override;
bool HelpersVisible() const override;
// EditorEntityViewportInteractionRequestBus overrides ...
void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntities) override;
@ -72,12 +60,5 @@ namespace AzManipulatorTestFramework
AzFramework::EntityVisibilityQuery m_entityVisibilityQuery;
AZStd::shared_ptr<AzFramework::DebugDisplayRequests> m_debugDisplayRequests;
AzFramework::CameraState m_cameraState;
float m_gridSize = 1.0f;
float m_angularStep = 0.0f;
bool m_gridSnapping = false;
bool m_angularSnapping = false;
bool m_stickySelect = true;
bool m_iconsVisible = true;
bool m_helpersVisible = true;
};
} // namespace AzManipulatorTestFramework

@ -37,46 +37,6 @@ namespace AzManipulatorTestFramework
return m_cameraState;
}
bool ViewportInteraction::GridSnappingEnabled() const
{
return m_gridSnapping;
}
float ViewportInteraction::GridSize() const
{
return m_gridSize;
}
bool ViewportInteraction::ShowGrid() const
{
return false;
}
bool ViewportInteraction::AngleSnappingEnabled() const
{
return m_angularSnapping;
}
float ViewportInteraction::AngleStep() const
{
return m_angularStep;
}
float ViewportInteraction::ManipulatorLineBoundWidth() const
{
return 0.1f;
}
float ViewportInteraction::ManipulatorCircleBoundWidth() const
{
return 0.1f;
}
bool ViewportInteraction::StickySelectEnabled() const
{
return m_stickySelect;
}
void ViewportInteraction::FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntitiesOut)
{
visibleEntitiesOut.assign(m_entityVisibilityQuery.Begin(), m_entityVisibilityQuery.End());
@ -127,11 +87,6 @@ namespace AzManipulatorTestFramework
m_helpersVisible = visible;
}
AZ::Vector3 ViewportInteraction::DefaultEditorCameraPosition() const
{
return {};
}
void ViewportInteraction::SetGridSize(float size)
{
m_gridSize = size;
@ -162,14 +117,4 @@ namespace AzManipulatorTestFramework
{
return 1.0f;
}
bool ViewportInteraction::IconsVisible() const
{
return m_iconsVisible;
}
bool ViewportInteraction::HelpersVisible() const
{
return m_helpersVisible;
}
} // namespace AzManipulatorTestFramework

@ -122,7 +122,7 @@ namespace AzToolsFramework
EditorInteractionSystemViewportSelectionRequestBus::Event(
GetEntityContextId(), &EditorInteractionSystemViewportSelection::SetHandler,
[](const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
[](const EditorVisibleEntityDataCacheInterface* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
{
return AZStd::make_unique<EditorPickEntitySelection>(entityDataCache, viewportEditorModeTracker);
});

@ -90,6 +90,61 @@ namespace UnitTest
return AZStd::string(keyText.toUtf8().data());
}
bool ViewportSettingsTestImpl::GridSnappingEnabled() const
{
return m_gridSnapping;
}
float ViewportSettingsTestImpl::GridSize() const
{
return m_gridSize;
}
bool ViewportSettingsTestImpl::ShowGrid() const
{
return false;
}
bool ViewportSettingsTestImpl::AngleSnappingEnabled() const
{
return m_angularSnapping;
}
float ViewportSettingsTestImpl::AngleStep() const
{
return m_angularStep;
}
float ViewportSettingsTestImpl::ManipulatorLineBoundWidth() const
{
return 0.1f;
}
float ViewportSettingsTestImpl::ManipulatorCircleBoundWidth() const
{
return 0.1f;
}
bool ViewportSettingsTestImpl::StickySelectEnabled() const
{
return m_stickySelect;
}
bool ViewportSettingsTestImpl::IconsVisible() const
{
return m_iconsVisible;
}
bool ViewportSettingsTestImpl::HelpersVisible() const
{
return m_helpersVisible;
}
AZ::Vector3 ViewportSettingsTestImpl::DefaultEditorCameraPosition() const
{
return {};
}
bool TestWidget::eventFilter(QObject* watched, QEvent* event)
{
AZ_UNUSED(watched);

@ -91,6 +91,43 @@ namespace UnitTest
/// @param modifiers Optional keyboard modifiers to include during the wheel events, defaults to Qt::NoModifier
AZStd::string QtKeyToAzString(Qt::Key key, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
//! Test implementation of the ViewportSettingsRequestBus.
//! @note Can be used to customize viewport settings during test execution.
class ViewportSettingsTestImpl : public AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler
{
public:
void Connect(const AzFramework::ViewportId viewportId)
{
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler::BusConnect(viewportId);
}
void Disconnect()
{
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler::BusDisconnect();
}
// ViewportSettingsRequestBus overrides ...
bool GridSnappingEnabled() const override;
float GridSize() const override;
bool ShowGrid() const override;
bool AngleSnappingEnabled() const override;
float AngleStep() const override;
float ManipulatorLineBoundWidth() const override;
float ManipulatorCircleBoundWidth() const override;
bool StickySelectEnabled() const override;
AZ::Vector3 DefaultEditorCameraPosition() const override;
bool IconsVisible() const override;
bool HelpersVisible() const override;
float m_gridSize = 1.0f;
float m_angularStep = 0.0f;
bool m_gridSnapping = false;
bool m_angularSnapping = false;
bool m_stickySelect = true;
bool m_iconsVisible = true;
bool m_helpersVisible = true;
};
/// Test widget to store QActions generated by EditorTransformComponentSelection.
class TestWidget : public QWidget
{
@ -207,7 +244,7 @@ namespace UnitTest
m_editorActions.Connect();
const auto viewportHandlerBuilder =
[this](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache,
[this](const AzToolsFramework::EditorVisibleEntityDataCacheInterface* entityDataCache,
[[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
{
// create the default viewport (handles ComponentMode)

@ -0,0 +1,27 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzToolsFramework/API/EditorViewportIconDisplayInterface.h>
#include <gmock/gmock.h>
namespace UnitTest
{
class MockEditorViewportIconDisplayInterface : public AZ::Interface<AzToolsFramework::EditorViewportIconDisplayInterface>::Registrar
{
public:
virtual ~MockEditorViewportIconDisplayInterface() = default;
//! AzToolsFramework::EditorViewportIconDisplayInterface overrides ...
MOCK_METHOD1(DrawIcon, void(const DrawParameters&));
MOCK_METHOD1(GetOrLoadIconForPath, IconId(AZStd::string_view path));
MOCK_METHOD1(GetIconLoadStatus, IconLoadStatus(IconId icon));
};
} // namespace UnitTest

@ -0,0 +1,37 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h>
#include <gmock/gmock.h>
namespace UnitTest
{
class MockEditorVisibleEntityDataCacheInterface : public AzToolsFramework::EditorVisibleEntityDataCacheInterface
{
using ComponentEntityAccentType = AzToolsFramework::Components::EditorSelectionAccentSystemComponent::ComponentEntityAccentType;
public:
virtual ~MockEditorVisibleEntityDataCacheInterface() = default;
// AzToolsFramework::EditorVisibleEntityDataCacheInterface overrides ...
MOCK_CONST_METHOD0(VisibleEntityDataCount, size_t());
MOCK_CONST_METHOD1(GetVisibleEntityPosition, AZ::Vector3(size_t));
MOCK_CONST_METHOD1(GetVisibleEntityTransform, const AZ::Transform&(size_t));
MOCK_CONST_METHOD1(GetVisibleEntityId, AZ::EntityId(size_t));
MOCK_CONST_METHOD1(GetVisibleEntityAccent, ComponentEntityAccentType(size_t));
MOCK_CONST_METHOD1(IsVisibleEntityLocked, bool(size_t));
MOCK_CONST_METHOD1(IsVisibleEntityVisible, bool(size_t));
MOCK_CONST_METHOD1(IsVisibleEntitySelected, bool(size_t));
MOCK_CONST_METHOD1(IsVisibleEntityIconHidden, bool(size_t));
MOCK_CONST_METHOD1(IsVisibleEntityIndividuallySelectableInViewport, bool(size_t));
MOCK_CONST_METHOD1(GetVisibleEntityIndexFromId, AZStd::optional<size_t>(AZ::EntityId entityId));
};
} // namespace UnitTest

@ -0,0 +1,29 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <AzToolsFramework/FocusMode/FocusModeInterface.h>
#include <gmock/gmock.h>
namespace UnitTest
{
class MockFocusModeInterface : public AZ::Interface<AzToolsFramework::FocusModeInterface>::Registrar
{
public:
virtual ~MockFocusModeInterface() = default;
// AzToolsFramework::FocusModeInterface overrides ...
MOCK_METHOD1(SetFocusRoot, void(AZ::EntityId entityId));
MOCK_METHOD1(ClearFocusRoot, void(AzFramework::EntityContextId entityContextId));
MOCK_METHOD1(GetFocusRoot, AZ::EntityId(AzFramework::EntityContextId entityContextId));
MOCK_METHOD1(GetFocusedEntities, AzToolsFramework::EntityIdList(AzFramework::EntityContextId entityContextId));
MOCK_CONST_METHOD1(IsInFocusSubTree, bool(AZ::EntityId entityId));
};
} // namespace UnitTest

@ -21,9 +21,8 @@ namespace AzToolsFramework
AZ_CLASS_ALLOCATOR_IMPL(EditorDefaultSelection, AZ::SystemAllocator, 0)
EditorDefaultSelection::EditorDefaultSelection(
const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
const EditorVisibleEntityDataCacheInterface* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
: m_phantomWidget(nullptr)
, m_entityDataCache(entityDataCache)
, m_viewportEditorModeTracker(viewportEditorModeTracker)
, m_componentModeCollection(viewportEditorModeTracker)
{

@ -27,7 +27,8 @@ namespace AzToolsFramework
AZ_CLASS_ALLOCATOR_DECL
//! @cond
EditorDefaultSelection(const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker);
EditorDefaultSelection(
const EditorVisibleEntityDataCacheInterface* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker);
EditorDefaultSelection(const EditorDefaultSelection&) = delete;
EditorDefaultSelection& operator=(const EditorDefaultSelection&) = delete;
virtual ~EditorDefaultSelection();
@ -85,10 +86,8 @@ namespace AzToolsFramework
QWidget m_phantomWidget; //!< The phantom widget responsible for holding QActions while in ComponentMode.
QWidget* m_phantomOverrideWidget = nullptr; //!< It's possible to override the phantom widget in special circumstances (eg testing).
ComponentModeFramework::ComponentModeCollection m_componentModeCollection; //!< Handles all active ComponentMode types.
AZStd::unique_ptr<EditorTransformComponentSelection> m_transformComponentSelection =
nullptr; //!< Viewport selection (responsible for
//!< manipulators and transform modifications).
const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; //!< Reference to cached visible EntityData.
//! Viewport selection (responsible for manipulators and transform modifications).
AZStd::unique_ptr<EditorTransformComponentSelection> m_transformComponentSelection = nullptr;
//! Mapping between passed ActionOverride (AddActionOverride) and allocated QAction.
struct ActionOverrideMapping
@ -112,7 +111,7 @@ namespace AzToolsFramework
AZStd::shared_ptr<AzToolsFramework::ManipulatorManager> m_manipulatorManager; //!< The default manipulator manager.
ViewportInteraction::MouseInteraction m_currentInteraction; //!< Current mouse interaction to be used for drawing manipulators.
ViewportEditorModeTrackerInterface* m_viewportEditorModeTracker = nullptr; //!< Tracker for activating/deactivating viewport editor modes.
//! Tracker for activating/deactivating viewport editor modes.
ViewportEditorModeTrackerInterface* m_viewportEditorModeTracker = nullptr;
};
} // namespace AzToolsFramework

@ -159,7 +159,7 @@ namespace AzToolsFramework
return false;
}
EditorHelpers::EditorHelpers(const EditorVisibleEntityDataCache* entityDataCache)
EditorHelpers::EditorHelpers(const EditorVisibleEntityDataCacheInterface* entityDataCache)
: m_entityDataCache(entityDataCache)
{
m_focusModeInterface = AZ::Interface<FocusModeInterface>::Get();
@ -344,9 +344,19 @@ namespace AzToolsFramework
continue;
}
int iconTextureId = 0;
EditorEntityIconComponentRequestBus::EventResult(
iconTextureId, entityId, &EditorEntityIconComponentRequests::GetEntityIconTextureId);
const AZ::Vector3& entityPosition = m_entityDataCache->GetVisibleEntityPosition(entityCacheIndex);
const AZ::Vector3 entityCameraVector = entityPosition - cameraState.m_position;
if (const float directionFromCamera = entityCameraVector.Dot(cameraState.m_forward); directionFromCamera < 0.0f)
{
continue;
}
const float distanceFromCamera = entityCameraVector.GetLength();
if (distanceFromCamera < cameraState.m_nearClip)
{
continue;
}
using ComponentEntityAccentType = Components::EditorSelectionAccentSystemComponent::ComponentEntityAccentType;
const AZ::Color iconHighlight = [this, entityCacheIndex]()
@ -364,13 +374,13 @@ namespace AzToolsFramework
return AZ::Color(1.0f, 1.0f, 1.0f, 1.0f);
}();
const AZ::Vector3& entityPosition = m_entityDataCache->GetVisibleEntityPosition(entityCacheIndex);
const float distanceFromCamera = cameraState.m_position.GetDistance(entityPosition);
const float iconSize = GetIconSize(distanceFromCamera);
int iconTextureId = 0;
EditorEntityIconComponentRequestBus::EventResult(
iconTextureId, entityId, &EditorEntityIconComponentRequestBus::Events::GetEntityIconTextureId);
editorViewportIconDisplay->DrawIcon({ viewportInfo.m_viewportId, iconTextureId, iconHighlight, entityPosition,
EditorViewportIconDisplayInterface::CoordinateSpace::WorldSpace,
AZ::Vector2{ iconSize, iconSize } });
editorViewportIconDisplay->DrawIcon(EditorViewportIconDisplayInterface::DrawParameters{
viewportInfo.m_viewportId, iconTextureId, iconHighlight, entityPosition,
EditorViewportIconDisplayInterface::CoordinateSpace::WorldSpace, AZ::Vector2(GetIconSize(distanceFromCamera)) });
}
}
}

@ -24,7 +24,7 @@ namespace AzFramework
namespace AzToolsFramework
{
class EditorVisibleEntityDataCache;
class EditorVisibleEntityDataCacheInterface;
class FocusModeInterface;
namespace ViewportInteraction
@ -64,7 +64,7 @@ namespace AzToolsFramework
//! An EditorVisibleEntityDataCache must be passed to EditorHelpers to allow it to
//! efficiently read entity data without resorting to EBus calls.
explicit EditorHelpers(const EditorVisibleEntityDataCache* entityDataCache);
explicit EditorHelpers(const EditorVisibleEntityDataCacheInterface* entityDataCache);
EditorHelpers(const EditorHelpers&) = delete;
EditorHelpers& operator=(const EditorHelpers&) = delete;
~EditorHelpers() = default;
@ -103,7 +103,7 @@ namespace AzToolsFramework
AZStd::unique_ptr<InvalidClicks> m_invalidClicks; //!< Display for invalid click behavior.
const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; //!< Entity Data queried by the EditorHelpers.
const EditorVisibleEntityDataCacheInterface* m_entityDataCache = nullptr; //!< Entity Data queried by the EditorHelpers.
const FocusModeInterface* m_focusModeInterface = nullptr; //!< API to interact with focus mode functionality.
};

@ -84,7 +84,7 @@ namespace AzToolsFramework
void EditorInteractionSystemComponent::SetDefaultHandler()
{
SetHandler(
[](const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
[](const EditorVisibleEntityDataCacheInterface* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
{
return AZStd::make_unique<EditorDefaultSelection>(entityDataCache, viewportEditorModeTracker);
});

@ -16,7 +16,7 @@
namespace AzToolsFramework
{
class EditorVisibleEntityDataCache;
class EditorVisibleEntityDataCacheInterface;
class ViewportEditorModeTrackerInterface;
//! Bus to handle all mouse events originating from the viewport.
@ -34,7 +34,7 @@ namespace AzToolsFramework
//! Alias for factory function to create a new type implementing the ViewportSelectionRequests interface.
using ViewportSelectionRequestsBuilderFn = AZStd::function<AZStd::unique_ptr<ViewportInteraction::InternalViewportSelectionRequests>(
const EditorVisibleEntityDataCache*, ViewportEditorModeTrackerInterface*)>;
const EditorVisibleEntityDataCacheInterface*, ViewportEditorModeTrackerInterface*)>;
//! Interface for system component implementing the ViewportSelectionRequests interface.
//! This interface also includes a setter to set a custom handler also implementing

@ -17,7 +17,7 @@ namespace AzToolsFramework
AZ_CLASS_ALLOCATOR_IMPL(EditorPickEntitySelection, AZ::SystemAllocator, 0)
EditorPickEntitySelection::EditorPickEntitySelection(
const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
const EditorVisibleEntityDataCacheInterface* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
: m_editorHelpers(AZStd::make_unique<EditorHelpers>(entityDataCache))
, m_viewportEditorModeTracker(viewportEditorModeTracker)
{

@ -13,6 +13,7 @@
namespace AzToolsFramework
{
class EditorVisibleEntityDataCacheInterface;
class ViewportEditorModeTrackerInterface;
//! Viewport interaction that will handle assigning an entity in the viewport to
@ -23,7 +24,7 @@ namespace AzToolsFramework
AZ_CLASS_ALLOCATOR_DECL
EditorPickEntitySelection(
const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker);
const EditorVisibleEntityDataCacheInterface* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker);
~EditorPickEntitySelection();
private:
@ -35,6 +36,7 @@ namespace AzToolsFramework
AZStd::unique_ptr<EditorHelpers> m_editorHelpers; //!< Editor visualization of entities (icons, shapes, debug visuals etc).
AZ::EntityId m_hoveredEntityId; //!< What EntityId is the mouse currently hovering over (if any).
AZ::EntityId m_cachedEntityIdUnderCursor; //!< Store the EntityId on each mouse move for use in Display.
ViewportEditorModeTrackerInterface* m_viewportEditorModeTracker = nullptr; //!< Tracker for activating/deactivating viewport editor modes.
//! Tracker for activating/deactivating viewport editor modes.
ViewportEditorModeTrackerInterface* m_viewportEditorModeTracker = nullptr;
};
} // namespace AzToolsFramework

@ -381,7 +381,7 @@ namespace AzToolsFramework
EntityIdContainer& selectedEntityIdsBeforeBoxSelect,
EntityIdContainer& potentialSelectedEntityIds,
EntityIdContainer& potentialDeselectedEntityIds,
const EditorVisibleEntityDataCache& entityDataCache,
const EditorVisibleEntityDataCacheInterface& entityDataCache,
const int viewportId,
const ViewportInteraction::KeyboardModifiers currentKeyboardModifiers,
const ViewportInteraction::KeyboardModifiers& previousKeyboardModifiers)
@ -958,7 +958,7 @@ namespace AzToolsFramework
// (useful in the context of drawing when we only care about entities we can see)
// note: return the index if it is selectable, nullopt otherwise
static AZStd::optional<size_t> SelectableInVisibleViewportCache(
const EditorVisibleEntityDataCache& entityDataCache, const AZ::EntityId entityId)
const EditorVisibleEntityDataCacheInterface& entityDataCache, const AZ::EntityId entityId)
{
if (auto entityIndex = entityDataCache.GetVisibleEntityIndexFromId(entityId))
{
@ -1002,7 +1002,7 @@ namespace AzToolsFramework
}
}
EditorTransformComponentSelection::EditorTransformComponentSelection(const EditorVisibleEntityDataCache* entityDataCache)
EditorTransformComponentSelection::EditorTransformComponentSelection(const EditorVisibleEntityDataCacheInterface* entityDataCache)
: m_entityDataCache(entityDataCache)
{
const AzFramework::EntityContextId entityContextId = GetEntityContextId();

@ -34,7 +34,7 @@
namespace AzToolsFramework
{
class EditorVisibleEntityDataCache;
class EditorVisibleEntityDataCacheInterface;
using EntityIdSet = AZStd::unordered_set<AZ::EntityId>; //!< Alias for unordered_set of EntityIds.
@ -167,7 +167,7 @@ namespace AzToolsFramework
AZ_CLASS_ALLOCATOR_DECL
EditorTransformComponentSelection() = default;
explicit EditorTransformComponentSelection(const EditorVisibleEntityDataCache* entityDataCache);
explicit EditorTransformComponentSelection(const EditorVisibleEntityDataCacheInterface* entityDataCache);
EditorTransformComponentSelection(const EditorTransformComponentSelection&) = delete;
EditorTransformComponentSelection& operator=(const EditorTransformComponentSelection&) = delete;
virtual ~EditorTransformComponentSelection();
@ -325,10 +325,8 @@ namespace AzToolsFramework
AZ::EntityId m_currentEntityIdUnderCursor; //!< Store the EntityId on each mouse move for use in Display.
AZ::EntityId m_editorCameraComponentEntityId; //!< The EditorCameraComponent EntityId if it is set.
EntityIdSet m_selectedEntityIds; //!< Represents the current entities in the selection.
const EditorVisibleEntityDataCache* m_entityDataCache = nullptr; //!< A cache of packed EntityData that can be
//!< iterated over efficiently without the need
//!< to make individual EBus calls.
//! A cache of packed EntityData that can be iterated over efficiently without the need to make individual EBus calls.
const EditorVisibleEntityDataCacheInterface* m_entityDataCache = nullptr;
AZStd::unique_ptr<EditorHelpers> m_editorHelpers; //!< Editor visualization of entities (icons, shapes, debug visuals etc).
EntityIdManipulators m_entityIdManipulators; //!< Mapping from a Manipulator to potentially many EntityIds.

@ -20,10 +20,36 @@
namespace AzToolsFramework
{
//! Read-only interface for EditorVisibleEntityDataCache to be used by systems that want to efficiently
//! query the state of visible entities in the viewport.
class EditorVisibleEntityDataCacheInterface
{
using ComponentEntityAccentType = Components::EditorSelectionAccentSystemComponent::ComponentEntityAccentType;
public:
virtual ~EditorVisibleEntityDataCacheInterface() = default;
virtual size_t VisibleEntityDataCount() const = 0;
virtual AZ::Vector3 GetVisibleEntityPosition(size_t index) const = 0;
virtual const AZ::Transform& GetVisibleEntityTransform(size_t index) const = 0;
virtual AZ::EntityId GetVisibleEntityId(size_t index) const = 0;
virtual ComponentEntityAccentType GetVisibleEntityAccent(size_t index) const = 0;
virtual bool IsVisibleEntityLocked(size_t index) const = 0;
virtual bool IsVisibleEntityVisible(size_t index) const = 0;
virtual bool IsVisibleEntitySelected(size_t index) const = 0;
virtual bool IsVisibleEntityIconHidden(size_t index) const = 0;
//! Returns true if the entity is individually selectable (none of its ancestors are a closed container entity).
//! @note It may still be desirable to be able to 'click' an entity that is a descendant of a closed container
//! to select the container itself, not the individual entity.
virtual bool IsVisibleEntityIndividuallySelectableInViewport(size_t index) const = 0;
virtual AZStd::optional<size_t> GetVisibleEntityIndexFromId(AZ::EntityId entityId) const = 0;
};
//! A cache of packed EntityData that can be iterated over efficiently without
//! the need to make individual EBus calls
class EditorVisibleEntityDataCache
: private EditorEntityVisibilityNotificationBus::Router
: public EditorVisibleEntityDataCacheInterface
, private EditorEntityVisibilityNotificationBus::Router
, private EditorEntityLockComponentNotificationBus::Router
, private AZ::TransformNotificationBus::Router
, private EditorComponentSelectionNotificationsBus::Router
@ -45,22 +71,18 @@ namespace AzToolsFramework
void CalculateVisibleEntityDatas(const AzFramework::ViewportInfo& viewportInfo);
//! EditorVisibleEntityDataCache interface
size_t VisibleEntityDataCount() const;
AZ::Vector3 GetVisibleEntityPosition(size_t index) const;
const AZ::Transform& GetVisibleEntityTransform(size_t index) const;
AZ::EntityId GetVisibleEntityId(size_t index) const;
ComponentEntityAccentType GetVisibleEntityAccent(size_t index) const;
bool IsVisibleEntityLocked(size_t index) const;
bool IsVisibleEntityVisible(size_t index) const;
bool IsVisibleEntitySelected(size_t index) const;
bool IsVisibleEntityIconHidden(size_t index) const;
//! Returns true if the entity is individually selectable (none of its ancestors are a closed container entity).
//! @note It may still be desirable to be able to 'click' an entity that is a descendant of a closed container
//! to select the container itself, not the individual entity.
bool IsVisibleEntityIndividuallySelectableInViewport(size_t index) const;
AZStd::optional<size_t> GetVisibleEntityIndexFromId(AZ::EntityId entityId) const;
//! EditorVisibleEntityDataCacheInterface overrides ...
size_t VisibleEntityDataCount() const override;
AZ::Vector3 GetVisibleEntityPosition(size_t index) const override;
const AZ::Transform& GetVisibleEntityTransform(size_t index) const override;
AZ::EntityId GetVisibleEntityId(size_t index) const override;
ComponentEntityAccentType GetVisibleEntityAccent(size_t index) const override;
bool IsVisibleEntityLocked(size_t index) const override;
bool IsVisibleEntityVisible(size_t index) const override;
bool IsVisibleEntitySelected(size_t index) const override;
bool IsVisibleEntityIconHidden(size_t index) const override;
bool IsVisibleEntityIndividuallySelectableInViewport(size_t index) const override;
AZStd::optional<size_t> GetVisibleEntityIndexFromId(AZ::EntityId entityId) const override;
void AddEntityIds(const EntityIdList& entityIds);

@ -9,6 +9,9 @@
set(FILES
UnitTest/AzToolsFrameworkTestHelpers.cpp
UnitTest/AzToolsFrameworkTestHelpers.h
UnitTest/Mocks/MockFocusModeInterface.h
UnitTest/Mocks/MockEditorVisibleEntityDataCacheInterface.h
UnitTest/Mocks/MockEditorViewportIconDisplayInterface.h
UnitTest/ToolsTestApplication.cpp
UnitTest/ToolsTestApplication.h
)

@ -265,7 +265,7 @@ namespace UnitTest
using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus;
EditorInteractionSystemViewportSelectionRequestBus::Event(
AzToolsFramework::GetEntityContextId(), &EditorInteractionSystemViewportSelectionRequestBus::Events::SetHandler,
[](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache,
[](const AzToolsFramework::EditorVisibleEntityDataCacheInterface* entityDataCache,
[[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
{
return AZStd::make_unique<AzToolsFramework::EditorPickEntitySelection>(entityDataCache, viewportEditorModeTracker);

@ -0,0 +1,116 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/UnitTest/TestTypes.h>
#include <AzFramework/UnitTest/TestDebugDisplayRequests.h>
#include <AzFramework/Viewport/CameraState.h>
#include <AzTest/AzTest.h>
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
#include <AzToolsFramework/UnitTest/Mocks/MockEditorViewportIconDisplayInterface.h>
#include <AzToolsFramework/UnitTest/Mocks/MockEditorVisibleEntityDataCacheInterface.h>
#include <AzToolsFramework/UnitTest/Mocks/MockFocusModeInterface.h>
#include <AzToolsFramework/ViewportSelection/EditorHelpers.h>
#include <AzToolsFramework/ViewportSelection/EditorVisibleEntityDataCache.h>
namespace UnitTest
{
class EditorViewportIconFixture : public AllocatorsTestFixture
{
public:
inline static constexpr AzFramework::ViewportId TestViewportId = 2468;
void SetUp() override
{
AllocatorsTestFixture::SetUp();
m_focusModeMock = AZStd::make_unique<::testing::NiceMock<MockFocusModeInterface>>();
m_editorViewportIconDisplayMock = AZStd::make_unique<::testing::NiceMock<MockEditorViewportIconDisplayInterface>>();
m_entityVisibleEntityDataCacheMock = AZStd::make_unique<::testing::NiceMock<MockEditorVisibleEntityDataCacheInterface>>();
m_editorHelpers = AZStd::make_unique<AzToolsFramework::EditorHelpers>(m_entityVisibleEntityDataCacheMock.get());
m_viewportSettings = AZStd::make_unique<ViewportSettingsTestImpl>();
m_viewportSettings->Connect(TestViewportId);
m_viewportSettings->m_helpersVisible = false;
m_viewportSettings->m_iconsVisible = true;
m_cameraState = AzFramework::CreateDefaultCamera(AZ::Transform::CreateIdentity(), AZ::Vector2(1024.0f, 768.0f));
using ::testing::_;
using ::testing::Return;
ON_CALL(*m_entityVisibleEntityDataCacheMock, VisibleEntityDataCount()).WillByDefault(Return(1));
ON_CALL(*m_entityVisibleEntityDataCacheMock, GetVisibleEntityId(_)).WillByDefault(Return(AZ::EntityId()));
ON_CALL(*m_entityVisibleEntityDataCacheMock, IsVisibleEntityIconHidden(_)).WillByDefault(Return(false));
ON_CALL(*m_entityVisibleEntityDataCacheMock, IsVisibleEntityVisible(_)).WillByDefault(Return(true));
ON_CALL(*m_focusModeMock, IsInFocusSubTree(_)).WillByDefault(Return(true));
}
void TearDown() override
{
m_viewportSettings->Disconnect();
m_viewportSettings.reset();
m_editorHelpers.reset();
m_entityVisibleEntityDataCacheMock.reset();
m_editorViewportIconDisplayMock.reset();
m_focusModeMock.reset();
AllocatorsTestFixture::TearDown();
}
AZStd::unique_ptr<ViewportSettingsTestImpl> m_viewportSettings;
AZStd::unique_ptr<AzToolsFramework::EditorHelpers> m_editorHelpers;
AZStd::unique_ptr<::testing::NiceMock<MockFocusModeInterface>> m_focusModeMock;
AZStd::unique_ptr<::testing::NiceMock<MockEditorVisibleEntityDataCacheInterface>> m_entityVisibleEntityDataCacheMock;
AZStd::unique_ptr<::testing::NiceMock<MockEditorViewportIconDisplayInterface>> m_editorViewportIconDisplayMock;
AzFramework::CameraState m_cameraState;
};
TEST_F(EditorViewportIconFixture, ViewportIconsAreNotDisplayedWhenInBetweenCameraAndNearClipPlane)
{
NullDebugDisplayRequests nullDebugDisplayRequests;
const auto insideNearClip = m_cameraState.m_nearClip * 0.5f;
using ::testing::_;
using ::testing::Return;
// given
// entity position (where icon will be drawn) is in between near clip plane and camera position
ON_CALL(*m_entityVisibleEntityDataCacheMock, GetVisibleEntityPosition(_))
.WillByDefault(Return(AZ::Vector3(0.0f, insideNearClip, 0.0f)));
EXPECT_CALL(*m_editorViewportIconDisplayMock, DrawIcon(_)).Times(0);
// when
m_editorHelpers->DisplayHelpers(
AzFramework::ViewportInfo{ TestViewportId }, m_cameraState, nullDebugDisplayRequests,
[](AZ::EntityId)
{
return true;
});
}
TEST_F(EditorViewportIconFixture, ViewportIconsAreNotDisplayedWhenBehindCamera)
{
NullDebugDisplayRequests nullDebugDisplayRequests;
using ::testing::_;
using ::testing::Return;
// given
// entity position (where icon will be drawn) behind the camera position
ON_CALL(*m_entityVisibleEntityDataCacheMock, GetVisibleEntityPosition(_)).WillByDefault(Return(AZ::Vector3(0.0f, -1.0f, 0.0f)));
EXPECT_CALL(*m_editorViewportIconDisplayMock, DrawIcon(_)).Times(0);
// when
m_editorHelpers->DisplayHelpers(
AzFramework::ViewportInfo{ TestViewportId }, m_cameraState, nullDebugDisplayRequests,
[](AZ::EntityId)
{
return true;
});
}
} // namespace UnitTest

@ -573,7 +573,7 @@ namespace UnitTest
using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus;
EditorInteractionSystemViewportSelectionRequestBus::Event(
AzToolsFramework::GetEntityContextId(), &EditorInteractionSystemViewportSelectionRequestBus::Events::SetHandler,
[](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache,
[](const AzToolsFramework::EditorVisibleEntityDataCacheInterface* entityDataCache,
[[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
{
return AZStd::make_unique<AzToolsFramework::EditorPickEntitySelection>(entityDataCache, viewportEditorModeTracker);
@ -591,7 +591,7 @@ namespace UnitTest
using AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus;
EditorInteractionSystemViewportSelectionRequestBus::Event(
AzToolsFramework::GetEntityContextId(), &EditorInteractionSystemViewportSelectionRequestBus::Events::SetHandler,
[](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache,
[](const AzToolsFramework::EditorVisibleEntityDataCacheInterface* entityDataCache,
[[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
{
return AZStd::make_unique<AzToolsFramework::EditorPickEntitySelection>(entityDataCache, viewportEditorModeTracker);
@ -599,7 +599,7 @@ namespace UnitTest
EditorInteractionSystemViewportSelectionRequestBus::Event(
AzToolsFramework::GetEntityContextId(), &EditorInteractionSystemViewportSelectionRequestBus::Events::SetHandler,
[](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache,
[](const AzToolsFramework::EditorVisibleEntityDataCacheInterface* entityDataCache,
[[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
{
return AZStd::make_unique<AzToolsFramework::EditorDefaultSelection>(entityDataCache, viewportEditorModeTracker);

@ -24,6 +24,7 @@ set(FILES
ComponentModeTests.cpp
EditorTransformComponentSelectionTests.cpp
EditorVertexSelectionTests.cpp
EditorViewportIconTests.cpp
Entity/EditorEntityContextComponentTests.cpp
Entity/EditorEntityHelpersTests.cpp
Entity/EditorEntitySearchComponentTests.cpp

Loading…
Cancel
Save