diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h index 85250f2a32..d202735522 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/Viewport/ViewportMessages.h @@ -210,6 +210,15 @@ namespace AzToolsFramework //! Type to inherit to implement ViewportInteractionRequests. using ViewportInteractionRequestBus = AZ::EBus; + //! An interface to notify when changes to viewport settings have happened. + class ViewportSettingNotifications + { + public: + virtual void OnGridSnappingChanged(bool enabled) = 0; + }; + + using ViewportSettingsNotificationBus = AZ::EBus; + //! Requests to freeze the Viewport Input //! Added to prevent a bug with the legacy CryEngine Viewport code that would //! keep doing raycast tests even when no level is loaded, causing a crash. diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp index c4f1ae33da..3e16088f0e 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.cpp @@ -489,6 +489,16 @@ namespace AzToolsFramework return buttonId; } + void SnappingCluster::TrySetVisible(const bool visible) + { + bool snapping = false; + ViewportInteraction::ViewportInteractionRequestBus::EventResult( + snapping, ViewportUi::DefaultViewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::GridSnappingEnabled); + + // show snapping viewport ui only if there are entities selected and snapping is enabled + SetViewportUiClusterVisible(m_clusterId, visible && snapping); + } + // return either center or entity pivot static AZ::Vector3 CalculatePivotTranslation(const AZ::EntityId entityId, const EditorTransformComponentSelectionRequests::Pivot pivot) { @@ -1035,6 +1045,7 @@ namespace AzToolsFramework EditorEntityLockComponentNotificationBus::Router::BusRouterConnect(); EditorManipulatorCommandUndoRedoRequestBus::Handler::BusConnect(entityContextId); EditorContextMenuBus::Handler::BusConnect(); + ViewportInteraction::ViewportSettingsNotificationBus::Handler::BusConnect(ViewportUi::DefaultViewportId); CreateTransformModeSelectionCluster(); CreateSpaceSelectionCluster(); @@ -1058,6 +1069,7 @@ namespace AzToolsFramework m_pivotOverrideFrame.Reset(); + ViewportInteraction::ViewportSettingsNotificationBus::Handler::BusDisconnect(); EditorContextMenuBus::Handler::BusConnect(); EditorManipulatorCommandUndoRedoRequestBus::Handler::BusDisconnect(); EditorEntityLockComponentNotificationBus::Router::BusRouterDisconnect(); @@ -3253,7 +3265,7 @@ namespace AzToolsFramework m_didSetSelectedEntities = false; } - SetViewportUiClusterVisible(m_snappingCluster.m_clusterId, m_viewportUiVisible && !m_selectedEntityIds.empty()); + m_snappingCluster.TrySetVisible(m_viewportUiVisible && !m_selectedEntityIds.empty()); RegenerateManipulators(); } @@ -3717,6 +3729,11 @@ namespace AzToolsFramework SetAllViewportUiVisible(true); } + void EditorTransformComponentSelection::OnGridSnappingChanged([[maybe_unused]] const bool enabled) + { + m_snappingCluster.TrySetVisible(m_viewportUiVisible && !m_selectedEntityIds.empty()); + } + namespace ETCS { // little raii wrapper to switch a value from true to false and back diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h index db96d91911..00c2cb4e50 100644 --- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h +++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportSelection/EditorTransformComponentSelection.h @@ -131,6 +131,9 @@ namespace AzToolsFramework SnappingCluster(const SnappingCluster&) = delete; SnappingCluster& operator=(const SnappingCluster&) = delete; + //! Attempt to show the snapping cluster (will only succeed if snapping is enabled). + void TrySetVisible(bool visible); + ViewportUi::ClusterId m_clusterId; //!< The cluster id for all snapping buttons. ViewportUi::ButtonId m_snapToWorldButtonId; //!< The button id for snapping all axes to the world. AZ::Event::Handler m_snappingHandler; //!< Callback for when a snapping cluster button is pressed. @@ -151,6 +154,7 @@ namespace AzToolsFramework , private EditorEntityLockComponentNotificationBus::Router , private EditorManipulatorCommandUndoRedoRequestBus::Handler , private AZ::TransformNotificationBus::MultiHandler + , private ViewportInteraction::ViewportSettingsNotificationBus::Handler { public: AZ_CLASS_ALLOCATOR_DECL @@ -289,6 +293,9 @@ namespace AzToolsFramework void OnStartPlayInEditor() override; void OnStopPlayInEditor() override; + // ViewportSettingsNotificationBus overrides ... + void OnGridSnappingChanged(bool enabled) override; + // Helpers to safely interact with the TransformBus (requests). void SetEntityWorldTranslation(AZ::EntityId entityId, const AZ::Vector3& worldTranslation); void SetEntityLocalTranslation(AZ::EntityId entityId, const AZ::Vector3& localTranslation); diff --git a/Code/Sandbox/Editor/EditorViewportSettings.cpp b/Code/Sandbox/Editor/EditorViewportSettings.cpp index dbfd3ea4ed..02e280b8d1 100644 --- a/Code/Sandbox/Editor/EditorViewportSettings.cpp +++ b/Code/Sandbox/Editor/EditorViewportSettings.cpp @@ -14,6 +14,7 @@ #include #include +#include #include namespace SandboxEditor @@ -56,6 +57,39 @@ namespace SandboxEditor return value; } + struct EditorViewportSettingsCallbacksImpl : public EditorViewportSettingsCallbacks + { + EditorViewportSettingsCallbacksImpl() + { + if (auto* registry = AZ::SettingsRegistry::Get()) + { + using AZ::SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual; + + m_notifyEventHandler = registry->RegisterNotifier( + [this](const AZStd::string_view path, [[maybe_unused]] const AZ::SettingsRegistryInterface::Type type) + { + if (IsPathAncestorDescendantOrEqual(GridSnappingSetting, path)) + { + m_gridSnappingChanged.Signal(GridSnappingEnabled()); + } + }); + } + } + + void SetGridSnappingChangedEvent(GridSnappingChangedEvent::Handler& handler) override + { + handler.Connect(m_gridSnappingChanged); + } + + GridSnappingChangedEvent m_gridSnappingChanged; + AZ::SettingsRegistryInterface::NotifyEventHandler m_notifyEventHandler; + }; + + AZStd::unique_ptr CreateEditorViewportSettingsCallbacks() + { + return AZStd::make_unique(); + } + bool GridSnappingEnabled() { return GetRegistry(GridSnappingSetting, false); diff --git a/Code/Sandbox/Editor/EditorViewportSettings.h b/Code/Sandbox/Editor/EditorViewportSettings.h index a2f80d196e..d3a082c095 100644 --- a/Code/Sandbox/Editor/EditorViewportSettings.h +++ b/Code/Sandbox/Editor/EditorViewportSettings.h @@ -14,8 +14,27 @@ #include +#include +#include + namespace SandboxEditor { + using GridSnappingChangedEvent = AZ::Event; + + //! Set callbacks to listen for editor settings change events. + class EditorViewportSettingsCallbacks + { + public: + virtual ~EditorViewportSettingsCallbacks() = default; + + virtual void SetGridSnappingChangedEvent(GridSnappingChangedEvent::Handler& handler) = 0; + }; + + //! Create an instance of EditorViewportSettingsCallbacks + //! Note: EditorViewportSettingsCallbacks is implemented in EditorViewportSettings.cpp - a change + //! event will fire when a value in the settings registry (editorpreferences.setreg) is modified. + SANDBOX_API AZStd::unique_ptr CreateEditorViewportSettingsCallbacks(); + SANDBOX_API bool GridSnappingEnabled(); SANDBOX_API void SetGridSnapping(bool enabled); diff --git a/Code/Sandbox/Editor/EditorViewportWidget.cpp b/Code/Sandbox/Editor/EditorViewportWidget.cpp index 1a7c54967b..699cd7acb9 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.cpp +++ b/Code/Sandbox/Editor/EditorViewportWidget.cpp @@ -76,7 +76,6 @@ #include "EditorPreferencesPageGeneral.h" #include "ViewportManipulatorController.h" #include "LegacyViewportCameraController.h" -#include "EditorViewportSettings.h" #include "ViewPane.h" #include "CustomResolutionDlg.h" @@ -1450,6 +1449,17 @@ void EditorViewportWidget::SetViewportId(int id) { SetAsActiveViewport(); } + + m_editorViewportSettingsCallbacks = SandboxEditor::CreateEditorViewportSettingsCallbacks(); + + m_gridSnappingHandler = SandboxEditor::GridSnappingChangedEvent::Handler( + [id](const bool snapping) + { + AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Event( + id, &AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Events::OnGridSnappingChanged, snapping); + }); + + m_editorViewportSettingsCallbacks->SetGridSnappingChangedEvent(m_gridSnappingHandler); } void EditorViewportWidget::ConnectViewportInteractionRequestBus() diff --git a/Code/Sandbox/Editor/EditorViewportWidget.h b/Code/Sandbox/Editor/EditorViewportWidget.h index 511a7910c6..670694f91f 100644 --- a/Code/Sandbox/Editor/EditorViewportWidget.h +++ b/Code/Sandbox/Editor/EditorViewportWidget.h @@ -24,6 +24,7 @@ #include "Objects/DisplayContext.h" #include "Undo/Undo.h" #include "Util/PredefinedAspectRatios.h" +#include "EditorViewportSettings.h" #include #include @@ -571,6 +572,9 @@ private: AzFramework::EntityVisibilityQuery m_entityVisibilityQuery; + SandboxEditor::GridSnappingChangedEvent::Handler m_gridSnappingHandler; + AZStd::unique_ptr m_editorViewportSettingsCallbacks; + QSet m_keyDown; bool m_freezeViewportInput = false;