From 18d8c181a3074599dcb2b6bf30246b9d01c6d427 Mon Sep 17 00:00:00 2001 From: tritao Date: Sat, 18 Jan 2025 13:12:42 +0000 Subject: [PATCH] Gui: Fix invalid scene graph mutation in `EditableDatumLabel`. `EditableDatumLabel` uses `activate`/`deactivate` methods for showing or hiding its widgets in the scene. However, `activate`/`deactivate` methods can end up being called as part of a scene graph / Coin action (`SoAction`) handler, in the context of `SoFCUnifiedSelection`, and this ended up in a Coin warning and eventual crash due to the scene graph being manipulated (nodes being removed), which Coin has checks for in debug mode: ``` Coin error in SoGroup::removeChild(): tried to remove non-existent child 0x5555579c5290 (Annotation) ``` Fix this issue by using a `SoSwitch` node instead and by controling the child visibility using it instead. --- src/Gui/EditableDatumLabel.cpp | 22 ++++++++++++++-------- src/Gui/EditableDatumLabel.h | 5 ++++- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/Gui/EditableDatumLabel.cpp b/src/Gui/EditableDatumLabel.cpp index bca2b209b2..5fa800935e 100644 --- a/src/Gui/EditableDatumLabel.cpp +++ b/src/Gui/EditableDatumLabel.cpp @@ -27,6 +27,7 @@ # include # include # include +# include #endif // _PreComp_ #include @@ -60,13 +61,17 @@ EditableDatumLabel::EditableDatumLabel(View3DInventorViewer* view, , function(Function::Positioning) { // NOLINTBEGIN - root = new SoAnnotation; + root = new SoSwitch; root->ref(); - root->renderCaching = SoSeparator::OFF; + + annotation = new SoAnnotation; + annotation->ref(); + annotation->renderCaching = SoSeparator::OFF; + root->addChild(annotation); transform = new SoTransform(); transform->ref(); - root->addChild(transform); + annotation->addChild(transform); label = new SoDatumLabel(); label->ref(); @@ -82,16 +87,19 @@ EditableDatumLabel::EditableDatumLabel(View3DInventorViewer* view, if (autoDistance) { setLabelRecommendedDistance(); } - root->addChild(label); + annotation->addChild(label); setPlacement(plc); // NOLINTEND + + static_cast(viewer->getSceneGraph())->addChild(root); // NOLINT } EditableDatumLabel::~EditableDatumLabel() { deactivate(); transform->unref(); + annotation->unref(); root->unref(); label->unref(); } @@ -102,7 +110,7 @@ void EditableDatumLabel::activate() return; } - static_cast(viewer->getSceneGraph())->addChild(root); // NOLINT + root->whichChild = 0; //track camera movements to update spinbox position. auto info = new NodeData{ this }; @@ -129,9 +137,7 @@ void EditableDatumLabel::deactivate() cameraSensor = nullptr; } - if (viewer) { - static_cast(viewer->getSceneGraph())->removeChild(root); // NOLINT - } + root->whichChild = SO_SWITCH_NONE; } void EditableDatumLabel::startEdit(double val, QObject* eventFilteringObj, bool visibleToMouse) diff --git a/src/Gui/EditableDatumLabel.h b/src/Gui/EditableDatumLabel.h index 80d6bffe06..ea224ff31a 100644 --- a/src/Gui/EditableDatumLabel.h +++ b/src/Gui/EditableDatumLabel.h @@ -34,6 +34,8 @@ class SoNodeSensor; class SoTransform; +class SoAnnotation; +class SoSwitch; namespace Gui { @@ -97,7 +99,8 @@ private: SbVec3f getTextCenterPoint() const; private: - SoSeparator* root; + SoSwitch* root; + SoAnnotation* annotation; SoTransform* transform; QPointer viewer; QuantitySpinBox* spinBox;