From fec214c552231c4f05b42f8d3e3f65b5e01c5067 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 30 May 2015 02:01:11 -0700 Subject: [PATCH] Working on consistent input response --- interface/src/Application.cpp | 25 +++--- interface/src/GLCanvas.cpp | 11 +-- interface/src/LegacyDisplayPlugin.cpp | 15 ++-- interface/src/LegacyDisplayPlugin.h | 3 + libraries/display-plugins/CMakeLists.txt | 2 +- .../src/display-plugins/DisplayPlugin.h | 3 + .../display-plugins/GlWindowDisplayPlugin.cpp | 80 +++++++---------- .../display-plugins/GlWindowDisplayPlugin.h | 9 +- .../src/display-plugins/NullDisplayPlugin.h | 1 - .../OculusWin32DisplayPlugin.cpp | 2 +- .../OculusWin32DisplayPlugin.h | 4 + .../src/display-plugins/Tv3dDisplayPlugin.cpp | 88 +++++++++++-------- 12 files changed, 130 insertions(+), 113 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9839794127..071ca30c10 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1102,9 +1102,9 @@ bool Application::event(QEvent* event) { } bool Application::eventFilter(QObject* object, QEvent* event) { - if (event->type() == QEvent::ShortcutOverride) { - if (DependencyManager::get()->shouldSwallowShortcut(event)) { + auto offscreenUi = DependencyManager::get(); + if (offscreenUi->shouldSwallowShortcut(event)) { event->accept(); return true; } @@ -1115,7 +1115,6 @@ bool Application::eventFilter(QObject* object, QEvent* event) { return true; } } - return false; } @@ -1459,7 +1458,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { } - if (activeWindow() == _window) { + if (hasFocus()) { _keyboardMouseDevice.mousePressEvent(event); if (event->button() == Qt::LeftButton) { @@ -1500,7 +1499,7 @@ void Application::mouseDoublePressEvent(QMouseEvent* event, unsigned int deviceI return; } - if (activeWindow() == _window) { + if (hasFocus()) { if (event->button() == Qt::LeftButton) { if (mouseOnScreen()) { if (DependencyManager::get()->mouseDoublePressEvent(getMouseX(), getMouseY())) { @@ -1525,7 +1524,7 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { return; } - if (activeWindow() == _window) { + if (hasFocus()) { _keyboardMouseDevice.mouseReleaseEvent(event); if (event->button() == Qt::LeftButton) { @@ -1563,7 +1562,7 @@ void Application::touchUpdateEvent(QTouchEvent* event) { _keyboardMouseDevice.touchUpdateEvent(event); bool validTouch = false; - if (activeWindow() == _window) { + if (hasFocus()) { const QList& tPoints = event->touchPoints(); _touchAvg = glm::vec2(0); int numTouches = tPoints.count(); @@ -4675,21 +4674,23 @@ void Application::updateDisplayMode() { } } if (_displayPlugin != newDisplayPlugin) { + DependencyManager::get()->setProxyWindow(nullptr); + if (newDisplayPlugin) { _offscreenContext->makeCurrent(); newDisplayPlugin->activate(this); + newDisplayPlugin->installEventFilter(DependencyManager::get().data()); + newDisplayPlugin->installEventFilter(qApp); QWindow* pluginWindow = newDisplayPlugin->getWindow(); if (pluginWindow) { - // Event filter queue is 'last in, first used' - pluginWindow->installEventFilter(DependencyManager::get().data()); - pluginWindow->installEventFilter(qApp); DependencyManager::get()->setProxyWindow(pluginWindow); - } + } _offscreenContext->makeCurrent(); - } + } std::swap(newDisplayPlugin, _displayPlugin); if (newDisplayPlugin) { + newDisplayPlugin->removeEventFilter(DependencyManager::get().data()); newDisplayPlugin->deactivate(); _offscreenContext->makeCurrent(); } diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index 066ae97ebf..6fb2a742f3 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -9,13 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include -#include #include "Application.h" #include "GLCanvas.h" -#include "MainWindow.h" + const int MSECS_PER_FRAME_WHEN_THROTTLED = 66; @@ -35,7 +32,7 @@ void GLCanvas::stopFrameTimer() { } bool GLCanvas::isThrottleRendering() const { - return _throttleRendering || Application::getInstance()->getWindow()->isMinimized(); + return _throttleRendering || parentWidget()->isMinimized(); } int GLCanvas::getDeviceWidth() const { @@ -57,7 +54,7 @@ void GLCanvas::initializeGL() { } void GLCanvas::paintGL() { - if (!_throttleRendering && !Application::getInstance()->getWindow()->isMinimized()) { + if (!isThrottleRendering()) { Application::getInstance()->paintGL(); } } @@ -93,7 +90,7 @@ void GLCanvas::activeChanged(Qt::ApplicationState state) { void GLCanvas::throttleRender() { _frameTimer.start(_idleRenderInterval); - if (!Application::getInstance()->getWindow()->isMinimized()) { + if (!parentWidget()->isMinimized()) { Application::getInstance()->paintGL(); } } diff --git a/interface/src/LegacyDisplayPlugin.cpp b/interface/src/LegacyDisplayPlugin.cpp index 4fbb02e454..76629e896e 100644 --- a/interface/src/LegacyDisplayPlugin.cpp +++ b/interface/src/LegacyDisplayPlugin.cpp @@ -29,12 +29,8 @@ static QWidget * oldWidget = nullptr; void LegacyDisplayPlugin::activate(PluginContainer * container) { _window = new GLCanvas(); - QOpenGLContext * sourceContext = QOpenGLContext::currentContext(); - - QOpenGLContext * newContext = new QOpenGLContext(); - { QSurfaceFormat format; format.setOption(QSurfaceFormat::DebugContext); @@ -56,11 +52,8 @@ void LegacyDisplayPlugin::activate(PluginContainer * container) { _timer.start(8); } - void LegacyDisplayPlugin::deactivate() { _timer.stop(); - _window->removeEventFilter(DependencyManager::get().data()); - _window->removeEventFilter(qApp); // FIXME, during shutdown, this causes an NPE. Need to deactivate the plugin before the main window is destroyed. // if (qApp->getWindow()) { // qApp->getWindow()->setCentralWidget(oldWidget); @@ -121,3 +114,11 @@ ivec2 LegacyDisplayPlugin::getTrueMousePosition() const { QWindow* LegacyDisplayPlugin::getWindow() const { return _window->windowHandle(); } + +void LegacyDisplayPlugin::installEventFilter(QObject* filter) { + _window->installEventFilter(filter); +} + +void LegacyDisplayPlugin::removeEventFilter(QObject* filter) { + _window->removeEventFilter(filter); +} \ No newline at end of file diff --git a/interface/src/LegacyDisplayPlugin.h b/interface/src/LegacyDisplayPlugin.h index 223f4d9e01..d41dc25090 100644 --- a/interface/src/LegacyDisplayPlugin.h +++ b/interface/src/LegacyDisplayPlugin.h @@ -31,7 +31,10 @@ public: virtual void preDisplay(); virtual void idle(); virtual ivec2 getTrueMousePosition() const; + virtual QWindow* getWindow() const; + virtual void installEventFilter(QObject* filter); + virtual void removeEventFilter(QObject* filter); protected: virtual void makeCurrent() final; diff --git a/libraries/display-plugins/CMakeLists.txt b/libraries/display-plugins/CMakeLists.txt index cbfecfb0da..98d15a7804 100644 --- a/libraries/display-plugins/CMakeLists.txt +++ b/libraries/display-plugins/CMakeLists.txt @@ -5,7 +5,7 @@ setup_hifi_library(OpenGL) setup_hifi_opengl() -link_hifi_libraries(shared plugins ) +link_hifi_libraries(shared plugins gpu render-utils) add_dependency_external_projects(glm) find_package(GLM REQUIRED) diff --git a/libraries/display-plugins/src/display-plugins/DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/DisplayPlugin.h index b2726288cf..f8563f4e20 100644 --- a/libraries/display-plugins/src/display-plugins/DisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/DisplayPlugin.h @@ -92,6 +92,9 @@ public: // The window for the surface, used for event interception. May be null. virtual QWindow* getWindow() const = 0; + virtual void installEventFilter(QObject* filter) {} + virtual void removeEventFilter(QObject* filter) {} + // The mouse position relative to the window (or proxy window) surface virtual glm::ivec2 getTrueMousePosition() const = 0; diff --git a/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp index a456bf667b..fe3347a185 100644 --- a/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp @@ -47,51 +47,6 @@ QWindow* GlWindowDisplayPlugin::getWindow() const { return _window; } -bool GlWindowDisplayPlugin::eventFilter(QObject* object, QEvent* event) { - if (qApp->eventFilter(object, event)) { - return true; - } - - // FIXME - /* - auto offscreenUi = DependencyManager::get(); - if (offscreenUi->eventFilter(object, event)) { - return true; - } - */ - - // distinct calls for easier debugging with breakpoints - switch (event->type()) { - case QEvent::KeyPress: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - case QEvent::KeyRelease: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - case QEvent::MouseButtonPress: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - case QEvent::MouseButtonRelease: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - case QEvent::FocusIn: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - case QEvent::FocusOut: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - case QEvent::Resize: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - case QEvent::MouseMove: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - default: - break; - } - return false; -} - void GlWindowDisplayPlugin::activate(PluginContainer * container) { Q_ASSERT(nullptr == _window); _window = new GlWindow(QOpenGLContext::currentContext()); @@ -101,8 +56,6 @@ void GlWindowDisplayPlugin::activate(PluginContainer * container) { _timer->start(8); makeCurrent(); customizeContext(); - // FIXME - //DependencyManager::get()->setProxyWindow(_window); } void GlWindowDisplayPlugin::deactivate() { @@ -125,3 +78,36 @@ glm::ivec2 GlWindowDisplayPlugin::getCanvasSize() const { bool GlWindowDisplayPlugin::hasFocus() const { return _window->isActive(); } + +void GlWindowDisplayPlugin::installEventFilter(QObject* filter) { + _window->installEventFilter(filter); +} + +void GlWindowDisplayPlugin::removeEventFilter(QObject* filter) { + _window->removeEventFilter(filter); +} + +bool GlWindowDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { + switch (event->type()) { + case QEvent::MouseMove: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::FocusIn: + case QEvent::FocusOut: + case QEvent::Resize: + case QEvent::TouchBegin: + case QEvent::TouchEnd: + case QEvent::TouchUpdate: + case QEvent::Wheel: + case QEvent::DragEnter: + case QEvent::Drop: + if (QCoreApplication::sendEvent(QCoreApplication::instance(), event)) { + return true; + } + break; + } + return false; +} \ No newline at end of file diff --git a/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h index 1833ab3a84..9a7c284ff9 100644 --- a/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h @@ -21,16 +21,23 @@ public: virtual QSize getDeviceSize() const final; virtual glm::ivec2 getCanvasSize() const final; virtual bool hasFocus() const; - virtual bool eventFilter(QObject* object, QEvent* event); virtual glm::ivec2 getTrueMousePosition() const; virtual QWindow* getWindow() const; + virtual bool eventFilter(QObject* receiver, QEvent* event); + virtual void installEventFilter(QObject* filter); + virtual void removeEventFilter(QObject* filter); protected: virtual void makeCurrent() final; virtual void doneCurrent() final; virtual void swapBuffers() final; + + // Called by the activate method to specify the initial window geometry + // flags, etc virtual void customizeWindow() = 0; + // Called by the activate method after the GL context has been created to + // initialize OpenGL context settings needed by the plugin virtual void customizeContext() = 0; private: diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h index 0fedf872b1..123bf55d33 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h @@ -32,5 +32,4 @@ public: virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize, GLuint overlayTexture, const glm::uvec2& overlaySize); virtual void finishFrame(); - }; diff --git a/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp index a15550a20b..ee6f2dc4a4 100644 --- a/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp @@ -14,7 +14,6 @@ #include "../OglplusHelpers.h" -#if 0 bool OculusWin32DisplayPlugin::isSupported() { ovr_Initialize(nullptr); bool result = false; @@ -25,6 +24,7 @@ bool OculusWin32DisplayPlugin::isSupported() { return result; } +#if 0 // A basic wrapper for constructing a framebuffer with a renderbuffer // for the depth attachment and an undefined type for the color attachement // This allows us to reuse the basic framebuffer code for both the Mirror diff --git a/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h index 6866f096fc..d1203bde77 100644 --- a/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h @@ -9,7 +9,11 @@ #include "OculusBaseDisplayPlugin.h" +class OffscreenGlCanvas; class OculusWin32DisplayPlugin : public OculusBaseDisplayPlugin { public: virtual bool isSupported(); + +private: + OffscreenGlCanvas* _canvas; }; diff --git a/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp index b6607e5518..db5e1422cf 100644 --- a/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp @@ -16,6 +16,8 @@ #include #include +#include +#include #include "../OglplusHelpers.h" @@ -35,6 +37,7 @@ bool Tv3dDisplayPlugin::isSupported() const { static ProgramPtr program; static ShapeWrapperPtr plane; +static gpu::TexturePointer crosshairTexture; void Tv3dDisplayPlugin::customizeWindow() { _window->setFlags(Qt::FramelessWindowHint); @@ -64,15 +67,19 @@ void Tv3dDisplayPlugin::customizeContext() { program = loadDefaultShader(); plane = loadPlane(program); Context::ClearColor(0, 0, 0, 1); - // _crosshairTexture = DependencyManager::get()-> - // getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png"); + crosshairTexture = DependencyManager::get()-> + getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png"); } +// FIXME make this into a setting that can be adjusted const float DEFAULT_IPD = 0.064f; const float HALF_DEFAULT_IPD = DEFAULT_IPD / 2.0f; glm::mat4 Tv3dDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProjection) const { + // Refer to http://www.nvidia.com/content/gtc-2010/pdfs/2010_gtc2010.pdf on creating + // stereo projection matrices. Do NOT use "toe-in", use translation. + float nearZ = DEFAULT_NEAR_CLIP; // near clipping plane float screenZ = 0.25f; // screen projection plane // FIXME verify this is the right calculation @@ -91,15 +98,24 @@ glm::mat4 Tv3dDisplayPlugin::getModelview(Eye eye, const glm::mat4& baseModelvie return baseModelview * glm::translate(mat4(), vec3(modelviewShift, 0, 0)); } - +template +void sbs_for_each_eye(const uvec2& size, F f) { + QRect r(QPoint(0, 0), QSize(size.x / 2, size.y)); + for_each_eye([&](Eye eye) { + oglplus::Context::Viewport(r.x(), r.y(), r.width(), r.height()); + f(eye); + }, [&] { + r.moveLeft(r.width()); + }); +} void Tv3dDisplayPlugin::display( GLuint sceneTexture, const glm::uvec2& sceneSize, GLuint overlayTexture, const glm::uvec2& overlaySize) { - QSize size = getDeviceSize(); + uvec2 size = toGlm(getDeviceSize()); using namespace oglplus; - Context::Viewport(size.width(), size.height()); + Context::Viewport(size.x, size.y); Context::Clear().ColorBuffer().DepthBuffer(); Mat4Uniform(*program, "ModelView").Set(mat4()); @@ -109,10 +125,11 @@ void Tv3dDisplayPlugin::display( plane->Draw(); - const float overlayAspect = aspect(toGlm(size)); + // FIXME the + const float screenAspect = aspect(size); const GLfloat distance = 1.0f; const GLfloat halfQuadHeight = distance * tan(DEFAULT_FIELD_OF_VIEW_DEGREES); - const GLfloat halfQuadWidth = halfQuadHeight * (float)size.width() / (float)size.height(); + const GLfloat halfQuadWidth = halfQuadHeight * screenAspect; const GLfloat quadWidth = halfQuadWidth * 2.0f; const GLfloat quadHeight = halfQuadHeight * 2.0f; @@ -123,38 +140,39 @@ void Tv3dDisplayPlugin::display( Context::Enable(Capability::Blend); glBindTexture(GL_TEXTURE_2D, overlayTexture); - mat4 pr = glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), aspect(toGlm(size)), DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP); + mat4 pr = glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), screenAspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP); Mat4Uniform(*program, "Projection").Set(pr); + // Position the camera relative to the overlay texture MatrixStack mv; - mv.translate(vec3(0, 0, -distance)).scale(vec3(0.7f, 0.7f / overlayAspect, 1.0f)); // .scale(vec3(quadWidth, quadHeight, 1.0)); + mv.translate(vec3(0, 0, -distance)).scale(vec3(0.7f, 0.7f / screenAspect, 1.0f)); // .scale(vec3(quadWidth, quadHeight, 1.0)); + sbs_for_each_eye(size, [&](Eye eye) { + mv.withPush([&] { + // translate + mv.top() = getModelview(eye, mv.top()); + Mat4Uniform(*program, "ModelView").Set(mv.top()); + plane->Draw(); + }); + }); - QRect r(QPoint(0, 0), QSize(size.width() / 2, size.height())); - for (int i = 0; i < 2; ++i) { - Context::Viewport(r.x(), r.y(), r.width(), r.height()); - Mat4Uniform(*program, "ModelView").Set(mv.top()); - plane->Draw(); - r.moveLeft(r.width()); - } - -#if 0 - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture)); - glm::vec2 canvasSize = qApp->getCanvasSize(); - glm::vec2 mouse = qApp->getMouse(); + glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(crosshairTexture)); + glm::vec2 canvasSize = getCanvasSize(); + glm::vec2 mouse = toGlm(_window->mapFromGlobal(QCursor::pos())); mouse /= canvasSize; mouse *= 2.0f; mouse -= 1.0f; mouse.y *= -1.0f; - mv.translate(mouse); - mv.scale(0.1f); - Mat4Uniform(*program, "ModelView").Set(mv.top()); - r = QRect(QPoint(0, 0), QSize(size.width() / 2, size.height())); - for (int i = 0; i < 2; ++i) { - Context::Viewport(r.x(), r.y(), r.width(), r.height()); - plane->Draw(); - r.moveLeft(r.width()); - } -#endif + sbs_for_each_eye(size, [&](Eye eye) { + mv.withPush([&] { + // translate + mv.top() = getModelview(eye, mv.top()); + mv.translate(mouse); + //mv.scale(0.05f); + mv.scale(vec3(0.025f, 0.05f, 1.0f)); + Mat4Uniform(*program, "ModelView").Set(mv.top()); + plane->Draw(); + }); + }); Context::Disable(Capability::Blend); } @@ -166,11 +184,9 @@ void Tv3dDisplayPlugin::activate(PluginContainer * container) { void Tv3dDisplayPlugin::deactivate() { makeCurrent(); - if (plane) { - plane.reset(); - program.reset(); -// _crosshairTexture.reset(); - } + plane.reset(); + program.reset(); + crosshairTexture.reset(); doneCurrent(); GlWindowDisplayPlugin::deactivate(); }