diff --git a/src/components/2d-mute-state-indicator.js b/src/components/2d-mute-state-indicator.js index 134e1fa13d0d0418a64c2d3e74d5f992e52b321b..d93c83bab0e54a26be03bb6caf3190213e08a289 100644 --- a/src/components/2d-mute-state-indicator.js +++ b/src/components/2d-mute-state-indicator.js @@ -12,8 +12,6 @@ AFRAME.registerComponent("2d-mute-state-indicator", { this.muteIcon = document.createElement("div"); this.muteIcon.id = "mic-flat"; this.muteIcon.classList.add(styles.indicator); - console.log("foobar"); - console.log(this.muteIcon); document.body.appendChild(this.muteIcon); this.updateMuteState(); diff --git a/src/components/in-world-hud.js b/src/components/in-world-hud.js new file mode 100644 index 0000000000000000000000000000000000000000..3781379f3907e9648caa1cb1431569375145d505 --- /dev/null +++ b/src/components/in-world-hud.js @@ -0,0 +1,132 @@ +AFRAME.registerComponent("in-world-hud", { + init() { + this.bg = document.createElement("a-box"); + this.mic = document.createElement("a-image"); + this.nametag = document.createElement("a-text"); + this.avatar = document.createElement("a-image"); + this.el.appendChild(this.bg); + this.bg.appendChild(this.mic); + this.bg.appendChild(this.nametag); + this.bg.appendChild(this.avatar); + + this.bg.setAttribute("position", "0 2.0 -1"); + this.bg.setAttribute("geometry", { + height: 0.13, + width: 0.6, + depth: 0.001 + }); + this.bg.setAttribute("material", { + color: "#000000", + opacity: 0.35 + }); + + const muted = this.el.sceneEl.is("muted"); + this.mic.setAttribute("src", muted ? "#muted" : "#unmuted"); + this.mic.setAttribute("scale", "-0.1 0.1 0.1"); + this.mic.setAttribute("position", "-0.2 0.0 0.001"); + this.mic.classList.add("menu"); + + this.avatar.setAttribute("src", "#avatar"); + const avatarScale = "0.1 0.1 0.1"; + const flipXAvatarScale = "-" + avatarScale; + this.avatar.setAttribute("scale", avatarScale); + this.avatar.setAttribute("position", "0.2 0 0.001"); + this.avatar.classList.add("menu"); + + this.nametag.setAttribute("scale", "0.3 0.3 0.3"); + this.nametag.setAttribute("position", "-0.12 0 0.0001"); + this.nametag.classList.add("menu"); + + const scene = document.querySelector("a-scene"); + this.onUsernameChanged = this.onUsernameChanged.bind(this); + scene.addEventListener("username-changed", this.onUsernameChanged); + + this.addBlue = () => { + this.nametag.setAttribute("color", "cyan"); + }; + this.removeBlue = () => { + this.nametag.setAttribute("color", "white"); + }; + this.flipX = () => { + this.avatar.setAttribute("scale", flipXAvatarScale); + }; + this.unflipX = () => { + this.avatar.setAttribute("scale", avatarScale); + }; + this.onMicHover = () => { + this.hoveredOnMic = true; + const muted = scene.is("muted"); + this.mic.setAttribute("src", muted ? "#unmuted" : "#muted"); + }; + + this.onStateChange = evt => { + if (evt.detail.state !== "muted") return; + this.showCorrectMuteState(); + }; + this.showCorrectMuteState = () => { + this.hoveredOnMic = false; + const muted = this.el.sceneEl.is("muted"); + this.mic.setAttribute("src", muted ? "#muted" : "#unmuted"); + }; + + this.onSelect = evt => { + if (this.hoveredOnMic) { + this.el.emit("action_mute"); + } + }; + + this.onClick = () => { + this.el.emit("action_select_hud_item"); + }; + }, + + play() { + this.mic.addEventListener("raycaster-intersected", this.onMicHover); + this.mic.addEventListener("raycaster-intersected-cleared", this.showCorrectMuteState); + + this.nametag.addEventListener("raycaster-intersected", this.addBlue); + this.nametag.addEventListener("raycaster-intersected-cleared", this.removeBlue); + + this.avatar.addEventListener("raycaster-intersected", this.flipX); + this.avatar.addEventListener("raycaster-intersected-cleared", this.unflipX); + + this.el.sceneEl.addEventListener("stateadded", this.onStateChange); + this.el.sceneEl.addEventListener("stateremoved", this.onStateChange); + + this.el.sceneEl.addEventListener("action_select_hud_item", this.onSelect); + document.addEventListener("click", this.onClick); + }, + + pause() { + this.nametag.removeEventListener("raycaster-intersected", this.addBlue); + this.nametag.removeEventListener("raycaster-intersected-cleared", this.removeBlue); + + this.mic.removeEventListener("raycaster-intersected", this.onMicHover); + this.mic.removeEventListener("raycaster-intersected-cleared", this.showCorrectMuteState); + + this.avatar.removeEventListener("raycaster-intersected", this.flipX); + this.avatar.removeEventListener("raycaster-intersected-cleared", this.unflipX); + + this.el.sceneEl.removeEventListener("stateadded", this.onStateChange); + this.el.sceneEl.removeEventListener("stateremoved", this.onStateChange); + this.el.sceneEl.removeEventListener("action_select_hud_item", this.onSelect); + document.removeEventListener("click", this.onClick); + }, + + onUsernameChanged(evt) { + var width; + if (evt.detail.username.length == 0) { + width = 1; + } else { + width = 40 / evt.detail.username.length; + } + const maxWidth = 6; + if (width > maxWidth) { + width = maxWidth; + } + + this.nametag.setAttribute("text", "width", width); + this.nametag.setAttribute("text", "value", evt.detail.username); + this.nametag.components["text"].updateFont(); + } +}); diff --git a/src/input-mappings.js b/src/input-mappings.js index 272e3889ada96d6638d27544d3ea27ec379e5395..99234f30d1995abd6306faeb0234e7dbfc5f7cc3 100644 --- a/src/input-mappings.js +++ b/src/input-mappings.js @@ -67,6 +67,7 @@ const config = { q_press: "snap_rotate_left", e_press: "snap_rotate_right", v_press: "action_share_screen", + b_press: "action_select_hud_item", // We can't create a keyboard behaviour with AFIM yet, // so these will get captured by wasd-to-analog2d diff --git a/src/room.js b/src/room.js index 71beeb949d4bbeaa425b17438ee09e0aaa1707f5..4eec066b3764a4c626309a6913d4acdccf57259f 100644 --- a/src/room.js +++ b/src/room.js @@ -27,6 +27,7 @@ import "./components/nametag-transform"; import "./components/bone-mute-state-indicator"; import "./components/2d-mute-state-indicator"; import "./components/2d-hud"; +import "./components/in-world-hud"; import "./components/virtual-gamepad-controls"; import "./components/body-controller"; import "./components/hand-controls2"; diff --git a/templates/room.hbs b/templates/room.hbs index 7fb2b0d56eca65bad334025ffeb478e4894ef8fb..b4758f7ea23bc31c7aca12398889cd65e70d533c 100644 --- a/templates/room.hbs +++ b/templates/room.hbs @@ -41,11 +41,17 @@ onConnect: App.onConnect; connectOnLoad: false;" mute-mic="eventSrc: a-scene; toggleEvents: action_mute" + raycaster="objects:.menu;" + cursor="rayOrigin: mouse;" 2d-mute-state-indicator 2d-hud + in-world-hud light="defaultLightsEnabled: false"> <a-assets> + <img id="unmuted" src="assets/hud/unmuted.png" > + <img id="muted" src="assets/hud/muted.png" > + <img id="avatar" src="assets/hud/avatar.png" > <a-asset-item id="bot-head-mesh" response-type="arraybuffer" src="{{asset "assets/avatars/Bot_Head_Mesh.glb" }}"></a-asset-item> <a-asset-item id="bot-body-mesh" response-type="arraybuffer" src="{{asset "assets/avatars/Bot_Body_Mesh.glb" }}"></a-asset-item> <a-asset-item id="bot-left-hand-mesh" response-type="arraybuffer" src="{{asset "assets/avatars/Bot_LeftHand_Mesh.glb" }}"></a-asset-item> @@ -142,8 +148,6 @@ look-controls networked="template: #head-template; showLocalTemplate: false;" > - <!-- Head-locked Menu for Monoscopic displays --> - <!-- <a-image mixin="image" src="#avatar" scale="1 1 1" position="-0.2 -0.1 -0.2"> </a-image> --> </a-entity> <a-entity