initial commit. work on ui
This commit is contained in:
57
src/components/challenge-loader.js
Normal file
57
src/components/challenge-loader.js
Normal file
@@ -0,0 +1,57 @@
|
||||
AFRAME.registerComponent('song-loader', {
|
||||
schema: {
|
||||
challengeId: {type: 'string'},
|
||||
},
|
||||
|
||||
update: async function () {
|
||||
var challengeId = this.data.challengeId;
|
||||
var frameSystem = this.el.systems.frames;
|
||||
var punchSystem = this.el.systems.punches;
|
||||
|
||||
if (!challengeId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const firstClient = new Client({ query: { id: challengeId } });
|
||||
const resp = await firstClient.challengeById(challengeId);
|
||||
const challenge = resp.performance;
|
||||
const auth = firstClient.serialize();
|
||||
|
||||
const client = new Client({ auth });
|
||||
this.el.emit('challengeloadstart');
|
||||
|
||||
console.log('Loading punches...');
|
||||
this.el.emit('challengeloadingpunches');
|
||||
const punches = await client.challengePunches(challenge);
|
||||
|
||||
console.log('Loading frames...');
|
||||
this.el.emit('challengeloadingframes');
|
||||
const frames = await client.challengeFrames(challenge);
|
||||
|
||||
history.pushState(
|
||||
'',
|
||||
challenge.song_name,
|
||||
updateQueryParam(window.location.href, 'challenge', this.data.challengeId)
|
||||
);
|
||||
|
||||
document.title = `Soundboxing - ${challenge.song_name}`;
|
||||
this.el.emit('challengeloaded', {
|
||||
frames: frames,
|
||||
punches: punches,
|
||||
title: challenge.song_name,
|
||||
videoId: challenge.youtube_id,
|
||||
});
|
||||
|
||||
console.log('Finished loading challenge data.');
|
||||
},
|
||||
});
|
||||
|
||||
function updateQueryParam(uri, key, value) {
|
||||
var re = new RegExp('([?&])' + key + '=.*?(&|$)', 'i');
|
||||
var separator = uri.indexOf('?') !== -1 ? '&' : '?';
|
||||
if (uri.match(re)) {
|
||||
return uri.replace(re, '$1' + key + '=' + value + '$2');
|
||||
} else {
|
||||
return uri + separator + key + '=' + value;
|
||||
}
|
||||
}
|
||||
6
src/components/console-shortcuts.js
Normal file
6
src/components/console-shortcuts.js
Normal file
@@ -0,0 +1,6 @@
|
||||
AFRAME.registerComponent('console-shortcuts', {
|
||||
play: function() {
|
||||
window.scene = this.el;
|
||||
window.state = this.el.systems.state.state;
|
||||
},
|
||||
});
|
||||
117
src/components/debug-controller.js
Normal file
117
src/components/debug-controller.js
Normal file
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
* Keyboard bindings to control controller.
|
||||
* Position controller in front of camera.
|
||||
*/
|
||||
AFRAME.registerComponent('debug-controller', {
|
||||
schema: {
|
||||
enabled: { default: false },
|
||||
},
|
||||
|
||||
init: function() {
|
||||
var primaryHand;
|
||||
var secondaryHand;
|
||||
|
||||
if (!this.data.enabled && !AFRAME.utils.getUrlParameter('debug')) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('%c debug-controller enabled ', 'background: #111; color: red');
|
||||
|
||||
this.isTriggerDown = false;
|
||||
|
||||
primaryHand = document.getElementById('leftGloveContainer');
|
||||
secondaryHand = document.getElementById('rightGloveContainer');
|
||||
|
||||
primaryHand.setAttribute('position', { x: 0.2, y: 1.5, z: -0.5 });
|
||||
secondaryHand.setAttribute('position', { x: -0.2, y: 1.5, z: -0.5 });
|
||||
primaryHand.setAttribute('rotation', { x: 0, y: 0, z: 0 });
|
||||
secondaryHand.setAttribute('rotation', { x: 0, y: 0, z: 0 });
|
||||
|
||||
document.addEventListener('keydown', evt => {
|
||||
var primaryPosition;
|
||||
var primaryRotation;
|
||||
var secondaryPosition;
|
||||
|
||||
if (!evt.shiftKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
// <space> for trigger.
|
||||
if (evt.keyCode === 32) {
|
||||
if (this.isTriggerDown) {
|
||||
primaryHand.emit('triggerup');
|
||||
this.isTriggerDown = false;
|
||||
} else {
|
||||
primaryHand.emit('triggerdown');
|
||||
this.isTriggerDown = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// <n> secondary grip.
|
||||
if (evt.keyCode === 78) {
|
||||
if (this.secondaryGripDown) {
|
||||
secondaryHand.emit('gripup');
|
||||
this.secondaryGripDown = false;
|
||||
} else {
|
||||
secondaryHand.emit('gripdown');
|
||||
this.secondaryGripDown = true;
|
||||
}
|
||||
}
|
||||
|
||||
// <m> primary grip.
|
||||
if (evt.keyCode === 77) {
|
||||
if (this.primaryGripDown) {
|
||||
primaryHand.emit('gripup');
|
||||
this.primaryGripDown = false;
|
||||
} else {
|
||||
primaryHand.emit('gripdown');
|
||||
this.primaryGripDown = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Position bindings.
|
||||
if (!evt.ctrlKey) {
|
||||
primaryPosition = primaryHand.object3D.position;
|
||||
if (evt.keyCode === 72) {
|
||||
primaryPosition.x -= 0.01;
|
||||
} // h.
|
||||
if (evt.keyCode === 74) {
|
||||
primaryPosition.y -= 0.01;
|
||||
} // j.
|
||||
if (evt.keyCode === 75) {
|
||||
primaryPosition.y += 0.01;
|
||||
} // k.
|
||||
if (evt.keyCode === 76) {
|
||||
primaryPosition.x += 0.01;
|
||||
} // l.
|
||||
if (evt.keyCode === 59 || evt.keyCode === 186) {
|
||||
primaryPosition.z -= 0.01;
|
||||
} // ;.
|
||||
if (evt.keyCode === 222) {
|
||||
primaryPosition.z += 0.01;
|
||||
} // ;.
|
||||
} else {
|
||||
secondaryPosition = secondaryHand.object3D.position;
|
||||
if (evt.keyCode === 72) {
|
||||
secondaryPosition.x -= 0.01;
|
||||
} // h.
|
||||
if (evt.keyCode === 74) {
|
||||
secondaryPosition.y -= 0.01;
|
||||
} // j.
|
||||
if (evt.keyCode === 75) {
|
||||
secondaryPosition.y += 0.01;
|
||||
} // k.
|
||||
if (evt.keyCode === 76) {
|
||||
secondaryPosition.x += 0.01;
|
||||
} // l.
|
||||
if (evt.keyCode === 59 || evt.keyCode === 186) {
|
||||
secondaryPosition.z -= 0.01;
|
||||
} // ;.
|
||||
if (evt.keyCode === 222) {
|
||||
secondaryPosition.z += 0.01;
|
||||
} // ;.
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
31
src/components/debug-cursor.js
Normal file
31
src/components/debug-cursor.js
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Log cursor events.
|
||||
*/
|
||||
AFRAME.registerComponent('debug-cursor', {
|
||||
init: function() {
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.el.addEventListener('mouseenter', evt => {
|
||||
this.log('mouseenter', evt.detail.intersectedEl, 'green');
|
||||
});
|
||||
|
||||
this.el.addEventListener('mouseleave', evt => {
|
||||
this.log('mouseleave', evt.detail.intersectedEl, 'red');
|
||||
});
|
||||
|
||||
this.el.addEventListener('click', evt => {
|
||||
this.log('click', evt.detail.intersectedEl, 'blue');
|
||||
});
|
||||
},
|
||||
|
||||
log: function(event, intersectedEl, color) {
|
||||
if (intersectedEl.id) {
|
||||
console.log(`%c[${event}] ${intersectedEl.id}`, `color: ${color}`);
|
||||
} else {
|
||||
console.log(`%c[${event}]`, `color: ${color}`);
|
||||
console.log(intersectedEl);
|
||||
}
|
||||
},
|
||||
});
|
||||
16
src/components/discolight.js
Normal file
16
src/components/discolight.js
Normal file
@@ -0,0 +1,16 @@
|
||||
AFRAME.registerComponent('discolight', {
|
||||
schema: {
|
||||
color: { type: 'color' },
|
||||
speed: { default: 1.0 },
|
||||
},
|
||||
init: function() {
|
||||
this.color = new THREE.Color(this.data.color);
|
||||
this.hsl = this.color.getHSL();
|
||||
},
|
||||
tick: function(time, delta) {
|
||||
this.hsl.h += delta * 0.0001 * this.data.speed;
|
||||
if (this.hsl.l > 1.0) this.hsl.l = 0.0;
|
||||
this.color.setHSL(this.hsl.h, this.hsl.s, this.hsl.l);
|
||||
this.el.setAttribute('light', { color: this.color.getHex() });
|
||||
},
|
||||
});
|
||||
14
src/components/discotube.js
Normal file
14
src/components/discotube.js
Normal file
@@ -0,0 +1,14 @@
|
||||
AFRAME.registerComponent('discotube', {
|
||||
schema: {
|
||||
speedX: { default: 1.0 },
|
||||
speedY: { default: 0.1 },
|
||||
},
|
||||
init: function() {
|
||||
this.material = this.el.object3D.children[0].material;
|
||||
},
|
||||
tick: function(time, delta) {
|
||||
if (this.material == null) return;
|
||||
this.material.map.offset.x -= delta * 0.0001 * this.data.speedX;
|
||||
this.material.map.offset.y -= delta * 0.0001 * this.data.speedY;
|
||||
},
|
||||
});
|
||||
10
src/components/keyboard-raycastable.js
Normal file
10
src/components/keyboard-raycastable.js
Normal file
@@ -0,0 +1,10 @@
|
||||
AFRAME.registerComponent('keyboard-raycastable', {
|
||||
play: function() {
|
||||
var els;
|
||||
var i;
|
||||
els = this.el.querySelectorAll('*');
|
||||
for (i = 0; i < els.length; i++) {
|
||||
els[i].setAttribute('bind-toggle__raycastable', 'isSearchScreen');
|
||||
}
|
||||
},
|
||||
});
|
||||
26
src/components/play-audio.js
Normal file
26
src/components/play-audio.js
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Play audio element on event.
|
||||
*/
|
||||
AFRAME.registerComponent('play-audio', {
|
||||
schema: {
|
||||
audio: { type: 'string' },
|
||||
event: { type: 'string' },
|
||||
volume: { type: 'number', default: 1 },
|
||||
},
|
||||
|
||||
multiple: true,
|
||||
|
||||
init: function() {
|
||||
var audio;
|
||||
audio = document.querySelector(this.data.audio);
|
||||
audio.volume = this.data.volume;
|
||||
|
||||
this.el.addEventListener(this.data.event, evt => {
|
||||
if (!audio.paused) {
|
||||
audio.pause();
|
||||
audio.currentTime = 0;
|
||||
}
|
||||
audio.play();
|
||||
});
|
||||
},
|
||||
});
|
||||
13
src/components/play-button.js
Normal file
13
src/components/play-button.js
Normal file
@@ -0,0 +1,13 @@
|
||||
AFRAME.registerComponent('play-button', {
|
||||
init: function() {
|
||||
var el = this.el;
|
||||
|
||||
el.addEventListener('click', () => {
|
||||
el.sceneEl.emit('playbuttonclick');
|
||||
});
|
||||
|
||||
el.sceneEl.addEventListener('youtubefinished', evt => {
|
||||
el.object3D.visible = false;
|
||||
});
|
||||
},
|
||||
});
|
||||
38
src/components/preloader.js
Normal file
38
src/components/preloader.js
Normal file
@@ -0,0 +1,38 @@
|
||||
AFRAME.registerComponent('gpu-preloader', {
|
||||
init: function() {
|
||||
setTimeout(() => {
|
||||
this.preloadFont();
|
||||
this.preloadKeyboard();
|
||||
}, 1000);
|
||||
|
||||
setTimeout(() => {
|
||||
this.el.object3D.visible = false;
|
||||
}, 2000);
|
||||
},
|
||||
|
||||
preloadFont: function() {
|
||||
var text;
|
||||
text = document.querySelector('[text]');
|
||||
if (text.components.text.texture) {
|
||||
this.preloadTexture(text.components.text.texture);
|
||||
} else {
|
||||
text.addEventListener('textfontset', () => {
|
||||
this.preloadTexture(text.components.text.texture);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
preloadKeyboard: function() {
|
||||
var kbd;
|
||||
kbd = document.getElementById('kb');
|
||||
kbd.object3D.traverse(node => {
|
||||
if (node.material && node.material.map) {
|
||||
this.preloadTexture(node.material.map);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
preloadTexture: function(texture) {
|
||||
this.el.sceneEl.renderer.setTexture2D(texture, 0);
|
||||
},
|
||||
});
|
||||
1
src/components/raycastable.js
Normal file
1
src/components/raycastable.js
Normal file
@@ -0,0 +1 @@
|
||||
AFRAME.registerComponent('raycastable', {});
|
||||
75
src/components/recenter.js
Normal file
75
src/components/recenter.js
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Pivot the scene when user enters VR to face the links.
|
||||
*/
|
||||
AFRAME.registerComponent('recenter', {
|
||||
init: function() {
|
||||
var sceneEl = this.el.sceneEl;
|
||||
this.matrix = new THREE.Matrix4();
|
||||
this.frustum = new THREE.Frustum();
|
||||
this.rotationOffset = 0;
|
||||
this.euler = new THREE.Euler();
|
||||
this.euler.order = 'YXZ';
|
||||
this.menuPosition = new THREE.Vector3();
|
||||
this.recenter = this.recenter.bind(this);
|
||||
this.checkInViewAfterRecenter = this.checkInViewAfterRecenter.bind(this);
|
||||
// Delay to make sure we have a valid pose.
|
||||
sceneEl.addEventListener('enter-vr', () => {
|
||||
setTimeout(() => {
|
||||
this.recenter();
|
||||
}, 100);
|
||||
});
|
||||
// User can also recenter the menu manually.
|
||||
sceneEl.addEventListener('menudown', () => {
|
||||
this.recenter();
|
||||
});
|
||||
sceneEl.addEventListener('thumbstickdown', () => {
|
||||
this.recenter();
|
||||
});
|
||||
},
|
||||
|
||||
recenter: function(skipCheck) {
|
||||
var euler = this.euler;
|
||||
euler.setFromRotationMatrix(
|
||||
this.el.sceneEl.camera.el.object3D.matrixWorld,
|
||||
'YXZ'
|
||||
);
|
||||
this.el.object3D.rotation.y = euler.y + this.rotationOffset;
|
||||
// Check if the menu is in camera frustum in next tick after a frame has rendered.
|
||||
if (skipCheck) {
|
||||
return;
|
||||
}
|
||||
setTimeout(this.checkInViewAfterRecenter, 0);
|
||||
},
|
||||
|
||||
/*
|
||||
* Sometimes the quaternion returns the yaw in the [-180, 180] range.
|
||||
* Check if the menu is in the camera frustum after recenter it to
|
||||
* decide if we apply an offset or not.
|
||||
*/
|
||||
checkInViewAfterRecenter: function() {
|
||||
var camera = this.el.sceneEl.camera;
|
||||
var frustum = this.frustum;
|
||||
var menu = document.querySelector('#menu');
|
||||
var menuPosition = this.menuPosition;
|
||||
camera.updateMatrix();
|
||||
camera.updateMatrixWorld();
|
||||
frustum.setFromMatrix(
|
||||
this.matrix.multiplyMatrices(
|
||||
camera.projectionMatrix,
|
||||
camera.matrixWorldInverse
|
||||
)
|
||||
);
|
||||
menu.object3D.updateMatrixWorld();
|
||||
menuPosition.setFromMatrixPosition(menu.object3D.matrixWorld);
|
||||
if (frustum.containsPoint(menuPosition)) {
|
||||
return;
|
||||
}
|
||||
this.rotationOffset = this.rotationOffset === 0 ? Math.PI : 0;
|
||||
// Recenter again with the new offset.
|
||||
this.recenter(true);
|
||||
},
|
||||
|
||||
remove: function() {
|
||||
this.el.sceneEl.removeEventListener('enter-vr', this.recenter);
|
||||
},
|
||||
});
|
||||
42
src/components/search.js
Normal file
42
src/components/search.js
Normal file
@@ -0,0 +1,42 @@
|
||||
var algoliasearch = require('algoliasearch/lite');
|
||||
|
||||
var client = algoliasearch('QULTOY3ZWU', 'be07164192471df7e97e6fa70c1d041d');
|
||||
var index = client.initIndex('supersaber');
|
||||
|
||||
/**
|
||||
* Search (including the initial list of popular searches).
|
||||
*/
|
||||
AFRAME.registerComponent('search', {
|
||||
init: function() {
|
||||
this.eventDetail = {results: []};
|
||||
this.queryObject = {query: ''};
|
||||
|
||||
// Populate popular.
|
||||
this.search('');
|
||||
},
|
||||
|
||||
search: function (query) {
|
||||
this.queryObject.query = query;
|
||||
index.search(this.queryObject, (err, content) => {
|
||||
this.eventDetail.results = content.hits;
|
||||
console.log(content.hits);
|
||||
this.el.sceneEl.emit('searchresults', this.eventDetail);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Click listener for search result.
|
||||
*/
|
||||
AFRAME.registerComponent('search-result', {
|
||||
init: function() {
|
||||
var el = this.el;
|
||||
|
||||
this.eventDetail = {};
|
||||
el.addEventListener('click', () => {
|
||||
this.eventDetail.challengeId = el.getAttribute('data-song-id');
|
||||
this.eventDetail.title = el.getAttribute('data-title');
|
||||
el.sceneEl.emit('challengeset', this.eventDetail);
|
||||
});
|
||||
},
|
||||
});
|
||||
10
src/components/toggle-pause-play.js
Normal file
10
src/components/toggle-pause-play.js
Normal file
@@ -0,0 +1,10 @@
|
||||
AFRAME.registerComponent('toggle-pause-play', {
|
||||
schema: {
|
||||
isPlaying: { default: false },
|
||||
},
|
||||
|
||||
update: function() {
|
||||
const action = this.data.isPlaying ? 'pause' : 'play';
|
||||
parent.postMessage(JSON.stringify({ verify: 'game-action', action }), '*');
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user