| @@ -0,0 +1,255 @@ |
| | 1 | // |
| | 2 | // hudOverlayPointer.js |
| | 3 | // |
| | 4 | // scripts/system/controllers/controllerModules/ |
| | 5 | // |
| | 6 | // Created by Dante Ruiz 2017-9-21 |
| | 7 | // Copyright 2017 High Fidelity, Inc. |
| | 8 | // |
| | 9 | // Distributed under the Apache License, Version 2.0. |
| | 10 | // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html |
| | 11 | // |
| | 12 | |
| | 13 | /* global Script, HMD, WebTablet, UIWebTablet, UserActivityLogger, Settings, Entities, Messages, Tablet, Overlays, |
| | 14 | MyAvatar, Menu, AvatarInputs, Vec3 */ |
| | 15 | (function() { |
| | 16 | Script.include("/~/system/libraries/controllers.js") |
| | 17 | var ControllerDispatcherUtils = Script.require("/~/system/libraries/controllerDispatcherUtils.js"); |
| | 18 | var halfPath = { |
| | 19 | type: "line3d", |
| | 20 | color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE, |
| | 21 | visible: true, |
| | 22 | alpha: 1, |
| | 23 | solid: true, |
| | 24 | glow: 1.0, |
| | 25 | lineWidth: 5, |
| | 26 | ignoreRayIntersection: true, // always ignore this |
| | 27 | drawHUDLayer: true, // Even when burried inside of something, show it. |
| | 28 | parentID: AVATAR_SELF_ID |
| | 29 | }; |
| | 30 | var halfEnd = { |
| | 31 | type: "sphere", |
| | 32 | solid: true, |
| | 33 | color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE, |
| | 34 | alpha: 0.9, |
| | 35 | ignoreRayIntersection: true, |
| | 36 | drawHUDLayer: true, // Even when burried inside of something, show it. |
| | 37 | visible: true |
| | 38 | }; |
| | 39 | var fullPath = { |
| | 40 | type: "line3d", |
| | 41 | color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE, |
| | 42 | visible: true, |
| | 43 | alpha: 1, |
| | 44 | solid: true, |
| | 45 | glow: 1.0, |
| | 46 | lineWidth: 5, |
| | 47 | ignoreRayIntersection: true, // always ignore this |
| | 48 | drawHUDLayer: true, // Even when burried inside of something, show it. |
| | 49 | parentID: AVATAR_SELF_ID |
| | 50 | }; |
| | 51 | var fullEnd = { |
| | 52 | type: "sphere", |
| | 53 | solid: true, |
| | 54 | color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE, |
| | 55 | alpha: 0.9, |
| | 56 | ignoreRayIntersection: true, |
| | 57 | drawHUDLayer: true, // Even when burried inside of something, show it. |
| | 58 | visible: true |
| | 59 | }; |
| | 60 | var holdPath = { |
| | 61 | type: "line3d", |
| | 62 | color: COLORS_GRAB_DISTANCE_HOLD, |
| | 63 | visible: true, |
| | 64 | alpha: 1, |
| | 65 | solid: true, |
| | 66 | glow: 1.0, |
| | 67 | lineWidth: 5, |
| | 68 | ignoreRayIntersection: true, // always ignore this |
| | 69 | drawHUDLayer: true, // Even when burried inside of something, show it. |
| | 70 | parentID: AVATAR_SELF_ID |
| | 71 | }; |
| | 72 | |
| | 73 | var renderStates = [ |
| | 74 | {name: "half", path: halfPath, end: halfEnd}, |
| | 75 | {name: "full", path: fullPath, end: fullEnd}, |
| | 76 | {name: "hold", path: holdPath} |
| | 77 | ]; |
| | 78 | |
| | 79 | var defaultRenderStates = [ |
| | 80 | {name: "half", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: halfPath}, |
| | 81 | {name: "full", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: fullPath}, |
| | 82 | {name: "hold", distance: DEFAULT_SEARCH_SPHERE_DISTANCE, path: holdPath} |
| | 83 | ]; |
| | 84 | |
| | 85 | |
| | 86 | // triggered when stylus presses a web overlay/entity |
| | 87 | var HAPTIC_STYLUS_STRENGTH = 1.0; |
| | 88 | var HAPTIC_STYLUS_DURATION = 20.0; |
| | 89 | var MARGIN = 25; |
| | 90 | |
| | 91 | function distance2D(a, b) { |
| | 92 | var dx = (a.x - b.x); |
| | 93 | var dy = (a.y - b.y); |
| | 94 | return Math.sqrt(dx * dx + dy * dy); |
| | 95 | } |
| | 96 | |
| | 97 | function HudOverlayPointer(hand) { |
| | 98 | var _this = this; |
| | 99 | this.hand = hand; |
| | 100 | this.reticleMinX = MARGIN; |
| | 101 | this.reticleMaxX; |
| | 102 | this.reticleMinY = MARGIN; |
| | 103 | this.reticleMaxY; |
| | 104 | this.clicked = false; |
| | 105 | this.triggerClicked = 0; |
| | 106 | this.parameters = ControllerDispatcherUtils.makeDispatcherModuleParameters( |
| | 107 | 540, |
| | 108 | this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], |
| | 109 | [], |
| | 110 | 100); |
| | 111 | |
| | 112 | this.getOtherHandController = function() { |
| | 113 | return (this.hand === RIGHT_HAND) ? Controller.Standard.LeftHand : Controller.Standard.RightHand; |
| | 114 | }; |
| | 115 | |
| | 116 | this.clicked = function() { |
| | 117 | return this.clicked; |
| | 118 | }; |
| | 119 | |
| | 120 | this.getOtherModule = function() { |
| | 121 | return (this.hand === RIGHT_HAND) ? leftOverlayLaserInput : rightOverlayLaserInput; |
| | 122 | }; |
| | 123 | |
| | 124 | this.handToController = function() { |
| | 125 | return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; |
| | 126 | }; |
| | 127 | |
| | 128 | this.updateRecommendedArea = function() { |
| | 129 | var dims = Controller.getViewportDimensions(); |
| | 130 | this.reticleMaxX = dims.x - MARGIN; |
| | 131 | this.reticleMaxY = dims.y - MARGIN; |
| | 132 | }; |
| | 133 | |
| | 134 | this.hasNotSentClick = function() { |
| | 135 | if (!_this.clicked) { |
| | 136 | _this.clicked = true; |
| | 137 | return true; |
| | 138 | } |
| | 139 | return false; |
| | 140 | }; |
| | 141 | |
| | 142 | this.updateLaserPointer = function(controllerData) { |
| | 143 | var RADIUS = 0.005; |
| | 144 | var dim = { x: RADIUS, y: RADIUS, z: RADIUS }; |
| | 145 | |
| | 146 | if (this.mode === "full") { |
| | 147 | this.fullEnd.dimensions = dim; |
| | 148 | LaserPointers.editRenderState(this.laserPointer, this.mode, {path: fullPath, end: this.fullEnd}); |
| | 149 | } else if (this.mode === "half") { |
| | 150 | this.halfEnd.dimensions = dim; |
| | 151 | LaserPointers.editRenderState(this.laserPointer, this.mode, {path: halfPath, end: this.halfEnd}); |
| | 152 | } |
| | 153 | |
| | 154 | LaserPointers.enableLaserPointer(this.laserPointer); |
| | 155 | LaserPointers.setRenderState(this.laserPointer, this.mode); |
| | 156 | }; |
| | 157 | |
| | 158 | this.processControllerTriggers = function(controllerData) { |
| | 159 | if (controllerData.triggerClicks[this.hand]) { |
| | 160 | this.mode = "full"; |
| | 161 | } else if (controllerData.triggerValues[this.hand] > TRIGGER_ON_VALUE) { |
| | 162 | this.clicked = false; |
| | 163 | this.mode = "half"; |
| | 164 | } else { |
| | 165 | this.mode = "none"; |
| | 166 | } |
| | 167 | }; |
| | 168 | |
| | 169 | this.calculateNewReticlePosition = function(intersection) { |
| | 170 | this.updateRecommendedArea(); |
| | 171 | var point2d = HMD.overlayFromWorldPoint(intersection); |
| | 172 | point2d.x = Math.max(this.reticleMinX, Math.min(point2d.x, this.reticleMaxX)); |
| | 173 | point2d.y = Math.max(this.reticleMinY, Math.min(point2d.y, this.reticleMaxY)); |
| | 174 | return point2d; |
| | 175 | }; |
| | 176 | |
| | 177 | this.setReticlePosition = function(point2d) { |
| | 178 | Reticle.setPosition(point2d); |
| | 179 | }; |
| | 180 | |
| | 181 | this.processLaser = function(controllerData) { |
| | 182 | var controllerLocation = controllerData.controllerLocations[this.hand]; |
| | 183 | if (controllerData.triggerValues[this.hand] < ControllerDispatcherUtils.TRIGGER_OFF_VALUE || !controllerLocation.valid) { |
| | 184 | this.exitModule(); |
| | 185 | return false; |
| | 186 | } |
| | 187 | |
| | 188 | var hudRayPick = controllerData.hudRayPicks[this.hand]; |
| | 189 | var controllerLocation = controllerData.controllerLocations[this.hand]; |
| | 190 | var point2d = this.calculateNewReticlePosition(hudRayPick.intersection); |
| | 191 | this.setReticlePosition(point2d); |
| | 192 | print(Reticle.isPointOnSystemOverlay(point2d)); |
| | 193 | if (!Reticle.isPointOnSystemOverlay(point2d)) { |
| | 194 | this.exitModule(); |
| | 195 | print("----> exiting <------"); |
| | 196 | return false; |
| | 197 | } |
| | 198 | |
| | 199 | //this.setReticlePosition(point2d); |
| | 200 | |
| | 201 | this.clicked = controllerData.triggerClicked[this.hand]; |
| | 202 | |
| | 203 | this.processControllerTriggers(controllerData); |
| | 204 | this.updateLaserPointer(controllerData); |
| | 205 | return true; |
| | 206 | }; |
| | 207 | |
| | 208 | this.exitModule = function() { |
| | 209 | LaserPointers.disableLaserPointer(this.laserPointer); |
| | 210 | }; |
| | 211 | |
| | 212 | this.isReady = function (controllerData) { |
| | 213 | if (this.processLaser(controllerData)) { |
| | 214 | return ControllerDispatcherUtils.makeRunningValues(true, [], []); |
| | 215 | } else { |
| | 216 | return ControllerDispatcherUtils.makeRunningValues(false, [], []); |
| | 217 | } |
| | 218 | }; |
| | 219 | |
| | 220 | this.run = function (controllerData, deltaTime) { |
| | 221 | return this.isReady(controllerData); |
| | 222 | }; |
| | 223 | |
| | 224 | this.cleanup = function () { |
| | 225 | LaserPointers.disableLaserPointer(this.laserPointer); |
| | 226 | LaserPointers.removeLaserPointer(this.laserPointer); |
| | 227 | }; |
| | 228 | |
| | 229 | this.halfEnd = halfEnd; |
| | 230 | this.fullEnd = fullEnd; |
| | 231 | this.laserPointer = LaserPointers.createLaserPointer({ |
| | 232 | joint: (this.hand === RIGHT_HAND) ? "_CONTROLLER_RIGHTHAND" : "_CONTROLLER_LEFTHAND", |
| | 233 | filter: RayPick.PICK_HUD, |
| | 234 | maxDistance: PICK_MAX_DISTANCE, |
| | 235 | posOffset: getGrabPointSphereOffset(this.handToController(), true), |
| | 236 | renderStates: renderStates, |
| | 237 | enabled: true, |
| | 238 | defaultRenderStates: defaultRenderStates |
| | 239 | }); |
| | 240 | } |
| | 241 | |
| | 242 | |
| | 243 | var leftHudOverlayPointer = new HudOverlayPointer(LEFT_HAND); |
| | 244 | var rightHudOverlayPointer = new HudOverlayPointer(RIGHT_HAND); |
| | 245 | |
| | 246 | var clickMapping = Controller.newMapping('HudOverlayPointer-click'); |
| | 247 | clickMapping.from(rightHudOverlayPointer.clicked()).when(rightHudOverlayPointer.hasNotSentClick()).to(Controller.Actions.ReticleClick); |
| | 248 | clickMapping.from(leftHudOverlayPointer.clicked()).when(leftHudOverlayPointer.hasNotSentClick()).to(Controller.Actions.ReticleClick); |
| | 249 | clickMapping.enable(); |
| | 250 | |
| | 251 | enableDispatcherModule("LeftHudOverlayPointer", leftHudOverlayPointer); |
| | 252 | enableDispatcherModule("RightHudOverlayPointer", rightHudOverlayPointer); |
| | 253 | |
| | 254 | |
| | 255 | })(); |