diff --git a/assets/models/laser/laser.jpg b/assets/models/laser/laser.jpg
new file mode 100644
index 0000000..e758a4f
Binary files /dev/null and b/assets/models/laser/laser.jpg differ
diff --git a/assets/models/laser/laser.obj b/assets/models/laser/laser.obj
new file mode 100644
index 0000000..552386a
--- /dev/null
+++ b/assets/models/laser/laser.obj
@@ -0,0 +1,240 @@
+# Blender v2.78 (sub 0) OBJ File: ''
+# www.blender.org
+o beam
+v 0.000000 0.006935 -0.006970
+v 0.000000 0.002125 0.964190
+v 0.005422 0.004324 -0.006970
+v 0.001662 0.001325 0.964190
+v 0.006761 -0.001543 -0.006970
+v 0.002072 -0.000473 0.964190
+v 0.003009 -0.006248 -0.006970
+v 0.000922 -0.001915 0.964190
+v -0.003009 -0.006248 -0.006970
+v -0.000922 -0.001915 0.964190
+v -0.006761 -0.001543 -0.006970
+v -0.002072 -0.000473 0.964190
+v -0.005422 0.004324 -0.006970
+v -0.001662 0.001325 0.964190
+v 0.000000 0.008160 -0.006357
+v 0.000000 0.005860 0.703495
+v 0.006380 0.005088 -0.006357
+v 0.004582 0.003654 0.703495
+v 0.007956 -0.001816 -0.006357
+v 0.005713 -0.001304 0.703495
+v 0.003541 -0.007352 -0.006357
+v 0.002543 -0.005280 0.703495
+v -0.003541 -0.007352 -0.006357
+v -0.002543 -0.005280 0.703495
+v -0.007956 -0.001816 -0.006357
+v -0.005713 -0.001304 0.703495
+v -0.006380 0.005088 -0.006357
+v -0.004582 0.003654 0.703495
+v -0.003177 0.003391 0.012037
+v -0.000974 0.001039 0.157890
+v 0.000670 0.004598 0.012037
+v 0.000205 0.001409 0.157890
+v 0.004013 0.002343 0.012037
+v 0.001230 0.000718 0.157890
+v 0.004334 -0.001677 0.012037
+v 0.001328 -0.000514 0.157890
+v 0.001391 -0.004434 0.012037
+v 0.000426 -0.001359 0.157890
+v -0.002599 -0.003852 0.012037
+v -0.000797 -0.001180 0.157890
+v -0.004632 -0.000369 0.012037
+v -0.001420 -0.000113 0.157890
+v 0.000000 0.004484 -0.007003
+v -0.000000 0.001374 0.449267
+v 0.003506 0.002796 -0.007003
+v 0.001074 0.000857 0.449267
+v 0.004372 -0.000998 -0.007003
+v 0.001340 -0.000306 0.449267
+v 0.001946 -0.004040 -0.007003
+v 0.000596 -0.001238 0.449267
+v -0.001946 -0.004040 -0.007003
+v -0.000596 -0.001238 0.449267
+v -0.004372 -0.000998 -0.007003
+v -0.001340 -0.000306 0.449267
+v -0.003506 0.002796 -0.007003
+v -0.001074 0.000857 0.449267
+vt 0.9512 0.8812
+vt 0.0114 0.8659
+vt 0.0114 0.8812
+vt 0.9512 0.8964
+vt 0.0114 0.8812
+vt 0.0114 0.8964
+vt 0.9512 0.9117
+vt 0.0114 0.8964
+vt 0.0114 0.9117
+vt 0.9512 0.9270
+vt 0.0114 0.9117
+vt 0.0114 0.9270
+vt 0.0114 0.9422
+vt 0.9512 0.9270
+vt 0.0114 0.9270
+vt 0.0114 0.9575
+vt 0.9512 0.9422
+vt 0.0114 0.9422
+vt 0.9512 0.9728
+vt 0.0114 0.9575
+vt 0.0114 0.9728
+vt 0.9512 0.8812
+vt 0.0114 0.8659
+vt 0.0114 0.8812
+vt 0.9512 0.8964
+vt 0.0114 0.8812
+vt 0.0114 0.8964
+vt 0.9512 0.9117
+vt 0.0114 0.8964
+vt 0.0114 0.9117
+vt 0.9512 0.9270
+vt 0.0114 0.9117
+vt 0.0114 0.9270
+vt 0.9512 0.9422
+vt 0.0114 0.9270
+vt 0.0114 0.9422
+vt 0.0114 0.9575
+vt 0.9512 0.9422
+vt 0.0114 0.9422
+vt 0.9512 0.9728
+vt 0.0114 0.9575
+vt 0.0114 0.9728
+vt 0.9512 0.8812
+vt 0.0114 0.8659
+vt 0.0114 0.8812
+vt 0.9512 0.8964
+vt 0.0114 0.8812
+vt 0.0114 0.8964
+vt 0.0114 0.9117
+vt 0.9512 0.8964
+vt 0.0114 0.8964
+vt 0.9512 0.9270
+vt 0.0114 0.9117
+vt 0.0114 0.9270
+vt 0.9512 0.9422
+vt 0.0114 0.9270
+vt 0.0114 0.9422
+vt 0.9512 0.9575
+vt 0.0114 0.9422
+vt 0.0114 0.9575
+vt 0.9512 0.9728
+vt 0.0114 0.9575
+vt 0.0114 0.9728
+vt 0.9512 0.8812
+vt 0.0114 0.8659
+vt 0.0114 0.8812
+vt 0.9512 0.8964
+vt 0.0114 0.8812
+vt 0.0114 0.8964
+vt 0.9512 0.9117
+vt 0.0114 0.8964
+vt 0.0114 0.9117
+vt 0.9512 0.9270
+vt 0.0114 0.9117
+vt 0.0114 0.9270
+vt 0.9512 0.9422
+vt 0.0114 0.9270
+vt 0.0114 0.9422
+vt 0.9512 0.9575
+vt 0.0114 0.9422
+vt 0.0114 0.9575
+vt 0.0114 0.9728
+vt 0.9512 0.9575
+vt 0.0114 0.9575
+vt 0.9512 0.8659
+vt 0.9512 0.8812
+vt 0.9512 0.8964
+vt 0.9512 0.9117
+vt 0.9512 0.9422
+vt 0.9512 0.9575
+vt 0.9512 0.9575
+vt 0.9512 0.8659
+vt 0.9512 0.8812
+vt 0.9512 0.8964
+vt 0.9512 0.9117
+vt 0.9512 0.9270
+vt 0.9512 0.9575
+vt 0.9512 0.9575
+vt 0.9512 0.8659
+vt 0.9512 0.8812
+vt 0.9512 0.9117
+vt 0.9512 0.9117
+vt 0.9512 0.9270
+vt 0.9512 0.9422
+vt 0.9512 0.9575
+vt 0.9512 0.8659
+vt 0.9512 0.8812
+vt 0.9512 0.8964
+vt 0.9512 0.9117
+vt 0.9512 0.9270
+vt 0.9512 0.9422
+vt 0.9512 0.9728
+s off
+f 2/1 3/2 1/3
+f 4/4 5/5 3/6
+f 6/7 7/8 5/9
+f 8/10 9/11 7/12
+f 9/13 12/14 11/15
+f 11/16 14/17 13/18
+f 14/19 1/20 13/21
+f 16/22 17/23 15/24
+f 18/25 19/26 17/27
+f 20/28 21/29 19/30
+f 22/31 23/32 21/33
+f 24/34 25/35 23/36
+f 25/37 28/38 27/39
+f 28/40 15/41 27/42
+f 30/43 31/44 29/45
+f 32/46 33/47 31/48
+f 33/49 36/50 35/51
+f 36/52 37/53 35/54
+f 38/55 39/56 37/57
+f 40/58 41/59 39/60
+f 42/61 29/62 41/63
+f 44/64 45/65 43/66
+f 46/67 47/68 45/69
+f 48/70 49/71 47/72
+f 50/73 51/74 49/75
+f 52/76 53/77 51/78
+f 54/79 55/80 53/81
+f 55/82 44/83 43/84
+f 2/1 4/85 3/2
+f 4/4 6/86 5/5
+f 6/7 8/87 7/8
+f 8/10 10/88 9/11
+f 9/13 10/89 12/14
+f 11/16 12/90 14/17
+f 14/19 2/91 1/20
+f 16/22 18/92 17/23
+f 18/25 20/93 19/26
+f 20/28 22/94 21/29
+f 22/31 24/95 23/32
+f 24/34 26/96 25/35
+f 25/37 26/97 28/38
+f 28/40 16/98 15/41
+f 30/43 32/99 31/44
+f 32/46 34/100 33/47
+f 33/49 34/101 36/50
+f 36/52 38/102 37/53
+f 38/55 40/103 39/56
+f 40/58 42/104 41/59
+f 42/61 30/105 29/62
+f 44/64 46/106 45/65
+f 46/67 48/107 47/68
+f 48/70 50/108 49/71
+f 50/73 52/109 51/74
+f 52/76 54/110 53/77
+f 54/79 56/111 55/80
+f 55/82 56/112 44/83
+o glow
+v -0.087472 -0.087472 0.003930
+v 0.087472 -0.087472 0.003930
+v -0.087472 0.087472 0.003930
+v 0.087472 0.087472 0.003930
+vt 0.8261 0.8360
+vt 0.0459 0.0558
+vt 0.8261 0.0558
+vt 0.0459 0.8360
+s off
+f 58/113 59/114 57/115
+f 58/113 60/116 59/114
diff --git a/assets/models/laser/laser.png b/assets/models/laser/laser.png
new file mode 100644
index 0000000..a7f8588
Binary files /dev/null and b/assets/models/laser/laser.png differ
diff --git a/package-lock.json b/package-lock.json
index b248e07..909a0fb 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -157,6 +157,11 @@
"resolved": "https://registry.npmjs.org/aframe-slice9-component/-/aframe-slice9-component-1.0.0.tgz",
"integrity": "sha1-+w+EQdrdHosRzCRRK6eqaS1iK+E="
},
+ "aframe-state-component": {
+ "version": "5.0.0-beta6",
+ "resolved": "https://registry.npmjs.org/aframe-state-component/-/aframe-state-component-5.0.0-beta6.tgz",
+ "integrity": "sha512-2N4V1Atq4xHEfaiEJD+ryQPBZmCA4gZGV2bbYPWImGAuFiEthaqvXp64TI0K82JjWaIEMeUTSKF1FTeCtyLq3w=="
+ },
"aframe-super-keyboard": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/aframe-super-keyboard/-/aframe-super-keyboard-2.0.2.tgz",
diff --git a/package.json b/package.json
index 862b5f0..d3efd5a 100644
--- a/package.json
+++ b/package.json
@@ -20,7 +20,7 @@
"aframe-particleplayer-component": "github:supermedium/aframe-particleplayer-component#master",
"aframe-proxy-event-component": "^1.1.1",
"aframe-slice9-component": "^1.0.0",
- "aframe-state-component": "5.0.0-beta6",
+ "aframe-state-component": "^5.0.0-beta6",
"aframe-super-keyboard": "2.0.2",
"algoliasearch": "^3.29.0",
"ansi-html": "0.0.7",
diff --git a/src/components/laser.js b/src/components/laser.js
new file mode 100644
index 0000000..03d24d5
--- /dev/null
+++ b/src/components/laser.js
@@ -0,0 +1,59 @@
+/**
+ * Laser beam.
+ * Automatically set length on intersection.
+ */
+AFRAME.registerComponent('cursor-laser', {
+ dependencies: ['sub-object'],
+
+ schema: {
+ hand: {type: 'string'}
+ },
+
+ init: function () {
+ const el = this.el;
+ const box = new THREE.Box3();
+ const size = new THREE.Vector3();
+
+ this.currentLength = undefined;
+ this.originalSize = undefined;
+
+ // Calculate size to position beam at tip of controller.
+ el.addEventListener('subobjectloaded', () => {
+ box.setFromObject(el.getObject3D('mesh'));
+ box.getSize(size);
+ el.object3D.position.z -= size.z;
+ this.originalSize = size.z;
+ this.currentLength = size.z;
+ });
+ },
+
+ tick: function () {
+ const el = this.el;
+
+ // Not yet ready.
+ if (this.currentLength === undefined) { return; }
+
+ const cursor = el.parentNode.components.cursor;
+ if (!cursor) { return; }
+
+ // Toggle beam.
+ const intersectedEl = cursor.intersectedEl;
+
+ if (!intersectedEl) {
+ // Retract the beam if not intersecting.
+ el.object3D.position.z = this.originalSize * -0.35;
+ el.object3D.scale.x = 0.25;
+ el.object3D.scale.z = this.originalSize * 0.35;
+ this.currentLength = this.originalSize * 0.35;
+ return;
+ }
+
+ // Set appropriate length of beam on intersection.
+ const intersection = el.parentNode.components.raycaster.intersections[0];
+ const ratio = intersection.distance / this.currentLength;
+ el.object3D.scale.x = 1;
+ el.object3D.position.z *= ratio;
+ el.object3D.scale.z *= ratio;
+ this.currentLength = el.object3D.scale.z;
+ }
+});
diff --git a/src/components/sub-object.js b/src/components/sub-object.js
new file mode 100644
index 0000000..7b7d5ee
--- /dev/null
+++ b/src/components/sub-object.js
@@ -0,0 +1,22 @@
+/**
+ * Pull a submesh out of a model file.
+ */
+AFRAME.registerComponent('sub-object', {
+ schema: {
+ from: {type: 'selector'},
+ name: {type: 'string'}
+ },
+
+ init: function () {
+ var el = this.el;
+ var data = this.data;
+
+ data.from.addEventListener('model-loaded', evt => {
+ const model = evt.detail.model;
+ const subset = model.getObjectByName(data.name);
+ el.setObject3D('mesh', subset.clone());
+ el.setAttribute('material', 'shader', 'flat');
+ el.emit('subobjectloaded', null, false);
+ });
+ }
+});
diff --git a/src/index.html b/src/index.html
index 3099966..20b778b 100644
--- a/src/index.html
+++ b/src/index.html
@@ -27,11 +27,14 @@
+
+
+
-
+
@@ -40,14 +43,14 @@
-
-
-
+
+
+
{% include './templates/stage.html' %}
{% include './templates/gameUi.html' %}
@@ -59,6 +62,10 @@
id="raycaster"
raycaster="objects: [raycastable]; far: 3"
line="opacity: 0.75">
+
@@ -67,11 +74,17 @@
mixin="raycaster"
bind__hand-swapper="enabled: {{ otherHand }}RaycasterActive"
bind__pauser="enabled: !menu.active"
- bind__raycaster="enabled: {{ hand }}RaycasterActive; showLine: {{ hand }}RaycasterActive"
+ bind__raycaster="enabled: {{ hand }}RaycasterActive"
haptics="events: mouseenter; dur: 35; force: 0.075"
- line="color: {{ color }}"
saber-controls="hand: {{ hand }}">
+
+
+
+
{% endmacro %}
{{ saber('left', 'right', '#FFA8A8', 'pink') }}
{{ saber('right', 'left', '#78AAFF', 'cyan') }}
-
-
-
{% if not IS_PRODUCTION %}
diff --git a/src/templates/stage.html b/src/templates/stage.html
index 9af0014..0e75552 100644
--- a/src/templates/stage.html
+++ b/src/templates/stage.html
@@ -28,14 +28,14 @@
-
-
-
+
+
+
-
-
-
+
+
+