Expose the ability to control manipulator line bounds (#3890)

Signed-off-by: hultonha <hultonha@amazon.co.uk>
This commit is contained in:
hultonha
2021-09-03 10:14:03 +01:00
committed by GitHub
parent daf901e809
commit 5851031d2e
25 changed files with 210 additions and 191 deletions
@@ -40,11 +40,13 @@ namespace AzManipulatorTestFramework
float DeviceScalingFactor() override;
private:
// ViewportInteractionRequestBus ...
bool GridSnappingEnabled();
float GridSize();
bool ShowGrid();
bool AngleSnappingEnabled();
float AngleStep();
bool GridSnappingEnabled() override;
float GridSize() override;
bool ShowGrid() override;
bool AngleSnappingEnabled() override;
float AngleStep() override;
float ManipulatorLineBoundWidth() override;
AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition);
private:
AZStd::unique_ptr<NullDebugDisplayRequests> m_nullDebugDisplayRequests;
@@ -62,6 +62,11 @@ namespace AzManipulatorTestFramework
return m_angularStep;
}
float ViewportInteraction::ManipulatorLineBoundWidth()
{
return 0.1f;
}
AzFramework::ScreenPoint ViewportInteraction::ViewportWorldToScreen(const AZ::Vector3& worldPosition)
{
return AzFramework::WorldToScreen(worldPosition, m_cameraState);
@@ -226,6 +226,8 @@ namespace AzToolsFramework
m_translationManipulator = AZStd::make_shared<IndexedTranslationManipulator<Vertex>>(
Dimensions(), vertexIndex, vertex, WorldFromLocalWithUniformScale(entityComponentIdPair.GetEntityId()),
GetNonUniformScale(entityComponentIdPair.GetEntityId()));
m_translationManipulator->m_manipulator.SetLineBoundWidth(
AzToolsFramework::ManipulatorLineBoundWidth(AzFramework::InvalidViewportId));
// setup how the manipulator should look
m_manipulatorConfiguratorFn(&m_translationManipulator->m_manipulator);
@@ -8,6 +8,7 @@
#include "ManipulatorView.h"
#include <AzCore/Console/IConsole.h>
#include <AzCore/Component/NonUniformScaleBus.h>
#include <AzCore/Component/TransformBus.h>
#include <AzCore/Math/VectorConversions.h>
@@ -22,6 +23,14 @@
#include <AzToolsFramework/Maths/TransformUtils.h>
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
AZ_CVAR(
bool,
ed_manipulatorDisplayBoundDebug,
false,
nullptr,
AZ::ConsoleFunctorFlags::Null,
"Display additional debug drawing for manipulator bounds");
namespace AzToolsFramework
{
const float g_defaultManipulatorSphereRadius = 0.1f;
@@ -118,6 +127,14 @@ namespace AzToolsFramework
return quadBound;
}
// calculate line in world space (axis and length).
static AZStd::pair<AZ::Vector3, AZ::Vector3> CalculateLine(
const AZ::Vector3& localPosition, const AZ::Transform& worldFromLocal, const AZ::Vector3& axis, const float length)
{
return { worldFromLocal.TransformPoint(localPosition),
TransformPositionNoScaling(worldFromLocal, localPosition + (axis * length)) };
}
// calculate line bound in world space (axis and length).
static Picking::BoundShapeLineSegment CalculateLineBound(
const AZ::Vector3& localPosition,
@@ -127,8 +144,9 @@ namespace AzToolsFramework
const float width)
{
Picking::BoundShapeLineSegment lineBound;
lineBound.m_start = worldFromLocal.TransformPoint(localPosition);
lineBound.m_end = TransformPositionNoScaling(worldFromLocal, localPosition + (axis * length));
const auto line = CalculateLine(localPosition, worldFromLocal, axis, length);
lineBound.m_start = line.first;
lineBound.m_end = line.second;
lineBound.m_width = width;
return lineBound;
}
@@ -395,13 +413,29 @@ namespace AzToolsFramework
m_axis, m_cameraCorrectedAxis, managerState, mouseInteraction, manipulatorState.m_worldFromLocal,
manipulatorState.m_localPosition, cameraState);
const Picking::BoundShapeLineSegment lineBound = CalculateLineBound(
manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal, m_cameraCorrectedAxis, m_length * viewScale,
m_width * viewScale);
const auto worldLine = CalculateLine(
manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal, m_cameraCorrectedAxis, m_length * viewScale);
debugDisplay.SetColor(ViewColor(manipulatorState.m_mouseOver, m_color, m_mouseOverColor).GetAsVector4());
debugDisplay.SetLineWidth(defaultLineWidth(manipulatorState.m_mouseOver));
debugDisplay.DrawLine(lineBound.m_start, lineBound.m_end);
debugDisplay.DrawLine(worldLine.first, worldLine.second);
// ensure length of bound takes into account logical width of line (m_length - m_width)
const Picking::BoundShapeLineSegment lineBound = CalculateLineBound(
manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal, m_cameraCorrectedAxis, (m_length - m_width) * viewScale,
m_width * viewScale);
if (ed_manipulatorDisplayBoundDebug)
{
debugDisplay.DrawBall(lineBound.m_start, lineBound.m_width, false);
debugDisplay.DrawBall(lineBound.m_end, lineBound.m_width, false);
const auto line = lineBound.m_end - lineBound.m_start;
const auto height = line.GetLength();
const auto axis = line / height;
const auto center = lineBound.m_start + axis * height * 0.5f;
debugDisplay.DrawSolidCylinder(center, axis, lineBound.m_width, height, false);
}
RefreshBoundInternal(managerId, manipulatorId, lineBound);
}
@@ -120,18 +120,18 @@ namespace AzToolsFramework
const float axisLength, const AZ::Color& axis1Color, const AZ::Color& axis2Color, const AZ::Color& axis3Color)
{
const float boxSize = 0.1f;
const float lineWidth = 0.05f;
const AZ::Color colors[] = { axis1Color, axis2Color, axis3Color };
for (size_t manipulatorIndex = 0; manipulatorIndex < m_axisScaleManipulators.size(); ++manipulatorIndex)
{
const auto lineLength = axisLength - boxSize;
ManipulatorViews views;
views.emplace_back(
CreateManipulatorViewLine(*m_axisScaleManipulators[manipulatorIndex], colors[manipulatorIndex], axisLength, lineWidth));
CreateManipulatorViewLine(*m_axisScaleManipulators[manipulatorIndex], colors[manipulatorIndex], axisLength, m_lineBoundWidth));
views.emplace_back(CreateManipulatorViewBox(
AZ::Transform::CreateIdentity(), colors[manipulatorIndex],
m_axisScaleManipulators[manipulatorIndex]->GetAxis() * (axisLength - boxSize), AZ::Vector3(boxSize)));
m_axisScaleManipulators[manipulatorIndex]->GetAxis() * lineLength, AZ::Vector3(boxSize)));
m_axisScaleManipulators[manipulatorIndex]->SetViews(AZStd::move(views));
}
@@ -150,4 +150,9 @@ namespace AzToolsFramework
manipulatorFn(m_uniformScaleManipulator.get());
}
void ScaleManipulators::SetLineBoundWidth(const float lineBoundWidth)
{
m_lineBoundWidth = lineBoundWidth;
}
} // namespace AzToolsFramework
@@ -41,6 +41,9 @@ namespace AzToolsFramework
void ConfigureView(float axisLength, const AZ::Color& axis1Color, const AZ::Color& axis2Color, const AZ::Color& axis3Color);
//! Sets the bound width to use for the line/axis of a linear manipulator.
void SetLineBoundWidth(float lineBoundWidth);
private:
AZ_DISABLE_COPY_MOVE(ScaleManipulators)
@@ -49,5 +52,6 @@ namespace AzToolsFramework
AZStd::array<AZStd::shared_ptr<LinearManipulator>, 3> m_axisScaleManipulators;
AZStd::shared_ptr<LinearManipulator> m_uniformScaleManipulator;
float m_lineBoundWidth = 0.01f; //!< The default line bound width for the linear manipulator axis.
};
} // namespace AzToolsFramework
@@ -235,24 +235,25 @@ namespace AzToolsFramework
}
void TranslationManipulators::ConfigureLinearView(
float axisLength,
const float axisLength,
const AZ::Color& axis1Color,
const AZ::Color& axis2Color,
const AZ::Color& axis3Color /*= AZ::Color(0.0f, 0.0f, 1.0f, 0.5f)*/)
{
const float coneLength = 0.28f;
const float coneRadius = 0.07f;
const float lineWidth = 0.05f;
const AZ::Color axesColor[] = { axis1Color, axis2Color, axis3Color };
const auto configureLinearView =
[lineWidth, coneLength, axisLength, coneRadius](LinearManipulator* linearManipulator, const AZ::Color& color)
const auto configureLinearView = [lineBoundWidth = m_lineBoundWidth, coneLength, axisLength,
coneRadius](LinearManipulator* linearManipulator, const AZ::Color& color)
{
const auto lineLength = axisLength - coneLength;
ManipulatorViews views;
views.emplace_back(CreateManipulatorViewLine(*linearManipulator, color, axisLength, lineWidth));
views.emplace_back(CreateManipulatorViewCone(
*linearManipulator, color, linearManipulator->GetAxis() * (axisLength - coneLength), coneLength, coneRadius));
views.emplace_back(CreateManipulatorViewLine(*linearManipulator, color, lineLength, lineBoundWidth));
views.emplace_back(
CreateManipulatorViewCone(*linearManipulator, color, linearManipulator->GetAxis() * lineLength, coneLength, coneRadius));
linearManipulator->SetViews(AZStd::move(views));
};
@@ -316,6 +317,11 @@ namespace AzToolsFramework
}
}
void TranslationManipulators::SetLineBoundWidth(const float lineBoundWidth)
{
m_lineBoundWidth = lineBoundWidth;
}
void ConfigureTranslationManipulatorAppearance3d(TranslationManipulators* translationManipulators)
{
translationManipulators->SetAxes(AZ::Vector3::CreateAxisX(), AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ());
@@ -65,6 +65,9 @@ namespace AzToolsFramework
void ConfigureSurfaceView(float radius, const AZ::Color& color);
//! Sets the bound width to use for the line/axis of a linear manipulator.
void SetLineBoundWidth(float lineBoundWidth);
private:
AZ_DISABLE_COPY_MOVE(TranslationManipulators)
@@ -76,6 +79,7 @@ namespace AzToolsFramework
AZStd::vector<AZStd::shared_ptr<LinearManipulator>> m_linearManipulators;
AZStd::vector<AZStd::shared_ptr<PlanarManipulator>> m_planarManipulators;
AZStd::shared_ptr<SurfaceManipulator> m_surfaceManipulator = nullptr;
float m_lineBoundWidth = 0.01f; //!< The default line bound width for the linear manipulator axis.
};
//! IndexedTranslationManipulator wraps a standard TranslationManipulators and allows it to be linked
@@ -156,22 +156,24 @@ namespace AzToolsFramework
class ViewportInteractionRequests
{
public:
//! Return the current camera state for this viewport.
//! Returns the current camera state for this viewport.
virtual AzFramework::CameraState GetCameraState() = 0;
//! Return if grid snapping is enabled.
//! Returns if grid snapping is enabled.
virtual bool GridSnappingEnabled() = 0;
//! Return the grid snapping size.
//! Returns the grid snapping size.
virtual float GridSize() = 0;
//! Does the grid currently want to be displayed.
virtual bool ShowGrid() = 0;
//! Return if angle snapping is enabled.
//! Returns if angle snapping is enabled.
virtual bool AngleSnappingEnabled() = 0;
//! Return the angle snapping/step size.
//! Returns the angle snapping/step size.
virtual float AngleStep() = 0;
//! Transform a point in world space to screen space coordinates in Qt Widget space.
//! Returns the current line bound width for manipulators.
virtual float ManipulatorLineBoundWidth() = 0;
//! Transforms a point in world space to screen space coordinates in Qt Widget space.
//! Multiply by DeviceScalingFactor to get the position in viewport pixel space.
virtual AzFramework::ScreenPoint ViewportWorldToScreen(const AZ::Vector3& worldPosition) = 0;
//! Transform a point from Qt widget screen space to world space based on the given clip space depth.
//! Transforms a point from Qt widget screen space to world space based on the given clip space depth.
//! Depth specifies a relative camera depth to project in the range of [0.f, 1.f].
//! Returns the world space position if successful.
virtual AZStd::optional<AZ::Vector3> ViewportScreenToWorld(const AzFramework::ScreenPoint& screenPosition, float depth) = 0;
@@ -201,6 +203,8 @@ namespace AzToolsFramework
virtual bool AngleSnappingEnabled() const = 0;
//! Return the angle snapping/step size.
virtual float AngleStep() const = 0;
//! Returns the current line bound width for manipulators.
virtual float ManipulatorLineBoundWidth() const = 0;
};
//! Type to inherit to implement ViewportInteractionRequests.
@@ -210,11 +214,15 @@ namespace AzToolsFramework
class ViewportSettingNotifications
{
public:
virtual void OnGridSnappingChanged([[maybe_unused]] bool enabled) {}
virtual void OnDrawHelpersChanged([[maybe_unused]] bool enabled) {}
virtual void OnGridSnappingChanged([[maybe_unused]] bool enabled)
{
}
virtual void OnDrawHelpersChanged([[maybe_unused]] bool enabled)
{
}
protected:
ViewportSettingNotifications() = default;
~ViewportSettingNotifications() = default;
};
using ViewportSettingsNotificationBus = AZ::EBus<ViewportSettingNotifications, ViewportEBusTraits>;
@@ -336,4 +344,23 @@ namespace AzToolsFramework
}
return AzFramework::ClickDetector::ClickEvent::Nil;
}
//! Wrap EBus call to retrieve manipulator line bound width.
//! @note It is possible to pass AzFramework::InvalidViewportId to perform a Broadcast as opposed to a targeted Event.
inline float ManipulatorLineBoundWidth(AzFramework::ViewportId viewportId)
{
float lineBoundWidth = 0.0f;
if (viewportId != AzFramework::InvalidViewportId)
{
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
lineBoundWidth, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::ManipulatorLineBoundWidth);
}
else
{
ViewportInteraction::ViewportInteractionRequestBus::BroadcastResult(
lineBoundWidth, &ViewportInteraction::ViewportInteractionRequestBus::Events::ManipulatorLineBoundWidth);
}
return lineBoundWidth;
}
} // namespace AzToolsFramework
@@ -1249,6 +1249,7 @@ namespace AzToolsFramework
AZStd::unique_ptr<TranslationManipulators> translationManipulators = AZStd::make_unique<TranslationManipulators>(
TranslationManipulators::Dimensions::Three, AZ::Transform::CreateIdentity(), AZ::Vector3::CreateOne());
translationManipulators->SetLineBoundWidth(ManipulatorLineBoundWidth(ViewportUi::DefaultViewportId));
InitializeManipulators(*translationManipulators);
@@ -1545,6 +1546,7 @@ namespace AzToolsFramework
AZ_PROFILE_FUNCTION(AzToolsFramework);
AZStd::unique_ptr<ScaleManipulators> scaleManipulators = AZStd::make_unique<ScaleManipulators>(AZ::Transform::CreateIdentity());
scaleManipulators->SetLineBoundWidth(ManipulatorLineBoundWidth(ViewportUi::DefaultViewportId));
InitializeManipulators(*scaleManipulators);