1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
|
/* 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);
}
},
});
})();
|