From 53efe6bfb2d80bb9cfdd3f4cf5582a1101bf927f Mon Sep 17 00:00:00 2001 From: druiz17 Date: Thu, 21 Sep 2017 18:17:05 -0700 Subject: [PATCH 1/7] working on fix --- .../src/display-plugins/CompositorHelper.cpp | 16 ++ .../src/display-plugins/CompositorHelper.h | 2 + .../controllerModules/farActionGrabEntity.js | 12 +- .../controllerModules/hudOverlayPointer.js | 255 ++++++++++++++++++ .../controllerModules/scaleAvatar.js | 5 +- .../system/controllers/controllerScripts.js | 7 +- .../controllers/handControllerPointer.js | 10 +- .../libraries/controllerDispatcherUtils.js | 20 +- scripts/system/tablet-ui/tabletUI.js | 30 +++ 9 files changed, 337 insertions(+), 20 deletions(-) create mode 100644 scripts/system/controllers/controllerModules/hudOverlayPointer.js diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp index 2f57cc29d0..294a3f6e55 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp @@ -279,6 +279,18 @@ bool CompositorHelper::getReticleOverDesktop() const { return _isOverDesktop; } +bool CompositorHelper::isPositionOverDesktop(glm::vec2 position) const { + if (isHMD()) { + glm::vec2 maxOverlayPosition = _currentDisplayPlugin->getRecommendedUiSize(); + static const glm::vec2 minOverlayPosition; + if (glm::any(glm::lessThan(position, minOverlayPosition)) || + glm::any(glm::greaterThan(position, maxOverlayPosition))) { + return true; + } + } + return _isOverDesktop; +} + glm::vec2 CompositorHelper::getReticleMaximumPosition() const { glm::vec2 result; if (isHMD()) { @@ -468,3 +480,7 @@ void ReticleInterface::setScale(float scale) { auto& cursorManager = Cursor::Manager::instance(); cursorManager.setScale(scale); } + +bool ReticleInterface::isPointOnSystemOverlay(QVariant position) { + return !_compositor->isPositionOverDesktop(vec2FromVariant(position)); +} diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h index b1d2815f65..8534de6b9d 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h @@ -106,6 +106,7 @@ public: /// if the reticle is pointing to a system overlay (a dialog box for example) then the function returns true otherwise false bool getReticleOverDesktop() const; + bool isPositionOverDesktop(glm::vec2 position) const; void setReticleOverDesktop(bool value) { _isOverDesktop = value; } void setDisplayPlugin(const DisplayPluginPointer& displayPlugin) { _currentDisplayPlugin = displayPlugin; } @@ -195,6 +196,7 @@ public: Q_INVOKABLE void setAllowMouseCapture(bool value) { return _compositor->setAllowMouseCapture(value); } Q_INVOKABLE bool isPointingAtSystemOverlay() { return !_compositor->getReticleOverDesktop(); } + Q_INVOKABLE bool isPointOnSystemOverlay(QVariant position); Q_INVOKABLE bool getVisible() { return _compositor->getReticleVisible(); } Q_INVOKABLE void setVisible(bool visible) { _compositor->setReticleVisible(visible); } diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index eb73b0f908..72da3c3f70 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -13,7 +13,7 @@ makeDispatcherModuleParameters, MSECS_PER_SEC, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, AVATAR_SELF_ID, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic, - getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays + getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays, isPointingAtUI */ @@ -21,7 +21,6 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); (function() { - var PICK_WITH_HAND_RAY = true; var halfPath = { @@ -423,12 +422,9 @@ Script.include("/~/system/libraries/controllers.js"); this.isPointingAtUI = function(controllerData) { var hudRayPickInfo = controllerData.hudRayPicks[this.hand]; - var hudPoint2d = HMD.overlayFromWorldPoint(hudRayPickInfo.intersection); - if (Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(hudPoint2d || Reticle.position)) { - return true; - } - - return false; + var result = isPointingAtUI(hudRayPickInfo); + print(result); + return result; }; this.run = function (controllerData) { diff --git a/scripts/system/controllers/controllerModules/hudOverlayPointer.js b/scripts/system/controllers/controllerModules/hudOverlayPointer.js new file mode 100644 index 0000000000..0015a4a2d6 --- /dev/null +++ b/scripts/system/controllers/controllerModules/hudOverlayPointer.js @@ -0,0 +1,255 @@ +// +// hudOverlayPointer.js +// +// scripts/system/controllers/controllerModules/ +// +// Created by Dante Ruiz 2017-9-21 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +/* global Script, HMD, WebTablet, UIWebTablet, UserActivityLogger, Settings, Entities, Messages, Tablet, Overlays, + MyAvatar, Menu, AvatarInputs, Vec3 */ +(function() { + Script.include("/~/system/libraries/controllers.js") + var ControllerDispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); + var halfPath = { + type: "line3d", + color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE, + visible: true, + alpha: 1, + solid: true, + glow: 1.0, + lineWidth: 5, + ignoreRayIntersection: true, // always ignore this + drawHUDLayer: true, // Even when burried inside of something, show it. + parentID: AVATAR_SELF_ID + }; + var halfEnd = { + type: "sphere", + solid: true, + color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE, + alpha: 0.9, + ignoreRayIntersection: true, + drawHUDLayer: true, // Even when burried inside of something, show it. + visible: true + }; + var fullPath = { + type: "line3d", + color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE, + visible: true, + alpha: 1, + solid: true, + glow: 1.0, + lineWidth: 5, + ignoreRayIntersection: true, // always ignore this + drawHUDLayer: true, // Even when burried inside of something, show it. + parentID: AVATAR_SELF_ID + }; + var fullEnd = { + type: "sphere", + solid: true, + color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE, + alpha: 0.9, + ignoreRayIntersection: true, + drawHUDLayer: true, // Even when burried inside of something, show it. + visible: true + }; + var holdPath = { + type: "line3d", + color: COLORS_GRAB_DISTANCE_HOLD, + visible: true, + alpha: 1, + solid: true, + glow: 1.0, + lineWidth: 5, + ignoreRayIntersection: true, // always ignore this + drawHUDLayer: true, // Even when burried inside of something, show it. + parentID: AVATAR_SELF_ID + }; + + var renderStates = [ + {name: "half", path: halfPath, end: halfEnd}, + {name: "full", path: fullPath, end: fullEnd}, + {name: "hold", path: holdPath} + ]; + + var defaultRenderStates = [ + {name: "half", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: halfPath}, + {name: "full", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: fullPath}, + {name: "hold", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: holdPath} + ]; + + + // triggered when stylus presses a web overlay/entity + var HAPTIC_STYLUS_STRENGTH = 1.0; + var HAPTIC_STYLUS_DURATION = 20.0; + var MARGIN = 25; + + function distance2D(a, b) { + var dx = (a.x - b.x); + var dy = (a.y - b.y); + return Math.sqrt(dx * dx + dy * dy); + } + + function HudOverlayPointer(hand) { + var _this = this; + this.hand = hand; + this.reticleMinX = MARGIN; + this.reticleMaxX; + this.reticleMinY = MARGIN; + this.reticleMaxY; + this.clicked = false; + this.triggerClicked = 0; + this.parameters = ControllerDispatcherUtils.makeDispatcherModuleParameters( + 540, + this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], + [], + 100); + + this.getOtherHandController = function() { + return (this.hand === RIGHT_HAND) ? Controller.Standard.LeftHand : Controller.Standard.RightHand; + }; + + this.clicked = function() { + return this.clicked; + }; + + this.getOtherModule = function() { + return (this.hand === RIGHT_HAND) ? leftOverlayLaserInput : rightOverlayLaserInput; + }; + + this.handToController = function() { + return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; + }; + + this.updateRecommendedArea = function() { + var dims = Controller.getViewportDimensions(); + this.reticleMaxX = dims.x - MARGIN; + this.reticleMaxY = dims.y - MARGIN; + }; + + this.hasNotSentClick = function() { + if (!_this.clicked) { + _this.clicked = true; + return true; + } + return false; + }; + + this.updateLaserPointer = function(controllerData) { + var RADIUS = 0.005; + var dim = { x: RADIUS, y: RADIUS, z: RADIUS }; + + if (this.mode === "full") { + this.fullEnd.dimensions = dim; + LaserPointers.editRenderState(this.laserPointer, this.mode, {path: fullPath, end: this.fullEnd}); + } else if (this.mode === "half") { + this.halfEnd.dimensions = dim; + LaserPointers.editRenderState(this.laserPointer, this.mode, {path: halfPath, end: this.halfEnd}); + } + + LaserPointers.enableLaserPointer(this.laserPointer); + LaserPointers.setRenderState(this.laserPointer, this.mode); + }; + + this.processControllerTriggers = function(controllerData) { + if (controllerData.triggerClicks[this.hand]) { + this.mode = "full"; + } else if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) { + this.clicked = false; + this.mode = "half"; + } else { + this.mode = "none"; + } + }; + + this.calculateNewReticlePosition = function(intersection) { + this.updateRecommendedArea(); + var point2d = HMD.overlayFromWorldPoint(intersection); + point2d.x = Math.max(this.reticleMinX, Math.min(point2d.x, this.reticleMaxX)); + point2d.y = Math.max(this.reticleMinY, Math.min(point2d.y, this.reticleMaxY)); + return point2d; + }; + + this.setReticlePosition = function(point2d) { + Reticle.setPosition(point2d); + }; + + this.processLaser = function(controllerData) { + var controllerLocation = controllerData.controllerLocations[this.hand]; + if (controllerData.triggerValues[this.hand] < ControllerDispatcherUtils.TRIGGER_OFF_VALUE || !controllerLocation.valid) { + this.exitModule(); + return false; + } + + var hudRayPick = controllerData.hudRayPicks[this.hand]; + var controllerLocation = controllerData.controllerLocations[this.hand]; + var point2d = this.calculateNewReticlePosition(hudRayPick.intersection); + this.setReticlePosition(point2d); + print(Reticle.isPointOnSystemOverlay(point2d)); + if (!Reticle.isPointOnSystemOverlay(point2d)) { + this.exitModule(); + print("----> exiting <------"); + return false; + } + + //this.setReticlePosition(point2d); + + this.clicked = controllerData.triggerClicked[this.hand]; + + this.processControllerTriggers(controllerData); + this.updateLaserPointer(controllerData); + return true; + }; + + this.exitModule = function() { + LaserPointers.disableLaserPointer(this.laserPointer); + }; + + this.isReady = function (controllerData) { + if (this.processLaser(controllerData)) { + return ControllerDispatcherUtils.makeRunningValues(true, [], []); + } else { + return ControllerDispatcherUtils.makeRunningValues(false, [], []); + } + }; + + this.run = function (controllerData, deltaTime) { + return this.isReady(controllerData); + }; + + this.cleanup = function () { + LaserPointers.disableLaserPointer(this.laserPointer); + LaserPointers.removeLaserPointer(this.laserPointer); + }; + + this.halfEnd = halfEnd; + this.fullEnd = fullEnd; + this.laserPointer = LaserPointers.createLaserPointer({ + joint: (this.hand === RIGHT_HAND) ? "_CONTROLLER_RIGHTHAND" : "_CONTROLLER_LEFTHAND", + filter: RayPick.PICK_HUD, + maxDistance: PICK_MAX_DISTANCE, + posOffset: getGrabPointSphereOffset(this.handToController(), true), + renderStates: renderStates, + enabled: true, + defaultRenderStates: defaultRenderStates + }); + } + + + var leftHudOverlayPointer = new HudOverlayPointer(LEFT_HAND); + var rightHudOverlayPointer = new HudOverlayPointer(RIGHT_HAND); + + var clickMapping = Controller.newMapping('HudOverlayPointer-click'); + clickMapping.from(rightHudOverlayPointer.clicked()).when(rightHudOverlayPointer.hasNotSentClick()).to(Controller.Actions.ReticleClick); + clickMapping.from(leftHudOverlayPointer.clicked()).when(leftHudOverlayPointer.hasNotSentClick()).to(Controller.Actions.ReticleClick); + clickMapping.enable(); + + enableDispatcherModule("LeftHudOverlayPointer", leftHudOverlayPointer); + enableDispatcherModule("RightHudOverlayPointer", rightHudOverlayPointer); + + +})(); diff --git a/scripts/system/controllers/controllerModules/scaleAvatar.js b/scripts/system/controllers/controllerModules/scaleAvatar.js index 05804c967b..de0434258c 100644 --- a/scripts/system/controllers/controllerModules/scaleAvatar.js +++ b/scripts/system/controllers/controllerModules/scaleAvatar.js @@ -1,4 +1,4 @@ -// handControllerGrab.js +// scaleAvatar.js // // Created by Dante Ruiz on 9/11/17 // @@ -76,8 +76,9 @@ dispatcherUtils.enableDispatcherModule("LeftScaleAvatar", leftScaleAvatar); dispatcherUtils.enableDispatcherModule("RightScaleAvatar", rightScaleAvatar); - this.cleanup = function() { + function cleanup() { dispatcherUtils.disableDispatcherModule("LeftScaleAvatar"); dispatcherUtils.disableDispatcherModule("RightScaleAvatar"); }; + Script.scriptEnding.connect(cleanup); })(); diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index e8b07c623d..695dea7b2c 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -12,14 +12,14 @@ var CONTOLLER_SCRIPTS = [ "squeezeHands.js", "controllerDisplayManager.js", - "handControllerPointer.js", + //"handControllerPointer.js", "grab.js", "toggleAdvancedMovementForHandControllers.js", "controllerDispatcher.js", "controllerModules/nearParentGrabEntity.js", "controllerModules/nearParentGrabOverlay.js", "controllerModules/nearActionGrabEntity.js", - "controllerModules/farActionGrabEntity.js", + //"controllerModules/farActionGrabEntity.js", "controllerModules/tabletStylusInput.js", "controllerModules/equipEntity.js", "controllerModules/nearTrigger.js", @@ -29,7 +29,8 @@ var CONTOLLER_SCRIPTS = [ "controllerModules/disableOtherModule.js", "controllerModules/farTrigger.js", "controllerModules/teleport.js", - "controllerModules/scaleAvatar.js" + "controllerModules/scaleAvatar.js", + "controllerModules/hudOverlayPointer.js" ]; var DEBUG_MENU_ITEM = "Debug defaultScripts.js"; diff --git a/scripts/system/controllers/handControllerPointer.js b/scripts/system/controllers/handControllerPointer.js index 832fe10d5f..1c988bfd34 100644 --- a/scripts/system/controllers/handControllerPointer.js +++ b/scripts/system/controllers/handControllerPointer.js @@ -314,7 +314,7 @@ function activeHudPoint2dGamePad() { var hudPoint2d = overlayFromWorldPoint(hudPoint3d); // We don't know yet if we'll want to make the cursor or laser visble, but we need to move it to see if - // it's pointing at a QML tool (aka system overlay). + // it's pointing at aQML tool (aka system overlay). setReticlePosition(hudPoint2d); return hudPoint2d; @@ -328,7 +328,7 @@ function activeHudPoint2d(activeHand) { // if controller is valid, update reticl } var controllerPosition = controllerPose.position; var controllerDirection = Quat.getUp(controllerPose.rotation); - + var hudPoint3d = calculateRayUICollisionPoint(controllerPosition, controllerDirection, true); if (!hudPoint3d) { if (Menu.isOptionChecked("Overlays")) { // With our hud resetting strategy, hudPoint3d should be valid here @@ -523,21 +523,21 @@ var wantsMenu = 0; clickMapping.from(function () { return wantsMenu; }).to(Controller.Actions.ContextMenu); clickMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(function (clicked) { if (clicked) { - activeHudPoint2d(Controller.Standard.RightHand); + //activeHudPoint2d(Controller.Standard.RightHand); Messages.sendLocalMessage("toggleHand", Controller.Standard.RightHand); } wantsMenu = clicked; }); clickMapping.from(Controller.Standard.LeftSecondaryThumb).peek().to(function (clicked) { if (clicked) { - activeHudPoint2d(Controller.Standard.LeftHand); + //activeHudPoint2d(Controller.Standard.LeftHand); Messages.sendLocalMessage("toggleHand", Controller.Standard.LeftHand); } wantsMenu = clicked; }); clickMapping.from(Controller.Standard.Start).peek().to(function (clicked) { if (clicked) { - activeHudPoint2dGamePad(); + //activeHudPoint2dGamePad(); var noHands = -1; Messages.sendLocalMessage("toggleHand", Controller.Standard.LeftHand); } diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index 10931e4e93..652bd5765b 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -40,7 +40,8 @@ entityHasActions:true, ensureDynamic:true, findGroupParent:true, - BUMPER_ON_VALUE:true + BUMPER_ON_VALUE:true, + isPointingAtUI: true */ MSECS_PER_SEC = 1000.0; @@ -310,6 +311,18 @@ findGroupParent = function (controllerData, targetProps) { return targetProps; }; +isPointingAtUI = function(intersection) { + var MARGIN = 25; + var reticleMinX = MARGIN, reticleMaxX, reticleMinY = MARGIN, reticleMaxY; + var dims = Controller.getViewportDimensions(); + reticleMaxX = dims.x - MARGIN; + reticleMaxY = dims.y - MARGIN; + var point2d = HMD.overlayFromWorldPoint(intersection.intersection); + point2d.x = Math.max(reticleMinX, Math.min(point2d.x, reticleMaxX)); + point2d.y = Math.max(reticleMinY, Math.min(point2d.y, reticleMaxY)); + return point2d; +} + if (typeof module !== 'undefined') { module.exports = { makeDispatcherModuleParameters: makeDispatcherModuleParameters, @@ -318,8 +331,11 @@ if (typeof module !== 'undefined') { makeRunningValues: makeRunningValues, LEFT_HAND: LEFT_HAND, RIGHT_HAND: RIGHT_HAND, + isPointingAtUI: isPointingAtUI, BUMPER_ON_VALUE: BUMPER_ON_VALUE, projectOntoOverlayXYPlane: projectOntoOverlayXYPlane, - projectOntoEntityXYPlane: projectOntoEntityXYPlane + projectOntoEntityXYPlane: projectOntoEntityXYPlane, + TRIGGER_OFF_VALUE: TRIGGER_OFF_VALUE, + TRIGGER_ON_VALUE: TRIGGER_ON_VALUE }; } diff --git a/scripts/system/tablet-ui/tabletUI.js b/scripts/system/tablet-ui/tabletUI.js index 63c1cc51aa..9d2382b3f8 100644 --- a/scripts/system/tablet-ui/tabletUI.js +++ b/scripts/system/tablet-ui/tabletUI.js @@ -272,6 +272,36 @@ Messages.subscribe("home"); Messages.messageReceived.connect(handleMessage); + var clickMapping = Controller.newMapping('tabletToggle-click'); + var wantsMenu = 0; + clickMapping.from(function () { return wantsMenu; }).to(Controller.Actions.ContextMenu); + clickMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(function (clicked) { + if (clicked) { + //activeHudPoint2d(Controller.Standard.RightHand); + Messages.sendLocalMessage("toggleHand", Controller.Standard.RightHand); + } + wantsMenu = clicked; + }); + + clickMapping.from(Controller.Standard.LeftSecondaryThumb).peek().to(function (clicked) { + if (clicked) { + //activeHudPoint2d(Controller.Standard.LeftHand); + Messages.sendLocalMessage("toggleHand", Controller.Standard.LeftHand); + } + wantsMenu = clicked; + }); + + clickMapping.from(Controller.Standard.Start).peek().to(function (clicked) { + if (clicked) { + //activeHudPoint2dGamePad(); + var noHands = -1; + Messages.sendLocalMessage("toggleHand", Controller.Standard.LeftHand); + } + + wantsMenu = clicked; + }); + clickMapping.enable(); + Script.setInterval(updateShowTablet, 100); Script.scriptEnding.connect(function () { From e965b7fff1e1ae57ac384403e334a6a67f630ba4 Mon Sep 17 00:00:00 2001 From: druiz17 Date: Fri, 22 Sep 2017 15:32:40 -0700 Subject: [PATCH 2/7] hand controller pointer --- .../controllerModules/farActionGrabEntity.js | 9 +- .../controllerModules/hudOverlayPointer.js | 44 ++++--- .../controllers/controllerModules/mouseHMD.js | 123 ++++++++++++++++++ .../system/controllers/controllerScripts.js | 5 +- 4 files changed, 155 insertions(+), 26 deletions(-) create mode 100644 scripts/system/controllers/controllerModules/mouseHMD.js diff --git a/scripts/system/controllers/controllerModules/farActionGrabEntity.js b/scripts/system/controllers/controllerModules/farActionGrabEntity.js index 72da3c3f70..d82048385f 100644 --- a/scripts/system/controllers/controllerModules/farActionGrabEntity.js +++ b/scripts/system/controllers/controllerModules/farActionGrabEntity.js @@ -420,16 +420,9 @@ Script.include("/~/system/libraries/controllers.js"); } }; - this.isPointingAtUI = function(controllerData) { - var hudRayPickInfo = controllerData.hudRayPicks[this.hand]; - var result = isPointingAtUI(hudRayPickInfo); - print(result); - return result; - }; - this.run = function (controllerData) { if (controllerData.triggerValues[this.hand] < TRIGGER_OFF_VALUE || - this.notPointingAtEntity(controllerData) || this.isPointingAtUI(controllerData)) { + this.notPointingAtEntity(controllerData)) { this.endNearGrabAction(); this.laserPointerOff(); return makeRunningValues(false, [], []); diff --git a/scripts/system/controllers/controllerModules/hudOverlayPointer.js b/scripts/system/controllers/controllerModules/hudOverlayPointer.js index 0015a4a2d6..fdc5758416 100644 --- a/scripts/system/controllers/controllerModules/hudOverlayPointer.js +++ b/scripts/system/controllers/controllerModules/hudOverlayPointer.js @@ -103,6 +103,7 @@ this.reticleMaxY; this.clicked = false; this.triggerClicked = 0; + this.movedAway = false; this.parameters = ControllerDispatcherUtils.makeDispatcherModuleParameters( 540, this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], @@ -113,8 +114,8 @@ return (this.hand === RIGHT_HAND) ? Controller.Standard.LeftHand : Controller.Standard.RightHand; }; - this.clicked = function() { - return this.clicked; + _this.isClicked = function() { + return _this.triggerClicked; }; this.getOtherModule = function() { @@ -131,8 +132,9 @@ this.reticleMaxY = dims.y - MARGIN; }; - this.hasNotSentClick = function() { + _this.hasNotSentClick = function() { if (!_this.clicked) { + print("sending clicked"); _this.clicked = true; return true; } @@ -178,34 +180,44 @@ Reticle.setPosition(point2d); }; + this.pointingAtTablet = function(controllerData) { + var rayPick = controllerData.rayPicks[this.hand]; + return (rayPick.objectID === HMD.tabletScreenID || rayPick.objectID === HMD.homeButtonID); + }; + + this.moveMouseAwayFromTablet = function() { + if (!this.movedAway) { + var point = {x: 25, y: 25}; + // this.setReticlePosition(point); + this.movedAway = true; + } + } + this.processLaser = function(controllerData) { var controllerLocation = controllerData.controllerLocations[this.hand]; - if (controllerData.triggerValues[this.hand] < ControllerDispatcherUtils.TRIGGER_OFF_VALUE || !controllerLocation.valid) { + if ((controllerData.triggerValues[this.hand] < ControllerDispatcherUtils.TRIGGER_ON_VALUE || !controllerLocation.valid) || + this.pointingAtTablet(controllerData)) { this.exitModule(); return false; } - var hudRayPick = controllerData.hudRayPicks[this.hand]; var controllerLocation = controllerData.controllerLocations[this.hand]; var point2d = this.calculateNewReticlePosition(hudRayPick.intersection); this.setReticlePosition(point2d); - print(Reticle.isPointOnSystemOverlay(point2d)); - if (!Reticle.isPointOnSystemOverlay(point2d)) { + if (!Reticle.isPointingAtSystemOverlay(point2d)) { this.exitModule(); - print("----> exiting <------"); return false; } - - //this.setReticlePosition(point2d); - - this.clicked = controllerData.triggerClicked[this.hand]; - + Reticle.visible = false; + this.movedAway = false; + this.triggerClicked = controllerData.triggerClicks[this.hand]; this.processControllerTriggers(controllerData); this.updateLaserPointer(controllerData); return true; }; this.exitModule = function() { + this.moveMouseAwayFromTablet(); LaserPointers.disableLaserPointer(this.laserPointer); }; @@ -240,12 +252,12 @@ } - var leftHudOverlayPointer = new HudOverlayPointer(LEFT_HAND); + var leftHudOverlayPointer = new HudOverlayPointer(LEFT_HAND); var rightHudOverlayPointer = new HudOverlayPointer(RIGHT_HAND); var clickMapping = Controller.newMapping('HudOverlayPointer-click'); - clickMapping.from(rightHudOverlayPointer.clicked()).when(rightHudOverlayPointer.hasNotSentClick()).to(Controller.Actions.ReticleClick); - clickMapping.from(leftHudOverlayPointer.clicked()).when(leftHudOverlayPointer.hasNotSentClick()).to(Controller.Actions.ReticleClick); + clickMapping.from(rightHudOverlayPointer.isClicked).to(Controller.Actions.ReticleClick); + clickMapping.from(leftHudOverlayPointer.isClicked).to(Controller.Actions.ReticleClick); clickMapping.enable(); enableDispatcherModule("LeftHudOverlayPointer", leftHudOverlayPointer); diff --git a/scripts/system/controllers/controllerModules/mouseHMD.js b/scripts/system/controllers/controllerModules/mouseHMD.js new file mode 100644 index 0000000000..746fed1246 --- /dev/null +++ b/scripts/system/controllers/controllerModules/mouseHMD.js @@ -0,0 +1,123 @@ +// +// mouseHMD.js +// +// scripts/system/controllers/controllerModules/ +// +// Created by Dante Ruiz 2017-9-22 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +(function() { + var ControllerDispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); + + var WEIGHTING = 1 / 20; // simple moving average over last 20 samples + var ONE_MINUS_WEIGHTING = 1 - WEIGHTING; + var AVERAGE_MOUSE_VELOCITY_FOR_SEEK_TO = 20; + function TimeLock(experation) { + this.experation = experation; + this.last = 0; + this.update = function(time) { + this.last = time || Date.now(); + }; + + this.expired = function(time) { + return ((time || Date.now()) - this.last) > this.experation; + }; + } + + function MouseHMD() { + var _this = this; + this.mouseMoved = false; + this.mouseActivity = new TimeLock(5000); + this.handControllerActivity = new TimeLock(4000); + this.parameters = ControllerDispatcherUtils.makeDispatcherModuleParameters( + 10, + ["mouse"], + [], + 100); + + this.onMouseMove = function() { + _this.updateMouseActivity(); + }; + + this.onMouseClick = function() { + _this.updateMouseActivity(); + }; + + this.updateMouseActivity = function(isClick) { + if (_this.ignoreMouseActivity()) { + return; + } + + if (HMD.active) { + var now = Date.now(); + _this.mouseActivity.update(now); + } + }; + + this.ignoreMouseActivity = function() { + if (!Reticle.allowMouseCapture) { + return true; + } + + var pos = Reticle.position; + if (!pos || (pos.x == -1 && pos.y == -1)) { + return true; + } + + if (!_this.handControllerActivity.expired()) { + print("has not expired"); + return true; + } + + return false; + }; + + this.triggersPressed = function(controllerData, now) { + var onValue = ControllerDispatcherUtils.TRIGGER_ON_VALUE; + var rightHand = ControllerDispatcherUtils.RIGHT_HAND; + var leftHand = ControllerDispatcherUtils.LEFT_HAND; + var leftTriggerValue = controllerData.triggerValues[leftHand]; + var rightTriggerValue = controllerData.triggerValues[rightHand]; + + if (leftTriggerValue > onValue || rightTriggerValue > onValue) { + this.handControllerActivity.update(now); + return true; + } + + return false; + }; + + this.isReady = function(controllerData, deltaTime) { + var now = Date.now(); + this.triggersPressed(controllerData, now); + if ((HMD.active && !this.mouseActivity.expired(now)) && _this.handControllerActivity.expired()) { + Reticle.visible = true; + return ControllerDispatcherUtils.makeRunningValues(true, [], []); + } + if (HMD.active) { + Reticle.visble = false; + } + + return ControllerDispatcherUtils.makeRunningValues(false, [], []); + }; + + this.run = function(controllerData, deltaTime) { + var now = Date.now(); + if (this.mouseActivity.expired(now) || this.triggersPressed(controllerData, now)) { + Reticle.visible = false; + return ControllerDispatcherUtils.makeRunningValues(false, [], []); + } + return ControllerDispatcherUtils.makeRunningValues(true, [], []); + }; + } + + var mouseHMD = new MouseHMD(); + enableDispatcherModule("MouseHMD", mouseHMD); + + Controller.mouseMoveEvent.connect(mouseHMD.onMouseMove); + Controller.mousePressEvent.connect(mouseHMD.onMouseClick); +})(); diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index 695dea7b2c..a671651a9f 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -19,7 +19,7 @@ var CONTOLLER_SCRIPTS = [ "controllerModules/nearParentGrabEntity.js", "controllerModules/nearParentGrabOverlay.js", "controllerModules/nearActionGrabEntity.js", - //"controllerModules/farActionGrabEntity.js", + "controllerModules/farActionGrabEntity.js", "controllerModules/tabletStylusInput.js", "controllerModules/equipEntity.js", "controllerModules/nearTrigger.js", @@ -30,7 +30,8 @@ var CONTOLLER_SCRIPTS = [ "controllerModules/farTrigger.js", "controllerModules/teleport.js", "controllerModules/scaleAvatar.js", - "controllerModules/hudOverlayPointer.js" + "controllerModules/hudOverlayPointer.js", + "controllerModules/mouseHMD.js" ]; var DEBUG_MENU_ITEM = "Debug defaultScripts.js"; From ee9ac3e7f9c4b9d92090b29a6ea9b8af32b7562e Mon Sep 17 00:00:00 2001 From: druiz17 Date: Fri, 22 Sep 2017 15:38:39 -0700 Subject: [PATCH 3/7] undo unnessary changes --- .../src/display-plugins/CompositorHelper.cpp | 16 ---------------- .../src/display-plugins/CompositorHelper.h | 2 -- .../libraries/controllerDispatcherUtils.js | 15 +-------------- 3 files changed, 1 insertion(+), 32 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp index 294a3f6e55..2f57cc29d0 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp @@ -279,18 +279,6 @@ bool CompositorHelper::getReticleOverDesktop() const { return _isOverDesktop; } -bool CompositorHelper::isPositionOverDesktop(glm::vec2 position) const { - if (isHMD()) { - glm::vec2 maxOverlayPosition = _currentDisplayPlugin->getRecommendedUiSize(); - static const glm::vec2 minOverlayPosition; - if (glm::any(glm::lessThan(position, minOverlayPosition)) || - glm::any(glm::greaterThan(position, maxOverlayPosition))) { - return true; - } - } - return _isOverDesktop; -} - glm::vec2 CompositorHelper::getReticleMaximumPosition() const { glm::vec2 result; if (isHMD()) { @@ -480,7 +468,3 @@ void ReticleInterface::setScale(float scale) { auto& cursorManager = Cursor::Manager::instance(); cursorManager.setScale(scale); } - -bool ReticleInterface::isPointOnSystemOverlay(QVariant position) { - return !_compositor->isPositionOverDesktop(vec2FromVariant(position)); -} diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h index 8534de6b9d..b1d2815f65 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h @@ -106,7 +106,6 @@ public: /// if the reticle is pointing to a system overlay (a dialog box for example) then the function returns true otherwise false bool getReticleOverDesktop() const; - bool isPositionOverDesktop(glm::vec2 position) const; void setReticleOverDesktop(bool value) { _isOverDesktop = value; } void setDisplayPlugin(const DisplayPluginPointer& displayPlugin) { _currentDisplayPlugin = displayPlugin; } @@ -196,7 +195,6 @@ public: Q_INVOKABLE void setAllowMouseCapture(bool value) { return _compositor->setAllowMouseCapture(value); } Q_INVOKABLE bool isPointingAtSystemOverlay() { return !_compositor->getReticleOverDesktop(); } - Q_INVOKABLE bool isPointOnSystemOverlay(QVariant position); Q_INVOKABLE bool getVisible() { return _compositor->getReticleVisible(); } Q_INVOKABLE void setVisible(bool visible) { _compositor->setReticleVisible(visible); } diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index 652bd5765b..a05b108b31 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -40,8 +40,7 @@ entityHasActions:true, ensureDynamic:true, findGroupParent:true, - BUMPER_ON_VALUE:true, - isPointingAtUI: true + BUMPER_ON_VALUE:true */ MSECS_PER_SEC = 1000.0; @@ -311,18 +310,6 @@ findGroupParent = function (controllerData, targetProps) { return targetProps; }; -isPointingAtUI = function(intersection) { - var MARGIN = 25; - var reticleMinX = MARGIN, reticleMaxX, reticleMinY = MARGIN, reticleMaxY; - var dims = Controller.getViewportDimensions(); - reticleMaxX = dims.x - MARGIN; - reticleMaxY = dims.y - MARGIN; - var point2d = HMD.overlayFromWorldPoint(intersection.intersection); - point2d.x = Math.max(reticleMinX, Math.min(point2d.x, reticleMaxX)); - point2d.y = Math.max(reticleMinY, Math.min(point2d.y, reticleMaxY)); - return point2d; -} - if (typeof module !== 'undefined') { module.exports = { makeDispatcherModuleParameters: makeDispatcherModuleParameters, From 2c7b8cdb4f9b3b12d1c893c1f4cc840a4bc67cfc Mon Sep 17 00:00:00 2001 From: druiz17 Date: Fri, 22 Sep 2017 16:26:41 -0700 Subject: [PATCH 4/7] fixing script issues --- .../controllerModules/hudOverlayPointer.js | 18 +- .../controllers/controllerModules/mouseHMD.js | 9 +- .../system/controllers/controllerScripts.js | 1 - .../controllers/handControllerPointer.js | 706 ------------------ 4 files changed, 14 insertions(+), 720 deletions(-) delete mode 100644 scripts/system/controllers/handControllerPointer.js diff --git a/scripts/system/controllers/controllerModules/hudOverlayPointer.js b/scripts/system/controllers/controllerModules/hudOverlayPointer.js index fdc5758416..6eaf7f1cf7 100644 --- a/scripts/system/controllers/controllerModules/hudOverlayPointer.js +++ b/scripts/system/controllers/controllerModules/hudOverlayPointer.js @@ -132,15 +132,6 @@ this.reticleMaxY = dims.y - MARGIN; }; - _this.hasNotSentClick = function() { - if (!_this.clicked) { - print("sending clicked"); - _this.clicked = true; - return true; - } - return false; - }; - this.updateLaserPointer = function(controllerData) { var RADIUS = 0.005; var dim = { x: RADIUS, y: RADIUS, z: RADIUS }; @@ -260,8 +251,13 @@ clickMapping.from(leftHudOverlayPointer.isClicked).to(Controller.Actions.ReticleClick); clickMapping.enable(); - enableDispatcherModule("LeftHudOverlayPointer", leftHudOverlayPointer); - enableDispatcherModule("RightHudOverlayPointer", rightHudOverlayPointer); + ControllerDispatcherUtils.enableDispatcherModule("LeftHudOverlayPointer", leftHudOverlayPointer); + ControllerDispatcherUtils.enableDispatcherModule("RightHudOverlayPointer", rightHudOverlayPointer); + function cleanup() { + ControllerDispatcherUtils.disableDispatcherModule("LeftHudOverlayPointer"); + ControllerDispatcherUtils.disbaleDispatcherModule("RightHudOverlayPointer"); + } + Script.scriptEnding.connect(cleanup); })(); diff --git a/scripts/system/controllers/controllerModules/mouseHMD.js b/scripts/system/controllers/controllerModules/mouseHMD.js index 746fed1246..10fe714348 100644 --- a/scripts/system/controllers/controllerModules/mouseHMD.js +++ b/scripts/system/controllers/controllerModules/mouseHMD.js @@ -69,7 +69,6 @@ } if (!_this.handControllerActivity.expired()) { - print("has not expired"); return true; } @@ -116,8 +115,14 @@ } var mouseHMD = new MouseHMD(); - enableDispatcherModule("MouseHMD", mouseHMD); + ControllerDispatcherUtils.enableDispatcherModule("MouseHMD", mouseHMD); Controller.mouseMoveEvent.connect(mouseHMD.onMouseMove); Controller.mousePressEvent.connect(mouseHMD.onMouseClick); + + function cleanup() { + ControllerDispatcherUtils.disableDispatcherModule("MouseHMD"); + } + + Script.scriptEnding.connect(cleanup); })(); diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index a671651a9f..bba305fe40 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -12,7 +12,6 @@ var CONTOLLER_SCRIPTS = [ "squeezeHands.js", "controllerDisplayManager.js", - //"handControllerPointer.js", "grab.js", "toggleAdvancedMovementForHandControllers.js", "controllerDispatcher.js", diff --git a/scripts/system/controllers/handControllerPointer.js b/scripts/system/controllers/handControllerPointer.js deleted file mode 100644 index 1c988bfd34..0000000000 --- a/scripts/system/controllers/handControllerPointer.js +++ /dev/null @@ -1,706 +0,0 @@ -"use strict"; - -// -// handControllerPointer.js -// examples/controllers -// -// Created by Howard Stearns on 2016/04/22 -// Copyright 2016 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -(function() { // BEGIN LOCAL_SCOPE - -// Control the "mouse" using hand controller. (HMD and desktop.) -// First-person only. -// Starts right handed, but switches to whichever is free: Whichever hand was NOT most recently squeezed. -// (For now, the thumb buttons on both controllers are always on.) -// When partially squeezing over a HUD element, a laser or the reticle is shown where the active hand -// controller beam intersects the HUD. - -var activeTrigger; -function isLaserOn() { - return activeTrigger.partial(); -} -Script.include("../libraries/controllers.js"); - -// UTILITIES ------------- -// -function ignore() { } - -// Utility to make it easier to setup and disconnect cleanly. -function setupHandler(event, handler) { - event.connect(handler); - Script.scriptEnding.connect(function () { - event.disconnect(handler); - }); -} - -// If some capability is not available until expiration milliseconds after the last update. -function TimeLock(expiration) { - var last = 0; - this.update = function (optionalNow) { - last = optionalNow || Date.now(); - }; - this.expired = function (optionalNow) { - return ((optionalNow || Date.now()) - last) > expiration; - }; -} - -var handControllerLockOut = new TimeLock(2000); - -function Trigger(label) { - // This part is copied and adapted from handControllerGrab.js. Maybe we should refactor this. - var that = this; - that.label = label; - that.TRIGGER_SMOOTH_RATIO = 0.1; // Time averaging of trigger - 0.0 disables smoothing - that.TRIGGER_OFF_VALUE = 0.10; - that.TRIGGER_ON_VALUE = that.TRIGGER_OFF_VALUE + 0.05; // Squeezed just enough to activate search or near grab - that.rawTriggerValue = 0; - that.triggerValue = 0; // rolling average of trigger value - that.triggerClicked = false; - that.triggerClick = function (value) { that.triggerClicked = value; }; - that.triggerPress = function (value) { that.rawTriggerValue = value; }; - that.updateSmoothedTrigger = function () { // e.g., call once/update for effect - var triggerValue = that.rawTriggerValue; - // smooth out trigger value - that.triggerValue = (that.triggerValue * that.TRIGGER_SMOOTH_RATIO) + - (triggerValue * (1.0 - that.TRIGGER_SMOOTH_RATIO)); - OffscreenFlags.navigationFocusDisabled = that.triggerValue != 0.0; - }; - // Current smoothed state, without hysteresis. Answering booleans. - that.triggerSmoothedClick = function () { - return that.triggerClicked; - }; - that.triggerSmoothedSqueezed = function () { - return that.triggerValue > that.TRIGGER_ON_VALUE; - }; - that.triggerSmoothedReleased = function () { - return that.triggerValue < that.TRIGGER_OFF_VALUE; - }; - - // This part is not from handControllerGrab.js - that.state = null; // tri-state: falsey, 'partial', 'full' - that.update = function () { // update state, called from an update function - var state = that.state; - that.updateSmoothedTrigger(); - - // The first two are independent of previous state: - if (that.triggerSmoothedClick()) { - state = 'full'; - } else if (that.triggerSmoothedReleased()) { - state = null; - } else if (that.triggerSmoothedSqueezed()) { - // Another way to do this would be to have hysteresis in this branch, but that seems to make things harder to use. - // In particular, the vive has a nice detent as you release off of full, and we want that to be a transition from - // full to partial. - state = 'partial'; - } - that.state = state; - }; - // Answer a controller source function (answering either 0.0 or 1.0). - that.partial = function () { - return that.state ? 1.0 : 0.0; // either 'partial' or 'full' - }; - that.full = function () { - return (that.state === 'full') ? 1.0 : 0.0; - }; -} - -// VERTICAL FIELD OF VIEW --------- -// -// Cache the verticalFieldOfView setting and update it every so often. -var verticalFieldOfView, DEFAULT_VERTICAL_FIELD_OF_VIEW = 45; // degrees -function updateFieldOfView() { - verticalFieldOfView = Settings.getValue('fieldOfView') || DEFAULT_VERTICAL_FIELD_OF_VIEW; -} - -// SHIMS ---------- -// -var weMovedReticle = false; -function ignoreMouseActivity() { - // If we're paused, or if change in cursor position is from this script, not the hardware mouse. - if (!Reticle.allowMouseCapture) { - return true; - } - var pos = Reticle.position; - if (!pos || (pos.x == -1 && pos.y == -1)) { - return true; - } - // Only we know if we moved it, which is why this script has to replace depthReticle.js - if (!weMovedReticle) { - return false; - } - weMovedReticle = false; - return true; -} -var MARGIN = 25; -var reticleMinX = MARGIN, reticleMaxX, reticleMinY = MARGIN, reticleMaxY; -function updateRecommendedArea() { - var dims = Controller.getViewportDimensions(); - reticleMaxX = dims.x - MARGIN; - reticleMaxY = dims.y - MARGIN; -} -var setReticlePosition = function (point2d) { - weMovedReticle = true; - point2d.x = Math.max(reticleMinX, Math.min(point2d.x, reticleMaxX)); - point2d.y = Math.max(reticleMinY, Math.min(point2d.y, reticleMaxY)); - Reticle.setPosition(point2d); -}; - -// VISUAL AID ----------- -// Same properties as handControllerGrab search sphere -var LASER_ALPHA = 0.5; -var LASER_SEARCH_COLOR = {red: 10, green: 10, blue: 255}; -var LASER_TRIGGER_COLOR = {red: 250, green: 10, blue: 10}; -var END_DIAMETER = 0.05; -var systemLaserOn = false; - -var triggerPath = { - type: "line3d", - color: LASER_TRIGGER_COLOR, - ignoreRayIntersection: true, - visible: true, - alpha: LASER_ALPHA, - solid: true, - glow: 1.0, - drawHUDLayer: true -} -var triggerEnd = { - type: "sphere", - dimensions: {x: END_DIAMETER, y: END_DIAMETER, z: END_DIAMETER}, - color: LASER_TRIGGER_COLOR, - ignoreRayIntersection: true, - visible: true, - alpha: LASER_ALPHA, - solid: true, - drawHUDLayer: true -} - -var searchPath = { - type: "line3d", - color: LASER_SEARCH_COLOR, - ignoreRayIntersection: true, - visible: true, - alpha: LASER_ALPHA, - solid: true, - glow: 1.0, - drawHUDLayer: true -} -var searchEnd = { - type: "sphere", - dimensions: {x: END_DIAMETER, y: END_DIAMETER, z: END_DIAMETER}, - color: LASER_SEARCH_COLOR, - ignoreRayIntersection: true, - visible: true, - alpha: LASER_ALPHA, - solid: true, - drawHUDLayer: true -} - -var hudRayStates = [{name: "trigger", path: triggerPath, end: triggerEnd}, - {name: "search", path: searchPath, end: searchEnd}]; -// this offset needs to match the one in libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp:378 -var GRAB_POINT_SPHERE_OFFSET_RIGHT = { x: 0.04, y: 0.13, z: 0.039 }; -var GRAB_POINT_SPHERE_OFFSET_LEFT = { x: -0.04, y: 0.13, z: 0.039 }; -var hudRayRight = LaserPointers.createLaserPointer({ - joint: "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", - filter: RayPick.PICK_HUD, - posOffset: GRAB_POINT_SPHERE_OFFSET_RIGHT, - renderStates: hudRayStates, - enabled: true -}); -var hudRayLeft = LaserPointers.createLaserPointer({ - joint: "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", - filter: RayPick.PICK_HUD, - posOffset: GRAB_POINT_SPHERE_OFFSET_LEFT, - renderStates: hudRayStates, - enabled: true -}); - -// NOTE: keep this offset in sync with scripts/system/librarires/controllers.js:57 -var VERTICAL_HEAD_LASER_OFFSET = 0.1; -var hudRayHead = LaserPointers.createLaserPointer({ - joint: "Avatar", - filter: RayPick.PICK_HUD, - posOffset: {x: 0, y: VERTICAL_HEAD_LASER_OFFSET, z: 0}, - renderStates: hudRayStates, - enabled: true -}); - -var mouseRayPick = RayPick.createRayPick({ - joint: "Mouse", - filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, - enabled: true -}); - -function isPointingAtOverlay(optionalHudPosition2d) { - return Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(optionalHudPosition2d || Reticle.position); -} - -// Generalized HUD utilities, with or without HMD: -// This "var" is for documentation. Do not change the value! -var PLANAR_PERPENDICULAR_HUD_DISTANCE = 1; -function calculateRayUICollisionPoint(position, direction, isHands) { - // Answer the 3D intersection of the HUD by the given ray, or falsey if no intersection. - if (HMD.active) { - var laserPointer; - if (isHands) { - laserPointer = activeHand == Controller.Standard.RightHand ? hudRayRight : hudRayLeft; - } else { - laserPointer = hudRayHead; - } - var result = LaserPointers.getPrevRayPickResult(laserPointer); - if (result.type != RayPick.INTERSECTED_NONE) { - return result.intersection; - } else { - return null; - } - } - // interect HUD plane, 1m in front of camera, using formula: - // scale = hudNormal dot (hudPoint - position) / hudNormal dot direction - // intersection = postion + scale*direction - var hudNormal = Quat.getForward(Camera.getOrientation()); - var hudPoint = Vec3.sum(Camera.getPosition(), hudNormal); // must also scale if PLANAR_PERPENDICULAR_HUD_DISTANCE!=1 - var denominator = Vec3.dot(hudNormal, direction); - if (denominator === 0) { - return null; - } // parallel to plane - var numerator = Vec3.dot(hudNormal, Vec3.subtract(hudPoint, position)); - var scale = numerator / denominator; - return Vec3.sum(position, Vec3.multiply(scale, direction)); -} -var DEGREES_TO_HALF_RADIANS = Math.PI / 360; -function overlayFromWorldPoint(point) { - // Answer the 2d pixel-space location in the HUD that covers the given 3D point. - // REQUIRES: that the 3d point be on the hud surface! - // Note that this is based on the Camera, and doesn't know anything about any - // ray that may or may not have been used to compute the point. E.g., the - // overlay point is NOT the intersection of some non-camera ray with the HUD. - if (HMD.active) { - return HMD.overlayFromWorldPoint(point); - } - var cameraToPoint = Vec3.subtract(point, Camera.getPosition()); - var cameraX = Vec3.dot(cameraToPoint, Quat.getRight(Camera.getOrientation())); - var cameraY = Vec3.dot(cameraToPoint, Quat.getUp(Camera.getOrientation())); - var size = Controller.getViewportDimensions(); - var hudHeight = 2 * Math.tan(verticalFieldOfView * DEGREES_TO_HALF_RADIANS); // must adjust if PLANAR_PERPENDICULAR_HUD_DISTANCE!=1 - var hudWidth = hudHeight * size.x / size.y; - var horizontalFraction = (cameraX / hudWidth + 0.5); - var verticalFraction = 1 - (cameraY / hudHeight + 0.5); - var horizontalPixels = size.x * horizontalFraction; - var verticalPixels = size.y * verticalFraction; - return { x: horizontalPixels, y: verticalPixels }; -} - -var gamePad = Controller.findDevice("GamePad"); -function activeHudPoint2dGamePad() { - if (!HMD.active) { - return; - } - var headPosition = MyAvatar.getHeadPosition(); - var headDirection = Quat.getUp(Quat.multiply(MyAvatar.headOrientation, Quat.angleAxis(-90, { x: 1, y: 0, z: 0 }))); - - var hudPoint3d = calculateRayUICollisionPoint(headPosition, headDirection, false); - - if (!hudPoint3d) { - if (Menu.isOptionChecked("Overlays")) { // With our hud resetting strategy, hudPoint3d should be valid here - print('Controller is parallel to HUD'); // so let us know that our assumptions are wrong. - } - return; - } - var hudPoint2d = overlayFromWorldPoint(hudPoint3d); - - // We don't know yet if we'll want to make the cursor or laser visble, but we need to move it to see if - // it's pointing at aQML tool (aka system overlay). - setReticlePosition(hudPoint2d); - - return hudPoint2d; -} - - -function activeHudPoint2d(activeHand) { // if controller is valid, update reticle position and answer 2d point. Otherwise falsey. - var controllerPose = getControllerWorldLocation(activeHand, true); // note: this will return head pose if hand pose is invalid (third eye) - if (!controllerPose.valid) { - return; // Controller is cradled. - } - var controllerPosition = controllerPose.position; - var controllerDirection = Quat.getUp(controllerPose.rotation); - - var hudPoint3d = calculateRayUICollisionPoint(controllerPosition, controllerDirection, true); - if (!hudPoint3d) { - if (Menu.isOptionChecked("Overlays")) { // With our hud resetting strategy, hudPoint3d should be valid here - print('Controller is parallel to HUD'); // so let us know that our assumptions are wrong. - } - return; - } - var hudPoint2d = overlayFromWorldPoint(hudPoint3d); - - // We don't know yet if we'll want to make the cursor or laser visble, but we need to move it to see if - // it's pointing at a QML tool (aka system overlay). - setReticlePosition(hudPoint2d); - return hudPoint2d; -} - -// MOUSE ACTIVITY -------- -// -var isSeeking = false; -var averageMouseVelocity = 0, lastIntegration = 0, lastMouse; -var WEIGHTING = 1 / 20; // simple moving average over last 20 samples -var ONE_MINUS_WEIGHTING = 1 - WEIGHTING; -var AVERAGE_MOUSE_VELOCITY_FOR_SEEK_TO = 20; -function isShakingMouse() { // True if the person is waving the mouse around trying to find it. - var now = Date.now(), mouse = Reticle.position, isShaking = false; - if (lastIntegration && (lastIntegration !== now)) { - var velocity = Vec3.length(Vec3.subtract(mouse, lastMouse)) / (now - lastIntegration); - averageMouseVelocity = (ONE_MINUS_WEIGHTING * averageMouseVelocity) + (WEIGHTING * velocity); - if (averageMouseVelocity > AVERAGE_MOUSE_VELOCITY_FOR_SEEK_TO) { - isShaking = true; - } - } - lastIntegration = now; - lastMouse = mouse; - return isShaking; -} -var NON_LINEAR_DIVISOR = 2; -var MINIMUM_SEEK_DISTANCE = 0.1; -function updateSeeking(doNotStartSeeking) { - if (!doNotStartSeeking && !isLaserOn() && (!Reticle.visible || isShakingMouse())) { - isSeeking = true; - } // e.g., if we're about to turn it on with first movement. - if (!isSeeking) { - return; - } - averageMouseVelocity = lastIntegration = 0; - var lookAt2D = HMD.getHUDLookAtPosition2D(); - if (!lookAt2D) { // If this happens, something has gone terribly wrong. - isSeeking = false; - return; // E.g., if parallel to location in HUD - } - var copy = Reticle.position; - function updateDimension(axis) { - var distanceBetween = lookAt2D[axis] - Reticle.position[axis]; - var move = distanceBetween / NON_LINEAR_DIVISOR; - if (Math.abs(move) < MINIMUM_SEEK_DISTANCE) { - return false; - } - copy[axis] += move; - return true; - } - var okX = !updateDimension('x'), okY = !updateDimension('y'); // Evaluate both. Don't short-circuit. - if (okX && okY) { - isSeeking = false; - } else { - Reticle.setPosition(copy); // Not setReticlePosition - } -} - -var mouseCursorActivity = new TimeLock(5000); -var APPARENT_MAXIMUM_DEPTH = 100.0; // this is a depth at which things all seem sufficiently distant -function updateMouseActivity(isClick) { - if (ignoreMouseActivity()) { - return; - } - var now = Date.now(); - mouseCursorActivity.update(now); - if (isClick) { - return; - } // Bug: mouse clicks should keep going. Just not hand controller clicks - handControllerLockOut.update(now); - Reticle.visible = true; -} -function expireMouseCursor(now) { - if (!isPointingAtOverlay() && mouseCursorActivity.expired(now)) { - Reticle.visible = false; - } -} -function hudReticleDistance() { // 3d distance from camera to the reticle position on hud - // (The camera is only in the center of the sphere on reset.) - var reticlePositionOnHUD = HMD.worldPointFromOverlay(Reticle.position); - return Vec3.distance(reticlePositionOnHUD, HMD.position); -} - -function maybeAdjustReticleDepth() { - if (HMD.active) { // set depth - if (isPointingAtOverlay()) { - Reticle.depth = hudReticleDistance(); - } - } -} -var ADJUST_RETICLE_DEPTH_INTERVAL = 50; // 20hz -Script.setInterval(maybeAdjustReticleDepth,ADJUST_RETICLE_DEPTH_INTERVAL); - -function onMouseMove() { - // Display cursor at correct depth (as in depthReticle.js), and updateMouseActivity. - if (ignoreMouseActivity()) { - return; - } - - if (HMD.active) { // set depth - updateSeeking(); - if (isPointingAtOverlay()) { - Reticle.depth = hudReticleDistance(); - } else { - var result = RayPick.getPrevRayPickResult(mouseRayPick); - Reticle.depth = result.intersects ? result.distance : APPARENT_MAXIMUM_DEPTH; - } - } - updateMouseActivity(); // After the above, just in case the depth movement is awkward when becoming visible. -} -function onMouseClick() { - updateMouseActivity(true); -} -setupHandler(Controller.mouseMoveEvent, onMouseMove); -setupHandler(Controller.mousePressEvent, onMouseClick); -setupHandler(Controller.mouseDoublePressEvent, onMouseClick); - -// CONTROLLER MAPPING --------- -// - -var leftTrigger = new Trigger('left'); -var rightTrigger = new Trigger('right'); -activeTrigger = rightTrigger; -var activeHand = Controller.Standard.RightHand; -var LEFT_HUD_LASER = 1; -var RIGHT_HUD_LASER = 2; -var BOTH_HUD_LASERS = LEFT_HUD_LASER + RIGHT_HUD_LASER; -var activeHudLaser = RIGHT_HUD_LASER; -function toggleHand() { // unequivocally switch which hand controls mouse position - if (activeHand === Controller.Standard.RightHand) { - activeHand = Controller.Standard.LeftHand; - activeTrigger = leftTrigger; - activeHudLaser = LEFT_HUD_LASER; - } else { - activeHand = Controller.Standard.RightHand; - activeTrigger = rightTrigger; - activeHudLaser = RIGHT_HUD_LASER; - } - clearSystemLaser(); -} -function makeToggleAction(hand) { // return a function(0|1) that makes the specified hand control mouse when 1 - return function (on) { - if (on && (activeHand !== hand)) { - toggleHand(); - } - }; -} - -var clickMapping = Controller.newMapping('handControllerPointer-click'); -Script.scriptEnding.connect(clickMapping.disable); - -// Gather the trigger data for smoothing. -clickMapping.from(Controller.Standard.RT).peek().to(rightTrigger.triggerPress); -clickMapping.from(Controller.Standard.LT).peek().to(leftTrigger.triggerPress); -clickMapping.from(Controller.Standard.RTClick).peek().to(rightTrigger.triggerClick); -clickMapping.from(Controller.Standard.LTClick).peek().to(leftTrigger.triggerClick); -// Full smoothed trigger is a click. -function isPointingAtOverlayStartedNonFullTrigger(trigger) { - // true if isPointingAtOverlay AND we were NOT full triggered when we became so. - // The idea is to not count clicks when we're full-triggering and reach the edge of a window. - var lockedIn = false; - return function () { - if (trigger !== activeTrigger) { - return lockedIn = false; - } - if (!isPointingAtOverlay()) { - return lockedIn = false; - } - if (lockedIn) { - return true; - } - lockedIn = !trigger.full(); - return lockedIn; - } -} -clickMapping.from(rightTrigger.full).when(isPointingAtOverlayStartedNonFullTrigger(rightTrigger)).to(Controller.Actions.ReticleClick); -clickMapping.from(leftTrigger.full).when(isPointingAtOverlayStartedNonFullTrigger(leftTrigger)).to(Controller.Actions.ReticleClick); -// The following is essentially like Left and Right versions of -// clickMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(Controller.Actions.ContextMenu); -// except that we first update the reticle position from the appropriate hand position, before invoking the . -var wantsMenu = 0; -clickMapping.from(function () { return wantsMenu; }).to(Controller.Actions.ContextMenu); -clickMapping.from(Controller.Standard.RightSecondaryThumb).peek().to(function (clicked) { - if (clicked) { - //activeHudPoint2d(Controller.Standard.RightHand); - Messages.sendLocalMessage("toggleHand", Controller.Standard.RightHand); - } - wantsMenu = clicked; -}); -clickMapping.from(Controller.Standard.LeftSecondaryThumb).peek().to(function (clicked) { - if (clicked) { - //activeHudPoint2d(Controller.Standard.LeftHand); - Messages.sendLocalMessage("toggleHand", Controller.Standard.LeftHand); - } - wantsMenu = clicked; -}); -clickMapping.from(Controller.Standard.Start).peek().to(function (clicked) { - if (clicked) { - //activeHudPoint2dGamePad(); - var noHands = -1; - Messages.sendLocalMessage("toggleHand", Controller.Standard.LeftHand); - } - - wantsMenu = clicked; -}); -clickMapping.from(Controller.Hardware.Keyboard.RightMouseClicked).peek().to(function () { - // Allow the reticle depth to be set correctly: - // Wait a tick for the context menu to be displayed, and then simulate a (non-hand-controller) mouse move - // so that the system updates qml state (Reticle.pointingAtSystemOverlay) before it gives us a mouseMove. - // We don't want the system code to always do this for us, because, e.g., we do not want to get a mouseMove - // after the Left/RightSecondaryThumb gives us a context menu. Only from the mouse. - Script.setTimeout(function () { - var noHands = -1; - Messages.sendLocalMessage("toggleHand", noHands); - Reticle.setPosition(Reticle.position); - }, 0); -}); -// Partial smoothed trigger is activation. -clickMapping.from(rightTrigger.partial).to(makeToggleAction(Controller.Standard.RightHand)); -clickMapping.from(leftTrigger.partial).to(makeToggleAction(Controller.Standard.LeftHand)); -clickMapping.enable(); - -var HIFI_POINTER_DISABLE_MESSAGE_CHANNEL = "Hifi-Pointer-Disable"; -var isPointerEnabled = true; - -function clearSystemLaser() { - if (!systemLaserOn) { - return; - } - HMD.deactivateHMDHandMouse(); - LaserPointers.setRenderState(hudRayRight, ""); - LaserPointers.setRenderState(hudRayLeft, ""); - LaserPointers.setRenderState(hudRayHead, ""); - systemLaserOn = false; - weMovedReticle = true; -} -function setColoredLaser() { // answer trigger state if lasers supported, else falsey. - var mode = (activeTrigger.state === 'full') ? 'trigger' : 'search'; - - if (!systemLaserOn) { - HMD.activateHMDHandMouse(); - } - - var pose = Controller.getPoseValue(activeHand); - if (!pose.valid) { - LaserPointers.setRenderState(hudRayRight, ""); - LaserPointers.setRenderState(hudRayLeft, ""); - LaserPointers.setRenderState(hudRayHead, mode); - return true; - } - - var right = activeHand == Controller.Standard.RightHand; - LaserPointers.setRenderState(hudRayRight, right ? mode : ""); - LaserPointers.setRenderState(hudRayLeft, right ? "" : mode); - LaserPointers.setRenderState(hudRayHead, ""); - - return activeTrigger.state; -} - -// MAIN OPERATIONS ----------- -// -function update() { - var now = Date.now(); - function off() { - expireMouseCursor(); - clearSystemLaser(); - } - - updateSeeking(true); - if (!handControllerLockOut.expired(now)) { - return off(); // Let them use mouse in peace. - } - - if ((!Window.hasFocus() && !HMD.active) || !Reticle.allowMouseCapture) { - // In desktop it's pretty clear when another app is on top. In that case we bail, because - // hand controllers might be sputtering "valid" data and that will keep someone from deliberately - // using the mouse on another app. (Fogbugz case 546.) - // However, in HMD, you might not realize you're not on top, and you wouldn't be able to operate - // other apps anyway. So in that case, we DO keep going even though we're not on top. (Fogbugz 1831.) - return off(); // Don't mess with other apps or paused mouse activity - } - - leftTrigger.update(); - rightTrigger.update(); - if (!activeTrigger.state) { - return off(); // No trigger - } - - if (getGrabCommunications()) { - return off(); - } - - - var hudPoint2d = activeHudPoint2d(activeHand); - if (!hudPoint2d) { - return off(); - } - - // If there's a HUD element at the (newly moved) reticle, just make it visible and bail. - if (isPointingAtOverlay(hudPoint2d) && isPointerEnabled) { - if (HMD.active) { - Reticle.depth = hudReticleDistance(); - - var pose = Controller.getPoseValue(activeHand); - if (!pose.valid) { - var mode = (activeTrigger.state === 'full') ? 'trigger' : 'search'; - if (!systemLaserOn) { - HMD.activateHMDHandMouse(); - } - LaserPointers.setRenderState(hudRayHead, mode); - } - } - - if (activeTrigger.state && (!systemLaserOn || (systemLaserOn !== activeTrigger.state))) { // last=>wrong color - // If the active plugin doesn't implement hand lasers, show the mouse reticle instead. - systemLaserOn = setColoredLaser(); - Reticle.visible = !systemLaserOn; - } else if ((systemLaserOn || Reticle.visible) && !activeTrigger.state) { - clearSystemLaser(); - Reticle.visible = false; - } - return; - } - // We are not pointing at a HUD element (but it could be a 3d overlay). - clearSystemLaser(); - Reticle.visible = false; -} - -// Check periodically for changes to setup. -var SETTINGS_CHANGE_RECHECK_INTERVAL = 10 * 1000; // 10 seconds -function checkSettings() { - updateFieldOfView(); - updateRecommendedArea(); -} -checkSettings(); - -// Enable/disable pointer. -function handleMessages(channel, message, sender) { - if (sender === MyAvatar.sessionUUID && channel === HIFI_POINTER_DISABLE_MESSAGE_CHANNEL) { - var data = JSON.parse(message); - if (data.pointerEnabled !== undefined) { - print("pointerEnabled: " + data.pointerEnabled); - isPointerEnabled = data.pointerEnabled; - } - } -} - -Messages.subscribe(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL); -Messages.messageReceived.connect(handleMessages); - -var settingsChecker = Script.setInterval(checkSettings, SETTINGS_CHANGE_RECHECK_INTERVAL); -Script.update.connect(update); -Script.scriptEnding.connect(function () { - Messages.unsubscribe(HIFI_POINTER_DISABLE_MESSAGE_CHANNEL); - Messages.messageReceived.disconnect(handleMessages); - Script.clearInterval(settingsChecker); - Script.update.disconnect(update); - OffscreenFlags.navigationFocusDisabled = false; - LaserPointers.removeLaserPointer(hudRayRight); - LaserPointers.removeLaserPointer(hudRayLeft); - LaserPointers.removeLaserPointer(hudRayHead); - HMD.deactivateHMDHandMouse(); -}); - -}()); // END LOCAL_SCOPE From b8ee60a394d01cdf4b3813e495924345c081e33e Mon Sep 17 00:00:00 2001 From: druiz17 Date: Fri, 22 Sep 2017 17:13:48 -0700 Subject: [PATCH 5/7] fix scripting error --- scripts/system/libraries/controllerDispatcherUtils.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/system/libraries/controllerDispatcherUtils.js b/scripts/system/libraries/controllerDispatcherUtils.js index a05b108b31..6df5fa9975 100644 --- a/scripts/system/libraries/controllerDispatcherUtils.js +++ b/scripts/system/libraries/controllerDispatcherUtils.js @@ -318,7 +318,6 @@ if (typeof module !== 'undefined') { makeRunningValues: makeRunningValues, LEFT_HAND: LEFT_HAND, RIGHT_HAND: RIGHT_HAND, - isPointingAtUI: isPointingAtUI, BUMPER_ON_VALUE: BUMPER_ON_VALUE, projectOntoOverlayXYPlane: projectOntoOverlayXYPlane, projectOntoEntityXYPlane: projectOntoEntityXYPlane, From b1b31444f0859c8a864369134009791cc10ecfcc Mon Sep 17 00:00:00 2001 From: druiz17 Date: Mon, 25 Sep 2017 11:34:18 -0700 Subject: [PATCH 6/7] fix mouse visiblity --- scripts/system/controllers/controllerDispatcher.js | 9 ++++++++- .../controllers/controllerModules/mouseHMD.js | 13 ++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/controllerDispatcher.js b/scripts/system/controllers/controllerDispatcher.js index 22987245a4..13789a4a8e 100644 --- a/scripts/system/controllers/controllerDispatcher.js +++ b/scripts/system/controllers/controllerDispatcher.js @@ -236,6 +236,7 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); RayPick.getPrevRayPickResult(_this.leftControllerHudRayPick), RayPick.getPrevRayPickResult(_this.rightControllerHudRayPick) ]; + var mouseRayPick = RayPick.getPrevRayPickResult(_this.mouseRayPick); // if the pickray hit something very nearby, put it into the nearby entities list for (h = LEFT_HAND; h <= RIGHT_HAND; h++) { @@ -274,7 +275,8 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); nearbyEntityPropertiesByID: nearbyEntityPropertiesByID, nearbyOverlayIDs: nearbyOverlayIDs, rayPicks: rayPicks, - hudRayPicks: hudRayPicks + hudRayPicks: hudRayPicks, + mouseRayPick: mouseRayPick }; if (PROFILE) { Script.endProfileRange("dispatch.gather"); @@ -390,6 +392,11 @@ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); maxDistance: DEFAULT_SEARCH_SPHERE_DISTANCE, posOffset: getGrabPointSphereOffset(Controller.Standard.RightHand, true) }); + this.mouseRayPick = RayPick.createRayPick({ + joint: "Mouse", + filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, + enabled: true + }); this.handleHandMessage = function(channel, message, sender) { var data; diff --git a/scripts/system/controllers/controllerModules/mouseHMD.js b/scripts/system/controllers/controllerModules/mouseHMD.js index 10fe714348..f60136ed4e 100644 --- a/scripts/system/controllers/controllerModules/mouseHMD.js +++ b/scripts/system/controllers/controllerModules/mouseHMD.js @@ -58,6 +58,16 @@ } }; + this.adjustReticleDepth = function(controllerData) { + if (Reticle.isPointingAtSystemOverlay(Reticle.position)) { + var reticlePositionOnHUD = HMD.worldPointFromOverlay(Reticle.position); + Reticle.depth = Vec3.distance(reticlePositionOnHUD, HMD.position); + } else { + var APPARENT_MAXIMUM_DEPTH = 100.0; + var result = controllerData.mouseRayPick; + Reticle.depth = result.intersects ? result.distance : APPARENT_MAXIMUM_DEPTH; + } + } this.ignoreMouseActivity = function() { if (!Reticle.allowMouseCapture) { return true; @@ -98,7 +108,7 @@ return ControllerDispatcherUtils.makeRunningValues(true, [], []); } if (HMD.active) { - Reticle.visble = false; + Reticle.visible = false; } return ControllerDispatcherUtils.makeRunningValues(false, [], []); @@ -110,6 +120,7 @@ Reticle.visible = false; return ControllerDispatcherUtils.makeRunningValues(false, [], []); } + this.adjustReticleDepth(controllerData); return ControllerDispatcherUtils.makeRunningValues(true, [], []); }; } From ec40df711d8f2b9a3165bd07f43a0bcfcf78b5e1 Mon Sep 17 00:00:00 2001 From: druiz17 Date: Mon, 25 Sep 2017 14:31:13 -0700 Subject: [PATCH 7/7] fix tablet grabbing and eslint changes --- .../controllerModules/hudOverlayPointer.js | 51 +++++++------------ .../controllers/controllerModules/mouseHMD.js | 14 +++-- .../controllerModules/tabletStylusInput.js | 9 +++- 3 files changed, 31 insertions(+), 43 deletions(-) diff --git a/scripts/system/controllers/controllerModules/hudOverlayPointer.js b/scripts/system/controllers/controllerModules/hudOverlayPointer.js index 6eaf7f1cf7..487e491201 100644 --- a/scripts/system/controllers/controllerModules/hudOverlayPointer.js +++ b/scripts/system/controllers/controllerModules/hudOverlayPointer.js @@ -10,10 +10,17 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -/* global Script, HMD, WebTablet, UIWebTablet, UserActivityLogger, Settings, Entities, Messages, Tablet, Overlays, - MyAvatar, Menu, AvatarInputs, Vec3 */ +/* global Script, Controller, LaserPointers, RayPick, RIGHT_HAND, LEFT_HAND, Mat4, MyAvatar, Vec3, Camera, Quat, + getGrabPointSphereOffset, getEnabledModuleByName, makeRunningValues, Entities, NULL_UUID, + enableDispatcherModule, disableDispatcherModule, entityIsDistanceGrabbable, + makeDispatcherModuleParameters, MSECS_PER_SEC, HAPTIC_PULSE_STRENGTH, HAPTIC_PULSE_DURATION, + PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, + AVATAR_SELF_ID, DEFAULT_SEARCH_SPHERE_DISTANCE, TRIGGER_OFF_VALUE, TRIGGER_ON_VALUE, ZERO_VEC, ensureDynamic, + getControllerWorldLocation, projectOntoEntityXYPlane, ContextOverlay, HMD, Reticle, Overlays, isPointingAtUI + +*/ (function() { - Script.include("/~/system/libraries/controllers.js") + Script.include("/~/system/libraries/controllers.js"); var ControllerDispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); var halfPath = { type: "line3d", @@ -82,18 +89,8 @@ {name: "hold", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: holdPath} ]; - - // triggered when stylus presses a web overlay/entity - var HAPTIC_STYLUS_STRENGTH = 1.0; - var HAPTIC_STYLUS_DURATION = 20.0; var MARGIN = 25; - function distance2D(a, b) { - var dx = (a.x - b.x); - var dy = (a.y - b.y); - return Math.sqrt(dx * dx + dy * dy); - } - function HudOverlayPointer(hand) { var _this = this; this.hand = hand; @@ -118,15 +115,11 @@ return _this.triggerClicked; }; - this.getOtherModule = function() { - return (this.hand === RIGHT_HAND) ? leftOverlayLaserInput : rightOverlayLaserInput; - }; - this.handToController = function() { return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; }; - this.updateRecommendedArea = function() { + this.updateRecommendedArea = function() { var dims = Controller.getViewportDimensions(); this.reticleMaxX = dims.x - MARGIN; this.reticleMaxY = dims.y - MARGIN; @@ -159,7 +152,7 @@ } }; - 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)); @@ -176,14 +169,6 @@ return (rayPick.objectID === HMD.tabletScreenID || rayPick.objectID === HMD.homeButtonID); }; - this.moveMouseAwayFromTablet = function() { - if (!this.movedAway) { - var point = {x: 25, y: 25}; - // this.setReticlePosition(point); - this.movedAway = true; - } - } - this.processLaser = function(controllerData) { var controllerLocation = controllerData.controllerLocations[this.hand]; if ((controllerData.triggerValues[this.hand] < ControllerDispatcherUtils.TRIGGER_ON_VALUE || !controllerLocation.valid) || @@ -192,7 +177,6 @@ return false; } var hudRayPick = controllerData.hudRayPicks[this.hand]; - var controllerLocation = controllerData.controllerLocations[this.hand]; var point2d = this.calculateNewReticlePosition(hudRayPick.intersection); this.setReticlePosition(point2d); if (!Reticle.isPointingAtSystemOverlay(point2d)) { @@ -208,10 +192,9 @@ }; this.exitModule = function() { - this.moveMouseAwayFromTablet(); LaserPointers.disableLaserPointer(this.laserPointer); }; - + this.isReady = function (controllerData) { if (this.processLaser(controllerData)) { return ControllerDispatcherUtils.makeRunningValues(true, [], []); @@ -240,12 +223,12 @@ enabled: true, defaultRenderStates: defaultRenderStates }); - } + } - - var leftHudOverlayPointer = new HudOverlayPointer(LEFT_HAND); + + var leftHudOverlayPointer = new HudOverlayPointer(LEFT_HAND); var rightHudOverlayPointer = new HudOverlayPointer(RIGHT_HAND); - + var clickMapping = Controller.newMapping('HudOverlayPointer-click'); clickMapping.from(rightHudOverlayPointer.isClicked).to(Controller.Actions.ReticleClick); clickMapping.from(leftHudOverlayPointer.isClicked).to(Controller.Actions.ReticleClick); diff --git a/scripts/system/controllers/controllerModules/mouseHMD.js b/scripts/system/controllers/controllerModules/mouseHMD.js index f60136ed4e..9ccf4912a1 100644 --- a/scripts/system/controllers/controllerModules/mouseHMD.js +++ b/scripts/system/controllers/controllerModules/mouseHMD.js @@ -13,9 +13,6 @@ (function() { var ControllerDispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); - var WEIGHTING = 1 / 20; // simple moving average over last 20 samples - var ONE_MINUS_WEIGHTING = 1 - WEIGHTING; - var AVERAGE_MOUSE_VELOCITY_FOR_SEEK_TO = 20; function TimeLock(experation) { this.experation = experation; this.last = 0; @@ -27,7 +24,7 @@ return ((time || Date.now()) - this.last) > this.experation; }; } - + function MouseHMD() { var _this = this; this.mouseMoved = false; @@ -67,14 +64,15 @@ var result = controllerData.mouseRayPick; Reticle.depth = result.intersects ? result.distance : APPARENT_MAXIMUM_DEPTH; } - } + }; + this.ignoreMouseActivity = function() { if (!Reticle.allowMouseCapture) { return true; } var pos = Reticle.position; - if (!pos || (pos.x == -1 && pos.y == -1)) { + if (!pos || (pos.x === -1 && pos.y === -1)) { return true; } @@ -99,7 +97,7 @@ return false; }; - + this.isReady = function(controllerData, deltaTime) { var now = Date.now(); this.triggersPressed(controllerData, now); @@ -113,7 +111,7 @@ return ControllerDispatcherUtils.makeRunningValues(false, [], []); }; - + this.run = function(controllerData, deltaTime) { var now = Date.now(); if (this.mouseActivity.expired(now) || this.triggersPressed(controllerData, now)) { diff --git a/scripts/system/controllers/controllerModules/tabletStylusInput.js b/scripts/system/controllers/controllerModules/tabletStylusInput.js index 9d01ceef65..def958b223 100644 --- a/scripts/system/controllers/controllerModules/tabletStylusInput.js +++ b/scripts/system/controllers/controllerModules/tabletStylusInput.js @@ -248,10 +248,17 @@ Script.include("/~/system/libraries/controllers.js"); } }; + this.nearGrabWantsToRun = function(controllerData) { + var moduleName = this.hand === RIGHT_HAND ? "RightNearParentingGrabOverlay" : "LeftNearParentingGrabOverlay"; + var module = getEnabledModuleByName(moduleName); + var ready = module ? module.isReady(controllerData) : makeRunningValues(false, [], []); + return ready.active; + }; + this.processStylus = function(controllerData) { this.updateStylusTip(); - if (!this.stylusTip.valid || this.overlayLaserActive(controllerData)) { + if (!this.stylusTip.valid || this.overlayLaserActive(controllerData) || this.nearGrabWantsToRun(controllerData)) { this.pointFinger(false); this.hideStylus(); return false;