#include "viewer/GraphicsWindowEx.h" #include #include #include #include #include #include #include "viewer/StateEx.h" #include "config.h" #include "common/SpdLogger.h" // //GraphicsWindowEx::GraphicsWindowEx(osg::GraphicsContext::Traits* traits) // : osgViewer::GraphicsWindowEmbedded(traits) { // _traits = traits; // // init(); //} namespace { 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_Insert] = osgGA::GUIEventAdapter::KEY_KP_Insert; } ~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; static void setKeyboardModifiers(osgGA::EventQueue* eventQueue, QInputEvent* event) { unsigned 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; eventQueue->getCurrentEventState()->setModKeyMask(mask); } } // namespace GraphicsWindowEx::GraphicsWindowEx(int x, int y, int width, int height) : osgViewer::GraphicsWindowEmbedded(x, y, width == 0 ? 1 : width, height == 0 ? 1 : height) { LOG_INFO("actor, self={}", spdlog::fmt_lib::ptr(this)); } GraphicsWindowEx::~GraphicsWindowEx() { LOG_INFO("dctor isSharedContextSet_:{}, self={}", isSharedContextSet_, spdlog::fmt_lib::ptr(this)); } bool GraphicsWindowEx::realizeImplementation() { LOG_INFO("realizeImplementation, isRealized_:{}, self={}", isRealized_, spdlog::fmt_lib::ptr(this)); if (isRealized_) { return true; } dyt_check(nullptr != _state); _state->resetVertexAttributeAlias(false); _state->setModeValidity(GL_LIGHTING, false); _state->setModeValidity(GL_NORMALIZE, false); _state->setModeValidity(GL_RESCALE_NORMAL, false); _state->setModeValidity(GL_LINE_STIPPLE, false); _state->setModeValidity(GL_LINE_SMOOTH, false); isRealized_ = true; return true; } bool GraphicsWindowEx::makeCurrentImplementation() { LOG_INFO("makeCurrentImplementation, isRealized_:{}, self={}", isRealized_, spdlog::fmt_lib::ptr(this)); InitOffScreenContext(); if (nullptr != offScreenContext_) { offScreenContext_->makeCurrent(offScreenSurface_.get()); } InitFrameBuffer(); setDefaultFboId(renderFramebuffer_->handle()); renderFramebuffer_->bind(); return true; } void GraphicsWindowEx::closeImplementation() { if (!isSharedContextSet_) { return; } if (isFrameBufferInitialized_) { offScreenContext_->makeCurrent(offScreenSurface_.get()); renderFramebuffer_.reset(); sharedFrameBuffer_.reset(); offScreenContext_->doneCurrent(); } offScreenContext_.reset(); offScreenSurface_.reset(); } bool GraphicsWindowEx::releaseContextImplementation() { LOG_INFO("releaseContextImplementation, self={}", spdlog::fmt_lib::ptr(this)); QOpenGLFramebufferObject::bindDefault(); offScreenContext_->doneCurrent(); return true; } void GraphicsWindowEx::swapBuffersImplementation() { offScreenContext_->functions()->glFinish(); frameBufferId_ = renderFramebuffer_->texture(); if (!isRenderDonwn_) { return; } qSwap(renderFramebuffer_, sharedFrameBuffer_); isRenderDonwn_ = false; } bool GraphicsWindowEx::SetSharedContext(QOpenGLContext* sharedContext) { sharedContext_ = sharedContext; return true; } void GraphicsWindowEx::ReizeWindow(int width, int height) { if (width == _traits->width && height == _traits->height) { return; } getEventQueue()->windowResize(0, 0, width, height); resized(0, 0, width, height); isFrameBufferInitialized_ = false; } void GraphicsWindowEx::keyPressEvent(QKeyEvent* event) { setKeyboardModifiers(getEventQueue(), event); int value = s_QtKeyboardMap.remapKey(event); getEventQueue()->keyPress(value); } void GraphicsWindowEx::keyReleaseEvent(QKeyEvent* event) { if (event->isAutoRepeat()) { event->ignore(); } else { setKeyboardModifiers(getEventQueue(), event); int value = s_QtKeyboardMap.remapKey(event); getEventQueue()->keyPress(value); } } void GraphicsWindowEx::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(getEventQueue(), event); getEventQueue()->mouseButtonPress(event->x() * windowScale_, event->y() * windowScale_, button); } void GraphicsWindowEx::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(getEventQueue(), event); getEventQueue()->mouseButtonRelease(event->x() * windowScale_, event->y() * windowScale_, button); } void GraphicsWindowEx::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(getEventQueue(), event); getEventQueue()->mouseDoubleButtonPress(event->x() * windowScale_, event->y() * windowScale_, button); } void GraphicsWindowEx::mouseMoveEvent(QMouseEvent* event) { setKeyboardModifiers(getEventQueue(), event); getEventQueue()->mouseMotion(event->x() * windowScale_, event->y() * windowScale_); } void GraphicsWindowEx::wheelEvent(QWheelEvent* event) { setKeyboardModifiers(getEventQueue(), event); getEventQueue()->mouseMotion(event->x() * windowScale_, event->y() * windowScale_); 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)); } void GraphicsWindowEx::InitOffScreenContext() { if (isSharedContextSet_) { return; } if (!offScreenSurface_) { offScreenSurface_.reset(new QOffscreenSurface); } if (!offScreenContext_) { offScreenContext_.reset(new QOpenGLContext); } LOG_INFO("Set shared context"); dyt_check(nullptr != sharedContext_); offScreenContext_->setFormat(sharedContext_->format()); offScreenContext_->setShareContext(sharedContext_); isSharedContextSet_ = offScreenContext_->create(); if (!isSharedContextSet_) { LOG_ERROR("Failed to create offscreen context"); return; } offScreenSurface_->setFormat(offScreenContext_->format()); offScreenSurface_->create(); } void GraphicsWindowEx::InitFrameBuffer() { if (isFrameBufferInitialized_) { return; } QOpenGLFramebufferObjectFormat format; format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); dyt_check(nullptr != _traits); renderFramebuffer_.reset(new QOpenGLFramebufferObject(_traits->width, _traits->height, format)); sharedFrameBuffer_.reset(new QOpenGLFramebufferObject(_traits->width, _traits->height, format)); isFrameBufferInitialized_ = true; }