From 7b57a55b74bb3a60516831e21bacdd900b6b602d Mon Sep 17 00:00:00 2001 From: netpro2k <netpro2k@gmail.com> Date: Tue, 10 Apr 2018 16:06:59 -0700 Subject: [PATCH] Move hud-controller to its own file --- src/components/hud-controller.js | 77 +++++++++++++++++++++++++++++++ src/hub.js | 1 + src/systems/app-mode.js | 78 +------------------------------- 3 files changed, 79 insertions(+), 77 deletions(-) create mode 100644 src/components/hud-controller.js diff --git a/src/components/hud-controller.js b/src/components/hud-controller.js new file mode 100644 index 000000000..4ee274f34 --- /dev/null +++ b/src/components/hud-controller.js @@ -0,0 +1,77 @@ +import { AppModes } from "../systems/app-mode.js"; + +const TWOPI = Math.PI * 2; +function deltaAngle(a, b) { + const p = Math.abs(b - a) % TWOPI; + return p > Math.PI ? TWOPI - p : p; +} + +/** + * Positions the HUD and toggles app mode based on where the user is looking + */ +AFRAME.registerComponent("hud-controller", { + schema: { + head: { type: "selector" }, + offset: { default: 0.7 }, // distance from hud above head, + lookCutoff: { default: 20 }, // angle at which the hud should be "on", + animRange: { default: 30 }, // degrees over which to animate the hud into view + yawCutoff: { default: 50 } // yaw degrees at wich the hud should reoirent even if the user is looking up + }, + init() { + this.isYLocked = false; + this.lockedHeadPositionY = 0; + }, + + pause() { + // TODO: this assumes full control over current app mode reguardless of what else might be manipulating it, this is obviously wrong + const AppModeSystem = this.el.sceneEl.systems["app-mode"]; + AppModeSystem.setMode(AppModes.DEFAULT); + }, + + tick() { + const hud = this.el.object3D; + const head = this.data.head.object3D; + const sceneEl = this.el.sceneEl; + + const { offset, lookCutoff, animRange, yawCutoff } = this.data; + + const pitch = head.rotation.x * THREE.Math.RAD2DEG; + const yawDif = deltaAngle(head.rotation.y, hud.rotation.y) * THREE.Math.RAD2DEG; + + // Reorient the hud only if the user is looking away from the hud, for right now this arbitrarily means the hud is 1/3 way animated away + // TODO: come up with better huristics for this that maybe account for the user turning away from the hud "too far", also animate the position so that it doesnt just snap. + if (yawDif >= yawCutoff || pitch < lookCutoff - animRange / 3) { + const lookDir = new THREE.Vector3(0, 0, -1); + lookDir.applyQuaternion(head.quaternion); + lookDir.add(head.position); + hud.position.x = lookDir.x; + hud.position.z = lookDir.z; + hud.setRotationFromEuler(new THREE.Euler(0, head.rotation.y, 0)); + } + + // animate the hud into place over animRange degrees as the user aproaches the lookCutoff angle + const t = 1 - THREE.Math.clamp(lookCutoff - pitch, 0, animRange) / animRange; + + // Lock the hud in place relative to a known head position so it doesn't bob up and down + // with the user's head + if (!this.isYLocked && t === 1) { + this.lockedHeadPositionY = head.position.y; + } + const EPSILON = 0.001; + this.isYLocked = t > 1 - EPSILON; + + hud.position.y = (this.isYLocked ? this.lockedHeadPositionY : head.position.y) + offset + (1 - t) * offset; + hud.rotation.x = (1 - t) * THREE.Math.DEG2RAD * 90; + + // update the app mode when the HUD locks on or off + // TODO: this assumes full control over current app mode reguardless of what else might be manipulating it, this is obviously wrong + const AppModeSystem = sceneEl.systems["app-mode"]; + if (pitch > lookCutoff && AppModeSystem.mode !== AppModes.HUD) { + AppModeSystem.setMode(AppModes.HUD); + sceneEl.renderer.sortObjects = true; + } else if (pitch < lookCutoff && AppModeSystem.mode === AppModes.HUD) { + AppModeSystem.setMode(AppModes.DEFAULT); + sceneEl.renderer.sortObjects = false; + } + } +}); diff --git a/src/hub.js b/src/hub.js index d3bb84845..c0a69b01f 100644 --- a/src/hub.js +++ b/src/hub.js @@ -45,6 +45,7 @@ import "./components/animation-mixer"; import "./components/loop-animation"; import "./components/gltf-model-plus"; import "./components/gltf-bundle"; +import "./components/hud-controller"; import ReactDOM from "react-dom"; import React from "react"; diff --git a/src/systems/app-mode.js b/src/systems/app-mode.js index da5a42392..49e8d361b 100644 --- a/src/systems/app-mode.js +++ b/src/systems/app-mode.js @@ -1,6 +1,6 @@ /* global AFRAME, console, setTimeout, clearTimeout */ -const AppModes = Object.freeze({ DEFAULT: "default", HUD: "hud" }); +export const AppModes = Object.freeze({ DEFAULT: "default", HUD: "hud" }); /** * Simple system for keeping track of a modal app state @@ -89,82 +89,6 @@ AFRAME.registerComponent("app-mode-input-mappings", { } }); -const TWOPI = Math.PI * 2; -function deltaAngle(a, b) { - const p = Math.abs(b - a) % TWOPI; - return p > Math.PI ? TWOPI - p : p; -} - -/** - * Positions the HUD and toggles app mode based on where the user is looking - */ -AFRAME.registerComponent("hud-controller", { - schema: { - head: { type: "selector" }, - offset: { default: 0.7 }, // distance from hud above head, - lookCutoff: { default: 20 }, // angle at which the hud should be "on", - animRange: { default: 30 }, // degrees over which to animate the hud into view - yawCutoff: { default: 50 } // yaw degrees at wich the hud should reoirent even if the user is looking up - }, - init() { - this.isYLocked = false; - this.lockedHeadPositionY = 0; - }, - - pause() { - // TODO: this assumes full control over current app mode reguardless of what else might be manipulating it, this is obviously wrong - const AppModeSystem = this.el.sceneEl.systems["app-mode"]; - AppModeSystem.setMode(AppModes.DEFAULT); - }, - - tick() { - const hud = this.el.object3D; - const head = this.data.head.object3D; - const sceneEl = this.el.sceneEl; - - const { offset, lookCutoff, animRange, yawCutoff } = this.data; - - const pitch = head.rotation.x * THREE.Math.RAD2DEG; - const yawDif = deltaAngle(head.rotation.y, hud.rotation.y) * THREE.Math.RAD2DEG; - - // Reorient the hud only if the user is looking away from the hud, for right now this arbitrarily means the hud is 1/3 way animated away - // TODO: come up with better huristics for this that maybe account for the user turning away from the hud "too far", also animate the position so that it doesnt just snap. - if (yawDif >= yawCutoff || pitch < lookCutoff - animRange / 3) { - const lookDir = new THREE.Vector3(0, 0, -1); - lookDir.applyQuaternion(head.quaternion); - lookDir.add(head.position); - hud.position.x = lookDir.x; - hud.position.z = lookDir.z; - hud.setRotationFromEuler(new THREE.Euler(0, head.rotation.y, 0)); - } - - // animate the hud into place over animRange degrees as the user aproaches the lookCutoff angle - const t = 1 - THREE.Math.clamp(lookCutoff - pitch, 0, animRange) / animRange; - - // Lock the hud in place relative to a known head position so it doesn't bob up and down - // with the user's head - if (!this.isYLocked && t === 1) { - this.lockedHeadPositionY = head.position.y; - } - const EPSILON = 0.001; - this.isYLocked = t > 1 - EPSILON; - - hud.position.y = (this.isYLocked ? this.lockedHeadPositionY : head.position.y) + offset + (1 - t) * offset; - hud.rotation.x = (1 - t) * THREE.Math.DEG2RAD * 90; - - // update the app mode when the HUD locks on or off - // TODO: this assumes full control over current app mode reguardless of what else might be manipulating it, this is obviously wrong - const AppModeSystem = sceneEl.systems["app-mode"]; - if (pitch > lookCutoff && AppModeSystem.mode !== AppModes.HUD) { - AppModeSystem.setMode(AppModes.HUD); - sceneEl.renderer.sortObjects = true; - } else if (pitch < lookCutoff && AppModeSystem.mode === AppModes.HUD) { - AppModeSystem.setMode(AppModes.DEFAULT); - sceneEl.renderer.sortObjects = false; - } - } -}); - /** * Toggle visibility of an entity based on if the user is in vr mode or not */ -- GitLab