diff --git a/scripts/system/controllers/handControllerPointer.js b/scripts/system/controllers/handControllerPointer.js index 229aa79fed..ed062018fe 100644 --- a/scripts/system/controllers/handControllerPointer.js +++ b/scripts/system/controllers/handControllerPointer.js @@ -27,6 +27,7 @@ // On Windows, the upper left corner of Interface must be in the upper left corner of the screen, and the title bar must be 50px high. (System bug.) // While hardware mouse move switches to mouse move, hardware mouse click (without amove) does not. + // UTILITIES ------------- // @@ -63,35 +64,6 @@ function LatchedToggle(onFunction, offFunction, state) { }; } -// Code copied and adapted from handControllerGrab.js. We should refactor this. -function Trigger() { - var TRIGGER_SMOOTH_RATIO = 0.1; // Time averaging of trigger - 0.0 disables smoothing - var TRIGGER_ON_VALUE = 0.4; // Squeezed just enough to activate search or near grab - var TRIGGER_GRAB_VALUE = 0.85; // Squeezed far enough to complete distant grab - var TRIGGER_OFF_VALUE = 0.15; - var that = this; - that.triggerValue = 0; // rolling average of trigger value - that.rawTriggerValue = 0; - that.triggerPress = function (value) { - that.rawTriggerValue = value; - }; - that.updateSmoothedTrigger = function () { - var triggerValue = that.rawTriggerValue; - // smooth out trigger value - that.triggerValue = (that.triggerValue * TRIGGER_SMOOTH_RATIO) + - (triggerValue * (1.0 - TRIGGER_SMOOTH_RATIO)); - }; - that.triggerSmoothedGrab = function () { - return that.triggerValue > TRIGGER_GRAB_VALUE; - }; - that.triggerSmoothedSqueezed = function () { - return that.triggerValue > TRIGGER_ON_VALUE; - }; - that.triggerSmoothedReleased = function () { - return that.triggerValue < TRIGGER_OFF_VALUE; - }; -} - // VERTICAL FIELD OF VIEW --------- // // Cache the verticalFieldOfView setting and update it every so often. @@ -205,7 +177,7 @@ function updateSeeking() { averageMouseVelocity = lastIntegration = 0; var lookAt2D = HMD.getHUDLookAtPosition2D(); if (!lookAt2D) { return; } // E.g., if parallel to location in HUD - var copy = Reticle.position; // Idiomatic javascript would let us side effect the reticle, but this is a copy. + var copy = Reticle.position; function updateDimension(axis) { var distanceBetween = lookAt2D[axis] - Reticle.position[axis]; var move = distanceBetween / NON_LINEAR_DIVISOR; @@ -216,7 +188,7 @@ function updateSeeking() { if (!updateDimension('x') && !updateDimension('y')) { isSeeking = false; } else { - Reticle.position = copy; + Reticle.position(copy); } } @@ -242,10 +214,11 @@ function onMouseMove() { if (HMD.active) { // set depth updateSeeking(); if (isPointingAtOverlay()) { - Reticle.depth = SPHERICAL_HUD_DISTANCE; // NOT CORRECT IF WE SWITCH TO OFFSET SPHERE! + Reticle.setDepth(SPHERICAL_HUD_DISTANCE); // NOT CORRECT IF WE SWITCH TO OFFSET SPHERE! } else { var result = findRayIntersection(Camera.computePickRay(Reticle.position.x, Reticle.position.y)); - Reticle.depth = result.intersects ? result.distance : APPARENT_MAXIMUM_DEPTH; + var depth = result.intersects ? result.distance : APPARENT_MAXIMUM_DEPTH; + Reticle.setDepth(depth); } } updateMouseActivity(); // After the above, just in case the depth movement is awkward when becoming visible. @@ -259,10 +232,15 @@ setupHandler(Controller.mouseDoublePressEvent, onMouseClick); // CONTROLLER MAPPING --------- // -// Synthesize left and right mouse click from controller, and get trigger values matching handControllerGrab. -var triggerMapping; -var leftTrigger = new Trigger(); -var rightTrigger = new Trigger(); + +var activeHand = Controller.Standard.RightHand; +function toggleHand() { + if (activeHand === Controller.Standard.RightHand) { + activeHand = Controller.Standard.LeftHand; + } else { + activeHand = Controller.Standard.RightHand; + } +} // Create clickMappings as needed, on demand. var clickMappings = {}, clickMapping, clickMapToggle; @@ -273,7 +251,6 @@ function checkHardware() { print('Setting mapping for new controller hardware:', newHardware); if (clickMapToggle) { clickMapToggle.setState(false); - triggerMapping.disable(); // FIX SYSTEM BUG: This does not work when hardware changes. Window.alert("This isn't likely to work because of " + 'https://app.asana.com/0/26225263936266/118428633439654\n' + @@ -281,24 +258,39 @@ function checkHardware() { } hardware = newHardware; if (clickMappings[hardware]) { - clickMapping = clickMappings[hardware].click; - triggerMapping = clickMappings[hardware].trigger; + clickMapping = clickMappings[hardware]; } else { clickMapping = Controller.newMapping(Script.resolvePath('') + '-click-' + hardware); Script.scriptEnding.connect(clickMapping.disable); function mapToAction(button, action) { clickMapping.from(Controller.Hardware[hardware][button]).peek().to(Controller.Actions[action]); } + function makeHandToggle(button, hand, optionalWhen) { + var whenThunk = optionalWhen || function () { return true; }; + function maybeToggle() { + if (activeHand !== Controller.Standard[hand]) { + toggleHand(); + } + + } + clickMapping.from(Controller.Hardware[hardware][button]).peek().when(whenThunk).to(maybeToggle); + } function makeViveWhen(click, x, y) { var viveClick = Controller.Hardware.Vive[click], - viveX = Controller.Hardware.Vive[x], - viveY = Controller.Hardware.Vive[y]; + viveX = Controller.Standard[x], // Standard after filtering by mapping + viveY = Controller.Standard[y]; return function () { - return Controller.getValue(viveClick) && !Controller.getValue(viveX) && !Controller.getValue(viveY); + var clickValue = Controller.getValue(viveClick); + var xValue = Controller.getValue(viveX); + var yValue = Controller.getValue(viveY); + return clickValue && !xValue && !yValue; }; } switch (hardware) { case 'Hydra': + makeHandToggle('R3', 'RightHand'); + makeHandToggle('L3', 'LeftHand'); + mapToAction('R3', 'ReticleClick'); mapToAction('L3', 'ReticleClick'); mapToAction('R4', 'ContextMenu'); @@ -306,41 +298,21 @@ function checkHardware() { break; case 'Vive': // When touchpad click is NOT treated as movement, treat as left click + makeHandToggle('RS', 'RightHand', makeViveWhen('RS', 'RX', 'RY')); + makeHandToggle('LS', 'LeftHand', makeViveWhen('LS', 'LX', 'LY')); clickMapping.from(Controller.Hardware.Vive.RS).when(makeViveWhen('RS', 'RX', 'RY')).to(Controller.Actions.ReticleClick); clickMapping.from(Controller.Hardware.Vive.LS).when(makeViveWhen('LS', 'LX', 'LY')).to(Controller.Actions.ReticleClick); mapToAction('RightApplicationMenu', 'ContextMenu'); mapToAction('LeftApplicationMenu', 'ContextMenu'); break; } - - triggerMapping = Controller.newMapping(Script.resolvePath('') + '-trigger-' + hardware); - Script.scriptEnding.connect(triggerMapping.disable); - triggerMapping.from(Controller.Standard.RT).peek().to(rightTrigger.triggerPress); - triggerMapping.from(Controller.Standard.LT).peek().to(leftTrigger.triggerPress); - - clickMappings[hardware] = {click: clickMapping, trigger: triggerMapping}; + clickMappings[hardware] = clickMapping; } clickMapToggle = new LatchedToggle(clickMapping.enable, clickMapping.disable); clickMapToggle.setState(true); - triggerMapping.enable(); } checkHardware(); -var activeHand = Controller.Standard.RightHand; -var activeTrigger = rightTrigger; -var inactiveTrigger = leftTrigger; -function toggleHand() { - if (activeHand === Controller.Standard.RightHand) { - activeHand = Controller.Standard.LeftHand; - activeTrigger = leftTrigger; - inactiveTrigger = rightTrigger; - } else { - activeHand = Controller.Standard.RightHand; - activeTrigger = rightTrigger; - inactiveTrigger = leftTrigger; - } -} - // VISUAL AID ----------- // Same properties as handControllerGrab search sphere var BALL_SIZE = 0.011; @@ -402,15 +374,11 @@ function updateVisualization(controllerPosition, controllerDirection, hudPositio // function update() { var now = Date.now(); - leftTrigger.updateSmoothedTrigger(); - rightTrigger.updateSmoothedTrigger(); if (!handControllerLockOut.expired(now)) { return turnOffVisualization(); } // Let them use mouse it in peace. - - if (activeTrigger.triggerSmoothedSqueezed() && !inactiveTrigger.triggerSmoothedSqueezed()) { toggleHand(); } - if (!Menu.isOptionChecked("First Person")) { return turnOffVisualization(); } // What to do? menus can be behind hand! var controllerPose = Controller.getPoseValue(activeHand); - if (!controllerPose.valid) { return turnOffVisualization(); } // Controller is cradled. + // Vive is effectively invalid when not in HMD + if (!controllerPose.valid || ((hardware === 'Vive') && !HMD.active)) { return turnOffVisualization(); } // Controller is cradled. var controllerPosition = Vec3.sum(Vec3.multiplyQbyV(MyAvatar.orientation, controllerPose.translation), MyAvatar.position); // This gets point direction right, but if you want general quaternion it would be more complicated: