diff --git a/src/components/axis-dpad.js b/src/components/axis-dpad.js index 853e1569714a87ec0da79dea7fa423cabd721b36..b4ccef1298dd0ac434eba62138f7860b1da1b024 100644 --- a/src/components/axis-dpad.js +++ b/src/components/axis-dpad.js @@ -8,18 +8,7 @@ * @TODO make axes configurable */ -const angleToDirection = function(angle) { - angle = (angle * THREE.Math.RAD2DEG + 180 + 45) % 360; - if (angle > 0 && angle < 90) { - return "down"; - } else if (angle >= 90 && angle < 180) { - return "left"; - } else if (angle >= 180 && angle < 270) { - return "up"; - } else { - return "right"; - } -}; +import angleToDirection from "../utils"; AFRAME.registerComponent("axis-dpad", { schema: { diff --git a/src/components/character-controller.js b/src/components/character-controller.js index b92077fc9e2334593d458320cdb9a93a7757f90d..b1c1caf386ca3d1a8691c08acfa15ab02ac8395b 100644 --- a/src/components/character-controller.js +++ b/src/components/character-controller.js @@ -17,7 +17,7 @@ AFRAME.registerComponent("character-controller", { this.boost = 1.0; this.pendingSnapRotationMatrix = new THREE.Matrix4(); this.angularVelocity = 0; // Scalar value because we only allow rotation around Y - this.onMove = this.onMove.bind(this); + this.setAccelerationInput = this.setAccelerationInput.bind(this); this.onBoost = this.onBoost.bind(this); this.onSnapRotateLeft = this.onSnapRotateLeft.bind(this); this.onSnapRotateRight = this.onSnapRotateRight.bind(this); @@ -35,7 +35,7 @@ AFRAME.registerComponent("character-controller", { play: function() { const eventSrc = this.el.sceneEl; - eventSrc.addEventListener("move", this.onMove); + eventSrc.addEventListener("move", this.setAccelerationInput); eventSrc.addEventListener("rotateY", this.onRotateY); eventSrc.addEventListener("action_snap_rotate_left", this.onSnapRotateLeft); eventSrc.addEventListener( @@ -47,7 +47,7 @@ AFRAME.registerComponent("character-controller", { pause: function() { const eventSrc = this.el.sceneEl; - eventSrc.removeEventListener("move", this.onMove); + eventSrc.removeEventListener("move", this.setAccelerationInput); eventSrc.removeEventListener("rotateY", this.onRotateY); eventSrc.removeEventListener( "action_snap_rotate_left", @@ -59,7 +59,7 @@ AFRAME.registerComponent("character-controller", { ); }, - onMove: function(event) { + setAccelerationInput: function(event) { const axes = event.detail.axis; this.accelerationInput.set(axes[0], 0, axes[1]); }, diff --git a/src/components/dpad-as-axes.js b/src/components/dpad-as-axes.js new file mode 100644 index 0000000000000000000000000000000000000000..c0a232a5554d8b066e79bebc35ceff52e0c00c14 --- /dev/null +++ b/src/components/dpad-as-axes.js @@ -0,0 +1,74 @@ +AFRAME.registerComponent("dpad-as-axes", { + schema: { + dpadActionPrefix: { default: "dpad" }, + analog2dOutputAction: { default: "keyboard_dpad_axes" }, + emitter: { default: "#left-hand" } + }, + + init: function() { + this.handlers = []; + this.directionsAndAxes = [ + { + direction: "north", + axes: [0, 1] + }, + { + direction: "northeast", + axes: [1, 1] + }, + { + direction: "east", + axes: [1, 0] + }, + { + direction: "southeast", + axes: [1, -1] + }, + { + direction: "south", + axes: [0, -1] + }, + { + direction: "southwest", + axes: [-1, -1] + }, + { + direction: "west", + axes: [-1, 0] + }, + { + direction: "northwest", + axes: [-1, 1] + } + ]; + }, + + play: function() { + const inputAction = this.data.dpadActionPrefix; + for (var tuple of this.directionsAndAxes) { + this.handlers[tuple.direction] = this.emitAnalog2d(tuple.axes).bind(this); + this.el.addEventListener( + `${inputAction}_${tuple.direction}`, + this.handlers[tuple.direction] + ); + } + }, + + pause: function() { + const inputAction = this.data.dpadActionPrefix; + for (var tuple of this.directionsAndAxes) { + this.el.removeEventListener( + `${inputAction}_${tuple.direction}`, + this.handlers[tuple.direction] + ); + } + }, + + emitAnalog2d: function(axes) { + const outputAction = this.data.analog2dOutputAction; + const emitter = document.querySelector(this.data.emitter); + return function(event) { + emitter.emit(outputAction, { axis: [axes[0], axes[1]] }); + }; + } +}); diff --git a/src/components/haptic-feedback.js b/src/components/haptic-feedback.js new file mode 100644 index 0000000000000000000000000000000000000000..0ac0512d2cf7fe9d16724c6441036484d321cf59 --- /dev/null +++ b/src/components/haptic-feedback.js @@ -0,0 +1,50 @@ +AFRAME.registerComponent("haptic-feedback", { + schema: { + hapticEventName: { default: "haptic_pulse" } + }, + + init: function() { + this.pulse = this.pulse.bind(this); + this.tryGetActuator = this.tryGetActuator.bind(this); + this.tryGetActuator(); + }, + + tryGetActuator() { + var trackedControls = this.el.components["tracked-controls"]; + if (trackedControls && trackedControls.controller) { + this.actuator = trackedControls.controller.hapticActuators[0]; + } else { + setTimeout(this.tryGetActuator, 1000); + } + }, + + play: function() { + this.el.addEventListener(`${this.data.hand}_haptic_pulse`, this.pulse); + }, + pause: function() { + this.el.removeEventListener(`${this.data.hand}_haptic_pulse`, this.pulse); + }, + + pulse: function(event) { + let { strength, duration, intensity } = event.detail; + switch (intensity) { + case "low": { + strength = 0.07; + duration = 12; + } + case "medium": { + strength = 0.2; + duration = 12; + } + case "high": { + strength = 1; + duration = 12; + } + case "none": { + return; + } + } + + this.actuator.pulse(strength, duration); + } +}); diff --git a/src/components/keyboard-dpad.js b/src/components/keyboard-dpad.js new file mode 100644 index 0000000000000000000000000000000000000000..7ce1eb8d5e4629bbce486642e2efbd95b9cc58d6 --- /dev/null +++ b/src/components/keyboard-dpad.js @@ -0,0 +1,56 @@ +/// Listens to four keyboard events, then emits dpad events. +AFRAME.registerComponent("keyboard-dpad", { + schema: { + north: { default: "w" }, + east: { default: "d" }, + south: { default: "s" }, + west: { default: "a" }, + dpadActionPrefix: { type: "string" } + }, + + init: function() { + this.onKeyPress = this.onKeyPress.bind(this); + this.onKeyUp = this.onKeyUp.bind(this); + this.keys = {}; + }, + + play: function() { + window.addEventListener("keypress", this.onKeyPress); + window.addEventListener("keyup", this.onKeyUp); + }, + + pause: function() { + window.remove("keypress", this.onKeyPress); + window.remove("keyup", this.onKeyUp); + }, + + tick: function(t, dt) { + const { north, east, south, west, dpadActionPrefix } = this.data; + var direction = ""; + direction += this.keys[north] ? "north" : ""; + direction += this.keys[south] ? "south" : ""; + direction += this.keys[east] ? "east" : ""; + direction += this.keys[west] ? "west" : ""; + if (direction !== "") { + this.el.emit(`${dpadActionPrefix}_${direction}`); + } + }, + + onKeyPress: function(event) { + const { north, east, south, west } = this.data; + for (var dir of [north, south, east, west]) { + if (event.key === dir) { + this.keys[dir] = true; + } + } + }, + + onKeyUp: function(event) { + const { north, east, south, west } = this.data; + for (var dir of [north, south, east, west]) { + if (event.key === dir) { + this.keys[dir] = false; + } + } + } +}); diff --git a/src/components/oculus-touch-controls-extended.js b/src/components/oculus-touch-controls-extended.js new file mode 100644 index 0000000000000000000000000000000000000000..519e33c34fa19391f108849daf85073d80e38cb2 --- /dev/null +++ b/src/components/oculus-touch-controls-extended.js @@ -0,0 +1,62 @@ +import { angleTo4Direction, angleTo8Direction } from "../utils"; + +AFRAME.registerComponent("oculus-touch-controls-extended", { + schema: { + hand: { default: "left" }, + dpad_enabled: { default: false }, + dpad_deadzone: { default: 0.85 }, + dpad_livezone: { default: 0.35 }, + dpad_directions: { default: 4 }, // one of [4, 8] + dpad_turbo: { default: false }, + dpad_haptic_intensity: { default: "none" } // one of ["none", "low", "medium", "high"] + }, + + init: function() { + this.filterAxisMove = this.filterAxisMove.bind(this); + this.dpadCanFire = true; + }, + + play: function(old) { + this.el.addEventListener("axismove", this.filterAxisMove); + }, + + pause: function(old) { + this.el.removeEventListener("axismove", this.filterAxisMove); + }, + + filterAxisMove: function(event) { + const x = event.detail.axis[0]; + const y = event.detail.axis[1]; + const deadzone = this.data.dpad_deadzone; + const turbo = this.data.dpad_turbo; + const livezone = this.data.dpad_livezone; + const directions = this.data.dpad_directions; + const haptic_intensity = this.data.dpad_haptic_intensity; + const hand = this.data.hand; + + event.target.emit(`${hand}_axismove`, { + axis: [event.detail.axis[0], -event.detail.axis[1]] + }); + + if (!this.data.dpad_enabled) { + return; + } + if (!turbo && Math.abs(x) < livezone && Math.abs(y) < livezone) { + this.dpadCanFire = true; + } + if (!this.dpadCanFire) return; + + const deadzoneFilteredX = Math.abs(x) < deadzone ? 0 : x; + const deadzoneFilteredY = Math.abs(y) < deadzone ? 0 : y; + if (deadzoneFilteredX == 0 && deadzoneFilteredY == 0) return; + const angle = Math.atan2(deadzoneFilteredX, deadzoneFilteredY); + const direction = + directions === 4 ? angleTo4Direction(angle) : angleTo8Direction(angle); + + event.target.emit(`${hand}_dpad_${direction}`); + event.target.emit(`${hand}_haptic_pulse`, { intensity: haptic_intensity }); + if (!turbo) { + this.dpadCanFire = false; + } + } +}); diff --git a/src/components/split-axis-events.js b/src/components/split-axis-events.js index e78e8115906b1f9b1bc19dbd3b412b78a1eb5ab5..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 --- a/src/components/split-axis-events.js +++ b/src/components/split-axis-events.js @@ -1,376 +0,0 @@ -const angleTo4Direction = function(angle) { - angle = (angle * THREE.Math.RAD2DEG + 180 + 45) % 360; - if (angle > 0 && angle < 90) { - return "north"; - } else if (angle >= 90 && angle < 180) { - return "west"; - } else if (angle >= 180 && angle < 270) { - return "south"; - } else { - return "east"; - } -}; - -const angleTo8Direction = function(angle) { - angle = (angle * THREE.Math.RAD2DEG + 180 + 45) % 360; - var direction = ""; - if ((angle >= 0 && angle < 120) || angle >= 330) { - direction += "north"; - } - if (angle >= 150 && angle < 300) { - direction += "south"; - } - if (angle >= 60 && angle < 210) { - direction += "west"; - } - if ((angle >= 240 && angle < 360) || angle < 30) { - direction += "east"; - } - return direction; -}; - -AFRAME.registerComponent("dpad-as-axes", { - schema: { - inputName: { default: "dpad" }, - name: { default: "dpad_axes" }, - emitter: { default: "#left-hand" } - }, - - init: function() { - this.mapping = [ - { - direction: "north", - axes: [0, 1] - }, - { - direction: "northeast", - axes: [1, 1] - }, - { - direction: "east", - axes: [1, 0] - }, - { - direction: "southeast", - axes: [1, -1] - }, - { - direction: "south", - axes: [0, -1] - }, - { - direction: "southwest", - axes: [-1, -1] - }, - { - direction: "west", - axes: [-1, 0] - }, - { - direction: "northwest", - axes: [-1, 1] - } - ]; - this.handlers = []; - }, - - play: function() { - var inputName = this.data.inputName; - for (var pair of this.mapping) { - this.handlers[pair.direction] = this.emitAxes(pair.axes).bind(this); - this.el.addEventListener( - `${inputName}_${pair.direction}`, - this.handlers[pair.direction] - ); - } - }, - - pause: function() { - var inputName = this.data.inputName; - for (var pair of this.mapping) { - this.el.removeEventListener( - `${inputName}_${pair.direction}`, - this.handlers[pair.direction] - ); - } - }, - - emitAxes: function(axes) { - const name = this.data.name; - const inputName = this.data.inputName; - const emitter = document.querySelector(this.data.emitter); - return function(event) { - emitter.emit(name, { axis: [axes[0], axes[1]] }); - }; - } -}); - -AFRAME.registerComponent("wasd-dpad", { - schema: { - north: { default: "w" }, - east: { default: "d" }, - south: { default: "s" }, - west: { default: "a" } - }, - - init: function() { - this.onKeyPress = this.onKeyPress.bind(this); - this.onKeyUp = this.onKeyUp.bind(this); - this.keys = {}; - }, - - play: function() { - window.addEventListener("keypress", this.onKeyPress); - window.addEventListener("keyup", this.onKeyUp); - }, - - pause: function() { - window.remove("keypress", this.onKeyPress); - window.remove("keyup", this.onKeyUp); - }, - - tick: function(t, dt) { - const { north, east, south, west } = this.data; - var direction = ""; - direction += this.keys[north] ? "north" : ""; - direction += this.keys[south] ? "south" : ""; - direction += this.keys[east] ? "east" : ""; - direction += this.keys[west] ? "west" : ""; - if (direction !== "") { - this.el.emit(`dpad_${direction}`); - } - }, - - onKeyPress: function(event) { - const { north, east, south, west } = this.data; - for (var dir of [north, south, east, west]) { - if (event.key === dir) { - this.keys[dir] = true; - } - } - }, - - onKeyUp: function(event) { - const { north, east, south, west } = this.data; - for (var dir of [north, south, east, west]) { - if (event.key === dir) { - this.keys[dir] = false; - } - } - } -}); - -AFRAME.registerComponent("oculus-touch-controls-extended", { - schema: { - hand: { default: "left" }, - dpad: { default: false }, - dpad_deadzone: { default: 0.85 }, - dpad_livezone: { default: 0.35 }, - dpad_directions: { default: 4 }, // one of [4, 8] - dpad_turbo: { default: false }, - dpad_haptic_intensity: { default: "none" } // one of ["none", "low", "mid", "high"] - }, - - init: function() { - this.axisToDpad = this.axisToDpad.bind(this); - this.dpadCanFire = true; - }, - - update: function(old) { - if (old.dpad && !this.data.dpad) { - this.el.removeEventListener("axismove", this.axisToDpad); - } - if (!old.dpad && this.data.dpad) { - this.el.addEventListener("axismove", this.axisToDpad); - } - }, - - axisToDpad: function(event) { - var x = event.detail.axis[0]; - var y = event.detail.axis[1]; - var deadzone = this.data.dpad_deadzone; - var turbo = this.data.dpad_turbo; - var livezone = this.data.dpad_livezone; - var directions = this.data.dpad_directions; - var haptic_intensity = this.data.dpad_haptic_intensity; - var hand = this.data.hand; - - event.target.emit(`${hand}_axismove`, { - axis: [event.detail.axis[0], -event.detail.axis[1]] - }); - - if (!turbo && Math.abs(x) < livezone && Math.abs(y) < livezone) { - this.dpadCanFire = true; - } - if (!this.dpadCanFire) return; - - x = Math.abs(x) < deadzone ? 0 : x; - y = Math.abs(y) < deadzone ? 0 : y; - if (x == 0 && y == 0) return; - var angle = Math.atan2(x, y); - var direction = - directions === 4 ? angleTo4Direction(angle) : angleTo8Direction(angle); - - event.target.emit(`${hand}_dpad_${direction}`); - event.target.emit(`${hand}_haptic_pulse`, { intensity: haptic_intensity }); - if (!turbo) { - this.dpadCanFire = false; - } - } -}); - -AFRAME.registerComponent("haptic-feedback", { - schema: { - hand: { default: "left" } - }, - - init: function() { - this.pulse = this.pulse.bind(this); - this.tryGetActuator = this.tryGetActuator.bind(this); - this.tryGetActuator(); - }, - - tryGetActuator() { - var trackedControls = this.el.components["tracked-controls"]; - if (trackedControls && trackedControls.controller) { - this.actuator = trackedControls.controller.hapticActuators[0]; - } else { - setTimeout(this.tryGetActuator, 1000); - } - }, - - play: function() { - this.el.addEventListener(`${this.data.hand}_haptic_pulse`, this.pulse); - }, - pause: function() { - this.el.removeEventListener(`${this.data.hand}_haptic_pulse`, this.pulse); - }, - - pulse: function(event) { - let { strength, duration, intensity } = event.detail; - if (intensity === "low") { - strength = 0.07; - duration = 12; - } - if (intensity === "medium") { - strength = 0.2; - duration = 12; - } - if (intensity === "high") { - strength = 1; - duration = 12; - } - if (intensity === "none") { - return; - } - - this.actuator.pulse(strength, duration); - } -}); - -AFRAME.registerComponent("vive-controls-extended", { - schema: { - hand: { default: "left" }, - dpad: { default: false }, - dpad_livezone: { default: 0.3 }, - dpad_deadzone: { default: 0.8 }, - dpad_directions: { default: 4 }, - dpad_turbo: { default: true }, - dpad_pressed_turbo: { default: false }, - center_zone: { default: 0.3 }, - dpad_haptic_intensity: { default: "none" }, - dpad_pressed_haptic_intensity: { default: "none" } - }, - - init: function() { - this.dpadCanFire = true; - this.dpadPressedCanFire = true; - this.trackpadPressed = false; - this.onAxisMove = this.onAxisMove.bind(this); - this.lastSeenAxes = [0, 0]; - this.onButtonChanged = this.onButtonChanged.bind(this); - }, - - play: function() { - this.el.addEventListener("axismove", this.onAxisMove); - this.el.addEventListener("trackpadchanged", this.onButtonChanged); - }, - - pause: function() { - this.el.removeEventListener("axismove", this.onAxisMove); - this.el.removeEventListener("trackpadchanged", this.onButtonChanged); - }, - - onAxisMove: function(event) { - var x = event.detail.axis[0]; - var y = event.detail.axis[1]; - this.lastSeenAxes = [x, y]; - var hand = this.data.hand; - const axisMoveEvent = `${hand}_trackpad${this.trackpadPressed - ? "_pressed" - : ""}_axismove`; - this.el.emit(axisMoveEvent, { - axis: [x, y] - }); - - var deadzone = this.data.dpad_deadzone; - var turbo = this.data.dpad_turbo; - var pressedTurbo = this.data.dpad_pressed_turbo; - var livezone = this.data.dpad_livezone; - var directions = this.data.dpad_directions; - var hapticIntensity = this.data.dpad_haptic_intensity; - var pressedHapticIntensity = this.data.dpad_pressed_haptic_intensity; - - if (!turbo && Math.abs(x) < livezone && Math.abs(y) < livezone) { - this.dpadCanFire = true; - } - - event.target.emit(`${hand}_haptic_pulse`, { - intensity: this.trackpadPressed ? pressedHapticIntensity : hapticIntensity - }); - - x = Math.abs(x) < deadzone ? 0 : x; - y = Math.abs(y) < deadzone ? 0 : y; - if (x == 0 && y == 0) return; - var angle = Math.atan2(x, y); - var direction = - directions === 4 ? angleTo4Direction(angle) : angleTo8Direction(angle); - - if (!this.trackpadPressed && !this.dpadCanFire) { - return; - } - if (this.trackpadPressed && !this.dpadPressedCanFire) { - return; - } - var dpadEvent = `${hand}_trackpad_dpad${this.trackpadPressed - ? "_pressed" - : ""}_${direction}`; - event.target.emit(dpadEvent); - - if (!this.trackpadPressed && !turbo) { - this.dpadCanFire = false; - } else if (this.trackpadPressed && !pressedTurbo) { - this.dpadPressedCanFire = false; - } - }, - - onButtonChanged: function(event) { - const x = this.lastSeenAxes[0]; - const y = this.lastSeenAxes[1]; - const hand = this.data.hand; - const centerZone = this.data.center_zone; - const down = !this.trackpadPressed && event.detail.pressed; - const up = this.trackpadPressed && !event.detail.pressed; - const center = - Math.abs(x) < centerZone && Math.abs(y) < centerZone ? "_center" : ""; - const eventName = `${hand}_trackpad${center}${up ? "_up" : ""}${down - ? "_down" - : ""}`; - this.el.emit(eventName); - if (up) { - this.dpadPressedCanFire = true; - } - - this.trackpadPressed = event.detail.pressed; - } -}); diff --git a/src/components/virtual-gamepad-controls.js b/src/components/virtual-gamepad-controls.js index afa01aa81d3de5bf80d951b9b65c3f40a0c80c38..d399e38b29765280a677bb23289cdc3e4c2aff6b 100644 --- a/src/components/virtual-gamepad-controls.js +++ b/src/components/virtual-gamepad-controls.js @@ -53,10 +53,10 @@ AFRAME.registerComponent("virtual-gamepad-controls", { onJoystickChanged(event, joystick) { if (event.target.id === this.leftStick.id) { if (event.type === "move") { - var angle = joystick.angle.radian; - var force = joystick.force < 1 ? joystick.force : 1; - var x = Math.cos(angle) * force; - var z = Math.sin(angle) * force; + const angle = joystick.angle.radian; + const force = joystick.force < 1 ? joystick.force : 1; + const x = Math.cos(angle) * force; + const z = Math.sin(angle) * force; this.el.sceneEl.emit("move", { axis: [x, z] }); } else { this.el.sceneEl.emit("move", { axis: [0, 0] }); diff --git a/src/components/vive-controls-extended.js b/src/components/vive-controls-extended.js new file mode 100644 index 0000000000000000000000000000000000000000..7dfde12a0db85752c8545a69a8d983cb84d0d7b1 --- /dev/null +++ b/src/components/vive-controls-extended.js @@ -0,0 +1,105 @@ +import { angleTo4Direction, angleTo8Direction } from "../utils"; + +AFRAME.registerComponent("vive-controls-extended", { + schema: { + hand: { type: "string" }, + dpad_enabled: { default: false }, + dpad_livezone: { default: 0.3 }, + dpad_deadzone: { default: 0.7 }, + dpad_directions: { default: 4 }, + dpad_turbo: { default: false }, + dpad_pressed_turbo: { default: false }, + center_zone: { default: 0.3 }, + dpad_haptic_intensity: { default: "none" }, + dpad_pressed_haptic_intensity: { default: "none" } + }, + + init: function() { + this.dpadCanFire = true; + this.dpadPressedCanFire = true; + this.trackpadPressed = false; + this.onAxisMove = this.onAxisMove.bind(this); + this.lastSeenAxes = [0, 0]; + this.onButtonChanged = this.onButtonChanged.bind(this); + }, + + play: function() { + this.el.addEventListener("axismove", this.onAxisMove); + this.el.addEventListener("trackpadchanged", this.onButtonChanged); + }, + + pause: function() { + this.el.removeEventListener("axismove", this.onAxisMove); + this.el.removeEventListener("trackpadchanged", this.onButtonChanged); + }, + + onAxisMove: function(event) { + const x = event.detail.axis[0]; + const y = event.detail.axis[1]; + this.lastSeenAxes = [x, y]; + const hand = this.data.hand; + const pressed = this.trackpadPressed ? "_pressed" : ""; + const axisMoveEvent = `${hand}_trackpad${pressed}_axismove`; + this.el.emit(axisMoveEvent, { + axis: [x, y] + }); + + const deadzone = this.data.dpad_deadzone; + const turbo = this.data.dpad_turbo; + const pressedTurbo = this.data.dpad_pressed_turbo; + const livezone = this.data.dpad_livezone; + const directions = this.data.dpad_directions; + const hapticIntensity = this.data.dpad_haptic_intensity; + const pressedHapticIntensity = this.data.dpad_pressed_haptic_intensity; + + if (!turbo && Math.abs(x) < livezone && Math.abs(y) < livezone) { + this.dpadCanFire = true; + } + + event.target.emit(`${hand}_haptic_pulse`, { + intensity: this.trackpadPressed ? pressedHapticIntensity : hapticIntensity + }); + + const deadzoneFilteredX = Math.abs(x) < deadzone ? 0 : x; + const deadzoneFilteredY = Math.abs(y) < deadzone ? 0 : y; + if (deadzoneFilteredX == 0 && deadzoneFilteredY == 0) return; + const angle = Math.atan2(deadzoneFilteredX, deadzoneFilteredY); + const direction = + directions === 4 ? angleTo4Direction(angle) : angleTo8Direction(angle); + + if (!this.trackpadPressed && !this.dpadCanFire) { + return; + } + if (this.trackpadPressed && !this.dpadPressedCanFire) { + return; + } + const dpadEvent = `${hand}_trackpad_dpad${pressed}_${direction}`; + event.target.emit(dpadEvent); + + if (!this.trackpadPressed && !turbo) { + this.dpadCanFire = false; + } else if (this.trackpadPressed && !pressedTurbo) { + this.dpadPressedCanFire = false; + } + }, + + onButtonChanged: function(event) { + const x = this.lastSeenAxes[0]; + const y = this.lastSeenAxes[1]; + const hand = this.data.hand; + const centerZone = this.data.center_zone; + const down = !this.trackpadPressed && event.detail.pressed; + const up = this.trackpadPressed && !event.detail.pressed; + const center = + Math.abs(x) < centerZone && Math.abs(y) < centerZone ? "_center" : ""; + const eventName = `${hand}_trackpad${center}${up ? "_up" : ""}${down + ? "_down" + : ""}`; + this.el.emit(eventName); + if (up) { + this.dpadPressedCanFire = true; + } + + this.trackpadPressed = event.detail.pressed; + } +}); diff --git a/src/room.js b/src/room.js index 2330ffd76d063980a44352fb51430ea34ec35845..b660adffec6884491d67024f96ba73d781781eb7 100644 --- a/src/room.js +++ b/src/room.js @@ -20,6 +20,11 @@ import "./components/body-controller"; import "./components/hand-controls2"; import "./components/character-controller"; import "./components/split-axis-events"; +import "./components/dpad-as-axes"; +import "./components/keyboard-dpad"; +import "./components/oculus-touch-controls-extended"; +import "./components/vive-controls-extended"; +import "./components/haptic-feedback"; import "./components/networked-video-player"; import "./components/offset-relative-to"; import "./components/cached-gltf-model"; diff --git a/src/utils.js b/src/utils.js index b37764120a388120c89392fb6b9b97f31dd59578..1c09c032f010a84eddfa67ad7197a3d3bc92b603 100644 --- a/src/utils.js +++ b/src/utils.js @@ -167,9 +167,8 @@ export function generateName() { } export function promptForName(username) { - if (!username) - username = generateName(); - + if (!username) username = generateName(); + do { username = prompt("Choose a username", username); } while (!(username && username.length)); @@ -179,11 +178,59 @@ export function promptForName(username) { export function getCookie(name) { var value = "; " + document.cookie; var parts = value.split("; " + name + "="); - if (parts.length == 2) return parts.pop().split(";").shift(); + if (parts.length == 2) + return parts + .pop() + .split(";") + .shift(); } -export function parseJwt (token) { - var base64Url = token.split('.')[1]; - var base64 = base64Url.replace('-', '+').replace('_', '/'); +export function parseJwt(token) { + var base64Url = token.split(".")[1]; + var base64 = base64Url.replace("-", "+").replace("_", "/"); return JSON.parse(window.atob(base64)); } + +export function angleToDirection(angle) { + angle = (angle * THREE.Math.RAD2DEG + 180 + 45) % 360; + if (angle > 0 && angle < 90) { + return "down"; + } else if (angle >= 90 && angle < 180) { + return "left"; + } else if (angle >= 180 && angle < 270) { + return "up"; + } else { + return "right"; + } +} + +export function angleTo4Direction(angle) { + angle = (angle * THREE.Math.RAD2DEG + 180 + 45) % 360; + if (angle > 0 && angle < 90) { + return "north"; + } else if (angle >= 90 && angle < 180) { + return "west"; + } else if (angle >= 180 && angle < 270) { + return "south"; + } else { + return "east"; + } +} + +export function angleTo8Direction(angle) { + angle = (angle * THREE.Math.RAD2DEG + 180 + 45) % 360; + var direction = ""; + if ((angle >= 0 && angle < 120) || angle >= 330) { + direction += "north"; + } + if (angle >= 150 && angle < 300) { + direction += "south"; + } + if (angle >= 60 && angle < 210) { + direction += "west"; + } + if ((angle >= 240 && angle < 360) || angle < 30) { + direction += "east"; + } + return direction; +} diff --git a/templates/room.hbs b/templates/room.hbs index 8371574e69255d44343dd814a8ec0418d89971fa..5234c5de1181e98ed34618c75f1b18a343b01c0b 100644 --- a/templates/room.hbs +++ b/templates/room.hbs @@ -122,8 +122,6 @@ networked spawn-controller="radius: 4;" character-controller="pivot: #head" - wasd-dpad - dpad-as-axes="inputName:dpad; name:keyboard_dpad_axes; emitter: #left-hand" > <a-sphere scale="0.1 0.1 0.1"></a-sphere> @@ -149,22 +147,19 @@ id="left-hand" hand-controls2="left" tracked-controls - haptic-feedback="hand:left;" + haptic-feedback="hapticEventName: left_haptic_pulse;" vive-controls-extended=" - hand:left; - dpad_haptic_intensity: none; - dpad_deadzone: 0.6; + hand: left; + dpad_turbo: true; dpad_pressed_haptic_intensity: low" oculus-touch-controls-extended=" - dpad: true; - dpad_deadzone: 0.8; - dpad_livezone: 0.3; + dpad_enabled: true; dpad_directions: 8; dpad_turbo: true; dpad_haptic_intensity: none" dpad-as-axes=" - inputName:left_dpad; - name:left_dpad_axes; + dpadActionPrefix:left_dpad; + analog2dOutputAction:left_dpad_axes; emitter: #left-hand" teleport-controls="cameraRig: #player-rig; teleportOrigin: #head; button: action_teleport_" networked="template: #left-hand-template;" @@ -182,24 +177,16 @@ <a-entity id="right-hand" hand-controls2="right" - haptic-feedback="hand:right;" + haptic-feedback="hapticEventName: right_haptic_pulse;" vive-controls-extended=" hand:right; - dpad: true; + dpad_enabled: true; dpad_livezone: 1.0; dpad_deadzone: 0.6; - dpad_directions: 4; - dpad_turbo: false; - dpad_haptic_intensity: none; dpad_pressed_haptic_intensity: low;" oculus-touch-controls-extended=" hand:right; - dpad: true; - dpad_livezone: 0.3; - dpad_deadzone: 0.8; - dpad_directions: 4; - dpad_turbo: false; - dpad_haptic_intensity: none" + dpad_enabled: true;" teleport-controls="cameraRig: #player-rig; teleportOrigin: #head; hitEntity: #telepor-indicator;