"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. Load more
"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 avatar var ABOVE_GROUND_DROP = 2; var MOVE_BY = 1; // Swipe/Drag vars var PINCH_INCREMENT_FIRST = 0.4; // 0.1 meters zoom in - out var PINCH_INCREMENT = 0.4; // 0.1 meters zoom in - out var 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 them var RADAR_ICONS_APPARENT_DISTANCE_TO_AVATAR_BASE = 1; // How much above the avatar base should the icon appear var 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 time var draggingCamera = false; // is trying var 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 {