From d00d9a9515363ed5474462c6460693ec08532925 Mon Sep 17 00:00:00 2001 From: Roman <69218254+amzn-rhhong@users.noreply.github.com> Date: Wed, 22 Sep 2021 09:41:45 -0700 Subject: [PATCH] Fix the crash when switching between sim obj and physix layout in animation editor. (#4185) * Update the simulated object layout Signed-off-by: rhhong * Fixed the bug. Do not store uncessory cached selected model indices which would become stall. Signed-off-by: rhhong * update the simulted object layout. Signed-off-by: rhhong * Get rid of locally cached selectedIndices variable. Signed-off-by: rhhong * Remove debug code Signed-off-by: rhhong --- .../Editor/Layouts/SimulatedObjects.layout | Bin 6901 -> 7805 bytes .../Editor/Plugins/Cloth/ClothJointWidget.cpp | 10 +-- .../HitDetection/HitDetectionJointWidget.cpp | 10 +-- .../Plugins/Ragdoll/RagdollNodeWidget.cpp | 16 +++-- .../SimulatedObjectColliderWidget.cpp | 20 +++--- .../SkeletonOutlinerPlugin.cpp | 8 +-- .../Editor/SkeletonModelJointWidget.cpp | 61 +++++++++--------- .../Source/Editor/SkeletonModelJointWidget.h | 4 +- 8 files changed, 67 insertions(+), 62 deletions(-) diff --git a/Gems/EMotionFX/Assets/Editor/Layouts/SimulatedObjects.layout b/Gems/EMotionFX/Assets/Editor/Layouts/SimulatedObjects.layout index a7879584a9601f005f1c5aeba8d04f3320c8c66c..f52df642e84ae9f7b9b8b2f3685b3cb684345746 100644 GIT binary patch literal 7805 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 Y4c;%&vwCCXjrClearInstances(false); @@ -142,7 +143,7 @@ namespace EMotionFX m_collidersWidget->Reset(); } - m_jointLimitWidget->Update(m_selectedModelIndices[0]); + m_jointLimitWidget->Update(selectedModelIndices[0]); m_ragdollNodeCard->setExpanded(true); m_ragdollNodeCard->show(); m_jointLimitWidget->show(); @@ -169,31 +170,32 @@ namespace EMotionFX void RagdollNodeWidget::OnAddRemoveRagdollNode() { + const QModelIndexList& selectedModelIndices = GetSelectedModelIndices(); if (GetRagdollNodeConfig()) { // The node is present in the ragdoll, remove it. - RagdollNodeInspectorPlugin::RemoveFromRagdoll(m_selectedModelIndices); + RagdollNodeInspectorPlugin::RemoveFromRagdoll(selectedModelIndices); } else { // The node is not part of the ragdoll, add it. - RagdollNodeInspectorPlugin::AddToRagdoll(m_selectedModelIndices); + RagdollNodeInspectorPlugin::AddToRagdoll(selectedModelIndices); } } void RagdollNodeWidget::OnAddCollider(const AZ::TypeId& colliderType) { - ColliderHelpers::AddCollider(m_selectedModelIndices, PhysicsSetup::Ragdoll, colliderType); + ColliderHelpers::AddCollider(GetSelectedModelIndices(), PhysicsSetup::Ragdoll, colliderType); } void RagdollNodeWidget::OnCopyCollider(size_t colliderIndex) { - ColliderHelpers::CopyColliderToClipboard(m_selectedModelIndices.first(), colliderIndex, PhysicsSetup::Ragdoll); + ColliderHelpers::CopyColliderToClipboard(GetSelectedModelIndices().first(), colliderIndex, PhysicsSetup::Ragdoll); } void RagdollNodeWidget::OnPasteCollider(size_t colliderIndex, bool replace) { - ColliderHelpers::PasteColliderFromClipboard(m_selectedModelIndices.first(), colliderIndex, PhysicsSetup::Ragdoll, replace); + ColliderHelpers::PasteColliderFromClipboard(GetSelectedModelIndices().first(), colliderIndex, PhysicsSetup::Ragdoll, replace); } void RagdollNodeWidget::OnRemoveCollider(size_t colliderIndex) diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectColliderWidget.cpp b/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectColliderWidget.cpp index 8c6c72934d..b56cafc9be 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectColliderWidget.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/SimulatedObject/SimulatedObjectColliderWidget.cpp @@ -131,7 +131,8 @@ namespace EMotionFX void SimulatedObjectColliderWidget::InternalReinit() { - if (m_selectedModelIndices.size() == 1) + const QModelIndexList& selectedModelIndices = GetSelectedModelIndices(); + if (selectedModelIndices.size() == 1) { Physics::CharacterColliderNodeConfiguration* nodeConfig = GetNodeConfig(); if (nodeConfig) @@ -172,12 +173,13 @@ namespace EMotionFX } AZStd::string labelText; + const QModelIndexList& selectedModelIndices = GetSelectedModelIndices(); const AZStd::vector& simObjs = actor->GetSimulatedObjectSetup()->GetSimulatedObjects(); for (const SimulatedObject* obj : simObjs) { - for (int i = 0; i < m_selectedModelIndices.size(); ++i) + for (int i = 0; i < selectedModelIndices.size(); ++i) { - Node* node = m_selectedModelIndices[i].data(SkeletonModel::ROLE_POINTER).value(); + Node* node = selectedModelIndices[i].data(SkeletonModel::ROLE_POINTER).value(); if (obj->FindSimulatedJointBySkeletonJointIndex(node->GetNodeIndex())) { if (!labelText.empty()) @@ -208,8 +210,9 @@ namespace EMotionFX return; } + const QModelIndexList& selectedModelIndices = GetSelectedModelIndices(); // Only show the notification when it is single selection. - if (m_selectedModelIndices.size() != 1) + if (selectedModelIndices.size() != 1) { return; } @@ -250,17 +253,18 @@ namespace EMotionFX void SimulatedObjectColliderWidget::OnAddCollider(const AZ::TypeId& colliderType) { - ColliderHelpers::AddCollider(m_selectedModelIndices, PhysicsSetup::SimulatedObjectCollider, colliderType); + ColliderHelpers::AddCollider(GetSelectedModelIndices(), PhysicsSetup::SimulatedObjectCollider, colliderType); } void SimulatedObjectColliderWidget::OnCopyCollider(size_t colliderIndex) { - ColliderHelpers::CopyColliderToClipboard(m_selectedModelIndices.first(), colliderIndex, PhysicsSetup::SimulatedObjectCollider); + ColliderHelpers::CopyColliderToClipboard(GetSelectedModelIndices().first(), colliderIndex, PhysicsSetup::SimulatedObjectCollider); } void SimulatedObjectColliderWidget::OnPasteCollider(size_t colliderIndex, bool replace) { - ColliderHelpers::PasteColliderFromClipboard(m_selectedModelIndices.first(), colliderIndex, PhysicsSetup::SimulatedObjectCollider, replace); + ColliderHelpers::PasteColliderFromClipboard( + GetSelectedModelIndices().first(), colliderIndex, PhysicsSetup::SimulatedObjectCollider, replace); } void SimulatedObjectColliderWidget::OnRemoveCollider(size_t colliderIndex) @@ -270,7 +274,7 @@ namespace EMotionFX Physics::CharacterColliderNodeConfiguration* SimulatedObjectColliderWidget::GetNodeConfig() const { - AZ_Assert(m_selectedModelIndices.size() == 1, "Get Node config function only return the config when it is single seleted"); + AZ_Assert(GetSelectedModelIndices().size() == 1, "Get Node config function only return the config when it is single seleted"); Actor* actor = GetActor(); Node* joint = GetNode(); if (!actor || !joint) diff --git a/Gems/EMotionFX/Code/Source/Editor/Plugins/SkeletonOutliner/SkeletonOutlinerPlugin.cpp b/Gems/EMotionFX/Code/Source/Editor/Plugins/SkeletonOutliner/SkeletonOutlinerPlugin.cpp index f8ca291d55..ec8d1147f2 100644 --- a/Gems/EMotionFX/Code/Source/Editor/Plugins/SkeletonOutliner/SkeletonOutlinerPlugin.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/Plugins/SkeletonOutliner/SkeletonOutlinerPlugin.cpp @@ -211,15 +211,15 @@ namespace EMotionFX AZ::Outcome SkeletonOutlinerPlugin::GetSelectedRowIndices() { - return AZ::Success(m_selectedRows); + return AZ::Success(m_treeView->selectionModel()->selectedRows()); } void SkeletonOutlinerPlugin::OnSelectionChanged([[maybe_unused]] const QItemSelection& selected, [[maybe_unused]] const QItemSelection& deselected) { - m_selectedRows = m_treeView->selectionModel()->selectedRows(); - if (m_selectedRows.size() == 1) + QModelIndexList selectedRows = m_treeView->selectionModel()->selectedRows(); + if (selectedRows.size() == 1) { - const QModelIndex& modelIndex = m_selectedRows[0]; + const QModelIndex& modelIndex = selectedRows[0]; Node* selectedNode = modelIndex.data(SkeletonModel::ROLE_POINTER).value(); Actor* selectedActor = modelIndex.data(SkeletonModel::ROLE_ACTOR_POINTER).value(); SkeletonOutlinerNotificationBus::Broadcast(&SkeletonOutlinerNotifications::SingleNodeSelectionChanged, selectedActor, selectedNode); diff --git a/Gems/EMotionFX/Code/Source/Editor/SkeletonModelJointWidget.cpp b/Gems/EMotionFX/Code/Source/Editor/SkeletonModelJointWidget.cpp index e9eeb7530d..9cfc763fc6 100644 --- a/Gems/EMotionFX/Code/Source/Editor/SkeletonModelJointWidget.cpp +++ b/Gems/EMotionFX/Code/Source/Editor/SkeletonModelJointWidget.cpp @@ -72,14 +72,7 @@ namespace EMotionFX setLayout(mainLayout); - AZ::Outcome selectedRowIndicesOutcome; - QModelIndexList selectedModelIndices; - SkeletonOutlinerRequestBus::BroadcastResult(selectedRowIndicesOutcome, &SkeletonOutlinerRequests::GetSelectedRowIndices); - if (selectedRowIndicesOutcome.IsSuccess()) - { - selectedModelIndices = selectedRowIndicesOutcome.GetValue(); - } - Reinit(selectedModelIndices); + Reinit(); // Connect to the model. SkeletonModel* skeletonModel = nullptr; @@ -92,9 +85,9 @@ namespace EMotionFX } } - void SkeletonModelJointWidget::Reinit(const QModelIndexList& selectedModelIndices) + void SkeletonModelJointWidget::Reinit() { - m_selectedModelIndices = selectedModelIndices; + const QModelIndexList& selectedModelIndices = GetSelectedModelIndices(); if (!EMStudio::GetManager()->GetIgnoreVisibility() && !isVisible()) { @@ -103,15 +96,15 @@ namespace EMotionFX if (GetActor()) { - if (!m_selectedModelIndices.isEmpty()) + if (!selectedModelIndices.isEmpty()) { - if (m_selectedModelIndices.size() == 1) + if (selectedModelIndices.size() == 1) { m_jointNameLabel->setText(GetNode()->GetName()); } else { - m_jointNameLabel->setText(QString("%1 joints selected").arg(m_selectedModelIndices.size())); + m_jointNameLabel->setText(QString("%1 joints selected").arg(selectedModelIndices.size())); } m_noSelectionWidget->hide(); @@ -136,7 +129,7 @@ namespace EMotionFX void SkeletonModelJointWidget::showEvent(QShowEvent* event) { QWidget::showEvent(event); - Reinit(m_selectedModelIndices); + Reinit(); } void SkeletonModelJointWidget::OnSelectionChanged([[maybe_unused]] const QItemSelection& selected, [[maybe_unused]] const QItemSelection& deselected) @@ -146,36 +139,28 @@ namespace EMotionFX if (skeletonModel) { const QModelIndexList selectedRows = skeletonModel->GetSelectionModel().selectedRows(); - Reinit(selectedRows); } + Reinit(); } void SkeletonModelJointWidget::OnDataChanged([[maybe_unused]] const QModelIndex& topLeft, [[maybe_unused]] const QModelIndex& bottomRight, [[maybe_unused]] const QVector& roles) { - Reinit(m_selectedModelIndices); + Reinit(); } void SkeletonModelJointWidget::OnModelReset() { - Reinit(QModelIndexList()); + Reinit(); } Actor* SkeletonModelJointWidget::GetActor() const { Actor* actor = nullptr; - if (!m_selectedModelIndices.empty()) + SkeletonModel* skeletonModel = nullptr; + SkeletonOutlinerRequestBus::BroadcastResult(skeletonModel, &SkeletonOutlinerRequests::GetModel); + if (skeletonModel) { - actor = m_selectedModelIndices[0].data(SkeletonModel::ROLE_ACTOR_POINTER).value(); - } - - if (!actor) - { - SkeletonModel* skeletonModel = nullptr; - SkeletonOutlinerRequestBus::BroadcastResult(skeletonModel, &SkeletonOutlinerRequests::GetModel); - if (skeletonModel) - { - actor = skeletonModel->GetActor(); - } + actor = skeletonModel->GetActor(); } return actor; } @@ -183,10 +168,24 @@ namespace EMotionFX Node* SkeletonModelJointWidget::GetNode() const { Node* node = nullptr; - if (!m_selectedModelIndices.empty()) + const QModelIndexList& selectedModelIndices = GetSelectedModelIndices(); + if (!selectedModelIndices.empty()) { - node = m_selectedModelIndices[0].data(SkeletonModel::ROLE_POINTER).value(); + node = selectedModelIndices[0].data(SkeletonModel::ROLE_POINTER).value(); } return node; } + + QModelIndexList SkeletonModelJointWidget::GetSelectedModelIndices() const + { + QModelIndexList selectedModelIndices; + SkeletonModel* skeletonModel = nullptr; + SkeletonOutlinerRequestBus::BroadcastResult(skeletonModel, &SkeletonOutlinerRequests::GetModel); + if (skeletonModel) + { + selectedModelIndices = skeletonModel->GetSelectionModel().selectedRows(); + } + + return selectedModelIndices; + } } // namespace EMotionFX diff --git a/Gems/EMotionFX/Code/Source/Editor/SkeletonModelJointWidget.h b/Gems/EMotionFX/Code/Source/Editor/SkeletonModelJointWidget.h index 52178b4b55..399615c42a 100644 --- a/Gems/EMotionFX/Code/Source/Editor/SkeletonModelJointWidget.h +++ b/Gems/EMotionFX/Code/Source/Editor/SkeletonModelJointWidget.h @@ -33,13 +33,14 @@ namespace EMotionFX virtual void CreateGUI(); - void Reinit(const QModelIndexList& selectedModelIndices); + void Reinit(); void showEvent(QShowEvent* event) override; protected: Actor* GetActor() const; Node* GetNode() const; + QModelIndexList GetSelectedModelIndices() const; virtual QWidget* CreateContentWidget(QWidget* parent) = 0; virtual QWidget* CreateNoSelectionWidget(QWidget* parent) = 0; virtual void InternalReinit() = 0; @@ -50,7 +51,6 @@ namespace EMotionFX void OnModelReset(); protected: - QModelIndexList m_selectedModelIndices; QLabel* m_jointNameLabel; static int s_jointLabelSpacing; static int s_jointNameSpacing;