Merge pull request #7463 from aws-lumberyard-dev/box-manipulators-nus
Fixing various bugs with collider and box shape manipulators with non-uniform scale
This commit is contained in:
+38
-28
@@ -14,6 +14,8 @@
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorSnapping.h>
|
||||
#include <AzFramework/Viewport/ViewportColors.h>
|
||||
#include <AzFramework/Viewport/ViewportConstants.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Component/NonUniformScaleBus.h>
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
@@ -37,20 +39,20 @@ namespace AzToolsFramework
|
||||
void BoxViewportEdit::UpdateManipulators()
|
||||
{
|
||||
AZ::Transform boxWorldFromLocal = AZ::Transform::CreateIdentity();
|
||||
BoxManipulatorRequestBus::EventResult(
|
||||
boxWorldFromLocal, m_entityComponentIdPair, &BoxManipulatorRequests::GetCurrentTransform);
|
||||
AZ::TransformBus::EventResult(
|
||||
boxWorldFromLocal, m_entityComponentIdPair.GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
|
||||
|
||||
AZ::Vector3 boxScale = AZ::Vector3::CreateOne();
|
||||
BoxManipulatorRequestBus::EventResult(
|
||||
boxScale, m_entityComponentIdPair, &BoxManipulatorRequests::GetBoxScale);
|
||||
AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne();
|
||||
AZ::NonUniformScaleRequestBus::EventResult(
|
||||
nonUniformScale, m_entityComponentIdPair.GetEntityId(), &AZ::NonUniformScaleRequestBus::Events::GetScale);
|
||||
|
||||
AZ::Vector3 boxDimensions = AZ::Vector3::CreateZero();
|
||||
BoxManipulatorRequestBus::EventResult(
|
||||
boxDimensions, m_entityComponentIdPair, &BoxManipulatorRequests::GetDimensions);
|
||||
boxDimensions, m_entityComponentIdPair, &BoxManipulatorRequestBus::Events::GetDimensions);
|
||||
|
||||
// ensure we apply the entity scale to the box dimensions so
|
||||
// the manipulators appear in the correct location
|
||||
boxDimensions *= boxScale;
|
||||
AZ::Transform boxLocalTransform = AZ::Transform::CreateIdentity();
|
||||
BoxManipulatorRequestBus::EventResult(
|
||||
boxLocalTransform, m_entityComponentIdPair, &BoxManipulatorRequestBus::Events::GetCurrentLocalTransform);
|
||||
|
||||
for (size_t manipulatorIndex = 0; manipulatorIndex < m_linearManipulators.size(); ++manipulatorIndex)
|
||||
{
|
||||
@@ -58,7 +60,8 @@ namespace AzToolsFramework
|
||||
{
|
||||
linearManipulator->SetSpace(boxWorldFromLocal);
|
||||
linearManipulator->SetLocalTransform(
|
||||
AZ::Transform::CreateTranslation(s_boxAxes[manipulatorIndex] * 0.5f * boxDimensions));
|
||||
boxLocalTransform * AZ::Transform::CreateTranslation(s_boxAxes[manipulatorIndex] * 0.5f * boxDimensions));
|
||||
linearManipulator->SetNonUniformScale(nonUniformScale);
|
||||
linearManipulator->SetBoundsDirty();
|
||||
}
|
||||
}
|
||||
@@ -69,8 +72,8 @@ namespace AzToolsFramework
|
||||
m_entityComponentIdPair = entityComponentIdPair;
|
||||
|
||||
AZ::Transform worldFromLocal = AZ::Transform::CreateIdentity();
|
||||
BoxManipulatorRequestBus::EventResult(
|
||||
worldFromLocal, entityComponentIdPair, &BoxManipulatorRequests::GetCurrentTransform);
|
||||
AZ::TransformBus::EventResult(
|
||||
worldFromLocal, entityComponentIdPair.GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
|
||||
|
||||
for (size_t manipulatorIndex = 0; manipulatorIndex < m_linearManipulators.size(); ++manipulatorIndex)
|
||||
{
|
||||
@@ -85,36 +88,35 @@ namespace AzToolsFramework
|
||||
|
||||
ManipulatorViews views;
|
||||
views.emplace_back(CreateManipulatorViewQuadBillboard(
|
||||
AzFramework::ViewportColors::DefaultManipulatorHandleColor, AzFramework::ViewportConstants::DefaultManipulatorHandleSize));
|
||||
AzFramework::ViewportColors::DefaultManipulatorHandleColor,
|
||||
AzFramework::ViewportConstants::DefaultManipulatorHandleSize));
|
||||
linearManipulator->SetViews(AZStd::move(views));
|
||||
|
||||
linearManipulator->InstallMouseMoveCallback(
|
||||
[this, entityComponentIdPair](
|
||||
const LinearManipulator::Action& action)
|
||||
[this, entityComponentIdPair,
|
||||
transformScale{ linearManipulator->GetSpace().GetUniformScale() }](const LinearManipulator::Action& action)
|
||||
{
|
||||
AZ::Transform boxLocalTransform = AZ::Transform::CreateIdentity();
|
||||
BoxManipulatorRequestBus::EventResult(
|
||||
boxLocalTransform, entityComponentIdPair, &BoxManipulatorRequestBus::Events::GetCurrentLocalTransform);
|
||||
|
||||
const AZ::Vector3 manipulatorPosition = GetPositionInManipulatorFrame(transformScale, boxLocalTransform, action);
|
||||
|
||||
// calculate the amount of displacement along an axis this manipulator has moved
|
||||
// clamp movement so it cannot go negative based on axis direction
|
||||
const AZ::Vector3 axisDisplacement =
|
||||
action.LocalPosition().GetAbs() * 2.0f
|
||||
* AZ::GetMax<float>(0.0f, action.LocalPosition().GetNormalized().Dot(action.m_fixed.m_axis));
|
||||
|
||||
AZ::Vector3 boxScale = AZ::Vector3::CreateOne();
|
||||
BoxManipulatorRequestBus::EventResult(
|
||||
boxScale, entityComponentIdPair, &BoxManipulatorRequests::GetBoxScale);
|
||||
manipulatorPosition.GetAbs() * 2.0f
|
||||
* AZ::GetMax(0.0f, manipulatorPosition.GetNormalized().Dot(action.m_fixed.m_axis));
|
||||
|
||||
AZ::Vector3 boxDimensions = AZ::Vector3::CreateZero();
|
||||
BoxManipulatorRequestBus::EventResult(
|
||||
boxDimensions, entityComponentIdPair, &BoxManipulatorRequests::GetDimensions);
|
||||
|
||||
// ensure we take into account the entity scale using the axis displacement
|
||||
const AZ::Vector3 scaledAxisDisplacement =
|
||||
axisDisplacement / boxScale;
|
||||
boxDimensions, entityComponentIdPair, &BoxManipulatorRequestBus::Events::GetDimensions);
|
||||
|
||||
// update dimensions - preserve dimensions not effected by this
|
||||
// axis, and update current axis displacement
|
||||
BoxManipulatorRequestBus::Event(
|
||||
entityComponentIdPair, &BoxManipulatorRequests::SetDimensions,
|
||||
(NotAxis(action.m_fixed.m_axis) * boxDimensions).GetMax(scaledAxisDisplacement));
|
||||
entityComponentIdPair, &BoxManipulatorRequestBus::Events::SetDimensions,
|
||||
(NotAxis(action.m_fixed.m_axis) * boxDimensions).GetMax(axisDisplacement));
|
||||
|
||||
UpdateManipulators();
|
||||
});
|
||||
@@ -137,4 +139,12 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AZ::Vector3 GetPositionInManipulatorFrame(float worldUniformScale, const AZ::Transform& manipulatorLocalTransform,
|
||||
const LinearManipulator::Action& action)
|
||||
{
|
||||
return manipulatorLocalTransform.GetInverse().TransformPoint(
|
||||
action.m_start.m_localPosition +
|
||||
action.m_current.m_localPositionOffset / AZ::GetClamp(worldUniformScale, AZ::MinTransformScale, AZ::MaxTransformScale));
|
||||
}
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
@@ -31,4 +31,10 @@ namespace AzToolsFramework
|
||||
using BoxManipulators = AZStd::array<AZStd::shared_ptr<LinearManipulator>, 6>;
|
||||
BoxManipulators m_linearManipulators; ///< Manipulators for editing box size.
|
||||
};
|
||||
|
||||
/// Calculates the position of the manipulator in its own reference frame.
|
||||
/// Removes the effects of the manipulator local transform, and accounts for world transform scale in
|
||||
/// the action local offset.
|
||||
AZ::Vector3 GetPositionInManipulatorFrame(float worldUniformScale, const AZ::Transform& manipulatorLocalTransform,
|
||||
const LinearManipulator::Action& action);
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
+10
@@ -26,11 +26,21 @@ namespace AzToolsFramework
|
||||
virtual AZ::Vector3 GetDimensions() = 0;
|
||||
//! Set the X/Y/Z dimensions of the box shape/collider.
|
||||
virtual void SetDimensions(const AZ::Vector3& dimensions) = 0;
|
||||
// O3DE_DEPRECATION_NOTICE(GHI-7572)
|
||||
//! @deprecated Because non-uniform scale effects can be complex, it is recommended to separately use
|
||||
//! AZ::TransformBus::Events::GetWorldTM, AZ::NonUniformScaleRequests::GetScale and GetCurrentLocalTransform
|
||||
//! and combine their effects.
|
||||
//! Get the transform of the box shape/collider.
|
||||
//! This is used by \ref BoxComponentMode instead of the \ref \AZ::TransformBus
|
||||
//! because a collider may have an additional translation/orientation offset from
|
||||
//! the Entity transform.
|
||||
virtual AZ::Transform GetCurrentTransform() = 0;
|
||||
//! Get the transform of the box relative to the entity.
|
||||
virtual AZ::Transform GetCurrentLocalTransform() = 0;
|
||||
// O3DE_DEPRECATION_NOTICE(GHI-7572)
|
||||
//! @deprecated Because non-uniform scale effects can be complex, it is recommended to separately use
|
||||
//! AZ::TransformBus::Events::GetWorldTM, AZ::NonUniformScaleRequests::GetScale and GetCurrentLocalTransform
|
||||
//! and combine their effects.
|
||||
//! Get the scale currently applied to the box.
|
||||
//! With the Box Shape, the largest x/y/z component is taken
|
||||
//! so scale is always uniform, with colliders the scale may
|
||||
|
||||
@@ -161,6 +161,11 @@ namespace LmbrCentral
|
||||
return AzToolsFramework::TransformNormalizedScale(m_aaboxShape.GetCurrentTransform());
|
||||
}
|
||||
|
||||
AZ::Transform EditorAxisAlignedBoxShapeComponent::GetCurrentLocalTransform()
|
||||
{
|
||||
return AZ::Transform::CreateIdentity();
|
||||
}
|
||||
|
||||
AZ::Vector3 EditorAxisAlignedBoxShapeComponent::GetBoxScale()
|
||||
{
|
||||
return AZ::Vector3(m_aaboxShape.GetCurrentTransform().GetUniformScale() * m_aaboxShape.GetCurrentNonUniformScale());
|
||||
|
||||
@@ -58,6 +58,7 @@ namespace LmbrCentral
|
||||
AZ::Vector3 GetDimensions() override;
|
||||
void SetDimensions(const AZ::Vector3& dimensions) override;
|
||||
AZ::Transform GetCurrentTransform() override;
|
||||
AZ::Transform GetCurrentLocalTransform() override;
|
||||
AZ::Vector3 GetBoxScale() override;
|
||||
|
||||
void ConfigurationChanged();
|
||||
|
||||
@@ -167,6 +167,11 @@ namespace LmbrCentral
|
||||
return AzToolsFramework::TransformNormalizedScale(m_boxShape.GetCurrentTransform());
|
||||
}
|
||||
|
||||
AZ::Transform EditorBoxShapeComponent::GetCurrentLocalTransform()
|
||||
{
|
||||
return AZ::Transform::CreateIdentity();
|
||||
}
|
||||
|
||||
AZ::Vector3 EditorBoxShapeComponent::GetBoxScale()
|
||||
{
|
||||
return AZ::Vector3(m_boxShape.GetCurrentTransform().GetUniformScale() * m_boxShape.GetCurrentNonUniformScale());
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace LmbrCentral
|
||||
AZ::Vector3 GetDimensions() override;
|
||||
void SetDimensions(const AZ::Vector3& dimensions) override;
|
||||
AZ::Transform GetCurrentTransform() override;
|
||||
AZ::Transform GetCurrentLocalTransform() override;
|
||||
AZ::Vector3 GetBoxScale() override;
|
||||
|
||||
void ConfigurationChanged();
|
||||
|
||||
@@ -7,6 +7,17 @@
|
||||
*/
|
||||
#include "LmbrCentralReflectionTest.h"
|
||||
#include "Shape/EditorBoxShapeComponent.h"
|
||||
#include "Shape/EditorSphereShapeComponent.h"
|
||||
#include <AzCore/Component/NonUniformScaleBus.h>
|
||||
#include <AzFramework/Viewport/ViewportScreen.h>
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkTestHelpers.h>
|
||||
#include <AzManipulatorTestFramework/ImmediateModeActionDispatcher.h>
|
||||
#include <AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h>
|
||||
#include <AzManipulatorTestFramework/ViewportInteraction.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.h>
|
||||
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
|
||||
|
||||
namespace LmbrCentral
|
||||
{
|
||||
@@ -56,5 +67,110 @@ namespace LmbrCentral
|
||||
|
||||
EXPECT_EQ(dimensions, AZ::Vector3(0.37f, 0.57f, 0.66f));
|
||||
}
|
||||
|
||||
class EditorBoxShapeComponentFixture : public UnitTest::ToolsApplicationFixture
|
||||
{
|
||||
public:
|
||||
void SetUpEditorFixtureImpl() override;
|
||||
void TearDownEditorFixtureImpl() override;
|
||||
|
||||
AZStd::unique_ptr<AZ::ComponentDescriptor> m_editorBoxShapeComponentDescriptor;
|
||||
AZStd::unique_ptr<AZ::ComponentDescriptor> m_editorSphereShapeComponentDescriptor;
|
||||
|
||||
AZ::Entity* m_entity = nullptr;
|
||||
};
|
||||
|
||||
void EditorBoxShapeComponentFixture::SetUpEditorFixtureImpl()
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = nullptr;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
|
||||
|
||||
// need to reflect EditorSphereShapeComponent in order for EditorBaseShapeComponent to be reflected
|
||||
m_editorSphereShapeComponentDescriptor = AZStd::unique_ptr<AZ::ComponentDescriptor>(EditorSphereShapeComponent::CreateDescriptor());
|
||||
|
||||
m_editorBoxShapeComponentDescriptor =
|
||||
AZStd::unique_ptr<AZ::ComponentDescriptor>(EditorBoxShapeComponent::CreateDescriptor());
|
||||
|
||||
ShapeComponentConfig::Reflect(serializeContext);
|
||||
BoxShape::Reflect(serializeContext);
|
||||
m_editorSphereShapeComponentDescriptor->Reflect(serializeContext);
|
||||
m_editorBoxShapeComponentDescriptor->Reflect(serializeContext);
|
||||
|
||||
UnitTest::CreateDefaultEditorEntity("BoxShapeComponentEntity", &m_entity);
|
||||
m_entity->Deactivate();
|
||||
m_entity->CreateComponent(AzToolsFramework::Components::EditorNonUniformScaleComponent::RTTI_Type());
|
||||
m_entity->CreateComponent(EditorBoxShapeComponentTypeId);
|
||||
m_entity->Activate();
|
||||
}
|
||||
|
||||
void EditorBoxShapeComponentFixture::TearDownEditorFixtureImpl()
|
||||
{
|
||||
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
|
||||
&AzToolsFramework::EditorEntityContextRequestBus::Events::DestroyEditorEntity, m_entity->GetId());
|
||||
m_entity = nullptr;
|
||||
|
||||
m_editorBoxShapeComponentDescriptor.reset();
|
||||
m_editorSphereShapeComponentDescriptor.reset();
|
||||
}
|
||||
|
||||
using EditorBoxShapeComponentManipulatorFixture =
|
||||
UnitTest::IndirectCallManipulatorViewportInteractionFixtureMixin<EditorBoxShapeComponentFixture>;
|
||||
|
||||
TEST_F(EditorBoxShapeComponentManipulatorFixture, BoxShapeNonUniformScaleManipulatorsScaleCorrectly)
|
||||
{
|
||||
// a rotation which rotates the x-axis to (0.8, 0.6, 0)
|
||||
const AZ::Quaternion boxRotation(0.0f, 0.0f, 0.316228f, 0.948683f);
|
||||
AZ::Transform boxTransform = AZ::Transform::CreateFromQuaternionAndTranslation(boxRotation, AZ::Vector3(2.0f, 3.0f, 4.0f));
|
||||
boxTransform.SetUniformScale(1.5f);
|
||||
AZ::TransformBus::Event(m_entity->GetId(), &AZ::TransformBus::Events::SetWorldTM, boxTransform);
|
||||
|
||||
const AZ::Vector3 nonUniformScale(4.0f, 1.5f, 2.0f);
|
||||
AZ::NonUniformScaleRequestBus::Event(m_entity->GetId(), &AZ::NonUniformScaleRequests::SetScale, nonUniformScale);
|
||||
|
||||
const AZ::Vector3 boxDimensions(1.0f, 2.0f, 2.5f);
|
||||
BoxShapeComponentRequestsBus::Event(m_entity->GetId(), &BoxShapeComponentRequests::SetBoxDimensions, boxDimensions);
|
||||
|
||||
// enter the box shape component's component mode
|
||||
AzToolsFramework::SelectEntity(m_entity->GetId());
|
||||
AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Broadcast(
|
||||
&AzToolsFramework::ComponentModeFramework::ComponentModeSystemRequestBus::Events::AddSelectedComponentModesOfType,
|
||||
EditorBoxShapeComponentTypeId);
|
||||
|
||||
// position the camera so it is looking down at the box
|
||||
AzFramework::SetCameraTransform(
|
||||
m_cameraState,
|
||||
AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
AZ::Quaternion::CreateRotationX(-AZ::Constants::HalfPi), AZ::Vector3(2.0f, 3.0f, 20.0f)));
|
||||
|
||||
// position in world space which should allow grabbing the box's x scale manipulator
|
||||
// the unscaled position of the x scale manipulator in the box's local frame should be (0.5f, 0.0f, 0.0f)
|
||||
// after non-uniform scale, the manipulator position should be (2.0f, 0.0f, 0.0f)
|
||||
// after the scale of the entity transform, the manipulator position should be (3.0f, 0.0f, 0.0f)
|
||||
// after the rotation of the entity transform, the manipulator position should be (2.4f, 1.8f, 0.0f)
|
||||
// after the translation of the entity transform, the manipulator position should be (4.4f, 4.8f, 4.0f)
|
||||
const AZ::Vector3 worldStart(4.4f, 4.8f, 4.0f);
|
||||
|
||||
// position in world space to move to
|
||||
const AZ::Vector3 worldEnd(6.8f, 6.6f, 4.0f);
|
||||
|
||||
const auto screenStart = AzFramework::WorldToScreen(worldStart, m_cameraState);
|
||||
const auto screenEnd = AzFramework::WorldToScreen(worldEnd, m_cameraState);
|
||||
|
||||
m_actionDispatcher
|
||||
->CameraState(m_cameraState)
|
||||
// move the mouse to the position of the x scale manipulator
|
||||
->MousePosition(screenStart)
|
||||
// drag to move the manipulator
|
||||
->MouseLButtonDown()
|
||||
->MousePosition(screenEnd)
|
||||
->MouseLButtonUp();
|
||||
|
||||
AZ::Vector3 newBoxDimensions = AZ::Vector3::CreateZero();
|
||||
BoxShapeComponentRequestsBus::EventResult(newBoxDimensions, m_entity->GetId(), &BoxShapeComponentRequests::GetBoxDimensions);
|
||||
|
||||
const AZ::Vector3 expectedBoxDimensions(2.0f, 2.0f, 2.5f);
|
||||
// allow a reasonably high tolerance because we can't get better accuracy than the resolution of the viewport
|
||||
EXPECT_THAT(newBoxDimensions, UnitTest::IsCloseTolerance(expectedBoxDimensions, 1e-2f));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,11 +8,14 @@
|
||||
|
||||
#include "ColliderCapsuleMode.h"
|
||||
#include <PhysX/EditorColliderComponentRequestBus.h>
|
||||
#include <Source/Utils.h>
|
||||
|
||||
#include <AzToolsFramework/Manipulators/LinearManipulator.h>
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
|
||||
#include <AzToolsFramework/ComponentModes/BoxViewportEdit.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Component/NonUniformScaleBus.h>
|
||||
#include <AzFramework/Viewport/ViewportColors.h>
|
||||
#include <AzFramework/Viewport/ViewportConstants.h>
|
||||
|
||||
@@ -34,10 +37,15 @@ namespace PhysX
|
||||
void ColliderCapsuleMode::Setup(const AZ::EntityComponentIdPair& idPair)
|
||||
{
|
||||
AZ::Transform colliderWorldTransform = AZ::Transform::Identity();
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(colliderWorldTransform, idPair, &PhysX::EditorColliderComponentRequests::GetColliderWorldTransform);
|
||||
AZ::TransformBus::EventResult(colliderWorldTransform, idPair.GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
|
||||
|
||||
SetupRadiusManipulator(idPair, colliderWorldTransform);
|
||||
SetupHeightManipulator(idPair, colliderWorldTransform);
|
||||
AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne();
|
||||
AZ::NonUniformScaleRequestBus::EventResult(nonUniformScale, idPair.GetEntityId(), &AZ::NonUniformScaleRequests::GetScale);
|
||||
|
||||
const AZ::Transform colliderLocalTransform = Utils::GetColliderLocalTransform(idPair);
|
||||
|
||||
SetupRadiusManipulator(idPair, colliderWorldTransform, colliderLocalTransform, nonUniformScale);
|
||||
SetupHeightManipulator(idPair, colliderWorldTransform, colliderLocalTransform, nonUniformScale);
|
||||
|
||||
AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(idPair.GetEntityId());
|
||||
}
|
||||
@@ -45,7 +53,12 @@ namespace PhysX
|
||||
void ColliderCapsuleMode::Refresh(const AZ::EntityComponentIdPair& idPair)
|
||||
{
|
||||
AZ::Transform colliderWorldTransform = AZ::Transform::Identity();
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(colliderWorldTransform, idPair, &PhysX::EditorColliderComponentRequests::GetColliderWorldTransform);
|
||||
AZ::TransformBus::EventResult(colliderWorldTransform, idPair.GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
|
||||
|
||||
AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne();
|
||||
AZ::NonUniformScaleRequestBus::EventResult(nonUniformScale, idPair.GetEntityId(), &AZ::NonUniformScaleRequests::GetScale);
|
||||
|
||||
AZ::Transform colliderLocalTransform = Utils::GetColliderLocalTransform(idPair);
|
||||
|
||||
// Read the state of the capsule into manipulators to support undo/redo
|
||||
float capsuleHeight = 0.0f;
|
||||
@@ -55,9 +68,13 @@ namespace PhysX
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(capsuleRadius, idPair, &PhysX::EditorColliderComponentRequests::GetCapsuleRadius);
|
||||
|
||||
m_radiusManipulator->SetSpace(colliderWorldTransform);
|
||||
m_radiusManipulator->SetLocalPosition(m_radiusManipulator->GetAxis() * capsuleRadius);
|
||||
m_radiusManipulator->SetLocalTransform(
|
||||
colliderLocalTransform * AZ::Transform::CreateTranslation(m_radiusManipulator->GetAxis() * capsuleRadius));
|
||||
m_radiusManipulator->SetNonUniformScale(nonUniformScale);
|
||||
m_heightManipulator->SetSpace(colliderWorldTransform);
|
||||
m_heightManipulator->SetLocalPosition(m_heightManipulator->GetAxis() * capsuleHeight * HalfHeight);
|
||||
m_heightManipulator->SetLocalTransform(
|
||||
colliderLocalTransform * AZ::Transform::CreateTranslation(m_heightManipulator->GetAxis() * capsuleHeight * HalfHeight));
|
||||
m_heightManipulator->SetNonUniformScale(nonUniformScale);
|
||||
}
|
||||
|
||||
void ColliderCapsuleMode::Teardown(const AZ::EntityComponentIdPair& idPair)
|
||||
@@ -83,13 +100,23 @@ namespace PhysX
|
||||
AZ_UNUSED(debugDisplay);
|
||||
|
||||
const AzFramework::CameraState cameraState = AzToolsFramework::GetCameraState(viewportInfo.m_viewportId);
|
||||
float radius = m_radiusManipulator->GetLocalPosition().GetLength();
|
||||
|
||||
m_radiusManipulator->SetAxis(cameraState.m_side);
|
||||
m_radiusManipulator->SetLocalPosition(cameraState.m_side * radius);
|
||||
if (!m_radiusManipulator->EntityComponentIdPairs().empty())
|
||||
{
|
||||
const AZ::EntityComponentIdPair idPair = *m_radiusManipulator->EntityComponentIdPairs().begin();
|
||||
float radius = 0.0f;
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(radius, idPair, &PhysX::EditorColliderComponentRequests::GetCapsuleRadius);
|
||||
const AZ::Transform colliderLocalTransform = Utils::GetColliderLocalTransform(idPair);
|
||||
m_radiusManipulator->SetAxis(cameraState.m_side);
|
||||
m_radiusManipulator->SetLocalTransform(colliderLocalTransform * AZ::Transform::CreateTranslation(cameraState.m_side * radius));
|
||||
}
|
||||
}
|
||||
|
||||
void ColliderCapsuleMode::SetupRadiusManipulator(const AZ::EntityComponentIdPair& idPair, const AZ::Transform& worldTransform)
|
||||
void ColliderCapsuleMode::SetupRadiusManipulator(
|
||||
const AZ::EntityComponentIdPair& idPair,
|
||||
const AZ::Transform& worldTransform,
|
||||
const AZ::Transform& localTransform,
|
||||
const AZ::Vector3& nonUniformScale)
|
||||
{
|
||||
// Radius manipulator
|
||||
float capsuleRadius = 0.0f;
|
||||
@@ -99,7 +126,8 @@ namespace PhysX
|
||||
m_radiusManipulator->AddEntityComponentIdPair(idPair);
|
||||
m_radiusManipulator->SetAxis(RadiusManipulatorAxis);
|
||||
m_radiusManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
|
||||
m_radiusManipulator->SetLocalPosition(RadiusManipulatorAxis * capsuleRadius);
|
||||
m_radiusManipulator->SetLocalTransform(localTransform * AZ::Transform::CreateTranslation(RadiusManipulatorAxis * capsuleRadius));
|
||||
m_radiusManipulator->SetNonUniformScale(nonUniformScale);
|
||||
|
||||
{
|
||||
AzToolsFramework::ManipulatorViews views;
|
||||
@@ -114,7 +142,11 @@ namespace PhysX
|
||||
});
|
||||
}
|
||||
|
||||
void ColliderCapsuleMode::SetupHeightManipulator(const AZ::EntityComponentIdPair& idPair, const AZ::Transform& worldTransform)
|
||||
void ColliderCapsuleMode::SetupHeightManipulator(
|
||||
const AZ::EntityComponentIdPair& idPair,
|
||||
const AZ::Transform& worldTransform,
|
||||
const AZ::Transform& localTransform,
|
||||
const AZ::Vector3& nonUniformScale)
|
||||
{
|
||||
// Height manipulator
|
||||
float capsuleHeight = 0.0f;
|
||||
@@ -124,7 +156,9 @@ namespace PhysX
|
||||
m_heightManipulator->AddEntityComponentIdPair(idPair);
|
||||
m_heightManipulator->SetAxis(HeightManipulatorAxis);
|
||||
m_heightManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
|
||||
m_heightManipulator->SetLocalPosition(HeightManipulatorAxis * capsuleHeight * HalfHeight); // Manipulator positioned at half the capsules height.
|
||||
m_heightManipulator->SetLocalTransform(
|
||||
localTransform * AZ::Transform::CreateTranslation(HeightManipulatorAxis * capsuleHeight * HalfHeight));
|
||||
m_heightManipulator->SetNonUniformScale(nonUniformScale);
|
||||
|
||||
{
|
||||
AzToolsFramework::ManipulatorViews views;
|
||||
@@ -137,19 +171,23 @@ namespace PhysX
|
||||
{
|
||||
OnHeightManipulatorMoved(action, idPair);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void ColliderCapsuleMode::OnRadiusManipulatorMoved(const AzToolsFramework::LinearManipulator::Action& action, const AZ::EntityComponentIdPair& idPair)
|
||||
{
|
||||
// manipulator action offsets do not take entity transform scale into account, so need to apply it here
|
||||
const AZ::Transform colliderLocalTransform = Utils::GetColliderLocalTransform(idPair);
|
||||
const AZ::Vector3 manipulatorPosition = AzToolsFramework::GetPositionInManipulatorFrame(
|
||||
m_radiusManipulator->GetSpace().GetUniformScale(), colliderLocalTransform, action);
|
||||
|
||||
// Get the distance the manipulator has moved along the axis.
|
||||
float extent = action.LocalPosition().Dot(action.m_fixed.m_axis);
|
||||
float extent = manipulatorPosition.Dot(action.m_fixed.m_axis);
|
||||
|
||||
// Clamp radius to a small value.
|
||||
extent = AZ::GetMax(extent, MinCapsuleRadius);
|
||||
|
||||
// Update the manipulator and capsule radius.
|
||||
m_radiusManipulator->SetLocalPosition(extent * action.m_fixed.m_axis);
|
||||
m_radiusManipulator->SetLocalTransform(colliderLocalTransform * AZ::Transform::CreateTranslation(extent * action.m_fixed.m_axis));
|
||||
|
||||
// Adjust the height manipulator so it is always clamped to twice the radius.
|
||||
AdjustHeightManipulator(idPair, static_cast<float>(extent));
|
||||
@@ -160,14 +198,19 @@ namespace PhysX
|
||||
|
||||
void ColliderCapsuleMode::OnHeightManipulatorMoved(const AzToolsFramework::LinearManipulator::Action& action, const AZ::EntityComponentIdPair& idPair)
|
||||
{
|
||||
// manipulator action offsets do not take entity transform scale into account, so need to apply it here
|
||||
const AZ::Transform colliderLocalTransform = Utils::GetColliderLocalTransform(idPair);
|
||||
const AZ::Vector3 manipulatorPosition = AzToolsFramework::GetPositionInManipulatorFrame(
|
||||
m_heightManipulator->GetSpace().GetUniformScale(), colliderLocalTransform, action);
|
||||
|
||||
// Get the distance the manipulator has moved along the axis.
|
||||
float extent = action.LocalPosition().Dot(action.m_fixed.m_axis);
|
||||
float extent = manipulatorPosition.Dot(action.m_fixed.m_axis);
|
||||
|
||||
// Ensure capsule's half height is always greater than the radius.
|
||||
extent = AZ::GetMax(extent, MinCapsuleHeight);
|
||||
|
||||
// Update the manipulator and capsule height.
|
||||
m_heightManipulator->SetLocalPosition(extent * action.m_fixed.m_axis);
|
||||
m_heightManipulator->SetLocalTransform(colliderLocalTransform * AZ::Transform::CreateTranslation(extent * action.m_fixed.m_axis));
|
||||
|
||||
// The final height of the capsule is twice the manipulator's extent.
|
||||
float capsuleHeight = extent / HalfHeight;
|
||||
@@ -188,7 +231,9 @@ namespace PhysX
|
||||
capsuleRadius = AZ::GetMin(capsuleRadius, capsuleHeight * HalfHeight);
|
||||
|
||||
// Update manipulator and the capsule radius.
|
||||
m_radiusManipulator->SetLocalPosition(capsuleRadius * m_radiusManipulator->GetAxis());
|
||||
const AZ::Transform colliderLocalTransform = Utils::GetColliderLocalTransform(idPair);
|
||||
m_radiusManipulator->SetLocalTransform(
|
||||
colliderLocalTransform * AZ::Transform::CreateTranslation(capsuleRadius * m_radiusManipulator->GetAxis()));
|
||||
PhysX::EditorColliderComponentRequestBus::Event(idPair, &PhysX::EditorColliderComponentRequests::SetCapsuleRadius, capsuleRadius);
|
||||
}
|
||||
|
||||
@@ -201,7 +246,9 @@ namespace PhysX
|
||||
capsuleHeight = AZ::GetMax(capsuleHeight, capsuleRadius / HalfHeight);
|
||||
|
||||
// Update the manipulator and capsule height.
|
||||
m_heightManipulator->SetLocalPosition(capsuleHeight * HalfHeight * m_heightManipulator->GetAxis());
|
||||
const AZ::Transform colliderLocalTransform = Utils::GetColliderLocalTransform(idPair);
|
||||
m_heightManipulator->SetLocalTransform(
|
||||
colliderLocalTransform * AZ::Transform::CreateTranslation(capsuleHeight * HalfHeight * m_heightManipulator->GetAxis()));
|
||||
PhysX::EditorColliderComponentRequestBus::Event(idPair, &PhysX::EditorColliderComponentRequests::SetCapsuleHeight, capsuleHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,8 +34,16 @@ namespace PhysX
|
||||
const AzFramework::ViewportInfo& viewportInfo,
|
||||
AzFramework::DebugDisplayRequests& debugDisplay) override;
|
||||
|
||||
void SetupRadiusManipulator(const AZ::EntityComponentIdPair& idPair, const AZ::Transform& worldTransform);
|
||||
void SetupHeightManipulator(const AZ::EntityComponentIdPair& idPair, const AZ::Transform& worldTransform);
|
||||
void SetupRadiusManipulator(
|
||||
const AZ::EntityComponentIdPair& idPair,
|
||||
const AZ::Transform& worldTransform,
|
||||
const AZ::Transform& localTransform,
|
||||
const AZ::Vector3& nonUniformScale);
|
||||
void SetupHeightManipulator(
|
||||
const AZ::EntityComponentIdPair& idPair,
|
||||
const AZ::Transform& worldTransform,
|
||||
const AZ::Transform& localTransform,
|
||||
const AZ::Vector3& nonUniformScale);
|
||||
void OnRadiusManipulatorMoved(const AzToolsFramework::LinearManipulator::Action& action, const AZ::EntityComponentIdPair& idPair);
|
||||
void OnHeightManipulatorMoved(const AzToolsFramework::LinearManipulator::Action& action, const AZ::EntityComponentIdPair& idPair);
|
||||
void AdjustRadiusManipulator(const AZ::EntityComponentIdPair& idPair, const float capsuleHeight);
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <PhysX/EditorColliderComponentRequestBus.h>
|
||||
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
|
||||
#include <AzCore/Component/NonUniformScaleBus.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Component/ComponentBus.h>
|
||||
|
||||
@@ -28,10 +29,14 @@ namespace PhysX
|
||||
AZ::Transform worldTransform;
|
||||
AZ::TransformBus::EventResult(worldTransform, idPair.GetEntityId(), &AZ::TransformInterface::GetWorldTM);
|
||||
|
||||
AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne();
|
||||
AZ::NonUniformScaleRequestBus::EventResult(nonUniformScale, idPair.GetEntityId(), &AZ::NonUniformScaleRequests::GetScale);
|
||||
|
||||
AZ::Vector3 colliderOffset;
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(colliderOffset, idPair, &PhysX::EditorColliderComponentRequests::GetColliderOffset);
|
||||
|
||||
m_translationManipulators.SetSpace(worldTransform);
|
||||
m_translationManipulators.SetNonUniformScale(nonUniformScale);
|
||||
m_translationManipulators.SetLocalPosition(colliderOffset);
|
||||
m_translationManipulators.AddEntityComponentIdPair(idPair);
|
||||
m_translationManipulators.Register(AzToolsFramework::g_mainManipulatorManagerId);
|
||||
@@ -40,19 +45,19 @@ namespace PhysX
|
||||
m_translationManipulators.InstallLinearManipulatorMouseMoveCallback([this, idPair](
|
||||
const AzToolsFramework::LinearManipulator::Action& action)
|
||||
{
|
||||
OnManipulatorMoved(action.LocalPosition(), idPair);
|
||||
OnManipulatorMoved(action.m_start.m_localPosition, action.m_current.m_localPositionOffset, idPair);
|
||||
});
|
||||
|
||||
m_translationManipulators.InstallPlanarManipulatorMouseMoveCallback([this, idPair](
|
||||
const AzToolsFramework::PlanarManipulator::Action& action)
|
||||
{
|
||||
OnManipulatorMoved(action.LocalPosition(), idPair);
|
||||
OnManipulatorMoved(action.m_start.m_localPosition, action.m_current.m_localOffset, idPair);
|
||||
});
|
||||
|
||||
m_translationManipulators.InstallSurfaceManipulatorMouseMoveCallback([this, idPair](
|
||||
const AzToolsFramework::SurfaceManipulator::Action& action)
|
||||
{
|
||||
OnManipulatorMoved(action.LocalPosition(), idPair);
|
||||
OnManipulatorMoved(action.m_start.m_localPosition, action.m_current.m_localOffset, idPair);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -69,10 +74,14 @@ namespace PhysX
|
||||
m_translationManipulators.Unregister();
|
||||
}
|
||||
|
||||
void ColliderOffsetMode::OnManipulatorMoved(const AZ::Vector3& position, const AZ::EntityComponentIdPair& idPair)
|
||||
void ColliderOffsetMode::OnManipulatorMoved(const AZ::Vector3& startPosition, const AZ::Vector3& offset, const AZ::EntityComponentIdPair& idPair)
|
||||
{
|
||||
m_translationManipulators.SetLocalPosition(position);
|
||||
PhysX::EditorColliderComponentRequestBus::Event(idPair, &PhysX::EditorColliderComponentRequests::SetColliderOffset, position);
|
||||
AZ::Transform worldTransform = AZ::Transform::CreateIdentity();
|
||||
AZ::TransformBus::EventResult(worldTransform, idPair.GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
|
||||
const float scale = AZ::GetMax(AZ::MinTransformScale, worldTransform.GetUniformScale());
|
||||
const AZ::Vector3 newPosition = startPosition + offset / scale;
|
||||
m_translationManipulators.SetLocalPosition(newPosition);
|
||||
PhysX::EditorColliderComponentRequestBus::Event(idPair, &PhysX::EditorColliderComponentRequests::SetColliderOffset, newPosition);
|
||||
}
|
||||
|
||||
void ColliderOffsetMode::ResetValues(const AZ::EntityComponentIdPair& idPair)
|
||||
|
||||
@@ -28,7 +28,8 @@ namespace PhysX
|
||||
void ResetValues(const AZ::EntityComponentIdPair& idPair) override;
|
||||
|
||||
private:
|
||||
void OnManipulatorMoved(const AZ::Vector3& position, const AZ::EntityComponentIdPair& idPair);
|
||||
void OnManipulatorMoved(
|
||||
const AZ::Vector3& startPosition, const AZ::Vector3& offset, const AZ::EntityComponentIdPair& idPair);
|
||||
|
||||
AzToolsFramework::TranslationManipulators m_translationManipulators;
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <PhysX/EditorColliderComponentRequestBus.h>
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Component/NonUniformScaleBus.h>
|
||||
#include <AzFramework/Viewport/ViewportColors.h>
|
||||
#include <AzToolsFramework/Manipulators/AngularManipulator.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
|
||||
@@ -29,6 +30,9 @@ namespace PhysX
|
||||
AZ::Transform worldTransform;
|
||||
AZ::TransformBus::EventResult(worldTransform, idPair.GetEntityId(), &AZ::TransformInterface::GetWorldTM);
|
||||
|
||||
AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne();
|
||||
AZ::NonUniformScaleRequestBus::EventResult(nonUniformScale, idPair.GetEntityId(), &AZ::NonUniformScaleRequests::GetScale);
|
||||
|
||||
AZ::Quaternion colliderRotation;
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(colliderRotation, idPair, &PhysX::EditorColliderComponentRequests::GetColliderRotation);
|
||||
|
||||
@@ -36,7 +40,8 @@ namespace PhysX
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(colliderOffset, idPair, &PhysX::EditorColliderComponentRequests::GetColliderOffset);
|
||||
|
||||
m_rotationManipulators.SetSpace(worldTransform);
|
||||
m_rotationManipulators.SetLocalPosition(colliderOffset);
|
||||
m_rotationManipulators.SetNonUniformScale(nonUniformScale);
|
||||
m_rotationManipulators.SetLocalPosition(nonUniformScale * colliderOffset);
|
||||
m_rotationManipulators.SetLocalOrientation(colliderRotation);
|
||||
m_rotationManipulators.AddEntityComponentIdPair(idPair);
|
||||
m_rotationManipulators.Register(AzToolsFramework::g_mainManipulatorManagerId);
|
||||
@@ -70,7 +75,11 @@ namespace PhysX
|
||||
|
||||
AZ::Vector3 colliderOffset = AZ::Vector3::CreateZero();
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(colliderOffset, idPair, &PhysX::EditorColliderComponentRequests::GetColliderOffset);
|
||||
m_rotationManipulators.SetLocalPosition(colliderOffset);
|
||||
|
||||
AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne();
|
||||
AZ::NonUniformScaleRequestBus::EventResult(nonUniformScale, idPair.GetEntityId(), &AZ::NonUniformScaleRequests::GetScale);
|
||||
|
||||
m_rotationManipulators.SetLocalPosition(nonUniformScale * colliderOffset);
|
||||
}
|
||||
|
||||
void ColliderRotationMode::Teardown(const AZ::EntityComponentIdPair& idPair)
|
||||
|
||||
@@ -8,11 +8,14 @@
|
||||
|
||||
#include "ColliderSphereMode.h"
|
||||
#include <PhysX/EditorColliderComponentRequestBus.h>
|
||||
#include <Source/Utils.h>
|
||||
|
||||
#include <AzToolsFramework/Manipulators/LinearManipulator.h>
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
|
||||
#include <AzToolsFramework/ComponentModes/BoxViewportEdit.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
#include <AzCore/Component/NonUniformScaleBus.h>
|
||||
#include <AzCore/Math/ToString.h>
|
||||
#include <AzFramework/Viewport/ViewportColors.h>
|
||||
#include <AzFramework/Viewport/ViewportConstants.h>
|
||||
@@ -27,7 +30,12 @@ namespace PhysX
|
||||
void ColliderSphereMode::Setup(const AZ::EntityComponentIdPair& idPair)
|
||||
{
|
||||
AZ::Transform colliderWorldTransform = AZ::Transform::Identity();
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(colliderWorldTransform, idPair, &PhysX::EditorColliderComponentRequests::GetColliderWorldTransform);
|
||||
AZ::TransformBus::EventResult(colliderWorldTransform, idPair.GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
|
||||
|
||||
AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne();
|
||||
AZ::NonUniformScaleRequestBus::EventResult(nonUniformScale, idPair.GetEntityId(), &AZ::NonUniformScaleRequests::GetScale);
|
||||
|
||||
const AZ::Transform colliderLocalTransform = Utils::GetColliderLocalTransform(idPair);
|
||||
|
||||
float sphereRadius = 0.0f;
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(sphereRadius, idPair, &PhysX::EditorColliderComponentRequests::GetSphereRadius);
|
||||
@@ -36,7 +44,9 @@ namespace PhysX
|
||||
m_radiusManipulator->AddEntityComponentIdPair(idPair);
|
||||
m_radiusManipulator->SetAxis(ManipulatorAxis);
|
||||
m_radiusManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
|
||||
m_radiusManipulator->SetLocalPosition(ManipulatorAxis * sphereRadius);
|
||||
m_radiusManipulator->SetLocalTransform(colliderLocalTransform * AZ::Transform::CreateTranslation(ManipulatorAxis * sphereRadius));
|
||||
m_radiusManipulator->SetNonUniformScale(nonUniformScale);
|
||||
m_radiusManipulator->SetBoundsDirty();
|
||||
|
||||
AzToolsFramework::ManipulatorViews views;
|
||||
views.emplace_back(AzToolsFramework::CreateManipulatorViewQuadBillboard(AzFramework::ViewportColors::DefaultManipulatorHandleColor, AzFramework::ViewportConstants::DefaultManipulatorHandleSize));
|
||||
@@ -53,12 +63,18 @@ namespace PhysX
|
||||
void ColliderSphereMode::Refresh(const AZ::EntityComponentIdPair& idPair)
|
||||
{
|
||||
AZ::Transform colliderWorldTransform = AZ::Transform::Identity();
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(colliderWorldTransform, idPair, &PhysX::EditorColliderComponentRequests::GetColliderWorldTransform);
|
||||
AZ::TransformBus::EventResult(colliderWorldTransform, idPair.GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
|
||||
m_radiusManipulator->SetSpace(colliderWorldTransform);
|
||||
|
||||
AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne();
|
||||
AZ::NonUniformScaleRequestBus::EventResult(nonUniformScale, idPair.GetEntityId(), &AZ::NonUniformScaleRequests::GetScale);
|
||||
|
||||
const AZ::Transform colliderLocalTransform = Utils::GetColliderLocalTransform(idPair);
|
||||
|
||||
float sphereRadius = 0.0f;
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(sphereRadius, idPair, &PhysX::EditorColliderComponentRequests::GetSphereRadius);
|
||||
m_radiusManipulator->SetLocalPosition(ManipulatorAxis * sphereRadius);
|
||||
m_radiusManipulator->SetLocalTransform(colliderLocalTransform * AZ::Transform::CreateTranslation(ManipulatorAxis * sphereRadius));
|
||||
m_radiusManipulator->SetBoundsDirty();
|
||||
}
|
||||
|
||||
void ColliderSphereMode::Teardown(const AZ::EntityComponentIdPair& idPair)
|
||||
@@ -80,22 +96,34 @@ namespace PhysX
|
||||
AZ_UNUSED(debugDisplay);
|
||||
|
||||
const AzFramework::CameraState cameraState = AzToolsFramework::GetCameraState(viewportInfo.m_viewportId);
|
||||
float radius = m_radiusManipulator->GetLocalPosition().GetLength();
|
||||
|
||||
m_radiusManipulator->SetAxis(cameraState.m_side);
|
||||
m_radiusManipulator->SetLocalPosition(cameraState.m_side * radius);
|
||||
if (!m_radiusManipulator->EntityComponentIdPairs().empty())
|
||||
{
|
||||
const AZ::EntityComponentIdPair idPair = *m_radiusManipulator->EntityComponentIdPairs().begin();
|
||||
float radius = 0.0f;
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(radius, idPair, &PhysX::EditorColliderComponentRequests::GetSphereRadius);
|
||||
const AZ::Transform colliderLocalTransform = Utils::GetColliderLocalTransform(idPair);
|
||||
m_radiusManipulator->SetAxis(cameraState.m_side);
|
||||
m_radiusManipulator->SetLocalTransform(colliderLocalTransform * AZ::Transform::CreateTranslation(cameraState.m_side * radius));
|
||||
}
|
||||
}
|
||||
|
||||
void ColliderSphereMode::OnManipulatorMoved(const AzToolsFramework::LinearManipulator::Action& action, const AZ::EntityComponentIdPair& idPair)
|
||||
{
|
||||
// manipulator offsets do not take transform scale into account, need to handle it here
|
||||
const AZ::Transform colliderLocalTransform = Utils::GetColliderLocalTransform(idPair);
|
||||
const AZ::Vector3 manipulatorPosition = AzToolsFramework::GetPositionInManipulatorFrame(
|
||||
m_radiusManipulator->GetSpace().GetUniformScale(), colliderLocalTransform, action);
|
||||
|
||||
// Get the distance the manipulator has moved along the axis.
|
||||
float extent = action.LocalPosition().Dot(action.m_fixed.m_axis);
|
||||
float extent = manipulatorPosition.Dot(action.m_fixed.m_axis);
|
||||
|
||||
// Clamp the distance to a small value to prevent it going negative.
|
||||
extent = AZ::GetMax(extent, MinSphereRadius);
|
||||
|
||||
// Update the manipulator and sphere radius
|
||||
m_radiusManipulator->SetLocalPosition(extent * action.m_fixed.m_axis);
|
||||
m_radiusManipulator->SetLocalTransform(
|
||||
Utils::GetColliderLocalTransform(idPair) * AZ::Transform::CreateTranslation(extent * action.m_fixed.m_axis));
|
||||
PhysX::EditorColliderComponentRequestBus::Event(idPair, &PhysX::EditorColliderComponentRequests::SetSphereRadius, extent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -582,9 +582,8 @@ namespace PhysX
|
||||
|
||||
AZ::Transform EditorColliderComponent::GetColliderLocalTransform() const
|
||||
{
|
||||
const AZ::Vector3 nonUniformScale = Utils::GetTransformScale(GetEntityId());
|
||||
return AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
m_configuration.m_rotation, m_configuration.m_position * nonUniformScale);
|
||||
m_configuration.m_rotation, m_configuration.m_position);
|
||||
}
|
||||
|
||||
void EditorColliderComponent::UpdateMeshAsset()
|
||||
@@ -970,8 +969,10 @@ namespace PhysX
|
||||
static_cast<const Physics::CookedMeshShapeConfiguration*>(shapeConfiguration);
|
||||
|
||||
const AZ::Vector3 overallScale = Utils::GetTransformScale(GetEntityId()) * m_cachedNonUniformScale * assetScale;
|
||||
Physics::ColliderConfiguration nonUniformScaledColliderConfiguration = *colliderConfiguration;
|
||||
nonUniformScaledColliderConfiguration.m_position *= m_cachedNonUniformScale;
|
||||
|
||||
m_colliderDebugDraw.DrawMesh(debugDisplay, *colliderConfiguration, *cookedMeshShapeConfiguration,
|
||||
m_colliderDebugDraw.DrawMesh(debugDisplay, nonUniformScaledColliderConfiguration, *cookedMeshShapeConfiguration,
|
||||
overallScale, static_cast<AZ::u32>(shapeIndex));
|
||||
break;
|
||||
}
|
||||
@@ -1054,12 +1055,17 @@ namespace PhysX
|
||||
|
||||
AZ::Transform EditorColliderComponent::GetCurrentTransform()
|
||||
{
|
||||
return GetColliderWorldTransform();
|
||||
return GetWorldTM();
|
||||
}
|
||||
|
||||
AZ::Transform EditorColliderComponent::GetCurrentLocalTransform()
|
||||
{
|
||||
return GetColliderLocalTransform();
|
||||
}
|
||||
|
||||
AZ::Vector3 EditorColliderComponent::GetBoxScale()
|
||||
{
|
||||
return AZ::Vector3(GetWorldTM().GetUniformScale());
|
||||
return AZ::Vector3::CreateOne();
|
||||
}
|
||||
|
||||
void EditorColliderComponent::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world)
|
||||
@@ -1203,7 +1209,7 @@ namespace PhysX
|
||||
|
||||
AZ::Transform EditorColliderComponent::GetColliderWorldTransform()
|
||||
{
|
||||
return AzToolsFramework::TransformNormalizedScale(GetWorldTM()) * GetColliderLocalTransform();
|
||||
return GetWorldTM() * GetColliderLocalTransform();
|
||||
}
|
||||
|
||||
bool EditorColliderComponent::ShouldUpdateCollisionMeshFromRender() const
|
||||
|
||||
@@ -171,6 +171,7 @@ namespace PhysX
|
||||
AZ::Vector3 GetDimensions() override;
|
||||
void SetDimensions(const AZ::Vector3& dimensions) override;
|
||||
AZ::Transform GetCurrentTransform() override;
|
||||
AZ::Transform GetCurrentLocalTransform() override;
|
||||
AZ::Vector3 GetBoxScale() override;
|
||||
|
||||
// AZ::Render::MeshComponentNotificationBus
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <AzFramework/Physics/HeightfieldProviderBus.h>
|
||||
|
||||
#include <PhysX/ColliderShapeBus.h>
|
||||
#include <PhysX/EditorColliderComponentRequestBus.h>
|
||||
#include <PhysX/SystemComponentBus.h>
|
||||
#include <PhysX/MeshAsset.h>
|
||||
#include <PhysX/Utils.h>
|
||||
@@ -832,6 +833,17 @@ namespace PhysX
|
||||
return AZ::Transform::CreateFromQuaternionAndTranslation(colliderRelativeRotation, colliderRelativePosition);
|
||||
}
|
||||
|
||||
AZ::Transform GetColliderLocalTransform(const AZ::EntityComponentIdPair& idPair)
|
||||
{
|
||||
AZ::Quaternion colliderRotation = AZ::Quaternion::CreateIdentity();
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(colliderRotation, idPair, &PhysX::EditorColliderComponentRequests::GetColliderRotation);
|
||||
|
||||
AZ::Vector3 colliderOffset = AZ::Vector3::CreateZero();
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(colliderOffset, idPair, &PhysX::EditorColliderComponentRequests::GetColliderOffset);
|
||||
|
||||
return AZ::Transform::CreateFromQuaternionAndTranslation(colliderRotation, colliderOffset);
|
||||
}
|
||||
|
||||
AZ::Transform GetColliderWorldTransform(const AZ::Transform& worldTransform,
|
||||
const AZ::Vector3& colliderRelativePosition,
|
||||
const AZ::Quaternion& colliderRelativeRotation)
|
||||
|
||||
@@ -142,6 +142,9 @@ namespace PhysX
|
||||
AZ::Transform GetColliderLocalTransform(const AZ::Vector3& colliderRelativePosition
|
||||
, const AZ::Quaternion& colliderRelativeRotation);
|
||||
|
||||
//! Gets the local transform for a collider (the position and rotation relative to its entity).
|
||||
AZ::Transform GetColliderLocalTransform(const AZ::EntityComponentIdPair& idPair);
|
||||
|
||||
//! Combines collider position and orientation offsets and world transform to a transform.
|
||||
AZ::Transform GetColliderWorldTransform(const AZ::Transform& worldTransform
|
||||
, const AZ::Vector3& colliderRelativePosition
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityHelpers.h>
|
||||
#include <AzToolsFramework/ViewportUi/ViewportUiManager.h>
|
||||
#include <AzToolsFramework/ToolsComponents/EditorNonUniformScaleComponent.h>
|
||||
#include <Tests/Viewport/ViewportUiManagerTests.cpp>
|
||||
#include <EditorColliderComponent.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
@@ -437,4 +439,378 @@ namespace UnitTest
|
||||
EXPECT_NEAR(assetScale.GetY(), 1.0f, tolerance);
|
||||
EXPECT_NEAR(assetScale.GetZ(), 1.0f, tolerance);
|
||||
}
|
||||
|
||||
class PhysXEditorColliderComponentFixture : public UnitTest::ToolsApplicationFixture
|
||||
{
|
||||
public:
|
||||
void SetUpEditorFixtureImpl() override;
|
||||
void TearDownEditorFixtureImpl() override;
|
||||
void SetupTransform(const AZ::Quaternion& rotation, const AZ::Vector3& translation, float uniformScale);
|
||||
void SetupCollider(
|
||||
const Physics::ShapeConfiguration& shapeConfiguration,
|
||||
const AZ::Quaternion& colliderRotation,
|
||||
const AZ::Vector3& colliderOffset);
|
||||
void SetupNonUniformScale(const AZ::Vector3& nonUniformScale);
|
||||
void EnterColliderSubMode(PhysX::ColliderComponentModeRequests::SubMode subMode);
|
||||
|
||||
AZ::Entity* m_entity = nullptr;
|
||||
AZ::EntityComponentIdPair m_idPair;
|
||||
};
|
||||
|
||||
void PhysXEditorColliderComponentFixture::SetUpEditorFixtureImpl()
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = nullptr;
|
||||
AZ::ComponentApplicationBus::BroadcastResult(serializeContext, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
|
||||
|
||||
UnitTest::CreateDefaultEditorEntity("EditorColliderComponentEntity", &m_entity);
|
||||
}
|
||||
|
||||
void PhysXEditorColliderComponentFixture::TearDownEditorFixtureImpl()
|
||||
{
|
||||
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
|
||||
&AzToolsFramework::EditorEntityContextRequestBus::Events::DestroyEditorEntity, m_entity->GetId());
|
||||
m_entity = nullptr;
|
||||
}
|
||||
|
||||
void PhysXEditorColliderComponentFixture::SetupTransform(
|
||||
const AZ::Quaternion& rotation, const AZ::Vector3& translation, float uniformScale)
|
||||
{
|
||||
const AZ::Transform transform = AZ::Transform::CreateFromQuaternionAndTranslation(rotation, translation);
|
||||
AZ::TransformBus::Event(m_entity->GetId(), &AZ::TransformBus::Events::SetWorldTM, transform);
|
||||
AZ::TransformBus::Event(m_entity->GetId(), &AZ::TransformBus::Events::SetLocalUniformScale, uniformScale);
|
||||
}
|
||||
|
||||
void PhysXEditorColliderComponentFixture::SetupCollider(
|
||||
const Physics::ShapeConfiguration& shapeConfiguration, const AZ::Quaternion& colliderRotation, const AZ::Vector3& colliderOffset)
|
||||
{
|
||||
m_entity->Deactivate();
|
||||
auto* colliderComponent =
|
||||
m_entity->CreateComponent<PhysX::EditorColliderComponent>(Physics::ColliderConfiguration(), shapeConfiguration);
|
||||
m_entity->Activate();
|
||||
m_idPair = AZ::EntityComponentIdPair(m_entity->GetId(), colliderComponent->GetId());
|
||||
PhysX::EditorColliderComponentRequestBus::Event(
|
||||
m_idPair, &PhysX::EditorColliderComponentRequests::SetColliderOffset, colliderOffset);
|
||||
PhysX::EditorColliderComponentRequestBus::Event(
|
||||
m_idPair, &PhysX::EditorColliderComponentRequests::SetColliderRotation, colliderRotation);
|
||||
}
|
||||
|
||||
void PhysXEditorColliderComponentFixture::SetupNonUniformScale(const AZ::Vector3& nonUniformScale)
|
||||
{
|
||||
m_entity->Deactivate();
|
||||
m_entity->CreateComponent(AzToolsFramework::Components::EditorNonUniformScaleComponent::RTTI_Type());
|
||||
m_entity->Activate();
|
||||
AZ::NonUniformScaleRequestBus::Event(m_entity->GetId(), &AZ::NonUniformScaleRequests::SetScale, nonUniformScale);
|
||||
}
|
||||
|
||||
void PhysXEditorColliderComponentFixture::EnterColliderSubMode(PhysX::ColliderComponentModeRequests::SubMode subMode)
|
||||
{
|
||||
AzToolsFramework::SelectEntity(m_entity->GetId());
|
||||
EnterComponentMode<PhysX::EditorColliderComponent>();
|
||||
PhysX::ColliderComponentModeRequestBus::Broadcast(&PhysX::ColliderComponentModeRequests::SetCurrentMode, subMode);
|
||||
}
|
||||
|
||||
using PhysXEditorColliderComponentManipulatorFixture =
|
||||
UnitTest::IndirectCallManipulatorViewportInteractionFixtureMixin<PhysXEditorColliderComponentFixture>;
|
||||
|
||||
// use a reasonably large tolerance because manipulator precision is limited by viewport resolution
|
||||
static const float ManipulatorTolerance = 0.01f;
|
||||
|
||||
TEST_F(PhysXEditorColliderComponentManipulatorFixture, OffsetManipulatorsCorrectlyLocatedRelativeToCollider)
|
||||
{
|
||||
const AZ::Vector3 boxDimensions(2.0f, 3.0f, 1.5f);
|
||||
const AZ::Quaternion boxRotation(0.1f, 0.1f, 0.7f, 0.7f);
|
||||
const AZ::Vector3 boxOffset(3.0f, 1.0f, 2.0f);
|
||||
SetupCollider(Physics::BoxShapeConfiguration(boxDimensions), boxRotation, boxOffset);
|
||||
const AZ::Quaternion entityRotation(0.8f, 0.2f, 0.4f, 0.4f);
|
||||
const AZ::Vector3 entityTranslation(2.0f, -3.0f, 0.5f);
|
||||
const float uniformScale = 2.0f;
|
||||
SetupTransform(entityRotation, entityTranslation, uniformScale);
|
||||
EnterColliderSubMode(PhysX::ColliderComponentModeRequests::SubMode::Offset);
|
||||
|
||||
// the expected position of the collider centre based on the combination of entity transform and collider offset
|
||||
const AZ::Vector3 expectedColliderPosition(8.8f, -2.28f, 3.54f);
|
||||
|
||||
// the expected world space direction of the collider offset x-axis based on the entity transform
|
||||
const AZ::Vector3 expectedXAxis(0.6f, 0.64f, 0.48f);
|
||||
|
||||
// position the camera to look down at the collider from above
|
||||
AzFramework::SetCameraTransform(
|
||||
m_cameraState,
|
||||
AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
AZ::Quaternion::CreateRotationX(-AZ::Constants::HalfPi), expectedColliderPosition + AZ::Vector3::CreateAxisZ(10.0f)));
|
||||
|
||||
// position in world space, slightly moved along the x-axis in order to grab the x translation manipulator
|
||||
const AZ::Vector3 worldStart = expectedColliderPosition + 0.5f * expectedXAxis;
|
||||
|
||||
// position in world space to move to
|
||||
const AZ::Vector3 worldEnd = worldStart + 2.0f * expectedXAxis;
|
||||
|
||||
const auto screenStart = AzFramework::WorldToScreen(worldStart, m_cameraState);
|
||||
const auto screenEnd = AzFramework::WorldToScreen(worldEnd, m_cameraState);
|
||||
|
||||
m_actionDispatcher
|
||||
->CameraState(m_cameraState)
|
||||
// move the mouse to the position of the x offset manipulator
|
||||
->MousePosition(screenStart)
|
||||
// drag to move the manipulator
|
||||
->MouseLButtonDown()
|
||||
->MousePosition(screenEnd)
|
||||
->MouseLButtonUp();
|
||||
|
||||
AZ::Vector3 newColliderOffset = AZ::Vector3::CreateZero();
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(
|
||||
newColliderOffset, m_idPair, &PhysX::EditorColliderComponentRequests::GetColliderOffset);
|
||||
|
||||
EXPECT_THAT(newColliderOffset, IsCloseTolerance(AZ::Vector3(4.0f, 1.0f, 2.0f), ManipulatorTolerance));
|
||||
}
|
||||
|
||||
TEST_F(PhysXEditorColliderComponentManipulatorFixture, OffsetManipulatorsCorrectlyLocatedRelativeToColliderWithNonUniformScale)
|
||||
{
|
||||
const float capsuleRadius = 0.5f;
|
||||
const float capsuleHeight = 2.0f;
|
||||
const AZ::Quaternion capsuleRotation(0.2f, -0.4f, 0.8f, 0.4f);
|
||||
const AZ::Vector3 capsuleOffset(-2.0f, 3.0f, -1.0f);
|
||||
SetupCollider(Physics::CapsuleShapeConfiguration(capsuleHeight, capsuleRadius), capsuleRotation, capsuleOffset);
|
||||
const AZ::Quaternion entityRotation(-0.1f, 0.7f, -0.7f, 0.1f);
|
||||
const AZ::Vector3 entityTranslation(-1.0f, 1.0f, -2.5f);
|
||||
const float uniformScale = 1.5f;
|
||||
SetupTransform(entityRotation, entityTranslation, uniformScale);
|
||||
const AZ::Vector3 nonUniformScale(2.0f, 0.5f, 1.5f);
|
||||
SetupNonUniformScale(nonUniformScale);
|
||||
EnterColliderSubMode(PhysX::ColliderComponentModeRequests::SubMode::Offset);
|
||||
|
||||
// the expected position of the collider centre based on the combination of entity transform, collider offset and non-uniform scale
|
||||
const AZ::Vector3 expectedColliderPosition(4.13f, 4.84f, -4.75f);
|
||||
|
||||
// the expected world space direction of the collider offset z-axis based on the entity transform
|
||||
const AZ::Vector3 expectedZAxis(0.28f, -0.96f, 0.0f);
|
||||
|
||||
// position the camera to look at the collider from underneath
|
||||
AzFramework::SetCameraTransform(
|
||||
m_cameraState,
|
||||
AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
AZ::Quaternion::CreateRotationX(AZ::Constants::HalfPi), expectedColliderPosition - AZ::Vector3::CreateAxisZ(10.0f)));
|
||||
|
||||
// position in world space, slightly moved along the z-axis in order to grab the z translation manipulator
|
||||
// need to go in the negative z direction because the camera angle causes the manipulator to flip
|
||||
const AZ::Vector3 worldStart = expectedColliderPosition - 0.5f * expectedZAxis;
|
||||
|
||||
// position in world space to move to
|
||||
const AZ::Vector3 worldEnd = worldStart - 2.25f * expectedZAxis;
|
||||
|
||||
const auto screenStart = AzFramework::WorldToScreen(worldStart, m_cameraState);
|
||||
const auto screenEnd = AzFramework::WorldToScreen(worldEnd, m_cameraState);
|
||||
|
||||
m_actionDispatcher
|
||||
->CameraState(m_cameraState)
|
||||
// move the mouse to the position of the z offset manipulator
|
||||
->MousePosition(screenStart)
|
||||
// drag to move the manipulator
|
||||
->MouseLButtonDown()
|
||||
->MousePosition(screenEnd)
|
||||
->MouseLButtonUp();
|
||||
|
||||
AZ::Vector3 newColliderOffset = AZ::Vector3::CreateZero();
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(
|
||||
newColliderOffset, m_idPair, &PhysX::EditorColliderComponentRequests::GetColliderOffset);
|
||||
|
||||
EXPECT_THAT(newColliderOffset, IsCloseTolerance(AZ::Vector3(-2.0f, 3.0f, -2.0f), ManipulatorTolerance));
|
||||
}
|
||||
|
||||
TEST_F(PhysXEditorColliderComponentManipulatorFixture, BoxColliderScaleManipulatorsCorrectlyLocatedRelativeToColliderWithNonUniformScale)
|
||||
{
|
||||
const AZ::Vector3 boxDimensions(2.0f, 2.0f, 3.0f);
|
||||
const AZ::Quaternion boxRotation(0.7f, 0.7f, -0.1f, 0.1f);
|
||||
const AZ::Vector3 boxOffset(0.5f, 1.5f, 2.0f);
|
||||
SetupCollider(Physics::BoxShapeConfiguration(boxDimensions), boxRotation, boxOffset);
|
||||
const AZ::Quaternion entityRotation(0.2f, 0.4f, -0.4f, 0.8f);
|
||||
const AZ::Vector3 entityTranslation(2.0f, -3.0f, -2.0f);
|
||||
const float uniformScale = 0.5f;
|
||||
SetupTransform(entityRotation, entityTranslation, uniformScale);
|
||||
const AZ::Vector3 nonUniformScale(3.0f, 1.5f, 2.5f);
|
||||
SetupNonUniformScale(nonUniformScale);
|
||||
EnterColliderSubMode(PhysX::ColliderComponentModeRequests::SubMode::Dimensions);
|
||||
|
||||
// the expected position of the collider centre based on the combination of entity transform, collider offset and non-uniform scale
|
||||
const AZ::Vector3 expectedColliderPosition(4.37f, -4.285f, -1.1f);
|
||||
|
||||
// the expected position of the y scale manipulator relative to the centre of the collider, based on collider
|
||||
// rotation, entity rotation and scale, and non-uniform scale
|
||||
const AZ::Vector3 scaleManipulatorYDelta(0.54f, -0.72f, -1.2f);
|
||||
|
||||
// position the camera to look at the collider along the x-y diagonal
|
||||
AzFramework::SetCameraTransform(
|
||||
m_cameraState,
|
||||
AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
AZ::Quaternion::CreateRotationZ(-AZ::Constants::QuarterPi), expectedColliderPosition - AZ::Vector3(2.0f, 2.0f, 0.0f)));
|
||||
|
||||
const AZ::Vector3 worldStart = expectedColliderPosition + scaleManipulatorYDelta;
|
||||
const AZ::Vector3 worldEnd = worldStart + 0.1f * scaleManipulatorYDelta;
|
||||
|
||||
const auto screenStart = AzFramework::WorldToScreen(worldStart, m_cameraState);
|
||||
const auto screenEnd = AzFramework::WorldToScreen(worldEnd, m_cameraState);
|
||||
|
||||
m_actionDispatcher
|
||||
->CameraState(m_cameraState)
|
||||
// move the mouse to the position of the y scale manipulator
|
||||
->MousePosition(screenStart)
|
||||
// drag to move the manipulator
|
||||
->MouseLButtonDown()
|
||||
->MousePosition(screenEnd)
|
||||
->MouseLButtonUp();
|
||||
|
||||
AZ::Vector3 newBoxDimensions = AZ::Vector3::CreateZero();
|
||||
AzToolsFramework::BoxManipulatorRequestBus::EventResult(
|
||||
newBoxDimensions, m_idPair, &AzToolsFramework::BoxManipulatorRequests::GetDimensions);
|
||||
|
||||
EXPECT_THAT(newBoxDimensions, IsCloseTolerance(AZ::Vector3(2.0f, 2.2f, 3.0f), ManipulatorTolerance));
|
||||
}
|
||||
|
||||
TEST_F(PhysXEditorColliderComponentManipulatorFixture, SphereColliderScaleManipulatorsCorrectlyLocatedRelativeToColliderWithNonUniformScale)
|
||||
{
|
||||
const float sphereRadius = 1.0f;
|
||||
const AZ::Quaternion sphereRotation(-0.1f, 0.7f, -0.7f, 0.1f);
|
||||
const AZ::Vector3 sphereOffset(-2.0f, 1.0f, -3.0f);
|
||||
SetupCollider(Physics::SphereShapeConfiguration(sphereRadius), sphereRotation, sphereOffset);
|
||||
const AZ::Quaternion entityRotation(-0.4f, -0.2f, 0.4f, 0.8f);
|
||||
const AZ::Vector3 entityTranslation(-1.0f, -3.0f, 3.0f);
|
||||
const float uniformScale = 1.5f;
|
||||
SetupTransform(entityRotation, entityTranslation, uniformScale);
|
||||
const AZ::Vector3 nonUniformScale(1.5f, 0.5f, 2.0f);
|
||||
SetupNonUniformScale(nonUniformScale);
|
||||
EnterColliderSubMode(PhysX::ColliderComponentModeRequests::SubMode::Dimensions);
|
||||
|
||||
// the expected position of the collider centre based on the combination of entity transform, collider offset and non-uniform scale
|
||||
const AZ::Vector3 expectedColliderPosition(1.7f, -10.65f, -3.0f);
|
||||
|
||||
// position the camera to look at the collider along the y-axis
|
||||
AzFramework::SetCameraTransform(
|
||||
m_cameraState, AZ::Transform::CreateTranslation(expectedColliderPosition - AZ::Vector3(0.0f, 5.0f, 0.0f)));
|
||||
|
||||
// the expected position of the scale manipulator relative to the centre of the collider, based on collider
|
||||
// rotation, entity scale, non-uniform scale and camera state
|
||||
const AZ::Vector3 scaleManipulatorDelta(-1.1952f, -1.8036f, 0.168f);
|
||||
|
||||
const AZ::Vector3 worldStart = expectedColliderPosition + scaleManipulatorDelta;
|
||||
const AZ::Vector3 worldEnd = worldStart - 0.1f * scaleManipulatorDelta;
|
||||
|
||||
const auto screenStart = AzFramework::WorldToScreen(worldStart, m_cameraState);
|
||||
const auto screenEnd = AzFramework::WorldToScreen(worldEnd, m_cameraState);
|
||||
|
||||
m_actionDispatcher
|
||||
->CameraState(m_cameraState)
|
||||
// move the mouse to the position of the y scale manipulator
|
||||
->MousePosition(screenStart)
|
||||
// drag to move the manipulator
|
||||
->MouseLButtonDown()
|
||||
->MousePosition(screenEnd)
|
||||
->MouseLButtonUp();
|
||||
|
||||
float newSphereRadius = 0.0f;
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(
|
||||
newSphereRadius, m_idPair, &PhysX::EditorColliderComponentRequests::GetSphereRadius);
|
||||
|
||||
EXPECT_NEAR(newSphereRadius, 0.9f, ManipulatorTolerance);
|
||||
}
|
||||
|
||||
TEST_F(PhysXEditorColliderComponentManipulatorFixture, CapsuleColliderScaleManipulatorsCorrectlyLocatedRelativeToColliderWithNonUniformScale)
|
||||
{
|
||||
const float capsuleRadius = 0.2f;
|
||||
const float capsuleHeight = 1.0f;
|
||||
const AZ::Quaternion capsuleRotation(-0.2f, -0.8f, -0.4f, 0.4f);
|
||||
const AZ::Vector3 capsuleOffset(1.0f, -2.0f, 1.0f);
|
||||
SetupCollider(Physics::CapsuleShapeConfiguration(capsuleHeight, capsuleRadius), capsuleRotation, capsuleOffset);
|
||||
const AZ::Quaternion entityRotation(0.7f, -0.1f, -0.1f, 0.7f);
|
||||
const AZ::Vector3 entityTranslation(-2.0f, 1.0f, -3.0f);
|
||||
const float uniformScale = 2.0f;
|
||||
SetupTransform(entityRotation, entityTranslation, uniformScale);
|
||||
const AZ::Vector3 nonUniformScale(1.0f, 0.5f, 1.5f);
|
||||
SetupNonUniformScale(nonUniformScale);
|
||||
EnterColliderSubMode(PhysX::ColliderComponentModeRequests::SubMode::Dimensions);
|
||||
|
||||
// the expected position of the collider centre based on the combination of entity transform, collider offset and non-uniform scale
|
||||
const AZ::Vector3 expectedColliderPosition(-0.92f, -2.44f, -5.0f);
|
||||
|
||||
// the expected position of the height manipulator relative to the centre of the collider, based on collider
|
||||
// rotation, entity scale and non-uniform scale
|
||||
const AZ::Vector3 heightManipulatorDelta(-0.3096f, 0.6528f, 0.4f);
|
||||
|
||||
// position the camera to look at the collider along the y-z diagonal
|
||||
AzFramework::SetCameraTransform(
|
||||
m_cameraState,
|
||||
AZ::Transform::CreateFromQuaternionAndTranslation(
|
||||
AZ::Quaternion::CreateRotationX(-AZ::Constants::QuarterPi), expectedColliderPosition + AZ::Vector3(0.0f, -1.0f, 1.0f)));
|
||||
|
||||
const AZ::Vector3 worldStart = expectedColliderPosition + heightManipulatorDelta;
|
||||
const AZ::Vector3 worldEnd = worldStart + 0.2f * heightManipulatorDelta;
|
||||
|
||||
const auto screenStart = AzFramework::WorldToScreen(worldStart, m_cameraState);
|
||||
const auto screenEnd = AzFramework::WorldToScreen(worldEnd, m_cameraState);
|
||||
|
||||
m_actionDispatcher
|
||||
->CameraState(m_cameraState)
|
||||
// move the mouse to the position of the height manipulator
|
||||
->MousePosition(screenStart)
|
||||
// drag to move the manipulator
|
||||
->MouseLButtonDown()
|
||||
->MousePosition(screenEnd)
|
||||
->MouseLButtonUp();
|
||||
|
||||
float newCapsuleHeight = 0.0f;
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(
|
||||
newCapsuleHeight, m_idPair, &PhysX::EditorColliderComponentRequests::GetCapsuleHeight);
|
||||
|
||||
EXPECT_NEAR(newCapsuleHeight, 1.2f, ManipulatorTolerance);
|
||||
}
|
||||
|
||||
TEST_F(PhysXEditorColliderComponentManipulatorFixture, ColliderRotationManipulatorsCorrectlyLocatedRelativeToColliderWithNonUniformScale)
|
||||
{
|
||||
const float capsuleRadius = 1.2f;
|
||||
const float capsuleHeight = 4.0f;
|
||||
const AZ::Quaternion capsuleRotation(0.7f, 0.7f, -0.1f, 0.1f);
|
||||
const AZ::Vector3 capsuleOffset(-2.0f, -2.0f, 1.0f);
|
||||
SetupCollider(Physics::CapsuleShapeConfiguration(capsuleHeight, capsuleRadius), capsuleRotation, capsuleOffset);
|
||||
const AZ::Quaternion entityRotation(0.8f, -0.4f, -0.4f, 0.2f);
|
||||
const AZ::Vector3 entityTranslation(1.0f, -1.5f, 2.0f);
|
||||
const float uniformScale = 1.5f;
|
||||
SetupTransform(entityRotation, entityTranslation, uniformScale);
|
||||
const AZ::Vector3 nonUniformScale(1.5f, 1.5f, 2.0f);
|
||||
SetupNonUniformScale(nonUniformScale);
|
||||
EnterColliderSubMode(PhysX::ColliderComponentModeRequests::SubMode::Rotation);
|
||||
|
||||
// the expected position of the collider centre based on the combination of entity transform, collider offset and non-uniform scale
|
||||
const AZ::Vector3 expectedColliderPosition(-0.86f, 4.8f, -0.52f);
|
||||
|
||||
// the y and z axes of the collider's frame in world space, used to locate points on the x rotation manipulator arc to interact with
|
||||
const AZ::Vector3 yDirection(0.36f, -0.8f, -0.48f);
|
||||
const AZ::Vector3 zDirection(0.9024f, 0.168f, 0.3968f);
|
||||
|
||||
// position the camera to look at the collider along the world y axis
|
||||
AzFramework::SetCameraTransform(
|
||||
m_cameraState,
|
||||
AZ::Transform::CreateTranslation(expectedColliderPosition - AZ::Vector3(0.0f, 10.0f, 0.0f)));
|
||||
|
||||
const float screenToWorldMultiplier = AzToolsFramework::CalculateScreenToWorldMultiplier(expectedColliderPosition, m_cameraState);
|
||||
const float manipulatorViewRadius = 2.0f;
|
||||
const AZ::Vector3 worldStart = expectedColliderPosition + screenToWorldMultiplier * manipulatorViewRadius * yDirection;
|
||||
const AZ::Vector3 worldEnd = expectedColliderPosition + screenToWorldMultiplier * manipulatorViewRadius * zDirection;
|
||||
|
||||
const auto screenStart = AzFramework::WorldToScreen(worldStart, m_cameraState);
|
||||
const auto screenEnd = AzFramework::WorldToScreen(worldEnd, m_cameraState);
|
||||
|
||||
m_actionDispatcher
|
||||
->CameraState(m_cameraState)
|
||||
// move the mouse to a position on the angular manipulator
|
||||
->MousePosition(screenStart)
|
||||
// drag to move the manipulator
|
||||
->MouseLButtonDown()
|
||||
->MousePosition(screenEnd)
|
||||
->MouseLButtonUp();
|
||||
|
||||
AZ::Quaternion newColliderRotation = AZ::Quaternion::CreateIdentity();
|
||||
PhysX::EditorColliderComponentRequestBus::EventResult(
|
||||
newColliderRotation, m_idPair, &PhysX::EditorColliderComponentRequests::GetColliderRotation);
|
||||
|
||||
EXPECT_THAT(newColliderRotation, testing::Not(IsCloseTolerance(capsuleRotation, ManipulatorTolerance)));
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
Reference in New Issue
Block a user