Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

aframe-teleport-controls

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

aframe-teleport-controls - npm Package Compare versions

Comparing version 0.3.0 to 0.3.1

176

dist/aframe-teleport-controls.js

@@ -47,3 +47,3 @@ /******/ (function(modules) { // webpackBootstrap

/* global THREE, AFRAME */
/* global THREE, AFRAME, Element */
var cylinderTexture = __webpack_require__(1);

@@ -76,5 +76,8 @@ var parabolicCurve = __webpack_require__(2);

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'},

@@ -89,2 +92,3 @@ hitCylinderRadius: {default: 0.25, min: 0},

curveShootingSpeed: {default: 5, min: 0, if: {type: ['parabolic']}},
defaultPlaneSize: { default: 100 },
landingNormal: {type: 'vec3', default: '0 1 0'},

@@ -98,2 +102,3 @@ landingMaxAngle: {default: '45', min: 0, max: 360}

var teleportEntity;
var i;

@@ -103,4 +108,12 @@ this.active = false;

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.prevHeightDiff = 0;
this.prevHitHeight = 0;
this.referenceNormal = new THREE.Vector3();

@@ -111,3 +124,3 @@ this.curveMissColor = new THREE.Color();

this.defaultPlane = createDefaultPlane();
this.defaultPlane = createDefaultPlane(this.data.defaultPlaneSize);

@@ -119,5 +132,17 @@ teleportEntity = this.teleportEntity = document.createElement('a-entity');

el.addEventListener(data.button + 'down', this.onButtonDown.bind(this));
el.addEventListener(data.button + 'up', this.onButtonUp.bind(this));
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();

@@ -173,2 +198,7 @@ },

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();

@@ -179,2 +209,3 @@ var translation = new THREE.Vector3();

var lastNext = new THREE.Vector3();
var auxDirection = new THREE.Vector3();

@@ -189,7 +220,6 @@ return function (time, delta) {

.applyQuaternion(quaternion).normalize();
this.line.setDirection(direction.clone());
p0.copy(this.obj.getWorldPosition());
this.line.setDirection(auxDirection.copy(direction));
this.obj.getWorldPosition(p0);
var last = p0.clone();
var next;
last.copy(p0);

@@ -203,9 +233,7 @@ // Set default status as non-hit

if (this.data.type === 'parabolic') {
var v0 = direction.clone().multiplyScalar(this.data.curveShootingSpeed);
var g = -9.8;
var a = new THREE.Vector3(0, g, 0);
v0.copy(direction).multiplyScalar(this.data.curveShootingSpeed);
for (var i = 0; i < this.line.numPoints; i++) {
var t = i / (this.line.numPoints - 1);
next = parabolicCurve(p0, v0, a, t);
parabolicCurve(p0, v0, a, t, next);
// Update the raycaster with the length of the current segment last->next

@@ -220,5 +248,4 @@ var dirLastNext = lastNext.copy(next).sub(last).normalize();

} else if (this.data.type === 'line') {
next = last.add(direction.clone().multiplyScalar(this.data.maxLength));
next.copy(last).add(auxDirection.copy(direction).multiplyScalar(this.data.maxLength));
this.raycaster.far = this.data.maxLength;
this.raycaster.set(p0, direction);

@@ -243,3 +270,3 @@ this.line.setPoint(0, p0);

this.collisionEntities = [];
return
return;
}

@@ -275,52 +302,60 @@

*/
onButtonUp: function (evt) {
if (!this.active) { return; }
onButtonUp: (function () {
const teleportOriginWorldPosition = new THREE.Vector3();
const newRigLocalPosition = new THREE.Vector3();
const newHandPosition = new THREE.Vector3();
const handPosition = new THREE.Vector3();
// Jump!
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);
// 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;
}
if (!this.hit) {
// Button released but not hit point
return;
}
// @todo Create this aux vectors outside
if (this.data.cameraRig) {
var cameraRigPosition = new THREE.Vector3().copy(this.data.cameraRig.getAttribute('position'));
var newCameraRigPositionY = cameraRigPosition.y + this.hitPoint.y - this.prevHeightDiff;
var newCameraRigPosition = new THREE.Vector3(this.hitPoint.x, newCameraRigPositionY, this.hitPoint.z);
this.prevHeightDiff = this.hitPoint.y;
this.data.cameraRig.setAttribute('position', newCameraRigPosition);
} else {
var cameraEl = this.el.sceneEl.camera.el;
var camPosition = new THREE.Vector3().copy(cameraEl.getAttribute('position'));
const rig = this.data.cameraRig || this.el.sceneEl.camera.el;
rig.object3D.getWorldPosition(this.rigWorldPosition);
this.newRigWorldPosition.copy(this.hitPoint);
var newCamPositionY = camPosition.y + this.hitPoint.y - this.prevHeightDiff;
var newCamPosition = new THREE.Vector3(this.hitPoint.x, newCamPositionY, this.hitPoint.z);
this.prevHeightDiff = this.hitPoint.y;
// 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);
}
cameraEl.setAttribute('position', newCamPosition);
// 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;
// Find the hands and move them proportionally
var hands = document.querySelectorAll('a-entity[tracked-controls]');
for (var i = 0; i < hands.length; i++) {
var position = hands[i].getAttribute('position');
var pos = new THREE.Vector3().copy(position);
var diff = camPosition.clone().sub(pos);
var newPosition = newCamPosition.clone().sub(diff);
hands[i].setAttribute('position', newPosition);
// Finally update the rigs position
newRigLocalPosition.copy(this.newRigWorldPosition);
if (rig.object3D.parent) {
rig.object3D.parent.worldToLocal(newRigLocalPosition);
}
}
rig.setAttribute('position', newRigLocalPosition);
this.el.emit('teleport', {
oldPosition: camPosition,
newPosition: newCamPosition,
hitPoint: this.hitPoint
});
},
// 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.copy(this.newRigWorldPosition).sub(this.rigWorldPosition).add(handPosition);
hands[i].setAttribute('position', newHandPosition);
}
}
this.el.emit('teleported', this.teleportEventDetail);
};
})(),
/**

@@ -334,7 +369,6 @@ * Check for raycaster intersection.

checkMeshCollisions: function (i, next) {
var intersects;
var meshes;
// Gather the meshes here to avoid having to wait for entities to iniitalize.
meshes = this.collisionEntities.map(function (entity) {
// @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 = this.collisionEntities.map(function (entity) {
return entity.getObject3D('mesh');

@@ -344,3 +378,3 @@ }).filter(function (n) { return n; });

intersects = this.raycaster.intersectObjects(meshes, true);
var intersects = this.raycaster.intersectObjects(meshes, true);
if (intersects.length > 0 && !this.hit &&

@@ -432,9 +466,8 @@ this.isValidNormalsAngle(intersects[0].face.normal)) {

function createDefaultPlane () {
function createDefaultPlane (size) {
var geometry;
var material;
// @hack: Because I can't get THREE.BufferPlane working on raycaster.
geometry = new THREE.BoxBufferGeometry(100, 0.5, 100);
geometry.applyMatrix(new THREE.Matrix4().makeTranslation(0, -0.25, 0));
geometry = new THREE.PlaneBufferGeometry(100, 100);
geometry.rotateX(-Math.PI / 2);
material = new THREE.MeshBasicMaterial({color: 0xffff00});

@@ -463,8 +496,7 @@ return new THREE.Mesh(geometry, material);

// Parabolic motion equation applied to 3 dimensions
function parabolicCurve (p0, v0, a, t) {
var ret = new THREE.Vector3();
ret.x = parabolicCurveScalar(p0.x, v0.x, a.x, t);
ret.y = parabolicCurveScalar(p0.y, v0.y, a.y, t);
ret.z = parabolicCurveScalar(p0.z, v0.z, a.z, t);
return ret;
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;
}

@@ -471,0 +503,0 @@

@@ -1,1 +0,1 @@

!function(t){function e(n){if(i[n])return i[n].exports;var r=i[n]={exports:{},id:n,loaded:!1};return t[n].call(r.exports,r,r.exports,e),r.loaded=!0,r.exports}var i={};return e.m=t,e.c=i,e.p="",e(0)}([function(t,e,i){function n(t){var e="line"===t.type?2:t.curveNumberPoints;return new h(e,t.curveLineWidth)}function r(t){var e,i,n;return i=document.createElement("a-entity"),i.className="hitEntity",n=document.createElement("a-entity"),n.setAttribute("geometry",{primitive:"torus",radius:t.hitCylinderRadius,radiusTubular:.01}),n.setAttribute("rotation",{x:90,y:0,z:0}),n.setAttribute("material",{shader:"flat",color:t.hitCylinderColor,side:"double",depthTest:!1}),i.appendChild(n),e=document.createElement("a-entity"),e.setAttribute("position",{x:0,y:t.hitCylinderHeight/2,z:0}),e.setAttribute("geometry",{primitive:"cylinder",segmentsHeight:1,radius:t.hitCylinderRadius,height:t.hitCylinderHeight,openEnded:!0}),e.setAttribute("material",{shader:"flat",color:t.hitCylinderColor,side:"double",src:s,transparent:!0,depthTest:!1}),i.appendChild(e),i}function o(){var t,e;return t=new THREE.BoxBufferGeometry(100,.5,100),t.applyMatrix((new THREE.Matrix4).makeTranslation(0,-.25,0)),e=new THREE.MeshBasicMaterial({color:16776960}),new THREE.Mesh(t,e)}var s=i(3),a=i(1),h=i(2);if("undefined"==typeof AFRAME)throw new Error("Component attempted to register before AFRAME was available.");Element.prototype.matches||(Element.prototype.matches=Element.prototype.matchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector||Element.prototype.webkitMatchesSelector||function(t){for(var e=(this.document||this.ownerDocument).querySelectorAll(t),i=e.length;--i>=0&&e.item(i)!==this;);return i>-1}),AFRAME.registerComponent("teleport-controls",{schema:{type:{default:"parabolic",oneOf:["parabolic","line"]},button:{default:"trackpad",oneOf:["trackpad","trigger","grip","menu"]},collisionEntities:{default:""},hitEntity:{type:"selector"},cameraRig:{type:"selector"},hitCylinderColor:{type:"color",default:"#99ff99"},hitCylinderRadius:{default:.25,min:0},hitCylinderHeight:{default:.3,min:0},maxLength:{default:10,min:0,if:{type:["line"]}},curveNumberPoints:{default:30,min:2,if:{type:["parabolic"]}},curveLineWidth:{default:.025},curveHitColor:{type:"color",default:"#99ff99"},curveMissColor:{type:"color",default:"#ff0000"},curveShootingSpeed:{default:5,min:0,if:{type:["parabolic"]}},landingNormal:{type:"vec3",default:"0 1 0"},landingMaxAngle:{default:"45",min:0,max:360}},init:function(){var t,e=this.data,i=this.el;this.active=!1,this.obj=i.object3D,this.hitPoint=new THREE.Vector3,this.hit=!1,this.prevHeightDiff=0,this.referenceNormal=new THREE.Vector3,this.curveMissColor=new THREE.Color,this.curveHitColor=new THREE.Color,this.raycaster=new THREE.Raycaster,this.defaultPlane=o(),t=this.teleportEntity=document.createElement("a-entity"),t.classList.add("teleportRay"),t.setAttribute("visible",!1),i.sceneEl.appendChild(this.teleportEntity),i.addEventListener(e.button+"down",this.onButtonDown.bind(this)),i.addEventListener(e.button+"up",this.onButtonUp.bind(this)),this.queryCollisionEntities()},update:function(t){var e=this.data,i=AFRAME.utils.diff(e,t);this.referenceNormal.copy(e.landingNormal),this.curveMissColor.set(e.curveMissColor),this.curveHitColor.set(e.curveHitColor),(!this.line||"curveLineWidth"in i||"curveNumberPoints"in i||"type"in i)&&(this.line=n(e),this.teleportEntity.setObject3D("mesh",this.line.mesh)),e.hitEntity?this.hitEntity=e.hitEntity:(!this.hitEntity||"hitCylinderColor"in i||"hitCylinderHeight"in i||"hitCylinderRadius"in i)&&(this.hitEntity&&this.hitEntity.parentNode.removeChild(this.hitEntity),this.hitEntity=r(e),this.el.sceneEl.appendChild(this.hitEntity)),this.hitEntity.setAttribute("visible",!1),"collisionEntities"in i&&this.queryCollisionEntities()},remove:function(){var t=this.el,e=this.hitEntity,i=this.teleportEntity;e&&e.parentNode.removeChild(e),i&&i.parentNode.removeChild(i),t.sceneEl.removeEventListener("child-attached",this.childAttachHandler),t.sceneEl.removeEventListener("child-detached",this.childDetachHandler)},tick:function(){var t=new THREE.Vector3,e=new THREE.Quaternion,i=new THREE.Vector3,n=new THREE.Vector3,r=new THREE.Vector3,o=new THREE.Vector3;return function(s,h){if(this.active){var l=this.obj.matrixWorld;l.decompose(i,e,n);var c=r.set(0,0,-1).applyQuaternion(e).normalize();this.line.setDirection(c.clone()),t.copy(this.obj.getWorldPosition());var u,d=t.clone();if(this.teleportEntity.setAttribute("visible",!0),this.line.material.color.set(this.curveMissColor),this.hitEntity.setAttribute("visible",!1),this.hit=!1,"parabolic"===this.data.type)for(var A=c.clone().multiplyScalar(this.data.curveShootingSpeed),E=-9.8,p=new THREE.Vector3(0,E,0),y=0;y<this.line.numPoints;y++){var m=y/(this.line.numPoints-1);u=a(t,A,p,m);var f=o.copy(u).sub(d).normalize();if(this.raycaster.far=f.length(),this.raycaster.set(d,f),this.checkMeshCollisions(y,u))break;d.copy(u)}else"line"===this.data.type&&(u=d.add(c.clone().multiplyScalar(this.data.maxLength)),this.raycaster.far=this.data.maxLength,this.raycaster.set(t,c),this.line.setPoint(0,t),this.checkMeshCollisions(1,u))}}}(),queryCollisionEntities:function(){var t,e=this.data,i=this.el;return e.collisionEntities?(t=[].slice.call(i.sceneEl.querySelectorAll(e.collisionEntities)),this.collisionEntities=t,this.childAttachHandler=function(i){i.detail.el.matches(e.collisionEntities)&&t.push(i.detail.el)},i.sceneEl.addEventListener("child-attached",this.childAttachHandler),this.childDetachHandler=function(i){var n;i.detail.el.matches(e.collisionEntities)&&(n=t.indexOf(i.detail.el),n!==-1&&t.splice(n,1))},void i.sceneEl.addEventListener("child-detached",this.childDetachHandler)):void(this.collisionEntities=[])},onButtonDown:function(){this.active=!0},onButtonUp:function(t){if(this.active&&(this.active=!1,this.hitEntity.setAttribute("visible",!1),this.teleportEntity.setAttribute("visible",!1),this.hit)){if(this.data.cameraRig){var e=(new THREE.Vector3).copy(this.data.cameraRig.getAttribute("position")),i=e.y+this.hitPoint.y-this.prevHeightDiff,n=new THREE.Vector3(this.hitPoint.x,i,this.hitPoint.z);this.prevHeightDiff=this.hitPoint.y,this.data.cameraRig.setAttribute("position",n)}else{var r=this.el.sceneEl.camera.el,o=(new THREE.Vector3).copy(r.getAttribute("position")),s=o.y+this.hitPoint.y-this.prevHeightDiff,a=new THREE.Vector3(this.hitPoint.x,s,this.hitPoint.z);this.prevHeightDiff=this.hitPoint.y,r.setAttribute("position",a);for(var h=document.querySelectorAll("a-entity[tracked-controls]"),l=0;l<h.length;l++){var c=h[l].getAttribute("position"),u=(new THREE.Vector3).copy(c),d=o.clone().sub(u),A=a.clone().sub(d);h[l].setAttribute("position",A)}}this.el.emit("teleport",{oldPosition:o,newPosition:a,hitPoint:this.hitPoint})}},checkMeshCollisions:function(t,e){var i,n;if(n=this.collisionEntities.map(function(t){return t.getObject3D("mesh")}).filter(function(t){return t}),n=n.length?n:[this.defaultPlane],i=this.raycaster.intersectObjects(n,!0),i.length>0&&!this.hit&&this.isValidNormalsAngle(i[0].face.normal)){var r=i[0].point;this.line.material.color.set(this.curveHitColor),this.hitEntity.setAttribute("position",r),this.hitEntity.setAttribute("visible",!0),this.hit=!0,this.hitPoint.copy(i[0].point);for(var o=t;o<this.line.numPoints;o++)this.line.setPoint(o,this.hitPoint);return!0}return this.line.setPoint(t,e),!1},isValidNormalsAngle:function(t){var e=this.referenceNormal.angleTo(t);return THREE.Math.RAD2DEG*e<=this.data.landingMaxAngle}})},function(t,e){function i(t,e,i,n){return t+e*n+.5*i*n*n}function n(t,e,n,r){var o=new THREE.Vector3;return o.x=i(t.x,e.x,n.x,r),o.y=i(t.y,e.y,n.y,r),o.z=i(t.z,e.z,n.z,r),o}t.exports=n},function(t,e){var i=function(t,e){this.geometry=new THREE.BufferGeometry,this.vertices=new Float32Array(3*t*2),this.uvs=new Float32Array(2*t*2),this.width=e,this.geometry.addAttribute("position",new THREE.BufferAttribute(this.vertices,3).setDynamic(!0)),this.material=new THREE.MeshBasicMaterial({side:THREE.DoubleSide,color:16711680}),this.mesh=new THREE.Mesh(this.geometry,this.material),this.mesh.drawMode=THREE.TriangleStripDrawMode,this.mesh.frustumCulled=!1,this.mesh.vertices=this.vertices,this.direction=new THREE.Vector3,this.numPoints=t};i.prototype={setDirection:function(t){var e=new THREE.Vector3(0,1,0);this.direction.copy(t).cross(e).normalize().multiplyScalar(this.width/2)},setWidth:function(t){this.width=t},setPoint:function(){var t=new THREE.Vector3,e=new THREE.Vector3;return function(i,n){t.copy(n).add(this.direction),e.copy(n).sub(this.direction);var r=6*i;this.vertices[r++]=t.x,this.vertices[r++]=t.y,this.vertices[r++]=t.z,this.vertices[r++]=e.x,this.vertices[r++]=e.y,this.vertices[r++]=e.z,this.geometry.attributes.position.needsUpdate=!0}}()},t.exports=i},function(t,e){t.exports="url(data:image/png;base64,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)"}]);
!function(t){function e(n){if(i[n])return i[n].exports;var o=i[n]={exports:{},id:n,loaded:!1};return t[n].call(o.exports,o,o.exports,e),o.loaded=!0,o.exports}var i={};return e.m=t,e.c=i,e.p="",e(0)}([function(t,e,i){function n(t){var e="line"===t.type?2:t.curveNumberPoints;return new l(e,t.curveLineWidth)}function o(t){var e,i,n;return i=document.createElement("a-entity"),i.className="hitEntity",n=document.createElement("a-entity"),n.setAttribute("geometry",{primitive:"torus",radius:t.hitCylinderRadius,radiusTubular:.01}),n.setAttribute("rotation",{x:90,y:0,z:0}),n.setAttribute("material",{shader:"flat",color:t.hitCylinderColor,side:"double",depthTest:!1}),i.appendChild(n),e=document.createElement("a-entity"),e.setAttribute("position",{x:0,y:t.hitCylinderHeight/2,z:0}),e.setAttribute("geometry",{primitive:"cylinder",segmentsHeight:1,radius:t.hitCylinderRadius,height:t.hitCylinderHeight,openEnded:!0}),e.setAttribute("material",{shader:"flat",color:t.hitCylinderColor,side:"double",src:s,transparent:!0,depthTest:!1}),i.appendChild(e),i}function r(t){var e,i;return e=new THREE.PlaneBufferGeometry(100,100),e.rotateX(-Math.PI/2),i=new THREE.MeshBasicMaterial({color:16776960}),new THREE.Mesh(e,i)}var s=i(3),a=i(1),l=i(2);if("undefined"==typeof AFRAME)throw new Error("Component attempted to register before AFRAME was available.");Element.prototype.matches||(Element.prototype.matches=Element.prototype.matchesSelector||Element.prototype.mozMatchesSelector||Element.prototype.msMatchesSelector||Element.prototype.oMatchesSelector||Element.prototype.webkitMatchesSelector||function(t){for(var e=(this.document||this.ownerDocument).querySelectorAll(t),i=e.length;--i>=0&&e.item(i)!==this;);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:.25,min:0},hitCylinderHeight:{default:.3,min:0},maxLength:{default:10,min:0,if:{type:["line"]}},curveNumberPoints:{default:30,min:2,if:{type:["parabolic"]}},curveLineWidth:{default:.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}},init:function(){var t,e,i=this.data,n=this.el;if(this.active=!1,this.obj=n.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=!1,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=r(this.data.defaultPlaneSize),t=this.teleportEntity=document.createElement("a-entity"),t.classList.add("teleportRay"),t.setAttribute("visible",!1),n.sceneEl.appendChild(this.teleportEntity),this.onButtonDown=this.onButtonDown.bind(this),this.onButtonUp=this.onButtonUp.bind(this),this.data.startEvents.length&&this.data.endEvents.length){for(e=0;e<this.data.startEvents.length;e++)n.addEventListener(this.data.startEvents[e],this.onButtonDown);for(e=0;e<this.data.endEvents.length;e++)n.addEventListener(this.data.endEvents[e],this.onButtonUp)}else n.addEventListener(i.button+"down",this.onButtonDown),n.addEventListener(i.button+"up",this.onButtonUp);this.queryCollisionEntities()},update:function(t){var e=this.data,i=AFRAME.utils.diff(e,t);this.referenceNormal.copy(e.landingNormal),this.curveMissColor.set(e.curveMissColor),this.curveHitColor.set(e.curveHitColor),(!this.line||"curveLineWidth"in i||"curveNumberPoints"in i||"type"in i)&&(this.line=n(e),this.teleportEntity.setObject3D("mesh",this.line.mesh)),e.hitEntity?this.hitEntity=e.hitEntity:(!this.hitEntity||"hitCylinderColor"in i||"hitCylinderHeight"in i||"hitCylinderRadius"in i)&&(this.hitEntity&&this.hitEntity.parentNode.removeChild(this.hitEntity),this.hitEntity=o(e),this.el.sceneEl.appendChild(this.hitEntity)),this.hitEntity.setAttribute("visible",!1),"collisionEntities"in i&&this.queryCollisionEntities()},remove:function(){var t=this.el,e=this.hitEntity,i=this.teleportEntity;e&&e.parentNode.removeChild(e),i&&i.parentNode.removeChild(i),t.sceneEl.removeEventListener("child-attached",this.childAttachHandler),t.sceneEl.removeEventListener("child-detached",this.childDetachHandler)},tick:function(){var t=new THREE.Vector3,e=new THREE.Vector3,i=-9.8,n=new THREE.Vector3(0,i,0),o=new THREE.Vector3,r=new THREE.Vector3,s=new THREE.Quaternion,l=new THREE.Vector3,h=new THREE.Vector3,c=new THREE.Vector3,d=new THREE.Vector3,u=new THREE.Vector3;return function(i,E){if(this.active){var A=this.obj.matrixWorld;A.decompose(l,s,h);var p=c.set(0,0,-1).applyQuaternion(s).normalize();if(this.line.setDirection(u.copy(p)),this.obj.getWorldPosition(t),r.copy(t),this.teleportEntity.setAttribute("visible",!0),this.line.material.color.set(this.curveMissColor),this.hitEntity.setAttribute("visible",!1),this.hit=!1,"parabolic"===this.data.type){e.copy(p).multiplyScalar(this.data.curveShootingSpeed);for(var y=0;y<this.line.numPoints;y++){var v=y/(this.line.numPoints-1);a(t,e,n,v,o);var m=d.copy(o).sub(r).normalize();if(this.raycaster.far=m.length(),this.raycaster.set(r,m),this.checkMeshCollisions(y,o))break;r.copy(o)}}else"line"===this.data.type&&(o.copy(r).add(u.copy(p).multiplyScalar(this.data.maxLength)),this.raycaster.far=this.data.maxLength,this.raycaster.set(t,p),this.line.setPoint(0,t),this.checkMeshCollisions(1,o))}}}(),queryCollisionEntities:function(){var t,e=this.data,i=this.el;return e.collisionEntities?(t=[].slice.call(i.sceneEl.querySelectorAll(e.collisionEntities)),this.collisionEntities=t,this.childAttachHandler=function(i){i.detail.el.matches(e.collisionEntities)&&t.push(i.detail.el)},i.sceneEl.addEventListener("child-attached",this.childAttachHandler),this.childDetachHandler=function(i){var n;i.detail.el.matches(e.collisionEntities)&&(n=t.indexOf(i.detail.el),n!==-1&&t.splice(n,1))},void i.sceneEl.addEventListener("child-detached",this.childDetachHandler)):void(this.collisionEntities=[])},onButtonDown:function(){this.active=!0},onButtonUp:function(){const t=new THREE.Vector3,e=new THREE.Vector3,i=new THREE.Vector3,n=new THREE.Vector3;return function(o){if(this.active&&(this.active=!1,this.hitEntity.setAttribute("visible",!1),this.teleportEntity.setAttribute("visible",!1),this.hit)){const r=this.data.cameraRig||this.el.sceneEl.camera.el;r.object3D.getWorldPosition(this.rigWorldPosition),this.newRigWorldPosition.copy(this.hitPoint);const s=this.data.teleportOrigin;if(s&&(s.object3D.getWorldPosition(t),this.newRigWorldPosition.sub(t).add(this.rigWorldPosition)),this.newRigWorldPosition.y=this.rigWorldPosition.y+this.hitPoint.y-this.prevHitHeight,this.prevHitHeight=this.hitPoint.y,e.copy(this.newRigWorldPosition),r.object3D.parent&&r.object3D.parent.worldToLocal(e),r.setAttribute("position",e),!this.data.cameraRig)for(var a=document.querySelectorAll("a-entity[tracked-controls]"),l=0;l<a.length;l++)a[l].object3D.getWorldPosition(n),i.copy(this.newRigWorldPosition).sub(this.rigWorldPosition).add(n),a[l].setAttribute("position",i);this.el.emit("teleported",this.teleportEventDetail)}}}(),checkMeshCollisions:function(t,e){var i=this.collisionEntities.map(function(t){return t.getObject3D("mesh")}).filter(function(t){return t});i=i.length?i:[this.defaultPlane];var n=this.raycaster.intersectObjects(i,!0);if(n.length>0&&!this.hit&&this.isValidNormalsAngle(n[0].face.normal)){var o=n[0].point;this.line.material.color.set(this.curveHitColor),this.hitEntity.setAttribute("position",o),this.hitEntity.setAttribute("visible",!0),this.hit=!0,this.hitPoint.copy(n[0].point);for(var r=t;r<this.line.numPoints;r++)this.line.setPoint(r,this.hitPoint);return!0}return this.line.setPoint(t,e),!1},isValidNormalsAngle:function(t){var e=this.referenceNormal.angleTo(t);return THREE.Math.RAD2DEG*e<=this.data.landingMaxAngle}})},function(t,e){function i(t,e,i,n){return t+e*n+.5*i*n*n}function n(t,e,n,o,r){return r.x=i(t.x,e.x,n.x,o),r.y=i(t.y,e.y,n.y,o),r.z=i(t.z,e.z,n.z,o),r}t.exports=n},function(t,e){var i=function(t,e){this.geometry=new THREE.BufferGeometry,this.vertices=new Float32Array(3*t*2),this.uvs=new Float32Array(2*t*2),this.width=e,this.geometry.addAttribute("position",new THREE.BufferAttribute(this.vertices,3).setDynamic(!0)),this.material=new THREE.MeshBasicMaterial({side:THREE.DoubleSide,color:16711680}),this.mesh=new THREE.Mesh(this.geometry,this.material),this.mesh.drawMode=THREE.TriangleStripDrawMode,this.mesh.frustumCulled=!1,this.mesh.vertices=this.vertices,this.direction=new THREE.Vector3,this.numPoints=t};i.prototype={setDirection:function(t){var e=new THREE.Vector3(0,1,0);this.direction.copy(t).cross(e).normalize().multiplyScalar(this.width/2)},setWidth:function(t){this.width=t},setPoint:function(){var t=new THREE.Vector3,e=new THREE.Vector3;return function(i,n){t.copy(n).add(this.direction),e.copy(n).sub(this.direction);var o=6*i;this.vertices[o++]=t.x,this.vertices[o++]=t.y,this.vertices[o++]=t.z,this.vertices[o++]=e.x,this.vertices[o++]=e.y,this.vertices[o++]=e.z,this.geometry.attributes.position.needsUpdate=!0}}()},t.exports=i},function(t,e){t.exports="url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAQCAYAAADXnxW3AAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAADJJREFUeNpEx7ENgDAAAzArK0JA6f8X9oewlcWStU1wBGdwB08wgjeYm79jc2nbYH0DAC/+CORJxO5fAAAAAElFTkSuQmCC)"}]);

@@ -1,2 +0,2 @@

/* global THREE, AFRAME */
/* global THREE, AFRAME, Element */
var cylinderTexture = require('./lib/cylinderTexture');

@@ -29,5 +29,8 @@ var parabolicCurve = require('./lib/ParabolicCurve');

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'},

@@ -42,2 +45,3 @@ hitCylinderRadius: {default: 0.25, min: 0},

curveShootingSpeed: {default: 5, min: 0, if: {type: ['parabolic']}},
defaultPlaneSize: { default: 100 },
landingNormal: {type: 'vec3', default: '0 1 0'},

@@ -51,2 +55,3 @@ landingMaxAngle: {default: '45', min: 0, max: 360}

var teleportEntity;
var i;

@@ -56,4 +61,12 @@ this.active = false;

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.prevHeightDiff = 0;
this.prevHitHeight = 0;
this.referenceNormal = new THREE.Vector3();

@@ -64,3 +77,3 @@ this.curveMissColor = new THREE.Color();

this.defaultPlane = createDefaultPlane();
this.defaultPlane = createDefaultPlane(this.data.defaultPlaneSize);

@@ -72,5 +85,17 @@ teleportEntity = this.teleportEntity = document.createElement('a-entity');

el.addEventListener(data.button + 'down', this.onButtonDown.bind(this));
el.addEventListener(data.button + 'up', this.onButtonUp.bind(this));
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();

@@ -126,2 +151,7 @@ },

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();

@@ -132,2 +162,3 @@ var translation = new THREE.Vector3();

var lastNext = new THREE.Vector3();
var auxDirection = new THREE.Vector3();

@@ -142,7 +173,6 @@ return function (time, delta) {

.applyQuaternion(quaternion).normalize();
this.line.setDirection(direction.clone());
p0.copy(this.obj.getWorldPosition());
this.line.setDirection(auxDirection.copy(direction));
this.obj.getWorldPosition(p0);
var last = p0.clone();
var next;
last.copy(p0);

@@ -156,9 +186,7 @@ // Set default status as non-hit

if (this.data.type === 'parabolic') {
var v0 = direction.clone().multiplyScalar(this.data.curveShootingSpeed);
var g = -9.8;
var a = new THREE.Vector3(0, g, 0);
v0.copy(direction).multiplyScalar(this.data.curveShootingSpeed);
for (var i = 0; i < this.line.numPoints; i++) {
var t = i / (this.line.numPoints - 1);
next = parabolicCurve(p0, v0, a, t);
parabolicCurve(p0, v0, a, t, next);
// Update the raycaster with the length of the current segment last->next

@@ -173,5 +201,4 @@ var dirLastNext = lastNext.copy(next).sub(last).normalize();

} else if (this.data.type === 'line') {
next = last.add(direction.clone().multiplyScalar(this.data.maxLength));
next.copy(last).add(auxDirection.copy(direction).multiplyScalar(this.data.maxLength));
this.raycaster.far = this.data.maxLength;
this.raycaster.set(p0, direction);

@@ -196,3 +223,3 @@ this.line.setPoint(0, p0);

this.collisionEntities = [];
return
return;
}

@@ -228,52 +255,60 @@

*/
onButtonUp: function (evt) {
if (!this.active) { return; }
onButtonUp: (function () {
const teleportOriginWorldPosition = new THREE.Vector3();
const newRigLocalPosition = new THREE.Vector3();
const newHandPosition = new THREE.Vector3();
const handPosition = new THREE.Vector3();
// Jump!
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);
// 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;
}
if (!this.hit) {
// Button released but not hit point
return;
}
// @todo Create this aux vectors outside
if (this.data.cameraRig) {
var cameraRigPosition = new THREE.Vector3().copy(this.data.cameraRig.getAttribute('position'));
var newCameraRigPositionY = cameraRigPosition.y + this.hitPoint.y - this.prevHeightDiff;
var newCameraRigPosition = new THREE.Vector3(this.hitPoint.x, newCameraRigPositionY, this.hitPoint.z);
this.prevHeightDiff = this.hitPoint.y;
this.data.cameraRig.setAttribute('position', newCameraRigPosition);
} else {
var cameraEl = this.el.sceneEl.camera.el;
var camPosition = new THREE.Vector3().copy(cameraEl.getAttribute('position'));
const rig = this.data.cameraRig || this.el.sceneEl.camera.el;
rig.object3D.getWorldPosition(this.rigWorldPosition);
this.newRigWorldPosition.copy(this.hitPoint);
var newCamPositionY = camPosition.y + this.hitPoint.y - this.prevHeightDiff;
var newCamPosition = new THREE.Vector3(this.hitPoint.x, newCamPositionY, this.hitPoint.z);
this.prevHeightDiff = this.hitPoint.y;
// 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);
}
cameraEl.setAttribute('position', newCamPosition);
// 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;
// Find the hands and move them proportionally
var hands = document.querySelectorAll('a-entity[tracked-controls]');
for (var i = 0; i < hands.length; i++) {
var position = hands[i].getAttribute('position');
var pos = new THREE.Vector3().copy(position);
var diff = camPosition.clone().sub(pos);
var newPosition = newCamPosition.clone().sub(diff);
hands[i].setAttribute('position', newPosition);
// Finally update the rigs position
newRigLocalPosition.copy(this.newRigWorldPosition);
if (rig.object3D.parent) {
rig.object3D.parent.worldToLocal(newRigLocalPosition);
}
}
rig.setAttribute('position', newRigLocalPosition);
this.el.emit('teleport', {
oldPosition: camPosition,
newPosition: newCamPosition,
hitPoint: this.hitPoint
});
},
// 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.copy(this.newRigWorldPosition).sub(this.rigWorldPosition).add(handPosition);
hands[i].setAttribute('position', newHandPosition);
}
}
this.el.emit('teleported', this.teleportEventDetail);
};
})(),
/**

@@ -287,7 +322,6 @@ * Check for raycaster intersection.

checkMeshCollisions: function (i, next) {
var intersects;
var meshes;
// Gather the meshes here to avoid having to wait for entities to iniitalize.
meshes = this.collisionEntities.map(function (entity) {
// @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 = this.collisionEntities.map(function (entity) {
return entity.getObject3D('mesh');

@@ -297,3 +331,3 @@ }).filter(function (n) { return n; });

intersects = this.raycaster.intersectObjects(meshes, true);
var intersects = this.raycaster.intersectObjects(meshes, true);
if (intersects.length > 0 && !this.hit &&

@@ -385,11 +419,10 @@ this.isValidNormalsAngle(intersects[0].face.normal)) {

function createDefaultPlane () {
function createDefaultPlane (size) {
var geometry;
var material;
// @hack: Because I can't get THREE.BufferPlane working on raycaster.
geometry = new THREE.BoxBufferGeometry(100, 0.5, 100);
geometry.applyMatrix(new THREE.Matrix4().makeTranslation(0, -0.25, 0));
geometry = new THREE.PlaneBufferGeometry(100, 100);
geometry.rotateX(-Math.PI / 2);
material = new THREE.MeshBasicMaterial({color: 0xffff00});
return new THREE.Mesh(geometry, material);
}

@@ -8,10 +8,9 @@ /* global THREE */

// Parabolic motion equation applied to 3 dimensions
function parabolicCurve (p0, v0, a, t) {
var ret = new THREE.Vector3();
ret.x = parabolicCurveScalar(p0.x, v0.x, a.x, t);
ret.y = parabolicCurveScalar(p0.y, v0.y, a.y, t);
ret.z = parabolicCurveScalar(p0.z, v0.z, a.z, t);
return ret;
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;
{
"name": "aframe-teleport-controls",
"version": "0.3.0",
"version": "0.3.1",
"description": "A-Frame teleport controls component",

@@ -5,0 +5,0 @@ "author": "Fernando Serrano <fernandojsg@gmail.com> (http://fernandojsg.com/)",

@@ -12,5 +12,7 @@ # aframe-teleport-controls

| cameraRig | Selector of the camera Rig to teleport | |
| teleportOrigin | Selector of the child of cameraRig to use as the center point for teleporting, typically the camera. If set teleporting will position the cameraRig such that this element ends up above the teleport location (rather than the center of the camreaRig) | |
| type | Type of teleport: line or parabolic | parabolic |
| button | Button used to launch the teleport | trackpad |
| button | Button used to launch the teleport: trackpad, trigger, grip, menu | trackpad |
| collisionEntities | Selector of the meshes used to check the collisions. If no value provided a plane Y=0 is used | |
| endEvents | Paired with `startEvents`, list of events to listen for to finish teleporting.| [] |
| hitEntity | Entity used to show at the hitting position. If no value provided a cylinder will be used as default. | |

@@ -20,3 +22,2 @@ | hitCylinderColor | Color used for the default `hitEntity` primitives | #99ff99 |

| hitCylinderHeight | Height used for the default `hitEntity` primitives | 0.3 |
| maxLength | Max. length for line teleport | 10 |
| curveHitColor | Color used for the curve when hit the mesh | #99ff99 |

@@ -27,5 +28,7 @@ | curveMissColor | Color used for the curve when it doesn't hit anything | #ff0000 |

| curveShootingSpeed | Curve shooting speed, as bigger value, farther distance. | 5 |
| defaultPlaneSize | Default plane size | 100 |
| maxLength | Max length of the ray when using type=line teleport | 10 |
| landingNormal | Normal vector to detect collisions with the `collisionEntity` | (0, 1, 0) |
| landingMaxAngle | Angle threshold (in degrees) used together with `landingNormal` to detect if the mesh is so steep to jump to it. | 45 |
| startEvents | Alternative to `button`, list of events to listen to start teleporting.| [] |

@@ -43,3 +46,3 @@ ### Usage

<title>My A-Frame Scene</title>
<script src="https://aframe.io/releases/0.4.0/aframe.min.js"></script>
<script src="https://aframe.io/releases/0.7.0/aframe.min.js"></script>
<script src="https://rawgit.com/fernandojsg/aframe-teleport-controls/master/dist/aframe-teleport-controls.min.js"></script>

@@ -52,6 +55,6 @@ </head>

<!-- camera -->
<a-entity camera wasd-controls look-controls></a-entity>
<a-entity id="head" camera wasd-controls look-controls></a-entity>
<!-- hand controls -->
<a-entity id="left-hand" teleport-controls="cameraRig: #cameraRig"></a-entity>
<a-entity id="right-hand" teleport-controls="cameraRig: #cameraRig"></a-entity>
<a-entity id="left-hand" teleport-controls="cameraRig: #cameraRig; teleportOrigin: #head;"></a-entity>
<a-entity id="right-hand" teleport-controls="cameraRig: #cameraRig; teleportOrigin: #head;"></a-entity>
</a-entity>

@@ -62,2 +65,26 @@ </a-scene>

To use this component with Gear VR, you need to add `gearvr-controls`:
```html
<a-scene>
<a-entity id="cameraRig">
<a-camera />
<a-entity
teleport-controls="cameraRig: #cameraRig"
gearvr-controls
/>
</a-entity>
</a-scene>
```
You can also use the trigger button instead of trackpad button by adding `button: trigger`.
For Daydream, replace `gearvr-controls` by `daydream-controls`.
If you use [aframe-environment-component](https://github.com/feiss/aframe-environment-component) > 1.0.0
and want to teleport on the generated ground, on the hills, you can
specify `collisionEntities: .environmentGround`. You can also add `.environmentDressing` if you want to teleport on the dressing like the mushrooms.
On Gear VR, it can be very slow with the curved line. Use `maxLength: 200; type: line;` in this case.
#### NPM Installation

@@ -64,0 +91,0 @@

@@ -11,2 +11,4 @@ /* global assert, setup, suite, test */

var sceneEl;
var rig;
var teleportOrigin;

@@ -21,2 +23,14 @@ setup(function (done) {

});
rig = document.createElement('a-entity');
rig.id = 'rig';
rig.setAttribute('position', '1 2 3');
teleportOrigin = document.createElement('a-entity');
teleportOrigin.id = 'origin';
teleportOrigin.setAttribute('position', '4 5 6');
rig.appendChild(teleportOrigin);
sceneEl.appendChild(rig);
el.setAttribute('teleport-controls', {});

@@ -146,2 +160,20 @@ });

test('teleports rig', function () {
el.setAttribute('teleport-controls', 'cameraRig', '#rig');
component.hitPoint = {x: 10, y: 20, z: 30};
component.onButtonUp();
assert.shallowDeepEqual(rig.getAttribute('position'), {x: 10, y: 22, z: 30});
});
test('teleports rig relative to teleportOrigin', function () {
el.setAttribute('teleport-controls', 'cameraRig', '#rig');
el.setAttribute('teleport-controls', 'teleportOrigin', '#origin');
component.hitPoint = {x: 10, y: 20, z: 30};
component.onButtonUp();
assert.shallowDeepEqual(rig.getAttribute('position'), {x: 6, y: 22, z: 24});
assert.shallowDeepEqual(teleportOrigin.getAttribute('position'), {x: 4, y: 5, z: 6});
});
test('teleports tracked-controls', function (done) {

@@ -148,0 +180,0 @@ var hand = document.createElement('a-entity');

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc