Merge branch 'development' into Prefab/SaveAllPrefabs
Signed-off-by: srikappa-amzn <srikappa@amazon.com>
This commit is contained in:
@@ -96,7 +96,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ::EBusReduceResult<AZ::Aabb, AzFramework::AabbUnionAggregator> aabbResult(AZ::Aabb::CreateNull());
|
||||
EditorComponentSelectionRequestsBus::EventResult(
|
||||
aabbResult, entityId, &EditorComponentSelectionRequests::GetEditorSelectionBoundsViewport, viewportInfo);
|
||||
aabbResult, entityId, &EditorComponentSelectionRequestsBus::Events::GetEditorSelectionBoundsViewport, viewportInfo);
|
||||
|
||||
return aabbResult.value;
|
||||
}
|
||||
|
||||
@@ -70,8 +70,12 @@ namespace AzToolsFramework
|
||||
//! Determines if the caller needs to wait for the Python VM to initialize (non-main thread only)
|
||||
virtual void WaitForInitialization() {}
|
||||
|
||||
//! Acquires the Python global interpreter lock (GIL) and executed the callback
|
||||
//! Acquires the Python global interpreter lock (GIL) and execute the callback
|
||||
virtual void ExecuteWithLock(AZStd::function<void()> executionCallback) = 0;
|
||||
|
||||
//! Tries to acquire the Python global interpreter lock (GIL) and execute the callback.
|
||||
//! @return Whether it was able to lock the mutex or not.
|
||||
virtual bool TryExecuteWithLock(AZStd::function<void()> executionCallback) = 0;
|
||||
};
|
||||
|
||||
//! A bus to handle post notifications to the console views of Python output
|
||||
|
||||
+1
@@ -226,6 +226,7 @@ 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());
|
||||
|
||||
// setup how the manipulator should look
|
||||
m_manipulatorConfiguratorFn(&m_translationManipulator->m_manipulator);
|
||||
|
||||
+10
-10
@@ -137,8 +137,8 @@ namespace AzToolsFramework
|
||||
bool GridSnapping(const int viewportId)
|
||||
{
|
||||
bool snapping = false;
|
||||
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
|
||||
snapping, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::GridSnappingEnabled);
|
||||
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
|
||||
snapping, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::GridSnappingEnabled);
|
||||
|
||||
return snapping;
|
||||
}
|
||||
@@ -146,8 +146,8 @@ namespace AzToolsFramework
|
||||
float GridSize(const int viewportId)
|
||||
{
|
||||
float gridSize = 0.0f;
|
||||
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
|
||||
gridSize, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::GridSize);
|
||||
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
|
||||
gridSize, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::GridSize);
|
||||
|
||||
return gridSize;
|
||||
}
|
||||
@@ -168,8 +168,8 @@ namespace AzToolsFramework
|
||||
bool AngleSnapping(const int viewportId)
|
||||
{
|
||||
bool snapping = false;
|
||||
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
|
||||
snapping, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::AngleSnappingEnabled);
|
||||
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
|
||||
snapping, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::AngleSnappingEnabled);
|
||||
|
||||
return snapping;
|
||||
}
|
||||
@@ -177,8 +177,8 @@ namespace AzToolsFramework
|
||||
float AngleStep(const int viewportId)
|
||||
{
|
||||
float angle = 0.0f;
|
||||
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
|
||||
angle, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::AngleStep);
|
||||
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
|
||||
angle, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::AngleStep);
|
||||
|
||||
return angle;
|
||||
}
|
||||
@@ -186,8 +186,8 @@ namespace AzToolsFramework
|
||||
bool ShowingGrid(const int viewportId)
|
||||
{
|
||||
bool show = false;
|
||||
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
|
||||
show, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::ShowGrid);
|
||||
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
|
||||
show, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::ShowGrid);
|
||||
|
||||
return show;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <AzCore/Component/NonUniformScaleBus.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Math/VectorConversions.h>
|
||||
#include <AzCore/std/containers/array.h>
|
||||
#include <AzFramework/Entity/EntityDebugDisplayBus.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);
|
||||
}
|
||||
@@ -578,13 +612,30 @@ namespace AzToolsFramework
|
||||
const Picking::BoundShapeTorus torusBound = CalculateTorusBound(
|
||||
manipulatorState.m_localPosition, manipulatorState.m_worldFromLocal, m_axis, m_radius * viewScale, m_width * viewScale);
|
||||
|
||||
// transform circle based on delta between default z up axis and other axes
|
||||
const AZ::Transform worldFromLocalWithOrientation =
|
||||
AZ::Transform::CreateTranslation(manipulatorState.m_worldFromLocal.GetTranslation()) *
|
||||
const AZ::Transform orientation =
|
||||
AZ::Transform::CreateFromQuaternion((QuaternionFromTransformNoScaling(manipulatorState.m_worldFromLocal) *
|
||||
AZ::Quaternion::CreateShortestArc(AZ::Vector3::CreateAxisZ(), m_axis))
|
||||
.GetNormalized());
|
||||
|
||||
// transform circle based on delta between default z up axis and other axes
|
||||
const AZ::Transform worldFromLocalWithOrientation =
|
||||
AZ::Transform::CreateTranslation(manipulatorState.m_worldFromLocal.GetTranslation()) * orientation;
|
||||
|
||||
if (ed_manipulatorDisplayBoundDebug)
|
||||
{
|
||||
debugDisplay.SetColor(AZ::Colors::BlanchedAlmond);
|
||||
debugDisplay.PushMatrix(orientation);
|
||||
debugDisplay.DrawCircle(torusBound.m_center + AZ::Vector3::CreateAxisZ() * torusBound.m_minorRadius, torusBound.m_majorRadius);
|
||||
debugDisplay.DrawCircle(
|
||||
torusBound.m_center + AZ::Vector3::CreateAxisZ() * torusBound.m_minorRadius,
|
||||
torusBound.m_majorRadius + torusBound.m_minorRadius);
|
||||
debugDisplay.DrawCircle(torusBound.m_center - AZ::Vector3::CreateAxisZ() * torusBound.m_minorRadius, torusBound.m_majorRadius);
|
||||
debugDisplay.DrawCircle(
|
||||
torusBound.m_center - AZ::Vector3::CreateAxisZ() * torusBound.m_minorRadius,
|
||||
torusBound.m_majorRadius + torusBound.m_minorRadius);
|
||||
debugDisplay.PopMatrix();
|
||||
}
|
||||
|
||||
debugDisplay.CullOn();
|
||||
debugDisplay.PushMatrix(worldFromLocalWithOrientation);
|
||||
debugDisplay.SetColor(ViewColor(manipulatorState.m_mouseOver, m_color, m_mouseOverColor).GetAsVector4());
|
||||
@@ -604,7 +655,10 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
void DrawFullCircle(
|
||||
AzFramework::DebugDisplayRequests& debugDisplay, const AZ::Vector3& position, const float radius, const AZ::Vector3& /*viewPos*/)
|
||||
AzFramework::DebugDisplayRequests& debugDisplay,
|
||||
const AZ::Vector3& position,
|
||||
const float radius,
|
||||
[[maybe_unused]] const AZ::Vector3& viewPos)
|
||||
{
|
||||
debugDisplay.DrawCircle(position, radius);
|
||||
}
|
||||
|
||||
+9
-2
@@ -130,11 +130,13 @@ namespace AzToolsFramework
|
||||
for (size_t manipulatorIndex = 0; manipulatorIndex < m_localAngularManipulators.size(); ++manipulatorIndex)
|
||||
{
|
||||
m_localAngularManipulators[manipulatorIndex]->SetView(CreateManipulatorViewCircle(
|
||||
*m_localAngularManipulators[manipulatorIndex], colors[manipulatorIndex], radius, 0.05f, DrawHalfDottedCircle));
|
||||
*m_localAngularManipulators[manipulatorIndex], colors[manipulatorIndex], radius, m_circleBoundWidth, DrawHalfDottedCircle));
|
||||
}
|
||||
|
||||
const float viewAlignedScale = 1.12f;
|
||||
m_viewAngularManipulator->SetView(CreateManipulatorViewCircle(
|
||||
*m_viewAngularManipulator, AZ::Color(1.0f, 1.0f, 1.0f, 1.0f), radius + (radius * 0.12f), 0.05f, DrawFullCircle));
|
||||
*m_viewAngularManipulator, AZ::Color(1.0f, 1.0f, 1.0f, 1.0f), radius * viewAlignedScale, m_circleBoundWidth,
|
||||
DrawFullCircle));
|
||||
}
|
||||
|
||||
bool RotationManipulators::PerformingActionViewAxis() const
|
||||
@@ -151,4 +153,9 @@ namespace AzToolsFramework
|
||||
|
||||
manipulatorFn(m_viewAngularManipulator.get());
|
||||
}
|
||||
|
||||
void RotationManipulators::SetCircleBoundWidth(const float circleBoundWidth)
|
||||
{
|
||||
m_circleBoundWidth = circleBoundWidth;
|
||||
}
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
@@ -42,6 +42,9 @@ namespace AzToolsFramework
|
||||
|
||||
bool PerformingActionViewAxis() const;
|
||||
|
||||
//! Sets the bound width to use for the circle (torus) of an angular manipulator.
|
||||
void SetCircleBoundWidth(float circleBoundWidth);
|
||||
|
||||
private:
|
||||
AZ_DISABLE_COPY_MOVE(RotationManipulators)
|
||||
|
||||
@@ -49,5 +52,6 @@ namespace AzToolsFramework
|
||||
|
||||
AZStd::array<AZStd::shared_ptr<AngularManipulator>, 3> m_localAngularManipulators;
|
||||
AZStd::shared_ptr<AngularManipulator> m_viewAngularManipulator;
|
||||
float m_circleBoundWidth = 0.1f; //!< The default circle bound width for the angular manipulator torus.
|
||||
};
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
@@ -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
|
||||
|
||||
+13
-7
@@ -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());
|
||||
|
||||
+4
@@ -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
|
||||
|
||||
+76
-4
@@ -16,6 +16,79 @@ namespace AzToolsFramework
|
||||
{
|
||||
namespace Picking
|
||||
{
|
||||
// this intersection algorithm is adapted from 'Capped Cone' by Inigo Quilez
|
||||
// ref: https://www.iquilezles.org/www/articles/intersectors/intersectors.htm and https://www.shadertoy.com/view/llcfRf
|
||||
// all algorithms/code snippets are kindly made available under the MIT License - https://www.iquilezles.org/www/index.htm
|
||||
bool IntersectRayCone(
|
||||
const AZ::Vector3& rayOrigin,
|
||||
const AZ::Vector3& rayDirection,
|
||||
const AZ::Vector3& coneApex,
|
||||
const AZ::Vector3& coneAxis,
|
||||
float coneHeight,
|
||||
float coneBaseRadius,
|
||||
float& t)
|
||||
{
|
||||
const AZ::Vector3& pa = coneApex;
|
||||
const AZ::Vector3& pb = coneApex + coneHeight * coneAxis;
|
||||
const AZ::Vector3& ro = rayOrigin;
|
||||
const AZ::Vector3& rd = rayDirection;
|
||||
float rb = coneBaseRadius;
|
||||
|
||||
AZ::Vector3 ba = pb - pa;
|
||||
AZ::Vector3 oa = ro - pa;
|
||||
AZ::Vector3 ob = ro - pb;
|
||||
|
||||
float m0 = ba.Dot(ba);
|
||||
float m1 = oa.Dot(ba);
|
||||
float m2 = ob.Dot(ba);
|
||||
float m3 = rd.Dot(ba);
|
||||
|
||||
auto dot2 = [](const AZ::Vector3& v)
|
||||
{
|
||||
return v.Dot(v);
|
||||
};
|
||||
|
||||
// cap
|
||||
if (m2 > 0.0f)
|
||||
{
|
||||
if (dot2(ob * m3 - rd * m2) < (rb * rb * m3 * m3))
|
||||
{
|
||||
t = -m2 / m3;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// body
|
||||
float m4 = rd.Dot(oa);
|
||||
float m5 = oa.Dot(oa);
|
||||
float hy = m0 + rb * rb;
|
||||
|
||||
float k2 = m0 * m0 - m3 * m3 * hy;
|
||||
float k1 = m0 * m0 * m4 - m1 * m3 * hy;
|
||||
float k0 = m0 * m0 * m5 - m1 * m1 * hy;
|
||||
|
||||
// note: solving for simultaneously being on the sloping surface of the cone and being on the ray boils down
|
||||
// to a quadratic equation - the discriminant of the quadratic determines if there are 1, 2 or no solutions
|
||||
//
|
||||
// if the discriminant is less than 0 the ray is not intersecting the cone, if it is equal to 0 then the ray
|
||||
// is intersecting the cone once and if it is greater than 0 the ray is intersecting the cone twice
|
||||
float discriminant = k1 * k1 - k2 * k0;
|
||||
if (discriminant < 0.0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float tt = (-k1 - AZ::Sqrt(discriminant)) / k2;
|
||||
float y = m1 + tt * m3;
|
||||
if (y >= 0.0f && y < m0)
|
||||
{
|
||||
t = tt;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ManipulatorBoundSphere::IntersectRay(
|
||||
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection, float& rayIntersectionDistance)
|
||||
{
|
||||
@@ -86,11 +159,10 @@ namespace AzToolsFramework
|
||||
bool ManipulatorBoundCone::IntersectRay(
|
||||
const AZ::Vector3& rayOrigin, const AZ::Vector3& rayDirection, float& rayIntersectionDistance)
|
||||
{
|
||||
float t1 = std::numeric_limits<float>::max();
|
||||
float t2 = std::numeric_limits<float>::max();
|
||||
if (AZ::Intersect::IntersectRayCone(rayOrigin, rayDirection, m_apexPosition, m_dir, m_height, m_radius, t1, t2) > 0)
|
||||
float t = std::numeric_limits<float>::max();
|
||||
if (IntersectRayCone(rayOrigin, rayDirection, m_apexPosition, m_dir, m_height, m_radius, t))
|
||||
{
|
||||
rayIntersectionDistance = AZStd::GetMin(t1, t2);
|
||||
rayIntersectionDistance = t;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+20
@@ -23,6 +23,26 @@ namespace AzToolsFramework
|
||||
{
|
||||
namespace Picking
|
||||
{
|
||||
//! Custom ray/cone intersect function for manipulator bounds to workaround a bug in the current AZ::Intersect implementation.
|
||||
//! @note Does not give reliable results if the ray origin is inside the cone.
|
||||
//! @param rayOrigin The origin of the ray to test.
|
||||
//! @param rayDirection The direction of the ray to test, it must be unit length.
|
||||
//! @param coneApex The apex of the cone.
|
||||
//! @param coneAxis The unit-length axis (direction) from the apex to the base.
|
||||
//! @param coneHeight The height of the cone, from the apex to the base.
|
||||
//! @param coneBaseRadius The radius of the cone base.
|
||||
//! @param[out] t A possible coefficient in the ray's explicit equation from which an intersecting point is calculated
|
||||
//! as "rayOrigin + t * rayDirection". 't' is the closest intersecting point to the ray origin.
|
||||
//! @return true for intersecting, false for not intersecting.
|
||||
bool IntersectRayCone(
|
||||
const AZ::Vector3& rayOrigin,
|
||||
const AZ::Vector3& rayDirection,
|
||||
const AZ::Vector3& coneApex,
|
||||
const AZ::Vector3& coneAxis,
|
||||
float coneHeight,
|
||||
float coneBaseRadius,
|
||||
float& t);
|
||||
|
||||
class ManipulatorBoundSphere : public BoundShapeInterface
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace AzToolsFramework
|
||||
m_prefabUndoCache.Destroy();
|
||||
}
|
||||
|
||||
PrefabOperationResult PrefabPublicHandler::CreatePrefabInMemory(const EntityIdList& entityIds, AZ::IO::PathView filePath)
|
||||
CreatePrefabResult PrefabPublicHandler::CreatePrefabInMemory(const EntityIdList& entityIds, AZ::IO::PathView filePath)
|
||||
{
|
||||
EntityList inputEntityList, topLevelEntities;
|
||||
AZ::EntityId commonRootEntityId;
|
||||
@@ -70,9 +70,11 @@ namespace AzToolsFramework
|
||||
entityIds, inputEntityList, topLevelEntities, commonRootEntityId, commonRootEntityOwningInstance);
|
||||
if (!findCommonRootOutcome.IsSuccess())
|
||||
{
|
||||
return findCommonRootOutcome;
|
||||
return AZ::Failure(findCommonRootOutcome.TakeError());
|
||||
}
|
||||
|
||||
AZ::EntityId containerEntityId;
|
||||
|
||||
InstanceOptionalReference instanceToCreate;
|
||||
{
|
||||
// Initialize Undo Batch object
|
||||
@@ -92,7 +94,7 @@ namespace AzToolsFramework
|
||||
inputEntityList, commonRootEntityOwningInstance->get(), entities, instances);
|
||||
if (!retrieveEntitiesAndInstancesOutcome.IsSuccess())
|
||||
{
|
||||
return retrieveEntitiesAndInstancesOutcome;
|
||||
return AZ::Failure(retrieveEntitiesAndInstancesOutcome.TakeError());
|
||||
}
|
||||
|
||||
AZStd::unordered_map<AZ::EntityId, AZStd::string> oldEntityAliases;
|
||||
@@ -153,7 +155,7 @@ namespace AzToolsFramework
|
||||
"(A null instance is returned)."));
|
||||
}
|
||||
|
||||
AZ::EntityId containerEntityId = instanceToCreate->get().GetContainerEntityId();
|
||||
containerEntityId = instanceToCreate->get().GetContainerEntityId();
|
||||
|
||||
// Apply the correct transform to the container for the new instance, and store the patch for use when creating the link.
|
||||
PrefabDom patch = ApplyContainerTransformAndGeneratePatch(containerEntityId, commonRootEntityId, topLevelEntities);
|
||||
@@ -261,10 +263,10 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
return AZ::Success();
|
||||
return AZ::Success(containerEntityId);
|
||||
}
|
||||
|
||||
PrefabOperationResult PrefabPublicHandler::CreatePrefabInDisk(const EntityIdList& entityIds, AZ::IO::PathView filePath)
|
||||
CreatePrefabResult PrefabPublicHandler::CreatePrefabInDisk(const EntityIdList& entityIds, AZ::IO::PathView filePath)
|
||||
{
|
||||
auto result = CreatePrefabInMemory(entityIds, filePath);
|
||||
if (result.IsSuccess())
|
||||
|
||||
@@ -42,11 +42,12 @@ namespace AzToolsFramework
|
||||
void UnregisterPrefabPublicHandlerInterface();
|
||||
|
||||
// PrefabPublicInterface...
|
||||
PrefabOperationResult CreatePrefabInDisk(
|
||||
CreatePrefabResult CreatePrefabInDisk(
|
||||
const EntityIdList& entityIds, AZ::IO::PathView filePath) override;
|
||||
PrefabOperationResult CreatePrefabInMemory(
|
||||
CreatePrefabResult CreatePrefabInMemory(
|
||||
const EntityIdList& entityIds, AZ::IO::PathView filePath) override;
|
||||
InstantiatePrefabResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) override;
|
||||
InstantiatePrefabResult InstantiatePrefab(
|
||||
AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) override;
|
||||
PrefabOperationResult SavePrefab(AZ::IO::Path filePath) override;
|
||||
PrefabEntityResult CreateEntity(AZ::EntityId parentId, const AZ::Vector3& position) override;
|
||||
|
||||
|
||||
@@ -24,8 +24,9 @@ namespace AzToolsFramework
|
||||
|
||||
namespace Prefab
|
||||
{
|
||||
typedef AZ::Outcome<void, AZStd::string> PrefabOperationResult;
|
||||
typedef AZ::Outcome<AZ::EntityId, AZStd::string> CreatePrefabResult;
|
||||
typedef AZ::Outcome<AZ::EntityId, AZStd::string> InstantiatePrefabResult;
|
||||
typedef AZ::Outcome<void, AZStd::string> PrefabOperationResult;
|
||||
typedef AZ::Outcome<bool, AZStd::string> PrefabRequestResult;
|
||||
typedef AZ::Outcome<AZ::EntityId, AZStd::string> PrefabEntityResult;
|
||||
|
||||
@@ -44,9 +45,10 @@ namespace AzToolsFramework
|
||||
* Automatically detects descendants of entities, and discerns between entities and child instances.
|
||||
* @param entityIds The entities that should form the new prefab (along with their descendants).
|
||||
* @param filePath The absolute path for the new prefab file.
|
||||
* @return An outcome object; on failure, it comes with an error message detailing the cause of the error.
|
||||
* @return An outcome object with an entityId of the new prefab's container entity;
|
||||
* on failure, it comes with an error message detailing the cause of the error.
|
||||
*/
|
||||
virtual PrefabOperationResult CreatePrefabInDisk(
|
||||
virtual CreatePrefabResult CreatePrefabInDisk(
|
||||
const EntityIdList& entityIds, AZ::IO::PathView filePath) = 0;
|
||||
|
||||
/**
|
||||
@@ -54,9 +56,10 @@ namespace AzToolsFramework
|
||||
* Automatically detects descendants of entities, and discerns between entities and child instances.
|
||||
* @param entityIds The entities that should form the new prefab (along with their descendants).
|
||||
* @param filePath The absolute path for the new prefab file.
|
||||
* @return An outcome object; on failure, it comes with an error message detailing the cause of the error.
|
||||
* @return An outcome object with an entityId of the new prefab's container entity;
|
||||
* on failure, it comes with an error message detailing the cause of the error.
|
||||
*/
|
||||
virtual PrefabOperationResult CreatePrefabInMemory(
|
||||
virtual CreatePrefabResult CreatePrefabInMemory(
|
||||
const EntityIdList& entityIds, AZ::IO::PathView filePath) = 0;
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <AzCore/Component/EntityId.h>
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzCore/Math/Vector3.h>
|
||||
#include <AzCore/Outcome/Outcome.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
@@ -22,8 +23,9 @@ namespace AzToolsFramework
|
||||
|
||||
namespace Prefab
|
||||
{
|
||||
using PrefabOperationResult = AZ::Outcome<void, AZStd::string>;
|
||||
using CreatePrefabResult = AZ::Outcome<AZ::EntityId, AZStd::string>;
|
||||
using InstantiatePrefabResult = AZ::Outcome<AZ::EntityId, AZStd::string>;
|
||||
using PrefabOperationResult = AZ::Outcome<void, AZStd::string>;
|
||||
|
||||
/**
|
||||
* The primary purpose of this bus is to facilitate writing automated tests for prefabs.
|
||||
@@ -47,14 +49,16 @@ namespace AzToolsFramework
|
||||
/**
|
||||
* Create a prefab out of the entities provided, at the path provided, and keep it in memory.
|
||||
* Automatically detects descendants of entities, and discerns between entities and child instances.
|
||||
* Return whether the creation succeeded or not.
|
||||
* Return an outcome object with an container entity id of the prefab created if creation succeeded;
|
||||
* on failure, it comes with an error message detailing the cause of the error.
|
||||
*/
|
||||
virtual PrefabOperationResult CreatePrefabInMemory(
|
||||
virtual CreatePrefabResult CreatePrefabInMemory(
|
||||
const EntityIdList& entityIds, AZStd::string_view filePath) = 0;
|
||||
|
||||
/**
|
||||
* Instantiate a prefab from a prefab file.
|
||||
* Return the container entity id of the prefab instantiated if instantiation succeeded.
|
||||
* Return an outcome object with an container entity id of the prefab instantiated if instantiation succeeded;
|
||||
* on failure, it comes with an error message detailing the cause of the error.
|
||||
*/
|
||||
virtual InstantiatePrefabResult InstantiatePrefab(
|
||||
AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) = 0;
|
||||
@@ -62,10 +66,9 @@ namespace AzToolsFramework
|
||||
/**
|
||||
* Deletes all entities and their descendants from the owning instance. Bails if the entities don't
|
||||
* all belong to the same instance.
|
||||
* Return whether the deletion succeeded or not.
|
||||
* Return an outcome object; on failure, it comes with an error message detailing the cause of the error.
|
||||
*/
|
||||
virtual PrefabOperationResult DeleteEntitiesAndAllDescendantsInInstance(const EntityIdList& entityIds) = 0;
|
||||
|
||||
};
|
||||
|
||||
using PrefabPublicRequestBus = AZ::EBus<PrefabPublicRequests>;
|
||||
|
||||
+1
-1
@@ -45,7 +45,7 @@ namespace AzToolsFramework
|
||||
m_prefabPublicInterface = nullptr;
|
||||
}
|
||||
|
||||
PrefabOperationResult PrefabPublicRequestHandler::CreatePrefabInMemory(const EntityIdList& entityIds, AZStd::string_view filePath)
|
||||
CreatePrefabResult PrefabPublicRequestHandler::CreatePrefabInMemory(const EntityIdList& entityIds, AZStd::string_view filePath)
|
||||
{
|
||||
return m_prefabPublicInterface->CreatePrefabInMemory(entityIds, filePath);
|
||||
}
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ namespace AzToolsFramework
|
||||
void Connect();
|
||||
void Disconnect();
|
||||
|
||||
PrefabOperationResult CreatePrefabInMemory(const EntityIdList& entityIds, AZStd::string_view filePath) override;
|
||||
CreatePrefabResult CreatePrefabInMemory(const EntityIdList& entityIds, AZStd::string_view filePath) override;
|
||||
InstantiatePrefabResult InstantiatePrefab(AZStd::string_view filePath, AZ::EntityId parent, const AZ::Vector3& position) override;
|
||||
PrefabOperationResult DeleteEntitiesAndAllDescendantsInInstance(const EntityIdList& entityIds) override;
|
||||
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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 <AzToolsFramework/Viewport/ViewportMessages.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction(
|
||||
const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
|
||||
{
|
||||
if (mouseInteraction.m_mouseInteraction.m_mouseButtons.Left())
|
||||
{
|
||||
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down)
|
||||
{
|
||||
return AzFramework::ClickDetector::ClickEvent::Down;
|
||||
}
|
||||
|
||||
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Up)
|
||||
{
|
||||
return AzFramework::ClickDetector::ClickEvent::Up;
|
||||
}
|
||||
}
|
||||
|
||||
return AzFramework::ClickDetector::ClickEvent::Nil;
|
||||
}
|
||||
|
||||
float ManipulatorLineBoundWidth(const AzFramework::ViewportId viewportId /*= AzFramework::InvalidViewportId*/)
|
||||
{
|
||||
float lineBoundWidth = 0.0f;
|
||||
if (viewportId != AzFramework::InvalidViewportId)
|
||||
{
|
||||
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
|
||||
lineBoundWidth, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::ManipulatorLineBoundWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
ViewportInteraction::ViewportSettingsRequestBus::BroadcastResult(
|
||||
lineBoundWidth, &ViewportInteraction::ViewportSettingsRequestBus::Events::ManipulatorLineBoundWidth);
|
||||
}
|
||||
|
||||
return lineBoundWidth;
|
||||
}
|
||||
|
||||
float ManipulatorCicleBoundWidth(const AzFramework::ViewportId viewportId /*= AzFramework::InvalidViewportId*/)
|
||||
{
|
||||
float circleBoundWidth = 0.0f;
|
||||
if (viewportId != AzFramework::InvalidViewportId)
|
||||
{
|
||||
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
|
||||
circleBoundWidth, viewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::ManipulatorCircleBoundWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
ViewportInteraction::ViewportSettingsRequestBus::BroadcastResult(
|
||||
circleBoundWidth, &ViewportInteraction::ViewportSettingsRequestBus::Events::ManipulatorCircleBoundWidth);
|
||||
}
|
||||
|
||||
return circleBoundWidth;
|
||||
}
|
||||
} // namespace AzToolsFramework
|
||||
@@ -156,22 +156,12 @@ 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.
|
||||
virtual bool GridSnappingEnabled() = 0;
|
||||
//! Return 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.
|
||||
virtual bool AngleSnappingEnabled() = 0;
|
||||
//! Return the angle snapping/step size.
|
||||
virtual float AngleStep() = 0;
|
||||
//! Transform a point in world space to screen space coordinates in Qt Widget space.
|
||||
//! 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;
|
||||
@@ -185,12 +175,13 @@ namespace AzToolsFramework
|
||||
~ViewportInteractionRequests() = default;
|
||||
};
|
||||
|
||||
//! Type to inherit to implement ViewportInteractionRequests.
|
||||
using ViewportInteractionRequestBus = AZ::EBus<ViewportInteractionRequests, ViewportEBusTraits>;
|
||||
|
||||
//! Interface to return only viewport specific settings (e.g. snapping).
|
||||
class ViewportSettings
|
||||
class ViewportSettingsRequests
|
||||
{
|
||||
public:
|
||||
virtual ~ViewportSettings() = default;
|
||||
|
||||
//! Return if grid snapping is enabled.
|
||||
virtual bool GridSnappingEnabled() const = 0;
|
||||
//! Return the grid snapping size.
|
||||
@@ -201,20 +192,31 @@ 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;
|
||||
//! Returns the current circle (torus) bound width for manipulators.
|
||||
virtual float ManipulatorCircleBoundWidth() const = 0;
|
||||
|
||||
protected:
|
||||
~ViewportSettingsRequests() = default;
|
||||
};
|
||||
|
||||
//! Type to inherit to implement ViewportInteractionRequests.
|
||||
using ViewportInteractionRequestBus = AZ::EBus<ViewportInteractionRequests, ViewportEBusTraits>;
|
||||
//! Type to inherit to implement ViewportSettingsRequests.
|
||||
using ViewportSettingsRequestBus = AZ::EBus<ViewportSettingsRequests, ViewportEBusTraits>;
|
||||
|
||||
//! An interface to notify when changes to viewport settings have happened.
|
||||
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>;
|
||||
@@ -248,8 +250,6 @@ namespace AzToolsFramework
|
||||
virtual AZ::Vector3 PickTerrain(const AzFramework::ScreenPoint& point) = 0;
|
||||
//! Return the terrain height given a world position in 2d (xy plane).
|
||||
virtual float TerrainHeight(const AZ::Vector2& position) = 0;
|
||||
//! Given the current view frustum (viewport) return all visible entities.
|
||||
virtual void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntities) = 0;
|
||||
//! Is the user holding a modifier key to move the manipulator space from local to world.
|
||||
virtual bool ShowingWorldSpace() = 0;
|
||||
//! Return the widget to use as the parent for the viewport context menu.
|
||||
@@ -267,7 +267,20 @@ namespace AzToolsFramework
|
||||
//! Type to inherit to implement MainEditorViewportInteractionRequests.
|
||||
using MainEditorViewportInteractionRequestBus = AZ::EBus<MainEditorViewportInteractionRequests, ViewportEBusTraits>;
|
||||
|
||||
//! Viewport requests for managing the viewport's cursor state.
|
||||
//! Editor entity requests to be made about the viewport.
|
||||
class EditorEntityViewportInteractionRequests
|
||||
{
|
||||
public:
|
||||
//! Given the current view frustum (viewport) return all visible entities.
|
||||
virtual void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntities) = 0;
|
||||
|
||||
protected:
|
||||
~EditorEntityViewportInteractionRequests() = default;
|
||||
};
|
||||
|
||||
using EditorEntityViewportInteractionRequestBus = AZ::EBus<EditorEntityViewportInteractionRequests, ViewportEBusTraits>;
|
||||
|
||||
//! Viewport requests for managing the viewport cursor state.
|
||||
class ViewportMouseCursorRequests
|
||||
{
|
||||
public:
|
||||
@@ -319,21 +332,14 @@ namespace AzToolsFramework
|
||||
|
||||
//! Maps a mouse interaction event to a ClickDetector event.
|
||||
//! @note Function only cares about up or down events, all other events are mapped to Nil (ignored).
|
||||
inline AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction(
|
||||
const ViewportInteraction::MouseInteractionEvent& mouseInteraction)
|
||||
{
|
||||
if (mouseInteraction.m_mouseInteraction.m_mouseButtons.Left())
|
||||
{
|
||||
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Down)
|
||||
{
|
||||
return AzFramework::ClickDetector::ClickEvent::Down;
|
||||
}
|
||||
AzFramework::ClickDetector::ClickEvent ClickDetectorEventFromViewportInteraction(
|
||||
const ViewportInteraction::MouseInteractionEvent& mouseInteraction);
|
||||
|
||||
if (mouseInteraction.m_mouseEvent == ViewportInteraction::MouseEvent::Up)
|
||||
{
|
||||
return AzFramework::ClickDetector::ClickEvent::Up;
|
||||
}
|
||||
}
|
||||
return AzFramework::ClickDetector::ClickEvent::Nil;
|
||||
}
|
||||
//! Wrap EBus call to retrieve manipulator line bound width.
|
||||
//! @note It is possible to pass AzFramework::InvalidViewportId (the default) to perform a Broadcast as opposed to a targeted Event.
|
||||
float ManipulatorLineBoundWidth(AzFramework::ViewportId viewportId = AzFramework::InvalidViewportId);
|
||||
|
||||
//! Wrap EBus call to retrieve manipulator circle bound width.
|
||||
//! @note It is possible to pass AzFramework::InvalidViewportId (the default) to perform a Broadcast as opposed to a targeted Event.
|
||||
float ManipulatorCicleBoundWidth(AzFramework::ViewportId viewportId = AzFramework::InvalidViewportId);
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
+18
-8
@@ -19,7 +19,7 @@
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
// default ray length for picking in the viewport
|
||||
static const float s_pickRayLength = 1000.0f;
|
||||
static const float EditorPickRayLength = 1000.0f;
|
||||
|
||||
AZ::Vector3 CalculateCenterOffset(const AZ::EntityId entityId, const EditorTransformComponentSelectionRequests::Pivot pivot)
|
||||
{
|
||||
@@ -60,16 +60,27 @@ namespace AzToolsFramework
|
||||
return screenPosition;
|
||||
}
|
||||
|
||||
bool AabbIntersectMouseRay(const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb)
|
||||
bool AabbIntersectRay(const AZ::Vector3& origin, const AZ::Vector3& direction, const AZ::Aabb& aabb, float& distance)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AzToolsFramework);
|
||||
|
||||
const AZ::Vector3 rayScaledDir = mouseInteraction.m_mousePick.m_rayDirection * s_pickRayLength;
|
||||
const AZ::Vector3 rayScaledDir = direction * EditorPickRayLength;
|
||||
|
||||
AZ::Vector3 startNormal;
|
||||
float t, end;
|
||||
return AZ::Intersect::IntersectRayAABB(
|
||||
mouseInteraction.m_mousePick.m_rayOrigin, rayScaledDir, rayScaledDir.GetReciprocal(), aabb, t, end, startNormal) > 0;
|
||||
AZ::Vector3 startNormal;
|
||||
if (AZ::Intersect::IntersectRayAABB(origin, rayScaledDir, rayScaledDir.GetReciprocal(), aabb, t, end, startNormal) > 0)
|
||||
{
|
||||
distance = t * EditorPickRayLength;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AabbIntersectMouseRay(const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb)
|
||||
{
|
||||
float unused;
|
||||
return AabbIntersectRay(mouseInteraction.m_mousePick.m_rayOrigin, mouseInteraction.m_mousePick.m_rayDirection, aabb, unused);
|
||||
}
|
||||
|
||||
bool PickEntity(
|
||||
@@ -117,8 +128,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
float scaling = 1.0f;
|
||||
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
|
||||
scaling, viewportId,
|
||||
&ViewportInteraction::ViewportInteractionRequestBus::Events::DeviceScalingFactor);
|
||||
scaling, viewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::DeviceScalingFactor);
|
||||
|
||||
return scaling;
|
||||
}
|
||||
|
||||
+4
@@ -46,6 +46,10 @@ namespace AzToolsFramework
|
||||
//! in screen space intersected an aabb in world space.
|
||||
bool AabbIntersectMouseRay(const ViewportInteraction::MouseInteraction& mouseInteraction, const AZ::Aabb& aabb);
|
||||
|
||||
//! Wrapper to perform an intersection between a ray and an aabb.
|
||||
//! Note: direction should be normalized (it is scaled internally by the editor pick distance).
|
||||
bool AabbIntersectRay(const AZ::Vector3& origin, const AZ::Vector3& direction, const AZ::Aabb& aabb, float& distance);
|
||||
|
||||
//! Return if a mouse interaction (pick ray) did intersect the tested EntityId.
|
||||
bool PickEntity(
|
||||
AZ::EntityId entityId, const ViewportInteraction::MouseInteraction& mouseInteraction, float& closestDistance, int viewportId);
|
||||
|
||||
+7
-4
@@ -488,8 +488,8 @@ namespace AzToolsFramework
|
||||
void SnappingCluster::TrySetVisible(const bool visible)
|
||||
{
|
||||
bool snapping = false;
|
||||
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
|
||||
snapping, ViewportUi::DefaultViewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::GridSnappingEnabled);
|
||||
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
|
||||
snapping, ViewportUi::DefaultViewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::GridSnappingEnabled);
|
||||
|
||||
// show snapping viewport ui only if there are entities selected and snapping is enabled
|
||||
SetViewportUiClusterVisible(m_clusterId, visible && snapping);
|
||||
@@ -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);
|
||||
|
||||
@@ -1376,6 +1377,7 @@ namespace AzToolsFramework
|
||||
|
||||
AZStd::unique_ptr<RotationManipulators> rotationManipulators =
|
||||
AZStd::make_unique<RotationManipulators>(AZ::Transform::CreateIdentity());
|
||||
rotationManipulators->SetCircleBoundWidth(ManipulatorCicleBoundWidth(ViewportUi::DefaultViewportId));
|
||||
|
||||
InitializeManipulators(*rotationManipulators);
|
||||
|
||||
@@ -1545,6 +1547,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);
|
||||
|
||||
@@ -2544,8 +2547,8 @@ namespace AzToolsFramework
|
||||
if (buttonId == m_snappingCluster.m_snapToWorldButtonId)
|
||||
{
|
||||
float gridSize = 1.0f;
|
||||
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
|
||||
gridSize, ViewportUi::DefaultViewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::GridSize);
|
||||
ViewportInteraction::ViewportSettingsRequestBus::EventResult(
|
||||
gridSize, ViewportUi::DefaultViewportId, &ViewportInteraction::ViewportSettingsRequestBus::Events::GridSize);
|
||||
|
||||
SnapSelectedEntitiesToWorldGrid(gridSize);
|
||||
}
|
||||
|
||||
+2
-2
@@ -161,8 +161,8 @@ namespace AzToolsFramework
|
||||
|
||||
// request list of visible entities from authoritative system
|
||||
EntityIdList nextVisibleEntityIds;
|
||||
ViewportInteraction::MainEditorViewportInteractionRequestBus::Event(
|
||||
viewportInfo.m_viewportId, &ViewportInteraction::MainEditorViewportInteractionRequestBus::Events::FindVisibleEntities,
|
||||
ViewportInteraction::EditorEntityViewportInteractionRequestBus::Event(
|
||||
viewportInfo.m_viewportId, &ViewportInteraction::EditorEntityViewportInteractionRequestBus::Events::FindVisibleEntities,
|
||||
nextVisibleEntityIds);
|
||||
|
||||
// only bother resorting if we know the lists have changed
|
||||
|
||||
@@ -481,6 +481,7 @@ set(FILES
|
||||
Viewport/VertexContainerDisplay.h
|
||||
Viewport/VertexContainerDisplay.cpp
|
||||
Viewport/ViewportMessages.h
|
||||
Viewport/ViewportMessages.cpp
|
||||
Viewport/ViewportTypes.h
|
||||
Viewport/ViewportTypes.cpp
|
||||
ViewportUi/Button.h
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ComponentModeTestDoubles.h"
|
||||
#include "ComponentModeTestFixture.h"
|
||||
#include "ComponentModeTestDoubles.h"
|
||||
|
||||
#include <AzCore/UserSettings/UserSettingsComponent.h>
|
||||
|
||||
@@ -15,17 +15,15 @@ namespace UnitTest
|
||||
{
|
||||
void ComponentModeTestFixture::SetUpEditorFixtureImpl()
|
||||
{
|
||||
using namespace AzToolsFramework;
|
||||
using namespace AzToolsFramework::ComponentModeFramework;
|
||||
namespace AztfCmf = AzToolsFramework::ComponentModeFramework;
|
||||
|
||||
auto* app = GetApplication();
|
||||
ASSERT_TRUE(app);
|
||||
|
||||
app->RegisterComponentDescriptor(PlaceholderEditorComponent::CreateDescriptor());
|
||||
app->RegisterComponentDescriptor(AnotherPlaceholderEditorComponent::CreateDescriptor());
|
||||
app->RegisterComponentDescriptor(DependentPlaceholderEditorComponent::CreateDescriptor());
|
||||
app->RegisterComponentDescriptor(AztfCmf::PlaceholderEditorComponent::CreateDescriptor());
|
||||
app->RegisterComponentDescriptor(AztfCmf::AnotherPlaceholderEditorComponent::CreateDescriptor());
|
||||
app->RegisterComponentDescriptor(AztfCmf::DependentPlaceholderEditorComponent::CreateDescriptor());
|
||||
app->RegisterComponentDescriptor(
|
||||
TestComponentModeComponent<OverrideMouseInteractionComponentMode>::CreateDescriptor());
|
||||
app->RegisterComponentDescriptor(IncompatiblePlaceholderEditorComponent::CreateDescriptor());
|
||||
AztfCmf::TestComponentModeComponent<AztfCmf::OverrideMouseInteractionComponentMode>::CreateDescriptor());
|
||||
app->RegisterComponentDescriptor(AztfCmf::IncompatiblePlaceholderEditorComponent::CreateDescriptor());
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -187,4 +187,51 @@ namespace UnitTest
|
||||
EXPECT_NEAR(intersectionDistance, 10.0f, g_epsilon);
|
||||
EXPECT_TRUE(intersection);
|
||||
}
|
||||
|
||||
// replicates a scenario in the Editor using a cone and a pick ray which should have failed but passed with Intersect::IntersectRayCone
|
||||
TEST(ManipulatorIntersectRayConeTest, RayConeEditorScenarioTest)
|
||||
{
|
||||
auto rayOrigin = AZ::Vector3(0.0f, -0.808944702f, 0.0f);
|
||||
auto rayDir = AZ::Vector3(0.301363617f, 0.939044654f, 0.165454566f);
|
||||
float t = 0.0f;
|
||||
bool hit = AzToolsFramework::Picking::IntersectRayCone(
|
||||
rayOrigin, rayDir, AZ::Vector3(0.0f, 0.0f, 0.161788940f), AZ::Vector3(0.0f, 0.0f, -1.0f), 0.0453009047, 0.0113252262, t);
|
||||
EXPECT_FALSE(hit);
|
||||
}
|
||||
|
||||
// cone lying flat, ray going towards base of cone
|
||||
TEST(ManipulatorIntersectRayConeTest, RayIntersectsConeBase)
|
||||
{
|
||||
auto rayOrigin = AZ::Vector3::CreateZero();
|
||||
auto rayDir = AZ::Vector3::CreateAxisY();
|
||||
float t = 0.0f;
|
||||
bool hit = AzToolsFramework::Picking::IntersectRayCone(
|
||||
rayOrigin, rayDir, AZ::Vector3::CreateAxisY(10.0f), AZ::Vector3::CreateAxisY(-1.0f), 5.0f, 1.0f, t);
|
||||
EXPECT_TRUE(hit);
|
||||
EXPECT_THAT(t, ::testing::FloatNear(5.0f, 0.0001f));
|
||||
}
|
||||
|
||||
// cone standing up, ray going towards mid side of cone
|
||||
TEST(ManipulatorIntersectRayConeTest, RayIntersectsConeSide)
|
||||
{
|
||||
auto rayOrigin = AZ::Vector3::CreateZero();
|
||||
auto rayDir = AZ::Vector3::CreateAxisY();
|
||||
float t = 0.0f;
|
||||
bool hit = AzToolsFramework::Picking::IntersectRayCone(
|
||||
rayOrigin, rayDir, AZ::Vector3(0.0f, 10.0f, 5.0f), AZ::Vector3::CreateAxisZ(-1.0f), 10.0f, 5.0f, t);
|
||||
EXPECT_TRUE(hit);
|
||||
EXPECT_THAT(t, ::testing::FloatNear(7.5f, 0.0001f));
|
||||
}
|
||||
|
||||
// cone standing up, ray going towards mid side of cone
|
||||
TEST(ManipulatorIntersectRayConeTest, RayIntersectsConeApex)
|
||||
{
|
||||
auto rayOrigin = AZ::Vector3::CreateZero();
|
||||
auto rayDir = AZ::Vector3::CreateAxisY();
|
||||
float t = 0.0f;
|
||||
bool hit = AzToolsFramework::Picking::IntersectRayCone(
|
||||
rayOrigin, rayDir, AZ::Vector3::CreateAxisY(2.5f), AZ::Vector3::CreateAxisY(1.0f), 5.0f, 1.0f, t);
|
||||
EXPECT_TRUE(hit);
|
||||
EXPECT_THAT(t, ::testing::FloatNear(2.5f, 0.0001f));
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
Reference in New Issue
Block a user