/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};

/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {

/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId])
/******/ 			return installedModules[moduleId].exports;

/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			exports: {},
/******/ 			id: moduleId,
/******/ 			loaded: false
/******/ 		};

/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/ 		// Flag the module as loaded
/******/ 		module.loaded = true;

/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}


/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;

/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;

/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";

/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {

	/* global THREE, AFRAME, Element  */
	var cylinderTexture = __webpack_require__(1);
	var parabolicCurve = __webpack_require__(2);
	var RayCurve = __webpack_require__(3);

	if (typeof AFRAME === 'undefined') {
	  throw new Error('Component attempted to register before AFRAME was available.');
	}

	if (!Element.prototype.matches) {
	  Element.prototype.matches =
	    Element.prototype.matchesSelector ||
	    Element.prototype.mozMatchesSelector ||
	    Element.prototype.msMatchesSelector ||
	    Element.prototype.oMatchesSelector ||
	    Element.prototype.webkitMatchesSelector ||
	    function (s) {
	      var matches = (this.document || this.ownerDocument).querySelectorAll(s);
	      var i = matches.length;
	      while (--i >= 0 && matches.item(i) !== this) { /* no-op */ }
	      return i > -1;
	    };
	}

	AFRAME.registerComponent('teleport-controls', {
	  schema: {
	    type: {default: 'parabolic', oneOf: ['parabolic', 'line']},
	    button: {default: 'trackpad', oneOf: ['trackpad', 'trigger', 'grip', 'menu']},
	    startEvents: {type: 'array'},
	    endEvents: {type: 'array'},
	    collisionEntities: {default: ''},
	    hitEntity: {type: 'selector'},
	    cameraRig: {type: 'selector'},
	    teleportOrigin: {type: 'selector'},
	    hitCylinderColor: {type: 'color', default: '#99ff99'},
	    hitCylinderRadius: {default: 0.25, min: 0},
	    hitCylinderHeight: {default: 0.3, min: 0},
	    interval: {default: 0},
	    maxLength: {default: 10, min: 0, if: {type: ['line']}},
	    curveNumberPoints: {default: 30, min: 2, if: {type: ['parabolic']}},
	    curveLineWidth: {default: 0.025},
	    curveHitColor: {type: 'color', default: '#99ff99'},
	    curveMissColor: {type: 'color', default: '#ff0000'},
	    curveShootingSpeed: {default: 5, min: 0, if: {type: ['parabolic']}},
	    defaultPlaneSize: { default: 100 },
	    landingNormal: {type: 'vec3', default: '0 1 0'},
	    landingMaxAngle: {default: '45', min: 0, max: 360},
	    drawIncrementally: {default: false},
	    incrementalDrawMs: {default: 700},
	    missOpacity: {default: 1.0},
	    hitOpacity: {default: 1.0}
	  },

	  init: function () {
	    var data = this.data;
	    var el = this.el;
	    var teleportEntity;
	    var i;

	    this.active = false;
	    this.obj = el.object3D;
	    this.hitPoint = new THREE.Vector3();
	    this.rigWorldPosition = new THREE.Vector3();
	    this.newRigWorldPosition = new THREE.Vector3();
	    this.teleportEventDetail = {
	      oldPosition: this.rigWorldPosition,
	      newPosition: this.newRigWorldPosition,
	      hitPoint: this.hitPoint
	    };

	    this.hit = false;
	    this.prevCheckTime = undefined;
	    this.prevHitHeight = 0;
	    this.referenceNormal = new THREE.Vector3();
	    this.curveMissColor = new THREE.Color();
	    this.curveHitColor = new THREE.Color();
	    this.raycaster = new THREE.Raycaster();

	    this.defaultPlane = createDefaultPlane(this.data.defaultPlaneSize);
	    this.defaultCollisionMeshes = [this.defaultPlane];

	    teleportEntity = this.teleportEntity = document.createElement('a-entity');
	    teleportEntity.classList.add('teleportRay');
	    teleportEntity.setAttribute('visible', false);
	    el.sceneEl.appendChild(this.teleportEntity);

	    this.onButtonDown = this.onButtonDown.bind(this);
	    this.onButtonUp = this.onButtonUp.bind(this);
	    if (this.data.startEvents.length && this.data.endEvents.length) {

	      for (i = 0; i < this.data.startEvents.length; i++) {
	        el.addEventListener(this.data.startEvents[i], this.onButtonDown);
	      }
	      for (i = 0; i < this.data.endEvents.length; i++) {
	        el.addEventListener(this.data.endEvents[i], this.onButtonUp);
	      }
	    } else {
	      el.addEventListener(data.button + 'down', this.onButtonDown);
	      el.addEventListener(data.button + 'up', this.onButtonUp);
	    }

	    this.queryCollisionEntities();
	  },

	  update: function (oldData) {
	    var data = this.data;
	    var diff = AFRAME.utils.diff(data, oldData);

	    // Update normal.
	    this.referenceNormal.copy(data.landingNormal);

	    // Update colors.
	    this.curveMissColor.set(data.curveMissColor);
	    this.curveHitColor.set(data.curveHitColor);


	    // Create or update line mesh.
	    if (!this.line ||
	        'curveLineWidth' in diff || 'curveNumberPoints' in diff || 'type' in diff) {

	      this.line = createLine(data);
	      this.line.material.opacity = this.data.hitOpacity;
	      this.line.material.transparent = this.data.hitOpacity < 1;
	      this.numActivePoints = data.curveNumberPoints;
	      this.teleportEntity.setObject3D('mesh', this.line.mesh);
	    }

	    // Create or update hit entity.
	    if (data.hitEntity) {
	      this.hitEntity = data.hitEntity;
	    } else if (!this.hitEntity || 'hitCylinderColor' in diff || 'hitCylinderHeight' in diff ||
	               'hitCylinderRadius' in diff) {
	      // Remove previous entity, create new entity (could be more performant).
	      if (this.hitEntity) { this.hitEntity.parentNode.removeChild(this.hitEntity); }
	      this.hitEntity = createHitEntity(data);
	      this.el.sceneEl.appendChild(this.hitEntity);
	    }
	    this.hitEntity.setAttribute('visible', false);

	    if ('collisionEntities' in diff) { this.queryCollisionEntities(); }
	  },

	  remove: function () {
	    var el = this.el;
	    var hitEntity = this.hitEntity;
	    var teleportEntity = this.teleportEntity;

	    if (hitEntity) { hitEntity.parentNode.removeChild(hitEntity); }
	    if (teleportEntity) { teleportEntity.parentNode.removeChild(teleportEntity); }

	    el.sceneEl.removeEventListener('child-attached', this.childAttachHandler);
	    el.sceneEl.removeEventListener('child-detached', this.childDetachHandler);
	  },

	  tick: (function () {
	    var p0 = new THREE.Vector3();
	    var v0 = new THREE.Vector3();
	    var g = -9.8;
	    var a = new THREE.Vector3(0, g, 0);
	    var next = new THREE.Vector3();
	    var last = new THREE.Vector3();
	    var quaternion = new THREE.Quaternion();
	    var translation = new THREE.Vector3();
	    var scale = new THREE.Vector3();
	    var shootAngle = new THREE.Vector3();
	    var lastNext = new THREE.Vector3();
	    var auxDirection = new THREE.Vector3();
	    var timeSinceDrawStart = 0;

	    return function (time, delta) {
	      if (!this.active) { return; }
	      if (this.data.drawIncrementally && this.redrawLine){
	        this.redrawLine = false;
	        timeSinceDrawStart = 0;
	      }
	      timeSinceDrawStart += delta;
	      this.numActivePoints = this.data.curveNumberPoints*timeSinceDrawStart/this.data.incrementalDrawMs;
	      if (this.numActivePoints > this.data.curveNumberPoints){
	        this.numActivePoints = this.data.curveNumberPoints;
	      }

	      // Only check for intersection if interval time has passed.
	      if (this.prevCheckTime && (time - this.prevCheckTime < this.data.interval)) { return; }
	      // Update check time.
	      this.prevCheckTime = time;

	      var matrixWorld = this.obj.matrixWorld;
	      matrixWorld.decompose(translation, quaternion, scale);

	      var direction = shootAngle.set(0, 0, -1)
	        .applyQuaternion(quaternion).normalize();
	      this.line.setDirection(auxDirection.copy(direction));
	      this.obj.getWorldPosition(p0);

	      last.copy(p0);

	      // Set default status as non-hit
	      this.teleportEntity.setAttribute('visible', true);
	      this.line.material.color.set(this.curveMissColor);
	      this.line.material.opacity = this.data.missOpacity;
	      this.line.material.transparent = this.data.missOpacity < 1;
	      this.hitEntity.setAttribute('visible', false);
	      this.hit = false;

	      if (this.data.type === 'parabolic') {
	        v0.copy(direction).multiplyScalar(this.data.curveShootingSpeed);

	        this.lastDrawnIndex = 0;
	        const numPoints = this.data.drawIncrementally ? this.numActivePoints : this.line.numPoints;
	        for (var i = 0; i < numPoints+1; i++) {
	          var t;
	          if (i == Math.floor(numPoints+1)){
	            t =  numPoints / (this.line.numPoints - 1);
	          }
	          else {
	            t = i / (this.line.numPoints - 1);
	          }
	          parabolicCurve(p0, v0, a, t, next);
	          // Update the raycaster with the length of the current segment last->next
	          var dirLastNext = lastNext.copy(next).sub(last).normalize();
	          this.raycaster.far = dirLastNext.length();
	          this.raycaster.set(last, dirLastNext);

	          this.lastDrawnPoint = next;
	          this.lastDrawnIndex = i;
	          if (this.checkMeshCollisions(i, next)) { break; }

	          last.copy(next);
	        }
	        for (var j = this.lastDrawnIndex+1; j < this.line.numPoints; j++) {
	          this.line.setPoint(j, this.lastDrawnPoint);
	        }
	      } else if (this.data.type === 'line') {
	        next.copy(last).add(auxDirection.copy(direction).multiplyScalar(this.data.maxLength));
	        this.raycaster.far = this.data.maxLength;
	        this.raycaster.set(p0, direction);
	        this.line.setPoint(0, p0);

	        this.checkMeshCollisions(1, next);
	      }
	    };
	  })(),

	  /**
	   * Run `querySelectorAll` for `collisionEntities` and maintain it with `child-attached`
	   * and `child-detached` events.
	   */
	  queryCollisionEntities: function () {
	    var collisionEntities;
	    var data = this.data;
	    var el = this.el;

	    if (!data.collisionEntities) {
	      this.collisionEntities = [];
	      return;
	    }

	    collisionEntities = [].slice.call(el.sceneEl.querySelectorAll(data.collisionEntities));
	    this.collisionEntities = collisionEntities;

	    // Update entity list on attach.
	    this.childAttachHandler = function childAttachHandler (evt) {
	      if (!evt.detail.el.matches(data.collisionEntities)) { return; }
	      collisionEntities.push(evt.detail.el);
	    };
	    el.sceneEl.addEventListener('child-attached', this.childAttachHandler);

	    // Update entity list on detach.
	    this.childDetachHandler = function childDetachHandler (evt) {
	      var index;
	      if (!evt.detail.el.matches(data.collisionEntities)) { return; }
	      index = collisionEntities.indexOf(evt.detail.el);
	      if (index === -1) { return; }
	      collisionEntities.splice(index, 1);
	    };
	    el.sceneEl.addEventListener('child-detached', this.childDetachHandler);
	  },

	  onButtonDown: function () {
	    this.active = true;
	    this.redrawLine = true;
	  },

	  /**
	   * Jump!
	   */
	  onButtonUp: (function () {
	    const teleportOriginWorldPosition = new THREE.Vector3();
	    const newRigLocalPosition = new THREE.Vector3();
	    const newHandPosition = [new THREE.Vector3(), new THREE.Vector3()]; // Left and right
	    const handPosition = new THREE.Vector3();

	    return function (evt) {
	      if (!this.active) { return; }

	      // Hide the hit point and the curve
	      this.active = false;
	      this.hitEntity.setAttribute('visible', false);
	      this.teleportEntity.setAttribute('visible', false);

	      if (!this.hit) {
	        // Button released but not hit point
	        return;
	      }

	      const rig = this.data.cameraRig || this.el.sceneEl.camera.el;
	      rig.object3D.getWorldPosition(this.rigWorldPosition);
	      this.newRigWorldPosition.copy(this.hitPoint);

	      // If a teleportOrigin exists, offset the rig such that the teleportOrigin is above the hitPoint
	      const teleportOrigin = this.data.teleportOrigin;
	      if (teleportOrigin) {
	        teleportOrigin.object3D.getWorldPosition(teleportOriginWorldPosition);
	        this.newRigWorldPosition.sub(teleportOriginWorldPosition).add(this.rigWorldPosition);
	      }

	      // Always keep the rig at the same offset off the ground after teleporting
	      this.newRigWorldPosition.y = this.rigWorldPosition.y + this.hitPoint.y - this.prevHitHeight;
	      this.prevHitHeight = this.hitPoint.y;

	      // Finally update the rigs position
	      newRigLocalPosition.copy(this.newRigWorldPosition);
	      if (rig.object3D.parent) {
	        rig.object3D.parent.worldToLocal(newRigLocalPosition);
	      }
	      rig.setAttribute('position', newRigLocalPosition);

	      // If a rig was not explicitly declared, look for hands and mvoe them proportionally as well
	      if (!this.data.cameraRig) {
	        var hands = document.querySelectorAll('a-entity[tracked-controls]');
	        for (var i = 0; i < hands.length; i++) {
	          hands[i].object3D.getWorldPosition(handPosition);

	          // diff = rigWorldPosition - handPosition
	          // newPos = newRigWorldPosition - diff
	          newHandPosition[i].copy(this.newRigWorldPosition).sub(this.rigWorldPosition).add(handPosition);
	          hands[i].setAttribute('position', newHandPosition[i]);
	        }
	      }

	      this.el.emit('teleported', this.teleportEventDetail);
	    };
	  })(),

	  /**
	   * Check for raycaster intersection.
	   *
	   * @param {number} Line fragment point index.
	   * @param {number} Next line fragment point index.
	   * @returns {boolean} true if there's an intersection.
	   */
	  checkMeshCollisions: function (i, next) {
	    // @todo We should add a property to define if the collisionEntity is dynamic or static
	    // If static we should do the map just once, otherwise we're recreating the array in every
	    // loop when aiming.
	    var meshes;
	    if (!this.data.collisionEntities) {
	      meshes = this.defaultCollisionMeshes;
	    } else {
	      meshes = this.collisionEntities.map(function (entity) {
	        return entity.getObject3D('mesh');
	      }).filter(function (n) { return n; });
	      meshes = meshes.length ? meshes : this.defaultCollisionMeshes;
	    }

	    var intersects = this.raycaster.intersectObjects(meshes, true);
	    if (intersects.length > 0 && !this.hit &&
	        this.isValidNormalsAngle(intersects[0].face.normal)) {
	      var point = intersects[0].point;

	      this.line.material.color.set(this.curveHitColor);
	      this.line.material.opacity = this.data.hitOpacity;
	      this.line.material.transparent= this.data.hitOpacity < 1;
	      this.hitEntity.setAttribute('position', point);
	      this.hitEntity.setAttribute('visible', true);

	      this.hit = true;
	      this.hitPoint.copy(intersects[0].point);

	      // If hit, just fill the rest of the points with the hit point and break the loop
	      for (var j = i; j < this.line.numPoints; j++) {
	        this.line.setPoint(j, this.hitPoint);
	      }
	      return true;
	    } else {
	      this.line.setPoint(i, next);
	      return false;
	    }
	  },

	  isValidNormalsAngle: function (collisionNormal) {
	    var angleNormals = this.referenceNormal.angleTo(collisionNormal);
	    return (THREE.Math.RAD2DEG * angleNormals <= this.data.landingMaxAngle);
	  },
	});


	function createLine (data) {
	  var numPoints = data.type === 'line' ? 2 : data.curveNumberPoints;
	  return new RayCurve(numPoints, data.curveLineWidth);
	}

	/**
	 * Create mesh to represent the area of intersection.
	 * Default to a combination of torus and cylinder.
	 */
	function createHitEntity (data) {
	  var cylinder;
	  var hitEntity;
	  var torus;

	  // Parent.
	  hitEntity = document.createElement('a-entity');
	  hitEntity.className = 'hitEntity';

	  // Torus.
	  torus = document.createElement('a-entity');
	  torus.setAttribute('geometry', {
	    primitive: 'torus',
	    radius: data.hitCylinderRadius,
	    radiusTubular: 0.01
	  });
	  torus.setAttribute('rotation', {x: 90, y: 0, z: 0});
	  torus.setAttribute('material', {
	    shader: 'flat',
	    color: data.hitCylinderColor,
	    side: 'double',
	    depthTest: false
	  });
	  hitEntity.appendChild(torus);

	  // Cylinder.
	  cylinder = document.createElement('a-entity');
	  cylinder.setAttribute('position', {x: 0, y: data.hitCylinderHeight / 2, z: 0});
	  cylinder.setAttribute('geometry', {
	    primitive: 'cylinder',
	    segmentsHeight: 1,
	    radius: data.hitCylinderRadius,
	    height: data.hitCylinderHeight,
	    openEnded: true
	  });
	  cylinder.setAttribute('material', {
	    shader: 'flat',
	    color: data.hitCylinderColor,
	    side: 'double',
	    src: cylinderTexture,
	    transparent: true,
	    depthTest: false
	  });
	  hitEntity.appendChild(cylinder);

	  return hitEntity;
	}

	function createDefaultPlane (size) {
	  var geometry;
	  var material;

	  geometry = new THREE.PlaneBufferGeometry(100, 100);
	  geometry.rotateX(-Math.PI / 2);
	  material = new THREE.MeshBasicMaterial({color: 0xffff00});
	  return new THREE.Mesh(geometry, material);
	}


/***/ }),
/* 1 */
/***/ (function(module, exports) {

	module.exports = 'url(data:image/png;base64,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)';


/***/ }),
/* 2 */
/***/ (function(module, exports) {

	/* global THREE */
	// Parabolic motion equation, y = p0 + v0*t + 1/2at^2
	function parabolicCurveScalar (p0, v0, a, t) {
	  return p0 + v0 * t + 0.5 * a * t * t;
	}

	// Parabolic motion equation applied to 3 dimensions
	function parabolicCurve (p0, v0, a, t, out) {
	  out.x = parabolicCurveScalar(p0.x, v0.x, a.x, t);
	  out.y = parabolicCurveScalar(p0.y, v0.y, a.y, t);
	  out.z = parabolicCurveScalar(p0.z, v0.z, a.z, t);
	  return out;
	}

	module.exports = parabolicCurve;


/***/ }),
/* 3 */
/***/ (function(module, exports) {

	/* global THREE */
	var RayCurve = function (numPoints, width) {
	  this.geometry = new THREE.BufferGeometry();
	  this.vertices = new Float32Array(numPoints * 3 * 2);
	  this.uvs = new Float32Array(numPoints * 2 * 2);
	  this.width = width;

	  this.geometry.setAttribute('position', new THREE.BufferAttribute(this.vertices, 3).setUsage(THREE.DynamicDrawUsage));

	  this.material = new THREE.MeshBasicMaterial({
	    side: THREE.DoubleSide,
	    color: 0xff0000
	  });

	  this.mesh = new THREE.Mesh(this.geometry, this.material);
	  THREE.BufferGeometryUtils.toTrianglesDrawMode(this.mesh.geometry, THREE.TriangleStripDrawMode);
	  //this.mesh.drawMode = THREE.TriangleStripDrawMode;

	  this.mesh.frustumCulled = false;
	  this.mesh.vertices = this.vertices;

	  this.direction = new THREE.Vector3();
	  this.numPoints = numPoints;
	};

	RayCurve.prototype = {
	  setDirection: function (direction) {
	    var UP = new THREE.Vector3(0, 1, 0);
	    this.direction
	      .copy(direction)
	      .cross(UP)
	      .normalize()
	      .multiplyScalar(this.width / 2);
	  },

	  setWidth: function (width) {
	    this.width = width;
	  },

	  setPoint: (function () {
	    var posA = new THREE.Vector3();
	    var posB = new THREE.Vector3();

	    return function (i, point) {
	      posA.copy(point).add(this.direction);
	      posB.copy(point).sub(this.direction);

	      var idx = 2 * 3 * i;
	      this.vertices[idx++] = posA.x;
	      this.vertices[idx++] = posA.y;
	      this.vertices[idx++] = posA.z;

	      this.vertices[idx++] = posB.x;
	      this.vertices[idx++] = posB.y;
	      this.vertices[idx++] = posB.z;

	      this.geometry.attributes.position.needsUpdate = true;
	    };
	  })()
	};

	module.exports = RayCurve;


/***/ })
/******/ ]);