Merge pull request #3868 from ZappoMan/HMDMode

First cut at HMD Tools window
This commit is contained in:
Philip Rosedale 2014-11-26 14:53:25 -08:00
commit 91aca51dc6
12 changed files with 468 additions and 7 deletions

View file

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

View file

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

View file

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

View file

@ -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<DataWebDialog> _newLocationDialog;
QPointer<DataWebDialog> _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";

View file

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

View file

@ -14,9 +14,14 @@
#include "OculusManager.h"
#include <QDesktopWidget>
#include <QGuiApplication>
#include <QOpenGLFramebufferObject>
#include <QScreen>
#include <glm/glm.hpp>
#include <SharedUtil.h>
#include <UserActivityLogger.h>
#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;
}

View file

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

View file

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

View file

@ -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 <QFormLayout>
#include <QGuiApplication>
#include <QDialogButtonBox>
#include <QDesktopWidget>
#include <QPushButton>
#include <QString>
#include <QScreen>
#include <QWindow>
#include <VoxelConstants.h>
#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());
}

View file

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

View file

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

View file

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