1f9b284de2
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> # Conflicts: # Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h # Code/Editor/Plugins/EditorCommon/EditorCommon_precompiled.h # Code/Editor/Plugins/EditorCommon/stdafx.cpp # Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin_precompiled.h # Code/Editor/Plugins/PerforcePlugin/PerforcePlugin_precompiled.h # Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsTool_precompiled.h # Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFramework_precompiled.h # Code/Tools/AssetProcessor/native/precompiled.h # Code/Tools/Standalone/StandaloneTools_precompiled.h # Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer_precompiled.h # Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageProcessing_precompiled.h # Gems/Atom/RHI/DX12/Code/Source/RHI/Atom_RHI_DX12_precompiled.h # Gems/Atom/RHI/Metal/Code/Include/Platform/Mac/Atom_RHI_Metal_precompiled_Platform.h # Gems/Atom/RHI/Metal/Code/Include/Platform/iOS/Atom_RHI_Metal_precompiled_Platform.h # Gems/Atom/RHI/Metal/Code/Source/Atom_RHI_Metal_precompiled.h # Gems/Atom/RHI/Metal/Code/atom_rhi_metal_common_files.cmake # Gems/Atom/RHI/Null/Code/Source/Atom_RHI_Null_precompiled.h # Gems/Atom/RHI/Null/Code/atom_rhi_null_common_files.cmake # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Android/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Linux/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Mac/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Windows/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Source/Atom_RHI_Vulkan_precompiled.h # Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp # Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_common_files.cmake # Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h # Gems/Blast/Code/Source/StdAfx.cpp # Gems/Camera/Code/Source/Camera_precompiled.h # Gems/EMotionFX/Code/Source/EMotionFX_precompiled.h # Gems/FastNoise/Code/Source/FastNoise_precompiled.h # Gems/Gestures/Code/Source/Gestures_precompiled.h # Gems/GradientSignal/Code/Source/GradientSignal_precompiled.h # Gems/GraphCanvas/Code/precompiled.h # Gems/ImGui/Code/Source/ImGui_precompiled.h # Gems/InAppPurchases/Code/Source/InAppPurchases_precompiled.h # Gems/LmbrCentral/Code/Source/LmbrCentral_precompiled.h # Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp # Gems/LyShine/Code/Editor/UiCanvasEditor_precompiled.h # Gems/LyShine/Code/Source/Animation/LyShine_precompiled.h # Gems/LyShine/Code/Source/LyShine_precompiled.h # Gems/LyShineExamples/Code/Source/LyShineExamples_precompiled.h # Gems/Maestro/Code/Source/Cinematics/Maestro_precompiled.h # Gems/Maestro/Code/Source/Maestro_precompiled.h # Gems/MessagePopup/Code/Source/MessagePopup_precompiled.h # Gems/Metastream/Code/Source/Metastream_precompiled.h # Gems/Microphone/Code/Source/Microphone_precompiled.h # Gems/Multiplayer/Code/Source/Multiplayer_precompiled.h # Gems/PhysX/Code/NumericalMethods/Source/NumericalMethods_precompiled.h # Gems/PhysX/Code/Source/PhysXUnsupported_precompiled.h # Gems/PhysX/Code/Source/PhysX_precompiled.h # Gems/PhysX/Code/physx_unsupported_files.cmake # Gems/PhysXDebug/Code/Source/PhysXDebugUnsupported_precompiled.h # Gems/PhysXDebug/Code/Source/PhysXDebug_precompiled.h # Gems/ScriptCanvas/Code/Editor/precompiled.h # Gems/ScriptCanvas/Code/Source/precompiled.h # Gems/ScriptCanvasDeveloper/Code/Source/precompiled.h # Gems/ScriptCanvasPhysics/Code/Source/ScriptCanvasPhysics_precompiled.h # Gems/ScriptEvents/Code/Source/precompiled.h # Gems/ScriptEvents/Code/Tests/Editor/EditorTests.cpp # Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweener_precompiled.h # Gems/SliceFavorites/Code/Source/SliceFavorites_precompiled.h # Gems/StartingPointCamera/Code/Source/StartingPointCamera_precompiled.h # Gems/StartingPointInput/Code/Source/StartingPointInput_precompiled.h # Gems/StartingPointMovement/Code/Source/StartingPointMovement_precompiled.h # Gems/SurfaceData/Code/Source/SurfaceData_precompiled.h # Gems/TextureAtlas/Code/Source/TextureAtlas_precompiled.h # Gems/TickBusOrderViewer/Code/Source/TickBusOrderViewer_precompiled.h # Gems/Twitch/Code/Source/Twitch_precompiled.h # Gems/VirtualGamepad/Code/Source/VirtualGamepad_precompiled.h # Gems/WhiteBox/Code/Source/WhiteBoxUnsupported_precompiled.h # Gems/WhiteBox/Code/Source/WhiteBox_precompiled.h
332 lines
14 KiB
C++
332 lines
14 KiB
C++
/*
|
|
* 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 <AzCore/Component/TransformBus.h>
|
|
#include <AzCore/Interface/Interface.h>
|
|
#include <AzCore/Math/IntersectSegment.h>
|
|
#include <AzCore/Serialization/EditContext.h>
|
|
#include <AzCore/Serialization/SerializeContext.h>
|
|
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
|
|
|
|
#include <PhysX/Configuration/PhysXConfiguration.h>
|
|
#include <Editor/EditorJointComponentMode.h>
|
|
#include <Source/EditorColliderComponent.h>
|
|
#include <Source/EditorJointComponent.h>
|
|
#include <Source/EditorRigidBodyComponent.h>
|
|
#include <Source/Utils.h>
|
|
#include <System/PhysXSystem.h>
|
|
|
|
namespace PhysX
|
|
{
|
|
const constexpr float JointAabbHalfExtent = 0.5f;
|
|
|
|
void EditorJointComponent::Reflect(AZ::ReflectContext* context)
|
|
{
|
|
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
|
{
|
|
serializeContext->Class<EditorJointComponent, AzToolsFramework::Components::EditorComponentBase>()
|
|
->Version(1)
|
|
->Field("Configuration", &EditorJointComponent::m_config)
|
|
;
|
|
|
|
if (auto* editContext = serializeContext->GetEditContext())
|
|
{
|
|
editContext->Class<EditorJointComponent>(
|
|
"PhysX Joint", "The joint constrains the position and orientation of a body to another.")
|
|
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
|
->Attribute(AZ::Edit::Attributes::Category, "PhysX")
|
|
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
|
->DataElement(0, &EditorJointComponent::m_config, "Standard Joint Parameters", "Joint parameters shared by all joint types")
|
|
;
|
|
}
|
|
}
|
|
}
|
|
|
|
void EditorJointComponent::Activate()
|
|
{
|
|
AzToolsFramework::Components::EditorComponentBase::Activate();
|
|
|
|
m_config.m_followerEntity = GetEntityId();
|
|
|
|
AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusConnect(m_config.m_followerEntity);
|
|
AzToolsFramework::EditorComponentSelectionNotificationsBus::Handler::BusConnect(m_config.m_followerEntity);
|
|
PhysX::EditorJointRequestBus::Handler::BusConnect(AZ::EntityComponentIdPair(m_config.m_followerEntity, GetId()));
|
|
AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(m_config.m_followerEntity);
|
|
AzFramework::BoundsRequestBus::Handler::BusConnect(m_config.m_followerEntity);
|
|
}
|
|
|
|
void EditorJointComponent::Deactivate()
|
|
{
|
|
AzFramework::BoundsRequestBus::Handler::BusDisconnect();
|
|
AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
|
|
PhysX::EditorJointRequestBus::Handler::BusDisconnect();
|
|
|
|
AzToolsFramework::EditorComponentSelectionNotificationsBus::Handler::BusDisconnect();
|
|
AzToolsFramework::EditorComponentSelectionRequestsBus::Handler::BusDisconnect();
|
|
AzToolsFramework::Components::EditorComponentBase::Deactivate();
|
|
}
|
|
|
|
AZ::Aabb EditorJointComponent::GetEditorSelectionBoundsViewport(
|
|
const AzFramework::ViewportInfo& viewportInfo)
|
|
{
|
|
AZ::Transform worldTM = AZ::Transform::CreateIdentity();
|
|
AZ::TransformBus::EventResult(worldTM, GetEntityId(), &AZ::TransformInterface::GetWorldTM);
|
|
const AZ::Vector3 position = worldTM.GetTranslation();
|
|
|
|
AzFramework::CameraState cameraState;
|
|
AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::EventResult(
|
|
cameraState, viewportInfo.m_viewportId,
|
|
&AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Events::GetCameraState);
|
|
|
|
const float screenToWorldScale = AzToolsFramework::CalculateScreenToWorldMultiplier(position, cameraState);
|
|
|
|
const float scaledJointHalfAabbExtent = JointAabbHalfExtent * screenToWorldScale;
|
|
const AZ::Vector3 selectionSize(scaledJointHalfAabbExtent);
|
|
const AZ::Vector3 positionMin = position - selectionSize;
|
|
const AZ::Vector3 positionMax = position + selectionSize;
|
|
|
|
AZ::Aabb aabb = AZ::Aabb::CreateFromMinMax(positionMin, positionMax);
|
|
|
|
return aabb;
|
|
}
|
|
|
|
AZ::Aabb EditorJointComponent::GetWorldBounds()
|
|
{
|
|
AZ::Transform worldTM = AZ::Transform::CreateIdentity();
|
|
AZ::TransformBus::EventResult(worldTM, GetEntityId(), &AZ::TransformInterface::GetWorldTM);
|
|
|
|
return GetLocalBounds().GetTransformedAabb(worldTM);
|
|
}
|
|
|
|
AZ::Aabb EditorJointComponent::GetLocalBounds()
|
|
{
|
|
return AZ::Aabb::CreateFromMinMax(-AZ::Vector3(JointAabbHalfExtent), AZ::Vector3(JointAabbHalfExtent));
|
|
}
|
|
|
|
bool EditorJointComponent::EditorSelectionIntersectRayViewport(
|
|
const AzFramework::ViewportInfo& viewportInfo,
|
|
const AZ::Vector3& src, const AZ::Vector3& dir, float& distance)
|
|
{
|
|
const float rayLength = 10000.0f;
|
|
AZ::Vector3 startNormal;
|
|
float tEnd;
|
|
float tStart;
|
|
const AZ::Vector3 scaledDir = dir * rayLength;
|
|
const AZ::Aabb aabb = GetEditorSelectionBoundsViewport(viewportInfo);
|
|
const int intersection = AZ::Intersect::IntersectRayAABB(
|
|
src, scaledDir, scaledDir.GetReciprocal(), aabb, tStart, tEnd, startNormal);
|
|
|
|
if (intersection == AZ::Intersect::RayAABBIsectTypes::ISECT_RAY_AABB_ISECT)
|
|
{
|
|
distance = tStart * rayLength;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool EditorJointComponent::GetBoolValue(const AZStd::string& parameterName)
|
|
{
|
|
if (parameterName == PhysX::EditorJointComponentMode::s_parameterComponentMode)
|
|
{
|
|
return m_config.m_inComponentMode;
|
|
}
|
|
else if (parameterName == PhysX::EditorJointComponentMode::s_parameterSelectOnSnap)
|
|
{
|
|
return m_config.m_selectLeadOnSnap;
|
|
}
|
|
AZ_Error("EditorJointComponent::GetBoolValue", false, "bool parameter not recognized: %s", parameterName.c_str());
|
|
return false;
|
|
}
|
|
|
|
AZ::EntityId EditorJointComponent::GetEntityIdValue(const AZStd::string& parameterName)
|
|
{
|
|
if (parameterName == PhysX::EditorJointComponentMode::s_parameterLeadEntity)
|
|
{
|
|
return m_config.m_leadEntity;
|
|
}
|
|
AZ_Error("EditorJointComponent::GetEntityIdValue", false, "EntityId parameter not recognized: %s", parameterName.c_str());
|
|
AZ::EntityId defaultEntityId;
|
|
defaultEntityId.SetInvalid();
|
|
return defaultEntityId;
|
|
}
|
|
|
|
float EditorJointComponent::GetLinearValue(const AZStd::string& parameterName)
|
|
{
|
|
if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxForce)
|
|
{
|
|
return m_config.m_forceMax;
|
|
}
|
|
else if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxTorque)
|
|
{
|
|
return m_config.m_torqueMax;
|
|
}
|
|
AZ_Error("EditorJointComponent::GetLinearValue", false, "Linear value parameter not recognized: %s", parameterName.c_str());
|
|
return 0.0f;
|
|
}
|
|
|
|
AngleLimitsFloatPair EditorJointComponent::GetLinearValuePair(const AZStd::string& parameterName)
|
|
{
|
|
AZ_UNUSED(parameterName);
|
|
AZ_Error("EditorJointComponent::GetLinearValuePair", false, "Linear value pair parameter not recognized: %s", parameterName.c_str());
|
|
return AngleLimitsFloatPair();
|
|
}
|
|
|
|
AZ::Transform EditorJointComponent::GetTransformValue(const AZStd::string& parameterName)
|
|
{
|
|
if (parameterName == PhysX::EditorJointComponentMode::s_parameterTransform)
|
|
{
|
|
return AZ::Transform::CreateFromQuaternionAndTranslation(AZ::Quaternion::CreateFromEulerAnglesDegrees(m_config.m_localRotation),
|
|
m_config.m_localPosition);
|
|
}
|
|
AZ_Error("EditorJointComponent::GetTransformValue", false, "Transform value parameter not recognized: %s", parameterName.c_str());
|
|
return AZ::Transform::CreateIdentity();
|
|
}
|
|
|
|
AZ::Vector3 EditorJointComponent::GetVector3Value(const AZStd::string& parameterName)
|
|
{
|
|
if (parameterName == PhysX::EditorJointComponentMode::s_parameterPosition)
|
|
{
|
|
return m_config.m_localPosition;
|
|
}
|
|
if (parameterName == PhysX::EditorJointComponentMode::s_parameterRotation)
|
|
{
|
|
return m_config.m_localRotation;
|
|
}
|
|
AZ_Error("EditorJointComponent::GetVector3Value", false, "Vector3 value parameter not recognized: %s", parameterName.c_str());
|
|
return AZ::Vector3::CreateZero();
|
|
}
|
|
|
|
bool EditorJointComponent::IsParameterUsed(const AZStd::string& parameterName)
|
|
{
|
|
if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxForce
|
|
|| parameterName == PhysX::EditorJointComponentMode::s_parameterMaxTorque
|
|
)
|
|
{
|
|
return m_config.m_breakable;
|
|
}
|
|
return true; // Sub-component mode always enabled unless disabled explicitly.
|
|
}
|
|
|
|
void EditorJointComponent::SetLinearValue(const AZStd::string& parameterName, float value)
|
|
{
|
|
if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxForce)
|
|
{
|
|
m_config.m_forceMax = value;
|
|
}
|
|
else if (parameterName == PhysX::EditorJointComponentMode::s_parameterMaxTorque)
|
|
{
|
|
m_config.m_torqueMax = value;
|
|
}
|
|
}
|
|
|
|
void EditorJointComponent::SetLinearValuePair(const AZStd::string& parameterName, const AngleLimitsFloatPair& valuePair)
|
|
{
|
|
AZ_UNUSED(parameterName);
|
|
AZ_UNUSED(valuePair);
|
|
}
|
|
|
|
void EditorJointComponent::SetVector3Value(const AZStd::string& parameterName, const AZ::Vector3& value)
|
|
{
|
|
if (parameterName == PhysX::EditorJointComponentMode::s_parameterPosition)
|
|
{
|
|
m_config.m_localPosition = value;
|
|
}
|
|
else if (parameterName == PhysX::EditorJointComponentMode::s_parameterRotation)
|
|
{
|
|
m_config.m_localRotation = value;
|
|
}
|
|
}
|
|
|
|
void EditorJointComponent::SetBoolValue(const AZStd::string& parameterName, bool value)
|
|
{
|
|
if (parameterName == PhysX::EditorJointComponentMode::s_parameterComponentMode)
|
|
{
|
|
m_config.m_inComponentMode = value;
|
|
|
|
AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(
|
|
&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay
|
|
, AzToolsFramework::Refresh_EntireTree);
|
|
}
|
|
else if (parameterName == PhysX::EditorJointComponentMode::s_parameterSelectOnSnap)
|
|
{
|
|
m_config.m_selectLeadOnSnap = value;
|
|
}
|
|
}
|
|
|
|
void EditorJointComponent::SetEntityIdValue(const AZStd::string& parameterName, AZ::EntityId value)
|
|
{
|
|
if (parameterName == PhysX::EditorJointComponentMode::s_parameterLeadEntity)
|
|
{
|
|
m_config.SetLeadEntityId(value);
|
|
}
|
|
}
|
|
|
|
void EditorJointComponent::DisplayEntityViewport(
|
|
const AzFramework::ViewportInfo& viewportInfo,
|
|
AzFramework::DebugDisplayRequests& debugDisplay)
|
|
{
|
|
AZ_UNUSED(viewportInfo);
|
|
|
|
auto* physXDebug = AZ::Interface<Debug::PhysXDebugInterface>::Get();
|
|
if (physXDebug == nullptr)
|
|
{
|
|
return;
|
|
}
|
|
|
|
const PhysX::Debug::DebugDisplayData& displayData = physXDebug->GetDebugDisplayData();
|
|
if (displayData.m_showJointHierarchy)
|
|
{
|
|
const AZ::Color leadLineColor = displayData.GetJointLeadColor();
|
|
const AZ::Color followerLineColor = displayData.GetJointFollowerColor();
|
|
|
|
const AZ::Transform followerWorldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_config.m_followerEntity);
|
|
const AZ::Vector3 followerWorldPosition = followerWorldTransform.GetTranslation();
|
|
|
|
const AZ::Transform jointLocalTransform = AZ::Transform::CreateFromQuaternionAndTranslation(AZ::Quaternion::CreateFromEulerAnglesDegrees(m_config.m_localRotation),
|
|
m_config.m_localPosition);
|
|
const AZ::Vector3 jointWorldPosition = PhysX::Utils::ComputeJointWorldTransform(jointLocalTransform, followerWorldTransform).GetTranslation();
|
|
|
|
const float distance = followerWorldPosition.GetDistance(jointWorldPosition);
|
|
|
|
const float lineWidth = 4.0f;
|
|
|
|
AZ::u32 stateBefore = debugDisplay.GetState();
|
|
debugDisplay.DepthTestOff();
|
|
debugDisplay.SetColor(leadLineColor);
|
|
debugDisplay.SetLineWidth(lineWidth);
|
|
|
|
if (m_config.m_leadEntity.IsValid() &&
|
|
distance < displayData.m_jointHierarchyDistanceThreshold)
|
|
{
|
|
const AZ::Transform leadWorldTransform = PhysX::Utils::GetEntityWorldTransformWithoutScale(m_config.m_leadEntity);
|
|
const AZ::Vector3 leadWorldPosition = leadWorldTransform.GetTranslation();
|
|
|
|
const AZ::Vector3 midPoint = (jointWorldPosition + leadWorldPosition) * 0.5f;
|
|
|
|
debugDisplay.DrawLine(jointWorldPosition, midPoint);
|
|
debugDisplay.SetColor(followerLineColor);
|
|
debugDisplay.DrawLine(midPoint, leadWorldPosition);
|
|
}
|
|
else
|
|
{
|
|
const AZ::Vector3 midPoint = (jointWorldPosition + followerWorldPosition) * 0.5f;
|
|
|
|
debugDisplay.DrawLine(jointWorldPosition, midPoint);
|
|
debugDisplay.SetColor(followerLineColor);
|
|
debugDisplay.DrawLine(midPoint, followerWorldPosition);
|
|
|
|
}
|
|
|
|
debugDisplay.SetState(stateBefore);
|
|
}
|
|
}
|
|
}
|