Working on consistent input response

This commit is contained in:
Brad Davis 2015-05-30 02:01:11 -07:00
parent 2758718c8d
commit fec214c552
12 changed files with 130 additions and 113 deletions

View file

@ -1102,9 +1102,9 @@ bool Application::event(QEvent* event) {
}
bool Application::eventFilter(QObject* object, QEvent* event) {
if (event->type() == QEvent::ShortcutOverride) {
if (DependencyManager::get<OffscreenUi>()->shouldSwallowShortcut(event)) {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
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<CameraToolBox>()->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<QTouchEvent::TouchPoint>& tPoints = event->touchPoints();
_touchAvg = glm::vec2(0);
int numTouches = tPoints.count();
@ -4675,21 +4674,23 @@ void Application::updateDisplayMode() {
}
}
if (_displayPlugin != newDisplayPlugin) {
DependencyManager::get<OffscreenUi>()->setProxyWindow(nullptr);
if (newDisplayPlugin) {
_offscreenContext->makeCurrent();
newDisplayPlugin->activate(this);
newDisplayPlugin->installEventFilter(DependencyManager::get<OffscreenUi>().data());
newDisplayPlugin->installEventFilter(qApp);
QWindow* pluginWindow = newDisplayPlugin->getWindow();
if (pluginWindow) {
// Event filter queue is 'last in, first used'
pluginWindow->installEventFilter(DependencyManager::get<OffscreenUi>().data());
pluginWindow->installEventFilter(qApp);
DependencyManager::get<OffscreenUi>()->setProxyWindow(pluginWindow);
}
}
_offscreenContext->makeCurrent();
}
}
std::swap(newDisplayPlugin, _displayPlugin);
if (newDisplayPlugin) {
newDisplayPlugin->removeEventFilter(DependencyManager::get<OffscreenUi>().data());
newDisplayPlugin->deactivate();
_offscreenContext->makeCurrent();
}

View file

@ -9,13 +9,10 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QMimeData>
#include <QUrl>
#include <QWindow>
#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();
}
}

View file

@ -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<OffscreenUi>().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);
}

View file

@ -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;

View file

@ -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)

View file

@ -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;

View file

@ -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<OffscreenUi>();
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<OffscreenUi>()->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;
}

View file

@ -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:

View file

@ -32,5 +32,4 @@ public:
virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize);
virtual void finishFrame();
};

View file

@ -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

View file

@ -9,7 +9,11 @@
#include "OculusBaseDisplayPlugin.h"
class OffscreenGlCanvas;
class OculusWin32DisplayPlugin : public OculusBaseDisplayPlugin {
public:
virtual bool isSupported();
private:
OffscreenGlCanvas* _canvas;
};

View file

@ -16,6 +16,8 @@
#include <MatrixStack.h>
#include <PathUtils.h>
#include <TextureCache.h>
#include <gpu/GLBackend.h>
#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<TextureCache>()->
// getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png");
crosshairTexture = DependencyManager::get<TextureCache>()->
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 <typename F>
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();
}