From 80f5df8435babe320ecd991ceca5c9054cfaf35e Mon Sep 17 00:00:00 2001 From: PaddleStroke Date: Tue, 21 Oct 2025 09:51:15 +0200 Subject: [PATCH] Assembly: Prevent crash when toggling rigid of grounded sub assembly (#24761) * Assembly: Prevent crash when toggling rigid of grounded sub assembly * to squash * to squash * Update AssemblyLink.cpp --- src/Mod/Assembly/App/AssemblyLink.cpp | 20 +++++++++++++++++++ src/Mod/Assembly/App/AssemblyObject.cpp | 5 +++++ src/Mod/Assembly/Gui/ViewProviderAssembly.cpp | 6 ++++++ 3 files changed, 31 insertions(+) diff --git a/src/Mod/Assembly/App/AssemblyLink.cpp b/src/Mod/Assembly/App/AssemblyLink.cpp index 9e2dbd57ce..7d87e3d5cd 100644 --- a/src/Mod/Assembly/App/AssemblyLink.cpp +++ b/src/Mod/Assembly/App/AssemblyLink.cpp @@ -101,6 +101,26 @@ void AssemblyLink::onChanged(const App::Property* prop) if (prop == &Rigid) { Base::Placement movePlc; + // A flexible sub-assembly cannot be grounded. + // If a rigid sub-assembly has an object that is grounded, we also remove it. + auto groundedJoints = getParentAssembly()->getGroundedJoints(); + for (auto* joint : groundedJoints) { + auto* propObj = + dynamic_cast(joint->getPropertyByName("ObjectToGround")); + if (!propObj) { + continue; + } + auto* groundedObj = propObj->getValue(); + if (auto* linkElt = dynamic_cast(groundedObj)) { + // hasObject does not handle link groups so we must handle it manually. + groundedObj = linkElt->getLinkGroup(); + } + + if (Rigid.getValue() ? hasObject(groundedObj) : groundedObj == this) { + getDocument()->removeObject(joint->getNameInDocument()); + } + } + if (Rigid.getValue()) { // movePlc needs to be computed before updateContents. App::DocumentObject* firstLink = nullptr; diff --git a/src/Mod/Assembly/App/AssemblyObject.cpp b/src/Mod/Assembly/App/AssemblyObject.cpp index 5f7a4982b0..df25cfc044 100644 --- a/src/Mod/Assembly/App/AssemblyObject.cpp +++ b/src/Mod/Assembly/App/AssemblyObject.cpp @@ -781,6 +781,11 @@ std::unordered_set AssemblyObject::getGroundedParts() if (propObj) { App::DocumentObject* objToGround = propObj->getValue(); if (objToGround) { + if (auto* asmLink = dynamic_cast(objToGround)) { + if (!asmLink->isRigid()) { + continue; + } + } groundedSet.insert(objToGround); } } diff --git a/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp b/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp index 4f73df6e44..8c10b125f9 100644 --- a/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp +++ b/src/Mod/Assembly/Gui/ViewProviderAssembly.cpp @@ -628,6 +628,12 @@ bool ViewProviderAssembly::canDragObjectIn3d(App::DocumentObject* obj) const return false; } + if (auto* asmLink = dynamic_cast(obj)) { + if (!asmLink->isRigid()) { + return false; + } + } + auto* assemblyPart = getObject(); // Check if the selected object is a child of the assembly