From 0c20107203fed02fa0a90d7e268b5b2ebd228900 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Fri, 18 Jan 2019 12:46:19 -0800 Subject: [PATCH 001/158] Add Controller menu items for hand/head-relative movement. --- interface/src/avatar/MyAvatar.cpp | 20 ++++++++++++++++++-- interface/src/avatar/MyAvatar.h | 18 ++++++++++++++++++ interface/src/ui/PreferencesDialog.cpp | 11 +++++++++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index cc7742c517..81d6c94c1b 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -106,7 +106,7 @@ MyAvatar::MyAvatar(QThread* thread) : _characterController(this), _eyeContactTarget(LEFT_EYE), _realWorldFieldOfView("realWorldFieldOfView", - DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES), + DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES), _useAdvancedMovementControls("advancedMovementForHandControllersIsChecked", true), _showPlayArea("showPlayArea", true), _smoothOrientationTimer(std::numeric_limits::max()), @@ -130,7 +130,7 @@ MyAvatar::MyAvatar(QThread* thread) : _yawSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "yawSpeed", _yawSpeed), _pitchSpeedSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "pitchSpeed", _pitchSpeed), _fullAvatarURLSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "fullAvatarURL", - AvatarData::defaultFullAvatarModelUrl()), + AvatarData::defaultFullAvatarModelUrl()), _fullAvatarModelNameSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "fullAvatarModelName", _fullAvatarModelName), _animGraphURLSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "animGraphURL", QUrl("")), _displayNameSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "displayName", ""), @@ -138,6 +138,7 @@ MyAvatar::MyAvatar(QThread* thread) : _useSnapTurnSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "useSnapTurn", _useSnapTurn), _userHeightSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "userHeight", DEFAULT_AVATAR_HEIGHT), _flyingHMDSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "flyingHMD", _flyingPrefHMD), + _handRelativeMovementSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "handRelativeMovement", _handRelativeMovement), _avatarEntityCountSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "avatarEntityData" << "size", 0) { _clientTraitsHandler.reset(new ClientTraitsHandler(this)); @@ -1300,6 +1301,7 @@ void MyAvatar::saveData() { _useSnapTurnSetting.set(_useSnapTurn); _userHeightSetting.set(getUserHeight()); _flyingHMDSetting.set(getFlyingHMDPref()); + _handRelativeMovementSetting.set(getHandRelativeMovement()); auto hmdInterface = DependencyManager::get(); saveAvatarEntityDataToSettings(); @@ -1876,6 +1878,7 @@ void MyAvatar::loadData() { // Flying preferences must be loaded before calling setFlyingEnabled() Setting::Handle firstRunVal { Settings::firstRun, true }; setFlyingHMDPref(firstRunVal.get() ? false : _flyingHMDSetting.get()); + setHandRelativeMovement(firstRunVal.get() ? false : _handRelativeMovementSetting.get()); setFlyingEnabled(getFlyingEnabled()); setDisplayName(_displayNameSetting.get()); @@ -3287,6 +3290,7 @@ void MyAvatar::updateActionMotor(float deltaTime) { CharacterController::State state = _characterController.getState(); // compute action input + // Determine if we're head or controller relative... glm::vec3 forward = (getDriveKey(TRANSLATE_Z)) * IDENTITY_FORWARD; glm::vec3 right = (getDriveKey(TRANSLATE_X)) * IDENTITY_RIGHT; @@ -3816,6 +3820,18 @@ void MyAvatar::setFlyingHMDPref(bool enabled) { _flyingPrefHMD = enabled; } +void MyAvatar::setHandRelativeMovement(bool enabled) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setHandRelativeMovement", Q_ARG(bool, enabled)); + return; + } + _handRelativeMovement = enabled; +} + +bool MyAvatar::getHandRelativeMovement() { + return _handRelativeMovement; +} + bool MyAvatar::getFlyingHMDPref() { return _flyingPrefHMD; } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 58880acb08..65a3eac665 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1044,6 +1044,22 @@ public: Q_INVOKABLE bool getFlyingHMDPref(); + /**jsdoc + * Set your preference for hand-relative movement. + * @function MyAvatar.setHandRelativeMovement + * @param {boolean} enabled - Set true if you want to enable hand-relative movement, otherwise set to false. + * + */ + Q_INVOKABLE void setHandRelativeMovement(bool enabled); + + /**jsdoc + * Get your preference for hand-relative movement. + * @function MyAvatar.getHandRelativeMovement + * @returns {boolean} true if your preference is for user locomotion to be relative to the direction your + * controller is pointing, otherwise false. + */ + Q_INVOKABLE bool getHandRelativeMovement(); + /**jsdoc * @function MyAvatar.getAvatarScale * @returns {number} @@ -1705,6 +1721,7 @@ private: bool _enableFlying { false }; bool _flyingPrefDesktop { true }; bool _flyingPrefHMD { false }; + bool _handRelativeMovement{ false }; bool _wasPushing { false }; bool _isPushing { false }; bool _isBeingPushed { false }; @@ -1950,6 +1967,7 @@ private: Setting::Handle _useSnapTurnSetting; Setting::Handle _userHeightSetting; Setting::Handle _flyingHMDSetting; + Setting::Handle _handRelativeMovementSetting; Setting::Handle _avatarEntityCountSetting; Setting::Handle _allowTeleportingSetting { "allowTeleporting", true }; std::vector> _avatarEntityIDSettings; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 3d7971cf57..81db8d0ef9 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -265,6 +265,12 @@ void setupPreferences() { auto preference = new CheckPreference(VR_MOVEMENT, "Walking", getter, setter); preferences->addPreference(preference); } + { + auto getter = [myAvatar]()->bool { return myAvatar->getHandRelativeMovement(); }; + auto setter = [myAvatar](bool value) { myAvatar->setHandRelativeMovement(value); }; + auto preference = new CheckPreference(VR_MOVEMENT, "Hand-Relative Movement", getter, setter); + preferences->addPreference(preference); + } { auto getter = [myAvatar]()->bool { return myAvatar->getFlyingHMDPref(); }; auto setter = [myAvatar](bool value) { myAvatar->setFlyingHMDPref(value); }; @@ -272,6 +278,11 @@ void setupPreferences() { preference->setIndented(true); preferences->addPreference(preference); } + { + auto getter = [myAvatar]()->QString { return myAvatar->getDominantHand(); }; + auto setter = [myAvatar](const QString& value) { myAvatar->setDominantHand(value); }; + preferences->addPreference(new PrimaryHandPreference(VR_MOVEMENT, "Dominant Hand", getter, setter)); + } { auto getter = [myAvatar]()->int { return myAvatar->getSnapTurn() ? 0 : 1; }; auto setter = [myAvatar](int value) { myAvatar->setSnapTurn(value == 0); }; From 79ff0a5b658ec70bde6f91d144aebe5d0a0a56d1 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Fri, 18 Jan 2019 14:35:26 -0800 Subject: [PATCH 002/158] Basic controller-relative (non-leveled) locomotion working. --- interface/src/avatar/MyAvatar.cpp | 24 ++++++++++++++++++++++-- interface/src/avatar/MyAvatar.h | 1 + 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 81d6c94c1b..05db6f436d 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2525,6 +2525,12 @@ controller::Pose MyAvatar::getControllerPoseInAvatarFrame(controller::Action act } } +quat MyAvatar::getDominantHandRotation() const { + auto hand = (getDominantHand() == DOMINANT_RIGHT_HAND) ? controller::Action::RIGHT_HAND : controller::Action::LEFT_HAND; + auto pose = getControllerPoseInAvatarFrame(hand); + return pose.rotation; +} + void MyAvatar::updateMotors() { _characterController.clearMotors(); glm::quat motorRotation; @@ -3291,10 +3297,24 @@ void MyAvatar::updateActionMotor(float deltaTime) { // compute action input // Determine if we're head or controller relative... - glm::vec3 forward = (getDriveKey(TRANSLATE_Z)) * IDENTITY_FORWARD; - glm::vec3 right = (getDriveKey(TRANSLATE_X)) * IDENTITY_RIGHT; + glm::vec3 forward, right; + if (getHandRelativeMovement()) { + // Here we have to get the rotation of the dominant hand and apply that to the direction vector. + // If we're on the right hand, we have to flip the x-axis. + auto handRotation = getDominantHandRotation(); + glm::vec3 controllerForward(0.0f, 1.0f, 0.0f); + glm::vec3 controllerRight((getDominantHand() == DOMINANT_RIGHT_HAND ? -1.0f : 1.0f), 0.0f, 0.0f); + forward = (getDriveKey(TRANSLATE_Z)) * (handRotation * controllerForward); + right = (getDriveKey(TRANSLATE_X)) * (handRotation * controllerRight); + } + else { + forward = (getDriveKey(TRANSLATE_Z)) * IDENTITY_FORWARD; + right = (getDriveKey(TRANSLATE_X)) * IDENTITY_RIGHT; + } glm::vec3 direction = forward + right; + + // RKNOTE: This may need to be changed later... if (state == CharacterController::State::Hover || _characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { glm::vec3 up = (getDriveKey(TRANSLATE_Y)) * IDENTITY_UP; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 65a3eac665..16df224aa5 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -961,6 +961,7 @@ public: controller::Pose getControllerPoseInSensorFrame(controller::Action action) const; controller::Pose getControllerPoseInWorldFrame(controller::Action action) const; controller::Pose getControllerPoseInAvatarFrame(controller::Action action) const; + quat MyAvatar::getDominantHandRotation() const; bool hasDriveInput() const; From 6bfe9bf19ef712d5cf5f40ee779b333dca3fde8a Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Fri, 18 Jan 2019 14:53:25 -0800 Subject: [PATCH 003/158] Move hand-relative entry in Controls menu. --- interface/src/ui/PreferencesDialog.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 81db8d0ef9..918fb6d830 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -265,12 +265,6 @@ void setupPreferences() { auto preference = new CheckPreference(VR_MOVEMENT, "Walking", getter, setter); preferences->addPreference(preference); } - { - auto getter = [myAvatar]()->bool { return myAvatar->getHandRelativeMovement(); }; - auto setter = [myAvatar](bool value) { myAvatar->setHandRelativeMovement(value); }; - auto preference = new CheckPreference(VR_MOVEMENT, "Hand-Relative Movement", getter, setter); - preferences->addPreference(preference); - } { auto getter = [myAvatar]()->bool { return myAvatar->getFlyingHMDPref(); }; auto setter = [myAvatar](bool value) { myAvatar->setFlyingHMDPref(value); }; @@ -278,6 +272,12 @@ void setupPreferences() { preference->setIndented(true); preferences->addPreference(preference); } + { + auto getter = [myAvatar]()->bool { return myAvatar->getHandRelativeMovement(); }; + auto setter = [myAvatar](bool value) { myAvatar->setHandRelativeMovement(value); }; + auto preference = new CheckPreference(VR_MOVEMENT, "Hand-Relative Movement", getter, setter); + preferences->addPreference(preference); + } { auto getter = [myAvatar]()->QString { return myAvatar->getDominantHand(); }; auto setter = [myAvatar](const QString& value) { myAvatar->setDominantHand(value); }; From 4fa84542163291f7928edce9bebe3579c5c74c1f Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 21 Jan 2019 13:25:06 -0800 Subject: [PATCH 004/158] Add condition for HMD mode to hand-relative code block. --- interface/src/avatar/MyAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 05db6f436d..ef0d16f9f0 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3298,7 +3298,7 @@ void MyAvatar::updateActionMotor(float deltaTime) { // compute action input // Determine if we're head or controller relative... glm::vec3 forward, right; - if (getHandRelativeMovement()) { + if (getHandRelativeMovement() && qApp->isHMDMode()) { // Here we have to get the rotation of the dominant hand and apply that to the direction vector. // If we're on the right hand, we have to flip the x-axis. auto handRotation = getDominantHandRotation(); From ea025a687865475fc6189ab3e84f67d1f9792278 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 21 Jan 2019 15:38:36 -0800 Subject: [PATCH 005/158] Add hand dominance states to Controller.Hardware.Application for left and right hand dominance. --- interface/src/Application.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7ed05611ee..95c9cbcff5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -689,6 +689,8 @@ private: * InHMDnumbernumberThe user is in HMD mode. * AdvancedMovementnumbernumberAdvanced movement controls are enabled. * + * LeftHandDominantnumbernumberDominant hand set to left. + * RightHandDominantnumbernumberDominant hand set to right. * SnapTurnnumbernumberSnap turn is enabled. * GroundednumbernumberThe user's avatar is on the ground. * NavigationFocusednumbernumberNot used. @@ -710,6 +712,8 @@ static const QString STATE_NAV_FOCUSED = "NavigationFocused"; static const QString STATE_PLATFORM_WINDOWS = "PlatformWindows"; static const QString STATE_PLATFORM_MAC = "PlatformMac"; static const QString STATE_PLATFORM_ANDROID = "PlatformAndroid"; +static const QString STATE_LEFT_HAND_DOMINANT = "LeftHandDominant"; +static const QString STATE_RIGHT_HAND_DOMINANT = "RightHandDominant"; // Statically provided display and input plugins extern DisplayPluginList getDisplayPlugins(); @@ -898,7 +902,7 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { controller::StateController::setStateVariables({ { STATE_IN_HMD, STATE_CAMERA_FULL_SCREEN_MIRROR, STATE_CAMERA_FIRST_PERSON, STATE_CAMERA_THIRD_PERSON, STATE_CAMERA_ENTITY, STATE_CAMERA_INDEPENDENT, STATE_SNAP_TURN, STATE_ADVANCED_MOVEMENT_CONTROLS, STATE_GROUNDED, STATE_NAV_FOCUSED, - STATE_PLATFORM_WINDOWS, STATE_PLATFORM_MAC, STATE_PLATFORM_ANDROID } }); + STATE_PLATFORM_WINDOWS, STATE_PLATFORM_MAC, STATE_PLATFORM_ANDROID, STATE_LEFT_HAND_DOMINANT, STATE_RIGHT_HAND_DOMINANT } }); DependencyManager::set(); DependencyManager::set(); DependencyManager::set(); @@ -1720,6 +1724,12 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo _applicationStateDevice->setInputVariant(STATE_ADVANCED_MOVEMENT_CONTROLS, []() -> float { return qApp->getMyAvatar()->useAdvancedMovementControls() ? 1 : 0; }); + _applicationStateDevice->setInputVariant(STATE_LEFT_HAND_DOMINANT, []() -> float { + return qApp->getMyAvatar()->getDominantHand() == "left" ? 1 : 0; + }); + _applicationStateDevice->setInputVariant(STATE_RIGHT_HAND_DOMINANT, []() -> float { + return qApp->getMyAvatar()->getDominantHand() == "right" ? 1 : 0; + }); _applicationStateDevice->setInputVariant(STATE_GROUNDED, []() -> float { return qApp->getMyAvatar()->getCharacterController()->onGround() ? 1 : 0; From 9586f88ebc34aa772a8efa0693b556a30d8f5f3a Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 21 Jan 2019 15:39:27 -0800 Subject: [PATCH 006/158] Add hand dominance state awareness to bindings, add bindings for both cases. --- interface/resources/controllers/standard.json | 80 +++++++++++++++++-- 1 file changed, 72 insertions(+), 8 deletions(-) diff --git a/interface/resources/controllers/standard.json b/interface/resources/controllers/standard.json index 28f15605e0..a1faf8e760 100644 --- a/interface/resources/controllers/standard.json +++ b/interface/resources/controllers/standard.json @@ -1,11 +1,14 @@ { "name": "Standard to Action", "channels": [ - { "from": "Standard.LY", "to": "Actions.TranslateZ" }, + { "from": "Standard.LY", + "when": "Application.LeftHandDominant", + "to": "Actions.TranslateZ" + }, { "from": "Standard.LX", "when": [ - "Application.InHMD", "!Application.AdvancedMovement", + "Application.InHMD", "!Application.AdvancedMovement", "Application.LeftHandDominant", "Application.SnapTurn", "!Standard.RX" ], "to": "Actions.StepYaw", @@ -18,14 +21,14 @@ ] }, { "from": "Standard.LX", "to": "Actions.TranslateX", - "when": [ "Application.AdvancedMovement" ] + "when": [ "Application.AdvancedMovement", "Application.LeftHandDominant" ] }, { "from": "Standard.LX", "to": "Actions.Yaw", - "when": [ "!Application.AdvancedMovement", "!Application.SnapTurn" ] + "when": [ "!Application.AdvancedMovement", "!Application.SnapTurn", "Application.LeftHandDominant" ] }, { "from": "Standard.RX", - "when": [ "Application.SnapTurn" ], + "when": [ "Application.SnapTurn", "Application.LeftHandDominant" ], "to": "Actions.StepYaw", "filters": [ @@ -36,11 +39,11 @@ ] }, { "from": "Standard.RX", "to": "Actions.Yaw", - "when": [ "!Application.SnapTurn" ] + "when": [ "!Application.SnapTurn", "Application.LeftHandDominant" ] }, { "from": "Standard.RY", - "when": "Application.Grounded", + "when": [ "Application.Grounded", "Application.LeftHandDominant" ], "to": "Actions.Up", "filters": [ @@ -49,7 +52,68 @@ ] }, - { "from": "Standard.RY", "to": "Actions.Up", "filters": "invert"}, + { "from": "Standard.RY", + "when": "Application.LeftHandDominant", + "to": "Actions.Up", + "filters": "invert" + }, + + { "from": "Standard.RY", + "when": "Application.RightHandDominant", + "to": "Actions.TranslateZ" + }, + + { "from": "Standard.RX", + "when": [ + "Application.InHMD", "!Application.AdvancedMovement", "Application.RightHandDominant", + "Application.SnapTurn", "!Standard.RX" + ], + "to": "Actions.StepYaw", + "filters": + [ + { "type": "deadZone", "min": 0.15 }, + "constrainToInteger", + { "type": "pulse", "interval": 0.25 }, + { "type": "scale", "scale": 22.5 } + ] + }, + { "from": "Standard.RX", "to": "Actions.TranslateX", + "when": [ "Application.AdvancedMovement", "Application.RightHandDominant" ] + }, + { "from": "Standard.RX", "to": "Actions.Yaw", + "when": [ "!Application.AdvancedMovement", "!Application.SnapTurn", "Application.RightHandDominant" ] + }, + + { "from": "Standard.LX", + "when": [ "Application.SnapTurn", "Application.RightHandDominant" ], + "to": "Actions.StepYaw", + "filters": + [ + { "type": "deadZone", "min": 0.15 }, + "constrainToInteger", + { "type": "pulse", "interval": 0.25 }, + { "type": "scale", "scale": 22.5 } + ] + }, + { "from": "Standard.LX", "to": "Actions.Yaw", + "when": [ "!Application.SnapTurn", "Application.RightHandDominant" ] + }, + + { "from": "Standard.LY", + "when": [ "Application.Grounded", "Application.RightHandDominant" ], + "to": "Actions.Up", + "filters": + [ + { "type": "deadZone", "min": 0.6 }, + "invert" + ] + }, + + { "from": "Standard.LY", + "when": "Application.RightHandDominant", + "to": "Actions.Up", + "filters": "invert" + }, { "from": "Standard.Back", "to": "Actions.CycleCamera" }, { "from": "Standard.Start", "to": "Actions.ContextMenu" }, From d3c1843d45d777a32dbc1f62f54a1f242bc63280 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 21 Jan 2019 15:40:12 -0800 Subject: [PATCH 007/158] Disable toggleAdvancedMovementForHandControllers.js until such time the Controller.Standard.RY binding can be fixed. --- scripts/system/controllers/controllerScripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index 2114f2c0b2..3693e3651b 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -15,7 +15,7 @@ var CONTOLLER_SCRIPTS = [ "squeezeHands.js", "controllerDisplayManager.js", "grab.js", - "toggleAdvancedMovementForHandControllers.js", + //"toggleAdvancedMovementForHandControllers.js", "handTouch.js", "controllerDispatcher.js", "controllerModules/nearParentGrabOverlay.js", From 1e10afe762d6d0ce8685de69a00b9d5c2ed27ac2 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 22 Jan 2019 14:14:54 -0800 Subject: [PATCH 008/158] Add function for calculating direction in MyAvatar. --- interface/src/avatar/MyAvatar.cpp | 46 ++++++++++++++++++------------- interface/src/avatar/MyAvatar.h | 1 + 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ef0d16f9f0..5242d52431 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3278,21 +3278,7 @@ static float scaleSpeedByDirection(const glm::vec2 velocityDirection, const floa return scaledSpeed; } -void MyAvatar::updateActionMotor(float deltaTime) { - bool thrustIsPushing = (glm::length2(_thrust) > EPSILON); - bool scriptedMotorIsPushing = (_motionBehaviors & AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED) - && _scriptedMotorTimescale < MAX_CHARACTER_MOTOR_TIMESCALE; - _isBeingPushed = thrustIsPushing || scriptedMotorIsPushing; - if (_isPushing || _isBeingPushed) { - // we don't want the motor to brake if a script is pushing the avatar around - // (we assume the avatar is driving itself via script) - _isBraking = false; - } else { - float speed = glm::length(_actionMotorVelocity); - const float MIN_ACTION_BRAKE_SPEED = 0.1f; - _isBraking = _wasPushing || (_isBraking && speed > MIN_ACTION_BRAKE_SPEED); - } - +glm::vec3 MyAvatar::calculateScaledDirection(){ CharacterController::State state = _characterController.getState(); // compute action input @@ -3313,11 +3299,12 @@ void MyAvatar::updateActionMotor(float deltaTime) { } glm::vec3 direction = forward + right; - + // RKNOTE: This may need to be changed later... if (state == CharacterController::State::Hover || - _characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { + _characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { glm::vec3 up = (getDriveKey(TRANSLATE_Y)) * IDENTITY_UP; + up /= glm::length(up); direction += up; } @@ -3325,13 +3312,34 @@ void MyAvatar::updateActionMotor(float deltaTime) { float directionLength = glm::length(direction); _isPushing = directionLength > EPSILON; - // normalize direction if (_isPushing) { - direction /= directionLength; + direction; } else { direction = Vectors::ZERO; } + return direction; +} + +void MyAvatar::updateActionMotor(float deltaTime) { + bool thrustIsPushing = (glm::length2(_thrust) > EPSILON); + bool scriptedMotorIsPushing = (_motionBehaviors & AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED) + && _scriptedMotorTimescale < MAX_CHARACTER_MOTOR_TIMESCALE; + _isBeingPushed = thrustIsPushing || scriptedMotorIsPushing; + if (_isPushing || _isBeingPushed) { + // we don't want the motor to brake if a script is pushing the avatar around + // (we assume the avatar is driving itself via script) + _isBraking = false; + } else { + float speed = glm::length(_actionMotorVelocity); + const float MIN_ACTION_BRAKE_SPEED = 0.1f; + _isBraking = _wasPushing || (_isBraking && speed > MIN_ACTION_BRAKE_SPEED); + } + + CharacterController::State state = _characterController.getState(); + + glm::vec3 direction = calculateScaledDirection(); + if (state == CharacterController::State::Hover) { // we're flying --> complex acceleration curve that builds on top of current motor speed and caps at some max speed diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 16df224aa5..9520fb7cc4 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1772,6 +1772,7 @@ private: // private methods void updateOrientation(float deltaTime); + glm::vec3 calculateScaledDirection(); void updateActionMotor(float deltaTime); void updatePosition(float deltaTime); void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency); From 09d15c9cb058864b2fe87baa92fc1cf8aac99b30 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Thu, 24 Jan 2019 14:20:42 -0800 Subject: [PATCH 009/158] Block TranslateZ when off-hand Y axis is active. --- interface/resources/controllers/standard.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/resources/controllers/standard.json b/interface/resources/controllers/standard.json index a1faf8e760..25f75c5670 100644 --- a/interface/resources/controllers/standard.json +++ b/interface/resources/controllers/standard.json @@ -2,7 +2,7 @@ "name": "Standard to Action", "channels": [ { "from": "Standard.LY", - "when": "Application.LeftHandDominant", + "when": ["Application.LeftHandDominant", "!Standard.RY"], "to": "Actions.TranslateZ" }, @@ -59,7 +59,7 @@ }, { "from": "Standard.RY", - "when": "Application.RightHandDominant", + "when": ["Application.RightHandDominant", "!Standard.LY"], "to": "Actions.TranslateZ" }, From 690f67c9d99d0bf2a83588dda415e9d3c9cd8088 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Thu, 24 Jan 2019 14:21:18 -0800 Subject: [PATCH 010/158] Add variable for teleport deadzone on y-axis. --- scripts/system/libraries/controllerDispatcherUtils.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index 221af07474..27e637ab63 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -103,6 +103,8 @@ TEAR_AWAY_DISTANCE = 0.15; // ungrab an entity if its bounding-box moves this fa TEAR_AWAY_COUNT = 2; // multiply by TEAR_AWAY_CHECK_TIME to know how long the item must be away TEAR_AWAY_CHECK_TIME = 0.15; // seconds, duration between checks +TELEPORT_DEADZONE = 0.15; + NEAR_GRAB_DISTANCE = 0.14; // Grab an entity if its bounding box is within this distance. // Smaller than TEAR_AWAY_DISTANCE for hysteresis. From 80abfbab5ee60f08f4896fa773589f8bbc08f9e4 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Thu, 24 Jan 2019 14:22:01 -0800 Subject: [PATCH 011/158] Modify teleport to 'superpower' spec. --- .../controllers/controllerModules/teleport.js | 53 ++++++++++++++++++- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/controllerModules/teleport.js b/scripts/system/controllers/controllerModules/teleport.js index 8770ae8dde..bbc690d663 100644 --- a/scripts/system/controllers/controllerModules/teleport.js +++ b/scripts/system/controllers/controllerModules/teleport.js @@ -129,6 +129,8 @@ Script.include("/~/system/libraries/controllers.js"); this.init = false; this.hand = hand; this.buttonValue = 0; + this.standardAxisLY = 0.0; + this.standardAxisRY = 0.0; this.disabled = false; // used by the 'Hifi-Teleport-Disabler' message handler this.active = false; this.state = TELEPORTER_STATES.IDLE; @@ -690,6 +692,43 @@ Script.include("/~/system/libraries/controllers.js"); } }; + this.getStandardLY = function (value) { + _this.standardAxisLY = value; + }; + + this.getStandardRY = function (value) { + _this.standardAxisRY = value; + }; + + // Return value for the getDominantY and getOffhandY functions has to be inverted. + this.getDominantY = function () { + return (MyAvatar.getDominantHand() === "left") ? -(_this.standardAxisLY) : -(_this.standardAxisRY); + }; + + this.getOffhandY = function () { + return (MyAvatar.getDominantHand() === "left") ? -(_this.standardAxisRY) : -(_this.standardAxisLY); + }; + + this.getDominantHand = function () { + return (MyAvatar.getDominantHand() === "left") ? LEFT_HAND : RIGHT_HAND; + } + + this.getOffHand = function () { + return (MyAvatar.getDominantHand() === "left") ? RIGHT_HAND : LEFT_HAND; + } + + this.showReticle = function () { + return (_this.getOffhandY() > TELEPORT_DEADZONE) ? true : false; + }; + + this.shouldTeleport = function () { + return (_this.getDominantY() > TELEPORT_DEADZONE && _this.getOffhandY() > TELEPORT_DEADZONE) ? true : false; + }; + + this.shouldCancel = function () { + return (_this.getDominantY() < -TELEPORT_DEADZONE || _this.getOffhandY() < -TELEPORT_DEADZONE) ? true : false; + }; + this.parameters = makeDispatcherModuleParameters( 80, this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], @@ -706,7 +745,7 @@ Script.include("/~/system/libraries/controllers.js"); } var otherModule = this.getOtherModule(); - if (!this.disabled && this.buttonValue !== 0 && !otherModule.active) { + if (!this.disabled && this.showReticle() && !otherModule.active && this.hand === this.getOffHand()) { this.active = true; this.enterTeleport(); return makeRunningValues(true, [], []); @@ -715,6 +754,12 @@ Script.include("/~/system/libraries/controllers.js"); }; this.run = function(controllerData, deltaTime) { + // Kill condition: + if (this.shouldCancel()) { + this.disableLasers(); + this.active = false; + return makeRunningValues(false, [], []); + } // Get current hand pose information to see if the pose is valid var pose = Controller.getPoseValue(handInfo[(_this.hand === RIGHT_HAND) ? 'right' : 'left'].controllerInput); @@ -778,7 +823,7 @@ Script.include("/~/system/libraries/controllers.js"); this.teleport = function(newResult, target) { var result = newResult; this.teleportedPosition = newResult.intersection; - if (_this.buttonValue !== 0) { + if (!_this.shouldTeleport()) { return makeRunningValues(true, [], []); } @@ -982,6 +1027,10 @@ Script.include("/~/system/libraries/controllers.js"); // Teleport actions. teleportMapping.from(Controller.Standard.LeftPrimaryThumb).peek().to(leftTeleporter.buttonPress); teleportMapping.from(Controller.Standard.RightPrimaryThumb).peek().to(rightTeleporter.buttonPress); + teleportMapping.from(Controller.Standard.LY).peek().to(leftTeleporter.getStandardLY); + teleportMapping.from(Controller.Standard.RY).peek().to(leftTeleporter.getStandardRY); + teleportMapping.from(Controller.Standard.LY).peek().to(rightTeleporter.getStandardLY); + teleportMapping.from(Controller.Standard.RY).peek().to(rightTeleporter.getStandardRY); } var leftTeleporter = new Teleporter(LEFT_HAND); From a1c24516c28f4265465b4e9bcd073e6d2c2de192 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Thu, 24 Jan 2019 14:38:31 -0800 Subject: [PATCH 012/158] Fix strafing with controller-relative movement (was wrong local axis for controller). --- interface/src/avatar/MyAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 5242d52431..3183388214 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3289,7 +3289,7 @@ glm::vec3 MyAvatar::calculateScaledDirection(){ // If we're on the right hand, we have to flip the x-axis. auto handRotation = getDominantHandRotation(); glm::vec3 controllerForward(0.0f, 1.0f, 0.0f); - glm::vec3 controllerRight((getDominantHand() == DOMINANT_RIGHT_HAND ? -1.0f : 1.0f), 0.0f, 0.0f); + glm::vec3 controllerRight(0.0f, 0.0f, (getDominantHand() == DOMINANT_RIGHT_HAND ? -1.0f : 1.0f)); forward = (getDriveKey(TRANSLATE_Z)) * (handRotation * controllerForward); right = (getDriveKey(TRANSLATE_X)) * (handRotation * controllerRight); } From 9ea476ea89dd956d23c96916c6fa53bc37af54e3 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Fri, 25 Jan 2019 12:53:59 -0800 Subject: [PATCH 013/158] Attempt to add acceleration curve. --- .../qml/hifi/tablet/ControllerSettings.qml | 2 +- interface/src/avatar/MyAvatar.cpp | 618 ++++++++++-------- interface/src/avatar/MyAvatar.h | 96 +++ interface/src/ui/PreferencesDialog.cpp | 47 ++ 4 files changed, 493 insertions(+), 270 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/ControllerSettings.qml b/interface/resources/qml/hifi/tablet/ControllerSettings.qml index 6727047eb0..9feb0f6f08 100644 --- a/interface/resources/qml/hifi/tablet/ControllerSettings.qml +++ b/interface/resources/qml/hifi/tablet/ControllerSettings.qml @@ -332,7 +332,7 @@ Item { anchors.fill: stackView id: controllerPrefereneces objectName: "TabletControllerPreferences" - showCategories: ["VR Movement", "Game Controller", "Sixense Controllers", "Perception Neuron", "Leap Motion"] + showCategories: ["VR Movement", "Acceleration Step Function", "Game Controller", "Sixense Controllers", "Perception Neuron", "Leap Motion"] categoryProperties: { "VR Movement" : { "User real-world height (meters)" : { "anchors.right" : "undefined" }, diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 3183388214..f37b8e1b0a 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -139,7 +139,12 @@ MyAvatar::MyAvatar(QThread* thread) : _userHeightSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "userHeight", DEFAULT_AVATAR_HEIGHT), _flyingHMDSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "flyingHMD", _flyingPrefHMD), _handRelativeMovementSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "handRelativeMovement", _handRelativeMovement), - _avatarEntityCountSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "avatarEntityData" << "size", 0) + _avatarEntityCountSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "avatarEntityData" << "size", 0), + _driveGear1Setting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "driveGear1", _driveGear1), + _driveGear2Setting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "driveGear2", _driveGear2), + _driveGear3Setting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "driveGear3", _driveGear3), + _driveGear4Setting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "driveGear4", _driveGear4), + _driveGear5Setting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "driveGear5", _driveGear5) { _clientTraitsHandler.reset(new ClientTraitsHandler(this)); @@ -161,7 +166,7 @@ MyAvatar::MyAvatar(QThread* thread) : qApp->loadAvatarScripts(hfmModel.scripts); _shouldLoadScripts = false; } - // Load and convert old attachments to avatar entities + // Load and convert old attachments to avatar entities if (_oldAttachmentData.size() > 0) { setAttachmentData(_oldAttachmentData); _oldAttachmentData.clear(); @@ -182,7 +187,7 @@ MyAvatar::MyAvatar(QThread* thread) : // connect to AddressManager signal for location jumps connect(DependencyManager::get().data(), &AddressManager::locationChangeRequired, - this, static_cast(&MyAvatar::goToFeetLocation)); + this, static_cast(&MyAvatar::goToFeetLocation)); // handle scale constraints imposed on us by the domain-server auto& domainHandler = DependencyManager::get()->getDomainHandler(); @@ -393,7 +398,7 @@ void MyAvatar::centerBody() { // derive the desired body orientation from the current hmd orientation, before the sensor reset. auto newBodySensorMatrix = deriveBodyFromHMDSensor(); // Based on current cached HMD position/rotation.. - // transform this body into world space + // transform this body into world space auto worldBodyMatrix = _sensorToWorldMatrix * newBodySensorMatrix; auto worldBodyPos = extractTranslation(worldBodyMatrix); auto worldBodyRot = glmExtractRotation(worldBodyMatrix); @@ -446,7 +451,7 @@ void MyAvatar::reset(bool andRecenter, bool andReload, bool andHead) { // derive the desired body orientation from the *old* hmd orientation, before the sensor reset. auto newBodySensorMatrix = deriveBodyFromHMDSensor(); // Based on current cached HMD position/rotation.. - // transform this body into world space + // transform this body into world space auto worldBodyMatrix = _sensorToWorldMatrix * newBodySensorMatrix; auto worldBodyPos = extractTranslation(worldBodyMatrix); auto worldBodyRot = glmExtractRotation(worldBodyMatrix); @@ -701,16 +706,16 @@ void MyAvatar::updateEyeContactTarget(float deltaTime) { float const FIFTY_FIFTY_CHANCE = 0.5f; float const EYE_TO_MOUTH_CHANCE = 0.25f; switch (_eyeContactTarget) { - case LEFT_EYE: - _eyeContactTarget = (randFloat() < EYE_TO_MOUTH_CHANCE) ? MOUTH : RIGHT_EYE; - break; - case RIGHT_EYE: - _eyeContactTarget = (randFloat() < EYE_TO_MOUTH_CHANCE) ? MOUTH : LEFT_EYE; - break; - case MOUTH: - default: - _eyeContactTarget = (randFloat() < FIFTY_FIFTY_CHANCE) ? RIGHT_EYE : LEFT_EYE; - break; + case LEFT_EYE: + _eyeContactTarget = (randFloat() < EYE_TO_MOUTH_CHANCE) ? MOUTH : RIGHT_EYE; + break; + case RIGHT_EYE: + _eyeContactTarget = (randFloat() < EYE_TO_MOUTH_CHANCE) ? MOUTH : LEFT_EYE; + break; + case MOUTH: + default: + _eyeContactTarget = (randFloat() < FIFTY_FIFTY_CHANCE) ? RIGHT_EYE : LEFT_EYE; + break; } const float EYE_TARGET_DELAY_TIME = 0.33f; @@ -1010,17 +1015,17 @@ void MyAvatar::updateSensorToWorldMatrix() { if (_enableDebugDrawSensorToWorldMatrix) { DebugDraw::getInstance().addMarker("sensorToWorldMatrix", glmExtractRotation(_sensorToWorldMatrix), - extractTranslation(_sensorToWorldMatrix), glm::vec4(1)); + extractTranslation(_sensorToWorldMatrix), glm::vec4(1)); } _sensorToWorldMatrixCache.set(_sensorToWorldMatrix); updateJointFromController(controller::Action::LEFT_HAND, _controllerLeftHandMatrixCache); updateJointFromController(controller::Action::RIGHT_HAND, _controllerRightHandMatrixCache); - + if (hasSensorToWorldScaleChanged) { emit sensorToWorldScaleChanged(sensorToWorldScale); } - + } // Update avatar head rotation with sensor data @@ -1046,7 +1051,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) { const float TRACKER_MIN_YAW_TURN = 15.0f; const float TRACKER_MAX_YAW_TURN = 50.0f; if ( (fabs(estimatedRotation.y) > TRACKER_MIN_YAW_TURN) && - (fabs(estimatedRotation.y) < TRACKER_MAX_YAW_TURN) ) { + (fabs(estimatedRotation.y) < TRACKER_MAX_YAW_TURN) ) { if (estimatedRotation.y > 0.0f) { _bodyYawDelta += (estimatedRotation.y - TRACKER_MIN_YAW_TURN) * TRACKER_YAW_TURN_SENSITIVITY; } else { @@ -1206,7 +1211,7 @@ void MyAvatar::render(RenderArgs* renderArgs) { void MyAvatar::overrideAnimation(const QString& url, float fps, bool loop, float firstFrame, float lastFrame) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "overrideAnimation", Q_ARG(const QString&, url), Q_ARG(float, fps), - Q_ARG(bool, loop), Q_ARG(float, firstFrame), Q_ARG(float, lastFrame)); + Q_ARG(bool, loop), Q_ARG(float, firstFrame), Q_ARG(float, lastFrame)); return; } _skeletonModel->getRig().overrideAnimation(url, fps, loop, firstFrame, lastFrame); @@ -1230,10 +1235,10 @@ QStringList MyAvatar::getAnimationRoles() { } void MyAvatar::overrideRoleAnimation(const QString& role, const QString& url, float fps, bool loop, - float firstFrame, float lastFrame) { + float firstFrame, float lastFrame) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "overrideRoleAnimation", Q_ARG(const QString&, role), Q_ARG(const QString&, url), - Q_ARG(float, fps), Q_ARG(bool, loop), Q_ARG(float, firstFrame), Q_ARG(float, lastFrame)); + Q_ARG(float, fps), Q_ARG(bool, loop), Q_ARG(float, firstFrame), Q_ARG(float, lastFrame)); return; } _skeletonModel->getRig().overrideRoleAnimation(role, url, fps, loop, firstFrame, lastFrame); @@ -1250,8 +1255,8 @@ void MyAvatar::restoreRoleAnimation(const QString& role) { void MyAvatar::saveAvatarUrl() { if (qApp->getSaveAvatarOverrideUrl() || !qApp->getAvatarOverrideUrl().isValid()) { _fullAvatarURLSetting.set(_fullAvatarURLFromPreferences == AvatarData::defaultFullAvatarModelUrl() ? - "" : - _fullAvatarURLFromPreferences.toString()); + "" : + _fullAvatarURLFromPreferences.toString()); } } @@ -1268,10 +1273,10 @@ void MyAvatar::resizeAvatarEntitySettingHandles(uint32_t maxIndex) { uint32_t settingsIndex = (uint32_t)_avatarEntityIDSettings.size() + 1; while (settingsIndex <= maxIndex) { Setting::Handle idHandle(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "avatarEntityData" - << QString::number(settingsIndex) << "id", QUuid()); + << QString::number(settingsIndex) << "id", QUuid()); _avatarEntityIDSettings.push_back(idHandle); Setting::Handle dataHandle(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "avatarEntityData" - << QString::number(settingsIndex) << "properties", QByteArray()); + << QString::number(settingsIndex) << "properties", QByteArray()); _avatarEntityDataSettings.push_back(dataHandle); settingsIndex++; } @@ -1289,8 +1294,8 @@ void MyAvatar::saveData() { // --replaceAvatarURL (so _saveAvatarOverrideUrl is true) if (qApp->getSaveAvatarOverrideUrl() || !qApp->getAvatarOverrideUrl().isValid() ) { _fullAvatarURLSetting.set(_fullAvatarURLFromPreferences == AvatarData::defaultFullAvatarModelUrl() ? - "" : - _fullAvatarURLFromPreferences.toString()); + "" : + _fullAvatarURLFromPreferences.toString()); } _fullAvatarModelNameSetting.set(_fullAvatarModelName); @@ -1302,6 +1307,11 @@ void MyAvatar::saveData() { _userHeightSetting.set(getUserHeight()); _flyingHMDSetting.set(getFlyingHMDPref()); _handRelativeMovementSetting.set(getHandRelativeMovement()); + _driveGear1Setting.set(getDriveGear1()); + _driveGear2Setting.set(getDriveGear2()); + _driveGear3Setting.set(getDriveGear3()); + _driveGear4Setting.set(getDriveGear4()); + _driveGear5Setting.set(getDriveGear5()); auto hmdInterface = DependencyManager::get(); saveAvatarEntityDataToSettings(); @@ -1879,6 +1889,11 @@ void MyAvatar::loadData() { Setting::Handle firstRunVal { Settings::firstRun, true }; setFlyingHMDPref(firstRunVal.get() ? false : _flyingHMDSetting.get()); setHandRelativeMovement(firstRunVal.get() ? false : _handRelativeMovementSetting.get()); + setDriveGear1(firstRunVal.get() ? DEFAULT_GEAR_1 : _driveGear1Setting.get()); + setDriveGear2(firstRunVal.get() ? DEFAULT_GEAR_2 : _driveGear2Setting.get()); + setDriveGear3(firstRunVal.get() ? DEFAULT_GEAR_3 : _driveGear3Setting.get()); + setDriveGear4(firstRunVal.get() ? DEFAULT_GEAR_4 : _driveGear4Setting.get()); + setDriveGear5(firstRunVal.get() ? DEFAULT_GEAR_5 : _driveGear5Setting.get()); setFlyingEnabled(getFlyingEnabled()); setDisplayName(_displayNameSetting.get()); @@ -2005,7 +2020,7 @@ ScriptAvatarData* MyAvatar::getTargetAvatar() const { } static float lookAtCostFunction(const glm::vec3& myForward, const glm::vec3& myPosition, const glm::vec3& otherForward, const glm::vec3& otherPosition, - bool otherIsTalking, bool lookingAtOtherAlready) { + bool otherIsTalking, bool lookingAtOtherAlready) { const float DISTANCE_FACTOR = 3.14f; const float MY_ANGLE_FACTOR = 1.0f; const float OTHER_ANGLE_FACTOR = 1.0f; @@ -2026,10 +2041,10 @@ static float lookAtCostFunction(const glm::vec3& myForward, const glm::vec3& myP return FLT_MAX; } else { return (DISTANCE_FACTOR * distance + - MY_ANGLE_FACTOR * myAngle + - OTHER_ANGLE_FACTOR * otherAngle + - OTHER_IS_TALKING_TERM + - LOOKING_AT_OTHER_ALREADY_TERM); + MY_ANGLE_FACTOR * myAngle + + OTHER_ANGLE_FACTOR * otherAngle + + OTHER_IS_TALKING_TERM + + LOOKING_AT_OTHER_ALREADY_TERM); } } @@ -2077,8 +2092,8 @@ void MyAvatar::snapOtherAvatarLookAtTargetsToMe(const AvatarHash& hash) { // Alter their gaze to look directly at my camera; this looks more natural than looking at my avatar's face. glm::vec3 lookAtPosition = avatar->getHead()->getLookAtPosition(); // A position, in world space, on my avatar. - // The camera isn't at the point midway between the avatar eyes. (Even without an HMD, the head can be offset a bit.) - // Let's get everything to world space: + // The camera isn't at the point midway between the avatar eyes. (Even without an HMD, the head can be offset a bit.) + // Let's get everything to world space: glm::vec3 avatarLeftEye = getHead()->getLeftEyePosition(); glm::vec3 avatarRightEye = getHead()->getRightEyePosition(); @@ -2086,12 +2101,12 @@ void MyAvatar::snapOtherAvatarLookAtTargetsToMe(const AvatarHash& hash) { // (We will be adding that offset to the camera position, after making some other adjustments.) glm::vec3 gazeOffset = lookAtPosition - getHead()->getEyePosition(); - ViewFrustum viewFrustum; - qApp->copyViewFrustum(viewFrustum); + ViewFrustum viewFrustum; + qApp->copyViewFrustum(viewFrustum); - glm::vec3 viewPosition = viewFrustum.getPosition(); + glm::vec3 viewPosition = viewFrustum.getPosition(); #if DEBUG_ALWAYS_LOOKAT_EYES_NOT_CAMERA - viewPosition = (avatarLeftEye + avatarRightEye) / 2.0f; + viewPosition = (avatarLeftEye + avatarRightEye) / 2.0f; #endif // scale gazeOffset by IPD, if wearing an HMD. if (qApp->isHMDMode()) { @@ -2166,121 +2181,121 @@ void MyAvatar::setJointRotations(const QVector& jointRotations) { void MyAvatar::setJointData(int index, const glm::quat& rotation, const glm::vec3& translation) { switch (index) { - case FARGRAB_RIGHTHAND_INDEX: { - _farGrabRightMatrixCache.set(createMatFromQuatAndPos(rotation, translation)); - break; - } - case FARGRAB_LEFTHAND_INDEX: { - _farGrabLeftMatrixCache.set(createMatFromQuatAndPos(rotation, translation)); - break; - } - case FARGRAB_MOUSE_INDEX: { - _farGrabMouseMatrixCache.set(createMatFromQuatAndPos(rotation, translation)); - break; - } - default: { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setJointData", Q_ARG(int, index), Q_ARG(const glm::quat&, rotation), - Q_ARG(const glm::vec3&, translation)); - return; - } - // HACK: ATM only JS scripts call setJointData() on MyAvatar so we hardcode the priority - _skeletonModel->getRig().setJointState(index, true, rotation, translation, SCRIPT_PRIORITY); + case FARGRAB_RIGHTHAND_INDEX: { + _farGrabRightMatrixCache.set(createMatFromQuatAndPos(rotation, translation)); + break; + } + case FARGRAB_LEFTHAND_INDEX: { + _farGrabLeftMatrixCache.set(createMatFromQuatAndPos(rotation, translation)); + break; + } + case FARGRAB_MOUSE_INDEX: { + _farGrabMouseMatrixCache.set(createMatFromQuatAndPos(rotation, translation)); + break; + } + default: { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setJointData", Q_ARG(int, index), Q_ARG(const glm::quat&, rotation), + Q_ARG(const glm::vec3&, translation)); + return; } + // HACK: ATM only JS scripts call setJointData() on MyAvatar so we hardcode the priority + _skeletonModel->getRig().setJointState(index, true, rotation, translation, SCRIPT_PRIORITY); + } } } void MyAvatar::setJointRotation(int index, const glm::quat& rotation) { switch (index) { - case FARGRAB_RIGHTHAND_INDEX: { - glm::mat4 prevMat = _farGrabRightMatrixCache.get(); - glm::vec3 previousTranslation = extractTranslation(prevMat); - _farGrabRightMatrixCache.set(createMatFromQuatAndPos(rotation, previousTranslation)); - break; - } - case FARGRAB_LEFTHAND_INDEX: { - glm::mat4 prevMat = _farGrabLeftMatrixCache.get(); - glm::vec3 previousTranslation = extractTranslation(prevMat); - _farGrabLeftMatrixCache.set(createMatFromQuatAndPos(rotation, previousTranslation)); - break; - } - case FARGRAB_MOUSE_INDEX: { - glm::mat4 prevMat = _farGrabMouseMatrixCache.get(); - glm::vec3 previousTranslation = extractTranslation(prevMat); - _farGrabMouseMatrixCache.set(createMatFromQuatAndPos(rotation, previousTranslation)); - break; - } - default: { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setJointRotation", Q_ARG(int, index), Q_ARG(const glm::quat&, rotation)); - return; - } - // HACK: ATM only JS scripts call setJointData() on MyAvatar so we hardcode the priority - _skeletonModel->getRig().setJointRotation(index, true, rotation, SCRIPT_PRIORITY); + case FARGRAB_RIGHTHAND_INDEX: { + glm::mat4 prevMat = _farGrabRightMatrixCache.get(); + glm::vec3 previousTranslation = extractTranslation(prevMat); + _farGrabRightMatrixCache.set(createMatFromQuatAndPos(rotation, previousTranslation)); + break; + } + case FARGRAB_LEFTHAND_INDEX: { + glm::mat4 prevMat = _farGrabLeftMatrixCache.get(); + glm::vec3 previousTranslation = extractTranslation(prevMat); + _farGrabLeftMatrixCache.set(createMatFromQuatAndPos(rotation, previousTranslation)); + break; + } + case FARGRAB_MOUSE_INDEX: { + glm::mat4 prevMat = _farGrabMouseMatrixCache.get(); + glm::vec3 previousTranslation = extractTranslation(prevMat); + _farGrabMouseMatrixCache.set(createMatFromQuatAndPos(rotation, previousTranslation)); + break; + } + default: { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setJointRotation", Q_ARG(int, index), Q_ARG(const glm::quat&, rotation)); + return; } + // HACK: ATM only JS scripts call setJointData() on MyAvatar so we hardcode the priority + _skeletonModel->getRig().setJointRotation(index, true, rotation, SCRIPT_PRIORITY); + } } } void MyAvatar::setJointTranslation(int index, const glm::vec3& translation) { switch (index) { - case FARGRAB_RIGHTHAND_INDEX: { - glm::mat4 prevMat = _farGrabRightMatrixCache.get(); - glm::quat previousRotation = extractRotation(prevMat); - _farGrabRightMatrixCache.set(createMatFromQuatAndPos(previousRotation, translation)); - break; - } - case FARGRAB_LEFTHAND_INDEX: { - glm::mat4 prevMat = _farGrabLeftMatrixCache.get(); - glm::quat previousRotation = extractRotation(prevMat); - _farGrabLeftMatrixCache.set(createMatFromQuatAndPos(previousRotation, translation)); - break; - } - case FARGRAB_MOUSE_INDEX: { - glm::mat4 prevMat = _farGrabMouseMatrixCache.get(); - glm::quat previousRotation = extractRotation(prevMat); - _farGrabMouseMatrixCache.set(createMatFromQuatAndPos(previousRotation, translation)); - break; - } - default: { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setJointTranslation", - Q_ARG(int, index), Q_ARG(const glm::vec3&, translation)); - return; - } - // HACK: ATM only JS scripts call setJointData() on MyAvatar so we hardcode the priority - _skeletonModel->getRig().setJointTranslation(index, true, translation, SCRIPT_PRIORITY); + case FARGRAB_RIGHTHAND_INDEX: { + glm::mat4 prevMat = _farGrabRightMatrixCache.get(); + glm::quat previousRotation = extractRotation(prevMat); + _farGrabRightMatrixCache.set(createMatFromQuatAndPos(previousRotation, translation)); + break; + } + case FARGRAB_LEFTHAND_INDEX: { + glm::mat4 prevMat = _farGrabLeftMatrixCache.get(); + glm::quat previousRotation = extractRotation(prevMat); + _farGrabLeftMatrixCache.set(createMatFromQuatAndPos(previousRotation, translation)); + break; + } + case FARGRAB_MOUSE_INDEX: { + glm::mat4 prevMat = _farGrabMouseMatrixCache.get(); + glm::quat previousRotation = extractRotation(prevMat); + _farGrabMouseMatrixCache.set(createMatFromQuatAndPos(previousRotation, translation)); + break; + } + default: { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setJointTranslation", + Q_ARG(int, index), Q_ARG(const glm::vec3&, translation)); + return; } + // HACK: ATM only JS scripts call setJointData() on MyAvatar so we hardcode the priority + _skeletonModel->getRig().setJointTranslation(index, true, translation, SCRIPT_PRIORITY); + } } } void MyAvatar::clearJointData(int index) { switch (index) { - case FARGRAB_RIGHTHAND_INDEX: { - _farGrabRightMatrixCache.invalidate(); - break; - } - case FARGRAB_LEFTHAND_INDEX: { - _farGrabLeftMatrixCache.invalidate(); - break; - } - case FARGRAB_MOUSE_INDEX: { - _farGrabMouseMatrixCache.invalidate(); - break; - } - default: { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "clearJointData", Q_ARG(int, index)); - return; - } - _skeletonModel->getRig().clearJointAnimationPriority(index); + case FARGRAB_RIGHTHAND_INDEX: { + _farGrabRightMatrixCache.invalidate(); + break; + } + case FARGRAB_LEFTHAND_INDEX: { + _farGrabLeftMatrixCache.invalidate(); + break; + } + case FARGRAB_MOUSE_INDEX: { + _farGrabMouseMatrixCache.invalidate(); + break; + } + default: { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "clearJointData", Q_ARG(int, index)); + return; } + _skeletonModel->getRig().clearJointAnimationPriority(index); + } } } void MyAvatar::setJointData(const QString& name, const glm::quat& rotation, const glm::vec3& translation) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "setJointData", Q_ARG(QString, name), Q_ARG(const glm::quat&, rotation), - Q_ARG(const glm::vec3&, translation)); + Q_ARG(const glm::vec3&, translation)); return; } writeLockWithNamedJointIndex(name, [&](int index) { @@ -2346,25 +2361,25 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { std::shared_ptr skeletonConnection = std::make_shared(); *skeletonConnection = QObject::connect(_skeletonModel.get(), &SkeletonModel::skeletonLoaded, [this, skeletonModelChangeCount, skeletonConnection]() { - if (skeletonModelChangeCount == _skeletonModelChangeCount) { + if (skeletonModelChangeCount == _skeletonModelChangeCount) { - if (_fullAvatarModelName.isEmpty()) { - // Store the FST file name into preferences - const auto& mapping = _skeletonModel->getGeometry()->getMapping(); - if (mapping.value("name").isValid()) { - _fullAvatarModelName = mapping.value("name").toString(); - } - } + if (_fullAvatarModelName.isEmpty()) { + // Store the FST file name into preferences + const auto& mapping = _skeletonModel->getGeometry()->getMapping(); + if (mapping.value("name").isValid()) { + _fullAvatarModelName = mapping.value("name").toString(); + } + } - initHeadBones(); - _skeletonModel->setCauterizeBoneSet(_headBoneSet); - _fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl(); - initAnimGraph(); - _skeletonModelLoaded = true; - } - QObject::disconnect(*skeletonConnection); + initHeadBones(); + _skeletonModel->setCauterizeBoneSet(_headBoneSet); + _fstAnimGraphOverrideUrl = _skeletonModel->getGeometry()->getAnimGraphOverrideUrl(); + initAnimGraph(); + _skeletonModelLoaded = true; + } + QObject::disconnect(*skeletonConnection); }); - + saveAvatarUrl(); emit skeletonChanged(); } @@ -2413,7 +2428,7 @@ QVariantList MyAvatar::getAvatarEntitiesVariant() { if (entityTree) { QList avatarEntityIDs; _avatarEntitiesLock.withReadLock([&] { - avatarEntityIDs = _packedAvatarEntityData.keys(); + avatarEntityIDs = _packedAvatarEntityData.keys(); }); for (const auto& entityID : avatarEntityIDs) { auto entity = entityTree->findEntityByID(entityID); @@ -2447,8 +2462,8 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN if (QThread::currentThread() != thread()) { BLOCKING_INVOKE_METHOD(this, "useFullAvatarURL", - Q_ARG(const QUrl&, fullAvatarURL), - Q_ARG(const QString&, modelName)); + Q_ARG(const QUrl&, fullAvatarURL), + Q_ARG(const QString&, modelName)); return; } @@ -2543,7 +2558,7 @@ void MyAvatar::updateMotors() { float verticalMotorTimescale; if (_characterController.getState() == CharacterController::State::Hover || - _characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { + _characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { horizontalMotorTimescale = FLYING_MOTOR_TIMESCALE; verticalMotorTimescale = FLYING_MOTOR_TIMESCALE; } else { @@ -2553,7 +2568,7 @@ void MyAvatar::updateMotors() { if (_motionBehaviors & AVATAR_MOTION_ACTION_MOTOR_ENABLED) { if (_characterController.getState() == CharacterController::State::Hover || - _characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { + _characterController.computeCollisionGroup() == BULLET_COLLISION_GROUP_COLLISIONLESS) { motorRotation = getMyHead()->getHeadOrientation(); } else { // non-hovering = walking: follow camera twist about vertical but not lift @@ -2694,7 +2709,7 @@ void MyAvatar::setScriptedMotorTimescale(float timescale) { // we clamp the timescale on the large side (instead of just the low side) to prevent // obnoxiously large values from introducing NaN into avatar's velocity _scriptedMotorTimescale = glm::clamp(timescale, MIN_SCRIPTED_MOTOR_TIMESCALE, - DEFAULT_SCRIPTED_MOTOR_TIMESCALE); + DEFAULT_SCRIPTED_MOTOR_TIMESCALE); } void MyAvatar::setScriptedMotorFrame(QString frame) { @@ -2736,9 +2751,9 @@ SharedSoundPointer MyAvatar::getCollisionSound() { } void MyAvatar::attach(const QString& modelURL, const QString& jointName, - const glm::vec3& translation, const glm::quat& rotation, - float scale, bool isSoft, - bool allowDuplicates, bool useSaved) { + const glm::vec3& translation, const glm::quat& rotation, + float scale, bool isSoft, + bool allowDuplicates, bool useSaved) { if (QThread::currentThread() != thread()) { BLOCKING_INVOKE_METHOD(this, "attach", Q_ARG(const QString&, modelURL), @@ -2863,7 +2878,7 @@ void MyAvatar::setAttachmentsVariant(const QVariantList& variant) { bool MyAvatar::findAvatarEntity(const QString& modelURL, const QString& jointName, QUuid& entityID) { QList avatarEntityIDs; _avatarEntitiesLock.withReadLock([&] { - avatarEntityIDs = _packedAvatarEntityData.keys(); + avatarEntityIDs = _packedAvatarEntityData.keys(); }); for (const auto& entityID : avatarEntityIDs) { auto props = DependencyManager::get()->getEntityProperties(entityID); @@ -3420,7 +3435,7 @@ void MyAvatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTim } bool findAvatarAvatarPenetration(const glm::vec3 positionA, float radiusA, float heightA, - const glm::vec3 positionB, float radiusB, float heightB, glm::vec3& penetration) { + const glm::vec3 positionB, float radiusB, float heightB, glm::vec3& penetration) { glm::vec3 positionBA = positionB - positionA; float xzDistance = sqrt(positionBA.x * positionBA.x + positionBA.z * positionBA.z); if (xzDistance < (radiusA + radiusB)) { @@ -3525,7 +3540,7 @@ void MyAvatar::restrictScaleFromDomainSettings(const QJsonObject& domainSettings _targetScale = getDomainLimitedScale(); qCDebug(interfaceapp) << "This domain requires a minimum avatar scale of " << _domainMinimumHeight - << " and a maximum avatar scale of " << _domainMaximumHeight; + << " and a maximum avatar scale of " << _domainMaximumHeight; _isAnimatingScale = true; @@ -3585,15 +3600,15 @@ void MyAvatar::goToLocation(const QVariant& propertiesVar) { } void MyAvatar::goToFeetLocation(const glm::vec3& newPosition, - bool hasOrientation, const glm::quat& newOrientation, - bool shouldFaceLocation) { + bool hasOrientation, const glm::quat& newOrientation, + bool shouldFaceLocation) { _goToFeetAjustment = true; goToLocation(newPosition, hasOrientation, newOrientation, shouldFaceLocation); } void MyAvatar::goToLocation(const glm::vec3& newPosition, - bool hasOrientation, const glm::quat& newOrientation, - bool shouldFaceLocation, bool withSafeLanding) { + bool hasOrientation, const glm::quat& newOrientation, + bool shouldFaceLocation, bool withSafeLanding) { // Most cases of going to a place or user go through this now. Some possible improvements to think about in the future: // - It would be nice if this used the same teleport steps and smoothing as in the teleport.js script, as long as it @@ -3617,7 +3632,7 @@ void MyAvatar::goToLocation(const glm::vec3& newPosition, _goToOrientation = getWorldOrientation(); if (hasOrientation) { qCDebug(interfaceapp).nospace() << "MyAvatar goToLocation - new orientation is " - << newOrientation.x << ", " << newOrientation.y << ", " << newOrientation.z << ", " << newOrientation.w; + << newOrientation.x << ", " << newOrientation.y << ", " << newOrientation.z << ", " << newOrientation.w; // orient the user to face the target glm::quat quatOrientation = cancelOutRollAndPitch(newOrientation); @@ -3662,13 +3677,13 @@ bool MyAvatar::safeLanding(const glm::vec3& position) { } if (!getCollisionsEnabled()) { goToLocation(better); // recurses on next update - } else { // If you try to go while stuck, physics will keep you stuck. + } else { // If you try to go while stuck, physics will keep you stuck. setCollisionsEnabled(false); // Don't goToLocation just yet. Yield so that physics can act on the above. QMetaObject::invokeMethod(this, "goToLocationAndEnableCollisions", Qt::QueuedConnection, // The equivalent of javascript nextTick Q_ARG(glm::vec3, better)); - } - return true; + } + return true; } // If position is not reliably safe from being stuck by physics, answer true and place a candidate better position in betterPositionOut. @@ -3860,6 +3875,71 @@ bool MyAvatar::getHandRelativeMovement() { return _handRelativeMovement; } +void MyAvatar::setDriveGear1(float shiftPoint) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setDriveGear1", Q_ARG(float, shiftPoint)); + return; + } + if (shiftPoint > 1.0 || shiftPoint < 0) return; + _driveGear1 = (shiftPoint <= _driveGear2) ? shiftPoint : _driveGear1; +} + +float MyAvatar::getDriveGear1() { + return _driveGear1; +} + +void MyAvatar::setDriveGear2(float shiftPoint) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setDriveGear2", Q_ARG(float, shiftPoint)); + return; + } + if (shiftPoint > 1.0 || shiftPoint < 0) return; + _driveGear2 = (shiftPoint <= _driveGear3 && shiftPoint >= _driveGear1) ? shiftPoint : _driveGear2; +} + +float MyAvatar::getDriveGear2() { + return _driveGear2; +} + +void MyAvatar::setDriveGear3(float shiftPoint) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setDriveGear3", Q_ARG(float, shiftPoint)); + return; + } + if (shiftPoint > 1.0 || shiftPoint < 0) return; + _driveGear3 = (shiftPoint <= _driveGear4 && shiftPoint >= _driveGear2) ? shiftPoint : _driveGear3; +} + +float MyAvatar::getDriveGear3() { + return _driveGear3; +} + +void MyAvatar::setDriveGear4(float shiftPoint) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setDriveGear4", Q_ARG(float, shiftPoint)); + return; + } + if (shiftPoint > 1.0 || shiftPoint < 0) return; + _driveGear4 = (shiftPoint <= _driveGear5 && shiftPoint >= _driveGear3) ? shiftPoint : _driveGear4; +} + +float MyAvatar::getDriveGear4() { + return _driveGear4; +} + +void MyAvatar::setDriveGear5(float shiftPoint) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setDriveGear5", Q_ARG(float, shiftPoint)); + return; + } + if (shiftPoint > 1.0 || shiftPoint < 0) return; + _driveGear5 = (shiftPoint >= _driveGear4) ? shiftPoint : _driveGear5; +} + +float MyAvatar::getDriveGear5() { + return _driveGear5; +} + bool MyAvatar::getFlyingHMDPref() { return _flyingPrefHMD; } @@ -4490,27 +4570,27 @@ void MyAvatar::setUserRecenterModel(MyAvatar::SitStandModelType modelName) { _userRecenterModel.set(modelName); switch (modelName) { - case MyAvatar::SitStandModelType::ForceSit: - setHMDLeanRecenterEnabled(true); - setIsInSittingState(true); - setIsSitStandStateLocked(true); - break; - case MyAvatar::SitStandModelType::ForceStand: - setHMDLeanRecenterEnabled(true); - setIsInSittingState(false); - setIsSitStandStateLocked(true); - break; - case MyAvatar::SitStandModelType::Auto: - default: - setHMDLeanRecenterEnabled(true); - setIsInSittingState(false); - setIsSitStandStateLocked(false); - break; - case MyAvatar::SitStandModelType::DisableHMDLean: - setHMDLeanRecenterEnabled(false); - setIsInSittingState(false); - setIsSitStandStateLocked(false); - break; + case MyAvatar::SitStandModelType::ForceSit: + setHMDLeanRecenterEnabled(true); + setIsInSittingState(true); + setIsSitStandStateLocked(true); + break; + case MyAvatar::SitStandModelType::ForceStand: + setHMDLeanRecenterEnabled(true); + setIsInSittingState(false); + setIsSitStandStateLocked(true); + break; + case MyAvatar::SitStandModelType::Auto: + default: + setHMDLeanRecenterEnabled(true); + setIsInSittingState(false); + setIsSitStandStateLocked(false); + break; + case MyAvatar::SitStandModelType::DisableHMDLean: + setHMDLeanRecenterEnabled(false); + setIsInSittingState(false); + setIsSitStandStateLocked(false); + break; } } @@ -4558,15 +4638,15 @@ QVector MyAvatar::getScriptUrls() { glm::vec3 MyAvatar::getPositionForAudio() { glm::vec3 result; switch (_audioListenerMode) { - case AudioListenerMode::FROM_HEAD: - result = getHead()->getPosition(); - break; - case AudioListenerMode::FROM_CAMERA: - result = qApp->getCamera().getPosition(); - break; - case AudioListenerMode::CUSTOM: - result = _customListenPosition; - break; + case AudioListenerMode::FROM_HEAD: + result = getHead()->getPosition(); + break; + case AudioListenerMode::FROM_CAMERA: + result = qApp->getCamera().getPosition(); + break; + case AudioListenerMode::CUSTOM: + result = _customListenPosition; + break; } if (isNaN(result)) { @@ -4581,15 +4661,15 @@ glm::quat MyAvatar::getOrientationForAudio() { glm::quat result; switch (_audioListenerMode) { - case AudioListenerMode::FROM_HEAD: - result = getHead()->getFinalOrientationInWorldFrame(); - break; - case AudioListenerMode::FROM_CAMERA: - result = qApp->getCamera().getOrientation(); - break; - case AudioListenerMode::CUSTOM: - result = _customListenOrientation; - break; + case AudioListenerMode::FROM_HEAD: + result = getHead()->getFinalOrientationInWorldFrame(); + break; + case AudioListenerMode::FROM_CAMERA: + result = qApp->getCamera().getOrientation(); + break; + case AudioListenerMode::CUSTOM: + result = _customListenOrientation; + break; } if (isNaN(result)) { @@ -4794,7 +4874,7 @@ bool MyAvatar::FollowHelper::shouldActivateVertical(const MyAvatar& myAvatar, co } void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat4& desiredBodyMatrix, - const glm::mat4& currentBodyMatrix, bool hasDriveInput) { + const glm::mat4& currentBodyMatrix, bool hasDriveInput) { if (myAvatar.getHMDLeanRecenterEnabled() && qApp->getCamera().getMode() != CAMERA_MODE_MIRROR) { @@ -4858,8 +4938,8 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat followWorldPose.scale() = glm::vec3(1.0f); if (isActive(Rotation)) { - //use the hmd reading for the hips follow - followWorldPose.rot() = glmExtractRotation(desiredWorldMatrix); + //use the hmd reading for the hips follow + followWorldPose.rot() = glmExtractRotation(desiredWorldMatrix); } if (isActive(Horizontal)) { glm::vec3 desiredTranslation = extractTranslation(desiredWorldMatrix); @@ -4890,7 +4970,7 @@ glm::mat4 MyAvatar::FollowHelper::postPhysicsUpdate(MyAvatar& myAvatar, const gl glm::quat sensorAngularDisplacement = glmExtractRotation(worldToSensorMatrix) * worldAngularDisplacement * glmExtractRotation(sensorToWorldMatrix); glm::mat4 newBodyMat = createMatFromQuatAndPos(sensorAngularDisplacement * glmExtractRotation(currentBodyMatrix), - sensorLinearDisplacement + extractTranslation(currentBodyMatrix)); + sensorLinearDisplacement + extractTranslation(currentBodyMatrix)); if (myAvatar.getSitStandStateChange()) { myAvatar.setSitStandStateChange(false); deactivate(Vertical); @@ -5002,34 +5082,34 @@ glm::quat MyAvatar::getAbsoluteJointRotationInObjectFrame(int index) const { } switch (index) { - case CONTROLLER_LEFTHAND_INDEX: { - return getControllerPoseInAvatarFrame(controller::Action::LEFT_HAND).getRotation(); - } - case CONTROLLER_RIGHTHAND_INDEX: { - return getControllerPoseInAvatarFrame(controller::Action::RIGHT_HAND).getRotation(); - } - case CAMERA_RELATIVE_CONTROLLER_LEFTHAND_INDEX: { - auto pose = getControllerPoseInSensorFrame(controller::Action::LEFT_HAND); - glm::mat4 controllerSensorMatrix = createMatFromQuatAndPos(pose.rotation, pose.translation); - glm::mat4 result = computeCameraRelativeHandControllerMatrix(controllerSensorMatrix); - return glmExtractRotation(result); - } - case CAMERA_RELATIVE_CONTROLLER_RIGHTHAND_INDEX: { - auto pose = getControllerPoseInSensorFrame(controller::Action::RIGHT_HAND); - glm::mat4 controllerSensorMatrix = createMatFromQuatAndPos(pose.rotation, pose.translation); - glm::mat4 result = computeCameraRelativeHandControllerMatrix(controllerSensorMatrix); - return glmExtractRotation(result); - } - case CAMERA_MATRIX_INDEX: { - bool success; - Transform avatarTransform; - Transform::mult(avatarTransform, getParentTransform(success), getLocalTransform()); - glm::mat4 invAvatarMat = avatarTransform.getInverseMatrix(); - return glmExtractRotation(invAvatarMat * qApp->getCamera().getTransform()); - } - default: { - return Avatar::getAbsoluteJointRotationInObjectFrame(index); - } + case CONTROLLER_LEFTHAND_INDEX: { + return getControllerPoseInAvatarFrame(controller::Action::LEFT_HAND).getRotation(); + } + case CONTROLLER_RIGHTHAND_INDEX: { + return getControllerPoseInAvatarFrame(controller::Action::RIGHT_HAND).getRotation(); + } + case CAMERA_RELATIVE_CONTROLLER_LEFTHAND_INDEX: { + auto pose = getControllerPoseInSensorFrame(controller::Action::LEFT_HAND); + glm::mat4 controllerSensorMatrix = createMatFromQuatAndPos(pose.rotation, pose.translation); + glm::mat4 result = computeCameraRelativeHandControllerMatrix(controllerSensorMatrix); + return glmExtractRotation(result); + } + case CAMERA_RELATIVE_CONTROLLER_RIGHTHAND_INDEX: { + auto pose = getControllerPoseInSensorFrame(controller::Action::RIGHT_HAND); + glm::mat4 controllerSensorMatrix = createMatFromQuatAndPos(pose.rotation, pose.translation); + glm::mat4 result = computeCameraRelativeHandControllerMatrix(controllerSensorMatrix); + return glmExtractRotation(result); + } + case CAMERA_MATRIX_INDEX: { + bool success; + Transform avatarTransform; + Transform::mult(avatarTransform, getParentTransform(success), getLocalTransform()); + glm::mat4 invAvatarMat = avatarTransform.getInverseMatrix(); + return glmExtractRotation(invAvatarMat * qApp->getCamera().getTransform()); + } + default: { + return Avatar::getAbsoluteJointRotationInObjectFrame(index); + } } } @@ -5039,34 +5119,34 @@ glm::vec3 MyAvatar::getAbsoluteJointTranslationInObjectFrame(int index) const { } switch (index) { - case CONTROLLER_LEFTHAND_INDEX: { - return getControllerPoseInAvatarFrame(controller::Action::LEFT_HAND).getTranslation(); - } - case CONTROLLER_RIGHTHAND_INDEX: { - return getControllerPoseInAvatarFrame(controller::Action::RIGHT_HAND).getTranslation(); - } - case CAMERA_RELATIVE_CONTROLLER_LEFTHAND_INDEX: { - auto pose = getControllerPoseInSensorFrame(controller::Action::LEFT_HAND); - glm::mat4 controllerSensorMatrix = createMatFromQuatAndPos(pose.rotation, pose.translation); - glm::mat4 result = computeCameraRelativeHandControllerMatrix(controllerSensorMatrix); - return extractTranslation(result); - } - case CAMERA_RELATIVE_CONTROLLER_RIGHTHAND_INDEX: { - auto pose = getControllerPoseInSensorFrame(controller::Action::RIGHT_HAND); - glm::mat4 controllerSensorMatrix = createMatFromQuatAndPos(pose.rotation, pose.translation); - glm::mat4 result = computeCameraRelativeHandControllerMatrix(controllerSensorMatrix); - return extractTranslation(result); - } - case CAMERA_MATRIX_INDEX: { - bool success; - Transform avatarTransform; - Transform::mult(avatarTransform, getParentTransform(success), getLocalTransform()); - glm::mat4 invAvatarMat = avatarTransform.getInverseMatrix(); - return extractTranslation(invAvatarMat * qApp->getCamera().getTransform()); - } - default: { - return Avatar::getAbsoluteJointTranslationInObjectFrame(index); - } + case CONTROLLER_LEFTHAND_INDEX: { + return getControllerPoseInAvatarFrame(controller::Action::LEFT_HAND).getTranslation(); + } + case CONTROLLER_RIGHTHAND_INDEX: { + return getControllerPoseInAvatarFrame(controller::Action::RIGHT_HAND).getTranslation(); + } + case CAMERA_RELATIVE_CONTROLLER_LEFTHAND_INDEX: { + auto pose = getControllerPoseInSensorFrame(controller::Action::LEFT_HAND); + glm::mat4 controllerSensorMatrix = createMatFromQuatAndPos(pose.rotation, pose.translation); + glm::mat4 result = computeCameraRelativeHandControllerMatrix(controllerSensorMatrix); + return extractTranslation(result); + } + case CAMERA_RELATIVE_CONTROLLER_RIGHTHAND_INDEX: { + auto pose = getControllerPoseInSensorFrame(controller::Action::RIGHT_HAND); + glm::mat4 controllerSensorMatrix = createMatFromQuatAndPos(pose.rotation, pose.translation); + glm::mat4 result = computeCameraRelativeHandControllerMatrix(controllerSensorMatrix); + return extractTranslation(result); + } + case CAMERA_MATRIX_INDEX: { + bool success; + Transform avatarTransform; + Transform::mult(avatarTransform, getParentTransform(success), getLocalTransform()); + glm::mat4 invAvatarMat = avatarTransform.getInverseMatrix(); + return extractTranslation(invAvatarMat * qApp->getCamera().getTransform()); + } + default: { + return Avatar::getAbsoluteJointTranslationInObjectFrame(index); + } } } @@ -5286,7 +5366,7 @@ SpatialParentTree* MyAvatar::getParentTree() const { } const QUuid MyAvatar::grab(const QUuid& targetID, int parentJointIndex, - glm::vec3 positionalOffset, glm::quat rotationalOffset) { + glm::vec3 positionalOffset, glm::quat rotationalOffset) { auto grabID = QUuid::createUuid(); // create a temporary grab object to get grabData @@ -5297,14 +5377,14 @@ const QUuid MyAvatar::grab(const QUuid& targetID, int parentJointIndex, parentJointIndex == getJointIndex("RightHand")) { hand = "right"; } else if (parentJointIndex == CONTROLLER_LEFTHAND_INDEX || - parentJointIndex == CAMERA_RELATIVE_CONTROLLER_LEFTHAND_INDEX || - parentJointIndex == FARGRAB_LEFTHAND_INDEX || - parentJointIndex == getJointIndex("LeftHand")) { + parentJointIndex == CAMERA_RELATIVE_CONTROLLER_LEFTHAND_INDEX || + parentJointIndex == FARGRAB_LEFTHAND_INDEX || + parentJointIndex == getJointIndex("LeftHand")) { hand = "left"; } Grab tmpGrab(DependencyManager::get()->getSessionUUID(), - targetID, parentJointIndex, hand, positionalOffset, rotationalOffset); + targetID, parentJointIndex, hand, positionalOffset, rotationalOffset); QByteArray grabData = tmpGrab.toByteArray(); bool dataChanged = updateAvatarGrabData(grabID, grabData); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 9520fb7cc4..c5c3b1b46a 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -253,6 +253,12 @@ class MyAvatar : public Avatar { const QString DOMINANT_LEFT_HAND = "left"; const QString DOMINANT_RIGHT_HAND = "right"; + const float DEFAULT_GEAR_1 = 0.2f; + const float DEFAULT_GEAR_2 = 0.4f; + const float DEFAULT_GEAR_3 = 0.8f; + const float DEFAULT_GEAR_4 = 0.9f; + const float DEFAULT_GEAR_5 = 1.0f; + public: enum DriveKeys { TRANSLATE_X = 0, @@ -1061,6 +1067,76 @@ public: */ Q_INVOKABLE bool getHandRelativeMovement(); + /**jsdoc + * Set the first 'shifting point' for acceleration step function. + * @function MyAvatar.setDriveGear1 + * @param {number} shiftPoint - Set the first shift point for analog movement acceleration step function, between [0.0, 1.0]. Must be less than or equal to Gear 2. + */ + Q_INVOKABLE void setDriveGear1(float shiftPoint); + + /**jsdoc + * Get the first 'shifting point' for acceleration step function. + * @function MyAvatar.getDriveGear1 + * @returns {number} Value between [0.0, 1.0]. + */ + Q_INVOKABLE float getDriveGear1(); + + /**jsdoc + * Set the second 'shifting point' for acceleration step function. + * @function MyAvatar.setDriveGear2 + * @param {number} shiftPoint - Defines the second shift point for analog movement acceleration step function, between [0, 1]. Must be greater than or equal to Gear 1 and less than or equal to Gear 2. + */ + Q_INVOKABLE void setDriveGear2(float shiftPoint); + + /**jsdoc + * Get the second 'shifting point' for acceleration step function. + * @function MyAvatar.getDriveGear2 + * @returns {number} Value between [0.0, 1.0]. + */ + Q_INVOKABLE float getDriveGear2(); + + /**jsdoc + * Set the third 'shifting point' for acceleration step function. + * @function MyAvatar.setDriveGear3 + * @param {number} shiftPoint - Defines the third shift point for analog movement acceleration step function, between [0, 1]. Must be greater than or equal to Gear 2 and less than or equal to Gear 4. + */ + Q_INVOKABLE void setDriveGear3(float shiftPoint); + + /**jsdoc + * Get the third 'shifting point' for acceleration step function. + * @function MyAvatar.getDriveGear3 + * @returns {number} Value between [0.0, 1.0]. + */ + Q_INVOKABLE float getDriveGear3(); + + /**jsdoc + * Set the fourth 'shifting point' for acceleration step function. + * @function MyAvatar.setDriveGear4 + * @param {number} shiftPoint - Defines the fourth shift point for analog movement acceleration step function, between [0, 1]. Must be greater than Gear 3 and less than Gear 5. + */ + Q_INVOKABLE void setDriveGear4(float shiftPoint); + + /**jsdoc + * Get the fourth 'shifting point' for acceleration step function. + * @function MyAvatar.getDriveGear4 + * @returns {number} Value between [0.0, 1.0]. + */ + Q_INVOKABLE float getDriveGear4(); + + /**jsdoc + * Set the fifth 'shifting point' for acceleration step function. + * @function MyAvatar.setDriveGear5 + * @param {number} shiftPoint - Defines the fifth shift point for analog movement acceleration step function, between [0, 1]. Must be greater than or equal to Gear 4. + */ + Q_INVOKABLE void setDriveGear5(float shiftPoint); + + /**jsdoc + * Get the fifth 'shifting point' for acceleration step function. + * @function MyAvatar.getDriveGear5 + * @returns {number} Value between [0.0, 1.0]. + */ + Q_INVOKABLE float getDriveGear5(); + /**jsdoc * @function MyAvatar.getAvatarScale * @returns {number} @@ -1732,6 +1808,20 @@ private: float _boomLength { ZOOM_DEFAULT }; float _yawSpeed; // degrees/sec float _pitchSpeed; // degrees/sec + float _driveGear1 { DEFAULT_GEAR_1 }; + float _driveGear2 { DEFAULT_GEAR_2 }; + float _driveGear3 { DEFAULT_GEAR_3 }; + float _driveGear4 { DEFAULT_GEAR_4 }; + float _driveGear5 { DEFAULT_GEAR_5 }; + + int _controlSchemeIndex; + + //Setting::Handle _driveGear1Setting; + //Setting::Handle _driveGear2Setting; + //Setting::Handle _driveGear3Setting; + //Setting::Handle _driveGear4Setting; + //Setting::Handle _driveGear5Setting; + //Setting::Handle controlSchemeIndex; glm::vec3 _thrust { 0.0f }; // impulse accumulator for outside sources @@ -1972,6 +2062,12 @@ private: Setting::Handle _handRelativeMovementSetting; Setting::Handle _avatarEntityCountSetting; Setting::Handle _allowTeleportingSetting { "allowTeleporting", true }; + Setting::Handle _driveGear1Setting; + Setting::Handle _driveGear2Setting; + Setting::Handle _driveGear3Setting; + Setting::Handle _driveGear4Setting; + Setting::Handle _driveGear5Setting; + Setting::Handle controlSchemeIndexSetting; std::vector> _avatarEntityIDSettings; std::vector> _avatarEntityDataSettings; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 918fb6d830..97561eb78d 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -348,6 +348,53 @@ void setupPreferences() { preferences->addPreference(preference); } + static const QString ACCEL_CURVE{ "Acceleration Step Function" }; + { + auto getter = [myAvatar]()->float { return myAvatar->getDriveGear1(); }; + auto setter = [myAvatar](float value) { myAvatar->setDriveGear1(value); }; + auto preference = new SpinnerPreference(ACCEL_CURVE, "Gear 1", getter, setter); + preference->setMin(1); + preference->setMax(5); + preference->setStep(1); + preferences->addPreference(preference); + } + { + auto getter = [myAvatar]()->float { return myAvatar->getDriveGear2(); }; + auto setter = [myAvatar](float value) { myAvatar->setDriveGear2(value); }; + auto preference = new SpinnerPreference(ACCEL_CURVE, "Gear 2", getter, setter); + preference->setMin(1); + preference->setMax(5); + preference->setStep(1); + preferences->addPreference(preference); + } + { + auto getter = [myAvatar]()->float { return myAvatar->getDriveGear3(); }; + auto setter = [myAvatar](float value) { myAvatar->setDriveGear3(value); }; + auto preference = new SpinnerPreference(ACCEL_CURVE, "Gear 3", getter, setter); + preference->setMin(1); + preference->setMax(5); + preference->setStep(1); + preferences->addPreference(preference); + } + { + auto getter = [myAvatar]()->float { return myAvatar->getDriveGear4(); }; + auto setter = [myAvatar](float value) { myAvatar->setDriveGear4(value); }; + auto preference = new SpinnerPreference(ACCEL_CURVE, "Gear 4", getter, setter); + preference->setMin(1); + preference->setMax(5); + preference->setStep(1); + preferences->addPreference(preference); + } + { + auto getter = [myAvatar]()->float { return myAvatar->getDriveGear5(); }; + auto setter = [myAvatar](float value) { myAvatar->setDriveGear5(value); }; + auto preference = new SpinnerPreference(ACCEL_CURVE, "Gear 5", getter, setter); + preference->setMin(1); + preference->setMax(5); + preference->setStep(1); + preferences->addPreference(preference); + } + static const QString AVATAR_CAMERA{ "Mouse Sensitivity" }; { auto getter = [myAvatar]()->float { return myAvatar->getPitchSpeed(); }; From 35818e9b9d495b883b1be7af9c5a958bb6086833 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Fri, 25 Jan 2019 14:27:02 -0800 Subject: [PATCH 014/158] Add menu items for 'gear' selection. --- interface/src/avatar/MyAvatar.h | 10 ---------- interface/src/ui/PreferencesDialog.cpp | 25 +++++++++++++++---------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index c5c3b1b46a..799fcef1ea 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1814,15 +1814,6 @@ private: float _driveGear4 { DEFAULT_GEAR_4 }; float _driveGear5 { DEFAULT_GEAR_5 }; - int _controlSchemeIndex; - - //Setting::Handle _driveGear1Setting; - //Setting::Handle _driveGear2Setting; - //Setting::Handle _driveGear3Setting; - //Setting::Handle _driveGear4Setting; - //Setting::Handle _driveGear5Setting; - //Setting::Handle controlSchemeIndex; - glm::vec3 _thrust { 0.0f }; // impulse accumulator for outside sources glm::vec3 _actionMotorVelocity; // target local-frame velocity of avatar (default controller actions) @@ -2067,7 +2058,6 @@ private: Setting::Handle _driveGear3Setting; Setting::Handle _driveGear4Setting; Setting::Handle _driveGear5Setting; - Setting::Handle controlSchemeIndexSetting; std::vector> _avatarEntityIDSettings; std::vector> _avatarEntityDataSettings; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 97561eb78d..ae5eefbe7a 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -353,45 +353,50 @@ void setupPreferences() { auto getter = [myAvatar]()->float { return myAvatar->getDriveGear1(); }; auto setter = [myAvatar](float value) { myAvatar->setDriveGear1(value); }; auto preference = new SpinnerPreference(ACCEL_CURVE, "Gear 1", getter, setter); - preference->setMin(1); - preference->setMax(5); + preference->setMin(0.0f); + preference->setMax(1.0f); preference->setStep(1); + preference->setDecimals(2); preferences->addPreference(preference); } { auto getter = [myAvatar]()->float { return myAvatar->getDriveGear2(); }; auto setter = [myAvatar](float value) { myAvatar->setDriveGear2(value); }; auto preference = new SpinnerPreference(ACCEL_CURVE, "Gear 2", getter, setter); - preference->setMin(1); - preference->setMax(5); + preference->setMin(0.0f); + preference->setMax(1.0f); preference->setStep(1); + preference->setDecimals(2); preferences->addPreference(preference); } { auto getter = [myAvatar]()->float { return myAvatar->getDriveGear3(); }; auto setter = [myAvatar](float value) { myAvatar->setDriveGear3(value); }; auto preference = new SpinnerPreference(ACCEL_CURVE, "Gear 3", getter, setter); - preference->setMin(1); - preference->setMax(5); + preference->setMin(0.0f); + preference->setMax(1.0f); preference->setStep(1); + preference->setDecimals(2); preferences->addPreference(preference); } { auto getter = [myAvatar]()->float { return myAvatar->getDriveGear4(); }; auto setter = [myAvatar](float value) { myAvatar->setDriveGear4(value); }; auto preference = new SpinnerPreference(ACCEL_CURVE, "Gear 4", getter, setter); - preference->setMin(1); - preference->setMax(5); + preference->setMin(0.0f); + preference->setMax(1.0f); preference->setStep(1); + preference->setDecimals(2); preferences->addPreference(preference); } { auto getter = [myAvatar]()->float { return myAvatar->getDriveGear5(); }; auto setter = [myAvatar](float value) { myAvatar->setDriveGear5(value); }; auto preference = new SpinnerPreference(ACCEL_CURVE, "Gear 5", getter, setter); - preference->setMin(1); - preference->setMax(5); + preference->setMin(0.0f); + preference->setMax(1.0f); preference->setStep(1); + preference->setDecimals(2); preferences->addPreference(preference); } From 338d4c3c18fdb8147994401177c69871fed58035 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Fri, 25 Jan 2019 15:14:17 -0800 Subject: [PATCH 015/158] Lay groundwork for control scheme selection. --- interface/src/avatar/MyAvatar.cpp | 18 +++++++++++++++++- interface/src/avatar/MyAvatar.h | 17 +++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index f37b8e1b0a..789e192a69 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -144,7 +144,8 @@ MyAvatar::MyAvatar(QThread* thread) : _driveGear2Setting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "driveGear2", _driveGear2), _driveGear3Setting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "driveGear3", _driveGear3), _driveGear4Setting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "driveGear4", _driveGear4), - _driveGear5Setting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "driveGear5", _driveGear5) + _driveGear5Setting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "driveGear5", _driveGear5), + _controlSchemeIndexSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "controlSchemeIndex", _controlSchemeIndex) { _clientTraitsHandler.reset(new ClientTraitsHandler(this)); @@ -1312,6 +1313,7 @@ void MyAvatar::saveData() { _driveGear3Setting.set(getDriveGear3()); _driveGear4Setting.set(getDriveGear4()); _driveGear5Setting.set(getDriveGear5()); + _controlSchemeIndexSetting.set(getControlSchemeIndex()); auto hmdInterface = DependencyManager::get(); saveAvatarEntityDataToSettings(); @@ -1894,6 +1896,7 @@ void MyAvatar::loadData() { setDriveGear3(firstRunVal.get() ? DEFAULT_GEAR_3 : _driveGear3Setting.get()); setDriveGear4(firstRunVal.get() ? DEFAULT_GEAR_4 : _driveGear4Setting.get()); setDriveGear5(firstRunVal.get() ? DEFAULT_GEAR_5 : _driveGear5Setting.get()); + setControlSchemeIndex(firstRunVal.get() ? DEFAULT_CONTROL_SCHEME_INDEX : _controlSchemeIndexSetting.get()); setFlyingEnabled(getFlyingEnabled()); setDisplayName(_displayNameSetting.get()); @@ -3875,6 +3878,19 @@ bool MyAvatar::getHandRelativeMovement() { return _handRelativeMovement; } +void MyAvatar::setControlSchemeIndex(int index){ + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setControlSchemeIndex", Q_ARG(int, index)); + return; + } + // Need to add checks for valid indices. + _controlSchemeIndex = index; +} + +int MyAvatar::getControlSchemeIndex() { + return _controlSchemeIndex; +} + void MyAvatar::setDriveGear1(float shiftPoint) { if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "setDriveGear1", Q_ARG(float, shiftPoint)); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 799fcef1ea..c0264b97dc 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -258,6 +258,7 @@ class MyAvatar : public Avatar { const float DEFAULT_GEAR_3 = 0.8f; const float DEFAULT_GEAR_4 = 0.9f; const float DEFAULT_GEAR_5 = 1.0f; + const int DEFAULT_CONTROL_SCHEME_INDEX = 0; public: enum DriveKeys { @@ -1137,6 +1138,20 @@ public: */ Q_INVOKABLE float getDriveGear5(); + /**jsdoc + * Choose the control scheme. + * @function MyAvatar.setControlSchemeIndex + * @param {number} Choose the control scheme to be used. + */ + void setControlSchemeIndex(int index); + + /**jsdoc + * Check what control scheme is in use. + * @function MyAvatar.getControlSchemeIndex + * @returns {number} Returns the index associated with a given control scheme. + */ + int getControlSchemeIndex(); + /**jsdoc * @function MyAvatar.getAvatarScale * @returns {number} @@ -1813,6 +1828,7 @@ private: float _driveGear3 { DEFAULT_GEAR_3 }; float _driveGear4 { DEFAULT_GEAR_4 }; float _driveGear5 { DEFAULT_GEAR_5 }; + int _controlSchemeIndex { DEFAULT_CONTROL_SCHEME_INDEX }; glm::vec3 _thrust { 0.0f }; // impulse accumulator for outside sources @@ -2058,6 +2074,7 @@ private: Setting::Handle _driveGear3Setting; Setting::Handle _driveGear4Setting; Setting::Handle _driveGear5Setting; + Setting::Handle _controlSchemeIndexSetting; std::vector> _avatarEntityIDSettings; std::vector> _avatarEntityDataSettings; From 6552d8d9eed25efa6c53dc58add838323a111922 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 28 Jan 2019 10:40:31 -0800 Subject: [PATCH 016/158] Add settings for control scheme. --- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/avatar/MyAvatar.h | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 789e192a69..8d7d0d2972 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1896,7 +1896,7 @@ void MyAvatar::loadData() { setDriveGear3(firstRunVal.get() ? DEFAULT_GEAR_3 : _driveGear3Setting.get()); setDriveGear4(firstRunVal.get() ? DEFAULT_GEAR_4 : _driveGear4Setting.get()); setDriveGear5(firstRunVal.get() ? DEFAULT_GEAR_5 : _driveGear5Setting.get()); - setControlSchemeIndex(firstRunVal.get() ? DEFAULT_CONTROL_SCHEME_INDEX : _controlSchemeIndexSetting.get()); + setControlSchemeIndex(firstRunVal.get() ? CONTROLS_DEFAULT : _controlSchemeIndexSetting.get()); setFlyingEnabled(getFlyingEnabled()); setDisplayName(_displayNameSetting.get()); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index c0264b97dc..98a84b3a0e 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -258,7 +258,9 @@ class MyAvatar : public Avatar { const float DEFAULT_GEAR_3 = 0.8f; const float DEFAULT_GEAR_4 = 0.9f; const float DEFAULT_GEAR_5 = 1.0f; - const int DEFAULT_CONTROL_SCHEME_INDEX = 0; + const int CONTROLS_DEFAULT = 0; + const int CONTROLS_ANALOG = 1; + const int CONTROLS_ANALOG_PLUS = 2; public: enum DriveKeys { @@ -511,7 +513,17 @@ public: */ Q_INVOKABLE void setSnapTurn(bool on) { _useSnapTurn = on; } + /** + * @function MyAvatar.getControlScheme + * @returns {number} + */ + Q_INVOKABLE int getControlScheme() const { return _controlSchemeIndex; } + /** + * @function MyAvatar.setControlScheme + * @param {number} index + */ + Q_INVOKABLE void setControlScheme(int index) { _controlSchemeIndex = index; } /**jsdoc * @function MyAvatar.setDominantHand * @param {string} hand @@ -1828,7 +1840,7 @@ private: float _driveGear3 { DEFAULT_GEAR_3 }; float _driveGear4 { DEFAULT_GEAR_4 }; float _driveGear5 { DEFAULT_GEAR_5 }; - int _controlSchemeIndex { DEFAULT_CONTROL_SCHEME_INDEX }; + int _controlSchemeIndex { CONTROLS_DEFAULT }; glm::vec3 _thrust { 0.0f }; // impulse accumulator for outside sources From f45ff3c6627ca1e537891fa244c542eb8130c41a Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 28 Jan 2019 10:40:43 -0800 Subject: [PATCH 017/158] Add menu item for selecting control scheme. --- interface/src/ui/PreferencesDialog.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index ae5eefbe7a..e08e4bfe8f 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -293,6 +293,16 @@ void setupPreferences() { preference->setItems(items); preferences->addPreference(preference); } + { + auto getter = [myAvatar]()->int { return myAvatar->getControlScheme(); }; + auto setter = [myAvatar](int index) { myAvatar->setControlScheme(index); }; + auto preference = new RadioButtonsPreference(VR_MOVEMENT, "Control Scheme", getter, setter); + QStringList items; + items << "Default" << "Analog" << "Analog++"; + preference->setHeading("Control Scheme Selection"); + preference->setItems(items); + preferences->addPreference(preference); + } { auto getter = [myAvatar]()->bool { return myAvatar->getShowPlayArea(); }; auto setter = [myAvatar](bool value) { myAvatar->setShowPlayArea(value); }; From 0429280148d6643212b30ac943c533289670205b Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 28 Jan 2019 14:06:32 -0800 Subject: [PATCH 018/158] Default vs Analog implemented. --- interface/src/avatar/MyAvatar.cpp | 76 +++++++++++++++++++++++-------- interface/src/avatar/MyAvatar.h | 11 +++-- 2 files changed, 64 insertions(+), 23 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 8d7d0d2972..b7b1c173b6 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3296,6 +3296,44 @@ static float scaleSpeedByDirection(const glm::vec2 velocityDirection, const floa return scaledSpeed; } +glm::vec3 MyAvatar::scaleMotorSpeed(const glm::vec3 forward, const glm::vec3 right) { + float stickFullOn = 0.95f; + auto zSpeed = getDriveKey(TRANSLATE_Z); + auto xSpeed = getDriveKey(TRANSLATE_X); + glm::vec3 direction; + switch(_controlSchemeIndex) { + case CONTROLS_DEFAULT: + // No acceleration curve for this one, constant speed. + if (zSpeed || xSpeed) { + direction = forward + right; + return getSensorToWorldScale() * _walkSpeedScalar * direction; + } else { + return Vectors::ZERO; + } + case CONTROLS_ANALOG: + if (zSpeed || xSpeed) { + glm::vec3 scaledForward = getSensorToWorldScale() * zSpeed * ((zSpeed >= stickFullOn) ? _sprintSpeed.get() : _walkSpeed.get()) * forward; + glm::vec3 scaledRight = getSensorToWorldScale() * xSpeed * ((xSpeed > stickFullOn) ? _sprintSpeed.get() : _walkSpeed.get()) * right; + direction = scaledForward + scaledRight; + return direction; + } else { + return Vectors::ZERO; + } + case CONTROLS_ANALOG_PLUS: + if (zSpeed || xSpeed) { + glm::vec3 scaledForward = getSensorToWorldScale() * zSpeed * ((zSpeed >= stickFullOn) ? _sprintSpeed.get() : _walkSpeed.get()) * forward; + glm::vec3 scaledRight = getSensorToWorldScale() * xSpeed * ((xSpeed > stickFullOn) ? _sprintSpeed.get() : _walkSpeed.get()) * right; + direction = scaledForward + scaledRight; + return direction; + } else { + return Vectors::ZERO; + } + default: + qDebug() << "Invalid control scheme index."; + return Vectors::ZERO; + } +} + glm::vec3 MyAvatar::calculateScaledDirection(){ CharacterController::State state = _characterController.getState(); @@ -3308,15 +3346,15 @@ glm::vec3 MyAvatar::calculateScaledDirection(){ auto handRotation = getDominantHandRotation(); glm::vec3 controllerForward(0.0f, 1.0f, 0.0f); glm::vec3 controllerRight(0.0f, 0.0f, (getDominantHand() == DOMINANT_RIGHT_HAND ? -1.0f : 1.0f)); - forward = (getDriveKey(TRANSLATE_Z)) * (handRotation * controllerForward); - right = (getDriveKey(TRANSLATE_X)) * (handRotation * controllerRight); + forward = (handRotation * controllerForward); + right = (handRotation * controllerRight); } else { - forward = (getDriveKey(TRANSLATE_Z)) * IDENTITY_FORWARD; - right = (getDriveKey(TRANSLATE_X)) * IDENTITY_RIGHT; + forward = IDENTITY_FORWARD; + right = IDENTITY_RIGHT; } - glm::vec3 direction = forward + right; + glm::vec3 direction = scaleMotorSpeed(forward, right); // RKNOTE: This may need to be changed later... if (state == CharacterController::State::Hover || @@ -3326,16 +3364,6 @@ glm::vec3 MyAvatar::calculateScaledDirection(){ direction += up; } - _wasPushing = _isPushing; - float directionLength = glm::length(direction); - _isPushing = directionLength > EPSILON; - - if (_isPushing) { - direction; - } else { - direction = Vectors::ZERO; - } - return direction; } @@ -3358,6 +3386,16 @@ void MyAvatar::updateActionMotor(float deltaTime) { glm::vec3 direction = calculateScaledDirection(); + _wasPushing = _isPushing; + float directionLength = glm::length(direction); + _isPushing = directionLength > EPSILON; + + if (_isPushing) { + direction; + } else { + direction = Vectors::ZERO; + } + if (state == CharacterController::State::Hover) { // we're flying --> complex acceleration curve that builds on top of current motor speed and caps at some max speed @@ -3369,6 +3407,7 @@ void MyAvatar::updateActionMotor(float deltaTime) { const float maxBoostSpeed = getSensorToWorldScale() * MAX_BOOST_SPEED; if (_isPushing) { + direction /= direction; if (motorSpeed < maxBoostSpeed) { // an active action motor should never be slower than this float boostCoefficient = (maxBoostSpeed - motorSpeed) / maxBoostSpeed; @@ -3380,10 +3419,11 @@ void MyAvatar::updateActionMotor(float deltaTime) { _actionMotorVelocity = motorSpeed * direction; } else { // we're interacting with a floor --> simple horizontal speed and exponential decay - const glm::vec2 currentVel = { direction.x, direction.z }; - float scaledSpeed = scaleSpeedByDirection(currentVel, _walkSpeed.get(), _walkBackwardSpeed.get()); + //const glm::vec2 currentVel = { direction.x, direction.z }; + //float scaledSpeed = scaleSpeedByDirection(currentVel, _walkSpeed.get(), _walkBackwardSpeed.get()); // _walkSpeedScalar is a multiplier if we are in sprint mode, otherwise 1.0 - _actionMotorVelocity = getSensorToWorldScale() * (scaledSpeed * _walkSpeedScalar) * direction; + _actionMotorVelocity = direction; + //_actionMotorVelocity = getSensorToWorldScale() * (scaledSpeed * _walkSpeedScalar) * direction; } float previousBoomLength = _boomLength; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 98a84b3a0e..91dc0d47b0 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -38,6 +38,10 @@ class AvatarActionHold; class ModelItemID; class MyHead; +const int CONTROLS_DEFAULT = 0; +const int CONTROLS_ANALOG = 1; +const int CONTROLS_ANALOG_PLUS = 2; + enum eyeContactTarget { LEFT_EYE, RIGHT_EYE, @@ -258,10 +262,6 @@ class MyAvatar : public Avatar { const float DEFAULT_GEAR_3 = 0.8f; const float DEFAULT_GEAR_4 = 0.9f; const float DEFAULT_GEAR_5 = 1.0f; - const int CONTROLS_DEFAULT = 0; - const int CONTROLS_ANALOG = 1; - const int CONTROLS_ANALOG_PLUS = 2; - public: enum DriveKeys { TRANSLATE_X = 0, @@ -523,7 +523,7 @@ public: * @function MyAvatar.setControlScheme * @param {number} index */ - Q_INVOKABLE void setControlScheme(int index) { _controlSchemeIndex = index; } + Q_INVOKABLE void setControlScheme(int index) { _controlSchemeIndex = (index >= 0 && index <= 2) ? index : 0; } /**jsdoc * @function MyAvatar.setDominantHand * @param {string} hand @@ -1882,6 +1882,7 @@ private: // private methods void updateOrientation(float deltaTime); glm::vec3 calculateScaledDirection(); + glm::vec3 scaleMotorSpeed(const glm::vec3 forward, const glm::vec3 right); void updateActionMotor(float deltaTime); void updatePosition(float deltaTime); void updateCollisionSound(const glm::vec3& penetration, float deltaTime, float frequency); From b6036e492127810709d11b4540d905d3ca7a2e2b Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 28 Jan 2019 15:04:51 -0800 Subject: [PATCH 019/158] Remove needless qualification breaking Mac builds. --- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/avatar/MyAvatar.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index b7b1c173b6..121d7bd5a5 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2543,7 +2543,7 @@ controller::Pose MyAvatar::getControllerPoseInAvatarFrame(controller::Action act } } -quat MyAvatar::getDominantHandRotation() const { +quat MyAvatar::getDominantHandRotation() { auto hand = (getDominantHand() == DOMINANT_RIGHT_HAND) ? controller::Action::RIGHT_HAND : controller::Action::LEFT_HAND; auto pose = getControllerPoseInAvatarFrame(hand); return pose.rotation; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 91dc0d47b0..cb751aac2c 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -980,7 +980,7 @@ public: controller::Pose getControllerPoseInSensorFrame(controller::Action action) const; controller::Pose getControllerPoseInWorldFrame(controller::Action action) const; controller::Pose getControllerPoseInAvatarFrame(controller::Action action) const; - quat MyAvatar::getDominantHandRotation() const; + quat MyAvatar::getDominantHandRotation(); bool hasDriveInput() const; From 0f45781779e47553a67572f0d13cf4ffd00e44f3 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 28 Jan 2019 15:52:18 -0800 Subject: [PATCH 020/158] Remove extra qualifier from function signature in MyAvatar.h --- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/avatar/MyAvatar.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index b7b1c173b6..c9c2105aba 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2543,7 +2543,7 @@ controller::Pose MyAvatar::getControllerPoseInAvatarFrame(controller::Action act } } -quat MyAvatar::getDominantHandRotation() const { +glm::quat MyAvatar::getDominantHandRotation() const { auto hand = (getDominantHand() == DOMINANT_RIGHT_HAND) ? controller::Action::RIGHT_HAND : controller::Action::LEFT_HAND; auto pose = getControllerPoseInAvatarFrame(hand); return pose.rotation; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 91dc0d47b0..e6f967e563 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -980,7 +980,7 @@ public: controller::Pose getControllerPoseInSensorFrame(controller::Action action) const; controller::Pose getControllerPoseInWorldFrame(controller::Action action) const; controller::Pose getControllerPoseInAvatarFrame(controller::Action action) const; - quat MyAvatar::getDominantHandRotation() const; + glm::quat getDominantHandRotation() const; bool hasDriveInput() const; From d4cf1de4ddf0e756a7175fd5686eb269da608649 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 29 Jan 2019 12:02:02 -0800 Subject: [PATCH 021/158] Fix default locomotion scaling. --- interface/src/avatar/MyAvatar.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c9c2105aba..23fad72181 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3305,8 +3305,11 @@ glm::vec3 MyAvatar::scaleMotorSpeed(const glm::vec3 forward, const glm::vec3 rig case CONTROLS_DEFAULT: // No acceleration curve for this one, constant speed. if (zSpeed || xSpeed) { - direction = forward + right; - return getSensorToWorldScale() * _walkSpeedScalar * direction; + direction = (zSpeed * forward) + (xSpeed * right); + // Normalize direction. + direction /= glm::length(direction); + float scale = scaleSpeedByDirection(direction, _walkSpeed.get(), _walkBackwardSpeed.get()); + return getSensorToWorldScale() * scale * direction; } else { return Vectors::ZERO; } From 4d2ee07512845378d6e5c4129899681f0f7f62a0 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 29 Jan 2019 12:02:23 -0800 Subject: [PATCH 022/158] Change deactivation criteria as per conversation between Joshua and Mukul. --- scripts/system/controllers/controllerModules/teleport.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/teleport.js b/scripts/system/controllers/controllerModules/teleport.js index bbc690d663..124fe3d3ea 100644 --- a/scripts/system/controllers/controllerModules/teleport.js +++ b/scripts/system/controllers/controllerModules/teleport.js @@ -726,7 +726,8 @@ Script.include("/~/system/libraries/controllers.js"); }; this.shouldCancel = function () { - return (_this.getDominantY() < -TELEPORT_DEADZONE || _this.getOffhandY() < -TELEPORT_DEADZONE) ? true : false; + //return (_this.getDominantY() < -TELEPORT_DEADZONE || _this.getOffhandY() < -TELEPORT_DEADZONE) ? true : false; + return (_this.getOffhandY() <= TELEPORT_DEADZONE) ? true : false; }; this.parameters = makeDispatcherModuleParameters( From e1cbb187cd33981a25cdc0ae701485faaa1660a2 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 29 Jan 2019 16:12:49 -0800 Subject: [PATCH 023/158] Clean up comments in MyAvatar.cpp --- interface/src/avatar/MyAvatar.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 23fad72181..c1ebd10f81 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3308,8 +3308,7 @@ glm::vec3 MyAvatar::scaleMotorSpeed(const glm::vec3 forward, const glm::vec3 rig direction = (zSpeed * forward) + (xSpeed * right); // Normalize direction. direction /= glm::length(direction); - float scale = scaleSpeedByDirection(direction, _walkSpeed.get(), _walkBackwardSpeed.get()); - return getSensorToWorldScale() * scale * direction; + return getSensorToWorldScale() * direction * _sprintSpeed.get(); } else { return Vectors::ZERO; } From 17518640425b0b23f84e1e90ed81029f8463762a Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 29 Jan 2019 16:13:11 -0800 Subject: [PATCH 024/158] Fix this references in module run function. --- scripts/system/controllers/controllerModules/teleport.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/controllerModules/teleport.js b/scripts/system/controllers/controllerModules/teleport.js index 124fe3d3ea..386e03d616 100644 --- a/scripts/system/controllers/controllerModules/teleport.js +++ b/scripts/system/controllers/controllerModules/teleport.js @@ -756,8 +756,8 @@ Script.include("/~/system/libraries/controllers.js"); this.run = function(controllerData, deltaTime) { // Kill condition: - if (this.shouldCancel()) { - this.disableLasers(); + if (_this.shouldCancel()) { + _this.disableLasers(); this.active = false; return makeRunningValues(false, [], []); } From 7e9d35a0fb3e06fbf89622e79b4e434df1fb9508 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Wed, 30 Jan 2019 15:06:35 -0800 Subject: [PATCH 025/158] Add individual speed settings per control mode. --- interface/src/avatar/MyAvatar.cpp | 96 ++++++++++++++++++++++---- interface/src/avatar/MyAvatar.h | 13 +++- libraries/shared/src/AvatarConstants.h | 13 +++- 3 files changed, 106 insertions(+), 16 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c1ebd10f81..dfc95a1d8a 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3308,14 +3308,14 @@ glm::vec3 MyAvatar::scaleMotorSpeed(const glm::vec3 forward, const glm::vec3 rig direction = (zSpeed * forward) + (xSpeed * right); // Normalize direction. direction /= glm::length(direction); - return getSensorToWorldScale() * direction * _sprintSpeed.get(); + return getSensorToWorldScale() * direction * getSprintSpeed(); } else { return Vectors::ZERO; } case CONTROLS_ANALOG: if (zSpeed || xSpeed) { - glm::vec3 scaledForward = getSensorToWorldScale() * zSpeed * ((zSpeed >= stickFullOn) ? _sprintSpeed.get() : _walkSpeed.get()) * forward; - glm::vec3 scaledRight = getSensorToWorldScale() * xSpeed * ((xSpeed > stickFullOn) ? _sprintSpeed.get() : _walkSpeed.get()) * right; + glm::vec3 scaledForward = getSensorToWorldScale() * zSpeed * ((zSpeed >= stickFullOn) ? getSprintSpeed() : getWalkSpeed()) * forward; + glm::vec3 scaledRight = getSensorToWorldScale() * xSpeed * ((xSpeed > stickFullOn) ? getSprintSpeed() : getWalkSpeed()) * right; direction = scaledForward + scaledRight; return direction; } else { @@ -3323,8 +3323,8 @@ glm::vec3 MyAvatar::scaleMotorSpeed(const glm::vec3 forward, const glm::vec3 rig } case CONTROLS_ANALOG_PLUS: if (zSpeed || xSpeed) { - glm::vec3 scaledForward = getSensorToWorldScale() * zSpeed * ((zSpeed >= stickFullOn) ? _sprintSpeed.get() : _walkSpeed.get()) * forward; - glm::vec3 scaledRight = getSensorToWorldScale() * xSpeed * ((xSpeed > stickFullOn) ? _sprintSpeed.get() : _walkSpeed.get()) * right; + glm::vec3 scaledForward = getSensorToWorldScale() * zSpeed * ((zSpeed >= stickFullOn) ? getSprintSpeed() : getWalkSpeed()) * forward; + glm::vec3 scaledRight = getSensorToWorldScale() * xSpeed * ((xSpeed > stickFullOn) ? getSprintSpeed() : getWalkSpeed()) * right; direction = scaledForward + scaledRight; return direction; } else { @@ -4590,11 +4590,27 @@ bool MyAvatar::getIsSitStandStateLocked() const { } float MyAvatar::getWalkSpeed() const { - return _walkSpeed.get() * _walkSpeedScalar; + switch(_controlSchemeIndex) { + case CONTROLS_ANALOG: + return _analogWalkSpeed.get() * _walkSpeedScalar; + case CONTROLS_ANALOG_PLUS: + return _analogPlusWalkSpeed.get() * _walkSpeedScalar; + case CONTROLS_DEFAULT: + default: + return _defaultWalkSpeed.get() * _walkSpeedScalar; + } } float MyAvatar::getWalkBackwardSpeed() const { - return _walkSpeed.get() * _walkSpeedScalar; + switch(_controlSchemeIndex) { + case CONTROLS_ANALOG: + return _analogWalkBackwardSpeed.get() * _walkSpeedScalar; + case CONTROLS_ANALOG_PLUS: + return _analogPlusWalkBackwardSpeed.get() * _walkSpeedScalar; + case CONTROLS_DEFAULT: + default: + return _defaultWalkBackwardSpeed.get() * _walkSpeedScalar; + } } bool MyAvatar::isReadyForPhysics() const { @@ -4602,7 +4618,19 @@ bool MyAvatar::isReadyForPhysics() const { } void MyAvatar::setSprintMode(bool sprint) { - _walkSpeedScalar = sprint ? _sprintSpeed.get() : AVATAR_WALK_SPEED_SCALAR; + float value = AVATAR_WALK_SPEED_SCALAR; + if (sprint) { + switch(_controlSchemeIndex) { + case CONTROLS_ANALOG: + value = _analogSprintSpeed.get() * _walkSpeedScalar; + case CONTROLS_ANALOG_PLUS: + value = _analogPlusSprintSpeed.get() * _walkSpeedScalar; + case CONTROLS_DEFAULT: + default: + value = _defaultSprintSpeed.get() * _walkSpeedScalar; + } + } + _walkSpeedScalar = value; } void MyAvatar::setIsInWalkingState(bool isWalking) { @@ -4665,19 +4693,63 @@ void MyAvatar::setIsSitStandStateLocked(bool isLocked) { } void MyAvatar::setWalkSpeed(float value) { - _walkSpeed.set(value); + switch(_controlSchemeIndex) { + case CONTROLS_DEFAULT: + _defaultWalkSpeed.set(value); + break; + case CONTROLS_ANALOG: + _analogWalkSpeed.set(value); + break; + case CONTROLS_ANALOG_PLUS: + _analogPlusWalkSpeed.set(value); + break; + default: + break; + } } void MyAvatar::setWalkBackwardSpeed(float value) { - _walkBackwardSpeed.set(value); + switch(_controlSchemeIndex) { + case CONTROLS_DEFAULT: + _defaultWalkBackwardSpeed.set(value); + break; + case CONTROLS_ANALOG: + _analogWalkBackwardSpeed.set(value); + break; + case CONTROLS_ANALOG_PLUS: + _analogPlusWalkBackwardSpeed.set(value); + break; + default: + break; + } } void MyAvatar::setSprintSpeed(float value) { - _sprintSpeed.set(value); + switch(_controlSchemeIndex) { + case CONTROLS_DEFAULT: + _defaultSprintSpeed.set(value); + break; + case CONTROLS_ANALOG: + _analogSprintSpeed.set(value); + break; + case CONTROLS_ANALOG_PLUS: + _analogPlusSprintSpeed.set(value); + break; + default: + break; + } } float MyAvatar::getSprintSpeed() const { - return _sprintSpeed.get(); + switch(_controlSchemeIndex) { + case CONTROLS_ANALOG: + return _analogSprintSpeed.get(); + case CONTROLS_ANALOG_PLUS: + return _analogPlusSprintSpeed.get(); + case CONTROLS_DEFAULT: + default: + return _defaultSprintSpeed.get(); + } } void MyAvatar::setSitStandStateChange(bool stateChanged) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index e6f967e563..eee8036235 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -2047,9 +2047,16 @@ private: ThreadSafeValueCache _lockSitStandState { false }; // max unscaled forward movement speed - ThreadSafeValueCache _walkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED }; - ThreadSafeValueCache _walkBackwardSpeed { DEFAULT_AVATAR_MAX_WALKING_BACKWARD_SPEED }; - ThreadSafeValueCache _sprintSpeed { AVATAR_SPRINT_SPEED_SCALAR }; + ThreadSafeValueCache _defaultWalkSpeed { DEFAULT_AVATAR_MAX_WALKING_SPEED }; + ThreadSafeValueCache _defaultWalkBackwardSpeed { DEFAULT_AVATAR_MAX_WALKING_BACKWARD_SPEED }; + ThreadSafeValueCache _defaultSprintSpeed { DEFAULT_AVATAR_MAX_SPRINT_SPEED }; + ThreadSafeValueCache _analogWalkSpeed { ANALOG_AVATAR_MAX_WALKING_SPEED }; + ThreadSafeValueCache _analogWalkBackwardSpeed { ANALOG_AVATAR_MAX_WALKING_BACKWARD_SPEED }; + ThreadSafeValueCache _analogSprintSpeed { ANALOG_AVATAR_MAX_SPRINT_SPEED }; + ThreadSafeValueCache _analogPlusWalkSpeed { ANALOG_PLUS_AVATAR_MAX_WALKING_SPEED }; + ThreadSafeValueCache _analogPlusWalkBackwardSpeed { ANALOG_PLUS_AVATAR_MAX_WALKING_BACKWARD_SPEED }; + ThreadSafeValueCache _analogPlusSprintSpeed { ANALOG_PLUS_AVATAR_MAX_SPRINT_SPEED }; + float _walkSpeedScalar { AVATAR_WALK_SPEED_SCALAR }; bool _isInWalkingState { false }; ThreadSafeValueCache _isInSittingState { false }; diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index 87da47a27a..d4af94e68c 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -68,7 +68,18 @@ const glm::quat DEFAULT_AVATAR_RIGHTFOOT_ROT { -0.4016716778278351f, 0.915461599 const float DEFAULT_AVATAR_MAX_WALKING_SPEED = 2.6f; // meters / second const float DEFAULT_AVATAR_MAX_WALKING_BACKWARD_SPEED = 2.2f; // meters / second const float DEFAULT_AVATAR_MAX_FLYING_SPEED = 30.0f; // meters / second -const float DEFAULT_AVATAR_WALK_SPEED_THRESHOLD = 0.15f; +const float DEFAULT_AVATAR_MAX_SPRINT_SPEED = 3.0f; // meters / second +const float DEFAULT_AVATAR_WALK_SPEED_THRESHOLD = 0.15f; // meters / second + +const float ANALOG_AVATAR_MAX_WALKING_SPEED = 2.6f; // meters / second +const float ANALOG_AVATAR_MAX_WALKING_BACKWARD_SPEED = 2.2f; // meters / second +const float ANALOG_AVATAR_MAX_FLYING_SPEED = 30.0f; // meters / second +const float ANALOG_AVATAR_MAX_SPRINT_SPEED = 3.0f; // meters / second + +const float ANALOG_PLUS_AVATAR_MAX_WALKING_SPEED = 3.3f; // meters / second +const float ANALOG_PLUS_AVATAR_MAX_WALKING_BACKWARD_SPEED = 2.42f; // meters / second +const float ANALOG_PLUS_AVATAR_MAX_FLYING_SPEED = 30.0f; // meters / second +const float ANALOG_PLUS_AVATAR_MAX_SPRINT_SPEED = 4.0f; // meters / second const float DEFAULT_AVATAR_GRAVITY = -5.0f; // meters / second^2 (world) const float DEFAULT_AVATAR_JUMP_SPEED = 3.5f; // meters / second (sensor) From bdafb99402cc3d7a680ad40d060e67719bdd1723 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 11 Feb 2019 14:19:15 -0800 Subject: [PATCH 026/158] Remove unused variable and function to address warnings in Mac and Linux builds. --- interface/src/avatar/MyAvatar.cpp | 42 +++++++++++++++++-------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index dfc95a1d8a..e0dff940d5 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3279,22 +3279,22 @@ void MyAvatar::updateOrientation(float deltaTime) { } } -static float scaleSpeedByDirection(const glm::vec2 velocityDirection, const float forwardSpeed, const float backwardSpeed) { - // for the elipse function --> (x^2)/(backwardSpeed*backwardSpeed) + y^2/(forwardSpeed*forwardSpeed) = 1, scale == y^2 when x is 0 - float fwdScale = forwardSpeed * forwardSpeed; - float backScale = backwardSpeed * backwardSpeed; - float scaledX = velocityDirection.x * backwardSpeed; - float scaledSpeed = forwardSpeed; - if (velocityDirection.y < 0.0f) { - if (backScale > 0.0f) { - float yValue = sqrtf(fwdScale * (1.0f - ((scaledX * scaledX) / backScale))); - scaledSpeed = sqrtf((scaledX * scaledX) + (yValue * yValue)); - } - } else { - scaledSpeed = backwardSpeed; - } - return scaledSpeed; -} +//static float scaleSpeedByDirection(const glm::vec2 velocityDirection, const float forwardSpeed, const float backwardSpeed) { +// // for the elipse function --> (x^2)/(backwardSpeed*backwardSpeed) + y^2/(forwardSpeed*forwardSpeed) = 1, scale == y^2 when x is 0 +// float fwdScale = forwardSpeed * forwardSpeed; +// float backScale = backwardSpeed * backwardSpeed; +// float scaledX = velocityDirection.x * backwardSpeed; +// float scaledSpeed = forwardSpeed; +// if (velocityDirection.y < 0.0f) { +// if (backScale > 0.0f) { +// float yValue = sqrtf(fwdScale * (1.0f - ((scaledX * scaledX) / backScale))); +// scaledSpeed = sqrtf((scaledX * scaledX) + (yValue * yValue)); +// } +// } else { +// scaledSpeed = backwardSpeed; +// } +// return scaledSpeed; +//} glm::vec3 MyAvatar::scaleMotorSpeed(const glm::vec3 forward, const glm::vec3 right) { float stickFullOn = 0.95f; @@ -3392,9 +3392,13 @@ void MyAvatar::updateActionMotor(float deltaTime) { float directionLength = glm::length(direction); _isPushing = directionLength > EPSILON; - if (_isPushing) { - direction; - } else { + //if (_isPushing) { + // direction; + //} else { + // direction = Vectors::ZERO; + //} + + if (!_isPushing) { direction = Vectors::ZERO; } From f52b096bb92b1c792a52338976b28623d7d43f41 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 19 Feb 2019 11:26:42 -0800 Subject: [PATCH 027/158] Change far grab to chorded input 'superpower' --- .../controllerModules/farGrabEntity.js | 115 ++++++++++++++---- 1 file changed, 90 insertions(+), 25 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index dab1aa97af..40f7fc57d7 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -18,7 +18,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); -(function() { +(function () { var MARGIN = 25; function TargetObject(entityID, entityProps) { @@ -27,12 +27,13 @@ Script.include("/~/system/libraries/controllers.js"); this.targetEntityID = null; this.targetEntityProps = null; - this.getTargetEntity = function() { + this.getTargetEntity = function () { var parentPropsLength = this.parentProps.length; if (parentPropsLength !== 0) { var targetEntity = { id: this.parentProps[parentPropsLength - 1].id, - props: this.parentProps[parentPropsLength - 1]}; + props: this.parentProps[parentPropsLength - 1] + }; this.targetEntityID = targetEntity.id; this.targetEntityProps = targetEntity.props; return targetEntity; @@ -41,11 +42,13 @@ Script.include("/~/system/libraries/controllers.js"); this.targetEntityProps = this.entityProps; return { id: this.entityID, - props: this.entityProps}; + props: this.entityProps + }; }; } function FarGrabEntity(hand) { + var _this = this; this.hand = hand; this.grabbing = false; this.targetEntityID = null; @@ -76,11 +79,11 @@ Script.include("/~/system/libraries/controllers.js"); makeLaserParams(this.hand, false)); - this.handToController = function() { + this.handToController = function () { return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; }; - this.distanceGrabTimescale = function(mass, distance) { + this.distanceGrabTimescale = function (mass, distance) { var timeScale = DISTANCE_HOLDING_ACTION_TIMEFRAME * mass / DISTANCE_HOLDING_UNITY_MASS * distance / DISTANCE_HOLDING_UNITY_DISTANCE; @@ -90,7 +93,7 @@ Script.include("/~/system/libraries/controllers.js"); return timeScale; }; - this.getMass = function(dimensions, density) { + this.getMass = function (dimensions, density) { return (dimensions.x * dimensions.y * dimensions.z) * density; }; @@ -156,8 +159,8 @@ Script.include("/~/system/libraries/controllers.js"); } var farJointIndex = FAR_GRAB_JOINTS[this.hand]; this.grabID = MyAvatar.grab(targetProps.id, farJointIndex, - Entities.worldToLocalPosition(targetProps.position, MyAvatar.SELF_ID, farJointIndex), - Entities.worldToLocalRotation(targetProps.rotation, MyAvatar.SELF_ID, farJointIndex)); + Entities.worldToLocalPosition(targetProps.position, MyAvatar.SELF_ID, farJointIndex), + Entities.worldToLocalRotation(targetProps.rotation, MyAvatar.SELF_ID, farJointIndex)); Messages.sendMessage('Hifi-Object-Manipulation', JSON.stringify({ action: 'grab', @@ -169,7 +172,7 @@ Script.include("/~/system/libraries/controllers.js"); this.previousRoomControllerPosition = roomControllerPosition; }; - this.continueDistanceHolding = function(controllerData) { + this.continueDistanceHolding = function (controllerData) { var controllerLocation = controllerData.controllerLocations[this.hand]; var worldControllerPosition = controllerLocation.position; var worldControllerRotation = controllerLocation.orientation; @@ -215,7 +218,7 @@ Script.include("/~/system/libraries/controllers.js"); var RADIAL_GRAB_AMPLIFIER = 10.0; if (Math.abs(this.grabRadialVelocity) > 0.0) { this.grabRadius = this.grabRadius + (this.grabRadialVelocity * deltaObjectTime * - this.grabRadius * RADIAL_GRAB_AMPLIFIER); + this.grabRadius * RADIAL_GRAB_AMPLIFIER); } // don't let grabRadius go all the way to zero, because it can't come back from that @@ -259,13 +262,13 @@ Script.include("/~/system/libraries/controllers.js"); MyAvatar.clearJointData(FAR_GRAB_JOINTS[this.hand]); }; - this.updateRecommendedArea = function() { + this.updateRecommendedArea = function () { var dims = Controller.getViewportDimensions(); this.reticleMaxX = dims.x - MARGIN; this.reticleMaxY = dims.y - MARGIN; }; - this.calculateNewReticlePosition = function(intersection) { + this.calculateNewReticlePosition = function (intersection) { this.updateRecommendedArea(); var point2d = HMD.overlayFromWorldPoint(intersection); point2d.x = Math.max(this.reticleMinX, Math.min(point2d.x, this.reticleMaxX)); @@ -273,7 +276,7 @@ Script.include("/~/system/libraries/controllers.js"); return point2d; }; - this.notPointingAtEntity = function(controllerData) { + this.notPointingAtEntity = function (controllerData) { var intersection = controllerData.rayPicks[this.hand]; var entityProperty = Entities.getEntityProperties(intersection.objectID, DISPATCHER_PROPERTIES); var entityType = entityProperty.type; @@ -286,7 +289,7 @@ Script.include("/~/system/libraries/controllers.js"); return false; }; - this.destroyContextOverlay = function(controllerData) { + this.destroyContextOverlay = function (controllerData) { if (this.entityWithContextOverlay) { ContextOverlay.destroyContextOverlay(this.entityWithContextOverlay); this.entityWithContextOverlay = false; @@ -294,7 +297,7 @@ Script.include("/~/system/libraries/controllers.js"); } }; - this.targetIsNull = function() { + this.targetIsNull = function () { var properties = Entities.getEntityProperties(this.targetEntityID, DISPATCHER_PROPERTIES); if (Object.keys(properties).length === 0 && this.distanceHolding) { return true; @@ -318,15 +321,70 @@ Script.include("/~/system/libraries/controllers.js"); return null; }; + var mappingName = "FarGrab-Mapping-" + Math.random(); + var grabMapping; + + this.setup = function () { + grabMapping = Controller.newMapping(mappingName); + grabMapping.from(Controller.Standard.LT).peek().to(_this.getLeftTrigger); + grabMapping.from(Controller.Standard.RT).peek().to(_this.getRightTrigger); + Controller.enableMapping(mappingName); + }; + + this.cleanup = function () { + grabMapping.disable(); + }; + + this.leftTrigger = 0.0; + this.rightTrigger = 0.0; + + this.getDominantHand = function () { + return (MyAvatar.getDominantHand() === "left") ? LEFT_HAND : RIGHT_HAND; + }; + + this.getOffHand = function () { + return (MyAvatar.getDominantHand() === "left") ? RIGHT_HAND : LEFT_HAND; + }; + + this.getLeftTrigger = function (value) { + _this.leftTrigger = value; + }; + + this.getRightTrigger = function (value) { + _this.rightTrigger = value; + }; + + this.getDominantTrigger = function () { + return (MyAvatar.getDominantHand() === "left") ? (_this.leftTrigger) : (_this.rightTrigger); + }; + + this.getOffHandTrigger = function () { + return (MyAvatar.getDominantHand() === "left") ? (_this.rightTrigger) : (_this.leftTrigger); + }; + + this.shouldShowLaser = function () { + return (_this.getOffHandTrigger() > TRIGGER_ON_VALUE) ? true : false; + }; + + this.shouldGrab = function () { + return (_this.getDominantTrigger() > TRIGGER_ON_VALUE && _this.getOffHandTrigger() > TRIGGER_ON_VALUE) ? true : false; + }; + + this.shouldCancel = function () { + // Kill condition : Off hand is <= 15% trigger pull. + return (_this.getOffHandTrigger() <= TRIGGER_OFF_VALUE) ? true : false; + }; + this.isReady = function (controllerData) { - if (HMD.active) { + if (HMD.active && this.hand === this.getOffHand()) { if (this.notPointingAtEntity(controllerData)) { return makeRunningValues(false, [], []); } this.distanceHolding = false; - if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) { + //if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) { + if (this.shouldShowLaser()) { return makeRunningValues(true, [], []); } else { this.destroyContextOverlay(); @@ -336,7 +394,9 @@ Script.include("/~/system/libraries/controllers.js"); }; this.run = function (controllerData) { - if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || this.targetIsNull()) { + //if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || this.targetIsNull()) { + if (this.shouldCancel() || this.targetIsNull()) { + print("Canceling..."); this.endFarGrabEntity(controllerData); return makeRunningValues(false, [], []); } @@ -383,7 +443,8 @@ Script.include("/~/system/libraries/controllers.js"); var rayPickInfo = controllerData.rayPicks[this.hand]; if (rayPickInfo.type === Picks.INTERSECTED_ENTITY) { - if (controllerData.triggerClicks[this.hand]) { + if (this.shouldGrab()) { + print("Grabbing..."); var entityID = rayPickInfo.objectID; var targetProps = Entities.getEntityProperties(entityID, DISPATCHER_PROPERTIES); if (targetProps.href !== "") { @@ -432,12 +493,12 @@ Script.include("/~/system/libraries/controllers.js"); _this.contextOverlayTimer && _this.potentialEntityWithContextOverlay === rayPickInfo.objectID) { var cotProps = Entities.getEntityProperties(rayPickInfo.objectID, - DISPATCHER_PROPERTIES); + DISPATCHER_PROPERTIES); var pointerEvent = { type: "Move", id: _this.hand + 1, // 0 is reserved for hardware mouse pos2D: projectOntoEntityXYPlane(rayPickInfo.objectID, - rayPickInfo.intersection, cotProps), + rayPickInfo.intersection, cotProps), pos3D: rayPickInfo.intersection, normal: rayPickInfo.surfaceNormal, direction: Vec3.subtract(ZERO_VEC, rayPickInfo.surfaceNormal), @@ -456,7 +517,7 @@ Script.include("/~/system/libraries/controllers.js"); return this.exitIfDisabled(controllerData); }; - this.exitIfDisabled = function(controllerData) { + this.exitIfDisabled = function (controllerData) { var moduleName = this.hand === RIGHT_HAND ? "RightDisableModules" : "LeftDisableModules"; var disableModule = getEnabledModuleByName(moduleName); if (disableModule) { @@ -473,10 +534,10 @@ Script.include("/~/system/libraries/controllers.js"); return makeRunningValues(true, [], [], laserLockInfo); }; - this.calculateOffset = function(controllerData) { + this.calculateOffset = function (controllerData) { if (this.distanceHolding) { var targetProps = Entities.getEntityProperties(this.targetObject.entityID, - [ "position", "rotation", "registrationPoint", "dimensions" ]); + ["position", "rotation", "registrationPoint", "dimensions"]); return worldPositionToRegistrationFrameMatrix(targetProps, controllerData.rayPicks[this.hand].intersection); } return undefined; @@ -485,11 +546,15 @@ Script.include("/~/system/libraries/controllers.js"); var leftFarGrabEntity = new FarGrabEntity(LEFT_HAND); var rightFarGrabEntity = new FarGrabEntity(RIGHT_HAND); + leftFarGrabEntity.setup(); + rightFarGrabEntity.setup(); enableDispatcherModule("LeftFarGrabEntity", leftFarGrabEntity); enableDispatcherModule("RightFarGrabEntity", rightFarGrabEntity); function cleanup() { + leftFarGrabEntity.cleanup(); + rightFarGrabEntity.cleanup(); disableDispatcherModule("LeftFarGrabEntity"); disableDispatcherModule("RightFarGrabEntity"); } From 03058775f63bc9acb513d7681c5d10c3e2c6fd12 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 19 Feb 2019 11:27:13 -0800 Subject: [PATCH 028/158] Remove debug prints. --- scripts/system/controllers/controllerModules/farGrabEntity.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index 40f7fc57d7..69c17229e3 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -396,7 +396,6 @@ Script.include("/~/system/libraries/controllers.js"); this.run = function (controllerData) { //if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || this.targetIsNull()) { if (this.shouldCancel() || this.targetIsNull()) { - print("Canceling..."); this.endFarGrabEntity(controllerData); return makeRunningValues(false, [], []); } @@ -444,7 +443,6 @@ Script.include("/~/system/libraries/controllers.js"); var rayPickInfo = controllerData.rayPicks[this.hand]; if (rayPickInfo.type === Picks.INTERSECTED_ENTITY) { if (this.shouldGrab()) { - print("Grabbing..."); var entityID = rayPickInfo.objectID; var targetProps = Entities.getEntityProperties(entityID, DISPATCHER_PROPERTIES); if (targetProps.href !== "") { From d8b1a479742d8efce3f7351383cf6453e967ee7b Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 19 Feb 2019 15:05:39 -0800 Subject: [PATCH 029/158] Fix oversized Vive deadzone. --- interface/resources/controllers/vive.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/resources/controllers/vive.json b/interface/resources/controllers/vive.json index 24b1587691..b937cee511 100644 --- a/interface/resources/controllers/vive.json +++ b/interface/resources/controllers/vive.json @@ -10,8 +10,8 @@ "filters": [ { "type": "hysteresis", "min": 0.7, "max": 0.75 } ] }, - { "from": "Vive.LY", "when": "Vive.LSY", "filters": ["invert"], "to": "Standard.LY" }, - { "from": "Vive.LX", "when": "Vive.LSX", "to": "Standard.LX" }, + { "from": "Vive.LY", "when": "Vive.LS", "filters": ["invert"], "to": "Standard.LY" }, + { "from": "Vive.LX", "when": "Vive.LS", "to": "Standard.LX" }, { "from": "Vive.LT", "to": "Standard.LT", "filters": [ @@ -28,8 +28,8 @@ }, { "from": "Vive.LSTouch", "to": "Standard.LSTouch" }, - { "from": "Vive.RY", "when": "Vive.RSY", "filters": ["invert"], "to": "Standard.RY" }, - { "from": "Vive.RX", "when": "Vive.RSX", "to": "Standard.RX" }, + { "from": "Vive.RY", "when": "Vive.RS", "filters": ["invert"], "to": "Standard.RY" }, + { "from": "Vive.RX", "when": "Vive.RS", "to": "Standard.RX" }, { "from": "Vive.RT", "to": "Standard.RT", "filters": [ From 0255036e6da8fbe2aacac6ed3e4b1a03b16825a7 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 19 Feb 2019 15:23:05 -0800 Subject: [PATCH 030/158] Fix default mappings' deadzones. --- .../resources/controllers/oculus_touch.json | 8 ++++---- interface/resources/controllers/vive.json | 18 ++++++++++++++---- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/interface/resources/controllers/oculus_touch.json b/interface/resources/controllers/oculus_touch.json index b818d371e3..86f559d964 100644 --- a/interface/resources/controllers/oculus_touch.json +++ b/interface/resources/controllers/oculus_touch.json @@ -13,11 +13,11 @@ { "from": "OculusTouch.LY", "to": "Standard.LY", "filters": [ - { "type": "deadZone", "min": 0.7 }, + { "type": "deadZone", "min": 0.15 }, "invert" ] }, - { "from": "OculusTouch.LX", "filters": { "type": "deadZone", "min": 0.7 }, "to": "Standard.LX" }, + { "from": "OculusTouch.LX", "filters": { "type": "deadZone", "min": 0.15 }, "to": "Standard.LX" }, { "from": "OculusTouch.LT", "to": "Standard.LTClick", "peek": true, "filters": [ { "type": "hysteresis", "min": 0.85, "max": 0.9 } ] @@ -29,11 +29,11 @@ { "from": "OculusTouch.RY", "to": "Standard.RY", "filters": [ - { "type": "deadZone", "min": 0.7 }, + { "type": "deadZone", "min": 0.15 }, "invert" ] }, - { "from": "OculusTouch.RX", "filters": { "type": "deadZone", "min": 0.7 }, "to": "Standard.RX" }, + { "from": "OculusTouch.RX", "filters": { "type": "deadZone", "min": 0.15 }, "to": "Standard.RX" }, { "from": "OculusTouch.RT", "to": "Standard.RTClick", "peek": true, "filters": [ { "type": "hysteresis", "min": 0.85, "max": 0.9 } ] diff --git a/interface/resources/controllers/vive.json b/interface/resources/controllers/vive.json index b937cee511..d6d8f9f929 100644 --- a/interface/resources/controllers/vive.json +++ b/interface/resources/controllers/vive.json @@ -10,8 +10,13 @@ "filters": [ { "type": "hysteresis", "min": 0.7, "max": 0.75 } ] }, - { "from": "Vive.LY", "when": "Vive.LS", "filters": ["invert"], "to": "Standard.LY" }, - { "from": "Vive.LX", "when": "Vive.LS", "to": "Standard.LX" }, + { "from": "Vive.LY", "when": "Vive.LS", + "filters": [ + { "type": "deadZone", "min": 0.15 }, + "invert" + ] + , "to": "Standard.LY" }, + { "from": "Vive.LX", "when": "Vive.LS", "filters": { "type": "deadZone", "min": 0.15 }, "to": "Standard.LX" }, { "from": "Vive.LT", "to": "Standard.LT", "filters": [ @@ -28,8 +33,13 @@ }, { "from": "Vive.LSTouch", "to": "Standard.LSTouch" }, - { "from": "Vive.RY", "when": "Vive.RS", "filters": ["invert"], "to": "Standard.RY" }, - { "from": "Vive.RX", "when": "Vive.RS", "to": "Standard.RX" }, + { "from": "Vive.RY", "when": "Vive.RS", + "filters": [ + { "type": "deadZone", "min": 0.15 }, + "invert" + ] + , "to": "Standard.RY" }, + { "from": "Vive.RX", "when": "Vive.RS", "filters": { "type": "deadZone", "min": 0.15 }, "to": "Standard.RX" }, { "from": "Vive.RT", "to": "Standard.RT", "filters": [ From a3c474729022531a8a6269077e459dc8a8487488 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Thu, 21 Feb 2019 11:17:31 -0800 Subject: [PATCH 031/158] Add leveled controller-relative movement option. --- interface/src/avatar/MyAvatar.cpp | 47 +++++++++++++++++++++----- interface/src/avatar/MyAvatar.h | 16 +++++---- interface/src/ui/PreferencesDialog.cpp | 11 ++++-- 3 files changed, 56 insertions(+), 18 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 1953f5fba8..eeab2d1ac0 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -169,7 +169,7 @@ MyAvatar::MyAvatar(QThread* thread) : _useSnapTurnSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "useSnapTurn", _useSnapTurn), _userHeightSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "userHeight", DEFAULT_AVATAR_HEIGHT), _flyingHMDSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "flyingHMD", _flyingPrefHMD), - _handRelativeMovementSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "handRelativeMovement", _handRelativeMovement), + _movementReferenceSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "movementReference", _movementReference), _avatarEntityCountSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "avatarEntityData" << "size", 0), _userRecenterModelSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "userRecenterModel", USER_RECENTER_MODEL_AUTO), _driveGear1Setting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "driveGear1", _driveGear1), @@ -1283,7 +1283,7 @@ void MyAvatar::saveData() { _useSnapTurnSetting.set(_useSnapTurn); _userHeightSetting.set(getUserHeight()); _flyingHMDSetting.set(getFlyingHMDPref()); - _handRelativeMovementSetting.set(getHandRelativeMovement()); + _movementReferenceSetting.set(getMovementReference()); _driveGear1Setting.set(getDriveGear1()); _driveGear2Setting.set(getDriveGear2()); _driveGear3Setting.set(getDriveGear3()); @@ -1867,7 +1867,7 @@ void MyAvatar::loadData() { // Flying preferences must be loaded before calling setFlyingEnabled() Setting::Handle firstRunVal { Settings::firstRun, true }; setFlyingHMDPref(firstRunVal.get() ? false : _flyingHMDSetting.get()); - setHandRelativeMovement(firstRunVal.get() ? false : _handRelativeMovementSetting.get()); + setMovementReference(firstRunVal.get() ? false : _movementReferenceSetting.get()); setDriveGear1(firstRunVal.get() ? DEFAULT_GEAR_1 : _driveGear1Setting.get()); setDriveGear2(firstRunVal.get() ? DEFAULT_GEAR_2 : _driveGear2Setting.get()); setDriveGear3(firstRunVal.get() ? DEFAULT_GEAR_3 : _driveGear3Setting.get()); @@ -3354,7 +3354,36 @@ glm::vec3 MyAvatar::calculateScaledDirection(){ // compute action input // Determine if we're head or controller relative... glm::vec3 forward, right; - if (getHandRelativeMovement() && qApp->isHMDMode()) { + + if (qApp->isHMDMode()) { + auto handRotation = getDominantHandRotation(); + glm::vec3 controllerForward(0.0f, 1.0f, 0.0f); + glm::vec3 controllerRight(0.0f, 0.0f, (getDominantHand() == DOMINANT_RIGHT_HAND ? -1.0f : 1.0f)); + // Do shit here. + switch (getMovementReference()) { + case MOVEMENT_HAND_RELATIVE: + forward = (handRotation * controllerForward); + right = (handRotation * controllerRight); + break; + case MOVEMENT_HAND_RELATIVE_LEVELED: + forward = (handRotation * controllerForward); + forward.y = 0.0f; + forward /= forward.length(); + right = (handRotation * controllerRight); + right.y = 0.0f; + right /= right.length(); + break; + case MOVEMENT_HMD_RELATIVE: + default: + forward = IDENTITY_FORWARD; + right = IDENTITY_RIGHT; + } + } else { + forward = IDENTITY_FORWARD; + right = IDENTITY_RIGHT; + } + + if (getMovementReference() && qApp->isHMDMode()) { // Here we have to get the rotation of the dominant hand and apply that to the direction vector. // If we're on the right hand, we have to flip the x-axis. auto handRotation = getDominantHandRotation(); @@ -3923,16 +3952,16 @@ void MyAvatar::setFlyingHMDPref(bool enabled) { _flyingPrefHMD = enabled; } -void MyAvatar::setHandRelativeMovement(bool enabled) { +void MyAvatar::setMovementReference(int enabled) { if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "setHandRelativeMovement", Q_ARG(bool, enabled)); + QMetaObject::invokeMethod(this, "setMovementReference", Q_ARG(bool, enabled)); return; } - _handRelativeMovement = enabled; + _movementReference = enabled; } -bool MyAvatar::getHandRelativeMovement() { - return _handRelativeMovement; +int MyAvatar::getMovementReference() { + return _movementReference; } void MyAvatar::setControlSchemeIndex(int index){ diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 815c324195..d75622eefb 100755 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -43,6 +43,10 @@ const int CONTROLS_DEFAULT = 0; const int CONTROLS_ANALOG = 1; const int CONTROLS_ANALOG_PLUS = 2; +const int MOVEMENT_HMD_RELATIVE = 0; +const int MOVEMENT_HAND_RELATIVE = 1; +const int MOVEMENT_HAND_RELATIVE_LEVELED = 2; + enum eyeContactTarget { LEFT_EYE, RIGHT_EYE, @@ -1036,18 +1040,18 @@ public: /**jsdoc * Set your preference for hand-relative movement. * @function MyAvatar.setHandRelativeMovement - * @param {boolean} enabled - Set true if you want to enable hand-relative movement, otherwise set to false. + * @param {number} enabled - Set true if you want to enable hand-relative movement, otherwise set to false. * */ - Q_INVOKABLE void setHandRelativeMovement(bool enabled); + Q_INVOKABLE void setMovementReference(int enabled); /**jsdoc * Get your preference for hand-relative movement. * @function MyAvatar.getHandRelativeMovement - * @returns {boolean} true if your preference is for user locomotion to be relative to the direction your + * @returns {number} true if your preference is for user locomotion to be relative to the direction your * controller is pointing, otherwise false. */ - Q_INVOKABLE bool getHandRelativeMovement(); + Q_INVOKABLE int getMovementReference(); /**jsdoc * Set the first 'shifting point' for acceleration step function. @@ -1802,7 +1806,6 @@ private: bool _enableFlying { false }; bool _flyingPrefDesktop { true }; bool _flyingPrefHMD { false }; - bool _handRelativeMovement{ false }; bool _wasPushing { false }; bool _isPushing { false }; bool _isBeingPushed { false }; @@ -1818,6 +1821,7 @@ private: float _driveGear4 { DEFAULT_GEAR_4 }; float _driveGear5 { DEFAULT_GEAR_5 }; int _controlSchemeIndex { CONTROLS_DEFAULT }; + int _movementReference{ 0 }; glm::vec3 _thrust { 0.0f }; // impulse accumulator for outside sources @@ -2069,7 +2073,7 @@ private: Setting::Handle _useSnapTurnSetting; Setting::Handle _userHeightSetting; Setting::Handle _flyingHMDSetting; - Setting::Handle _handRelativeMovementSetting; + Setting::Handle _movementReferenceSetting; Setting::Handle _avatarEntityCountSetting; Setting::Handle _allowTeleportingSetting { "allowTeleporting", true }; Setting::Handle _driveGear1Setting; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index e08e4bfe8f..2ae04da445 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -273,9 +273,14 @@ void setupPreferences() { preferences->addPreference(preference); } { - auto getter = [myAvatar]()->bool { return myAvatar->getHandRelativeMovement(); }; - auto setter = [myAvatar](bool value) { myAvatar->setHandRelativeMovement(value); }; - auto preference = new CheckPreference(VR_MOVEMENT, "Hand-Relative Movement", getter, setter); + auto getter = [myAvatar]()->int { return myAvatar->getMovementReference(); }; + auto setter = [myAvatar](int value) { myAvatar->setMovementReference(value); }; + //auto preference = new CheckPreference(VR_MOVEMENT, "Hand-Relative Movement", getter, setter); + auto preference = new RadioButtonsPreference(VR_MOVEMENT, "Movement Direction", getter, setter); + QStringList items; + items << "HMD-Relative" << "Hand-Relative" << "Hand-Relative (Leveled)"; + preference->setHeading("Movement Direction"); + preference->setItems(items); preferences->addPreference(preference); } { From 58906d84eb10c85cdbcc54bd12aa8e6c3bc9a7c5 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Thu, 21 Feb 2019 15:22:21 -0800 Subject: [PATCH 032/158] Add grip button polling. --- .../controllerModules/farGrabEntity.js | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index e9e7068206..9c78c576d5 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -328,6 +328,8 @@ Script.include("/~/system/libraries/controllers.js"); grabMapping = Controller.newMapping(mappingName); grabMapping.from(Controller.Standard.LT).peek().to(_this.getLeftTrigger); grabMapping.from(Controller.Standard.RT).peek().to(_this.getRightTrigger); + grabMapping.from(Controller.Standard.LeftGrip).peek().to(_this.setLeftGrip); + grabMapping.from(Controller.Standard.RightGrip).peek().to(_this.setRightGrip); Controller.enableMapping(mappingName); }; @@ -337,6 +339,8 @@ Script.include("/~/system/libraries/controllers.js"); this.leftTrigger = 0.0; this.rightTrigger = 0.0; + this.leftGrip = 0.0; + this.rightGrip = 0.0; this.getDominantHand = function () { return (MyAvatar.getDominantHand() === "left") ? LEFT_HAND : RIGHT_HAND; @@ -362,6 +366,22 @@ Script.include("/~/system/libraries/controllers.js"); return (MyAvatar.getDominantHand() === "left") ? (_this.rightTrigger) : (_this.leftTrigger); }; + this.setLeftGrip = function (value) { + this.leftGrip = value; + } + + this.setRightGrip = function (value) { + this.rightGrip = value; + } + + this.getDominantGrip = function () { + return (MyAvatar.getDominantHand() === "left" ? (_this.leftGrip) : (_this.rightGrip)); + } + + this.getOffhandGrip = function () { + return (MyAvatar.getDominantHand() === "left" ? (_this.rightGrip) : (_this.leftGrip)); + } + this.shouldShowLaser = function () { return (_this.getOffHandTrigger() > TRIGGER_ON_VALUE) ? true : false; }; From c6a3496b2573057381da004ea030114ffe92ecf9 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Sun, 24 Feb 2019 12:36:44 -0800 Subject: [PATCH 033/158] Add utility functions for adjusting target rotation and position. --- .../controllerModules/farGrabEntity.js | 64 ++++++++++++++++++- 1 file changed, 61 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index 9c78c576d5..92fc4a45f1 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -146,7 +146,7 @@ Script.include("/~/system/libraries/controllers.js"); var newTargetPosLocal = MyAvatar.worldToJointPoint(targetProps.position); MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], newTargetPosLocal); - MyAvatar.setJointRotation(FAR_GRAB_JOINTS[this.hand], { x: 0, y: 0, z: 0, w: 1 }); + MyAvatar.setJointRotation(FAR_GRAB_JOINTS[this.hand], { x: 0, y: 0, z: 0, w: 1 }); // RKNOTE: This is where the rotation should be updated. var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(targetProps.id, "startDistanceGrab", args); @@ -235,7 +235,7 @@ Script.include("/~/system/libraries/controllers.js"); // var newTargetPosLocal = Mat4.transformPoint(MyAvatar.getSensorToWorldMatrix(), newTargetPosition); var newTargetPosLocal = MyAvatar.worldToJointPoint(newTargetPosition); MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], newTargetPosLocal); - MyAvatar.setJointRotation(FAR_GRAB_JOINTS[this.hand], { x: 0, y: 0, z: 0, w: 1 }); + MyAvatar.setJointRotation(FAR_GRAB_JOINTS[this.hand], { x: 0, y: 0, z: 0, w: 1 }); // RKNOTE: This is where the rotation should be updated. this.previousRoomControllerPosition = roomControllerPosition; }; @@ -259,7 +259,7 @@ Script.include("/~/system/libraries/controllers.js"); this.grabbing = false; this.targetEntityID = null; this.potentialEntityWithContextOverlay = false; - MyAvatar.clearJointData(FAR_GRAB_JOINTS[this.hand]); + MyAvatar.clearJointData(FAR_GRAB_JOINTS[this.hand]); // RKNOTE: Here, we should edit the entity's position and rotation data with the current joint rotation data. }; this.updateRecommendedArea = function () { @@ -395,6 +395,64 @@ Script.include("/~/system/libraries/controllers.js"); return (_this.getOffHandTrigger() <= TRIGGER_OFF_VALUE) ? true : false; }; + this.getTargetPosition = function () { + if (this.targetIsNull()) { + return null; + } else { + var props = Entities.getEntityProperties(this.targetEntityID, ["position"]); + return props.position; + } + }; + + this.getTargetRotation = function () { + if (this.targetIsNull()) { + return null; + } else { + var props = Entities.getEntityProperties(this.targetEntityID, ["rotation"]); + return props.rotation; + } + }; + + this.getTargetLocalPosition = function () { + if (this.targetIsNull()) { + return null; + } else { + var props = Entities.getEntityProperties(this.targetEntityID, ["localPosition"]); + return props.localPosition; + } + }; + + this.getTargetLocalRotation = function () { + if (this.targetIsNull()) { + return null; + } else { + var props = Entities.getEntityProperties(this.targetEntityID, ["localRotation"]); + return props.localRotation; + } + }; + + this.setTargetPosition = function (newPos) { + if (this.targetIsNull()) { + print("Fargrab Error: No target to edit position."); + return; + } else { + var props; + props.position = newPos; + Entities.editEntity(this.targetEntityID, props); + } + }; + + this.setTargetRotation = function (newRot) { + if (this.targetIsNull()) { + print("Fargrab Error: No target to edit rotation."); + return; + } else { + var props; + props.rotation = newRot; + Entitis.editEntity(this.targetEntityID, props); + } + } + this.isReady = function (controllerData) { if (HMD.active && this.hand === this.getOffHand()) { if (this.notPointingAtEntity(controllerData)) { From d79681470e8ebae6561f036b3021a8dfb006a0f2 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 25 Feb 2019 13:10:25 -0800 Subject: [PATCH 034/158] Saving changes before merging master... --- .../controllerModules/farGrabEntity.js | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index 92fc4a45f1..5947633508 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -111,6 +111,7 @@ Script.include("/~/system/libraries/controllers.js"); this.currentObjectPosition = targetProps.position; this.currentObjectRotation = targetProps.rotation; this.currentObjectTime = now; + this.initialEntityRotation = targetProps.rotation; this.grabRadius = this.grabbedDistance; this.grabRadialVelocity = 0.0; @@ -145,8 +146,14 @@ Script.include("/~/system/libraries/controllers.js"); Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message)); var newTargetPosLocal = MyAvatar.worldToJointPoint(targetProps.position); - MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], newTargetPosLocal); - MyAvatar.setJointRotation(FAR_GRAB_JOINTS[this.hand], { x: 0, y: 0, z: 0, w: 1 }); // RKNOTE: This is where the rotation should be updated. + var newTargetRotLocal = this.targetProps.rotation; + if (this.shouldManipulateTarget()) { + var rotBetween = this.calculateEntityRotationManipulation(worldControllerRotation); + var newTargetRotLocal = Quat.multiply(rotBetween, newTargetRotLocal); + } + //MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], newTargetPosLocal); + this.setJointTranslation(newTargetPosLocal); + this.setJointRotation(newTargetRotLocal); var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(targetProps.id, "startDistanceGrab", args); @@ -234,8 +241,14 @@ Script.include("/~/system/libraries/controllers.js"); // var newTargetPosLocal = Mat4.transformPoint(MyAvatar.getSensorToWorldMatrix(), newTargetPosition); var newTargetPosLocal = MyAvatar.worldToJointPoint(newTargetPosition); - MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], newTargetPosLocal); - MyAvatar.setJointRotation(FAR_GRAB_JOINTS[this.hand], { x: 0, y: 0, z: 0, w: 1 }); // RKNOTE: This is where the rotation should be updated. + var newTargetRotLocal = this.initialEntityRotation; + if (this.shouldManipulateTarget()) { + var rotBetween = this.calculateEntityRotationManipulation(worldControllerRotation); + var newTargetRotLocal = Quat.multiply(rotBetween, newTargetRotLocal); + } + //MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], newTargetPosLocal); + this.setJointTranslation(newTargetPosLocal); + this.setJointRotation(newTargetRotLocal); this.previousRoomControllerPosition = roomControllerPosition; }; @@ -257,9 +270,10 @@ Script.include("/~/system/libraries/controllers.js"); })); unhighlightTargetEntity(this.targetEntityID); this.grabbing = false; - this.targetEntityID = null; this.potentialEntityWithContextOverlay = false; MyAvatar.clearJointData(FAR_GRAB_JOINTS[this.hand]); // RKNOTE: Here, we should edit the entity's position and rotation data with the current joint rotation data. + this.setTargetRotation(this.lastFarGrabJointRotation); + this.targetEntityID = null; }; this.updateRecommendedArea = function () { @@ -337,6 +351,10 @@ Script.include("/~/system/libraries/controllers.js"); grabMapping.disable(); }; + this.initialControllerRotation = Quat.IDENTITY; + this.initialEntityRotation = Quat.IDENTITY; + this.lastFarGrabJointRotation = Quat.IDENTITY; + this.leftTrigger = 0.0; this.rightTrigger = 0.0; this.leftGrip = 0.0; @@ -451,8 +469,25 @@ Script.include("/~/system/libraries/controllers.js"); props.rotation = newRot; Entitis.editEntity(this.targetEntityID, props); } + }; + + this.shouldManipulateTarget = function () { + return (this.getDominantGrip() > TRIGGER_ON_VALUE); } + this.calculateEntityRotationManipulation = function (controllerRotation) { + return Quat.multiply(controllerRotation, Quat.inverse(this.initialControllerRotation)); + } + + this.setJointTranslation(newTargetPosLocal) { + MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], newTargetPosLocal); + }; + + this.setJointRotation(newTargetRotLocal) { + this.lastFarGrabJointRotation = newTargetRotLocal; + MyAvatar.setJointRotation(FAR_GRAB_JOINTS[this.hand], newTargetRotLocal); + }; + this.isReady = function (controllerData) { if (HMD.active && this.hand === this.getOffHand()) { if (this.notPointingAtEntity(controllerData)) { From a66c76bf3847e4832809f18d62b205dd3f12b436 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 25 Feb 2019 13:47:31 -0800 Subject: [PATCH 035/158] Fixing typos. --- .../controllerModules/farGrabEntity.js | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index 5947633508..028fe3c804 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -146,7 +146,7 @@ Script.include("/~/system/libraries/controllers.js"); Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message)); var newTargetPosLocal = MyAvatar.worldToJointPoint(targetProps.position); - var newTargetRotLocal = this.targetProps.rotation; + var newTargetRotLocal = targetProps.rotation; if (this.shouldManipulateTarget()) { var rotBetween = this.calculateEntityRotationManipulation(worldControllerRotation); var newTargetRotLocal = Quat.multiply(rotBetween, newTargetRotLocal); @@ -243,6 +243,7 @@ Script.include("/~/system/libraries/controllers.js"); var newTargetPosLocal = MyAvatar.worldToJointPoint(newTargetPosition); var newTargetRotLocal = this.initialEntityRotation; if (this.shouldManipulateTarget()) { + print("Test this thing."); var rotBetween = this.calculateEntityRotationManipulation(worldControllerRotation); var newTargetRotLocal = Quat.multiply(rotBetween, newTargetRotLocal); } @@ -272,7 +273,8 @@ Script.include("/~/system/libraries/controllers.js"); this.grabbing = false; this.potentialEntityWithContextOverlay = false; MyAvatar.clearJointData(FAR_GRAB_JOINTS[this.hand]); // RKNOTE: Here, we should edit the entity's position and rotation data with the current joint rotation data. - this.setTargetRotation(this.lastFarGrabJointRotation); + this.setTargetRotation(Quat.multiply(this.lastFarGrabJointRotation, this.initialEntityRotation)); + this.initialEntityRotation = Quat.IDENTITY; this.targetEntityID = null; }; @@ -386,19 +388,19 @@ Script.include("/~/system/libraries/controllers.js"); this.setLeftGrip = function (value) { this.leftGrip = value; - } + }; this.setRightGrip = function (value) { this.rightGrip = value; - } + }; this.getDominantGrip = function () { return (MyAvatar.getDominantHand() === "left" ? (_this.leftGrip) : (_this.rightGrip)); - } + }; this.getOffhandGrip = function () { return (MyAvatar.getDominantHand() === "left" ? (_this.rightGrip) : (_this.leftGrip)); - } + }; this.shouldShowLaser = function () { return (_this.getOffHandTrigger() > TRIGGER_ON_VALUE) ? true : false; @@ -454,8 +456,7 @@ Script.include("/~/system/libraries/controllers.js"); print("Fargrab Error: No target to edit position."); return; } else { - var props; - props.position = newPos; + var props = { position: newPos }; Entities.editEntity(this.targetEntityID, props); } }; @@ -465,25 +466,24 @@ Script.include("/~/system/libraries/controllers.js"); print("Fargrab Error: No target to edit rotation."); return; } else { - var props; - props.rotation = newRot; - Entitis.editEntity(this.targetEntityID, props); + var props = { rotation: newRot }; + Entities.editEntity(this.targetEntityID, props); } }; this.shouldManipulateTarget = function () { return (this.getDominantGrip() > TRIGGER_ON_VALUE); - } + }; this.calculateEntityRotationManipulation = function (controllerRotation) { return Quat.multiply(controllerRotation, Quat.inverse(this.initialControllerRotation)); - } + }; - this.setJointTranslation(newTargetPosLocal) { + this.setJointTranslation = function (newTargetPosLocal) { MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], newTargetPosLocal); }; - this.setJointRotation(newTargetRotLocal) { + this.setJointRotation = function (newTargetRotLocal) { this.lastFarGrabJointRotation = newTargetRotLocal; MyAvatar.setJointRotation(FAR_GRAB_JOINTS[this.hand], newTargetRotLocal); }; From 52b62784d6e440079c3c28d1122b2cfbd1ed4e22 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 25 Feb 2019 14:10:48 -0800 Subject: [PATCH 036/158] Incremental, broken progress. --- .../system/controllers/controllerModules/farGrabEntity.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index 028fe3c804..0aa54bc8e5 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -243,7 +243,6 @@ Script.include("/~/system/libraries/controllers.js"); var newTargetPosLocal = MyAvatar.worldToJointPoint(newTargetPosition); var newTargetRotLocal = this.initialEntityRotation; if (this.shouldManipulateTarget()) { - print("Test this thing."); var rotBetween = this.calculateEntityRotationManipulation(worldControllerRotation); var newTargetRotLocal = Quat.multiply(rotBetween, newTargetRotLocal); } @@ -272,8 +271,9 @@ Script.include("/~/system/libraries/controllers.js"); unhighlightTargetEntity(this.targetEntityID); this.grabbing = false; this.potentialEntityWithContextOverlay = false; + var rot = this.getTargetRotation(); MyAvatar.clearJointData(FAR_GRAB_JOINTS[this.hand]); // RKNOTE: Here, we should edit the entity's position and rotation data with the current joint rotation data. - this.setTargetRotation(Quat.multiply(this.lastFarGrabJointRotation, this.initialEntityRotation)); + this.setTargetRotation(Quat.multiply(this.lastFarGrabJointRotation, rot)); this.initialEntityRotation = Quat.IDENTITY; this.targetEntityID = null; }; @@ -472,7 +472,9 @@ Script.include("/~/system/libraries/controllers.js"); }; this.shouldManipulateTarget = function () { - return (this.getDominantGrip() > TRIGGER_ON_VALUE); + //var test = this.getDominantGrip() > TRIGGER_ON_VALUE; + //return test; + return true; }; this.calculateEntityRotationManipulation = function (controllerRotation) { From 0b651a8d633bcaa834492a54132d33bf1cf83d48 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 26 Feb 2019 11:29:06 -0800 Subject: [PATCH 037/158] Fix fargrab rotation with dominant hand, need to fix activation criteria next. --- .../controllerModules/farGrabEntity.js | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index 0aa54bc8e5..d5bebc549f 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -111,7 +111,7 @@ Script.include("/~/system/libraries/controllers.js"); this.currentObjectPosition = targetProps.position; this.currentObjectRotation = targetProps.rotation; this.currentObjectTime = now; - this.initialEntityRotation = targetProps.rotation; + this.initialEntityRotation = targetProps.rotation; // World frame. this.grabRadius = this.grabbedDistance; this.grabRadialVelocity = 0.0; @@ -145,13 +145,10 @@ Script.include("/~/system/libraries/controllers.js"); Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message)); - var newTargetPosLocal = MyAvatar.worldToJointPoint(targetProps.position); - var newTargetRotLocal = targetProps.rotation; - if (this.shouldManipulateTarget()) { - var rotBetween = this.calculateEntityRotationManipulation(worldControllerRotation); - var newTargetRotLocal = Quat.multiply(rotBetween, newTargetRotLocal); - } //MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], newTargetPosLocal); + + var newTargetPosLocal = MyAvatar.worldToJointPoint(targetProps.position); // World frame. + var newTargetRotLocal = targetProps.rotation; // World frame. this.setJointTranslation(newTargetPosLocal); this.setJointRotation(newTargetRotLocal); @@ -243,10 +240,14 @@ Script.include("/~/system/libraries/controllers.js"); var newTargetPosLocal = MyAvatar.worldToJointPoint(newTargetPosition); var newTargetRotLocal = this.initialEntityRotation; if (this.shouldManipulateTarget()) { - var rotBetween = this.calculateEntityRotationManipulation(worldControllerRotation); + var dominantHandControllerLocation = controllerData.controllerLocations[this.getDominantHand()]; + var worldDominantHandControllerRotation = dominantHandControllerLocation.rotation; + if (Quat.equal(Quat.IDENTITY, this.initialControllerRotation)) { + this.initialControllerRotation = worldDominantHandControllerRotation; + } + var rotBetween = this.calculateEntityRotationManipulation(worldDominantHandControllerRotation); var newTargetRotLocal = Quat.multiply(rotBetween, newTargetRotLocal); } - //MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], newTargetPosLocal); this.setJointTranslation(newTargetPosLocal); this.setJointRotation(newTargetRotLocal); @@ -271,10 +272,9 @@ Script.include("/~/system/libraries/controllers.js"); unhighlightTargetEntity(this.targetEntityID); this.grabbing = false; this.potentialEntityWithContextOverlay = false; - var rot = this.getTargetRotation(); - MyAvatar.clearJointData(FAR_GRAB_JOINTS[this.hand]); // RKNOTE: Here, we should edit the entity's position and rotation data with the current joint rotation data. - this.setTargetRotation(Quat.multiply(this.lastFarGrabJointRotation, rot)); + MyAvatar.clearJointData(FAR_GRAB_JOINTS[this.hand]); this.initialEntityRotation = Quat.IDENTITY; + this.initialControllerRotation = Quat.IDENTITY; this.targetEntityID = null; }; @@ -355,7 +355,6 @@ Script.include("/~/system/libraries/controllers.js"); this.initialControllerRotation = Quat.IDENTITY; this.initialEntityRotation = Quat.IDENTITY; - this.lastFarGrabJointRotation = Quat.IDENTITY; this.leftTrigger = 0.0; this.rightTrigger = 0.0; @@ -486,7 +485,6 @@ Script.include("/~/system/libraries/controllers.js"); }; this.setJointRotation = function (newTargetRotLocal) { - this.lastFarGrabJointRotation = newTargetRotLocal; MyAvatar.setJointRotation(FAR_GRAB_JOINTS[this.hand], newTargetRotLocal); }; From 2a04d2b9c59c259ad9f492f34014f49863a8a8bd Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 26 Feb 2019 12:39:51 -0800 Subject: [PATCH 038/158] Closer... --- .../controllerModules/farGrabEntity.js | 40 ++++++++++++------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index d5bebc549f..ee0fe5f106 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -111,7 +111,7 @@ Script.include("/~/system/libraries/controllers.js"); this.currentObjectPosition = targetProps.position; this.currentObjectRotation = targetProps.rotation; this.currentObjectTime = now; - this.initialEntityRotation = targetProps.rotation; // World frame. + //this.initialEntityRotation = targetProps.rotation; // World frame. this.grabRadius = this.grabbedDistance; this.grabRadialVelocity = 0.0; @@ -238,18 +238,27 @@ Script.include("/~/system/libraries/controllers.js"); // var newTargetPosLocal = Mat4.transformPoint(MyAvatar.getSensorToWorldMatrix(), newTargetPosition); var newTargetPosLocal = MyAvatar.worldToJointPoint(newTargetPosition); - var newTargetRotLocal = this.initialEntityRotation; if (this.shouldManipulateTarget()) { - var dominantHandControllerLocation = controllerData.controllerLocations[this.getDominantHand()]; - var worldDominantHandControllerRotation = dominantHandControllerLocation.rotation; - if (Quat.equal(Quat.IDENTITY, this.initialControllerRotation)) { - this.initialControllerRotation = worldDominantHandControllerRotation; + var pose = Controller.getPoseValue((this.getDominantHand() ? Controller.Standard.RightHand : Controller.Standard.LeftHand)); + if (pose.valid) { + if (!this.manipulating) { + //this.initialEntityRotation = Quat.multiply(this.getTargetRotation(), Quat.inverse(MyAvatar.orientation)); // Avatar frame. + this.initialEntityRotation = this.getTargetRotation(); // Worldframe. + this.initialControllerRotation = Quat.multiply(MyAvatar.orientation, pose.rotation); // Worldframe. + //this.initialEntityRotation = Quat.multiply(this.getTargetRotation(), Quat.inverse(MyAvatar.orientation)); + this.manipulating = true; + } } - var rotBetween = this.calculateEntityRotationManipulation(worldDominantHandControllerRotation); - var newTargetRotLocal = Quat.multiply(rotBetween, newTargetRotLocal); + + var rot = Quat.multiply(MyAvatar.orientation, pose.rotation); + var rotBetween = this.calculateEntityRotationManipulation(rot); + this.setJointRotation(Quat.multiply(rotBetween, this.initialEntityRotation)); + } else { + this.manipulating = false; + this.initialEntityRotation = Quat.IDENTITY; + this.initialControllerRotation = Quat.IDENTITY; } this.setJointTranslation(newTargetPosLocal); - this.setJointRotation(newTargetRotLocal); this.previousRoomControllerPosition = roomControllerPosition; }; @@ -276,6 +285,7 @@ Script.include("/~/system/libraries/controllers.js"); this.initialEntityRotation = Quat.IDENTITY; this.initialControllerRotation = Quat.IDENTITY; this.targetEntityID = null; + this.manipulating = false; }; this.updateRecommendedArea = function () { @@ -355,6 +365,7 @@ Script.include("/~/system/libraries/controllers.js"); this.initialControllerRotation = Quat.IDENTITY; this.initialEntityRotation = Quat.IDENTITY; + this.manipulating = false; this.leftTrigger = 0.0; this.rightTrigger = 0.0; @@ -414,6 +425,11 @@ Script.include("/~/system/libraries/controllers.js"); return (_this.getOffHandTrigger() <= TRIGGER_OFF_VALUE) ? true : false; }; + this.shouldManipulateTarget = function () { + return (_this.getDominantTrigger() > TRIGGER_ON_VALUE) ? true : false; + }; + + this.getTargetPosition = function () { if (this.targetIsNull()) { return null; @@ -470,12 +486,6 @@ Script.include("/~/system/libraries/controllers.js"); } }; - this.shouldManipulateTarget = function () { - //var test = this.getDominantGrip() > TRIGGER_ON_VALUE; - //return test; - return true; - }; - this.calculateEntityRotationManipulation = function (controllerRotation) { return Quat.multiply(controllerRotation, Quat.inverse(this.initialControllerRotation)); }; From f3b65d06ada804155ff4d6b992189eed68bb86f6 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 26 Feb 2019 12:46:46 -0800 Subject: [PATCH 039/158] Fix frame of reference for rotations. --- .../system/controllers/controllerModules/farGrabEntity.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index ee0fe5f106..2166495567 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -242,15 +242,13 @@ Script.include("/~/system/libraries/controllers.js"); var pose = Controller.getPoseValue((this.getDominantHand() ? Controller.Standard.RightHand : Controller.Standard.LeftHand)); if (pose.valid) { if (!this.manipulating) { - //this.initialEntityRotation = Quat.multiply(this.getTargetRotation(), Quat.inverse(MyAvatar.orientation)); // Avatar frame. this.initialEntityRotation = this.getTargetRotation(); // Worldframe. - this.initialControllerRotation = Quat.multiply(MyAvatar.orientation, pose.rotation); // Worldframe. - //this.initialEntityRotation = Quat.multiply(this.getTargetRotation(), Quat.inverse(MyAvatar.orientation)); + this.initialControllerRotation = Quat.multiply(pose.rotation, MyAvatar.orientation); // Worldframe. this.manipulating = true; } } - var rot = Quat.multiply(MyAvatar.orientation, pose.rotation); + var rot = Quat.multiply(pose.rotation, MyAvatar.orientation); var rotBetween = this.calculateEntityRotationManipulation(rot); this.setJointRotation(Quat.multiply(rotBetween, this.initialEntityRotation)); } else { From 030211aea8047d94db19d3ec26c87164473f41ce Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 26 Feb 2019 14:46:04 -0800 Subject: [PATCH 040/158] Fix OSX compiler error, init list in wrong order after merge. --- interface/src/avatar/MyAvatar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 94c5e2e708..14e9f1a987 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -171,13 +171,13 @@ MyAvatar::MyAvatar(QThread* thread) : _flyingHMDSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "flyingHMD", _flyingPrefHMD), _movementReferenceSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "movementReference", _movementReference), _avatarEntityCountSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "avatarEntityData" << "size", 0), - _userRecenterModelSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "userRecenterModel", USER_RECENTER_MODEL_AUTO), _driveGear1Setting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "driveGear1", _driveGear1), _driveGear2Setting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "driveGear2", _driveGear2), _driveGear3Setting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "driveGear3", _driveGear3), _driveGear4Setting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "driveGear4", _driveGear4), _driveGear5Setting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "driveGear5", _driveGear5), - _controlSchemeIndexSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "controlSchemeIndex", _controlSchemeIndex) + _controlSchemeIndexSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "controlSchemeIndex", _controlSchemeIndex), + _userRecenterModelSetting(QStringList() << AVATAR_SETTINGS_GROUP_NAME << "userRecenterModel", USER_RECENTER_MODEL_AUTO) { _clientTraitsHandler.reset(new ClientTraitsHandler(this)); From 2077e012dbbfa441eb5b1b92a62b8a786f27b3ff Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 26 Feb 2019 15:00:44 -0800 Subject: [PATCH 041/158] Fix case of repeated manipulations with fargrab. --- .../controllers/controllerModules/farGrabEntity.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index 2166495567..756f8cd0db 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -242,7 +242,9 @@ Script.include("/~/system/libraries/controllers.js"); var pose = Controller.getPoseValue((this.getDominantHand() ? Controller.Standard.RightHand : Controller.Standard.LeftHand)); if (pose.valid) { if (!this.manipulating) { - this.initialEntityRotation = this.getTargetRotation(); // Worldframe. + if (!this.wasManipulating) { + this.initialEntityRotation = this.getTargetRotation(); // Worldframe. + } this.initialControllerRotation = Quat.multiply(pose.rotation, MyAvatar.orientation); // Worldframe. this.manipulating = true; } @@ -250,10 +252,14 @@ Script.include("/~/system/libraries/controllers.js"); var rot = Quat.multiply(pose.rotation, MyAvatar.orientation); var rotBetween = this.calculateEntityRotationManipulation(rot); - this.setJointRotation(Quat.multiply(rotBetween, this.initialEntityRotation)); + this.lastJointRotation = Quat.multiply(rotBetween, this.initialEntityRotation); + this.setJointRotation(this.lastJointRotation); } else { + if (this.manipulating) { + this.initialEntityRotation = this.lastJointRotation; + this.wasManipulating = true; + } this.manipulating = false; - this.initialEntityRotation = Quat.IDENTITY; this.initialControllerRotation = Quat.IDENTITY; } this.setJointTranslation(newTargetPosLocal); @@ -284,6 +290,7 @@ Script.include("/~/system/libraries/controllers.js"); this.initialControllerRotation = Quat.IDENTITY; this.targetEntityID = null; this.manipulating = false; + this.wasManipulating = false; }; this.updateRecommendedArea = function () { @@ -364,6 +371,7 @@ Script.include("/~/system/libraries/controllers.js"); this.initialControllerRotation = Quat.IDENTITY; this.initialEntityRotation = Quat.IDENTITY; this.manipulating = false; + this.wasManipulating = false; this.leftTrigger = 0.0; this.rightTrigger = 0.0; From 42b62ff2d531c8eda9960d185a19f2a201ac320e Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 26 Feb 2019 19:16:34 -0800 Subject: [PATCH 042/158] Fix Ubuntu compiler warnings. --- interface/src/avatar/MyAvatar.cpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 64c251f1fa..b202c2f570 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3371,12 +3371,11 @@ glm::vec3 MyAvatar::calculateScaledDirection(){ right = (handRotation * controllerRight); break; case MOVEMENT_HAND_RELATIVE_LEVELED: + handRotation = cancelOutRoll(handRotation); forward = (handRotation * controllerForward); - forward.y = 0.0f; - forward /= forward.length(); + //forward = glm::normalize(forward - (glm::dot(forward, Vectors::UNIT_Y) * Vectors::UNIT_Y)); right = (handRotation * controllerRight); - right.y = 0.0f; - right /= right.length(); + //right = glm::normalize(right - (glm::dot(right, Vectors::UNIT_Y) * Vectors::UNIT_Y)); break; case MOVEMENT_HMD_RELATIVE: default: @@ -3987,7 +3986,7 @@ void MyAvatar::setDriveGear1(float shiftPoint) { QMetaObject::invokeMethod(this, "setDriveGear1", Q_ARG(float, shiftPoint)); return; } - if (shiftPoint > 1.0 || shiftPoint < 0) return; + if (shiftPoint > 1.0f || shiftPoint < 0.0f) return; _driveGear1 = (shiftPoint <= _driveGear2) ? shiftPoint : _driveGear1; } @@ -4000,7 +3999,7 @@ void MyAvatar::setDriveGear2(float shiftPoint) { QMetaObject::invokeMethod(this, "setDriveGear2", Q_ARG(float, shiftPoint)); return; } - if (shiftPoint > 1.0 || shiftPoint < 0) return; + if (shiftPoint > 1.0f || shiftPoint < 0.0f) return; _driveGear2 = (shiftPoint <= _driveGear3 && shiftPoint >= _driveGear1) ? shiftPoint : _driveGear2; } @@ -4013,7 +4012,7 @@ void MyAvatar::setDriveGear3(float shiftPoint) { QMetaObject::invokeMethod(this, "setDriveGear3", Q_ARG(float, shiftPoint)); return; } - if (shiftPoint > 1.0 || shiftPoint < 0) return; + if (shiftPoint > 1.0f || shiftPoint < 0.0f) return; _driveGear3 = (shiftPoint <= _driveGear4 && shiftPoint >= _driveGear2) ? shiftPoint : _driveGear3; } @@ -4026,7 +4025,7 @@ void MyAvatar::setDriveGear4(float shiftPoint) { QMetaObject::invokeMethod(this, "setDriveGear4", Q_ARG(float, shiftPoint)); return; } - if (shiftPoint > 1.0 || shiftPoint < 0) return; + if (shiftPoint > 1.0f || shiftPoint < 0.0f) return; _driveGear4 = (shiftPoint <= _driveGear5 && shiftPoint >= _driveGear3) ? shiftPoint : _driveGear4; } @@ -4039,7 +4038,7 @@ void MyAvatar::setDriveGear5(float shiftPoint) { QMetaObject::invokeMethod(this, "setDriveGear5", Q_ARG(float, shiftPoint)); return; } - if (shiftPoint > 1.0 || shiftPoint < 0) return; + if (shiftPoint > 1.0f || shiftPoint < 0.0f) return; _driveGear5 = (shiftPoint >= _driveGear4) ? shiftPoint : _driveGear5; } From 7c515ccd452d3d6322916675893aaab199494664 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Tue, 26 Feb 2019 19:16:45 -0800 Subject: [PATCH 043/158] Add 2x rotation multiplier. --- .../controllerModules/farGrabEntity.js | 23 ++----------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index 756f8cd0db..ea0c3e8ad6 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -252,7 +252,8 @@ Script.include("/~/system/libraries/controllers.js"); var rot = Quat.multiply(pose.rotation, MyAvatar.orientation); var rotBetween = this.calculateEntityRotationManipulation(rot); - this.lastJointRotation = Quat.multiply(rotBetween, this.initialEntityRotation); + var doubleRot = Quat.multiply(rotBetween, rotBetween); + this.lastJointRotation = Quat.multiply(doubleRot, this.initialEntityRotation); this.setJointRotation(this.lastJointRotation); } else { if (this.manipulating) { @@ -359,8 +360,6 @@ Script.include("/~/system/libraries/controllers.js"); grabMapping = Controller.newMapping(mappingName); grabMapping.from(Controller.Standard.LT).peek().to(_this.getLeftTrigger); grabMapping.from(Controller.Standard.RT).peek().to(_this.getRightTrigger); - grabMapping.from(Controller.Standard.LeftGrip).peek().to(_this.setLeftGrip); - grabMapping.from(Controller.Standard.RightGrip).peek().to(_this.setRightGrip); Controller.enableMapping(mappingName); }; @@ -375,8 +374,6 @@ Script.include("/~/system/libraries/controllers.js"); this.leftTrigger = 0.0; this.rightTrigger = 0.0; - this.leftGrip = 0.0; - this.rightGrip = 0.0; this.getDominantHand = function () { return (MyAvatar.getDominantHand() === "left") ? LEFT_HAND : RIGHT_HAND; @@ -402,22 +399,6 @@ Script.include("/~/system/libraries/controllers.js"); return (MyAvatar.getDominantHand() === "left") ? (_this.rightTrigger) : (_this.leftTrigger); }; - this.setLeftGrip = function (value) { - this.leftGrip = value; - }; - - this.setRightGrip = function (value) { - this.rightGrip = value; - }; - - this.getDominantGrip = function () { - return (MyAvatar.getDominantHand() === "left" ? (_this.leftGrip) : (_this.rightGrip)); - }; - - this.getOffhandGrip = function () { - return (MyAvatar.getDominantHand() === "left" ? (_this.rightGrip) : (_this.leftGrip)); - }; - this.shouldShowLaser = function () { return (_this.getOffHandTrigger() > TRIGGER_ON_VALUE) ? true : false; }; From fcdfae5a678ed3180b1190ef823a6ebc641910ea Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Wed, 27 Feb 2019 08:39:35 -0800 Subject: [PATCH 044/158] Fix notion of hand dominance. --- interface/resources/controllers/standard.json | 128 +++++++++--------- .../controllerModules/farGrabEntity.js | 10 +- .../controllers/controllerModules/teleport.js | 6 +- 3 files changed, 72 insertions(+), 72 deletions(-) diff --git a/interface/resources/controllers/standard.json b/interface/resources/controllers/standard.json index 25f75c5670..7e23379394 100644 --- a/interface/resources/controllers/standard.json +++ b/interface/resources/controllers/standard.json @@ -2,68 +2,11 @@ "name": "Standard to Action", "channels": [ { "from": "Standard.LY", - "when": ["Application.LeftHandDominant", "!Standard.RY"], + "when": ["Application.RightHandDominant", "!Standard.RY"], "to": "Actions.TranslateZ" }, { "from": "Standard.LX", - "when": [ - "Application.InHMD", "!Application.AdvancedMovement", "Application.LeftHandDominant", - "Application.SnapTurn", "!Standard.RX" - ], - "to": "Actions.StepYaw", - "filters": - [ - { "type": "deadZone", "min": 0.15 }, - "constrainToInteger", - { "type": "pulse", "interval": 0.25 }, - { "type": "scale", "scale": 22.5 } - ] - }, - { "from": "Standard.LX", "to": "Actions.TranslateX", - "when": [ "Application.AdvancedMovement", "Application.LeftHandDominant" ] - }, - { "from": "Standard.LX", "to": "Actions.Yaw", - "when": [ "!Application.AdvancedMovement", "!Application.SnapTurn", "Application.LeftHandDominant" ] - }, - - { "from": "Standard.RX", - "when": [ "Application.SnapTurn", "Application.LeftHandDominant" ], - "to": "Actions.StepYaw", - "filters": - [ - { "type": "deadZone", "min": 0.15 }, - "constrainToInteger", - { "type": "pulse", "interval": 0.25 }, - { "type": "scale", "scale": 22.5 } - ] - }, - { "from": "Standard.RX", "to": "Actions.Yaw", - "when": [ "!Application.SnapTurn", "Application.LeftHandDominant" ] - }, - - { "from": "Standard.RY", - "when": [ "Application.Grounded", "Application.LeftHandDominant" ], - "to": "Actions.Up", - "filters": - [ - { "type": "deadZone", "min": 0.6 }, - "invert" - ] - }, - - { "from": "Standard.RY", - "when": "Application.LeftHandDominant", - "to": "Actions.Up", - "filters": "invert" - }, - - { "from": "Standard.RY", - "when": ["Application.RightHandDominant", "!Standard.LY"], - "to": "Actions.TranslateZ" - }, - - { "from": "Standard.RX", "when": [ "Application.InHMD", "!Application.AdvancedMovement", "Application.RightHandDominant", "Application.SnapTurn", "!Standard.RX" @@ -77,14 +20,14 @@ { "type": "scale", "scale": 22.5 } ] }, - { "from": "Standard.RX", "to": "Actions.TranslateX", + { "from": "Standard.LX", "to": "Actions.TranslateX", "when": [ "Application.AdvancedMovement", "Application.RightHandDominant" ] }, - { "from": "Standard.RX", "to": "Actions.Yaw", + { "from": "Standard.LX", "to": "Actions.Yaw", "when": [ "!Application.AdvancedMovement", "!Application.SnapTurn", "Application.RightHandDominant" ] }, - { "from": "Standard.LX", + { "from": "Standard.RX", "when": [ "Application.SnapTurn", "Application.RightHandDominant" ], "to": "Actions.StepYaw", "filters": @@ -95,11 +38,11 @@ { "type": "scale", "scale": 22.5 } ] }, - { "from": "Standard.LX", "to": "Actions.Yaw", + { "from": "Standard.RX", "to": "Actions.Yaw", "when": [ "!Application.SnapTurn", "Application.RightHandDominant" ] }, - { "from": "Standard.LY", + { "from": "Standard.RY", "when": [ "Application.Grounded", "Application.RightHandDominant" ], "to": "Actions.Up", "filters": @@ -109,11 +52,68 @@ ] }, - { "from": "Standard.LY", + { "from": "Standard.RY", "when": "Application.RightHandDominant", "to": "Actions.Up", "filters": "invert" }, + + { "from": "Standard.RY", + "when": ["Application.LeftHandDominant", "!Standard.LY"], + "to": "Actions.TranslateZ" + }, + + { "from": "Standard.RX", + "when": [ + "Application.InHMD", "!Application.AdvancedMovement", "Application.LeftHandDominant", + "Application.SnapTurn", "!Standard.RX" + ], + "to": "Actions.StepYaw", + "filters": + [ + { "type": "deadZone", "min": 0.15 }, + "constrainToInteger", + { "type": "pulse", "interval": 0.25 }, + { "type": "scale", "scale": 22.5 } + ] + }, + { "from": "Standard.RX", "to": "Actions.TranslateX", + "when": [ "Application.AdvancedMovement", "Application.LeftHandDominant" ] + }, + { "from": "Standard.RX", "to": "Actions.Yaw", + "when": [ "!Application.AdvancedMovement", "!Application.SnapTurn", "Application.LeftHandDominant" ] + }, + + { "from": "Standard.LX", + "when": [ "Application.SnapTurn", "Application.LeftHandDominant" ], + "to": "Actions.StepYaw", + "filters": + [ + { "type": "deadZone", "min": 0.15 }, + "constrainToInteger", + { "type": "pulse", "interval": 0.25 }, + { "type": "scale", "scale": 22.5 } + ] + }, + { "from": "Standard.LX", "to": "Actions.Yaw", + "when": [ "!Application.SnapTurn", "Application.LeftHandDominant" ] + }, + + { "from": "Standard.LY", + "when": [ "Application.Grounded", "Application.LeftHandDominant" ], + "to": "Actions.Up", + "filters": + [ + { "type": "deadZone", "min": 0.6 }, + "invert" + ] + }, + + { "from": "Standard.LY", + "when": "Application.LeftHandDominant", + "to": "Actions.Up", + "filters": "invert" + }, { "from": "Standard.Back", "to": "Actions.CycleCamera" }, { "from": "Standard.Start", "to": "Actions.ContextMenu" }, diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index ea0c3e8ad6..600f9a2772 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -239,7 +239,7 @@ Script.include("/~/system/libraries/controllers.js"); // var newTargetPosLocal = Mat4.transformPoint(MyAvatar.getSensorToWorldMatrix(), newTargetPosition); var newTargetPosLocal = MyAvatar.worldToJointPoint(newTargetPosition); if (this.shouldManipulateTarget()) { - var pose = Controller.getPoseValue((this.getDominantHand() ? Controller.Standard.RightHand : Controller.Standard.LeftHand)); + var pose = Controller.getPoseValue((this.getDominantHand() ? Controller.Standard.LeftHand : Controller.Standard.RightHand)); if (pose.valid) { if (!this.manipulating) { if (!this.wasManipulating) { @@ -400,7 +400,7 @@ Script.include("/~/system/libraries/controllers.js"); }; this.shouldShowLaser = function () { - return (_this.getOffHandTrigger() > TRIGGER_ON_VALUE) ? true : false; + return (_this.getDominantTrigger() > TRIGGER_ON_VALUE) ? true : false; }; this.shouldGrab = function () { @@ -409,11 +409,11 @@ Script.include("/~/system/libraries/controllers.js"); this.shouldCancel = function () { // Kill condition : Off hand is <= 15% trigger pull. - return (_this.getOffHandTrigger() <= TRIGGER_OFF_VALUE) ? true : false; + return (_this.getDominantTrigger() <= TRIGGER_OFF_VALUE) ? true : false; }; this.shouldManipulateTarget = function () { - return (_this.getDominantTrigger() > TRIGGER_ON_VALUE) ? true : false; + return (_this.getOffHandTrigger() > TRIGGER_ON_VALUE) ? true : false; }; @@ -486,7 +486,7 @@ Script.include("/~/system/libraries/controllers.js"); }; this.isReady = function (controllerData) { - if (HMD.active && this.hand === this.getOffHand()) { + if (HMD.active && this.hand === this.getDominantHand()) { if (this.notPointingAtEntity(controllerData)) { return makeRunningValues(false, [], []); } diff --git a/scripts/system/controllers/controllerModules/teleport.js b/scripts/system/controllers/controllerModules/teleport.js index 9dcb456541..cd04dc9fd7 100644 --- a/scripts/system/controllers/controllerModules/teleport.js +++ b/scripts/system/controllers/controllerModules/teleport.js @@ -718,7 +718,7 @@ Script.include("/~/system/libraries/controllers.js"); } this.showReticle = function () { - return (_this.getOffhandY() > TELEPORT_DEADZONE) ? true : false; + return (_this.getDominantY() > TELEPORT_DEADZONE) ? true : false; }; this.shouldTeleport = function () { @@ -727,7 +727,7 @@ Script.include("/~/system/libraries/controllers.js"); this.shouldCancel = function () { //return (_this.getDominantY() < -TELEPORT_DEADZONE || _this.getOffhandY() < -TELEPORT_DEADZONE) ? true : false; - return (_this.getOffhandY() <= TELEPORT_DEADZONE) ? true : false; + return (_this.getDominantY() <= TELEPORT_DEADZONE) ? true : false; }; this.parameters = makeDispatcherModuleParameters( @@ -746,7 +746,7 @@ Script.include("/~/system/libraries/controllers.js"); } var otherModule = this.getOtherModule(); - if (!this.disabled && this.showReticle() && !otherModule.active && this.hand === this.getOffHand()) { + if (!this.disabled && this.showReticle() && !otherModule.active && this.hand === this.getDominantHand()) { this.active = true; this.enterTeleport(); return makeRunningValues(true, [], []); From 1ec887ffc2b63b6584a752affdd31e667aafbcb3 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Wed, 27 Feb 2019 10:51:38 -0800 Subject: [PATCH 045/158] Fix teleportation play area indicator not hiding on cancel. --- scripts/system/controllers/controllerModules/teleport.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/controllerModules/teleport.js b/scripts/system/controllers/controllerModules/teleport.js index cd04dc9fd7..5a51773930 100644 --- a/scripts/system/controllers/controllerModules/teleport.js +++ b/scripts/system/controllers/controllerModules/teleport.js @@ -847,8 +847,8 @@ Script.include("/~/system/libraries/controllers.js"); }; this.disableLasers = function() { - _this.setPlayAreaVisible(false, null, true); - _this.setTeleportVisible(false, null, true); + _this.setPlayAreaVisible(false, null, false); + _this.setTeleportVisible(false, null, false); Pointers.disablePointer(_this.teleportParabolaHandVisuals); Pointers.disablePointer(_this.teleportParabolaHandCollisions); Pointers.disablePointer(_this.teleportParabolaHeadVisuals); From 3a5698236b9b3f2435b541534f6d8e5f236c06d0 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Wed, 27 Feb 2019 10:57:35 -0800 Subject: [PATCH 046/158] Swap FarGrab from superpower to alternative version from PR#15043 --- .../controllerModules/farGrabEntity.js | 225 ++++++------------ 1 file changed, 71 insertions(+), 154 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index 600f9a2772..55ef4dd922 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -48,7 +48,6 @@ Script.include("/~/system/libraries/controllers.js"); } function FarGrabEntity(hand) { - var _this = this; this.hand = hand; this.grabbing = false; this.targetEntityID = null; @@ -63,6 +62,14 @@ Script.include("/~/system/libraries/controllers.js"); this.reticleMaxY = 0; this.endedGrab = 0; this.MIN_HAPTIC_PULSE_INTERVAL = 500; // ms + this.disabled = false; + var _this = this; + this.leftTrigger = 0.0; + this.rightTrigger = 0.0; + this.initialControllerRotation = Quat.IDENTITY; + this.currentControllerRotation = Quat.IDENTITY; + this.manipulating = false; + this.wasManipulating = false; var FAR_GRAB_JOINTS = [65527, 65528]; // FARGRAB_LEFTHAND_INDEX, FARGRAB_RIGHTHAND_INDEX @@ -78,6 +85,46 @@ Script.include("/~/system/libraries/controllers.js"); 100, makeLaserParams(this.hand, false)); + //enableDispatcherModule("LeftFarGrabEntity", leftFarGrabEntity); + //enableDispatcherModule("RightFarGrabEntity", rightFarGrabEntity); + + this.getOtherModule = function () { + // Used to fetch other module. + return getEnabledModuleByName(this.hand === RIGHT_HAND ? ("LeftFarGrabEntity") : ("RightFarGrabEntity")); + }; + + this.getTargetRotation = function () { + if (this.targetIsNull()) { + return null; + } else { + var props = Entities.getEntityProperties(this.targetEntityID, ["rotation"]); + return props.rotation; + } + }; + + this.getOffhand = function () { + return (this.hand === RIGHT_HAND ? LEFT_HAND : RIGHT_HAND); + } + + this.getOffhandTrigger = function () { + return (_this.hand === RIGHT_HAND ? _this.leftTrigger : _this.rightTrigger); + } + + this.shouldManipulateTarget = function () { + return (_this.getOffhandTrigger() > TRIGGER_ON_VALUE) ? true : false; + }; + + this.calculateEntityRotationManipulation = function (controllerRotation) { + return Quat.multiply(controllerRotation, Quat.inverse(this.initialControllerRotation)); + }; + + this.setJointTranslation = function (newTargetPosLocal) { + MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], newTargetPosLocal); + }; + + this.setJointRotation = function (newTargetRotLocal) { + MyAvatar.setJointRotation(FAR_GRAB_JOINTS[this.hand], newTargetRotLocal); + }; this.handToController = function () { return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; @@ -111,7 +158,6 @@ Script.include("/~/system/libraries/controllers.js"); this.currentObjectPosition = targetProps.position; this.currentObjectRotation = targetProps.rotation; this.currentObjectTime = now; - //this.initialEntityRotation = targetProps.rotation; // World frame. this.grabRadius = this.grabbedDistance; this.grabRadialVelocity = 0.0; @@ -145,10 +191,8 @@ Script.include("/~/system/libraries/controllers.js"); Messages.sendLocalMessage('Hifi-unhighlight-entity', JSON.stringify(message)); - //MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], newTargetPosLocal); - - var newTargetPosLocal = MyAvatar.worldToJointPoint(targetProps.position); // World frame. - var newTargetRotLocal = targetProps.rotation; // World frame. + var newTargetPosLocal = MyAvatar.worldToJointPoint(targetProps.position); + var newTargetRotLocal = targetProps.rotation; this.setJointTranslation(newTargetPosLocal); this.setJointRotation(newTargetRotLocal); @@ -234,18 +278,23 @@ Script.include("/~/system/libraries/controllers.js"); newTargetPosition = Vec3.sum(newTargetPosition, worldControllerPosition); newTargetPosition = Vec3.sum(newTargetPosition, this.offsetPosition); - // MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], MyAvatar.worldToJointPoint(newTargetPosition)); - - // var newTargetPosLocal = Mat4.transformPoint(MyAvatar.getSensorToWorldMatrix(), newTargetPosition); var newTargetPosLocal = MyAvatar.worldToJointPoint(newTargetPosition); + + // This block handles the user's ability to rotate the object they're FarGrabbing if (this.shouldManipulateTarget()) { - var pose = Controller.getPoseValue((this.getDominantHand() ? Controller.Standard.LeftHand : Controller.Standard.RightHand)); + // Get the pose of the controller that is not grabbing. + var pose = Controller.getPoseValue((this.getOffhand() ? Controller.Standard.RightHand : Controller.Standard.LeftHand)); if (pose.valid) { + // If we weren't manipulating the object yet, initialize the entity's original position. if (!this.manipulating) { + // This will only be triggered if we've let go of the off-hand trigger and pulled it again without ending a grab. + // Need to poll the entity's rotation again here. if (!this.wasManipulating) { - this.initialEntityRotation = this.getTargetRotation(); // Worldframe. + this.initialEntityRotation = this.getTargetRotation(); } - this.initialControllerRotation = Quat.multiply(pose.rotation, MyAvatar.orientation); // Worldframe. + // Save the original controller orientation, we only care about the delta between this rotation and wherever + // the controller rotates, so that we can apply it to the entity's rotation. + this.initialControllerRotation = Quat.multiply(pose.rotation, MyAvatar.orientation); this.manipulating = true; } } @@ -292,6 +341,8 @@ Script.include("/~/system/libraries/controllers.js"); this.targetEntityID = null; this.manipulating = false; this.wasManipulating = false; + var otherModule = this.getOtherModule(); + otherModule.disabled = false; }; this.updateRecommendedArea = function () { @@ -353,148 +404,17 @@ Script.include("/~/system/libraries/controllers.js"); return null; }; - var mappingName = "FarGrab-Mapping-" + Math.random(); - var grabMapping; - - this.setup = function () { - grabMapping = Controller.newMapping(mappingName); - grabMapping.from(Controller.Standard.LT).peek().to(_this.getLeftTrigger); - grabMapping.from(Controller.Standard.RT).peek().to(_this.getRightTrigger); - Controller.enableMapping(mappingName); - }; - - this.cleanup = function () { - grabMapping.disable(); - }; - - this.initialControllerRotation = Quat.IDENTITY; - this.initialEntityRotation = Quat.IDENTITY; - this.manipulating = false; - this.wasManipulating = false; - - this.leftTrigger = 0.0; - this.rightTrigger = 0.0; - - this.getDominantHand = function () { - return (MyAvatar.getDominantHand() === "left") ? LEFT_HAND : RIGHT_HAND; - }; - - this.getOffHand = function () { - return (MyAvatar.getDominantHand() === "left") ? RIGHT_HAND : LEFT_HAND; - }; - - this.getLeftTrigger = function (value) { - _this.leftTrigger = value; - }; - - this.getRightTrigger = function (value) { - _this.rightTrigger = value; - }; - - this.getDominantTrigger = function () { - return (MyAvatar.getDominantHand() === "left") ? (_this.leftTrigger) : (_this.rightTrigger); - }; - - this.getOffHandTrigger = function () { - return (MyAvatar.getDominantHand() === "left") ? (_this.rightTrigger) : (_this.leftTrigger); - }; - - this.shouldShowLaser = function () { - return (_this.getDominantTrigger() > TRIGGER_ON_VALUE) ? true : false; - }; - - this.shouldGrab = function () { - return (_this.getDominantTrigger() > TRIGGER_ON_VALUE && _this.getOffHandTrigger() > TRIGGER_ON_VALUE) ? true : false; - }; - - this.shouldCancel = function () { - // Kill condition : Off hand is <= 15% trigger pull. - return (_this.getDominantTrigger() <= TRIGGER_OFF_VALUE) ? true : false; - }; - - this.shouldManipulateTarget = function () { - return (_this.getOffHandTrigger() > TRIGGER_ON_VALUE) ? true : false; - }; - - - this.getTargetPosition = function () { - if (this.targetIsNull()) { - return null; - } else { - var props = Entities.getEntityProperties(this.targetEntityID, ["position"]); - return props.position; - } - }; - - this.getTargetRotation = function () { - if (this.targetIsNull()) { - return null; - } else { - var props = Entities.getEntityProperties(this.targetEntityID, ["rotation"]); - return props.rotation; - } - }; - - this.getTargetLocalPosition = function () { - if (this.targetIsNull()) { - return null; - } else { - var props = Entities.getEntityProperties(this.targetEntityID, ["localPosition"]); - return props.localPosition; - } - }; - - this.getTargetLocalRotation = function () { - if (this.targetIsNull()) { - return null; - } else { - var props = Entities.getEntityProperties(this.targetEntityID, ["localRotation"]); - return props.localRotation; - } - }; - - this.setTargetPosition = function (newPos) { - if (this.targetIsNull()) { - print("Fargrab Error: No target to edit position."); - return; - } else { - var props = { position: newPos }; - Entities.editEntity(this.targetEntityID, props); - } - }; - - this.setTargetRotation = function (newRot) { - if (this.targetIsNull()) { - print("Fargrab Error: No target to edit rotation."); - return; - } else { - var props = { rotation: newRot }; - Entities.editEntity(this.targetEntityID, props); - } - }; - - this.calculateEntityRotationManipulation = function (controllerRotation) { - return Quat.multiply(controllerRotation, Quat.inverse(this.initialControllerRotation)); - }; - - this.setJointTranslation = function (newTargetPosLocal) { - MyAvatar.setJointTranslation(FAR_GRAB_JOINTS[this.hand], newTargetPosLocal); - }; - - this.setJointRotation = function (newTargetRotLocal) { - MyAvatar.setJointRotation(FAR_GRAB_JOINTS[this.hand], newTargetRotLocal); - }; - this.isReady = function (controllerData) { - if (HMD.active && this.hand === this.getDominantHand()) { + if (HMD.active) { if (this.notPointingAtEntity(controllerData)) { return makeRunningValues(false, [], []); } this.distanceHolding = false; - //if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) { - if (this.shouldShowLaser()) { + if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE && !this.disabled) { + var otherModule = this.getOtherModule(); + otherModule.disabled = true; return makeRunningValues(true, [], []); } else { this.destroyContextOverlay(); @@ -504,8 +424,9 @@ Script.include("/~/system/libraries/controllers.js"); }; this.run = function (controllerData) { - //if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || this.targetIsNull()) { - if (this.shouldCancel() || this.targetIsNull()) { + this.leftTrigger = controllerData.triggerValues[LEFT_HAND]; + this.rightTrigger = controllerData.triggerValues[RIGHT_HAND]; + if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || this.targetIsNull()) { this.endFarGrabEntity(controllerData); return makeRunningValues(false, [], []); } @@ -552,7 +473,7 @@ Script.include("/~/system/libraries/controllers.js"); var rayPickInfo = controllerData.rayPicks[this.hand]; if (rayPickInfo.type === Picks.INTERSECTED_ENTITY) { - if (this.shouldGrab()) { + if (controllerData.triggerClicks[this.hand]) { var entityID = rayPickInfo.objectID; var targetProps = Entities.getEntityProperties(entityID, DISPATCHER_PROPERTIES); if (targetProps.href !== "") { @@ -654,15 +575,11 @@ Script.include("/~/system/libraries/controllers.js"); var leftFarGrabEntity = new FarGrabEntity(LEFT_HAND); var rightFarGrabEntity = new FarGrabEntity(RIGHT_HAND); - leftFarGrabEntity.setup(); - rightFarGrabEntity.setup(); enableDispatcherModule("LeftFarGrabEntity", leftFarGrabEntity); enableDispatcherModule("RightFarGrabEntity", rightFarGrabEntity); function cleanup() { - leftFarGrabEntity.cleanup(); - rightFarGrabEntity.cleanup(); disableDispatcherModule("LeftFarGrabEntity"); disableDispatcherModule("RightFarGrabEntity"); } From 79b7a3d28de7894ce3f29be4abcda89d6a784920 Mon Sep 17 00:00:00 2001 From: luiscuenca Date: Mon, 4 Mar 2019 13:15:15 -0700 Subject: [PATCH 047/158] Apply kdop computation after reading the joint rotation offsets --- libraries/fbx/src/FBXSerializer.cpp | 57 +------------------ libraries/hfm/src/hfm/HFM.cpp | 52 +++++++++++++++++ libraries/hfm/src/hfm/HFM.h | 4 ++ .../model-baker/src/model-baker/Baker.cpp | 1 + libraries/physics/src/CharacterController.cpp | 2 +- 5 files changed, 61 insertions(+), 55 deletions(-) diff --git a/libraries/fbx/src/FBXSerializer.cpp b/libraries/fbx/src/FBXSerializer.cpp index 9e7f422b40..43ff8ee459 100644 --- a/libraries/fbx/src/FBXSerializer.cpp +++ b/libraries/fbx/src/FBXSerializer.cpp @@ -301,8 +301,6 @@ QString getString(const QVariant& value) { return list.isEmpty() ? value.toString() : list.at(0).toString(); } -typedef std::vector ShapeVertices; - class AnimationCurve { public: QVector values; @@ -1319,8 +1317,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr } // NOTE: shapeVertices are in joint-frame - std::vector shapeVertices; - shapeVertices.resize(std::max(1, hfmModel.joints.size()) ); + hfmModel.shapeVertices.resize(std::max(1, hfmModel.joints.size()) ); hfmModel.bindExtents.reset(); hfmModel.meshExtents.reset(); @@ -1511,7 +1508,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr } glm::mat4 meshToJoint = glm::inverse(joint.bindTransform) * modelTransform; - ShapeVertices& points = shapeVertices.at(jointIndex); + ShapeVertices& points = hfmModel.shapeVertices.at(jointIndex); for (int j = 0; j < cluster.indices.size(); j++) { int oldIndex = cluster.indices.at(j); @@ -1580,7 +1577,7 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr // transform cluster vertices to joint-frame and save for later glm::mat4 meshToJoint = glm::inverse(joint.bindTransform) * modelTransform; - ShapeVertices& points = shapeVertices.at(jointIndex); + ShapeVertices& points = hfmModel.shapeVertices.at(jointIndex); foreach (const glm::vec3& vertex, extracted.mesh.vertices) { const glm::mat4 vertexTransform = meshToJoint * glm::translate(vertex); points.push_back(extractTranslation(vertexTransform)); @@ -1600,54 +1597,6 @@ HFMModel* FBXSerializer::extractHFMModel(const QVariantHash& mapping, const QStr meshIDsToMeshIndices.insert(it.key(), meshIndex); } - const float INV_SQRT_3 = 0.57735026918f; - ShapeVertices cardinalDirections = { - Vectors::UNIT_X, - Vectors::UNIT_Y, - Vectors::UNIT_Z, - glm::vec3(INV_SQRT_3, INV_SQRT_3, INV_SQRT_3), - glm::vec3(INV_SQRT_3, -INV_SQRT_3, INV_SQRT_3), - glm::vec3(INV_SQRT_3, INV_SQRT_3, -INV_SQRT_3), - glm::vec3(INV_SQRT_3, -INV_SQRT_3, -INV_SQRT_3) - }; - - // now that all joints have been scanned compute a k-Dop bounding volume of mesh - for (int i = 0; i < hfmModel.joints.size(); ++i) { - HFMJoint& joint = hfmModel.joints[i]; - - // NOTE: points are in joint-frame - ShapeVertices& points = shapeVertices.at(i); - if (points.size() > 0) { - // compute average point - glm::vec3 avgPoint = glm::vec3(0.0f); - for (uint32_t j = 0; j < points.size(); ++j) { - avgPoint += points[j]; - } - avgPoint /= (float)points.size(); - joint.shapeInfo.avgPoint = avgPoint; - - // compute a k-Dop bounding volume - for (uint32_t j = 0; j < cardinalDirections.size(); ++j) { - float maxDot = -FLT_MAX; - float minDot = FLT_MIN; - for (uint32_t k = 0; k < points.size(); ++k) { - float kDot = glm::dot(cardinalDirections[j], points[k] - avgPoint); - if (kDot > maxDot) { - maxDot = kDot; - } - if (kDot < minDot) { - minDot = kDot; - } - } - joint.shapeInfo.points.push_back(avgPoint + maxDot * cardinalDirections[j]); - joint.shapeInfo.dots.push_back(maxDot); - joint.shapeInfo.points.push_back(avgPoint + minDot * cardinalDirections[j]); - joint.shapeInfo.dots.push_back(-minDot); - } - generateBoundryLinesForDop14(joint.shapeInfo.dots, joint.shapeInfo.avgPoint, joint.shapeInfo.debugLines); - } - } - // attempt to map any meshes to a named model for (QHash::const_iterator m = meshIDsToMeshIndices.constBegin(); m != meshIDsToMeshIndices.constEnd(); m++) { diff --git a/libraries/hfm/src/hfm/HFM.cpp b/libraries/hfm/src/hfm/HFM.cpp index f0fc97c5c7..e930f30d1a 100644 --- a/libraries/hfm/src/hfm/HFM.cpp +++ b/libraries/hfm/src/hfm/HFM.cpp @@ -154,3 +154,55 @@ QString HFMModel::getModelNameOfMesh(int meshIndex) const { } return QString(); } + +void HFMModel::computeKdops() { + const float INV_SQRT_3 = 0.57735026918f; + ShapeVertices cardinalDirections = { + Vectors::UNIT_X, + Vectors::UNIT_Y, + Vectors::UNIT_Z, + glm::vec3(INV_SQRT_3, INV_SQRT_3, INV_SQRT_3), + glm::vec3(INV_SQRT_3, -INV_SQRT_3, INV_SQRT_3), + glm::vec3(INV_SQRT_3, INV_SQRT_3, -INV_SQRT_3), + glm::vec3(INV_SQRT_3, -INV_SQRT_3, -INV_SQRT_3) + }; + + // now that all joints have been scanned compute a k-Dop bounding volume of mesh + for (int i = 0; i < joints.size(); ++i) { + HFMJoint& joint = joints[i]; + + // NOTE: points are in joint-frame + ShapeVertices& points = shapeVertices.at(i); + glm::quat rotOffset = jointRotationOffsets.contains(i) ? glm::inverse(jointRotationOffsets[i]) : quat(); + if (points.size() > 0) { + // compute average point + glm::vec3 avgPoint = glm::vec3(0.0f); + for (uint32_t j = 0; j < points.size(); ++j) { + points[j] = rotOffset * points[j]; + avgPoint += points[j]; + } + avgPoint /= (float)points.size(); + joint.shapeInfo.avgPoint = avgPoint; + + // compute a k-Dop bounding volume + for (uint32_t j = 0; j < cardinalDirections.size(); ++j) { + float maxDot = -FLT_MAX; + float minDot = FLT_MIN; + for (uint32_t k = 0; k < points.size(); ++k) { + float kDot = glm::dot(cardinalDirections[j], points[k] - avgPoint); + if (kDot > maxDot) { + maxDot = kDot; + } + if (kDot < minDot) { + minDot = kDot; + } + } + joint.shapeInfo.points.push_back(avgPoint + maxDot * cardinalDirections[j]); + joint.shapeInfo.dots.push_back(maxDot); + joint.shapeInfo.points.push_back(avgPoint + minDot * cardinalDirections[j]); + joint.shapeInfo.dots.push_back(-minDot); + } + generateBoundryLinesForDop14(joint.shapeInfo.dots, joint.shapeInfo.avgPoint, joint.shapeInfo.debugLines); + } + } +} diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index 9f3de3302c..c9df45cde3 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -53,6 +53,8 @@ using ColorType = glm::vec3; const int MAX_NUM_PIXELS_FOR_FBX_TEXTURE = 2048 * 2048; +using ShapeVertices = std::vector; + // High Fidelity Model namespace namespace hfm { @@ -319,6 +321,8 @@ public: QList blendshapeChannelNames; QMap jointRotationOffsets; + std::vector shapeVertices; + void computeKdops(); }; }; diff --git a/libraries/model-baker/src/model-baker/Baker.cpp b/libraries/model-baker/src/model-baker/Baker.cpp index dfb18eef86..ab41914d08 100644 --- a/libraries/model-baker/src/model-baker/Baker.cpp +++ b/libraries/model-baker/src/model-baker/Baker.cpp @@ -111,6 +111,7 @@ namespace baker { hfmModelOut->joints = QVector::fromStdVector(input.get2()); hfmModelOut->jointRotationOffsets = input.get3(); hfmModelOut->jointIndices = input.get4(); + hfmModelOut->computeKdops(); output = hfmModelOut; } }; diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 66ce5f32bf..02dc6e3b4d 100755 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -436,7 +436,7 @@ void CharacterController::setLocalBoundingBox(const glm::vec3& minCorner, const float z = scale.z; float radius = 0.5f * sqrtf(0.5f * (x * x + z * z)); float halfHeight = 0.5f * scale.y - radius; - float MIN_HALF_HEIGHT = 0.1f; + float MIN_HALF_HEIGHT = 0.0f; if (halfHeight < MIN_HALF_HEIGHT) { halfHeight = MIN_HALF_HEIGHT; } From cbd841a14de18549d5ddabc68ef8ab28080334f5 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 11 Mar 2019 16:22:48 -0700 Subject: [PATCH 048/158] Update gearing system. --- interface/src/avatar/MyAvatar.cpp | 89 ++++++++++++++++++++++---- interface/src/avatar/MyAvatar.h | 1 + libraries/shared/src/AvatarConstants.h | 5 ++ 3 files changed, 81 insertions(+), 14 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 14e9f1a987..9c1c5b49c9 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3312,6 +3312,27 @@ void MyAvatar::updateOrientation(float deltaTime) { // return scaledSpeed; //} +float MyAvatar::calculateGearedSpeed(const float driveKey) { + if (driveKey > getDriveGear5()) { + return 1.0f; + } + else if (driveKey > getDriveGear4()) { + return 0.8f; + } + else if (driveKey > getDriveGear3()) { + return 0.6f; + } + else if (driveKey > getDriveGear2()) { + return 0.4f; + } + else if (driveKey > getDriveGear1()) { + return 0.2f; + } + else { + return 0.0f; + } +} + glm::vec3 MyAvatar::scaleMotorSpeed(const glm::vec3 forward, const glm::vec3 right) { float stickFullOn = 0.95f; auto zSpeed = getDriveKey(TRANSLATE_Z); @@ -3330,8 +3351,8 @@ glm::vec3 MyAvatar::scaleMotorSpeed(const glm::vec3 forward, const glm::vec3 rig } case CONTROLS_ANALOG: if (zSpeed || xSpeed) { - glm::vec3 scaledForward = getSensorToWorldScale() * zSpeed * ((zSpeed >= stickFullOn) ? getSprintSpeed() : getWalkSpeed()) * forward; - glm::vec3 scaledRight = getSensorToWorldScale() * xSpeed * ((xSpeed > stickFullOn) ? getSprintSpeed() : getWalkSpeed()) * right; + glm::vec3 scaledForward = getSensorToWorldScale() * calculateGearedSpeed(zSpeed) * ((zSpeed >= stickFullOn) ? getSprintSpeed() : getWalkSpeed()) * forward; + glm::vec3 scaledRight = getSensorToWorldScale() * calculateGearedSpeed(xSpeed) * ((xSpeed > stickFullOn) ? getSprintSpeed() : getWalkSpeed()) * right; direction = scaledForward + scaledRight; return direction; } else { @@ -3339,8 +3360,8 @@ glm::vec3 MyAvatar::scaleMotorSpeed(const glm::vec3 forward, const glm::vec3 rig } case CONTROLS_ANALOG_PLUS: if (zSpeed || xSpeed) { - glm::vec3 scaledForward = getSensorToWorldScale() * zSpeed * ((zSpeed >= stickFullOn) ? getSprintSpeed() : getWalkSpeed()) * forward; - glm::vec3 scaledRight = getSensorToWorldScale() * xSpeed * ((xSpeed > stickFullOn) ? getSprintSpeed() : getWalkSpeed()) * right; + glm::vec3 scaledForward = getSensorToWorldScale() * calculateGearedSpeed(zSpeed) * ((zSpeed >= stickFullOn) ? getSprintSpeed() : getWalkSpeed()) * forward; + glm::vec3 scaledRight = getSensorToWorldScale() * calculateGearedSpeed(xSpeed) * ((xSpeed > stickFullOn) ? getSprintSpeed() : getWalkSpeed()) * right; direction = scaledForward + scaledRight; return direction; } else { @@ -3987,11 +4008,19 @@ void MyAvatar::setDriveGear1(float shiftPoint) { return; } if (shiftPoint > 1.0 || shiftPoint < 0) return; - _driveGear1 = (shiftPoint <= _driveGear2) ? shiftPoint : _driveGear1; + _driveGear1 = (shiftPoint < _driveGear2) ? shiftPoint : _driveGear1; } float MyAvatar::getDriveGear1() { - return _driveGear1; + switch (_controlSchemeIndex) { + case CONTROLS_ANALOG: + return ANALOG_AVATAR_GEAR_1; + case CONTROLS_ANALOG_PLUS: + return _driveGear1; + case CONTROLS_DEFAULT: + default: + return 1.0f; + } } void MyAvatar::setDriveGear2(float shiftPoint) { @@ -4000,11 +4029,19 @@ void MyAvatar::setDriveGear2(float shiftPoint) { return; } if (shiftPoint > 1.0 || shiftPoint < 0) return; - _driveGear2 = (shiftPoint <= _driveGear3 && shiftPoint >= _driveGear1) ? shiftPoint : _driveGear2; + _driveGear2 = (shiftPoint < _driveGear3 && shiftPoint >= _driveGear1) ? shiftPoint : _driveGear2; } float MyAvatar::getDriveGear2() { - return _driveGear2; + switch (_controlSchemeIndex) { + case CONTROLS_ANALOG: + return ANALOG_AVATAR_GEAR_2; + case CONTROLS_ANALOG_PLUS: + return _driveGear2; + case CONTROLS_DEFAULT: + default: + return 1.0f; + } } void MyAvatar::setDriveGear3(float shiftPoint) { @@ -4013,11 +4050,19 @@ void MyAvatar::setDriveGear3(float shiftPoint) { return; } if (shiftPoint > 1.0 || shiftPoint < 0) return; - _driveGear3 = (shiftPoint <= _driveGear4 && shiftPoint >= _driveGear2) ? shiftPoint : _driveGear3; + _driveGear3 = (shiftPoint < _driveGear4 && shiftPoint >= _driveGear2) ? shiftPoint : _driveGear3; } float MyAvatar::getDriveGear3() { - return _driveGear3; + switch (_controlSchemeIndex) { + case CONTROLS_ANALOG: + return ANALOG_AVATAR_GEAR_3; + case CONTROLS_ANALOG_PLUS: + return _driveGear3; + case CONTROLS_DEFAULT: + default: + return 1.0f; + } } void MyAvatar::setDriveGear4(float shiftPoint) { @@ -4026,11 +4071,19 @@ void MyAvatar::setDriveGear4(float shiftPoint) { return; } if (shiftPoint > 1.0 || shiftPoint < 0) return; - _driveGear4 = (shiftPoint <= _driveGear5 && shiftPoint >= _driveGear3) ? shiftPoint : _driveGear4; + _driveGear4 = (shiftPoint < _driveGear5 && shiftPoint >= _driveGear3) ? shiftPoint : _driveGear4; } float MyAvatar::getDriveGear4() { - return _driveGear4; + switch (_controlSchemeIndex) { + case CONTROLS_ANALOG: + return ANALOG_AVATAR_GEAR_4; + case CONTROLS_ANALOG_PLUS: + return _driveGear4; + case CONTROLS_DEFAULT: + default: + return 1.0f; + } } void MyAvatar::setDriveGear5(float shiftPoint) { @@ -4039,11 +4092,19 @@ void MyAvatar::setDriveGear5(float shiftPoint) { return; } if (shiftPoint > 1.0 || shiftPoint < 0) return; - _driveGear5 = (shiftPoint >= _driveGear4) ? shiftPoint : _driveGear5; + _driveGear5 = (shiftPoint > _driveGear4) ? shiftPoint : _driveGear5; } float MyAvatar::getDriveGear5() { - return _driveGear5; + switch (_controlSchemeIndex) { + case CONTROLS_ANALOG: + return ANALOG_AVATAR_GEAR_5; + case CONTROLS_ANALOG_PLUS: + return _driveGear5; + case CONTROLS_DEFAULT: + default: + return 1.0f; + } } bool MyAvatar::getFlyingHMDPref() { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index cee0a33fb4..0da2171ca3 100755 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1877,6 +1877,7 @@ private: // private methods void updateOrientation(float deltaTime); glm::vec3 calculateScaledDirection(); + float calculateGearedSpeed(const float driveKey); glm::vec3 scaleMotorSpeed(const glm::vec3 forward, const glm::vec3 right); void updateActionMotor(float deltaTime); void updatePosition(float deltaTime); diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index 1518497961..a150eb34da 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -76,6 +76,11 @@ const float ANALOG_AVATAR_MAX_WALKING_SPEED = 2.6f; // meters / second const float ANALOG_AVATAR_MAX_WALKING_BACKWARD_SPEED = 2.2f; // meters / second const float ANALOG_AVATAR_MAX_FLYING_SPEED = 30.0f; // meters / second const float ANALOG_AVATAR_MAX_SPRINT_SPEED = 3.0f; // meters / second +const float ANALOG_AVATAR_GEAR_1 = 0.2f; // meters / second +const float ANALOG_AVATAR_GEAR_2 = 0.4f; // meters / second +const float ANALOG_AVATAR_GEAR_3 = 0.6f; // meters / second +const float ANALOG_AVATAR_GEAR_4 = 0.8f; // meters / second +const float ANALOG_AVATAR_GEAR_5 = 1.0f; // meters / second const float ANALOG_PLUS_AVATAR_MAX_WALKING_SPEED = 3.3f; // meters / second const float ANALOG_PLUS_AVATAR_MAX_WALKING_BACKWARD_SPEED = 2.42f; // meters / second From 6ce955d915a4fe5ba2c3215d017e1fb5716b8528 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Mon, 11 Mar 2019 18:19:43 -0700 Subject: [PATCH 049/158] Fix hand-relative movement after hand dominance notion swap. --- interface/src/avatar/MyAvatar.cpp | 52 +++++++++++-------------------- interface/src/avatar/MyAvatar.h | 2 +- 2 files changed, 20 insertions(+), 34 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index dfeae14cca..17f90d8542 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2527,8 +2527,8 @@ controller::Pose MyAvatar::getControllerPoseInAvatarFrame(controller::Action act } } -glm::quat MyAvatar::getDominantHandRotation() const { - auto hand = (getDominantHand() == DOMINANT_RIGHT_HAND) ? controller::Action::RIGHT_HAND : controller::Action::LEFT_HAND; +glm::quat MyAvatar::getOffHandRotation() const { + auto hand = (getDominantHand() == DOMINANT_RIGHT_HAND) ? controller::Action::LEFT_HAND : controller::Action::RIGHT_HAND; auto pose = getControllerPoseInAvatarFrame(hand); return pose.rotation; } @@ -3317,23 +3317,25 @@ void MyAvatar::updateOrientation(float deltaTime) { //} float MyAvatar::calculateGearedSpeed(const float driveKey) { - if (driveKey > getDriveGear5()) { - return 1.0f; + float absDriveKey = abs(driveKey); + float sign = (driveKey < 0.0f) ? -1.0f : 1.0f; + if (absDriveKey > getDriveGear5()) { + return sign * 1.0f; } - else if (driveKey > getDriveGear4()) { - return 0.8f; + else if (absDriveKey > getDriveGear4()) { + return sign * 0.8f; } - else if (driveKey > getDriveGear3()) { - return 0.6f; + else if (absDriveKey > getDriveGear3()) { + return sign * 0.6f; } - else if (driveKey > getDriveGear2()) { - return 0.4f; + else if (absDriveKey > getDriveGear2()) { + return sign * 0.4f; } - else if (driveKey > getDriveGear1()) { - return 0.2f; + else if (absDriveKey > getDriveGear1()) { + return sign * 0.2f; } else { - return 0.0f; + return sign * 0.0f; } } @@ -3385,21 +3387,19 @@ glm::vec3 MyAvatar::calculateScaledDirection(){ glm::vec3 forward, right; if (qApp->isHMDMode()) { - auto handRotation = getDominantHandRotation(); + auto handRotation = getOffHandRotation(); glm::vec3 controllerForward(0.0f, 1.0f, 0.0f); - glm::vec3 controllerRight(0.0f, 0.0f, (getDominantHand() == DOMINANT_RIGHT_HAND ? -1.0f : 1.0f)); - // Do shit here. + glm::vec3 controllerRight(0.0f, 0.0f, (getDominantHand() == DOMINANT_RIGHT_HAND ? 1.0f : -1.0f)); switch (getMovementReference()) { case MOVEMENT_HAND_RELATIVE: forward = (handRotation * controllerForward); right = (handRotation * controllerRight); break; case MOVEMENT_HAND_RELATIVE_LEVELED: - handRotation = cancelOutRoll(handRotation); forward = (handRotation * controllerForward); - //forward = glm::normalize(forward - (glm::dot(forward, Vectors::UNIT_Y) * Vectors::UNIT_Y)); + forward = glm::normalize(forward - (glm::dot(forward, Vectors::UNIT_Y) * Vectors::UNIT_Y)); right = (handRotation * controllerRight); - //right = glm::normalize(right - (glm::dot(right, Vectors::UNIT_Y) * Vectors::UNIT_Y)); + right = glm::normalize(right - (glm::dot(right, Vectors::UNIT_Y) * Vectors::UNIT_Y)); break; case MOVEMENT_HMD_RELATIVE: default: @@ -3411,20 +3411,6 @@ glm::vec3 MyAvatar::calculateScaledDirection(){ right = IDENTITY_RIGHT; } - if (getMovementReference() && qApp->isHMDMode()) { - // Here we have to get the rotation of the dominant hand and apply that to the direction vector. - // If we're on the right hand, we have to flip the x-axis. - auto handRotation = getDominantHandRotation(); - glm::vec3 controllerForward(0.0f, 1.0f, 0.0f); - glm::vec3 controllerRight(0.0f, 0.0f, (getDominantHand() == DOMINANT_RIGHT_HAND ? -1.0f : 1.0f)); - forward = (handRotation * controllerForward); - right = (handRotation * controllerRight); - } - else { - forward = IDENTITY_FORWARD; - right = IDENTITY_RIGHT; - } - glm::vec3 direction = scaleMotorSpeed(forward, right); // RKNOTE: This may need to be changed later... diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 858a7d1c0b..4a248d27ae 100755 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -953,7 +953,7 @@ public: controller::Pose getControllerPoseInSensorFrame(controller::Action action) const; controller::Pose getControllerPoseInWorldFrame(controller::Action action) const; controller::Pose getControllerPoseInAvatarFrame(controller::Action action) const; - glm::quat getDominantHandRotation() const; + glm::quat getOffHandRotation() const; bool hasDriveInput() const; From 38fe22e4f749cf2d756a3d80d0a62b267c70c3f0 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Thu, 14 Mar 2019 16:27:40 -0700 Subject: [PATCH 050/158] Fix compiler error for Linux. --- interface/src/avatar/MyAvatar.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 17f90d8542..cc13e75a0f 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3996,7 +3996,7 @@ void MyAvatar::setDriveGear1(float shiftPoint) { QMetaObject::invokeMethod(this, "setDriveGear1", Q_ARG(float, shiftPoint)); return; } - if (shiftPoint > 1.0 || shiftPoint < 0) return; + if (shiftPoint > 1.0f || shiftPoint < 0.0f) return; _driveGear1 = (shiftPoint < _driveGear2) ? shiftPoint : _driveGear1; } @@ -4017,7 +4017,7 @@ void MyAvatar::setDriveGear2(float shiftPoint) { QMetaObject::invokeMethod(this, "setDriveGear2", Q_ARG(float, shiftPoint)); return; } - if (shiftPoint > 1.0 || shiftPoint < 0) return; + if (shiftPoint > 1.0f || shiftPoint < 0.0f) return; _driveGear2 = (shiftPoint < _driveGear3 && shiftPoint >= _driveGear1) ? shiftPoint : _driveGear2; } @@ -4038,7 +4038,7 @@ void MyAvatar::setDriveGear3(float shiftPoint) { QMetaObject::invokeMethod(this, "setDriveGear3", Q_ARG(float, shiftPoint)); return; } - if (shiftPoint > 1.0 || shiftPoint < 0) return; + if (shiftPoint > 1.0f || shiftPoint < 0.0f) return; _driveGear3 = (shiftPoint < _driveGear4 && shiftPoint >= _driveGear2) ? shiftPoint : _driveGear3; } @@ -4059,7 +4059,7 @@ void MyAvatar::setDriveGear4(float shiftPoint) { QMetaObject::invokeMethod(this, "setDriveGear4", Q_ARG(float, shiftPoint)); return; } - if (shiftPoint > 1.0 || shiftPoint < 0) return; + if (shiftPoint > 1.0f || shiftPoint < 0.0f) return; _driveGear4 = (shiftPoint < _driveGear5 && shiftPoint >= _driveGear3) ? shiftPoint : _driveGear4; } @@ -4080,7 +4080,7 @@ void MyAvatar::setDriveGear5(float shiftPoint) { QMetaObject::invokeMethod(this, "setDriveGear5", Q_ARG(float, shiftPoint)); return; } - if (shiftPoint > 1.0 || shiftPoint < 0) return; + if (shiftPoint > 1.0f || shiftPoint < 0.0f) return; _driveGear5 = (shiftPoint > _driveGear4) ? shiftPoint : _driveGear5; } From c9ade7ccb8ab2ce1ce5682bc796c9843dd1716bb Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Fri, 15 Mar 2019 16:09:01 -0700 Subject: [PATCH 051/158] Add grip to fargrab. --- .../controllers/controllerModules/farGrabEntity.js | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/scripts/system/controllers/controllerModules/farGrabEntity.js b/scripts/system/controllers/controllerModules/farGrabEntity.js index 953083302a..bde5f8a8a8 100644 --- a/scripts/system/controllers/controllerModules/farGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farGrabEntity.js @@ -64,8 +64,6 @@ Script.include("/~/system/libraries/controllers.js"); this.MIN_HAPTIC_PULSE_INTERVAL = 500; // ms this.disabled = false; var _this = this; - this.leftTrigger = 0.0; - this.rightTrigger = 0.0; this.initialControllerRotation = Quat.IDENTITY; this.currentControllerRotation = Quat.IDENTITY; this.manipulating = false; @@ -103,13 +101,9 @@ Script.include("/~/system/libraries/controllers.js"); return (this.hand === RIGHT_HAND ? LEFT_HAND : RIGHT_HAND); } - this.getOffhandTrigger = function () { - return (_this.hand === RIGHT_HAND ? _this.leftTrigger : _this.rightTrigger); - } - // Activation criteria for rotating a fargrabbed entity. If we're changing the mapping, this is where to do it. - this.shouldManipulateTarget = function () { - return (_this.getOffhandTrigger() > TRIGGER_ON_VALUE) ? true : false; + this.shouldManipulateTarget = function (controllerData) { + return (controllerData.triggerValues[this.getOffhand()] > TRIGGER_ON_VALUE || controllerdata.secondaryValues[this.getOffhand()] > TRIGGER_ON_VALUE) ? true : false; }; // Get the delta between the current rotation and where the controller was when manipulation started. @@ -284,7 +278,7 @@ Script.include("/~/system/libraries/controllers.js"); var newTargetPosLocal = MyAvatar.worldToJointPoint(newTargetPosition); // This block handles the user's ability to rotate the object they're FarGrabbing - if (this.shouldManipulateTarget()) { + if (this.shouldManipulateTarget(controllerData)) { // Get the pose of the controller that is not grabbing. var pose = Controller.getPoseValue((this.getOffhand() ? Controller.Standard.RightHand : Controller.Standard.LeftHand)); if (pose.valid) { @@ -430,8 +424,6 @@ Script.include("/~/system/libraries/controllers.js"); }; this.run = function (controllerData) { - this.leftTrigger = controllerData.triggerValues[LEFT_HAND]; - this.rightTrigger = controllerData.triggerValues[RIGHT_HAND]; if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || this.targetIsNull()) { this.endFarGrabEntity(controllerData); return makeRunningValues(false, [], []); From 5271d2b7c8707d728e48259849df0b12fdc985b5 Mon Sep 17 00:00:00 2001 From: ingerjm0 Date: Wed, 20 Mar 2019 10:13:53 -0700 Subject: [PATCH 052/158] JSDoc template updates for branding --- tools/jsdoc/config.json | 1 + tools/jsdoc/hifi-jsdoc-template/publish.js | 2 +- .../static/fonts/Cairo-Bold.ttf | Bin 170996 -> 0 bytes .../static/fonts/Graphik-Regular.otf | Bin 0 -> 125772 bytes .../static/fonts/Graphik-Semibold.otf | Bin 0 -> 132784 bytes .../static/images/fav-icon.ico | Bin 0 -> 15086 bytes .../static/images/white-logo.png | Bin 31280 -> 50233 bytes .../static/styles/jsdoc.css | 140 ++++++++++-------- 8 files changed, 84 insertions(+), 59 deletions(-) delete mode 100644 tools/jsdoc/hifi-jsdoc-template/static/fonts/Cairo-Bold.ttf create mode 100644 tools/jsdoc/hifi-jsdoc-template/static/fonts/Graphik-Regular.otf create mode 100644 tools/jsdoc/hifi-jsdoc-template/static/fonts/Graphik-Semibold.otf create mode 100644 tools/jsdoc/hifi-jsdoc-template/static/images/fav-icon.ico diff --git a/tools/jsdoc/config.json b/tools/jsdoc/config.json index 5074362225..d5760b0332 100644 --- a/tools/jsdoc/config.json +++ b/tools/jsdoc/config.json @@ -1,5 +1,6 @@ { "opts": { + "readme": "api-mainpage.md", "template": "hifi-jsdoc-template" }, "docdash": { diff --git a/tools/jsdoc/hifi-jsdoc-template/publish.js b/tools/jsdoc/hifi-jsdoc-template/publish.js index 9cd428bbbb..7d0ded5a0b 100644 --- a/tools/jsdoc/hifi-jsdoc-template/publish.js +++ b/tools/jsdoc/hifi-jsdoc-template/publish.js @@ -420,7 +420,7 @@ function linktoExternal(longName, name) { */ function buildNav(members) { - var nav = '

Home

'; + var nav = '

API Reference Home

'; var seen = {}; var seenTutorials = {}; var docdash = env && env.conf && env.conf.docdash || {}; diff --git a/tools/jsdoc/hifi-jsdoc-template/static/fonts/Cairo-Bold.ttf b/tools/jsdoc/hifi-jsdoc-template/static/fonts/Cairo-Bold.ttf deleted file mode 100644 index ad884391d78a4c9012f51b6681746bb51cb7f7c0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 170996 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 z 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�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 diff --git a/tools/jsdoc/hifi-jsdoc-template/static/fonts/Graphik-Regular.otf b/tools/jsdoc/hifi-jsdoc-template/static/fonts/Graphik-Regular.otf new file mode 100644 index 0000000000000000000000000000000000000000..8100438827a114c8a825c0aca59d9c972af57af7 GIT binary patch literal 125772 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 HG4THY5Z2EH literal 0 HcmV?d00001 diff --git a/tools/jsdoc/hifi-jsdoc-template/static/fonts/Graphik-Semibold.otf b/tools/jsdoc/hifi-jsdoc-template/static/fonts/Graphik-Semibold.otf new file mode 100644 index 0000000000000000000000000000000000000000..45cf6bc865c2abcf35110bdfbf7c62f17ed6b724 GIT binary patch literal 132784 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 OqZ0#ckD@-!zxaQUuk}R$ literal 0 HcmV?d00001 diff --git a/tools/jsdoc/hifi-jsdoc-template/static/images/fav-icon.ico b/tools/jsdoc/hifi-jsdoc-template/static/images/fav-icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..2bacaf10830a7093029d6d9b841e56e01e5ff388 GIT binary patch literal 15086 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
  • D0Wo~|f&UIc~RpVT13BgI~&$dQUV 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�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 NqW-1x#kvlU{s*yk?ZW^7 diff --git a/tools/jsdoc/hifi-jsdoc-template/static/styles/jsdoc.css b/tools/jsdoc/hifi-jsdoc-template/static/styles/jsdoc.css index 2ba9c84954..844fb04e72 100644 --- a/tools/jsdoc/hifi-jsdoc-template/static/styles/jsdoc.css +++ b/tools/jsdoc/hifi-jsdoc-template/static/styles/jsdoc.css @@ -4,8 +4,13 @@ ********************************************************************/ @font-face{ - font-family: 'Cairo'; - src: url('../fonts/Cairo-Bold.ttf') format('truetype'); + font-family: 'Graphik Semibold'; + src: url('../fonts/Graphik-SemiBold.otf') format('opentype'); +} + +@font-face{ + font-family: 'Graphik Regular'; + src: url('../fonts/Graphik-Regular.otf') format('opentype'); } @font-face{ @@ -29,12 +34,16 @@ html body { - font-family: 'Proxima Nova', sans-serif; - font-size: 1rem; - line-height: 1.5; - letter-spacing: 0.5px; - margin: 1.5rem; - color: #555; + font-family: 'Graphik Regular', 'Proxima Nova', arial, sans-serif; + font-weight: 400; + color: #000000; + letter-spacing: 0.5px; +} + +#main p { + font-size: 0.95rem; + line-height: 24px; + margin-bottom: 24px; } section @@ -50,14 +59,13 @@ section ********************************************************************/ h1, h2, h3, h4 { - font-family: "Cairo", Helvetica, sans-serif; + font-family: "Graphik Semibold", Helvetica, sans-serif; } h1 { font-size: 3.25rem; text-align: center; - letter-spacing: 1.5px; margin: 50px 25px 25px; } @@ -69,15 +77,13 @@ h2 h3 { - font-size: 1.5rem; + font-size: 28px; } h4 { - font-size: 18px; - letter-spacing: -0.33px; - margin-bottom: 12px; - color: #4d4e53; + font-family: 'Graphik Regular'; + font-size: 1.03rem; } h6 @@ -119,7 +125,7 @@ table background-color: #fff; border-collapse: collapse; border-spacing: 0; - border: 1px solid #ccc; + border: solid #d8e1d9 1px; text-align: left; overflow: auto; font-size: 0.9rem; @@ -128,18 +134,19 @@ table } table > thead { - background-color: #ddd; - border-bottom: 1px solid #ccc; + border-color: #d8e1d9; + background: #d8e1d9; font-weight: 400; } table th, table td { padding: 0.5rem; - border-left: 1px solid #ccc; + border-left: 1px solid #d8e1d9; + font-size: .95em; } table tr { - border-bottom: 1px solid #ccc; + border-bottom: 1px solid #d8e1d9; } table tr:nth-child(even) { @@ -150,18 +157,14 @@ table tr:nth-child(even) { ****************************** Link styles ************************* ********************************************************************/ -a, a:visited, a:active { - color: #1694CA; - text-decoration: none; +a, a:hover, a:active, a:visited { + text-decoration: none; } -article a:hover { - color: #0e6185; - text-decoration: none; - font-weight: bold; +#main a, #main a:visited, #main a:active, #main a:hover { + color: #009ee0; } - /******************************************************************* ***************************** List styles ************************** ********************************************************************/ @@ -171,20 +174,29 @@ article ul { } article li { + font-size: .95rem; padding-bottom: 5px; } +.readme ul { + font-size: 0.95rem; + line-height: 24px; + margin-bottom: 24px; + +} + /******************************************************************* ********************** Navigation sidebar styles ******************* ********************************************************************/ nav { position: fixed; - top: 165px; + top: 260px; bottom: 0; left: 0; right: 0; - width: 305px; + width: 300px; + background-color: #000000; border-right: 1px solid #ccc; overflow-y: scroll; padding-left: 20px; @@ -192,6 +204,11 @@ nav { box-sizing: border-box; } +nav::-webkit-scrollbar { + width: 0; + height: 0; +} + nav #nav-search { width: 210px; height: 30px; @@ -207,21 +224,28 @@ nav #nav-search { position: fixed; top: 0; left: 0; - height: 165px; - width: 305px; - background-color: #00B4EF; - vertical-align: middle; + height: 260px; + width: 300px; + background-color: #000000; + color: #FFFFFF; text-align: center; margin-top: 0px; } .nav-header p { - padding-top: 15px; + padding-top: 8px; +} + +.nav-header a { + color: #FFFFFF; + font-size: .9rem; + line-height: 1.5; } nav h3 { - font-family: "Proxima Nova", sans-serif; + font-family: "Graphik Regular", sans-serif; font-size: 0.9rem; + color: #FFFFFF; text-transform: uppercase; letter-spacing: 0.5px; } @@ -233,8 +257,16 @@ nav ul { list-style: none; } +nav h3 a { + color: #FFFFFF; +} + nav ul a, nav ul a:visited, nav ul a:active { - color: #a1a1a1; + color: #FFFFFF; +} + +nav ul a:hover { + font-weight: bold; } nav ul ul { @@ -250,7 +282,7 @@ nav ul ul li:first-child nav li { - margin-top: 3px; + margin-top: 14px; } @@ -333,14 +365,14 @@ nav > h2 > a { .search-input { - font-family: 'Proxima Nova', sans-serif; - font-size: 0.9rem; + font-family: 'Graphik Regular', sans-serif; + font-size: 80%; border: 1px solid #ddd; box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.06); - border-radius: 0.1875rem; + border-radius: 0; color: #3A3F3E; - width: 75%; - padding: 0.425rem; + width: 70%; + padding: 10px; } /******************************************************************** @@ -349,23 +381,20 @@ nav > h2 > a { tt, code, kbd, samp { font-family: Consolas, Monaco, 'Andale Mono', monospace; - font-size: 0.8rem; + font-size: 0.9rem; } .name, .signature { font-family: Consolas, Monaco, 'Andale Mono', monospace; - font-size: 0.8rem; + font-size: 0.9rem; } - - - - - img { + display: block; max-width: 100%; + margin: auto; } p, ul, ol, blockquote { @@ -427,7 +456,7 @@ header { color: #999 !important; } -.availableIn +#main p.availableIn { font-size: 0.8rem; } @@ -517,7 +546,7 @@ header { .prettyprint code { - font-size: 0.65rem; + font-size: 0.7rem; line-height: 18px; display: block; padding: 4px 12px; @@ -580,13 +609,8 @@ header { padding-top: 0; } -.params td.description > p:last-child, .props td.description > p:last-child { - margin-bottom: 0; - padding-bottom: 0; -} - span.param-type, .params td .param-type, .param-type dd { - color: #606; + color: #606; font-family: Consolas, Monaco, 'Andale Mono', monospace } From b10eb4e1d9339d0eb4e034af3eba4446e5334772 Mon Sep 17 00:00:00 2001 From: ingerjm0 Date: Wed, 20 Mar 2019 10:14:32 -0700 Subject: [PATCH 053/158] Add intro page to API docs --- tools/jsdoc/api-mainpage.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 tools/jsdoc/api-mainpage.md diff --git a/tools/jsdoc/api-mainpage.md b/tools/jsdoc/api-mainpage.md new file mode 100644 index 0000000000..504b2c1ed0 --- /dev/null +++ b/tools/jsdoc/api-mainpage.md @@ -0,0 +1,9 @@ +The High Fidelity JavaScript API lets content creators and developers create new experiences and transform virtual worlds within the High Fidelity metaverse. With it, you can build great content, customize avatars, play audio and so much more. + +You are most likely to interact with these APIs: + +* The **[Entities](Entities.html)** namespace lets creators add, remove, and edit entities around you to build an interactive environment. In addition, everyone has access to the `get` properties of an entity, which can be used to find entities in range, direction, collision, or raytrace. +* The **[AvatarList](AvatarList.html)**, **[MyAvatar](MyAvatar.html)**, and **[Avatar](Avatar.html)** namespaces affect your personal avatars, and lets you get information on other people's avatars. +* The **[Script](Script.html)** namespace lets you to connect callbacks from your client to script, such as functionality that is dependent on time (`Script.update`, `Script.setTimeout`, `Script.setInterval`, etc), connect paths relatively to Assets (`Script.relativePath`), refer to other scripts (`Script.require`, `Script.include`), or create events which occur when the script is turned off (`Script.scriptEnding`). + +To learn more about using High Fidelity and exploring the metaverse, visit the [High Fidelity Documentation](https://docs.highfidelity.com). \ No newline at end of file From 76bc5c52a74eb28281387832122c31312a8419d7 Mon Sep 17 00:00:00 2001 From: ingerjm0 Date: Wed, 20 Mar 2019 10:20:30 -0700 Subject: [PATCH 054/158] Template fixes for new API system --- .../hifi-jsdoc-template/tmpl/layout.tmpl | 54 ++++++++++++++++++- .../hifi-jsdoc-template/tmpl/params.tmpl | 9 ++++ .../hifi-jsdoc-template/tmpl/signalList.tmpl | 4 +- 3 files changed, 63 insertions(+), 4 deletions(-) diff --git a/tools/jsdoc/hifi-jsdoc-template/tmpl/layout.tmpl b/tools/jsdoc/hifi-jsdoc-template/tmpl/layout.tmpl index 6f267587c0..41a324fdaf 100644 --- a/tools/jsdoc/hifi-jsdoc-template/tmpl/layout.tmpl +++ b/tools/jsdoc/hifi-jsdoc-template/tmpl/layout.tmpl @@ -16,10 +16,11 @@