From 35f27313baeadb9ca3312f1c30ed55d84ac0c50d Mon Sep 17 00:00:00 2001 From: humbletim Date: Fri, 23 Jun 2017 12:05:44 -0400 Subject: [PATCH 01/52] persist command history to data folder; fix warning message color --- interface/src/ui/JSConsole.cpp | 32 ++++++++++++++++++++++++-------- interface/src/ui/JSConsole.h | 1 + 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index 79314ce49a..820ed4207d 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -23,13 +23,14 @@ #include "ScriptHighlighting.h" const int NO_CURRENT_HISTORY_COMMAND = -1; -const int MAX_HISTORY_SIZE = 64; +const int MAX_HISTORY_SIZE = 256; +const QString HISTORY_FILENAME = "JSConsole.history.txt"; const QString COMMAND_STYLE = "color: #266a9b;"; const QString RESULT_SUCCESS_STYLE = "color: #677373;"; const QString RESULT_INFO_STYLE = "color: #223bd1;"; -const QString RESULT_WARNING_STYLE = "color: #d13b22;"; +const QString RESULT_WARNING_STYLE = "color: #999922;"; const QString RESULT_ERROR_STYLE = "color: #d13b22;"; const QString GUTTER_PREVIOUS_COMMAND = "<"; @@ -37,14 +38,26 @@ const QString GUTTER_ERROR = "X"; const QString JSConsole::_consoleFileName { "about:console" }; +QList _readLines(const QString& filename) { + QFile file(filename); + file.open(QFile::ReadOnly); + return QTextStream(&file).readAll().split("\r\n"); +} + +void _writeLines(const QString& filename, const QList& lines) { + QFile file(filename); + file.open(QFile::WriteOnly); + QTextStream(&file) << lines.join("\r\n"); +} + JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : QWidget(parent), _ui(new Ui::Console), _currentCommandInHistory(NO_CURRENT_HISTORY_COMMAND), - _commandHistory(), + _savedHistoryFilename(QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + HISTORY_FILENAME), + _commandHistory(_readLines(_savedHistoryFilename)), _ownScriptEngine(scriptEngine == NULL), _scriptEngine(NULL) { - _ui->setupUi(this); _ui->promptTextEdit->setLineWrapMode(QTextEdit::NoWrap); _ui->promptTextEdit->setWordWrapMode(QTextOption::NoWrap); @@ -100,9 +113,12 @@ void JSConsole::setScriptEngine(ScriptEngine* scriptEngine) { } void JSConsole::executeCommand(const QString& command) { - _commandHistory.prepend(command); - if (_commandHistory.length() > MAX_HISTORY_SIZE) { - _commandHistory.removeLast(); + if (_commandHistory.constFirst() != command) { + _commandHistory.prepend(command); + if (_commandHistory.length() > MAX_HISTORY_SIZE) { + _commandHistory.removeLast(); + } + _writeLines(_savedHistoryFilename, _commandHistory); } _ui->promptTextEdit->setDisabled(true); @@ -181,7 +197,7 @@ bool JSConsole::eventFilter(QObject* sender, QEvent* event) { // a new QTextBlock isn't created. keyEvent->setModifiers(keyEvent->modifiers() & ~Qt::ShiftModifier); } else { - QString command = _ui->promptTextEdit->toPlainText().trimmed(); + QString command = _ui->promptTextEdit->toPlainText().replace("\r\n","\n").trimmed(); if (!command.isEmpty()) { QTextCursor cursor = _ui->promptTextEdit->textCursor(); diff --git a/interface/src/ui/JSConsole.h b/interface/src/ui/JSConsole.h index 864f847071..59280f65aa 100644 --- a/interface/src/ui/JSConsole.h +++ b/interface/src/ui/JSConsole.h @@ -63,6 +63,7 @@ private: QFutureWatcher _executeWatcher; Ui::Console* _ui; int _currentCommandInHistory; + QString _savedHistoryFilename; QList _commandHistory; // Keeps track if the script engine is created inside the JSConsole bool _ownScriptEngine; From 5abd254a5893c7f10b1e1e9462ad1964d2f27a0c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 26 Jun 2017 15:58:14 +1200 Subject: [PATCH 02/52] Bail in Neuron plugin update if plugin not enabled --- plugins/hifiNeuron/src/NeuronPlugin.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/plugins/hifiNeuron/src/NeuronPlugin.cpp b/plugins/hifiNeuron/src/NeuronPlugin.cpp index 93e7da028f..4e27777628 100644 --- a/plugins/hifiNeuron/src/NeuronPlugin.cpp +++ b/plugins/hifiNeuron/src/NeuronPlugin.cpp @@ -367,6 +367,12 @@ void NeuronPlugin::init() { auto preferences = DependencyManager::get(); static const QString NEURON_PLUGIN { "Perception Neuron" }; + { + auto getter = [this]()->bool { return _enabled; }; + auto setter = [this](bool value) { _enabled = value; saveSettings(); }; + auto preference = new CheckPreference(NEURON_PLUGIN, "Enabled", getter, setter); + preferences->addPreference(preference); + } { auto getter = [this]()->QString { return _serverAddress; }; auto setter = [this](const QString& value) { _serverAddress = value; saveSettings(); }; @@ -387,12 +393,6 @@ void NeuronPlugin::init() { preference->setStep(1); preferences->addPreference(preference); } - { - auto getter = [this]()->bool { return _enabled; }; - auto setter = [this](bool value) { _enabled = value; saveSettings(); }; - auto preference = new CheckPreference(NEURON_PLUGIN, "Enabled", getter, setter); - preferences->addPreference(preference); - } } bool NeuronPlugin::isSupported() const { @@ -455,6 +455,10 @@ void NeuronPlugin::deactivate() { } void NeuronPlugin::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { + if (!_enabled) { + return; + } + std::vector joints; { // lock and copy From 361bc1ce034190a81b913a9fe078284d5a2d4a2a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 26 Jun 2017 16:00:18 +1200 Subject: [PATCH 03/52] Add "enabled" setting for SDL2 joystick; bail in update if not enabled --- .../hifi/dialogs/GeneralPreferencesDialog.qml | 2 +- .../hifi/tablet/TabletGeneralPreferences.qml | 2 +- plugins/hifiSdl2/src/SDL2Manager.cpp | 48 ++++++++++++++++++- plugins/hifiSdl2/src/SDL2Manager.h | 8 +++- 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml index 44cae95696..605e2e79db 100644 --- a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml +++ b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml @@ -17,7 +17,7 @@ PreferencesDialog { id: root objectName: "GeneralPreferencesDialog" title: "General Settings" - showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Sixense Controllers", "Perception Neuron", "Kinect"] + showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "SDL2 Joystick", "Sixense Controllers", "Perception Neuron", "Kinect"] property var settings: Settings { category: root.objectName property alias x: root.x diff --git a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml index fe043f6ac7..2558100d0f 100644 --- a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml +++ b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml @@ -32,6 +32,6 @@ StackView { TabletPreferencesDialog { id: root objectName: "TabletGeneralPreferences" - showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Sixense Controllers", "Perception Neuron", "Kinect", "Vive Pucks Configuration"] + showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "SDL2 Joystick", "Sixense Controllers", "Perception Neuron", "Kinect", "Vive Pucks Configuration"] } } diff --git a/plugins/hifiSdl2/src/SDL2Manager.cpp b/plugins/hifiSdl2/src/SDL2Manager.cpp index 5ab5758412..2f7d91846d 100644 --- a/plugins/hifiSdl2/src/SDL2Manager.cpp +++ b/plugins/hifiSdl2/src/SDL2Manager.cpp @@ -11,8 +11,10 @@ #include -#include #include +#include +#include +#include #include "SDL2Manager.h" @@ -38,10 +40,13 @@ static_assert( (int)controller::RY == (int)SDL_CONTROLLER_AXIS_RIGHTY && (int)controller::LT == (int)SDL_CONTROLLER_AXIS_TRIGGERLEFT && (int)controller::RT == (int)SDL_CONTROLLER_AXIS_TRIGGERRIGHT, - "SDL2 equvalence: Enums and values from StandardControls.h are assumed to match enums from SDL_gamecontroller.h"); + "SDL2 equivalence: Enums and values from StandardControls.h are assumed to match enums from SDL_gamecontroller.h"); const char* SDL2Manager::NAME = "SDL2"; +const char* SDL2Manager::SDL2_ID_STRING = "SDL2"; + +const bool DEFAULT_ENABLED = false; SDL_JoystickID SDL2Manager::getInstanceId(SDL_GameController* controller) { SDL_Joystick* joystick = SDL_GameControllerGetJoystick(controller); @@ -49,6 +54,20 @@ SDL_JoystickID SDL2Manager::getInstanceId(SDL_GameController* controller) { } void SDL2Manager::init() { + loadSettings(); + + auto preferences = DependencyManager::get(); + static const QString SDL2_PLUGIN { "SDL2 Joystick" }; + { + auto getter = [this]()->bool { return _isEnabled; }; + auto setter = [this](bool value) { + _isEnabled = value; + saveSettings(); + }; + auto preference = new CheckPreference(SDL2_PLUGIN, "Enabled", getter, setter); + preferences->addPreference(preference); + } + bool initSuccess = (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) == 0); if (initSuccess) { @@ -110,6 +129,27 @@ void SDL2Manager::deactivate() { InputPlugin::deactivate(); } +const char* SETTINGS_ENABLED_KEY = "enabled"; + +void SDL2Manager::saveSettings() const { + Settings settings; + QString idString = getID(); + settings.beginGroup(idString); + { + settings.setValue(QString(SETTINGS_ENABLED_KEY), _isEnabled); + } + settings.endGroup(); +} + +void SDL2Manager::loadSettings() { + Settings settings; + QString idString = getID(); + settings.beginGroup(idString); + { + _isEnabled = settings.value(SETTINGS_ENABLED_KEY, QVariant(DEFAULT_ENABLED)).toBool(); + } + settings.endGroup(); +} bool SDL2Manager::isSupported() const { return true; @@ -122,6 +162,10 @@ void SDL2Manager::pluginFocusOutEvent() { } void SDL2Manager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { + if (!_isEnabled) { + return; + } + if (_isInitialized) { auto userInputMapper = DependencyManager::get(); for (auto joystick : _openJoysticks) { diff --git a/plugins/hifiSdl2/src/SDL2Manager.h b/plugins/hifiSdl2/src/SDL2Manager.h index 9cb4d268c0..48e779a204 100644 --- a/plugins/hifiSdl2/src/SDL2Manager.h +++ b/plugins/hifiSdl2/src/SDL2Manager.h @@ -25,6 +25,7 @@ public: // Plugin functions bool isSupported() const override; const QString getName() const override { return NAME; } + const QString getID() const override { return SDL2_ID_STRING; } QStringList getSubdeviceNames() override; @@ -39,6 +40,9 @@ public: void pluginFocusOutEvent() override; void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override; + virtual void saveSettings() const override; + virtual void loadSettings() override; + signals: void joystickAdded(Joystick* joystick); void joystickRemoved(Joystick* joystick); @@ -77,8 +81,10 @@ private: int buttonRelease() const { return SDL_RELEASED; } QMap _openJoysticks; - bool _isInitialized { false } ; + bool _isEnabled { false }; + bool _isInitialized { false }; static const char* NAME; + static const char* SDL2_ID_STRING; QStringList _subdeviceNames; }; From 31714675c358d3e76204d4d25a6927452aa4213f Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 26 Jun 2017 16:14:57 +1200 Subject: [PATCH 04/52] Remove unused Sixense preference and associated methods --- .../qml/hifi/dialogs/GeneralPreferencesDialog.qml | 2 +- .../qml/hifi/tablet/TabletGeneralPreferences.qml | 2 +- interface/src/ui/PreferencesDialog.cpp | 11 ----------- .../controllers/src/controllers/InputDevice.cpp | 14 -------------- .../controllers/src/controllers/InputDevice.h | 4 ---- 5 files changed, 2 insertions(+), 31 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml index 605e2e79db..08631bc6e8 100644 --- a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml +++ b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml @@ -17,7 +17,7 @@ PreferencesDialog { id: root objectName: "GeneralPreferencesDialog" title: "General Settings" - showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "SDL2 Joystick", "Sixense Controllers", "Perception Neuron", "Kinect"] + showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "SDL2 Joystick", "Perception Neuron", "Kinect"] property var settings: Settings { category: root.objectName property alias x: root.x diff --git a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml index 2558100d0f..d893bab776 100644 --- a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml +++ b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml @@ -32,6 +32,6 @@ StackView { TabletPreferencesDialog { id: root objectName: "TabletGeneralPreferences" - showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "SDL2 Joystick", "Sixense Controllers", "Perception Neuron", "Kinect", "Vive Pucks Configuration"] + showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "SDL2 Joystick", "Perception Neuron", "Kinect", "Vive Pucks Configuration"] } } diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 41a4ebdf68..d9f71c8d3d 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -297,17 +297,6 @@ void setupPreferences() { preferences->addPreference(preference); } - - { - auto getter = []()->float { return controller::InputDevice::getReticleMoveSpeed(); }; - auto setter = [](float value) { controller::InputDevice::setReticleMoveSpeed(value); }; - auto preference = new SpinnerPreference("Sixense Controllers", "Reticle movement speed", getter, setter); - preference->setMin(0); - preference->setMax(100); - preference->setStep(1); - preferences->addPreference(preference); - } - { static const QString RENDER("Graphics"); auto renderConfig = qApp->getRenderEngine()->getConfiguration(); diff --git a/libraries/controllers/src/controllers/InputDevice.cpp b/libraries/controllers/src/controllers/InputDevice.cpp index dd27726a55..a907842a17 100644 --- a/libraries/controllers/src/controllers/InputDevice.cpp +++ b/libraries/controllers/src/controllers/InputDevice.cpp @@ -15,20 +15,6 @@ namespace controller { - const float DEFAULT_HAND_RETICLE_MOVE_SPEED = 37.5f; - float InputDevice::_reticleMoveSpeed = DEFAULT_HAND_RETICLE_MOVE_SPEED; - - //Constants for getCursorPixelRangeMultiplier() - const float MIN_PIXEL_RANGE_MULT = 0.4f; - const float MAX_PIXEL_RANGE_MULT = 2.0f; - const float RANGE_MULT = (MAX_PIXEL_RANGE_MULT - MIN_PIXEL_RANGE_MULT) * 0.01f; - - //Returns a multiplier to be applied to the cursor range for the controllers - float InputDevice::getCursorPixelRangeMult() { - //scales (0,100) to (MINIMUM_PIXEL_RANGE_MULT, MAXIMUM_PIXEL_RANGE_MULT) - return InputDevice::_reticleMoveSpeed * RANGE_MULT + MIN_PIXEL_RANGE_MULT; - } - float InputDevice::getButton(int channel) const { if (!_buttonPressedMap.empty()) { if (_buttonPressedMap.find(channel) != _buttonPressedMap.end()) { diff --git a/libraries/controllers/src/controllers/InputDevice.h b/libraries/controllers/src/controllers/InputDevice.h index 9d46930104..7315868bb4 100644 --- a/libraries/controllers/src/controllers/InputDevice.h +++ b/libraries/controllers/src/controllers/InputDevice.h @@ -73,10 +73,6 @@ public: int getDeviceID() { return _deviceID; } void setDeviceID(int deviceID) { _deviceID = deviceID; } - static float getCursorPixelRangeMult(); - static float getReticleMoveSpeed() { return _reticleMoveSpeed; } - static void setReticleMoveSpeed(float reticleMoveSpeed) { _reticleMoveSpeed = reticleMoveSpeed; } - Input makeInput(StandardButtonChannel button) const; Input makeInput(StandardAxisChannel axis) const; Input makeInput(StandardPoseChannel pose) const; From 72d712ac767ebc04ab8a1fcb83b0f79ede6d43e7 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 26 Jun 2017 16:43:06 +1200 Subject: [PATCH 05/52] Add "enabled" setting for Sixense; bail in update if note enabled --- .../hifi/dialogs/GeneralPreferencesDialog.qml | 2 +- .../hifi/tablet/TabletGeneralPreferences.qml | 2 +- plugins/hifiSixense/src/SixenseManager.cpp | 47 +++++++++++++++---- plugins/hifiSixense/src/SixenseManager.h | 7 ++- 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml index 08631bc6e8..605e2e79db 100644 --- a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml +++ b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml @@ -17,7 +17,7 @@ PreferencesDialog { id: root objectName: "GeneralPreferencesDialog" title: "General Settings" - showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "SDL2 Joystick", "Perception Neuron", "Kinect"] + showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "SDL2 Joystick", "Sixense Controllers", "Perception Neuron", "Kinect"] property var settings: Settings { category: root.objectName property alias x: root.x diff --git a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml index d893bab776..2558100d0f 100644 --- a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml +++ b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml @@ -32,6 +32,6 @@ StackView { TabletPreferencesDialog { id: root objectName: "TabletGeneralPreferences" - showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "SDL2 Joystick", "Perception Neuron", "Kinect", "Vive Pucks Configuration"] + showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "SDL2 Joystick", "Sixense Controllers", "Perception Neuron", "Kinect", "Vive Pucks Configuration"] } } diff --git a/plugins/hifiSixense/src/SixenseManager.cpp b/plugins/hifiSixense/src/SixenseManager.cpp index 7d443bd50d..88f73786bd 100644 --- a/plugins/hifiSixense/src/SixenseManager.cpp +++ b/plugins/hifiSixense/src/SixenseManager.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -46,19 +47,26 @@ static const unsigned int BUTTON_TRIGGER = 1U << 8; const glm::vec3 SixenseManager::DEFAULT_AVATAR_POSITION { -0.25f, -0.35f, -0.3f }; // in hydra frame const float SixenseManager::CONTROLLER_THRESHOLD { 0.35f }; + +bool SixenseManager::_isEnabled = false; bool SixenseManager::_sixenseLoaded = false; +#define BAIL_IF_NOT_ENABLED \ + if (!_isEnabled) { \ + return; \ + } + #define BAIL_IF_NOT_LOADED \ if (!_sixenseLoaded) { \ return; \ } - - const char* SixenseManager::NAME { "Sixense" }; -const char* SixenseManager::HYDRA_ID_STRING { "Razer Hydra" }; +const char* SixenseManager::SIXENSE_ID_STRING { "Sixense" }; -const char* MENU_PARENT { "Developer" }; +const bool DEFAULT_ENABLED = false; + +const char* MENU_PARENT{ "Developer" }; const char* MENU_NAME { "Sixense" }; const char* MENU_PATH { "Developer" ">" "Sixense" }; const char* TOGGLE_SMOOTH { "Smooth Sixense Movement" }; @@ -73,6 +81,22 @@ bool SixenseManager::isSupported() const { #endif } +void SixenseManager::init() { + loadSettings(); + + auto preferences = DependencyManager::get(); + static const QString SIXENSE_PLUGIN { "Sixense Controllers" }; + { + auto getter = [this]()->bool { return _isEnabled; }; + auto setter = [this](bool value) { + _isEnabled = value; + saveSettings(); + }; + auto preference = new CheckPreference(SIXENSE_PLUGIN, "Enabled", getter, setter); + preferences->addPreference(preference); + } +} + bool SixenseManager::activate() { InputPlugin::activate(); @@ -133,6 +157,7 @@ void SixenseManager::setSixenseFilter(bool filter) { } void SixenseManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) { + BAIL_IF_NOT_ENABLED BAIL_IF_NOT_LOADED #ifdef HAVE_SIXENSE @@ -553,14 +578,19 @@ QString SixenseManager::InputDevice::getDefaultMappingConfig() const { return MAPPING_JSON; } +const char* SETTINGS_ENABLED_KEY = "enabled"; +const char* SETTINGS_AVATAR_POSITION_KEY = "avatarPosition"; +const char* SETTINGS_AVATAR_ROTATION_KEY = "avatarPosition"; + // virtual void SixenseManager::saveSettings() const { Settings settings; QString idString = getID(); settings.beginGroup(idString); { - settings.setVec3Value(QString("avatarPosition"), _inputDevice->_avatarPosition); - settings.setQuatValue(QString("avatarRotation"), _inputDevice->_avatarRotation); + settings.setValue(QString(SETTINGS_ENABLED_KEY), _isEnabled); + settings.setVec3Value(QString(SETTINGS_AVATAR_POSITION_KEY), _inputDevice->_avatarPosition); + settings.setQuatValue(QString(SETTINGS_AVATAR_ROTATION_KEY), _inputDevice->_avatarRotation); } settings.endGroup(); } @@ -570,8 +600,9 @@ void SixenseManager::loadSettings() { QString idString = getID(); settings.beginGroup(idString); { - settings.getVec3ValueIfValid(QString("avatarPosition"), _inputDevice->_avatarPosition); - settings.getQuatValueIfValid(QString("avatarRotation"), _inputDevice->_avatarRotation); + _isEnabled = settings.value(SETTINGS_ENABLED_KEY, QVariant(DEFAULT_ENABLED)).toBool(); + settings.getVec3ValueIfValid(QString(SETTINGS_AVATAR_POSITION_KEY), _inputDevice->_avatarPosition); + settings.getQuatValueIfValid(QString(SETTINGS_AVATAR_ROTATION_KEY), _inputDevice->_avatarRotation); } settings.endGroup(); } diff --git a/plugins/hifiSixense/src/SixenseManager.h b/plugins/hifiSixense/src/SixenseManager.h index 5b2c140868..e9d571ad8c 100644 --- a/plugins/hifiSixense/src/SixenseManager.h +++ b/plugins/hifiSixense/src/SixenseManager.h @@ -29,12 +29,14 @@ public: // Plugin functions virtual bool isSupported() const override; virtual const QString getName() const override { return NAME; } - virtual const QString getID() const override { return HYDRA_ID_STRING; } + virtual const QString getID() const override { return SIXENSE_ID_STRING; } // Sixense always seems to initialize even if the hydras are not present. Is there // a way we can properly detect whether the hydras are present? // bool isHandController() const override { return true; } + virtual void init() override; + virtual bool activate() override; virtual void deactivate() override; @@ -93,8 +95,9 @@ private: std::shared_ptr _inputDevice { std::make_shared() }; static const char* NAME; - static const char* HYDRA_ID_STRING; + static const char* SIXENSE_ID_STRING; + static bool _isEnabled; static bool _sixenseLoaded; }; From 88ed69a4a12ae021edc33b7dde633f8bbbd2ae43 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 29 Jun 2017 08:58:27 +1200 Subject: [PATCH 06/52] Code review --- libraries/controllers/src/controllers/InputDevice.h | 3 --- plugins/hifiSixense/src/SixenseManager.cpp | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/controllers/src/controllers/InputDevice.h b/libraries/controllers/src/controllers/InputDevice.h index 7315868bb4..ff665d912d 100644 --- a/libraries/controllers/src/controllers/InputDevice.h +++ b/libraries/controllers/src/controllers/InputDevice.h @@ -95,9 +95,6 @@ protected: ButtonPressedMap _buttonPressedMap; AxisStateMap _axisStateMap; PoseStateMap _poseStateMap; - -private: - static float _reticleMoveSpeed; }; } diff --git a/plugins/hifiSixense/src/SixenseManager.cpp b/plugins/hifiSixense/src/SixenseManager.cpp index 88f73786bd..c2c1cb2ab2 100644 --- a/plugins/hifiSixense/src/SixenseManager.cpp +++ b/plugins/hifiSixense/src/SixenseManager.cpp @@ -54,7 +54,7 @@ bool SixenseManager::_sixenseLoaded = false; #define BAIL_IF_NOT_ENABLED \ if (!_isEnabled) { \ return; \ - } + } #define BAIL_IF_NOT_LOADED \ if (!_sixenseLoaded) { \ From be0e1a75a4cf84f82a096379a4837546d200b90e Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 29 Jun 2017 10:03:58 +1200 Subject: [PATCH 07/52] User-friendly SDL2 controller name --- .../resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml | 2 +- .../resources/qml/hifi/tablet/TabletGeneralPreferences.qml | 2 +- plugins/hifiSdl2/src/SDL2Manager.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml index 605e2e79db..33a5e62b1f 100644 --- a/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml +++ b/interface/resources/qml/hifi/dialogs/GeneralPreferencesDialog.qml @@ -17,7 +17,7 @@ PreferencesDialog { id: root objectName: "GeneralPreferencesDialog" title: "General Settings" - showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "SDL2 Joystick", "Sixense Controllers", "Perception Neuron", "Kinect"] + showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Game Controller", "Sixense Controllers", "Perception Neuron", "Kinect"] property var settings: Settings { category: root.objectName property alias x: root.x diff --git a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml index 2558100d0f..005f09afe6 100644 --- a/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml +++ b/interface/resources/qml/hifi/tablet/TabletGeneralPreferences.qml @@ -32,6 +32,6 @@ StackView { TabletPreferencesDialog { id: root objectName: "TabletGeneralPreferences" - showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "SDL2 Joystick", "Sixense Controllers", "Perception Neuron", "Kinect", "Vive Pucks Configuration"] + showCategories: ["UI", "Snapshots", "Scripts", "Privacy", "Octree", "HMD", "Game Controller", "Sixense Controllers", "Perception Neuron", "Kinect", "Vive Pucks Configuration"] } } diff --git a/plugins/hifiSdl2/src/SDL2Manager.cpp b/plugins/hifiSdl2/src/SDL2Manager.cpp index 2f7d91846d..021cb4dfec 100644 --- a/plugins/hifiSdl2/src/SDL2Manager.cpp +++ b/plugins/hifiSdl2/src/SDL2Manager.cpp @@ -57,7 +57,7 @@ void SDL2Manager::init() { loadSettings(); auto preferences = DependencyManager::get(); - static const QString SDL2_PLUGIN { "SDL2 Joystick" }; + static const QString SDL2_PLUGIN { "Game Controller" }; { auto getter = [this]()->bool { return _isEnabled; }; auto setter = [this](bool value) { From 9c610f52eca11a94a637a9f408fb6f0c597a0628 Mon Sep 17 00:00:00 2001 From: humbletim Date: Mon, 17 Jul 2017 15:34:41 -0400 Subject: [PATCH 08/52] switch history file format to JSON --- interface/src/ui/JSConsole.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index 820ed4207d..ef38ea6d29 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -24,7 +24,7 @@ const int NO_CURRENT_HISTORY_COMMAND = -1; const int MAX_HISTORY_SIZE = 256; -const QString HISTORY_FILENAME = "JSConsole.history.txt"; +const QString HISTORY_FILENAME = "JSConsole.history.json"; const QString COMMAND_STYLE = "color: #266a9b;"; @@ -38,16 +38,25 @@ const QString GUTTER_ERROR = "X"; const QString JSConsole::_consoleFileName { "about:console" }; +const QString JSON_KEY = "entries"; QList _readLines(const QString& filename) { QFile file(filename); file.open(QFile::ReadOnly); - return QTextStream(&file).readAll().split("\r\n"); + auto json = QTextStream(&file).readAll().toUtf8(); + auto root = QJsonDocument::fromJson(json).object(); + // TODO: check root["version"] + return root[JSON_KEY].toVariant().toStringList(); } void _writeLines(const QString& filename, const QList& lines) { QFile file(filename); file.open(QFile::WriteOnly); - QTextStream(&file) << lines.join("\r\n"); + auto root = QJsonObject(); + root["version"] = 1.0; + root["last-modified"] = QDateTime::currentDateTime().toTimeSpec(Qt::OffsetFromUTC).toString(Qt::ISODate); + root[JSON_KEY] = QJsonArray::fromStringList(lines); + auto json = QJsonDocument(root).toJson(); + QTextStream(&file) << json; } JSConsole::JSConsole(QWidget* parent, ScriptEngine* scriptEngine) : From 4ad36ccec9bdf1bd8951fd41cfe15063409c1b32 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 17 Jul 2017 16:21:28 -0700 Subject: [PATCH 09/52] Trying to resolve QML / Audio deadlocks --- interface/resources/qml/hifi/audio/Audio.qml | 52 +++++++++++--------- interface/src/scripting/Audio.cpp | 16 +++++- interface/src/scripting/Audio.h | 2 + interface/src/scripting/AudioDevices.cpp | 5 +- 4 files changed, 51 insertions(+), 24 deletions(-) diff --git a/interface/resources/qml/hifi/audio/Audio.qml b/interface/resources/qml/hifi/audio/Audio.qml index 519499e35c..03d27e3831 100644 --- a/interface/resources/qml/hifi/audio/Audio.qml +++ b/interface/resources/qml/hifi/audio/Audio.qml @@ -117,26 +117,28 @@ Rectangle { delegate: Item { width: parent.width; height: 36; + + AudioControls.CheckBox { + id: checkbox + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + text: display; + wrap: false; + checked: selected; + enabled: false; + } - RowLayout { - width: parent.width; + MouseArea { + anchors.fill: checkbox + onClicked: Audio.setInputDevice(info); + } - AudioControls.CheckBox { - Layout.maximumWidth: parent.width - level.width - 40; - text: display; - wrap: false; - checked: selected; - onClicked: { - selected = checked; - checked = Qt.binding(function() { return selected; }); // restore binding - } - } - InputLevel { - id: level; - Layout.alignment: Qt.AlignRight; - Layout.rightMargin: 30; - visible: selected; - } + InputLevel { + id: level; + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + anchors.rightMargin: 30 + visible: selected; } } } @@ -174,13 +176,19 @@ Rectangle { delegate: Item { width: parent.width; height: 36; + AudioControls.CheckBox { + id: checkbox + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left text: display; checked: selected; - onClicked: { - selected = checked; - checked = Qt.binding(function() { return selected; }); // restore binding - } + enabled: false; + } + + MouseArea { + anchors.fill: checkbox + onClicked: Audio.setOutputDevice(info); } } } diff --git a/interface/src/scripting/Audio.cpp b/interface/src/scripting/Audio.cpp index 8125f9a9f0..860fe4f2a5 100644 --- a/interface/src/scripting/Audio.cpp +++ b/interface/src/scripting/Audio.cpp @@ -133,4 +133,18 @@ void Audio::setReverb(bool enable) { void Audio::setReverbOptions(const AudioEffectOptions* options) { DependencyManager::get()->setReverbOptions(options); -} \ No newline at end of file +} + +void Audio::setInputDevice(const QAudioDeviceInfo& device) { + auto client = DependencyManager::get(); + QMetaObject::invokeMethod(client.data(), "switchAudioDevice", + Q_ARG(QAudio::Mode, QAudio::AudioInput), + Q_ARG(const QAudioDeviceInfo&, device)); +} + +void Audio::setOutputDevice(const QAudioDeviceInfo& device) { + auto client = DependencyManager::get(); + QMetaObject::invokeMethod(client.data(), "switchAudioDevice", + Q_ARG(QAudio::Mode, QAudio::AudioOutput), + Q_ARG(const QAudioDeviceInfo&, device)); +} diff --git a/interface/src/scripting/Audio.h b/interface/src/scripting/Audio.h index ca89521489..acf101159b 100644 --- a/interface/src/scripting/Audio.h +++ b/interface/src/scripting/Audio.h @@ -50,6 +50,8 @@ public: void showMicMeter(bool show); void setInputVolume(float volume); + Q_INVOKABLE void setInputDevice(const QAudioDeviceInfo& device); + Q_INVOKABLE void setOutputDevice(const QAudioDeviceInfo& device); Q_INVOKABLE void setReverb(bool enable); Q_INVOKABLE void setReverbOptions(const AudioEffectOptions* options); diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index e26ebac3f1..2813f75110 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -38,7 +38,8 @@ Setting::Handle& getSetting(bool contextIsHMD, QAudio::Mode mode) { QHash AudioDeviceList::_roles { { Qt::DisplayRole, "display" }, - { Qt::CheckStateRole, "selected" } + { Qt::CheckStateRole, "selected" }, + { Qt::UserRole, "info" } }; Qt::ItemFlags AudioDeviceList::_flags { Qt::ItemIsSelectable | Qt::ItemIsEnabled }; @@ -51,6 +52,8 @@ QVariant AudioDeviceList::data(const QModelIndex& index, int role) const { return _devices.at(index.row()).display; } else if (role == Qt::CheckStateRole) { return _devices.at(index.row()).selected; + } else if (role == Qt::UserRole) { + return QVariant::fromValue(_devices.at(index.row()).info); } else { return QVariant(); } From aeabfe84f0cec8ea0f908da96eeda84f3bbd277d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 17 Jul 2017 18:54:52 -0700 Subject: [PATCH 10/52] Cleanup dead code, fix startup behavior --- interface/src/scripting/Audio.cpp | 10 +- interface/src/scripting/AudioDevices.cpp | 114 ++++++++--------------- interface/src/scripting/AudioDevices.h | 10 +- 3 files changed, 43 insertions(+), 91 deletions(-) diff --git a/interface/src/scripting/Audio.cpp b/interface/src/scripting/Audio.cpp index 860fe4f2a5..9719c23885 100644 --- a/interface/src/scripting/Audio.cpp +++ b/interface/src/scripting/Audio.cpp @@ -136,15 +136,9 @@ void Audio::setReverbOptions(const AudioEffectOptions* options) { } void Audio::setInputDevice(const QAudioDeviceInfo& device) { - auto client = DependencyManager::get(); - QMetaObject::invokeMethod(client.data(), "switchAudioDevice", - Q_ARG(QAudio::Mode, QAudio::AudioInput), - Q_ARG(const QAudioDeviceInfo&, device)); + _devices.chooseInputDevice(device); } void Audio::setOutputDevice(const QAudioDeviceInfo& device) { - auto client = DependencyManager::get(); - QMetaObject::invokeMethod(client.data(), "switchAudioDevice", - Q_ARG(QAudio::Mode, QAudio::AudioOutput), - Q_ARG(const QAudioDeviceInfo&, device)); + _devices.chooseOutputDevice(device); } diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index 2813f75110..a284e38dac 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -59,61 +59,17 @@ QVariant AudioDeviceList::data(const QModelIndex& index, int role) const { } } -bool AudioDeviceList::setData(const QModelIndex& index, const QVariant& value, int role) { - if (!index.isValid() || index.row() >= _devices.size() || role != Qt::CheckStateRole) { - return false; - } - - // only allow switching to a new device, not deactivating an in-use device - auto selected = value.toBool(); - if (!selected) { - return false; - } - - return setDevice(index.row(), true); -} - -bool AudioDeviceList::setDevice(int row, bool fromUser) { - bool success = false; - auto& device = _devices[row]; - _userSelection = fromUser; - - // skip if already selected - if (!device.selected) { - auto client = DependencyManager::get(); - QMetaObject::invokeMethod(client.data(), "switchAudioDevice", - Q_ARG(QAudio::Mode, _mode), - Q_ARG(const QAudioDeviceInfo&, device.info)); - } - - emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0)); - return success; -} void AudioDeviceList::resetDevice(bool contextIsHMD, const QString& device) { - bool success { false }; - - // try to set the last selected device - if (!device.isNull()) { - auto i = 0; - for (; i < rowCount(); ++i) { - if (device == _devices[i].info.deviceName()) { - break; - } - } - if (i < rowCount()) { - success = setDevice(i, false); - } - - // the selection failed - reset it - if (!success) { - emit deviceSelected(); - } - } + auto client = DependencyManager::get().data(); + auto deviceName = getSetting(contextIsHMD, _mode).get(); + bool switchResult = false; + QMetaObject::invokeMethod(client, "switchAudioDevice", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(bool, switchResult), + Q_ARG(QAudio::Mode, _mode), Q_ARG(QString, deviceName)); // try to set to the default device for this mode - if (!success) { - auto client = DependencyManager::get().data(); + if (!switchResult) { if (contextIsHMD) { QString deviceName; if (_mode == QAudio::AudioInput) { @@ -144,11 +100,6 @@ void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device) { } } - if (_userSelection) { - _userSelection = false; - emit deviceSelected(_selectedDevice, oldDevice); - } - emit deviceChanged(_selectedDevice); emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0)); } @@ -183,13 +134,6 @@ AudioDevices::AudioDevices(bool& contextIsHMD) : _contextIsHMD(contextIsHMD) { _outputs.onDeviceChanged(client->getActiveAudioDevice(QAudio::AudioOutput)); _inputs.onDevicesChanged(client->getAudioDevices(QAudio::AudioInput)); _outputs.onDevicesChanged(client->getAudioDevices(QAudio::AudioOutput)); - - connect(&_inputs, &AudioDeviceList::deviceSelected, [&](const QAudioDeviceInfo& device, const QAudioDeviceInfo& previousDevice) { - onDeviceSelected(QAudio::AudioInput, device, previousDevice); - }); - connect(&_outputs, &AudioDeviceList::deviceSelected, [&](const QAudioDeviceInfo& device, const QAudioDeviceInfo& previousDevice) { - onDeviceSelected(QAudio::AudioOutput, device, previousDevice); - }); } void AudioDevices::onContextChanged(const QString& context) { @@ -245,22 +189,40 @@ void AudioDevices::onDeviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& de } void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList& devices) { - static bool initialized { false }; - auto initialize = [&]{ - if (initialized) { - onContextChanged(QString()); - } else { - initialized = true; - } - }; - + static std::once_flag once; if (mode == QAudio::AudioInput) { _inputs.onDevicesChanged(devices); - static std::once_flag inputFlag; - std::call_once(inputFlag, initialize); } else { // if (mode == QAudio::AudioOutput) _outputs.onDevicesChanged(devices); - static std::once_flag outputFlag; - std::call_once(outputFlag, initialize); + } + std::call_once(once, [&] { onContextChanged(QString()); }); +} + + +void AudioDevices::chooseInputDevice(const QAudioDeviceInfo& device) { + auto client = DependencyManager::get(); + bool success = false; + QMetaObject::invokeMethod(client.data(), "switchAudioDevice", + Qt::BlockingQueuedConnection, + Q_RETURN_ARG(bool, success), + Q_ARG(QAudio::Mode, QAudio::AudioInput), + Q_ARG(const QAudioDeviceInfo&, device)); + + if (success) { + onDeviceSelected(QAudio::AudioInput, device, _inputs._selectedDevice); + } +} + +void AudioDevices::chooseOutputDevice(const QAudioDeviceInfo& device) { + auto client = DependencyManager::get(); + bool success = false; + QMetaObject::invokeMethod(client.data(), "switchAudioDevice", + Qt::BlockingQueuedConnection, + Q_RETURN_ARG(bool, success), + Q_ARG(QAudio::Mode, QAudio::AudioOutput), + Q_ARG(const QAudioDeviceInfo&, device)); + + if (success) { + onDeviceSelected(QAudio::AudioOutput, device, _outputs._selectedDevice); } } diff --git a/interface/src/scripting/AudioDevices.h b/interface/src/scripting/AudioDevices.h index 8e82ddc4fb..a17c577535 100644 --- a/interface/src/scripting/AudioDevices.h +++ b/interface/src/scripting/AudioDevices.h @@ -37,14 +37,11 @@ public: // get/set devices through a QML ListView QVariant data(const QModelIndex& index, int role) const override; - bool setData(const QModelIndex& index, const QVariant &value, int role) override; // reset device to the last selected device in this context, or the default void resetDevice(bool contextIsHMD, const QString& device); signals: - void deviceSelected(const QAudioDeviceInfo& device = QAudioDeviceInfo(), - const QAudioDeviceInfo& previousDevice = QAudioDeviceInfo()); void deviceChanged(const QAudioDeviceInfo& device); private slots: @@ -54,12 +51,9 @@ private slots: private: friend class AudioDevices; - bool setDevice(int index, bool fromUser); - static QHash _roles; static Qt::ItemFlags _flags; - bool _userSelection { false }; - QAudio::Mode _mode; + const QAudio::Mode _mode; QAudioDeviceInfo _selectedDevice; QList _devices; }; @@ -73,6 +67,8 @@ class AudioDevices : public QObject { public: AudioDevices(bool& contextIsHMD); + void chooseInputDevice(const QAudioDeviceInfo& device); + void chooseOutputDevice(const QAudioDeviceInfo& device); signals: void nop(); From 02363e06de87f32a9997d4df62deba6c99a30007 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 18 Jul 2017 08:58:17 -0700 Subject: [PATCH 11/52] Ensure input and output device containers are protected by mutex --- libraries/audio-client/src/AudioClient.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 3d9b1de10f..bc02da1cc4 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -92,6 +92,7 @@ void AudioClient::checkDevices() { auto inputDevices = getAvailableDevices(QAudio::AudioInput); auto outputDevices = getAvailableDevices(QAudio::AudioOutput); + Lock lock(_deviceMutex); if (inputDevices != _inputDevices) { _inputDevices.swap(inputDevices); emit devicesChanged(QAudio::AudioInput, _inputDevices); From 4b94d24c2922a3028cf9898f367b6b7077530260 Mon Sep 17 00:00:00 2001 From: vladest Date: Tue, 18 Jul 2017 23:51:19 +0200 Subject: [PATCH 12/52] Change default mouse speeds for avatar --- interface/src/avatar/MyAvatar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index f9a4d491c8..a6958c9089 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -69,8 +69,8 @@ const float MAX_BOOST_SPEED = 0.5f * MAX_WALKING_SPEED; // action motor gets add const float MIN_AVATAR_SPEED = 0.05f; const float MIN_AVATAR_SPEED_SQUARED = MIN_AVATAR_SPEED * MIN_AVATAR_SPEED; // speed is set to zero below this -const float YAW_SPEED_DEFAULT = 120.0f; // degrees/sec -const float PITCH_SPEED_DEFAULT = 90.0f; // degrees/sec +const float YAW_SPEED_DEFAULT = 60.0f; // degrees/sec +const float PITCH_SPEED_DEFAULT = 45.0f; // degrees/sec // TODO: normalize avatar speed for standard avatar size, then scale all motion logic // to properly follow avatar size. From 009df176c511a7acde67a4baaa709263bfe0936d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 18 Jul 2017 13:44:58 -0700 Subject: [PATCH 13/52] Ensure we continue calling idle when minimized Conflicts: interface/src/Application.cpp --- interface/src/Application.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a214068239..0cb4b90174 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2742,6 +2742,16 @@ bool Application::event(QEvent* event) { static_cast(event)->call(); return true; + // Explicit idle keeps the idle running at a lower interval, but without any rendering + // see (windowMinimizedChanged) + case Event::Idle: + { + float nsecsElapsed = (float)_lastTimeUpdated.nsecsElapsed(); + _lastTimeUpdated.start(); + idle(nsecsElapsed); + } + return true; + case Event::Present: if (!_renderRequested) { float nsecsElapsed = (float)_lastTimeUpdated.nsecsElapsed(); From a8698c2fbc164071320a64df805e64ca50ad9dde Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 19 Jul 2017 08:59:09 -0700 Subject: [PATCH 14/52] EntityScriptingInterface::getMeshes support for Model entities --- .../src/RenderableModelEntityItem.cpp | 7 ++++ .../src/RenderableModelEntityItem.h | 2 ++ libraries/model/src/model/Geometry.cpp | 2 +- libraries/model/src/model/Geometry.h | 2 +- libraries/render-utils/src/Model.cpp | 35 +++++++++++++++++++ libraries/render-utils/src/Model.h | 2 ++ 6 files changed, 48 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 0b6271a6b1..5c0c6101a3 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -1282,3 +1282,10 @@ void RenderableModelEntityItem::mapJoints(const QStringList& modelJointNames) { } } } + +bool RenderableModelEntityItem::getMeshes(MeshProxyList& result) { + if (!_model || !_model->isLoaded()) { + return false; + } + return _model->getMeshes(result); +} diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 2d240c01a6..a5ba7bedda 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -116,6 +116,8 @@ public: return _animation; } + bool getMeshes(MeshProxyList& result) override; + private: QVariantMap parseTexturesToMap(QString textures); void remapTextures(); diff --git a/libraries/model/src/model/Geometry.cpp b/libraries/model/src/model/Geometry.cpp index f88c8233ea..ac4c5dc188 100755 --- a/libraries/model/src/model/Geometry.cpp +++ b/libraries/model/src/model/Geometry.cpp @@ -137,7 +137,7 @@ Box Mesh::evalPartsBound(int partStart, int partEnd) const { model::MeshPointer Mesh::map(std::function vertexFunc, std::function normalFunc, - std::function indexFunc) { + std::function indexFunc) const { // vertex data const gpu::BufferView& vertexBufferView = getVertexBuffer(); gpu::BufferView::Index numVertices = (gpu::BufferView::Index)getNumVertices(); diff --git a/libraries/model/src/model/Geometry.h b/libraries/model/src/model/Geometry.h index a3198eed26..f273435545 100755 --- a/libraries/model/src/model/Geometry.h +++ b/libraries/model/src/model/Geometry.h @@ -124,7 +124,7 @@ public: // create a copy of this mesh after passing its vertices, normals, and indexes though the provided functions MeshPointer map(std::function vertexFunc, std::function normalFunc, - std::function indexFunc); + std::function indexFunc) const; void forEach(std::function vertexFunc, std::function normalFunc, diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 45be09b701..5e3c9c8ecd 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include "AbstractViewStateInterface.h" #include "MeshPartPayload.h" @@ -462,6 +463,40 @@ bool Model::convexHullContains(glm::vec3 point) { return false; } +bool Model::getMeshes(MeshProxyList& result) { + const Geometry::Pointer& renderGeometry = getGeometry(); + const Geometry::GeometryMeshes& meshes = renderGeometry->getMeshes(); + + if (!isLoaded()) { + return false; + } + + Transform offset; + offset.setScale(_scale); + // not set -- far to the right + // offset.postTranslate(_offset); // far to right + // offset.postTranslate(-_offset); // a bit to left + glm::mat4 offsetMat = offset.getMatrix(); + + for (std::shared_ptr mesh : meshes) { + if (!mesh) { + continue; + } + + MeshProxy* meshProxy = new SimpleMeshProxy( + mesh->map([=](glm::vec3 position) { + const glm::vec3 DEFAULT_ENTITY_REGISTRATION_POINT = glm::vec3(0.5f, 0.5f, 0.5f); + glm::vec3 regis = _registrationPoint - DEFAULT_ENTITY_REGISTRATION_POINT; + return glm::vec3(offsetMat * glm::vec4(position + _offset, 1.0f)) + regis; // very close + }, + [=](glm::vec3 normal){ return glm::normalize(glm::vec3(offsetMat * glm::vec4(normal, 0.0f))); }, + [&](uint32_t index){ return index; })); + result << meshProxy; + } + + return true; +} + void Model::calculateTriangleSets() { PROFILE_RANGE(render, __FUNCTION__); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 3eb796b763..1738af661b 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -257,6 +257,8 @@ public: int getResourceDownloadAttempts() { return _renderWatcher.getResourceDownloadAttempts(); } int getResourceDownloadAttemptsRemaining() { return _renderWatcher.getResourceDownloadAttemptsRemaining(); } + bool getMeshes(MeshProxyList& result); + public slots: void loadURLFinished(bool success); From 750b7192afb70e582e4978f6e7bced1d07b6f488 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 19 Jul 2017 13:58:03 -0700 Subject: [PATCH 15/52] trying to get the resulting model to line up with the originals --- .../entities/src/EntityScriptingInterface.cpp | 2 +- libraries/render-utils/src/Model.cpp | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 2cefd647cb..1dc3cf8f75 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -1738,7 +1738,7 @@ glm::mat4 EntityScriptingInterface::getEntityTransform(const QUuid& entityID) { glm::mat4 rotation = glm::mat4_cast(entity->getRotation()); glm::mat4 registration = glm::translate(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - entity->getRegistrationPoint()); - result = translation * rotation * registration; + result = translation * rotation /* * registration */; } }); } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 5e3c9c8ecd..6219e83bf1 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -473,11 +473,16 @@ bool Model::getMeshes(MeshProxyList& result) { Transform offset; offset.setScale(_scale); - // not set -- far to the right - // offset.postTranslate(_offset); // far to right - // offset.postTranslate(-_offset); // a bit to left + // offset.postTranslate(_offset); glm::mat4 offsetMat = offset.getMatrix(); + Extents modelExtents = getUnscaledMeshExtents(); + glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; + + const glm::vec3 DEFAULT_ENTITY_REGISTRATION_POINT = glm::vec3(0.5f, 0.5f, 0.5f); + glm::vec3 regis = (DEFAULT_ENTITY_REGISTRATION_POINT - _registrationPoint); + glm::vec3 regisOffset = dimensions * regis; + for (std::shared_ptr mesh : meshes) { if (!mesh) { continue; @@ -485,9 +490,7 @@ bool Model::getMeshes(MeshProxyList& result) { MeshProxy* meshProxy = new SimpleMeshProxy( mesh->map([=](glm::vec3 position) { - const glm::vec3 DEFAULT_ENTITY_REGISTRATION_POINT = glm::vec3(0.5f, 0.5f, 0.5f); - glm::vec3 regis = _registrationPoint - DEFAULT_ENTITY_REGISTRATION_POINT; - return glm::vec3(offsetMat * glm::vec4(position + _offset, 1.0f)) + regis; // very close + return glm::vec3(offsetMat * glm::vec4(position, 1.0f)); }, [=](glm::vec3 normal){ return glm::normalize(glm::vec3(offsetMat * glm::vec4(normal, 0.0f))); }, [&](uint32_t index){ return index; })); From be48268be827edecf9702b556353cd5f0928dcbb Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 19 Jul 2017 15:02:40 -0700 Subject: [PATCH 16/52] getMeshes handles registration point --- libraries/entities/src/EntityScriptingInterface.cpp | 8 ++------ libraries/render-utils/src/Model.cpp | 9 +-------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 1dc3cf8f75..9d2cb30c6e 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -1736,9 +1736,7 @@ glm::mat4 EntityScriptingInterface::getEntityTransform(const QUuid& entityID) { if (entity) { glm::mat4 translation = glm::translate(entity->getPosition()); glm::mat4 rotation = glm::mat4_cast(entity->getRotation()); - glm::mat4 registration = glm::translate(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - - entity->getRegistrationPoint()); - result = translation * rotation /* * registration */; + result = translation * rotation; } }); } @@ -1753,9 +1751,7 @@ glm::mat4 EntityScriptingInterface::getEntityLocalTransform(const QUuid& entityI if (entity) { glm::mat4 translation = glm::translate(entity->getLocalPosition()); glm::mat4 rotation = glm::mat4_cast(entity->getLocalOrientation()); - glm::mat4 registration = glm::translate(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - - entity->getRegistrationPoint()); - result = translation * rotation * registration; + result = translation * rotation; } }); } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 6219e83bf1..e38a556487 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -473,16 +473,9 @@ bool Model::getMeshes(MeshProxyList& result) { Transform offset; offset.setScale(_scale); - // offset.postTranslate(_offset); + offset.postTranslate(_offset); glm::mat4 offsetMat = offset.getMatrix(); - Extents modelExtents = getUnscaledMeshExtents(); - glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; - - const glm::vec3 DEFAULT_ENTITY_REGISTRATION_POINT = glm::vec3(0.5f, 0.5f, 0.5f); - glm::vec3 regis = (DEFAULT_ENTITY_REGISTRATION_POINT - _registrationPoint); - glm::vec3 regisOffset = dimensions * regis; - for (std::shared_ptr mesh : meshes) { if (!mesh) { continue; From 3936ee93f0e08da594a3279fe7505c09994658f5 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 19 Jul 2017 16:34:04 -0700 Subject: [PATCH 17/52] use default scripts path in EditTabView to fix load on OS X --- .../resources/qml/hifi/tablet/EditTabView.qml | 20 +++++++++---------- libraries/shared/src/PathUtils.h | 3 +++ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/EditTabView.qml b/interface/resources/qml/hifi/tablet/EditTabView.qml index e4a20a0316..e94325f399 100644 --- a/interface/resources/qml/hifi/tablet/EditTabView.qml +++ b/interface/resources/qml/hifi/tablet/EditTabView.qml @@ -21,7 +21,7 @@ TabView { enabled: true property string originalUrl: "" - Rectangle { + Rectangle { color: "#404040" Text { @@ -180,7 +180,7 @@ TabView { WebView { id: entityListToolWebView - url: "../../../../../scripts/system/html/entityList.html" + url: Paths.defaultScripts + "/system/html/entityList.html" anchors.fill: parent enabled: true } @@ -194,7 +194,7 @@ TabView { WebView { id: entityPropertiesWebView - url: "../../../../../scripts/system/html/entityProperties.html" + url: Paths.defaultScripts + "/system/html/entityProperties.html" anchors.fill: parent enabled: true } @@ -208,7 +208,7 @@ TabView { WebView { id: gridControlsWebView - url: "../../../../../scripts/system/html/gridControls.html" + url: Paths.defaultScripts + "/system/html/gridControls.html" anchors.fill: parent enabled: true } @@ -222,7 +222,7 @@ TabView { WebView { id: particleExplorerWebView - url: "../../../../../scripts/system/particle_explorer/particleExplorer.html" + url: Paths.defaultScripts + "/system/particle_explorer/particleExplorer.html" anchors.fill: parent enabled: true } @@ -293,16 +293,16 @@ TabView { break; case 'list': editTabView.currentIndex = 1; - break; + break; case 'properties': editTabView.currentIndex = 2; - break; + break; case 'grid': editTabView.currentIndex = 3; - break; + break; case 'particle': editTabView.currentIndex = 4; - break; + break; default: console.warn('Attempt to switch to invalid tab:', id); } @@ -310,4 +310,4 @@ TabView { console.warn('Attempt to switch tabs with invalid input:', JSON.stringify(id)); } } -} \ No newline at end of file +} diff --git a/libraries/shared/src/PathUtils.h b/libraries/shared/src/PathUtils.h index 14eb81dd9a..577c215c9e 100644 --- a/libraries/shared/src/PathUtils.h +++ b/libraries/shared/src/PathUtils.h @@ -13,6 +13,8 @@ #define hifi_PathUtils_h #include +#include + #include "DependencyManager.h" /**jsdoc @@ -24,6 +26,7 @@ class PathUtils : public QObject, public Dependency { Q_OBJECT SINGLETON_DEPENDENCY Q_PROPERTY(QString resources READ resourcesPath) + Q_PROPERTY(QUrl defaultScripts READ defaultScriptsLocation) public: static const QString& resourcesPath(); From 3805228b70635e4c18332fd1f941bffb8d6539a5 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 20 Jul 2017 16:26:51 +0100 Subject: [PATCH 18/52] fixed grab the tablet in third person --- scripts/system/controllers/handControllerGrab.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/handControllerGrab.js b/scripts/system/controllers/handControllerGrab.js index e2de13d4b1..6b671d366f 100644 --- a/scripts/system/controllers/handControllerGrab.js +++ b/scripts/system/controllers/handControllerGrab.js @@ -1034,9 +1034,18 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp) { function getControllerJointIndex(hand) { if (HMD.isHandControllerAvailable()) { - return MyAvatar.getJointIndex(hand === RIGHT_HAND ? - "_CONTROLLER_RIGHTHAND" : - "_CONTROLLER_LEFTHAND"); + var controllerJointIndex = -1; + if (Camera.mode === "first person") { + controllerJointIndex = MyAvatar.getJointIndex(hand === RIGHT_HAND ? + "_CONTROLLER_RIGHTHAND" : + "_CONTROLLER_LEFTHAND"); + } else if (Camera.mode === "third person") { + controllerJointIndex = MyAvatar.getJointIndex(hand === RIGHT_HAND ? + "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : + "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND"); + } + + return controllerJointIndex; } return MyAvatar.getJointIndex("Head"); From 72e5fecb4e6feb98786651a7dd04df66504e38ab Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 20 Jul 2017 16:34:34 -0700 Subject: [PATCH 19/52] do Model::getMeshes on the correct thread. added ModelScriptingInterface::getVertexCount and ModelScriptingInterface::getVertex --- .../src/RenderableModelEntityItem.cpp | 4 ++- libraries/render-utils/src/Model.cpp | 7 ++-- libraries/render-utils/src/Model.h | 2 +- .../src/ModelScriptingInterface.cpp | 35 +++++++++++++++++++ .../src/ModelScriptingInterface.h | 2 ++ 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 5c0c6101a3..9884debcce 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "EntityTreeRenderer.h" #include "EntitiesRendererLogging.h" @@ -1287,5 +1288,6 @@ bool RenderableModelEntityItem::getMeshes(MeshProxyList& result) { if (!_model || !_model->isLoaded()) { return false; } - return _model->getMeshes(result); + BLOCKING_INVOKE_METHOD(_model.get(), "getMeshes", Q_RETURN_ARG(MeshProxyList, result)); + return !result.isEmpty(); } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index e38a556487..3755ca7cfc 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -463,12 +463,13 @@ bool Model::convexHullContains(glm::vec3 point) { return false; } -bool Model::getMeshes(MeshProxyList& result) { +MeshProxyList Model::getMeshes() { + MeshProxyList result; const Geometry::Pointer& renderGeometry = getGeometry(); const Geometry::GeometryMeshes& meshes = renderGeometry->getMeshes(); if (!isLoaded()) { - return false; + return result; } Transform offset; @@ -490,7 +491,7 @@ bool Model::getMeshes(MeshProxyList& result) { result << meshProxy; } - return true; + return result; } void Model::calculateTriangleSets() { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 1738af661b..da8677aeed 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -257,7 +257,7 @@ public: int getResourceDownloadAttempts() { return _renderWatcher.getResourceDownloadAttempts(); } int getResourceDownloadAttemptsRemaining() { return _renderWatcher.getResourceDownloadAttemptsRemaining(); } - bool getMeshes(MeshProxyList& result); + Q_INVOKABLE MeshProxyList getMeshes(); public slots: void loadURLFinished(bool success); diff --git a/libraries/script-engine/src/ModelScriptingInterface.cpp b/libraries/script-engine/src/ModelScriptingInterface.cpp index 762d9ffb29..64fb365d0c 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.cpp +++ b/libraries/script-engine/src/ModelScriptingInterface.cpp @@ -138,6 +138,41 @@ QScriptValue ModelScriptingInterface::transformMesh(glm::mat4 transform, MeshPro return meshToScriptValue(_modelScriptEngine, resultProxy); } +QScriptValue ModelScriptingInterface::getVertexCount(MeshProxy* meshProxy) { + if (!meshProxy) { + return QScriptValue(false); + } + MeshPointer mesh = meshProxy->getMeshPointer(); + if (!mesh) { + return QScriptValue(false); + } + + gpu::BufferView::Index numVertices = (gpu::BufferView::Index)mesh->getNumVertices(); + + return numVertices; +} + +QScriptValue ModelScriptingInterface::getVertex(MeshProxy* meshProxy, int vertexIndex) { + if (!meshProxy) { + return QScriptValue(false); + } + MeshPointer mesh = meshProxy->getMeshPointer(); + if (!mesh) { + return QScriptValue(false); + } + + const gpu::BufferView& vertexBufferView = mesh->getVertexBuffer(); + gpu::BufferView::Index numVertices = (gpu::BufferView::Index)mesh->getNumVertices(); + + if (vertexIndex < 0 || vertexIndex >= numVertices) { + return QScriptValue(false); + } + + glm::vec3 pos = vertexBufferView.get(vertexIndex); + return vec3toScriptValue(_modelScriptEngine, pos); +} + + QScriptValue ModelScriptingInterface::newMesh(const QVector& vertices, const QVector& normals, const QVector& faces) { diff --git a/libraries/script-engine/src/ModelScriptingInterface.h b/libraries/script-engine/src/ModelScriptingInterface.h index ba23623acf..3c239f006f 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.h +++ b/libraries/script-engine/src/ModelScriptingInterface.h @@ -29,6 +29,8 @@ public: Q_INVOKABLE QScriptValue newMesh(const QVector& vertices, const QVector& normals, const QVector& faces); + Q_INVOKABLE QScriptValue getVertexCount(MeshProxy* meshProxy); + Q_INVOKABLE QScriptValue getVertex(MeshProxy* meshProxy, int vertexIndex); private: QScriptEngine* _modelScriptEngine { nullptr }; From 26cc8134eba5d1e1a49ef0a3a7778efdea631968 Mon Sep 17 00:00:00 2001 From: Leander Hasty <1p-cusack@1stplayable.com> Date: Fri, 21 Jul 2017 10:56:24 -0400 Subject: [PATCH 20/52] WL21463 - entitySelectionTool: use multiarg findRayIntersection instead of editOverlay. We're seeing the ignoreRayIntersection flag not take effect before findRayIntersection calls. This may be due to editOverlay and editOverlays becoming non-blocking in 1f7d2b2 . This altered the flow in mousePressEvent significantly; the first block, intended to handle scale/clone only, started handling rotation (should have been second block) and sometimes selection (should have been third block). Similarly, in the various rotate grabbers' onMove methods, the pickRay will no longer intersect anything other than rotateOverlayTarget; this avoids some awful behavior when scrubbing over the size and clone grabbers. This also reverts unnecessary parts of the prior commits to keep the diff for this WL cleaner, and adds a few TODO comments to revisit about redundant statements and incorrect names. In addition, we've noticed but not fixed herein: * There is a minor edgecase near 0 and 180, where it's difficult to get within a degree or two of the poles occasionally. * The scale/clone grabbers don't stay disappeared for rotation in some cases. This doesn't impact usability anymore, but it'd be nice to determine why they come back when they hide briefly. * The addGrabbers for yaw/pitch/roll could be deduplicated, and yaw has some multiselect "reposition" enable/disable logic that pitch and roll lack. Reviewed-by: LaShonda Hopper --- .../system/libraries/entitySelectionTool.js | 61 ++++--------------- 1 file changed, 12 insertions(+), 49 deletions(-) diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js index 725803f824..2d1853fae2 100644 --- a/scripts/system/libraries/entitySelectionTool.js +++ b/scripts/system/libraries/entitySelectionTool.js @@ -1560,7 +1560,6 @@ SelectionDisplay = (function() { visible: rotationOverlaysVisible }); - // TODO: we have not implemented the rotating handle/controls yet... so for now, these handles are hidden Overlays.editOverlay(yawHandle, { visible: rotateHandlesVisible, position: yawCorner, @@ -3615,24 +3614,21 @@ SelectionDisplay = (function() { onMove: function(event) { var pickRay = generalComputePickRay(event.x, event.y); Overlays.editOverlay(selectionBox, { - ignoreRayIntersection: true, visible: false }); Overlays.editOverlay(baseOfEntityProjectionOverlay, { - ignoreRayIntersection: true, visible: false }); - Overlays.editOverlay(rotateOverlayTarget, { - ignoreRayIntersection: false - }); - var result = Overlays.findRayIntersection(pickRay); + var result = Overlays.findRayIntersection(pickRay, true, [rotateOverlayTarget]); if (result.intersects) { var center = yawCenter; var zero = yawZero; + // TODO: these vectors are backwards to their names, doesn't matter for this use case (inverted vectors still give same angle) var centerToZero = Vec3.subtract(center, zero); var centerToIntersect = Vec3.subtract(center, result.intersection); + // TODO: orientedAngle wants normalized centerToZero and centerToIntersect var angleFromZero = Vec3.orientedAngle(centerToZero, centerToIntersect, rotationNormal); var distanceFromCenter = Vec3.distance(center, result.intersection); var snapToInner = distanceFromCenter < innerRadius; @@ -3785,17 +3781,12 @@ SelectionDisplay = (function() { onMove: function(event) { var pickRay = generalComputePickRay(event.x, event.y); Overlays.editOverlay(selectionBox, { - ignoreRayIntersection: true, visible: false }); Overlays.editOverlay(baseOfEntityProjectionOverlay, { - ignoreRayIntersection: true, visible: false }); - Overlays.editOverlay(rotateOverlayTarget, { - ignoreRayIntersection: false - }); - var result = Overlays.findRayIntersection(pickRay); + var result = Overlays.findRayIntersection(pickRay, true, [rotateOverlayTarget]); if (result.intersects) { var properties = Entities.getEntityProperties(selectionManager.selections[0]); @@ -3947,17 +3938,12 @@ SelectionDisplay = (function() { onMove: function(event) { var pickRay = generalComputePickRay(event.x, event.y); Overlays.editOverlay(selectionBox, { - ignoreRayIntersection: true, visible: false }); Overlays.editOverlay(baseOfEntityProjectionOverlay, { - ignoreRayIntersection: true, visible: false }); - Overlays.editOverlay(rotateOverlayTarget, { - ignoreRayIntersection: false - }); - var result = Overlays.findRayIntersection(pickRay); + var result = Overlays.findRayIntersection(pickRay, true, [rotateOverlayTarget]); if (result.intersects) { var properties = Entities.getEntityProperties(selectionManager.selections[0]); @@ -4074,21 +4060,8 @@ SelectionDisplay = (function() { return false; } - // before we do a ray test for grabbers, disable the ray intersection for our selection box - Overlays.editOverlay(selectionBox, { - ignoreRayIntersection: true - }); - Overlays.editOverlay(yawHandle, { - ignoreRayIntersection: true - }); - Overlays.editOverlay(pitchHandle, { - ignoreRayIntersection: true - }); - Overlays.editOverlay(rollHandle, { - ignoreRayIntersection: true - }); - - result = Overlays.findRayIntersection(pickRay); + // ignore ray intersection for our selection box and yaw/pitch/roll + result = Overlays.findRayIntersection(pickRay, true, null, [ yawHandle, pitchHandle, rollHandle, selectionBox ] ); if (result.intersects) { if (wantDebug) { print("something intersects... "); @@ -4191,17 +4164,8 @@ SelectionDisplay = (function() { } - // After testing our stretch handles, then check out rotate handles - Overlays.editOverlay(yawHandle, { - ignoreRayIntersection: false - }); - Overlays.editOverlay(pitchHandle, { - ignoreRayIntersection: false - }); - Overlays.editOverlay(rollHandle, { - ignoreRayIntersection: false - }); - var result = Overlays.findRayIntersection(pickRay); + // Only intersect versus yaw/pitch/roll. + var result = Overlays.findRayIntersection(pickRay, true, [ yawHandle, pitchHandle, rollHandle ] ); var overlayOrientation; var overlayCenter; @@ -4306,6 +4270,7 @@ SelectionDisplay = (function() { }); + // TODO: these three duplicate prior three, remove them. Overlays.editOverlay(yawHandle, { visible: false }); @@ -4402,10 +4367,8 @@ SelectionDisplay = (function() { } if (!somethingClicked) { - Overlays.editOverlay(selectionBox, { - ignoreRayIntersection: false - }); - var result = Overlays.findRayIntersection(pickRay); + // Only intersect versus selectionBox. + var result = Overlays.findRayIntersection(pickRay, true, [selectionBox]); if (result.intersects) { switch (result.overlayID) { case selectionBox: From 33a8ab2d58eead3f286ccf3763fd242cb215a613 Mon Sep 17 00:00:00 2001 From: vladest Date: Fri, 21 Jul 2017 18:18:23 +0200 Subject: [PATCH 21/52] Adjusted according discussion in PR --- .../resources/controllers/keyboardMouse.json | 21 ++++++++++++++++--- interface/src/avatar/MyAvatar.cpp | 4 ++-- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/interface/resources/controllers/keyboardMouse.json b/interface/resources/controllers/keyboardMouse.json index 8baf56684a..2faabf0f91 100644 --- a/interface/resources/controllers/keyboardMouse.json +++ b/interface/resources/controllers/keyboardMouse.json @@ -81,7 +81,11 @@ { "from": { "makeAxis" : ["Keyboard.MouseMoveLeft", "Keyboard.MouseMoveRight"] }, "when": "Keyboard.RightMouseButton", - "to": "Actions.Yaw" + "to": "Actions.Yaw", + "filters": + [ + { "type": "scale", "scale": 0.1 } + ] }, { "from": "Keyboard.W", "to": "Actions.LONGITUDINAL_FORWARD" }, @@ -102,8 +106,19 @@ { "from": "Keyboard.PgDown", "to": "Actions.VERTICAL_DOWN" }, { "from": "Keyboard.PgUp", "to": "Actions.VERTICAL_UP" }, - { "from": "Keyboard.MouseMoveUp", "when": "Keyboard.RightMouseButton", "to": "Actions.PITCH_UP" }, - { "from": "Keyboard.MouseMoveDown", "when": "Keyboard.RightMouseButton", "to": "Actions.PITCH_DOWN" }, + { "from": "Keyboard.MouseMoveUp", "when": "Keyboard.RightMouseButton", "to": "Actions.PITCH_UP", + "filters": + [ + { "type": "scale", "scale": 0.1 } + ] + + }, + { "from": "Keyboard.MouseMoveDown", "when": "Keyboard.RightMouseButton", "to": "Actions.PITCH_DOWN", + "filters": + [ + { "type": "scale", "scale": 0.1 } + ] + }, { "from": "Keyboard.TouchpadDown", "to": "Actions.PITCH_DOWN" }, { "from": "Keyboard.TouchpadUp", "to": "Actions.PITCH_UP" }, diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index a6958c9089..b32ef4024e 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -69,8 +69,8 @@ const float MAX_BOOST_SPEED = 0.5f * MAX_WALKING_SPEED; // action motor gets add const float MIN_AVATAR_SPEED = 0.05f; const float MIN_AVATAR_SPEED_SQUARED = MIN_AVATAR_SPEED * MIN_AVATAR_SPEED; // speed is set to zero below this -const float YAW_SPEED_DEFAULT = 60.0f; // degrees/sec -const float PITCH_SPEED_DEFAULT = 45.0f; // degrees/sec +const float YAW_SPEED_DEFAULT = 100.0f; // degrees/sec +const float PITCH_SPEED_DEFAULT = 75.0f; // degrees/sec // TODO: normalize avatar speed for standard avatar size, then scale all motion logic // to properly follow avatar size. From d1c2218a31e52305dbabfa151e4499c90b3a631c Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 20 Jul 2017 17:06:36 -0700 Subject: [PATCH 22/52] Temporary patch for deadlock --- interface/src/scripting/AudioDevices.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index a284e38dac..3416366558 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -63,6 +63,14 @@ QVariant AudioDeviceList::data(const QModelIndex& index, int role) const { void AudioDeviceList::resetDevice(bool contextIsHMD, const QString& device) { auto client = DependencyManager::get().data(); auto deviceName = getSetting(contextIsHMD, _mode).get(); + + // FIXME hack to prevent deadlock on startup. The real fix will be to have the + // audio client emit success and failure messages in response to audio device + // switches made here +#if 1 + QMetaObject::invokeMethod(client, "switchAudioDevice", + Q_ARG(QAudio::Mode, _mode), Q_ARG(QString, deviceName)); +#else bool switchResult = false; QMetaObject::invokeMethod(client, "switchAudioDevice", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, switchResult), @@ -85,6 +93,7 @@ void AudioDeviceList::resetDevice(bool contextIsHMD, const QString& device) { QMetaObject::invokeMethod(client, "switchAudioDevice", Q_ARG(QAudio::Mode, _mode)); } } +#endif } void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device) { @@ -201,6 +210,14 @@ void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList(); + + // FIXME hack to prevent deadlock on startup +#if 1 + QMetaObject::invokeMethod(client.data(), "switchAudioDevice", + Q_ARG(QAudio::Mode, QAudio::AudioInput), + Q_ARG(const QAudioDeviceInfo&, device)); + onDeviceSelected(QAudio::AudioInput, device, _inputs._selectedDevice); +#else bool success = false; QMetaObject::invokeMethod(client.data(), "switchAudioDevice", Qt::BlockingQueuedConnection, @@ -211,6 +228,7 @@ void AudioDevices::chooseInputDevice(const QAudioDeviceInfo& device) { if (success) { onDeviceSelected(QAudio::AudioInput, device, _inputs._selectedDevice); } +#endif } void AudioDevices::chooseOutputDevice(const QAudioDeviceInfo& device) { From 5b5e94700ecc20e0cfd939bec833e8f14a4e187d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 20 Jul 2017 18:17:09 -0700 Subject: [PATCH 23/52] Additional audio fixes --- interface/src/scripting/AudioDevices.cpp | 70 +++++++++++------------- interface/src/scripting/AudioDevices.h | 6 +- 2 files changed, 37 insertions(+), 39 deletions(-) diff --git a/interface/src/scripting/AudioDevices.cpp b/interface/src/scripting/AudioDevices.cpp index 3416366558..d02f4d8fcf 100644 --- a/interface/src/scripting/AudioDevices.cpp +++ b/interface/src/scripting/AudioDevices.cpp @@ -36,6 +36,21 @@ Setting::Handle& getSetting(bool contextIsHMD, QAudio::Mode mode) { } } +static QString getTargetDevice(bool hmd, QAudio::Mode mode) { + QString deviceName; + auto& setting = getSetting(hmd, mode); + if (setting.isSet()) { + deviceName = setting.get(); + } else if (hmd) { + if (mode == QAudio::AudioInput) { + deviceName = qApp->getActiveDisplayPlugin()->getPreferredAudioInDevice(); + } else { // if (_mode == QAudio::AudioOutput) + deviceName = qApp->getActiveDisplayPlugin()->getPreferredAudioOutDevice(); + } + } + return deviceName; +} + QHash AudioDeviceList::_roles { { Qt::DisplayRole, "display" }, { Qt::CheckStateRole, "selected" }, @@ -59,18 +74,15 @@ QVariant AudioDeviceList::data(const QModelIndex& index, int role) const { } } - -void AudioDeviceList::resetDevice(bool contextIsHMD, const QString& device) { +void AudioDeviceList::resetDevice(bool contextIsHMD) { auto client = DependencyManager::get().data(); - auto deviceName = getSetting(contextIsHMD, _mode).get(); - - // FIXME hack to prevent deadlock on startup. The real fix will be to have the - // audio client emit success and failure messages in response to audio device - // switches made here -#if 1 + QString deviceName = getTargetDevice(contextIsHMD, _mode); + // FIXME can't use blocking connections here, so we can't determine whether the switch succeeded or not + // We need to have the AudioClient emit signals on switch success / failure QMetaObject::invokeMethod(client, "switchAudioDevice", Q_ARG(QAudio::Mode, _mode), Q_ARG(QString, deviceName)); -#else + +#if 0 bool switchResult = false; QMetaObject::invokeMethod(client, "switchAudioDevice", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, switchResult), @@ -146,11 +158,8 @@ AudioDevices::AudioDevices(bool& contextIsHMD) : _contextIsHMD(contextIsHMD) { } void AudioDevices::onContextChanged(const QString& context) { - auto input = getSetting(_contextIsHMD, QAudio::AudioInput).get(); - auto output = getSetting(_contextIsHMD, QAudio::AudioOutput).get(); - - _inputs.resetDevice(_contextIsHMD, input); - _outputs.resetDevice(_contextIsHMD, output); + _inputs.resetDevice(_contextIsHMD); + _outputs.resetDevice(_contextIsHMD); } void AudioDevices::onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& device, const QAudioDeviceInfo& previousDevice) { @@ -191,8 +200,16 @@ void AudioDevices::onDeviceSelected(QAudio::Mode mode, const QAudioDeviceInfo& d void AudioDevices::onDeviceChanged(QAudio::Mode mode, const QAudioDeviceInfo& device) { if (mode == QAudio::AudioInput) { + if (_requestedInputDevice == device) { + onDeviceSelected(QAudio::AudioInput, device, _inputs._selectedDevice); + _requestedInputDevice = QAudioDeviceInfo(); + } _inputs.onDeviceChanged(device); } else { // if (mode == QAudio::AudioOutput) + if (_requestedOutputDevice == device) { + onDeviceSelected(QAudio::AudioOutput, device, _outputs._selectedDevice); + _requestedOutputDevice = QAudioDeviceInfo(); + } _outputs.onDeviceChanged(device); } } @@ -210,37 +227,16 @@ void AudioDevices::onDevicesChanged(QAudio::Mode mode, const QList(); - - // FIXME hack to prevent deadlock on startup -#if 1 + _requestedInputDevice = device; QMetaObject::invokeMethod(client.data(), "switchAudioDevice", Q_ARG(QAudio::Mode, QAudio::AudioInput), Q_ARG(const QAudioDeviceInfo&, device)); - onDeviceSelected(QAudio::AudioInput, device, _inputs._selectedDevice); -#else - bool success = false; - QMetaObject::invokeMethod(client.data(), "switchAudioDevice", - Qt::BlockingQueuedConnection, - Q_RETURN_ARG(bool, success), - Q_ARG(QAudio::Mode, QAudio::AudioInput), - Q_ARG(const QAudioDeviceInfo&, device)); - - if (success) { - onDeviceSelected(QAudio::AudioInput, device, _inputs._selectedDevice); - } -#endif } void AudioDevices::chooseOutputDevice(const QAudioDeviceInfo& device) { auto client = DependencyManager::get(); - bool success = false; + _requestedOutputDevice = device; QMetaObject::invokeMethod(client.data(), "switchAudioDevice", - Qt::BlockingQueuedConnection, - Q_RETURN_ARG(bool, success), Q_ARG(QAudio::Mode, QAudio::AudioOutput), Q_ARG(const QAudioDeviceInfo&, device)); - - if (success) { - onDeviceSelected(QAudio::AudioOutput, device, _outputs._selectedDevice); - } } diff --git a/interface/src/scripting/AudioDevices.h b/interface/src/scripting/AudioDevices.h index a17c577535..3278a53374 100644 --- a/interface/src/scripting/AudioDevices.h +++ b/interface/src/scripting/AudioDevices.h @@ -39,7 +39,7 @@ public: QVariant data(const QModelIndex& index, int role) const override; // reset device to the last selected device in this context, or the default - void resetDevice(bool contextIsHMD, const QString& device); + void resetDevice(bool contextIsHMD); signals: void deviceChanged(const QAudioDeviceInfo& device); @@ -87,8 +87,10 @@ private: AudioDeviceList _inputs { QAudio::AudioInput }; AudioDeviceList _outputs { QAudio::AudioOutput }; + QAudioDeviceInfo _requestedOutputDevice; + QAudioDeviceInfo _requestedInputDevice; - bool& _contextIsHMD; + const bool& _contextIsHMD; }; }; From 615a3c52e4f74599912021bd6e067b8ad1a35f47 Mon Sep 17 00:00:00 2001 From: vladest Date: Fri, 21 Jul 2017 21:26:33 +0200 Subject: [PATCH 24/52] Ooops.. --- interface/resources/controllers/keyboardMouse.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/resources/controllers/keyboardMouse.json b/interface/resources/controllers/keyboardMouse.json index 2faabf0f91..c384817ff6 100644 --- a/interface/resources/controllers/keyboardMouse.json +++ b/interface/resources/controllers/keyboardMouse.json @@ -84,7 +84,7 @@ "to": "Actions.Yaw", "filters": [ - { "type": "scale", "scale": 0.1 } + { "type": "scale", "scale": 0.6 } ] }, @@ -109,14 +109,14 @@ { "from": "Keyboard.MouseMoveUp", "when": "Keyboard.RightMouseButton", "to": "Actions.PITCH_UP", "filters": [ - { "type": "scale", "scale": 0.1 } + { "type": "scale", "scale": 0.6 } ] }, { "from": "Keyboard.MouseMoveDown", "when": "Keyboard.RightMouseButton", "to": "Actions.PITCH_DOWN", "filters": [ - { "type": "scale", "scale": 0.1 } + { "type": "scale", "scale": 0.6 } ] }, From 5e04e849535f484fc60902878886ded483f7fc34 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 22 Jul 2017 11:57:51 -0700 Subject: [PATCH 25/52] make OBJ reader able to handle files where some vertices have colors and others don't --- libraries/fbx/src/OBJReader.cpp | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index a171f92907..5ec6a9023d 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -118,7 +118,7 @@ glm::vec3 OBJTokenizer::getVec3() { auto z = getFloat(); auto v = glm::vec3(x, y, z); while (isNextTokenFloat()) { - // the spec(s) get(s) vague here. might be w, might be a color... chop it off. + // ignore any following floats nextToken(); } return v; @@ -130,6 +130,7 @@ bool OBJTokenizer::getVertex(glm::vec3& vertex, glm::vec3& vertexColor) { auto y = getFloat(); // And order of arguments is different on Windows/Linux. auto z = getFloat(); vertex = glm::vec3(x, y, z); + vertexColor = glm::vec3(1.0f); // default, in case there is not color information auto r = 1.0f, g = 1.0f, b = 1.0f; bool hasVertexColor = false; @@ -139,7 +140,7 @@ bool OBJTokenizer::getVertex(glm::vec3& vertex, glm::vec3& vertexColor) { // only a single value) that it's a vertex color. r = getFloat(); if (isNextTokenFloat()) { - // Safe to assume the following values are the green/blue components. + // Safe to assume the following values are the green/blue components. g = getFloat(); b = getFloat(); @@ -351,6 +352,8 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi bool result = true; int originalFaceCountForDebugging = 0; QString currentGroup; + bool anyVertexColor { false }; + int vertexCount { 0 }; setMeshPartDefaults(meshPart, QString("dontknow") + QString::number(mesh.parts.count())); @@ -416,10 +419,20 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi bool hasVertexColor = tokenizer.getVertex(vertex, vertexColor); vertices.append(vertex); - - if(hasVertexColor) { + + // if any vertex has color, they all need to. + if (hasVertexColor && !anyVertexColor) { + // we've had a gap of zero or more vertices without color, followed + // by one that has color. catch up: + for (int i = 0; i < vertexCount; i++) { + vertexColors.append(glm::vec3(1.0f)); + } + anyVertexColor = true; + } + if (anyVertexColor) { vertexColors.append(vertexColor); } + vertexCount++; } else if (token == "vn") { normals.append(tokenizer.getVec3()); } else if (token == "vt") { From 6f86b266cbd8a972c8bf60ecd84d9f647c46c487 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 23 Jul 2017 08:04:34 -0700 Subject: [PATCH 26/52] support writing of vertex colors --- libraries/fbx/src/OBJWriter.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/libraries/fbx/src/OBJWriter.cpp b/libraries/fbx/src/OBJWriter.cpp index 034263eb53..e0d3d36b06 100644 --- a/libraries/fbx/src/OBJWriter.cpp +++ b/libraries/fbx/src/OBJWriter.cpp @@ -40,8 +40,6 @@ static QString formatFloat(double n) { } bool writeOBJToTextStream(QTextStream& out, QList meshes) { - int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h - // each mesh's vertices are numbered from zero. We're combining all their vertices into one list here, // so keep track of the start index for each mesh. QList meshVertexStartOffset; @@ -49,10 +47,15 @@ bool writeOBJToTextStream(QTextStream& out, QList meshes) { int currentVertexStartOffset = 0; int currentNormalStartOffset = 0; - // write out vertices + // write out vertices (and maybe colors) foreach (const MeshPointer& mesh, meshes) { meshVertexStartOffset.append(currentVertexStartOffset); const gpu::BufferView& vertexBuffer = mesh->getVertexBuffer(); + + const gpu::BufferView& colorsBufferView = mesh->getAttributeBuffer(gpu::Stream::COLOR); + gpu::BufferView::Index numColors = (gpu::BufferView::Index)colorsBufferView.getNumElements(); + gpu::BufferView::Index colorIndex = 0; + int vertexCount = 0; gpu::BufferView::Iterator vertexItr = vertexBuffer.cbegin(); while (vertexItr != vertexBuffer.cend()) { @@ -60,7 +63,15 @@ bool writeOBJToTextStream(QTextStream& out, QList meshes) { out << "v "; out << formatFloat(v[0]) << " "; out << formatFloat(v[1]) << " "; - out << formatFloat(v[2]) << "\n"; + out << formatFloat(v[2]); + if (colorIndex < numColors) { + glm::vec3 color = colorsBufferView.get(colorIndex); + out << " " << formatFloat(color[0]); + out << " " << formatFloat(color[1]); + out << " " << formatFloat(color[2]); + colorIndex++; + } + out << "\n"; vertexItr++; vertexCount++; } @@ -72,7 +83,7 @@ bool writeOBJToTextStream(QTextStream& out, QList meshes) { bool haveNormals = true; foreach (const MeshPointer& mesh, meshes) { meshNormalStartOffset.append(currentNormalStartOffset); - const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(attributeTypeNormal); + const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(gpu::Stream::InputSlot::NORMAL); gpu::BufferView::Index numNormals = (gpu::BufferView::Index)normalsBufferView.getNumElements(); for (gpu::BufferView::Index i = 0; i < numNormals; i++) { glm::vec3 normal = normalsBufferView.get(i); From 6e0394865e9ee2f2abc722be2bb6236d77fef53d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 23 Jul 2017 08:05:09 -0700 Subject: [PATCH 27/52] fix bug in getNumElements that kept it from working on buffer-views with a non-zero offset --- libraries/gpu/src/gpu/Buffer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/Buffer.h b/libraries/gpu/src/gpu/Buffer.h index 2eb2267f0d..c5df94235c 100644 --- a/libraries/gpu/src/gpu/Buffer.h +++ b/libraries/gpu/src/gpu/Buffer.h @@ -192,7 +192,7 @@ public: BufferView(const BufferPointer& buffer, Size offset, Size size, const Element& element = DEFAULT_ELEMENT); BufferView(const BufferPointer& buffer, Size offset, Size size, uint16 stride, const Element& element = DEFAULT_ELEMENT); - Size getNumElements() const { return (_size - _offset) / _stride; } + Size getNumElements() const { return _size / _stride; } //Template iterator with random access on the buffer sysmem template From 47ea32f4d3ce94399f37547e25149e9d6f3a143a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 23 Jul 2017 08:06:26 -0700 Subject: [PATCH 28/52] vertex color support in ModelScriptingInterface --- .../src/RenderablePolyVoxEntityItem.cpp | 1 + libraries/model/src/model/Geometry.cpp | 37 ++++++++++++++++++- libraries/model/src/model/Geometry.h | 2 + libraries/render-utils/src/Model.cpp | 12 +++--- .../src/ModelScriptingInterface.cpp | 28 ++++++++++++-- 5 files changed, 70 insertions(+), 10 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 1d309a8e14..6687d4e721 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -1663,6 +1663,7 @@ bool RenderablePolyVoxEntityItem::getMeshes(MeshProxyList& result) { // the mesh will be in voxel-space. transform it into object-space meshProxy = new SimpleMeshProxy( _mesh->map([=](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); }, + [=](glm::vec3 color){ return color; }, [=](glm::vec3 normal){ return glm::normalize(glm::vec3(transform * glm::vec4(normal, 0.0f))); }, [&](uint32_t index){ return index; })); result << meshProxy; diff --git a/libraries/model/src/model/Geometry.cpp b/libraries/model/src/model/Geometry.cpp index ac4c5dc188..5a8f4de0ca 100755 --- a/libraries/model/src/model/Geometry.cpp +++ b/libraries/model/src/model/Geometry.cpp @@ -11,8 +11,6 @@ #include "Geometry.h" -#include - using namespace model; Mesh::Mesh() : @@ -136,11 +134,13 @@ Box Mesh::evalPartsBound(int partStart, int partEnd) const { model::MeshPointer Mesh::map(std::function vertexFunc, + std::function colorFunc, std::function normalFunc, std::function indexFunc) const { // vertex data const gpu::BufferView& vertexBufferView = getVertexBuffer(); gpu::BufferView::Index numVertices = (gpu::BufferView::Index)getNumVertices(); + gpu::Resource::Size vertexSize = numVertices * sizeof(glm::vec3); unsigned char* resultVertexData = new unsigned char[vertexSize]; unsigned char* vertexDataCursor = resultVertexData; @@ -151,6 +151,23 @@ model::MeshPointer Mesh::map(std::function vertexFunc, vertexDataCursor += sizeof(pos); } + // color data + // static const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::NUINT8, gpu::RGBA }; + // int attributeTypeColor = gpu::Stream::InputSlot::COLOR; // libraries/gpu/src/gpu/Stream.h + int attributeTypeColor = gpu::Stream::COLOR; + const gpu::BufferView& colorsBufferView = getAttributeBuffer(attributeTypeColor); + gpu::BufferView::Index numColors = (gpu::BufferView::Index)colorsBufferView.getNumElements(); + + gpu::Resource::Size colorSize = numColors * sizeof(glm::vec3); + unsigned char* resultColorData = new unsigned char[colorSize]; + unsigned char* colorDataCursor = resultColorData; + + for (gpu::BufferView::Index i = 0; i < numColors; i++) { + glm::vec3 color = colorFunc(colorsBufferView.get(i)); + memcpy(colorDataCursor, &color, sizeof(color)); + colorDataCursor += sizeof(color); + } + // normal data int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h const gpu::BufferView& normalsBufferView = getAttributeBuffer(attributeTypeNormal); @@ -187,6 +204,12 @@ model::MeshPointer Mesh::map(std::function vertexFunc, gpu::BufferView resultVertexBufferView(resultVertexBufferPointer, vertexElement); result->setVertexBuffer(resultVertexBufferView); + gpu::Element colorElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); + gpu::Buffer* resultColorsBuffer = new gpu::Buffer(colorSize, resultColorData); + gpu::BufferPointer resultColorsBufferPointer(resultColorsBuffer); + gpu::BufferView resultColorsBufferView(resultColorsBufferPointer, colorElement); + result->addAttribute(attributeTypeColor, resultColorsBufferView); + gpu::Element normalElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); gpu::Buffer* resultNormalsBuffer = new gpu::Buffer(normalSize, resultNormalData); gpu::BufferPointer resultNormalsBufferPointer(resultNormalsBuffer); @@ -215,6 +238,7 @@ model::MeshPointer Mesh::map(std::function vertexFunc, void Mesh::forEach(std::function vertexFunc, + std::function colorFunc, std::function normalFunc, std::function indexFunc) { // vertex data @@ -224,6 +248,15 @@ void Mesh::forEach(std::function vertexFunc, vertexFunc(vertexBufferView.get(i)); } + // color data + int attributeTypeColor = gpu::Stream::InputSlot::COLOR; // libraries/gpu/src/gpu/Stream.h + // int attributeTypeColor = gpu::Stream::COLOR; + const gpu::BufferView& colorsBufferView = getAttributeBuffer(attributeTypeColor); + gpu::BufferView::Index numColors = (gpu::BufferView::Index)colorsBufferView.getNumElements(); + for (gpu::BufferView::Index i = 0; i < numColors; i++) { + colorFunc(colorsBufferView.get(i)); + } + // normal data int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h const gpu::BufferView& normalsBufferView = getAttributeBuffer(attributeTypeNormal); diff --git a/libraries/model/src/model/Geometry.h b/libraries/model/src/model/Geometry.h index f273435545..260de313ab 100755 --- a/libraries/model/src/model/Geometry.h +++ b/libraries/model/src/model/Geometry.h @@ -123,10 +123,12 @@ public: // create a copy of this mesh after passing its vertices, normals, and indexes though the provided functions MeshPointer map(std::function vertexFunc, + std::function colorFunc, std::function normalFunc, std::function indexFunc) const; void forEach(std::function vertexFunc, + std::function colorFunc, std::function normalFunc, std::function indexFunc); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 3755ca7cfc..917d284f86 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -483,11 +483,13 @@ MeshProxyList Model::getMeshes() { } MeshProxy* meshProxy = new SimpleMeshProxy( - mesh->map([=](glm::vec3 position) { - return glm::vec3(offsetMat * glm::vec4(position, 1.0f)); - }, - [=](glm::vec3 normal){ return glm::normalize(glm::vec3(offsetMat * glm::vec4(normal, 0.0f))); }, - [&](uint32_t index){ return index; })); + mesh->map( + [=](glm::vec3 position) { + return glm::vec3(offsetMat * glm::vec4(position, 1.0f)); + }, + [=](glm::vec3 color) { return color; }, + [=](glm::vec3 normal) { return glm::normalize(glm::vec3(offsetMat * glm::vec4(normal, 0.0f))); }, + [&](uint32_t index) { return index; })); result << meshProxy; } diff --git a/libraries/script-engine/src/ModelScriptingInterface.cpp b/libraries/script-engine/src/ModelScriptingInterface.cpp index 64fb365d0c..3234a079ec 100644 --- a/libraries/script-engine/src/ModelScriptingInterface.cpp +++ b/libraries/script-engine/src/ModelScriptingInterface.cpp @@ -38,16 +38,22 @@ QString ModelScriptingInterface::meshToOBJ(MeshProxyList in) { QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { // figure out the size of the resulting mesh size_t totalVertexCount { 0 }; - size_t totalAttributeCount { 0 }; + size_t totalColorCount { 0 }; + size_t totalNormalCount { 0 }; size_t totalIndexCount { 0 }; foreach (const MeshProxy* meshProxy, in) { MeshPointer mesh = meshProxy->getMeshPointer(); totalVertexCount += mesh->getNumVertices(); + int attributeTypeColor = gpu::Stream::InputSlot::COLOR; // libraries/gpu/src/gpu/Stream.h + const gpu::BufferView& colorsBufferView = mesh->getAttributeBuffer(attributeTypeColor); + gpu::BufferView::Index numColors = (gpu::BufferView::Index)colorsBufferView.getNumElements(); + totalColorCount += numColors; + int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h const gpu::BufferView& normalsBufferView = mesh->getAttributeBuffer(attributeTypeNormal); gpu::BufferView::Index numNormals = (gpu::BufferView::Index)normalsBufferView.getNumElements(); - totalAttributeCount += numNormals; + totalNormalCount += numNormals; totalIndexCount += mesh->getNumIndices(); } @@ -57,7 +63,11 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { unsigned char* combinedVertexData = new unsigned char[combinedVertexSize]; unsigned char* combinedVertexDataCursor = combinedVertexData; - gpu::Resource::Size combinedNormalSize = totalAttributeCount * sizeof(glm::vec3); + gpu::Resource::Size combinedColorSize = totalColorCount * sizeof(glm::vec3); + unsigned char* combinedColorData = new unsigned char[combinedColorSize]; + unsigned char* combinedColorDataCursor = combinedColorData; + + gpu::Resource::Size combinedNormalSize = totalNormalCount * sizeof(glm::vec3); unsigned char* combinedNormalData = new unsigned char[combinedNormalSize]; unsigned char* combinedNormalDataCursor = combinedNormalData; @@ -74,6 +84,10 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { memcpy(combinedVertexDataCursor, &position, sizeof(position)); combinedVertexDataCursor += sizeof(position); }, + [&](glm::vec3 color){ + memcpy(combinedColorDataCursor, &color, sizeof(color)); + combinedColorDataCursor += sizeof(color); + }, [&](glm::vec3 normal){ memcpy(combinedNormalDataCursor, &normal, sizeof(normal)); combinedNormalDataCursor += sizeof(normal); @@ -96,6 +110,13 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) { gpu::BufferView combinedVertexBufferView(combinedVertexBufferPointer, vertexElement); result->setVertexBuffer(combinedVertexBufferView); + int attributeTypeColor = gpu::Stream::InputSlot::COLOR; // libraries/gpu/src/gpu/Stream.h + gpu::Element colorElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); + gpu::Buffer* combinedColorsBuffer = new gpu::Buffer(combinedColorSize, combinedColorData); + gpu::BufferPointer combinedColorsBufferPointer(combinedColorsBuffer); + gpu::BufferView combinedColorsBufferView(combinedColorsBufferPointer, colorElement); + result->addAttribute(attributeTypeColor, combinedColorsBufferView); + int attributeTypeNormal = gpu::Stream::InputSlot::NORMAL; // libraries/gpu/src/gpu/Stream.h gpu::Element normalElement = gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ); gpu::Buffer* combinedNormalsBuffer = new gpu::Buffer(combinedNormalSize, combinedNormalData); @@ -132,6 +153,7 @@ QScriptValue ModelScriptingInterface::transformMesh(glm::mat4 transform, MeshPro } model::MeshPointer result = mesh->map([&](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); }, + [&](glm::vec3 color){ return color; }, [&](glm::vec3 normal){ return glm::vec3(transform * glm::vec4(normal, 0.0f)); }, [&](uint32_t index){ return index; }); MeshProxy* resultProxy = new SimpleMeshProxy(result); From a1107deef19c713d84bf1a46c9234745bb6bf31f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 23 Jul 2017 08:21:50 -0700 Subject: [PATCH 29/52] cleanups --- libraries/model/src/model/Geometry.cpp | 3 --- libraries/render-utils/src/Model.cpp | 4 +++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libraries/model/src/model/Geometry.cpp b/libraries/model/src/model/Geometry.cpp index 5a8f4de0ca..5627746c43 100755 --- a/libraries/model/src/model/Geometry.cpp +++ b/libraries/model/src/model/Geometry.cpp @@ -152,8 +152,6 @@ model::MeshPointer Mesh::map(std::function vertexFunc, } // color data - // static const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::NUINT8, gpu::RGBA }; - // int attributeTypeColor = gpu::Stream::InputSlot::COLOR; // libraries/gpu/src/gpu/Stream.h int attributeTypeColor = gpu::Stream::COLOR; const gpu::BufferView& colorsBufferView = getAttributeBuffer(attributeTypeColor); gpu::BufferView::Index numColors = (gpu::BufferView::Index)colorsBufferView.getNumElements(); @@ -250,7 +248,6 @@ void Mesh::forEach(std::function vertexFunc, // color data int attributeTypeColor = gpu::Stream::InputSlot::COLOR; // libraries/gpu/src/gpu/Stream.h - // int attributeTypeColor = gpu::Stream::COLOR; const gpu::BufferView& colorsBufferView = getAttributeBuffer(attributeTypeColor); gpu::BufferView::Index numColors = (gpu::BufferView::Index)colorsBufferView.getNumElements(); for (gpu::BufferView::Index i = 0; i < numColors; i++) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 917d284f86..095712f351 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -488,7 +488,9 @@ MeshProxyList Model::getMeshes() { return glm::vec3(offsetMat * glm::vec4(position, 1.0f)); }, [=](glm::vec3 color) { return color; }, - [=](glm::vec3 normal) { return glm::normalize(glm::vec3(offsetMat * glm::vec4(normal, 0.0f))); }, + [=](glm::vec3 normal) { + return glm::normalize(glm::vec3(offsetMat * glm::vec4(normal, 0.0f))); + }, [&](uint32_t index) { return index; })); result << meshProxy; } From 300b926464e1412be5744316252ba82a1caa8576 Mon Sep 17 00:00:00 2001 From: humbletim Date: Sun, 23 Jul 2017 14:11:59 -0400 Subject: [PATCH 30/52] only call QList::constFirst when history list isn't empty --- interface/src/ui/JSConsole.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/JSConsole.cpp b/interface/src/ui/JSConsole.cpp index ef38ea6d29..394b947372 100644 --- a/interface/src/ui/JSConsole.cpp +++ b/interface/src/ui/JSConsole.cpp @@ -122,7 +122,7 @@ void JSConsole::setScriptEngine(ScriptEngine* scriptEngine) { } void JSConsole::executeCommand(const QString& command) { - if (_commandHistory.constFirst() != command) { + if (_commandHistory.isEmpty() || _commandHistory.constFirst() != command) { _commandHistory.prepend(command); if (_commandHistory.length() > MAX_HISTORY_SIZE) { _commandHistory.removeLast(); From 630922dd95d39a3c6feeb6bf442f917ad847f92e Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 24 Jul 2017 05:25:52 +0100 Subject: [PATCH 31/52] Dominant Hands Branch Initial Commit Adds a new option in the Avatar Basics section of the Avatar Settings. API Accessible Functions: MyAvatar.getUseAlternativeHand() MyAvatar.setUseAlternativeHand() Defaults to false (Right Hand). Will return True if set to Left Hand. --- .../qml/controls-uit/RadioButton.qml | 71 ++++++++++++ .../preferences/PrimaryHandPreference.qml | 102 ++++++++++++++++++ .../qml/dialogs/preferences/Section.qml | 5 + interface/src/avatar/MyAvatar.cpp | 3 +- interface/src/avatar/MyAvatar.h | 5 +- interface/src/ui/PreferencesDialog.cpp | 6 ++ libraries/shared/src/Preferences.h | 9 ++ 7 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 interface/resources/qml/controls-uit/RadioButton.qml create mode 100644 interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml diff --git a/interface/resources/qml/controls-uit/RadioButton.qml b/interface/resources/qml/controls-uit/RadioButton.qml new file mode 100644 index 0000000000..76b7902435 --- /dev/null +++ b/interface/resources/qml/controls-uit/RadioButton.qml @@ -0,0 +1,71 @@ +// +// RadioButton.qml +// +// Created by Cain Kilgore on 20th July 2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 as Original +import QtQuick.Controls.Styles 1.4 + +import "../styles-uit" +import "../controls-uit" as HifiControls + +Original.RadioButton { + id: radioButton + HifiConstants { id: hifi } + + property int colorScheme: hifi.colorSchemes.light + readonly property bool isLightColorScheme: colorScheme == hifi.colorSchemes.light + + readonly property int boxSize: 14 + readonly property int boxRadius: 3 + readonly property int checkSize: 10 + readonly property int checkRadius: 2 + + style: RadioButtonStyle { + indicator: Rectangle { + id: box + width: boxSize + height: boxSize + radius: boxRadius + gradient: Gradient { + GradientStop { + position: 0.2 + color: pressed || hovered + ? (radioButton.isLightColorScheme ? hifi.colors.checkboxDarkStart : hifi.colors.checkboxLightStart) + : (radioButton.isLightColorScheme ? hifi.colors.checkboxLightStart : hifi.colors.checkboxDarkStart) + } + GradientStop { + position: 1.0 + color: pressed || hovered + ? (radioButton.isLightColorScheme ? hifi.colors.checkboxDarkFinish : hifi.colors.checkboxLightFinish) + : (radioButton.isLightColorScheme ? hifi.colors.checkboxLightFinish : hifi.colors.checkboxDarkFinish) + } + } + + Rectangle { + id: check + width: checkSize + height: checkSize + radius: checkRadius + anchors.centerIn: parent + color: hifi.colors.checkBoxChecked + border.width: 1 + border.color: hifi.colors.checkBoxCheckedBorder + visible: checked && !pressed || !checked && pressed + } + } + + label: RalewaySemiBold { + text: control.text + size: hifi.fontSizes.inputLabel + color: isLightColorScheme ? hifi.colors.lightGray : hifi.colors.lightGrayText + x: radioButton.boxSize / 2 + } + } +} diff --git a/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml b/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml new file mode 100644 index 0000000000..74044ea27d --- /dev/null +++ b/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml @@ -0,0 +1,102 @@ +// +// PrimaryHandPreference.qml +// +// Created by Cain Kilgore on 20th July 2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 + +import "../../controls-uit" + +Preference { + id: root + property alias box1: box1 + property alias box2: box2 + + height: control.height + hifi.dimensions.controlInterlineHeight + + Component.onCompleted: { + if(preference.value) { + box1.checked = true; + } else { + box2.checked = true; + } + } + + function save() { + // Box1 = True, Box2 = False (Right Hand for Default) + if(box1.checked && !box2.checked) { + preference.value = true; + } + if(!box1.checked && box2.checked) { + preference.value = false; + } + preference.save(); + } + + Item { + id: control + anchors { + left: parent.left + right: parent.right + bottom: parent.bottom + } + height: Math.max(labelName.height, box1.height, box2.height) + + Label { + id: labelName + text: root.label + ":" + colorScheme: hifi.colorSchemes.dark + anchors { + left: parent.left + right: box1.left + rightMargin: hifi.dimensions.labelPadding + verticalCenter: parent.verticalCenter + } + horizontalAlignment: Text.AlignRight + wrapMode: Text.Wrap + } + + RadioButton { + id: box1 + text: "Left" + width: 60 + anchors { + right: box2.left + verticalCenter: parent.verticalCenter + } + onClicked: { + if(box2.checked) { + box2.checked = false; + } + if(!box1.checked && !box2.checked) { + box2.checked = true; + } + } + colorScheme: hifi.colorSchemes.dark + } + + RadioButton { + id: box2 + text: "Right" + width: 60 + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + } + onClicked: { + if(box1.checked) { + box1.checked = false; + } + if(!box1.checked && !box2.checked) { + box2.checked = true; + } + } + colorScheme: hifi.colorSchemes.dark + } + } +} diff --git a/interface/resources/qml/dialogs/preferences/Section.qml b/interface/resources/qml/dialogs/preferences/Section.qml index 3985c7d6f6..af2e58c875 100644 --- a/interface/resources/qml/dialogs/preferences/Section.qml +++ b/interface/resources/qml/dialogs/preferences/Section.qml @@ -73,6 +73,7 @@ Preference { property var buttonBuilder: Component { ButtonPreference { } } property var comboBoxBuilder: Component { ComboBoxPreference { } } property var spinnerSliderBuilder: Component { SpinnerSliderPreference { } } + property var primaryHandBuilder: Component { PrimaryHandPreference { } } property var preferences: [] property int checkBoxCount: 0 @@ -134,6 +135,10 @@ Preference { checkBoxCount = 0; builder = spinnerSliderBuilder; break; + case Preference.PrimaryHand: + checkBoxCount++; + builder = primaryHandBuilder; + break; }; if (builder) { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index f9a4d491c8..0a3d9f4c74 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -926,6 +926,7 @@ void MyAvatar::saveData() { Settings settings; settings.beginGroup("Avatar"); + settings.setValue("useAlternativeHand", _useAlternativeHand); settings.setValue("headPitch", getHead()->getBasePitch()); settings.setValue("scale", _targetScale); @@ -1122,7 +1123,7 @@ void MyAvatar::loadData() { setCollisionSoundURL(settings.value("collisionSoundURL", DEFAULT_AVATAR_COLLISION_SOUND_URL).toString()); setSnapTurn(settings.value("useSnapTurn", _useSnapTurn).toBool()); setClearOverlayWhenMoving(settings.value("clearOverlayWhenMoving", _clearOverlayWhenMoving).toBool()); - + setUseAlternativeHand(settings.value("useAlternativeHand", _useAlternativeHand).toBool()); settings.endGroup(); setEnableMeshVisible(Menu::getInstance()->isOptionChecked(MenuOption::MeshVisible)); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 648a5b5f29..8ff616b36b 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -339,6 +339,9 @@ public: Q_INVOKABLE bool getClearOverlayWhenMoving() const { return _clearOverlayWhenMoving; } Q_INVOKABLE void setClearOverlayWhenMoving(bool on) { _clearOverlayWhenMoving = on; } + Q_INVOKABLE void setUseAlternativeHand(bool hand) { _useAlternativeHand = hand; } + Q_INVOKABLE bool getUseAlternativeHand() const { return _useAlternativeHand; } + Q_INVOKABLE void setHMDLeanRecenterEnabled(bool value) { _hmdLeanRecenterEnabled = value; } Q_INVOKABLE bool getHMDLeanRecenterEnabled() const { return _hmdLeanRecenterEnabled; } @@ -424,7 +427,6 @@ public: Q_INVOKABLE QString getFullAvatarModelName() const { return _fullAvatarModelName; } void resetFullAvatarURL(); - virtual void setAttachmentData(const QVector& attachmentData) override; MyCharacterController* getCharacterController() { return &_characterController; } @@ -720,6 +722,7 @@ private: QUrl _fstAnimGraphOverrideUrl; bool _useSnapTurn { true }; bool _clearOverlayWhenMoving { true }; + bool _useAlternativeHand{ false }; // False defaults to right hand, true to left const float ROLL_CONTROL_DEAD_ZONE_DEFAULT = 8.0f; // deg const float ROLL_CONTROL_RATE_DEFAULT = 2.5f; // deg/sec/deg diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 87131e4f5c..b962b456af 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -67,6 +67,12 @@ void setupPreferences() { auto setter = [=](bool value) { myAvatar->setClearOverlayWhenMoving(value); }; preferences->addPreference(new CheckPreference(AVATAR_BASICS, "Clear overlays when moving", getter, setter)); } + { + auto getter = [=]()->bool { return myAvatar->getUseAlternativeHand(); }; + auto setter = [=](bool value) { myAvatar->setUseAlternativeHand(value); }; + preferences->addPreference(new PrimaryHandPreference(AVATAR_BASICS, "Dominant Hand", getter, setter)); + + } // UI static const QString UI_CATEGORY { "UI" }; diff --git a/libraries/shared/src/Preferences.h b/libraries/shared/src/Preferences.h index 6093cd3c8a..73cce1e909 100644 --- a/libraries/shared/src/Preferences.h +++ b/libraries/shared/src/Preferences.h @@ -56,6 +56,7 @@ public: Checkbox, Button, ComboBox, + PrimaryHand, // Special casing for an unusual preference Avatar }; @@ -339,6 +340,14 @@ public: Type getType() override { return Checkbox; } }; +class PrimaryHandPreference : public BoolPreference { + Q_OBJECT +public: + PrimaryHandPreference(const QString& category, const QString& name, Getter getter, Setter setter) + : BoolPreference(category, name, getter, setter) { } + Type getType() override { return PrimaryHand; } +}; + #endif From a4cf27402dcf541374c1b13d3e938517b3740b75 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 24 Jul 2017 06:27:14 +0100 Subject: [PATCH 32/52] Tabs and Cleanup of Code --- .../preferences/PrimaryHandPreference.qml | 20 +++++++++---------- .../qml/dialogs/preferences/Section.qml | 3 ++- interface/src/ui/PreferencesDialog.cpp | 1 - 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml b/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml index 74044ea27d..af9999ae7a 100644 --- a/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml +++ b/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml @@ -20,7 +20,7 @@ Preference { height: control.height + hifi.dimensions.controlInterlineHeight Component.onCompleted: { - if(preference.value) { + if (preference.value) { box1.checked = true; } else { box2.checked = true; @@ -28,13 +28,13 @@ Preference { } function save() { - // Box1 = True, Box2 = False (Right Hand for Default) - if(box1.checked && !box2.checked) { - preference.value = true; - } - if(!box1.checked && box2.checked) { - preference.value = false; - } + // Box1 = True, Box2 = False (Right Hand for Default) + if (box1.checked && !box2.checked) { + preference.value = true; + } + if (!box1.checked && box2.checked) { + preference.value = false; + } preference.save(); } @@ -70,10 +70,10 @@ Preference { verticalCenter: parent.verticalCenter } onClicked: { - if(box2.checked) { + if (box2.checked) { box2.checked = false; } - if(!box1.checked && !box2.checked) { + if (!box1.checked && !box2.checked) { box2.checked = true; } } diff --git a/interface/resources/qml/dialogs/preferences/Section.qml b/interface/resources/qml/dialogs/preferences/Section.qml index af2e58c875..4a16036a69 100644 --- a/interface/resources/qml/dialogs/preferences/Section.qml +++ b/interface/resources/qml/dialogs/preferences/Section.qml @@ -73,7 +73,7 @@ Preference { property var buttonBuilder: Component { ButtonPreference { } } property var comboBoxBuilder: Component { ComboBoxPreference { } } property var spinnerSliderBuilder: Component { SpinnerSliderPreference { } } - property var primaryHandBuilder: Component { PrimaryHandPreference { } } + property var primaryHandBuilder: Component { PrimaryHandPreference { } } property var preferences: [] property int checkBoxCount: 0 @@ -135,6 +135,7 @@ Preference { checkBoxCount = 0; builder = spinnerSliderBuilder; break; + case Preference.PrimaryHand: checkBoxCount++; builder = primaryHandBuilder; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index b962b456af..fe1663b98d 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -71,7 +71,6 @@ void setupPreferences() { auto getter = [=]()->bool { return myAvatar->getUseAlternativeHand(); }; auto setter = [=](bool value) { myAvatar->setUseAlternativeHand(value); }; preferences->addPreference(new PrimaryHandPreference(AVATAR_BASICS, "Dominant Hand", getter, setter)); - } // UI From 1ce1204a64805ca3fde7ed7430362cb649e53be0 Mon Sep 17 00:00:00 2001 From: milad Date: Mon, 24 Jul 2017 10:06:44 -0500 Subject: [PATCH 33/52] WORKLIST ISSUE # 21471 : FIX PARENT JOINT IN EDIT JS In entityPropeties.js line #1079 says: elParentJointIndex.addEventListener('change', createEmitNumberPropertyUpdateFunction('parentJointIndex')); The problem should be fixed by changing it to: elParentJointIndex.addEventListener('change', createEmitNumberPropertyUpdateFunction('parentJointIndex', 0)); createEmitNumberPropertyUpdateFunction() is parsing the value as a float to a default decimal position of 4. Looks like it only accepts integers. By adding in that 0 as a second argument, it should coerce the value to one that will be recognized by the UI/backend. --- scripts/system/html/js/entityProperties.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index 777ef54085..70594d8f1e 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -1074,7 +1074,7 @@ function loaded() { elDimensionsZ.addEventListener('change', dimensionsChangeFunction); elParentID.addEventListener('change', createEmitTextPropertyUpdateFunction('parentID')); - elParentJointIndex.addEventListener('change', createEmitNumberPropertyUpdateFunction('parentJointIndex')); + elParentJointIndex.addEventListener('change', createEmitNumberPropertyUpdateFunction('parentJointIndex', 0)); var registrationChangeFunction = createEmitVec3PropertyUpdateFunction( 'registrationPoint', elRegistrationX, elRegistrationY, elRegistrationZ); From 42742ba1f9fda98db0fd11281a5b68b5a471fa09 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 24 Jul 2017 18:31:16 +0100 Subject: [PATCH 34/52] Changed the Return to a String "left/right" instead. --- .../qml/dialogs/preferences/PrimaryHandPreference.qml | 6 +++--- interface/src/avatar/MyAvatar.cpp | 4 ++-- interface/src/avatar/MyAvatar.h | 11 ++++++++--- interface/src/ui/PreferencesDialog.cpp | 4 ++-- libraries/shared/src/Preferences.h | 4 ++-- 5 files changed, 17 insertions(+), 12 deletions(-) diff --git a/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml b/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml index af9999ae7a..c89756f678 100644 --- a/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml +++ b/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml @@ -20,7 +20,7 @@ Preference { height: control.height + hifi.dimensions.controlInterlineHeight Component.onCompleted: { - if (preference.value) { + if (preference.value == "left") { box1.checked = true; } else { box2.checked = true; @@ -30,10 +30,10 @@ Preference { function save() { // Box1 = True, Box2 = False (Right Hand for Default) if (box1.checked && !box2.checked) { - preference.value = true; + preference.value = "left"; } if (!box1.checked && box2.checked) { - preference.value = false; + preference.value = "right"; } preference.save(); } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0a3d9f4c74..9b42310c3c 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -926,7 +926,7 @@ void MyAvatar::saveData() { Settings settings; settings.beginGroup("Avatar"); - settings.setValue("useAlternativeHand", _useAlternativeHand); + settings.setValue("dominantHand", _dominantHand); settings.setValue("headPitch", getHead()->getBasePitch()); settings.setValue("scale", _targetScale); @@ -1123,7 +1123,7 @@ void MyAvatar::loadData() { setCollisionSoundURL(settings.value("collisionSoundURL", DEFAULT_AVATAR_COLLISION_SOUND_URL).toString()); setSnapTurn(settings.value("useSnapTurn", _useSnapTurn).toBool()); setClearOverlayWhenMoving(settings.value("clearOverlayWhenMoving", _clearOverlayWhenMoving).toBool()); - setUseAlternativeHand(settings.value("useAlternativeHand", _useAlternativeHand).toBool()); + setDominantHand(settings.value("dominantHand", _dominantHand).toString().toLower()); settings.endGroup(); setEnableMeshVisible(Menu::getInstance()->isOptionChecked(MenuOption::MeshVisible)); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 8ff616b36b..05af26416c 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -339,8 +339,13 @@ public: Q_INVOKABLE bool getClearOverlayWhenMoving() const { return _clearOverlayWhenMoving; } Q_INVOKABLE void setClearOverlayWhenMoving(bool on) { _clearOverlayWhenMoving = on; } - Q_INVOKABLE void setUseAlternativeHand(bool hand) { _useAlternativeHand = hand; } - Q_INVOKABLE bool getUseAlternativeHand() const { return _useAlternativeHand; } + Q_INVOKABLE void setDominantHand(const QString& hand) { + if (hand == "left" || hand == "right") { + _dominantHand = hand; + } + } + + Q_INVOKABLE QString getDominantHand() const { return _dominantHand; } Q_INVOKABLE void setHMDLeanRecenterEnabled(bool value) { _hmdLeanRecenterEnabled = value; } Q_INVOKABLE bool getHMDLeanRecenterEnabled() const { return _hmdLeanRecenterEnabled; } @@ -722,7 +727,7 @@ private: QUrl _fstAnimGraphOverrideUrl; bool _useSnapTurn { true }; bool _clearOverlayWhenMoving { true }; - bool _useAlternativeHand{ false }; // False defaults to right hand, true to left + QString _dominantHand{ "right" }; const float ROLL_CONTROL_DEAD_ZONE_DEFAULT = 8.0f; // deg const float ROLL_CONTROL_RATE_DEFAULT = 2.5f; // deg/sec/deg diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index fe1663b98d..fd0847c945 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -68,8 +68,8 @@ void setupPreferences() { preferences->addPreference(new CheckPreference(AVATAR_BASICS, "Clear overlays when moving", getter, setter)); } { - auto getter = [=]()->bool { return myAvatar->getUseAlternativeHand(); }; - auto setter = [=](bool value) { myAvatar->setUseAlternativeHand(value); }; + auto getter = [=]()->QString { return myAvatar->getDominantHand(); }; + auto setter = [=](const QString& value) { myAvatar->setDominantHand(value); }; preferences->addPreference(new PrimaryHandPreference(AVATAR_BASICS, "Dominant Hand", getter, setter)); } diff --git a/libraries/shared/src/Preferences.h b/libraries/shared/src/Preferences.h index 73cce1e909..6fa2cb9b1f 100644 --- a/libraries/shared/src/Preferences.h +++ b/libraries/shared/src/Preferences.h @@ -340,11 +340,11 @@ public: Type getType() override { return Checkbox; } }; -class PrimaryHandPreference : public BoolPreference { +class PrimaryHandPreference : public StringPreference { Q_OBJECT public: PrimaryHandPreference(const QString& category, const QString& name, Getter getter, Setter setter) - : BoolPreference(category, name, getter, setter) { } + : StringPreference(category, name, getter, setter) { } Type getType() override { return PrimaryHand; } }; From e6fd85f45ac4e748d54af6dbf749668e4c9b3a21 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 24 Jul 2017 19:02:40 +0100 Subject: [PATCH 35/52] Some code cleanup --- .../dialogs/preferences/PrimaryHandPreference.qml | 4 ++-- interface/src/avatar/MyAvatar.cpp | 12 ++++++++++++ interface/src/avatar/MyAvatar.h | 12 +++++++----- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml b/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml index c89756f678..d230f7e0da 100644 --- a/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml +++ b/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml @@ -89,10 +89,10 @@ Preference { verticalCenter: parent.verticalCenter } onClicked: { - if(box1.checked) { + if (box1.checked) { box1.checked = false; } - if(!box1.checked && !box2.checked) { + if (!box1.checked && !box2.checked) { box2.checked = true; } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9b42310c3c..90870f83c2 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -72,6 +72,9 @@ const float MIN_AVATAR_SPEED_SQUARED = MIN_AVATAR_SPEED * MIN_AVATAR_SPEED; // s const float YAW_SPEED_DEFAULT = 120.0f; // degrees/sec const float PITCH_SPEED_DEFAULT = 90.0f; // degrees/sec +const QString DOMINANT_HAND_LEFT = "left"; +const QString DOMINANT_HAND_RIGHT = "right"; + // TODO: normalize avatar speed for standard avatar size, then scale all motion logic // to properly follow avatar size. float MAX_AVATAR_SPEED = 30.0f; @@ -87,6 +90,9 @@ const float MyAvatar::ZOOM_MIN = 0.5f; const float MyAvatar::ZOOM_MAX = 25.0f; const float MyAvatar::ZOOM_DEFAULT = 1.5f; +const QString& DOMINANT_LEFT_HAND = "left"; +const QString& DOMINANT_RIGHT_HAND = "right"; + // default values, used when avatar is missing joints... (avatar space) static const glm::quat DEFAULT_AVATAR_MIDDLE_EYE_ROT { Quaternions::Y_180 }; static const glm::vec3 DEFAULT_AVATAR_MIDDLE_EYE_POS { 0.0f, 0.6f, 0.0f }; @@ -255,6 +261,12 @@ MyAvatar::~MyAvatar() { _lookAtTargetAvatar.reset(); } +void MyAvatar::setDominantHand(const QString& hand) { + if (hand == DOMINANT_HAND_LEFT || hand == DOMINANT_HAND_RIGHT) { + _dominantHand = hand; + } +} + void MyAvatar::registerMetaTypes(QScriptEngine* engine) { QScriptValue value = engine->newQObject(this, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects); engine->globalObject().setProperty("MyAvatar", value); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 05af26416c..0f4d2c7464 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -43,6 +43,12 @@ enum AudioListenerMode { FROM_CAMERA, CUSTOM }; + +enum DominantHand { + LEFT_HAND, + RIGHT_HAND +}; + Q_DECLARE_METATYPE(AudioListenerMode); class MyAvatar : public Avatar { @@ -339,11 +345,7 @@ public: Q_INVOKABLE bool getClearOverlayWhenMoving() const { return _clearOverlayWhenMoving; } Q_INVOKABLE void setClearOverlayWhenMoving(bool on) { _clearOverlayWhenMoving = on; } - Q_INVOKABLE void setDominantHand(const QString& hand) { - if (hand == "left" || hand == "right") { - _dominantHand = hand; - } - } + Q_INVOKABLE void setDominantHand(const QString& hand); Q_INVOKABLE QString getDominantHand() const { return _dominantHand; } From fd2264f7c92d170b4ce34714e01e2d922e3f629a Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 24 Jul 2017 19:05:49 +0100 Subject: [PATCH 36/52] removed duplicate --- interface/src/avatar/MyAvatar.cpp | 3 --- interface/src/avatar/MyAvatar.h | 5 ----- 2 files changed, 8 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 90870f83c2..a0086723ae 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -72,9 +72,6 @@ const float MIN_AVATAR_SPEED_SQUARED = MIN_AVATAR_SPEED * MIN_AVATAR_SPEED; // s const float YAW_SPEED_DEFAULT = 120.0f; // degrees/sec const float PITCH_SPEED_DEFAULT = 90.0f; // degrees/sec -const QString DOMINANT_HAND_LEFT = "left"; -const QString DOMINANT_HAND_RIGHT = "right"; - // TODO: normalize avatar speed for standard avatar size, then scale all motion logic // to properly follow avatar size. float MAX_AVATAR_SPEED = 30.0f; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 0f4d2c7464..1239989c05 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -44,11 +44,6 @@ enum AudioListenerMode { CUSTOM }; -enum DominantHand { - LEFT_HAND, - RIGHT_HAND -}; - Q_DECLARE_METATYPE(AudioListenerMode); class MyAvatar : public Avatar { From 64ba159adf325f5a00fc71b7e87d97242a34ce7a Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 24 Jul 2017 19:12:14 +0100 Subject: [PATCH 37/52] Updating Small Reference --- interface/src/avatar/MyAvatar.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 1239989c05..dc306bd09a 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -724,7 +724,7 @@ private: QUrl _fstAnimGraphOverrideUrl; bool _useSnapTurn { true }; bool _clearOverlayWhenMoving { true }; - QString _dominantHand{ "right" }; + QString _dominantHand{ DOMINANT_RIGHT_HAND }; const float ROLL_CONTROL_DEAD_ZONE_DEFAULT = 8.0f; // deg const float ROLL_CONTROL_RATE_DEFAULT = 2.5f; // deg/sec/deg From 9ff7891c880e94f593eba9db9d468c68fe188928 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 24 Jul 2017 19:56:02 +0100 Subject: [PATCH 38/52] Fixed reference error, Gustavo should build now. --- interface/src/avatar/MyAvatar.cpp | 5 +---- interface/src/avatar/MyAvatar.h | 6 ++++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index a0086723ae..081ab8e8f1 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -87,9 +87,6 @@ const float MyAvatar::ZOOM_MIN = 0.5f; const float MyAvatar::ZOOM_MAX = 25.0f; const float MyAvatar::ZOOM_DEFAULT = 1.5f; -const QString& DOMINANT_LEFT_HAND = "left"; -const QString& DOMINANT_RIGHT_HAND = "right"; - // default values, used when avatar is missing joints... (avatar space) static const glm::quat DEFAULT_AVATAR_MIDDLE_EYE_ROT { Quaternions::Y_180 }; static const glm::vec3 DEFAULT_AVATAR_MIDDLE_EYE_POS { 0.0f, 0.6f, 0.0f }; @@ -259,7 +256,7 @@ MyAvatar::~MyAvatar() { } void MyAvatar::setDominantHand(const QString& hand) { - if (hand == DOMINANT_HAND_LEFT || hand == DOMINANT_HAND_RIGHT) { + if (hand == DOMINANT_LEFT_HAND || hand == DOMINANT_RIGHT_HAND) { _dominantHand = hand; } } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index dc306bd09a..1657f78b26 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -142,6 +142,9 @@ class MyAvatar : public Avatar { Q_PROPERTY(float hmdRollControlDeadZone READ getHMDRollControlDeadZone WRITE setHMDRollControlDeadZone) Q_PROPERTY(float hmdRollControlRate READ getHMDRollControlRate WRITE setHMDRollControlRate) + const QString DOMINANT_LEFT_HAND = "left"; + const QString DOMINANT_RIGHT_HAND = "right"; + public: enum DriveKeys { TRANSLATE_X = 0, @@ -341,7 +344,6 @@ public: Q_INVOKABLE void setClearOverlayWhenMoving(bool on) { _clearOverlayWhenMoving = on; } Q_INVOKABLE void setDominantHand(const QString& hand); - Q_INVOKABLE QString getDominantHand() const { return _dominantHand; } Q_INVOKABLE void setHMDLeanRecenterEnabled(bool value) { _hmdLeanRecenterEnabled = value; } @@ -724,7 +726,7 @@ private: QUrl _fstAnimGraphOverrideUrl; bool _useSnapTurn { true }; bool _clearOverlayWhenMoving { true }; - QString _dominantHand{ DOMINANT_RIGHT_HAND }; + QString _dominantHand { DOMINANT_RIGHT_HAND }; const float ROLL_CONTROL_DEAD_ZONE_DEFAULT = 8.0f; // deg const float ROLL_CONTROL_RATE_DEFAULT = 2.5f; // deg/sec/deg From 9c152ddc6f7d0c86c88b8423a8ee64f295351a29 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 24 Jul 2017 22:30:43 +0100 Subject: [PATCH 39/52] Ticking left will keep it on left, not right --- .../resources/qml/dialogs/preferences/PrimaryHandPreference.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml b/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml index d230f7e0da..07b9c958dd 100644 --- a/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml +++ b/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml @@ -74,7 +74,7 @@ Preference { box2.checked = false; } if (!box1.checked && !box2.checked) { - box2.checked = true; + box1.checked = true; } } colorScheme: hifi.colorSchemes.dark From 7c62ed6dac2c324097f18b9fd49efcd832be5b14 Mon Sep 17 00:00:00 2001 From: utkarshgautamnyu Date: Mon, 24 Jul 2017 14:46:32 -0700 Subject: [PATCH 40/52] made sendRequest depend on hasValidAccessToken being true --- domain-server/src/DomainGatekeeper.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 62f56184f4..6421a50fe3 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -927,9 +927,13 @@ void DomainGatekeeper::getDomainOwnerFriendsList() { callbackParams.errorCallbackMethod = "getDomainOwnerFriendsListErrorCallback"; const QString GET_FRIENDS_LIST_PATH = "api/v1/user/friends"; - DependencyManager::get()->sendRequest(GET_FRIENDS_LIST_PATH, AccountManagerAuth::Required, - QNetworkAccessManager::GetOperation, callbackParams, QByteArray(), - NULL, QVariantMap()); + if (DependencyManager::get()->hasValidAccessToken()) + { + DependencyManager::get()->sendRequest(GET_FRIENDS_LIST_PATH, AccountManagerAuth::Required, + QNetworkAccessManager::GetOperation, callbackParams, QByteArray(), + NULL, QVariantMap()); + } + } void DomainGatekeeper::getDomainOwnerFriendsListJSONCallback(QNetworkReply& requestReply) { From 884bdb3b7e776a21f2216ccd6e248c2e73a7b1b5 Mon Sep 17 00:00:00 2001 From: utkarshgautamnyu Date: Mon, 24 Jul 2017 14:57:22 -0700 Subject: [PATCH 41/52] Update DomainGatekeeper.cpp --- domain-server/src/DomainGatekeeper.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 6421a50fe3..4c9f90b9ae 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -930,8 +930,8 @@ void DomainGatekeeper::getDomainOwnerFriendsList() { if (DependencyManager::get()->hasValidAccessToken()) { DependencyManager::get()->sendRequest(GET_FRIENDS_LIST_PATH, AccountManagerAuth::Required, - QNetworkAccessManager::GetOperation, callbackParams, QByteArray(), - NULL, QVariantMap()); + QNetworkAccessManager::GetOperation, callbackParams, QByteArray(), + NULL, QVariantMap()); } } From 84609f27e36e161d4fb36039823396ec659e5fdf Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 24 Jul 2017 23:53:03 +0100 Subject: [PATCH 42/52] Final Change - They're now Radio Boxes. --- interface/resources/qml/controls-uit/RadioButton.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/controls-uit/RadioButton.qml b/interface/resources/qml/controls-uit/RadioButton.qml index 76b7902435..3cc3db4e46 100644 --- a/interface/resources/qml/controls-uit/RadioButton.qml +++ b/interface/resources/qml/controls-uit/RadioButton.qml @@ -32,7 +32,7 @@ Original.RadioButton { id: box width: boxSize height: boxSize - radius: boxRadius + radius: 7 gradient: Gradient { GradientStop { position: 0.2 @@ -52,7 +52,7 @@ Original.RadioButton { id: check width: checkSize height: checkSize - radius: checkRadius + radius: 7 anchors.centerIn: parent color: hifi.colors.checkBoxChecked border.width: 1 From 5771ee27e1f510a563b4d25b39f8071d3e93d547 Mon Sep 17 00:00:00 2001 From: utkarshgautamnyu Date: Mon, 24 Jul 2017 17:33:01 -0700 Subject: [PATCH 43/52] Update DomainGatekeeper.cpp --- domain-server/src/DomainGatekeeper.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 4c9f90b9ae..da31fed387 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -927,8 +927,7 @@ void DomainGatekeeper::getDomainOwnerFriendsList() { callbackParams.errorCallbackMethod = "getDomainOwnerFriendsListErrorCallback"; const QString GET_FRIENDS_LIST_PATH = "api/v1/user/friends"; - if (DependencyManager::get()->hasValidAccessToken()) - { + if (DependencyManager::get()->hasValidAccessToken()) { DependencyManager::get()->sendRequest(GET_FRIENDS_LIST_PATH, AccountManagerAuth::Required, QNetworkAccessManager::GetOperation, callbackParams, QByteArray(), NULL, QVariantMap()); From 280a7a7e42e5dabf8c6b284bcce4595c660ccd5d Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Tue, 25 Jul 2017 01:48:55 +0100 Subject: [PATCH 44/52] Fixing Styling, added Preference to Tablet, Moved Location to Avatar Tuning --- interface/resources/qml/controls-uit/RadioButton.qml | 4 ++-- .../qml/dialogs/preferences/PrimaryHandPreference.qml | 1 - interface/src/ui/PreferencesDialog.cpp | 10 +++++----- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/interface/resources/qml/controls-uit/RadioButton.qml b/interface/resources/qml/controls-uit/RadioButton.qml index 3cc3db4e46..ab11ec68b1 100644 --- a/interface/resources/qml/controls-uit/RadioButton.qml +++ b/interface/resources/qml/controls-uit/RadioButton.qml @@ -54,9 +54,9 @@ Original.RadioButton { height: checkSize radius: 7 anchors.centerIn: parent - color: hifi.colors.checkBoxChecked + color: "#00B4EF" border.width: 1 - border.color: hifi.colors.checkBoxCheckedBorder + border.color: "#36CDFF" visible: checked && !pressed || !checked && pressed } } diff --git a/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml b/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml index 07b9c958dd..cfc2e94ed9 100644 --- a/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml +++ b/interface/resources/qml/dialogs/preferences/PrimaryHandPreference.qml @@ -28,7 +28,6 @@ Preference { } function save() { - // Box1 = True, Box2 = False (Right Hand for Default) if (box1.checked && !box2.checked) { preference.value = "left"; } diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index fd0847c945..bf99daab67 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -67,11 +67,6 @@ void setupPreferences() { auto setter = [=](bool value) { myAvatar->setClearOverlayWhenMoving(value); }; preferences->addPreference(new CheckPreference(AVATAR_BASICS, "Clear overlays when moving", getter, setter)); } - { - auto getter = [=]()->QString { return myAvatar->getDominantHand(); }; - auto setter = [=](const QString& value) { myAvatar->setDominantHand(value); }; - preferences->addPreference(new PrimaryHandPreference(AVATAR_BASICS, "Dominant Hand", getter, setter)); - } // UI static const QString UI_CATEGORY { "UI" }; @@ -186,6 +181,11 @@ void setupPreferences() { preference->setStep(1); preferences->addPreference(preference); } + { + auto getter = [=]()->QString { return myAvatar->getDominantHand(); }; + auto setter = [=](const QString& value) { myAvatar->setDominantHand(value); }; + preferences->addPreference(new PrimaryHandPreference(AVATAR_TUNING, "Dominant Hand", getter, setter)); + } { auto getter = [=]()->float { return myAvatar->getUniformScale(); }; auto setter = [=](float value) { myAvatar->setTargetScale(value); }; From e900dae70879852c2db0bf9133b8e1fd52d52ede Mon Sep 17 00:00:00 2001 From: Mike Moody Date: Mon, 24 Jul 2017 18:34:58 -0700 Subject: [PATCH 45/52] Created script for spherical gravity. --- unpublishedScripts/gravity.js | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 unpublishedScripts/gravity.js diff --git a/unpublishedScripts/gravity.js b/unpublishedScripts/gravity.js new file mode 100644 index 0000000000..f468bfc717 --- /dev/null +++ b/unpublishedScripts/gravity.js @@ -0,0 +1,55 @@ +// +// gravity.js +// scripts/system/ +// +// Created by Alan-Michael Moody on 7/24/17 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function () { + + var _entityID; + + this.preload = function (entityID) { + _entityID = entityID; + }; + + function update(deltatime) { + var planet = Entities.getEntityProperties(_entityID); + var direction = Vec3.normalize(Vec3.subtract(MyAvatar.position, planet.position)); + var localUp = Quat.getUp(MyAvatar.orientation); + + MyAvatar.orientation = Quat.multiply(Quat.rotationBetween(localUp, direction), MyAvatar.orientation); + } + + function init() { + Script.update.connect(update); + } + + function clean() { + Script.update.disconnect(update); + MyAvatar.orientation = Quat.fromVec3Degrees({ + x: 0, + y: 0, + z: 0 + }); + } + + var _switch = true; + + this.clickDownOnEntity = function(uuid, mouseEvent) { + + if (_switch) { + init(); + } else { + clean(); + } + _switch = !_switch; + }; + + Script.scriptEnding.connect(clean); + +}); \ No newline at end of file From 62efb32671652a9f6629c2fda1f80d396f8dc2c2 Mon Sep 17 00:00:00 2001 From: Mike Moody Date: Mon, 24 Jul 2017 18:39:09 -0700 Subject: [PATCH 46/52] Created script for spherical gravity. --- unpublishedScripts/gravity.js | 1 - 1 file changed, 1 deletion(-) diff --git a/unpublishedScripts/gravity.js b/unpublishedScripts/gravity.js index f468bfc717..a7ad5c889b 100644 --- a/unpublishedScripts/gravity.js +++ b/unpublishedScripts/gravity.js @@ -1,6 +1,5 @@ // // gravity.js -// scripts/system/ // // Created by Alan-Michael Moody on 7/24/17 // Copyright 2016 High Fidelity, Inc. From 1bf2855e9b5a4960333e5c777816a0dfadc8bd58 Mon Sep 17 00:00:00 2001 From: Mike Moody Date: Mon, 24 Jul 2017 18:47:24 -0700 Subject: [PATCH 47/52] Created script for spherical gravity. --- unpublishedScripts/gravity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unpublishedScripts/gravity.js b/unpublishedScripts/gravity.js index a7ad5c889b..ea7ec83d67 100644 --- a/unpublishedScripts/gravity.js +++ b/unpublishedScripts/gravity.js @@ -2,7 +2,7 @@ // gravity.js // // Created by Alan-Michael Moody on 7/24/17 -// Copyright 2016 High Fidelity, Inc. +// Copyright 2017 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html From c4d909927a249824ecf73af4061bf36e9474bd2d Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 24 Jul 2017 19:23:39 -0700 Subject: [PATCH 48/52] make atp-client work again --- tools/atp-client/src/ATPClientApp.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/atp-client/src/ATPClientApp.cpp b/tools/atp-client/src/ATPClientApp.cpp index 3e2f8ca71d..7d091aec74 100644 --- a/tools/atp-client/src/ATPClientApp.cpp +++ b/tools/atp-client/src/ATPClientApp.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include "ATPClientApp.h" @@ -137,6 +138,7 @@ ATPClientApp::ATPClientApp(int argc, char* argv[]) : Setting::init(); DependencyManager::registerInheritance(); + DependencyManager::set(); DependencyManager::set([&]{ return QString(HIGH_FIDELITY_ATP_CLIENT_USER_AGENT); }); DependencyManager::set(); DependencyManager::set(NodeType::Agent, _listenPort); From a3f4aeb1826e2249a2f9e1332f0e108bcaf2d730 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 24 Jul 2017 19:41:30 -0700 Subject: [PATCH 49/52] code review --- libraries/fbx/src/OBJReader.cpp | 4 ++-- libraries/render-utils/src/Model.cpp | 2 +- libraries/render-utils/src/Model.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 5ec6a9023d..3099782588 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -130,7 +130,6 @@ bool OBJTokenizer::getVertex(glm::vec3& vertex, glm::vec3& vertexColor) { auto y = getFloat(); // And order of arguments is different on Windows/Linux. auto z = getFloat(); vertex = glm::vec3(x, y, z); - vertexColor = glm::vec3(1.0f); // default, in case there is not color information auto r = 1.0f, g = 1.0f, b = 1.0f; bool hasVertexColor = false; @@ -415,7 +414,8 @@ bool OBJReader::parseOBJGroup(OBJTokenizer& tokenizer, const QVariantHash& mappi #endif } } else if (token == "v") { - glm::vec3 vertex, vertexColor; + glm::vec3 vertex; + glm::vec3 vertexColor { glm::vec3(1.0f) }; bool hasVertexColor = tokenizer.getVertex(vertex, vertexColor); vertices.append(vertex); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 095712f351..42bb91ce94 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -463,7 +463,7 @@ bool Model::convexHullContains(glm::vec3 point) { return false; } -MeshProxyList Model::getMeshes() { +MeshProxyList Model::getMeshes() const { MeshProxyList result; const Geometry::Pointer& renderGeometry = getGeometry(); const Geometry::GeometryMeshes& meshes = renderGeometry->getMeshes(); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index da8677aeed..497346c138 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -257,7 +257,7 @@ public: int getResourceDownloadAttempts() { return _renderWatcher.getResourceDownloadAttempts(); } int getResourceDownloadAttemptsRemaining() { return _renderWatcher.getResourceDownloadAttemptsRemaining(); } - Q_INVOKABLE MeshProxyList getMeshes(); + Q_INVOKABLE MeshProxyList getMeshes() const; public slots: void loadURLFinished(bool success); From 2f857a6d1a8b58332eabc4e4329e30753abd17a3 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Tue, 25 Jul 2017 06:05:06 +0100 Subject: [PATCH 50/52] Forgot a file --- .../resources/qml/controls/RadioButton.qml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 interface/resources/qml/controls/RadioButton.qml diff --git a/interface/resources/qml/controls/RadioButton.qml b/interface/resources/qml/controls/RadioButton.qml new file mode 100644 index 0000000000..6bd9c860d2 --- /dev/null +++ b/interface/resources/qml/controls/RadioButton.qml @@ -0,0 +1,17 @@ +import QtQuick.Controls 1.3 as Original +import QtQuick.Controls.Styles 1.3 +import "../styles" +import "." +Original.RadioButton { + text: "Radio Button" + style: RadioButtonStyle { + indicator: FontAwesome { + text: control.checked ? "\uf046" : "\uf096" + } + label: Text { + text: control.text + renderType: Text.QtRendering + } + } + +} From 34594b914da0a3679878c47fc885769b910edeef Mon Sep 17 00:00:00 2001 From: Mike Moody Date: Mon, 24 Jul 2017 23:55:44 -0700 Subject: [PATCH 51/52] Added and removed different normalizations. --- unpublishedScripts/gravity.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/unpublishedScripts/gravity.js b/unpublishedScripts/gravity.js index ea7ec83d67..0ef7b0caa9 100644 --- a/unpublishedScripts/gravity.js +++ b/unpublishedScripts/gravity.js @@ -18,10 +18,12 @@ function update(deltatime) { var planet = Entities.getEntityProperties(_entityID); - var direction = Vec3.normalize(Vec3.subtract(MyAvatar.position, planet.position)); + + //normalization happens in rotationBetween. + var direction = Vec3.subtract(MyAvatar.position, planet.position); var localUp = Quat.getUp(MyAvatar.orientation); - MyAvatar.orientation = Quat.multiply(Quat.rotationBetween(localUp, direction), MyAvatar.orientation); + MyAvatar.orientation = Quat.normalize(Quat.multiply(Quat.rotationBetween(localUp, direction), MyAvatar.orientation)); } function init() { From f9204a7034d06a25391a74caf79cfb4ab272ab62 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Tue, 25 Jul 2017 09:03:47 +0100 Subject: [PATCH 52/52] Now it should appear.. --- .../qml/hifi/tablet/tabletWindows/preferences/Section.qml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/interface/resources/qml/hifi/tablet/tabletWindows/preferences/Section.qml b/interface/resources/qml/hifi/tablet/tabletWindows/preferences/Section.qml index af1fbd0070..8cf254809d 100644 --- a/interface/resources/qml/hifi/tablet/tabletWindows/preferences/Section.qml +++ b/interface/resources/qml/hifi/tablet/tabletWindows/preferences/Section.qml @@ -82,6 +82,7 @@ Preference { property var buttonBuilder: Component { ButtonPreference { } } property var comboBoxBuilder: Component { ComboBoxPreference { } } property var spinnerSliderBuilder: Component { SpinnerSliderPreference { } } + property var primaryHandBuilder: Component { PrimaryHandPreference { } } property var preferences: [] property int checkBoxCount: 0 @@ -144,10 +145,16 @@ Preference { //to be not overlapped when drop down is active zpos = root.z + 1000 - itemNum break; + case Preference.SpinnerSlider: checkBoxCount = 0; builder = spinnerSliderBuilder; break; + + case Preference.PrimaryHand: + checkBoxCount++; + builder = primaryHandBuilder; + break; }; if (builder) {