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.
This commit is contained in:
tritao
2025-01-18 13:12:42 +00:00
committed by Yorik van Havre
parent b95b500e5b
commit 18d8c181a3
2 changed files with 18 additions and 9 deletions

View File

@@ -27,6 +27,7 @@
# include <Inventor/nodes/SoAnnotation.h>
# include <Inventor/nodes/SoOrthographicCamera.h>
# include <Inventor/nodes/SoTransform.h>
# include <Inventor/nodes/SoSwitch.h>
#endif // _PreComp_
#include <Gui/Application.h>
@@ -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<SoSeparator*>(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<SoSeparator*>(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<SoSeparator*>(viewer->getSceneGraph())->removeChild(root); // NOLINT
}
root->whichChild = SO_SWITCH_NONE;
}
void EditableDatumLabel::startEdit(double val, QObject* eventFilteringObj, bool visibleToMouse)

View File

@@ -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<View3DInventorViewer> viewer;
QuantitySpinBox* spinBox;