"use strict"; // farTrigger.js // // 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, Controller, LaserPointers, RayPick, RIGHT_HAND, LEFT_HAND, MyAvatar, getGrabPointSphereOffset, makeRunningValues, Entities, enableDispatcherModule, disableDispatcherModule, makeDispatcherModuleParameters, PICK_MAX_DISTANCE, COLORS_GRAB_SEARCHING_HALF_SQUEEZE, COLORS_GRAB_SEARCHING_FULL_SQUEEZE, COLORS_GRAB_DISTANCE_HOLD, DEFAULT_SEARCH_SPHERE_DISTANCE, getGrabbableData */ Script.include("/~/system/libraries/controllerDispatcherUtils.js"); Script.include("/~/system/libraries/controllers.js"); (function() { var SEARCH_SPHERE_SIZE = 0.0132; var dim = {x: SEARCH_SPHERE_SIZE, y: SEARCH_SPHERE_SIZE, z: SEARCH_SPHERE_SIZE}; 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 drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID }; var halfEnd = { type: "sphere", dimensions: dim, solid: true, color: COLORS_GRAB_SEARCHING_HALF_SQUEEZE, alpha: 0.9, ignoreRayIntersection: true, drawInFront: 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 drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.SELF_ID }; var fullEnd = { type: "sphere", dimensions: dim, solid: true, color: COLORS_GRAB_SEARCHING_FULL_SQUEEZE, alpha: 0.9, ignoreRayIntersection: true, drawInFront: 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 drawInFront: true, // Even when burried inside of something, show it. parentID: MyAvatar.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} ]; function entityWantsNearTrigger(props) { var grabbableData = getGrabbableData(props); return grabbableData.triggerable || grabbableData.wantsTrigger; } function FarTriggerEntity(hand) { this.hand = hand; this.targetEntityID = null; this.grabbing = false; this.previousParentID = {}; this.previousParentJointIndex = {}; this.previouslyUnhooked = {}; this.parameters = makeDispatcherModuleParameters( 520, this.hand === RIGHT_HAND ? ["rightHand"] : ["leftHand"], [], 100); this.handToController = function() { return (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; }; this.updateLaserPointer = function(controllerData) { var mode = "none"; if (controllerData.triggerClicks[this.hand]) { mode = "full"; } else { mode = "half"; } LaserPointers.enableLaserPointer(this.laserPointer); LaserPointers.setRenderState(this.laserPointer, mode); }; this.laserPointerOff = function() { LaserPointers.disableLaserPointer(this.laserPointer); }; this.getTargetProps = function (controllerData) { // nearbyEntityProperties is already sorted by length from controller var targetEntity = controllerData.rayPicks[this.hand].objectID; if (targetEntity) { var targetProperties = Entities.getEntityProperties(targetEntity); if (entityWantsNearTrigger(targetProperties)) { return targetProperties; } } return null; }; this.startFarTrigger = function (controllerData) { var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.targetEntityID, "startFarTrigger", args); }; this.continueFarTrigger = function (controllerData) { var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.targetEntityID, "continueFarTrigger", args); }; this.endFarTrigger = function (controllerData) { var args = [this.hand === RIGHT_HAND ? "right" : "left", MyAvatar.sessionUUID]; Entities.callEntityMethod(this.targetEntityID, "stopFarTrigger", args); this.laserPointerOff(); }; this.isReady = function (controllerData) { this.targetEntityID = null; if (controllerData.triggerClicks[this.hand] === 0) { return makeRunningValues(false, [], []); } var targetProps = this.getTargetProps(controllerData); if (targetProps) { this.targetEntityID = targetProps.id; this.startFarTrigger(controllerData); return makeRunningValues(true, [this.targetEntityID], []); } else { return makeRunningValues(false, [], []); } }; this.run = function (controllerData) { var targetEntity = controllerData.rayPicks[this.hand].objectID; if (controllerData.triggerClicks[this.hand] === 0 || this.targetEntityID !== targetEntity) { this.endFarTrigger(controllerData); return makeRunningValues(false, [], []); } this.updateLaserPointer(controllerData); this.continueFarTrigger(controllerData); return makeRunningValues(true, [this.targetEntityID], []); }; this.laserPointer = LaserPointers.createLaserPointer({ joint: (this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, maxDistance: PICK_MAX_DISTANCE, posOffset: getGrabPointSphereOffset(this.handToController(), true), renderStates: renderStates, faceAvatar: true, distanceScaleEnd: true, defaultRenderStates: defaultRenderStates }); this.cleanup = function () { if (this.targetEntityID) { this.endFarTrigger(); } LaserPointers.disableLaserPointer(this.laserPointer); LaserPointers.removeLaserPointer(this.laserPointer); }; } var leftFarTriggerEntity = new FarTriggerEntity(LEFT_HAND); var rightFarTriggerEntity = new FarTriggerEntity(RIGHT_HAND); enableDispatcherModule("LeftFarTriggerEntity", leftFarTriggerEntity); enableDispatcherModule("RightFarTriggerEntity", rightFarTriggerEntity); this.cleanup = function () { leftFarTriggerEntity.cleanup(); rightFarTriggerEntity.cleanup(); disableDispatcherModule("LeftFarTriggerEntity"); disableDispatcherModule("RightFarTriggerEntity"); }; Script.scriptEnding.connect(this.cleanup); }());