From 5c406a0e0663f05dad0e874e0ac3c0ec49812db9 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Sep 2014 15:11:45 -0700 Subject: [PATCH 01/58] Add "Leap Motion on HMD" developer menu option --- interface/src/Menu.cpp | 3 +++ interface/src/Menu.h | 1 + 2 files changed, 4 insertions(+) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 8f7b2be43b..d18b2b7d77 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -446,6 +446,9 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseMouseInput, 0, true); addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseLasers, 0, false); + QMenu* leapOptionsMenu = handOptionsMenu->addMenu("Leap Motion"); + addCheckableActionToQMenuAndActionHash(leapOptionsMenu, MenuOption::LeapMotionOnHMD, 0, false); + QMenu* networkMenu = developerMenu->addMenu("Network"); addCheckableActionToQMenuAndActionHash(networkMenu, MenuOption::DisableNackPackets, 0, false); addCheckableActionToQMenuAndActionHash(networkMenu, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index b267ab8b2c..38b16f9f6c 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -402,6 +402,7 @@ namespace MenuOption { const QString IncreaseAvatarSize = "Increase Avatar Size"; const QString IncreaseVoxelSize = "Increase Voxel Size"; const QString KeyboardMotorControl = "Enable Keyboard Motor Control"; + const QString LeapMotionOnHMD = "Leap Motion on HMD"; const QString LoadScript = "Open and Run Script File..."; const QString LoadScriptURL = "Open and Run Script from URL..."; const QString LodTools = "LOD Tools"; From 6375e42d886ddb38df695c77543215b73e070eb1 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Sep 2014 15:13:01 -0700 Subject: [PATCH 02/58] Configure Leap controller per HMD option when controller is created --- interface/src/devices/Leapmotion.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/interface/src/devices/Leapmotion.cpp b/interface/src/devices/Leapmotion.cpp index 7060c5c5e9..a3794123ce 100644 --- a/interface/src/devices/Leapmotion.cpp +++ b/interface/src/devices/Leapmotion.cpp @@ -8,8 +8,9 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "SharedUtil.h" #include "Leapmotion.h" +#include "Menu.h" +#include "SharedUtil.h" const int PALMROOT_NUM_JOINTS = 3; const int FINGER_NUM_JOINTS = 4; @@ -101,6 +102,12 @@ Leapmotion::Leapmotion() : } } } + +#ifdef HAVE_LEAPMOTION + if (Menu::getInstance()->isOptionChecked(MenuOption::LeapMotionOnHMD)) { + _controller.setPolicyFlags(Leap::Controller::POLICY_OPTIMIZE_HMD); + } +#endif } Leapmotion::~Leapmotion() { From c02cd66dcbeb8d0a436e93d9af24a33794ff9920 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 23 Sep 2014 15:14:01 -0700 Subject: [PATCH 03/58] Don't calibrate avatar for Leap Motion if mounted on HMD --- examples/leapHands.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/examples/leapHands.js b/examples/leapHands.js index 95d3969a08..ba6ce432de 100644 --- a/examples/leapHands.js +++ b/examples/leapHands.js @@ -13,7 +13,8 @@ var leapHands = (function () { - var hands, + var isOnHMD, + hands, wrists, NUM_HANDS = 2, // 0 = left; 1 = right fingers, @@ -188,8 +189,6 @@ var leapHands = (function () { function setUp() { - calibrationStatus = UNCALIBRATED; - // TODO: Leap Motion controller joint naming doesn't match up with skeleton joint naming; numbers are out by 1. hands = [ @@ -265,6 +264,19 @@ var leapHands = (function () { { jointName: "RightHandPinky3", controller: Controller.createInputController("Spatial", "joint_R_pinky4") } ] ]; + + isOnHMD = Menu.isOptionChecked("Leap Motion on HMD"); + if (isOnHMD) { + print("Leap Motion is on HMD"); + + hands[0].zeroPosition = { x: 0.0, y: 0.0, z: 0.0 }; + hands[1].zeroPosition = { x: 0.0, y: 0.0, z: 0.0 }; + + calibrationStatus = CALIBRATED; + } else { + print("Leap Motion is on desk"); + calibrationStatus = UNCALIBRATED; + } } function moveHands() { From 5e2870ac5f249da597b9f312bce5b9648103e50c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 29 Sep 2014 09:30:08 -0700 Subject: [PATCH 04/58] require a distinction between master config and user config --- domain-server/src/DomainServer.cpp | 4 +- .../src/DomainServerSettingsManager.cpp | 23 +++------- .../src/DomainServerSettingsManager.h | 10 ++-- libraries/shared/src/HifiConfigVariantMap.cpp | 46 +++++++++---------- libraries/shared/src/HifiConfigVariantMap.h | 22 +++++++-- 5 files changed, 52 insertions(+), 53 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index b1ed765be6..d347cb088f 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -48,7 +48,7 @@ DomainServer::DomainServer(int argc, char* argv[]) : _sessionAuthenticationHash(), _webAuthenticationStateSet(), _cookieSessionHash(), - _settingsManager() + _settingsManager(arguments()) { LogUtils::init(); @@ -57,8 +57,6 @@ DomainServer::DomainServer(int argc, char* argv[]) : setApplicationName("domain-server"); QSettings::setDefaultFormat(QSettings::IniFormat); - _settingsManager.loadSettingsMap(arguments()); - installNativeEventFilter(&_shutdownEventListener); connect(&_shutdownEventListener, SIGNAL(receivedCloseEvent()), SLOT(quit())); diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index d9b1d4d8d6..ae5a815e92 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -26,9 +26,9 @@ const QString SETTINGS_DESCRIPTION_RELATIVE_PATH = "/resources/describe-settings.json"; -DomainServerSettingsManager::DomainServerSettingsManager() : +DomainServerSettingsManager::DomainServerSettingsManager(const QStringList& argumentList) : _descriptionArray(), - _settingsMap() + _configMap(argumentList) { // load the description object from the settings description QFile descriptionFile(QCoreApplication::applicationDirPath() + SETTINGS_DESCRIPTION_RELATIVE_PATH); @@ -37,13 +37,6 @@ DomainServerSettingsManager::DomainServerSettingsManager() : _descriptionArray = QJsonDocument::fromJson(descriptionFile.readAll()).array(); } -void DomainServerSettingsManager::loadSettingsMap(const QStringList& argumentList) { - _settingsMap = HifiConfigVariantMap::mergeMasterConfigWithUserConfig(argumentList); - - // figure out where we are supposed to persist our settings to - _settingsFilepath = HifiConfigVariantMap::userConfigFilepath(argumentList); -} - const QString SETTINGS_PATH = "/settings.json"; bool DomainServerSettingsManager::handlePublicHTTPRequest(HTTPConnection* connection, const QUrl &url) { @@ -76,7 +69,7 @@ bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection QJsonObject postedObject = postedDocument.object(); // we recurse one level deep below each group for the appropriate setting - recurseJSONObjectAndOverwriteSettings(postedObject, _settingsMap, _descriptionArray); + recurseJSONObjectAndOverwriteSettings(postedObject, _configMap.getUserConfig(), _descriptionArray); // store whatever the current _settingsMap is to file persistToFile(); @@ -99,6 +92,7 @@ bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection rootObject[SETTINGS_RESPONSE_DESCRIPTION_KEY] = _descriptionArray; rootObject[SETTINGS_RESPONSE_VALUE_KEY] = responseObjectForType("", true); + connection->respond(HTTPConnection::StatusCode200, QJsonDocument(rootObject).toJson(), "application/json"); } @@ -145,7 +139,8 @@ QJsonObject DomainServerSettingsManager::responseObjectForType(const QString& ty // we need to check if the settings map has a value for this setting QVariant variantValue; - QVariant settingsMapGroupValue = _settingsMap.value(groupObject[DESCRIPTION_NAME_KEY].toString()); + QVariant settingsMapGroupValue = _configMap.getMergedConfig() + .value(groupObject[DESCRIPTION_NAME_KEY].toString()); if (!settingsMapGroupValue.isNull()) { variantValue = settingsMapGroupValue.toMap().value(settingName); @@ -239,10 +234,6 @@ void DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ } } -QByteArray DomainServerSettingsManager::getJSONSettingsMap() const { - return QJsonDocument::fromVariant(_settingsMap).toJson(); -} - void DomainServerSettingsManager::persistToFile() { // make sure we have the dir the settings file is supposed to live in @@ -255,7 +246,7 @@ void DomainServerSettingsManager::persistToFile() { QFile settingsFile(_settingsFilepath); if (settingsFile.open(QIODevice::WriteOnly)) { - settingsFile.write(getJSONSettingsMap()); + settingsFile.write(QJsonDocument::fromVariant(_configMap.getUserConfig()).toJson()); } else { qCritical("Could not write to JSON settings file. Unable to persist settings."); } diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h index 29b773a354..4b884dfd5b 100644 --- a/domain-server/src/DomainServerSettingsManager.h +++ b/domain-server/src/DomainServerSettingsManager.h @@ -15,19 +15,17 @@ #include #include +#include #include class DomainServerSettingsManager : public QObject { Q_OBJECT public: - DomainServerSettingsManager(); + DomainServerSettingsManager(const QStringList& argumentList); bool handlePublicHTTPRequest(HTTPConnection* connection, const QUrl& url); bool handleAuthenticatedHTTPRequest(HTTPConnection* connection, const QUrl& url); - void loadSettingsMap(const QStringList& argumentList); - - QByteArray getJSONSettingsMap() const; - QVariantMap& getSettingsMap() { return _settingsMap; } + QVariantMap& getSettingsMap() { return _configMap.getMergedConfig(); } private: QJsonObject responseObjectForType(const QString& typeValue, bool isAuthenticated = false); void recurseJSONObjectAndOverwriteSettings(const QJsonObject& postedObject, QVariantMap& settingsVariant, @@ -35,7 +33,7 @@ private: void persistToFile(); QJsonArray _descriptionArray; - QVariantMap _settingsMap; + HifiConfigVariantMap _configMap; QString _settingsFilepath; }; diff --git a/libraries/shared/src/HifiConfigVariantMap.cpp b/libraries/shared/src/HifiConfigVariantMap.cpp index d3626e0249..fabb185a35 100644 --- a/libraries/shared/src/HifiConfigVariantMap.cpp +++ b/libraries/shared/src/HifiConfigVariantMap.cpp @@ -87,43 +87,46 @@ QVariantMap HifiConfigVariantMap::mergeCLParametersWithJSONConfig(const QStringL return mergedMap; } -QVariantMap HifiConfigVariantMap::mergeMasterConfigWithUserConfig(const QStringList& argumentList) { +HifiConfigVariantMap::HifiConfigVariantMap(const QStringList& argumentList) : + _masterConfigPath(), + _userConfigPath(), + _masterConfig(), + _userConfig(), + _mergedConfig() +{ // check if there is a master config file const QString MASTER_CONFIG_FILE_OPTION = "--master-config"; - QVariantMap configVariantMap; - int masterConfigIndex = argumentList.indexOf(MASTER_CONFIG_FILE_OPTION); if (masterConfigIndex != -1) { QString masterConfigFilepath = argumentList[masterConfigIndex + 1]; - mergeMapWithJSONFile(configVariantMap, masterConfigFilepath); + loadMapFromJSONFile(_masterConfig, masterConfigFilepath); } - // merge the existing configVariantMap with the user config file - mergeMapWithJSONFile(configVariantMap, userConfigFilepath(argumentList)); - - return configVariantMap; -} - -QString HifiConfigVariantMap::userConfigFilepath(const QStringList& argumentList) { - // we've loaded up the master config file, now fill in anything it didn't have with the user config file + // load the user config const QString USER_CONFIG_FILE_OPTION = "--user-config"; int userConfigIndex = argumentList.indexOf(USER_CONFIG_FILE_OPTION); QString userConfigFilepath; if (userConfigIndex != -1) { - userConfigFilepath = argumentList[userConfigIndex + 1]; + _userConfigPath = argumentList[userConfigIndex + 1]; } else { - userConfigFilepath = QString("%1/%2/%3/config.json").arg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation), - QCoreApplication::organizationName(), - QCoreApplication::applicationName()); + _userConfigPath = QString("%1%2/%3/config.json").arg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation), + QCoreApplication::organizationName(), + QCoreApplication::applicationName()); } - return userConfigFilepath; + loadMapFromJSONFile(_userConfig, _userConfigPath); + + // the merged config is initially matched to the master config + _mergedConfig = _masterConfig; + + // then we merge in anything missing from the user config + addMissingValuesToExistingMap(_mergedConfig, _userConfig); } -void HifiConfigVariantMap::mergeMapWithJSONFile(QVariantMap& existingMap, const QString& filename) { +void HifiConfigVariantMap::loadMapFromJSONFile(QVariantMap& existingMap, const QString& filename) { QFile configFile(filename); if (configFile.exists()) { @@ -131,12 +134,7 @@ void HifiConfigVariantMap::mergeMapWithJSONFile(QVariantMap& existingMap, const configFile.open(QIODevice::ReadOnly); QJsonDocument configDocument = QJsonDocument::fromJson(configFile.readAll()); - - if (existingMap.isEmpty()) { - existingMap = configDocument.toVariant().toMap(); - } else { - addMissingValuesToExistingMap(existingMap, configDocument.toVariant().toMap()); - } + existingMap = configDocument.toVariant().toMap(); } else { qDebug() << "Could not find JSON config file at" << filename; diff --git a/libraries/shared/src/HifiConfigVariantMap.h b/libraries/shared/src/HifiConfigVariantMap.h index b1b6b55aa2..12cc05d2e9 100644 --- a/libraries/shared/src/HifiConfigVariantMap.h +++ b/libraries/shared/src/HifiConfigVariantMap.h @@ -17,11 +17,25 @@ class HifiConfigVariantMap { public: static QVariantMap mergeCLParametersWithJSONConfig(const QStringList& argumentList); - static QVariantMap mergeMasterConfigWithUserConfig(const QStringList& argumentList); - static QString userConfigFilepath(const QStringList& argumentList); + + HifiConfigVariantMap(const QStringList& argumentList); + + const QVariantMap& getMasterConfig() const { return _masterConfig; } + QVariantMap& getUserConfig() { return _userConfig; } + QVariantMap& getMergedConfig() { return _mergedConfig; } + + const QString& userConfigFilepath() const { return _userConfigPath; } private: - static void mergeMapWithJSONFile(QVariantMap& existingMap, const QString& filename); - static void addMissingValuesToExistingMap(QVariantMap& existingMap, const QVariantMap& newMap); + QString _masterConfigPath; + QString _userConfigPath; + + QVariantMap _masterConfig; + QVariantMap _userConfig; + QVariantMap _mergedConfig; + + QVariantMap mergeMasterConfigWithUserConfig(const QStringList& argumentList); + void loadMapFromJSONFile(QVariantMap& existingMap, const QString& filename); + void addMissingValuesToExistingMap(QVariantMap& existingMap, const QVariantMap& newMap); }; const QVariant* valueForKeyPath(QVariantMap& variantMap, const QString& keyPath); From ec0805acc53af942a1a78eb39b1bd72eb6f0ecbf Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 29 Sep 2014 09:34:04 -0700 Subject: [PATCH 05/58] add locked settings to json return for auth'ed settings --- domain-server/src/DomainServerSettingsManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index ae5a815e92..e262d4e8a4 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -87,10 +87,12 @@ bool DomainServerSettingsManager::handleAuthenticatedHTTPRequest(HTTPConnection // setup a JSON Object with descriptions and non-omitted settings const QString SETTINGS_RESPONSE_DESCRIPTION_KEY = "descriptions"; const QString SETTINGS_RESPONSE_VALUE_KEY = "values"; + const QString SETTINGS_RESPONSE_LOCKED_VALUES_KEY = "locked"; QJsonObject rootObject; rootObject[SETTINGS_RESPONSE_DESCRIPTION_KEY] = _descriptionArray; rootObject[SETTINGS_RESPONSE_VALUE_KEY] = responseObjectForType("", true); + rootObject[SETTINGS_RESPONSE_LOCKED_VALUES_KEY] = QJsonDocument::fromVariant(_configMap.getMasterConfig()).object(); connection->respond(HTTPConnection::StatusCode200, QJsonDocument(rootObject).toJson(), "application/json"); From 58b03c7ef2e54820404090a8ed82118e5415e885 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 29 Sep 2014 09:53:27 -0700 Subject: [PATCH 06/58] disable form inputs for values set by master config --- domain-server/resources/describe-settings.json | 2 +- domain-server/resources/web/js/settings.js | 12 ++++++++---- domain-server/resources/web/settings/index.shtml | 6 ++++-- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 8fb7bddb89..19c293b610 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -116,7 +116,7 @@ "advanced": true }, { - "name": "I-print-stream-stats", + "name": "print-stream-stats", "type": "checkbox", "label": "Print Stream Stats:", "help": "audio upstream and downstream stats of each agent printed to audio-mixer stdout", diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index 8bb02e6e94..2d079e9a7c 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -3,9 +3,11 @@ var Settings = { }; var viewHelpers = { - getFormGroup: function(groupName, setting, values, isAdvanced) { + getFormGroup: function(groupName, setting, values, isAdvanced, isLocked) { setting_id = groupName + "_" + setting.name + console.log(setting.name + " in " + groupName + " is " + isLocked) + form_group = "
" if (_.has(values, groupName) && _.has(values[groupName], setting.name)) { @@ -18,9 +20,10 @@ var viewHelpers = { if (setting.type === 'checkbox') { form_group += "" - form_group += "
" + form_group += "
" form_group += ""; form_group += "
" } else { @@ -29,7 +32,7 @@ var viewHelpers = { form_group += ""; form_group += "" + "' value='" + setting_value + "'" + (isLocked ? " disabled" : "") + "/>" form_group += "" + setting.help + "" } @@ -101,6 +104,7 @@ function reloadSettings() { $('#panels').html(Settings.panelsTemplate(data)) Settings.initialValues = form2js('settings-form', "_", false, cleanupFormValues, true); + $('[data-target=tooltip]').tooltip() }); } diff --git a/domain-server/resources/web/settings/index.shtml b/domain-server/resources/web/settings/index.shtml index 54fbb02eca..2f0cdf6537 100644 --- a/domain-server/resources/web/settings/index.shtml +++ b/domain-server/resources/web/settings/index.shtml @@ -38,10 +38,12 @@
<% split_settings = _.partition(group.settings, function(value, index) { return !value.advanced }) %> <% _.each(split_settings[0], function(setting) { %> - <%= getFormGroup(group.name, setting, values, false) %> + <%= getFormGroup(group.name, setting, values, false, + (_.has(locked, group.name) && _.has(locked[group.name], setting.name))) %> <% }); %> <% _.each(split_settings[1], function(setting) { %> - <%= getFormGroup(group.name, setting, values, true) %> + <%= getFormGroup(group.name, setting, values, true, + (_.has(locked, group.name) && _.has(locked[group.name], setting.name))) %> <% }); %>
From 46258ae78f78abde987c49e59350d2ca278edb9c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 29 Sep 2014 10:02:01 -0700 Subject: [PATCH 07/58] add a tooltip to say why locked settings cannot be changed --- domain-server/resources/web/css/style.css | 4 ++++ domain-server/resources/web/js/settings.js | 16 +++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/domain-server/resources/web/css/style.css b/domain-server/resources/web/css/style.css index cef30b5782..a75b1a23ae 100644 --- a/domain-server/resources/web/css/style.css +++ b/domain-server/resources/web/css/style.css @@ -52,6 +52,10 @@ span.port { color: red; } +.locked { + color: blue; +} + .advanced-setting { display: none; } diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index 2d079e9a7c..3313bce06d 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -18,8 +18,13 @@ var viewHelpers = { setting_value = "" } + label_class = 'control-label' + if (isLocked) { + label_class += ' locked' + } + if (setting.type === 'checkbox') { - form_group += "" + form_group += "" form_group += "
" form_group += ""; + form_group += ""; form_group += "" @@ -104,7 +109,12 @@ function reloadSettings() { $('#panels').html(Settings.panelsTemplate(data)) Settings.initialValues = form2js('settings-form', "_", false, cleanupFormValues, true); - $('[data-target=tooltip]').tooltip() + + // add tooltip to locked settings + $('label.locked').tooltip({ + placement: 'right', + title: 'This setting is in the master config file and cannot be changed' + }) }); } From bd4a32551b723d1fe5290f108beb4856ba8c9782 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 29 Sep 2014 10:09:33 -0700 Subject: [PATCH 08/58] fix for settings save without organization --- domain-server/src/DomainServer.cpp | 4 +++- .../src/DomainServerSettingsManager.cpp | 12 +++++++---- .../src/DomainServerSettingsManager.h | 5 +++-- libraries/shared/src/HifiConfigVariantMap.cpp | 20 ++++++++++--------- libraries/shared/src/HifiConfigVariantMap.h | 8 ++++---- 5 files changed, 29 insertions(+), 20 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index d347cb088f..4f048a2ec9 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -48,7 +48,7 @@ DomainServer::DomainServer(int argc, char* argv[]) : _sessionAuthenticationHash(), _webAuthenticationStateSet(), _cookieSessionHash(), - _settingsManager(arguments()) + _settingsManager() { LogUtils::init(); @@ -57,6 +57,8 @@ DomainServer::DomainServer(int argc, char* argv[]) : setApplicationName("domain-server"); QSettings::setDefaultFormat(QSettings::IniFormat); + _settingsManager.setupConfigMap(arguments()); + installNativeEventFilter(&_shutdownEventListener); connect(&_shutdownEventListener, SIGNAL(receivedCloseEvent()), SLOT(quit())); diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index e262d4e8a4..fc36a97a25 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -26,9 +26,9 @@ const QString SETTINGS_DESCRIPTION_RELATIVE_PATH = "/resources/describe-settings.json"; -DomainServerSettingsManager::DomainServerSettingsManager(const QStringList& argumentList) : +DomainServerSettingsManager::DomainServerSettingsManager() : _descriptionArray(), - _configMap(argumentList) + _configMap() { // load the description object from the settings description QFile descriptionFile(QCoreApplication::applicationDirPath() + SETTINGS_DESCRIPTION_RELATIVE_PATH); @@ -37,6 +37,10 @@ DomainServerSettingsManager::DomainServerSettingsManager(const QStringList& argu _descriptionArray = QJsonDocument::fromJson(descriptionFile.readAll()).array(); } +void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList) { + _configMap.loadMasterAndUserConfig(argumentList); +} + const QString SETTINGS_PATH = "/settings.json"; bool DomainServerSettingsManager::handlePublicHTTPRequest(HTTPConnection* connection, const QUrl &url) { @@ -239,13 +243,13 @@ void DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ void DomainServerSettingsManager::persistToFile() { // make sure we have the dir the settings file is supposed to live in - QFileInfo settingsFileInfo(_settingsFilepath); + QFileInfo settingsFileInfo(_configMap.getUserConfigFilename()); if (!settingsFileInfo.dir().exists()) { settingsFileInfo.dir().mkpath("."); } - QFile settingsFile(_settingsFilepath); + QFile settingsFile(_configMap.getUserConfigFilename()); if (settingsFile.open(QIODevice::WriteOnly)) { settingsFile.write(QJsonDocument::fromVariant(_configMap.getUserConfig()).toJson()); diff --git a/domain-server/src/DomainServerSettingsManager.h b/domain-server/src/DomainServerSettingsManager.h index 4b884dfd5b..b60cb32dfd 100644 --- a/domain-server/src/DomainServerSettingsManager.h +++ b/domain-server/src/DomainServerSettingsManager.h @@ -21,10 +21,12 @@ class DomainServerSettingsManager : public QObject { Q_OBJECT public: - DomainServerSettingsManager(const QStringList& argumentList); + DomainServerSettingsManager(); bool handlePublicHTTPRequest(HTTPConnection* connection, const QUrl& url); bool handleAuthenticatedHTTPRequest(HTTPConnection* connection, const QUrl& url); + void setupConfigMap(const QStringList& argumentList); + QVariantMap& getSettingsMap() { return _configMap.getMergedConfig(); } private: QJsonObject responseObjectForType(const QString& typeValue, bool isAuthenticated = false); @@ -34,7 +36,6 @@ private: QJsonArray _descriptionArray; HifiConfigVariantMap _configMap; - QString _settingsFilepath; }; #endif // hifi_DomainServerSettingsManager_h \ No newline at end of file diff --git a/libraries/shared/src/HifiConfigVariantMap.cpp b/libraries/shared/src/HifiConfigVariantMap.cpp index fabb185a35..648f15648a 100644 --- a/libraries/shared/src/HifiConfigVariantMap.cpp +++ b/libraries/shared/src/HifiConfigVariantMap.cpp @@ -87,13 +87,16 @@ QVariantMap HifiConfigVariantMap::mergeCLParametersWithJSONConfig(const QStringL return mergedMap; } -HifiConfigVariantMap::HifiConfigVariantMap(const QStringList& argumentList) : - _masterConfigPath(), - _userConfigPath(), +HifiConfigVariantMap::HifiConfigVariantMap() : + _userConfigFilename(), _masterConfig(), _userConfig(), _mergedConfig() { + +} + +void HifiConfigVariantMap::loadMasterAndUserConfig(const QStringList& argumentList) { // check if there is a master config file const QString MASTER_CONFIG_FILE_OPTION = "--master-config"; @@ -108,16 +111,15 @@ HifiConfigVariantMap::HifiConfigVariantMap(const QStringList& argumentList) : const QString USER_CONFIG_FILE_OPTION = "--user-config"; int userConfigIndex = argumentList.indexOf(USER_CONFIG_FILE_OPTION); - QString userConfigFilepath; if (userConfigIndex != -1) { - _userConfigPath = argumentList[userConfigIndex + 1]; + _userConfigFilename = argumentList[userConfigIndex + 1]; } else { - _userConfigPath = QString("%1%2/%3/config.json").arg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation), - QCoreApplication::organizationName(), - QCoreApplication::applicationName()); + _userConfigFilename = QString("%1/%2/%3/config.json").arg(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation), + QCoreApplication::organizationName(), + QCoreApplication::applicationName()); } - loadMapFromJSONFile(_userConfig, _userConfigPath); + loadMapFromJSONFile(_userConfig, _userConfigFilename); // the merged config is initially matched to the master config _mergedConfig = _masterConfig; diff --git a/libraries/shared/src/HifiConfigVariantMap.h b/libraries/shared/src/HifiConfigVariantMap.h index 12cc05d2e9..99a58d731e 100644 --- a/libraries/shared/src/HifiConfigVariantMap.h +++ b/libraries/shared/src/HifiConfigVariantMap.h @@ -18,16 +18,16 @@ class HifiConfigVariantMap { public: static QVariantMap mergeCLParametersWithJSONConfig(const QStringList& argumentList); - HifiConfigVariantMap(const QStringList& argumentList); + HifiConfigVariantMap(); + void loadMasterAndUserConfig(const QStringList& argumentList); const QVariantMap& getMasterConfig() const { return _masterConfig; } QVariantMap& getUserConfig() { return _userConfig; } QVariantMap& getMergedConfig() { return _mergedConfig; } - const QString& userConfigFilepath() const { return _userConfigPath; } + const QString& getUserConfigFilename() const { return _userConfigFilename; } private: - QString _masterConfigPath; - QString _userConfigPath; + QString _userConfigFilename; QVariantMap _masterConfig; QVariantMap _userConfig; From eb7ee361683258f4a265904fbd0aaa68378f3928 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 29 Sep 2014 10:29:40 -0700 Subject: [PATCH 09/58] use two dashes for url as command line option --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0fd7ae96d1..c00b83b53d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -304,8 +304,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(&addressManager, &AddressManager::possibleDomainChangeRequired, this, &Application::changeDomainHostname); - // when -url in command line, teleport to location - addressManager.handleLookupString(getCmdOption(argc, constArgv, "-url")); + // when --url in command line, teleport to location + addressManager.handleLookupString(getCmdOption(argc, constArgv, "--url")); _settings = new QSettings(this); _numChangedSettings = 0; From 9855fbcfb4e209ced4e007ebf2a9e02192e63ea5 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 29 Sep 2014 11:45:12 -0700 Subject: [PATCH 10/58] Don't bother using a callback to render the eye vectors; just rely on the post-lighting call to Avatar::render, like everything else. This should fix the crash that Philip was seeing (presumably due to avatars' being deleted during the draw process). --- interface/src/avatar/Avatar.cpp | 24 +++++++++++------------- interface/src/avatar/Head.cpp | 15 +++++++-------- interface/src/avatar/Head.h | 6 ++---- interface/src/avatar/MyAvatar.cpp | 24 +++++++++++------------- 4 files changed, 31 insertions(+), 38 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index c82eaa2bac..2b72fe2c23 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -520,20 +520,18 @@ void Avatar::renderBody(RenderMode renderMode, bool postLighting, float glowLeve renderAttachments(renderMode); } } - if (!postLighting) { - getHead()->render(1.0f, modelRenderMode); + getHead()->render(1.0f, modelRenderMode, postLighting); - if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) { - // Render Hair - glPushMatrix(); - glm::vec3 headPosition = getHead()->getPosition(); - glTranslatef(headPosition.x, headPosition.y, headPosition.z); - const glm::quat& rotation = getHead()->getFinalOrientationInWorldFrame(); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - _hair.render(); - glPopMatrix(); - } + if (!postLighting && Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) { + // Render Hair + glPushMatrix(); + glm::vec3 headPosition = getHead()->getPosition(); + glTranslatef(headPosition.x, headPosition.y, headPosition.z); + const glm::quat& rotation = getHead()->getFinalOrientationInWorldFrame(); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + _hair.render(); + glPopMatrix(); } } diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index f67a131221..bc557bdb57 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -211,17 +211,16 @@ void Head::relaxLean(float deltaTime) { _deltaLeanForward *= relaxationFactor; } -void Head::render(float alpha, Model::RenderMode mode) { - _faceModel.render(alpha, mode); - if (_renderLookatVectors && mode != Model::SHADOW_RENDER_MODE) { - Application::getInstance()->getDeferredLightingEffect()->addPostLightingRenderable(this); +void Head::render(float alpha, Model::RenderMode mode, bool postLighting) { + if (postLighting) { + if (_renderLookatVectors) { + renderLookatVectors(_leftEyePosition, _rightEyePosition, getCorrectedLookAtPosition()); + } + } else { + _faceModel.render(alpha, mode); } } -void Head::renderPostLighting() { - renderLookatVectors(_leftEyePosition, _rightEyePosition, getCorrectedLookAtPosition()); -} - void Head::setScale (float scale) { if (_scale == scale) { return; diff --git a/interface/src/avatar/Head.h b/interface/src/avatar/Head.h index efcee9ed8d..bc4142eab0 100644 --- a/interface/src/avatar/Head.h +++ b/interface/src/avatar/Head.h @@ -23,7 +23,6 @@ #include "FaceModel.h" #include "InterfaceConfig.h" #include "world.h" -#include "renderer/DeferredLightingEffect.h" enum eyeContactTargets { LEFT_EYE, @@ -36,15 +35,14 @@ const float EYE_EAR_GAP = 0.08f; class Avatar; class ProgramObject; -class Head : public HeadData, public PostLightingRenderable { +class Head : public HeadData { public: Head(Avatar* owningAvatar); void init(); void reset(); void simulate(float deltaTime, bool isMine, bool billboard = false); - void render(float alpha, Model::RenderMode mode); - virtual void renderPostLighting(); + void render(float alpha, Model::RenderMode mode, bool postLighting); void setScale(float scale); void setPosition(glm::vec3 position) { _position = position; } void setAverageLoudness(float averageLoudness) { _averageLoudness = averageLoudness; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 5cd8ba2052..f7aa8a2bd6 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1147,20 +1147,18 @@ void MyAvatar::renderBody(RenderMode renderMode, bool postLighting, float glowLe const Camera *camera = Application::getInstance()->getCamera(); const glm::vec3 cameraPos = camera->getPosition() + (camera->getRotation() * glm::vec3(0.0f, 0.0f, 1.0f)) * camera->getDistance(); if (shouldRenderHead(cameraPos, renderMode)) { - if (!postLighting) { - getHead()->render(1.0f, modelRenderMode); + getHead()->render(1.0f, modelRenderMode, postLighting); - if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) { - // Render Hair - glPushMatrix(); - glm::vec3 headPosition = getHead()->getPosition(); - glTranslatef(headPosition.x, headPosition.y, headPosition.z); - const glm::quat& rotation = getHead()->getFinalOrientationInWorldFrame(); - glm::vec3 axis = glm::axis(rotation); - glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - _hair.render(); - glPopMatrix(); - } + if (!postLighting && Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) { + // Render Hair + glPushMatrix(); + glm::vec3 headPosition = getHead()->getPosition(); + glTranslatef(headPosition.x, headPosition.y, headPosition.z); + const glm::quat& rotation = getHead()->getFinalOrientationInWorldFrame(); + glm::vec3 axis = glm::axis(rotation); + glRotatef(glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); + _hair.render(); + glPopMatrix(); } } if (postLighting) { From 6d157282838646a4e8050ccb08f749d3fcc1e05d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 29 Sep 2014 12:30:10 -0700 Subject: [PATCH 11/58] frame interpolation for recordings --- libraries/avatars/src/Player.cpp | 79 ++++++++++++++++++++++++++++---- libraries/avatars/src/Player.h | 1 + 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/libraries/avatars/src/Player.cpp b/libraries/avatars/src/Player.cpp index 9732ccd780..929f9cddb9 100644 --- a/libraries/avatars/src/Player.cpp +++ b/libraries/avatars/src/Player.cpp @@ -223,22 +223,65 @@ void Player::play() { context = &_currentContext; } const RecordingFrame& currentFrame = _recording->getFrame(_currentFrame); + const RecordingFrame& nextFrame = _recording->getFrame(_currentFrame + 1); - _avatar->setPosition(context->position + context->orientation * currentFrame.getTranslation()); - _avatar->setOrientation(context->orientation * currentFrame.getRotation()); - _avatar->setTargetScale(context->scale * currentFrame.getScale()); - _avatar->setJointRotations(currentFrame.getJointRotations()); + glm::vec3 translation = glm::mix(currentFrame.getTranslation(), + nextFrame.getTranslation(), + _frameInterpolationFactor); + _avatar->setPosition(context->position + context->orientation * translation); + + glm::quat rotation = safeMix(currentFrame.getRotation(), + nextFrame.getRotation(), + _frameInterpolationFactor); + _avatar->setOrientation(context->orientation * rotation); + + float scale = glm::mix(currentFrame.getScale(), + nextFrame.getScale(), + _frameInterpolationFactor); + _avatar->setTargetScale(context->scale * scale); + + + QVector jointRotations(currentFrame.getJointRotations().size()); + for (int i = 0; i < currentFrame.getJointRotations().size(); ++i) { + jointRotations[i] = safeMix(currentFrame.getJointRotations()[i], + nextFrame.getJointRotations()[i], + _frameInterpolationFactor); + } + _avatar->setJointRotations(jointRotations); HeadData* head = const_cast(_avatar->getHeadData()); if (head) { - head->setBlendshapeCoefficients(currentFrame.getBlendshapeCoefficients()); - head->setLeanSideways(currentFrame.getLeanSideways()); + QVector blendCoef(currentFrame.getBlendshapeCoefficients().size()); + for (int i = 0; i < currentFrame.getBlendshapeCoefficients().size(); ++i) { + blendCoef[i] = glm::mix(currentFrame.getBlendshapeCoefficients()[i], + nextFrame.getBlendshapeCoefficients()[i], + _frameInterpolationFactor); + } + head->setBlendshapeCoefficients(blendCoef); + + float leanSideways = glm::mix(currentFrame.getLeanSideways(), + nextFrame.getLeanSideways(), + _frameInterpolationFactor); + head->setLeanSideways(leanSideways); + + float leanForward = glm::mix(currentFrame.getLeanForward(), + nextFrame.getLeanForward(), + _frameInterpolationFactor); head->setLeanForward(currentFrame.getLeanForward()); - glm::vec3 eulers = glm::degrees(safeEulerAngles(currentFrame.getHeadRotation())); + + glm::quat headRotation = safeMix(currentFrame.getHeadRotation(), + nextFrame.getHeadRotation(), + _frameInterpolationFactor); + glm::vec3 eulers = glm::degrees(safeEulerAngles(headRotation)); head->setFinalPitch(eulers.x); head->setFinalYaw(eulers.y); head->setFinalRoll(eulers.z); - head->setLookAtPosition(context->position + context->orientation * currentFrame.getLookAtPosition()); + + + glm::vec3 lookAt = glm::mix(currentFrame.getLookAtPosition(), + nextFrame.getLookAtPosition(), + _frameInterpolationFactor); + head->setLookAtPosition(context->position + context->orientation * lookAt); } else { qDebug() << "WARNING: Player couldn't find head data."; } @@ -332,10 +375,26 @@ bool Player::computeCurrentFrame() { _currentFrame = 0; } - while (_currentFrame < _recording->getFrameNumber() - 1 && - _recording->getFrameTimestamp(_currentFrame) < elapsed()) { + qint64 elapsed = Player::elapsed(); + while (_currentFrame < _recording->getFrameNumber() && + _recording->getFrameTimestamp(_currentFrame) < elapsed) { ++_currentFrame; } + --_currentFrame; + if (_currentFrame == _recording->getFrameNumber() - 1) { + --_currentFrame; + _frameInterpolationFactor = 1.0f; + } else { + qint64 currentTimestamps = _recording->getFrameTimestamp(_currentFrame); + qint64 nextTimestamps = _recording->getFrameTimestamp(_currentFrame + 1); + _frameInterpolationFactor = (float)(elapsed - currentTimestamps) / + (float)(nextTimestamps - currentTimestamps); + } + + if (_frameInterpolationFactor < 0.0f || _frameInterpolationFactor > 1.0f) { + _frameInterpolationFactor = 0.0f; + qDebug() << "Invalid frame interpolation value: overriding"; + } return true; } diff --git a/libraries/avatars/src/Player.h b/libraries/avatars/src/Player.h index 51e120917c..5db56d725a 100644 --- a/libraries/avatars/src/Player.h +++ b/libraries/avatars/src/Player.h @@ -64,6 +64,7 @@ private: QElapsedTimer _timer; RecordingPointer _recording; int _currentFrame; + float _frameInterpolationFactor; int _pausedFrame; qint64 _timerOffset; From f7a17b7deca5128638eeb6412d73b985bac83e53 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 29 Sep 2014 12:58:01 -0700 Subject: [PATCH 12/58] dynamically load sixense lib on OS X to make avoiding hid_init crash easier --- interface/CMakeLists.txt | 5 +- interface/src/Application.cpp | 22 +- interface/src/Application.h | 2 - interface/src/Menu.cpp | 21 +- interface/src/Menu.h | 2 + interface/src/devices/SixenseManager.cpp | 363 ++++++++++++++--------- interface/src/devices/SixenseManager.h | 21 +- interface/src/ui/ApplicationOverlay.cpp | 2 +- 8 files changed, 276 insertions(+), 162 deletions(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index a2a832afe0..ddc034801b 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -137,8 +137,9 @@ foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) set(${${EXTERNAL}_UPPERCASE}_LIBRARIES ${${${EXTERNAL}_UPPERCASE}_LIBRARY}) endif () - target_link_libraries(${TARGET_NAME} ${${${EXTERNAL}_UPPERCASE}_LIBRARIES}) - + if (NOT APPLE OR NOT ${${EXTERNAL}_UPPERCASE} MATCHES "SIXENSE") + target_link_libraries(${TARGET_NAME} ${${${EXTERNAL}_UPPERCASE}_LIBRARIES}) + endif () endif () endforeach() diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0fd7ae96d1..a5d9c89033 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -182,7 +182,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _lastNackTime(usecTimestampNow()), _lastSendDownstreamAudioStats(usecTimestampNow()) { - // read the ApplicationInfo.ini file for Name/Version/Domain information QSettings applicationInfo(Application::resourcesPath() + "info/ApplicationInfo.ini", QSettings::IniFormat); @@ -381,12 +380,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _particleEditSender.setPacketsPerSecond(3000); // super high!! _entityEditSender.setPacketsPerSecond(3000); // super high!! - // Set the sixense filtering - _sixenseManager.setFilter(Menu::getInstance()->isOptionChecked(MenuOption::FilterSixense)); - - // Set hand controller velocity filtering - _sixenseManager.setLowVelocityFilter(Menu::getInstance()->isOptionChecked(MenuOption::LowVelocityFilter)); - checkVersion(); _overlays.init(_glWidget); // do this before scripts load @@ -1484,7 +1477,7 @@ void Application::setRenderVoxels(bool voxelRender) { } void Application::setLowVelocityFilter(bool lowVelocityFilter) { - getSixenseManager()->setLowVelocityFilter(lowVelocityFilter); + SixenseManager::getInstance().setLowVelocityFilter(lowVelocityFilter); } void Application::doKillLocalVoxels() { @@ -1798,6 +1791,17 @@ void Application::init() { _audio.setReceivedAudioStreamSettings(Menu::getInstance()->getReceivedAudioStreamSettings()); qDebug("Loaded settings"); + +#ifdef __APPLE__ + if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseEnabled)) { + // on OS X we only setup sixense if the user wants it on - this allows running without the hid_init crash + // if hydra support is temporarily not required + Menu::getInstance()->toggleSixense(true); + } +#else + // setup sixense + Menu::getInstance()->toggleSixense(true); +#endif // initialize our face trackers after loading the menu settings _faceshift.init(); @@ -2174,7 +2178,7 @@ void Application::update(float deltaTime) { DeviceTracker::updateAll(); updateFaceshift(); updateVisage(); - _sixenseManager.update(deltaTime); + SixenseManager::getInstance().update(deltaTime); JoystickScriptingInterface::getInstance().update(); _prioVR.update(deltaTime); diff --git a/interface/src/Application.h b/interface/src/Application.h index f8710bae7b..e50039a20e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -219,7 +219,6 @@ public: DdeFaceTracker* getDDE() { return &_dde; } CaraFaceTracker* getCara() { return &_cara; } FaceTracker* getActiveFaceTracker(); - SixenseManager* getSixenseManager() { return &_sixenseManager; } PrioVR* getPrioVR() { return &_prioVR; } BandwidthMeter* getBandwidthMeter() { return &_bandwidthMeter; } QUndoStack* getUndoStack() { return &_undoStack; } @@ -510,7 +509,6 @@ private: CaraFaceTracker _cara; DdeFaceTracker _dde; - SixenseManager _sixenseManager; PrioVR _prioVR; Camera _myCamera; // My view onto the world diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 8f7b2be43b..1da85aad16 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -431,11 +431,18 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false); QMenu* sixenseOptionsMenu = handOptionsMenu->addMenu("Sixense"); +#ifdef __APPLE__ + addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, + MenuOption::SixenseEnabled, + 0, true, + this, + SLOT(toggleSixense(bool))); +#endif addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::FilterSixense, 0, true, - appInstance->getSixenseManager(), + &SixenseManager::getInstance(), SLOT(setFilter(bool))); addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::LowVelocityFilter, @@ -1134,6 +1141,18 @@ void Menu::editAnimations() { } } +void Menu::toggleSixense(bool shouldEnable) { + SixenseManager& sixenseManager = SixenseManager::getInstance(); + + if (shouldEnable && !sixenseManager.isInitialized()) { + sixenseManager.initialize(); + sixenseManager.setFilter(isOptionChecked(MenuOption::FilterSixense)); + sixenseManager.setLowVelocityFilter(isOptionChecked(MenuOption::LowVelocityFilter)); + } + + sixenseManager.setIsEnabled(shouldEnable); +} + void Menu::changePrivateKey() { // setup the dialog QInputDialog privateKeyDialog(Application::getInstance()->getWindow()); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index b267ab8b2c..c47c04e177 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -186,6 +186,7 @@ public slots: void pasteToVoxel(); void toggleLoginMenuItem(); + void toggleSixense(bool shouldEnable); QMenu* addMenu(const QString& menuName); void removeMenu(const QString& menuName); @@ -448,6 +449,7 @@ namespace MenuOption { const QString ShowBordersVoxelNodes = "Show Voxel Nodes"; const QString ShowIKConstraints = "Show IK Constraints"; const QString SimpleShadows = "Simple"; + const QString SixenseEnabled = "Enable Hydra Support"; const QString SixenseMouseInput = "Enable Sixense Mouse Input"; const QString SixenseLasers = "Enable Sixense UI Lasers"; const QString StandOnNearbyFloors = "Stand on nearby floors"; diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 417b0619f8..14b598f58c 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -30,23 +30,28 @@ const int CALIBRATION_STATE_COMPLETE = 4; const float NECK_X = 0.25f; // meters const float NECK_Y = 0.3f; // meters const float NECK_Z = 0.3f; // meters + +#ifdef __APPLE__ +typedef int (*SixenseBaseFunction)(); +typedef int (*SixenseTakeIntFunction)(int); +typedef int (*SixenseTakeIntAndSixenseControllerData)(int, sixenseControllerData*); #endif -SixenseManager::SixenseManager() { -#ifdef HAVE_SIXENSE - _lastMovement = 0; - _amountMoved = glm::vec3(0.0f); - _lowVelocityFilter = false; - - _calibrationState = CALIBRATION_STATE_IDLE; - // By default we assume the _neckBase (in orb frame) is as high above the orb - // as the "torso" is below it. - _neckBase = glm::vec3(NECK_X, -NECK_Y, NECK_Z); - - sixenseInit(); - #endif - _hydrasConnected = false; + +SixenseManager& SixenseManager::getInstance() { + static SixenseManager sharedInstance; + return sharedInstance; +} + +SixenseManager::SixenseManager() : +#ifdef __APPLE__ + _sixenseLibrary(NULL), +#endif + _isInitialized(false), + _isEnabled(true), + _hydrasConnected(false) +{ _triggerPressed[0] = false; _bumperPressed[0] = false; _oldX[0] = -1; @@ -58,155 +63,223 @@ SixenseManager::SixenseManager() { } SixenseManager::~SixenseManager() { + + if (_isInitialized) { +#ifdef __APPLE__ + SixenseBaseFunction sixenseExit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseExit"); +#endif + + sixenseExit(); + } + +#ifdef __APPLE__ + delete _sixenseLibrary; +#endif +} + +void SixenseManager::initialize() { #ifdef HAVE_SIXENSE - sixenseExit(); + + if (!_isInitialized) { + _lastMovement = 0; + _amountMoved = glm::vec3(0.0f); + _lowVelocityFilter = false; + + _calibrationState = CALIBRATION_STATE_IDLE; + // By default we assume the _neckBase (in orb frame) is as high above the orb + // as the "torso" is below it. + _neckBase = glm::vec3(NECK_X, -NECK_Y, NECK_Z); + +#ifdef __APPLE__ + + if (!_sixenseLibrary) { + _sixenseLibrary = new QLibrary("libsixense_x64.dylib"); + } + + SixenseBaseFunction sixenseInit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseInit"); +#endif + + sixenseInit(); + + _isInitialized = true; + } + #endif } void SixenseManager::setFilter(bool filter) { #ifdef HAVE_SIXENSE - if (filter) { - sixenseSetFilterEnabled(1); - } else { - sixenseSetFilterEnabled(0); + + if (_isInitialized) { +#ifdef __APPLE__ + SixenseTakeIntFunction sixenseSetFilterEnabled = (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseSetFilterEnabled"); +#endif + + if (filter) { + sixenseSetFilterEnabled(1); + } else { + sixenseSetFilterEnabled(0); + } } + #endif } void SixenseManager::update(float deltaTime) { #ifdef HAVE_SIXENSE - // if the controllers haven't been moved in a while, disable - const unsigned int MOVEMENT_DISABLE_SECONDS = 3; - if (usecTimestampNow() - _lastMovement > (MOVEMENT_DISABLE_SECONDS * USECS_PER_SECOND)) { - Hand* hand = Application::getInstance()->getAvatar()->getHand(); - for (std::vector::iterator it = hand->getPalms().begin(); it != hand->getPalms().end(); it++) { - it->setActive(false); - } - _lastMovement = usecTimestampNow(); - } - - if (sixenseGetNumActiveControllers() == 0) { - _hydrasConnected = false; - return; - } - - PerformanceTimer perfTimer("sixense"); - if (!_hydrasConnected) { - _hydrasConnected = true; - UserActivityLogger::getInstance().connectedDevice("spatial_controller", "hydra"); - } - MyAvatar* avatar = Application::getInstance()->getAvatar(); - Hand* hand = avatar->getHand(); - - int maxControllers = sixenseGetMaxControllers(); - - // we only support two controllers - sixenseControllerData controllers[2]; - - int numActiveControllers = 0; - for (int i = 0; i < maxControllers && numActiveControllers < 2; i++) { - if (!sixenseIsControllerEnabled(i)) { - continue; - } - sixenseControllerData* data = controllers + numActiveControllers; - ++numActiveControllers; - sixenseGetNewestData(i, data); - - // Set palm position and normal based on Hydra position/orientation - - // Either find a palm matching the sixense controller, or make a new one - PalmData* palm; - bool foundHand = false; - for (size_t j = 0; j < hand->getNumPalms(); j++) { - if (hand->getPalms()[j].getSixenseID() == data->controller_index) { - palm = &(hand->getPalms()[j]); - foundHand = true; + if (_isInitialized && _isEnabled) { + // if the controllers haven't been moved in a while, disable + const unsigned int MOVEMENT_DISABLE_SECONDS = 3; + if (usecTimestampNow() - _lastMovement > (MOVEMENT_DISABLE_SECONDS * USECS_PER_SECOND)) { + Hand* hand = Application::getInstance()->getAvatar()->getHand(); + for (std::vector::iterator it = hand->getPalms().begin(); it != hand->getPalms().end(); it++) { + it->setActive(false); } - } - if (!foundHand) { - PalmData newPalm(hand); - hand->getPalms().push_back(newPalm); - palm = &(hand->getPalms()[hand->getNumPalms() - 1]); - palm->setSixenseID(data->controller_index); - qDebug("Found new Sixense controller, ID %i", data->controller_index); - } - - palm->setActive(true); - - // Read controller buttons and joystick into the hand - palm->setControllerButtons(data->buttons); - palm->setTrigger(data->trigger); - palm->setJoystick(data->joystick_x, data->joystick_y); - - - // Emulate the mouse so we can use scripts - if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput)) { - emulateMouse(palm, numActiveControllers - 1); - } - - // NOTE: Sixense API returns pos data in millimeters but we IMMEDIATELY convert to meters. - glm::vec3 position(data->pos[0], data->pos[1], data->pos[2]); - position *= METERS_PER_MILLIMETER; - - // Transform the measured position into body frame. - glm::vec3 neck = _neckBase; - // Zeroing y component of the "neck" effectively raises the measured position a little bit. - neck.y = 0.f; - position = _orbRotation * (position - neck); - - // Rotation of Palm - glm::quat rotation(data->rot_quat[3], -data->rot_quat[0], data->rot_quat[1], -data->rot_quat[2]); - rotation = glm::angleAxis(PI, glm::vec3(0.f, 1.f, 0.f)) * _orbRotation * rotation; - - // Compute current velocity from position change - glm::vec3 rawVelocity; - if (deltaTime > 0.f) { - rawVelocity = (position - palm->getRawPosition()) / deltaTime; - } else { - rawVelocity = glm::vec3(0.0f); - } - palm->setRawVelocity(rawVelocity); // meters/sec - - // adjustment for hydra controllers fit into hands - float sign = (i == 0) ? -1.0f : 1.0f; - rotation *= glm::angleAxis(sign * PI/4.0f, glm::vec3(0.0f, 0.0f, 1.0f)); - - if (_lowVelocityFilter) { - // Use a velocity sensitive filter to damp small motions and preserve large ones with - // no latency. - float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f); - position = palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter); - rotation = safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter); - palm->setRawPosition(position); - palm->setRawRotation(rotation); - } else { - palm->setRawPosition(position); - palm->setRawRotation(rotation); - } - - // use the velocity to determine whether there's any movement (if the hand isn't new) - const float MOVEMENT_DISTANCE_THRESHOLD = 0.003f; - _amountMoved += rawVelocity * deltaTime; - if (glm::length(_amountMoved) > MOVEMENT_DISTANCE_THRESHOLD && foundHand) { _lastMovement = usecTimestampNow(); - _amountMoved = glm::vec3(0.0f); } - // Store the one fingertip in the palm structure so we can track velocity - const float FINGER_LENGTH = 0.3f; // meters - const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH); - const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR; - glm::vec3 oldTipPosition = palm->getTipRawPosition(); - if (deltaTime > 0.f) { - palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime); - } else { - palm->setTipVelocity(glm::vec3(0.f)); +#ifdef __APPLE__ + SixenseBaseFunction sixenseGetNumActiveControllers = + (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseGetNumActiveControllers"); +#endif + + if (sixenseGetNumActiveControllers() == 0) { + _hydrasConnected = false; + return; + } + + PerformanceTimer perfTimer("sixense"); + if (!_hydrasConnected) { + _hydrasConnected = true; + UserActivityLogger::getInstance().connectedDevice("spatial_controller", "hydra"); + } + MyAvatar* avatar = Application::getInstance()->getAvatar(); + Hand* hand = avatar->getHand(); + +#ifdef __APPLE__ + SixenseBaseFunction sixenseGetMaxControllers = + (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseGetMaxControllers"); +#endif + + int maxControllers = sixenseGetMaxControllers(); + + // we only support two controllers + sixenseControllerData controllers[2]; + +#ifdef __APPLE__ + SixenseTakeIntFunction sixenseIsControllerEnabled = + (SixenseTakeIntFunction) _sixenseLibrary->resolve("sixenseIsControllerEnabled"); + + SixenseTakeIntAndSixenseControllerData sixenseGetNewestData = + (SixenseTakeIntAndSixenseControllerData) _sixenseLibrary->resolve("sixenseGetNewestData"); +#endif + + int numActiveControllers = 0; + for (int i = 0; i < maxControllers && numActiveControllers < 2; i++) { + if (!sixenseIsControllerEnabled(i)) { + continue; + } + sixenseControllerData* data = controllers + numActiveControllers; + ++numActiveControllers; + sixenseGetNewestData(i, data); + + // Set palm position and normal based on Hydra position/orientation + + // Either find a palm matching the sixense controller, or make a new one + PalmData* palm; + bool foundHand = false; + for (size_t j = 0; j < hand->getNumPalms(); j++) { + if (hand->getPalms()[j].getSixenseID() == data->controller_index) { + palm = &(hand->getPalms()[j]); + foundHand = true; + } + } + if (!foundHand) { + PalmData newPalm(hand); + hand->getPalms().push_back(newPalm); + palm = &(hand->getPalms()[hand->getNumPalms() - 1]); + palm->setSixenseID(data->controller_index); + qDebug("Found new Sixense controller, ID %i", data->controller_index); + } + + palm->setActive(true); + + // Read controller buttons and joystick into the hand + palm->setControllerButtons(data->buttons); + palm->setTrigger(data->trigger); + palm->setJoystick(data->joystick_x, data->joystick_y); + + + // Emulate the mouse so we can use scripts + if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput)) { + emulateMouse(palm, numActiveControllers - 1); + } + + // NOTE: Sixense API returns pos data in millimeters but we IMMEDIATELY convert to meters. + glm::vec3 position(data->pos[0], data->pos[1], data->pos[2]); + position *= METERS_PER_MILLIMETER; + + // Transform the measured position into body frame. + glm::vec3 neck = _neckBase; + // Zeroing y component of the "neck" effectively raises the measured position a little bit. + neck.y = 0.f; + position = _orbRotation * (position - neck); + + // Rotation of Palm + glm::quat rotation(data->rot_quat[3], -data->rot_quat[0], data->rot_quat[1], -data->rot_quat[2]); + rotation = glm::angleAxis(PI, glm::vec3(0.f, 1.f, 0.f)) * _orbRotation * rotation; + + // Compute current velocity from position change + glm::vec3 rawVelocity; + if (deltaTime > 0.f) { + rawVelocity = (position - palm->getRawPosition()) / deltaTime; + } else { + rawVelocity = glm::vec3(0.0f); + } + palm->setRawVelocity(rawVelocity); // meters/sec + + // adjustment for hydra controllers fit into hands + float sign = (i == 0) ? -1.0f : 1.0f; + rotation *= glm::angleAxis(sign * PI/4.0f, glm::vec3(0.0f, 0.0f, 1.0f)); + + if (_lowVelocityFilter) { + // Use a velocity sensitive filter to damp small motions and preserve large ones with + // no latency. + float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f); + position = palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter); + rotation = safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter); + palm->setRawPosition(position); + palm->setRawRotation(rotation); + } else { + palm->setRawPosition(position); + palm->setRawRotation(rotation); + } + + // use the velocity to determine whether there's any movement (if the hand isn't new) + const float MOVEMENT_DISTANCE_THRESHOLD = 0.003f; + _amountMoved += rawVelocity * deltaTime; + if (glm::length(_amountMoved) > MOVEMENT_DISTANCE_THRESHOLD && foundHand) { + _lastMovement = usecTimestampNow(); + _amountMoved = glm::vec3(0.0f); + } + + // Store the one fingertip in the palm structure so we can track velocity + const float FINGER_LENGTH = 0.3f; // meters + const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH); + const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR; + glm::vec3 oldTipPosition = palm->getTipRawPosition(); + if (deltaTime > 0.f) { + palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime); + } else { + palm->setTipVelocity(glm::vec3(0.f)); + } + palm->setTipPosition(newTipPosition); + } + + if (numActiveControllers == 2) { + updateCalibration(controllers); } - palm->setTipPosition(newTipPosition); - } - if (numActiveControllers == 2) { - updateCalibration(controllers); } #endif // HAVE_SIXENSE } diff --git a/interface/src/devices/SixenseManager.h b/interface/src/devices/SixenseManager.h index 664c102f76..1954ac91bc 100644 --- a/interface/src/devices/SixenseManager.h +++ b/interface/src/devices/SixenseManager.h @@ -18,6 +18,11 @@ #include #include #include "sixense.h" + +#ifdef __APPLE__ + #include +#endif + #endif const unsigned int BUTTON_0 = 1U << 0; // the skinny button between 1 and 2 @@ -38,9 +43,12 @@ const bool DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS = false; class SixenseManager : public QObject { Q_OBJECT public: + static SixenseManager& getInstance(); - SixenseManager(); - ~SixenseManager(); + void initialize(); + bool isInitialized() const { return _isInitialized; } + + void setIsEnabled(bool isEnabled) { _isEnabled = isEnabled; } void update(float deltaTime); float getCursorPixelRangeMult() const; @@ -51,6 +59,9 @@ public slots: void setLowVelocityFilter(bool lowVelocityFilter) { _lowVelocityFilter = lowVelocityFilter; }; private: + SixenseManager(); + ~SixenseManager(); + #ifdef HAVE_SIXENSE void updateCalibration(const sixenseControllerData* controllers); void emulateMouse(PalmData* palm, int index); @@ -72,7 +83,13 @@ private: glm::vec3 _reachForward; float _lastDistance; +#ifdef __APPLE__ + QLibrary* _sixenseLibrary; #endif + +#endif + bool _isInitialized; + bool _isEnabled; bool _hydrasConnected; quint64 _lastMovement; glm::vec3 _amountMoved; diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index df7c2d2289..d8d2213d8f 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -671,7 +671,7 @@ void ApplicationOverlay::renderControllerPointers() { float yAngle = 0.5f - ((atan2(direction.z, direction.y) + M_PI_2)); // Get the pixel range over which the xAngle and yAngle are scaled - float cursorRange = glWidget->width() * application->getSixenseManager()->getCursorPixelRangeMult(); + float cursorRange = glWidget->width() * SixenseManager::getInstance().getCursorPixelRangeMult(); mouseX = (glWidget->width() / 2.0f + cursorRange * xAngle); mouseY = (glWidget->height() / 2.0f + cursorRange * yAngle); From db0bfd53ae4758a0a601f07200b08dd9d0f74a93 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 29 Sep 2014 12:58:40 -0700 Subject: [PATCH 13/58] make the sixense library name a constant --- interface/src/devices/SixenseManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 14b598f58c..5068427db8 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -93,7 +93,8 @@ void SixenseManager::initialize() { #ifdef __APPLE__ if (!_sixenseLibrary) { - _sixenseLibrary = new QLibrary("libsixense_x64.dylib"); + const QString SIXENSE_LIBRARY_NAME = "libsixense_x64.dylib"; + _sixenseLibrary = new QLibrary(SIXENSE_LIBRARY_NAME); } SixenseBaseFunction sixenseInit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseInit"); From 1f4c0b6340ab1282066c67f8b3f5ada401d278a2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 29 Sep 2014 13:09:25 -0700 Subject: [PATCH 14/58] wrap sixenseExit call in HAVE_SIXENSE ifdef --- interface/src/devices/SixenseManager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 5068427db8..7823d6e840 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -63,6 +63,7 @@ SixenseManager::SixenseManager() : } SixenseManager::~SixenseManager() { +#ifdef HAVE_SIXENSE_ if (_isInitialized) { #ifdef __APPLE__ @@ -75,6 +76,8 @@ SixenseManager::~SixenseManager() { #ifdef __APPLE__ delete _sixenseLibrary; #endif + +#endif } void SixenseManager::initialize() { From 3fbf14168657e52d162a0242dcada9e812375337 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 29 Sep 2014 13:14:25 -0700 Subject: [PATCH 15/58] handle avatar location changes after avatar position has been reloaded --- interface/src/Application.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c00b83b53d..261411b5fb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -303,9 +303,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // connect to the domainChangeRequired signal on AddressManager connect(&addressManager, &AddressManager::possibleDomainChangeRequired, this, &Application::changeDomainHostname); - - // when --url in command line, teleport to location - addressManager.handleLookupString(getCmdOption(argc, constArgv, "--url")); _settings = new QSettings(this); _numChangedSettings = 0; @@ -1796,6 +1793,13 @@ void Application::init() { Menu::getInstance()->loadSettings(); _audio.setReceivedAudioStreamSettings(Menu::getInstance()->getReceivedAudioStreamSettings()); + + // when --url in command line, teleport to location + const QString HIFI_URL_COMMAND_LINE_KEY = "--url"; + int urlIndex = arguments().indexOf(HIFI_URL_COMMAND_LINE_KEY); + if (urlIndex != -1) { + AddressManager::getInstance().handleLookupString(arguments().value(urlIndex + 1)); + } qDebug("Loaded settings"); From a847c2d80d70ec74383b2afd94c57a543bd2b6f8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 29 Sep 2014 13:15:28 -0700 Subject: [PATCH 16/58] move url handling to after settings load debug --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 261411b5fb..e0c03584bf 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1793,6 +1793,8 @@ void Application::init() { Menu::getInstance()->loadSettings(); _audio.setReceivedAudioStreamSettings(Menu::getInstance()->getReceivedAudioStreamSettings()); + + qDebug() << "Loaded settings"; // when --url in command line, teleport to location const QString HIFI_URL_COMMAND_LINE_KEY = "--url"; @@ -1801,8 +1803,6 @@ void Application::init() { AddressManager::getInstance().handleLookupString(arguments().value(urlIndex + 1)); } - qDebug("Loaded settings"); - // initialize our face trackers after loading the menu settings _faceshift.init(); _faceplus.init(); From 72ff908bd3fb125e2c16ee63325e953ee3e22aba Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 29 Sep 2014 14:37:11 -0700 Subject: [PATCH 17/58] Fix for metavoxel crashes on Windows. I was expecting the scope of a temporary object to last until the next line; turns out VC++ can destroy it in the middle of evaluating the line. --- interface/src/MetavoxelSystem.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index b993d5243e..e8a70a2419 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -1204,7 +1204,8 @@ int PointAugmentVisitor::visit(MetavoxelInfo& info) { _points.swap(swapPoints); buffer = new PointBuffer(swapPoints); } - info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(buffer))); + BufferDataPointer pointer(buffer); + info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer)); } return STOP_RECURSION; } @@ -1219,7 +1220,8 @@ bool PointAugmentVisitor::postVisit(MetavoxelInfo& info) { _points.swap(swapPoints); buffer = new PointBuffer(swapPoints); } - info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(buffer))); + BufferDataPointer pointer(buffer); + info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer)); return true; } @@ -1446,7 +1448,8 @@ int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) { _data->guide(_fetchVisitor); } } - info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(buffer))); + BufferDataPointer pointer(buffer); + info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer)); return STOP_RECURSION; } @@ -1505,7 +1508,8 @@ int HeightfieldUpdateVisitor::visit(MetavoxelInfo& info) { buffer->getHeight(), buffer->getColor(), buffer->getMaterial(), buffer->getMaterials()); _fetchVisitor.init(newBuffer); _data->guide(_fetchVisitor); - info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(newBuffer))); + BufferDataPointer pointer(newBuffer); + info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer)); return STOP_RECURSION; } @@ -2078,7 +2082,8 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { buffer = new VoxelBuffer(vertices, indices, material->getMaterials()); } - info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(buffer))); + BufferDataPointer pointer(buffer); + info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer)); return STOP_RECURSION; } From c99047677fd7ed5f5faeb1b297b815110aa21125 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 29 Sep 2014 14:49:55 -0700 Subject: [PATCH 18/58] Members initialisation --- libraries/avatars/src/Player.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libraries/avatars/src/Player.cpp b/libraries/avatars/src/Player.cpp index 929f9cddb9..2540d7d004 100644 --- a/libraries/avatars/src/Player.cpp +++ b/libraries/avatars/src/Player.cpp @@ -19,6 +19,8 @@ Player::Player(AvatarData* avatar) : _recording(new Recording()), + _currentFrame(-1), + _frameInterpolationFactor(0.0f), _pausedFrame(-1), _timerOffset(0), _avatar(avatar), @@ -267,7 +269,7 @@ void Player::play() { float leanForward = glm::mix(currentFrame.getLeanForward(), nextFrame.getLeanForward(), _frameInterpolationFactor); - head->setLeanForward(currentFrame.getLeanForward()); + head->setLeanForward(leanForward); glm::quat headRotation = safeMix(currentFrame.getHeadRotation(), nextFrame.getHeadRotation(), From 4c617c6d5562ff709815463c9e0eefcece06da2c Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 29 Sep 2014 14:51:45 -0700 Subject: [PATCH 19/58] Stop using the emissive color for glow. --- interface/src/renderer/Model.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 858d8c9239..55eefb0bde 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1335,11 +1335,7 @@ void Model::renderMeshes(RenderMode mode, bool translucent, float alphaThreshold } else { glm::vec4 diffuse = glm::vec4(part.diffuseColor, part.opacity); if (!(translucent && alphaThreshold == 0.0f)) { - float emissive = (part.emissiveColor.r + part.emissiveColor.g + part.emissiveColor.b) / 3.0f; - diffuse.a = qMax(Application::getInstance()->getGlowEffect()->getIntensity(), emissive); - glAlphaFunc(GL_EQUAL, diffuse.a); - diffuse = glm::vec4(qMax(diffuse.r, part.emissiveColor.r), qMax(diffuse.g, part.emissiveColor.g), - qMax(diffuse.b, part.emissiveColor.b), diffuse.a); + glAlphaFunc(GL_EQUAL, diffuse.a = Application::getInstance()->getGlowEffect()->getIntensity()); } glm::vec4 specular = glm::vec4(part.specularColor, 1.0f); glMaterialfv(GL_FRONT, GL_AMBIENT, (const float*)&diffuse); From c16ab0a19fa388afc2f8b31cd8ca6e653c231a1c Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 29 Sep 2014 15:27:45 -0700 Subject: [PATCH 20/58] remove definition for an unused method --- libraries/shared/src/HifiConfigVariantMap.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/shared/src/HifiConfigVariantMap.h b/libraries/shared/src/HifiConfigVariantMap.h index 99a58d731e..6bdeb15589 100644 --- a/libraries/shared/src/HifiConfigVariantMap.h +++ b/libraries/shared/src/HifiConfigVariantMap.h @@ -33,7 +33,6 @@ private: QVariantMap _userConfig; QVariantMap _mergedConfig; - QVariantMap mergeMasterConfigWithUserConfig(const QStringList& argumentList); void loadMapFromJSONFile(QVariantMap& existingMap, const QString& filename); void addMissingValuesToExistingMap(QVariantMap& existingMap, const QVariantMap& newMap); }; From 1bffaa262d36f1f3a23a6081299e3b44f722fbae Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 29 Sep 2014 15:46:22 -0700 Subject: [PATCH 21/58] Reference camera object rather than copy it --- interface/src/Application.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0fd7ae96d1..57a0bb336d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -650,7 +650,7 @@ void Application::paintGL() { // Why have two cameras? Well, one reason is that because in the case of the renderViewFrustum() // code, we want to keep the state of "myCamera" intact, so we can render what the view frustum of // myCamera is. But we also want to do meaningful camera transforms on OpenGL for the offset camera - Camera whichCamera = _myCamera; + Camera* whichCamera = &_myCamera; if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum)) { @@ -664,7 +664,7 @@ void Application::paintGL() { _viewFrustumOffsetCamera.setDistance(viewFrustumOffset.distance); _viewFrustumOffsetCamera.initialize(); // force immediate snap to ideal position and orientation _viewFrustumOffsetCamera.update(1.f/_fps); - whichCamera = _viewFrustumOffsetCamera; + whichCamera = &_viewFrustumOffsetCamera; } if (Menu::getInstance()->getShadowsEnabled()) { @@ -677,15 +677,15 @@ void Application::paintGL() { glClear(GL_COLOR_BUFFER_BIT); //When in mirror mode, use camera rotation. Otherwise, use body rotation - if (whichCamera.getMode() == CAMERA_MODE_MIRROR) { - OculusManager::display(whichCamera.getRotation(), whichCamera.getPosition(), whichCamera); + if (whichCamera->getMode() == CAMERA_MODE_MIRROR) { + OculusManager::display(whichCamera->getRotation(), whichCamera->getPosition(), *whichCamera); } else { - OculusManager::display(_myAvatar->getWorldAlignedOrientation(), _myAvatar->getDefaultEyePosition(), whichCamera); + OculusManager::display(_myAvatar->getWorldAlignedOrientation(), _myAvatar->getDefaultEyePosition(), *whichCamera); } } else if (TV3DManager::isConnected()) { - TV3DManager::display(whichCamera); + TV3DManager::display(*whichCamera); } else { _glowEffect.prepare(); @@ -693,7 +693,7 @@ void Application::paintGL() { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); - displaySide(whichCamera); + displaySide(*whichCamera); glPopMatrix(); if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { From 2fbd249d9f3da191a30dc94dd0b7c1912fcdb11f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 29 Sep 2014 16:38:10 -0700 Subject: [PATCH 22/58] fix reset password link for LoginDialog --- interface/src/ui/LoginDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/LoginDialog.cpp b/interface/src/ui/LoginDialog.cpp index 57e02689c1..6583e170d3 100644 --- a/interface/src/ui/LoginDialog.cpp +++ b/interface/src/ui/LoginDialog.cpp @@ -21,7 +21,7 @@ #include "LoginDialog.h" -const QString FORGOT_PASSWORD_URL = "https://data.highfidelity.io/password/new"; +const QString FORGOT_PASSWORD_URL = "https://data.highfidelity.io/users/password/new"; LoginDialog::LoginDialog(QWidget* parent) : FramelessDialog(parent, 0, FramelessDialog::POSITION_TOP), From f047c2dff09fd586b9d7f790a1e56c1881768127 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 29 Sep 2014 17:08:06 -0700 Subject: [PATCH 23/58] have OS X hydra support be disabled by default --- interface/src/Menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 1da85aad16..d2ae9160ad 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -434,7 +434,7 @@ Menu::Menu() : #ifdef __APPLE__ addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseEnabled, - 0, true, + 0, false, this, SLOT(toggleSixense(bool))); #endif From e512b05e621293f75bcbab45f104f0918c373e91 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Mon, 29 Sep 2014 17:28:50 -0700 Subject: [PATCH 24/58] add extra debug for hydra library initialization --- interface/src/devices/SixenseManager.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 7823d6e840..28b125b6da 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -100,6 +100,8 @@ void SixenseManager::initialize() { _sixenseLibrary = new QLibrary(SIXENSE_LIBRARY_NAME); } + qDebug() << "Initializing sixense library for hydra support - libsixense_x64.dylib load state is" + << _sixenseLibrary->isLoaded(); SixenseBaseFunction sixenseInit = (SixenseBaseFunction) _sixenseLibrary->resolve("sixenseInit"); #endif From 802b14d5abe84f6bbb7154ca9abdfb925d8e87be Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Mon, 29 Sep 2014 19:14:17 -0700 Subject: [PATCH 25/58] Use Jacobi eigenvalue algorithm to get eigenvalues/eigenvectors. --- interface/src/MetavoxelSystem.cpp | 128 +++++++----------------------- 1 file changed, 28 insertions(+), 100 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index b993d5243e..00050e5553 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -1878,114 +1878,42 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { glm::mat3 atrans = glm::transpose(a); glm::mat3 ata = atrans * a; - // compute the SVD of ata; first, find the eigenvalues - // (see http://en.wikipedia.org/wiki/Eigenvalue_algorithm#3.C3.973_matrices) - glm::vec3 eigenvalues; - float p1 = ata[0][1] * ata[0][1] + ata[0][2] * ata[0][2] + ata[1][2] * ata[1][2]; - if (p1 < EPSILON) { - eigenvalues = glm::vec3(ata[0][0], ata[1][1], ata[2][2]); - if (eigenvalues[2] < eigenvalues[1]) { - qSwap(eigenvalues[2], eigenvalues[1]); + // find the eigenvalues and eigenvectors of ata + // (see http://en.wikipedia.org/wiki/Jacobi_eigenvalue_algorithm) + glm::mat3 d = ata; + glm::quat combinedRotation; + const int MAX_ITERATIONS = 20; + for (int i = 0; i < MAX_ITERATIONS; i++) { + glm::vec3 offDiagonals = glm::abs(glm::vec3(d[1][0], d[2][0], d[2][1])); + int largestIndex = (offDiagonals[0] > offDiagonals[1]) ? (offDiagonals[0] > offDiagonals[2] ? 0 : 2) : + (offDiagonals[1] > offDiagonals[2] ? 1 : 2); + const float DESIRED_PRECISION = 0.00001f; + if (offDiagonals[largestIndex] < DESIRED_PRECISION) { + break; } - if (eigenvalues[1] < eigenvalues[0]) { - qSwap(eigenvalues[1], eigenvalues[0]); + int largestJ = (largestIndex == 2) ? 1 : 0; + int largestI = (largestIndex == 0) ? 1 : 2; + float sjj = d[largestJ][largestJ]; + float sii = d[largestI][largestI]; + float angle = (sii == sjj ? PI_OVER_TWO : glm::atan(2.0f * d[largestJ][largestI], sjj - sii)) / 2.0f; + glm::quat rotation = glm::angleAxis(angle, largestIndex == 0 ? glm::vec3(0.0f, 0.0f, -1.0f) : + (largestIndex == 1 ? glm::vec3(0.0f, 1.0f, 0.0f) : glm::vec3(-1.0f, 0.0f, 0.0f))); + if (rotation.w == 0.0f) { + break; } - if (eigenvalues[2] < eigenvalues[1]) { - qSwap(eigenvalues[2], eigenvalues[1]); - } - } else { - float q = (ata[0][0] + ata[1][1] + ata[2][2]) / 3.0f; - float d1 = ata[0][0] - q, d2 = ata[1][1] - q, d3 = ata[2][2] - q; - float p2 = d1 * d1 + d2 * d2 + d3 * d3 + 2.0f * p1; - float p = glm::sqrt(p2 / 6.0f); - glm::mat3 b = (ata - glm::mat3(q)) / p; - float r = glm::determinant(b) / 2.0f; - float phi; - if (r <= -1.0f) { - phi = PI / 3.0f; - } else if (r >= 1.0f) { - phi = 0.0f; - } else { - phi = glm::acos(r) / 3.0f; - } - eigenvalues[2] = q + 2.0f * p * glm::cos(phi); - eigenvalues[0] = q + 2.0f * p * glm::cos(phi + (2.0f * PI / 3.0f)); - eigenvalues[1] = 3.0f * q - eigenvalues[0] - eigenvalues[2]; + combinedRotation = glm::normalize(rotation * combinedRotation); + glm::mat3 matrix = glm::mat3_cast(combinedRotation); + d = matrix * ata * glm::transpose(matrix); } // form the singular matrix from the eigenvalues - glm::mat3 d; const float MIN_SINGULAR_THRESHOLD = 0.1f; - d[0][0] = (eigenvalues[0] < MIN_SINGULAR_THRESHOLD) ? 0.0f : 1.0f / eigenvalues[0]; - d[1][1] = (eigenvalues[1] < MIN_SINGULAR_THRESHOLD) ? 0.0f : 1.0f / eigenvalues[1]; - d[2][2] = (eigenvalues[2] < MIN_SINGULAR_THRESHOLD) ? 0.0f : 1.0f / eigenvalues[2]; - - glm::mat3 m[] = { ata - glm::mat3(eigenvalues[0]), ata - glm::mat3(eigenvalues[1]), - ata - glm::mat3(eigenvalues[2]) }; - - // form the orthogonal matrix from the eigenvectors - // see http://www.geometrictools.com/Documentation/EigenSymmetric3x3.pdf - bool same01 = glm::abs(eigenvalues[0] - eigenvalues[1]) < EPSILON; - bool same12 = glm::abs(eigenvalues[1] - eigenvalues[2]) < EPSILON; - glm::mat3 u; - if (!(same01 && same12)) { - if (same01 || same12) { - int i = same01 ? 2 : 0; - for (int j = 0; j < 3; j++) { - glm::vec3 first = glm::vec3(m[i][0][j], m[i][1][j], m[i][2][j]); - int j2 = (j + 1) % 3; - glm::vec3 second = glm::vec3(m[i][0][j2], m[i][1][j2], m[i][2][j2]); - glm::vec3 cross = glm::cross(first, second); - float length = glm::length(cross); - if (length > EPSILON) { - u[0][i] = cross[0] / length; - u[1][i] = cross[1] / length; - u[2][i] = cross[2] / length; - break; - } - } - i = (i + 1) % 3; - for (int j = 0; j < 3; j++) { - glm::vec3 first = glm::vec3(m[i][0][j], m[i][1][j], m[i][2][j]); - float length = glm::length(first); - if (length > EPSILON) { - glm::vec3 second = glm::cross(first, glm::vec3(1.0f, 0.0f, 0.0f)); - length = glm::length(second); - if (length < EPSILON) { - second = glm::cross(first, glm::vec3(0.0f, 1.0f, 0.0f)); - length = glm::length(second); - } - u[0][i] = second[0] / length; - u[1][i] = second[1] / length; - u[2][i] = second[2] / length; - second = glm::normalize(glm::cross(second, first)); - i = (i + 1) % 3; - u[0][i] = second[0]; - u[1][i] = second[1]; - u[2][i] = second[2]; - break; - } - } - } else { - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - glm::vec3 first = glm::vec3(m[i][0][j], m[i][1][j], m[i][2][j]); - int j2 = (j + 1) % 3; - glm::vec3 second = glm::vec3(m[i][0][j2], m[i][1][j2], m[i][2][j2]); - glm::vec3 cross = glm::cross(first, second); - float length = glm::length(cross); - if (length > EPSILON) { - u[0][i] = cross[0] / length; - u[1][i] = cross[1] / length; - u[2][i] = cross[2] / length; - break; - } - } - } - } - } + d[0][0] = (d[0][0] < MIN_SINGULAR_THRESHOLD) ? 0.0f : 1.0f / d[0][0]; + d[1][1] = (d[1][1] < MIN_SINGULAR_THRESHOLD) ? 0.0f : 1.0f / d[1][1]; + d[2][2] = (d[2][2] < MIN_SINGULAR_THRESHOLD) ? 0.0f : 1.0f / d[2][2]; // compute the pseudo-inverse, ataplus, and use to find the minimizing solution + glm::mat3 u = glm::mat3_cast(combinedRotation); glm::mat3 ataplus = glm::transpose(u) * d * u; glm::vec3 solution = (ataplus * atrans * b) + center; From c84aac9d2e65472cfa2b97c4963a3ee5e5f43fe2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 09:12:53 -0700 Subject: [PATCH 26/58] remove an extra console log --- domain-server/resources/web/js/settings.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index 3313bce06d..8c1faf9003 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -6,8 +6,6 @@ var viewHelpers = { getFormGroup: function(groupName, setting, values, isAdvanced, isLocked) { setting_id = groupName + "_" + setting.name - console.log(setting.name + " in " + groupName + " is " + isLocked) - form_group = "
" if (_.has(values, groupName) && _.has(values[groupName], setting.name)) { @@ -41,7 +39,6 @@ var viewHelpers = { form_group += "" + setting.help + "" } - form_group += "
" return form_group } From 85aa0c34fbe42127b18d172b06a26bdd43f198e5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 09:31:04 -0700 Subject: [PATCH 27/58] stub of domain-server choose domain handler --- domain-server/resources/web/js/bootbox.min.js | 6 ++++++ domain-server/resources/web/js/settings.js | 17 +++++++++++++++++ .../resources/web/settings/index.shtml | 1 + 3 files changed, 24 insertions(+) create mode 100644 domain-server/resources/web/js/bootbox.min.js diff --git a/domain-server/resources/web/js/bootbox.min.js b/domain-server/resources/web/js/bootbox.min.js new file mode 100644 index 0000000000..a7ea24fe7a --- /dev/null +++ b/domain-server/resources/web/js/bootbox.min.js @@ -0,0 +1,6 @@ +/** + * bootbox.js v4.3.0 + * + * http://bootboxjs.com/license.txt + */ +!function(a,b){"use strict";"function"==typeof define&&define.amd?define(["jquery"],b):"object"==typeof exports?module.exports=b(require("jquery")):a.bootbox=b(a.jQuery)}(this,function a(b,c){"use strict";function d(a){var b=q[o.locale];return b?b[a]:q.en[a]}function e(a,c,d){a.stopPropagation(),a.preventDefault();var e=b.isFunction(d)&&d(a)===!1;e||c.modal("hide")}function f(a){var b,c=0;for(b in a)c++;return c}function g(a,c){var d=0;b.each(a,function(a,b){c(a,b,d++)})}function h(a){var c,d;if("object"!=typeof a)throw new Error("Please supply an object of options");if(!a.message)throw new Error("Please specify a message");return a=b.extend({},o,a),a.buttons||(a.buttons={}),a.backdrop=a.backdrop?"static":!1,c=a.buttons,d=f(c),g(c,function(a,e,f){if(b.isFunction(e)&&(e=c[a]={callback:e}),"object"!==b.type(e))throw new Error("button with key "+a+" must be an object");e.label||(e.label=a),e.className||(e.className=2>=d&&f===d-1?"btn-primary":"btn-default")}),a}function i(a,b){var c=a.length,d={};if(1>c||c>2)throw new Error("Invalid argument length");return 2===c||"string"==typeof a[0]?(d[b[0]]=a[0],d[b[1]]=a[1]):d=a[0],d}function j(a,c,d){return b.extend(!0,{},a,i(c,d))}function k(a,b,c,d){var e={className:"bootbox-"+a,buttons:l.apply(null,b)};return m(j(e,d,c),b)}function l(){for(var a={},b=0,c=arguments.length;c>b;b++){var e=arguments[b],f=e.toLowerCase(),g=e.toUpperCase();a[f]={label:d(g)}}return a}function m(a,b){var d={};return g(b,function(a,b){d[b]=!0}),g(a.buttons,function(a){if(d[a]===c)throw new Error("button key "+a+" is not allowed (options are "+b.join("\n")+")")}),a}var n={dialog:"",header:"",footer:"",closeButton:"",form:"
",inputs:{text:"",textarea:"",email:"",select:"",checkbox:"
",date:"",time:"",number:"",password:""}},o={locale:"en",backdrop:!0,animate:!0,className:null,closeButton:!0,show:!0,container:"body"},p={};p.alert=function(){var a;if(a=k("alert",["ok"],["message","callback"],arguments),a.callback&&!b.isFunction(a.callback))throw new Error("alert requires callback property to be a function when provided");return a.buttons.ok.callback=a.onEscape=function(){return b.isFunction(a.callback)?a.callback():!0},p.dialog(a)},p.confirm=function(){var a;if(a=k("confirm",["cancel","confirm"],["message","callback"],arguments),a.buttons.cancel.callback=a.onEscape=function(){return a.callback(!1)},a.buttons.confirm.callback=function(){return a.callback(!0)},!b.isFunction(a.callback))throw new Error("confirm requires a callback");return p.dialog(a)},p.prompt=function(){var a,d,e,f,h,i,k;if(f=b(n.form),d={className:"bootbox-prompt",buttons:l("cancel","confirm"),value:"",inputType:"text"},a=m(j(d,arguments,["title","callback"]),["cancel","confirm"]),i=a.show===c?!0:a.show,a.message=f,a.buttons.cancel.callback=a.onEscape=function(){return a.callback(null)},a.buttons.confirm.callback=function(){var c;switch(a.inputType){case"text":case"textarea":case"email":case"select":case"date":case"time":case"number":case"password":c=h.val();break;case"checkbox":var d=h.find("input:checked");c=[],g(d,function(a,d){c.push(b(d).val())})}return a.callback(c)},a.show=!1,!a.title)throw new Error("prompt requires a title");if(!b.isFunction(a.callback))throw new Error("prompt requires a callback");if(!n.inputs[a.inputType])throw new Error("invalid prompt type");switch(h=b(n.inputs[a.inputType]),a.inputType){case"text":case"textarea":case"email":case"date":case"time":case"number":case"password":h.val(a.value);break;case"select":var o={};if(k=a.inputOptions||[],!k.length)throw new Error("prompt with select requires options");g(k,function(a,d){var e=h;if(d.value===c||d.text===c)throw new Error("given options in wrong format");d.group&&(o[d.group]||(o[d.group]=b("").attr("label",d.group)),e=o[d.group]),e.append("")}),g(o,function(a,b){h.append(b)}),h.val(a.value);break;case"checkbox":var q=b.isArray(a.value)?a.value:[a.value];if(k=a.inputOptions||[],!k.length)throw new Error("prompt with checkbox requires options");if(!k[0].value||!k[0].text)throw new Error("given options in wrong format");h=b("
"),g(k,function(c,d){var e=b(n.inputs[a.inputType]);e.find("input").attr("value",d.value),e.find("label").append(d.text),g(q,function(a,b){b===d.value&&e.find("input").prop("checked",!0)}),h.append(e)})}return a.placeholder&&h.attr("placeholder",a.placeholder),a.pattern&&h.attr("pattern",a.pattern),f.append(h),f.on("submit",function(a){a.preventDefault(),a.stopPropagation(),e.find(".btn-primary").click()}),e=p.dialog(a),e.off("shown.bs.modal"),e.on("shown.bs.modal",function(){h.focus()}),i===!0&&e.modal("show"),e},p.dialog=function(a){a=h(a);var c=b(n.dialog),d=c.find(".modal-dialog"),f=c.find(".modal-body"),i=a.buttons,j="",k={onEscape:a.onEscape};if(g(i,function(a,b){j+="",k[a]=b.callback}),f.find(".bootbox-body").html(a.message),a.animate===!0&&c.addClass("fade"),a.className&&c.addClass(a.className),"large"===a.size&&d.addClass("modal-lg"),"small"===a.size&&d.addClass("modal-sm"),a.title&&f.before(n.header),a.closeButton){var l=b(n.closeButton);a.title?c.find(".modal-header").prepend(l):l.css("margin-top","-10px").prependTo(f)}return a.title&&c.find(".modal-title").html(a.title),j.length&&(f.after(n.footer),c.find(".modal-footer").html(j)),c.on("hidden.bs.modal",function(a){a.target===this&&c.remove()}),c.on("shown.bs.modal",function(){c.find(".btn-primary:first").focus()}),c.on("escape.close.bb",function(a){k.onEscape&&e(a,c,k.onEscape)}),c.on("click",".modal-footer button",function(a){var d=b(this).data("bb-handler");e(a,c,k[d])}),c.on("click",".bootbox-close-button",function(a){e(a,c,k.onEscape)}),c.on("keyup",function(a){27===a.which&&c.trigger("escape.close.bb")}),b(a.container).append(c),c.modal({backdrop:a.backdrop,keyboard:!1,show:!1}),a.show&&c.modal("show"),c},p.setDefaults=function(){var a={};2===arguments.length?a[arguments[0]]=arguments[1]:a=arguments[0],b.extend(o,a)},p.hideAll=function(){return b(".bootbox").modal("hide"),p};var q={br:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Sim"},cs:{OK:"OK",CANCEL:"Zrušit",CONFIRM:"Potvrdit"},da:{OK:"OK",CANCEL:"Annuller",CONFIRM:"Accepter"},de:{OK:"OK",CANCEL:"Abbrechen",CONFIRM:"Akzeptieren"},el:{OK:"Εντάξει",CANCEL:"Ακύρωση",CONFIRM:"Επιβεβαίωση"},en:{OK:"OK",CANCEL:"Cancel",CONFIRM:"OK"},es:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Aceptar"},et:{OK:"OK",CANCEL:"Katkesta",CONFIRM:"OK"},fi:{OK:"OK",CANCEL:"Peruuta",CONFIRM:"OK"},fr:{OK:"OK",CANCEL:"Annuler",CONFIRM:"D'accord"},he:{OK:"אישור",CANCEL:"ביטול",CONFIRM:"אישור"},id:{OK:"OK",CANCEL:"Batal",CONFIRM:"OK"},it:{OK:"OK",CANCEL:"Annulla",CONFIRM:"Conferma"},ja:{OK:"OK",CANCEL:"キャンセル",CONFIRM:"確認"},lt:{OK:"Gerai",CANCEL:"Atšaukti",CONFIRM:"Patvirtinti"},lv:{OK:"Labi",CANCEL:"Atcelt",CONFIRM:"Apstiprināt"},nl:{OK:"OK",CANCEL:"Annuleren",CONFIRM:"Accepteren"},no:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},pl:{OK:"OK",CANCEL:"Anuluj",CONFIRM:"Potwierdź"},pt:{OK:"OK",CANCEL:"Cancelar",CONFIRM:"Confirmar"},ru:{OK:"OK",CANCEL:"Отмена",CONFIRM:"Применить"},sv:{OK:"OK",CANCEL:"Avbryt",CONFIRM:"OK"},tr:{OK:"Tamam",CANCEL:"İptal",CONFIRM:"Onayla"},zh_CN:{OK:"OK",CANCEL:"取消",CONFIRM:"确认"},zh_TW:{OK:"OK",CANCEL:"取消",CONFIRM:"確認"}};return p.init=function(c){return a(c||b)},p}); \ No newline at end of file diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index 8c1faf9003..adcd2dd8b7 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -86,6 +86,15 @@ $(document).ready(function(){ $(this).blur() }) + + $('#settings-form').on('click', '#choose-domain-btn', function(){ + // setup the modal to help user pick their domain + if (Settings.initialValues.metaverse["access-token"]) { + + } else { + + } + }) var panelsSource = $('#panels-template').html() Settings.panelsTemplate = _.template(panelsSource) @@ -112,9 +121,17 @@ function reloadSettings() { placement: 'right', title: 'This setting is in the master config file and cannot be changed' }) + + appendDomainSelectionModal() }); } +function appendDomainSelectionModal() { + var metaverseFormGroup = $('#metaverse_id').parent('.form-group'); + var chooseButton = ""; + metaverseFormGroup.append(chooseButton); +} + var SETTINGS_ERROR_MESSAGE = "There was a problem saving domain settings. Please try again!"; $('body').on('click', '.save-button', function(e){ diff --git a/domain-server/resources/web/settings/index.shtml b/domain-server/resources/web/settings/index.shtml index 2f0cdf6537..18b1f40d60 100644 --- a/domain-server/resources/web/settings/index.shtml +++ b/domain-server/resources/web/settings/index.shtml @@ -75,6 +75,7 @@ + \ No newline at end of file From f07a8fd672aa4a94f05c7b16bda74b3901dd86e4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 09:37:41 -0700 Subject: [PATCH 28/58] add a message for domain query with missing access token --- domain-server/resources/web/js/settings.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index adcd2dd8b7..45638a8b0d 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -92,7 +92,11 @@ $(document).ready(function(){ if (Settings.initialValues.metaverse["access-token"]) { } else { - + bootbox.alert({ + message: "You must have an access token to query your High Fidelity domains.

" + + "Please follow the instructions on the settings page to add an access token.", + title: "Access token required" + }) } }) From 68a70cc914fc6b4afab71edad730f32205abf210 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 09:40:54 -0700 Subject: [PATCH 29/58] don't use dashes in settings JSON keys --- assignment-client/src/audio/AudioMixer.cpp | 22 +++++++-------- .../resources/describe-settings.json | 28 +++++++++---------- domain-server/src/DomainServer.cpp | 4 +-- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 3670653493..2fb7342b0c 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -643,7 +643,7 @@ void AudioMixer::run() { QJsonObject audioGroupObject = settingsObject[AUDIO_GROUP_KEY].toObject(); // check the payload to see if we have asked for dynamicJitterBuffer support - const QString DYNAMIC_JITTER_BUFFER_JSON_KEY = "dynamic-jitter-buffer"; + const QString DYNAMIC_JITTER_BUFFER_JSON_KEY = "dynamic_jitter_buffer"; _streamSettings._dynamicJitterBuffers = audioGroupObject[DYNAMIC_JITTER_BUFFER_JSON_KEY].toBool(); if (_streamSettings._dynamicJitterBuffers) { qDebug() << "Enable dynamic jitter buffers."; @@ -652,21 +652,21 @@ void AudioMixer::run() { } bool ok; - const QString DESIRED_JITTER_BUFFER_FRAMES_KEY = "static-desired-jitter-buffer-frames"; + const QString DESIRED_JITTER_BUFFER_FRAMES_KEY = "static_desired_jitter_buffer_frames"; _streamSettings._staticDesiredJitterBufferFrames = audioGroupObject[DESIRED_JITTER_BUFFER_FRAMES_KEY].toString().toInt(&ok); if (!ok) { _streamSettings._staticDesiredJitterBufferFrames = DEFAULT_STATIC_DESIRED_JITTER_BUFFER_FRAMES; } qDebug() << "Static desired jitter buffer frames:" << _streamSettings._staticDesiredJitterBufferFrames; - const QString MAX_FRAMES_OVER_DESIRED_JSON_KEY = "max-frames-over-desired"; + const QString MAX_FRAMES_OVER_DESIRED_JSON_KEY = "max_frames_over_desired"; _streamSettings._maxFramesOverDesired = audioGroupObject[MAX_FRAMES_OVER_DESIRED_JSON_KEY].toString().toInt(&ok); if (!ok) { _streamSettings._maxFramesOverDesired = DEFAULT_MAX_FRAMES_OVER_DESIRED; } qDebug() << "Max frames over desired:" << _streamSettings._maxFramesOverDesired; - const QString USE_STDEV_FOR_DESIRED_CALC_JSON_KEY = "use-stdev-for-desired-calc"; + const QString USE_STDEV_FOR_DESIRED_CALC_JSON_KEY = "use_stdev_for_desired_calc"; _streamSettings._useStDevForJitterCalc = audioGroupObject[USE_STDEV_FOR_DESIRED_CALC_JSON_KEY].toBool(); if (_streamSettings._useStDevForJitterCalc) { qDebug() << "Using Philip's stdev method for jitter calc if dynamic jitter buffers enabled"; @@ -674,28 +674,28 @@ void AudioMixer::run() { qDebug() << "Using Fred's max-gap method for jitter calc if dynamic jitter buffers enabled"; } - const QString WINDOW_STARVE_THRESHOLD_JSON_KEY = "window-starve-threshold"; + const QString WINDOW_STARVE_THRESHOLD_JSON_KEY = "window_starve_threshold"; _streamSettings._windowStarveThreshold = audioGroupObject[WINDOW_STARVE_THRESHOLD_JSON_KEY].toString().toInt(&ok); if (!ok) { _streamSettings._windowStarveThreshold = DEFAULT_WINDOW_STARVE_THRESHOLD; } qDebug() << "Window A starve threshold:" << _streamSettings._windowStarveThreshold; - const QString WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES_JSON_KEY = "window-seconds-for-desired-calc-on-too-many-starves"; + const QString WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES_JSON_KEY = "window_seconds_for_desired_calc_on_too_many_starves"; _streamSettings._windowSecondsForDesiredCalcOnTooManyStarves = audioGroupObject[WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES_JSON_KEY].toString().toInt(&ok); if (!ok) { _streamSettings._windowSecondsForDesiredCalcOnTooManyStarves = DEFAULT_WINDOW_SECONDS_FOR_DESIRED_CALC_ON_TOO_MANY_STARVES; } qDebug() << "Window A length:" << _streamSettings._windowSecondsForDesiredCalcOnTooManyStarves << "seconds"; - const QString WINDOW_SECONDS_FOR_DESIRED_REDUCTION_JSON_KEY = "window-seconds-for-desired-reduction"; + const QString WINDOW_SECONDS_FOR_DESIRED_REDUCTION_JSON_KEY = "window_seconds_for_desired_reduction"; _streamSettings._windowSecondsForDesiredReduction = audioGroupObject[WINDOW_SECONDS_FOR_DESIRED_REDUCTION_JSON_KEY].toString().toInt(&ok); if (!ok) { _streamSettings._windowSecondsForDesiredReduction = DEFAULT_WINDOW_SECONDS_FOR_DESIRED_REDUCTION; } qDebug() << "Window B length:" << _streamSettings._windowSecondsForDesiredReduction << "seconds"; - const QString REPETITION_WITH_FADE_JSON_KEY = "repetition-with-fade"; + const QString REPETITION_WITH_FADE_JSON_KEY = "repetition_with_fade"; _streamSettings._repetitionWithFade = audioGroupObject[REPETITION_WITH_FADE_JSON_KEY].toBool(); if (_streamSettings._repetitionWithFade) { qDebug() << "Repetition with fade enabled"; @@ -703,13 +703,13 @@ void AudioMixer::run() { qDebug() << "Repetition with fade disabled"; } - const QString PRINT_STREAM_STATS_JSON_KEY = "print-stream-stats"; + const QString PRINT_STREAM_STATS_JSON_KEY = "print_stream_stats"; _printStreamStats = audioGroupObject[PRINT_STREAM_STATS_JSON_KEY].toBool(); if (_printStreamStats) { qDebug() << "Stream stats will be printed to stdout"; } - const QString FILTER_KEY = "enable-filter"; + const QString FILTER_KEY = "enable_filter"; if (audioGroupObject[FILTER_KEY].isBool()) { _enableFilter = audioGroupObject[FILTER_KEY].toBool(); } @@ -717,7 +717,7 @@ void AudioMixer::run() { qDebug() << "Filter enabled"; } - const QString UNATTENUATED_ZONE_KEY = "unattenuated-zone"; + const QString UNATTENUATED_ZONE_KEY = "unattenuated_zone"; QString unattenuatedZoneString = audioGroupObject[UNATTENUATED_ZONE_KEY].toString(); if (!unattenuatedZoneString.isEmpty()) { diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 19c293b610..cec1aabe75 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -4,7 +4,7 @@ "label": "Metaverse Registration", "settings": [ { - "name": "access-token", + "name": "access_token", "label": "Access Token", "help": "This is an access token generated on the My Tokens page of your High Fidelity account.
Generate a token with the 'domains' scope and paste it here.
This is required to associate this domain-server with a domain in your account." }, @@ -20,12 +20,12 @@ "label": "Security", "settings": [ { - "name": "http-username", + "name": "http_username", "label": "HTTP Username", "help": "Username used for basic HTTP authentication." }, { - "name": "http-password", + "name": "http_password", "label": "HTTP Password", "type": "password", "help": "Password used for basic HTTP authentication. Leave this blank if you do not want to change it.", @@ -39,20 +39,20 @@ "assignment-types": [0], "settings": [ { - "name": "enable-filter", + "name": "enable_filter", "type": "checkbox", "label": "Enable Positional Filter", "help": "positional audio stream uses lowpass filter", "default": true }, { - "name": "unattenuated-zone", + "name": "unattenuated_zone", "label": "Unattenuated Zone", "help": "Boxes for source and listener (corner x, corner y, corner z, size x, size y, size z, corner x, corner y, corner z, size x, size y, size z)", "placeholder": "no zone" }, { - "name": "dynamic-jitter-buffer", + "name": "dynamic_jitter_buffer", "type": "checkbox", "label": "Dynamic Jitter Buffers", "help": "dynamically buffer client audio based on perceived jitter in packet receipt timing", @@ -60,7 +60,7 @@ "advanced": true }, { - "name": "static-desired-jitter-buffer-frames", + "name": "static_desired_jitter_buffer_frames", "label": "Static Desired Jitter Buffer Frames", "help": "If dynamic jitter buffers is disabled, this determines the target number of frames maintained by the AudioMixer's jitter buffers", "placeholder": "1", @@ -68,7 +68,7 @@ "advanced": true }, { - "name": "max-frames-over-desired", + "name": "max_frames_over_desired", "label": "Max Frames Over Desired", "help": "The highest number of frames an AudioMixer's ringbuffer can exceed the desired jitter buffer frames by", "placeholder": "10", @@ -76,7 +76,7 @@ "advanced": true }, { - "name": "use-stdev-for-desired-calc", + "name": "use_stdev_for_desired_calc", "type": "checkbox", "label": "Use Stdev for Desired Jitter Frames Calc:", "help": "use Philip's method (stdev of timegaps) to calculate desired jitter frames (otherwise Fred's max timegap method is used)", @@ -84,7 +84,7 @@ "advanced": true }, { - "name": "window-starve-threshold", + "name": "window_starve_threshold", "label": "Window Starve Threshold", "help": "If this many starves occur in an N-second window (N is the number in the next field), then the desired jitter frames will be re-evaluated using Window A.", "placeholder": "3", @@ -92,7 +92,7 @@ "advanced": true }, { - "name": "window-seconds-for-desired-calc-on-too-many-starves", + "name": "window_seconds_for_desired_calc_on_too_many_starves", "label": "Timegaps Window (A) Seconds:", "help": "Window A contains a history of timegaps. Its max timegap is used to re-evaluate the desired jitter frames when too many starves occur within it.", "placeholder": "50", @@ -100,7 +100,7 @@ "advanced": true }, { - "name": "window-seconds-for-desired-reduction", + "name": "window_seconds_for_desired_reduction", "label": "Timegaps Window (B) Seconds:", "help": "Window B contains a history of timegaps. Its max timegap is used as a ceiling for the desired jitter frames value.", "placeholder": "10", @@ -108,7 +108,7 @@ "advanced": true }, { - "name": "repetition-with-fade", + "name": "repetition_with_fade", "type": "checkbox", "label": "Repetition with Fade:", "help": "dropped frames and mixing during starves repeat the last frame, eventually fading to silence", @@ -116,7 +116,7 @@ "advanced": true }, { - "name": "print-stream-stats", + "name": "print_stream_stats", "type": "checkbox", "label": "Print Stream Stats:", "help": "audio upstream and downstream stats of each agent printed to audio-mixer stdout", diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 4f048a2ec9..eccd52dfc1 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1396,8 +1396,8 @@ bool DomainServer::isAuthenticatedRequest(HTTPConnection* connection, const QUrl const QByteArray HTTP_COOKIE_HEADER_KEY = "Cookie"; const QString ADMIN_USERS_CONFIG_KEY = "admin-users"; const QString ADMIN_ROLES_CONFIG_KEY = "admin-roles"; - const QString BASIC_AUTH_USERNAME_KEY_PATH = "security.http-username"; - const QString BASIC_AUTH_PASSWORD_KEY_PATH = "security.http-password"; + const QString BASIC_AUTH_USERNAME_KEY_PATH = "security.http_username"; + const QString BASIC_AUTH_PASSWORD_KEY_PATH = "security.http_password"; const QByteArray UNAUTHENTICATED_BODY = "You do not have permission to access this domain-server."; From 7e184d67e5db5b587529bc40da1edfba0a3bff6e Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 09:49:34 -0700 Subject: [PATCH 30/58] handle transition from dashed JSON settings keys to underscore --- .../src/DomainServerSettingsManager.cpp | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index fc36a97a25..b5d7df65cf 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -39,6 +39,28 @@ DomainServerSettingsManager::DomainServerSettingsManager() : void DomainServerSettingsManager::setupConfigMap(const QStringList& argumentList) { _configMap.loadMasterAndUserConfig(argumentList); + + // for now we perform a temporary transition from http-username and http-password to http_username and http_password + const QVariant* oldUsername = valueForKeyPath(_configMap.getUserConfig(), "security.http-username"); + const QVariant* oldPassword = valueForKeyPath(_configMap.getUserConfig(), "security.http-password"); + + if (oldUsername || oldPassword) { + QVariantMap& settingsMap = *reinterpret_cast(_configMap.getUserConfig()["security"].data()); + + // remove old keys, move to new format + if (oldUsername) { + settingsMap["http_username"] = oldUsername->toString(); + settingsMap.remove("http-username"); + } + + if (oldPassword) { + settingsMap["http_password"] = oldPassword->toString(); + settingsMap.remove("http-password"); + } + + // save the updated settings + persistToFile(); + } } const QString SETTINGS_PATH = "/settings.json"; From a07a0f4f723d46718af4cba2347b218044f3ea21 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Tue, 30 Sep 2014 09:57:05 -0700 Subject: [PATCH 31/58] Disable room limits set for demo comedy club --- examples/headMove.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/headMove.js b/examples/headMove.js index 894575ead1..086ef80abc 100644 --- a/examples/headMove.js +++ b/examples/headMove.js @@ -43,7 +43,7 @@ var noFly = true; var fixedWalkVelocity = true; //var roomLimits = { xMin: 618, xMax: 635.5, zMin: 528, zMax: 552.5 }; -var roomLimits = { xMin: 100.0, xMax: 206.5, zMin: 251.4, zMax: 269.5 }; +var roomLimits = { xMin: -1.0, xMax: -1.0, zMin: -1.0, zMax: -1.0 }; function isInRoom(position) { var BUFFER = 2.0; From 673afca11b4e527658ffe59b759524b26e8df11b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 30 Sep 2014 10:05:59 -0700 Subject: [PATCH 32/58] Update camera object's position and orientation with actual Rift values --- interface/src/Application.cpp | 12 +++++++++--- interface/src/devices/OculusManager.cpp | 4 ++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 57a0bb336d..dc3b48ae85 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -609,8 +609,11 @@ void Application::paintGL() { if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { _myCamera.setTightness(0.0f); // In first person, camera follows (untweaked) head exactly without delay - _myCamera.setTargetPosition(_myAvatar->getHead()->getEyePosition()); - _myCamera.setTargetRotation(_myAvatar->getHead()->getCameraOrientation()); + if (!OculusManager::isConnected()) { + _myCamera.setTargetPosition(_myAvatar->getHead()->getEyePosition()); + _myCamera.setTargetRotation(_myAvatar->getHead()->getCameraOrientation()); + } + // OculusManager::display() updates camera position and rotation a bit further on. } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { //Note, the camera distance is set in Camera::setMode() so we dont have to do it here. @@ -640,7 +643,9 @@ void Application::paintGL() { } // Update camera position - _myCamera.update( 1.f/_fps ); + if (!OculusManager::isConnected()) { + _myCamera.update(1.f / _fps); + } // Note: whichCamera is used to pick between the normal camera myCamera for our // main camera, vs, an alternate camera. The alternate camera we support right now @@ -682,6 +687,7 @@ void Application::paintGL() { } else { OculusManager::display(_myAvatar->getWorldAlignedOrientation(), _myAvatar->getDefaultEyePosition(), *whichCamera); } + _myCamera.update(1.f / _fps); } else if (TV3DManager::isConnected()) { diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index 27590d9a72..65518b839c 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -412,6 +412,10 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p glBindTexture(GL_TEXTURE_2D, 0); + // Update camera for use by rest of Interface. + whichCamera.setTargetPosition((_leftEyePosition + _rightEyePosition) / 2.f); + whichCamera.setTargetRotation(_camera->getTargetRotation()); + #endif } From 26cd76e07b08b02c1272535d4e25e12bc0808303 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 30 Sep 2014 10:08:50 -0700 Subject: [PATCH 33/58] Position and orient hands when using Leap on HMD --- examples/leapHands.js | 102 +++++++++++++++++++++++++++++++----------- 1 file changed, 77 insertions(+), 25 deletions(-) diff --git a/examples/leapHands.js b/examples/leapHands.js index ba6ce432de..cc50a328f8 100644 --- a/examples/leapHands.js +++ b/examples/leapHands.js @@ -14,6 +14,8 @@ var leapHands = (function () { var isOnHMD, + LEAP_OFFSET = 0.019, // Thickness of Leap Motion plus HMD clip + HMD_OFFSET = 0.100, // Eyeballs to front surface of Oculus DK2 TODO: Confirm and make depend on device and eye relief hands, wrists, NUM_HANDS = 2, // 0 = left; 1 = right @@ -269,8 +271,9 @@ var leapHands = (function () { if (isOnHMD) { print("Leap Motion is on HMD"); - hands[0].zeroPosition = { x: 0.0, y: 0.0, z: 0.0 }; - hands[1].zeroPosition = { x: 0.0, y: 0.0, z: 0.0 }; + // Offset of Leap Motion origin from physical eye position + hands[0].zeroPosition = { x: 0.0, y: 0.0, z: HMD_OFFSET + LEAP_OFFSET }; + hands[1].zeroPosition = { x: 0.0, y: 0.0, z: HMD_OFFSET + LEAP_OFFSET }; calibrationStatus = CALIBRATED; } else { @@ -290,7 +293,9 @@ var leapHands = (function () { handYaw, handRotation, wristAbsRotation, - locRotation; + locRotation, + cameraOrientation, + inverseAvatarOrientation; for (h = 0; h < NUM_HANDS; h += 1) { side = h === 0 ? -1.0 : 1.0; @@ -303,35 +308,82 @@ var leapHands = (function () { } // Hand position ... - handOffset = hands[h].controller.getAbsTranslation(); - handOffset = { - x: -handOffset.x, - y: hands[h].zeroPosition.y + handOffset.y, - z: hands[h].zeroPosition.z - handOffset.z - }; + if (isOnHMD) { - // TODO: 2.0* scale factor should not be necessary; Leap Motion controller code needs investigating. - handRoll = 2.0 * -hands[h].controller.getAbsRotation().z; - wristAbsRotation = wrists[h].controller.getAbsRotation(); - handPitch = 2.0 * -wristAbsRotation.x; - handYaw = 2.0 * wristAbsRotation.y; + // Hand offset in camera coordinates ... + handOffset = hands[h].controller.getAbsTranslation(); + handOffset = { + x: hands[h].zeroPosition.x - handOffset.x, + y: hands[h].zeroPosition.y - handOffset.z, + z: hands[h].zeroPosition.z + handOffset.y + }; + handOffset.z = -handOffset.z; - // TODO: Leap Motion controller's right-hand roll calculation only works if physical hand is upside down. - // Approximate fix is to add a fudge factor. - if (h === 1 && isWindows) { - handRoll = handRoll + 0.6 * PI; - } + // Hand offset in world coordinates ... + cameraOrientation = Camera.getOrientation(); + handOffset = Vec3.sum(Camera.getPosition(), Vec3.multiplyQbyV(cameraOrientation, handOffset)); - // Hand position and orientation ... - if (h === 0) { - handRotation = Quat.multiply(Quat.angleAxis(-90.0, { x: 0, y: 1, z: 0 }), - Quat.fromVec3Radians({ x: handRoll, y: handYaw, z: -handPitch })); + // Hand offset in avatar coordinates ... + inverseAvatarOrientation = Quat.inverse(MyAvatar.orientation); + handOffset = Vec3.subtract(handOffset, MyAvatar.position); + handOffset = Vec3.multiplyQbyV(inverseAvatarOrientation, handOffset); + handOffset.z = -handOffset.z; + handOffset.x = -handOffset.x; + // Hand rotation in camera coordinates ... + // TODO: 2.0* scale factors should not be necessary; Leap Motion controller code needs investigating. + handRoll = 2.0 * -hands[h].controller.getAbsRotation().z; + wristAbsRotation = wrists[h].controller.getAbsRotation(); + handPitch = 2.0 * wristAbsRotation.x - PI / 2.0; + handYaw = 2.0 * -wristAbsRotation.y; + // TODO: Roll values only work if hand is upside down; Leap Motion controller code needs investigating. + handRoll = PI + handRoll; + + if (h === 0) { + handRotation = Quat.multiply(Quat.angleAxis(-90.0, { x: 0, y: 1, z: 0 }), + Quat.fromVec3Radians({ x: handRoll, y: handYaw, z: -handPitch })); + } else { + handRotation = Quat.multiply(Quat.angleAxis(90.0, { x: 0, y: 1, z: 0 }), + Quat.fromVec3Radians({ x: -handRoll, y: handYaw, z: handPitch })); + } + + // Hand rotation in avatar coordinates ... + cameraOrientation.x = -cameraOrientation.x; + cameraOrientation.z = -cameraOrientation.z; + handRotation = Quat.multiply(cameraOrientation, handRotation); + handRotation = Quat.multiply(inverseAvatarOrientation, handRotation); } else { - handRotation = Quat.multiply(Quat.angleAxis(90.0, { x: 0, y: 1, z: 0 }), - Quat.fromVec3Radians({ x: -handRoll, y: handYaw, z: handPitch })); + + handOffset = hands[h].controller.getAbsTranslation(); + handOffset = { + x: -handOffset.x, + y: hands[h].zeroPosition.y + handOffset.y, + z: hands[h].zeroPosition.z - handOffset.z + }; + + // TODO: 2.0* scale factors should not be necessary; Leap Motion controller code needs investigating. + handRoll = 2.0 * -hands[h].controller.getAbsRotation().z; + wristAbsRotation = wrists[h].controller.getAbsRotation(); + handPitch = 2.0 * -wristAbsRotation.x; + handYaw = 2.0 * wristAbsRotation.y; + + // TODO: Leap Motion controller's right-hand roll calculation only works if physical hand is upside down. + // Approximate fix is to add a fudge factor. + if (h === 1 && isWindows) { + handRoll = handRoll + 0.6 * PI; + } + + // Hand position and orientation ... + if (h === 0) { + handRotation = Quat.multiply(Quat.angleAxis(-90.0, { x: 0, y: 1, z: 0 }), + Quat.fromVec3Radians({ x: handRoll, y: handYaw, z: -handPitch })); + } else { + handRotation = Quat.multiply(Quat.angleAxis(90.0, { x: 0, y: 1, z: 0 }), + Quat.fromVec3Radians({ x: -handRoll, y: handYaw, z: handPitch })); + } } + MyAvatar.setJointModelPositionAndOrientation(hands[h].jointName, handOffset, handRotation, true); // Finger joints ... From 5b03a445a802020981970b8bdaf5bbbfae753f9f Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 10:47:52 -0700 Subject: [PATCH 34/58] allow user to choose domain ID from High Fidelity domains --- domain-server/resources/web/js/settings.js | 92 +++++++++++++++++----- 1 file changed, 72 insertions(+), 20 deletions(-) diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index 45638a8b0d..76b2e52078 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -4,7 +4,7 @@ var Settings = { var viewHelpers = { getFormGroup: function(groupName, setting, values, isAdvanced, isLocked) { - setting_id = groupName + "_" + setting.name + setting_name = groupName + "." + setting.name form_group = "
" @@ -24,16 +24,16 @@ var viewHelpers = { if (setting.type === 'checkbox') { form_group += "" form_group += "
" - form_group += ""; form_group += "
" } else { input_type = _.has(setting, 'type') ? setting.type : "text" - form_group += ""; - form_group += "" + setting.label + ""; + form_group += "" form_group += "" + setting.help + "" @@ -88,16 +88,7 @@ $(document).ready(function(){ }) $('#settings-form').on('click', '#choose-domain-btn', function(){ - // setup the modal to help user pick their domain - if (Settings.initialValues.metaverse["access-token"]) { - - } else { - bootbox.alert({ - message: "You must have an access token to query your High Fidelity domains.

" + - "Please follow the instructions on the settings page to add an access token.", - title: "Access token required" - }) - } + chooseFromHighFidelityDomains($(this)) }) var panelsSource = $('#panels-template').html() @@ -118,7 +109,7 @@ function reloadSettings() { $('.nav-stacked').html(Settings.sidebarTemplate(data)) $('#panels').html(Settings.panelsTemplate(data)) - Settings.initialValues = form2js('settings-form', "_", false, cleanupFormValues, true); + Settings.initialValues = form2js('settings-form', ".", false, cleanupFormValues, true); // add tooltip to locked settings $('label.locked').tooltip({ @@ -131,7 +122,7 @@ function reloadSettings() { } function appendDomainSelectionModal() { - var metaverseFormGroup = $('#metaverse_id').parent('.form-group'); + var metaverseFormGroup = $("[name='metaverse.id']").parent('.form-group'); var chooseButton = ""; metaverseFormGroup.append(chooseButton); } @@ -145,7 +136,7 @@ $('body').on('click', '.save-button', function(e){ }); // grab a JSON representation of the form via form2js - var formJSON = form2js('settings-form', "_", false, cleanupFormValues, true); + var formJSON = form2js('settings-form', ".", false, cleanupFormValues, true); // re-enable all inputs $("input").each(function(){ @@ -180,13 +171,13 @@ function badgeSidebarForDifferences(changedInput) { var panelParentID = changedInput.closest('.panel').attr('id') // get a JSON representation of that section - var rootJSON = form2js(panelParentID, "_", false, cleanupFormValues, true); + var rootJSON = form2js(panelParentID, ".", false, cleanupFormValues, true); var panelJSON = rootJSON[panelParentID] var badgeValue = 0 for (var setting in panelJSON) { - if (panelJSON[setting] != Settings.initialValues[panelParentID][ setting]) { + if (panelJSON[setting] != Settings.initialValues[panelParentID][setting]) { badgeValue += 1 } } @@ -238,4 +229,65 @@ function showAlertMessage(message, isSuccess) { alertBox.addClass(isSuccess ? 'alert-success' : 'alert-danger'); alertBox.html(message); alertBox.fadeIn(); +} + +function chooseFromHighFidelityDomains(clickedButton) { + // setup the modal to help user pick their domain + if (Settings.initialValues.metaverse.access_token) { + + // add a spinner to the choose button + + // get a list of user domains from data-web + data_web_domains_url = "https://data.highfidelity.io/api/v1/domains?access_token=" + $.getJSON(data_web_domains_url + Settings.initialValues.metaverse.access_token, function(data){ + + modal_buttons = { + cancel: { + label: 'Cancel', + className: 'btn-default' + } + } + + if (data.data.domains.length) { + // setup a select box for the returned domains + modal_body = "

Choose the High Fidelity domain you want this domain-server to represent.
This will set your domain ID on the settings page.

" + domain_select = $("") + _.each(data.data.domains, function(domain){ + domain_select.append("") + }) + modal_body += "" + domain_select[0].outerHTML + modal_buttons["success"] = { + label: 'Choose domain', + callback: function() { + domainID = $('#domain-name-select').val() + // set the domain ID on the form + $("[name='metaverse.id']").val(domainID).change(); + } + } + } else { + modal_buttons["success"] = { + label: 'Create new domain', + callback: function() { + window.open("https://data.highfidelity.io/domains", '_blank'); + } + } + modal_body = "

You do not have any domains in your High Fidelity account." + + "

Go to your domains page to create a new one. Once your domain is created re-open this dialog to select it.

" + } + + + bootbox.dialog({ + title: "Choose matching domain", + message: modal_body, + buttons: modal_buttons + }) + }) + + } else { + bootbox.alert({ + message: "You must have an access token to query your High Fidelity domains.

" + + "Please follow the instructions on the settings page to add an access token.", + title: "Access token required" + }) + } } \ No newline at end of file From 541c3c6da81f396667d49b30fe2ed008de52d7ff Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 11:02:47 -0700 Subject: [PATCH 35/58] handle style of button while domains are loading --- domain-server/resources/web/css/style.css | 2 +- domain-server/resources/web/js/settings.js | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/domain-server/resources/web/css/style.css b/domain-server/resources/web/css/style.css index a75b1a23ae..60f493593a 100644 --- a/domain-server/resources/web/css/style.css +++ b/domain-server/resources/web/css/style.css @@ -73,4 +73,4 @@ span.port { #small-save-button { width: 100%; margin-bottom: 15px; -} \ No newline at end of file +} diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index 76b2e52078..e7db8291ed 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -236,6 +236,8 @@ function chooseFromHighFidelityDomains(clickedButton) { if (Settings.initialValues.metaverse.access_token) { // add a spinner to the choose button + clickedButton.html("Loading domains...") + clickedButton.attr('disabled', 'disabled') // get a list of user domains from data-web data_web_domains_url = "https://data.highfidelity.io/api/v1/domains?access_token=" @@ -281,6 +283,10 @@ function chooseFromHighFidelityDomains(clickedButton) { message: modal_body, buttons: modal_buttons }) + + // remove the spinner from the choose button + clickedButton.html("Choose from my domains") + clickedButton.removeAttr('disabled') }) } else { From f566b42d18332d39497b9b4f98e33d9f6186a1b2 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 11:17:55 -0700 Subject: [PATCH 36/58] make My Tokens link open in a new tab --- domain-server/resources/describe-settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index cec1aabe75..e2a3e32c46 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -6,7 +6,7 @@ { "name": "access_token", "label": "Access Token", - "help": "This is an access token generated on the My Tokens page of your High Fidelity account.
Generate a token with the 'domains' scope and paste it here.
This is required to associate this domain-server with a domain in your account." + "help": "This is an access token generated on the My Tokens page of your High Fidelity account.
Generate a token with the 'domains' scope and paste it here.
This is required to associate this domain-server with a domain in your account." }, { "name": "id", From dbc81fcdca0ca2ebc03f9440f08025ae25938ee6 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 30 Sep 2014 11:19:45 -0700 Subject: [PATCH 37/58] Update audio injector volume every frame --- libraries/audio/src/AudioInjector.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index d5e1c59d7a..31c135fd58 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -96,6 +96,7 @@ void AudioInjector::injectAudio() { packetStream << radius; // pack 255 for attenuation byte + int volumeOptionOffset = injectAudioPacket.size(); quint8 volume = MAX_INJECTOR_VOLUME * _options.getVolume(); packetStream << volume; @@ -118,6 +119,8 @@ void AudioInjector::injectAudio() { memcpy(injectAudioPacket.data() + orientationOptionOffset, &_options.getOrientation(), sizeof(_options.getOrientation())); + volume = MAX_INJECTOR_VOLUME * _options.getVolume(); + memcpy(injectAudioPacket.data() + volumeOptionOffset, &volume, sizeof(volume)); // resize the QByteArray to the right size injectAudioPacket.resize(numPreAudioDataBytes + bytesToCopy); From 26c2aece7a16e5c81310aaaaefe915eeff046ad8 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 11:21:35 -0700 Subject: [PATCH 38/58] fix target blank link from domain-server settings --- domain-server/resources/describe-settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index e2a3e32c46..364743110d 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -6,7 +6,7 @@ { "name": "access_token", "label": "Access Token", - "help": "This is an access token generated on the My Tokens page of your High Fidelity account.
Generate a token with the 'domains' scope and paste it here.
This is required to associate this domain-server with a domain in your account." + "help": "This is an access token generated on the My Tokens page of your High Fidelity account.
Generate a token with the 'domains' scope and paste it here.
This is required to associate this domain-server with a domain in your account." }, { "name": "id", From 1afdd3457724be589a9c133a711f93501391f464 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 30 Sep 2014 11:23:25 -0700 Subject: [PATCH 39/58] Added custom audio offset and volume to Player --- libraries/avatars/src/Player.cpp | 59 ++++++++++++++++++++++---------- libraries/avatars/src/Player.h | 16 +++++---- 2 files changed, 50 insertions(+), 25 deletions(-) diff --git a/libraries/avatars/src/Player.cpp b/libraries/avatars/src/Player.cpp index 2540d7d004..224f613497 100644 --- a/libraries/avatars/src/Player.cpp +++ b/libraries/avatars/src/Player.cpp @@ -17,13 +17,16 @@ #include "AvatarData.h" #include "Player.h" +static const int INVALID_FRAME = -1; + Player::Player(AvatarData* avatar) : - _recording(new Recording()), - _currentFrame(-1), - _frameInterpolationFactor(0.0f), - _pausedFrame(-1), - _timerOffset(0), _avatar(avatar), + _recording(new Recording()), + _currentFrame(INVALID_FRAME), + _frameInterpolationFactor(0.0f), + _pausedFrame(INVALID_FRAME), + _timerOffset(0), + _audioOffset(0), _audioThread(NULL), _playFromCurrentPosition(true), _loop(false), @@ -33,8 +36,6 @@ Player::Player(AvatarData* avatar) : _useSkeletonURL(true) { _timer.invalidate(); - _options.setLoop(false); - _options.setVolume(1.0f); } bool Player::isPlaying() const { @@ -42,7 +43,7 @@ bool Player::isPlaying() const { } bool Player::isPaused() const { - return (_pausedFrame != -1); + return (_pausedFrame != INVALID_FRAME); } qint64 Player::elapsed() const { @@ -122,7 +123,7 @@ void Player::startPlaying() { _timer.start(); setCurrentFrame(_pausedFrame); - _pausedFrame = -1; + _pausedFrame = INVALID_FRAME; } } @@ -130,7 +131,7 @@ void Player::stopPlaying() { if (!isPlaying()) { return; } - _pausedFrame = -1; + _pausedFrame = INVALID_FRAME; _timer.invalidate(); cleanupAudioThread(); _avatar->clearJointsData(); @@ -201,12 +202,12 @@ void Player::loadFromFile(const QString& file) { } readRecordingFromFile(_recording, file); - _pausedFrame = -1; + _pausedFrame = INVALID_FRAME; } void Player::loadRecording(RecordingPointer recording) { _recording = recording; - _pausedFrame = -1; + _pausedFrame = INVALID_FRAME; } void Player::play() { @@ -253,6 +254,9 @@ void Player::play() { HeadData* head = const_cast(_avatar->getHeadData()); if (head) { + // Make sure fake faceshift connection doesn't get turned off + _avatar->setForceFaceshiftConnected(true); + QVector blendCoef(currentFrame.getBlendshapeCoefficients().size()); for (int i = 0; i < currentFrame.getBlendshapeCoefficients().size(); ++i) { blendCoef[i] = glm::mix(currentFrame.getBlendshapeCoefficients()[i], @@ -293,8 +297,8 @@ void Player::play() { _injector->setOptions(_options); } -void Player::setCurrentFrame(int currentFrame) { - if (_recording && (currentFrame < 0 || currentFrame >= _recording->getFrameNumber())) { +void Player::setCurrentFrame(quint64 currentFrame) { + if (_recording && currentFrame >= _recording->getFrameNumber()) { stopPlaying(); return; } @@ -306,12 +310,12 @@ void Player::setCurrentFrame(int currentFrame) { _timer.start(); setAudionInjectorPosition(); } else { - _pausedFrame = currentFrame; + _pausedFrame = _currentFrame; } } -void Player::setCurrentTime(qint64 currentTime) { - if (currentTime < 0 || currentTime >= _recording->getLength()) { +void Player::setCurrentTime(quint64 currentTime) { + if (currentTime >= _recording->getLength()) { stopPlaying(); return; } @@ -355,6 +359,18 @@ void Player::setCurrentTime(qint64 currentTime) { } } +void Player::setVolume(float volume) { + _options.setVolume(volume); + if (_injector) { + _injector->setOptions(_options); + } + qDebug() << "New volume: " << volume; +} + +void Player::setAudioOffset(int audioOffset) { + _audioOffset = audioOffset; +} + void Player::setAudionInjectorPosition() { int MSEC_PER_SEC = 1000; int SAMPLE_SIZE = 2; // 16 bits @@ -370,14 +386,19 @@ void Player::setPlayFromCurrentLocation(bool playFromCurrentLocation) { bool Player::computeCurrentFrame() { if (!isPlaying()) { - _currentFrame = -1; + _currentFrame = INVALID_FRAME; return false; } if (_currentFrame < 0) { _currentFrame = 0; } - qint64 elapsed = Player::elapsed(); + quint64 elapsed = glm::clamp(Player::elapsed() - _audioOffset, (qint64)0, (qint64)_recording->getLength()); + while(_currentFrame >= 0 && + _recording->getFrameTimestamp(_currentFrame) > elapsed) { + --_currentFrame; + } + while (_currentFrame < _recording->getFrameNumber() && _recording->getFrameTimestamp(_currentFrame) < elapsed) { ++_currentFrame; diff --git a/libraries/avatars/src/Player.h b/libraries/avatars/src/Player.h index 5db56d725a..8137acbfe7 100644 --- a/libraries/avatars/src/Player.h +++ b/libraries/avatars/src/Player.h @@ -44,8 +44,11 @@ public slots: void loadRecording(RecordingPointer recording); void play(); - void setCurrentFrame(int currentFrame); - void setCurrentTime(qint64 currentTime); + void setCurrentFrame(quint64 currentFrame); + void setCurrentTime(quint64 currentTime); + + void setVolume(float volume); + void setAudioOffset(int audioOffset); void setPlayFromCurrentLocation(bool playFromCurrentPosition); void setLoop(bool loop) { _loop = loop; } @@ -61,19 +64,20 @@ private: void setAudionInjectorPosition(); bool computeCurrentFrame(); - QElapsedTimer _timer; + AvatarData* _avatar; RecordingPointer _recording; int _currentFrame; float _frameInterpolationFactor; int _pausedFrame; + + QElapsedTimer _timer; qint64 _timerOffset; + qint64 _audioOffset; + QThread* _audioThread; QSharedPointer _injector; AudioInjectorOptions _options; - AvatarData* _avatar; - QThread* _audioThread; - RecordingContext _currentContext; bool _playFromCurrentPosition; bool _loop; From 5f95cbc10122e019b446d8095bf302a3b1ef01bf Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 30 Sep 2014 11:23:33 -0700 Subject: [PATCH 40/58] JS hooks --- libraries/avatars/src/AvatarData.cpp | 12 ++++++++++++ libraries/avatars/src/AvatarData.h | 4 ++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 126da654ae..76bb64481e 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -652,6 +652,18 @@ void AvatarData::startPlaying() { _player->startPlaying(); } +void AvatarData::setPlayerVolume(float volume) { + if (_player) { + _player->setVolume(volume); + } +} + +void AvatarData::setPlayerAudioOffset(qint64 audioOffset) { + if (_player) { + _player->setAudioOffset(audioOffset); + } +} + void AvatarData::setPlayerFrame(int frame) { if (_player) { _player->setCurrentFrame(frame); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 9b28fdc258..3436e35972 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -100,8 +100,6 @@ enum KeyState { DELETE_KEY_DOWN }; -const glm::vec3 vec3Zero(0.0f); - class QDataStream; class AttachmentData; @@ -304,6 +302,8 @@ public slots: void loadRecording(QString filename); void startPlaying(); + void setPlayerVolume(float volume); + void setPlayerAudioOffset(qint64 audioOffset); void setPlayerFrame(int frame); void setPlayerTime(qint64 time); void setPlayFromCurrentLocation(bool playFromCurrentLocation); From df5ab50703396c02357f11948f3a710acaf12eef Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 11:34:03 -0700 Subject: [PATCH 41/58] clear up domain ID selection on domain settings page --- domain-server/resources/web/js/settings.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index e7db8291ed..17365a27a1 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -122,9 +122,9 @@ function reloadSettings() { } function appendDomainSelectionModal() { - var metaverseFormGroup = $("[name='metaverse.id']").parent('.form-group'); - var chooseButton = ""; - metaverseFormGroup.append(chooseButton); + var metaverseInput = $("[name='metaverse.id']"); + var chooseButton = $(""); + metaverseInput.after(chooseButton); } var SETTINGS_ERROR_MESSAGE = "There was a problem saving domain settings. Please try again!"; From 39ee62608b213ab6509b5f3160cb157f2695e422 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 11:35:53 -0700 Subject: [PATCH 42/58] ensure HAVE_SIXENSE is defined to define _sixenseLibrary --- interface/src/devices/SixenseManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index 28b125b6da..c3d694d06c 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -45,7 +45,7 @@ SixenseManager& SixenseManager::getInstance() { } SixenseManager::SixenseManager() : -#ifdef __APPLE__ +#if defined(HAVE_SIXENSE) && defined(__APPLE__) _sixenseLibrary(NULL), #endif _isInitialized(false), From 4e7bf0487b5ad90d1776696619d0cc03cac716dd Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 30 Sep 2014 12:50:50 -0700 Subject: [PATCH 43/58] Add attenuation setting on DS page --- assignment-client/src/audio/AudioMixer.cpp | 18 ++++++++++++++++-- assignment-client/src/audio/AudioMixer.h | 1 + domain-server/resources/describe-settings.json | 8 ++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 3670653493..133e7a1bcd 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -62,6 +62,7 @@ #include "AudioMixer.h" const float LOUDNESS_TO_DISTANCE_RATIO = 0.00001f; +const float DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE = 0.18; const QString AUDIO_MIXER_LOGGING_TARGET_NAME = "audio-mixer"; @@ -82,6 +83,7 @@ AudioMixer::AudioMixer(const QByteArray& packet) : _trailingSleepRatio(1.0f), _minAudibilityThreshold(LOUDNESS_TO_DISTANCE_RATIO / 2.0f), _performanceThrottlingRatio(0.0f), + _attenuationPerDoublingInDistance(DEFAULT_ATTENUATION_PER_DOUBLING_IN_DISTANCE), _numStatFrames(0), _sumListeners(0), _sumMixes(0), @@ -104,7 +106,6 @@ AudioMixer::~AudioMixer() { } const float ATTENUATION_BEGINS_AT_DISTANCE = 1.0f; -const float ATTENUATION_AMOUNT_PER_DOUBLING_IN_DISTANCE = 0.18f; const float RADIUS_OF_HEAD = 0.076f; int AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData* listenerNodeData, @@ -210,7 +211,7 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData* l if (shouldDistanceAttenuate && (distanceBetween >= ATTENUATION_BEGINS_AT_DISTANCE)) { // calculate the distance coefficient using the distance to this node float distanceCoefficient = 1 - (logf(distanceBetween / ATTENUATION_BEGINS_AT_DISTANCE) / logf(2.0f) - * ATTENUATION_AMOUNT_PER_DOUBLING_IN_DISTANCE); + * _attenuationPerDoublingInDistance); if (distanceCoefficient < 0) { distanceCoefficient = 0; @@ -740,6 +741,19 @@ void AudioMixer::run() { qDebug() << "Buffers inside this zone will not be attenuated inside a box with center at" << QString("%1, %2, %3").arg(destinationCenter.x).arg(destinationCenter.y).arg(destinationCenter.z); } + + const QString ATTENATION_PER_DOULING_IN_DISTANCE = "attenuation-per-doubling-in-distance"; + qDebug() << "contains:" << audioGroupObject.contains(ATTENATION_PER_DOULING_IN_DISTANCE); + if (audioGroupObject[ATTENATION_PER_DOULING_IN_DISTANCE].isString()) { + qDebug() << "isString"; + bool ok = false; + float attenuation = audioGroupObject[ATTENATION_PER_DOULING_IN_DISTANCE].toString().toFloat(&ok); + + if (ok) { + _attenuationPerDoublingInDistance = attenuation; + qDebug() << "Attenuation per doubling in distance changed to" << _attenuationPerDoublingInDistance; + } + } } int nextFrame = 0; diff --git a/assignment-client/src/audio/AudioMixer.h b/assignment-client/src/audio/AudioMixer.h index 6c25fe21d9..4d08d480f8 100644 --- a/assignment-client/src/audio/AudioMixer.h +++ b/assignment-client/src/audio/AudioMixer.h @@ -69,6 +69,7 @@ private: float _trailingSleepRatio; float _minAudibilityThreshold; float _performanceThrottlingRatio; + float _attenuationPerDoublingInDistance; int _numStatFrames; int _sumListeners; int _sumMixes; diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 19c293b610..afb287d06b 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -51,6 +51,14 @@ "help": "Boxes for source and listener (corner x, corner y, corner z, size x, size y, size z, corner x, corner y, corner z, size x, size y, size z)", "placeholder": "no zone" }, + { + "name": "attenuation-per-doubling-in-distance", + "label": "Attenuattion per doubling in distance", + "help": "Factor between 0.0 and 1.0", + "placeholder": "0.18", + "default": "0.18", + "advanced": true + }, { "name": "dynamic-jitter-buffer", "type": "checkbox", From b571fb86ae6bd08c4b00bcf2f081ce732e7ab504 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 30 Sep 2014 12:53:33 -0700 Subject: [PATCH 44/58] Changed attenuation setting help --- domain-server/resources/describe-settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index afb287d06b..86d4da684b 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -54,7 +54,7 @@ { "name": "attenuation-per-doubling-in-distance", "label": "Attenuattion per doubling in distance", - "help": "Factor between 0.0 and 1.0", + "help": "Factor between 0.0 and 1.0 (0.0: No attenuation, 1.0: extreme attenuation)", "placeholder": "0.18", "default": "0.18", "advanced": true From 4c34571570044c6c9208eabde883bcca6e4b1fc1 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 30 Sep 2014 12:54:58 -0700 Subject: [PATCH 45/58] Removed debug --- assignment-client/src/audio/AudioMixer.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 133e7a1bcd..ce373f4d33 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -743,12 +743,9 @@ void AudioMixer::run() { } const QString ATTENATION_PER_DOULING_IN_DISTANCE = "attenuation-per-doubling-in-distance"; - qDebug() << "contains:" << audioGroupObject.contains(ATTENATION_PER_DOULING_IN_DISTANCE); if (audioGroupObject[ATTENATION_PER_DOULING_IN_DISTANCE].isString()) { - qDebug() << "isString"; bool ok = false; float attenuation = audioGroupObject[ATTENATION_PER_DOULING_IN_DISTANCE].toString().toFloat(&ok); - if (ok) { _attenuationPerDoublingInDistance = attenuation; qDebug() << "Attenuation per doubling in distance changed to" << _attenuationPerDoublingInDistance; From eed6e2e8f657e57a934c3604224121ddb3bb3e5f Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 30 Sep 2014 22:11:21 +0200 Subject: [PATCH 46/58] - Edit -> Model List menu option - Combo items can be JS objects now, write a toString() function for each JS object to describe them --- examples/editModels.js | 272 ++++++++++-------- .../scripting/WindowScriptingInterface.cpp | 28 +- 2 files changed, 172 insertions(+), 128 deletions(-) diff --git a/examples/editModels.js b/examples/editModels.js index c47c497a78..b734864b84 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -2745,7 +2745,7 @@ function setupModelMenus() { } Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." }); - + Menu.addMenuItem({ menuName: "Edit", menuItemName: "Model List", afterItem: "Models" }); Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" }); Menu.addMenuItem({ menuName: "File", menuItemName: "Export Models", shortcutKey: "CTRL+META+E", afterItem: "Models" }); Menu.addMenuItem({ menuName: "File", menuItemName: "Import Models", shortcutKey: "CTRL+META+I", afterItem: "Export Models" }); @@ -2796,6 +2796,128 @@ var dimensionY; var dimensionZ; var rescalePercentage; +function showPropertiesForm() { + propertiesForEditedEntity = Entities.getEntityProperties(editModelID); + var properties = propertiesForEditedEntity; + + var array = new Array(); + var index = 0; + var decimals = 3; + if (properties.type == "Model") { + array.push({ label: "Model URL:", value: properties.modelURL }); + index++; + array.push({ label: "Animation URL:", value: properties.animationURL }); + index++; + array.push({ label: "Animation is playing:", value: properties.animationIsPlaying }); + index++; + array.push({ label: "Animation FPS:", value: properties.animationFPS }); + index++; + array.push({ label: "Animation Frame:", value: properties.animationFrameIndex }); + index++; + } + array.push({ label: "Position:", type: "header" }); + index++; + array.push({ label: "X:", value: properties.position.x.toFixed(decimals) }); + index++; + array.push({ label: "Y:", value: properties.position.y.toFixed(decimals) }); + index++; + array.push({ label: "Z:", value: properties.position.z.toFixed(decimals) }); + index++; + + array.push({ label: "Registration X:", value: properties.registrationPoint.x.toFixed(decimals) }); + index++; + array.push({ label: "Registration Y:", value: properties.registrationPoint.y.toFixed(decimals) }); + index++; + array.push({ label: "Registration Z:", value: properties.registrationPoint.z.toFixed(decimals) }); + index++; + + array.push({ label: "Rotation:", type: "header" }); + index++; + var angles = Quat.safeEulerAngles(properties.rotation); + array.push({ label: "Pitch:", value: angles.x.toFixed(decimals) }); + index++; + array.push({ label: "Yaw:", value: angles.y.toFixed(decimals) }); + index++; + array.push({ label: "Roll:", value: angles.z.toFixed(decimals) }); + index++; + + array.push({ label: "Dimensions:", type: "header" }); + index++; + array.push({ label: "Width:", value: properties.dimensions.x.toFixed(decimals) }); + dimensionX = index; + index++; + array.push({ label: "Height:", value: properties.dimensions.y.toFixed(decimals) }); + dimensionY = index; + index++; + array.push({ label: "Depth:", value: properties.dimensions.z.toFixed(decimals) }); + dimensionZ = index; + index++; + array.push({ label: "", type: "inlineButton", buttonLabel: "Reset to Natural Dimensions", name: "resetDimensions" }); + index++; + array.push({ label: "Rescale Percentage:", value: 100 }); + rescalePercentage = index; + index++; + array.push({ label: "", type: "inlineButton", buttonLabel: "Rescale", name: "rescaleDimensions" }); + index++; + + array.push({ label: "Velocity:", type: "header" }); + index++; + array.push({ label: "Linear X:", value: properties.velocity.x.toFixed(decimals) }); + index++; + array.push({ label: "Linear Y:", value: properties.velocity.y.toFixed(decimals) }); + index++; + array.push({ label: "Linear Z:", value: properties.velocity.z.toFixed(decimals) }); + index++; + array.push({ label: "Linear Damping:", value: properties.damping.toFixed(decimals) }); + index++; + array.push({ label: "Angular Pitch:", value: properties.angularVelocity.x.toFixed(decimals) }); + index++; + array.push({ label: "Angular Yaw:", value: properties.angularVelocity.y.toFixed(decimals) }); + index++; + array.push({ label: "Angular Roll:", value: properties.angularVelocity.z.toFixed(decimals) }); + index++; + array.push({ label: "Angular Damping:", value: properties.angularDamping.toFixed(decimals) }); + index++; + + array.push({ label: "Gravity X:", value: properties.gravity.x.toFixed(decimals) }); + index++; + array.push({ label: "Gravity Y:", value: properties.gravity.y.toFixed(decimals) }); + index++; + array.push({ label: "Gravity Z:", value: properties.gravity.z.toFixed(decimals) }); + index++; + + array.push({ label: "Collisions:", type: "header" }); + index++; + array.push({ label: "Mass:", value: properties.mass.toFixed(decimals) }); + index++; + array.push({ label: "Ignore for Collisions:", value: properties.ignoreForCollisions }); + index++; + array.push({ label: "Collisions Will Move:", value: properties.collisionsWillMove }); + index++; + + array.push({ label: "Lifetime:", value: properties.lifetime.toFixed(decimals) }); + index++; + + array.push({ label: "Visible:", value: properties.visible }); + index++; + + if (properties.type == "Box" || properties.type == "Sphere") { + array.push({ label: "Color:", type: "header" }); + index++; + array.push({ label: "Red:", value: properties.color.red }); + index++; + array.push({ label: "Green:", value: properties.color.green }); + index++; + array.push({ label: "Blue:", value: properties.color.blue }); + index++; + } + array.push({ button: "Cancel" }); + index++; + + editEntityFormArray = array; + Window.nonBlockingForm("Edit Properties", array); +} + function handeMenuEvent(menuItem) { print("menuItemEvent() in JS... menuItem=" + menuItem); if (menuItem == "Delete") { @@ -2823,6 +2945,33 @@ function handeMenuEvent(menuItem) { } else { print(" Delete Entity.... not holding..."); } + } else if (menuItem == "Model List") { + var models = new Array(); + models = Entities.findEntities(MyAvatar.position, Number.MAX_VALUE); + for (var i = 0; i < models.length; i++) { + models[i].properties = Entities.getEntityProperties(models[i]); + models[i].toString = function() { + var modelname = decodeURIComponent( + this.properties.modelURL.indexOf("/") != -1 ? + this.properties.modelURL.substring(this.properties.modelURL.lastIndexOf("/") + 1) : + this.properties.modelURL); + return "[" + this.properties.type + "] " + modelname; + }; + } + var form = [{label: "Model: ", options: models}]; + form.push({label: "Action: ", options: ["Properties", "Delete", "Teleport"]}); + form.push({ button: "Cancel" }); + if (Window.form("Model List", form)) { + var selectedModel = form[0].value; + if (form[1].value == "Properties") { + editModelID = selectedModel; + showPropertiesForm(); + } else if (form[1].value == "Delete") { + Entities.deleteEntity(selectedModel); + } else if (form[1].value == "Teleport") { + MyAvatar.position = selectedModel.properties.position; + } + } } else if (menuItem == "Edit Properties...") { editModelID = -1; if (leftController.grabbing) { @@ -2839,126 +2988,7 @@ function handeMenuEvent(menuItem) { } if (editModelID != -1) { print(" Edit Properties.... about to edit properties..."); - - propertiesForEditedEntity = Entities.getEntityProperties(editModelID); - var properties = propertiesForEditedEntity; - - var array = new Array(); - var index = 0; - var decimals = 3; - if (properties.type == "Model") { - array.push({ label: "Model URL:", value: properties.modelURL }); - index++; - array.push({ label: "Animation URL:", value: properties.animationURL }); - index++; - array.push({ label: "Animation is playing:", value: properties.animationIsPlaying }); - index++; - array.push({ label: "Animation FPS:", value: properties.animationFPS }); - index++; - array.push({ label: "Animation Frame:", value: properties.animationFrameIndex }); - index++; - } - array.push({ label: "Position:", type: "header" }); - index++; - array.push({ label: "X:", value: properties.position.x.toFixed(decimals) }); - index++; - array.push({ label: "Y:", value: properties.position.y.toFixed(decimals) }); - index++; - array.push({ label: "Z:", value: properties.position.z.toFixed(decimals) }); - index++; - - array.push({ label: "Registration X:", value: properties.registrationPoint.x.toFixed(decimals) }); - index++; - array.push({ label: "Registration Y:", value: properties.registrationPoint.y.toFixed(decimals) }); - index++; - array.push({ label: "Registration Z:", value: properties.registrationPoint.z.toFixed(decimals) }); - index++; - - array.push({ label: "Rotation:", type: "header" }); - index++; - var angles = Quat.safeEulerAngles(properties.rotation); - array.push({ label: "Pitch:", value: angles.x.toFixed(decimals) }); - index++; - array.push({ label: "Yaw:", value: angles.y.toFixed(decimals) }); - index++; - array.push({ label: "Roll:", value: angles.z.toFixed(decimals) }); - index++; - - array.push({ label: "Dimensions:", type: "header" }); - index++; - array.push({ label: "Width:", value: properties.dimensions.x.toFixed(decimals) }); - dimensionX = index; - index++; - array.push({ label: "Height:", value: properties.dimensions.y.toFixed(decimals) }); - dimensionY = index; - index++; - array.push({ label: "Depth:", value: properties.dimensions.z.toFixed(decimals) }); - dimensionZ = index; - index++; - array.push({ label: "", type: "inlineButton", buttonLabel: "Reset to Natural Dimensions", name: "resetDimensions" }); - index++; - array.push({ label: "Rescale Percentage:", value: 100 }); - rescalePercentage = index; - index++; - array.push({ label: "", type: "inlineButton", buttonLabel: "Rescale", name: "rescaleDimensions" }); - index++; - - array.push({ label: "Velocity:", type: "header" }); - index++; - array.push({ label: "Linear X:", value: properties.velocity.x.toFixed(decimals) }); - index++; - array.push({ label: "Linear Y:", value: properties.velocity.y.toFixed(decimals) }); - index++; - array.push({ label: "Linear Z:", value: properties.velocity.z.toFixed(decimals) }); - index++; - array.push({ label: "Linear Damping:", value: properties.damping.toFixed(decimals) }); - index++; - array.push({ label: "Angular Pitch:", value: properties.angularVelocity.x.toFixed(decimals) }); - index++; - array.push({ label: "Angular Yaw:", value: properties.angularVelocity.y.toFixed(decimals) }); - index++; - array.push({ label: "Angular Roll:", value: properties.angularVelocity.z.toFixed(decimals) }); - index++; - array.push({ label: "Angular Damping:", value: properties.angularDamping.toFixed(decimals) }); - index++; - - array.push({ label: "Gravity X:", value: properties.gravity.x.toFixed(decimals) }); - index++; - array.push({ label: "Gravity Y:", value: properties.gravity.y.toFixed(decimals) }); - index++; - array.push({ label: "Gravity Z:", value: properties.gravity.z.toFixed(decimals) }); - index++; - - array.push({ label: "Collisions:", type: "header" }); - index++; - array.push({ label: "Mass:", value: properties.mass.toFixed(decimals) }); - index++; - array.push({ label: "Ignore for Collisions:", value: properties.ignoreForCollisions }); - index++; - array.push({ label: "Collisions Will Move:", value: properties.collisionsWillMove }); - index++; - - array.push({ label: "Lifetime:", value: properties.lifetime.toFixed(decimals) }); - index++; - - array.push({ label: "Visible:", value: properties.visible }); - index++; - - if (properties.type == "Box" || properties.type == "Sphere") { - array.push({ label: "Color:", type: "header" }); - index++; - array.push({ label: "Red:", value: properties.color.red }); - index++; - array.push({ label: "Green:", value: properties.color.green }); - index++; - array.push({ label: "Blue:", value: properties.color.blue }); - index++; - } - array.push({ button: "Cancel" }); - index++; - - editEntityFormArray = array; - Window.nonBlockingForm("Edit Properties", array); + showPropertiesForm(editModelID); } } else if (menuItem == "Paste Models") { modelImporter.paste(); diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 913655195d..4f0020ee61 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -265,7 +265,11 @@ QScriptValue WindowScriptingInterface::doPeekNonBlockingFormResult(QScriptValue _form.setProperty(i, item); } else if (item.property("options").isArray()) { c += 1; - item.setProperty("value", _combos.at(c)->currentText()); + item.setProperty("value", + _combos.at(c)->currentIndex() < item.property("options").property("length").toInt32() ? + item.property("options").property(_combos.at(c)->currentIndex()) : + array.engine()->undefinedValue() + ); _form.setProperty(i, item); } else { e += 1; @@ -318,7 +322,11 @@ QScriptValue WindowScriptingInterface::doGetNonBlockingFormResult(QScriptValue a _form.setProperty(i, item); } else if (item.property("options").isArray()) { c += 1; - item.setProperty("value", _combos.at(c)->currentText()); + item.setProperty("value", + _combos.at(c)->currentIndex() < item.property("options").property("length").toInt32() ? + item.property("options").property(_combos.at(c)->currentIndex()) : + array.engine()->undefinedValue() + ); _form.setProperty(i, item); } else { e += 1; @@ -349,6 +357,7 @@ QScriptValue WindowScriptingInterface::doGetNonBlockingFormResult(QScriptValue a _form = QScriptValue(); _edits.clear(); _directories.clear(); + _combos.clear(); array = _form; return (_formResult == QDialog::Accepted); @@ -391,8 +400,12 @@ QScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptVal form.setProperty(i, item); } else if (item.property("options").isArray()) { c += 1; - item.setProperty("value", _combos.at(c)->currentText()); - _form.setProperty(i, item); + item.setProperty("value", + _combos.at(c)->currentIndex() < item.property("options").property("length").toInt32() ? + item.property("options").property(_combos.at(c)->currentIndex()) : + form.engine()->undefinedValue() + ); + form.setProperty(i, item); } else { e += 1; bool ok = true; @@ -418,6 +431,7 @@ QScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptVal } delete editDialog; + _combos.clear(); _edits.clear(); _directories.clear(); return (result == QDialog::Accepted); @@ -498,9 +512,9 @@ QDialog* WindowScriptingInterface::createForm(const QString& title, QScriptValue } else if (item.property("options").isArray()) { QComboBox* combo = new QComboBox(); combo->setMinimumWidth(200); - QStringList options = item.property("options").toVariant().toStringList(); - for (QStringList::const_iterator it = options.begin(); it != options.end(); it += 1) { - combo->addItem(*it); + qint32 options_count = item.property("options").property("length").toInt32();// .toJsonArray(); + for (qint32 i = 0; i < options_count; i++) { + combo->addItem(item.property("options").property(i).toString()); } _combos.push_back(combo); formLayout->addRow(new QLabel(item.property("label").toString()), combo); From 9ba2a9736c3155aa67c3306170bd58052d7d3e0d Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 30 Sep 2014 22:23:40 +0200 Subject: [PATCH 47/58] style --- examples/editModels.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/editModels.js b/examples/editModels.js index b734864b84..5c426c9fb3 100644 --- a/examples/editModels.js +++ b/examples/editModels.js @@ -2964,7 +2964,7 @@ function handeMenuEvent(menuItem) { if (Window.form("Model List", form)) { var selectedModel = form[0].value; if (form[1].value == "Properties") { - editModelID = selectedModel; + editModelID = selectedModel; showPropertiesForm(); } else if (form[1].value == "Delete") { Entities.deleteEntity(selectedModel); From 7f34079d8fde6fe850d3cea401d8688d521f5d2b Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 30 Sep 2014 22:31:41 +0200 Subject: [PATCH 48/58] cleared comment --- interface/src/scripting/WindowScriptingInterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 4f0020ee61..2c0226e3bc 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -512,7 +512,7 @@ QDialog* WindowScriptingInterface::createForm(const QString& title, QScriptValue } else if (item.property("options").isArray()) { QComboBox* combo = new QComboBox(); combo->setMinimumWidth(200); - qint32 options_count = item.property("options").property("length").toInt32();// .toJsonArray(); + qint32 options_count = item.property("options").property("length").toInt32(); for (qint32 i = 0; i < options_count; i++) { combo->addItem(item.property("options").property(i).toString()); } From fd21d100f6a9dd90566e53e1fa9cd22afba630c6 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 30 Sep 2014 22:37:29 +0200 Subject: [PATCH 49/58] line indention fixes --- .../scripting/WindowScriptingInterface.cpp | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 2c0226e3bc..ed6f0cf600 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -266,10 +266,10 @@ QScriptValue WindowScriptingInterface::doPeekNonBlockingFormResult(QScriptValue } else if (item.property("options").isArray()) { c += 1; item.setProperty("value", - _combos.at(c)->currentIndex() < item.property("options").property("length").toInt32() ? - item.property("options").property(_combos.at(c)->currentIndex()) : - array.engine()->undefinedValue() - ); + _combos.at(c)->currentIndex() < item.property("options").property("length").toInt32() ? + item.property("options").property(_combos.at(c)->currentIndex()) : + array.engine()->undefinedValue() + ); _form.setProperty(i, item); } else { e += 1; @@ -323,10 +323,10 @@ QScriptValue WindowScriptingInterface::doGetNonBlockingFormResult(QScriptValue a } else if (item.property("options").isArray()) { c += 1; item.setProperty("value", - _combos.at(c)->currentIndex() < item.property("options").property("length").toInt32() ? - item.property("options").property(_combos.at(c)->currentIndex()) : - array.engine()->undefinedValue() - ); + _combos.at(c)->currentIndex() < item.property("options").property("length").toInt32() ? + item.property("options").property(_combos.at(c)->currentIndex()) : + array.engine()->undefinedValue() + ); _form.setProperty(i, item); } else { e += 1; @@ -401,10 +401,10 @@ QScriptValue WindowScriptingInterface::showForm(const QString& title, QScriptVal } else if (item.property("options").isArray()) { c += 1; item.setProperty("value", - _combos.at(c)->currentIndex() < item.property("options").property("length").toInt32() ? - item.property("options").property(_combos.at(c)->currentIndex()) : - form.engine()->undefinedValue() - ); + _combos.at(c)->currentIndex() < item.property("options").property("length").toInt32() ? + item.property("options").property(_combos.at(c)->currentIndex()) : + form.engine()->undefinedValue() + ); form.setProperty(i, item); } else { e += 1; From 68c25e805ad5fd41d922f359d0c024a3fb0da686 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 30 Sep 2014 14:31:40 -0700 Subject: [PATCH 50/58] Switch int64 to int --- libraries/avatars/src/Player.cpp | 4 ++-- libraries/avatars/src/Player.h | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/avatars/src/Player.cpp b/libraries/avatars/src/Player.cpp index 224f613497..35a822f11b 100644 --- a/libraries/avatars/src/Player.cpp +++ b/libraries/avatars/src/Player.cpp @@ -297,7 +297,7 @@ void Player::play() { _injector->setOptions(_options); } -void Player::setCurrentFrame(quint64 currentFrame) { +void Player::setCurrentFrame(unsigned int currentFrame) { if (_recording && currentFrame >= _recording->getFrameNumber()) { stopPlaying(); return; @@ -314,7 +314,7 @@ void Player::setCurrentFrame(quint64 currentFrame) { } } -void Player::setCurrentTime(quint64 currentTime) { +void Player::setCurrentTime(unsigned int currentTime) { if (currentTime >= _recording->getLength()) { stopPlaying(); return; diff --git a/libraries/avatars/src/Player.h b/libraries/avatars/src/Player.h index 8137acbfe7..043fcc4a25 100644 --- a/libraries/avatars/src/Player.h +++ b/libraries/avatars/src/Player.h @@ -44,8 +44,8 @@ public slots: void loadRecording(RecordingPointer recording); void play(); - void setCurrentFrame(quint64 currentFrame); - void setCurrentTime(quint64 currentTime); + void setCurrentFrame(unsigned int currentFrame); + void setCurrentTime(unsigned int currentTime); void setVolume(float volume); void setAudioOffset(int audioOffset); @@ -71,8 +71,8 @@ private: int _pausedFrame; QElapsedTimer _timer; - qint64 _timerOffset; - qint64 _audioOffset; + int _timerOffset; + int _audioOffset; QThread* _audioThread; QSharedPointer _injector; From fed7dad2b62ca1d8742922bc0c38bbf7866cc852 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 14:36:32 -0700 Subject: [PATCH 51/58] use an auto_ptr to be able to reset the AccountManager --- domain-server/src/DomainServer.cpp | 5 +++++ libraries/networking/src/AccountManager.cpp | 11 ++++++++--- libraries/networking/src/AccountManager.h | 2 +- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index eccd52dfc1..fb475f681d 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -81,6 +81,11 @@ DomainServer::DomainServer(int argc, char* argv[]) : void DomainServer::restart() { qDebug() << "domain-server is restarting."; + + // make sure all static instances are reset + LimitedNodeList::getInstance()->reset(); + AccountManager::getInstance(true); + exit(DomainServer::EXIT_CODE_REBOOT); } diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 88e4bad7b2..015f86c3e6 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -25,9 +25,14 @@ const bool VERBOSE_HTTP_REQUEST_DEBUGGING = false; -AccountManager& AccountManager::getInstance() { - static AccountManager sharedInstance; - return sharedInstance; +AccountManager& AccountManager::getInstance(bool forceReset) { + static std::auto_ptr sharedInstance(new AccountManager()); + + if (forceReset) { + sharedInstance.reset(new AccountManager()); + } + + return *sharedInstance; } Q_DECLARE_METATYPE(OAuthAccessToken) diff --git a/libraries/networking/src/AccountManager.h b/libraries/networking/src/AccountManager.h index edccab0b75..8d1a127408 100644 --- a/libraries/networking/src/AccountManager.h +++ b/libraries/networking/src/AccountManager.h @@ -42,7 +42,7 @@ const QByteArray ACCESS_TOKEN_AUTHORIZATION_HEADER = "Authorization"; class AccountManager : public QObject { Q_OBJECT public: - static AccountManager& getInstance(); + static AccountManager& getInstance(bool forceReset = false); void authenticatedRequest(const QString& path, QNetworkAccessManager::Operation operation = QNetworkAccessManager::GetOperation, From 9950ed9f9fc723b11ec1cb08cbe9896643dafbff Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 14:57:32 -0700 Subject: [PATCH 52/58] use auto_ptr in NodeList and LimitedNodeList for cleaner mem management --- interface/src/Application.cpp | 2 ++ libraries/networking/src/LimitedNodeList.cpp | 25 ++++++++--------- libraries/networking/src/LimitedNodeList.h | 2 +- libraries/networking/src/NodeList.cpp | 29 ++++++++------------ libraries/networking/src/NodeList.h | 2 -- 5 files changed, 26 insertions(+), 34 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0e63c3dfb2..4550d3f95c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -232,6 +232,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // put the NodeList and datagram processing on the node thread NodeList* nodeList = NodeList::createInstance(NodeType::Agent, listenPort); + + qDebug() << "NL pointer is" << nodeList; nodeList->moveToThread(_nodeThread); _datagramProcessor.moveToThread(_nodeThread); diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index d42cab6210..202e3e3c8a 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -35,29 +35,26 @@ const char SOLO_NODE_TYPES[2] = { const QUrl DEFAULT_NODE_AUTH_URL = QUrl("https://data.highfidelity.io"); -LimitedNodeList* LimitedNodeList::_sharedInstance = NULL; +std::auto_ptr LimitedNodeList::_sharedInstance; LimitedNodeList* LimitedNodeList::createInstance(unsigned short socketListenPort, unsigned short dtlsPort) { - if (!_sharedInstance) { - NodeType::init(); - - _sharedInstance = new LimitedNodeList(socketListenPort, dtlsPort); + NodeType::init(); + + delete _sharedInstance.release(); + _sharedInstance = std::auto_ptr(new LimitedNodeList(socketListenPort, dtlsPort)); + + // register the SharedNodePointer meta-type for signals/slots + qRegisterMetaType(); - // register the SharedNodePointer meta-type for signals/slots - qRegisterMetaType(); - } else { - qDebug("LimitedNodeList createInstance called with existing instance."); - } - - return _sharedInstance; + return _sharedInstance.get(); } LimitedNodeList* LimitedNodeList::getInstance() { - if (!_sharedInstance) { + if (!_sharedInstance.get()) { qDebug("LimitedNodeList getInstance called before call to createInstance. Returning NULL pointer."); } - return _sharedInstance; + return _sharedInstance.get(); } diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index 337d66616e..cf33970d53 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -118,7 +118,7 @@ signals: void nodeKilled(SharedNodePointer); void publicSockAddrChanged(const HifiSockAddr& publicSockAddr); protected: - static LimitedNodeList* _sharedInstance; + static std::auto_ptr _sharedInstance; LimitedNodeList(unsigned short socketListenPort, unsigned short dtlsListenPort); LimitedNodeList(LimitedNodeList const&); // Don't implement, needed to avoid copies of singleton diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 7ae9f9ba00..c130b72c22 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -24,30 +24,25 @@ #include "SharedUtil.h" #include "UUID.h" -NodeList* NodeList::_sharedInstance = NULL; - NodeList* NodeList::createInstance(char ownerType, unsigned short socketListenPort, unsigned short dtlsPort) { - if (!_sharedInstance) { - NodeType::init(); - - _sharedInstance = new NodeList(ownerType, socketListenPort, dtlsPort); - LimitedNodeList::_sharedInstance = _sharedInstance; - - // register the SharedNodePointer meta-type for signals/slots - qRegisterMetaType(); - } else { - qDebug("NodeList createInstance called with existing instance."); - } - - return _sharedInstance; + + NodeType::init(); + + delete _sharedInstance.release(); + _sharedInstance = std::auto_ptr(new NodeList(ownerType, socketListenPort, dtlsPort)); + + // register the SharedNodePointer meta-type for signals/slots + qRegisterMetaType(); + + return static_cast(_sharedInstance.get()); } NodeList* NodeList::getInstance() { - if (!_sharedInstance) { + if (!_sharedInstance.get()) { qDebug("NodeList getInstance called before call to createInstance. Returning NULL pointer."); } - return _sharedInstance; + return static_cast(_sharedInstance.get()); } NodeList::NodeList(char newOwnerType, unsigned short socketListenPort, unsigned short dtlsListenPort) : diff --git a/libraries/networking/src/NodeList.h b/libraries/networking/src/NodeList.h index d17e56fd48..8293d0a05a 100644 --- a/libraries/networking/src/NodeList.h +++ b/libraries/networking/src/NodeList.h @@ -84,8 +84,6 @@ public slots: signals: void limitOfSilentDomainCheckInsReached(); private: - static NodeList* _sharedInstance; - NodeList(char ownerType, unsigned short socketListenPort, unsigned short dtlsListenPort); NodeList(NodeList const&); // Don't implement, needed to avoid copies of singleton void operator=(NodeList const&); // Don't implement, needed to avoid copies of singleton From cd9029bb9248222b2963a1b48532038bf7281157 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 14:59:12 -0700 Subject: [PATCH 53/58] add some debug to NodeList instance refresh --- libraries/networking/src/LimitedNodeList.cpp | 8 +++++++- libraries/networking/src/NodeList.cpp | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/libraries/networking/src/LimitedNodeList.cpp b/libraries/networking/src/LimitedNodeList.cpp index 202e3e3c8a..2c8e968375 100644 --- a/libraries/networking/src/LimitedNodeList.cpp +++ b/libraries/networking/src/LimitedNodeList.cpp @@ -40,7 +40,13 @@ std::auto_ptr LimitedNodeList::_sharedInstance; LimitedNodeList* LimitedNodeList::createInstance(unsigned short socketListenPort, unsigned short dtlsPort) { NodeType::init(); - delete _sharedInstance.release(); + if (_sharedInstance.get()) { + qDebug() << "LimitedNodeList called with existing instance." << + "Releasing auto_ptr, deleting existing instance and creating a new one."; + + delete _sharedInstance.release(); + } + _sharedInstance = std::auto_ptr(new LimitedNodeList(socketListenPort, dtlsPort)); // register the SharedNodePointer meta-type for signals/slots diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index c130b72c22..3a1ed79f77 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -28,7 +28,13 @@ NodeList* NodeList::createInstance(char ownerType, unsigned short socketListenPo NodeType::init(); - delete _sharedInstance.release(); + if (_sharedInstance.get()) { + qDebug() << "NodeList called with existing instance." << + "Releasing auto_ptr, deleting existing instance and creating a new one."; + + delete _sharedInstance.release(); + } + _sharedInstance = std::auto_ptr(new NodeList(ownerType, socketListenPort, dtlsPort)); // register the SharedNodePointer meta-type for signals/slots From 4ef2863b79b26afa0e28a6b86fb98f1a3bc1483a Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 15:01:37 -0700 Subject: [PATCH 54/58] fix setting posting for checkbox values --- domain-server/resources/web/js/settings.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/domain-server/resources/web/js/settings.js b/domain-server/resources/web/js/settings.js index 17365a27a1..fa05b1cce9 100644 --- a/domain-server/resources/web/js/settings.js +++ b/domain-server/resources/web/js/settings.js @@ -138,6 +138,8 @@ $('body').on('click', '.save-button', function(e){ // grab a JSON representation of the form via form2js var formJSON = form2js('settings-form', ".", false, cleanupFormValues, true); + console.log(formJSON); + // re-enable all inputs $("input").each(function(){ $(this).prop('disabled', false); @@ -217,7 +219,7 @@ function showRestartModal() { function cleanupFormValues(node) { if (node.type && node.type === 'checkbox') { - return { name: node.id, value: node.checked ? true : false }; + return { name: node.name, value: node.checked ? true : false }; } else { return false; } From ac4a767d60bdfc6a121d3bd8ff8646744de2afac Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 15:25:40 -0700 Subject: [PATCH 55/58] include memory for auto_ptr --- libraries/networking/src/AccountManager.cpp | 2 ++ libraries/networking/src/LimitedNodeList.h | 1 + 2 files changed, 3 insertions(+) diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index 015f86c3e6..f79b66b539 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include #include #include diff --git a/libraries/networking/src/LimitedNodeList.h b/libraries/networking/src/LimitedNodeList.h index cf33970d53..b34845719c 100644 --- a/libraries/networking/src/LimitedNodeList.h +++ b/libraries/networking/src/LimitedNodeList.h @@ -14,6 +14,7 @@ #include #include +#include #ifndef _WIN32 #include // not on windows, not needed for mac or windows From 7f2008161d10e8e84489d8c74d5d4f16145e669d Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 30 Sep 2014 17:25:19 -0700 Subject: [PATCH 56/58] remove a debug line that slipped through the cracks --- interface/src/Application.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4550d3f95c..0e63c3dfb2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -232,8 +232,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // put the NodeList and datagram processing on the node thread NodeList* nodeList = NodeList::createInstance(NodeType::Agent, listenPort); - - qDebug() << "NL pointer is" << nodeList; nodeList->moveToThread(_nodeThread); _datagramProcessor.moveToThread(_nodeThread); From 56acc86f4f0514450e16c1a80bd0b3b32c63a85d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 30 Sep 2014 21:20:37 -0700 Subject: [PATCH 57/58] Missed some qints --- libraries/avatars/src/AvatarData.cpp | 6 +++--- libraries/avatars/src/AvatarData.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 76bb64481e..ef7083e3bf 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -658,19 +658,19 @@ void AvatarData::setPlayerVolume(float volume) { } } -void AvatarData::setPlayerAudioOffset(qint64 audioOffset) { +void AvatarData::setPlayerAudioOffset(int audioOffset) { if (_player) { _player->setAudioOffset(audioOffset); } } -void AvatarData::setPlayerFrame(int frame) { +void AvatarData::setPlayerFrame(unsigned int frame) { if (_player) { _player->setCurrentFrame(frame); } } -void AvatarData::setPlayerTime(qint64 time) { +void AvatarData::setPlayerTime(unsigned int time) { if (_player) { _player->setCurrentTime(time); } diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 3436e35972..1fd4052974 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -303,9 +303,9 @@ public slots: void loadRecording(QString filename); void startPlaying(); void setPlayerVolume(float volume); - void setPlayerAudioOffset(qint64 audioOffset); - void setPlayerFrame(int frame); - void setPlayerTime(qint64 time); + void setPlayerAudioOffset(int audioOffset); + void setPlayerFrame(unsigned int frame); + void setPlayerTime(unsigned int time); void setPlayFromCurrentLocation(bool playFromCurrentLocation); void setPlayerLoop(bool loop); void setPlayerUseDisplayName(bool useDisplayName); From f1de2ac937643bf80f86af2e130aae958b99be50 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 1 Oct 2014 09:00:24 -0700 Subject: [PATCH 58/58] rename jquery for easier updating in domain-server --- domain-server/resources/web/assignment/index.shtml | 2 +- domain-server/resources/web/footer.html | 2 +- .../resources/web/js/{jquery-2.1.1.min.js => jquery.min.js} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename domain-server/resources/web/js/{jquery-2.1.1.min.js => jquery.min.js} (100%) diff --git a/domain-server/resources/web/assignment/index.shtml b/domain-server/resources/web/assignment/index.shtml index 27c84be985..b8f4fbb637 100644 --- a/domain-server/resources/web/assignment/index.shtml +++ b/domain-server/resources/web/assignment/index.shtml @@ -6,7 +6,7 @@
- +
diff --git a/domain-server/resources/web/footer.html b/domain-server/resources/web/footer.html index 199a835cf1..4ab3ed0b31 100644 --- a/domain-server/resources/web/footer.html +++ b/domain-server/resources/web/footer.html @@ -1,4 +1,4 @@
- + \ No newline at end of file diff --git a/domain-server/resources/web/js/jquery-2.1.1.min.js b/domain-server/resources/web/js/jquery.min.js similarity index 100% rename from domain-server/resources/web/js/jquery-2.1.1.min.js rename to domain-server/resources/web/js/jquery.min.js