From e35242345c2643b8f6c6c399abda7a0315e73994 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 25 Nov 2014 09:26:24 -0800 Subject: [PATCH] first cut at HMD Tools dialog --- interface/src/Application.h | 2 + interface/src/Menu.cpp | 18 ++++ interface/src/Menu.h | 6 ++ interface/src/devices/OculusManager.cpp | 64 +++++++++++- interface/src/devices/OculusManager.h | 4 + interface/src/ui/HMDToolsDialog.cpp | 131 ++++++++++++++++++++++++ interface/src/ui/HMDToolsDialog.h | 43 ++++++++ 7 files changed, 266 insertions(+), 2 deletions(-) create mode 100644 interface/src/ui/HMDToolsDialog.cpp create mode 100644 interface/src/ui/HMDToolsDialog.h diff --git a/interface/src/Application.h b/interface/src/Application.h index c75202d96f..9f2cdbd520 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -71,6 +71,7 @@ #include "scripting/ControllerScriptingInterface.h" #include "ui/BandwidthDialog.h" #include "ui/BandwidthMeter.h" +#include "ui/HMDToolsDialog.h" #include "ui/ModelsBrowser.h" #include "ui/NodeBounds.h" #include "ui/OctreeStatsDialog.h" @@ -395,6 +396,7 @@ private slots: void connectedToDomain(const QString& hostname); + friend class HMDToolsDialog; void setFullscreen(bool fullscreen); void setEnable3DTVMode(bool enable3DTVMode); void setEnableVRMode(bool enableVRMode); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index db5cd5170d..151e9682ed 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -97,6 +97,7 @@ Menu::Menu() : _jsConsole(NULL), _octreeStatsDialog(NULL), _lodToolsDialog(NULL), + _hmdToolsDialog(NULL), _newLocationDialog(NULL), _userLocationsDialog(NULL), #if defined(Q_OS_MAC) || defined(Q_OS_WIN) @@ -334,6 +335,7 @@ Menu::Menu() : appInstance, SLOT(cameraMenuChanged())); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::UserInterface, Qt::Key_Slash, true); + addActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools, 0, this, SLOT(hmdTools())); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::EnableVRMode, 0, false, appInstance, @@ -1646,6 +1648,22 @@ void Menu::lodToolsClosed() { } } +void Menu::hmdTools() { + if (!_hmdToolsDialog) { + _hmdToolsDialog = new HMDToolsDialog(Application::getInstance()->getGLWidget()); + connect(_hmdToolsDialog, SIGNAL(closed()), SLOT(hmdToolsClosed())); + _hmdToolsDialog->show(); + } + _hmdToolsDialog->raise(); +} + +void Menu::hmdToolsClosed() { + if (_hmdToolsDialog) { + delete _hmdToolsDialog; + _hmdToolsDialog = NULL; + } +} + void Menu::cycleFrustumRenderMode() { _frustumDrawMode = (FrustumDrawMode)((_frustumDrawMode + 1) % FRUSTUM_DRAW_MODE_COUNT); updateFrustumRenderModeAction(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 7e153eba5e..e41e2f35ea 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -76,6 +76,7 @@ class QSettings; class AnimationsDialog; class AttachmentsDialog; class BandwidthDialog; +class HMDToolsDialog; class LodToolsDialog; class MetavoxelEditor; class MetavoxelNetworkSimulator; @@ -120,6 +121,7 @@ public: ViewFrustumOffset getViewFrustumOffset() const { return _viewFrustumOffset; } OctreeStatsDialog* getOctreeStatsDialog() const { return _octreeStatsDialog; } LodToolsDialog* getLodToolsDialog() const { return _lodToolsDialog; } + HMDToolsDialog* getHMDToolsDialog() const { return _hmdToolsDialog; } int getMaxVoxels() const { return _maxVoxels; } QAction* getUseVoxelShader() const { return _useVoxelShader; } @@ -183,6 +185,7 @@ public slots: void bandwidthDetails(); void octreeStatsDetails(); void lodTools(); + void hmdTools(); void loadSettings(QSettings* settings = NULL); void saveSettings(QSettings* settings = NULL); void importSettings(); @@ -217,6 +220,7 @@ private slots: void bandwidthDetailsClosed(); void octreeStatsDetailsClosed(); void lodToolsClosed(); + void hmdToolsClosed(); void cycleFrustumRenderMode(); void runTests(); void showMetavoxelEditor(); @@ -284,6 +288,7 @@ private: QDialog* _jsConsole; OctreeStatsDialog* _octreeStatsDialog; LodToolsDialog* _lodToolsDialog; + HMDToolsDialog* _hmdToolsDialog; QPointer _newLocationDialog; QPointer _userLocationsDialog; #if defined(Q_OS_MAC) || defined(Q_OS_WIN) @@ -412,6 +417,7 @@ namespace MenuOption { const QString NamesAboveHeads = "Names Above Heads"; const QString GoToUser = "Go To User"; const QString HeadMouse = "Head Mouse"; + const QString HMDTools = "HMD Tools"; const QString IncreaseAvatarSize = "Increase Avatar Size"; const QString IncreaseVoxelSize = "Increase Voxel Size"; const QString KeyboardMotorControl = "Enable Keyboard Motor Control"; diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index e68a08a8f4..dfec98c358 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -14,9 +14,14 @@ #include "OculusManager.h" +#include +#include #include +#include #include + +#include #include #include "Application.h" @@ -75,9 +80,7 @@ glm::vec3 OculusManager::_rightEyePosition = glm::vec3(); void OculusManager::connect() { #ifdef HAVE_LIBOVR _calibrationState = UNCALIBRATED; - qDebug() << "Oculus SDK" << OVR_VERSION_STRING; - ovr_Initialize(); _ovrHmd = ovrHmd_Create(0); @@ -86,6 +89,7 @@ void OculusManager::connect() { UserActivityLogger::getInstance().connectedDevice("hmd", "oculus"); } _isConnected = true; + #if defined(__APPLE__) || defined(_WIN32) _eyeFov[0] = _ovrHmd->DefaultEyeFov[0]; _eyeFov[1] = _ovrHmd->DefaultEyeFov[1]; @@ -715,3 +719,59 @@ void OculusManager::overrideOffAxisFrustum(float& left, float& right, float& bot } #endif } + +int OculusManager::getHMDScreen() { + int hmdScreenIndex = -1; // unknown +#ifdef HAVE_LIBOVR + // TODO: it might be smarter to handle multiple HMDs connected in this case. but for now, + // we will simply assume the initialization code that set up _ovrHmd picked the best hmd + + if (_ovrHmd) { + QString productNameFromOVR = _ovrHmd->ProductName; + + int hmdWidth = _ovrHmd->Resolution.w; + int hmdHeight = _ovrHmd->Resolution.h; + int hmdAtX = _ovrHmd->WindowsPos.x; + int hmdAtY = _ovrHmd->WindowsPos.y; + + // we will score the likelihood that each screen is a match based on the following + // rubrik of potential matching features + const int EXACT_NAME_MATCH = 100; + const int SIMILAR_NAMES = 10; + const int EXACT_LOCATION_MATCH = 50; + const int EXACT_RESOLUTION_MATCH = 25; + + int bestMatchScore = 0; + + // look at the display list and see if we can find the best match + QDesktopWidget* desktop = QApplication::desktop(); + int screenNumber = 0; + foreach (QScreen* screen, QGuiApplication::screens()) { + QString screenName = screen->name(); + QRect screenRect = desktop->screenGeometry(screenNumber); + + int screenScore = 0; + if (screenName == productNameFromOVR) { + screenScore += EXACT_NAME_MATCH; + } + if (similarStrings(screenName, productNameFromOVR)) { + screenScore += SIMILAR_NAMES; + } + if (hmdWidth == screenRect.width() && hmdHeight == screenRect.height()) { + screenScore += EXACT_RESOLUTION_MATCH; + } + if (hmdAtX == screenRect.x() && hmdAtY == screenRect.y()) { + screenScore += EXACT_LOCATION_MATCH; + } + if (screenScore > bestMatchScore) { + bestMatchScore = screenScore; + hmdScreenIndex = screenNumber; + } + + screenNumber++; + } + } +#endif + return hmdScreenIndex; +} + diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index 20e43d572c..2e0354f61a 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -52,11 +52,15 @@ public: static glm::vec3 getLeftEyePosition() { return _leftEyePosition; } static glm::vec3 getRightEyePosition() { return _rightEyePosition; } + static int getHMDScreen(); + private: #ifdef HAVE_LIBOVR static void generateDistortionMesh(); static void renderDistortionMesh(ovrPosef eyeRenderPose[ovrEye_Count]); + static bool similarNames(const QString& nameA,const QString& nameB); + struct DistortionVertex { glm::vec2 pos; glm::vec2 texR; diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp new file mode 100644 index 0000000000..11cc652c37 --- /dev/null +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -0,0 +1,131 @@ +// +// HMDToolsDialog.cpp +// interface/src/ui +// +// Created by Brad Hefta-Gaub on 7/19/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include "Menu.h" +#include "devices/OculusManager.h" +#include "ui/HMDToolsDialog.h" + + +HMDToolsDialog::HMDToolsDialog(QWidget* parent) : + QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) +{ + this->setWindowTitle("HMD Tools"); + + // Create layouter + QFormLayout* form = new QFormLayout(); + + // Add a button to enter + QPushButton* enterModeButton = new QPushButton("Enter HMD Mode"); + form->addRow("", enterModeButton); + connect(enterModeButton,SIGNAL(clicked(bool)),this,SLOT(enterModeClicked(bool))); + + // Add a button to leave + QPushButton* leaveModeButton = new QPushButton("Leave HMD Mode"); + form->addRow("", leaveModeButton); + connect(leaveModeButton,SIGNAL(clicked(bool)),this,SLOT(leaveModeClicked(bool))); + + this->QDialog::setLayout(form); + + + _wasMoved = false; + + _previousRect = Application::getInstance()->getWindow()->rect(); + + + // QDesktopWidget::screenCountChanged() SIGNAL +} + +HMDToolsDialog::~HMDToolsDialog() { +} + +void HMDToolsDialog::enterModeClicked(bool checked) { + qDebug() << "enterModeClicked"; + + int hmdScreen = OculusManager::getHMDScreen(); + + // hack to test... + if (hmdScreen == -1) { + hmdScreen = 0; + } + + if (hmdScreen >= 0) { + QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); + QScreen* targetScreen = QGuiApplication::screens()[hmdScreen]; + + _previousRect = Application::getInstance()->getWindow()->rect(); + qDebug() << "_previousRect:" << _previousRect; + _previousRect = QRect(mainWindow->mapToGlobal(_previousRect.topLeft()), + mainWindow->mapToGlobal(_previousRect.bottomRight())); + qDebug() << "after mapping... _previousRect:" << _previousRect; + + _previousScreen = mainWindow->screen(); + qDebug() << "_previousScreen:" << _previousScreen; + + QRect rect = QApplication::desktop()->screenGeometry(hmdScreen); + + qDebug() << "about to move to:" << rect.topLeft(); + + mainWindow->setScreen(targetScreen); + mainWindow->setGeometry(rect); + + _wasMoved = true; + } + Application::getInstance()->setFullscreen(true); + Application::getInstance()->setEnableVRMode(true); +} + +void HMDToolsDialog::moveWindowAfterLeaveMode() { + qDebug() << "moveWindowAfterLeaveMode"; + QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); + mainWindow->setScreen(_previousScreen); + mainWindow->setGeometry(_previousRect); +} + +void HMDToolsDialog::leaveModeClicked(bool checked) { + qDebug() << "leaveModeClicked"; + + Application::getInstance()->setFullscreen(false); + Application::getInstance()->setEnableVRMode(false); + + if (_wasMoved) { + QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); + mainWindow->setScreen(_previousScreen); + mainWindow->setGeometry(_previousRect); + + const int SLIGHT_DELAY = 1500; + QTimer::singleShot(SLIGHT_DELAY, this, SLOT(moveWindowAfterLeaveMode())); + } + _wasMoved = false; +} + +void HMDToolsDialog::reject() { + // Just regularly close upon ESC + this->QDialog::close(); +} + +void HMDToolsDialog::closeEvent(QCloseEvent* event) { + this->QDialog::closeEvent(event); + emit closed(); +} + + diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h new file mode 100644 index 0000000000..ac6bebc5f4 --- /dev/null +++ b/interface/src/ui/HMDToolsDialog.h @@ -0,0 +1,43 @@ +// +// HMDToolsDialog.h +// interface/src/ui +// +// Created by Brad Hefta-Gaub on 7/19/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_HMDToolsDialog_h +#define hifi_HMDToolsDialog_h + +#include + +class HMDToolsDialog : public QDialog { + Q_OBJECT +public: + // Sets up the UI + HMDToolsDialog(QWidget* parent); + ~HMDToolsDialog(); + +signals: + void closed(); + +public slots: + void reject(); + void enterModeClicked(bool checked); + void leaveModeClicked(bool checked); + void moveWindowAfterLeaveMode(); + +protected: + // Emits a 'closed' signal when this dialog is closed. + void closeEvent(QCloseEvent*); + +private: + bool _wasMoved; + QRect _previousRect; + QScreen* _previousScreen; +}; + +#endif // hifi_HMDToolsDialog_h