Merge branch 'development' into TIF/Runtime

This commit is contained in:
John
2021-06-18 10:15:04 +01:00
108 changed files with 2948 additions and 1819 deletions
@@ -0,0 +1,36 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzFramework/Physics/Common/PhysicsJoint.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzFramework/Physics/PhysicsScene.h>
#include <AzFramework/Physics/PhysicsSystem.h>
namespace AzPhysics
{
AZ_CLASS_ALLOCATOR_IMPL(Joint, AZ::SystemAllocator, 0);
void Joint::Reflect(AZ::ReflectContext* context)
{
if (auto* serializeContext = azdynamic_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<AzPhysics::Joint>()
->Version(1)
->Field("SceneOwner", &Joint::m_sceneOwner)
->Field("JointHandle", &Joint::m_jointHandle)
;
}
}
}
@@ -0,0 +1,143 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Math/Aabb.h>
#include <AzCore/Math/Crc.h>
#include <AzCore/Math/Quaternion.h>
#include <AzCore/Memory/Memory.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/std/containers/variant.h>
#include <AzCore/std/containers/vector.h>
#include <AzFramework/Physics/Common/PhysicsSimulatedBodyEvents.h>
#include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
#include <AzFramework/Physics/Common/PhysicsTypes.h>
namespace AZ
{
class ReflectContext;
}
namespace AzPhysics
{
struct JointConfiguration;
//! Base class for all Joints in Physics.
struct Joint
{
AZ_CLASS_ALLOCATOR_DECL;
AZ_RTTI(AzPhysics::Joint, "{1EEC9382-3434-4866-9B18-E93F151A6F59}");
static void Reflect(AZ::ReflectContext* context);
virtual ~Joint() = default;
//! The current Scene the joint is contained.
SceneHandle m_sceneOwner = AzPhysics::InvalidSceneHandle;
//! The handle to this joint.
JointHandle m_jointHandle = AzPhysics::InvalidJointHandle;
//! Helper functions for setting user data.
//! @param userData Can be a pointer to any type as internally will be cast to a void*. Object lifetime not managed by the Joint.
template<typename T>
void SetUserData(T* userData)
{
m_customUserData = static_cast<void*>(userData);
}
//! Helper functions for getting the set user data.
//! @return Will return a void* to the user data set.
void* GetUserData()
{
return m_customUserData;
}
virtual AZ::Crc32 GetNativeType() const = 0;
virtual void* GetNativePointer() const = 0;
virtual AzPhysics::SimulatedBodyHandle GetParentBodyHandle() const = 0;
virtual AzPhysics::SimulatedBodyHandle GetChildBodyHandle() const = 0;
virtual void SetParentBody(AzPhysics::SimulatedBodyHandle parentBody) = 0;
virtual void SetChildBody(AzPhysics::SimulatedBodyHandle childBody) = 0;
virtual void GenerateJointLimitVisualizationData(
[[ maybe_unused ]] float scale,
[[ maybe_unused ]] AZ::u32 angularSubdivisions,
[[ maybe_unused ]] AZ::u32 radialSubdivisions,
[[ maybe_unused ]] AZStd::vector<AZ::Vector3>& vertexBufferOut,
[[ maybe_unused ]] AZStd::vector<AZ::u32>& indexBufferOut,
[[ maybe_unused ]] AZStd::vector<AZ::Vector3>& lineBufferOut,
[[ maybe_unused ]] AZStd::vector<bool>& lineValidityBufferOut) { }
private:
void* m_customUserData = nullptr;
};
//! Alias for a list of non owning weak pointers to Joint objects.
using JointList = AZStd::vector<Joint*>;
//! Interface to access Joint utilities and helper functions
class JointHelpersInterface
{
public:
AZ_RTTI(AzPhysics::JointHelpersInterface, "{A511C64D-C8A5-4E8F-9C69-8DC5EFAD0C4C}");
JointHelpersInterface() = default;
virtual ~JointHelpersInterface() = default;
AZ_DISABLE_COPY_MOVE(JointHelpersInterface);
//! Returns a list of supported Joint types
virtual const AZStd::vector<AZ::TypeId> GetSupportedJointTypeIds() const = 0;
//! Returns a TypeID if the request joint type is supported.
//! If the Physics backend supports this joint type JointHelpersInterface::GetSupportedJointTypeId will return a AZ::TypeId.
virtual AZStd::optional<const AZ::TypeId> GetSupportedJointTypeId(JointType typeEnum) const = 0;
//! Computes parameters such as joint limit local rotations to give the desired initial joint limit orientation.
//! @param jointLimitTypeId The type ID used to identify the particular kind of joint limit configuration to be created.
//! @param parentWorldRotation The rotation in world space of the parent world body associated with the joint.
//! @param childWorldRotation The rotation in world space of the child world body associated with the joint.
//! @param axis Axis used to define the centre for limiting angular degrees of freedom.
//! @param exampleLocalRotations A vector (which may be empty) containing example valid rotations in the local space
//! of the child world body relative to the parent world body, which may optionally be used to help estimate the extents
//! of the joint limit.
virtual AZStd::unique_ptr<JointConfiguration> ComputeInitialJointLimitConfiguration(
const AZ::TypeId& jointLimitTypeId,
const AZ::Quaternion& parentWorldRotation,
const AZ::Quaternion& childWorldRotation,
const AZ::Vector3& axis,
const AZStd::vector<AZ::Quaternion>& exampleLocalRotations) = 0;
/// Generates joint limit visualization data in appropriate format to pass to DebugDisplayRequests draw functions.
/// @param configuration The joint configuration to generate visualization data for.
/// @param parentRotation The rotation of the joint's parent body (in the same frame as childRotation).
/// @param childRotation The rotation of the joint's child body (in the same frame as parentRotation).
/// @param scale Scale factor for the output display data.
/// @param angularSubdivisions Level of detail in the angular direction (may be clamped in the implementation).
/// @param radialSubdivisions Level of detail in the radial direction (may be clamped in the implementation).
/// @param[out] vertexBufferOut Used with indexBufferOut to define triangles to be displayed.
/// @param[out] indexBufferOut Used with vertexBufferOut to define triangles to be displayed.
/// @param[out] lineBufferOut Used to define lines to be displayed.
/// @param[out] lineValidityBufferOut Whether each line in the line buffer is part of a valid or violated limit.
virtual void GenerateJointLimitVisualizationData(
const JointConfiguration& configuration,
const AZ::Quaternion& parentRotation,
const AZ::Quaternion& childRotation,
float scale,
AZ::u32 angularSubdivisions,
AZ::u32 radialSubdivisions,
AZStd::vector<AZ::Vector3>& vertexBufferOut,
AZStd::vector<AZ::u32>& indexBufferOut,
AZStd::vector<AZ::Vector3>& lineBufferOut,
AZStd::vector<bool>& lineValidityBufferOut) = 0;
};
}
@@ -51,8 +51,10 @@ namespace AzPhysics
using SceneIndex = AZ::s8;
using SimulatedBodyIndex = AZ::s32;
using JointIndex = AZ::s32;
static_assert(std::is_signed<SceneIndex>::value
&& std::is_signed<SimulatedBodyIndex>::value, "SceneIndex and SimulatedBodyIndex must be signed integers.");
&& std::is_signed<SimulatedBodyIndex>::value
&& std::is_signed<JointIndex>::value, "SceneIndex, SimulatedBodyIndex and JointIndex must be signed integers.");
//! A handle to a Scene within the physics simulation.
@@ -69,12 +71,27 @@ namespace AzPhysics
static constexpr SimulatedBodyHandle InvalidSimulatedBodyHandle = { AZ::Crc32(), -1 };
using SimulatedBodyHandleList = AZStd::vector<SimulatedBodyHandle>;
//! A handle to a Joint within a physics scene.
//! A JointHandle is a tuple of a Crc of the scene's name and the index in the Joint list.
using JointHandle = AZStd::tuple<AZ::Crc32, JointIndex>;
static constexpr JointHandle InvalidJointHandle = { AZ::Crc32(), -1 };
//! Helper used for pairing the ShapeConfiguration and ColliderConfiguration together which is used when creating a Simulated Body.
using ShapeColliderPair = AZStd::pair<
AZStd::shared_ptr<Physics::ColliderConfiguration>,
AZStd::shared_ptr<Physics::ShapeConfiguration>>;
using ShapeColliderPairList = AZStd::vector<ShapeColliderPair>;
//! Joint types are used to request for AZ::TypeId with the JointHelpersInterface::GetSupportedJointTypeId.
//! If the Physics backend supports this joint type JointHelpersInterface::GetSupportedJointTypeId will return a AZ::TypeId.
enum class JointType
{
D6Joint,
FixedJoint,
BallJoint,
HingeJoint
};
//! Flags used to specifying which properties of a body to compute.
enum class MassComputeFlags : AZ::u8
{
@@ -0,0 +1,37 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzFramework/Physics/Configuration/JointConfiguration.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace AzPhysics
{
AZ_CLASS_ALLOCATOR_IMPL(JointConfiguration, AZ::SystemAllocator, 0);
void JointConfiguration::Reflect(AZ::ReflectContext* context)
{
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<JointConfiguration>()
->Version(1)
->Field("Name", &JointConfiguration::m_debugName)
->Field("ParentLocalRotation", &JointConfiguration::m_parentLocalRotation)
->Field("ParentLocalPosition", &JointConfiguration::m_parentLocalPosition)
->Field("ChildLocalRotation", &JointConfiguration::m_childLocalRotation)
->Field("ChildLocalPosition", &JointConfiguration::m_childLocalPosition)
->Field("StartSimulationEnabled", &JointConfiguration::m_startSimulationEnabled)
;
}
}
}
@@ -0,0 +1,51 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Component/EntityId.h>
#include <AzCore/Math/Quaternion.h>
#include <AzCore/Math/Vector3.h>
#include <AzCore/Memory/Memory.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzCore/std/containers/vector.h>
namespace AZ
{
class ReflectContext;
}
namespace AzPhysics
{
//! Base Class of all Physics Joints that will be simulated.
struct JointConfiguration
{
AZ_CLASS_ALLOCATOR_DECL;
AZ_RTTI(AzPhysics::JointConfiguration, "{DF91D39A-4901-48C4-9159-93FD2ACA5252}");
static void Reflect(AZ::ReflectContext* context);
JointConfiguration() = default;
virtual ~JointConfiguration() = default;
// Entity/object association.
void* m_customUserData = nullptr;
// Basic initial settings.
AZ::Quaternion m_parentLocalRotation = AZ::Quaternion::CreateIdentity(); ///< Parent joint frame relative to parent body.
AZ::Vector3 m_parentLocalPosition = AZ::Vector3::CreateZero(); ///< Joint position relative to parent body.
AZ::Quaternion m_childLocalRotation = AZ::Quaternion::CreateIdentity(); ///< Child joint frame relative to child body.
AZ::Vector3 m_childLocalPosition = AZ::Vector3::CreateZero(); ///< Joint position relative to child body.
bool m_startSimulationEnabled = true;
// For debugging/tracking purposes only.
AZStd::string m_debugName;
};
}
@@ -1,56 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzFramework/Physics/Joint.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
namespace Physics
{
const char* JointLimitConfiguration::GetTypeName()
{
return "Base Joint";
}
void JointLimitConfiguration::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<JointLimitConfiguration>()
->Version(1)
->Field("ParentLocalRotation", &JointLimitConfiguration::m_parentLocalRotation)
->Field("ParentLocalPosition", &JointLimitConfiguration::m_parentLocalPosition)
->Field("ChildLocalRotation", &JointLimitConfiguration::m_childLocalRotation)
->Field("ChildLocalPosition", &JointLimitConfiguration::m_childLocalPosition)
;
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<JointLimitConfiguration>(
"Joint Configuration", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &JointLimitConfiguration::m_parentLocalRotation,
"Parent local rotation", "The rotation of the parent joint frame relative to the parent body")
->DataElement(AZ::Edit::UIHandlers::Default, &JointLimitConfiguration::m_parentLocalPosition,
"Parent local position", "The position of the joint in the frame of the parent body")
->DataElement(AZ::Edit::UIHandlers::Default, &JointLimitConfiguration::m_childLocalRotation,
"Child local rotation", "The rotation of the child joint frame relative to the child body")
->DataElement(AZ::Edit::UIHandlers::Default, &JointLimitConfiguration::m_childLocalPosition,
"Child local position", "The position of the joint in the frame of the child body")
;
}
}
}
} // namespace Physics
@@ -1,75 +0,0 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#pragma once
#include <AzCore/Math/Transform.h>
#include <AzCore/Serialization/SerializeContext.h>
namespace AzPhysics
{
struct SimulatedBody;
}
namespace Physics
{
class JointLimitConfiguration
{
public:
AZ_CLASS_ALLOCATOR(JointLimitConfiguration, AZ::SystemAllocator, 0);
AZ_RTTI(JointLimitConfiguration, "{C9B70C4D-22D7-45AB-9B0A-30A4ED5E42DB}");
static void Reflect(AZ::ReflectContext* context);
JointLimitConfiguration() = default;
JointLimitConfiguration(const JointLimitConfiguration&) = default;
virtual ~JointLimitConfiguration() = default;
virtual const char* GetTypeName();
AZ::Quaternion m_parentLocalRotation = AZ::Quaternion::CreateIdentity(); ///< Parent joint frame relative to parent body.
AZ::Vector3 m_parentLocalPosition = AZ::Vector3::CreateZero(); ///< Joint position relative to parent body.
AZ::Quaternion m_childLocalRotation = AZ::Quaternion::CreateIdentity(); ///< Child joint frame relative to child body.
AZ::Vector3 m_childLocalPosition = AZ::Vector3::CreateZero(); ///< Joint position relative to child body.
};
class Joint
{
public:
AZ_CLASS_ALLOCATOR(Joint, AZ::SystemAllocator, 0);
AZ_RTTI(Joint, "{405F517C-E986-4ACB-9606-D5D080DDE987}");
virtual AzPhysics::SimulatedBody* GetParentBody() const = 0;
virtual AzPhysics::SimulatedBody* GetChildBody() const = 0;
virtual void SetParentBody(AzPhysics::SimulatedBody* parentBody) = 0;
virtual void SetChildBody(AzPhysics::SimulatedBody* childBody) = 0;
virtual const AZStd::string& GetName() const = 0;
virtual void SetName(const AZStd::string& name) = 0;
virtual const AZ::Crc32 GetNativeType() const = 0;
virtual void* GetNativePointer() = 0;
/// Generates joint limit visualization data in appropriate format to pass to DebugDisplayRequests draw functions.
/// @param scale Scale factor for the output display data.
/// @param angularSubdivisions Level of detail in the angular direction (may be clamped in the implementation).
/// @param radialSubdivisions Level of detail in the radial direction (may be clamped in the implementation).
/// @param[out] vertexBufferOut Used with indexBufferOut to define triangles to be displayed.
/// @param[out] indexBufferOut Used with vertexBufferOut to define triangles to be displayed.
/// @param[out] lineBufferOut Used to define lines to be displayed.
/// @param[out] lineValidityBufferOut Whether each line in the line buffer is part of a valid or violated limit.
virtual void GenerateJointLimitVisualizationData(
float scale,
AZ::u32 angularSubdivisions,
AZ::u32 radialSubdivisions,
AZStd::vector<AZ::Vector3>& vertexBufferOut,
AZStd::vector<AZ::u32>& indexBufferOut,
AZStd::vector<AZ::Vector3>& lineBufferOut,
AZStd::vector<bool>& lineValidityBufferOut) = 0;
};
} // namespace Physics
@@ -16,6 +16,8 @@
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
#include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
#include <AzFramework/Physics/Common/PhysicsTypes.h>
#include <AzFramework/Physics/Common/PhysicsJoint.h>
#include <AzFramework/Physics/Configuration/JointConfiguration.h>
#include <AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h>
namespace AzPhysics
@@ -103,6 +105,26 @@ namespace AzPhysics
virtual void EnableSimulationOfBody(SceneHandle sceneHandle, SimulatedBodyHandle bodyHandle) = 0;
virtual void DisableSimulationOfBody(SceneHandle sceneHandle, SimulatedBodyHandle bodyHandle) = 0;
//! Add a joint to the Scene.
//! @param sceneHandle A handle to the scene to add / remove the joint.
//! @param jointConfig The config of the joint.
//! @param parentBody The parent body of the joint.
//! @param childBody The child body of the joint
//! @return Returns a handle to the created joint. Will return AzPhyiscs::InvalidJointHandle if it fails.
virtual JointHandle AddJoint(SceneHandle sceneHandle, const JointConfiguration* jointConfig,
SimulatedBodyHandle parentBody, SimulatedBodyHandle childBody) = 0;
//! Get the Raw pointer to the requested joint.
//! @param sceneHandle A handle to the scene to get the simulated bodies from.
//! @param jointHandle A handle to the joint to retrieve the raw pointer.
//! @return A raw pointer to the Joint body. If the either handle is invalid this will return null.
virtual Joint* GetJointFromHandle(SceneHandle sceneHandle, JointHandle jointHandle) = 0;
//! Remove a joint from the Scene.
//! @param sceneHandle A handle to the scene to add / remove the joint.
//! @param jointHandle A handle to the joint being removed.
virtual void RemoveJoint(SceneHandle sceneHandle, JointHandle jointHandle) = 0;
//! Make a blocking query into the scene.
//! @param sceneHandle A handle to the scene to make the scene query with.
//! @param request The request to make. Should be one of RayCastRequest || ShapeCastRequest || OverlapRequest
@@ -299,6 +321,23 @@ namespace AzPhysics
virtual void EnableSimulationOfBody(SimulatedBodyHandle bodyHandle) = 0;
virtual void DisableSimulationOfBody(SimulatedBodyHandle bodyHandle) = 0;
//! Add a joint to the Scene.
//! @param jointConfig The config of the joint.
//! @param parentBody The parent body of the joint.
//! @param childBody The child body of the joint
//! @return Returns a handle to the created joint. Will return AzPhyiscs::InvalidJointHandle if it fails.
virtual JointHandle AddJoint(const JointConfiguration* jointConfig,
SimulatedBodyHandle parentBody, SimulatedBodyHandle childBody) = 0;
//! Get the Raw pointer to the requested joint.
//! @param jointHandle A handle to the joint to retrieve the raw pointer.
//! @return A raw pointer to the Joint body. If the either handle is invalid this will return null.
virtual Joint* GetJointFromHandle(JointHandle jointHandle) = 0;
//! Remove a joint from the Scene.
//! @param jointHandle A handle to the joint being removed.
virtual void RemoveJoint(JointHandle jointHandle) = 0;
//! Make a blocking query into the scene.
//! @param request The request to make. Should be one of RayCastRequest || ShapeCastRequest || OverlapRequest
//! @return Returns a structure that contains a list of Hits. Depending on flags set in the request, this may only contain 1 result.
@@ -36,8 +36,8 @@ namespace Physics
if (serializeContext)
{
serializeContext->Class<RagdollNodeConfiguration, RigidBodyConfiguration>()
->Version(4, &ClassConverters::RagdollNodeConfigConverter)
->Field("JointLimit", &RagdollNodeConfiguration::m_jointLimit)
->Version(5, &ClassConverters::RagdollNodeConfigConverter)
->Field("JointConfig", &RagdollNodeConfiguration::m_jointConfig)
;
AZ::EditContext* editContext = serializeContext->GetEditContext();
@@ -17,10 +17,11 @@
#include <AzFramework/Physics/Shape.h>
#include <AzFramework/Physics/SimulatedBodies/RigidBody.h>
#include <AzFramework/Physics/RagdollPhysicsBus.h>
#include <AzFramework/Physics/Joint.h>
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
#include <AzFramework/Physics/Common/PhysicsJoint.h>
#include <AzFramework/Physics/Configuration/RigidBodyConfiguration.h>
#include <AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h>
#include <AzFramework/Physics/Configuration/JointConfiguration.h>
namespace Physics
{
@@ -37,7 +38,7 @@ namespace Physics
RagdollNodeConfiguration();
RagdollNodeConfiguration(const RagdollNodeConfiguration& settings) = default;
AZStd::shared_ptr<JointLimitConfiguration> m_jointLimit;
AZStd::shared_ptr<AzPhysics::JointConfiguration> m_jointConfig;
};
class RagdollConfiguration
@@ -73,7 +74,7 @@ namespace Physics
virtual AzPhysics::RigidBody& GetRigidBody() = 0;
virtual ~RagdollNode() = default;
virtual const AZStd::shared_ptr<Physics::Joint>& GetJoint() const = 0;
virtual AzPhysics::Joint* GetJoint() = 0;
virtual bool IsSimulating() const = 0;
};
@@ -26,23 +26,15 @@ namespace AZ
namespace AzPhysics
{
struct SimulatedBody;
struct RigidBodyConfiguration;
struct RigidBody;
}
namespace Physics
{
class WorldBody;
class Shape;
class Material;
class MaterialSelection;
class MaterialConfiguration;
class ColliderConfiguration;
class ShapeConfiguration;
class JointLimitConfiguration;
class Joint;
class CharacterConfiguration;
class Character;
/// Represents a debug vertex (position & color).
struct DebugDrawVertex
@@ -148,51 +140,6 @@ namespace Physics
/// @param nativeMeshObject Pointer to the mesh object.
virtual void ReleaseNativeMeshObject(void* nativeMeshObject) = 0;
//////////////////////////////////////////////////////////////////////////
//// Joints
virtual AZStd::vector<AZ::TypeId> GetSupportedJointTypes() = 0;
virtual AZStd::shared_ptr<JointLimitConfiguration> CreateJointLimitConfiguration(AZ::TypeId jointType) = 0;
virtual AZStd::shared_ptr<Joint> CreateJoint(const AZStd::shared_ptr<JointLimitConfiguration>& configuration,
AzPhysics::SimulatedBody* parentBody, AzPhysics::SimulatedBody* childBody) = 0;
/// Generates joint limit visualization data in appropriate format to pass to DebugDisplayRequests draw functions.
/// @param configuration The joint configuration to generate visualization data for.
/// @param parentRotation The rotation of the joint's parent body (in the same frame as childRotation).
/// @param childRotation The rotation of the joint's child body (in the same frame as parentRotation).
/// @param scale Scale factor for the output display data.
/// @param angularSubdivisions Level of detail in the angular direction (may be clamped in the implementation).
/// @param radialSubdivisions Level of detail in the radial direction (may be clamped in the implementation).
/// @param[out] vertexBufferOut Used with indexBufferOut to define triangles to be displayed.
/// @param[out] indexBufferOut Used with vertexBufferOut to define triangles to be displayed.
/// @param[out] lineBufferOut Used to define lines to be displayed.
/// @param[out] lineValidityBufferOut Whether each line in the line buffer is part of a valid or violated limit.
virtual void GenerateJointLimitVisualizationData(
const JointLimitConfiguration& configuration,
const AZ::Quaternion& parentRotation,
const AZ::Quaternion& childRotation,
float scale,
AZ::u32 angularSubdivisions,
AZ::u32 radialSubdivisions,
AZStd::vector<AZ::Vector3>& vertexBufferOut,
AZStd::vector<AZ::u32>& indexBufferOut,
AZStd::vector<AZ::Vector3>& lineBufferOut,
AZStd::vector<bool>& lineValidityBufferOut) = 0;
/// Computes parameters such as joint limit local rotations to give the desired initial joint limit orientation.
/// @param jointLimitTypeId The type ID used to identify the particular kind of joint limit configuration to be created.
/// @param parentWorldRotation The rotation in world space of the parent world body associated with the joint.
/// @param childWorldRotation The rotation in world space of the child world body associated with the joint.
/// @param axis Axis used to define the centre for limiting angular degrees of freedom.
/// @param exampleLocalRotations A vector (which may be empty) containing example valid rotations in the local space
/// of the child world body relative to the parent world body, which may optionally be used to help estimate the extents
/// of the joint limit.
virtual AZStd::unique_ptr<JointLimitConfiguration> ComputeInitialJointLimitConfiguration(
const AZ::TypeId& jointLimitTypeId,
const AZ::Quaternion& parentWorldRotation,
const AZ::Quaternion& childWorldRotation,
const AZ::Vector3& axis,
const AZStd::vector<AZ::Quaternion>& exampleLocalRotations) = 0;
//////////////////////////////////////////////////////////////////////////
//// Cooking
@@ -34,6 +34,7 @@
#include <AzFramework/Physics/Configuration/SceneConfiguration.h>
#include <AzFramework/Physics/Configuration/SimulatedBodyConfiguration.h>
#include <AzFramework/Physics/SimulatedBodies/RigidBody.h>
#include <AzFramework/Physics/Common/PhysicsJoint.h>
namespace Physics
{
@@ -121,9 +122,9 @@ namespace Physics
DefaultMaterialConfiguration::Reflect(context);
MaterialLibraryAsset::Reflect(context);
MaterialInfoReflectionWrapper::Reflect(context);
JointLimitConfiguration::Reflect(context);
AzPhysics::SimulatedBodyConfiguration::Reflect(context);
AzPhysics::RigidBodyConfiguration::Reflect(context);
AzPhysics::JointConfiguration::Reflect(context);
RagdollNodeConfiguration::Reflect(context);
RagdollConfiguration::Reflect(context);
CharacterColliderNodeConfiguration::Reflect(context);
@@ -131,6 +132,7 @@ namespace Physics
AnimationConfiguration::Reflect(context);
CharacterConfiguration::Reflect(context);
AzPhysics::SimulatedBody::Reflect(context);
AzPhysics::Joint::Reflect(context);
ReflectSimulatedBodyComponentRequestsBus(context);
CollisionFilteringRequests::Reflect(context);
AzPhysics::SceneQuery::ReflectSceneQueryObjects(context);
@@ -204,6 +204,8 @@ set(FILES
Physics/Collision/CollisionLayers.cpp
Physics/Collision/CollisionGroups.h
Physics/Collision/CollisionGroups.cpp
Physics/Common/PhysicsJoint.h
Physics/Common/PhysicsJoint.cpp
Physics/Common/PhysicsSceneQueries.h
Physics/Common/PhysicsSceneQueries.cpp
Physics/Common/PhysicsEvents.h
@@ -215,6 +217,8 @@ set(FILES
Physics/Common/PhysicsSimulatedBodyEvents.cpp
Physics/Common/PhysicsTypes.h
Physics/Components/SimulatedBodyComponentBus.h
Physics/Configuration/JointConfiguration.h
Physics/Configuration/JointConfiguration.cpp
Physics/Configuration/CollisionConfiguration.h
Physics/Configuration/CollisionConfiguration.cpp
Physics/Configuration/RigidBodyConfiguration.h
@@ -259,8 +263,6 @@ set(FILES
Physics/Ragdoll.h
Physics/Utils.h
Physics/Utils.cpp
Physics/Joint.h
Physics/Joint.cpp
Physics/ClassConverters.cpp
Physics/ClassConverters.h
Physics/MaterialBus.h
@@ -210,6 +210,15 @@ namespace AzToolsFramework
//! Type to inherit to implement ViewportInteractionRequests.
using ViewportInteractionRequestBus = AZ::EBus<ViewportInteractionRequests, ViewportEBusTraits>;
//! An interface to notify when changes to viewport settings have happened.
class ViewportSettingNotifications
{
public:
virtual void OnGridSnappingChanged(bool enabled) = 0;
};
using ViewportSettingsNotificationBus = AZ::EBus<ViewportSettingNotifications, ViewportEBusTraits>;
//! Requests to freeze the Viewport Input
//! Added to prevent a bug with the legacy CryEngine Viewport code that would
//! keep doing raycast tests even when no level is loaded, causing a crash.
@@ -489,6 +489,16 @@ namespace AzToolsFramework
return buttonId;
}
void SnappingCluster::TrySetVisible(const bool visible)
{
bool snapping = false;
ViewportInteraction::ViewportInteractionRequestBus::EventResult(
snapping, ViewportUi::DefaultViewportId, &ViewportInteraction::ViewportInteractionRequestBus::Events::GridSnappingEnabled);
// show snapping viewport ui only if there are entities selected and snapping is enabled
SetViewportUiClusterVisible(m_clusterId, visible && snapping);
}
// return either center or entity pivot
static AZ::Vector3 CalculatePivotTranslation(const AZ::EntityId entityId, const EditorTransformComponentSelectionRequests::Pivot pivot)
{
@@ -1035,6 +1045,7 @@ namespace AzToolsFramework
EditorEntityLockComponentNotificationBus::Router::BusRouterConnect();
EditorManipulatorCommandUndoRedoRequestBus::Handler::BusConnect(entityContextId);
EditorContextMenuBus::Handler::BusConnect();
ViewportInteraction::ViewportSettingsNotificationBus::Handler::BusConnect(ViewportUi::DefaultViewportId);
CreateTransformModeSelectionCluster();
CreateSpaceSelectionCluster();
@@ -1058,6 +1069,7 @@ namespace AzToolsFramework
m_pivotOverrideFrame.Reset();
ViewportInteraction::ViewportSettingsNotificationBus::Handler::BusDisconnect();
EditorContextMenuBus::Handler::BusConnect();
EditorManipulatorCommandUndoRedoRequestBus::Handler::BusDisconnect();
EditorEntityLockComponentNotificationBus::Router::BusRouterDisconnect();
@@ -3253,7 +3265,7 @@ namespace AzToolsFramework
m_didSetSelectedEntities = false;
}
SetViewportUiClusterVisible(m_snappingCluster.m_clusterId, m_viewportUiVisible && !m_selectedEntityIds.empty());
m_snappingCluster.TrySetVisible(m_viewportUiVisible && !m_selectedEntityIds.empty());
RegenerateManipulators();
}
@@ -3717,6 +3729,11 @@ namespace AzToolsFramework
SetAllViewportUiVisible(true);
}
void EditorTransformComponentSelection::OnGridSnappingChanged([[maybe_unused]] const bool enabled)
{
m_snappingCluster.TrySetVisible(m_viewportUiVisible && !m_selectedEntityIds.empty());
}
namespace ETCS
{
// little raii wrapper to switch a value from true to false and back
@@ -131,6 +131,9 @@ namespace AzToolsFramework
SnappingCluster(const SnappingCluster&) = delete;
SnappingCluster& operator=(const SnappingCluster&) = delete;
//! Attempt to show the snapping cluster (will only succeed if snapping is enabled).
void TrySetVisible(bool visible);
ViewportUi::ClusterId m_clusterId; //!< The cluster id for all snapping buttons.
ViewportUi::ButtonId m_snapToWorldButtonId; //!< The button id for snapping all axes to the world.
AZ::Event<ViewportUi::ButtonId>::Handler m_snappingHandler; //!< Callback for when a snapping cluster button is pressed.
@@ -151,6 +154,7 @@ namespace AzToolsFramework
, private EditorEntityLockComponentNotificationBus::Router
, private EditorManipulatorCommandUndoRedoRequestBus::Handler
, private AZ::TransformNotificationBus::MultiHandler
, private ViewportInteraction::ViewportSettingsNotificationBus::Handler
{
public:
AZ_CLASS_ALLOCATOR_DECL
@@ -289,6 +293,9 @@ namespace AzToolsFramework
void OnStartPlayInEditor() override;
void OnStopPlayInEditor() override;
// ViewportSettingsNotificationBus overrides ...
void OnGridSnappingChanged(bool enabled) override;
// Helpers to safely interact with the TransformBus (requests).
void SetEntityWorldTranslation(AZ::EntityId entityId, const AZ::Vector3& worldTranslation);
void SetEntityLocalTranslation(AZ::EntityId entityId, const AZ::Vector3& localTranslation);
@@ -24,8 +24,6 @@
namespace AzToolsFramework::ViewportUi::Internal
{
// margin for the Viewport UI Overlay in pixels
const static int ViewportUiOverlayMargin = 5;
const static int HighlightBorderSize = 5;
const static int TopHighlightBorderSize = 25;
const static char* HighlightBorderColor = "#44B2F8";
@@ -387,7 +385,6 @@ namespace AzToolsFramework::ViewportUi::Internal
m_fullScreenLayout.setSpacing(0);
m_fullScreenLayout.setContentsMargins(0, 0, 0, 0);
m_fullScreenLayout.addLayout(&m_uiOverlayLayout, 0, 0, 1, 1);
m_uiOverlayLayout.setMargin(ViewportUiOverlayMargin);
// format the label which will appear on top of the highlight border
AZStd::string styleSheet = AZStd::string::format(
@@ -25,13 +25,15 @@ namespace AzToolsFramework::ViewportUi::Internal
: QGridLayout(parent)
{
// set margins and spacing for internal contents
setContentsMargins(0, 0, 0, 0);
setContentsMargins(
ViewportUiOverlayMargin, ViewportUiOverlayMargin + ViewportUiOverlayTopMarginPadding, ViewportUiOverlayMargin,
ViewportUiOverlayMargin);
setSpacing(ViewportUiDisplayLayoutSpacing);
// create a 3x2 map of sub layouts which will stack widgets according to their mapped alignment
m_internalLayouts = AZStd::unordered_map<Qt::Alignment, QBoxLayout*> {
CreateSubLayout(new QVBoxLayout(), 0, 0, Qt::AlignTop | Qt::AlignLeft),
CreateSubLayout(new QHBoxLayout(), 1, 0, Qt::AlignBottom | Qt::AlignLeft),
CreateSubLayout(new QVBoxLayout(), 1, 0, Qt::AlignBottom | Qt::AlignLeft),
CreateSubLayout(new QVBoxLayout(), 0, 1, Qt::AlignTop),
CreateSubLayout(new QHBoxLayout(), 1, 1, Qt::AlignBottom),
CreateSubLayout(new QVBoxLayout(), 0, 2, Qt::AlignTop | Qt::AlignRight),
@@ -50,9 +52,42 @@ namespace AzToolsFramework::ViewportUi::Internal
if (auto layoutForAlignment = m_internalLayouts.find(alignment);
layoutForAlignment != m_internalLayouts.end())
{
// place the widget before the invisible spacer
// spacer must be last item in layout to not interfere with positioning
int index = layoutForAlignment->second->count() - 1;
// place the widget before or after the invisible spacer
// depending on the layout alignment
int index = 0;
switch (alignment)
{
case Qt::AlignTop | Qt::AlignLeft:
case Qt::AlignTop:
index = layoutForAlignment->second->count() - 1;
break;
case Qt::AlignBottom | Qt::AlignRight:
case Qt::AlignBottom:
index = layoutForAlignment->second->count();
break;
// TopRight and BottomLeft are special cases
// place the spacer differently according to whether it's a vertical or horizontal layout
case Qt::AlignTop | Qt::AlignRight:
if (QVBoxLayout* vLayout = qobject_cast<QVBoxLayout*>(layoutForAlignment->second))
{
index = layoutForAlignment->second->count() - 1;
}
else if (QHBoxLayout* hLayout = qobject_cast<QHBoxLayout*>(layoutForAlignment->second))
{
index = layoutForAlignment->second->count();
}
break;
case Qt::AlignBottom | Qt::AlignLeft:
if (QVBoxLayout* vLayout = qobject_cast<QVBoxLayout*>(layoutForAlignment->second))
{
index = layoutForAlignment->second->count();
}
else if (QHBoxLayout* hLayout = qobject_cast<QHBoxLayout*>(layoutForAlignment->second))
{
index = layoutForAlignment->second->count() - 1;
}
break;
}
layoutForAlignment->second->insertWidget(index, widget);
}
}
@@ -19,6 +19,11 @@
namespace AzToolsFramework::ViewportUi::Internal
{
// margin for the Viewport UI Overlay in pixels
constexpr int ViewportUiOverlayMargin = 5;
// padding to make space for ImGui
constexpr int ViewportUiOverlayTopMarginPadding = 20;
//! QGridLayout implementation that uses a grid of QVBox/QHBoxLayouts internally to stack widgets.
class ViewportUiDisplayLayout : public QGridLayout
{
@@ -14,6 +14,7 @@
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/std/string/string_view.h>
namespace SandboxEditor
@@ -56,6 +57,39 @@ namespace SandboxEditor
return value;
}
struct EditorViewportSettingsCallbacksImpl : public EditorViewportSettingsCallbacks
{
EditorViewportSettingsCallbacksImpl()
{
if (auto* registry = AZ::SettingsRegistry::Get())
{
using AZ::SettingsRegistryMergeUtils::IsPathAncestorDescendantOrEqual;
m_notifyEventHandler = registry->RegisterNotifier(
[this](const AZStd::string_view path, [[maybe_unused]] const AZ::SettingsRegistryInterface::Type type)
{
if (IsPathAncestorDescendantOrEqual(GridSnappingSetting, path))
{
m_gridSnappingChanged.Signal(GridSnappingEnabled());
}
});
}
}
void SetGridSnappingChangedEvent(GridSnappingChangedEvent::Handler& handler) override
{
handler.Connect(m_gridSnappingChanged);
}
GridSnappingChangedEvent m_gridSnappingChanged;
AZ::SettingsRegistryInterface::NotifyEventHandler m_notifyEventHandler;
};
AZStd::unique_ptr<EditorViewportSettingsCallbacks> CreateEditorViewportSettingsCallbacks()
{
return AZStd::make_unique<EditorViewportSettingsCallbacksImpl>();
}
bool GridSnappingEnabled()
{
return GetRegistry(GridSnappingSetting, false);
@@ -14,8 +14,27 @@
#include <SandboxAPI.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <AzCore/std/smart_ptr/unique_ptr.h>
namespace SandboxEditor
{
using GridSnappingChangedEvent = AZ::Event<bool>;
//! Set callbacks to listen for editor settings change events.
class EditorViewportSettingsCallbacks
{
public:
virtual ~EditorViewportSettingsCallbacks() = default;
virtual void SetGridSnappingChangedEvent(GridSnappingChangedEvent::Handler& handler) = 0;
};
//! Create an instance of EditorViewportSettingsCallbacks
//! Note: EditorViewportSettingsCallbacks is implemented in EditorViewportSettings.cpp - a change
//! event will fire when a value in the settings registry (editorpreferences.setreg) is modified.
SANDBOX_API AZStd::unique_ptr<EditorViewportSettingsCallbacks> CreateEditorViewportSettingsCallbacks();
SANDBOX_API bool GridSnappingEnabled();
SANDBOX_API void SetGridSnapping(bool enabled);
+11 -1
View File
@@ -76,7 +76,6 @@
#include "EditorPreferencesPageGeneral.h"
#include "ViewportManipulatorController.h"
#include "LegacyViewportCameraController.h"
#include "EditorViewportSettings.h"
#include "ViewPane.h"
#include "CustomResolutionDlg.h"
@@ -1450,6 +1449,17 @@ void EditorViewportWidget::SetViewportId(int id)
{
SetAsActiveViewport();
}
m_editorViewportSettingsCallbacks = SandboxEditor::CreateEditorViewportSettingsCallbacks();
m_gridSnappingHandler = SandboxEditor::GridSnappingChangedEvent::Handler(
[id](const bool snapping)
{
AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Event(
id, &AzToolsFramework::ViewportInteraction::ViewportSettingsNotificationBus::Events::OnGridSnappingChanged, snapping);
});
m_editorViewportSettingsCallbacks->SetGridSnappingChangedEvent(m_gridSnappingHandler);
}
void EditorViewportWidget::ConnectViewportInteractionRequestBus()
@@ -24,6 +24,7 @@
#include "Objects/DisplayContext.h"
#include "Undo/Undo.h"
#include "Util/PredefinedAspectRatios.h"
#include "EditorViewportSettings.h"
#include <AzCore/Component/EntityId.h>
#include <AzCore/std/optional.h>
@@ -571,6 +572,9 @@ private:
AzFramework::EntityVisibilityQuery m_entityVisibilityQuery;
SandboxEditor::GridSnappingChangedEvent::Handler m_gridSnappingHandler;
AZStd::unique_ptr<SandboxEditor::EditorViewportSettingsCallbacks> m_editorViewportSettingsCallbacks;
QSet<int> m_keyDown;
bool m_freezeViewportInput = false;