diff --git a/src/components/hand-controls2.js b/src/components/hand-controls2.js index cdafd23c4379a6e8c1a87c5a1156a2d738e09c90..e2d7461d348422799895a087fc8cda984b141d47 100644 --- a/src/components/hand-controls2.js +++ b/src/components/hand-controls2.js @@ -1,3 +1,5 @@ +import { paths } from "../systems/userinput/paths"; + const POSES = { open: "open", point: "point", @@ -10,6 +12,8 @@ const POSES = { mrpDown: "mrpDown" }; +// TODO: If the hands or controllers are mispositioned, then rightHand.controllerPose and rightHand.pose +// should be bound differently. export const CONTROLLER_OFFSETS = { default: new THREE.Matrix4(), "oculus-touch-controls": new THREE.Matrix4().makeTranslation(0, -0.015, 0.04), @@ -29,160 +33,76 @@ export const CONTROLLER_OFFSETS = { }; /** - * Converts events from various 6DoF and 3DoF controllers into hand-pose events. + * Emits events indicating that avatar hands should be posed differently. * @namespace user-input * @component hand-controls2 */ AFRAME.registerComponent("hand-controls2", { schema: { default: "left" }, - init() { - const el = this.el; - - this.pose = POSES.open; - - this.fingersDown = { - thumb: false, - index: false, - middle: false, - ring: false, - pinky: false - }; - - this.onMiddleRingPinkyDown = this.updatePose.bind(this, { - middle: true, - ring: true, - pinky: true - }); - - this.onMiddleRingPinkyUp = this.updatePose.bind(this, { - middle: false, - ring: false, - pinky: false - }); - - this.onIndexDown = this.updatePose.bind(this, { - index: true - }); - - this.onIndexUp = this.updatePose.bind(this, { - index: false - }); - - this.onThumbDown = this.updatePose.bind(this, { - thumb: true - }); - - this.onThumbUp = this.updatePose.bind(this, { - thumb: false - }); - - this.onControllerConnected = this.onControllerConnected.bind(this); - this.onControllerDisconnected = this.onControllerDisconnected.bind(this); - - this.connectedController = null; - - el.addEventListener("controllerconnected", this.onControllerConnected); - el.addEventListener("controllerdisconnected", this.onControllerDisconnected); - - el.setAttribute("visible", false); - }, - - play() { - const el = this.el; - el.addEventListener("middle_ring_pinky_down", this.onMiddleRingPinkyDown); - el.addEventListener("middle_ring_pinky_up", this.onMiddleRingPinkyUp); - el.addEventListener("thumb_down", this.onThumbDown); - el.addEventListener("thumb_up", this.onThumbUp); - el.addEventListener("index_down", this.onIndexDown); - el.addEventListener("index_up", this.onIndexUp); + getControllerOffset() { + if (CONTROLLER_OFFSETS[this.connectedController] === undefined) { + return CONTROLLER_OFFSETS.default; + } + return CONTROLLER_OFFSETS[this.connectedController]; }, - pause() { - const el = this.el; - el.removeEventListener("middle_ring_pinky_down", this.onMiddleRingPinkyDown); - el.removeEventListener("middle_ring_pinky_up", this.onMiddleRingPinkyUp); - el.removeEventListener("thumb_down", this.onThumbDown); - el.removeEventListener("thumb_up", this.onThumbUp); - el.removeEventListener("index_down", this.onIndexDown); - el.removeEventListener("index_up", this.onIndexUp); + init() { + this.pose = POSES.open; + this.el.setAttribute("visible", false); }, - // Attach the platform specific tracked controllers. update(prevData) { - const el = this.el; const hand = this.data; const controlConfiguration = { hand: hand, - orientationOffset: { x: 0, y: 0, z: 0 } + orientationOffset: { x: 0, y: 0, z: 0 }, + model: false }; if (hand !== prevData) { - el.setAttribute("tracked-controls", controlConfiguration); - } - }, - - remove() { - const el = this.el; - el.removeEventListener("controllerconnected", this.onControllerConnected); - el.removeEventListener("controllerdisconnected", this.onControllerDisconnected); - }, - - updatePose(nextFingersDown) { - Object.assign(this.fingersDown, nextFingersDown); - const pose = this.determinePose(); - - if (pose !== this.pose) { - const previous = this.pose; - this.pose = pose; - this.el.emit("hand-pose", { previous: previous, current: this.pose }); + this.el.setAttribute("tracked-controls", controlConfiguration); + this.el.setAttribute("oculus-touch-controls", controlConfiguration); } }, - determinePose() { - const { thumb, index, middle, ring, pinky } = this.fingersDown; - - if (!thumb && !index && !middle && !ring && !pinky) { + poseForFingers(thumb, index, middleRingPinky) { + if (!thumb && !index && !middleRingPinky) { return POSES.open; - } else if (thumb && index && middle && ring && pinky) { + } else if (thumb && index && middleRingPinky) { return POSES.fist; - } else if (!thumb && index && middle && ring && pinky) { + } else if (!thumb && index && middleRingPinky) { return POSES.thumbUp; - } else if (!thumb && !index && middle && ring && pinky) { + } else if (!thumb && !index && middleRingPinky) { return POSES.mrpDown; - } else if (!thumb && index && !middle && !ring && !pinky) { + } else if (!thumb && index && !middleRingPinky) { return POSES.indexDown; - } else if (thumb && !index && !middle && !ring && !pinky) { + } else if (thumb && !index && !middleRingPinky) { return POSES.thumbDown; - } else if (thumb && index && !middle && !ring && !pinky) { + } else if (thumb && index && !middleRingPinky) { return POSES.pinch; - } else if (thumb && !index && middle && ring && pinky) { + } else if (thumb && !index && middleRingPinky) { return POSES.point; } - console.warn("Did not find matching pose for ", this.fingersDown); - + console.warn(`Did not find matching pose for thumb ${thumb}, index ${index}, middleRingPinky ${middleRingPinky}`); return POSES.open; }, - // Show controller when connected - onControllerConnected(e) { - this.connectedController = e.detail.name; - this.el.setAttribute("visible", true); - }, - - // Hide controller on disconnect - onControllerDisconnected() { - this.connectedController = null; - this.el.setAttribute("visible", false); - }, - - getControllerOffset() { - if (CONTROLLER_OFFSETS[this.connectedController] === undefined) { - return CONTROLLER_OFFSETS.default; + tick() { + const hand = this.data; + const userinput = AFRAME.scenes[0].systems.userinput; + const subpath = hand === "left" ? paths.actions.leftHand : paths.actions.rightHand; + const hasPose = userinput.readFrameValueAtPath(subpath.pose); + const thumb = userinput.readFrameValueAtPath(subpath.thumb); + const index = userinput.readFrameValueAtPath(subpath.index); + const middleRingPinky = userinput.readFrameValueAtPath(subpath.middleRingPinky); + const pose = this.poseForFingers(thumb, index, middleRingPinky); + if (pose !== this.pose) { + this.el.emit("hand-pose", { previous: this.pose, current: pose }); + this.pose = pose; } - - return CONTROLLER_OFFSETS[this.connectedController]; + this.el.setAttribute("visible", hasPose); } }); diff --git a/src/systems/userinput/bindings/oculus-touch-user.js b/src/systems/userinput/bindings/oculus-touch-user.js index d7e39357d5b835041f0209ea1bc369dda0f82540..d386016c27497b4c3faeae1fcc3d413f3a0476fd 100644 --- a/src/systems/userinput/bindings/oculus-touch-user.js +++ b/src/systems/userinput/bindings/oculus-touch-user.js @@ -57,6 +57,52 @@ const keyboardSnapLeft = `${name}/keyboard/snap-left`; export const oculusTouchUserBindings = { [sets.global]: [ + { + src: { + value: leftButton("grip").pressed + }, + dest: { + value: paths.actions.leftHand.middleRingPinky + }, + xform: xforms.copy + }, + { + src: [leftButton("x").touched, leftButton("y").touched, leftButton("thumbStick").touched], + dest: { + value: paths.actions.leftHand.thumb + }, + xform: xforms.any + }, + { + src: { value: leftButton("trigger").pressed }, + dest: { + value: paths.actions.leftHand.index + }, + xform: xforms.copy + }, + { + src: { + value: rightButton("grip").pressed + }, + dest: { + value: paths.actions.rightHand.middleRingPinky + }, + xform: xforms.copy + }, + { + src: [rightButton("x").touched, rightButton("y").touched, rightButton("thumbStick").touched], + dest: { + value: paths.actions.rightHand.thumb + }, + xform: xforms.any + }, + { + src: { value: rightButton("trigger").pressed }, + dest: { + value: paths.actions.rightHand.index + }, + xform: xforms.copy + }, { src: { value: paths.device.keyboard.key("b") diff --git a/src/systems/userinput/bindings/vive-user.js b/src/systems/userinput/bindings/vive-user.js index d276867e3c22d6ab4d3d5a9d303ec7bd815c6ae5..0e20233c7ff606ee29914e0d5293173404302491 100644 --- a/src/systems/userinput/bindings/vive-user.js +++ b/src/systems/userinput/bindings/vive-user.js @@ -118,6 +118,52 @@ const teleportRight = [ export const viveUserBindings = { [sets.global]: [ + { + src: { + value: lButton("grip").touched + }, + dest: { + value: paths.actions.leftHand.middleRingPinky + }, + xform: xforms.copy + }, + { + src: [lButton("touchpad").touched, lButton("top").touched], + dest: { + value: paths.actions.leftHand.thumb + }, + xform: xforms.any + }, + { + src: { value: lButton("trigger").pressed }, + dest: { + value: paths.actions.leftHand.index + }, + xform: xforms.copy + }, + { + src: { + value: rButton("grip").touched + }, + dest: { + value: paths.actions.rightHand.middleRingPinky + }, + xform: xforms.copy + }, + { + src: [rButton("touchpad").touched, rButton("top").touched], + dest: { + value: paths.actions.rightHand.thumb + }, + xform: xforms.any + }, + { + src: { value: rButton("trigger").pressed }, + dest: { + value: paths.actions.rightHand.index + }, + xform: xforms.copy + }, { src: { value: paths.device.keyboard.key("b") diff --git a/src/systems/userinput/paths.js b/src/systems/userinput/paths.js index 28a8fa9111c436eaeaeff1408e236143dfffc134..d4cc4994c7231a133d156ba116dfcf671464fb7a 100644 --- a/src/systems/userinput/paths.js +++ b/src/systems/userinput/paths.js @@ -42,6 +42,9 @@ paths.actions.rightHand.scalePenTip = "/actions/rightHandScalePenTip"; paths.actions.rightHand.startTeleport = "/actions/rightHandStartTeleport"; paths.actions.rightHand.stopTeleport = "/actions/rightHandStopTeleport"; paths.actions.rightHand.takeSnapshot = "/actions/rightHandTakeSnapshot"; +paths.actions.rightHand.thumb = "/actions/rightHand/thumbDown"; +paths.actions.rightHand.index = "/actions/rightHand/indexDown"; +paths.actions.rightHand.middleRingPinky = "/actions/rightHand/middleRingPinkyDown"; paths.actions.leftHand = {}; paths.actions.leftHand.pose = "/actions/leftHandPose"; paths.actions.leftHand.grab = "/actions/leftHandGrab"; @@ -55,6 +58,9 @@ paths.actions.leftHand.scalePenTip = "/actions/leftHandScalePenTip"; paths.actions.leftHand.startTeleport = "/actions/leftHandStartTeleport"; paths.actions.leftHand.stopTeleport = "/actions/leftHandStopTeleport"; paths.actions.leftHand.takeSnapshot = "/actions/leftHandTakeSnapshot"; +paths.actions.leftHand.thumb = "/actions/leftHand/thumbDown"; +paths.actions.leftHand.index = "/actions/leftHand/indexDown"; +paths.actions.leftHand.middleRingPinky = "/actions/leftHand/middleRingPinkyDown"; paths.device = {}; paths.device.mouse = {};