diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/Damping.svg b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/Damping.svg
new file mode 100644
index 0000000000..b12640bd59
--- /dev/null
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/Damping.svg
@@ -0,0 +1,18 @@
+
+
+
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/MaxForce.svg b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/MaxForce.svg
new file mode 100644
index 0000000000..b1b09104b1
--- /dev/null
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/MaxForce.svg
@@ -0,0 +1,22 @@
+
+
+
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/MaxTorque.svg b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/MaxTorque.svg
new file mode 100644
index 0000000000..3c40cb82b2
--- /dev/null
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/MaxTorque.svg
@@ -0,0 +1,15 @@
+
+
+
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SnapPosition.svg b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SnapPosition.svg
new file mode 100644
index 0000000000..a9c5811d7d
--- /dev/null
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SnapPosition.svg
@@ -0,0 +1,19 @@
+
+
+
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SnapRotation.svg b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SnapRotation.svg
new file mode 100644
index 0000000000..684c32a08d
--- /dev/null
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SnapRotation.svg
@@ -0,0 +1,17 @@
+
+
+
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/Stiffness.svg b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/Stiffness.svg
new file mode 100644
index 0000000000..456785f1bc
--- /dev/null
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/Stiffness.svg
@@ -0,0 +1,22 @@
+
+
+
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SwingLimits.svg b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SwingLimits.svg
new file mode 100644
index 0000000000..ec3d1114bb
--- /dev/null
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/SwingLimits.svg
@@ -0,0 +1,22 @@
+
+
+
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/TwistLimits.svg b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/TwistLimits.svg
new file mode 100644
index 0000000000..98f56f547d
--- /dev/null
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/img/UI20/toolbar/joints/TwistLimits.svg
@@ -0,0 +1,18 @@
+
+
+
diff --git a/Code/Framework/AzQtComponents/AzQtComponents/Components/resources.qrc b/Code/Framework/AzQtComponents/AzQtComponents/Components/resources.qrc
index 7321128b57..16d55f1b8c 100644
--- a/Code/Framework/AzQtComponents/AzQtComponents/Components/resources.qrc
+++ b/Code/Framework/AzQtComponents/AzQtComponents/Components/resources.qrc
@@ -390,6 +390,14 @@
img/UI20/toolbar/Y_axis.svg
img/UI20/toolbar/Z_axis.svg
img/UI20/toolbar/XY2_copy.svg
+ img/UI20/toolbar/joints/Damping.svg
+ img/UI20/toolbar/joints/MaxForce.svg
+ img/UI20/toolbar/joints/MaxTorque.svg
+ img/UI20/toolbar/joints/SnapPosition.svg
+ img/UI20/toolbar/joints/SnapRotation.svg
+ img/UI20/toolbar/joints/Stiffness.svg
+ img/UI20/toolbar/joints/SwingLimits.svg
+ img/UI20/toolbar/joints/TwistLimits.svg
img/triangle0.png
img/triangle0_highlighted.png
img/line.png
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.cpp
index e933940d95..372587c110 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.cpp
@@ -29,13 +29,29 @@ namespace AzToolsFramework::ViewportUi::Internal
void ButtonGroup::SetHighlightedButton(ButtonId buttonId)
{
+ if (buttonId == m_highlightedButtonId) // the requested button is highlighted, so do nothing.
+ {
+ return;
+ }
+
if (auto buttonEntry = m_buttons.find(buttonId); buttonEntry != m_buttons.end())
{
- for (auto& button : m_buttons)
- {
- button.second->m_state = Button::State::Deselected;
- }
+ ClearHighlightedButton();
buttonEntry->second->m_state = Button::State::Selected;
+ m_highlightedButtonId = buttonId;
+ }
+ }
+
+ void ButtonGroup::ClearHighlightedButton()
+ {
+ if (m_highlightedButtonId == InvalidButtonId)
+ {
+ return;
+ }
+ if (auto buttonEntry = m_buttons.find(m_highlightedButtonId); buttonEntry != m_buttons.end())
+ {
+ buttonEntry->second->m_state = Button::State::Deselected;
+ m_highlightedButtonId = InvalidButtonId;
}
}
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.h
index 888be6b3e0..7b6864a71b 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ButtonGroup.h
@@ -25,6 +25,7 @@ namespace AzToolsFramework::ViewportUi::Internal
~ButtonGroup() = default;
void SetHighlightedButton(ButtonId buttonId);
+ void ClearHighlightedButton();
void SetViewportUiElementId(ViewportUiElementId id);
ViewportUiElementId GetViewportUiElementId() const;
@@ -40,5 +41,6 @@ namespace AzToolsFramework::ViewportUi::Internal
AZ::Event m_buttonTriggeredEvent;
ViewportUiElementId m_viewportUiId;
AZStd::unordered_map> m_buttons;
+ ButtonId m_highlightedButtonId = InvalidButtonId;
};
} // namespace AzToolsFramework::ViewportUi::Internal
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.cpp b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.cpp
index cee4a311e8..255d11f561 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.cpp
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.cpp
@@ -50,6 +50,16 @@ namespace AzToolsFramework::ViewportUi
}
}
+ void ViewportUiManager::ClearClusterActiveButton(ClusterId clusterId)
+ {
+ if (auto clusterIt = m_clusterButtonGroups.find(clusterId); clusterIt != m_clusterButtonGroups.end())
+ {
+ auto cluster = clusterIt->second;
+ cluster->ClearHighlightedButton();
+ UpdateButtonGroupUi(cluster.get());
+ }
+ }
+
void ViewportUiManager::SetSwitcherActiveButton(const SwitcherId switcherId, const ButtonId buttonId)
{
if (auto switcherIt = m_switcherButtonGroups.find(switcherId); switcherIt != m_switcherButtonGroups.end())
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.h
index c5ecf7aee6..9ec6648451 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiManager.h
@@ -30,6 +30,7 @@ namespace AzToolsFramework::ViewportUi
const ClusterId CreateCluster(Alignment align) override;
const SwitcherId CreateSwitcher(Alignment align) override;
void SetClusterActiveButton(ClusterId clusterId, ButtonId buttonId) override;
+ void ClearClusterActiveButton(ClusterId clusterId) override;
void SetSwitcherActiveButton(SwitcherId switcherId, ButtonId buttonId) override;
void SetClusterButtonLocked(ClusterId clusterId, ButtonId buttonId, bool isLocked) override;
void SetClusterButtonTooltip(ClusterId clusterId, ButtonId buttonId, const AZStd::string& tooltip) override;
diff --git a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiRequestBus.h b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiRequestBus.h
index 649186c7e7..108d23950a 100644
--- a/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiRequestBus.h
+++ b/Code/Framework/AzToolsFramework/AzToolsFramework/ViewportUi/ViewportUiRequestBus.h
@@ -59,6 +59,8 @@ namespace AzToolsFramework::ViewportUi
virtual const SwitcherId CreateSwitcher(Alignment align) = 0;
//! Sets the active button of the cluster. This is the button which will display as highlighted.
virtual void SetClusterActiveButton(ClusterId clusterId, ButtonId buttonId) = 0;
+ //! Clears the active button of the cluster if one is active. The button will no longer display as highlighted.
+ virtual void ClearClusterActiveButton(ClusterId clusterId) = 0;
//! Sets the active button of the switcher. This is the button which has a text label.
virtual void SetSwitcherActiveButton(SwitcherId clusterId, ButtonId buttonId) = 0;
//! Adds a locked overlay to the cluster button's icon.
diff --git a/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportUiManagerTests.cpp b/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportUiManagerTests.cpp
index 676b9c5e35..daf4b9c29a 100644
--- a/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportUiManagerTests.cpp
+++ b/Code/Framework/AzToolsFramework/Tests/Viewport/ViewportUiManagerTests.cpp
@@ -127,6 +127,25 @@ namespace UnitTest
EXPECT_TRUE(button->m_state == AzToolsFramework::ViewportUi::Internal::Button::State::Selected);
}
+ TEST_F(ViewportUiManagerTestFixture, ClearClusterActiveButtonSetsButtonStateToDeselected)
+ {
+ // setup
+ auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft);
+ auto buttonId = m_viewportManagerWrapper.GetViewportManager()->CreateClusterButton(clusterId, "");
+
+ auto clusterEntry = m_viewportManagerWrapper.GetViewportManager()->GetClusterMap().find(clusterId);
+ auto button = clusterEntry->second->GetButton(buttonId);
+
+ // first set a button to active
+ m_viewportManagerWrapper.GetViewportManager()->SetClusterActiveButton(clusterId, buttonId);
+ EXPECT_TRUE(button->m_state == AzToolsFramework::ViewportUi::Internal::Button::State::Selected);
+
+ // clear the active button on the cluster
+ m_viewportManagerWrapper.GetViewportManager()->ClearClusterActiveButton(clusterId);
+ // the button should now be deselected
+ EXPECT_TRUE(button->m_state == AzToolsFramework::ViewportUi::Internal::Button::State::Deselected);
+ }
+
TEST_F(ViewportUiManagerTestFixture, RegisterClusterEventHandlerConnectsHandlerToClusterEvent)
{
auto clusterId = m_viewportManagerWrapper.GetViewportManager()->CreateCluster(AzToolsFramework::ViewportUi::Alignment::TopLeft);
diff --git a/Gems/PhysX/Code/Editor/ColliderAssetScaleMode.h b/Gems/PhysX/Code/Editor/ColliderAssetScaleMode.h
index 4659bf3677..24e33ea584 100644
--- a/Gems/PhysX/Code/Editor/ColliderAssetScaleMode.h
+++ b/Gems/PhysX/Code/Editor/ColliderAssetScaleMode.h
@@ -8,21 +8,20 @@
#pragma once
-#include "ColliderSubComponentMode.h"
+#include
#include
namespace PhysX
{
/// Sub component mode for modifying the asset scale on a collider in the viewport.
- class ColliderAssetScaleMode
- : public PhysX::ColliderSubComponentMode
+ class ColliderAssetScaleMode : public PhysXSubComponentModeBase
{
public:
AZ_CLASS_ALLOCATOR_DECL
ColliderAssetScaleMode();
- // ColliderSubComponentMode ...
+ // PhysXSubComponentModeBase ...
void Setup(const AZ::EntityComponentIdPair& idPair) override;
void Refresh(const AZ::EntityComponentIdPair& idPair) override;
void Teardown(const AZ::EntityComponentIdPair& idPair) override;
diff --git a/Gems/PhysX/Code/Editor/ColliderBoxMode.h b/Gems/PhysX/Code/Editor/ColliderBoxMode.h
index a8e0c03a3a..75ce928d80 100644
--- a/Gems/PhysX/Code/Editor/ColliderBoxMode.h
+++ b/Gems/PhysX/Code/Editor/ColliderBoxMode.h
@@ -8,19 +8,18 @@
#pragma once
-#include "ColliderSubComponentMode.h"
+#include
#include
namespace PhysX
{
/// Sub component mode for modifying the box dimensions on a collider.
- class ColliderBoxMode
- : public PhysX::ColliderSubComponentMode
+ class ColliderBoxMode : public PhysXSubComponentModeBase
{
public:
AZ_CLASS_ALLOCATOR_DECL
- // ColliderSubComponentMode ...
+ // PhysXSubComponentModeBase ...
void Setup(const AZ::EntityComponentIdPair& idPair) override;
void Refresh(const AZ::EntityComponentIdPair& idPair) override;
void Teardown(const AZ::EntityComponentIdPair& idPair) override;
diff --git a/Gems/PhysX/Code/Editor/ColliderCapsuleMode.h b/Gems/PhysX/Code/Editor/ColliderCapsuleMode.h
index b152801988..ceedd84a35 100644
--- a/Gems/PhysX/Code/Editor/ColliderCapsuleMode.h
+++ b/Gems/PhysX/Code/Editor/ColliderCapsuleMode.h
@@ -8,7 +8,7 @@
#pragma once
-#include "ColliderSubComponentMode.h"
+#include
#include
#include
@@ -16,13 +16,13 @@ namespace PhysX
{
/// Sub component mode for modifying the height and radius on a capsule collider.
class ColliderCapsuleMode
- : public PhysX::ColliderSubComponentMode
+ : public PhysXSubComponentModeBase
, private AzFramework::EntityDebugDisplayEventBus::Handler
{
public:
AZ_CLASS_ALLOCATOR_DECL
- // ColliderSubComponentMode ...
+ // PhysXSubComponentModeBase ...
void Setup(const AZ::EntityComponentIdPair& idPair) override;
void Refresh(const AZ::EntityComponentIdPair& idPair) override;
void Teardown(const AZ::EntityComponentIdPair& idPair) override;
diff --git a/Gems/PhysX/Code/Editor/ColliderComponentMode.cpp b/Gems/PhysX/Code/Editor/ColliderComponentMode.cpp
index 994811b8d1..5de625f679 100644
--- a/Gems/PhysX/Code/Editor/ColliderComponentMode.cpp
+++ b/Gems/PhysX/Code/Editor/ColliderComponentMode.cpp
@@ -7,7 +7,6 @@
*/
#include "ColliderComponentMode.h"
-#include "ColliderSubComponentMode.h"
#include "ColliderOffsetMode.h"
#include "ColliderRotationMode.h"
#include "ColliderBoxMode.h"
@@ -15,6 +14,7 @@
#include "ColliderCapsuleMode.h"
#include "ColliderAssetScaleMode.h"
+#include
#include
#include
diff --git a/Gems/PhysX/Code/Editor/ColliderComponentMode.h b/Gems/PhysX/Code/Editor/ColliderComponentMode.h
index 420e621054..b4ca060065 100644
--- a/Gems/PhysX/Code/Editor/ColliderComponentMode.h
+++ b/Gems/PhysX/Code/Editor/ColliderComponentMode.h
@@ -15,7 +15,7 @@
namespace PhysX
{
- class ColliderSubComponentMode;
+ class PhysXSubComponentModeBase;
//! ComponentMode for the Collider Component - Manages a list of Sub-Component Modes and
//! is responsible for switching between and activating them.
@@ -53,7 +53,7 @@ namespace PhysX
void CreateSubModes();
void ResetCurrentMode();
- AZStd::unordered_map> m_subModes;
+ AZStd::unordered_map> m_subModes;
SubMode m_subMode = SubMode::Dimensions;
//! Create the Viewport UI cluster for sub mode selection.
diff --git a/Gems/PhysX/Code/Editor/ColliderOffsetMode.h b/Gems/PhysX/Code/Editor/ColliderOffsetMode.h
index bcf140a5e3..6a2e6a8a12 100644
--- a/Gems/PhysX/Code/Editor/ColliderOffsetMode.h
+++ b/Gems/PhysX/Code/Editor/ColliderOffsetMode.h
@@ -8,21 +8,20 @@
#pragma once
-#include "ColliderSubComponentMode.h"
+#include
#include
namespace PhysX
{
/// Sub component mode for modifying offset on a collider in the viewport.
- class ColliderOffsetMode
- : public PhysX::ColliderSubComponentMode
+ class ColliderOffsetMode : public PhysXSubComponentModeBase
{
public:
AZ_CLASS_ALLOCATOR_DECL
ColliderOffsetMode();
- // ColliderSubComponentMode ...
+ // PhysXSubComponentModeBase ...
void Setup(const AZ::EntityComponentIdPair& idPair) override;
void Refresh(const AZ::EntityComponentIdPair& idPair) override;
void Teardown(const AZ::EntityComponentIdPair& idPair) override;
diff --git a/Gems/PhysX/Code/Editor/ColliderRotationMode.h b/Gems/PhysX/Code/Editor/ColliderRotationMode.h
index e1f578aed7..dc37e23b0e 100644
--- a/Gems/PhysX/Code/Editor/ColliderRotationMode.h
+++ b/Gems/PhysX/Code/Editor/ColliderRotationMode.h
@@ -8,7 +8,7 @@
#pragma once
-#include "ColliderSubComponentMode.h"
+#include
#include
#include
@@ -16,7 +16,7 @@ namespace PhysX
{
/// Sub component mode for modifying the rotation on a collider in the viewport.
class ColliderRotationMode
- : public PhysX::ColliderSubComponentMode
+ : public PhysXSubComponentModeBase
, private AzFramework::EntityDebugDisplayEventBus::Handler
{
public:
@@ -24,7 +24,7 @@ namespace PhysX
ColliderRotationMode();
- // ColliderSubComponentMode ...
+ // PhysXSubComponentModeBase ...
void Setup(const AZ::EntityComponentIdPair& idPair) override;
void Refresh(const AZ::EntityComponentIdPair& idPair) override;
void Teardown(const AZ::EntityComponentIdPair& idPair) override;
diff --git a/Gems/PhysX/Code/Editor/ColliderSphereMode.h b/Gems/PhysX/Code/Editor/ColliderSphereMode.h
index 08ee813cd0..7d255d598b 100644
--- a/Gems/PhysX/Code/Editor/ColliderSphereMode.h
+++ b/Gems/PhysX/Code/Editor/ColliderSphereMode.h
@@ -8,7 +8,7 @@
#pragma once
-#include "ColliderSubComponentMode.h"
+#include
#include
#include
@@ -16,13 +16,13 @@ namespace PhysX
{
/// Sub component mode for modifying the box dimensions on a collider.
class ColliderSphereMode
- : public PhysX::ColliderSubComponentMode
+ : public PhysXSubComponentModeBase
, private AzFramework::EntityDebugDisplayEventBus::Handler
{
public:
AZ_CLASS_ALLOCATOR_DECL
- // ColliderSubComponentMode ...
+ // PhysXSubComponentModeBase ...
void Setup(const AZ::EntityComponentIdPair& idPair) override;
void Refresh(const AZ::EntityComponentIdPair& idPair) override;
void Teardown(const AZ::EntityComponentIdPair& idPair) override;
diff --git a/Gems/PhysX/Code/Editor/ColliderSubComponentMode.h b/Gems/PhysX/Code/Editor/ColliderSubComponentMode.h
deleted file mode 100644
index 4711a20c86..0000000000
--- a/Gems/PhysX/Code/Editor/ColliderSubComponentMode.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-
-#pragma once
-
-namespace AZ
-{
- class EntityComponentIdPair;
-}
-
-namespace PhysX
-{
- /// Interface to implement when adding a new editing mode
- /// for collider component mode.
- class ColliderSubComponentMode
- {
- public:
- virtual ~ColliderSubComponentMode() {};
-
- /// Called when the mode is entered to initialise the mode.
- /// @param idPair The entity/component id pair.
- virtual void Setup(const AZ::EntityComponentIdPair& idPair) = 0;
-
- /// Called when the mode needs to refresh it's values.
- /// @param idPair The entity/component id pair.
- virtual void Refresh(const AZ::EntityComponentIdPair& idPair) = 0;
-
- /// Called when the mode exits to perform cleanup.
- /// @param idPair The entity/component id pair.
- virtual void Teardown(const AZ::EntityComponentIdPair& idPair) = 0;
-
- /// Called when reset hotkey is pressed.
- /// Should reset values in the sub component mode to sensible defaults.
- /// @param idPair The entity/component id pair.
- virtual void ResetValues(const AZ::EntityComponentIdPair& idPair) = 0;
- };
-}
diff --git a/Gems/PhysX/Code/Editor/EditorJointCommon.h b/Gems/PhysX/Code/Editor/EditorJointCommon.h
new file mode 100644
index 0000000000..031b293942
--- /dev/null
+++ b/Gems/PhysX/Code/Editor/EditorJointCommon.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+
+namespace PhysX
+{
+ //! Pair of floating point values for angular limits.
+ using AngleLimitsFloatPair = AZStd::pair;
+} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorJointComponentMode.cpp b/Gems/PhysX/Code/Editor/EditorJointComponentMode.cpp
deleted file mode 100644
index 39b028bef3..0000000000
--- a/Gems/PhysX/Code/Editor/EditorJointComponentMode.cpp
+++ /dev/null
@@ -1,577 +0,0 @@
-
-/*
- * 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
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-namespace PhysX
-{
- namespace
- {
- //! Uri's for shortcut actions.
- const AZ::Crc32 GoToNextModeActionUri = AZ_CRC("com.o3de.action.physx.joint.nextmode", 0xe9cf4ed6);
- const AZ::Crc32 GoToPrevModeActionUri = AZ_CRC("com.o3de.action.physx.joint.prevmode", 0xe70f8daa);
- }
-
- const AZStd::string EditorJointComponentMode::s_parameterAngularPair = "Twist Limits";
- const AZStd::string EditorJointComponentMode::s_parameterDamping = "Damping";
- const AZStd::string EditorJointComponentMode::s_parameterMaxForce = "Maximum Force";
- const AZStd::string EditorJointComponentMode::s_parameterMaxTorque = "Maximum Torque";
- const AZStd::string EditorJointComponentMode::s_parameterPosition = "Position";
- const AZStd::string EditorJointComponentMode::s_parameterRotation = "Rotation";
- const AZStd::string EditorJointComponentMode::s_parameterSnapPosition = "Snap Position";
- const AZStd::string EditorJointComponentMode::s_parameterSnapRotation = "Snap Rotation";
- const AZStd::string EditorJointComponentMode::s_parameterStiffness = "Stiffness";
- const AZStd::string EditorJointComponentMode::s_parameterSwingLimit = "Swing Limits";
- const AZStd::string EditorJointComponentMode::s_parameterTolerance = "Tolerance";
- const AZStd::string EditorJointComponentMode::s_parameterTransform = "Transform";
- const AZStd::string EditorJointComponentMode::s_parameterComponentMode = "Component Mode";
- const AZStd::string EditorJointComponentMode::s_parameterLeadEntity = "Lead Entity";
- const AZStd::string EditorJointComponentMode::s_parameterSelectOnSnap = "Select on Snap";
-
- EditorSubComponentModeConfig::EditorSubComponentModeConfig(const AZStd::string& name
- , EditorSubComponentModeType type)
- : m_name(name), m_type(type)
- {
- }
-
- EditorSubComponentModeConfig::EditorSubComponentModeConfig(const AZStd::string& name
- , EditorSubComponentModeType type
- , float exponent
- , float max
- , float min)
- : m_name(name), m_type(type), m_exponent(exponent), m_max(max), m_min(min)
- {
- }
-
- EditorSubComponentModeConfig::EditorSubComponentModeConfig(const AZStd::string& name
- , EditorSubComponentModeType type
- , const AZ::Vector3& axis
- , float max
- , float min)
- : m_name(name), m_type(type), m_axis(axis), m_max(max), m_min(min)
- {
- }
-
- EditorSubComponentModeConfig::EditorSubComponentModeConfig(const AZStd::string& name
- , EditorSubComponentModeType type
- , float max
- , float min)
- : m_name(name), m_type(type), m_max(max), m_min(min)
- {
- }
-
- EditorJointComponentMode::EditorJointComponentMode(
- const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType)
- : EditorBaseComponentMode(entityComponentIdPair, componentType)
- , m_entityComponentIdPair(entityComponentIdPair)
- , m_componentType(componentType)
- {
- EditorJointRequestBus::Event(
- m_entityComponentIdPair
- , &EditorJointRequests::SetBoolValue
- , EditorJointComponentMode::s_parameterComponentMode
- , true);
- }
-
- EditorJointComponentMode::~EditorJointComponentMode()
- {
- EditorJointRequestBus::Event(
- m_entityComponentIdPair
- , &EditorJointRequests::SetBoolValue
- , EditorJointComponentMode::s_parameterComponentMode
- , false);
- }
-
- bool EditorJointComponentMode::HandleMouseInteraction(
- const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction)
- {
- if (mouseInteraction.m_mouseEvent == AzToolsFramework::ViewportInteraction::MouseEvent::Wheel &&
- mouseInteraction.m_mouseInteraction.m_keyboardModifiers.Ctrl())
- {
- NextMode();
- return true;
- }
-
- // Propagate mouse interaction to sub-component mode.
- if (m_currentSubComponentMode)
- {
- m_currentSubComponentMode->HandleMouseInteraction(mouseInteraction);
- }
-
- return false;
- }
-
- AZStd::vector EditorJointComponentMode::PopulateActionsImpl()
- {
- AzToolsFramework::ActionOverride goToNextMode;
- goToNextMode.SetUri(GoToNextModeActionUri);
- goToNextMode.SetKeySequence(QKeySequence(Qt::Key_Tab));
- goToNextMode.SetTitle("Next Mode");
- goToNextMode.SetTip("Go to next mode");
- goToNextMode.SetEntityComponentIdPair(GetEntityComponentIdPair());
- goToNextMode.SetCallback([this]()
- {
- NextMode();
- });
-
- AzToolsFramework::ActionOverride goToPrevMode;
- goToPrevMode.SetUri(GoToPrevModeActionUri);
- goToPrevMode.SetKeySequence(QKeySequence(Qt::SHIFT + Qt::Key_Tab));
- goToPrevMode.SetTitle("Previous Mode");
- goToPrevMode.SetTip("Go to previous mode");
- goToPrevMode.SetEntityComponentIdPair(GetEntityComponentIdPair());
- goToPrevMode.SetCallback([this]()
- {
- PreviousMode();
- });
-
- return {goToNextMode, goToPrevMode};
- }
-
- void EditorJointComponentMode::NextMode()
- {
- const bool isForwardChange = true;
- ChangeMode(isForwardChange);
- }
-
- void EditorJointComponentMode::PreviousMode()
- {
- const bool isForwardChange = false;
- ChangeMode(isForwardChange);
- }
-
- void EditorJointComponentMode::ChangeMode(bool forwardChange)
- {
- if (m_configMap.empty())
- {
- return;
- }
-
- AZStd::string previousModeName;
- if (m_currentSubComponentMode)
- {
- previousModeName = m_currentSubComponentMode->m_name;
- m_currentSubComponentMode.reset();
- }
-
- ConfigMapIter configIter = m_configMap.begin();
- if (!previousModeName.empty())
- {
- configIter = m_configMap.find(previousModeName);
- }
-
- AZ::u32 iterCount = 0;
- do
- {
- if (forwardChange)
- {
- ++configIter;
- if (configIter == m_configMap.end())
- {
- configIter = m_configMap.begin();
- }
- }
- else
- {
- if (configIter == m_configMap.begin())
- {
- configIter = m_configMap.end();
- }
- --configIter;
- }
- ++iterCount;
- } while (!IsSubComponentModeUsed(configIter->second.m_name) && iterCount != m_configMap.size());
-
- if (iterCount == m_configMap.size()) // All sub component modes are not in use.
- {
- return;
- }
-
- SetCurrentSubComponentMode(configIter->second.m_name);
- }
-
- void EditorJointComponentMode::SetCurrentSubComponentMode(const AZStd::string& subComponentModeName)
- {
- ConfigMapIter configIter = m_configMap.find(subComponentModeName);
- if (configIter == m_configMap.end())
- {
- AZ_Warning("EditorJointComponentMode"
- , false
- , "Attempt to set sub component mode which does not exist: %s"
- , subComponentModeName.c_str());
- return;
- }
- EditorSubComponentModeConfig config = configIter->second;
-
- EditorJointRequestBus::EventResult(
- config.m_selectLeadOnSnap, m_entityComponentIdPair
- , &EditorJointRequests::GetBoolValue
- , s_parameterSelectOnSnap);
-
- m_currentSubComponentMode.reset();
-
- switch (config.m_type)
- {
- case EditorSubComponentModeType::Linear:
- SetSubComponentModeLinear(config);
- break;
- case EditorSubComponentModeType::AnglePair:
- SetSubComponentModeAnglePair(config);
- break;
- case EditorSubComponentModeType::AngleCone:
- SetSubComponentModeAngleCone(config);
- break;
- case EditorSubComponentModeType::Vec3:
- SetSubComponentModeVec3(config);
- break;
- case EditorSubComponentModeType::Rotation:
- SetSubComponentModeRotation(config);
- break;
- case EditorSubComponentModeType::SnapPosition:
- SetSubComponentModeSnapPosition(config);
- break;
- case EditorSubComponentModeType::SnapRotation:
- SetSubComponentModeSnapRotation(config);
- break;
- default:
- AZ_Error("EditorJointComponentMode::SetCurrentSubComponentMode"
- , false
- , "Unsupported sub-component mode type.");
- }
- }
-
- bool EditorJointComponentMode::IsSubComponentModeUsed(const AZStd::string& subComponentModeName)
- {
- bool isUsed = false;
- EditorJointRequestBus::EventResult(
- isUsed, m_entityComponentIdPair
- , &EditorJointRequests::IsParameterUsed
- , subComponentModeName);
- return isUsed;
- }
-
- void EditorJointComponentMode::SetSubComponentModeAngleCone(const EditorSubComponentModeConfig& config)
- {
- m_currentSubComponentMode = AZStd::make_shared(m_entityComponentIdPair
- , m_componentType
- , config.m_name
- , config.m_max
- , config.m_min);
- }
-
- void EditorJointComponentMode::SetSubComponentModeAnglePair(const EditorSubComponentModeConfig& config)
- {
- m_currentSubComponentMode = AZStd::make_shared(m_entityComponentIdPair
- , m_componentType
- , config.m_name
- , config.m_axis
- , config.m_max
- , config.m_min
- , config.m_min
- , -config.m_max);
- }
-
- void EditorJointComponentMode::SetSubComponentModeLinear(const EditorSubComponentModeConfig& config)
- {
- m_currentSubComponentMode = AZStd::make_shared(m_entityComponentIdPair
- , m_componentType
- , config.m_name
- , config.m_exponent
- , config.m_max
- , config.m_min);
- }
-
- void EditorJointComponentMode::SetSubComponentModeVec3(const EditorSubComponentModeConfig& config)
- {
- m_currentSubComponentMode = AZStd::make_shared(m_entityComponentIdPair
- , m_componentType
- , config.m_name);
- }
-
- void EditorJointComponentMode::SetSubComponentModeRotation(const EditorSubComponentModeConfig& config)
- {
- m_currentSubComponentMode = AZStd::make_shared(m_entityComponentIdPair
- , m_componentType
- , config.m_name);
- }
-
- void EditorJointComponentMode::SetSubComponentModeSnapPosition(const EditorSubComponentModeConfig& config)
- {
- m_currentSubComponentMode = AZStd::make_shared(m_entityComponentIdPair
- , m_componentType
- , config.m_name
- , config.m_selectLeadOnSnap);
- }
-
- void EditorJointComponentMode::SetSubComponentModeSnapRotation(const EditorSubComponentModeConfig& config)
- {
- m_currentSubComponentMode = AZStd::make_shared(m_entityComponentIdPair
- , m_componentType
- , config.m_name);
- }
-
- EditorBallJointComponentMode::EditorBallJointComponentMode(
- const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType)
- : EditorJointComponentMode(entityComponentIdPair, componentType)
- {
- m_configMap = Configure();
- NextMode();
- }
-
- EditorBallJointComponentMode::~EditorBallJointComponentMode()
- {
- if (m_currentSubComponentMode)
- {
- m_currentSubComponentMode.reset();
- }
- }
-
- void EditorJointComponentMode::Refresh()
- {
- if (m_currentSubComponentMode)
- {
- m_currentSubComponentMode->Refresh();
- }
- }
-
- AZStd::map EditorBallJointComponentMode::Configure()
- {
- AZStd::map configMap;
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterPosition
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterPosition
- , EditorSubComponentModeType::Vec3)
- );
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterRotation
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterRotation
- , EditorSubComponentModeType::Rotation)
- );
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterSnapPosition
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterSnapPosition
- , EditorSubComponentModeType::SnapPosition)
- );
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterSnapRotation
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterSnapRotation
- , EditorSubComponentModeType::SnapRotation)
- );
-
- const float exponentBreakage = 1.0f;
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterMaxForce
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterMaxForce
- , EditorSubComponentModeType::Linear
- , exponentBreakage
- , PhysX::EditorJointConfig::s_breakageMax
- , PhysX::EditorJointConfig::s_breakageMin)
- );
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterMaxTorque
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterMaxTorque
- , EditorSubComponentModeType::Linear
- , exponentBreakage
- , PhysX::EditorJointConfig::s_breakageMax
- , PhysX::EditorJointConfig::s_breakageMin)
- );
-
- const float exponentSpring = 2.0f;
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterDamping
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterDamping
- , EditorSubComponentModeType::Linear
- , exponentSpring
- , PhysX::EditorJointLimitConeConfig::s_springMax
- , PhysX::EditorJointLimitConeConfig::s_springMin)
- );
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterStiffness
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterStiffness
- , EditorSubComponentModeType::Linear
- , exponentSpring
- , PhysX::EditorJointLimitConeConfig::s_springMax
- , PhysX::EditorJointLimitConeConfig::s_springMin)
- );
-
- // Cone tip to base is always X-axis.
- //The angle cone defines the limitations for rotation about the Y and Z axes.
- configMap.emplace(
- EditorJointComponentMode::s_parameterSwingLimit
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterSwingLimit
- , EditorSubComponentModeType::AngleCone
- , PhysX::EditorJointLimitConeConfig::s_angleMax
- , PhysX::EditorJointLimitConeConfig::s_angleMin)
- );
-
- return configMap;
- }
-
- EditorFixedJointComponentMode::EditorFixedJointComponentMode(
- const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType)
- : EditorJointComponentMode(entityComponentIdPair, componentType)
- {
- m_configMap = Configure();
- NextMode();
- }
-
- EditorFixedJointComponentMode::~EditorFixedJointComponentMode()
- {
- if (m_currentSubComponentMode)
- {
- m_currentSubComponentMode.reset();
- }
- }
-
- AZStd::map EditorFixedJointComponentMode::Configure()
- {
- AZStd::map configMap;
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterPosition
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterPosition
- , EditorSubComponentModeType::Vec3)
- );
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterRotation
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterRotation
- , EditorSubComponentModeType::Rotation)
- );
-
- const float exponentBreakage = 1.0f;
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterMaxForce
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterMaxForce
- , EditorSubComponentModeType::Linear
- , exponentBreakage
- , PhysX::EditorJointConfig::s_breakageMax
- , PhysX::EditorJointConfig::s_breakageMin)
- );
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterMaxTorque
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterMaxTorque
- , EditorSubComponentModeType::Linear
- , exponentBreakage
- , PhysX::EditorJointConfig::s_breakageMax
- , PhysX::EditorJointConfig::s_breakageMin)
- );
-
- return configMap;
- }
-
- EditorHingeJointComponentMode::EditorHingeJointComponentMode(
- const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType)
- : EditorJointComponentMode(entityComponentIdPair, componentType)
- {
- m_configMap = Configure();
- NextMode();
- }
-
- EditorHingeJointComponentMode::~EditorHingeJointComponentMode()
- {
- if (m_currentSubComponentMode)
- {
- m_currentSubComponentMode.reset();
- }
- }
-
- AZStd::map EditorHingeJointComponentMode::Configure()
- {
- AZStd::map configMap;
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterPosition
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterPosition
- , EditorSubComponentModeType::Vec3)
- );
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterRotation
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterRotation
- , EditorSubComponentModeType::Rotation)
- );
-
- const float exponentBreakage = 1.0f;
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterMaxForce
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterMaxForce
- , EditorSubComponentModeType::Linear
- , exponentBreakage
- , PhysX::EditorJointConfig::s_breakageMax
- , PhysX::EditorJointConfig::s_breakageMin)
- );
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterMaxTorque
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterMaxTorque
- , EditorSubComponentModeType::Linear
- , exponentBreakage
- , PhysX::EditorJointConfig::s_breakageMax
- , PhysX::EditorJointConfig::s_breakageMin)
- );
-
- const float exponentSpring = 2.0f;
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterDamping
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterDamping
- , EditorSubComponentModeType::Linear
- , exponentSpring
- , PhysX::EditorJointLimitPairConfig::s_springMax
- , PhysX::EditorJointLimitPairConfig::s_springMin)
- );
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterStiffness
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterStiffness
- , EditorSubComponentModeType::Linear
- , exponentSpring
- , PhysX::EditorJointLimitPairConfig::s_springMax
- , PhysX::EditorJointLimitPairConfig::s_springMin)
- );
-
- AZ::Vector3 axis = AZ::Vector3::CreateAxisX(); // PhysX revolute joints uses the x-axis by default
- configMap.emplace(
- EditorJointComponentMode::s_parameterAngularPair
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterAngularPair
- , EditorSubComponentModeType::AnglePair
- , axis
- , PhysX::EditorJointLimitPairConfig::s_angleMax
- , PhysX::EditorJointLimitPairConfig::s_angleMin)
- );
-
- configMap.emplace(
- EditorJointComponentMode::s_parameterSnapPosition
- , EditorSubComponentModeConfig(EditorJointComponentMode::s_parameterSnapPosition
- , EditorSubComponentModeType::SnapPosition)
- );
-
- return configMap;
- }
-} // namespace LmbrCentral
diff --git a/Gems/PhysX/Code/Editor/EditorJointComponentMode.h b/Gems/PhysX/Code/Editor/EditorJointComponentMode.h
deleted file mode 100644
index 023edcc24b..0000000000
--- a/Gems/PhysX/Code/Editor/EditorJointComponentMode.h
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-#pragma once
-
-#include
-#include
-
-#include
-
-namespace PhysX
-{
- enum class EditorSubComponentModeType : AZ::u8
- {
- Linear, /// sub-component mode to modify a single linear value, e.g. a float value.
- AnglePair, /// sub-component mode to modify a pair of float values representing angles.
- AngleCone, /// sub-component mode to modify a constraint's swing limits and local transformation.
- Rotation, /// sub-component mode to modify local transformation.
- SnapPosition, /// sub-component mode to modify local position using a point-and-snap feature in the viewport.
- SnapRotation, /// sub-component mode to modify local rotation using a point-and-snap feature in the viewport.
- Vec3 /// sub-component mode to modify a Vector3 value.
- };
-
- /// Contains configuration of a sub-component mode. Shared by different types of sub-component mode.
- /// Alternative implementation of this struct using AZStd::Variant is pending the development of the rest of the joint types.
- struct EditorSubComponentModeConfig
- {
- EditorSubComponentModeConfig() = default;
-
- EditorSubComponentModeConfig(const AZStd::string& name
- , EditorSubComponentModeType type);
-
- EditorSubComponentModeConfig(const AZStd::string& name
- , EditorSubComponentModeType type
- , float exponent
- , float max
- , float min);
-
- EditorSubComponentModeConfig(const AZStd::string& name
- , EditorSubComponentModeType type
- , const AZ::Vector3& axis
- , float max
- , float min);
-
- EditorSubComponentModeConfig(const AZStd::string& name
- , EditorSubComponentModeType type
- , float max
- , float min);
-
- AZStd::string m_name;
- EditorSubComponentModeType m_type;
- AZ::Vector3 m_axis = AZ::Vector3::CreateAxisX();
- float m_exponent = 1.0f;
- float m_max = FLT_MAX;
- float m_min = -FLT_MAX;
- bool m_selectLeadOnSnap = true; ///< A user may use the snap-to-position component mode to snap the position of a joint to an entity. This flag indicates if the snapped-to entity would be selected as a joint's lead when that happens.
- };
-
- /// Generic component mode that supports multiple sub-component modes.
- class EditorJointComponentMode
- : public AzToolsFramework::ComponentModeFramework::EditorBaseComponentMode
- {
- public:
- static const AZStd::string s_parameterAngularPair;
- static const AZStd::string s_parameterDamping;
- static const AZStd::string s_parameterMaxForce;
- static const AZStd::string s_parameterMaxTorque;
- static const AZStd::string s_parameterPosition;
- static const AZStd::string s_parameterRotation;
- static const AZStd::string s_parameterSnapPosition;
- static const AZStd::string s_parameterSnapRotation;
- static const AZStd::string s_parameterStiffness;
- static const AZStd::string s_parameterSwingLimit;
- static const AZStd::string s_parameterTolerance;
- static const AZStd::string s_parameterTransform;
- static const AZStd::string s_parameterComponentMode;
- static const AZStd::string s_parameterLeadEntity;
- static const AZStd::string s_parameterSelectOnSnap;
-
- EditorJointComponentMode(
- const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType);
- ~EditorJointComponentMode();
-
- // EditorBaseComponentMode
- void Refresh() override;
-
- /// Returns map of sub-component mode configurations required by this component mode.
- virtual AZStd::map Configure() = 0;
-
- protected:
- /// AzToolsFramework::ViewportInteraction::MouseViewportRequests
- bool HandleMouseInteraction(
- const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
-
- /// EditorBaseComponentMode
- AZStd::vector PopulateActionsImpl() override;
-
- /// Changes to the next sub-component mode found in m_configMap.
- void NextMode();
-
- /// Changes to the previous sub-component mode found in m_configMap.
- void PreviousMode();
-
- /// Changes to the next or previous sub-component mode found in m_configMap.
- void ChangeMode(bool forwardChange);
-
- /// Replaces m_currentSubComponentMode with a new one instantiated using the configuration identified by the input subComponentModeName.
- void SetCurrentSubComponentMode(const AZStd::string& subComponentModeName);
-
- AZStd::shared_ptr m_currentSubComponentMode = nullptr; ///< The active sub-component mode in this component mode.
- AZ::Uuid m_componentType = AZ::Uuid::CreateNull();
- AZStd::map m_configMap; ///< Contains sub-component mode configurations supported by this component mode.
- AZ::EntityComponentIdPair m_entityComponentIdPair;
-
- private:
- bool IsSubComponentModeUsed(const AZStd::string& subComponentModeName);
-
- void SetSubComponentModeAngleCone(const EditorSubComponentModeConfig& config);
- void SetSubComponentModeAnglePair(const EditorSubComponentModeConfig& config);
- void SetSubComponentModeLinear(const EditorSubComponentModeConfig& config);
- void SetSubComponentModeVec3(const EditorSubComponentModeConfig& config);
- void SetSubComponentModeRotation(const EditorSubComponentModeConfig& config);
- void SetSubComponentModeSnapPosition(const EditorSubComponentModeConfig& config);
- void SetSubComponentModeSnapRotation(const EditorSubComponentModeConfig& config);
- };
-
- /// Ball joint specific component mode. Configure() is overriden to set up the required sub-component modes.
- class EditorBallJointComponentMode
- : public EditorJointComponentMode
- {
- public:
- EditorBallJointComponentMode(
- const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType);
- ~EditorBallJointComponentMode();
-
- // EditorJointComponentMode
- AZStd::map Configure() override;
- };
-
- /// Fixed joint specific component mode. Configure() is overriden to set up the required sub-component modes.
- class EditorFixedJointComponentMode
- : public EditorJointComponentMode
- {
- public:
- EditorFixedJointComponentMode(
- const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType);
- ~EditorFixedJointComponentMode();
-
- // EditorJointComponentMode
- AZStd::map Configure() override;
- };
-
- /// Hinge joint specific component mode. Configure() is overriden to set up the required sub-component modes.
- class EditorHingeJointComponentMode
- : public EditorJointComponentMode
- {
- public:
- EditorHingeJointComponentMode(
- const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Uuid& componentType);
- ~EditorHingeJointComponentMode();
-
- // EditorJointComponentMode
- AZStd::map Configure() override;
- };
-
- using ConfigMap = AZStd::map;
- using ConfigMapIter = ConfigMap::iterator;
- using ConfigMapReverseIter = ConfigMap::reverse_iterator;
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorJointTypeDrawer.cpp b/Gems/PhysX/Code/Editor/EditorJointTypeDrawer.cpp
deleted file mode 100644
index 53b27f6cde..0000000000
--- a/Gems/PhysX/Code/Editor/EditorJointTypeDrawer.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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
-#include
-
-namespace PhysX
-{
- EditorJointTypeDrawer::EditorJointTypeDrawer(EditorJointType jointType,
- AzFramework::EntityContextId entityContextId,
- const AZStd::string& subComponentModeName):
- m_subComponentModeName(subComponentModeName)
- {
- AzFramework::ViewportDebugDisplayEventBus::Handler::BusConnect(entityContextId);
- EditorJointTypeDrawerBus::Handler::BusConnect(EditorJointTypeDrawerId(jointType,
- EditorSubComponentModeNameCrc(subComponentModeName)));
- }
-
- EditorJointTypeDrawer::~EditorJointTypeDrawer()
- {
- EditorJointTypeDrawerBus::Handler::BusDisconnect();
- AzFramework::ViewportDebugDisplayEventBus::Handler::BusDisconnect();
- }
-
- void EditorJointTypeDrawer::DisplayViewport2d(
- const AzFramework::ViewportInfo& viewportInfo,
- AzFramework::DebugDisplayRequests& debugDisplay)
- {
- const AZ::u32 stateBefore = debugDisplay.GetState();
-
- const AzFramework::CameraState cameraState = AzToolsFramework::GetCameraState(viewportInfo.m_viewportId);
-
- const float xOffsetCurrentMode = 125.0f;
- const float yOffsetCurrentMode = 55.0f;
-
- const float xOffsetHotKeys = 125.0f;
- const float yOffsetHotKeys = 30.0f;
-
- const float viewportWidthHalf = cameraState.m_viewportSize.GetX() / 2.0f;
- const float viewportHeight = cameraState.m_viewportSize.GetY();
-
- debugDisplay.SetColor(AZ::Color(1.0f, 1.0f, 1.0f, 1.0f));
-
- AZStd::string screenTextCurrentMode = "Edit mode: " + m_subComponentModeName;
- float xPos = viewportWidthHalf - xOffsetCurrentMode;
- float yPos = viewportHeight - yOffsetCurrentMode;
- float textSize = 2.0f;
- debugDisplay.Draw2dTextLabel(xPos, yPos, textSize, screenTextCurrentMode.c_str());
-
- AZStd::string screenTextHotKeys = " or to change modes";
- xPos = viewportWidthHalf - xOffsetHotKeys;
- yPos = viewportHeight - yOffsetHotKeys;
- textSize = 1.2f;
- debugDisplay.Draw2dTextLabel(xPos, yPos, textSize, screenTextHotKeys.c_str());
-
- debugDisplay.SetState(stateBefore);
- }
-
- AZStd::shared_ptr EditorJointTypeDrawer::GetEditorJointTypeDrawer()
- {
- return shared_from_this();
- }
-
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorJointTypeDrawer.h b/Gems/PhysX/Code/Editor/EditorJointTypeDrawer.h
deleted file mode 100644
index 4172424f00..0000000000
--- a/Gems/PhysX/Code/Editor/EditorJointTypeDrawer.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-#pragma once
-
-#include
-#include
-#include
-
-namespace PhysX
-{
- /// This class enables drawing in the viewport once for the component modes of multiple components in one entity.
- /// Until the component mode framework allows a way to do this, a work-around like this class is necessary.
- /// An instance of this class is created for each pair of component type and sub-component mode.
- class EditorJointTypeDrawer
- : public EditorJointTypeDrawerBus::Handler
- , public AZStd::enable_shared_from_this
- , private AzFramework::ViewportDebugDisplayEventBus::Handler
- {
- public:
- EditorJointTypeDrawer(EditorJointType id,
- AzFramework::EntityContextId entityContextId,
- const AZStd::string& subComponentModeName);
- ~EditorJointTypeDrawer();
-
- private:
- // AzFramework::ViewportDebugDisplayEventBus
- void DisplayViewport2d(
- const AzFramework::ViewportInfo& viewportInfo,
- AzFramework::DebugDisplayRequests& debugDisplay) override;
-
- // PhysX::EditorJointTypeDrawerBus
- AZStd::shared_ptr GetEditorJointTypeDrawer() override;
-
- AZStd::string m_subComponentModeName;///< Name of the sub component mode. E.g. Position, Rotation, Snap Position, etc.
- };
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorJointTypeDrawerBus.h b/Gems/PhysX/Code/Editor/EditorJointTypeDrawerBus.h
deleted file mode 100644
index e47c447fe2..0000000000
--- a/Gems/PhysX/Code/Editor/EditorJointTypeDrawerBus.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-#pragma once
-
-#include
-
-namespace PhysX
-{
- class EditorJointTypeDrawer;
-
- using EditorJointType = AZ::Uuid;
- using EditorSubComponentModeNameCrc = AZ::Crc32;
- using EditorJointTypeDrawerId = AZStd::pair;
-
- /// The sub-component mode of a component type uses this bus (by invoking GetEditorJointTypeDrawer) to retrieve a drawer.
- /// If nothing is returned, it creates an instance of the drawer that will be shared by other instances of the same component type.
- class EditorJointTypeDrawerRequests : public AZ::EBusTraits
- {
- public:
- static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
- using BusIdType = EditorJointTypeDrawerId;
-
- virtual AZStd::shared_ptr GetEditorJointTypeDrawer() = 0;
- };
- using EditorJointTypeDrawerBus = AZ::EBus;
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeAngleCone.cpp b/Gems/PhysX/Code/Editor/EditorSubComponentModeAngleCone.cpp
deleted file mode 100644
index 43b9fd77f3..0000000000
--- a/Gems/PhysX/Code/Editor/EditorSubComponentModeAngleCone.cpp
+++ /dev/null
@@ -1,453 +0,0 @@
-
-/*
- * 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
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-namespace
-{
- const float ArrowLength = 2.0f;
- const float ConeHeight = 3.0f;
- const float XRotationManipulatorRadius = 2.0f;
- const float XRotationManipulatorWidth = 0.05f;
-}
-
-namespace PhysX
-{
- struct SharedRotationState
- {
- AZ::Vector3 m_axis;
- AZ::Quaternion m_savedOrientation = AZ::Quaternion::CreateIdentity();
- AngleLimitsFloatPair m_valuePair;
- };
-
- EditorSubComponentModeAngleCone::EditorSubComponentModeAngleCone(
- const AZ::EntityComponentIdPair& entityComponentIdPair
- , const AZ::Uuid& componentType
- , const AZStd::string& name
- , float max
- , float min)
- : EditorSubComponentModeBase(entityComponentIdPair, componentType, name)
- , m_max(max)
- , m_min(min)
- {
- AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId());
-
- AZ::Transform localTransform = AZ::Transform::CreateIdentity();
- EditorJointRequestBus::EventResult(
- localTransform, m_entityComponentId
- , &EditorJointRequests::GetTransformValue
- , PhysX::EditorJointComponentMode::s_parameterTransform);
- const AZ::Quaternion localRotation = localTransform.GetRotation();
-
- // Initialize manipulators used to resize the base of the cone.
- m_yLinearManipulator = AzToolsFramework::LinearManipulator::MakeShared(worldTransform);
- m_yLinearManipulator->AddEntityComponentIdPair(m_entityComponentId);
- m_yLinearManipulator->SetAxis(AZ::Vector3::CreateAxisZ());
-
- m_zLinearManipulator = AzToolsFramework::LinearManipulator::MakeShared(worldTransform);
- m_zLinearManipulator->AddEntityComponentIdPair(m_entityComponentId);
- m_zLinearManipulator->SetAxis(AZ::Vector3::CreateAxisY());
-
- m_yzPlanarManipulator = AzToolsFramework::PlanarManipulator::MakeShared(worldTransform);
- m_yzPlanarManipulator->AddEntityComponentIdPair(m_entityComponentId);
- m_yzPlanarManipulator->SetAxes(AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ());
-
- ConfigureLinearView(ArrowLength
- , AZ::Color(1.0f, 0.0f, 0.0f, 1.0f)
- , AZ::Color(0.0f, 1.0f, 0.0f, 1.0f)
- , AZ::Color(0.0f, 0.0f, 1.0f, 1.0f));
-
- ConfigurePlanarView(AZ::Color(0.0f, 1.0f, 0.0f, 1.0f)
- , AZ::Color(0.0f, 0.0f, 1.0f, 1.0f));
-
- // Position and orientate manipulators
- AZ::Transform displacementTransform = localTransform;
- AZ::Vector3 displacementTranslate = localRotation.TransformVector(AZ::Vector3(ConeHeight, 0.0f, 0.0f));
- displacementTransform.SetTranslation(localTransform.GetTranslation() + displacementTranslate);
-
- m_yLinearManipulator->SetLocalTransform(displacementTransform);
- m_zLinearManipulator->SetLocalTransform(displacementTransform);
- m_yzPlanarManipulator->SetLocalTransform(displacementTransform);
-
- // Initialize rotation manipulator for rotating cone
- m_xRotationManipulator = AzToolsFramework::AngularManipulator::MakeShared(worldTransform);
- m_xRotationManipulator->AddEntityComponentIdPair(m_entityComponentId);
- m_xRotationManipulator->SetAxis(AZ::Vector3::CreateAxisX());
- m_xRotationManipulator->SetLocalTransform(localTransform);
-
- const AZ::Color xRotationManipulatorColor = AZ::Color(1.0f, 0.0f, 0.0f, 1.0f);
- m_xRotationManipulator->SetView(AzToolsFramework::CreateManipulatorViewCircle(
- *m_xRotationManipulator, xRotationManipulatorColor,
- XRotationManipulatorRadius, XRotationManipulatorWidth, AzToolsFramework::DrawHalfDottedCircle));
-
- AZStd::shared_ptr sharedRotationState =
- AZStd::make_shared();
-
- struct SharedState
- {
- AngleLimitsFloatPair m_startValues;
- };
- auto sharedState = AZStd::make_shared();
-
- m_yLinearManipulator->InstallLeftMouseDownCallback(
- [this, sharedState](const AzToolsFramework::LinearManipulator::Action& /*action*/) mutable
- {
- AngleLimitsFloatPair currentValue;
- EditorJointRequestBus::EventResult(
- currentValue, m_entityComponentId
- , &EditorJointRequests::GetLinearValuePair
- , m_name);
- sharedState->m_startValues = currentValue;
- });
-
- m_yLinearManipulator->InstallMouseMoveCallback(
- [this, sharedState](const AzToolsFramework::LinearManipulator::Action& action)
- {
- AZ::Transform localTransform = AZ::Transform::CreateIdentity();
- EditorJointRequestBus::EventResult(
- localTransform, m_entityComponentId
- , &EditorJointRequests::GetTransformValue
- , PhysX::EditorJointComponentMode::s_parameterTransform);
- const AZ::Quaternion localRotation = localTransform.GetRotation();
- const float axisDisplacement = action.LocalPositionOffset().Dot(localRotation.TransformVector(action.m_fixed.m_axis));
- const float originalBaseY = tan(AZ::DegToRad(sharedState->m_startValues.first)) * ConeHeight;
- const float newBaseY = originalBaseY + axisDisplacement;
- const float newAngle = AZ::GetClamp(AZ::RadToDeg(atan(newBaseY / ConeHeight)), m_min, m_max);
-
- EditorJointRequestBus::Event(
- m_entityComponentId
- , &EditorJointRequests::SetLinearValuePair
- , m_name
- , AngleLimitsFloatPair(newAngle, sharedState->m_startValues.second));
-
- m_yLinearManipulator->SetBoundsDirty();
- });
-
- m_zLinearManipulator->InstallLeftMouseDownCallback(
- [this, sharedState](const AzToolsFramework::LinearManipulator::Action& /*action*/) mutable
- {
- AngleLimitsFloatPair currentValue;
- EditorJointRequestBus::EventResult(
- currentValue, m_entityComponentId
- , &EditorJointRequests::GetLinearValuePair
- , m_name);
- sharedState->m_startValues = currentValue;
- });
-
- m_zLinearManipulator->InstallMouseMoveCallback(
- [this, sharedState](const AzToolsFramework::LinearManipulator::Action& action)
- {
- AZ::Transform localTransform = AZ::Transform::CreateIdentity();
- EditorJointRequestBus::EventResult(
- localTransform, m_entityComponentId
- , &EditorJointRequests::GetTransformValue
- , PhysX::EditorJointComponentMode::s_parameterTransform);
- const AZ::Quaternion localRotation = localTransform.GetRotation();
- const float axisDisplacement = action.LocalPositionOffset().Dot(localRotation.TransformVector(action.m_fixed.m_axis));
- const float originalBaseZ = tan(AZ::DegToRad(sharedState->m_startValues.second)) * ConeHeight;
- const float newBaseZ = originalBaseZ + axisDisplacement;
- const float newAngle = AZ::GetClamp(AZ::RadToDeg(atan(newBaseZ / ConeHeight)), m_min, m_max);
-
- EditorJointRequestBus::Event(
- m_entityComponentId
- , &EditorJointRequests::SetLinearValuePair
- , m_name
- , AngleLimitsFloatPair(sharedState->m_startValues.first, newAngle));
-
- m_zLinearManipulator->SetBoundsDirty();
- });
-
- m_yzPlanarManipulator->InstallLeftMouseDownCallback(
- [this, sharedState](const AzToolsFramework::PlanarManipulator::Action& /*action*/) mutable
- {
- AngleLimitsFloatPair currentValue;
- EditorJointRequestBus::EventResult(
- currentValue, m_entityComponentId
- , &EditorJointRequests::GetLinearValuePair
- , m_name);
- sharedState->m_startValues = currentValue;
- });
-
- m_yzPlanarManipulator->InstallMouseMoveCallback(
- [this, sharedState](const AzToolsFramework::PlanarManipulator::Action& action)
- {
- AZ::Transform localTransform = AZ::Transform::CreateIdentity();
- EditorJointRequestBus::EventResult(
- localTransform, m_entityComponentId
- , &EditorJointRequests::GetTransformValue
- , PhysX::EditorJointComponentMode::s_parameterTransform);
-
- const AZ::Quaternion localRotation = localTransform.GetRotation();
-
- const float axisDisplacementY = action.LocalPositionOffset().Dot(localRotation.TransformVector(AZ::Vector3::CreateAxisY()));
- const float axisDisplacementZ = action.LocalPositionOffset().Dot(localRotation.TransformVector(AZ::Vector3::CreateAxisZ()));
- const float axisDisplacement = axisDisplacementZ > axisDisplacementY? axisDisplacementZ : axisDisplacementY;
-
- const float originalBaseY = tan(AZ::DegToRad(sharedState->m_startValues.first)) * ConeHeight;
- const float newBaseY = originalBaseY + axisDisplacement;
- const float newAngleY = AZ::GetClamp(AZ::RadToDeg(atan(newBaseY / ConeHeight)), m_min, m_max);
-
- const float originalBaseZ = tan(AZ::DegToRad(sharedState->m_startValues.second)) * ConeHeight;
- const float newBaseZ = originalBaseZ + axisDisplacement;
- const float newAngleZ = AZ::GetClamp(AZ::RadToDeg(atan(newBaseZ / ConeHeight)), m_min, m_max);
-
- EditorJointRequestBus::Event(
- m_entityComponentId
- , &EditorJointRequests::SetLinearValuePair
- , m_name
- , AngleLimitsFloatPair(newAngleY, newAngleZ));
-
- m_yzPlanarManipulator->SetBoundsDirty();
- });
-
- struct SharedStateXRotate
- {
- AZ::Transform m_startTM;
- };
- auto sharedStateXRotate = AZStd::make_shared();
-
- auto mouseDownCallback = [this, sharedRotationState](const AzToolsFramework::AngularManipulator::Action& action) mutable -> void
- {
- AZ::Quaternion normalizedStart = action.m_start.m_rotation.GetNormalized();
- sharedRotationState->m_axis = AZ::Vector3(normalizedStart.GetX(), normalizedStart.GetY(), normalizedStart.GetZ());
- sharedRotationState->m_savedOrientation = AZ::Quaternion::CreateIdentity();
-
- AngleLimitsFloatPair currentValue;
- EditorJointRequestBus::EventResult(
- currentValue, m_entityComponentId
- , &EditorJointRequests::GetLinearValuePair
- , m_name);
-
- sharedRotationState->m_valuePair = currentValue;
- };
-
- auto mouseDownRotateXCallback = [this, sharedStateXRotate]([[maybe_unused]] const AzToolsFramework::AngularManipulator::Action& action) mutable -> void
- {
- PhysX::EditorJointRequestBus::EventResult(sharedStateXRotate->m_startTM
- , m_entityComponentId
- , &PhysX::EditorJointRequests::GetTransformValue
- , PhysX::EditorJointComponentMode::s_parameterTransform);
- };
-
- m_xRotationManipulator->InstallLeftMouseDownCallback(mouseDownRotateXCallback);
-
- m_xRotationManipulator->InstallMouseMoveCallback(
- [this, sharedStateXRotate]
- (const AzToolsFramework::AngularManipulator::Action& action) mutable -> void
- {
- const AZ::Quaternion manipulatorOrientation = action.m_start.m_rotation * action.m_current.m_delta;
-
- AZ::Transform newTransform = AZ::Transform::CreateIdentity();
- newTransform = sharedStateXRotate->m_startTM * AZ::Transform::CreateFromQuaternion(action.m_current.m_delta);
-
- PhysX::EditorJointRequestBus::Event(m_entityComponentId
- , &PhysX::EditorJointRequests::SetVector3Value
- , PhysX::EditorJointComponentMode::s_parameterPosition
- , newTransform.GetTranslation());
- PhysX::EditorJointRequestBus::Event(m_entityComponentId
- , &PhysX::EditorJointRequests::SetVector3Value
- , PhysX::EditorJointComponentMode::s_parameterRotation
- , newTransform.GetRotation().GetEulerDegrees());
-
- m_yLinearManipulator->SetLocalOrientation(manipulatorOrientation);
- m_zLinearManipulator->SetLocalOrientation(manipulatorOrientation);
- m_yLinearManipulator->SetAxis(action.m_current.m_delta.TransformVector(AZ::Vector3::CreateAxisY()));
- m_zLinearManipulator->SetAxis(action.m_current.m_delta.TransformVector(AZ::Vector3::CreateAxisZ()));
- m_xRotationManipulator->SetLocalOrientation(manipulatorOrientation);
-
- m_yLinearManipulator->SetBoundsDirty();
- m_zLinearManipulator->SetBoundsDirty();
- m_xRotationManipulator->SetBoundsDirty();
- });
-
- m_xRotationManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
- m_yLinearManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
- m_zLinearManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
- m_yzPlanarManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
-
- AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(m_entityComponentId.GetEntityId());
-
- Refresh();
- }
-
- EditorSubComponentModeAngleCone::~EditorSubComponentModeAngleCone()
- {
- AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
-
- m_xRotationManipulator->Unregister();
- m_yLinearManipulator->Unregister();
- m_zLinearManipulator->Unregister();
- m_yzPlanarManipulator->Unregister();
- }
-
- void EditorSubComponentModeAngleCone::Refresh()
- {
- AZ::Transform localTransform = AZ::Transform::CreateIdentity();
- EditorJointRequestBus::EventResult(
- localTransform, m_entityComponentId
- , &EditorJointRequests::GetTransformValue
- , PhysX::EditorJointComponentMode::s_parameterTransform);
-
- float coneHeight = ConeHeight;
- AngleLimitsFloatPair yzSwingAngleLimits;
- EditorJointRequestBus::EventResult(
- yzSwingAngleLimits, m_entityComponentId
- , &EditorJointRequests::GetLinearValuePair
- , m_name);
-
- // Draw inverted cone (negative cone height) if angles are larger than 90 deg.
- if (yzSwingAngleLimits.first > 90.0f || yzSwingAngleLimits.second > 90.0f)
- {
- coneHeight = -ConeHeight;
- }
-
- // reposition manipulators
- const AZ::Quaternion localRotation = localTransform.GetRotation();
- const AZ::Vector3 linearManipulatorOffset = localTransform.GetTranslation() + localRotation.TransformVector(AZ::Vector3(coneHeight, 0.0f, 0.0f));
-
- m_xRotationManipulator->SetLocalTransform(localTransform);
- m_xRotationManipulator->SetBoundsDirty();
-
- localTransform.SetTranslation(linearManipulatorOffset);
-
- m_yLinearManipulator->SetLocalTransform(localTransform);
- m_zLinearManipulator->SetLocalTransform(localTransform);
- m_yzPlanarManipulator->SetLocalTransform(localTransform);
- m_yLinearManipulator->SetBoundsDirty();
- m_zLinearManipulator->SetBoundsDirty();
- m_yzPlanarManipulator->SetBoundsDirty();
- }
-
- void EditorSubComponentModeAngleCone::ConfigureLinearView(
- float axisLength, [[maybe_unused]] const AZ::Color& axis1Color, const AZ::Color& axis2Color,
- const AZ::Color& axis3Color)
- {
- const float coneLength = 0.28f;
- const float coneRadius = 0.07f;
-
- const auto configureLinearView = [coneLength, axisLength, coneRadius](
- AzToolsFramework::LinearManipulator* linearManipulator, const AZ::Color& color)
- {
- AzToolsFramework::ManipulatorViews views;
- views.emplace_back(CreateManipulatorViewLine(
- *linearManipulator, color, axisLength, AzToolsFramework::ManipulatorLineBoundWidth()));
- views.emplace_back(CreateManipulatorViewCone(
- *linearManipulator, color, linearManipulator->GetAxis() * (axisLength - coneLength),
- coneLength, coneRadius));
- linearManipulator->SetViews(AZStd::move(views));
- };
-
- configureLinearView(m_yLinearManipulator.get(), axis2Color);
- configureLinearView(m_zLinearManipulator.get(), axis3Color);
- }
-
- void EditorSubComponentModeAngleCone::ConfigurePlanarView(const AZ::Color& planeColor,
- const AZ::Color& plane2Color)
- {
- const float planeSize = 0.6f;
- AzToolsFramework::ManipulatorViews views;
- views.emplace_back(CreateManipulatorViewQuad(
- *m_yzPlanarManipulator
- , planeColor
- , plane2Color
- , planeSize));
- m_yzPlanarManipulator->SetViews(AZStd::move(views));
- }
-
- void EditorSubComponentModeAngleCone::DisplayEntityViewport(
- [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo,
- AzFramework::DebugDisplayRequests& debugDisplay)
- {
- AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId());
-
- AZ::Transform localTransform = AZ::Transform::CreateIdentity();
- EditorJointRequestBus::EventResult(
- localTransform, m_entityComponentId
- , &EditorJointRequests::GetTransformValue
- , PhysX::EditorJointComponentMode::s_parameterTransform);
-
- AZ::u32 stateBefore = debugDisplay.GetState();
- debugDisplay.CullOff();
-
- debugDisplay.PushMatrix(worldTransform);
- debugDisplay.PushMatrix(localTransform);
-
- const float xAxisArrowLength = 2.0f;
- debugDisplay.SetColor(AZ::Color(1.0f, 0.0f, 0.0f, 1.0f));
- debugDisplay.DrawArrow(AZ::Vector3(0.0f, 0.0f, 0.0f), AZ::Vector3(xAxisArrowLength, 0.0f, 0.0f));
-
- AngleLimitsFloatPair yzSwingAngleLimits;
- EditorJointRequestBus::EventResult(
- yzSwingAngleLimits, m_entityComponentId
- , &EditorJointRequests::GetLinearValuePair
- , m_name);
-
- const AZ::u32 numEllipseSamples = 16;
- AZ::Vector3 ellipseSamples[numEllipseSamples];
- float coneHeight = ConeHeight;
-
- // Draw inverted cone if angles are larger than 90 deg.
- if (yzSwingAngleLimits.first > 90.0f || yzSwingAngleLimits.second > 90.0f)
- {
- coneHeight = -ConeHeight;
- }
-
- // Compute points along perimeter of cone base
- const float coney = tanf(AZ::DegToRad(yzSwingAngleLimits.first)) * coneHeight;
- const float conez = tanf(AZ::DegToRad(yzSwingAngleLimits.second)) * coneHeight;
- const float step = AZ::Constants::TwoPi / numEllipseSamples;
- for (size_t i = 0; i < numEllipseSamples; ++i)
- {
- const float angleStep = step * i;
- ellipseSamples[i].SetX(coneHeight);
- ellipseSamples[i].SetY(conez * sin(angleStep));
- ellipseSamples[i].SetZ(coney * cos(angleStep));
- }
-
- // draw cone
- for (size_t i = 0; i < numEllipseSamples; ++i)
- {
- size_t nextIndex = i + 1;
- if (i == numEllipseSamples - 1)
- {
- nextIndex = 0;
- }
-
- // draw cone sides
- debugDisplay.SetColor(AZ::Color(1.0f, 1.0f, 1.0f, 0.2f));
- debugDisplay.DrawTri(AZ::Vector3(0.0f, 0.0f, 0.0f), ellipseSamples[i], ellipseSamples[nextIndex]);
-
- // draw parameter of cone base
- debugDisplay.SetColor(AZ::Color(0.4f, 0.4f, 0.4f, 0.4f));
- debugDisplay.DrawLine(ellipseSamples[i], ellipseSamples[nextIndex]);
- }
-
- // draw axis lines at base of cone, and from tip to base.
- debugDisplay.SetColor(AZ::Color(0.5f, 0.5f, 0.5f, 0.6f));
- debugDisplay.DrawLine(ellipseSamples[0], ellipseSamples[numEllipseSamples/2]);
- debugDisplay.DrawLine(ellipseSamples[numEllipseSamples*3/4], ellipseSamples[numEllipseSamples/4]);
- debugDisplay.DrawLine(AZ::Vector3(0.0f, 0.0f, 0.0f), AZ::Vector3(coneHeight, 0.0f, 0.0f));
-
- debugDisplay.PopMatrix();//pop local transform
- debugDisplay.PopMatrix();//pop world transform
- debugDisplay.SetState(stateBefore);
-
- // reposition and reorientate manipulators
- Refresh();
- }
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeAngleCone.h b/Gems/PhysX/Code/Editor/EditorSubComponentModeAngleCone.h
deleted file mode 100644
index bf113b4be1..0000000000
--- a/Gems/PhysX/Code/Editor/EditorSubComponentModeAngleCone.h
+++ /dev/null
@@ -1,63 +0,0 @@
-
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-#pragma once
-
-#include
-#include
-#include
-#include
-
-namespace AzToolsFramework
-{
- class AngularManipulator;
- class LinearManipulator;
- class PlanarManipulator;
-}
-
-namespace PhysX
-{
- class EditorSubComponentModeAngleCone
- : public PhysX::EditorSubComponentModeBase
- , private AzFramework::EntityDebugDisplayEventBus::Handler
- {
- public:
- EditorSubComponentModeAngleCone(
- const AZ::EntityComponentIdPair& entityComponentIdPair
- , const AZ::Uuid& componentType
- , const AZStd::string& name
- , float max
- , float min);
- ~EditorSubComponentModeAngleCone();
-
- // PhysX::EditorSubComponentModeBase
- void Refresh() override;
-
- private:
- // AzFramework::EntityDebugDisplayEventBus
- void DisplayEntityViewport(
- const AzFramework::ViewportInfo& viewportInfo,
- AzFramework::DebugDisplayRequests& debugDisplay) override;
-
- void ConfigureLinearView(
- float axisLength,
- const AZ::Color& axis1Color, const AZ::Color& axis2Color,
- const AZ::Color& axis3Color = AZ::Color(0.0f, 0.0f, 1.0f, 0.5f));
-
- void ConfigurePlanarView(const AZ::Color& planeColor = AZ::Color(0.0f, 1.0f, 0.0f, 0.5f)
- , const AZ::Color& plane2Color = AZ::Color(0.0f, 0.0f, 1.0f, 0.5f));
-
- AZStd::shared_ptr m_xRotationManipulator;
- AZStd::shared_ptr m_yLinearManipulator;
- AZStd::shared_ptr m_zLinearManipulator;
- AZStd::shared_ptr m_yzPlanarManipulator;
-
- float m_max = FLT_MAX;
- float m_min = 0.0f;
- };
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeAnglePair.cpp b/Gems/PhysX/Code/Editor/EditorSubComponentModeAnglePair.cpp
deleted file mode 100644
index 6fa74a3f05..0000000000
--- a/Gems/PhysX/Code/Editor/EditorSubComponentModeAnglePair.cpp
+++ /dev/null
@@ -1,318 +0,0 @@
-
-/*
- * 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
-#include
-#include
-
-#include
-#include
-#include
-
-namespace
-{
- const float Alpha = 0.6f;
- const AZ::Color ColorDefault = AZ::Color(1.0f, 1.0f, 1.0f, Alpha);
- const AZ::Color ColorFirst = AZ::Color(1.0f, 0.0f, 0.0f, Alpha);
- const AZ::Color ColorSecond = AZ::Color(0.0f, 1.0f, 0.0f, Alpha);
- const AZ::Color ColorSweepArc = AZ::Color(1.0f, 1.0f, 1.0f, Alpha);
-
- const float SweepLineDisplaceFactor = 0.5f;
- const float SweepLineThickness = 1.0f;
- const float SweepLineGranularity = 1.0f;
-}
-
-namespace PhysX
-{
- EditorSubComponentModeAnglePair::EditorSubComponentModeAnglePair(
- const AZ::EntityComponentIdPair& entityComponentIdPair
- , const AZ::Uuid& componentType
- , const AZStd::string& name
- , const AZ::Vector3& axis
- , float firstMax
- , float firstMin
- , float secondMax
- , float secondMin)
- : EditorSubComponentModeBase(entityComponentIdPair, componentType, name)
- , m_axis(axis)
- , m_firstMax(firstMax)
- , m_firstMin(firstMin)
- , m_secondMax(secondMax)
- , m_secondMin(secondMin)
- {
- AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId());
-
- AZ::Transform localTransform = AZ::Transform::CreateIdentity();
- EditorJointRequestBus::EventResult(
- localTransform, m_entityComponentId
- , &EditorJointRequests::GetTransformValue
- , PhysX::EditorJointComponentMode::s_parameterTransform);
- const AZ::Quaternion localRotation = localTransform.GetRotation();
-
- AZ::Vector3 displacement = m_axis;
- AZ::Transform displacementTransform = localTransform;
- AZ::Vector3 displacementTranslate = localRotation.TransformVector(displacement);
- displacementTransform.SetTranslation(localTransform.GetTranslation() + displacementTranslate);
-
- m_firstManipulator = AzToolsFramework::AngularManipulator::MakeShared(worldTransform);
- m_firstManipulator->AddEntityComponentIdPair(m_entityComponentId);
- m_firstManipulator->SetAxis(m_axis);
- m_firstManipulator->SetLocalTransform(displacementTransform);
-
- displacement = -m_axis;
- displacementTranslate = localRotation.TransformVector(displacement);
- displacementTransform.SetTranslation(localTransform.GetTranslation() + displacementTranslate);
- m_secondManipulator = AzToolsFramework::AngularManipulator::MakeShared(worldTransform);
- m_secondManipulator->AddEntityComponentIdPair(m_entityComponentId);
- m_secondManipulator->SetAxis(m_axis);
- m_secondManipulator->SetLocalTransform(displacementTransform);
-
- const float manipulatorRadius = 2.0f;
- const float manipulatorWidth = 0.05f;
- m_firstManipulator->SetView(AzToolsFramework::CreateManipulatorViewCircle(
- *m_firstManipulator, ColorFirst,
- manipulatorRadius, manipulatorWidth, AzToolsFramework::DrawHalfDottedCircle));
-
- m_secondManipulator->SetView(AzToolsFramework::CreateManipulatorViewCircle(
- *m_secondManipulator, ColorSecond,
- manipulatorRadius, manipulatorWidth, AzToolsFramework::DrawHalfDottedCircle));
-
- Refresh();
-
- AZStd::shared_ptr sharedRotationState =
- AZStd::make_shared();
-
- auto mouseDownCallback = [this, sharedRotationState](const AzToolsFramework::AngularManipulator::Action& action) mutable -> void
- {
- const AZ::Quaternion normalizedStart = action.m_start.m_rotation.GetNormalized();
- sharedRotationState->m_axis = AZ::Vector3(normalizedStart.GetX(), normalizedStart.GetY(), normalizedStart.GetZ());
- sharedRotationState->m_savedOrientation = AZ::Quaternion::CreateIdentity();
-
- AngleLimitsFloatPair currentValue;
- EditorJointRequestBus::EventResult(
- currentValue, m_entityComponentId
- , &EditorJointRequests::GetLinearValuePair
- , m_name);
-
- sharedRotationState->m_valuePair = currentValue;
- };
-
- m_firstManipulator->InstallLeftMouseDownCallback(mouseDownCallback);
-
- m_secondManipulator->InstallLeftMouseDownCallback(mouseDownCallback);
-
- m_firstManipulator->InstallMouseMoveCallback(
- [this, sharedRotationState]
- (const AzToolsFramework::AngularManipulator::Action& action) mutable -> void
- {
- float angleDelta;
- AZ::Quaternion manipulatorOrientation;
- const float newValue = MouseMove(sharedRotationState, action, true, angleDelta, manipulatorOrientation);
- if (newValue > m_firstMax || newValue < m_firstMin)
- {
- return;
- }
- m_firstManipulator->SetLocalOrientation(manipulatorOrientation);
- const float newFirstValue = AZ::GetClamp(sharedRotationState->m_valuePair.first + angleDelta, m_firstMin, m_firstMax);
-
- EditorJointRequestBus::Event(
- m_entityComponentId
- , &EditorJointRequests::SetLinearValuePair
- , m_name
- , AngleLimitsFloatPair(newFirstValue, sharedRotationState->m_valuePair.second));
-
- m_firstManipulator->SetBoundsDirty();
- });
-
- m_secondManipulator->InstallMouseMoveCallback(
- [this, sharedRotationState]
- (const AzToolsFramework::AngularManipulator::Action& action) mutable -> void
- {
- float angleDelta;
- AZ::Quaternion manipulatorOrientation;
- const float newValue = MouseMove(sharedRotationState, action, false, angleDelta, manipulatorOrientation);
- if (newValue > m_secondMax || newValue < m_secondMin)
- {
- return; //Not handling values exceeding limits
- }
-
- m_secondManipulator->SetLocalOrientation(manipulatorOrientation);
- float newSecondValue = AZ::GetClamp(sharedRotationState->m_valuePair.second + angleDelta, m_secondMin, m_secondMax);
-
- EditorJointRequestBus::Event(
- m_entityComponentId
- , &EditorJointRequests::SetLinearValuePair
- , m_name
- , AngleLimitsFloatPair(sharedRotationState->m_valuePair.first, newSecondValue));
-
- m_secondManipulator->SetBoundsDirty();
- });
-
-
- m_firstManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
- m_secondManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
-
- AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(m_entityComponentId.GetEntityId());
- }
-
- EditorSubComponentModeAnglePair::~EditorSubComponentModeAnglePair()
- {
- AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
-
- m_firstManipulator->Unregister();
- m_secondManipulator->Unregister();
- }
-
- void EditorSubComponentModeAnglePair::Refresh()
- {
- AZ::Transform localTransform = AZ::Transform::CreateIdentity();
- EditorJointRequestBus::EventResult(
- localTransform, m_entityComponentId
- , &EditorJointRequests::GetTransformValue
- , PhysX::EditorJointComponentMode::s_parameterTransform);
- const AZ::Quaternion localRotation = localTransform.GetRotation();
-
- AZ::Transform displacementTransform = localTransform;
- AZ::Vector3 displacement = m_axis;
- AZ::Vector3 displacementTranslate = localRotation.TransformVector(displacement);
- displacementTransform.SetTranslation(localTransform.GetTranslation() + displacementTranslate);
- m_firstManipulator->SetLocalTransform(displacementTransform);
-
- displacement = -m_axis;
- displacementTranslate = localRotation.TransformVector(displacement);
- displacementTransform.SetTranslation(localTransform.GetTranslation() + displacementTranslate);
- m_secondManipulator->SetLocalTransform(displacementTransform);
-
- m_firstManipulator->SetBoundsDirty();
- m_secondManipulator->SetBoundsDirty();
- }
-
- void EditorSubComponentModeAnglePair::DisplayEntityViewport(
- [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo,
- AzFramework::DebugDisplayRequests& debugDisplay)
- {
- AngleLimitsFloatPair currentValue;
- EditorJointRequestBus::EventResult(
- currentValue, m_entityComponentId
- , &EditorJointRequests::GetLinearValuePair
- , m_name);
-
- const float size = 2.0f;
- AZ::Vector3 axisPoint = m_axis * size * 0.5f;
-
- AZStd::array points = {
- -axisPoint
- , axisPoint
- , axisPoint
- , -axisPoint
- };
-
- if (abs(m_axis.GetX() - 1.0f) < FLT_EPSILON)
- {
- points[2].SetZ(size);
- points[3].SetZ(size);
- }
- else if (abs(m_axis.GetY() - 1.0f) < FLT_EPSILON)
- {
- points[2].SetX(size);
- points[3].SetX(size);
- }
- else if (abs(m_axis.GetZ() - 1.0f) < FLT_EPSILON)
- {
- points[2].SetX(size);
- points[3].SetX(size);
- }
-
- AZ::u32 stateBefore = debugDisplay.GetState();
- debugDisplay.CullOff();
- debugDisplay.SetAlpha(Alpha);
-
- AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId());
-
- AZ::Transform localTransform = AZ::Transform::CreateIdentity();
- EditorJointRequestBus::EventResult(
- localTransform, m_entityComponentId
- , &EditorJointRequests::GetTransformValue
- , PhysX::EditorJointComponentMode::s_parameterTransform);
-
- debugDisplay.PushMatrix(worldTransform);
- debugDisplay.PushMatrix(localTransform);
-
- debugDisplay.SetColor(ColorSweepArc);
-
- const AZ::Vector3 zeroVector = AZ::Vector3::CreateZero();
- const AZ::Vector3 posPosition = m_axis * SweepLineDisplaceFactor;
- const AZ::Vector3 negPosition = -posPosition;
- debugDisplay.DrawArc(posPosition, SweepLineThickness, -currentValue.first, currentValue.first, SweepLineGranularity, -m_axis);
- debugDisplay.DrawArc(zeroVector, SweepLineThickness, -currentValue.first, currentValue.first, SweepLineGranularity, -m_axis);
- debugDisplay.DrawArc(negPosition, SweepLineThickness, -currentValue.first, currentValue.first, SweepLineGranularity, -m_axis);
- debugDisplay.DrawArc(posPosition, SweepLineThickness, 0.0f, abs(currentValue.second), SweepLineGranularity, -m_axis);
- debugDisplay.DrawArc(zeroVector, SweepLineThickness, 0.0f, abs(currentValue.second), SweepLineGranularity, -m_axis);
- debugDisplay.DrawArc(negPosition, SweepLineThickness, 0.0f, abs(currentValue.second), SweepLineGranularity, -m_axis);
-
- AZ::Quaternion firstRotate = AZ::Quaternion::CreateFromAxisAngle(m_axis, AZ::DegToRad(currentValue.first));
- AZ::Transform firstTM = AZ::Transform::CreateFromQuaternion(firstRotate);
- debugDisplay.PushMatrix(firstTM);
- debugDisplay.SetColor(ColorFirst);
- debugDisplay.DrawQuad(points[0], points[1], points[2], points[3]);
- debugDisplay.PopMatrix();
-
- AZ::Quaternion secondRotate = AZ::Quaternion::CreateFromAxisAngle(m_axis, AZ::DegToRad(currentValue.second));
- AZ::Transform secondTM = AZ::Transform::CreateFromQuaternion(secondRotate);
- debugDisplay.PushMatrix(secondTM);
- debugDisplay.SetColor(ColorSecond);
- debugDisplay.DrawQuad(points[0], points[1], points[2], points[3]);
- debugDisplay.PopMatrix();
-
- debugDisplay.SetColor(ColorDefault);
- debugDisplay.DrawQuad(points[0], points[1], points[2], points[3]);
-
- debugDisplay.PopMatrix(); // pop local transform
- debugDisplay.PopMatrix(); // pop global transform
- debugDisplay.SetState(stateBefore);
-
- // reposition and reorientate manipulators
- Refresh();
- }
-
- float EditorSubComponentModeAnglePair::MouseMove(AZStd::shared_ptr& sharedRotationState
- , const AzToolsFramework::AngularManipulator::Action& action
- , bool isFirstValue
- , float& angleDelta
- , AZ::Quaternion& manipulatorOrientation)
- {
- sharedRotationState->m_savedOrientation = action.m_current.m_delta.GetInverseFull();
- angleDelta = 0.0f;
- AZ::Vector3 axis = m_axis;
- sharedRotationState->m_savedOrientation.ConvertToAxisAngle(axis, angleDelta);
- // Polarity of axis is switched by ConvertToAxisAngle call depending on direction of rotation
- if (abs(m_axis.GetX() - 1.0f) < FLT_EPSILON)
- {
- angleDelta = AZ::RadToDeg(angleDelta) * axis.GetX();
- }
- else if (abs(m_axis.GetY() - 1.0f) < FLT_EPSILON)
- {
- angleDelta = AZ::RadToDeg(angleDelta) * axis.GetY();
- }
- else if (abs(m_axis.GetZ() - 1.0f) < FLT_EPSILON)
- {
- angleDelta = AZ::RadToDeg(angleDelta) * axis.GetZ();
- }
-
- manipulatorOrientation = action.m_start.m_rotation * action.m_current.m_delta;
-
- if (isFirstValue)
- {
- return sharedRotationState->m_valuePair.first + angleDelta;
- }
- else
- {
- return sharedRotationState->m_valuePair.second + angleDelta;
- }
- }
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeAnglePair.h b/Gems/PhysX/Code/Editor/EditorSubComponentModeAnglePair.h
deleted file mode 100644
index cb96570ebe..0000000000
--- a/Gems/PhysX/Code/Editor/EditorSubComponentModeAnglePair.h
+++ /dev/null
@@ -1,66 +0,0 @@
-
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-#pragma once
-
-#include
-#include
-
-#include
-#include
-
-namespace PhysX
-{
- class EditorSubComponentModeAnglePair
- : public PhysX::EditorSubComponentModeBase
- , private AzFramework::EntityDebugDisplayEventBus::Handler
- {
- public:
- EditorSubComponentModeAnglePair(
- const AZ::EntityComponentIdPair& entityComponentIdPair
- , const AZ::Uuid& componentType
- , const AZStd::string& name
- , const AZ::Vector3& axis
- , float firstMax
- , float firstMin
- , float secondMax
- , float secondMin);
- ~EditorSubComponentModeAnglePair();
-
- // PhysX::EditorSubComponentModeBase
- void Refresh() override;
-
- private:
- struct SharedRotationState
- {
- AZ::Vector3 m_axis;
- AZ::Quaternion m_savedOrientation = AZ::Quaternion::CreateIdentity();
- AngleLimitsFloatPair m_valuePair;
- };
-
- // AzFramework::EntityDebugDisplayEventBus
- void DisplayEntityViewport(
- const AzFramework::ViewportInfo& viewportInfo,
- AzFramework::DebugDisplayRequests& debugDisplay) override;
-
- float MouseMove(AZStd::shared_ptr& sharedRotationState
- , const AzToolsFramework::AngularManipulator::Action& action
- , bool isFirstValue
- , float& angleDelta
- , AZ::Quaternion& manipulatorOrientation);
-
- AZStd::shared_ptr m_firstManipulator;
- AZStd::shared_ptr m_secondManipulator;
-
- AZ::Vector3 m_axis = AZ::Vector3::CreateAxisX();
- float m_firstMax = FLT_MAX;
- float m_firstMin = -FLT_MAX;
- float m_secondMax = FLT_MAX;
- float m_secondMin = -FLT_MAX;
- };
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeBase.cpp b/Gems/PhysX/Code/Editor/EditorSubComponentModeBase.cpp
deleted file mode 100644
index 1e02d52859..0000000000
--- a/Gems/PhysX/Code/Editor/EditorSubComponentModeBase.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-
-/*
- * 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
-#include
-#include
-#include
-
-namespace PhysX
-{
- EditorSubComponentModeBase::EditorSubComponentModeBase(
- const AZ::EntityComponentIdPair& entityComponentIdPair
- , const AZ::Uuid& componentType
- , const AZStd::string& name)
- : m_entityComponentId(entityComponentIdPair),
- m_name(name)
- {
- // The first time this is called, no object will respond to this bus call as no object is connected at the address,
- // and m_jointTypeDrawer will remain as a nullptr.
- EditorJointTypeDrawerBus::EventResult(m_jointTypeDrawer,
- EditorJointTypeDrawerId(componentType, EditorSubComponentModeNameCrc(name)),
- &EditorJointTypeDrawerBus::Events::GetEditorJointTypeDrawer);
-
- if (!m_jointTypeDrawer)
- {
- // Once this is called, the bus call to GetEditorJointTypeDrawer above will no longer get a null response, until m_jointTypeDrawer is destroyed.
- m_jointTypeDrawer = AZStd::make_shared(componentType,
- AzToolsFramework::GetEntityContextId(),
- m_name);
- }
- }
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeBase.h b/Gems/PhysX/Code/Editor/EditorSubComponentModeBase.h
deleted file mode 100644
index 09e06927f3..0000000000
--- a/Gems/PhysX/Code/Editor/EditorSubComponentModeBase.h
+++ /dev/null
@@ -1,55 +0,0 @@
-
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-#pragma once
-
-#include
-
-namespace AzFramework
-{
- class DebugDisplayRequests;
- struct ViewportInfo;
-}
-
-namespace AzToolsFramework
-{
- namespace ViewportInteraction
- {
- struct MouseInteractionEvent;
- }
-}
-
-namespace PhysX
-{
- class EditorJointTypeDrawer;
-
- /// Base class for (joints) sub-component modes.
- class EditorSubComponentModeBase
- {
- public:
- EditorSubComponentModeBase(
- const AZ::EntityComponentIdPair& entityComponentIdPair,
- const AZ::Uuid& componentType,
- const AZStd::string& name);
- virtual ~EditorSubComponentModeBase() = default;
-
- /// Additional mouse handling by sub-component mode. Does not absorb mouse event.
- virtual void HandleMouseInteraction(
- [[maybe_unused]] const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) {};
-
- virtual void Refresh() = 0;
-
- AZStd::string m_name;///< Name of sub-component mode.
-
- protected:
- AZ::EntityComponentIdPair m_entityComponentId;///< Entity Id and component pair.
-
- private:
- AZStd::shared_ptr m_jointTypeDrawer;///< Drawer that draws component type specific objects in the viewport.
- };
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeLinear.cpp b/Gems/PhysX/Code/Editor/EditorSubComponentModeLinear.cpp
deleted file mode 100644
index 378e1fb982..0000000000
--- a/Gems/PhysX/Code/Editor/EditorSubComponentModeLinear.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-
-/*
- * 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
-#include
-
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-namespace PhysX
-{
- EditorSubComponentModeLinear::EditorSubComponentModeLinear(
- const AZ::EntityComponentIdPair& entityComponentIdPair
- , const AZ::Uuid& componentType
- , const AZStd::string& name
- , float exponent
- , float max
- , float min)
- : EditorSubComponentModeBase(entityComponentIdPair, componentType, name)
- , m_exponent(exponent)
- , m_inverseExponent(1.0f/exponent)
- , m_max(max)
- , m_min(min)
- {
- AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId());
-
- AZ::Transform localTransform = AZ::Transform::CreateIdentity();
- EditorJointRequestBus::EventResult(
- localTransform, m_entityComponentId
- , &EditorJointRequests::GetTransformValue
- , PhysX::EditorJointComponentMode::s_parameterTransform);
-
- m_manipulator = AzToolsFramework::LinearManipulator::MakeShared(worldTransform);
- m_manipulator->AddEntityComponentIdPair(m_entityComponentId);
- m_manipulator->SetAxis(AZ::Vector3::CreateAxisX());
- m_manipulator->SetLocalTransform(localTransform);
-
- Refresh();
-
- const AZ::Color manipulatorColor(0.3f, 0.3f, 0.3f, 1.0f);
- const float manipulatorSize = 0.05f;
-
- AzToolsFramework::ManipulatorViews views;
- views.emplace_back(AzToolsFramework::CreateManipulatorViewQuadBillboard(manipulatorColor
- , manipulatorSize));
- m_manipulator->SetViews(AZStd::move(views));
-
- struct SharedState
- {
- float m_startingValue = 0.0f;
- };
- auto sharedState = AZStd::make_shared();
-
- m_manipulator->InstallLeftMouseDownCallback(
- [this, sharedState](const AzToolsFramework::LinearManipulator::Action& /*action*/) mutable
- {
- float currentValue = 0.0f;
-
- EditorJointRequestBus::EventResult(
- currentValue, m_entityComponentId
- , &EditorJointRequests::GetLinearValue
- , m_name);
- sharedState->m_startingValue = currentValue;
- });
-
- m_manipulator->InstallMouseMoveCallback(
- [this, sharedState](const AzToolsFramework::LinearManipulator::Action& action)
- {
- const float axisDisplacement = action.LocalPositionOffset().Dot(action.m_fixed.m_axis);
-
- float newValue = AZ::GetClamp(sharedState->m_startingValue + DisplacementToDeltaValue(axisDisplacement), m_min, m_max);
- EditorJointRequestBus::Event(
- m_entityComponentId
- , &EditorJointRequests::SetLinearValue
- , m_name
- , newValue);
-
- const AZ::Vector3 localPosition = action.LocalPosition().GetMax(AZ::Vector3(0.01f, 0.0f, 0.0f));
- m_manipulator->SetLocalTransform(AZ::Transform::CreateTranslation(localPosition));
- m_manipulator->SetBoundsDirty();
- });
-
- m_manipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
- }
-
- EditorSubComponentModeLinear::~EditorSubComponentModeLinear()
- {
- m_manipulator->Unregister();
- }
-
- void EditorSubComponentModeLinear::Refresh()
- {
- float currentValue = 0.0f;
-
- EditorJointRequestBus::EventResult(
- currentValue, m_entityComponentId
- , &EditorJointRequests::GetLinearValue
- , m_name);
-
- m_manipulator->SetLocalTransform(AZ::Transform::CreateTranslation(AZ::Vector3::CreateAxisX() * ValueToDisplacement(currentValue)));
- }
-
- float EditorSubComponentModeLinear::DisplacementToDeltaValue(float displacement) const
- {
- if (displacement > 0.0f)
- {
- return powf(displacement, m_exponent);
- }
- else if (displacement < 0.0f)
- {
- return -powf(fabsf(displacement), m_exponent);
- }
- else
- {
- return 0.0f;
- }
- }
-
- float EditorSubComponentModeLinear::ValueToDisplacement(float value) const
- {
- return powf(value, m_inverseExponent);
- }
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeLinear.h b/Gems/PhysX/Code/Editor/EditorSubComponentModeLinear.h
deleted file mode 100644
index 4d44d4aad4..0000000000
--- a/Gems/PhysX/Code/Editor/EditorSubComponentModeLinear.h
+++ /dev/null
@@ -1,46 +0,0 @@
-
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-#pragma once
-
-#include
-
-namespace AzToolsFramework
-{
- class LinearManipulator;
-}
-
-namespace PhysX
-{
- class EditorSubComponentModeLinear
- : public PhysX::EditorSubComponentModeBase
- {
- public:
- EditorSubComponentModeLinear(
- const AZ::EntityComponentIdPair& entityComponentIdPair
- , const AZ::Uuid& componentType
- , const AZStd::string& name
- , float exponent
- , float max
- , float min);
- ~EditorSubComponentModeLinear();
-
- // PhysX::EditorSubComponentModeBase
- void Refresh() override;
-
- private:
- float DisplacementToDeltaValue(float displacement) const;
- float ValueToDisplacement(float value) const;
-
- float m_exponent = 1.0f;
- float m_inverseExponent = 1.0f;
- AZStd::shared_ptr m_manipulator;
- float m_max = FLT_MAX;
- float m_min = -FLT_MAX;
- };
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeRotation.cpp b/Gems/PhysX/Code/Editor/EditorSubComponentModeRotation.cpp
deleted file mode 100644
index 7586ecc955..0000000000
--- a/Gems/PhysX/Code/Editor/EditorSubComponentModeRotation.cpp
+++ /dev/null
@@ -1,151 +0,0 @@
-
-/*
- * 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
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-namespace PhysX
-{
- EditorSubComponentModeRotation::EditorSubComponentModeRotation(
- const AZ::EntityComponentIdPair& entityComponentIdPair
- , const AZ::Uuid& componentType
- , const AZStd::string& name)
- : EditorSubComponentModeBase(entityComponentIdPair, componentType, name)
- {
- CreateManipulators();
- RegisterManipulators();
- AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(m_entityComponentId.GetEntityId());
- }
-
- EditorSubComponentModeRotation::~EditorSubComponentModeRotation()
- {
- AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
- UnregisterManipulators();
- }
-
- void EditorSubComponentModeRotation::Refresh()
- {
- AZ::Transform localTransform = AZ::Transform::CreateIdentity();
- EditorJointRequestBus::EventResult(
- localTransform, m_entityComponentId
- , &EditorJointRequests::GetTransformValue
- , PhysX::EditorJointComponentMode::s_parameterTransform);
-
- for (auto rotationManipulator : m_rotationManipulators)
- {
- rotationManipulator->SetLocalTransform(localTransform);
- rotationManipulator->SetBoundsDirty();
- }
- }
-
- void EditorSubComponentModeRotation::DisplayEntityViewport(
- [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo,
- [[maybe_unused]] AzFramework::DebugDisplayRequests& debugDisplay)
- {
- Refresh(); //Update position and orientation of manipulators.
- }
-
- void EditorSubComponentModeRotation::CreateManipulators()
- {
- AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId());
-
- const AZ::Quaternion worldRotation = worldTransform.GetRotation();
-
- AZ::Transform localTransform = AZ::Transform::CreateIdentity();
- EditorJointRequestBus::EventResult(
- localTransform, m_entityComponentId
- , &EditorJointRequests::GetTransformValue
- , PhysX::EditorJointComponentMode::s_parameterTransform);
-
- const AZStd::array axes = { AZ::Vector3::CreateAxisX()
- , AZ::Vector3::CreateAxisY()
- , AZ::Vector3::CreateAxisZ()};
-
- const AZStd::array colors = { AZ::Color(1.0f, 0.0f, 0.0f, 1.0f)
- , AZ::Color(0.0f, 1.0f, 0.0f, 1.0f)
- , AZ::Color(0.0f, 0.0f, 1.0f, 1.0f)};
-
- for (AZ::u32 i = 0; i < 3; ++i)
- {
- m_rotationManipulators[i] = AzToolsFramework::AngularManipulator::MakeShared(worldTransform);
- m_rotationManipulators[i]->AddEntityComponentIdPair(m_entityComponentId);
- m_rotationManipulators[i]->SetAxis(axes[i]);
- m_rotationManipulators[i]->SetLocalTransform(localTransform);
- const float manipulatorRadius = 2.0f;
- m_rotationManipulators[i]->SetView(AzToolsFramework::CreateManipulatorViewCircle(
- *m_rotationManipulators[i], colors[i], manipulatorRadius,
- AzToolsFramework::ManipulatorCicleBoundWidth(), AzToolsFramework::DrawHalfDottedCircle));
- }
-
- Refresh();
- InstallManipulatorMouseCallbacks();
- }
-
- void EditorSubComponentModeRotation::InstallManipulatorMouseCallbacks()
- {
- struct SharedState
- {
- AZ::Transform m_startTM;
- };
- auto sharedState = AZStd::make_shared();
-
- auto mouseDownRotateXCallback = [this, sharedState]([[maybe_unused]] const AzToolsFramework::AngularManipulator::Action& action) mutable -> void
- {
- PhysX::EditorJointRequestBus::EventResult(sharedState->m_startTM
- , m_entityComponentId
- , &PhysX::EditorJointRequests::GetTransformValue
- , PhysX::EditorJointComponentMode::s_parameterTransform);
- };
-
- for (AZ::u32 index = 0; index < 3; ++index)
- {
- m_rotationManipulators[index]->InstallLeftMouseDownCallback(mouseDownRotateXCallback);
-
- m_rotationManipulators[index]->InstallMouseMoveCallback(
- [this, index, sharedState]
- (const AzToolsFramework::AngularManipulator::Action& action) mutable -> void
- {
- const AZ::Quaternion manipulatorOrientation = action.m_start.m_rotation * action.m_current.m_delta;
-
- AZ::Transform newTransform = AZ::Transform::CreateIdentity();
- newTransform = sharedState->m_startTM * AZ::Transform::CreateFromQuaternion(action.m_current.m_delta);
-
- PhysX::EditorJointRequestBus::Event(m_entityComponentId
- , &PhysX::EditorJointRequests::SetVector3Value
- , PhysX::EditorJointComponentMode::s_parameterRotation
- , newTransform.GetRotation().GetEulerDegrees());
-
- m_rotationManipulators[index]->SetLocalOrientation(manipulatorOrientation);
- m_rotationManipulators[index]->SetBoundsDirty();
- });
- }
- }
-
- void EditorSubComponentModeRotation::RegisterManipulators()
- {
- for (auto rotationManipulator : m_rotationManipulators)
- {
- rotationManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
- }
- }
-
- void EditorSubComponentModeRotation::UnregisterManipulators()
- {
- for (auto rotationManipulator : m_rotationManipulators)
- {
- rotationManipulator->Unregister();
- }
- }
-}
diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeRotation.h b/Gems/PhysX/Code/Editor/EditorSubComponentModeRotation.h
deleted file mode 100644
index 349738909a..0000000000
--- a/Gems/PhysX/Code/Editor/EditorSubComponentModeRotation.h
+++ /dev/null
@@ -1,48 +0,0 @@
-
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-#pragma once
-
-#include
-#include
-
-namespace AzToolsFramework
-{
- class AngularManipulator;
-}
-
-namespace PhysX
-{
- class EditorSubComponentModeRotation
- : public PhysX::EditorSubComponentModeBase
- , private AzFramework::EntityDebugDisplayEventBus::Handler
- {
- public:
- EditorSubComponentModeRotation(
- const AZ::EntityComponentIdPair& entityComponentIdPair
- , const AZ::Uuid& componentType
- , const AZStd::string& name);
- ~EditorSubComponentModeRotation();
-
- // PhysX::EditorSubComponentModeBase
- void Refresh() override;
-
- private:
- // AzFramework::EntityDebugDisplayEventBus
- void DisplayEntityViewport(
- const AzFramework::ViewportInfo& viewportInfo,
- AzFramework::DebugDisplayRequests& debugDisplay) override;
-
- void CreateManipulators();
- void InstallManipulatorMouseCallbacks();
- void RegisterManipulators();
- void UnregisterManipulators();
-
- AZStd::array, 3> m_rotationManipulators;
- };
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapPosition.cpp b/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapPosition.cpp
deleted file mode 100644
index b086eb64ff..0000000000
--- a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapPosition.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-
-/*
- * 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
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-namespace PhysX
-{
- EditorSubComponentModeSnapPosition::EditorSubComponentModeSnapPosition(
- const AZ::EntityComponentIdPair& entityComponentIdPair
- , const AZ::Uuid& componentType
- , const AZStd::string& name
- , bool selectLeadOnSnap)
- : EditorSubComponentModeSnap(entityComponentIdPair, componentType, name)
- , m_selectLeadOnSnap(selectLeadOnSnap)
- {
- InitMouseDownCallBack();
- m_manipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
- AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(m_entityComponentId.GetEntityId());
- }
-
- EditorSubComponentModeSnapPosition::~EditorSubComponentModeSnapPosition()
- {
- AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
- m_manipulator->Unregister();
- }
-
- void EditorSubComponentModeSnapPosition::DisplaySpecificSnapType(
- [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo,
- AzFramework::DebugDisplayRequests& debugDisplay,
- const AZ::Vector3& jointPosition,
- const AZ::Vector3& snapDirection,
- const float snapLength)
- {
- const float arrowLength = 1.0f;
- const float iconGap = 1.0f;
- const AZ::Vector3 iconPosition = jointPosition +
- (snapDirection * (snapLength + arrowLength + iconGap));
-
- debugDisplay.SetColor(AZ::Colors::Red);
- debugDisplay.DrawArrow(iconPosition, iconPosition + AZ::Vector3(arrowLength, 0.0f, 0.0f));
- debugDisplay.SetColor(AZ::Colors::Green);
- debugDisplay.DrawArrow(iconPosition, iconPosition + AZ::Vector3(0.2f, arrowLength, 0.2f));
- debugDisplay.SetColor(AZ::Colors::Blue);
- debugDisplay.DrawArrow(iconPosition, iconPosition + AZ::Vector3(0.0f, 0.0f, arrowLength));
- }
-
- void EditorSubComponentModeSnapPosition::InitMouseDownCallBack()
- {
- m_manipulator->InstallLeftMouseDownCallback(
- [this](const AzToolsFramework::LinearManipulator::Action& /*action*/) mutable
- {
- if (!m_pickedEntity.IsValid())
- {
- return;
- }
-
- const AZ::Vector3 newLocalPosition = PhysX::Utils::ComputeJointLocalTransform(
- PhysX::Utils::GetEntityWorldTransformWithScale(m_pickedEntity),
- PhysX::Utils::GetEntityWorldTransformWithScale(m_entityComponentId.GetEntityId())).GetTranslation();
-
- PhysX::EditorJointRequestBus::Event(m_entityComponentId
- , &PhysX::EditorJointRequests::SetVector3Value
- , PhysX::EditorJointComponentMode::s_parameterPosition
- , newLocalPosition);
-
- const bool selectedEntityIsNotJointEntity = m_pickedEntity != m_entityComponentId.GetEntityId();
-
- AZ_Error("EditorSubComponentModeSnapPosition",
- selectedEntityIsNotJointEntity,
- "Joint's lead entity cannot be the same as the entity in which the joint resides. Select lead entity on snap failed.");
-
- if (m_selectLeadOnSnap &&
- selectedEntityIsNotJointEntity)
- {
- PhysX::EditorJointRequestBus::Event(m_entityComponentId
- , &PhysX::EditorJointRequests::SetEntityIdValue
- , PhysX::EditorJointComponentMode::s_parameterLeadEntity
- , m_pickedEntity);
- }
-
- m_manipulator->SetBoundsDirty();
- });
- }
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapPosition.h b/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapPosition.h
deleted file mode 100644
index d2fe803431..0000000000
--- a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapPosition.h
+++ /dev/null
@@ -1,42 +0,0 @@
-
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-#pragma once
-
-#include
-
-namespace PhysX
-{
- /// This sub-component mode gets an entity position from its base class on mouse down
- /// and sets a position (AZ::Vector3) value in the component that uses it.
- class EditorSubComponentModeSnapPosition
- : public EditorSubComponentModeSnap
- {
- public:
- EditorSubComponentModeSnapPosition(
- const AZ::EntityComponentIdPair& entityComponentIdPair
- , const AZ::Uuid& componentType
- , const AZStd::string& name
- , bool selectLeadOnSnap);
- ~EditorSubComponentModeSnapPosition() override;
-
- protected:
- // PhysX::EditorSubComponentModeSnap
- void DisplaySpecificSnapType(
- const AzFramework::ViewportInfo& viewportInfo,
- AzFramework::DebugDisplayRequests& debugDisplay,
- const AZ::Vector3& jointPosition,
- const AZ::Vector3& snapDirection,
- float snapLength) override;
-
- void InitMouseDownCallBack() override;
-
- private:
- bool m_selectLeadOnSnap = true;
- };
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapRotation.cpp b/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapRotation.cpp
deleted file mode 100644
index c68e058e29..0000000000
--- a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapRotation.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-
-/*
- * 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
-#include
-#include
-
-#include
-#include
-#include
-#include
-
-namespace PhysX
-{
- EditorSubComponentModeSnapRotation::EditorSubComponentModeSnapRotation(
- const AZ::EntityComponentIdPair& entityComponentIdPair
- , const AZ::Uuid& componentType
- , const AZStd::string& name)
- : EditorSubComponentModeSnap(entityComponentIdPair, componentType, name)
- {
- InitMouseDownCallBack();
- m_manipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
- AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(m_entityComponentId.GetEntityId());
- }
-
- EditorSubComponentModeSnapRotation::~EditorSubComponentModeSnapRotation()
- {
- AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
- m_manipulator->Unregister();
- }
-
- void EditorSubComponentModeSnapRotation::DisplaySpecificSnapType(
- [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo,
- AzFramework::DebugDisplayRequests& debugDisplay,
- const AZ::Vector3& jointPosition,
- const AZ::Vector3& snapDirection,
- const float snapLength)
- {
- const float circleRadius = 0.5f;
- const float iconGap = 1.0f;
-
- const AZ::Vector3 iconPosition = jointPosition +
- (snapDirection * (snapLength + circleRadius * 2.0f + iconGap));
-
- debugDisplay.SetColor(AZ::Colors::Red);
- debugDisplay.DrawCircle(iconPosition, circleRadius, 0);
- debugDisplay.SetColor(AZ::Colors::Green);
- debugDisplay.DrawCircle(iconPosition, circleRadius, 1);
- debugDisplay.SetColor(AZ::Colors::Blue);
- debugDisplay.DrawCircle(iconPosition, circleRadius, 2);
- }
-
- void EditorSubComponentModeSnapRotation::InitMouseDownCallBack()
- {
- m_manipulator->InstallLeftMouseDownCallback(
- [this]([[maybe_unused]] const AzToolsFramework::LinearManipulator::Action& action) mutable
- {
- if (!m_pickedEntity.IsValid())
- {
- return;
- }
-
- AZ::EntityId leadEntityId;
- PhysX::EditorJointRequestBus::EventResult(leadEntityId,
- m_entityComponentId,
- &PhysX::EditorJointRequests::GetEntityIdValue,
- PhysX::EditorJointComponentMode::s_parameterLeadEntity);
-
- if (leadEntityId.IsValid() && m_pickedEntity == leadEntityId)
- {
- AZ_Warning("EditorsubComponentModeSnapRotation",
- false,
- "The entity %s is the lead of the joint. Please snap rotation (or orientation) of joint to another entity that is not the lead entity.",
- GetPickedEntityName().c_str());
- return;
- }
-
- AZ::Transform worldTransform = AZ::Transform::CreateIdentity();
- AZ::TransformBus::EventResult(
- worldTransform, m_entityComponentId.GetEntityId(), &AZ::TransformInterface::GetWorldTM);
- worldTransform.ExtractUniformScale();
-
- AZ::Transform localTransform = AZ::Transform::CreateIdentity();
- EditorJointRequestBus::EventResult(
- localTransform, m_entityComponentId
- , &EditorJointRequests::GetTransformValue
- , PhysX::EditorJointComponentMode::s_parameterTransform);
-
- AZ::Transform pickedEntityTransform = AZ::Transform::CreateIdentity();
- AZ::TransformBus::EventResult(
- pickedEntityTransform, m_pickedEntity, &AZ::TransformInterface::GetWorldTM);
-
- const AZ::Transform worldTransformInv = worldTransform.GetInverse();
- const AZ::Vector3 pickedLocalPosition = worldTransformInv.TransformVector(pickedEntityTransform.GetTranslation()) - localTransform.GetTranslation();
-
- if (abs(pickedLocalPosition.GetLength()) < FLT_EPSILON)
- {
- AZ_Warning("EditorsubComponentModeSnapRotation",
- false,
- "The entity %s is too close to the joint position. Please snap rotation to an entity that is not at the position of the joint.",
- GetPickedEntityName().c_str());
- return;
- }
-
- const AZ::Vector3 targetDirection = pickedLocalPosition.GetNormalized();
- const AZ::Vector3 sourceDirection = AZ::Vector3::CreateAxisX();
- const AZ::Quaternion newLocalRotation = AZ::Quaternion::CreateShortestArc(sourceDirection, targetDirection);
-
- PhysX::EditorJointRequestBus::Event(m_entityComponentId
- , &PhysX::EditorJointRequests::SetVector3Value
- , PhysX::EditorJointComponentMode::s_parameterRotation //using rotation parameter name to set the local rotation value
- , newLocalRotation.GetEulerDegrees());
-
- m_manipulator->SetBoundsDirty();
- });
- }
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapRotation.h b/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapRotation.h
deleted file mode 100644
index 06d41df206..0000000000
--- a/Gems/PhysX/Code/Editor/EditorSubComponentModeSnapRotation.h
+++ /dev/null
@@ -1,38 +0,0 @@
-
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-#pragma once
-
-#include
-
-namespace PhysX
-{
- /// TThis sub-component mode gets an entity position from its base class on mouse down
- /// and sets a rotation (AZ::Quaternion) value in the component that uses it.
- class EditorSubComponentModeSnapRotation
- : public EditorSubComponentModeSnap
- {
- public:
- EditorSubComponentModeSnapRotation(
- const AZ::EntityComponentIdPair& entityComponentIdPair
- , const AZ::Uuid& componentType
- , const AZStd::string& name);
- ~EditorSubComponentModeSnapRotation() override;
-
- protected:
- // PhysX::EditorSubComponentModeSnap
- void DisplaySpecificSnapType(
- const AzFramework::ViewportInfo& viewportInfo,
- AzFramework::DebugDisplayRequests& debugDisplay,
- const AZ::Vector3& jointPosition,
- const AZ::Vector3& snapDirection,
- float snapLength) override;
-
- void InitMouseDownCallBack() override;
- };
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeVec3.cpp b/Gems/PhysX/Code/Editor/EditorSubComponentModeVec3.cpp
deleted file mode 100644
index 7e8affb086..0000000000
--- a/Gems/PhysX/Code/Editor/EditorSubComponentModeVec3.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-
-/*
- * 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
-#include
-#include
-
-#include
-#include
-#include
-
-namespace PhysX
-{
- EditorSubComponentModeVec3::EditorSubComponentModeVec3(
- const AZ::EntityComponentIdPair& entityComponentIdPair
- , const AZ::Uuid& componentType
- , const AZStd::string& name)
- : EditorSubComponentModeBase(entityComponentIdPair, componentType, name)
- , m_translationManipulators(AzToolsFramework::TranslationManipulators::Dimensions::Three,
- AZ::Transform::Identity(), AZ::Vector3::CreateOne())
- {
- AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId());
-
- AZ::Vector3 localTranslation;
- EditorJointRequestBus::EventResult(
- localTranslation, m_entityComponentId
- , &EditorJointRequests::GetVector3Value
- , m_name);
-
- m_translationManipulators.SetSpace(worldTransform);
- m_translationManipulators.SetLocalPosition(localTranslation);
- m_translationManipulators.AddEntityComponentIdPair(m_entityComponentId);
-
- m_translationManipulators.Register(AzToolsFramework::g_mainManipulatorManagerId);
-
- AzToolsFramework::ConfigureTranslationManipulatorAppearance3d(&m_translationManipulators);
-
- m_translationManipulators.InstallLinearManipulatorMouseMoveCallback([this](
- const AzToolsFramework::LinearManipulator::Action& action)
- {
- OnManipulatorMoved(action.LocalPosition());
- });
-
- m_translationManipulators.InstallPlanarManipulatorMouseMoveCallback([this](
- const AzToolsFramework::PlanarManipulator::Action& action)
- {
- OnManipulatorMoved(action.LocalPosition());
- });
-
- m_translationManipulators.InstallSurfaceManipulatorMouseMoveCallback([this](
- const AzToolsFramework::SurfaceManipulator::Action& action)
- {
- OnManipulatorMoved(action.LocalPosition());
- });
- }
-
- EditorSubComponentModeVec3::~EditorSubComponentModeVec3()
- {
- m_translationManipulators.Unregister();
- }
-
- void EditorSubComponentModeVec3::Refresh()
- {
- AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentId.GetEntityId());
-
- AZ::Vector3 localTranslation;
- EditorJointRequestBus::EventResult(
- localTranslation, m_entityComponentId
- , &EditorJointRequests::GetVector3Value
- , m_name);
-
- m_translationManipulators.SetSpace(worldTransform);
- m_translationManipulators.SetLocalPosition(localTranslation);
- m_translationManipulators.SetBoundsDirty();
- }
-
- void EditorSubComponentModeVec3::OnManipulatorMoved(const AZ::Vector3& position)
- {
- m_translationManipulators.SetLocalPosition(position);
- EditorJointRequestBus::Event(
- m_entityComponentId
- , &EditorJointRequests::SetVector3Value
- , m_name
- , position);
- }
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/EditorSubComponentModeVec3.h b/Gems/PhysX/Code/Editor/EditorSubComponentModeVec3.h
deleted file mode 100644
index 849125eb1c..0000000000
--- a/Gems/PhysX/Code/Editor/EditorSubComponentModeVec3.h
+++ /dev/null
@@ -1,34 +0,0 @@
-
-/*
- * Copyright (c) Contributors to the Open 3D Engine Project.
- * For complete copyright and license terms please see the LICENSE at the root of this distribution.
- *
- * SPDX-License-Identifier: Apache-2.0 OR MIT
- *
- */
-#pragma once
-
-#include
-#include
-
-namespace PhysX
-{
- class EditorSubComponentModeVec3
- : public PhysX::EditorSubComponentModeBase
- {
- public:
- EditorSubComponentModeVec3(
- const AZ::EntityComponentIdPair& entityComponentIdPair
- , const AZ::Uuid& componentType
- , const AZStd::string& name);
- ~EditorSubComponentModeVec3();
-
- // PhysX::EditorSubComponentModeBase
- void Refresh() override;
-
- private:
- void OnManipulatorMoved(const AZ::Vector3& position);
-
- AzToolsFramework::TranslationManipulators m_translationManipulators;
- };
-} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.cpp b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.cpp
new file mode 100644
index 0000000000..ce95e27db3
--- /dev/null
+++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.cpp
@@ -0,0 +1,601 @@
+/*
+ * 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
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace PhysX
+{
+ AZ_CLASS_ALLOCATOR_IMPL(JointsComponentMode, AZ::SystemAllocator, 0);
+
+ namespace SubModeData
+ {
+ const AZ::Crc32 SwitchToTranslationSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtotranslationsubmode");
+ static const char* TranslationTitle = "Switch to Position Mode";
+ static const char* TranslationToolTip = "Position Mode - Change the position of the joint.";
+
+ const AZ::Crc32 SwitchToRotationSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtorotationsubmode");
+ static const char* RotationTitle = "Switch to Rotation Mode";
+ static const char* RotationToolTip = "Rotation Mode- Change the rotation of the joint.";
+
+ const AZ::Crc32 SwitchToMaxForceSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtomaxforce");
+ static const char* MaxForceTitle = "Switch to Max Force Mode";
+ static const char* MaxForceToolTip = "Max Force Mode - Change the maximum force allowed before the joint breaks.";
+
+ const AZ::Crc32 SwitchToMaxTorqueSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtomaxtorque");
+ static const char* MaxTorqueTitle = "Switch to Max Torque Mode";
+ static const char* MaxTorqueToolTip = "Max Torque Mode - Change the maximum torque allowed before the joint breaks.";
+
+ const AZ::Crc32 SwitchToDampingSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtodamping");
+ static const char* DampingTitle = "Switch to Damping Mode";
+ static const char* DampingToolTip = "Damping Mode - Change the damping strength of the joint when beyond the limit.";
+
+ const AZ::Crc32 SwitchToStiffnessSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtostiffness");
+ static const char* StiffnessTitle = "Switch to Stiffness Mode";
+ static const char* StiffnessToolTip = "Stiffness Mode - Change the stiffness strength of the joint when beyond the limit.";
+
+ const AZ::Crc32 SwitchToTwistLimitsSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtotwistlimits");
+ static const char* TwistLimitsTitle = "Switch to Twist Limits Mode";
+ static const char* TwistLimitsToolTip = "Twist Limits Mode - Change the limits of the joint.";
+
+ const AZ::Crc32 SwitchToSwingLimitsSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtoswinglimits");
+ static const char* SwingLimitsTitle = "Switch to Swing Limits Mode";
+ static const char* SwingLimitsToolTip = "Swing Limits Mode - Change the limits of the joint.";
+
+ const AZ::Crc32 SwitchToSnapPositionSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtosnapposition");
+ static const char* SnapPositionTitle = "Switch to Snap Position Mode";
+ static const char* SnapPositionToolTip = "Snap Position Mode - Snap the position of the joint to another Entity.";
+
+ const AZ::Crc32 SwitchToSnapRotationSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.switchtosnaprotation");
+ static const char* SnapRotationTitle = "Switch to Snap Rotation Mode";
+ static const char* SnapRotationToolTip = "Snap Rotation Mode - Snap the rotation of the joint toward another Entity.";
+
+ const AZ::Crc32 ResetSubMode = AZ_CRC_CE("com.o3de.action.physx.joints.resetsubmode");
+ static const char* ResetTitle = "Reset Current Mode";
+ static const char* ResetToolTip = "Reset changes made during this mode edit.";
+
+ } // namespace ActionData
+
+ namespace Internal
+ {
+ static AzToolsFramework::ViewportUi::ButtonId RegisterClusterButton(
+ AzToolsFramework::ViewportUi::ClusterId clusterId, const char* iconName, const char* tooltip)
+ {
+ AzToolsFramework::ViewportUi::ButtonId buttonId;
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::EventResult(
+ buttonId, AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::CreateClusterButton, clusterId,
+ AZStd::string::format(":/stylesheet/img/UI20/toolbar/%s.svg", iconName));
+
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
+ AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterButtonTooltip, clusterId, buttonId, tooltip);
+
+ return buttonId;
+ }
+
+ void RefreshUI()
+ {
+ // The reason this is in a free function is because ColliderComponentMode
+ // privately inherits from ToolsApplicationNotificationBus. Trying to invoke
+ // the bus inside the class scope causes the compiler to complain it's not accessible
+ // to due private inheritance.
+ // Using the global namespace operator :: should have fixed that, except there
+ // is a bug in the Microsoft compiler meaning it doesn't work. So this is a work around.
+ AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(
+ &AzToolsFramework::ToolsApplicationNotificationBus::Events::InvalidatePropertyDisplay, AzToolsFramework::Refresh_Values);
+ }
+ } // namespace Internal
+
+ JointsComponentMode::JointsComponentMode(const AZ::EntityComponentIdPair& entityComponentIdPair, AZ::Uuid componentType)
+ : AzToolsFramework::ComponentModeFramework::EditorBaseComponentMode(entityComponentIdPair, componentType)
+ {
+ m_modeSelectionClusterIds.assign(static_cast(ClusterGroups::GroupCount), AzToolsFramework::ViewportUi::InvalidClusterId);
+ SetupSubModes(entityComponentIdPair);
+
+ EditorJointRequestBus::Event(
+ entityComponentIdPair, &EditorJointRequests::SetBoolValue, JointsComponentModeCommon::ParamaterNames::ComponentMode, true);
+ }
+
+ JointsComponentMode::~JointsComponentMode()
+ {
+ EditorJointRequestBus::Event(
+ GetEntityComponentIdPair(), &EditorJointRequests::SetBoolValue, JointsComponentModeCommon::ParamaterNames::ComponentMode,
+ false);
+
+ TeardownSubModes();
+ m_subModes[m_subMode]->Teardown(GetEntityComponentIdPair());
+ }
+
+ void JointsComponentMode::Refresh()
+ {
+ m_subModes[m_subMode]->Refresh(GetEntityComponentIdPair());
+ }
+
+ AZStd::vector JointsComponentMode::PopulateActionsImpl()
+ {
+ const AZ::EntityComponentIdPair entityComponentIdPair = GetEntityComponentIdPair();
+
+ AZStd::vector subModesState;
+ EditorJointRequestBus::EventResult(subModesState, entityComponentIdPair, &EditorJointRequests::GetSubComponentModesState);
+
+ auto makeActionOverride = [](const AZ::EntityComponentIdPair& entityComponentIdPair, const AZ::Crc32& actionUri,
+ const QString& title, const QString& tip,const AZStd::function&& callback)
+ {
+ AzToolsFramework::ActionOverride actionOverride;
+ actionOverride.SetTitle(title);
+ actionOverride.SetTip(tip);
+ actionOverride.SetUri(actionUri);
+ actionOverride.SetEntityComponentIdPair(entityComponentIdPair);
+ actionOverride.SetCallback(callback);
+ return actionOverride;
+ };
+
+ AZStd::vector actions;
+
+ // translation action
+ {
+ AzToolsFramework::ActionOverride translateAction = makeActionOverride(
+ entityComponentIdPair, SubModeData::SwitchToTranslationSubMode,
+ SubModeData::TranslationTitle, SubModeData::TranslationToolTip,
+ [this]()
+ {
+ SetCurrentMode(
+ JointsComponentModeCommon::SubComponentModes::ModeType::Translation,
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Translation]);
+ });
+ translateAction.SetKeySequence(QKeySequence(Qt::Key_1));
+ actions.emplace_back(translateAction);
+ }
+
+ // rotation action
+ {
+ AzToolsFramework::ActionOverride rotationAction = makeActionOverride(
+ entityComponentIdPair, SubModeData::SwitchToRotationSubMode,
+ SubModeData::RotationTitle, SubModeData::RotationToolTip,
+ [this]()
+ {
+ SetCurrentMode(
+ JointsComponentModeCommon::SubComponentModes::ModeType::Rotation,
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Rotation]);
+ });
+ rotationAction.SetKeySequence(QKeySequence(Qt::Key_2));
+ actions.emplace_back(rotationAction);
+ }
+
+ //setup action for other enabled options
+ for (auto [modeType, parameterString] : subModesState)
+ {
+ switch (modeType)
+ {
+ case JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce:
+ {
+ actions.emplace_back(makeActionOverride(
+ entityComponentIdPair, SubModeData::SwitchToMaxForceSubMode,
+ SubModeData::MaxForceTitle, SubModeData::MaxForceToolTip,
+ [this]()
+ {
+ SetCurrentMode(
+ JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce,
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce]);
+ }));
+ }
+ break;
+ case JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque:
+ {
+ actions.emplace_back(makeActionOverride(
+ entityComponentIdPair, SubModeData::SwitchToMaxTorqueSubMode,
+ SubModeData::MaxTorqueTitle, SubModeData::MaxTorqueToolTip,
+ [this]()
+ {
+ SetCurrentMode(
+ JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque,
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque]);
+ }));
+ }
+ break;
+ case JointsComponentModeCommon::SubComponentModes::ModeType::Damping:
+ {
+ actions.emplace_back(makeActionOverride(
+ entityComponentIdPair, SubModeData::SwitchToDampingSubMode,
+ SubModeData::DampingTitle, SubModeData::DampingToolTip,
+ [this]()
+ {
+ SetCurrentMode(
+ JointsComponentModeCommon::SubComponentModes::ModeType::Damping,
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Damping]);
+ }));
+ }
+ break;
+ case JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness:
+ {
+ actions.emplace_back(makeActionOverride(
+ entityComponentIdPair, SubModeData::SwitchToStiffnessSubMode,
+ SubModeData::StiffnessTitle, SubModeData::StiffnessToolTip,
+ [this]()
+ {
+ SetCurrentMode(
+ JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness,
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness]);
+ }));
+ }
+ break;
+ case JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits:
+ {
+ actions.emplace_back(makeActionOverride(
+ entityComponentIdPair, SubModeData::SwitchToTwistLimitsSubMode,
+ SubModeData::TwistLimitsTitle, SubModeData::TwistLimitsToolTip,
+ [this]()
+ {
+ SetCurrentMode(
+ JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits,
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits]);
+ }));
+ }
+ break;
+ case JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits:
+ {
+ actions.emplace_back(makeActionOverride(
+ entityComponentIdPair, SubModeData::SwitchToSwingLimitsSubMode,
+ SubModeData::SwingLimitsTitle, SubModeData::SwingLimitsToolTip,
+ [this]()
+ {
+ SetCurrentMode(
+ JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits,
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits]);
+ }));
+ }
+ break;
+ case JointsComponentModeCommon::SubComponentModes::ModeType::SnapPosition:
+ {
+ actions.emplace_back(makeActionOverride(
+ entityComponentIdPair, SubModeData::SwitchToSnapPositionSubMode,
+ SubModeData::SnapPositionTitle, SubModeData::SnapPositionToolTip,
+ [this]()
+ {
+ SetCurrentMode(
+ JointsComponentModeCommon::SubComponentModes::ModeType::SnapPosition,
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::SnapPosition]);
+ }));
+ }
+ break;
+ case JointsComponentModeCommon::SubComponentModes::ModeType::SnapRotation:
+ {
+ actions.emplace_back(makeActionOverride(
+ entityComponentIdPair, SubModeData::SwitchToSnapRotationSubMode,
+ SubModeData::SnapRotationTitle, SubModeData::SnapRotationToolTip,
+ [this]()
+ {
+ SetCurrentMode(
+ JointsComponentModeCommon::SubComponentModes::ModeType::SnapRotation,
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::SnapRotation]);
+ }));
+ }
+ break;
+ }
+ }
+
+ // reset values
+ {
+ AzToolsFramework::ActionOverride resetValuesAction = makeActionOverride(
+ entityComponentIdPair, SubModeData::ResetSubMode,
+ SubModeData::ResetTitle, SubModeData::ResetToolTip,
+ [this]()
+ {
+ ResetCurrentMode();
+ });
+ resetValuesAction.SetKeySequence(QKeySequence(Qt::Key_R));
+ actions.emplace_back(resetValuesAction);
+ }
+
+ return actions;
+ }
+
+ AZStd::vector JointsComponentMode::PopulateViewportUiImpl()
+ {
+ return AZStd::vector(m_modeSelectionClusterIds.begin(), m_modeSelectionClusterIds.end());
+ }
+
+ void JointsComponentMode::SetCurrentMode(JointsComponentModeCommon::SubComponentModes::ModeType newMode, ButtonData& buttonData)
+ {
+
+ if (auto subMode = m_subModes.find(newMode);
+ subMode != m_subModes.end())
+ {
+ const AZ::EntityComponentIdPair entityComponentIdPair = GetEntityComponentIdPair();
+ m_subModes[m_subMode]->Teardown(entityComponentIdPair);
+ m_subMode = newMode;
+ subMode->second->Setup(entityComponentIdPair);
+
+ // if this button is on a different cluster. clear the active state.
+ if (m_activeButton.m_clusterId != buttonData.m_clusterId)
+ {
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
+ AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::ClearClusterActiveButton, m_activeButton.m_clusterId);
+ }
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
+ AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterActiveButton, buttonData.m_clusterId,
+ buttonData.m_buttonId);
+ m_activeButton = buttonData;
+ }
+ else
+ {
+ AZ_Assert(false, "PhysXJoints Uninitialized joint component mode selected.");
+ }
+ }
+
+ bool JointsComponentMode::HandleMouseInteraction(const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction)
+ {
+ // Propagate mouse interaction to sub-component mode.
+ if (m_subModes[m_subMode])
+ {
+ m_subModes[m_subMode]->HandleMouseInteraction(mouseInteraction);
+ }
+
+ return false;
+ }
+
+ void JointsComponentMode::SetupSubModes(const AZ::EntityComponentIdPair& entityComponentIdPair)
+ {
+ //create the 3 cluster groups
+ for (auto& clusterId : m_modeSelectionClusterIds)
+ {
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::EventResult(
+ clusterId, AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::CreateCluster,
+ AzToolsFramework::ViewportUi::Alignment::TopLeft);
+ }
+
+ //retrieve the enabled sub components from the entity
+ AZStd::vector subModesState;
+ EditorJointRequestBus::EventResult(subModesState, entityComponentIdPair, &EditorJointRequests::GetSubComponentModesState);
+
+ const AzToolsFramework::ViewportUi::ClusterId group1ClusterId = GetClusterId(ClusterGroups::Group1);
+ const AzToolsFramework::ViewportUi::ClusterId group2ClusterId = GetClusterId(ClusterGroups::Group2);
+ //hide cluster 2, if something is added to it. it will make is visible
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
+ AzToolsFramework::ViewportUi::DefaultViewportId, &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible,
+ group2ClusterId, false);
+
+ const AzToolsFramework::ViewportUi::ClusterId group3ClusterId = GetClusterId(ClusterGroups::Group3);
+ // hide cluster 3, if something is added to it. it will make is visible
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
+ AzToolsFramework::ViewportUi::DefaultViewportId, &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible,
+ group3ClusterId, false);
+
+ //translation and rotation are enabled for all joints in group 1
+ m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::Translation] =
+ AZStd::make_unique();
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Translation] =
+ ButtonData{ group1ClusterId, Internal::RegisterClusterButton(group1ClusterId, "Move", SubModeData::TranslationToolTip) };
+
+ m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::Rotation] = AZStd::make_unique();
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Rotation] =
+ ButtonData{ group1ClusterId, Internal::RegisterClusterButton(group1ClusterId, "Rotate", SubModeData::RotationTitle) };
+
+ //some constants for some modes
+ const float ExponentBreakage = 1.0f;
+ const float ExponentSpring = 2.0f;
+
+ //setup the remaining modes if they're in the enabled list.
+ for (auto [modeType, parameterString] : subModesState)
+ {
+ switch (modeType)
+ {
+ case JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce:
+ {
+ m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce] =
+ AZStd::make_unique(
+ parameterString, ExponentBreakage, EditorJointConfig::s_breakageMax, EditorJointConfig::s_breakageMin);
+
+ const AzToolsFramework::ViewportUi::ButtonId buttonId =
+ Internal::RegisterClusterButton(group3ClusterId, "joints/MaxForce", SubModeData::MaxForceToolTip);
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::MaxForce] =
+ ButtonData{ group3ClusterId, buttonId };
+
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
+ AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group3ClusterId, true);
+ }
+ break;
+ case JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque:
+ {
+ m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque] =
+ AZStd::make_unique(
+ parameterString, ExponentBreakage, EditorJointConfig::s_breakageMax, EditorJointConfig::s_breakageMin);
+
+ const AzToolsFramework::ViewportUi::ButtonId buttonId =
+ Internal::RegisterClusterButton(group3ClusterId, "joints/MaxTorque", SubModeData::MaxTorqueToolTip);
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::MaxTorque] =
+ ButtonData{ group3ClusterId, buttonId };
+
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
+ AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group3ClusterId, true);
+ }
+ break;
+ case JointsComponentModeCommon::SubComponentModes::ModeType::Damping:
+ {
+ m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::Damping] =
+ AZStd::make_unique(
+ parameterString, ExponentSpring, EditorJointLimitBase::s_springMax, EditorJointLimitBase::s_springMin);
+
+ const AzToolsFramework::ViewportUi::ButtonId buttonId =
+ Internal::RegisterClusterButton(group2ClusterId, "joints/Damping", SubModeData::DampingToolTip);
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Damping] = ButtonData{ group2ClusterId, buttonId };
+
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
+ AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group2ClusterId, true);
+ }
+ break;
+ case JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness:
+ {
+ m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness] =
+ AZStd::make_unique(
+ parameterString, ExponentSpring, EditorJointLimitBase::s_springMax, EditorJointLimitBase::s_springMin);
+
+ const AzToolsFramework::ViewportUi::ButtonId buttonId =
+ Internal::RegisterClusterButton(group2ClusterId, "joints/Stiffness", SubModeData::StiffnessToolTip);
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Stiffness] =
+ ButtonData{ group2ClusterId, buttonId };
+
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
+ AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group2ClusterId, true);
+ }
+ break;
+ case JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits:
+ {
+ m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits] =
+ AZStd::make_unique(
+ parameterString,
+ AZ::Vector3::CreateAxisX(), // PhysX revolute joints uses the x-axis by default
+ EditorJointLimitPairConfig::s_angleMax, EditorJointLimitPairConfig::s_angleMin);
+
+ const AzToolsFramework::ViewportUi::ButtonId buttonId =
+ Internal::RegisterClusterButton(group2ClusterId, "joints/TwistLimits", SubModeData::TwistLimitsToolTip);
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::TwistLimits] =
+ ButtonData{ group2ClusterId, buttonId };
+
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
+ AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group2ClusterId, true);
+ }
+ break;
+ case JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits:
+ {
+ m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits] =
+ AZStd::make_unique(
+ parameterString, EditorJointLimitPairConfig::s_angleMax, EditorJointLimitPairConfig::s_angleMin);
+
+ const AzToolsFramework::ViewportUi::ButtonId buttonId =
+ Internal::RegisterClusterButton(group2ClusterId, "joints/SwingLimits", SubModeData::SwingLimitsToolTip);
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::SwingLimits] =
+ ButtonData{ group2ClusterId, buttonId };
+
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
+ AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::SetClusterVisible, group2ClusterId, true);
+ }
+ break;
+ case JointsComponentModeCommon::SubComponentModes::ModeType::SnapPosition:
+ {
+ m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::SnapPosition] =
+ AZStd::make_unique();
+
+ const AzToolsFramework::ViewportUi::ButtonId buttonId =
+ Internal::RegisterClusterButton(group1ClusterId, "joints/SnapPosition", SubModeData::SnapPositionToolTip);
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::SnapPosition] =
+ ButtonData{ group1ClusterId, buttonId };
+ }
+ break;
+ case JointsComponentModeCommon::SubComponentModes::ModeType::SnapRotation:
+ {
+ m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::SnapRotation] =
+ AZStd::make_unique();
+
+ const AzToolsFramework::ViewportUi::ButtonId buttonId =
+ Internal::RegisterClusterButton(group1ClusterId, "joints/SnapRotation", SubModeData::SnapRotationToolTip);
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::SnapRotation] =
+ ButtonData{ group1ClusterId, buttonId };
+ }
+ break;
+ }
+ }
+
+ //register click handler for the buttons
+ m_modeSelectionHandlers.push_back(AZ::Event::Handler(
+ [this](AzToolsFramework::ViewportUi::ButtonId buttonId)
+ {
+ for (auto itr : m_buttonData)
+ {
+ if (itr.second.m_clusterId == GetClusterId(ClusterGroups::Group1) && itr.second.m_buttonId == buttonId)
+ {
+ SetCurrentMode(itr.first, itr.second);
+ break;
+ }
+ }
+ }));
+ m_modeSelectionHandlers.push_back(AZ::Event::Handler(
+ [this](AzToolsFramework::ViewportUi::ButtonId buttonId)
+ {
+ for (auto itr : m_buttonData)
+ {
+ if (itr.second.m_clusterId == GetClusterId(ClusterGroups::Group2) && itr.second.m_buttonId == buttonId)
+ {
+ SetCurrentMode(itr.first, itr.second);
+ break;
+ }
+ }
+ }));
+ m_modeSelectionHandlers.push_back(AZ::Event::Handler(
+ [this](AzToolsFramework::ViewportUi::ButtonId buttonId)
+ {
+ for (auto itr : m_buttonData)
+ {
+ if (itr.second.m_clusterId == GetClusterId(ClusterGroups::Group3) && itr.second.m_buttonId == buttonId)
+ {
+ SetCurrentMode(itr.first, itr.second);
+ break;
+ }
+ }
+ }));
+
+ for (int i = 0; i < static_cast(ClusterGroups::GroupCount); i++)
+ {
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
+ AzToolsFramework::ViewportUi::DefaultViewportId,
+ &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RegisterClusterEventHandler, m_modeSelectionClusterIds[i],
+ m_modeSelectionHandlers[i]);
+ }
+
+ // set the translate as enabled by default.
+ SetCurrentMode(
+ JointsComponentModeCommon::SubComponentModes::ModeType::Translation,
+ m_buttonData[JointsComponentModeCommon::SubComponentModes::ModeType::Translation]);
+
+ m_subModes[JointsComponentModeCommon::SubComponentModes::ModeType::Translation]->Setup(GetEntityComponentIdPair());
+ m_subMode = JointsComponentModeCommon::SubComponentModes::ModeType::Translation;
+ }
+
+ void JointsComponentMode::ResetCurrentMode()
+ {
+ const AZ::EntityComponentIdPair entityComponentIdPair = GetEntityComponentIdPair();
+ m_subModes[m_subMode]->ResetValues(entityComponentIdPair);
+ m_subModes[m_subMode]->Refresh(entityComponentIdPair);
+
+ Internal::RefreshUI();
+ }
+
+ void JointsComponentMode::TeardownSubModes()
+ {
+ for (auto clusterid : m_modeSelectionClusterIds)
+ {
+ AzToolsFramework::ViewportUi::ViewportUiRequestBus::Event(
+ AzToolsFramework::ViewportUi::DefaultViewportId, &AzToolsFramework::ViewportUi::ViewportUiRequestBus::Events::RemoveCluster,
+ clusterid);
+ }
+ }
+
+ AzToolsFramework::ViewportUi::ClusterId JointsComponentMode::GetClusterId(ClusterGroups group)
+ {
+ return m_modeSelectionClusterIds[static_cast(group)];
+ }
+} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.h b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.h
new file mode 100644
index 0000000000..812bc71ec1
--- /dev/null
+++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentMode.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+namespace AZ
+{
+ class EntityComponentIdPair;
+}
+
+namespace PhysX
+{
+ //! Class responsible for managing component mode for joints.
+ class JointsComponentMode final
+ : public AzToolsFramework::ComponentModeFramework::EditorBaseComponentMode
+ {
+ public:
+ AZ_CLASS_ALLOCATOR_DECL;
+
+ JointsComponentMode(const AZ::EntityComponentIdPair& entityComponentIdPair, AZ::Uuid componentType);
+ ~JointsComponentMode();
+
+ // EditorBaseComponentMode ...
+ void Refresh() override;
+ AZStd::vector PopulateActionsImpl() override;
+ AZStd::vector PopulateViewportUiImpl() override;
+ private:
+ //! Used to identify the group of component modes.
+ enum class ClusterGroups
+ {
+ Group1 = 0, //!< Position Joint, Rotate Joint, Snap Position, Snap Rotation.
+ Group2, //!< Damping, Stiffness, Twist Limits, Swing Limits.
+ Group3, //!< Max Force, Max Torque.
+
+ GroupCount
+ };
+
+ //! Used to track the cluster that a specific button is apart of.
+ struct ButtonData
+ {
+ AzToolsFramework::ViewportUi::ClusterId m_clusterId;
+ AzToolsFramework::ViewportUi::ButtonId m_buttonId;
+ };
+
+ void SetCurrentMode(JointsComponentModeCommon::SubComponentModes::ModeType newMode, ButtonData& buttonData);
+ bool HandleMouseInteraction(const AzToolsFramework::ViewportInteraction::MouseInteractionEvent& mouseInteraction) override;
+ void SetupSubModes(const AZ::EntityComponentIdPair& entityComponentIdPair);
+ void ResetCurrentMode();
+ void TeardownSubModes();
+
+ AzToolsFramework::ViewportUi::ClusterId GetClusterId(ClusterGroups group);
+
+ AZStd::fixed_vector(ClusterGroups::GroupCount)> m_modeSelectionClusterIds; //!< List of the cluster ui's. The sub modes are split across 3 groups and each group is it's own cluster ui.
+ AZStd::unordered_map m_buttonData; //!< Mapping of joint component modes to the button data.
+
+ AZStd::fixed_vector::Handler, static_cast(ClusterGroups::GroupCount)>
+ m_modeSelectionHandlers; //!< Input handlers for each cluster UI.
+ ButtonData m_activeButton; //!< The current highlighted button data.
+
+ JointsComponentModeCommon::SubComponentModes::ModeType m_subMode = JointsComponentModeCommon::SubComponentModes::ModeType::Translation; //!< The current component mode that is active.
+ AZStd::unordered_map> m_subModes; //!< The logic handlers for each component mode.
+ };
+}
diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentModeCommon.cpp b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentModeCommon.cpp
new file mode 100644
index 0000000000..a400745c51
--- /dev/null
+++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentModeCommon.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include
+
+namespace PhysX::JointsComponentModeCommon
+{
+ const AZStd::string_view ParamaterNames::TwistLimits = "Twist Limits";
+ const AZStd::string_view ParamaterNames::Damping = "Damping";
+ const AZStd::string_view ParamaterNames::MaxForce = "Maximum Force";
+ const AZStd::string_view ParamaterNames::MaxTorque = "Maximum Torque";
+ const AZStd::string_view ParamaterNames::Position = "Position";
+ const AZStd::string_view ParamaterNames::Rotation = "Rotation";
+ const AZStd::string_view ParamaterNames::SnapPosition = "Snap Position";
+ const AZStd::string_view ParamaterNames::SnapRotation = "Snap Rotation";
+ const AZStd::string_view ParamaterNames::Stiffness = "Stiffness";
+ const AZStd::string_view ParamaterNames::SwingLimit = "Swing Limits";
+ const AZStd::string_view ParamaterNames::Transform = "Transform";
+ const AZStd::string_view ParamaterNames::ComponentMode = "Component Mode";
+ const AZStd::string_view ParamaterNames::LeadEntity = "Lead Entity";
+
+} // namespace PhysX::JointsComponentModeCommon
diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentModeCommon.h b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentModeCommon.h
new file mode 100644
index 0000000000..3deb3b7e3f
--- /dev/null
+++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsComponentModeCommon.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+#pragma once
+
+#include
+#include
+#include
+#include
+
+namespace PhysX::JointsComponentModeCommon
+{
+ namespace SubComponentModes
+ {
+ //! Used to identify a specific sub component mode used with joints
+ enum class ModeType : AZ::u32
+ {
+ Translation = 0,
+ Rotation,
+ MaxForce,
+ MaxTorque,
+ Damping,
+ Stiffness,
+ TwistLimits,
+ SwingLimits,
+ SnapPosition,
+ SnapRotation,
+
+ ModeCount
+ };
+
+ //! Shared data structure used with Angle Cone and Angle Pair sub component modes.
+ //! Holds information about the axis and limits of the angle.
+ struct AngleModesSharedRotationState
+ {
+ AZ::Vector3 m_axis; //!< The Axis of rotation to apply the limits.
+ AZ::Quaternion m_savedOrientation = AZ::Quaternion::CreateIdentity(); //!< The angle delta of the last mouse action.
+ PhysX::AngleLimitsFloatPair m_valuePair; //!< the current limits of the angle.
+ };
+ } // namespace SubComponentModes
+
+ //! Name Identifiers for the joint components sub modes.
+ struct ParamaterNames
+ {
+ static const AZStd::string_view TwistLimits;
+ static const AZStd::string_view Damping;
+ static const AZStd::string_view MaxForce;
+ static const AZStd::string_view MaxTorque;
+ static const AZStd::string_view Position;
+ static const AZStd::string_view Rotation;
+ static const AZStd::string_view SnapPosition;
+ static const AZStd::string_view SnapRotation;
+ static const AZStd::string_view Stiffness;
+ static const AZStd::string_view SwingLimit;
+ static const AZStd::string_view Transform;
+ static const AZStd::string_view ComponentMode;
+ static const AZStd::string_view LeadEntity;
+ };
+
+ //! A pairing of Sub component Names, and Id.
+ struct SubModeParamaterState
+ {
+ SubComponentModes::ModeType m_modeType = SubComponentModes::ModeType::ModeCount; //!< The Id of the sub component mode.
+ AZStd::string m_parameterName; //!< The name of the sub component mode.
+ };
+} // namespace PhysX::JointsComponentModeCommon
diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAngleCone.cpp b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAngleCone.cpp
new file mode 100644
index 0000000000..11abe0fa2a
--- /dev/null
+++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAngleCone.cpp
@@ -0,0 +1,432 @@
+/*
+ * 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
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+namespace PhysX
+{
+ AZ_CLASS_ALLOCATOR_IMPL(JointsSubComponentModeAngleCone, AZ::SystemAllocator, 0);
+
+ namespace Internal
+ {
+ const float ArrowLength = 2.0f;
+ const float ConeHeight = 3.0f;
+ const float XRotationManipulatorRadius = 2.0f;
+ const float XRotationManipulatorWidth = 0.05f;
+ } // namespace Internal
+
+ JointsSubComponentModeAngleCone::JointsSubComponentModeAngleCone(
+ const AZStd::string& propertyName, float max, float min)
+ : m_propertyName(propertyName)
+ , m_max(max)
+ , m_min(min)
+ {
+
+ }
+
+ void JointsSubComponentModeAngleCone::Setup(const AZ::EntityComponentIdPair& idPair)
+ {
+ m_entityComponentIdPair = idPair;
+ EditorJointRequestBus::EventResult(
+ m_resetPostion, m_entityComponentIdPair, &PhysX::EditorJointRequests::GetVector3Value, JointsComponentModeCommon::ParamaterNames::Position);
+ EditorJointRequestBus::EventResult(
+ m_resetRotation, m_entityComponentIdPair, &PhysX::EditorJointRequests::GetVector3Value, JointsComponentModeCommon::ParamaterNames::Rotation);
+ EditorJointRequestBus::EventResult(
+ m_resetLimits, m_entityComponentIdPair, &EditorJointRequests::GetLinearValuePair, m_propertyName);
+
+ AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentIdPair.GetEntityId());
+
+ AZ::Transform localTransform = AZ::Transform::CreateIdentity();
+ EditorJointRequestBus::EventResult(
+ localTransform, m_entityComponentIdPair, &EditorJointRequests::GetTransformValue, JointsComponentModeCommon::ParamaterNames::Transform);
+ const AZ::Quaternion localRotation = localTransform.GetRotation();
+
+ // Initialize manipulators used to resize the base of the cone.
+ m_yLinearManipulator = AzToolsFramework::LinearManipulator::MakeShared(worldTransform);
+ m_yLinearManipulator->AddEntityComponentIdPair(m_entityComponentIdPair);
+ m_yLinearManipulator->SetAxis(AZ::Vector3::CreateAxisZ());
+
+ m_zLinearManipulator = AzToolsFramework::LinearManipulator::MakeShared(worldTransform);
+ m_zLinearManipulator->AddEntityComponentIdPair(m_entityComponentIdPair);
+ m_zLinearManipulator->SetAxis(AZ::Vector3::CreateAxisY());
+
+ m_yzPlanarManipulator = AzToolsFramework::PlanarManipulator::MakeShared(worldTransform);
+ m_yzPlanarManipulator->AddEntityComponentIdPair(m_entityComponentIdPair);
+ m_yzPlanarManipulator->SetAxes(AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ());
+
+ ConfigureLinearView(
+ Internal::ArrowLength, AZ::Color(1.0f, 0.0f, 0.0f, 1.0f), AZ::Color(0.0f, 1.0f, 0.0f, 1.0f), AZ::Color(0.0f, 0.0f, 1.0f, 1.0f));
+
+ ConfigurePlanarView(AZ::Color(0.0f, 1.0f, 0.0f, 1.0f), AZ::Color(0.0f, 0.0f, 1.0f, 1.0f));
+
+ // Position and orientate manipulators
+ AZ::Transform displacementTransform = localTransform;
+ AZ::Vector3 displacementTranslate = localRotation.TransformVector(AZ::Vector3(Internal::ConeHeight, 0.0f, 0.0f));
+ displacementTransform.SetTranslation(localTransform.GetTranslation() + displacementTranslate);
+
+ m_yLinearManipulator->SetLocalTransform(displacementTransform);
+ m_zLinearManipulator->SetLocalTransform(displacementTransform);
+ m_yzPlanarManipulator->SetLocalTransform(displacementTransform);
+
+ // Initialize rotation manipulator for rotating cone
+ m_xRotationManipulator = AzToolsFramework::AngularManipulator::MakeShared(worldTransform);
+ m_xRotationManipulator->AddEntityComponentIdPair(m_entityComponentIdPair);
+ m_xRotationManipulator->SetAxis(AZ::Vector3::CreateAxisX());
+ m_xRotationManipulator->SetLocalTransform(localTransform);
+
+ const AZ::Color xRotationManipulatorColor = AZ::Color(1.0f, 0.0f, 0.0f, 1.0f);
+ m_xRotationManipulator->SetView(AzToolsFramework::CreateManipulatorViewCircle(
+ *m_xRotationManipulator, xRotationManipulatorColor, Internal::XRotationManipulatorRadius, Internal::XRotationManipulatorWidth,
+ AzToolsFramework::DrawHalfDottedCircle));
+
+ AZStd::shared_ptr sharedRotationState =
+ AZStd::make_shared();
+
+ struct SharedState
+ {
+ AngleLimitsFloatPair m_startValues;
+ };
+ auto sharedState = AZStd::make_shared();
+
+ m_yLinearManipulator->InstallLeftMouseDownCallback(
+ [this, sharedState](const AzToolsFramework::LinearManipulator::Action& /*action*/) mutable
+ {
+ AngleLimitsFloatPair currentValue;
+ EditorJointRequestBus::EventResult(
+ currentValue, m_entityComponentIdPair, &EditorJointRequests::GetLinearValuePair, m_propertyName);
+ sharedState->m_startValues = currentValue;
+ });
+
+ m_yLinearManipulator->InstallMouseMoveCallback(
+ [this, sharedState](const AzToolsFramework::LinearManipulator::Action& action)
+ {
+ AZ::Transform localTransform = AZ::Transform::CreateIdentity();
+ EditorJointRequestBus::EventResult(
+ localTransform, m_entityComponentIdPair, &EditorJointRequests::GetTransformValue,
+ JointsComponentModeCommon::ParamaterNames::Transform);
+ const AZ::Quaternion localRotation = localTransform.GetRotation();
+ const float axisDisplacement = action.LocalPositionOffset().Dot(localRotation.TransformVector(action.m_fixed.m_axis));
+ const float originalBaseY = tan(AZ::DegToRad(sharedState->m_startValues.first)) * Internal::ConeHeight;
+ const float newBaseY = originalBaseY + axisDisplacement;
+ const float newAngle = AZ::GetClamp(AZ::RadToDeg(atan(newBaseY / Internal::ConeHeight)), m_min, m_max);
+
+ EditorJointRequestBus::Event(
+ m_entityComponentIdPair, &EditorJointRequests::SetLinearValuePair, m_propertyName,
+ AngleLimitsFloatPair(newAngle, sharedState->m_startValues.second));
+
+ m_yLinearManipulator->SetBoundsDirty();
+ });
+
+ m_zLinearManipulator->InstallLeftMouseDownCallback(
+ [this, sharedState](const AzToolsFramework::LinearManipulator::Action& /*action*/) mutable
+ {
+ AngleLimitsFloatPair currentValue;
+ EditorJointRequestBus::EventResult(
+ currentValue, m_entityComponentIdPair, &EditorJointRequests::GetLinearValuePair, m_propertyName);
+ sharedState->m_startValues = currentValue;
+ });
+
+ m_zLinearManipulator->InstallMouseMoveCallback(
+ [this, sharedState](const AzToolsFramework::LinearManipulator::Action& action)
+ {
+ AZ::Transform localTransform = AZ::Transform::CreateIdentity();
+ EditorJointRequestBus::EventResult(
+ localTransform, m_entityComponentIdPair, &EditorJointRequests::GetTransformValue,
+ JointsComponentModeCommon::ParamaterNames::Transform);
+ const AZ::Quaternion localRotation = localTransform.GetRotation();
+ const float axisDisplacement = action.LocalPositionOffset().Dot(localRotation.TransformVector(action.m_fixed.m_axis));
+ const float originalBaseZ = tan(AZ::DegToRad(sharedState->m_startValues.second)) * Internal::ConeHeight;
+ const float newBaseZ = originalBaseZ + axisDisplacement;
+ const float newAngle = AZ::GetClamp(AZ::RadToDeg(atan(newBaseZ / Internal::ConeHeight)), m_min, m_max);
+
+ EditorJointRequestBus::Event(
+ m_entityComponentIdPair, &EditorJointRequests::SetLinearValuePair, m_propertyName,
+ AngleLimitsFloatPair(sharedState->m_startValues.first, newAngle));
+
+ m_zLinearManipulator->SetBoundsDirty();
+ });
+
+ m_yzPlanarManipulator->InstallLeftMouseDownCallback(
+ [this, sharedState]([[maybe_unused]]const AzToolsFramework::PlanarManipulator::Action& action) mutable
+ {
+ AngleLimitsFloatPair currentValue;
+ EditorJointRequestBus::EventResult(
+ currentValue, m_entityComponentIdPair, &EditorJointRequests::GetLinearValuePair, m_propertyName);
+ sharedState->m_startValues = currentValue;
+ });
+
+ m_yzPlanarManipulator->InstallMouseMoveCallback(
+ [this, sharedState](const AzToolsFramework::PlanarManipulator::Action& action)
+ {
+ AZ::Transform localTransform = AZ::Transform::CreateIdentity();
+ EditorJointRequestBus::EventResult(
+ localTransform, m_entityComponentIdPair, &EditorJointRequests::GetTransformValue,
+ JointsComponentModeCommon::ParamaterNames::Transform);
+
+ const AZ::Quaternion localRotation = localTransform.GetRotation();
+
+ const float axisDisplacementY = action.LocalPositionOffset().Dot(localRotation.TransformVector(AZ::Vector3::CreateAxisY()));
+ const float axisDisplacementZ = action.LocalPositionOffset().Dot(localRotation.TransformVector(AZ::Vector3::CreateAxisZ()));
+ const float axisDisplacement = axisDisplacementZ > axisDisplacementY ? axisDisplacementZ : axisDisplacementY;
+
+ const float originalBaseY = tan(AZ::DegToRad(sharedState->m_startValues.first)) * Internal::ConeHeight;
+ const float newBaseY = originalBaseY + axisDisplacement;
+ const float newAngleY = AZ::GetClamp(AZ::RadToDeg(atan(newBaseY / Internal::ConeHeight)), m_min, m_max);
+
+ const float originalBaseZ = tan(AZ::DegToRad(sharedState->m_startValues.second)) * Internal::ConeHeight;
+ const float newBaseZ = originalBaseZ + axisDisplacement;
+ const float newAngleZ = AZ::GetClamp(AZ::RadToDeg(atan(newBaseZ / Internal::ConeHeight)), m_min, m_max);
+
+ EditorJointRequestBus::Event(
+ m_entityComponentIdPair, &EditorJointRequests::SetLinearValuePair, m_propertyName,
+ AngleLimitsFloatPair(newAngleY, newAngleZ));
+
+ m_yzPlanarManipulator->SetBoundsDirty();
+ });
+
+ struct SharedStateXRotate
+ {
+ AZ::Transform m_startTM;
+ };
+ auto sharedStateXRotate = AZStd::make_shared();
+
+ auto mouseDownCallback = [this, sharedRotationState](const AzToolsFramework::AngularManipulator::Action& action) mutable -> void
+ {
+ AZ::Quaternion normalizedStart = action.m_start.m_rotation.GetNormalized();
+ sharedRotationState->m_axis = AZ::Vector3(normalizedStart.GetX(), normalizedStart.GetY(), normalizedStart.GetZ());
+ sharedRotationState->m_savedOrientation = AZ::Quaternion::CreateIdentity();
+
+ AngleLimitsFloatPair currentValue;
+ EditorJointRequestBus::EventResult(
+ currentValue, m_entityComponentIdPair, &EditorJointRequests::GetLinearValuePair, m_propertyName);
+
+ sharedRotationState->m_valuePair = currentValue;
+ };
+
+ auto mouseDownRotateXCallback =
+ [this, sharedStateXRotate]([[maybe_unused]] const AzToolsFramework::AngularManipulator::Action& action) mutable -> void
+ {
+ PhysX::EditorJointRequestBus::EventResult(
+ sharedStateXRotate->m_startTM, m_entityComponentIdPair, &PhysX::EditorJointRequests::GetTransformValue,
+ JointsComponentModeCommon::ParamaterNames::Transform);
+ };
+
+ m_xRotationManipulator->InstallLeftMouseDownCallback(mouseDownRotateXCallback);
+
+ m_xRotationManipulator->InstallMouseMoveCallback(
+ [this, sharedStateXRotate](const AzToolsFramework::AngularManipulator::Action& action) mutable -> void
+ {
+ const AZ::Quaternion manipulatorOrientation = action.m_start.m_rotation * action.m_current.m_delta;
+
+ AZ::Transform newTransform = AZ::Transform::CreateIdentity();
+ newTransform = sharedStateXRotate->m_startTM * AZ::Transform::CreateFromQuaternion(action.m_current.m_delta);
+
+ PhysX::EditorJointRequestBus::Event(
+ m_entityComponentIdPair, &PhysX::EditorJointRequests::SetVector3Value, JointsComponentModeCommon::ParamaterNames::Position,
+ newTransform.GetTranslation());
+ PhysX::EditorJointRequestBus::Event(
+ m_entityComponentIdPair, &PhysX::EditorJointRequests::SetVector3Value, JointsComponentModeCommon::ParamaterNames::Rotation,
+ newTransform.GetRotation().GetEulerDegrees());
+
+ m_yLinearManipulator->SetLocalOrientation(manipulatorOrientation);
+ m_zLinearManipulator->SetLocalOrientation(manipulatorOrientation);
+ m_yLinearManipulator->SetAxis(action.m_current.m_delta.TransformVector(AZ::Vector3::CreateAxisY()));
+ m_zLinearManipulator->SetAxis(action.m_current.m_delta.TransformVector(AZ::Vector3::CreateAxisZ()));
+ m_xRotationManipulator->SetLocalOrientation(manipulatorOrientation);
+
+ m_yLinearManipulator->SetBoundsDirty();
+ m_zLinearManipulator->SetBoundsDirty();
+ m_xRotationManipulator->SetBoundsDirty();
+ });
+
+ m_xRotationManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
+ m_yLinearManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
+ m_zLinearManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
+ m_yzPlanarManipulator->Register(AzToolsFramework::g_mainManipulatorManagerId);
+
+ AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(m_entityComponentIdPair.GetEntityId());
+
+ Refresh(m_entityComponentIdPair);
+ }
+
+ void JointsSubComponentModeAngleCone::Refresh(const AZ::EntityComponentIdPair& idPair)
+ {
+ AZ::Transform localTransform = AZ::Transform::CreateIdentity();
+ EditorJointRequestBus::EventResult(
+ localTransform, idPair, &EditorJointRequests::GetTransformValue, JointsComponentModeCommon::ParamaterNames::Transform);
+
+ float coneHeight = Internal::ConeHeight;
+ AngleLimitsFloatPair yzSwingAngleLimits;
+ EditorJointRequestBus::EventResult(yzSwingAngleLimits, idPair, &EditorJointRequests::GetLinearValuePair, m_propertyName);
+
+ // Draw inverted cone (negative cone height) if angles are larger than 90 deg.
+ if (yzSwingAngleLimits.first > 90.0f || yzSwingAngleLimits.second > 90.0f)
+ {
+ coneHeight = -Internal::ConeHeight;
+ }
+
+ // reposition manipulators
+ const AZ::Quaternion localRotation = localTransform.GetRotation();
+ const AZ::Vector3 linearManipulatorOffset =
+ localTransform.GetTranslation() + localRotation.TransformVector(AZ::Vector3(coneHeight, 0.0f, 0.0f));
+
+ m_xRotationManipulator->SetLocalTransform(localTransform);
+
+ localTransform.SetTranslation(linearManipulatorOffset);
+
+ m_yLinearManipulator->SetLocalTransform(localTransform);
+ m_zLinearManipulator->SetLocalTransform(localTransform);
+ m_yzPlanarManipulator->SetLocalTransform(localTransform);
+ }
+
+ void JointsSubComponentModeAngleCone::Teardown(const AZ::EntityComponentIdPair& idPair)
+ {
+ AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
+
+ m_xRotationManipulator->RemoveEntityComponentIdPair(idPair);
+ m_xRotationManipulator->Unregister();
+ m_yLinearManipulator->RemoveEntityComponentIdPair(idPair);
+ m_yLinearManipulator->Unregister();
+ m_zLinearManipulator->RemoveEntityComponentIdPair(idPair);
+ m_zLinearManipulator->Unregister();
+ m_yzPlanarManipulator->RemoveEntityComponentIdPair(idPair);
+ m_yzPlanarManipulator->Unregister();
+ }
+
+ void JointsSubComponentModeAngleCone::ResetValues(const AZ::EntityComponentIdPair& idPair)
+ {
+ EditorJointRequestBus::Event(
+ idPair, &PhysX::EditorJointRequests::SetVector3Value, JointsComponentModeCommon::ParamaterNames::Position, m_resetPostion);
+ EditorJointRequestBus::Event(
+ idPair, &PhysX::EditorJointRequests::SetVector3Value, JointsComponentModeCommon::ParamaterNames::Rotation, m_resetRotation);
+ EditorJointRequestBus::Event(idPair, &EditorJointRequests::SetLinearValuePair, m_propertyName, m_resetLimits);
+ }
+
+ void JointsSubComponentModeAngleCone::ConfigureLinearView(
+ float axisLength, [[maybe_unused]] const AZ::Color& axis1Color, const AZ::Color& axis2Color, const AZ::Color& axis3Color)
+ {
+ const float coneLength = 0.28f;
+ const float coneRadius = 0.07f;
+
+ const auto configureLinearView =
+ [coneLength, axisLength, coneRadius](AzToolsFramework::LinearManipulator* linearManipulator, const AZ::Color& color)
+ {
+ AzToolsFramework::ManipulatorViews views;
+ views.emplace_back(CreateManipulatorViewLine(
+ *linearManipulator, color, axisLength,
+ AzToolsFramework::ManipulatorLineBoundWidth(AzFramework::InvalidViewportId)));
+ views.emplace_back(CreateManipulatorViewCone(
+ *linearManipulator, color, linearManipulator->GetAxis() * (axisLength - coneLength), coneLength, coneRadius));
+ linearManipulator->SetViews(AZStd::move(views));
+ };
+
+ configureLinearView(m_yLinearManipulator.get(), axis2Color);
+ configureLinearView(m_zLinearManipulator.get(), axis3Color);
+ }
+
+ void JointsSubComponentModeAngleCone::ConfigurePlanarView(const AZ::Color& planeColor, const AZ::Color& plane2Color)
+ {
+ const float planeSize = 0.6f;
+ AzToolsFramework::ManipulatorViews views;
+ views.emplace_back(CreateManipulatorViewQuad(*m_yzPlanarManipulator, planeColor, plane2Color, planeSize));
+ m_yzPlanarManipulator->SetViews(AZStd::move(views));
+ }
+
+ void JointsSubComponentModeAngleCone::DisplayEntityViewport(
+ [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
+ {
+ AZ::Transform worldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_entityComponentIdPair.GetEntityId());
+
+ AZ::Transform localTransform = AZ::Transform::CreateIdentity();
+ EditorJointRequestBus::EventResult(
+ localTransform, m_entityComponentIdPair, &EditorJointRequests::GetTransformValue,
+ JointsComponentModeCommon::ParamaterNames::Transform);
+
+ AZ::u32 stateBefore = debugDisplay.GetState();
+ debugDisplay.CullOff();
+
+ debugDisplay.PushMatrix(worldTransform);
+ debugDisplay.PushMatrix(localTransform);
+
+ const float xAxisArrowLength = 2.0f;
+ debugDisplay.SetColor(AZ::Color(1.0f, 0.0f, 0.0f, 1.0f));
+ debugDisplay.DrawArrow(AZ::Vector3(0.0f, 0.0f, 0.0f), AZ::Vector3(xAxisArrowLength, 0.0f, 0.0f));
+
+ AngleLimitsFloatPair yzSwingAngleLimits;
+ EditorJointRequestBus::EventResult(
+ yzSwingAngleLimits, m_entityComponentIdPair, &EditorJointRequests::GetLinearValuePair, m_propertyName);
+
+ const AZ::u32 numEllipseSamples = 16;
+ AZ::Vector3 ellipseSamples[numEllipseSamples];
+ float coneHeight = Internal::ConeHeight;
+
+ // Draw inverted cone if angles are larger than 90 deg.
+ if (yzSwingAngleLimits.first > 90.0f || yzSwingAngleLimits.second > 90.0f)
+ {
+ coneHeight = -Internal::ConeHeight;
+ }
+
+ // Compute points along perimeter of cone base
+ const float coney = tanf(AZ::DegToRad(yzSwingAngleLimits.first)) * coneHeight;
+ const float conez = tanf(AZ::DegToRad(yzSwingAngleLimits.second)) * coneHeight;
+ const float step = AZ::Constants::TwoPi / numEllipseSamples;
+ for (size_t i = 0; i < numEllipseSamples; ++i)
+ {
+ const float angleStep = step * i;
+ ellipseSamples[i].SetX(coneHeight);
+ ellipseSamples[i].SetY(conez * sin(angleStep));
+ ellipseSamples[i].SetZ(coney * cos(angleStep));
+ }
+
+ // draw cone
+ for (size_t i = 0; i < numEllipseSamples; ++i)
+ {
+ size_t nextIndex = i + 1;
+ if (i == numEllipseSamples - 1)
+ {
+ nextIndex = 0;
+ }
+
+ // draw cone sides
+ debugDisplay.SetColor(AZ::Color(1.0f, 1.0f, 1.0f, 0.2f));
+ debugDisplay.DrawTri(AZ::Vector3(0.0f, 0.0f, 0.0f), ellipseSamples[i], ellipseSamples[nextIndex]);
+
+ // draw parameter of cone base
+ debugDisplay.SetColor(AZ::Color(0.4f, 0.4f, 0.4f, 0.4f));
+ debugDisplay.DrawLine(ellipseSamples[i], ellipseSamples[nextIndex]);
+ }
+
+ // draw axis lines at base of cone, and from tip to base.
+ debugDisplay.SetColor(AZ::Color(0.5f, 0.5f, 0.5f, 0.6f));
+ debugDisplay.DrawLine(ellipseSamples[0], ellipseSamples[numEllipseSamples / 2]);
+ debugDisplay.DrawLine(ellipseSamples[numEllipseSamples * 3 / 4], ellipseSamples[numEllipseSamples / 4]);
+ debugDisplay.DrawLine(AZ::Vector3(0.0f, 0.0f, 0.0f), AZ::Vector3(coneHeight, 0.0f, 0.0f));
+
+ debugDisplay.PopMatrix(); // pop local transform
+ debugDisplay.PopMatrix(); // pop world transform
+ debugDisplay.SetState(stateBefore);
+
+ // reposition and reorientate manipulators
+ Refresh(m_entityComponentIdPair);
+ }
+
+} // namespace PhysX
diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAngleCone.h b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAngleCone.h
new file mode 100644
index 0000000000..3f6d001112
--- /dev/null
+++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAngleCone.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace AzToolsFramework
+{
+ class AngularManipulator;
+ class LinearManipulator;
+ class PlanarManipulator;
+} // namespace AzToolsFramework
+
+namespace PhysX
+{
+ class JointsSubComponentModeAngleCone final
+ : public PhysXSubComponentModeBase
+ , private AzFramework::EntityDebugDisplayEventBus::Handler
+ {
+ public:
+ AZ_CLASS_ALLOCATOR_DECL;
+
+ JointsSubComponentModeAngleCone(const AZStd::string& propertyName, float max, float min);
+
+ // PhysXSubComponentModeBase ...
+ void Setup(const AZ::EntityComponentIdPair& idPair) override;
+ void Refresh(const AZ::EntityComponentIdPair& idPair) override;
+ void Teardown(const AZ::EntityComponentIdPair& idPair) override;
+ void ResetValues(const AZ::EntityComponentIdPair& idPair) override;
+
+ private:
+ void ConfigureLinearView(
+ float axisLength,
+ const AZ::Color& axis1Color,
+ const AZ::Color& axis2Color,
+ const AZ::Color& axis3Color = AZ::Color(0.0f, 0.0f, 1.0f, 0.5f));
+
+ void ConfigurePlanarView(
+ const AZ::Color& planeColor = AZ::Color(0.0f, 1.0f, 0.0f, 0.5f),
+ const AZ::Color& plane2Color = AZ::Color(0.0f, 0.0f, 1.0f, 0.5f));
+
+ // AzFramework::EntityDebugDisplayEventBus
+ void DisplayEntityViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
+
+ float m_max = AZStd::numeric_limits::max();
+ float m_min = -AZStd::numeric_limits::max();
+
+ AZ::EntityComponentIdPair m_entityComponentIdPair;
+ AZ::Vector3 m_resetPostion;
+ AZ::Vector3 m_resetRotation;
+ AngleLimitsFloatPair m_resetLimits;
+ AZStd::string m_propertyName;
+ AZStd::shared_ptr m_xRotationManipulator;
+ AZStd::shared_ptr m_yLinearManipulator;
+ AZStd::shared_ptr m_zLinearManipulator;
+ AZStd::shared_ptr m_yzPlanarManipulator;
+ };
+}
diff --git a/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAnglePair.cpp b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAnglePair.cpp
new file mode 100644
index 0000000000..84b0cd4b5b
--- /dev/null
+++ b/Gems/PhysX/Code/Editor/Source/ComponentModes/Joints/JointsSubComponentModeAnglePair.cpp
@@ -0,0 +1,305 @@
+/*
+ * 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
+
+#include