From 5abd254a5893c7f10b1e1e9462ad1964d2f27a0c Mon Sep 17 00:00:00 2001 From: David Rowe Date: Mon, 26 Jun 2017 15:58:14 +1200 Subject: [PATCH 01/44] 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 02/44] 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 03/44] 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 04/44] 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 05/44] 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 06/44] 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 a8698c2fbc164071320a64df805e64ca50ad9dde Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Wed, 19 Jul 2017 08:59:09 -0700 Subject: [PATCH 07/44] 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 08/44] 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 09/44] 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 3a31805dff12d499be937c9f1a798cf1e0720e69 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 14 Jun 2017 17:12:25 -0700 Subject: [PATCH 10/44] Fix warnings in Qt 59 / VS 2017 build --- CMakeLists.txt | 27 +++++++++++-------- cmake/externals/quazip/CMakeLists.txt | 4 +-- cmake/macros/SetPackagingParameters.cmake | 10 +++++-- .../gpu-gl/src/gpu/gl41/GL41BackendInput.cpp | 2 +- libraries/shared/src/shared/Storage.cpp | 5 ++-- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 4 +-- plugins/openvr/src/OpenVrHelpers.cpp | 2 +- 7 files changed, 32 insertions(+), 22 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c90256134..9712b2d32e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,8 @@ -cmake_minimum_required(VERSION 3.2) +if (WIN32) + cmake_minimum_required(VERSION 3.7) +else() + cmake_minimum_required(VERSION 3.2) +endif() if (USE_ANDROID_TOOLCHAIN) set(CMAKE_TOOLCHAIN_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cmake/android/android.toolchain.cmake") @@ -33,6 +37,10 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") find_package( Threads ) if (WIN32) + if (NOT "${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + message( FATAL_ERROR "Only 64 bit builds supported." ) + endif() + add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS) if (NOT WINDOW_SDK_PATH) @@ -41,16 +49,13 @@ if (WIN32) # sets path for Microsoft SDKs # if you get build error about missing 'glu32' this path is likely wrong - if (MSVC10) - set(WINDOW_SDK_PATH "C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1 " CACHE PATH "Windows SDK PATH") - elseif (MSVC12) - if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") - set(WINDOW_SDK_FOLDER "x64") - else() - set(WINDOW_SDK_FOLDER "x86") - endif() + if (MSVC_VERSION GREATER_EQUAL 1910) # VS 2017 + set(WINDOW_SDK_PATH "C:/Program Files (x86)/Windows Kits/10/Lib/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64" CACHE PATH "Windows SDK PATH") + elseif (MSVC_VERSION GREATER_EQUAL 1800) # VS 2013 set(WINDOW_SDK_PATH "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\${WINDOW_SDK_FOLDER}" CACHE PATH "Windows SDK PATH") - endif () + else() + message( FATAL_ERROR "Visual Studio 2013 or higher required." ) + endif() if (DEBUG_DISCOVERED_SDK_PATH) message(STATUS "The discovered Windows SDK path is ${WINDOW_SDK_PATH}") @@ -103,7 +108,7 @@ else () endif () if (APPLE) - set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++0x") + set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LANGUAGE_STANDARD "c++11") set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --stdlib=libc++") endif () diff --git a/cmake/externals/quazip/CMakeLists.txt b/cmake/externals/quazip/CMakeLists.txt index 7af13dafa7..d44c9ffde3 100644 --- a/cmake/externals/quazip/CMakeLists.txt +++ b/cmake/externals/quazip/CMakeLists.txt @@ -21,8 +21,8 @@ endif () ExternalProject_Add( ${EXTERNAL_NAME} - URL https://s3-us-west-1.amazonaws.com/hifi-production/dependencies/quazip-0.7.2.zip - URL_MD5 2955176048a31262c09259ca8d309d19 + URL https://s3.amazonaws.com/Oculus/quazip-0.7.3.zip + URL_MD5 ed03754d39b9da1775771819b8001d45 BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build CMAKE_ARGS ${QUAZIP_CMAKE_ARGS} LOG_DOWNLOAD 1 diff --git a/cmake/macros/SetPackagingParameters.cmake b/cmake/macros/SetPackagingParameters.cmake index 82a4a7d080..6f35b76f1d 100644 --- a/cmake/macros/SetPackagingParameters.cmake +++ b/cmake/macros/SetPackagingParameters.cmake @@ -126,8 +126,14 @@ macro(SET_PACKAGING_PARAMETERS) # check if we need to find signtool if (PRODUCTION_BUILD OR PR_BUILD) - find_program(SIGNTOOL_EXECUTABLE signtool PATHS "C:/Program Files (x86)/Windows Kits/8.1" PATH_SUFFIXES "bin/x64") - + if (MSVC_VERSION GREATER_EQUAL 1910) # VS 2017 + find_program(SIGNTOOL_EXECUTABLE signtool PATHS "C:/Program Files (x86)/Windows Kits/10" PATH_SUFFIXES "bin/${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}/x64") + elseif (MSVC_VERSION GREATER_EQUAL 1800) # VS 2013 + find_program(SIGNTOOL_EXECUTABLE signtool PATHS "C:/Program Files (x86)/Windows Kits/8.1" PATH_SUFFIXES "bin/x64") + else() + message( FATAL_ERROR "Visual Studio 2013 or higher required." ) + endif() + if (NOT SIGNTOOL_EXECUTABLE) message(FATAL_ERROR "Code signing of executables was requested but signtool.exe could not be found.") endif () diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp index 43b48f721f..e8ebcbe05c 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendInput.cpp @@ -95,7 +95,7 @@ void GL41Backend::updateInput() { // GLenum perLocationStride = strides[bufferNum]; GLenum perLocationStride = attrib._element.getLocationSize(); GLuint stride = (GLuint)strides[bufferNum]; - GLuint pointer = (GLuint)(attrib._offset + offsets[bufferNum]); + uintptr_t pointer = (uintptr_t)(attrib._offset + offsets[bufferNum]); GLboolean isNormalized = attrib._element.isNormalized(); for (size_t locNum = 0; locNum < locationCount; ++locNum) { diff --git a/libraries/shared/src/shared/Storage.cpp b/libraries/shared/src/shared/Storage.cpp index b07f896df0..7e9f86b049 100644 --- a/libraries/shared/src/shared/Storage.cpp +++ b/libraries/shared/src/shared/Storage.cpp @@ -92,9 +92,8 @@ FileStorage::FileStorage(const QString& filename) : _file(filename) { FileStorage::~FileStorage() { if (_mapped) { - if (!_file.unmap(_mapped)) { - throw std::runtime_error("Unable to unmap file"); - } + _file.unmap(_mapped); + _mapped = nullptr; } if (_file.isOpen()) { _file.close(); diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 7a73c91c7d..b31f55edeb 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -282,7 +282,7 @@ public: static const vr::VRTextureBounds_t leftBounds{ 0, 0, 0.5f, 1 }; static const vr::VRTextureBounds_t rightBounds{ 0.5f, 0, 1, 1 }; - vr::Texture_t texture{ (void*)_colors[currentColorBuffer], vr::TextureType_OpenGL, vr::ColorSpace_Auto }; + vr::Texture_t texture{ (void*)(uintptr_t)_colors[currentColorBuffer], vr::TextureType_OpenGL, vr::ColorSpace_Auto }; vr::VRCompositor()->Submit(vr::Eye_Left, &texture, &leftBounds); vr::VRCompositor()->Submit(vr::Eye_Right, &texture, &rightBounds); _plugin._presentRate.increment(); @@ -643,7 +643,7 @@ void OpenVrDisplayPlugin::hmdPresent() { _submitThread->waitForPresent(); } else { GLuint glTexId = getGLBackend()->getTextureID(_compositeFramebuffer->getRenderBuffer(0)); - vr::Texture_t vrTexture { (void*)glTexId, vr::TextureType_OpenGL, vr::ColorSpace_Auto }; + vr::Texture_t vrTexture { (void*)(uintptr_t)glTexId, vr::TextureType_OpenGL, vr::ColorSpace_Auto }; vr::VRCompositor()->Submit(vr::Eye_Left, &vrTexture, &OPENVR_TEXTURE_BOUNDS_LEFT); vr::VRCompositor()->Submit(vr::Eye_Right, &vrTexture, &OPENVR_TEXTURE_BOUNDS_RIGHT); vr::VRCompositor()->PostPresentHandoff(); diff --git a/plugins/openvr/src/OpenVrHelpers.cpp b/plugins/openvr/src/OpenVrHelpers.cpp index 7e287a16c3..c8a0cb5f8b 100644 --- a/plugins/openvr/src/OpenVrHelpers.cpp +++ b/plugins/openvr/src/OpenVrHelpers.cpp @@ -129,7 +129,7 @@ void releaseOpenVrSystem() { #endif // HACK: workaround openvr crash, call submit with an invalid texture, right before VR_Shutdown. - const GLuint INVALID_GL_TEXTURE_HANDLE = -1; + const void* INVALID_GL_TEXTURE_HANDLE = (void*)(uintptr_t)-1; vr::Texture_t vrTexture{ (void*)INVALID_GL_TEXTURE_HANDLE, vr::TextureType_OpenGL, vr::ColorSpace_Auto }; static vr::VRTextureBounds_t OPENVR_TEXTURE_BOUNDS_LEFT{ 0, 0, 0.5f, 1 }; static vr::VRTextureBounds_t OPENVR_TEXTURE_BOUNDS_RIGHT{ 0.5f, 0, 1, 1 }; From 72e5fecb4e6feb98786651a7dd04df66504e38ab Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 20 Jul 2017 16:34:34 -0700 Subject: [PATCH 11/44] 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 5e04e849535f484fc60902878886ded483f7fc34 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 22 Jul 2017 11:57:51 -0700 Subject: [PATCH 12/44] 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 13/44] 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 14/44] 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 15/44] 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 16/44] 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 630922dd95d39a3c6feeb6bf442f917ad847f92e Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 24 Jul 2017 05:25:52 +0100 Subject: [PATCH 17/44] 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 18/44] 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 42742ba1f9fda98db0fd11281a5b68b5a471fa09 Mon Sep 17 00:00:00 2001 From: Cain Kilgore Date: Mon, 24 Jul 2017 18:31:16 +0100 Subject: [PATCH 19/44] 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 20/44] 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 21/44] 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 22/44] 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 23/44] 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 24/44] 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 507368726f21561af92fd917c9938a4a8fb5a868 Mon Sep 17 00:00:00 2001 From: Rob Kayson Date: Mon, 24 Jul 2017 14:38:22 -0700 Subject: [PATCH 25/44] added dart scripts --- .../marketplace/dart/createDart.js | 91 +++++++++++++++++++ unpublishedScripts/marketplace/dart/dart.js | 81 +++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 unpublishedScripts/marketplace/dart/createDart.js create mode 100644 unpublishedScripts/marketplace/dart/dart.js diff --git a/unpublishedScripts/marketplace/dart/createDart.js b/unpublishedScripts/marketplace/dart/createDart.js new file mode 100644 index 0000000000..ff13a695a8 --- /dev/null +++ b/unpublishedScripts/marketplace/dart/createDart.js @@ -0,0 +1,91 @@ +"use strict"; +// +// createDart.js +// +// Created by MrRoboman on 17/05/04 +// Copyright 2017 High Fidelity, Inc. +// +// Creates five throwing darts. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +var MODEL_URL = "https://hifi-content.s3.amazonaws.com/wadewatts/dart.fbx"; +var SCRIPT_URL = Script.resolvePath("./dart.js?v=" + Date.now()); +var START_POSITION = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), 0.75)); +var START_ROTATION = MyAvatar.orientation +var SCALE_FACTOR = 1; + +var dart = { + type: "Model", + shapeType: "box", + name: "Dart", + description: "Throw it at something!", + script: SCRIPT_URL, + modelURL: MODEL_URL, + position: START_POSITION, + rotation: START_ROTATION, + lifetime: 300, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + dimensions: { + x: 0.1, + y: 0.1, + z: 0.3 + }, + dynamic: true, + owningAvatarID: MyAvatar.sessionUUID, + userData: JSON.stringify({ + grabbableKey: { + grabbable: true, + invertSolidWhileHeld: true, + ignoreIK: false + } + }) +}; + +var avatarUp = Quat.getUp(MyAvatar.orientation); +var platformPosition = Vec3.sum(START_POSITION, Vec3.multiply(avatarUp, -0.05)); +var platform = { + type: "Box", + name: "Dart Platform", + description: "Holds darts", + position: platformPosition, + rotation: START_ROTATION, + lifetime: 60, + dimensions: { + x: 0.15 * 5, + y: 0.01, + z: 0.3 + }, + color: { + red: 129, + green: 92, + blue: 11 + }, + owningAvatarID: MyAvatar.sessionUUID, + userData: JSON.stringify({ + grabbableKey: { + grabbable: true, + invertSolidWhileHeld: true, + ignoreIK: false + } + }) +}; + + +Entities.addEntity(platform); + +var dartCount = 5; +var avatarRight = Quat.getRight(MyAvatar.orientation); +for (var i = 0; i < dartCount; i++) { + var j = i - Math.floor(dartCount / 2); + var position = Vec3.sum(START_POSITION, Vec3.multiply(avatarRight, 0.15 * j)); + dart.position = position; + Entities.addEntity(dart); +} + +Script.stop(); diff --git a/unpublishedScripts/marketplace/dart/dart.js b/unpublishedScripts/marketplace/dart/dart.js new file mode 100644 index 0000000000..9debe910e3 --- /dev/null +++ b/unpublishedScripts/marketplace/dart/dart.js @@ -0,0 +1,81 @@ +"use strict"; +// +// dart.js +// +// Created by MrRoboman on 17/05/13 +// Copyright 2017 High Fidelity, Inc. +// +// Simple throwing dart. Sticks to static objects. +// +// 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 THROW_FACTOR = 3; + var DART_SOUND_URL = Script.resolvePath('https://hifi-content.s3.amazonaws.com/wadewatts/dart.wav?v=' + Date.now()); + + var Dart = function() {}; + + Dart.prototype = { + + preload: function(entityID) { + this.entityID = entityID; + this.actionID = null; + this.soundHasPlayed = true; + this.dartSound = SoundCache.getSound(DART_SOUND_URL); + }, + + playDartSound: function(sound) { + if (this.soundHasPlayed) { + return; + } + this.soundHasPlayed = true; + var position = Entities.getEntityProperties(this.entityID, 'position').position; + var audioProperties = { + volume: 0.15, + position: position + }; + Audio.playSound(this.dartSound, audioProperties); + }, + + releaseGrab: function() { + this.soundHasPlayed = false; + var velocity = Entities.getEntityProperties(this.entityID, 'velocity').velocity; + + var newVelocity = {}; + Object.keys(velocity).forEach(function(key) { + newVelocity[key] = velocity[key] * THROW_FACTOR; + }); + + Entities.editEntity(this.entityID, { + velocity: newVelocity + }); + + if (this.actionID) { + Entities.deleteAction(this.entityID, this.actionID); + } + this.actionID = Entities.addAction("travel-oriented", this.entityID, { + forward: { x: 0, y: 0, z: 1 }, + angularTimeScale: 0.1, + tag: "throwing dart", + ttl: 3600 + }); + }, + + collisionWithEntity: function(myID, otherID, collisionInfo) { + this.playDartSound(); + + Entities.editEntity(myID, { + velocity: {x: 0, y: 0, z: 0}, + angularVelocity: {x: 0, y: 0, z: 0} + }); + + if (this.actionID) { + Entities.deleteAction(myID, this.actionID); + this.actionID = null; + } + } + }; + + return new Dart(); +}); From 7c62ed6dac2c324097f18b9fd49efcd832be5b14 Mon Sep 17 00:00:00 2001 From: utkarshgautamnyu Date: Mon, 24 Jul 2017 14:46:32 -0700 Subject: [PATCH 26/44] 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 27/44] 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 28/44] 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 29/44] 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 30/44] 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 31/44] 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 32/44] 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 33/44] 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 34/44] 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 35/44] 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 36/44] 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 dc53017dd4fb68dc63fe7b6c4854057facd63cb6 Mon Sep 17 00:00:00 2001 From: Mike Moody Date: Mon, 24 Jul 2017 23:17:13 -0700 Subject: [PATCH 37/44] Created script to let Snails eat brussel sprouts. --- .../DomainContent/Cupcake/eatable.js | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 unpublishedScripts/DomainContent/Cupcake/eatable.js diff --git a/unpublishedScripts/DomainContent/Cupcake/eatable.js b/unpublishedScripts/DomainContent/Cupcake/eatable.js new file mode 100644 index 0000000000..8b261b7ea2 --- /dev/null +++ b/unpublishedScripts/DomainContent/Cupcake/eatable.js @@ -0,0 +1,36 @@ +// +// eatable.js +// +// Created by Alan-Michael Moody on 7/24/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 +// + +(function () { + var NOMNOM_SOUND = SoundCache.getSound('http://hifi-content.s3.amazonaws.com/DomainContent/production/audio/vegcrunch.wav'); + + var _entityID; + + this.preload = function (entityID) { + _entityID = entityID; + }; + + this.collisionWithEntity = function(entityUuid, collisionEntityID, collisionInfo) { + var entity = Entities.getEntityProperties(collisionEntityID, ['userData', 'name']); + var isClone = (entity.name.substring(1).split('-')[0] === 'clone'); + var isEatable = (JSON.parse(entity.userData).eatable); + + if (isEatable && isClone) { + Audio.playSound(NOMNOM_SOUND, { + position: Entities.getEntityProperties(_entityID, ['position']).position, + volume: 0.2, + localOnly: false + }); + + Entities.deleteEntity(collisionEntityID); + } + }; +}); \ No newline at end of file From 34594b914da0a3679878c47fc885769b910edeef Mon Sep 17 00:00:00 2001 From: Mike Moody Date: Mon, 24 Jul 2017 23:55:44 -0700 Subject: [PATCH 38/44] 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 39/44] 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) { From 6817cf9db4572fb22dc79efd2a267826ee118d97 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Tue, 25 Jul 2017 10:59:03 -0700 Subject: [PATCH 40/44] Fix entity properties sometimes being resent When writing entity properties to a packet, we start off with a list of requested properties (`requestedProperties`) and keep track of which properties didn't fit (`propertiesDidntFit`) the packet, which is intialized to requestedProperties. As we pack the properties, we remove them from propertiesDidntFit if they didn't need to be written or were able to be packed. At the end we store propertiesDidntFit, and use it in the future as our requestedProperties when we try to pack more data into a packet. The bug: because of the order in which propertiesDidntFit is initialized, it ended up always being the list of all properties for that entity. This typically wasn't an issue because we usually go through and try to append all of the properties, and if we don't need to append them (because they aren't in requestedProperties) we remove them from our propertiesDidntFit list. When we don't have enough remaining space in the current packet for even the entity header, which is fairly small, we don't bother trying to append any of the properties. When this happens, propertiesDidntFit contains the full list of properties, which we save for the next pass through the entity, and use as our requestedProperties, causing us to resend entity data again. In the worst case we never end up sending all of the entity's data. --- libraries/entities/src/EntityItem.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 5996327e87..378f344d26 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -182,7 +182,6 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet EntityPropertyFlags propertyFlags(PROP_LAST_ITEM); EntityPropertyFlags requestedProperties = getEntityProperties(params); - EntityPropertyFlags propertiesDidntFit = requestedProperties; // If we are being called for a subsequent pass at appendEntityData() that failed to completely encode this item, // then our entityTreeElementExtraEncodeData should include data about which properties we need to append. @@ -190,6 +189,8 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet requestedProperties = entityTreeElementExtraEncodeData->entities.value(getEntityItemID()); } + EntityPropertyFlags propertiesDidntFit = requestedProperties; + LevelDetails entityLevel = packetData->startLevel(); quint64 lastEdited = getLastEdited(); From 2d0c5ff37a8624bc75f7b94a5409ff841c8b1df7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 25 Jul 2017 11:41:34 -0700 Subject: [PATCH 41/44] remove preloading of allowed user keys since it happens on connect --- domain-server/src/DomainGatekeeper.cpp | 15 ++------------- domain-server/src/DomainGatekeeper.h | 2 -- domain-server/src/DomainServer.cpp | 4 +--- libraries/networking/src/NodeList.cpp | 2 +- 4 files changed, 4 insertions(+), 19 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index da31fed387..957830bc7b 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -604,19 +604,6 @@ bool DomainGatekeeper::isWithinMaxCapacity() { return true; } - -void DomainGatekeeper::preloadAllowedUserPublicKeys() { - QStringList allowedUsers = _server->_settingsManager.getAllNames(); - - if (allowedUsers.size() > 0) { - // in the future we may need to limit how many requests here - for now assume that lists of allowed users are not - // going to create > 100 requests - foreach(const QString& username, allowedUsers) { - requestUserPublicKey(username); - } - } -} - void DomainGatekeeper::requestUserPublicKey(const QString& username) { // don't request public keys for the standard psuedo-account-names if (NodePermissions::standardNames.contains(username, Qt::CaseInsensitive)) { @@ -667,6 +654,8 @@ void DomainGatekeeper::publicKeyJSONCallback(QNetworkReply& requestReply) { const QString JSON_DATA_KEY = "data"; const QString JSON_PUBLIC_KEY_KEY = "public_key"; + qDebug() << "Extracted public key for" << username.toLower(); + _userPublicKeys[username.toLower()] = QByteArray::fromBase64(jsonObject[JSON_DATA_KEY].toObject()[JSON_PUBLIC_KEY_KEY].toString().toUtf8()); } diff --git a/domain-server/src/DomainGatekeeper.h b/domain-server/src/DomainGatekeeper.h index 163f255411..03a6292c55 100644 --- a/domain-server/src/DomainGatekeeper.h +++ b/domain-server/src/DomainGatekeeper.h @@ -39,8 +39,6 @@ public: const QUuid& walletUUID, const QString& nodeVersion); QUuid assignmentUUIDForPendingAssignment(const QUuid& tempUUID); - void preloadAllowedUserPublicKeys(); - void removeICEPeer(const QUuid& peerUUID) { _icePeers.remove(peerUUID); } static void sendProtocolMismatchConnectionDenial(const HifiSockAddr& senderSockAddr); diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index c5171620de..163bd48f1b 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -160,9 +160,7 @@ DomainServer::DomainServer(int argc, char* argv[]) : getTemporaryName(); } - _gatekeeper.preloadAllowedUserPublicKeys(); // so they can connect on first request - - //send signal to DomainMetadata when descriptors changed + // send signal to DomainMetadata when descriptors changed _metadata = new DomainMetadata(this); connect(&_settingsManager, &DomainServerSettingsManager::settingsUpdated, _metadata, &DomainMetadata::descriptorsChanged); diff --git a/libraries/networking/src/NodeList.cpp b/libraries/networking/src/NodeList.cpp index 75c97cc205..48e5c8a62c 100644 --- a/libraries/networking/src/NodeList.cpp +++ b/libraries/networking/src/NodeList.cpp @@ -327,7 +327,7 @@ void NodeList::sendDomainServerCheckIn() { << "but no keypair is present. Waiting for keypair generation to complete."; accountManager->generateNewUserKeypair(); - // don't send the check in packet - wait for the keypair first + // don't send the check in packet - wait for the new public key to be available to the domain-server first return; } From b1aa6e19625f6e17c0f2c28cca494832cef2d96e Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 25 Jul 2017 13:42:29 -0700 Subject: [PATCH 42/44] Move hosting for quazip back to hifi S3 --- cmake/externals/quazip/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/externals/quazip/CMakeLists.txt b/cmake/externals/quazip/CMakeLists.txt index d44c9ffde3..01650a432d 100644 --- a/cmake/externals/quazip/CMakeLists.txt +++ b/cmake/externals/quazip/CMakeLists.txt @@ -21,7 +21,7 @@ endif () ExternalProject_Add( ${EXTERNAL_NAME} - URL https://s3.amazonaws.com/Oculus/quazip-0.7.3.zip + URL https://hifi-public.s3.amazonaws.com/dependencies/quazip-0.7.3.zip URL_MD5 ed03754d39b9da1775771819b8001d45 BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build CMAKE_ARGS ${QUAZIP_CMAKE_ARGS} From e9845784d5a5a6012b1b10c8729f5e5e6798ae94 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 25 Jul 2017 13:43:30 -0700 Subject: [PATCH 43/44] don't return error decrypting for optimistic public keys --- domain-server/src/DomainGatekeeper.cpp | 34 +++++++++++++++++--------- domain-server/src/DomainGatekeeper.h | 15 +++++++++--- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/domain-server/src/DomainGatekeeper.cpp b/domain-server/src/DomainGatekeeper.cpp index 957830bc7b..fc595be67e 100644 --- a/domain-server/src/DomainGatekeeper.cpp +++ b/domain-server/src/DomainGatekeeper.cpp @@ -385,7 +385,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect // user is attempting to prove their identity to us, but we don't have enough information sendConnectionTokenPacket(username, nodeConnection.senderSockAddr); // ask for their public key right now to make sure we have it - requestUserPublicKey(username); + requestUserPublicKey(username, true); getGroupMemberships(username); // optimistically get started on group memberships #ifdef WANT_DEBUG qDebug() << "stalling login because we have no username-signature:" << username; @@ -521,7 +521,10 @@ bool DomainGatekeeper::verifyUserSignature(const QString& username, const HifiSockAddr& senderSockAddr) { // it's possible this user can be allowed to connect, but we need to check their username signature auto lowerUsername = username.toLower(); - QByteArray publicKeyArray = _userPublicKeys.value(lowerUsername); + KeyFlagPair publicKeyPair = _userPublicKeys.value(lowerUsername); + + QByteArray publicKeyArray = publicKeyPair.first; + bool isOptimisticKey = publicKeyPair.second; const QUuid& connectionToken = _connectionTokenHash.value(lowerUsername); @@ -555,10 +558,16 @@ bool DomainGatekeeper::verifyUserSignature(const QString& username, return true; } else { - if (!senderSockAddr.isNull()) { - qDebug() << "Error decrypting username signature for " << username << "- denying connection."; + // we only send back a LoginError if this wasn't an "optimistic" key + // (a key that we hoped would work but is probably stale) + + if (!senderSockAddr.isNull() && !isOptimisticKey) { + qDebug() << "Error decrypting username signature for" << username << "- denying connection."; sendConnectionDeniedPacket("Error decrypting username signature.", senderSockAddr, DomainHandler::ConnectionRefusedReason::LoginError); + } else if (!senderSockAddr.isNull()) { + qDebug() << "Error decrypting username signature for" << username << "with optimisitic key -" + << "re-requesting public key and delaying connection"; } // free up the public key, we don't need it anymore @@ -604,7 +613,7 @@ bool DomainGatekeeper::isWithinMaxCapacity() { return true; } -void DomainGatekeeper::requestUserPublicKey(const QString& username) { +void DomainGatekeeper::requestUserPublicKey(const QString& username, bool isOptimistic) { // don't request public keys for the standard psuedo-account-names if (NodePermissions::standardNames.contains(username, Qt::CaseInsensitive)) { return; @@ -615,7 +624,7 @@ void DomainGatekeeper::requestUserPublicKey(const QString& username) { // public-key request for this username is already flight, not rerequesting return; } - _inFlightPublicKeyRequests += lowerUsername; + _inFlightPublicKeyRequests.insert(lowerUsername, isOptimistic); // even if we have a public key for them right now, request a new one in case it has just changed JSONCallbackParameters callbackParams; @@ -627,7 +636,7 @@ void DomainGatekeeper::requestUserPublicKey(const QString& username) { const QString USER_PUBLIC_KEY_PATH = "api/v1/users/%1/public_key"; - qDebug() << "Requesting public key for user" << username; + qDebug().nospace() << "Requesting " << (isOptimistic ? "optimistic " : " ") << "public key for user " << username; DependencyManager::get()->sendRequest(USER_PUBLIC_KEY_PATH.arg(username), AccountManagerAuth::None, @@ -649,18 +658,21 @@ void DomainGatekeeper::publicKeyJSONCallback(QNetworkReply& requestReply) { QJsonObject jsonObject = QJsonDocument::fromJson(requestReply.readAll()).object(); QString username = extractUsernameFromPublicKeyRequest(requestReply); + bool isOptimisticKey = _inFlightPublicKeyRequests.take(username); + if (jsonObject["status"].toString() == "success" && !username.isEmpty()) { // pull the public key as a QByteArray from this response const QString JSON_DATA_KEY = "data"; const QString JSON_PUBLIC_KEY_KEY = "public_key"; - qDebug() << "Extracted public key for" << username.toLower(); + qDebug().nospace() << "Extracted " << (isOptimisticKey ? "optimistic " : " ") << "public key for " << username.toLower(); _userPublicKeys[username.toLower()] = - QByteArray::fromBase64(jsonObject[JSON_DATA_KEY].toObject()[JSON_PUBLIC_KEY_KEY].toString().toUtf8()); + { + QByteArray::fromBase64(jsonObject[JSON_DATA_KEY].toObject()[JSON_PUBLIC_KEY_KEY].toString().toUtf8()), + isOptimisticKey + }; } - - _inFlightPublicKeyRequests.remove(username); } void DomainGatekeeper::publicKeyJSONErrorCallback(QNetworkReply& requestReply) { diff --git a/domain-server/src/DomainGatekeeper.h b/domain-server/src/DomainGatekeeper.h index 03a6292c55..36df77815a 100644 --- a/domain-server/src/DomainGatekeeper.h +++ b/domain-server/src/DomainGatekeeper.h @@ -91,7 +91,7 @@ private: void pingPunchForConnectingPeer(const SharedNetworkPeer& peer); - void requestUserPublicKey(const QString& username); + void requestUserPublicKey(const QString& username, bool isOptimistic = false); DomainServer* _server; @@ -100,8 +100,17 @@ private: QHash _icePeers; QHash _connectionTokenHash; - QHash _userPublicKeys; - QSet _inFlightPublicKeyRequests; // keep track of which we've already asked for + + // the word "optimistic" below is used for keys that we request during user connection before the user has + // had a change to upload a new public key + + // we don't send back user signature decryption errors for those keys so that there isn't a thrasing of key re-generation + // and connection refusal + + using KeyFlagPair = QPair; + + QHash _userPublicKeys; // keep track of keys and flag them as optimistic or not + QHash _inFlightPublicKeyRequests; // keep track of keys we've asked for (and if it was optimistic) QSet _domainOwnerFriends; // keep track of friends of the domain owner QSet _inFlightGroupMembershipsRequests; // keep track of which we've already asked for From dd3755596c48cf66b6f6ea5b80537959c0d56fac Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 25 Jul 2017 15:43:34 -0700 Subject: [PATCH 44/44] fix typo in comment in DomainGatekeeper header --- domain-server/src/DomainGatekeeper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/src/DomainGatekeeper.h b/domain-server/src/DomainGatekeeper.h index 36df77815a..09db075e07 100644 --- a/domain-server/src/DomainGatekeeper.h +++ b/domain-server/src/DomainGatekeeper.h @@ -102,7 +102,7 @@ private: QHash _connectionTokenHash; // the word "optimistic" below is used for keys that we request during user connection before the user has - // had a change to upload a new public key + // had a chance to upload a new public key // we don't send back user signature decryption errors for those keys so that there isn't a thrasing of key re-generation // and connection refusal