diff --git a/public/assets/skybox.png b/public/assets/skybox.png index d205ec4..c6b7430 100644 Binary files a/public/assets/skybox.png and b/public/assets/skybox.png differ diff --git a/public/quizz.html b/public/quizz.html index e2b75ca..9f743f3 100644 --- a/public/quizz.html +++ b/public/quizz.html @@ -42,10 +42,10 @@ - + - + diff --git a/src/components/face-target.js b/src/components/face-target.js new file mode 100644 index 0000000..61d9ada --- /dev/null +++ b/src/components/face-target.js @@ -0,0 +1,10 @@ +AFRAME.registerComponent('face-target', { + schema: { type: 'selector' }, + + init: function () {}, + + tick: function () { + let targetPos = this.data.object3D.position + this.el.object3D.lookAt(targetPos.x, targetPos.y, targetPos.z) + } + }) \ No newline at end of file diff --git a/src/quizz-scene.js b/src/quizz-scene.js index e7cd067..7edd85f 100644 --- a/src/quizz-scene.js +++ b/src/quizz-scene.js @@ -5,6 +5,7 @@ import './components/caustics'; import './components/arc-layout'; import './components/texture-map'; import './components/look-towards'; +import './components/face-target'; import 'aframe-extras'; import 'aframe-label'; diff --git a/src/scene-quizz/QuizzSceneController.js b/src/scene-quizz/QuizzSceneController.js index ddeb99a..bfb4c86 100644 --- a/src/scene-quizz/QuizzSceneController.js +++ b/src/scene-quizz/QuizzSceneController.js @@ -4,7 +4,7 @@ import TeamLayout from '../homie-lit-components/TeamLayout'; import { questionDisplayTemplate } from './questionDisplayTemplate'; import * as nools from 'nools'; import log from 'loglevel'; -import { render } from 'lit-html'; +import { html, render } from 'lit-html'; class PlayerNode { constructor(deviceId, nodeId, properties) { @@ -24,7 +24,9 @@ class QuizzSceneController { this.propertyBuffer = new HomiePropertyBuffer(this.homieObserver, 300); this.players = new Map(); this.terminalToPlayerMap = new Map(); + this.playerSayEntities = new Map(); this.teamLayout = new TeamLayout(this.teamParentElement); + this.flow = this.initNoolsFlow(); this.session = this.flow.getSession(); @@ -36,6 +38,8 @@ class QuizzSceneController { this.questionDisplayElement = document.createElement('a-entity'); this.questionDisplayElement.setAttribute('id', 'questionDisplay'); this.questionParentElement.appendChild(this.questionDisplayElement); + + this.emoji = '🎁'; } setupLogging() { @@ -62,6 +66,16 @@ class QuizzSceneController { handleVoteUpdate(update); } } + + + rule ProcessTerminalVoteUpdate { + when { + update: PropertyUpdate update.deviceId.startsWith('terminal-') && update.nodeId === 'vote' && update.propertyId === 'option' + } + then { + handleTerminalVoteUpdate(update); + } + } `, { define: { PropertyUpdate: PropertyUpdate, @@ -70,6 +84,7 @@ class QuizzSceneController { scope: { handlePropertyUpdate: this.handlePropertyUpdate.bind(this), handleVoteUpdate: this.handleVoteUpdate.bind(this), + handleTerminalVoteUpdate: this.handleTerminalVoteUpdate.bind(this), logger: console }, name: "quizz" @@ -145,6 +160,60 @@ class QuizzSceneController { log.debug(`Updating vote property: ${update.deviceId}/${update.propertyId} = ${update.value}`); } + handleTerminalVoteUpdate(update) { + const terminalId = update.deviceId.split('-')[1]; // remove the "terminal-" prefix + log.debug(`Received vote from terminal: ${terminalId}, option: ${update.value}`); + this.displayEmoji(terminalId); + } + +displayEmoji(terminalId) { + const playerNodeId = this.terminalToPlayerMap.get(terminalId); + + if (playerNodeId) { + const playerEntity = this.teamParentElement.querySelector(`#${playerNodeId}`); + if (playerEntity) { + this.renderEmojiEntity(playerEntity, playerNodeId); + } + } + } + + renderEmojiEntity(playerEntity, playerNodeId) { + const template = this.createEmojiTemplate(playerNodeId); + + let sayEntity = this.playerSayEntities.get(playerNodeId); + if (!sayEntity) { + sayEntity = document.createElement('a-entity'); + sayEntity.setAttribute('id', `${playerNodeId}-say`); + playerEntity.appendChild(sayEntity); + this.playerSayEntities.set(playerNodeId, sayEntity); + } + + render(template, sayEntity); + + // Make the entity visible + sayEntity.setAttribute('visible', 'true'); + + // Hide the entity after 5 seconds + // setTimeout(() => { + // sayEntity.setAttribute('visible', 'false'); + // }, 5000); + } + + createEmojiTemplate(playerNodeId) { + return html` + +
+ ${this.emoji} +
+
+ `; + } + updateQuestionDisplay() { if (this.currentVote && this.currentVote.properties['question-statement'] &&