From c153dd32090354347282687b9dde09c71d9297a3 Mon Sep 17 00:00:00 2001 From: johnshaughnessy <johnfshaughnessy@gmail.com> Date: Thu, 1 Nov 2018 09:47:05 -0700 Subject: [PATCH] Change priority resolution --- src/components/pitch-yaw-rotator.js | 4 +- .../userinput/bindings/daydream-user.js | 5 +- .../userinput/bindings/keyboard-debugging.js | 5 +- .../userinput/bindings/keyboard-mouse-user.js | 6 +- .../userinput/bindings/oculus-go-user.js | 5 +- .../userinput/bindings/oculus-touch-user.js | 5 +- .../userinput/bindings/touchscreen-user.js | 5 +- src/systems/userinput/bindings/utils.js | 11 ++ src/systems/userinput/bindings/vive-user.js | 5 +- .../bindings/xbox-controller-user.js | 5 +- src/systems/userinput/userinput.js | 187 +++++++++++++++--- 11 files changed, 197 insertions(+), 46 deletions(-) create mode 100644 src/systems/userinput/bindings/utils.js diff --git a/src/components/pitch-yaw-rotator.js b/src/components/pitch-yaw-rotator.js index a2c2ebdea..d3a400905 100644 --- a/src/components/pitch-yaw-rotator.js +++ b/src/components/pitch-yaw-rotator.js @@ -5,8 +5,8 @@ const radToDeg = THREE.Math.radToDeg; AFRAME.registerComponent("pitch-yaw-rotator", { schema: { - minPitch: { default: -50 }, - maxPitch: { default: 50 } + minPitch: { default: -65 }, + maxPitch: { default: 65 } }, init() { diff --git a/src/systems/userinput/bindings/daydream-user.js b/src/systems/userinput/bindings/daydream-user.js index e2cb60984..61526d9ee 100644 --- a/src/systems/userinput/bindings/daydream-user.js +++ b/src/systems/userinput/bindings/daydream-user.js @@ -1,6 +1,7 @@ import { paths } from "../paths"; import { sets } from "../sets"; import { xforms } from "./xforms"; +import { addSetsToBindings } from "./utils"; // vars const v = s => `/vars/daydream/${s}`; @@ -53,7 +54,7 @@ const dropOnCenterOrSouth = [ } ]; -export const daydreamUserBindings = { +export const daydreamUserBindings = addSetsToBindings({ [sets.global]: [ { src: { @@ -262,4 +263,4 @@ export const daydreamUserBindings = { }, ...dropOnCenterOrSouth ] -}; +}); diff --git a/src/systems/userinput/bindings/keyboard-debugging.js b/src/systems/userinput/bindings/keyboard-debugging.js index d1142ee33..0abcefb21 100644 --- a/src/systems/userinput/bindings/keyboard-debugging.js +++ b/src/systems/userinput/bindings/keyboard-debugging.js @@ -1,8 +1,9 @@ import { paths } from "../paths"; import { sets } from "../sets"; import { xforms } from "./xforms"; +import { addSetsToBindings } from "./utils"; -export const keyboardDebuggingBindings = { +export const keyboardDebuggingBindings = addSetsToBindings({ [sets.global]: [ { src: { @@ -14,4 +15,4 @@ export const keyboardDebuggingBindings = { xform: xforms.rising } ] -}; +}); diff --git a/src/systems/userinput/bindings/keyboard-mouse-user.js b/src/systems/userinput/bindings/keyboard-mouse-user.js index 12e3b3e4f..b42e5a165 100644 --- a/src/systems/userinput/bindings/keyboard-mouse-user.js +++ b/src/systems/userinput/bindings/keyboard-mouse-user.js @@ -1,6 +1,7 @@ import { paths } from "../paths"; import { sets } from "../sets"; import { xforms } from "./xforms"; +import { addSetsToBindings } from "./utils"; const wasd_vec2 = "/var/mouse-and-keyboard/wasd_vec2"; const keyboardCharacterAcceleration = "/var/mouse-and-keyboard/keyboardCharacterAcceleration"; @@ -28,7 +29,7 @@ const dropWithRMBorEscBindings = [ } ]; -export const keyboardMouseUserBindings = { +export const keyboardMouseUserBindings = addSetsToBindings({ [sets.global]: [ { src: { @@ -258,6 +259,7 @@ export const keyboardMouseUserBindings = { { src: { value: paths.device.mouse.buttonLeft }, xform: xforms.noop, + dest: { value: paths.noop }, priority: 200, root: "lmb" }, @@ -310,4 +312,4 @@ export const keyboardMouseUserBindings = { xform: xforms.rising } ] -}; +}); diff --git a/src/systems/userinput/bindings/oculus-go-user.js b/src/systems/userinput/bindings/oculus-go-user.js index c0ec9199a..15c4604fa 100644 --- a/src/systems/userinput/bindings/oculus-go-user.js +++ b/src/systems/userinput/bindings/oculus-go-user.js @@ -1,6 +1,7 @@ import { paths } from "../paths"; import { sets } from "../sets"; import { xforms } from "./xforms"; +import { addSetsToBindings } from "./utils"; const touchpad = "/vars/oculusgo/touchpad"; const touchpadPressed = "/vars/oculusgo/touchpadPressed"; @@ -25,7 +26,7 @@ const grabBinding = { priority: 200 }; -export const oculusGoUserBindings = { +export const oculusGoUserBindings = addSetsToBindings({ [sets.global]: [ { src: { @@ -241,4 +242,4 @@ export const oculusGoUserBindings = { xform: xforms.copyIfTrue } ] -}; +}); diff --git a/src/systems/userinput/bindings/oculus-touch-user.js b/src/systems/userinput/bindings/oculus-touch-user.js index 1d557129c..4688dac41 100644 --- a/src/systems/userinput/bindings/oculus-touch-user.js +++ b/src/systems/userinput/bindings/oculus-touch-user.js @@ -1,6 +1,7 @@ import { paths } from "../paths"; import { sets } from "../sets"; import { xforms } from "./xforms"; +import { addSetsToBindings } from "./utils"; const name = "/touch/var/"; @@ -58,7 +59,7 @@ const rightTouchSnapLeft = `${name}/right/snap-left`; const keyboardSnapRight = `${name}/keyboard/snap-right`; const keyboardSnapLeft = `${name}/keyboard/snap-left`; -export const oculusTouchUserBindings = { +export const oculusTouchUserBindings = addSetsToBindings({ [sets.global]: [ { src: { @@ -665,4 +666,4 @@ export const oculusTouchUserBindings = { ], [sets.rightHandHoveringOnNothing]: [] -}; +}); diff --git a/src/systems/userinput/bindings/touchscreen-user.js b/src/systems/userinput/bindings/touchscreen-user.js index 41503259f..02c8d833c 100644 --- a/src/systems/userinput/bindings/touchscreen-user.js +++ b/src/systems/userinput/bindings/touchscreen-user.js @@ -1,6 +1,7 @@ import { paths } from "../paths"; import { sets } from "../sets"; import { xforms } from "./xforms"; +import { addSetsToBindings } from "./utils"; const zero = "/vars/touchscreen/zero"; const forward = "/vars/touchscreen/pinchDeltaForward"; @@ -13,7 +14,7 @@ const gyroCamDelta = "vars/gyro/gyroCameraDelta"; const gyroCamDeltaXScaled = "vars/gyro/gyroCameraDelta/x/scaled"; const gyroCamDeltaYScaled = "vars/gyro/gyroCameraDelta/y/scaled"; -export const touchscreenUserBindings = { +export const touchscreenUserBindings = addSetsToBindings({ [sets.global]: [ { src: { value: paths.device.touchscreen.pinch.delta }, @@ -129,4 +130,4 @@ export const touchscreenUserBindings = { priority: 200 } ] -}; +}); diff --git a/src/systems/userinput/bindings/utils.js b/src/systems/userinput/bindings/utils.js new file mode 100644 index 000000000..67559c1a6 --- /dev/null +++ b/src/systems/userinput/bindings/utils.js @@ -0,0 +1,11 @@ +export const addSetsToBindings = mapping => { + for (const setName in mapping) { + for (const binding of mapping[setName]) { + if (!binding.sets) { + binding.sets = new Set(); + } + binding.sets.add(setName); + } + } + return mapping; +}; diff --git a/src/systems/userinput/bindings/vive-user.js b/src/systems/userinput/bindings/vive-user.js index 399544384..8a47985e8 100644 --- a/src/systems/userinput/bindings/vive-user.js +++ b/src/systems/userinput/bindings/vive-user.js @@ -1,6 +1,7 @@ import { paths } from "../paths"; import { sets } from "../sets"; import { xforms } from "./xforms"; +import { addSetsToBindings } from "./utils"; const v = name => { return `/vive-user/vive-var/${name}`; @@ -119,7 +120,7 @@ const teleportRight = [ } ]; -export const viveUserBindings = { +export const viveUserBindings = addSetsToBindings({ [sets.global]: [ { src: { @@ -806,4 +807,4 @@ export const viveUserBindings = { priority: 400 } ] -}; +}); diff --git a/src/systems/userinput/bindings/xbox-controller-user.js b/src/systems/userinput/bindings/xbox-controller-user.js index b9d230a79..67699c539 100644 --- a/src/systems/userinput/bindings/xbox-controller-user.js +++ b/src/systems/userinput/bindings/xbox-controller-user.js @@ -1,6 +1,7 @@ import { paths } from "../paths"; import { sets } from "../sets"; import { xforms } from "./xforms"; +import { addSetsToBindings } from "./utils"; const xboxUnscaledCursorScalePenTip = "foobarbazbotbooch"; @@ -8,7 +9,7 @@ const button = paths.device.xbox.button; const axis = paths.device.xbox.axis; const rightTriggerFalling = "/vars/xbox/rightTriggerFalling"; -export const xboxControllerUserBindings = { +export const xboxControllerUserBindings = addSetsToBindings({ [sets.cursorHoldingInteractable]: [ { src: { value: button("rightTrigger").pressed }, @@ -187,4 +188,4 @@ export const xboxControllerUserBindings = { priority: 100 } ] -}; +}); diff --git a/src/systems/userinput/userinput.js b/src/systems/userinput/userinput.js index 5460b7769..1ac910e9e 100644 --- a/src/systems/userinput/userinput.js +++ b/src/systems/userinput/userinput.js @@ -26,32 +26,32 @@ import { resolveActionSets } from "./resolve-action-sets"; import { GamepadDevice } from "./devices/gamepad"; import { gamepadBindings } from "./bindings/generic-gamepad"; -const priorityMap = new Map(); -function prioritizeBindings(registeredMappings, activeSets) { - const activeBindings = new Set(); - priorityMap.clear(); +function buildMap(registeredMappings) { + const map = new Map(); + const add = (path, binding) => { + if (!map.has(path)) { + map.set(path, [binding]); + } else { + map.get(path).push(binding); + } + }; for (const mapping of registeredMappings) { for (const setName in mapping) { - if (!activeSets.has(setName) || !mapping[setName]) continue; for (const binding of mapping[setName]) { - const { root, priority } = binding; - const prevBinding = priorityMap.get(root); - if (!root || !priority) { - activeBindings.add(binding); - } else if (!prevBinding) { - activeBindings.add(binding); - priorityMap.set(root, binding); - } else if (priority > prevBinding.priority) { - activeBindings.delete(priorityMap.get(root)); - activeBindings.add(binding); - priorityMap.set(root, binding); - } else if (prevBinding.priority === priority) { - console.error("equal priorities on same root", binding, priorityMap.get(root)); + if (Array.isArray(binding.src)) { + for (const path of binding.src) { + add(path, binding); + } + } else { + for (const srcKey in binding.src) { + const path = binding.src[srcKey]; + add(path, binding); + } } } } } - return activeBindings; + return map; } AFRAME.registerSystem("userinput", { @@ -71,6 +71,7 @@ AFRAME.registerSystem("userinput", { this.activeDevices = new Set([new MouseDevice(), new AppAwareMouseDevice(), new KeyboardDevice(), new HudDevice()]); this.registeredMappings = new Set([keyboardDebuggingBindings]); + this.map = buildMap(this.registeredMappings); this.xformStates = new Map(); const appAwareTouchscreenDevice = new AppAwareTouchscreenDevice(); @@ -91,6 +92,7 @@ AFRAME.registerSystem("userinput", { this.registeredMappings.add(keyboardMouseUserBindings); } } + this.map = buildMap(this.registeredMappings); }; this.el.sceneEl.addEventListener("enter-vr", updateBindingsForVRMode); this.el.sceneEl.addEventListener("exit-vr", updateBindingsForVRMode); @@ -127,6 +129,7 @@ AFRAME.registerSystem("userinput", { this.registeredMappings.add(gamepadBindings); } this.activeDevices.add(gamepadDevice); + this.map = buildMap(this.registeredMappings); }, false ); @@ -136,6 +139,7 @@ AFRAME.registerSystem("userinput", { for (const device of this.activeDevices) { if (device.gamepad === e.gamepad) { this.activeDevices.delete(device); + this.map = buildMap(this.registeredMappings); return; } } @@ -150,16 +154,73 @@ AFRAME.registerSystem("userinput", { for (const { set, value } of this.pendingSetChanges) { this.activeSets[value ? "add" : "delete"](set); } - this.pendingSetChanges.length = 0; + let runners = this.pendingSetChanges.length ? [] : this.runners; + if (this.pendingSetChanges.length) { + this.pendingSetChanges.length = 0; + this.actives = []; + for (const mapping of this.registeredMappings) { + for (const setName in mapping) { + if (!this.activeSets.has(setName) || !mapping[setName]) continue; + for (const binding of mapping[setName]) { + let active = false; + for (const set of binding.sets) { + if (this.activeSets.has(set)) { + active = true; + } + } + this.actives.push(active); + runners.push(binding); + } + } + } + + const maxAmongActive = (path, map) => { + let max = -1; + const bindings = map.get(path); + if (!bindings) { + return -1; + } + for (const binding of bindings) { + let active = false; + for (const set of binding.sets) { + if (this.activeSets.has(set)) { + active = true; + } + } + if (active && binding.priority && binding.priority > max) { + max = binding.priority; + } + } + return max; + }; + + for (const i in runners) { + if (!this.actives[i]) continue; + const binding = runners[i]; + let active = true; + for (const p in binding.src) { + const path = binding.src[p]; + let subpaths = String.split(path, "/"); + while (binding.priority && subpaths.length) { + if (binding.priority < maxAmongActive(Array.join(subpaths, "/"), this.map, this.activeSets)) { + active = false; + } + subpaths.pop(); + } + this.actives[i] = active; + } + } + } this.frame = {}; for (const device of this.activeDevices) { device.write(this.frame); } - const activeBindings = prioritizeBindings(this.registeredMappings, this.activeSets); - for (const binding of activeBindings) { - const bindingExistedLastFrame = this.activeBindings && this.activeBindings.has(binding); + for (const i in runners) { + const binding = runners[i]; + if (!this.actives[i]) continue; + const bindingExistedLastFrame = this.runners && this.runners.includes(binding); if (!bindingExistedLastFrame) { this.xformStates.delete(binding); } @@ -171,14 +232,84 @@ AFRAME.registerSystem("userinput", { } } - this.activeBindings = activeBindings; + this.runners = runners; if (this.frame[paths.actions.logDebugFrame] || this.frame[paths.actions.log]) { - console.log("frame", this.frame); - console.log("sets", this.activeSets); - console.log("bindings", this.activeBindings); - console.log("devices", this.activeDevices); + const line = "__________________________________________________________________"; + const bindingToString = b => { + let sb = []; + sb.push(" "); + sb.push("src: "); + sb.push("\n"); + for (const s of Object.keys(b.src)) { + sb.push(" "); + sb.push(" "); + sb.push(s); + sb.push(" : "); + sb.push(b.src[s]); + sb.push("\n"); + } + sb.push(" "); + sb.push("dest: "); + sb.push("\n"); + for (const s of Object.keys(b.dest)) { + sb.push(" "); + sb.push(" "); + sb.push(s); + sb.push(" : "); + sb.push(b.dest[s]); + sb.push("\n"); + } + sb.push(" "); + sb.push("priority"); + sb.push(" : "); + sb.push(b.priority || 0); + for (const s of b.sets) { + sb.push("\n"); + sb.push(" "); + sb.push("in set"); + sb.push(" : "); + sb.push(s); + sb.push("\n"); + } + sb.push(line); + sb.push("\n"); + return sb.join(""); + }; + let sb = []; + sb.push("\n"); + sb.push(line); + sb.push("\n"); + sb.push("actives:"); + sb.push("\n"); + sb.push(line); + sb.push("\n"); + for (let i = 0; i < this.runners.length; i++) { + if (this.actives[i]) { + sb.push(bindingToString(this.runners[i])); + } + } + sb.push("\n"); + sb.push(line); + sb.push("\n"); + sb.push("inactives:"); + sb.push("\n"); + sb.push(line); + sb.push("\n"); + for (let i = 0; i < this.runners.length; i++) { + if (!this.actives[i]) { + sb.push(bindingToString(this.runners[i])); + } + } + console.log("active and inactive bindings"); + console.log(sb.join("")); + console.log("runners", this.runners); + console.log("actives", this.actives); console.log("xformStates", this.xformStates); + console.log("devices", this.activeDevices); + console.log("map", this.map); + console.log("activeSets", this.activeSets); + console.log("frame", this.frame); } } }); -- GitLab