Files
o3de/Gems/PhysX/Code/Source/EditorJointComponent.cpp
T
Esteban Papp 1f9b284de2 Merge branch 'development' into cmake/SPEC-7179
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
2021-07-16 15:42:37 -07:00

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);
}
}
}