From 9b5f19399c6512d92ee1e79fdb1913e482e02253 Mon Sep 17 00:00:00 2001 From: Triplelexx Date: Tue, 25 Apr 2017 00:45:06 +0100 Subject: [PATCH 1/6] create tablet-raiseHand.js --- .../icons/tablet-icons/raise-hand-a.svg | 70 ++++++++++++ .../icons/tablet-icons/raise-hand-i.svg | 60 +++++++++++ .../tablet-raiseHand/tablet-raiseHand.js | 102 ++++++++++++++++++ 3 files changed, 232 insertions(+) create mode 100644 interface/resources/icons/tablet-icons/raise-hand-a.svg create mode 100644 interface/resources/icons/tablet-icons/raise-hand-i.svg create mode 100644 unpublishedScripts/marketplace/tablet-raiseHand/tablet-raiseHand.js diff --git a/interface/resources/icons/tablet-icons/raise-hand-a.svg b/interface/resources/icons/tablet-icons/raise-hand-a.svg new file mode 100644 index 0000000000..fd35073332 --- /dev/null +++ b/interface/resources/icons/tablet-icons/raise-hand-a.svg @@ -0,0 +1,70 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/interface/resources/icons/tablet-icons/raise-hand-i.svg b/interface/resources/icons/tablet-icons/raise-hand-i.svg new file mode 100644 index 0000000000..50a6aa2606 --- /dev/null +++ b/interface/resources/icons/tablet-icons/raise-hand-i.svg @@ -0,0 +1,60 @@ + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/unpublishedScripts/marketplace/tablet-raiseHand/tablet-raiseHand.js b/unpublishedScripts/marketplace/tablet-raiseHand/tablet-raiseHand.js new file mode 100644 index 0000000000..f7702053a4 --- /dev/null +++ b/unpublishedScripts/marketplace/tablet-raiseHand/tablet-raiseHand.js @@ -0,0 +1,102 @@ +"use strict"; +// +// tablet-raiseHand.js +// +// client script that creates a tablet button to raise hand +// +// Created by Triplelexx on 17/04/22 +// Copyright 2017 High Fidelity, Inc. +// +// Hand icons adapted from https://linearicons.com, created by Perxis https://perxis.com CC BY-SA 4.0 license. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { // BEGIN LOCAL_SCOPE + var BUTTON_NAME = "RAISE\nHAND"; + var USERCONNECTION_MESSAGE_CHANNEL = "io.highfidelity.makeUserConnection"; + var DEBUG_PREFIX = "TABLET RAISE HAND: "; + var isRaiseHandButtonActive = false; + var animHandlerId; + + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + text: BUTTON_NAME, + icon: "icons/tablet-icons/raise-hand-i.svg", + activeIcon: "icons/tablet-icons/raise-hand-a.svg" + }); + + function onClicked() { + isRaiseHandButtonActive = !isRaiseHandButtonActive; + button.editProperties({ isActive: isRaiseHandButtonActive }); + if (isRaiseHandButtonActive) { + removeAnimation(); + animHandlerId = MyAvatar.addAnimationStateHandler(raiseHandAnimation, []); + Messages.subscribe(USERCONNECTION_MESSAGE_CHANNEL); + Messages.messageReceived.connect(messageHandler); + } else { + removeAnimation(); + Messages.unsubscribe(USERCONNECTION_MESSAGE_CHANNEL); + Messages.messageReceived.disconnect(messageHandler); + } + } + + function removeAnimation() { + if (animHandlerId) { + animHandlerId = MyAvatar.removeAnimationStateHandler(animHandlerId); + } + } + + function raiseHandAnimation(animationProperties) { + // all we are doing here is moving the right hand to a spot that is above the hips. + var headIndex = MyAvatar.getJointIndex("Head"); + var offset = 0.0; + var result = {}; + if (headIndex) { + offset = 0.85 * MyAvatar.getAbsoluteJointTranslationInObjectFrame(headIndex).y; + } + var handPos = Vec3.multiply(offset, { x: -0.7, y: 1.25, z: 0.25 }); + result.rightHandPosition = handPos; + result.rightHandRotation = Quat.fromPitchYawRollDegrees(0, 0, 0); + return result; + } + + function messageHandler(channel, messageString, senderID) { + if (channel !== USERCONNECTION_MESSAGE_CHANNEL && senderID !== MyAvatar.sessionUUID) { + return; + } + var message = {}; + try { + message = JSON.parse(messageString); + } catch (e) { + print(DEBUG_PREFIX + "messageHandler error: " + e); + } + switch (message.key) { + case "waiting": + case "connecting": + case "connectionAck": + case "connectionRequest": + case "done": + removeAnimation(); + if (isRaiseHandButtonActive) { + isRaiseHandButtonActive = false; + button.editProperties({ isActive: isRaiseHandButtonActive }); + } + break; + default: + print(DEBUG_PREFIX + "messageHandler unknown message: " + message); + break; + } + } + + button.clicked.connect(onClicked); + + Script.scriptEnding.connect(function() { + Messages.unsubscribe(USERCONNECTION_MESSAGE_CHANNEL); + Messages.messageReceived.disconnect(messageHandler); + button.clicked.disconnect(onClicked); + tablet.removeButton(button); + removeAnimation(); + }); +}()); // END LOCAL_SCOPE From 52c288bfed215e817081542302a3b4766a2f0da2 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 11 May 2017 14:20:42 -0700 Subject: [PATCH 2/6] Desktop users of different height can shake hands --- scripts/system/makeUserConnection.js | 36 ++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/scripts/system/makeUserConnection.js b/scripts/system/makeUserConnection.js index a8afad2e1c..37a334bd70 100644 --- a/scripts/system/makeUserConnection.js +++ b/scripts/system/makeUserConnection.js @@ -198,7 +198,7 @@ } var animationData = {}; - function updateAnimationData() { + function updateAnimationData(verticalOffset) { // all we are doing here is moving the right hand to a spot // that is in front of and a bit above the hips. Basing how // far in front as scaling with the avatar's height (say hips @@ -209,6 +209,9 @@ offset = 0.8 * MyAvatar.getAbsoluteJointTranslationInObjectFrame(headIndex).y; } animationData.rightHandPosition = Vec3.multiply(offset, {x: -0.25, y: 0.8, z: 1.3}); + if (verticalOffset) { + animationData.rightHandPosition.y += verticalOffset; + } animationData.rightHandRotation = Quat.fromPitchYawRollDegrees(90, 0, 90); } function shakeHandsAnimation() { @@ -347,7 +350,32 @@ } return false; } - + function findNearestAvatar() { + // We only look some max distance away (much larger than the handshake distance, but still...) + var minDistance = MAX_AVATAR_DISTANCE * 20; + var closestAvatar; + AvatarList.getAvatarIdentifiers().forEach(function (id) { + var avatar = AvatarList.getAvatar(id); + if (avatar && avatar.sessionUUID != MyAvatar.sessionUUID) { + var currentDistance = Vec3.distance(avatar.position, MyAvatar.position); + if (minDistance > currentDistance) { + minDistance = currentDistance; + closestAvatar = avatar; + } + } + }); + return closestAvatar; + } + function adjustAnimationHeight() { + var avatar = findNearestAvatar(); + if (avatar) { + var myHeadIndex = MyAvatar.getJointIndex("Head"); + var otherHeadIndex = avatar.getJointIndex("Head"); + var diff = (avatar.getJointPosition(otherHeadIndex).y - MyAvatar.getJointPosition(myHeadIndex).y) / 2; + print("head height difference: " + diff); + updateAnimationData(diff); + } + } function findNearestWaitingAvatar() { var handPosition = getHandPosition(MyAvatar, currentHandJointIndex); var minDistance = MAX_AVATAR_DISTANCE; @@ -436,6 +464,10 @@ handStringMessageSend({ key: "waiting", }); + // potentially adjust height of handshake + if (fromKeyboard) { + adjustAnimationHeight(); + } lookForWaitingAvatar(); } } From 539aaf8c598d1ffde91fe402a5b9acfc314b90c5 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 11 May 2017 23:00:41 +0100 Subject: [PATCH 3/6] add debug statment and fixed sorting order --- plugins/openvr/src/ViveControllerManager.cpp | 19 +++++++++++++------ plugins/openvr/src/ViveControllerManager.h | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index e5cd7ffecc..8c357103c9 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -66,7 +66,7 @@ static glm::mat4 computeOffset(glm::mat4 defaultToReferenceMat, glm::mat4 defaul } static bool sortPucksYPosition(std::pair firstPuck, std::pair secondPuck) { - return (firstPuck.second.translation.y < firstPuck.second.translation.y); + return (firstPuck.second.translation.y < secondPuck.second.translation.y); } bool ViveControllerManager::isSupported() const { @@ -245,6 +245,7 @@ void ViveControllerManager::InputDevice::calibrateOrUncalibrate(const controller } void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibrationData& inputCalibration) { + qDebug() << "Puck Calibration: Starting..."; // convert the hmd head from sensor space to avatar space glm::mat4 hmdSensorFlippedMat = inputCalibration.hmdSensorMat * Matrices::Y_180; glm::mat4 sensorToAvatarMat = glm::inverse(inputCalibration.avatarMat) * inputCalibration.sensorToWorldMat; @@ -264,18 +265,24 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr glm::mat4 defaultToReferenceMat = currentHead * glm::inverse(inputCalibration.defaultHeadMat); int puckCount = (int)_validTrackedObjects.size(); + qDebug() << "Puck Calibration: " << puckCount << " pucks found for calibration"; _config = _preferedConfig; if (_config != Config::Auto && puckCount < MIN_PUCK_COUNT) { + qDebug() << "Puck Calibration: Failed: Could not meet the minimal # of pucks"; uncalibrate(); return; } else if (_config == Config::Auto){ if (puckCount == MIN_PUCK_COUNT) { _config = Config::Feet; + qDebug() << "Puck Calibration: Auto Config: " << configToString(_config) << " configuration"; } else if (puckCount == MIN_FEET_AND_HIPS) { _config = Config::FeetAndHips; + qDebug() << "Puck Calibration: Auto Config: " << configToString(_config) << " configuration"; } else if (puckCount >= MIN_FEET_HIPS_CHEST) { _config = Config::FeetHipsAndChest; + qDebug() << "Puck Calibration: Auto Config: " << configToString(_config) << " configuration"; } else { + qDebug() << "Puck Calibration: Auto Config Failed: Could not meet the minimal # of pucks"; uncalibrate(); return; } @@ -283,8 +290,6 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr std::sort(_validTrackedObjects.begin(), _validTrackedObjects.end(), sortPucksYPosition); - - auto& firstFoot = _validTrackedObjects[FIRST_FOOT]; auto& secondFoot = _validTrackedObjects[SECOND_FOOT]; controller::Pose& firstFootPose = firstFoot.second; @@ -314,10 +319,12 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr _jointToPuckMap[controller::SPINE2] = _validTrackedObjects[CHEST].first; _pucksOffset[_validTrackedObjects[CHEST].first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultSpine2, _validTrackedObjects[CHEST].second); } else { + qDebug() << "Puck Calibration: " << configToString(_config) << " Config Failed: Could not meet the minimal # of pucks"; uncalibrate(); return; } _calibrated = true; + qDebug() << "PuckCalibration: " << configToString(_config) << " Configuration Successful"; } void ViveControllerManager::InputDevice::uncalibrate() { @@ -575,9 +582,9 @@ void ViveControllerManager::InputDevice::saveSettings() const { settings.endGroup(); } -QString ViveControllerManager::InputDevice::configToString() { +QString ViveControllerManager::InputDevice::configToString(Config config) { QString currentConfig; - switch (_preferedConfig) { + switch (config) { case Config::Auto: currentConfig = "Auto"; break; @@ -615,7 +622,7 @@ void ViveControllerManager::InputDevice::createPreferences() { static const QString VIVE_PUCKS_CONFIG = "Vive Pucks Configuration"; { - auto getter = [this]()->QString { return configToString(); }; + auto getter = [this]()->QString { return configToString(_preferedConfig); }; auto setter = [this](const QString& value) { setConfigFromString(value); saveSettings(); }; auto preference = new ComboBoxPreference(VIVE_PUCKS_CONFIG, "Configuration", getter, setter); QStringList list = (QStringList() << "Auto" << "Feet" << "FeetAndHips" << "FeetHipsAndChest"); diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 9920fb003a..c2ebdc6144 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -126,7 +126,7 @@ private: bool _timeTilCalibrationSet { false }; mutable std::recursive_mutex _lock; - QString configToString(); + QString configToString(Config config); void setConfigFromString(const QString& value); void loadSettings(); void saveSettings() const; From ae5f9e4fb15e274aa9a143dfa101a5e6b1186730 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 11 May 2017 15:10:19 -0700 Subject: [PATCH 4/6] animate scroll of partially visible cards --- interface/resources/qml/hifi/Feed.qml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/Feed.qml b/interface/resources/qml/hifi/Feed.qml index fc108f47e3..3fd28aadb8 100644 --- a/interface/resources/qml/hifi/Feed.qml +++ b/interface/resources/qml/hifi/Feed.qml @@ -238,8 +238,24 @@ Column { stackShadowNarrowing: root.stackShadowNarrowing; shadowHeight: root.stackedCardShadowHeight; - hoverThunk: function () { scroll.currentIndex = index; } - unhoverThunk: function () { scroll.currentIndex = -1; } + hoverThunk: function () { scrollToIndex(index); } + unhoverThunk: function () { scrollToIndex(-1); } } } + NumberAnimation { + id: anim; + target: scroll; + property: "contentX"; + duration: 500; + } + function scrollToIndex(index) { + anim.running = false; + var pos = scroll.contentX; + var destPos; + scroll.positionViewAtIndex(index, ListView.Contain); + destPos = scroll.contentX; + anim.from = pos; + anim.to = destPos; + anim.running = true; + } } From e1c805e76f0a02d499a78c52732764cceddb7354 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 11 May 2017 17:02:00 -0700 Subject: [PATCH 5/6] lock in Overlays::findRayIntersectionInternal --- interface/src/ui/overlays/Overlays.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 61a283b88c..4970112405 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -408,6 +408,7 @@ RayToOverlayIntersectionResult Overlays::findRayIntersectionInternal(const PickR const QVector& overlaysToInclude, const QVector& overlaysToDiscard, bool visibleOnly, bool collidableOnly) { + QReadLocker lock(&_lock); float bestDistance = std::numeric_limits::max(); bool bestIsFront = false; From a9716313be317edfa72cdf10495e94a556cd9419 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 11 May 2017 17:02:37 -0700 Subject: [PATCH 6/6] cr feedback -- really good feedback in fact --- interface/resources/qml/hifi/Feed.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/Feed.qml b/interface/resources/qml/hifi/Feed.qml index 3fd28aadb8..c1bd35f49d 100644 --- a/interface/resources/qml/hifi/Feed.qml +++ b/interface/resources/qml/hifi/Feed.qml @@ -246,7 +246,7 @@ Column { id: anim; target: scroll; property: "contentX"; - duration: 500; + duration: 250; } function scrollToIndex(index) { anim.running = false; @@ -256,6 +256,7 @@ Column { destPos = scroll.contentX; anim.from = pos; anim.to = destPos; + scroll.currentIndex = index; anim.running = true; } }