EMotion FX: Colliders now also render without the collider plugins

Colliders only rendered in case the given plugin was active, no matter if they were enabled or not in the 3D viewport which was confusing for users. Colliders as well as ragdoll debug draw now renders independently of the plugins.

Signed-off-by: Benjamin Jillich <jillich@amazon.com>
monroegm-disable-blank-issue-2
Benjamin Jillich 4 years ago
parent 9a19ffc5b4
commit 5e3b176abf

@ -713,121 +713,6 @@ namespace EMotionFX
renderUtil->EnableLighting(oldLightingEnabled);
}
void ColliderContainerWidget::RenderColliders(
const AzPhysics::ShapeColliderPairList& colliders,
const ActorInstance* actorInstance,
const Node* node,
const AZ::Color& colliderColor)
{
const size_t nodeIndex = node->GetNodeIndex();
for (const auto& collider : colliders)
{
#ifndef EMFX_SCALE_DISABLED
const AZ::Vector3& worldScale = actorInstance->GetTransformData()->GetCurrentPose()->GetModelSpaceTransform(nodeIndex).m_scale;
#else
const AZ::Vector3 worldScale = AZ::Vector3::CreateOne();
#endif
const Transform colliderOffsetTransform(collider.first->m_position, collider.first->m_rotation);
const Transform& actorInstanceGlobalTransform = actorInstance->GetWorldSpaceTransform();
const Transform& emfxNodeGlobalTransform =
actorInstance->GetTransformData()->GetCurrentPose()->GetModelSpaceTransform(nodeIndex);
const Transform emfxColliderGlobalTransformNoScale =
colliderOffsetTransform * emfxNodeGlobalTransform * actorInstanceGlobalTransform;
AZ::s32 viewportId = -1;
EMStudio::ViewportPluginRequestBus::BroadcastResult(viewportId, &EMStudio::ViewportPluginRequestBus::Events::GetViewportId);
AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus;
AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, viewportId);
AzFramework::DebugDisplayRequests* debugDisplay = nullptr;
debugDisplay = AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus);
if (!debugDisplay)
{
return;
}
const AZ::TypeId colliderType = collider.second->RTTI_GetType();
if (colliderType == azrtti_typeid<Physics::SphereShapeConfiguration>())
{
Physics::SphereShapeConfiguration* sphere = static_cast<Physics::SphereShapeConfiguration*>(collider.second.get());
// O3DE Physics scaling rules: The maximum component from the node scale will be multiplied by the radius of the sphere.
const float radius = sphere->m_radius *
MCore::Max3<float>(static_cast<float>(worldScale.GetX()), static_cast<float>(worldScale.GetY()),
static_cast<float>(worldScale.GetZ()));
debugDisplay->DepthTestOff();
debugDisplay->SetColor(colliderColor);
debugDisplay->DrawWireSphere(emfxColliderGlobalTransformNoScale.m_position, radius);
}
else if (colliderType == azrtti_typeid<Physics::CapsuleShapeConfiguration>())
{
Physics::CapsuleShapeConfiguration* capsule = static_cast<Physics::CapsuleShapeConfiguration*>(collider.second.get());
// O3DE Physics scaling rules: The maximum of the X/Y scale components of the node scale will be multiplied by the radius of
// the capsule. The Z component of the entity scale will be multiplied by the height of the capsule.
const float radius =
capsule->m_radius * MCore::Max<float>(static_cast<float>(worldScale.GetX()), static_cast<float>(worldScale.GetY()));
const float height = capsule->m_height * static_cast<float>(worldScale.GetZ());
debugDisplay->DepthTestOff();
debugDisplay->SetColor(colliderColor);
debugDisplay->DrawWireCapsule(
emfxColliderGlobalTransformNoScale.m_position, emfxColliderGlobalTransformNoScale.ToAZTransform().GetBasisZ(), radius, height);
}
else if (colliderType == azrtti_typeid<Physics::BoxShapeConfiguration>())
{
Physics::BoxShapeConfiguration* box = static_cast<Physics::BoxShapeConfiguration*>(collider.second.get());
// O3DE Physics scaling rules: Each component of the box dimensions will be scaled by the node's world scale.
AZ::Vector3 dimensions = box->m_dimensions;
dimensions *= worldScale;
debugDisplay->DepthTestOff();
debugDisplay->SetColor(colliderColor);
debugDisplay->DrawWireBox(
emfxColliderGlobalTransformNoScale.m_position, emfxColliderGlobalTransformNoScale.m_position + dimensions);
}
}
}
void ColliderContainerWidget::RenderColliders(PhysicsSetup::ColliderConfigType colliderConfigType,
const AZ::Color& defaultColor, const AZ::Color& selectedColor)
{
if (colliderConfigType == PhysicsSetup::Unknown)
{
return;
}
const AZStd::unordered_set<size_t>& selectedJointIndices = EMStudio::GetManager()->GetSelectedJointIndices();
const ActorManager* actorManager = GetEMotionFX().GetActorManager();
const size_t actorInstanceCount = actorManager->GetNumActorInstances();
for (size_t i = 0; i < actorInstanceCount; ++i)
{
const ActorInstance* actorInstance = actorManager->GetActorInstance(i);
const Actor* actor = actorInstance->GetActor();
const AZStd::shared_ptr<PhysicsSetup>& physicsSetup = actor->GetPhysicsSetup();
const Physics::CharacterColliderConfiguration* colliderConfig = physicsSetup->GetColliderConfigByType(colliderConfigType);
if (colliderConfig)
{
for (const Physics::CharacterColliderNodeConfiguration& nodeConfig : colliderConfig->m_nodes)
{
const Node* joint = actor->GetSkeleton()->FindNodeByName(nodeConfig.m_name.c_str());
if (joint)
{
const bool jointSelected =
selectedJointIndices.empty() || selectedJointIndices.find(joint->GetNodeIndex()) != selectedJointIndices.end();
const AzPhysics::ShapeColliderPairList& colliders = nodeConfig.m_shapes;
RenderColliders(colliders, actorInstance, joint, jointSelected ? selectedColor : defaultColor);
}
}
}
}
}
///////////////////////////////////////////////////////////////////////////
ColliderContainerWidget::ColliderEditedCallback::ColliderEditedCallback(ColliderContainerWidget* parent, bool executePreUndo, bool executePreCommand)

@ -167,17 +167,6 @@ namespace EMotionFX
EMStudio::RenderPlugin* renderPlugin,
EMStudio::EMStudioPlugin::RenderInfo* renderInfo);
static void RenderColliders(
const AzPhysics::ShapeColliderPairList& colliders,
const ActorInstance* actorInstance,
const Node* node,
const AZ::Color& colliderColor);
static void RenderColliders(
PhysicsSetup::ColliderConfigType colliderConfigType,
const AZ::Color& defaultColor,
const AZ::Color& selectedColor);
static int s_layoutSpacing;
signals:

@ -195,15 +195,4 @@ namespace EMotionFX
renderPlugin,
renderInfo);
}
void ClothJointInspectorPlugin::Render(EMotionFX::ActorRenderFlags renderFlags)
{
if (!AZ::RHI::CheckBitsAny(renderFlags, EMotionFX::ActorRenderFlags::ClothColliders))
{
return;
}
const AZ::Render::RenderActorSettings& settings = EMotionFX::GetRenderActorSettings();
ColliderContainerWidget::RenderColliders(PhysicsSetup::Cloth, settings.m_clothColliderColor, settings.m_selectedClothColliderColor);
}
} // namespace EMotionFX

@ -48,7 +48,6 @@ namespace EMotionFX
void OnContextMenu(QMenu* menu, const QModelIndexList& selectedRowIndices) override;
void LegacyRender(EMStudio::RenderPlugin* renderPlugin, RenderInfo* renderInfo) override;
void Render(EMotionFX::ActorRenderFlags renderFlags) override;
static bool IsJointInCloth(const QModelIndex& index);
public slots:

@ -180,18 +180,4 @@ namespace EMotionFX
renderPlugin,
renderInfo);
}
void HitDetectionJointInspectorPlugin::Render(EMotionFX::ActorRenderFlags renderFlags)
{
if (!AZ::RHI::CheckBitsAny(renderFlags, EMotionFX::ActorRenderFlags::HitDetectionColliders))
{
return;
}
const AZ::Render::RenderActorSettings& settings = EMotionFX::GetRenderActorSettings();
ColliderContainerWidget::RenderColliders(
PhysicsSetup::HitDetection, settings.m_hitDetectionColliderColor,
settings.m_selectedHitDetectionColliderColor);
}
} // namespace EMotionFX

@ -44,7 +44,6 @@ namespace EMotionFX
void OnContextMenu(QMenu* menu, const QModelIndexList& selectedRowIndices) override;
void LegacyRender(EMStudio::RenderPlugin* renderPlugin, RenderInfo* renderInfo) override;
void Render(EMotionFX::ActorRenderFlags renderFlags) override;
public slots:
void OnAddCollider();

@ -32,10 +32,6 @@
namespace EMotionFX
{
float RagdollNodeInspectorPlugin::s_scale = 0.1f;
AZ::u32 RagdollNodeInspectorPlugin::s_angularSubdivisions = 32;
AZ::u32 RagdollNodeInspectorPlugin::s_radialSubdivisions = 2;
RagdollNodeInspectorPlugin::RagdollNodeInspectorPlugin()
: EMStudio::DockWidgetPlugin()
, m_nodeWidget(nullptr)
@ -520,7 +516,6 @@ namespace EMotionFX
const Node* ragdollParentNode = physicsSetup->FindRagdollParentNode(joint);
if (ragdollParentNode)
{
LegacyRenderJointLimit(*jointLimitConfig, actorInstance, joint, ragdollParentNode, renderPlugin, renderInfo, finalColor);
LegacyRenderJointFrame(*jointLimitConfig, actorInstance, joint, ragdollParentNode, renderInfo, finalColor);
}
}
@ -528,54 +523,6 @@ namespace EMotionFX
}
}
void RagdollNodeInspectorPlugin::LegacyRenderJointLimit(
const AzPhysics::JointConfiguration& configuration,
const ActorInstance* actorInstance,
const Node* node,
const Node* parentNode,
EMStudio::RenderPlugin* renderPlugin,
EMStudio::EMStudioPlugin::RenderInfo* renderInfo,
const MCore::RGBAColor& color)
{
const EMStudio::RenderOptions* renderOptions = renderPlugin->GetRenderOptions();
const MCore::RGBAColor violatedColor = renderOptions->GetViolatedJointLimitColor();
const size_t nodeIndex = node->GetNodeIndex();
const size_t parentNodeIndex = parentNode->GetNodeIndex();
const Transform& actorInstanceWorldTransform = actorInstance->GetWorldSpaceTransform();
const Pose* currentPose = actorInstance->GetTransformData()->GetCurrentPose();
const AZ::Quaternion& parentOrientation = currentPose->GetModelSpaceTransform(parentNodeIndex).m_rotation;
const AZ::Quaternion& childOrientation = currentPose->GetModelSpaceTransform(nodeIndex).m_rotation;
m_vertexBuffer.clear();
m_indexBuffer.clear();
m_lineBuffer.clear();
m_lineValidityBuffer.clear();
if(auto* jointHelpers = AZ::Interface<AzPhysics::JointHelpersInterface>::Get())
{
jointHelpers->GenerateJointLimitVisualizationData(
configuration, parentOrientation, childOrientation, s_scale, s_angularSubdivisions, s_radialSubdivisions, m_vertexBuffer,
m_indexBuffer, m_lineBuffer, m_lineValidityBuffer);
}
Transform jointModelSpaceTransform = currentPose->GetModelSpaceTransform(parentNodeIndex);
jointModelSpaceTransform.m_position = currentPose->GetModelSpaceTransform(nodeIndex).m_position;
const Transform jointGlobalTransformNoScale = jointModelSpaceTransform * actorInstanceWorldTransform;
MCommon::RenderUtil* renderUtil = renderInfo->m_renderUtil;
const size_t numLineBufferEntries = m_lineBuffer.size();
if (m_lineValidityBuffer.size() * 2 != numLineBufferEntries)
{
AZ_ErrorOnce("EMotionFX", false, "Unexpected buffer size in joint limit visualization for node %s", node->GetName());
return;
}
for (size_t i = 0; i < numLineBufferEntries; i += 2)
{
renderUtil->RenderLine(jointGlobalTransformNoScale.TransformPoint(m_lineBuffer[i]),
jointGlobalTransformNoScale.TransformPoint(m_lineBuffer[i + 1]), m_lineValidityBuffer[i / 2] ? color : violatedColor);
}
}
void RagdollNodeInspectorPlugin::LegacyRenderJointFrame(
const AzPhysics::JointConfiguration& configuration,
const ActorInstance* actorInstance,
@ -594,192 +541,4 @@ namespace EMotionFX
renderInfo->m_renderUtil->RenderArrow(0.1f, jointChildWorldSpaceTransformNoScale.m_position, MCore::GetRight(jointChildWorldSpaceTransformNoScale.ToAZTransform()), color);
}
void RagdollNodeInspectorPlugin::Render(EMotionFX::ActorRenderFlags renderFlags)
{
const bool renderColliders = AZ::RHI::CheckBitsAny(renderFlags, EMotionFX::ActorRenderFlags::RagdollColliders);
const bool renderJointLimits = AZ::RHI::CheckBitsAny(renderFlags, EMotionFX::ActorRenderFlags::RagdollJointLimits);
if (!renderColliders && !renderJointLimits)
{
return;
}
const size_t actorInstanceCount = GetActorManager().GetNumActorInstances();
for (size_t i = 0; i < actorInstanceCount; ++i)
{
ActorInstance* actorInstance = GetActorManager().GetActorInstance(i);
RenderRagdoll(actorInstance, renderColliders, renderJointLimits);
}
}
void RagdollNodeInspectorPlugin::RenderRagdoll(
ActorInstance* actorInstance,
bool renderColliders,
bool renderJointLimits)
{
const Actor* actor = actorInstance->GetActor();
const Skeleton* skeleton = actor->GetSkeleton();
const size_t numNodes = skeleton->GetNumNodes();
const AZStd::shared_ptr<EMotionFX::PhysicsSetup>& physicsSetup = actor->GetPhysicsSetup();
const Physics::RagdollConfiguration& ragdollConfig = physicsSetup->GetRagdollConfig();
const AZStd::vector<Physics::RagdollNodeConfiguration>& ragdollNodes = ragdollConfig.m_nodes;
const Physics::CharacterColliderConfiguration& colliderConfig = ragdollConfig.m_colliders;
const RagdollInstance* ragdollInstance = actorInstance->GetRagdollInstance();
const AZ::Render::RenderActorSettings& settings = EMotionFX::GetRenderActorSettings();
const AZ::Color& violatedColor = settings.m_violatedJointLimitColor;
const AZ::Color& defaultColor = settings.m_ragdollColliderColor;
const AZ::Color& selectedColor = settings.m_selectedRagdollColliderColor;
const AZStd::unordered_set<size_t>& selectedJointIndices = EMStudio::GetManager()->GetSelectedJointIndices();
for (size_t nodeIndex = 0; nodeIndex < numNodes; ++nodeIndex)
{
const Node* joint = skeleton->GetNode(nodeIndex);
const size_t jointIndex = joint->GetNodeIndex();
AZ::Outcome<size_t> ragdollNodeIndex = AZ::Failure();
if (ragdollInstance)
{
ragdollNodeIndex = ragdollInstance->GetRagdollNodeIndex(jointIndex);
}
else
{
ragdollNodeIndex = ragdollConfig.FindNodeConfigIndexByName(joint->GetNameString());
}
if (!ragdollNodeIndex.IsSuccess())
{
continue;
}
const bool jointSelected = selectedJointIndices.empty() || selectedJointIndices.find(jointIndex) != selectedJointIndices.end();
AZ::Color finalColor;
if (jointSelected)
{
finalColor = selectedColor;
}
else
{
finalColor = defaultColor;
}
const Physics::RagdollNodeConfiguration& ragdollNode = ragdollNodes[ragdollNodeIndex.GetValue()];
if (renderColliders)
{
const Physics::CharacterColliderNodeConfiguration* colliderNodeConfig =
colliderConfig.FindNodeConfigByName(joint->GetNameString());
if (colliderNodeConfig)
{
const AzPhysics::ShapeColliderPairList& colliders = colliderNodeConfig->m_shapes;
ColliderContainerWidget::RenderColliders(colliders, actorInstance, joint, finalColor);
}
}
if (renderJointLimits && jointSelected)
{
const AZStd::shared_ptr<AzPhysics::JointConfiguration>& jointLimitConfig = ragdollNode.m_jointConfig;
if (jointLimitConfig)
{
const Node* ragdollParentNode = physicsSetup->FindRagdollParentNode(joint);
if (ragdollParentNode)
{
RenderJointLimit(*jointLimitConfig, actorInstance, joint, ragdollParentNode, finalColor, violatedColor);
RenderJointFrame(*jointLimitConfig, actorInstance, joint, ragdollParentNode, finalColor);
}
}
}
}
}
void RagdollNodeInspectorPlugin::RenderJointLimit(
const AzPhysics::JointConfiguration& configuration,
const ActorInstance* actorInstance,
const Node* node,
const Node* parentNode,
const AZ::Color& regularColor,
const AZ::Color& violatedColor)
{
const size_t nodeIndex = node->GetNodeIndex();
const size_t parentNodeIndex = parentNode->GetNodeIndex();
const Transform& actorInstanceWorldTransform = actorInstance->GetWorldSpaceTransform();
const Pose* currentPose = actorInstance->GetTransformData()->GetCurrentPose();
const AZ::Quaternion& parentOrientation = currentPose->GetModelSpaceTransform(parentNodeIndex).m_rotation;
const AZ::Quaternion& childOrientation = currentPose->GetModelSpaceTransform(nodeIndex).m_rotation;
m_vertexBuffer.clear();
m_indexBuffer.clear();
m_lineBuffer.clear();
m_lineValidityBuffer.clear();
if (auto* jointHelpers = AZ::Interface<AzPhysics::JointHelpersInterface>::Get())
{
jointHelpers->GenerateJointLimitVisualizationData(
configuration, parentOrientation, childOrientation, s_scale, s_angularSubdivisions, s_radialSubdivisions, m_vertexBuffer,
m_indexBuffer, m_lineBuffer, m_lineValidityBuffer);
}
Transform jointModelSpaceTransform = currentPose->GetModelSpaceTransform(parentNodeIndex);
jointModelSpaceTransform.m_position = currentPose->GetModelSpaceTransform(nodeIndex).m_position;
const Transform jointGlobalTransformNoScale = jointModelSpaceTransform * actorInstanceWorldTransform;
const size_t numLineBufferEntries = m_lineBuffer.size();
if (m_lineValidityBuffer.size() * 2 != numLineBufferEntries)
{
AZ_ErrorOnce("EMotionFX", false, "Unexpected buffer size in joint limit visualization for node %s", node->GetName());
return;
}
AZ::s32 viewportId = -1;
EMStudio::ViewportPluginRequestBus::BroadcastResult(viewportId, &EMStudio::ViewportPluginRequestBus::Events::GetViewportId);
AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus;
AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, viewportId);
AzFramework::DebugDisplayRequests* debugDisplay = nullptr;
debugDisplay = AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus);
if (!debugDisplay)
{
return;
}
for (size_t i = 0; i < numLineBufferEntries; i += 2)
{
const AZ::Color& lineColor = m_lineValidityBuffer[i / 2] ? regularColor : violatedColor;
debugDisplay->DrawLine(
jointGlobalTransformNoScale.TransformPoint(m_lineBuffer[i]),
jointGlobalTransformNoScale.TransformPoint(m_lineBuffer[i + 1]), lineColor.GetAsVector4(), lineColor.GetAsVector4()
);
}
}
void RagdollNodeInspectorPlugin::RenderJointFrame(
const AzPhysics::JointConfiguration& configuration,
const ActorInstance* actorInstance,
const Node* node,
const Node* parentNode,
const AZ::Color& color)
{
AZ_UNUSED(parentNode);
const Transform& actorInstanceWorldSpaceTransform = actorInstance->GetWorldSpaceTransform();
const Pose* currentPose = actorInstance->GetTransformData()->GetCurrentPose();
const Transform childJointLocalSpaceTransform(AZ::Vector3::CreateZero(), configuration.m_childLocalRotation);
const Transform childModelSpaceTransform =
childJointLocalSpaceTransform * currentPose->GetModelSpaceTransform(node->GetNodeIndex());
const Transform jointChildWorldSpaceTransformNoScale = (childModelSpaceTransform * actorInstanceWorldSpaceTransform);
AZ::Vector3 dir = jointChildWorldSpaceTransformNoScale.ToAZTransform().GetBasisX();
AZ::s32 viewportId = -1;
EMStudio::ViewportPluginRequestBus::BroadcastResult(viewportId, &EMStudio::ViewportPluginRequestBus::Events::GetViewportId);
AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus;
AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, viewportId);
AzFramework::DebugDisplayRequests* debugDisplay = nullptr;
debugDisplay = AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus);
if (!debugDisplay)
{
return;
}
debugDisplay->SetColor(color);
debugDisplay->DrawArrow(jointChildWorldSpaceTransformNoScale.m_position, jointChildWorldSpaceTransformNoScale.m_position + dir, 0.1f);
}
} // namespace EMotionFX

@ -57,14 +57,6 @@ namespace EMotionFX
//! Deprecated: All legacy render function is tied to openGL. Will be removed after openGLPlugin is completely removed.
void LegacyRender(EMStudio::RenderPlugin* renderPlugin, RenderInfo* renderInfo) override;
void LegacyRenderRagdoll(ActorInstance* actorInstance, bool renderColliders, bool renderJointLimits, EMStudio::RenderPlugin* renderPlugin, RenderInfo* renderInfo);
void LegacyRenderJointLimit(
const AzPhysics::JointConfiguration& jointConfiguration,
const ActorInstance* actorInstance,
const Node* node,
const Node* parentNode,
EMStudio::RenderPlugin* renderPlugin,
EMStudio::EMStudioPlugin::RenderInfo* renderInfo,
const MCore::RGBAColor& color);
void LegacyRenderJointFrame(
const AzPhysics::JointConfiguration& jointConfiguration,
const ActorInstance* actorInstance,
@ -73,26 +65,6 @@ namespace EMotionFX
EMStudio::EMStudioPlugin::RenderInfo* renderInfo,
const MCore::RGBAColor& color);
//! Those function replaces legacyRender function and calls atom auxGeom render internally.
void Render(EMotionFX::ActorRenderFlags renderFlags) override;
void RenderRagdoll(
ActorInstance* actorInstance,
bool renderColliders,
bool renderJointLimits);
void RenderJointLimit(
const AzPhysics::JointConfiguration& jointConfiguration,
const ActorInstance* actorInstance,
const Node* node,
const Node* parentNode,
const AZ::Color& regularColor,
const AZ::Color& violatedColor);
void RenderJointFrame(
const AzPhysics::JointConfiguration& jointConfiguration,
const ActorInstance* actorInstance,
const Node* node,
const Node* parentNode,
const AZ::Color& color);
public slots:
void OnAddToRagdoll();
void OnAddCollider();
@ -103,14 +75,6 @@ namespace EMotionFX
private:
bool IsPhysXGemAvailable() const;
RagdollNodeWidget* m_nodeWidget;
static float s_scale;
static AZ::u32 s_angularSubdivisions;
static AZ::u32 s_radialSubdivisions;
AZStd::vector<AZ::Vector3> m_vertexBuffer;
AZStd::vector<AZ::u32> m_indexBuffer;
AZStd::vector<AZ::Vector3> m_lineBuffer;
AZStd::vector<bool> m_lineValidityBuffer;
RagdollNodeWidget* m_nodeWidget;
};
} // namespace EMotionFX

@ -577,7 +577,6 @@ namespace EMotionFX
return;
}
const AZ::Render::RenderActorSettings& settings = EMotionFX::GetRenderActorSettings();
const AZStd::unordered_set<size_t>& selectedJointIndices = EMStudio::GetManager()->GetSelectedJointIndices();
if (AZ::RHI::CheckBitsAny(renderFlags, EMotionFX::ActorRenderFlags::SimulatedJoints) && !selectedJointIndices.empty())
{
@ -611,12 +610,6 @@ namespace EMotionFX
}
}
}
if (AZ::RHI::CheckBitsAny(renderFlags, EMotionFX::ActorRenderFlags::SimulatedObjectColliders))
{
ColliderContainerWidget::RenderColliders(PhysicsSetup::SimulatedObjectCollider,
settings.m_simulatedObjectColliderColor, settings.m_selectedSimulatedObjectColliderColor);
}
}
void SimulatedObjectWidget::RenderJointRadius(const SimulatedJoint* joint, ActorInstance* actorInstance, const AZ::Color& color)

@ -28,8 +28,11 @@ namespace EMotionFX
SkeletonOutlinerPlugin::~SkeletonOutlinerPlugin()
{
// Reset selection on close.
m_skeletonModel->GetSelectionModel().clearSelection();
m_skeletonModel.reset();
if (m_skeletonModel)
{
m_skeletonModel->GetSelectionModel().clearSelection();
m_skeletonModel.reset();
}
for (MCore::Command::Callback* callback : m_commandCallbacks)
{

Loading…
Cancel
Save