diff --git a/src/assets.html b/src/assets.html
index 600141b..6e312f8 100644
--- a/src/assets.html
+++ b/src/assets.html
@@ -111,11 +111,10 @@
+ wall>
{
if (!evt.detail || !evt.detail.intersectedEl) { return; }
diff --git a/src/components/haptics-wall.js b/src/components/haptics-wall.js
index e50a7b7..1eb9554 100644
--- a/src/components/haptics-wall.js
+++ b/src/components/haptics-wall.js
@@ -5,7 +5,7 @@ AFRAME.registerComponent('haptics-wall', {
init: function () {
const el = this.el;
this.isHittingWall = false;
- el.setAttribute('haptics__wall', {dur: 50, force: 0.1});
+ el.setAttribute('haptics__wall', {dur: 50, force: 0.075});
this.checkIfHittingWall = this.checkIfHittingWall.bind(this);
el.addEventListener('mouseenter', this.checkIfHittingWall);
diff --git a/src/components/particleplayer.js b/src/components/particleplayer.js
index 2508bf4..a9e6a20 100644
--- a/src/components/particleplayer.js
+++ b/src/components/particleplayer.js
@@ -326,6 +326,7 @@ AFRAME.registerComponent('particleplayer', {
particleSystem.mesh.rotation.copy(rotation);
particleSystem.time = 0;
this.resetParticles(particleSystem);
+ return particleSystem;
},
doLoop: function (particleSystem) {
diff --git a/src/components/saber-intersection.js b/src/components/saber-intersection.js
deleted file mode 100644
index adaf233..0000000
--- a/src/components/saber-intersection.js
+++ /dev/null
@@ -1,67 +0,0 @@
-AFRAME.registerComponent('saber-intersection', {
- schema: {
- active: {default: true}
- },
-
- init: function () {
- this.hiddenIntersection = {x: 999, y: 0, z: 0};
- this.saberHit = {
- rightHand: {active: false, position: null, raycaster: null},
- leftHand: {active: false, position: null, raycaster: null}
- };
- this.particles = document.getElementById('sparkParticles');
- this.intersecting = false;
- this.saberEnterFunc = this.saberEnter.bind(this);
- this.saberLeaveFunc = this.saberLeave.bind(this);
- this.particlesPosition = {position: null, rotation: null};
- },
-
- pause: function () {
- this.el.removeAttribute('raycastable-game');
- this.el.removeEventListener('mouseenter', this.saberEnterFunc);
- this.el.removeEventListener('mouseleave', this.saberLeaveFunc);
- this.intersecting = false;
- },
-
- play: function () {
- this.el.setAttribute('raycastable-game', '');
- this.el.addEventListener('mouseenter', this.saberEnterFunc);
- this.el.addEventListener('mouseleave', this.saberLeaveFunc);
- this.material = this.el.getObject3D('mesh').material;
- this.saberHit.rightHand.raycaster = document.getElementById('rightHand').components.raycaster__game;
- this.saberHit.leftHand.raycaster = document.getElementById('leftHand').components.raycaster__game;
- },
-
- saberEnter: function (evt) {
- if (!this.data.active) { return; }
- const saber = this.saberHit[evt.detail.cursorEl.id];
- saber.active = true;
- var intersection = saber.raycaster.getIntersection(this.el);
- if (intersection) {
- this.particlesPosition.position = intersection.point;
- this.particles.emit('explode', this.particlesPosition, false);
- }
- this.intersecting = true;
- },
-
- saberLeave: function (evt) {
- const hand = evt.detail.cursorEl.id;
- this.saberHit[hand].active = false;
- this.material.uniforms[hand == 'rightHand' ? 'hitRight' : 'hitLeft'].value = this.hiddenIntersection;
- this.intersecting = this.saberHit.rightHand.active || this.saberHit.leftHand.active;
- },
-
- tick: function (time, delta) {
- if (this.data.active && this.intersecting) {
- var intersection;
- if (this.saberHit.rightHand.active) {
- intersection = this.saberHit.rightHand.raycaster.getIntersection(this.el);
- if (intersection) { this.material.uniforms.hitRight.value = intersection.point; }
- }
- if (this.saberHit.leftHand.active) {
- intersection = this.saberHit.leftHand.raycaster.getIntersection(this.el);
- if (intersection) { this.material.uniforms.hitLeft.value = intersection.point; }
- }
- }
- }
-});
diff --git a/src/components/saber-particles.js b/src/components/saber-particles.js
new file mode 100644
index 0000000..62b8913
--- /dev/null
+++ b/src/components/saber-particles.js
@@ -0,0 +1,85 @@
+const HIT_LEFT = 'hitLeft';
+const HIT_RIGHT = 'hitRight';
+const LEFT = 'left';
+const RIGHT = 'right';
+
+/**
+ * Show particles when touched by saber.
+ */
+AFRAME.registerComponent('saber-particles', {
+ schema: {
+ enabled: {default: false},
+ hand: {type: 'string'}
+ },
+
+ init: function () {
+ this.hiddenIntersection = {x: 999, y: 0, z: 0};
+ this.intersectedEl = null;
+
+ this.particles = document.getElementById('sparkParticles');
+ this.particleEventDetail = {position: new THREE.Vector3(), rotation: new THREE.Euler()};
+ this.particleEvent = {detail: this.particleEventDetail};
+ this.particleSystem = null;
+
+ this.saberEnter = this.saberEnter.bind(this);
+ this.saberLeave = this.saberLeave.bind(this);
+
+ },
+
+ pause: function () {
+ this.el.removeEventListener('mouseenter', this.saberEnter);
+ this.el.removeEventListener('mouseleave', this.saberLeave);
+ },
+
+ play: function () {
+ this.el.addEventListener('mouseenter', this.saberEnter);
+ this.el.addEventListener('mouseleave', this.saberLeave);
+ this.particlesDur = this.particles.getAttribute('particleplayer').dur;
+ },
+
+ saberEnter: function (evt) {
+ if (!this.data.enabled) { return; }
+ if (evt.target !== this.el) { return; }
+ if (!evt.detail.intersectedEl.hasAttribute('data-saber-particles')) { return; }
+ this.intersectedEl = evt.detail.intersectedEl;
+ },
+
+ saberLeave: function (evt) {
+ if (evt.detail.target !== this.el) { return; }
+
+ // Hide hit intersection texture.
+ if (this.intersectedEl.components.wall || this.intersectedEl.id === 'floor') {
+ const uniform = this.data.hand === RIGHT ? HIT_RIGHT : HIT_LEFT;
+ const material = this.intersectedEl.getObject3D('mesh').material;
+ material.uniforms[uniform].value = this.hiddenIntersection;
+ }
+ this.intersectedEl = null;
+ this.particleSystem = null;
+ },
+
+ tick: function (time, delta) {
+ if (!this.data.enabled || !this.intersectedEl) { return; }
+
+ const raycaster = this.el.components.raycaster__game;
+ const intersection = raycaster.getIntersection(this.intersectedEl);
+
+ if (!intersection) { return; }
+
+ // Update intersection material if necessary.
+ if (this.intersectedEl.components.wall || this.intersectedEl.id === 'floor') {
+ const uniform = this.data.hand === RIGHT ? HIT_RIGHT : HIT_LEFT;
+ const material = this.intersectedEl.getObject3D('mesh').material;
+ material.uniforms[uniform].value = intersection.point;
+ }
+
+ if (this.particleSystem && this.particleSystem.active) {
+ // Update particle position.
+ this.particleSystem.mesh.position.copy(intersection.point);
+ } else {
+ // Start particle system.
+ this.particleEventDetail.position.copy(intersection.point);
+ this.particleSystem = this.particles.components.particleplayer.startAfterDelay(
+ this.particleEvent);
+ }
+ }
+});
diff --git a/src/index.html b/src/index.html
index 4cb4b49..31f5715 100644
--- a/src/index.html
+++ b/src/index.html
@@ -99,7 +99,7 @@
particleplayer="src: #mineParticlesJSON; pscale: 0.5; scale: 1.4; loop: false; on: explode; img: #sparkImg; count: 20%; animateScale: true; initialScale: 3 1 1; finalScale: 0.2 0.2 1">
+ particleplayer="src: #sparksJSON; color: #fcc; pscale: 0.7; on: explode; scale: 0.1; loop: false; img: #spark2Img; dur: 700; count: 50%; animateScale: true; initialScale: 3 0.5 1; finalScale: 0.1 0.5 1">