/* global AFRAME, THREE */ // Floating name above a remote person's head. Always faces you, shows when // they're muted, and a dot under it glows while they talk. (function () { const worldPos = new THREE.Vector3(); const cameraPos = new THREE.Vector3(); const parentQuat = new THREE.Quaternion(); const yawQuat = new THREE.Quaternion(); const UP = new THREE.Vector3(0, 1, 0); AFRAME.registerComponent('nametag', { init() { this.label = document.createElement('a-entity'); this.label.setAttribute('text', { value: '', align: 'center', anchor: 'center', baseline: 'bottom', width: 1.4, wrapCount: 18, color: '#ffffff', side: 'double', }); this.el.appendChild(this.label); this.dot = document.createElement('a-circle'); this.dot.setAttribute('radius', 0.022); this.dot.setAttribute('position', '0 -0.035 0'); this.dot.setAttribute('material', { shader: 'flat', color: '#ffb36b', transparent: true, opacity: 0.25, side: 'double' }); this.el.appendChild(this.dot); this.head = this.el.parentEl; this.rig = this.head && this.head.parentEl; this.onInfo = (evt) => this.render(evt.detail); if (this.rig) { this.rig.addEventListener('player-info-changed', this.onInfo); const info = this.rig.getAttribute('player-info'); if (info) this.render(info); } }, remove() { if (this.rig) this.rig.removeEventListener('player-info-changed', this.onInfo); }, render(info) { const name = (info.name || 'Someone').slice(0, 20); this.label.setAttribute('text', { value: info.muted ? `${name}\n(muted)` : name, color: info.muted ? '#c9c9c9' : '#ffffff', }); this.dot.setAttribute('material', 'color', info.color || '#ffb36b'); }, tick() { const camera = this.el.sceneEl.camera; if (!camera) return; // Face the viewer, but stay upright however the speaker tilts their head. this.el.object3D.getWorldPosition(worldPos); camera.getWorldPosition(cameraPos); yawQuat.setFromAxisAngle(UP, Math.atan2(cameraPos.x - worldPos.x, cameraPos.z - worldPos.z)); this.el.object3D.parent.getWorldQuaternion(parentQuat).invert(); this.el.object3D.quaternion.copy(parentQuat).multiply(yawQuat); const voice = this.head && this.head.components['voice-level']; const level = voice ? voice.level : 0; const mesh = this.dot.getObject3D('mesh'); if (mesh) { mesh.material.opacity = 0.25 + level * 0.75; mesh.scale.setScalar(1 + level * 0.8); } }, }); })();