diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index fd1ac7c6db..397f883b3e 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1568,6 +1568,10 @@ void Application::checkBandwidthMeterClick() { } void Application::setFullscreen(bool fullscreen) { + if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen) != fullscreen) { + Menu::getInstance()->getActionForOption(MenuOption::Fullscreen)->setChecked(fullscreen); + } + if (Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) { if (fullscreen) { // Menu show() after hide() doesn't work with Rift VR display so set height instead. @@ -1578,6 +1582,7 @@ void Application::setFullscreen(bool fullscreen) { } _window->setWindowState(fullscreen ? (_window->windowState() | Qt::WindowFullScreen) : (_window->windowState() & ~Qt::WindowFullScreen)); + _window->show(); } void Application::setEnable3DTVMode(bool enable3DTVMode) { @@ -1585,6 +1590,10 @@ void Application::setEnable3DTVMode(bool enable3DTVMode) { } void Application::setEnableVRMode(bool enableVRMode) { + if (Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode) != enableVRMode) { + Menu::getInstance()->getActionForOption(MenuOption::EnableVRMode)->setChecked(enableVRMode); + } + if (enableVRMode) { if (!OculusManager::isConnected()) { // attempt to reconnect the Oculus manager - it's possible this was a workaround @@ -1595,6 +1604,11 @@ void Application::setEnableVRMode(bool enableVRMode) { OculusManager::recalibrate(); } else { OculusManager::abandonCalibration(); + + _mirrorCamera.setHmdPosition(glm::vec3()); + _mirrorCamera.setHmdRotation(glm::quat()); + _myCamera.setHmdPosition(glm::vec3()); + _myCamera.setHmdRotation(glm::quat()); } resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); @@ -3505,7 +3519,6 @@ void Application::deleteVoxelAt(const VoxelDetail& voxel) { } } - void Application::resetSensors() { _mouseX = _glWidget->width() / 2; _mouseY = _glWidget->height() / 2; @@ -3519,7 +3532,11 @@ void Application::resetSensors() { _prioVR.reset(); //_leapmotion.reset(); - QCursor::setPos(_mouseX, _mouseY); + QScreen* currentScreen = _window->windowHandle()->screen(); + QWindow* mainWindow = _window->windowHandle(); + QPoint windowCenter = mainWindow->geometry().center(); + QCursor::setPos(currentScreen, windowCenter); + _myAvatar->reset(); QMetaObject::invokeMethod(&_audio, "reset", Qt::QueuedConnection); 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 baac3629ac..2c7b4a9efd 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,12 @@ Menu::Menu() : appInstance, SLOT(cameraMenuChanged())); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::UserInterface, Qt::Key_Slash, true); + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::HMDTools, Qt::META | Qt::Key_H, + false, + this, + SLOT(hmdTools(bool))); + + addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::EnableVRMode, 0, false, appInstance, @@ -652,6 +659,10 @@ Menu::Menu() : Menu::~Menu() { bandwidthDetailsClosed(); octreeStatsDetailsClosed(); + if (_hmdToolsDialog) { + delete _hmdToolsDialog; + _hmdToolsDialog = NULL; + } } void Menu::loadSettings(QSettings* settings) { @@ -1594,6 +1605,25 @@ void Menu::lodToolsClosed() { } } +void Menu::hmdTools(bool showTools) { + if (showTools) { + if (!_hmdToolsDialog) { + _hmdToolsDialog = new HMDToolsDialog(Application::getInstance()->getGLWidget()); + connect(_hmdToolsDialog, SIGNAL(closed()), SLOT(hmdToolsClosed())); + } + _hmdToolsDialog->show(); + _hmdToolsDialog->raise(); + } else { + hmdToolsClosed(); + } + Application::getInstance()->getWindow()->activateWindow(); +} + +void Menu::hmdToolsClosed() { + Menu::getInstance()->getActionForOption(MenuOption::HMDTools)->setChecked(false); + _hmdToolsDialog->hide(); +} + 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 6ba34ca2b9..0d46c4020d 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(bool showTools); 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) @@ -400,6 +405,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/avatar/Head.cpp b/interface/src/avatar/Head.cpp index e237d0ae6b..660ebfcbb3 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -273,7 +273,12 @@ void Head::setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition) { _correctedLookAtPosition = correctedLookAtPosition; } -glm::quat Head::getCameraOrientation () const { +glm::quat Head::getCameraOrientation() const { + // NOTE: Head::getCameraOrientation() is not used for orienting the camera "view" while in Oculus mode, so + // you may wonder why this code is here. This method will be called while in Oculus mode to determine how + // to change the driving direction while in Oculus mode. It is used to support driving toward where you're + // head is looking. Note that in oculus mode, your actual camera view and where your head is looking is not + // always the same. if (OculusManager::isConnected()) { return getOrientation(); } 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/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 55d4cf7c8b..1307672ad1 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -984,7 +984,8 @@ void ApplicationOverlay::renderAudioMeter() { const int AUDIO_METER_X = MIRROR_VIEW_LEFT_PADDING + MUTE_ICON_SIZE + AUDIO_METER_INSET + AUDIO_METER_GAP; int audioMeterY; - bool boxed = Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && + bool smallMirrorVisible = Menu::getInstance()->isOptionChecked(MenuOption::Mirror) && !OculusManager::isConnected(); + bool boxed = smallMirrorVisible && !Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror); if (boxed) { audioMeterY = MIRROR_VIEW_HEIGHT + AUDIO_METER_GAP + MUTE_ICON_PADDING; diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp new file mode 100644 index 0000000000..a5e54fa546 --- /dev/null +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -0,0 +1,258 @@ +// +// 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) , + _previousScreen(NULL), + _hmdScreen(NULL), + _previousDialogScreen(NULL) +{ + 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))); + + // Create a label with debug details... + _debugDetails = new QLabel(); + _debugDetails->setText(getDebugDetails()); + const int WIDTH = 350; + const int HEIGHT = 100; + _debugDetails->setFixedSize(WIDTH, HEIGHT); + form->addRow("", _debugDetails); + + this->QDialog::setLayout(form); + + _wasMoved = false; + _previousRect = Application::getInstance()->getWindow()->rect(); + Application::getInstance()->getWindow()->activateWindow(); + + // watch for our application window moving screens. If it does we want to update our screen details + QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); + connect(mainWindow, &QWindow::screenChanged, this, &HMDToolsDialog::applicationWindowScreenChanged); + + // watch for our dialog window moving screens. If it does we want to enforce our rules about what screens we're + // allowed on + QWindow* dialogWindow = windowHandle(); + connect(dialogWindow, &QWindow::screenChanged, this, &HMDToolsDialog::dialogWindowScreenChanged); + connect(dialogWindow, &QWindow::xChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); + connect(dialogWindow, &QWindow::yChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); + connect(dialogWindow, &QWindow::widthChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); + connect(dialogWindow, &QWindow::heightChanged, this, &HMDToolsDialog::dialogWindowGeometryChanged); +} + +HMDToolsDialog::~HMDToolsDialog() { +} + +void HMDToolsDialog::applicationWindowScreenChanged(QScreen* screen) { + _debugDetails->setText(getDebugDetails()); +} + +void HMDToolsDialog::dialogWindowGeometryChanged(int arg) { + QWindow* dialogWindow = windowHandle(); + _previousDialogRect = rect(); + _previousDialogRect = QRect(dialogWindow->mapToGlobal(_previousDialogRect.topLeft()), + dialogWindow->mapToGlobal(_previousDialogRect.bottomRight())); + _previousDialogScreen = dialogWindow->screen(); +} + +void HMDToolsDialog::dialogWindowScreenChanged(QScreen* screen) { + _debugDetails->setText(getDebugDetails()); + + // if we have more than one screen, and a known hmdScreen then try to + // keep our dialog off of the hmdScreen + if (QApplication::desktop()->screenCount() > 1) { + int hmdScreenNumber = OculusManager::getHMDScreen(); + + if (hmdScreenNumber >= 0) { + QScreen* hmdScreen = QGuiApplication::screens()[hmdScreenNumber]; + + if (screen == hmdScreen) { + qDebug() << "HMD Tools: Whoa! What are you doing? You don't want to move me to the HMD Screen!"; + QWindow* dialogWindow = windowHandle(); + + // try to pick a better screen + QScreen* betterScreen = NULL; + + QWindow* appWindow = Application::getInstance()->getWindow()->windowHandle(); + QScreen* appScreen = appWindow->screen(); + + if (_previousDialogScreen && _previousDialogScreen != hmdScreen) { + // first, if the previous dialog screen is not the HMD screen, then move it there. + betterScreen = appScreen; + } else if (appScreen != hmdScreen) { + // second, if the application screen is not the HMD screen, then move it there. + betterScreen = appScreen; + } else if (_previousScreen && _previousScreen != hmdScreen) { + // third, if the application screen is the HMD screen, we want to move it to + // the previous screen + betterScreen = _previousScreen; + } else { + // last, if we can't use the previous screen the use the primary desktop screen + int desktopPrimaryScreenNumber = QApplication::desktop()->primaryScreen(); + QScreen* desktopPrimaryScreen = QGuiApplication::screens()[desktopPrimaryScreenNumber]; + betterScreen = desktopPrimaryScreen; + } + + if (betterScreen) { + dialogWindow->setScreen(betterScreen); + dialogWindow->setGeometry(_previousDialogRect); + } + } + } + } +} + +QString HMDToolsDialog::getDebugDetails() const { + QString results; + + int hmdScreenNumber = OculusManager::getHMDScreen(); + if (hmdScreenNumber >= 0) { + results += "HMD Screen: " + QGuiApplication::screens()[hmdScreenNumber]->name() + "\n"; + } else { + results += "HMD Screen Name: Unknown\n"; + } + + int desktopPrimaryScreenNumber = QApplication::desktop()->primaryScreen(); + QScreen* desktopPrimaryScreen = QGuiApplication::screens()[desktopPrimaryScreenNumber]; + results += "Desktop's Primary Screen: " + desktopPrimaryScreen->name() + "\n"; + + results += "Application Primary Screen: " + QGuiApplication::primaryScreen()->name() + "\n"; + QScreen* mainWindowScreen = Application::getInstance()->getWindow()->windowHandle()->screen(); + results += "Application Main Window Screen: " + mainWindowScreen->name() + "\n"; + + return results; +} + +void HMDToolsDialog::enterModeClicked(bool checked) { + _debugDetails->setText(getDebugDetails()); + + int hmdScreen = OculusManager::getHMDScreen(); + qDebug() << "enterModeClicked().... hmdScreen:" << hmdScreen; + + if (hmdScreen >= 0) { + QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); + _hmdScreen = QGuiApplication::screens()[hmdScreen]; + + _previousRect = Application::getInstance()->getWindow()->rect(); + _previousRect = QRect(mainWindow->mapToGlobal(_previousRect.topLeft()), + mainWindow->mapToGlobal(_previousRect.bottomRight())); + _previousScreen = mainWindow->screen(); + QRect rect = QApplication::desktop()->screenGeometry(hmdScreen); + mainWindow->setScreen(_hmdScreen); + mainWindow->setGeometry(rect); + + _wasMoved = true; + } + + + // if we're on a single screen setup, then hide our tools window when entering HMD mode + if (QApplication::desktop()->screenCount() == 1) { + close(); + } + + Application::getInstance()->setFullscreen(true); + Application::getInstance()->setEnableVRMode(true); + + const int SLIGHT_DELAY = 500; + QTimer::singleShot(SLIGHT_DELAY, this, SLOT(activateWindowAfterEnterMode())); +} + +void HMDToolsDialog::activateWindowAfterEnterMode() { + Application::getInstance()->getWindow()->activateWindow(); + + // center the cursor on the main application window + centerCursorOnWidget(Application::getInstance()->getWindow()); +} + + +void HMDToolsDialog::leaveModeClicked(bool checked) { + _debugDetails->setText(getDebugDetails()); + + Application::getInstance()->setFullscreen(false); + Application::getInstance()->setEnableVRMode(false); + Application::getInstance()->getWindow()->activateWindow(); + + 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::moveWindowAfterLeaveMode() { + QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); + mainWindow->setScreen(_previousScreen); + mainWindow->setGeometry(_previousRect); + Application::getInstance()->getWindow()->activateWindow(); + Application::getInstance()->resetSensors(); +} + + +void HMDToolsDialog::reject() { + // Just regularly close upon ESC + close(); +} + +void HMDToolsDialog::closeEvent(QCloseEvent* event) { + // TODO: consider if we want to prevent closing of this window with event->ignore(); + this->QDialog::closeEvent(event); + emit closed(); +} + +void HMDToolsDialog::centerCursorOnWidget(QWidget* widget) { + QWindow* window = widget->windowHandle(); + QScreen* screen = window->screen(); + QPoint windowCenter = window->geometry().center(); + QCursor::setPos(screen, windowCenter); +} + +void HMDToolsDialog::showEvent(QShowEvent* event) { + // center the cursor on the hmd tools dialog + centerCursorOnWidget(this); +} + +void HMDToolsDialog::hideEvent(QHideEvent* event) { + // center the cursor on the main application window + centerCursorOnWidget(Application::getInstance()->getWindow()); +} + + diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h new file mode 100644 index 0000000000..4fe0dd626f --- /dev/null +++ b/interface/src/ui/HMDToolsDialog.h @@ -0,0 +1,57 @@ +// +// 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(); + + QString getDebugDetails() const; + +signals: + void closed(); + +public slots: + void reject(); + void enterModeClicked(bool checked); + void leaveModeClicked(bool checked); + void activateWindowAfterEnterMode(); + void moveWindowAfterLeaveMode(); + void applicationWindowScreenChanged(QScreen* screen); + void dialogWindowScreenChanged(QScreen* screen); + void dialogWindowGeometryChanged(int arg); + +protected: + virtual void closeEvent(QCloseEvent*); // Emits a 'closed' signal when this dialog is closed. + virtual void showEvent(QShowEvent* event); + virtual void hideEvent(QHideEvent* event); + +private: + void centerCursorOnWidget(QWidget* widget); + + bool _wasMoved; + QRect _previousRect; + QScreen* _previousScreen; + QScreen* _hmdScreen; + QLabel* _debugDetails; + + QRect _previousDialogRect; + QScreen* _previousDialogScreen; +}; + +#endif // hifi_HMDToolsDialog_h diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index c376836d24..7b5a0bb15d 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -655,3 +655,24 @@ QString formatSecondsElapsed(float seconds) { } return result; } + +bool similarStrings(const QString& stringA, const QString& stringB) { + QStringList aWords = stringA.split(" "); + QStringList bWords = stringB.split(" "); + float aWordsInB = 0.0f; + foreach(QString aWord, aWords) { + if (bWords.contains(aWord)) { + aWordsInB += 1.0f; + } + } + float bWordsInA = 0.0f; + foreach(QString bWord, bWords) { + if (aWords.contains(bWord)) { + bWordsInA += 1.0f; + } + } + float similarity = 0.5f * (aWordsInB / (float)bWords.size()) + 0.5f * (bWordsInA / (float)aWords.size()); + const float SIMILAR_ENOUGH = 0.5f; // half the words the same is similar enough for us + return similarity >= SIMILAR_ENOUGH; +} + diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 01edcc01b9..61b7365877 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -131,6 +131,6 @@ bool isNaN(float value); QString formatUsecTime(float usecs, int prec = 3); QString formatSecondsElapsed(float seconds); - +bool similarStrings(const QString& stringA, const QString& stringB); #endif // hifi_SharedUtil_h