OSG QGLWidget ContextMenu删除致崩溃问题

2019-11-05

  去年,公司项目在三维交互中提出了一项需求。在QGLWidget上构造的右键菜单中直接删除点选中的对象。对于被选择的普通三维对象,弹出的右键菜单删除它是没有问题的,但是,删除overlay层控件时,却导致OSG内部崩溃。我查看了一下OSG源代码,发现是设计之初没有考虑过这个需求。然而,实现这个功能patch却是很简单的,只需要修改两个文件,并且,需要定制osgWidget::WindowManager,重新实现removeChild(Node *child)。具体修改代码如下:

 

src/osgWidget/WindowManager.cpp | 10 ++++++++++
1 file changed, 10 insertions(+)


diff --git a/src/osgWidget/WindowManager.cpp b/src/osgWidget/WindowManager.cpp
index 7bccbd348..d4561f790 100644
--- a/src/osgWidget/WindowManager.cpp
+++ b/src/osgWidget/WindowManager.cpp
@@ -634,4 +634,14 @@ osg::Camera* WindowManager::createParentOrthoCamera() {
     return camera;
}
+void WindowManager::setLastEventNull()
+{
+    this->_lastEvent = nullptr;        
+}
+
+const osgWidget::EventInterface* WindowManager::lastEvent()
+{
+    return this->_lastEvent ;
+}
+
}



include/osgWidget/WindowManager | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)


diff --git a/include/osgWidget/WindowManager b/include/osgWidget/WindowManager
index 49b5e6eeb..311d05820 100644
--- a/include/osgWidget/WindowManager
+++ b/include/osgWidget/WindowManager
@@ -99,7 +99,8 @@ class OSGWIDGET_EXPORT WindowManager: public osg::Switch, public UIObjectParent<
         bool mouseScroll (float, float);
         osg::Camera* createParentOrthoCamera();
-
+        void setLastEventNull();
+        const osgWidget::EventInterface* lastEvent();
         unsigned int getNodeMask() const {
             return _nodeMask;
         }

定制WindowManager:
bool WindowManager::removeChild(Node *child)
{
    osgWidget::Window* osgWindow = dynamic_cast<osgWidget::Window*>(child);
    if (nullptr != osgWindow)
    {
        if (this->lastEvent() == osgWindow){
            this->setLastEventNull();
        }
        else {
            // 正常逻辑,
        }
        bool ret = osgWidget::WindowManager::removeChild(osgWindow);
        return ret;
    }
    return osgWidget::WindowManager::removeChild(child);
}

  原因在于,WindowManager依赖于缓存的最后一次交互操作的Widget 对象,若没有清除此缓存,则在下一帧中会使用到已经被删除的对象,造成空指针错误。故需要主动清除此缓存。   
  不得不说,OSG WindowManager的实现还真是非常简单明了的。就几个文件,层次清晰。但是,osg学习开源的代码,还是非常有必要的。在自己的项目中使用了开源代码,发现了问题也不要怕,直接修改,若有必要,直接提交patch。

  

如果有任何意见,欢迎留言讨论。


[ 主页 ]
COMMENTS
POST A COMMENT

(optional)



(optional)