From 525c05fae52e8c2def1b9173f341b3bb44ad2b71 Mon Sep 17 00:00:00 2001 From: 0penBrain <48731257+0penBrain@users.noreply.github.com> Date: Tue, 18 Oct 2022 18:12:02 +0200 Subject: [PATCH] [Bugfix]Sketcher/BackEdit : Backedit lost if user changed camera mode - in current implementation, backedit feature is lost if user changes camera mode (for example from orthographic to perspective, or oppositely). This happens because when changing camera mode, Coin actually do not just change a parameter of the camera node, but delete the current camera node and add a new one to the scenegraph. Thus the SoFieldSensor currently used (attached to camera orientation) is just detached and sensing is left -- notice is would be same with a SoNodeSensor attached to camera node --. The solution is to attach the sensor at scenegraph root node so it isn't lost when camera mode changed. No pre-check (such as checking if camera node changed since last call) has been added currently because it would not actually reduce callback execution time (and even worsen it). --- src/Mod/Sketcher/Gui/ViewProviderSketch.cpp | 17 +++++++++++------ src/Mod/Sketcher/Gui/ViewProviderSketch.h | 16 ++++++++++------ 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp index 49a1749d6e..43f7e2734c 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.cpp @@ -3157,13 +3157,15 @@ void ViewProviderSketch::setEditViewer(Gui::View3DInventorViewer* viewer, int Mo viewer->setupEditingRoot(); - cameraSensor.setData(new VPCam{this, viewer->getSoRenderManager()->getCamera()}); - cameraSensor.attach(&viewer->getSoRenderManager()->getCamera()->orientation); + cameraSensor.setData(new VPRender{this, viewer->getSoRenderManager()}); + cameraSensor.attach(viewer->getSoRenderManager()->getSceneGraph()); } void ViewProviderSketch::unsetEditViewer(Gui::View3DInventorViewer* viewer) { - delete static_cast(cameraSensor.getData()); + auto dataPtr = static_cast(cameraSensor.getData()); + dataPtr->attached = false; + delete dataPtr; cameraSensor.detach(); viewer->removeGraphicsItem(rubberband.get()); @@ -3174,9 +3176,12 @@ void ViewProviderSketch::unsetEditViewer(Gui::View3DInventorViewer* viewer) void ViewProviderSketch::camSensCB(void *data, SoSensor *) { - VPCam *proxyVPCam = static_cast(data); - auto vp = proxyVPCam->vp; - auto cam = proxyVPCam->cam; + VPRender *proxyVPrdr = static_cast(data); + if (!proxyVPrdr->attached) + return; + + auto vp = proxyVPrdr->vp; + auto cam = proxyVPrdr->renderMgr->getCamera(); auto rotSk = Base::Rotation(vp->getDocument()->getEditingTransform()); //sketch orientation auto rotc = cam->orientation.getValue().getValue(); diff --git a/src/Mod/Sketcher/Gui/ViewProviderSketch.h b/src/Mod/Sketcher/Gui/ViewProviderSketch.h index 7620dc090f..aefd997c7c 100644 --- a/src/Mod/Sketcher/Gui/ViewProviderSketch.h +++ b/src/Mod/Sketcher/Gui/ViewProviderSketch.h @@ -42,8 +42,8 @@ #include -#include -#include +#include +#include class TopoDS_Shape; class TopoDS_Face; @@ -391,11 +391,15 @@ private: bool buttonPress = false; }; - /** @brief Private struct grouping ViewProvider and Camera node, to be used as SoFieldSensor data + /** @brief Private struct grouping ViewProvider and RenderManager node, to be used as SoNode sensor data */ - struct VPCam { + struct VPRender { ViewProviderSketch* vp; - SoCamera* cam; + SoRenderManager* renderMgr; + // we have to manage an internal flag because as sensor events are queued in Coin, + // it may happen that the callback is called while the sensor is detached, + // leading to subsequent code trying to access deleted objects (passed as sensor data) + bool attached = true; }; public: @@ -777,7 +781,7 @@ private: ViewProviderParameters viewProviderParameters; - SoFieldSensor cameraSensor; + SoNodeSensor cameraSensor; int viewOrientationFactor; // stores if sketch viewed from front or back };