371 lines
12 KiB
C++
371 lines
12 KiB
C++
#include "viewer/GraphicsWindowEx.h"
|
|
|
|
#include <QOpenGLFrameBufferObjectFormat>
|
|
#include <QOpenGLFunctions>
|
|
#include <QThread>
|
|
#include <QKeyEvent>
|
|
#include <QMouseEvent>
|
|
#include <QWheelEvent>
|
|
|
|
#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<unsigned int, int> 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;
|
|
}
|