1213 lines · 38.2 KB · JavaScript
RawDownload
"use strict";//// radar.js// scripts/system/+android///// Created by Cristian Duarte & Gabriel Calero on 31 Jan 2018// Copyright 2018 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// var radarModeInterface = {}; var logEnabled = false;function printd(str) {    if (logEnabled) {        print("[radar.js] " + str);    }} var radar = false;var RADAR_HEIGHT_INIT_DELTA = 10;var radarHeight = MyAvatar.position.y + RADAR_HEIGHT_INIT_DELTA; // camera position (absolute y)var tablet; var RADAR_CAMERA_OFFSET = -1; // 1 meter below the avatarvar ABOVE_GROUND_DROP = 2;var MOVE_BY = 1; // Swipe/Drag varsvar PINCH_INCREMENT_FIRST = 0.4; // 0.1 meters zoom in - outvar PINCH_INCREMENT = 0.4; // 0.1 meters zoom in - outvar RADAR_HEIGHT_MAX_PLUS_AVATAR = 80;var RADAR_HEIGHT_MIN_PLUS_AVATAR = 2;var RADAR_CAMERA_DISTANCE_TO_ICONS = 1.5; // Icons are near the camera to prevent the LOD manager dismissing themvar RADAR_ICONS_APPARENT_DISTANCE_TO_AVATAR_BASE = 1; // How much above the avatar base should the icon appearvar AVATAR_DISPLAY_NAME_HEIGHT = 106;var AVATAR_DISPLAY_NAME_CHAR_WIDTH = 48;var AVATAR_DISPLAY_NAME_FONT_SIZE = 50;var lastDragAt;var lastDeltaDrag; var uniqueColor; function moveTo(position) {    if (radar) {        MyAvatar.goToLocation(position, false);        Camera.position = {            x : position.x,            y : radarHeight,            z : position.z        };    }} function keyPressEvent(event) {    if (radar) {        switch (event.text) {        case "UP":            moveTo(Vec3.sum(MyAvatar.position, {                x : 0.0,                y : 0,                z : -1 * MOVE_BY            }));            break;        case "DOWN":            moveTo(Vec3.sum(MyAvatar.position, {                x : 0,                y : 0,                z : MOVE_BY            }));            break;        case "LEFT":            moveTo(Vec3.sum(MyAvatar.position, {                x : -1 * MOVE_BY,                y : 0,                z : 0            }));            break;        case "RIGHT":            moveTo(Vec3.sum(MyAvatar.position, {                x : MOVE_BY,                y : 0,                z : 0            }));            break;        }    }} function toggleRadarMode() {    if (radar) {        endRadar();    } else {        startRadar();    }} function fakeDoubleTap(event) {    // CLD - temporarily disable toggling mode through double tap    // * As we have a new UI for toggling between modes, it may be discarded    // completely in the future.    // toggleRadarMode();    teleporter.dragTeleportUpdate(event);    teleporter.dragTeleportRelease(event);} var DOUBLE_TAP_TIME = 300;var fakeDoubleTapStart = Date.now();var touchEndCount = 0; /* * Counts touchEnds and if there were 2 in the DOUBLE_TAP_TIME lapse, it * triggers a fakeDoubleTap and returns true. Otherwise, returns false (no * double tap yet) */function analyzeDoubleTap(event) {    var fakeDoubleTapEnd = Date.now();    var elapsed = fakeDoubleTapEnd - fakeDoubleTapStart;    if (elapsed > DOUBLE_TAP_TIME) {        touchEndCount = 0;    }     // if this is our first "up" then record time so we can    // later determine if second "up" is a double tap    if (touchEndCount == 0) {        fakeDoubleTapStart = Date.now();    }    touchEndCount++;     if (touchEndCount >= 2) {        var fakeDoubleTapEnd = Date.now();        var elapsed = fakeDoubleTapEnd - fakeDoubleTapStart;        printd("-- fakeDoubleTapEnd:" + fakeDoubleTapEnd + "-- elapsed:"                + elapsed)        if (elapsed <= DOUBLE_TAP_TIME) {            touchEndCount = 0;            fakeDoubleTap(event);            return true; // don't do the normal touch end processing        }         touchEndCount = 0;    }    return false;} function touchEnd(event) {    printd("touchEnd received " + JSON.stringify(event));    // Clean up touch variables    lastDragAt = null;    lastDeltaDrag = null;    touchStartingCoordinates = null; // maybe in special cases it should be                                        // setup later?    startedDraggingCamera = false;    prevTouchPinchRadius = null;    draggingCamera = false;     if (movingCamera) {        // if camera was indeed moving, we should not further process, it was        // just dragging        movingCamera = false;        dragModeFunc = null;        return;    }     // teleport release analysis    if (teleporter && teleporter.dragTeleportUpdate == dragModeFunc) {        teleporter.dragTeleportRelease(event);        dragModeFunc = null;        return;    }    dragModeFunc = null;     // if pinching or moving is still detected, cancel    if (event.isPinching) {        printd("touchEnd fail because isPinching");        return;    }    if (event.isPinchOpening) {        printd("touchEnd fail because isPinchingOpening");        return;    }    if (event.isMoved) {        printd("touchEnd fail because isMoved");        return;    }     if (analyzeDoubleTap(event))        return; // double tap detected, finish } /** * Polyfill for sign(x) */if (!Math.sign) {    Math.sign = function(x) {        // If x is NaN, the result is NaN.        // If x is -0, the result is -0.        // If x is +0, the result is +0.        // If x is negative and not -0, the result is -1.        // If x is positive and not +0, the result is +1.        x = +x; // convert to a number        if (x === 0 || isNaN(x)) {            return Number(x);        }        return x > 0 ? 1 : -1;    };} /******************************************************************************* * Line and Plane intersection methods ******************************************************************************/ /** * findLinePlaneIntersection Given points p {x: y: z:} and q that define a line, * and the plane of formula ax+by+cz+d = 0, returns the intersection point or * null if none. */function findLinePlaneIntersection(p, q, a, b, c, d) {    return findLinePlaneIntersectionCoords(p.x, p.y, p.z, q.x, q.y, q.z, a, b,            c, d);} /** * findLineToHeightIntersection Given points p {x: y: z:} and q that define a * line, and a planeY value that defines a plane paralel to 'the floor' xz * plane, returns the intersection to that plane or null if none. */function findLineToHeightIntersection(p, q, planeY) {    return findLinePlaneIntersection(p, q, 0, 1, 0, -planeY);} /** * findLinePlaneIntersectionCoords (to avoid requiring unnecessary * instantiation) Given points p with px py pz and q that define a line, and the * plane of formula ax+by+cz+d = 0, returns the intersection point or null if * none. */function findLinePlaneIntersectionCoords(px, py, pz, qx, qy, qz, a, b, c, d) {    var tDenom = a * (qx - px) + b * (qy - py) + c * (qz - pz);    if (tDenom == 0)        return null;     var t = -(a * px + b * py + c * pz + d) / tDenom;     return {        x : (px + t * (qx - px)),        y : (py + t * (qy - py)),        z : (pz + t * (qz - pz))    };} /** * findLineToHeightIntersection Given points p with px py pz and q that define a * line, and a planeY value that defines a plane paralel to 'the floor' xz * plane, returns the intersection to that plane or null if none. */function findLineToHeightIntersectionCoords(px, py, pz, qx, qy, qz, planeY) {    return findLinePlaneIntersectionCoords(px, py, pz, qx, qy, qz, 0, 1, 0,            -planeY);} function findRayIntersection(pickRay) {    // Check all entities. Argument is an object with origin and direction.    var result = Entities.findRayIntersection(pickRay, Picks.PICK_DOMAIN_ENTITIES | Picks.PICK_AVATAR_ENTITIES | Picks.PICK_LOCAL_ENTITIES);    return result;} /** * Given a 2d point (x,y) this function returns the intersection (x, y, z) of * the computedPickRay for that point with the plane y = py */function computePointAtPlaneY(x, y, py) {    var ray = Camera.computePickRay(x, y);    var p1 = ray.origin;    var p2 = Vec3.sum(p1, Vec3.multiply(ray.direction, 1));    return findLineToHeightIntersectionCoords(p1.x, p1.y, p1.z, p2.x, p2.y,            p2.z, py);} /******************************************************************************* *  ******************************************************************************/ var touchStartingCoordinates = null; var KEEP_PRESSED_FOR_TELEPORT_MODE_TIME = 750;var touchBeginTime; function touchBegin(event) {    var coords = {        x : event.x,        y : event.y    };    touchStartingCoordinates = coords;    touchBeginTime = Date.now();} var startedDraggingCamera = false; // first timevar draggingCamera = false; // is tryingvar movingCamera = false; // definitive var MIN_DRAG_DISTANCE_TO_CONSIDER = 100; // distance by axis, not real                                            // distance var prevTouchPinchRadius = null; function pinchUpdate(event) {    if (!event.isMoved)        return;    if (event.radius <= 0)        return;     // pinch management    var avatarY = MyAvatar.position.y;    var pinchIncrement;    if (!!prevTouchPinchRadius) {        // no prev value        pinchIncrement = PINCH_INCREMENT                * Math.abs(event.radius - prevTouchPinchRadius) * 0.1;    } else {        pinchIncrement = PINCH_INCREMENT_FIRST;    }     if (event.isPinching) {        if (radarHeight + pinchIncrement > RADAR_HEIGHT_MAX_PLUS_AVATAR                + avatarY) {            radarHeight = RADAR_HEIGHT_MAX_PLUS_AVATAR + avatarY;        } else {            radarHeight += pinchIncrement;        }    } else if (event.isPinchOpening) {        if (radarHeight - pinchIncrement < RADAR_HEIGHT_MIN_PLUS_AVATAR                + avatarY) {            radarHeight = RADAR_HEIGHT_MIN_PLUS_AVATAR + avatarY;        } else {            radarHeight -= pinchIncrement;        }    }     Camera.position = {         x : Camera.position.x,         y : radarHeight,         z : Camera.position.z     };     if (!draggingCamera) {        startedDraggingCamera = true;        draggingCamera = true;    }     prevTouchPinchRadius = event.radius;} function isInsideSquare(coords0, coords1, halfside) {    return coords0 != undefined && coords1 != undefined &&            Math.abs(coords0.x - coords1.x) <= halfside            && Math.abs(coords0.y - coords1.y) <= halfside;} function dragScrollUpdate(event) {    if (!event.isMoved)        return;     // drag management    var pickRay = Camera.computePickRay(event.x, event.y);    var dragAt = Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction,            radarHeight - MyAvatar.position.y));     if (lastDragAt === undefined || lastDragAt === null) {        lastDragAt = dragAt;        return;    }     var deltaDrag = {        x : (lastDragAt.x - dragAt.x),        y : 0,        z : (lastDragAt.z - dragAt.z)    };     lastDragAt = dragAt;    if (lastDeltaDrag === undefined || lastDeltaDrag === null) {        lastDeltaDrag = deltaDrag;        return;    }     if (!draggingCamera) {        startedDraggingCamera = true;        draggingCamera = true;    } else {        if (!movingCamera) {            if (!isInsideSquare(touchStartingCoordinates, event,                    MIN_DRAG_DISTANCE_TO_CONSIDER)) {                movingCamera = true;            }        }         if (movingCamera) {            if (Math.sign(deltaDrag.x) == Math.sign(lastDeltaDrag.x)                    && Math.sign(deltaDrag.z) == Math.sign(lastDeltaDrag.z)) {                // Process movement if direction of the movement is the same                // than the previous frame                // process delta                var moveCameraTo = Vec3.sum(Camera.position, deltaDrag);                // move camera                Camera.position = moveCameraTo;            } else {                // Do not move camera if it's changing direction in this case,                // wait until the next direction confirmation..            }            lastDeltaDrag = deltaDrag; // save last        }    }} /******************************************************************************* * Teleport feature ******************************************************************************/ function Teleporter() {     var SURFACE_DETECTION_FOR_TELEPORT = true; // true if uses teleport.js                                                // similar logic to detect                                                // surfaces. false if uses plain                                                // teleport to avatar same                                                // height.     var TELEPORT_TARGET_MODEL_URL = Script            .resolvePath("../assets/models/teleport-destination.fbx");    var TELEPORT_TOO_CLOSE_MODEL_URL = Script            .resolvePath("../assets/models/teleport-cancel.fbx");     var TELEPORT_MODEL_DEFAULT_DIMENSIONS = {        x : 0.10,        y : 0.00001,        z : 0.10    };     var teleportOverlay = Overlays.addOverlay("model", {        url : TELEPORT_TARGET_MODEL_URL,        dimensions : TELEPORT_MODEL_DEFAULT_DIMENSIONS,        orientation : Quat.fromPitchYawRollDegrees(0, 180, 0),        visible : false    });     var teleportCancelOverlay = Overlays.addOverlay("model", {        url : TELEPORT_TOO_CLOSE_MODEL_URL,        dimensions : TELEPORT_MODEL_DEFAULT_DIMENSIONS,        orientation : Quat.fromPitchYawRollDegrees(0, 180, 0),        visible : false    });     var TELEPORT_COLOR = {        red : 0,        green : 255,        blue : 255    };    var TELEPORT_CANCEL_COLOR = {        red : 255,        green : 255,        blue : 0    };     var teleportLine = Overlays.addOverlay("line3d", {        start : {            x : 0,            y : 0,            z : 0        },        end : {            x : 0,            y : 0,            z : 0        },        color : TELEPORT_COLOR,        alpha : 1,        lineWidth : 2,        dashed : false,        visible : false    });     // code from teleport.js    var TELEPORT_TARGET = {        NONE : 'none', // Not currently targetting anything        INVISIBLE : 'invisible', // The current target is an invvsible                                    // surface        INVALID : 'invalid', // The current target is invalid (wall, ceiling,                                // etc.)        SURFACE : 'surface', // The current target is a valid surface        SEAT : 'seat', // The current target is a seat    }     var TELEPORT_CANCEL_RANGE = 1;    var teleportTargetType = TELEPORT_TARGET.NONE;     function parseJSON(json) {        try {

Lines 1–500 of 1213.