From 65cbe121bf45f73ff4b9f1b6e44cbc701c158c58 Mon Sep 17 00:00:00 2001 From: brige Date: Sun, 13 Apr 2025 23:12:17 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9ui=E6=98=BE=E7=A4=BA=E5=92=8C?= =?UTF-8?q?osg=E7=9A=84=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/app/Application.cpp | 4 +- src/main.cpp | 23 +- src/osgqt/GraphicsWindowQt.cpp | 1066 +++++++++++++++++++++++ src/osgqt/GraphicsWindowQt.h | 195 +++++ src/osgqt/QFontImplementation.cpp | 149 ++++ src/osgqt/QFontImplementation.h | 52 ++ src/osgqt/QGraphicsViewAdapter.cpp | 613 +++++++++++++ src/osgqt/QGraphicsViewAdapter.h | 122 +++ src/osgqt/QWebViewImage.h | 108 +++ src/osgqt/QWidgetImage.cpp | 66 ++ src/osgqt/QWidgetImage.h | 60 ++ src/osgqt/ReaderQFont.cpp | 66 ++ src/translations/Dyt_zh_CN.ts | 46 +- src/ui/Dialog.cpp | 29 +- src/ui/Dialog.h | 10 +- src/ui/Dialog.ui | 65 ++ src/ui/DialogTitleBar.cpp | 74 ++ src/ui/DialogTitleBar.h | 36 + src/ui/DialogTitleBar.ui | 71 ++ src/ui/FrameTitleBar.cpp | 51 +- src/ui/FrameTitleBar.h | 6 + src/ui/FramelessDelegate.cpp | 4 +- src/ui/FramelessWindow.cpp | 12 +- src/ui/FramelessWindow.h | 2 +- src/ui/MainWindow.cpp | 10 +- src/ui/ModelBrowser/ModelTreeWidget.cpp | 54 +- src/ui/WorkSpace/WorkSpaceDlg.cpp | 46 +- src/ui/WorkSpace/WorkSpaceDlg.h | 2 +- src/viewer/OsgViewer.cpp | 254 +++--- src/viewer/OsgViewer.h | 88 +- src/viewer/OsgWidget.cpp | 10 +- src/viewer/QtOsgViewWidget.cpp | 24 +- src/viewer/UpdateRenderStd.cpp | 4 +- 33 files changed, 3118 insertions(+), 304 deletions(-) create mode 100644 src/osgqt/GraphicsWindowQt.cpp create mode 100644 src/osgqt/GraphicsWindowQt.h create mode 100644 src/osgqt/QFontImplementation.cpp create mode 100644 src/osgqt/QFontImplementation.h create mode 100644 src/osgqt/QGraphicsViewAdapter.cpp create mode 100644 src/osgqt/QGraphicsViewAdapter.h create mode 100644 src/osgqt/QWebViewImage.h create mode 100644 src/osgqt/QWidgetImage.cpp create mode 100644 src/osgqt/QWidgetImage.h create mode 100644 src/osgqt/ReaderQFont.cpp create mode 100644 src/ui/Dialog.ui create mode 100644 src/ui/DialogTitleBar.cpp create mode 100644 src/ui/DialogTitleBar.h create mode 100644 src/ui/DialogTitleBar.ui diff --git a/src/app/Application.cpp b/src/app/Application.cpp index 11ce89c2..8557120e 100644 --- a/src/app/Application.cpp +++ b/src/app/Application.cpp @@ -26,7 +26,7 @@ QString Application::GetWorkSpacePath() { void Application::Init() { Singleton::Create(this); - Singleton::Create(this); + //Singleton::Create(this); Singleton::Create(this); Singleton::Create(this); Singleton::Create(this); @@ -40,6 +40,6 @@ void Application::Uninit() { Singleton::Destory(); Singleton::Destory(); Singleton::Destory(); - Singleton::Destory(); + //Singleton::Destory(); Singleton::Destory(); } diff --git a/src/main.cpp b/src/main.cpp index 5d13ebaa..3617895d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -374,7 +374,7 @@ int main(int argc, char* argv[]) { SpdLogger logger("logs/log.txt", 5); // Application::setAttribute(Qt::AA_EnableHighDpiScaling); - // + //// Application app(argc, argv); app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); // InstallCrashHandler(); @@ -387,15 +387,14 @@ int main(int argc, char* argv[]) { int ret = app.exec(); return ret; - osg::ArgumentParser arguments(&argc, argv); - - // Qt5 is currently crashing and reporting "Cannot make QOpenGLContext current in a different thread" when the viewer is run multi-threaded, this is regression from Qt4 - osgViewer::ViewerBase::ThreadingModel threadingModel = osgViewer::ViewerBase::SingleThreaded; - - OsgWidget* viewWidget = new OsgWidget(nullptr, Qt::Widget); - // ViewerWidget* viewWidget = new ViewerWidget(nullptr, Qt::Widget, threadingModel); - viewWidget->setGeometry( 100, 100, 800, 600 ); - viewWidget->Initialize(); - viewWidget->show(); - return app.exec(); + //osg::ArgumentParser arguments(&argc, argv); + + //QMainWindow* mainWindow = new QMainWindow; + //OsgWidget* viewWidget = new OsgWidget(nullptr, Qt::Widget); + //mainWindow->setCentralWidget(viewWidget); + //// ViewerWidget* viewWidget = new ViewerWidget(nullptr, Qt::Widget, threadingModel); + ////viewWidget->setGeometry( 100, 100, 800, 600 ); + //viewWidget->Initialize(); + //mainWindow->show(); + //return app.exec(); } diff --git a/src/osgqt/GraphicsWindowQt.cpp b/src/osgqt/GraphicsWindowQt.cpp new file mode 100644 index 00000000..e40d626c --- /dev/null +++ b/src/osgqt/GraphicsWindowQt.cpp @@ -0,0 +1,1066 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009 Wang Rui + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ +#include "osgqt/GraphicsWindowQt.h" + +#include + +#include +#include +#include + +#if (QT_VERSION>=QT_VERSION_CHECK(4, 6, 0)) +# define USE_GESTURES +# include +# include +#endif + +using namespace osgQt; + + +class QtKeyboardMap +{ + +public: + QtKeyboardMap() + { + mKeyMap[Qt::Key_Escape ] = osgGA::GUIEventAdapter::KEY_Escape; + mKeyMap[Qt::Key_Delete ] = osgGA::GUIEventAdapter::KEY_Delete; + mKeyMap[Qt::Key_Home ] = osgGA::GUIEventAdapter::KEY_Home; + mKeyMap[Qt::Key_Enter ] = osgGA::GUIEventAdapter::KEY_KP_Enter; + mKeyMap[Qt::Key_End ] = osgGA::GUIEventAdapter::KEY_End; + mKeyMap[Qt::Key_Return ] = osgGA::GUIEventAdapter::KEY_Return; + mKeyMap[Qt::Key_PageUp ] = osgGA::GUIEventAdapter::KEY_Page_Up; + mKeyMap[Qt::Key_PageDown ] = osgGA::GUIEventAdapter::KEY_Page_Down; + mKeyMap[Qt::Key_Left ] = osgGA::GUIEventAdapter::KEY_Left; + mKeyMap[Qt::Key_Right ] = osgGA::GUIEventAdapter::KEY_Right; + mKeyMap[Qt::Key_Up ] = osgGA::GUIEventAdapter::KEY_Up; + mKeyMap[Qt::Key_Down ] = osgGA::GUIEventAdapter::KEY_Down; + mKeyMap[Qt::Key_Backspace ] = osgGA::GUIEventAdapter::KEY_BackSpace; + mKeyMap[Qt::Key_Tab ] = osgGA::GUIEventAdapter::KEY_Tab; + mKeyMap[Qt::Key_Space ] = osgGA::GUIEventAdapter::KEY_Space; + mKeyMap[Qt::Key_Delete ] = osgGA::GUIEventAdapter::KEY_Delete; + mKeyMap[Qt::Key_Alt ] = osgGA::GUIEventAdapter::KEY_Alt_L; + mKeyMap[Qt::Key_Shift ] = osgGA::GUIEventAdapter::KEY_Shift_L; + mKeyMap[Qt::Key_Control ] = osgGA::GUIEventAdapter::KEY_Control_L; + mKeyMap[Qt::Key_Meta ] = osgGA::GUIEventAdapter::KEY_Meta_L; + + mKeyMap[Qt::Key_F1 ] = osgGA::GUIEventAdapter::KEY_F1; + mKeyMap[Qt::Key_F2 ] = osgGA::GUIEventAdapter::KEY_F2; + mKeyMap[Qt::Key_F3 ] = osgGA::GUIEventAdapter::KEY_F3; + mKeyMap[Qt::Key_F4 ] = osgGA::GUIEventAdapter::KEY_F4; + mKeyMap[Qt::Key_F5 ] = osgGA::GUIEventAdapter::KEY_F5; + mKeyMap[Qt::Key_F6 ] = osgGA::GUIEventAdapter::KEY_F6; + mKeyMap[Qt::Key_F7 ] = osgGA::GUIEventAdapter::KEY_F7; + mKeyMap[Qt::Key_F8 ] = osgGA::GUIEventAdapter::KEY_F8; + mKeyMap[Qt::Key_F9 ] = osgGA::GUIEventAdapter::KEY_F9; + mKeyMap[Qt::Key_F10 ] = osgGA::GUIEventAdapter::KEY_F10; + mKeyMap[Qt::Key_F11 ] = osgGA::GUIEventAdapter::KEY_F11; + mKeyMap[Qt::Key_F12 ] = osgGA::GUIEventAdapter::KEY_F12; + mKeyMap[Qt::Key_F13 ] = osgGA::GUIEventAdapter::KEY_F13; + mKeyMap[Qt::Key_F14 ] = osgGA::GUIEventAdapter::KEY_F14; + mKeyMap[Qt::Key_F15 ] = osgGA::GUIEventAdapter::KEY_F15; + mKeyMap[Qt::Key_F16 ] = osgGA::GUIEventAdapter::KEY_F16; + mKeyMap[Qt::Key_F17 ] = osgGA::GUIEventAdapter::KEY_F17; + mKeyMap[Qt::Key_F18 ] = osgGA::GUIEventAdapter::KEY_F18; + mKeyMap[Qt::Key_F19 ] = osgGA::GUIEventAdapter::KEY_F19; + mKeyMap[Qt::Key_F20 ] = osgGA::GUIEventAdapter::KEY_F20; + + mKeyMap[Qt::Key_hyphen ] = '-'; + mKeyMap[Qt::Key_Equal ] = '='; + + mKeyMap[Qt::Key_division ] = osgGA::GUIEventAdapter::KEY_KP_Divide; + mKeyMap[Qt::Key_multiply ] = osgGA::GUIEventAdapter::KEY_KP_Multiply; + mKeyMap[Qt::Key_Minus ] = '-'; + mKeyMap[Qt::Key_Plus ] = '+'; + //mKeyMap[Qt::Key_H ] = osgGA::GUIEventAdapter::KEY_KP_Home; + //mKeyMap[Qt::Key_ ] = osgGA::GUIEventAdapter::KEY_KP_Up; + //mKeyMap[92 ] = osgGA::GUIEventAdapter::KEY_KP_Page_Up; + //mKeyMap[86 ] = osgGA::GUIEventAdapter::KEY_KP_Left; + //mKeyMap[87 ] = osgGA::GUIEventAdapter::KEY_KP_Begin; + //mKeyMap[88 ] = osgGA::GUIEventAdapter::KEY_KP_Right; + //mKeyMap[83 ] = osgGA::GUIEventAdapter::KEY_KP_End; + //mKeyMap[84 ] = osgGA::GUIEventAdapter::KEY_KP_Down; + //mKeyMap[85 ] = osgGA::GUIEventAdapter::KEY_KP_Page_Down; + mKeyMap[Qt::Key_Insert ] = osgGA::GUIEventAdapter::KEY_KP_Insert; + //mKeyMap[Qt::Key_Delete ] = osgGA::GUIEventAdapter::KEY_KP_Delete; + } + + ~QtKeyboardMap() + { + } + + int remapKey(QKeyEvent* event) + { + KeyMap::iterator itr = mKeyMap.find(event->key()); + if (itr == mKeyMap.end()) + { + return int(*(event->text().toLatin1().data())); + } + else + return itr->second; + } + + private: + typedef std::map KeyMap; + KeyMap mKeyMap; +}; + +static QtKeyboardMap s_QtKeyboardMap; + + +/// The object responsible for the scene re-rendering. +class HeartBeat : public QObject { +public: + int _timerId; + osg::Timer _lastFrameStartTime; + osg::observer_ptr< osgViewer::ViewerBase > _viewer; + + virtual ~HeartBeat(); + + void init( osgViewer::ViewerBase *viewer ); + void stopTimer(); + void timerEvent( QTimerEvent *event ); + + static HeartBeat* instance(); +private: + HeartBeat(); + + static QPointer heartBeat; +}; + +QPointer HeartBeat::heartBeat; + +#if (QT_VERSION < QT_VERSION_CHECK(5, 2, 0)) + #define GETDEVICEPIXELRATIO() 1.0 +#else + #define GETDEVICEPIXELRATIO() devicePixelRatio() +#endif + +GLWidget::GLWidget( QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f, bool forwardKeyEvents ) +: QGLWidget(parent, shareWidget, f), +_gw( NULL ), +_touchEventsEnabled( false ), +_forwardKeyEvents( forwardKeyEvents ) +{ + _devicePixelRatio = GETDEVICEPIXELRATIO(); +} + +GLWidget::GLWidget( QGLContext* context, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f, + bool forwardKeyEvents ) +: QGLWidget(context, parent, shareWidget, f), +_gw( NULL ), +_touchEventsEnabled( false ), +_forwardKeyEvents( forwardKeyEvents ) +{ + _devicePixelRatio = GETDEVICEPIXELRATIO(); +} + +GLWidget::GLWidget( const QGLFormat& format, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f, + bool forwardKeyEvents ) +: QGLWidget(format, parent, shareWidget, f), +_gw( NULL ), +_touchEventsEnabled( false ), +_forwardKeyEvents( forwardKeyEvents ) +{ + _devicePixelRatio = GETDEVICEPIXELRATIO(); +} + +GLWidget::~GLWidget() +{ + // close GraphicsWindowQt and remove the reference to us + if( _gw ) + { + _gw->close(); + _gw->_widget = NULL; + _gw = NULL; + } +} + +void GLWidget::setTouchEventsEnabled(bool e) +{ +#ifdef USE_GESTURES + if (e==_touchEventsEnabled) + return; + + _touchEventsEnabled = e; + + if (_touchEventsEnabled) + { + grabGesture(Qt::PinchGesture); + } + else + { + ungrabGesture(Qt::PinchGesture); + } +#endif +} + +void GLWidget::processDeferredEvents() +{ + QQueue deferredEventQueueCopy; + { + QMutexLocker lock(&_deferredEventQueueMutex); + deferredEventQueueCopy = _deferredEventQueue; + _eventCompressor.clear(); + _deferredEventQueue.clear(); + } + + while (!deferredEventQueueCopy.isEmpty()) + { + QEvent event(deferredEventQueueCopy.dequeue()); + QGLWidget::event(&event); + } +} + +bool GLWidget::event( QEvent* event ) +{ +#ifdef USE_GESTURES + if ( event->type()==QEvent::Gesture ) + return gestureEvent(static_cast(event)); +#endif + + // QEvent::Hide + // + // workaround "Qt-workaround" that does glFinish before hiding the widget + // (the Qt workaround was seen at least in Qt 4.6.3 and 4.7.0) + // + // Qt makes the context current, performs glFinish, and releases the context. + // This makes the problem in OSG multithreaded environment as the context + // is active in another thread, thus it can not be made current for the purpose + // of glFinish in this thread. + + // QEvent::ParentChange + // + // Reparenting GLWidget may create a new underlying window and a new GL context. + // Qt will then call doneCurrent on the GL context about to be deleted. The thread + // where old GL context was current has no longer current context to render to and + // we cannot make new GL context current in this thread. + + // We workaround above problems by deferring execution of problematic event requests. + // These events has to be enqueue and executed later in a main GUI thread (GUI operations + // outside the main thread are not allowed) just before makeCurrent is called from the + // right thread. The good place for doing that is right after swap in a swapBuffersImplementation. + + if (event->type() == QEvent::Hide) + { + // enqueue only the last of QEvent::Hide and QEvent::Show + enqueueDeferredEvent(QEvent::Hide, QEvent::Show); + return true; + } + else if (event->type() == QEvent::Show) + { + // enqueue only the last of QEvent::Show or QEvent::Hide + enqueueDeferredEvent(QEvent::Show, QEvent::Hide); + return true; + } + else if (event->type() == QEvent::ParentChange) + { + // enqueue only the last QEvent::ParentChange + enqueueDeferredEvent(QEvent::ParentChange); + return true; + } + + // perform regular event handling + return QGLWidget::event( event ); +} + +void GLWidget::setKeyboardModifiers( QInputEvent* event ) +{ + int modkey = event->modifiers() & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier); + unsigned int mask = 0; + if ( modkey & Qt::ShiftModifier ) mask |= osgGA::GUIEventAdapter::MODKEY_SHIFT; + if ( modkey & Qt::ControlModifier ) mask |= osgGA::GUIEventAdapter::MODKEY_CTRL; + if ( modkey & Qt::AltModifier ) mask |= osgGA::GUIEventAdapter::MODKEY_ALT; + _gw->getEventQueue()->getCurrentEventState()->setModKeyMask( mask ); +} + +void GLWidget::resizeEvent( QResizeEvent* event ) +{ + const QSize& size = event->size(); + + int scaled_width = static_cast(size.width()*_devicePixelRatio); + int scaled_height = static_cast(size.height()*_devicePixelRatio); + _gw->resized( x(), y(), scaled_width, scaled_height); + _gw->getEventQueue()->windowResize( x(), y(), scaled_width, scaled_height ); + _gw->requestRedraw(); +} + +void GLWidget::moveEvent( QMoveEvent* event ) +{ + const QPoint& pos = event->pos(); + int scaled_width = static_cast(width()*_devicePixelRatio); + int scaled_height = static_cast(height()*_devicePixelRatio); + _gw->resized( pos.x(), pos.y(), scaled_width, scaled_height ); + _gw->getEventQueue()->windowResize( pos.x(), pos.y(), scaled_width, scaled_height ); +} + +void GLWidget::glDraw() +{ + _gw->requestRedraw(); +} + +void GLWidget::keyPressEvent( QKeyEvent* event ) +{ + setKeyboardModifiers( event ); + int value = s_QtKeyboardMap.remapKey( event ); + _gw->getEventQueue()->keyPress( value ); + + // this passes the event to the regular Qt key event processing, + // among others, it closes popup windows on ESC and forwards the event to the parent widgets + if( _forwardKeyEvents ) + inherited::keyPressEvent( event ); +} + +void GLWidget::keyReleaseEvent( QKeyEvent* event ) +{ + if( event->isAutoRepeat() ) + { + event->ignore(); + } + else + { + setKeyboardModifiers( event ); + int value = s_QtKeyboardMap.remapKey( event ); + _gw->getEventQueue()->keyRelease( value ); + } + + // this passes the event to the regular Qt key event processing, + // among others, it closes popup windows on ESC and forwards the event to the parent widgets + if( _forwardKeyEvents ) + inherited::keyReleaseEvent( event ); +} + +void GLWidget::mousePressEvent( QMouseEvent* event ) +{ + int button = 0; + switch ( event->button() ) + { + case Qt::LeftButton: button = 1; break; + case Qt::MidButton: button = 2; break; + case Qt::RightButton: button = 3; break; + case Qt::NoButton: button = 0; break; + default: button = 0; break; + } + setKeyboardModifiers( event ); + _gw->getEventQueue()->mouseButtonPress( event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button ); +} + +void GLWidget::mouseReleaseEvent( QMouseEvent* event ) +{ + int button = 0; + switch ( event->button() ) + { + case Qt::LeftButton: button = 1; break; + case Qt::MidButton: button = 2; break; + case Qt::RightButton: button = 3; break; + case Qt::NoButton: button = 0; break; + default: button = 0; break; + } + setKeyboardModifiers( event ); + _gw->getEventQueue()->mouseButtonRelease( event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button ); +} + +void GLWidget::mouseDoubleClickEvent( QMouseEvent* event ) +{ + int button = 0; + switch ( event->button() ) + { + case Qt::LeftButton: button = 1; break; + case Qt::MidButton: button = 2; break; + case Qt::RightButton: button = 3; break; + case Qt::NoButton: button = 0; break; + default: button = 0; break; + } + setKeyboardModifiers( event ); + _gw->getEventQueue()->mouseDoubleButtonPress( event->x()*_devicePixelRatio, event->y()*_devicePixelRatio, button ); +} + +void GLWidget::mouseMoveEvent( QMouseEvent* event ) +{ + setKeyboardModifiers( event ); + _gw->getEventQueue()->mouseMotion( event->x()*_devicePixelRatio, event->y()*_devicePixelRatio ); +} + +void GLWidget::wheelEvent( QWheelEvent* event ) +{ + setKeyboardModifiers( event ); + _gw->getEventQueue()->mouseScroll( + event->orientation() == Qt::Vertical ? + (event->delta()>0 ? osgGA::GUIEventAdapter::SCROLL_UP : osgGA::GUIEventAdapter::SCROLL_DOWN) : + (event->delta()>0 ? osgGA::GUIEventAdapter::SCROLL_LEFT : osgGA::GUIEventAdapter::SCROLL_RIGHT) ); +} + +#ifdef USE_GESTURES +static osgGA::GUIEventAdapter::TouchPhase translateQtGestureState( Qt::GestureState state ) +{ + osgGA::GUIEventAdapter::TouchPhase touchPhase; + switch ( state ) + { + case Qt::GestureStarted: + touchPhase = osgGA::GUIEventAdapter::TOUCH_BEGAN; + break; + case Qt::GestureUpdated: + touchPhase = osgGA::GUIEventAdapter::TOUCH_MOVED; + break; + case Qt::GestureFinished: + case Qt::GestureCanceled: + touchPhase = osgGA::GUIEventAdapter::TOUCH_ENDED; + break; + default: + touchPhase = osgGA::GUIEventAdapter::TOUCH_UNKNOWN; + }; + + return touchPhase; +} +#endif + + +bool GLWidget::gestureEvent( QGestureEvent* qevent ) +{ +#ifndef USE_GESTURES + return false; +#else + + bool accept = false; + + if ( QPinchGesture* pinch = static_cast(qevent->gesture(Qt::PinchGesture) ) ) + { + const QPointF qcenterf = pinch->centerPoint(); + const float angle = pinch->totalRotationAngle(); + const float scale = pinch->totalScaleFactor(); + + const QPoint pinchCenterQt = mapFromGlobal(qcenterf.toPoint()); + const osg::Vec2 pinchCenter( pinchCenterQt.x(), pinchCenterQt.y() ); + + //We don't have absolute positions of the two touches, only a scale and rotation + //Hence we create pseudo-coordinates which are reasonable, and centered around the + //real position + const float radius = float(width()+height())/4.0f; + const osg::Vec2 vector( scale*cos(angle)*radius, scale*sin(angle)*radius); + const osg::Vec2 p0 = pinchCenter+vector; + const osg::Vec2 p1 = pinchCenter-vector; + + osg::ref_ptr event = 0; + const osgGA::GUIEventAdapter::TouchPhase touchPhase = translateQtGestureState( pinch->state() ); + if ( touchPhase==osgGA::GUIEventAdapter::TOUCH_BEGAN ) + { + event = _gw->getEventQueue()->touchBegan(0 , touchPhase, p0[0], p0[1] ); + } + else if ( touchPhase==osgGA::GUIEventAdapter::TOUCH_MOVED ) + { + event = _gw->getEventQueue()->touchMoved( 0, touchPhase, p0[0], p0[1] ); + } + else + { + event = _gw->getEventQueue()->touchEnded( 0, touchPhase, p0[0], p0[1], 1 ); + } + + if ( event ) + { + event->addTouchPoint( 1, touchPhase, p1[0], p1[1] ); + accept = true; + } + } + + if ( accept ) + qevent->accept(); + + return accept; +#endif +} + + + +GraphicsWindowQt::GraphicsWindowQt( osg::GraphicsContext::Traits* traits, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f ) +: _realized(false) +{ + + _widget = NULL; + _traits = traits; + init( parent, shareWidget, f ); +} + +GraphicsWindowQt::GraphicsWindowQt( GLWidget* widget ) +: _realized(false) +{ + _widget = widget; + _traits = _widget ? createTraits( _widget ) : new osg::GraphicsContext::Traits; + init( NULL, NULL, 0 ); +} + +GraphicsWindowQt::~GraphicsWindowQt() +{ + // close(); + + // remove reference from GLWidget + if ( _widget ) + _widget->_gw = NULL; +} + +bool GraphicsWindowQt::init( QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f ) +{ + // update _widget and parent by WindowData + WindowData* windowData = _traits.get() ? dynamic_cast(_traits->inheritedWindowData.get()) : 0; + if ( !_widget ) + _widget = windowData ? windowData->_widget : NULL; + if ( !parent ) + parent = windowData ? windowData->_parent : NULL; + + // create widget if it does not exist + _ownsWidget = _widget == NULL; + if ( !_widget ) + { + // shareWidget + if ( !shareWidget ) { + GraphicsWindowQt* sharedContextQt = dynamic_cast(_traits->sharedContext.get()); + if ( sharedContextQt ) + shareWidget = sharedContextQt->getGLWidget(); + } + + // WindowFlags + Qt::WindowFlags flags = f | Qt::Window | Qt::CustomizeWindowHint; + if ( _traits->windowDecoration ) + flags |= Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowSystemMenuHint +#if (QT_VERSION_CHECK(4, 5, 0) <= QT_VERSION) + | Qt::WindowCloseButtonHint +#endif + ; + + // create widget + _widget = new GLWidget( traits2qglFormat( _traits.get() ), parent, shareWidget, flags ); + } + + // set widget name and position + // (do not set it when we inherited the widget) + if ( _ownsWidget ) + { + _widget->setWindowTitle( _traits->windowName.c_str() ); + _widget->move( _traits->x, _traits->y ); + if ( !_traits->supportsResize ) _widget->setFixedSize( _traits->width, _traits->height ); + else _widget->resize( _traits->width, _traits->height ); + } + + // initialize widget properties + _widget->setAutoBufferSwap( false ); + _widget->setMouseTracking( true ); + _widget->setFocusPolicy( Qt::WheelFocus ); + _widget->setGraphicsWindow( this ); + useCursor( _traits->useCursor ); + + // initialize State + setState( new osg::State ); + getState()->setGraphicsContext(this); + + // initialize contextID + if ( _traits.valid() && _traits->sharedContext.valid() ) + { + getState()->setContextID( _traits->sharedContext->getState()->getContextID() ); + incrementContextIDUsageCount( getState()->getContextID() ); + } + else + { + getState()->setContextID( osg::GraphicsContext::createNewContextID() ); + } + + // make sure the event queue has the correct window rectangle size and input range + getEventQueue()->syncWindowRectangleWithGraphicsContext(); + + return true; +} + +QGLFormat GraphicsWindowQt::traits2qglFormat( const osg::GraphicsContext::Traits* traits ) +{ + QGLFormat format( QGLFormat::defaultFormat() ); + + format.setAlphaBufferSize( traits->alpha ); + format.setRedBufferSize( traits->red ); + format.setGreenBufferSize( traits->green ); + format.setBlueBufferSize( traits->blue ); + format.setDepthBufferSize( traits->depth ); + format.setStencilBufferSize( traits->stencil ); + format.setSampleBuffers( traits->sampleBuffers ); + format.setSamples( traits->samples ); + + format.setAlpha( traits->alpha>0 ); + format.setDepth( traits->depth>0 ); + format.setStencil( traits->stencil>0 ); + format.setDoubleBuffer( traits->doubleBuffer ); + format.setSwapInterval( traits->vsync ? 1 : 0 ); + format.setStereo( traits->quadBufferStereo ? 1 : 0 ); + + return format; +} + +void GraphicsWindowQt::qglFormat2traits( const QGLFormat& format, osg::GraphicsContext::Traits* traits ) +{ + traits->red = format.redBufferSize(); + traits->green = format.greenBufferSize(); + traits->blue = format.blueBufferSize(); + traits->alpha = format.alpha() ? format.alphaBufferSize() : 0; + traits->depth = format.depth() ? format.depthBufferSize() : 0; + traits->stencil = format.stencil() ? format.stencilBufferSize() : 0; + + traits->sampleBuffers = format.sampleBuffers() ? 1 : 0; + traits->samples = format.samples(); + + traits->quadBufferStereo = format.stereo(); + traits->doubleBuffer = format.doubleBuffer(); + + traits->vsync = format.swapInterval() >= 1; +} + +osg::GraphicsContext::Traits* GraphicsWindowQt::createTraits( const QGLWidget* widget ) +{ + osg::GraphicsContext::Traits *traits = new osg::GraphicsContext::Traits; + + qglFormat2traits( widget->format(), traits ); + + QRect r = widget->geometry(); + traits->x = r.x(); + traits->y = r.y(); + traits->width = r.width(); + traits->height = r.height(); + + traits->windowName = widget->windowTitle().toLocal8Bit().data(); + Qt::WindowFlags f = widget->windowFlags(); + traits->windowDecoration = ( f & Qt::WindowTitleHint ) && + ( f & Qt::WindowMinMaxButtonsHint ) && + ( f & Qt::WindowSystemMenuHint ); + QSizePolicy sp = widget->sizePolicy(); + traits->supportsResize = sp.horizontalPolicy() != QSizePolicy::Fixed || + sp.verticalPolicy() != QSizePolicy::Fixed; + + return traits; +} + +bool GraphicsWindowQt::setWindowRectangleImplementation( int x, int y, int width, int height ) +{ + if ( _widget == NULL ) + return false; + + _widget->setGeometry( x, y, width, height ); + return true; +} + +void GraphicsWindowQt::getWindowRectangle( int& x, int& y, int& width, int& height ) +{ + if ( _widget ) + { + const QRect& geom = _widget->geometry(); + x = geom.x(); + y = geom.y(); + width = geom.width(); + height = geom.height(); + } +} + +bool GraphicsWindowQt::setWindowDecorationImplementation( bool windowDecoration ) +{ + Qt::WindowFlags flags = Qt::Window|Qt::CustomizeWindowHint;//|Qt::WindowStaysOnTopHint; + if ( windowDecoration ) + flags |= Qt::WindowTitleHint|Qt::WindowMinMaxButtonsHint|Qt::WindowSystemMenuHint; + _traits->windowDecoration = windowDecoration; + + if ( _widget ) + { + _widget->setWindowFlags( flags ); + + return true; + } + + return false; +} + +bool GraphicsWindowQt::getWindowDecoration() const +{ + return _traits->windowDecoration; +} + +void GraphicsWindowQt::grabFocus() +{ + if ( _widget ) + _widget->setFocus( Qt::ActiveWindowFocusReason ); +} + +void GraphicsWindowQt::grabFocusIfPointerInWindow() +{ + if ( _widget->underMouse() ) + _widget->setFocus( Qt::ActiveWindowFocusReason ); +} + +void GraphicsWindowQt::raiseWindow() +{ + if ( _widget ) + _widget->raise(); +} + +void GraphicsWindowQt::setWindowName( const std::string& name ) +{ + if ( _widget ) + _widget->setWindowTitle( name.c_str() ); +} + +std::string GraphicsWindowQt::getWindowName() +{ + return _widget ? _widget->windowTitle().toStdString() : ""; +} + +void GraphicsWindowQt::useCursor( bool cursorOn ) +{ + if ( _widget ) + { + _traits->useCursor = cursorOn; + if ( !cursorOn ) _widget->setCursor( Qt::BlankCursor ); + else _widget->setCursor( _currentCursor ); + } +} + +void GraphicsWindowQt::setCursor( MouseCursor cursor ) +{ + if ( cursor==InheritCursor && _widget ) + { + _widget->unsetCursor(); + } + + switch ( cursor ) + { + case NoCursor: _currentCursor = Qt::BlankCursor; break; + case RightArrowCursor: case LeftArrowCursor: _currentCursor = Qt::ArrowCursor; break; + case InfoCursor: _currentCursor = Qt::SizeAllCursor; break; + case DestroyCursor: _currentCursor = Qt::ForbiddenCursor; break; + case HelpCursor: _currentCursor = Qt::WhatsThisCursor; break; + case CycleCursor: _currentCursor = Qt::ForbiddenCursor; break; + case SprayCursor: _currentCursor = Qt::SizeAllCursor; break; + case WaitCursor: _currentCursor = Qt::WaitCursor; break; + case TextCursor: _currentCursor = Qt::IBeamCursor; break; + case CrosshairCursor: _currentCursor = Qt::CrossCursor; break; + case HandCursor: _currentCursor = Qt::OpenHandCursor; break; + case UpDownCursor: _currentCursor = Qt::SizeVerCursor; break; + case LeftRightCursor: _currentCursor = Qt::SizeHorCursor; break; + case TopSideCursor: case BottomSideCursor: _currentCursor = Qt::UpArrowCursor; break; + case LeftSideCursor: case RightSideCursor: _currentCursor = Qt::SizeHorCursor; break; + case TopLeftCorner: _currentCursor = Qt::SizeBDiagCursor; break; + case TopRightCorner: _currentCursor = Qt::SizeFDiagCursor; break; + case BottomRightCorner: _currentCursor = Qt::SizeBDiagCursor; break; + case BottomLeftCorner: _currentCursor = Qt::SizeFDiagCursor; break; + default: break; + }; + if ( _widget ) _widget->setCursor( _currentCursor ); +} + +bool GraphicsWindowQt::valid() const +{ + return _widget && _widget->isValid(); +} + +bool GraphicsWindowQt::realizeImplementation() +{ + // save the current context + // note: this will save only Qt-based contexts + const QGLContext *savedContext = QGLContext::currentContext(); + + // initialize GL context for the widget + if ( !valid() ) + _widget->glInit(); + + // make current + _realized = true; + bool result = makeCurrent(); + _realized = false; + + // fail if we do not have current context + if ( !result ) + { + if ( savedContext ) + const_cast< QGLContext* >( savedContext )->makeCurrent(); + + OSG_WARN << "Window realize: Can make context current." << std::endl; + return false; + } + + _realized = true; + + // make sure the event queue has the correct window rectangle size and input range + getEventQueue()->syncWindowRectangleWithGraphicsContext(); + + // make this window's context not current + // note: this must be done as we will probably make the context current from another thread + // and it is not allowed to have one context current in two threads + if( !releaseContext() ) + OSG_WARN << "Window realize: Can not release context." << std::endl; + + // restore previous context + if ( savedContext ) + const_cast< QGLContext* >( savedContext )->makeCurrent(); + + return true; +} + +bool GraphicsWindowQt::isRealizedImplementation() const +{ + return _realized; +} + +void GraphicsWindowQt::closeImplementation() +{ + if ( _widget ) + _widget->close(); + _realized = false; +} + +void GraphicsWindowQt::runOperations() +{ + // While in graphics thread this is last chance to do something useful before + // graphics thread will execute its operations. + if (_widget->getNumDeferredEvents() > 0) + _widget->processDeferredEvents(); + + if (QGLContext::currentContext() != _widget->context()) + _widget->makeCurrent(); + + GraphicsWindow::runOperations(); +} + +bool GraphicsWindowQt::makeCurrentImplementation() +{ + if (_widget->getNumDeferredEvents() > 0) + _widget->processDeferredEvents(); + + if (QGLContext::currentContext() != _widget->context()) + _widget->makeCurrent(); + + return true; +} + +bool GraphicsWindowQt::releaseContextImplementation() +{ + _widget->doneCurrent(); + return true; +} + +void GraphicsWindowQt::swapBuffersImplementation() +{ + _widget->swapBuffers(); + + // FIXME: the processDeferredEvents should really be executed in a GUI (main) thread context but + // I couln't find any reliable way to do this. For now, lets hope non of *GUI thread only operations* will + // be executed in a QGLWidget::event handler. On the other hand, calling GUI only operations in the + // QGLWidget event handler is an indication of a Qt bug. + if (_widget->getNumDeferredEvents() > 0) + _widget->processDeferredEvents(); + + // We need to call makeCurrent here to restore our previously current context + // which may be changed by the processDeferredEvents function. + if (QGLContext::currentContext() != _widget->context()) + _widget->makeCurrent(); +} + +void GraphicsWindowQt::requestWarpPointer( float x, float y ) +{ + if ( _widget ) + QCursor::setPos( _widget->mapToGlobal(QPoint((int)x,(int)y)) ); +} + +class QtWindowingSystem : public osg::GraphicsContext::WindowingSystemInterface +{ +public: + + QtWindowingSystem() + { + OSG_INFO << "QtWindowingSystemInterface()" << std::endl; + } + + ~QtWindowingSystem() + { + if (osg::Referenced::getDeleteHandler()) + { + osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); + osg::Referenced::getDeleteHandler()->flushAll(); + } + } + + // Access the Qt windowing system through this singleton class. + static QtWindowingSystem* getInterface() + { + static QtWindowingSystem* qtInterface = new QtWindowingSystem; + return qtInterface; + } + + // Return the number of screens present in the system + virtual unsigned int getNumScreens( const osg::GraphicsContext::ScreenIdentifier& /*si*/ ) + { + OSG_WARN << "osgQt: getNumScreens() not implemented yet." << std::endl; + return 0; + } + + // Return the resolution of specified screen + // (0,0) is returned if screen is unknown + virtual void getScreenSettings( const osg::GraphicsContext::ScreenIdentifier& /*si*/, osg::GraphicsContext::ScreenSettings & /*resolution*/ ) + { + OSG_WARN << "osgQt: getScreenSettings() not implemented yet." << std::endl; + } + + // Set the resolution for given screen + virtual bool setScreenSettings( const osg::GraphicsContext::ScreenIdentifier& /*si*/, const osg::GraphicsContext::ScreenSettings & /*resolution*/ ) + { + OSG_WARN << "osgQt: setScreenSettings() not implemented yet." << std::endl; + return false; + } + + // Enumerates available resolutions + virtual void enumerateScreenSettings( const osg::GraphicsContext::ScreenIdentifier& /*screenIdentifier*/, osg::GraphicsContext::ScreenSettingsList & /*resolution*/ ) + { + OSG_WARN << "osgQt: enumerateScreenSettings() not implemented yet." << std::endl; + } + + // Create a graphics context with given traits + virtual osg::GraphicsContext* createGraphicsContext( osg::GraphicsContext::Traits* traits ) + { + if (traits->pbuffer) + { + OSG_WARN << "osgQt: createGraphicsContext - pbuffer not implemented yet." << std::endl; + return NULL; + } + else + { + osg::ref_ptr< GraphicsWindowQt > window = new GraphicsWindowQt( traits ); + if (window->valid()) return window.release(); + else return NULL; + } + } + +private: + + // No implementation for these + QtWindowingSystem( const QtWindowingSystem& ); + QtWindowingSystem& operator=( const QtWindowingSystem& ); +}; + +#if USE_NO_STATIC_REGISTRATION + +// declare C entry point for static compilation. +extern "C" void graphicswindow_Qt(void) { + osg::GraphicsContext::setWindowingSystemInterface(QtWindowingSystem::getInterface()); +} + + +void osgQt::initQtWindowingSystem() { + graphicswindow_Qt(); +} +#else + +REGISTER_WINDOWINGSYSTEMINTERFACE(Qt, QtWindowingSystem) + +#endif + + +void osgQt::setViewer( osgViewer::ViewerBase *viewer ) +{ + HeartBeat::instance()->init( viewer ); +} + + +/// Constructor. Must be called from main thread. +HeartBeat::HeartBeat() : _timerId( 0 ) +{ +} + + +/// Destructor. Must be called from main thread. +HeartBeat::~HeartBeat() +{ + stopTimer(); +} + +HeartBeat* HeartBeat::instance() +{ + if (!heartBeat) + { + heartBeat = new HeartBeat(); + } + return heartBeat; +} + +void HeartBeat::stopTimer() +{ + if ( _timerId != 0 ) + { + killTimer( _timerId ); + _timerId = 0; + } +} + + +/// Initializes the loop for viewer. Must be called from main thread. +void HeartBeat::init( osgViewer::ViewerBase *viewer ) +{ + if( _viewer == viewer ) + return; + + stopTimer(); + + _viewer = viewer; + + if( viewer ) + { + _timerId = startTimer( 0 ); + _lastFrameStartTime.setStartTick( 0 ); + } +} + + +void HeartBeat::timerEvent( QTimerEvent * /*event*/ ) +{ + osg::ref_ptr< osgViewer::ViewerBase > viewer; + if( !_viewer.lock( viewer ) ) + { + // viewer has been deleted -> stop timer + stopTimer(); + return; + } + + // limit the frame rate + if( viewer->getRunMaxFrameRate() > 0.0) + { + double dt = _lastFrameStartTime.time_s(); + double minFrameTime = 1.0 / viewer->getRunMaxFrameRate(); + if (dt < minFrameTime) + OpenThreads::Thread::microSleep(static_cast(1000000.0*(minFrameTime-dt))); + } + else + { + // avoid excessive CPU loading when no frame is required in ON_DEMAND mode + if( viewer->getRunFrameScheme() == osgViewer::ViewerBase::ON_DEMAND ) + { + double dt = _lastFrameStartTime.time_s(); + if (dt < 0.01) + OpenThreads::Thread::microSleep(static_cast(1000000.0*(0.01-dt))); + } + + // record start frame time + _lastFrameStartTime.setStartTick(); + + // make frame + if( viewer->getRunFrameScheme() == osgViewer::ViewerBase::ON_DEMAND ) + { + if( viewer->checkNeedToDoFrame() ) + { + viewer->frame(); + } + } + else + { + viewer->frame(); + } + } +} diff --git a/src/osgqt/GraphicsWindowQt.h b/src/osgqt/GraphicsWindowQt.h new file mode 100644 index 00000000..183facc7 --- /dev/null +++ b/src/osgqt/GraphicsWindowQt.h @@ -0,0 +1,195 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009 Wang Rui + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSGVIEWER_GRAPHICSWINDOWQT +#define OSGVIEWER_GRAPHICSWINDOWQT + +#define USE_NO_STATIC_REGISTRATION 1 + +#include + +#include +#include +#include +#include +#include + +class QInputEvent; +class QGestureEvent; + +namespace osgViewer { + class ViewerBase; +} + +namespace osgQt +{ + +// forward declarations +class GraphicsWindowQt; + +#if USE_NO_STATIC_REGISTRATION +/// The function sets the WindowingSystem to Qt. +void initQtWindowingSystem(); +#endif + +/** The function sets the viewer that will be used after entering + * the Qt main loop (QCoreApplication::exec()). + * + * The function also initializes internal structures required for proper + * scene rendering. + * + * The method must be called from main thread. */ +void setViewer( osgViewer::ViewerBase *viewer ); + + +class GLWidget : public QGLWidget +{ + typedef QGLWidget inherited; + +public: + + GLWidget( QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false ); + GLWidget( QGLContext* context, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false ); + GLWidget( const QGLFormat& format, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0, bool forwardKeyEvents = false ); + virtual ~GLWidget(); + + inline void setGraphicsWindow( GraphicsWindowQt* gw ) { _gw = gw; } + inline GraphicsWindowQt* getGraphicsWindow() { return _gw; } + inline const GraphicsWindowQt* getGraphicsWindow() const { return _gw; } + + inline bool getForwardKeyEvents() const { return _forwardKeyEvents; } + virtual void setForwardKeyEvents( bool f ) { _forwardKeyEvents = f; } + + inline bool getTouchEventsEnabled() const { return _touchEventsEnabled; } + void setTouchEventsEnabled( bool e ); + + void setKeyboardModifiers( QInputEvent* event ); + + virtual void keyPressEvent( QKeyEvent* event ); + virtual void keyReleaseEvent( QKeyEvent* event ); + virtual void mousePressEvent( QMouseEvent* event ); + virtual void mouseReleaseEvent( QMouseEvent* event ); + virtual void mouseDoubleClickEvent( QMouseEvent* event ); + virtual void mouseMoveEvent( QMouseEvent* event ); + virtual void wheelEvent( QWheelEvent* event ); + virtual bool gestureEvent( QGestureEvent* event ); + +protected: + + int getNumDeferredEvents() + { + QMutexLocker lock(&_deferredEventQueueMutex); + return _deferredEventQueue.count(); + } + void enqueueDeferredEvent(QEvent::Type eventType, QEvent::Type removeEventType = QEvent::None) + { + QMutexLocker lock(&_deferredEventQueueMutex); + + if (removeEventType != QEvent::None) + { + if (_deferredEventQueue.removeOne(removeEventType)) + _eventCompressor.remove(eventType); + } + + if (_eventCompressor.find(eventType) == _eventCompressor.end()) + { + _deferredEventQueue.enqueue(eventType); + _eventCompressor.insert(eventType); + } + } + void processDeferredEvents(); + + friend class GraphicsWindowQt; + GraphicsWindowQt* _gw; + + QMutex _deferredEventQueueMutex; + QQueue _deferredEventQueue; + QSet _eventCompressor; + + bool _touchEventsEnabled; + + bool _forwardKeyEvents; + qreal _devicePixelRatio; + + virtual void resizeEvent( QResizeEvent* event ); + virtual void moveEvent( QMoveEvent* event ); + virtual void glDraw(); + virtual bool event( QEvent* event ); +}; + +class GraphicsWindowQt : public osgViewer::GraphicsWindow +{ +public: + GraphicsWindowQt( osg::GraphicsContext::Traits* traits, QWidget* parent = NULL, const QGLWidget* shareWidget = NULL, Qt::WindowFlags f = 0 ); + GraphicsWindowQt( GLWidget* widget ); + virtual ~GraphicsWindowQt(); + + inline GLWidget* getGLWidget() { return _widget; } + inline const GLWidget* getGLWidget() const { return _widget; } + + /// deprecated + inline GLWidget* getGraphWidget() { return _widget; } + /// deprecated + inline const GLWidget* getGraphWidget() const { return _widget; } + + struct WindowData : public osg::Referenced + { + WindowData( GLWidget* widget = NULL, QWidget* parent = NULL ): _widget(widget), _parent(parent) {} + GLWidget* _widget; + QWidget* _parent; + }; + + bool init( QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags f ); + + static QGLFormat traits2qglFormat( const osg::GraphicsContext::Traits* traits ); + static void qglFormat2traits( const QGLFormat& format, osg::GraphicsContext::Traits* traits ); + static osg::GraphicsContext::Traits* createTraits( const QGLWidget* widget ); + + virtual bool setWindowRectangleImplementation( int x, int y, int width, int height ); + virtual void getWindowRectangle( int& x, int& y, int& width, int& height ); + virtual bool setWindowDecorationImplementation( bool windowDecoration ); + virtual bool getWindowDecoration() const; + virtual void grabFocus(); + virtual void grabFocusIfPointerInWindow(); + virtual void raiseWindow(); + virtual void setWindowName( const std::string& name ); + virtual std::string getWindowName(); + virtual void useCursor( bool cursorOn ); + virtual void setCursor( MouseCursor cursor ); + inline bool getTouchEventsEnabled() const { return _widget->getTouchEventsEnabled(); } + virtual void setTouchEventsEnabled( bool e ) { _widget->setTouchEventsEnabled(e); } + + + virtual bool valid() const; + virtual bool realizeImplementation(); + virtual bool isRealizedImplementation() const; + virtual void closeImplementation(); + virtual bool makeCurrentImplementation(); + virtual bool releaseContextImplementation(); + virtual void swapBuffersImplementation(); + virtual void runOperations(); + + virtual void requestWarpPointer( float x, float y ); + +protected: + + friend class GLWidget; + GLWidget* _widget; + bool _ownsWidget; + QCursor _currentCursor; + bool _realized; +}; + +} + +#endif diff --git a/src/osgqt/QFontImplementation.cpp b/src/osgqt/QFontImplementation.cpp new file mode 100644 index 00000000..8fb10bb6 --- /dev/null +++ b/src/osgqt/QFontImplementation.cpp @@ -0,0 +1,149 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009-2010 Mathias Froehlich + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ +#include "osgqt/QFontImplementation.h" + +#include +#include +#include + +#include +#include +#include +#include + + +#ifndef OSGTEXT_GLYPH_INTERNALFORMAT +#define OSGTEXT_GLYPH_INTERNALFORMAT GL_LUMINANCE_ALPHA +#endif +#ifndef OSGTEXT_GLYPH_FORMAT +#define OSGTEXT_GLYPH_FORMAT GL_LUMINANCE_ALPHA +#endif + + +namespace osgQt { + +QFontImplementation::QFontImplementation(const QFont& font) : + _filename(font.toString().toStdString() + ".qfont"), + _font(font) +{ +} + +QFontImplementation::~QFontImplementation() +{ +} + +std::string +QFontImplementation::getFileName() const +{ + return _filename; +} + +osgText::Glyph* +QFontImplementation::getGlyph(const osgText::FontResolution& fontRes, unsigned int charcode) +{ + unsigned int fontSize = fontRes.second; + _font.setPixelSize(fontSize); + + float coord_scale = 1.0f/float(fontSize); + + QFontMetrics fontMetrics(_font); + QFontMetricsF fontMetricsF(_font); + + QRect rect = fontMetrics.boundingRect(QChar(charcode)); + QRectF rectF = fontMetricsF.boundingRect(QChar(charcode)); + + int margin = 1; + + int imageWidth = rect.width() + 2*margin; + int imageHeight = rect.height() + 2*margin; + + // Now paint the glyph into the image + QImage image(imageWidth, imageHeight, QImage::Format_ARGB32); + image.fill(0); + QPainter painter(&image); + painter.setRenderHint(QPainter::TextAntialiasing); + + painter.setFont(_font); + + painter.setBackgroundMode(Qt::TransparentMode); + painter.setBrush(Qt::white); + painter.setPen(Qt::white); + + painter.drawText(margin - rect.left(), imageHeight - 1 - (margin + rect.bottom()), QString(QChar(charcode))); + painter.end(); + + // Transfer the rendered image to osg + osg::ref_ptr glyph = new osgText::Glyph(_facade, charcode); + + unsigned int dataSize = imageWidth*imageHeight; + unsigned char* data = new unsigned char[dataSize]; + + // copy the qimage into the texture memory + for (int x = 0; x < imageWidth; ++x) + { + for (int y = 0; y < imageHeight; ++y) + { + data[x + y*imageWidth] = qAlpha(image.pixel(x, imageHeight - 1 - y)); + } + } + + // the glyph texture in osg + glyph->setImage(imageWidth, imageHeight, 1, + OSGTEXT_GLYPH_INTERNALFORMAT, + OSGTEXT_GLYPH_FORMAT, GL_UNSIGNED_BYTE, + data, + osg::Image::USE_NEW_DELETE, + 1); + glyph->setInternalTextureFormat(OSGTEXT_GLYPH_INTERNALFORMAT); + + glyph->setWidth((float)imageWidth * coord_scale); + glyph->setHeight((float)imageHeight * coord_scale); + + // Layout parameters + float leftBearing = fontMetricsF.leftBearing(QChar(charcode)); + float rightBearing = fontMetricsF.rightBearing(QChar(charcode)); + + // for horizonal layout + osg::Vec2 bottomLeft(leftBearing - margin, - rectF.bottom() - margin); + glyph->setHorizontalBearing(bottomLeft * coord_scale); + glyph->setHorizontalAdvance(fontMetricsF.width(QChar(charcode)) * coord_scale); + + // for vertical layout + osg::Vec2 topMiddle(- margin + 0.5*(leftBearing - rect.width() - rightBearing), + rectF.top() - margin); + glyph->setVerticalBearing(topMiddle * coord_scale); + glyph->setVerticalAdvance((rectF.height() + fontMetricsF.overlinePos() - fontMetricsF.xHeight()) * coord_scale); + + // ... ready + //addGlyph(fontRes, charcode, glyph.get()); + + return glyph.release(); +} + +//osg::Vec2 +//QFontImplementation::getKerning(const osgText::FontResolution& /*fontRes*/, unsigned int /*leftcharcode*/, unsigned int /*rightcharcode*/, osgText::KerningType /*kerningType*/) +//{ +// return osg::Vec2(0, 0); +//} + +osg::Vec2 QFontImplementation::getKerning(unsigned int leftcharcode, unsigned int rightcharcode, osgText::KerningType kerningType) { + return osg::Vec2(0, 0); +} + +bool +QFontImplementation::hasVertical() const +{ + return true; +} + +} diff --git a/src/osgqt/QFontImplementation.h b/src/osgqt/QFontImplementation.h new file mode 100644 index 00000000..f7af75db --- /dev/null +++ b/src/osgqt/QFontImplementation.h @@ -0,0 +1,52 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009-2010 Mathias Froehlich + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ +#ifndef QFontImplementation_H +#define QFontImplementation_H + +#include + +#include + +#include + +namespace osgQt { + +class QFontImplementation : public osgText::Font::FontImplementation +{ +public: + QFontImplementation(const QFont& font); + virtual ~QFontImplementation(); + + virtual std::string getFileName() const; + + virtual bool supportsMultipleFontResolutions() const { return true; } + + virtual osgText::Glyph* getGlyph(const osgText::FontResolution& fontRes, unsigned int charcode); + + //virtual osgText::Glyph3D* getGlyph3D(const osgText::FontResolution& /*fontRes*/, unsigned int /*charcode*/) { return 0; } + virtual osgText::Glyph3D* getGlyph3D(unsigned int charcode) { return 0; } + + //virtual osg::Vec2 getKerning(const osgText::FontResolution& fontRes, unsigned int leftcharcode, unsigned int rightcharcode, osgText::KerningType kerningType); + virtual osg::Vec2 getKerning(unsigned int leftcharcode, unsigned int rightcharcode, osgText::KerningType kerningType); + + virtual bool hasVertical() const; + +protected: + + std::string _filename; + QFont _font; +}; + +} + +#endif diff --git a/src/osgqt/QGraphicsViewAdapter.cpp b/src/osgqt/QGraphicsViewAdapter.cpp new file mode 100644 index 00000000..b68916b2 --- /dev/null +++ b/src/osgqt/QGraphicsViewAdapter.cpp @@ -0,0 +1,613 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#include "osgqt/QGraphicsViewAdapter.h" +#include "osgqt/QWidgetImage.h" + +#include + +#include +#include + +#include +#include +#include +#include + +#define MYQKEYEVENT 2000 +#define MYQPOINTEREVENT 2001 + +namespace osgQt +{ + +QCoreApplication* getOrCreateQApplication() +{ + if (QApplication::instance()==0) + { + static char** argv = 0; + static int argc = 0; + static QApplication app(argc,argv); + } + return QApplication::instance(); +} + +class MyQKeyEvent : public QEvent +{ +public: + MyQKeyEvent( int key, bool down ): + QEvent( QEvent::Type(MYQKEYEVENT) ), + _key(key), _down(down) {} + + int _key; + bool _down; +}; + +struct MyQPointerEvent : public QEvent +{ + MyQPointerEvent(int x, int y, unsigned int buttonMask): + QEvent( QEvent::Type(MYQPOINTEREVENT) ), + _x(x), _y(y),_buttonMask(buttonMask) {} + + int _x, _y; + unsigned int _buttonMask; +}; + + +const QImage::Format s_imageFormat = QImage::Format_ARGB32_Premultiplied; + +QGraphicsViewAdapter::QGraphicsViewAdapter(osg::Image* image, QWidget* widget): + _image(image), + _backgroundWidget(0), + _previousButtonMask(0), + _previousMouseX(-1), + _previousMouseY(-1), + _previousQtMouseX(-1), + _previousQtMouseY(-1), + _previousSentEvent(false), + _requiresRendering(false), + _qtKeyModifiers(Qt::NoModifier), + _backgroundColor(255, 255, 255), + _widget(widget) +{ + // make sure we have a valid QApplication before we start creating widgets. + getOrCreateQApplication(); + + + setUpKeyMap(); + + _graphicsScene = new QGraphicsScene; + _graphicsScene->addWidget(widget); + + _graphicsView = new QGraphicsView; + _graphicsView->setScene(_graphicsScene); + _graphicsView->viewport()->setParent(0); + +#if (QT_VERSION_CHECK(4, 5, 0) <= QT_VERSION) + _graphicsScene->setStickyFocus(true); +#endif + + _width = static_cast(_graphicsScene->width()); + _height = static_cast(_graphicsScene->height()); + + _qimages[0] = QImage(QSize(_width, _height), s_imageFormat); + _qimages[1] = QImage(QSize(_width, _height), s_imageFormat); + _qimages[2] = QImage(QSize(_width, _height), s_imageFormat); + + _currentRead = 0; + _currentWrite = 1; + _previousWrite = 2; + _previousFrameNumber = osg::UNINITIALIZED_FRAME_NUMBER; + _newImageAvailable = false; + + connect(_graphicsScene, SIGNAL(changed(const QList &)), + this, SLOT(repaintRequestedSlot(const QList &))); + connect(_graphicsScene, SIGNAL(sceneRectChanged(const QRectF &)), + this, SLOT(repaintRequestedSlot(const QRectF &))); + + assignImage(0); +} + +void QGraphicsViewAdapter::repaintRequestedSlot(const QList&) +{ + // OSG_NOTICE<<"QGraphicsViewAdapter::repaintRequestedSlot"<type()==MYQKEYEVENT) + { + MyQKeyEvent* keyEvent = (MyQKeyEvent*)event; + handleKeyEvent(keyEvent->_key, keyEvent->_down); + } + else if (event->type()==MYQPOINTEREVENT) + { + MyQPointerEvent* pointerEvent = (MyQPointerEvent*)event; + handlePointerEvent(pointerEvent->_x, pointerEvent->_y, pointerEvent->_buttonMask); + } +} + + +void QGraphicsViewAdapter::setUpKeyMap() +{ + _keyMap[osgGA::GUIEventAdapter::KEY_BackSpace] = Qt::Key_Backspace; + _keyMap[osgGA::GUIEventAdapter::KEY_Tab] = Qt::Key_Tab; + _keyMap[osgGA::GUIEventAdapter::KEY_Linefeed] = Qt::Key_Return; // No LineFeed in Qt! + _keyMap[osgGA::GUIEventAdapter::KEY_Clear] = Qt::Key_Clear; + _keyMap[osgGA::GUIEventAdapter::KEY_Return] = Qt::Key_Return; + _keyMap[osgGA::GUIEventAdapter::KEY_Pause] = Qt::Key_Pause; + _keyMap[osgGA::GUIEventAdapter::KEY_Scroll_Lock] = Qt::Key_ScrollLock; + _keyMap[osgGA::GUIEventAdapter::KEY_Sys_Req] = Qt::Key_SysReq; + _keyMap[osgGA::GUIEventAdapter::KEY_Escape] = Qt::Key_Escape; + _keyMap[osgGA::GUIEventAdapter::KEY_Delete] = Qt::Key_Delete; + + _keyMap[osgGA::GUIEventAdapter::KEY_Home] = Qt::Key_Home; + _keyMap[osgGA::GUIEventAdapter::KEY_Left] = Qt::Key_Left; + _keyMap[osgGA::GUIEventAdapter::KEY_Up] = Qt::Key_Up; + _keyMap[osgGA::GUIEventAdapter::KEY_Right] = Qt::Key_Right; + _keyMap[osgGA::GUIEventAdapter::KEY_Down] = Qt::Key_Down; + _keyMap[osgGA::GUIEventAdapter::KEY_Prior] = Qt::Key_Left; // no Prior in Qt + _keyMap[osgGA::GUIEventAdapter::KEY_Page_Up] = Qt::Key_PageUp; + _keyMap[osgGA::GUIEventAdapter::KEY_Next] = Qt::Key_Right; // No Next in Qt + _keyMap[osgGA::GUIEventAdapter::KEY_Page_Down] = Qt::Key_PageDown; + _keyMap[osgGA::GUIEventAdapter::KEY_End] = Qt::Key_End; + _keyMap[osgGA::GUIEventAdapter::KEY_Begin] = Qt::Key_Home; // No Begin in Qt + + _keyMap[osgGA::GUIEventAdapter::KEY_Select] = Qt::Key_Select; + _keyMap[osgGA::GUIEventAdapter::KEY_Print] = Qt::Key_Print; + _keyMap[osgGA::GUIEventAdapter::KEY_Execute] = Qt::Key_Execute; + _keyMap[osgGA::GUIEventAdapter::KEY_Insert] = Qt::Key_Insert; + //_keyMap[osgGA::GUIEventAdapter::KEY_Undo] = Qt::Key_; // no Undo + //_keyMap[osgGA::GUIEventAdapter::KEY_Redo] = Qt::Key_; // no Redo + _keyMap[osgGA::GUIEventAdapter::KEY_Menu] = Qt::Key_Menu; + _keyMap[osgGA::GUIEventAdapter::KEY_Find] = Qt::Key_Search; // no Qt Find + _keyMap[osgGA::GUIEventAdapter::KEY_Cancel] = Qt::Key_Cancel; + _keyMap[osgGA::GUIEventAdapter::KEY_Help] = Qt::Key_Help; + _keyMap[osgGA::GUIEventAdapter::KEY_Break] = Qt::Key_Escape; // no break + _keyMap[osgGA::GUIEventAdapter::KEY_Mode_switch] = Qt::Key_Mode_switch; + _keyMap[osgGA::GUIEventAdapter::KEY_Script_switch] = Qt::Key_Mode_switch; // no Script switch + _keyMap[osgGA::GUIEventAdapter::KEY_Num_Lock] = Qt::Key_NumLock; + + _keyMap[osgGA::GUIEventAdapter::KEY_Shift_L] = Qt::Key_Shift; + _keyMap[osgGA::GUIEventAdapter::KEY_Shift_R] = Qt::Key_Shift; + _keyMap[osgGA::GUIEventAdapter::KEY_Control_L] = Qt::Key_Control; + _keyMap[osgGA::GUIEventAdapter::KEY_Control_R] = Qt::Key_Control; + _keyMap[osgGA::GUIEventAdapter::KEY_Caps_Lock] = Qt::Key_CapsLock; + _keyMap[osgGA::GUIEventAdapter::KEY_Shift_Lock] = Qt::Key_CapsLock; + + _keyMap[osgGA::GUIEventAdapter::KEY_Meta_L] = Qt::Key_Meta; // Qt doesn't have a Meta L + _keyMap[osgGA::GUIEventAdapter::KEY_Meta_R] = Qt::Key_Meta; // Qt doesn't have a Meta R + _keyMap[osgGA::GUIEventAdapter::KEY_Alt_L] = Qt::Key_Alt; // Qt doesn't have a Alt L + _keyMap[osgGA::GUIEventAdapter::KEY_Alt_R] = Qt::Key_Alt; // Qt doesn't have a Alt R + _keyMap[osgGA::GUIEventAdapter::KEY_Super_L] = Qt::Key_Super_L; + _keyMap[osgGA::GUIEventAdapter::KEY_Super_R] = Qt::Key_Super_R; + _keyMap[osgGA::GUIEventAdapter::KEY_Hyper_L] = Qt::Key_Hyper_L; + _keyMap[osgGA::GUIEventAdapter::KEY_Hyper_R] = Qt::Key_Hyper_R; + + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Space] = Qt::Key_Space; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Tab] = Qt::Key_Tab; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Enter] = Qt::Key_Enter; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_F1] = Qt::Key_F1; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_F2] = Qt::Key_F2; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_F3] = Qt::Key_F3; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_F4] = Qt::Key_F4; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Home] = Qt::Key_Home; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Left] = Qt::Key_Left; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Up] = Qt::Key_Up; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Right] = Qt::Key_Right; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Down] = Qt::Key_Down; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Prior] = Qt::Key_Left; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Page_Up] = Qt::Key_PageUp; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Next] = Qt::Key_Right; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Page_Down] = Qt::Key_PageDown; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_End] = Qt::Key_End; + + // _keyMap[osgGA::GUIEventAdapter::KEY_KP_Begin] = Qt::Key_Begin; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Insert] = Qt::Key_Insert; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Delete] = Qt::Key_Delete; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Equal] = Qt::Key_Equal; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Multiply] = Qt::Key_Asterisk; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Add] = Qt::Key_Plus; + //_keyMap[osgGA::GUIEventAdapter::KEY_KP_Separator] = Qt::Key_; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Subtract] = Qt::Key_Minus; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Decimal] = Qt::Key_Period; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_Divide] = Qt::Key_division; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_0] = Qt::Key_0; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_1] = Qt::Key_1; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_2] = Qt::Key_2; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_3] = Qt::Key_3; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_4] = Qt::Key_4; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_5] = Qt::Key_5; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_6] = Qt::Key_6; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_7] = Qt::Key_7; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_8] = Qt::Key_8; + _keyMap[osgGA::GUIEventAdapter::KEY_KP_9] = Qt::Key_9; + + _keyMap[osgGA::GUIEventAdapter::KEY_F1] = Qt::Key_F1; + _keyMap[osgGA::GUIEventAdapter::KEY_F2] = Qt::Key_F2; + _keyMap[osgGA::GUIEventAdapter::KEY_F3] = Qt::Key_F3; + _keyMap[osgGA::GUIEventAdapter::KEY_F4] = Qt::Key_F4; + _keyMap[osgGA::GUIEventAdapter::KEY_F5] = Qt::Key_F5; + _keyMap[osgGA::GUIEventAdapter::KEY_F6] = Qt::Key_F6; + _keyMap[osgGA::GUIEventAdapter::KEY_F7] = Qt::Key_F7; + _keyMap[osgGA::GUIEventAdapter::KEY_F8] = Qt::Key_F8; + _keyMap[osgGA::GUIEventAdapter::KEY_F9] = Qt::Key_F9; + _keyMap[osgGA::GUIEventAdapter::KEY_F10] = Qt::Key_F10; + _keyMap[osgGA::GUIEventAdapter::KEY_F11] = Qt::Key_F11; + _keyMap[osgGA::GUIEventAdapter::KEY_F12] = Qt::Key_F12; + _keyMap[osgGA::GUIEventAdapter::KEY_F13] = Qt::Key_F13; + _keyMap[osgGA::GUIEventAdapter::KEY_F14] = Qt::Key_F14; + _keyMap[osgGA::GUIEventAdapter::KEY_F15] = Qt::Key_F15; + _keyMap[osgGA::GUIEventAdapter::KEY_F16] = Qt::Key_F16; + _keyMap[osgGA::GUIEventAdapter::KEY_F17] = Qt::Key_F17; + _keyMap[osgGA::GUIEventAdapter::KEY_F18] = Qt::Key_F18; + _keyMap[osgGA::GUIEventAdapter::KEY_F19] = Qt::Key_F19; + _keyMap[osgGA::GUIEventAdapter::KEY_F20] = Qt::Key_F20; + _keyMap[osgGA::GUIEventAdapter::KEY_F21] = Qt::Key_F21; + _keyMap[osgGA::GUIEventAdapter::KEY_F22] = Qt::Key_F22; + _keyMap[osgGA::GUIEventAdapter::KEY_F23] = Qt::Key_F23; + _keyMap[osgGA::GUIEventAdapter::KEY_F24] = Qt::Key_F24; + _keyMap[osgGA::GUIEventAdapter::KEY_F25] = Qt::Key_F25; + _keyMap[osgGA::GUIEventAdapter::KEY_F26] = Qt::Key_F26; + _keyMap[osgGA::GUIEventAdapter::KEY_F27] = Qt::Key_F27; + _keyMap[osgGA::GUIEventAdapter::KEY_F28] = Qt::Key_F28; + _keyMap[osgGA::GUIEventAdapter::KEY_F29] = Qt::Key_F29; + _keyMap[osgGA::GUIEventAdapter::KEY_F30] = Qt::Key_F30; + _keyMap[osgGA::GUIEventAdapter::KEY_F31] = Qt::Key_F31; + _keyMap[osgGA::GUIEventAdapter::KEY_F32] = Qt::Key_F32; + _keyMap[osgGA::GUIEventAdapter::KEY_F33] = Qt::Key_F33; + _keyMap[osgGA::GUIEventAdapter::KEY_F34] = Qt::Key_F34; + _keyMap[osgGA::GUIEventAdapter::KEY_F35] = Qt::Key_F35; + +} + +QWidget* QGraphicsViewAdapter::getWidgetAt(const QPoint& pos) +{ + QWidget* childAt = _graphicsView->childAt(pos); + if(childAt) + { + return childAt; + } + + QGraphicsItem* item = _graphicsView->itemAt(pos); + if(item /*&& item->contains(item->mapFromScene(pos))*/) + { + QGraphicsProxyWidget* p = qgraphicsitem_cast(item); + if(p) + { + childAt = p->widget(); + QWidget* c; + while( (c = childAt->childAt(childAt->mapFromGlobal(pos)))!=0 ) + { + childAt = c; + } + + // Widgets like QTextEdit will automatically add child scroll area widgets + // that will be selected by childAt(), we have to change to parents at that moment + // Hardcoded by the internal widget's name 'qt_scrollarea_viewport' at present + if (childAt->objectName() == "qt_scrollarea_viewport") + { + childAt = childAt->parentWidget(); + } + return childAt; + } + } + return NULL; +} + +bool QGraphicsViewAdapter::sendPointerEvent(int x, int y, int buttonMask) +{ + _previousQtMouseX = x; + _previousQtMouseY = _graphicsView->size().height() - y; + + QPoint pos(_previousQtMouseX, _previousQtMouseY); + + QWidget* targetWidget = getWidgetAt(pos); + OSG_INFO << "Get " << (targetWidget ? targetWidget->metaObject()->className() : std::string("NULL")) + << " at global pos " << x << ", " << y << std::endl; + + if (_backgroundWidget && _backgroundWidget == targetWidget) + { + // Mouse is at background widget, so ignore such events + return false; + } + + if (targetWidget != NULL || (_previousSentEvent && buttonMask != 0)) + { + QCoreApplication::postEvent(this, new MyQPointerEvent(x,y,buttonMask)); + OSG_INFO<<"sendPointerEvent("<size().height()-y; + + bool leftButtonPressed = (buttonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)!=0; + bool middleButtonPressed = (buttonMask & osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON)!=0; + bool rightButtonPressed = (buttonMask & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)!=0; + + bool prev_leftButtonPressed = (_previousButtonMask & osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)!=0; + bool prev_middleButtonPressed = (_previousButtonMask & osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON)!=0; + bool prev_rightButtonPressed = (_previousButtonMask & osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)!=0; + + OSG_INFO<<"leftButtonPressed "<mapFromGlobal(globalPos); + QContextMenuEvent* cme = new QContextMenuEvent(QContextMenuEvent::Mouse, localPos, globalPos); + QCoreApplication::postEvent(targetWidget, cme); + } + } + } + + if (eventType==QEvent::MouseButtonPress) + { + _image->sendFocusHint(true); + if (targetWidget) targetWidget->setFocus(Qt::MouseFocusReason); + } + + QMouseEvent event(eventType, globalPos, qtButton, qtMouseButtons, 0); + QCoreApplication::sendEvent(_graphicsView->viewport(), &event); + + _previousButtonMask = buttonMask; + } + else if (x != _previousMouseX || y != _previousMouseY) + { + QMouseEvent event(QEvent::MouseMove, globalPos, Qt::NoButton, qtMouseButtons, 0); + QCoreApplication::sendEvent(_graphicsView->viewport(), &event); + + _previousMouseX = x; + _previousMouseY = y; + } + + return true; +} + +bool QGraphicsViewAdapter::sendKeyEvent(int key, bool keyDown) +{ + QPoint pos(_previousQtMouseX, _previousQtMouseY); + QWidget* targetWidget = getWidgetAt(pos); + if (_backgroundWidget && _backgroundWidget == targetWidget) + { + // Mouse is at background widget, so ignore such events + return false; + } + + if (targetWidget != NULL) + { + QCoreApplication::postEvent(this, new MyQKeyEvent(key,keyDown)); + return true; + } + + return false; +} + +bool QGraphicsViewAdapter::handleKeyEvent(int key, bool keyDown) +{ + QEvent::Type eventType = keyDown ? QEvent::KeyPress : QEvent::KeyRelease; + + OSG_INFO<<"sendKeyEvent("<second; + } + else + { + qtkey = (Qt::Key)key; + input = QChar(key); + } + + QKeyEvent event(eventType, qtkey, _qtKeyModifiers, input); + QCoreApplication::sendEvent(_graphicsScene.data(), &event); + return true; +} + +void QGraphicsViewAdapter::setFrameLastRendered(const osg::FrameStamp* frameStamp) +{ + OSG_INFO<<"setFrameLastRendered("<getFrameNumber()<<")"<getFrameNumber()) + { + { + OpenThreads::ScopedLock lock(_qimagesMutex); + + // make sure that _previousFrameNumber hasn't been updated by another thread since we entered this branch. + if (_previousFrameNumber==frameStamp->getFrameNumber()) return; + _previousFrameNumber = frameStamp->getFrameNumber(); + + std::swap(_currentRead, _previousWrite); + _newImageAvailable = false; + } + + assignImage(_currentRead); + } +} + +void QGraphicsViewAdapter::clearWriteBuffer() +{ + QImage& image = _qimages[_currentWrite]; + image.fill(_backgroundColor.rgba ()); + image = QGLWidget::convertToGLFormat(image); + + // swap the write buffers in a thread safe way + OpenThreads::ScopedLock lock(_qimagesMutex); + std::swap(_currentWrite, _previousWrite); + _newImageAvailable = true; +} + +void QGraphicsViewAdapter::render() +{ + OSG_INFO<<"Current write = "<<_currentWrite< lock(_qresizeMutex); + if (_graphicsView->size().width() != _width || _graphicsView->size().height() != _height) + { + _graphicsView->setGeometry(0, 0, _width, _height); + _graphicsView->viewport()->setGeometry(0, 0, _width, _height); + + _widget->setGeometry(0, 0, _width, _height); + } + + if (image.width() != _width || image.height() != _height) + { + _qimages[_currentWrite] = QImage(_width, _height, s_imageFormat); + image = _qimages[_currentWrite]; + } + OSG_INFO << "render image " << _currentWrite << " with size (" << _width << "," << _height << ")" <render(&painter, destinationRect, sourceRect, Qt::IgnoreAspectRatio); + painter.end(); +#elif 0 + QPixmap pixmap(QPixmap::grabWidget(_graphicsView.data(), QRect(0, 0, image.width(), image.height()))); + image = pixmap.toImage(); +#else + // paint the image with the graphics view + QPixmap pixmap(image.width(), image.height()); + // Clear the image otherwise there are artifacts for some widgets that overpaint. + pixmap.fill(Qt::transparent); + QPainter painter(&pixmap); + + QRectF destinationRect(0, 0, image.width(), image.height()); + QRect sourceRect(0, 0, image.width(), image.height()); + _graphicsView->render(&painter, destinationRect, _graphicsView->viewport()->rect()); + painter.end(); + + image = pixmap.toImage(); +#endif + + // convert into OpenGL format - flipping around the Y axis and swizzling the pixels + image = QGLWidget::convertToGLFormat(image); + + // swap the write buffers in a thread safe way + OpenThreads::ScopedLock lock(_qimagesMutex); + std::swap(_currentWrite, _previousWrite); + _newImageAvailable = true; +} + +void QGraphicsViewAdapter::assignImage(unsigned int i) +{ + QImage& image = _qimages[i]; + unsigned char* data = image.bits(); + + OSG_INFO<<"assignImage("< lock(_qresizeMutex); + _width = width; + _height = height; + } + + // Force an update so render() will be called. + _graphicsScene->update(_graphicsScene->sceneRect()); +} + +} diff --git a/src/osgqt/QGraphicsViewAdapter.h b/src/osgqt/QGraphicsViewAdapter.h new file mode 100644 index 00000000..d23adf00 --- /dev/null +++ b/src/osgqt/QGraphicsViewAdapter.h @@ -0,0 +1,122 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#ifndef QGRAPHICSVIEWADAPTER +#define QGRAPHICSVIEWADAPTER + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace osgQt +{ + +extern QCoreApplication* getOrCreateQApplication(); + +class QGraphicsViewAdapter : public QObject +{ + Q_OBJECT + + public: + + QGraphicsViewAdapter(osg::Image* image, QWidget* widget); + + void setUpKeyMap(); + + bool sendPointerEvent(int x, int y, int buttonMask); + + + bool sendKeyEvent(int key, bool keyDown); + + + void setFrameLastRendered(const osg::FrameStamp* frameStamp); + + void clearWriteBuffer(); + + bool requiresRendering() const { return _requiresRendering; } + void render(); + + void assignImage(unsigned int i); + + void resize(int width, int height); + + void setBackgroundColor(QColor color) { _backgroundColor = color; } + QColor getBackgroundColor() const { return _backgroundColor; } + + /** The 'background widget' will ignore mouse/keyboard events and let following handlers handle them + It is mainly used for integrating scene graph and full-screen UIs + */ + void setBackgroundWidget(QWidget* w) { _backgroundWidget = w; } + QWidget* getBackgroundWidget() { return _backgroundWidget; } + + QGraphicsView* getQGraphicsView() { return _graphicsView; } + QGraphicsScene* getQGraphicsScene() { return _graphicsScene; } + + protected: + + bool handlePointerEvent(int x, int y, int buttonMask); + bool handleKeyEvent(int key, bool keyDown); + QWidget* getWidgetAt(const QPoint& pos); + + osg::observer_ptr _image; + QWidget* _backgroundWidget; + + int _previousButtonMask; + int _previousMouseX; + int _previousMouseY; + int _previousQtMouseX; + int _previousQtMouseY; + bool _previousSentEvent; + bool _requiresRendering; + + int _width; + int _height; + + typedef std::map KeyMap; + KeyMap _keyMap; + Qt::KeyboardModifiers _qtKeyModifiers; + + QColor _backgroundColor; + QPointer _graphicsView; + QPointer _graphicsScene; + QPointer _widget; + + OpenThreads::Mutex _qimagesMutex; + OpenThreads::Mutex _qresizeMutex; + unsigned int _previousFrameNumber; + bool _newImageAvailable; + unsigned int _currentRead; + unsigned int _currentWrite; + unsigned int _previousWrite; + QImage _qimages[3]; + + virtual void customEvent ( QEvent * event ) ; + + private slots: + + void repaintRequestedSlot(const QList ®ions); + void repaintRequestedSlot(const QRectF ®ion); + +}; + +} + +#endif diff --git a/src/osgqt/QWebViewImage.h b/src/osgqt/QWebViewImage.h new file mode 100644 index 00000000..db39d7ed --- /dev/null +++ b/src/osgqt/QWebViewImage.h @@ -0,0 +1,108 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#ifndef QWEBVIEWIMAGE +#define QWEBVIEWIMAGE + +// make sure this header isn't built as par of osgQt, leaving it to applications to build +#if !defined(OSGQT_LIBRARY) && !defined(OSG_LIBRARY_STATIC) + +#if QT_VERSION >= 0x050000 +# include +#else +# include +#endif + + +#include +#include "osgqt/QGraphicsViewAdapter.h" + +namespace osgQt +{ + +class QWebViewImage : public osgWidget::BrowserImage +{ + public: + + QWebViewImage() + { + // make sure we have a valid QApplication before we start creating widgets. + getOrCreateQApplication(); + + _webView = new QWebView; + + _webPage = new QWebPage; + _webPage->settings()->setAttribute(QWebSettings::JavascriptEnabled, true); + _webPage->settings()->setAttribute(QWebSettings::PluginsEnabled, true); + + _webView->setPage(_webPage); + + _adapter = new QGraphicsViewAdapter(this, _webView.data()); + } + + virtual void navigateTo(const std::string& url) + { + _webView->load(QUrl(url.c_str())); + } + + QWebView* getQWebView() { return _webView; } + QWebPage* getQWebPage() { return _webPage; } + QGraphicsViewAdapter* getQGraphicsViewAdapter() { return _adapter; } + + void clearWriteBuffer() + { + _adapter->clearWriteBuffer(); + } + + void render() + { + if (_adapter->requiresRendering()) _adapter->render(); + } + + virtual bool requiresUpdateCall() const { return true; } + virtual void update( osg::NodeVisitor* nv ) { render(); } + + virtual bool sendFocusHint(bool focus) + { + QFocusEvent event(focus ? QEvent::FocusIn : QEvent::FocusOut, Qt::OtherFocusReason); + QCoreApplication::sendEvent(_webPage, &event); + return true; + } + + virtual bool sendPointerEvent(int x, int y, int buttonMask) + { + return _adapter->sendPointerEvent(x,y,buttonMask); + } + + virtual bool sendKeyEvent(int key, bool keyDown) + { + return QWebViewImage::_adapter->sendKeyEvent(key, keyDown); + } + + virtual void setFrameLastRendered(const osg::FrameStamp* frameStamp) + { + _adapter->setFrameLastRendered(frameStamp); + } + + protected: + + QPointer _adapter; + QPointer _webView; + QPointer _webPage; +}; + +} + +#endif + +#endif diff --git a/src/osgqt/QWidgetImage.cpp b/src/osgqt/QWidgetImage.cpp new file mode 100644 index 00000000..6d8cfda0 --- /dev/null +++ b/src/osgqt/QWidgetImage.cpp @@ -0,0 +1,66 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#include "osgqt/QWidgetImage.h" +#include + +namespace osgQt +{ + +QWidgetImage::QWidgetImage( QWidget* widget ) +{ + // make sure we have a valid QApplication before we start creating widgets. + getOrCreateQApplication(); + + _widget = widget; + _adapter = new QGraphicsViewAdapter(this, _widget.data()); +} + +bool QWidgetImage::sendFocusHint(bool focus) +{ + QFocusEvent event(focus ? QEvent::FocusIn : QEvent::FocusOut, Qt::OtherFocusReason); + QCoreApplication::sendEvent(_widget, &event); + return true; +} + +void QWidgetImage::clearWriteBuffer() +{ + _adapter->clearWriteBuffer(); +} + +void QWidgetImage::render() +{ + if (_adapter->requiresRendering()) _adapter->render(); +} + +void QWidgetImage::scaleImage(int s,int t,int /*r*/, GLenum /*newDataType*/) +{ + _adapter->resize(s, t); +} + +void QWidgetImage::setFrameLastRendered(const osg::FrameStamp* frameStamp) +{ + _adapter->setFrameLastRendered(frameStamp); +} + +bool QWidgetImage::sendPointerEvent(int x, int y, int buttonMask) +{ + return _adapter->sendPointerEvent(x,y,buttonMask); +} + +bool QWidgetImage::sendKeyEvent(int key, bool keyDown) +{ + return _adapter->sendKeyEvent(key, keyDown); +} + +} diff --git a/src/osgqt/QWidgetImage.h b/src/osgqt/QWidgetImage.h new file mode 100644 index 00000000..0d830859 --- /dev/null +++ b/src/osgqt/QWidgetImage.h @@ -0,0 +1,60 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2009 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ + +#ifndef QWIDGETIMAGE +#define QWIDGETIMAGE + +#include + +#include "osgQt/QGraphicsViewAdapter.h" + +namespace osgQt +{ + +class QWidgetImage : public osg::Image +{ + public: + + QWidgetImage( QWidget* widget=0 ); + + QWidget* getQWidget() { return _widget; } + QGraphicsViewAdapter* getQGraphicsViewAdapter() { return _adapter; } + + virtual bool requiresUpdateCall() const { return true; } + virtual void update( osg::NodeVisitor* /*nv*/ ) { render(); } + + void clearWriteBuffer(); + + void render(); + + /// Overridden scaleImage used to catch cases where the image is + /// fullscreen and the window is resized. + virtual void scaleImage(int s,int t,int r, GLenum newDataType); + + virtual bool sendFocusHint(bool focus); + + virtual bool sendPointerEvent(int x, int y, int buttonMask); + + virtual bool sendKeyEvent(int key, bool keyDown); + + virtual void setFrameLastRendered(const osg::FrameStamp* frameStamp); + + protected: + + QPointer _adapter; + QPointer _widget; +}; + +} + +#endif diff --git a/src/osgqt/ReaderQFont.cpp b/src/osgqt/ReaderQFont.cpp new file mode 100644 index 00000000..e9326969 --- /dev/null +++ b/src/osgqt/ReaderQFont.cpp @@ -0,0 +1,66 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 2009-2010 Mathias Froehlich + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * OpenSceneGraph Public License for more details. +*/ +#include "osgqt/QFontImplementation.h" + +#include +#include +#include + +#include +#include +#include +#include + +namespace osgQFont { + +class ReaderQFont : public osgDB::ReaderWriter +{ + public: + ReaderQFont() + { + supportsExtension("qfont", "Qt font meta loader"); + } + + virtual const char* className() const { return "QFont Font Reader"; } + + virtual ReadResult readObject(const std::string& file, const osgDB::ReaderWriter::Options* /*options*/) const + { + if (!acceptsExtension(osgDB::getLowerCaseFileExtension(file))) + return ReadResult::FILE_NOT_HANDLED; + + if (!QApplication::instance()) + { + OSG_WARN << "Trying to load qfont \"" << file << "\" from within a non qt application!" << std::endl; + return ReadResult::FILE_NOT_FOUND; + } + + if (!QFontDatabase::supportsThreadedFontRendering() && QApplication::instance()->thread() != QThread::currentThread()) + { + OSG_WARN << "Trying to load qfont \"" << file << "\" from a non gui thread " + "within qt application without threaded font rendering!" << std::endl; + return ReadResult::FILE_NOT_FOUND; + } + + QFont font; + if (!font.fromString(QString::fromStdString(osgDB::getNameLessExtension(file)))) + return ReadResult::FILE_NOT_FOUND; + + return new osgText::Font(new osgQt::QFontImplementation(font)); + } +}; + +// now register with Registry to instantiate the above +// reader/writer. +REGISTER_OSGPLUGIN(qfont, ReaderQFont) + +} diff --git a/src/translations/Dyt_zh_CN.ts b/src/translations/Dyt_zh_CN.ts index d9ee43d8..32055334 100644 --- a/src/translations/Dyt_zh_CN.ts +++ b/src/translations/Dyt_zh_CN.ts @@ -267,6 +267,22 @@ + + Dialog + + + Dialog + + + + + DialogTitleBar + + + DialogTitleBar + + + DockChildList @@ -428,17 +444,17 @@ - + default - + silver - + blue @@ -1727,52 +1743,52 @@ - + new workspace + - - - + + + - warning - + name or save path is empty, please check it - + save current workspace? - + current path is contains current folder, do you want to overwrite it? - + removeRecursively failed - + mkpath failed - + name is exits - + save spaceWork directory diff --git a/src/ui/Dialog.cpp b/src/ui/Dialog.cpp index 10ec3d6c..28042aa8 100644 --- a/src/ui/Dialog.cpp +++ b/src/ui/Dialog.cpp @@ -9,30 +9,35 @@ Dialog::Dialog(QWidget* parent) : QDialog(parent) - , delegate_(FramelessDelegate::Create(this)) { + , ui_(new Ui::Dialog) + /*, delegate_(FramelessDelegate::Create(this)) */{ setWindowFlags(windowFlags() | Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); + ui_->setupUi(this); + ui_->titleBar->SetMainWidget(this); InitFrame(); } +Dialog::~Dialog() { + delete ui_; + //delete delegate_; + //delegate_ = nullptr; +} + void Dialog::DeleteThisOnClose() { setAttribute(Qt::WA_DeleteOnClose); } void Dialog::SetTitleBar(FrameTitleBar* titleBar) { - delegate_->SetTitleBar(titleBar); + /* delegate_->SetTitleBar(titleBar); QVBoxLayout* layout = reinterpret_cast(this->layout()); - layout->insertWidget(0, titleBar, 0); + layout->insertWidget(0, titleBar, 0);*/ } void Dialog::SetTitle(const QString& title) { - if (!delegate_) { - return; - } - - delegate_->SetTitle(title); + ui_->titleBar->SetTitle(title); } void Dialog::hideEvent(QHideEvent*) { @@ -47,9 +52,10 @@ bool Dialog::nativeEvent(const QByteArray& eventType, void* message, long* resul #else bool Dialog::nativeEvent(const QByteArray& eventType, void* message, qintptr* result) { #endif - if (!delegate_->nativeEvent(eventType, message, result)) { + return QDialog::nativeEvent(eventType, message, result); + /*if (!delegate_->nativeEvent(eventType, message, result)) { return QDialog::nativeEvent(eventType, message, result); - } + }*/ return true; } @@ -62,6 +68,7 @@ void Dialog::paintEvent(QPaintEvent* event) { } void Dialog::InitFrame() { + /* ui-> FrameTitleBar* titleBar = new FrameTitleBar(this); titleBar->SetMainWidget(this); @@ -77,5 +84,5 @@ void Dialog::InitFrame() { SetTitleBar(titleBar); mainDilag_ = new QWidget(this); - layout->addWidget(mainDilag_, 1); + layout->addWidget(mainDilag_, 1);*/ } diff --git a/src/ui/Dialog.h b/src/ui/Dialog.h index 081e7a01..719df8e2 100644 --- a/src/ui/Dialog.h +++ b/src/ui/Dialog.h @@ -2,6 +2,8 @@ #include +#include "ui_Dialog.h" + class FrameTitleBar; class FramelessDelegate; @@ -10,7 +12,7 @@ class Dialog : public QDialog { public: Dialog(QWidget* parent); - ~Dialog() override = default; + ~Dialog() override; void DeleteThisOnClose(); void SetTitleBar(FrameTitleBar* titleBar); @@ -27,16 +29,18 @@ protected: #endif void paintEvent(QPaintEvent* event) override; + protected: template void SetupUI(UI* ui) { - ui->setupUi(mainDilag_); + //ui->setupUi(mainDilag_); + ui->setupUi(ui_->mianWidget); } private: void InitFrame(); private: + Ui::Dialog* ui_; FramelessDelegate* delegate_; - QWidget* mainDilag_{ nullptr }; }; \ No newline at end of file diff --git a/src/ui/Dialog.ui b/src/ui/Dialog.ui new file mode 100644 index 00000000..95bd971a --- /dev/null +++ b/src/ui/Dialog.ui @@ -0,0 +1,65 @@ + + + Dialog + + + + 0 + 0 + 654 + 509 + + + + Dialog + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 40 + + + + + 16777215 + 40 + + + + + + + + + + + + DialogTitleBar + QWidget +
DialogTitleBar.h
+ 1 +
+
+ + + + +
diff --git a/src/ui/DialogTitleBar.cpp b/src/ui/DialogTitleBar.cpp new file mode 100644 index 00000000..ecb1fd6a --- /dev/null +++ b/src/ui/DialogTitleBar.cpp @@ -0,0 +1,74 @@ +#include "DialogTitleBar.h" + +#include +#include +#include +#include + +#include "common/RecourceHelper.h" +#include "ui/Dialog.h" + +#include "ui_DialogTitleBar.h" + +DialogTitleBar::DialogTitleBar(QWidget* parent) + : QWidget(parent) + , ui(new Ui::DialogTitleBar) { + ui->setupUi(this); + connect(ui->sys_close, &QPushButton::clicked, this, &DialogTitleBar::closeDialog); +} + +DialogTitleBar::~DialogTitleBar() { + delete ui; +} + +//QSize DockTitleBar::minimumSizeHint() const { +// QSize s = size(); +// return s; +//} + +void DialogTitleBar::SetTitle(const QString& title) { + ui->sys_title->setText(title); +} + +void DialogTitleBar::paintEvent(QPaintEvent* event) { + QStyleOption opt; + opt.initFrom(this); + + QPainter p(this); + style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); +} + +void DialogTitleBar::mouseReleaseEvent(QMouseEvent* event) { + if (pressed_) { + pressed_ = false; + point_ = event->pos(); + } + QWidget::mouseReleaseEvent(event); +} + +void DialogTitleBar::mousePressEvent(QMouseEvent* event) { + if (event->button() == Qt::LeftButton) { + pressed_ = true; + point_ = event->pos(); + } + QWidget::mousePressEvent(event); +} + +void DialogTitleBar::mouseMoveEvent(QMouseEvent* event) { + if (pressed_) { + QPoint movePoint = event->globalPos() - point_; + if (nullptr != mainDialog_) { + mainDialog_->move(movePoint); + } + } + QWidget::mouseMoveEvent(event); +} + +void DialogTitleBar::closeDialog() { + if (nullptr != mainDialog_) { + mainDialog_->reject(); + return; + } + close(); +} + diff --git a/src/ui/DialogTitleBar.h b/src/ui/DialogTitleBar.h new file mode 100644 index 00000000..d8acfd0e --- /dev/null +++ b/src/ui/DialogTitleBar.h @@ -0,0 +1,36 @@ +#pragma once + +#include + +namespace Ui { + class DialogTitleBar; +} + +class DialogTitleBar : public QWidget { + Q_OBJECT + +public: + DialogTitleBar(QWidget* parent = 0); + ~DialogTitleBar() override; + + //QSize minimumSizeHint() const override; + + void SetMainWidget(class Dialog* dialog) { mainDialog_ = dialog; } + void SetTitle(const QString& title); + +protected: + void paintEvent(QPaintEvent* event) override; + void mouseReleaseEvent(QMouseEvent* event) override; + void mousePressEvent(QMouseEvent* event) override; + void mouseMoveEvent(QMouseEvent* event) override; + +protected: + void closeDialog(); + +private: + Ui::DialogTitleBar* ui; + class Dialog* mainDialog_{ nullptr }; + + bool pressed_{ false }; + QPoint point_; +}; \ No newline at end of file diff --git a/src/ui/DialogTitleBar.ui b/src/ui/DialogTitleBar.ui new file mode 100644 index 00000000..d55d0e04 --- /dev/null +++ b/src/ui/DialogTitleBar.ui @@ -0,0 +1,71 @@ + + + DialogTitleBar + + + + 0 + 0 + 451 + 42 + + + + DialogTitleBar + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + + + Qt::Horizontal + + + + 612 + 20 + + + + + + + + + 32 + 32 + + + + + + + + + + + + + + diff --git a/src/ui/FrameTitleBar.cpp b/src/ui/FrameTitleBar.cpp index c1589750..8188a43d 100644 --- a/src/ui/FrameTitleBar.cpp +++ b/src/ui/FrameTitleBar.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -44,7 +45,10 @@ void FrameTitleBar::SetTitle(const QString& title) { void FrameTitleBar::SetMainWidget(QWidget* widget) { mainWidget_ = widget; - + if (nullptr == mainWidget_) { + qDebug() << __FUNCTION__ << "mainWidget is nullptr"; + return; + } } void FrameTitleBar::OnMaximized(bool maximized) { ui->sys_restore->setVisible(maximized); @@ -72,6 +76,28 @@ void FrameTitleBar::paintEvent(QPaintEvent* event) { style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); } +void FrameTitleBar::mouseReleaseEvent(QMouseEvent* event) { + Q_UNUSED(event); + pressed_ = false; +} + +void FrameTitleBar::mousePressEvent(QMouseEvent* event) { + if (nullptr == mainWidget_ || mainWidget_->isMaximized()) { + return; + } + + if (event->button() == Qt::LeftButton) { + pressed_ = true; + point_ = event->pos(); + } +} + +void FrameTitleBar::mouseMoveEvent(QMouseEvent* event) { + if (pressed_ && nullptr != mainWidget_) { + mainWidget_->move(event->pos() - point_ + mainWidget_->pos()); + } +} + void FrameTitleBar::OnMinBtnClicked() { if (nullptr == mainWidget_) { qDebug() << __FUNCTION__ << "mainWidget is nullptr"; @@ -82,13 +108,20 @@ void FrameTitleBar::OnMinBtnClicked() { } void FrameTitleBar::OnMaxBtnClicked() { - if (nullptr == mainWidget_) { qDebug() << __FUNCTION__ << "mainWidget is nullptr"; return; } - mainWidget_->showMaximized(); + if (mainWidget_->isMaximized()) { + mainWidget_->showNormal(); + } else { + mainWidget_->showMaximized(); + } + ui->sys_max->hide(); + ui->sys_restore->show(); + + ui->sys_restore->setFocusPolicy(Qt::NoFocus); } void FrameTitleBar::OnRestorClicked() { @@ -97,7 +130,17 @@ void FrameTitleBar::OnRestorClicked() { return; } - mainWidget_->showNormal(); + if (!mainWidget_->isMaximized()) { + mainWidget_->showMaximized(); + } + else { + mainWidget_->showNormal(); + } + + ui->sys_max->show(); + ui->sys_restore->hide(); + + ui->sys_max->setFocusPolicy(Qt::NoFocus); } void FrameTitleBar::OnCloseBtnClicked() { diff --git a/src/ui/FrameTitleBar.h b/src/ui/FrameTitleBar.h index 04c90d07..75ec9b84 100644 --- a/src/ui/FrameTitleBar.h +++ b/src/ui/FrameTitleBar.h @@ -41,6 +41,9 @@ public: protected: void paintEvent(QPaintEvent* event) override; + void mouseReleaseEvent(QMouseEvent* event) override; + void mousePressEvent(QMouseEvent* event) override; + void mouseMoveEvent(QMouseEvent* event) override; protected: void OnMinBtnClicked(); @@ -55,4 +58,7 @@ private: class QBoxLayout* menuLayout_{ nullptr }; class QButtonGroup* buttonCourp_{ nullptr }; unsigned int ftbButton_{ 0 }; + + bool pressed_{ false }; + QPoint point_; }; \ No newline at end of file diff --git a/src/ui/FramelessDelegate.cpp b/src/ui/FramelessDelegate.cpp index f3ae03e3..cf9b20f9 100644 --- a/src/ui/FramelessDelegate.cpp +++ b/src/ui/FramelessDelegate.cpp @@ -32,7 +32,7 @@ bool FramelessDelegate::nativeEvent(const QByteArray & eventType, void* message, } void FramelessDelegate::SetTitleBar(FrameTitleBar* titleBar) { - if (nullptr == titleBar || titleBar_ == titleBar) { + /* if (nullptr == titleBar || titleBar_ == titleBar) { return; } if (nullptr != titleBar_) { @@ -43,7 +43,7 @@ void FramelessDelegate::SetTitleBar(FrameTitleBar* titleBar) { if (nullptr != titleBar_) { titleBar_->installEventFilter(this); - } + }*/ } void FramelessDelegate::SetTitle(const QString& title) { diff --git a/src/ui/FramelessWindow.cpp b/src/ui/FramelessWindow.cpp index d490e025..96ca14fd 100644 --- a/src/ui/FramelessWindow.cpp +++ b/src/ui/FramelessWindow.cpp @@ -6,8 +6,8 @@ FramelessWindow::FramelessWindow(QWidget* parent) : QFrame(parent) - , delegate_(FramelessDelegate::Create(this)) { - //setWindowFlags(windowFlags() | Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); + /* , delegate_(FramelessDelegate::Create(this))*/ { + setWindowFlags(windowFlags() | Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); } @@ -15,7 +15,8 @@ FramelessWindow::~FramelessWindow() { } void FramelessWindow::SetTitleBar(FrameTitleBar* titleBar) { - delegate_->SetTitleBar(titleBar); + /*delegate_->SetTitleBar(titleBar);*/ + titleBar->SetMainWidget(this); } #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) @@ -23,8 +24,9 @@ bool FramelessWindow::nativeEvent(const QByteArray& eventType, void* message, qi #else bool FramelessWindow::nativeEvent(const QByteArray & eventType, void* message, long* result) { #endif - if (!delegate_->nativeEvent(eventType, message, result)) { + /* if (!delegate_->nativeEvent(eventType, message, result)) { return QFrame::nativeEvent(eventType, message, result); - } + }*/ + return QFrame::nativeEvent(eventType, message, result); return true; } diff --git a/src/ui/FramelessWindow.h b/src/ui/FramelessWindow.h index dd2a1b7f..8b0301a1 100644 --- a/src/ui/FramelessWindow.h +++ b/src/ui/FramelessWindow.h @@ -22,5 +22,5 @@ protected: #endif private: - FramelessDelegate* delegate_; + FramelessDelegate* delegate_{ nullptr }; }; \ No newline at end of file diff --git a/src/ui/MainWindow.cpp b/src/ui/MainWindow.cpp index 9621afc2..6056bcc1 100644 --- a/src/ui/MainWindow.cpp +++ b/src/ui/MainWindow.cpp @@ -38,7 +38,7 @@ MainWindow::MainWindow(QWidget* parent) } MainWindow::~MainWindow() { - OsgViewer::Get().Uninitialize(); + //OsgViewer::Get().Uninitialize(); delete ui; } @@ -178,8 +178,8 @@ void MainWindow::InitUI() { //ui->viewWidget->layout()->addWidget(qtOsgViewWidget_); qtOsgViewWidget_->LoadDefaultScene(); - OsgViewer::Get().Initialize(); - OsgViewer::Get().OnFrame(); + /*OsgViewer::Get().Initialize(); + OsgViewer::Get().OnFrame();*/ #if 1 // MatlabObject* mtlb = new MatlabObject; @@ -205,8 +205,8 @@ void MainWindow::InitDockLayout() { tabWidget_->insertTab(i, mainWindow_, strTabName); if (listDocArea[0].toList().size() > 0) { mainWindow_->setCentralWidget(qtOsgViewWidget_); - OsgViewer::Get().Initialize(); - OsgViewer::Get().OnFrame(); + //OsgViewer::Get().Initialize(); + //OsgViewer::Get().OnFrame(); } else { mainWindow_->takeCentralWidget(); } diff --git a/src/ui/ModelBrowser/ModelTreeWidget.cpp b/src/ui/ModelBrowser/ModelTreeWidget.cpp index edf45cf7..26ad02b9 100644 --- a/src/ui/ModelBrowser/ModelTreeWidget.cpp +++ b/src/ui/ModelBrowser/ModelTreeWidget.cpp @@ -320,35 +320,35 @@ void ModelTreeWidget::OnAddSatelliteEntity() { } void ModelTreeWidget::OnTrackEntity(Entity* entity) { - OsgCameraManipulator* manipulator = OsgViewer::Get().GetView()->GetCameraManipulator(); - if (nullptr == manipulator) { - LOG_WARN("manipulator is nullptr"); - return; - } + //OsgCameraManipulator* manipulator = OsgViewer::Get().GetView()->GetCameraManipulator(); + //if (nullptr == manipulator) { + // LOG_WARN("manipulator is nullptr"); + // return; + //} - - osgGA::CameraManipulator* gaManipulator = manipulator->GetManipulator(); - osgEarth::Util::EarthManipulator* ccm = dynamic_cast(gaManipulator); - if (nullptr != ccm) { - if (nullptr != entity) { - osg::MatrixTransform* mt = entity->GetRootComponent()->GetMatrixTransform(); - ccm->setNode(mt); - ccm->getSettings()->setTetherMode(osgEarth::Util::EarthManipulator::TETHER_CENTER); - osgEarth::Util::Viewpoint newVP; - newVP.setNode(mt); - double range = mt->getBound().radius() * 10.0; - newVP.range()->set(range, osgEarth::Units::METERS); + // + //osgGA::CameraManipulator* gaManipulator = manipulator->GetManipulator(); + //osgEarth::Util::EarthManipulator* ccm = dynamic_cast(gaManipulator); + //if (nullptr != ccm) { + // if (nullptr != entity) { + // osg::MatrixTransform* mt = entity->GetRootComponent()->GetMatrixTransform(); + // ccm->setNode(mt); + // ccm->getSettings()->setTetherMode(osgEarth::Util::EarthManipulator::TETHER_CENTER); + // osgEarth::Util::Viewpoint newVP; + // newVP.setNode(mt); + // double range = mt->getBound().radius() * 10.0; + // newVP.range()->set(range, osgEarth::Units::METERS); - const osg::Vec3 rotation = entity->GetRootComponent()->GetTransform()->GetRotation(); - newVP.heading()->set(rotation.x(), osgEarth::Units::DEGREES); - newVP.pitch()->set(rotation.y() - 15.0, osgEarth::Units::DEGREES); - //newVP.roll()->set(rotation.z(), osgEarth::Units::DEGREES); - ccm->setViewpoint(newVP, 1.5); - //ccm->setTetherMode(osgGA::CameraManipulator::TETHER_CENTER_AND_ROTATION); - } else { - ccm->clearViewpoint(); - } - } + // const osg::Vec3 rotation = entity->GetRootComponent()->GetTransform()->GetRotation(); + // newVP.heading()->set(rotation.x(), osgEarth::Units::DEGREES); + // newVP.pitch()->set(rotation.y() - 15.0, osgEarth::Units::DEGREES); + // //newVP.roll()->set(rotation.z(), osgEarth::Units::DEGREES); + // ccm->setViewpoint(newVP, 1.5); + // //ccm->setTetherMode(osgGA::CameraManipulator::TETHER_CENTER_AND_ROTATION); + // } else { + // ccm->clearViewpoint(); + // } + //} } void ModelTreeWidget::AddEntity(class QTreeWidgetItem* parent, Entity* entity) { diff --git a/src/ui/WorkSpace/WorkSpaceDlg.cpp b/src/ui/WorkSpace/WorkSpaceDlg.cpp index 4e74e58b..4918bb9e 100644 --- a/src/ui/WorkSpace/WorkSpaceDlg.cpp +++ b/src/ui/WorkSpace/WorkSpaceDlg.cpp @@ -15,12 +15,6 @@ WorkSpaceDlg::WorkSpaceDlg(QWidget* parent) : Dialog(parent) , ui(new Ui::WorkSpaceDlg) { - /* setWindowFlags(windowFlags() | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint); - setAttribute(Qt::WA_TranslucentBackground);*/ - - - //QWidget* mainDilag_ = new QWidget(this); - //layout->addWidget(mainDilag_, 1); SetupUI(ui); InitConnect(); @@ -116,23 +110,23 @@ void WorkSpaceDlg::OnSelectSavePath() { ui->lePath->setText(QString("%1/%2").arg(path_).arg(ui->leName->text())); LOG_INFO("save path: {}", path_.toLocal8Bit().constData()); } - -void WorkSpaceDlg::InitFrame() { - FrameTitleBar* titleBar = new FrameTitleBar(this); - titleBar->SetMainWidget(this); - - titleBar->SetSysButton(FrameTitleBar::FTB_ICON | FrameTitleBar::FTB_CLOSE); - - QVBoxLayout* layout = new QVBoxLayout(this); - layout->setContentsMargins(0, 0, 0, 0); - layout->setSpacing(0); - - layout->setStretch(0, 0); - layout->setStretch(1, 1); - layout->setAlignment(Qt::AlignLeft | Qt::AlignTop); - SetTitleBar(titleBar); - - QWidget* mainDilag_ = new QWidget(this); - layout->addWidget(mainDilag_, 1); - ui->setupUi(mainDilag_); -} +// +//void WorkSpaceDlg::InitFrame() { +// FrameTitleBar* titleBar = new FrameTitleBar(this); +// titleBar->SetMainWidget(this); +// +// titleBar->SetSysButton(FrameTitleBar::FTB_ICON | FrameTitleBar::FTB_CLOSE); +// +// QVBoxLayout* layout = new QVBoxLayout(this); +// layout->setContentsMargins(0, 0, 0, 0); +// layout->setSpacing(0); +// +// layout->setStretch(0, 0); +// layout->setStretch(1, 1); +// layout->setAlignment(Qt::AlignLeft | Qt::AlignTop); +// SetTitleBar(titleBar); +// +// QWidget* mainDilag_ = new QWidget(this); +// layout->addWidget(mainDilag_, 1); +// ui->setupUi(mainDilag_); +//} diff --git a/src/ui/WorkSpace/WorkSpaceDlg.h b/src/ui/WorkSpace/WorkSpaceDlg.h index 65e580b0..1719ae5f 100644 --- a/src/ui/WorkSpace/WorkSpaceDlg.h +++ b/src/ui/WorkSpace/WorkSpaceDlg.h @@ -19,7 +19,7 @@ protected: void OnSure(); void OnSelectSavePath(); - void InitFrame(); + //void InitFrame(); private: Ui::WorkSpaceDlg* ui; diff --git a/src/viewer/OsgViewer.cpp b/src/viewer/OsgViewer.cpp index 303d2652..0d17899d 100644 --- a/src/viewer/OsgViewer.cpp +++ b/src/viewer/OsgViewer.cpp @@ -10,130 +10,130 @@ #include "viewer/OsgView.h" #include "viewer/IUpdateRender.h" #include "workspace/WorkSpaceManager.h" - -template<> OsgViewer* Singleton::instance_ = nullptr; - -constexpr QEvent::Type sOsgViewUpdateEvent{ QEvent::Type(QEvent::User + 1) }; - -OsgViewer::OsgViewer(QObject* parent) noexcept - : QObject(parent) { - LOG_INFO("actor, self={}", fmt::ptr(this)); - - //compositeViewer_->getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true, false); -} - -OsgViewer::~OsgViewer() { - compositeViewer_ = nullptr; - LOG_INFO("dctor, self={}", fmt::ptr(this)); -} - -void OsgViewer::OnDestory() { - -} - -void OsgViewer::OnFrame(void) { - assert(nullptr != compositeViewer_); - - WorkSpaceManager::Get().OnFrame(); - - if (IsDone()) { - RenderUpdate(); - - compositeViewer_->frame(); - } - - qApp->postEvent(this, new QEvent(sOsgViewUpdateEvent)); -} - -bool OsgViewer::IsDone() const { - assert(nullptr != compositeViewer_); - bool done = compositeViewer_->done(); - return !done && initalized_; -} - -OsgView* OsgViewer::GetView() const { - if (osgViews_.empty()) { - return nullptr; - } - - return *(osgViews_.begin()); -} - -bool OsgViewer::Initialize(void) { - if (initalized_) { - return initalized_; - } - initalized_ = true; - return initalized_; -} - -void OsgViewer::Uninitialize(void) { - initalized_ = false; -} - -void OsgViewer::RegistRender(IUpdateRender* render) { - if (nullptr == render) { - return; - } - - auto itor = std::find_if(updateRenderList_.begin(), updateRenderList_.end(), [render](auto& item) { - return render == item; - } - ); - - if (itor != updateRenderList_.end()) { - return; - } - - updateRenderList_.push_back(render); -} - -void OsgViewer::UnRegistRender(IUpdateRender* render) { - if (nullptr == render) { - return; - } - - auto itor = std::find_if(updateRenderList_.begin(), updateRenderList_.end(), [render](auto& item) { - return render == item; - } - ); - if (itor != updateRenderList_.end()) { - updateRenderList_.erase(itor); - } -} - -void OsgViewer::customEvent(QEvent* event) { - if (sOsgViewUpdateEvent == event->type()) { - OnFrame(); - } -} - -void OsgViewer::OnStartPlay() { - compositeViewer_->setStartTick(0); -} - -void OsgViewer::OnAddView(OsgView* osgView, int x, int y, int width, int height) { - osgViewer::View* view = new osgViewer::View; - osgView->InitView(view); - - compositeViewer_->addView(view); - osgViews_.insert(osgView); -} - -void OsgViewer::OnRemoveView(OsgView* osgView) { - if (nullptr == osgView || nullptr == osgView->GetView()) { - LOG_WARN("osgview is nullptr or getview is nullptr"); - return; - } - - osgViews_.erase(osgView); - compositeViewer_->removeView(osgView->GetView()); -} - -void OsgViewer::RenderUpdate() { - osg::FrameStamp* frameStamp = compositeViewer_->getFrameStamp(); - double dt = frameStamp->getSimulationTime(); - for (auto render : updateRenderList_) { - render->Render(dt); - } -} +// +//template<> OsgViewer* Singleton::instance_ = nullptr; +// +//constexpr QEvent::Type sOsgViewUpdateEvent{ QEvent::Type(QEvent::User + 1) }; +// +//OsgViewer::OsgViewer(QObject* parent) noexcept +// : QObject(parent) { +// LOG_INFO("actor, self={}", fmt::ptr(this)); +// +// //compositeViewer_->getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true, false); +//} +// +//OsgViewer::~OsgViewer() { +// compositeViewer_ = nullptr; +// LOG_INFO("dctor, self={}", fmt::ptr(this)); +//} +// +//void OsgViewer::OnDestory() { +// +//} +// +//void OsgViewer::OnFrame(void) { +// assert(nullptr != compositeViewer_); +// +// WorkSpaceManager::Get().OnFrame(); +// +// if (IsDone()) { +// RenderUpdate(); +// +// compositeViewer_->frame(); +// } +// +// qApp->postEvent(this, new QEvent(sOsgViewUpdateEvent)); +//} +// +//bool OsgViewer::IsDone() const { +// assert(nullptr != compositeViewer_); +// bool done = compositeViewer_->done(); +// return !done && initalized_; +//} +// +//OsgView* OsgViewer::GetView() const { +// if (osgViews_.empty()) { +// return nullptr; +// } +// +// return *(osgViews_.begin()); +//} +// +//bool OsgViewer::Initialize(void) { +// if (initalized_) { +// return initalized_; +// } +// initalized_ = true; +// return initalized_; +//} +// +//void OsgViewer::Uninitialize(void) { +// initalized_ = false; +//} +// +//void OsgViewer::RegistRender(IUpdateRender* render) { +// if (nullptr == render) { +// return; +// } +// +// auto itor = std::find_if(updateRenderList_.begin(), updateRenderList_.end(), [render](auto& item) { +// return render == item; +// } +// ); +// +// if (itor != updateRenderList_.end()) { +// return; +// } +// +// updateRenderList_.push_back(render); +//} +// +//void OsgViewer::UnRegistRender(IUpdateRender* render) { +// if (nullptr == render) { +// return; +// } +// +// auto itor = std::find_if(updateRenderList_.begin(), updateRenderList_.end(), [render](auto& item) { +// return render == item; +// } +// ); +// if (itor != updateRenderList_.end()) { +// updateRenderList_.erase(itor); +// } +//} +// +//void OsgViewer::customEvent(QEvent* event) { +// if (sOsgViewUpdateEvent == event->type()) { +// OnFrame(); +// } +//} +// +//void OsgViewer::OnStartPlay() { +// compositeViewer_->setStartTick(0); +//} +// +//void OsgViewer::OnAddView(OsgView* osgView, int x, int y, int width, int height) { +// osgViewer::View* view = new osgViewer::View; +// osgView->InitView(view); +// +// compositeViewer_->addView(view); +// osgViews_.insert(osgView); +//} +// +//void OsgViewer::OnRemoveView(OsgView* osgView) { +// if (nullptr == osgView || nullptr == osgView->GetView()) { +// LOG_WARN("osgview is nullptr or getview is nullptr"); +// return; +// } +// +// osgViews_.erase(osgView); +// compositeViewer_->removeView(osgView->GetView()); +//} +// +//void OsgViewer::RenderUpdate() { +// osg::FrameStamp* frameStamp = compositeViewer_->getFrameStamp(); +// double dt = frameStamp->getSimulationTime(); +// for (auto render : updateRenderList_) { +// render->Render(dt); +// } +//} diff --git a/src/viewer/OsgViewer.h b/src/viewer/OsgViewer.h index d3589ed4..4d3b1758 100644 --- a/src/viewer/OsgViewer.h +++ b/src/viewer/OsgViewer.h @@ -11,47 +11,47 @@ class OsgView; class IUpdateRender; - -class OsgViewer : public QObject, public Singleton { - Q_OBJECT - -public: - explicit OsgViewer(QObject* parent = nullptr) noexcept; - ~OsgViewer() override; - - void SetViewer(osgViewer::CompositeViewer* viewer) { - compositeViewer_ = viewer; - } - void OnDestory(); - - void OnFrame(void); - - bool IsDone(void) const; - - OsgView* GetView() const; - - bool Initialize(void); - void Uninitialize(void); - - void RegistRender(IUpdateRender* render); - void UnRegistRender(IUpdateRender* render); - -protected: - void customEvent(QEvent* event) override; - - void OnStartPlay(); - - void OnAddView(OsgView* view, int x, int y, int width, int height); - void OnRemoveView(OsgView* view); - void RenderUpdate(); - -private: - osgViewer::CompositeViewer* compositeViewer_; - bool initalized_{ false }; - - using OsgViewSet = std::set; - OsgViewSet osgViews_; - - using UpdateRenderList = std::vector; - UpdateRenderList updateRenderList_; -}; +// +//class OsgViewer : public QObject, public Singleton { +// Q_OBJECT +// +//public: +// explicit OsgViewer(QObject* parent = nullptr) noexcept; +// ~OsgViewer() override; +// +// void SetViewer(osgViewer::CompositeViewer* viewer) { +// compositeViewer_ = viewer; +// } +// void OnDestory(); +// +// void OnFrame(void); +// +// bool IsDone(void) const; +// +// OsgView* GetView() const; +// +// bool Initialize(void); +// void Uninitialize(void); +// +// void RegistRender(IUpdateRender* render); +// void UnRegistRender(IUpdateRender* render); +// +//protected: +// void customEvent(QEvent* event) override; +// +// void OnStartPlay(); +// +// void OnAddView(OsgView* view, int x, int y, int width, int height); +// void OnRemoveView(OsgView* view); +// void RenderUpdate(); +// +//private: +// osgViewer::CompositeViewer* compositeViewer_; +// bool initalized_{ false }; +// +// using OsgViewSet = std::set; +// OsgViewSet osgViews_; +// +// using UpdateRenderList = std::vector; +// UpdateRenderList updateRenderList_; +//}; diff --git a/src/viewer/OsgWidget.cpp b/src/viewer/OsgWidget.cpp index 41bf41e6..6011f62e 100644 --- a/src/viewer/OsgWidget.cpp +++ b/src/viewer/OsgWidget.cpp @@ -33,11 +33,11 @@ static void ConfigureView( osgViewer::View* view ) { OsgWidget::OsgWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { - // // setAttribute(Qt::WA_PaintOnScreen, true); - // // setAttribute(Qt::WA_StaticContents, true); - // // setAttribute(Qt::WA_NoSystemBackground, true); - // setAttribute(Qt::WA_OpaquePaintEvent, true); - // // setAttribute(Qt::WA_DontCreateNativeAncestors, false); + // setAttribute(Qt::WA_PaintOnScreen, true); + // setAttribute(Qt::WA_StaticContents, true); + // setAttribute(Qt::WA_NoSystemBackground, true); + //setAttribute(Qt::WA_OpaquePaintEvent, true); + // setAttribute(Qt::WA_DontCreateNativeAncestors, false); setThreadingModel(osgViewer::ViewerBase::SingleThreaded); setMouseTracking(true); diff --git a/src/viewer/QtOsgViewWidget.cpp b/src/viewer/QtOsgViewWidget.cpp index d53d110e..cbeaf0ae 100644 --- a/src/viewer/QtOsgViewWidget.cpp +++ b/src/viewer/QtOsgViewWidget.cpp @@ -85,19 +85,19 @@ void QtOsgViewWidget::Initialize(void) { if (nullptr == workspace) { return; } - OsgCameraManipulator* manipulator = OsgViewer::Get().GetView()->GetCameraManipulator(); - if (nullptr == manipulator) { - LOG_WARN("manipulator is nullptr"); - return; - } - osgGA::CameraManipulator* gaManipulator = manipulator->GetManipulator(); - osgEarth::Util::EarthManipulator* ccm = dynamic_cast(gaManipulator); - if (nullptr == ccm) { - LOG_WARN("ccm is nullptr"); - return; - } + //OsgCameraManipulator* manipulator = OsgViewer::Get().GetView()->GetCameraManipulator(); + //if (nullptr == manipulator) { + // LOG_WARN("manipulator is nullptr"); + // return; + //} + //osgGA::CameraManipulator* gaManipulator = manipulator->GetManipulator(); + //osgEarth::Util::EarthManipulator* ccm = dynamic_cast(gaManipulator); + //if (nullptr == ccm) { + // LOG_WARN("ccm is nullptr"); + // return; + //} - ccm->setViewpoint(workspace->GetHomeViewpoint(), 3.0); + //ccm->setViewpoint(workspace->GetHomeViewpoint(), 3.0); } ); diff --git a/src/viewer/UpdateRenderStd.cpp b/src/viewer/UpdateRenderStd.cpp index ba005a09..3b7e49d9 100644 --- a/src/viewer/UpdateRenderStd.cpp +++ b/src/viewer/UpdateRenderStd.cpp @@ -3,7 +3,7 @@ #include "viewer/OsgViewer.h" UpdateRenderStd::UpdateRenderStd() { - OsgViewer::Get().RegistRender(this); + //OsgViewer::Get().RegistRender(this); } UpdateRenderStd::~UpdateRenderStd() { @@ -11,5 +11,5 @@ UpdateRenderStd::~UpdateRenderStd() { } void UpdateRenderStd::OnDestroy() { - OsgViewer::Get().UnRegistRender(this); + //OsgViewer::Get().UnRegistRender(this); }