1145 lines · 50.1 KB · JavaScript
RawDownload
"use strict"; // Created by james b. pollack @imgntn on 7/2/2016// Copyright 2016 High Fidelity, Inc.////  Creates a beam and target and then teleports you there.  Release when its close to you to cancel.////  Distributed under the Apache License, Version 2.0.//  See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html /* jslint bitwise: true */ /* global Script, Entities, MyAvatar, Controller, Quat, RIGHT_HAND, LEFT_HAND,   enableDispatcherModule, disableDispatcherModule, Messages, makeDispatcherModuleParameters, makeRunningValues, Vec3,   HMD, Uuid, AvatarList, Picks, Pointers, PickType*/ Script.include("/~/system/libraries/Xform.js");Script.include("/~/system/libraries/controllerDispatcherUtils.js");Script.include("/~/system/libraries/controllers.js"); (function() { // BEGIN LOCAL_SCOPE     var controllerStandard = Controller.Standard;     var TARGET_MODEL_URL = Script.resolvePath("../../assets/models/teleportationSpotBasev8.fbx");    var SEAT_MODEL_URL = Script.resolvePath("../../assets/models/teleport-seat.fbx");     var TARGET_MODEL_DIMENSIONS = { x: 0.6552, y: 0.3063, z: 0.6552 };     var COLORS_TELEPORT_SEAT = {        red: 255,        green: 0,        blue: 170    };     var COLORS_TELEPORT_CAN_TELEPORT = {        red: 97,        green: 247,        blue: 255    };     var COLORS_TELEPORT_CANCEL = {        red: 255,        green: 184,        blue: 73    };     var handInfo = {        right: {            controllerInput: controllerStandard.RightHand        },        left: {            controllerInput: controllerStandard.LeftHand        }    };     var cancelPath = {        color: COLORS_TELEPORT_CANCEL,        alpha: 0.3,        width: 0.025,        drawInFront: true    };        var teleportPath = {        color: COLORS_TELEPORT_CAN_TELEPORT,        alpha: 0.7,        width: 0.025,        drawInFront: true    };        var seatPath = {        color: COLORS_TELEPORT_SEAT,        alpha: 0.7,        width: 0.025,        drawInFront: true    };     var teleportEnd = {        type: "Model",        modelURL: TARGET_MODEL_URL,        dimensions: TARGET_MODEL_DIMENSIONS,        ignorePickIntersection: true    };        var seatEnd = {        type: "Model",        modelURL: SEAT_MODEL_URL,        dimensions: TARGET_MODEL_DIMENSIONS,        ignorePickIntersection: true    };        var collisionEnd = {        type: "Box",        dimensions: { x: 1.0, y: 0.001, z: 1.0 },        alpha: 0.0,        ignorePickIntersection: true    };        var teleportRenderStates = [{name: "cancel", path: cancelPath},        {name: "teleport", path: teleportPath, end: teleportEnd},        {name: "seat", path: seatPath, end: seatEnd},        {name: "collision", end: collisionEnd}];     var DEFAULT_DISTANCE = 8.0;    var teleportDefaultRenderStates = [{name: "cancel", distance: DEFAULT_DISTANCE, path: cancelPath}];     var ignoredEntities = [];     var TELEPORTER_STATES = {        IDLE: 'idle',        TARGETTING: 'targetting',        TARGETTING_INVALID: 'targetting_invalid'    };     var TARGET = {        NONE: 'none', // Not currently targetting anything        INVALID: 'invalid', // The current target is invalid (wall, ceiling, etc.)        COLLIDES: 'collides', // Insufficient space to accommodate the avatar capsule        DISCREPANCY: 'discrepancy', // We are not 100% sure the avatar will fit so we trigger safe landing        SURFACE: 'surface', // The current target is a valid surface        SEAT: 'seat' // The current target is a seat    };     var speed = 9.3;    var accelerationAxis = {x: 0.0, y: -5.0, z: 0.0};     function Teleporter(hand) {        var _this = this;        this.init = false;        this.hand = hand;        this.buttonValue = 0;        this.buttonTeleporting = false; // True if buttonValue is controlling teleport.        this.standardAxisLY = 0.0;        this.standardAxisRY = 0.0;        this.disabled = false; // used by the 'Hifi-Teleport-Disabler' message handler        this.active = false;        this.state = TELEPORTER_STATES.IDLE;        this.currentTarget = TARGET.INVALID;        this.currentResult = null;        this.capsuleThreshold = 0.05;        this.pickHeightOffset = 0.05;         this.getOtherModule = function() {            var otherModule = this.hand === RIGHT_HAND ? leftTeleporter : rightTeleporter;            return otherModule;        };         this.teleportHeadCollisionPick;        this.teleportHandCollisionPick;        this.teleportParabolaHandVisuals;        this.teleportParabolaHandCollisions;        this.teleportParabolaHeadVisuals;        this.teleportParabolaHeadCollisions;          this.PLAY_AREA_OVERLAY_MODEL = Script.resolvePath("../../assets/models/trackingSpacev18.fbx");        this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS = { x: 1.969, y: 0.001, z: 1.969 };        this.PLAY_AREA_FLOAT_ABOVE_FLOOR = 0.005;        this.PLAY_AREA_OVERLAY_OFFSET = // Offset from floor.            { x: 0, y: this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y / 2 + this.PLAY_AREA_FLOAT_ABOVE_FLOOR, z: 0 };        this.PLAY_AREA_SENSOR_OVERLAY_MODEL = Script.resolvePath("../../assets/models/oculusSensorv11.fbx");        this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS = { x: 0.1198, y: 0.2981, z: 0.1198 };        this.PLAY_AREA_SENSOR_OVERLAY_ROTATION = Quat.fromVec3Degrees({ x: 0, y: -90, z: 0 });        this.PLAY_AREA_BOX_ALPHA = 1.0;        this.PLAY_AREA_SENSOR_ALPHA = 0.8;        this.playAreaSensorPositions = [];        this.playArea = { x: 0, y: 0 };        this.playAreaCenterOffset = this.PLAY_AREA_OVERLAY_OFFSET;        this.isPlayAreaVisible = false;        this.wasPlayAreaVisible = false;        this.isPlayAreaAvailable = false;        this.targetOverlayID = null;        this.playAreaOverlay = null;        this.playAreaSensorPositionOverlays = [];         this.TELEPORT_SCALE_DURATION = 130;        this.TELEPORT_SCALE_TIMEOUT = 25;        this.isTeleportVisible = false;        this.teleportScaleTimer = null;        this.teleportScaleStart = 0;        this.teleportScaleFactor = 0;        this.teleportScaleMode = "head";         this.TELEPORTED_FADE_DELAY_DURATION = 900;        this.TELEPORTED_FADE_DURATION = 200;        this.TELEPORTED_FADE_INTERVAL = 25;        this.TELEPORTED_FADE_DELAY_DELTA = this.TELEPORTED_FADE_INTERVAL / this.TELEPORTED_FADE_DELAY_DURATION;        this.TELEPORTED_FADE_DELTA = this.TELEPORTED_FADE_INTERVAL / this.TELEPORTED_FADE_DURATION;        this.teleportedFadeTimer = null;        this.teleportedFadeDelayFactor = 0;        this.teleportedFadeFactor = 0;        this.teleportedPosition = Vec3.ZERO;        this.TELEPORTED_TARGET_ALPHA = 1.0;        this.TELEPORTED_TARGET_ROTATION = Quat.fromVec3Degrees({ x: 0, y: 180, z: 0 });        this.teleportedTargetOverlay = null;         this.setPlayAreaDimensions = function () {            var avatarScale = MyAvatar.sensorToWorldScale;             var playAreaOverlayProperties = {                dimensions:                    Vec3.multiply(_this.teleportScaleFactor * avatarScale, {                        x: _this.playArea.width,                        y: _this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y,                        z: _this.playArea.height                    })            };             if (_this.teleportScaleFactor < 1) {                // Adjust position of playAreOverlay so that its base is at correct height.                // Always parenting to teleport target is good enough for this.                var sensorToWorldMatrix = MyAvatar.sensorToWorldMatrix;                var sensorToWorldRotation = Mat4.extractRotation(MyAvatar.sensorToWorldMatrix);                var worldToSensorMatrix = Mat4.inverse(sensorToWorldMatrix);                var avatarSensorPosition = Mat4.transformPoint(worldToSensorMatrix, MyAvatar.position);                avatarSensorPosition.y = 0;                 var targetRotation = Entities.getEntityProperties(_this.targetOverlayID, ["rotation"]).rotation;                if (targetRotation != null) {                    var relativePlayAreaCenterOffset =                        Vec3.sum(_this.playAreaCenterOffset, {x: 0, y: -TARGET_MODEL_DIMENSIONS.y / 2, z: 0});                    var localPosition = Vec3.multiplyQbyV(Quat.inverse(targetRotation),                        Vec3.multiplyQbyV(sensorToWorldRotation,                            Vec3.multiply(avatarScale, Vec3.subtract(relativePlayAreaCenterOffset, avatarSensorPosition))));                    localPosition.y = _this.teleportScaleFactor * localPosition.y;                } else {                    print("");                }                 playAreaOverlayProperties.parentID = _this.targetOverlayID;                if (targetRotation != null) {                    playAreaOverlayProperties.localPosition = localPosition;                }            }             Entities.editEntity(_this.playAreaOverlay, playAreaOverlayProperties);             for (var i = 0; i < _this.playAreaSensorPositionOverlays.length; i++) {                localPosition = _this.playAreaSensorPositions[i];                localPosition = Vec3.multiply(avatarScale, localPosition);                // Position relative to the play area.                localPosition.y = avatarScale * (_this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS.y / 2                    - _this.PLAY_AREA_OVERLAY_MODEL_DIMENSIONS.y / 2);                Entities.editEntity(_this.playAreaSensorPositionOverlays[i], {                    dimensions: Vec3.multiply(_this.teleportScaleFactor * avatarScale, _this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS),                    parentID: _this.playAreaOverlay,                    localPosition: localPosition                });            }        };         this.updatePlayAreaScale = function () {            if (_this.isPlayAreaAvailable) {                _this.setPlayAreaDimensions();            }        };          this.teleporterSelectionName = "teleporterSelection" + hand.toString();        this.TELEPORTER_SELECTION_STYLE = {            outlineUnoccludedColor: { red: 0, green: 0, blue: 0 },            outlineUnoccludedAlpha: 0,            outlineOccludedColor: { red: 0, green: 0, blue: 0 },            outlineOccludedAlpha: 0,            fillUnoccludedColor: { red: 0, green: 0, blue: 0 },            fillUnoccludedAlpha: 0,            fillOccludedColor: { red: 0, green: 0, blue: 255 },            fillOccludedAlpha: 0.84,            outlineWidth: 0,            isOutlineSmooth: false        };         this.addToSelectedItemsList = function (properties) {            for (var i = 0, length = teleportRenderStates.length; i < length; i++) {                var state = properties.renderStates[teleportRenderStates[i].name];                if (state && state.end) {                    Selection.addToSelectedItemsList(_this.teleporterSelectionName, "entity", state.end);                }            }        };          this.cleanup = function() {            Selection.removeListFromMap(_this.teleporterSelectionName);            Pointers.removePointer(_this.teleportParabolaHandVisuals);            Pointers.removePointer(_this.teleportParabolaHandCollisions);            Pointers.removePointer(_this.teleportParabolaHeadVisuals);            Pointers.removePointer(_this.teleportParabolaHeadCollisions);            Picks.removePick(_this.teleportHandCollisionPick);            Picks.removePick(_this.teleportHeadCollisionPick);            Entities.deleteEntity(_this.teleportedTargetOverlay);            Entities.deleteEntity(_this.playAreaOverlay);            for (var i = 0; i < _this.playAreaSensorPositionOverlays.length; i++) {                Entities.deleteEntity(_this.playAreaSensorPositionOverlays[i]);            }            _this.playAreaSensorPositionOverlays = [];        };         this.initPointers = function() {            if (_this.init) {                _this.cleanup();            }             // FIXME: the documentation has Pointers.createPointer(PickType.Parabola, ...),            // but that's a nonexistent function here. Is the documentation wrong or is            // the Pointers here from a library that's getting included?            _this.teleportParabolaHandVisuals = Pointers.createParabolaPointer({                joint: (_this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND",                dirOffset: { x: 0, y: 1, z: 0.1 },                posOffset: { x: (_this.hand === RIGHT_HAND) ? 0.03 : -0.03, y: 0.2, z: 0.02 },                filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE,                faceAvatar: true,                scaleWithParent: true,                centerEndY: false,                speed: speed,                accelerationAxis: accelerationAxis,                rotateAccelerationWithAvatar: true,                renderStates: teleportRenderStates,                defaultRenderStates: teleportDefaultRenderStates,                maxDistance: 8.0            });             _this.teleportParabolaHandCollisions = Pointers.createParabolaPointer({                joint: (_this.hand === RIGHT_HAND) ? "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND" : "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND",                dirOffset: { x: 0, y: 1, z: 0.1 },                posOffset: { x: (_this.hand === RIGHT_HAND) ? 0.03 : -0.03, y: 0.2, z: 0.02 },                filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE,                faceAvatar: true,                scaleWithParent: true,                centerEndY: false,                speed: speed,                accelerationAxis: accelerationAxis,                rotateAccelerationWithAvatar: true,                renderStates: teleportRenderStates,                maxDistance: 8.0            });             _this.teleportParabolaHeadVisuals = Pointers.createParabolaPointer({                joint: "Avatar",                filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE,                faceAvatar: true,                scaleWithParent: true,                centerEndY: false,                speed: speed,                accelerationAxis: accelerationAxis,                rotateAccelerationWithAvatar: true,                renderStates: teleportRenderStates,                defaultRenderStates: teleportDefaultRenderStates,                maxDistance: 8.0            });             _this.teleportParabolaHeadCollisions = Pointers.createParabolaPointer({                joint: "Avatar",                filter: Picks.PICK_ENTITIES | Picks.PICK_INCLUDE_INVISIBLE,                faceAvatar: true,                scaleWithParent: true,                centerEndY: false,                speed: speed,                accelerationAxis: accelerationAxis,                rotateAccelerationWithAvatar: true,                renderStates: teleportRenderStates,                maxDistance: 8.0            });             _this.addToSelectedItemsList(Pointers.getPointerProperties(_this.teleportParabolaHandVisuals));            _this.addToSelectedItemsList(Pointers.getPointerProperties(_this.teleportParabolaHeadVisuals));              var capsuleData = MyAvatar.getCollisionCapsule();             var sensorToWorldScale = MyAvatar.getSensorToWorldScale();             var diameter = 2.0 * capsuleData.radius / sensorToWorldScale;            var height = (Vec3.distance(capsuleData.start, capsuleData.end) + diameter) / sensorToWorldScale;            var capsuleRatio = 5.0 * diameter / height;            var offset = _this.pickHeightOffset * capsuleRatio;             _this.teleportHandCollisionPick = Picks.createPick(PickType.Collision, {                enabled: false,                parentID: Pointers.getPointerProperties(_this.teleportParabolaHandCollisions).renderStates["collision"].end,                filter: Picks.PICK_ENTITIES | Picks.PICK_AVATARS,                shape: {                    shapeType: "capsule-y",                    dimensions: {                        x: diameter,                        y: height,                        z: diameter                    }                },                position: { x: 0, y: offset + height * 0.5, z: 0 },                threshold: _this.capsuleThreshold            });             _this.teleportHeadCollisionPick = Picks.createPick(PickType.Collision, {                enabled: false,                parentID: Pointers.getPointerProperties(_this.teleportParabolaHeadCollisions).renderStates["collision"].end,                filter: Picks.PICK_ENTITIES | Picks.PICK_AVATARS,                shape: {                    shapeType: "capsule-y",                    dimensions: {                        x: diameter,                        y: height,                        z: diameter                    }                },                position: { x: 0, y: offset + height * 0.5, z: 0 },                threshold: _this.capsuleThreshold            });              _this.playAreaOverlay = Entities.addEntity({                type: "Model",                modelURL: _this.PLAY_AREA_OVERLAY_MODEL,                drawInFront: false,                visible: false            }, "local");             _this.teleportedTargetOverlay = Entities.addEntity({                type: "Model",                modelURL: TARGET_MODEL_URL,                alpha: _this.TELEPORTED_TARGET_ALPHA,                visible: false            }, "local");             Selection.addToSelectedItemsList(_this.teleporterSelectionName, "entity", _this.playAreaOverlay);            Selection.addToSelectedItemsList(_this.teleporterSelectionName, "entity", _this.teleportedTargetOverlay);              _this.playArea = HMD.playArea;            _this.isPlayAreaAvailable = HMD.active && _this.playArea.width !== 0 && _this.playArea.height !== 0;            if (_this.isPlayAreaAvailable) {                _this.playAreaCenterOffset = Vec3.sum({ x: _this.playArea.x, y: 0, z: _this.playArea.y },                    _this.PLAY_AREA_OVERLAY_OFFSET);                _this.playAreaSensorPositions = HMD.sensorPositions;                 for (var i = 0; i < _this.playAreaSensorPositions.length; i++) {                    if (i > _this.playAreaSensorPositionOverlays.length - 1) {                        var overlay = Entities.addEntity({                            type: "Model",                            modelURL: _this.PLAY_AREA_SENSOR_OVERLAY_MODEL,                            dimensions: _this.PLAY_AREA_SENSOR_OVERLAY_DIMENSIONS,                            parentID: _this.playAreaOverlay,                            localRotation: _this.PLAY_AREA_SENSOR_OVERLAY_ROTATION,                            drawInFront: false,                            visible: false                        }, "local");                        _this.playAreaSensorPositionOverlays.push(overlay);                        Selection.addToSelectedItemsList(_this.teleporterSelectionName, "entity", overlay);                    }                }                 _this.setPlayAreaDimensions();            }             _this.init = true;        };                _this.initPointers();          this.translateXAction = Controller.findAction("TranslateX");        this.translateYAction = Controller.findAction("TranslateY");        this.translateZAction = Controller.findAction("TranslateZ");         this.setPlayAreaVisible = function (visible, targetOverlayID, fade) {            if (!_this.isPlayAreaAvailable || _this.isPlayAreaVisible === visible) {                return;            }             _this.wasPlayAreaVisible = _this.isPlayAreaVisible;            _this.isPlayAreaVisible = visible;            _this.targetOverlayID = targetOverlayID;             if (_this.teleportedFadeTimer !== null) {                Script.clearTimeout(_this.teleportedFadeTimer);                _this.teleportedFadeTimer = null;            }            if (visible || !fade) {                // Immediately make visible or invisible.                _this.isPlayAreaVisible = visible;                Entities.editEntity(_this.playAreaOverlay, {                    dimensions: Vec3.ZERO,                    alpha: _this.PLAY_AREA_BOX_ALPHA,                    visible: visible                });                for (var i = 0; i < _this.playAreaSensorPositionOverlays.length; i++) {                    Entities.editEntity(_this.playAreaSensorPositionOverlays[i], {                        dimensions: Vec3.ZERO,                        alpha: _this.PLAY_AREA_SENSOR_ALPHA,                        visible: visible                    });                }                Entities.editEntity(_this.teleportedTargetOverlay, { visible: false });            } else {                // Fading out of overlays is initiated in setTeleportVisible().            }        };         this.updatePlayArea = function (position) {

Lines 1–500 of 1145.