From 6a399594c31a02693486b6ff35ffd6bc51c21c3b Mon Sep 17 00:00:00 2001 From: Kevin Lee <kevin@infinite-lee.com> Date: Wed, 18 Apr 2018 18:50:09 -0700 Subject: [PATCH] Adding cursor-controller. Mostly feature complete with a few bugs. Still WIP. --- src/components/cursor-controller.js | 337 ++++++++++++++++++++++++++++ src/components/event-repeater.js | 2 +- src/components/super-cursor.js | 168 -------------- src/components/super-spawner.js | 7 +- src/hub.html | 69 +++--- src/hub.js | 3 +- src/input-mappings.js | 44 ++-- 7 files changed, 402 insertions(+), 228 deletions(-) create mode 100644 src/components/cursor-controller.js delete mode 100644 src/components/super-cursor.js diff --git a/src/components/cursor-controller.js b/src/components/cursor-controller.js new file mode 100644 index 000000000..345ccb1fb --- /dev/null +++ b/src/components/cursor-controller.js @@ -0,0 +1,337 @@ +const TARGET_TYPE_NONE = 1; +const TARGET_TYPE_INTERACTABLE = 2; +const TARGET_TYPE_UI = 4; +const TARGET_TYPE_OTHER = 8; +const TARGET_TYPE_INTERACTABLE_OR_UI = TARGET_TYPE_INTERACTABLE | TARGET_TYPE_UI; + +AFRAME.registerComponent("cursor-controller", { + dependencies: ["raycaster", "line"], + schema: { + cursor: { type: "selector" }, + camera: { type: "selector" }, + controller: { type: "selector" }, + playerRig: { type: "selector" }, + otherHand: { type: "string" }, + hand: { default: "right" }, + trackedControls: { type: "selectorAll", default: "[tracked-controls]" }, + maxDistance: { default: 3 }, + minDistance: { default: 0.5 }, + cursorColorHovered: { default: "#FF0000" }, + cursorColorUnhovered: { efault: "#FFFFFF" }, + controllerEvent: { type: "string", default: "action_primary_down" }, + controllerEndEvent: { type: "string", default: "action_primary_up" }, + teleportEvent: { type: "string", default: "action_teleport_down" }, + teleportEndEvent: { type: "string", default: "action_teleport_up" } + }, + + init: function() { + this.inVR = false; + this.isMobile = AFRAME.utils.device.isMobile(); + this.trackedControls = []; + this.hasPointingDevice = false; + this.currentTargetType = TARGET_TYPE_NONE; + this.isGrabbing = false; + this.wasOtherHandGrabbing = false; + this.wasIntersecting = false; + this.currentDistance = this.data.maxDistance; + this.currentDistanceMod = 0; + this.origin = new THREE.Vector3(); + this.direction = new THREE.Vector3(); + this.point = new THREE.Vector3(); + this.mousePos = new THREE.Vector2(); + this.controllerQuaternion = new THREE.Quaternion(); + + this.data.cursor.setAttribute("material", { color: this.data.cursorColorUnhovered }); + + this.mouseDownListener = this._handleMouseDown.bind(this); + this.mouseMoveListener = this._handleMouseMove.bind(this); + this.mouseUpListener = this._handleMouseUp.bind(this); + this.wheelListener = this._handleWheel.bind(this); + + this.enterVRListener = this._handleEnterVR.bind(this); + this.exitVRListener = this._handleExitVR.bind(this); + + this.raycasterIntersectionListener = this._handleRaycasterIntersection.bind(this); + this.raycasterIntersectionClearedListener = this._handleRaycasterIntersectionCleared.bind(this); + + this.controllerEventListener = this._handleControllerEvent.bind(this); + this.controllerEndEventListener = this._handleControllerEndEvent.bind(this); + + this.modelLoadedListener = this._handleModelLoaded.bind(this); + }, + + update: function(oldData) { + if (this.data.controller !== oldData.controller) { + if (oldData.controller) { + oldData.controller.removeEventListener(this.data.controllerEvent, this.controllerEventListener); + oldData.controller.removeEventListener(this.data.controllerEndEvent, this.controllerEndEventListener); + } + + this.data.controller.addEventListener(this.data.controllerEvent, this.controllerEventListener); + this.data.controller.addEventListener(this.data.controllerEndEvent, this.controllerEndEventListener); + } + + if (oldData.otherHand && this.data.otherHand !== oldData.otherHand) { + this._handleModelLoaded(); + } + }, + + play: function() { + document.addEventListener("mousedown", this.mouseDownListener); + document.addEventListener("mousemove", this.mouseMoveListener); + document.addEventListener("mouseup", this.mouseUpListener); + document.addEventListener("wheel", this.wheelListener); + + window.addEventListener("enter-vr", this.enterVRListener); + window.addEventListener("exit-vr", this.exitVRListener); + + this.el.addEventListener("raycaster-intersection", this.raycasterIntersectionListener); + this.el.addEventListener("raycaster-intersection-cleared", this.raycasterIntersectionClearedListener); + + this.data.playerRig.addEventListener("model-loaded", this.modelLoadedListener); + + //TODO: separate this into its own component? Or find an existing component that does this better. + this.checkForPointingDeviceInterval = setInterval(() => { + const controller = this._getController(); + if (this.hasPointingDevice != !!controller) { + this.el.setAttribute("line", { visible: !!controller }); + } + this.hasPointingDevice = !!controller; + if (controller && this.data.hand != controller.hand) { + this.el.setAttribute("cursor-controller", { + hand: controller.hand, + controller: `#player-${controller.hand}-controller`, + otherHand: `#${controller.hand}-super-hand` + }); + } + }, 1000); + }, + + pause: function() { + document.removeEventListener("mousedown", this.mouseDownListener); + document.removeEventListener("mousemove", this.mouseMoveListener); + document.removeEventListener("mouseup", this.mouseUpListener); + document.removeEventListener("wheel", this.wheelListener); + + window.removeEventListener("enter-vr", this.enterVRListener); + window.removeEventListener("exit-vr", this.exitVRListener); + + this.el.removeEventListener("raycaster-intersection", this.raycasterIntersectionListener); + this.el.removeEventListener("raycaster-intersection-cleared", this.raycasterIntersectionClearedListener); + + this.data.controller.removeEventListener(this.data.controllerEvent, this.controllerEventListener); + this.data.controller.removeEventListener(this.data.controllerEndEvent, this.controllerEndEventListener); + + this.data.playerRig.removeEventListener("model-loaded", this.modelLoadedListener); + + clearInterval(this.checkForPointingDeviceInterval); + }, + + tick: function() { + this.isGrabbing = this.data.cursor.components["super-hands"].state.has("grab-start"); + + if (this.otherHand) { + const state = this.otherHand.components["super-hands"].state; + const isOtherHandGrabbing = state.has("grab-start") || state.has("hover-start"); + if (this.wasOtherHandGrabbing != isOtherHandGrabbing) { + this.data.cursor.setAttribute("visible", !isOtherHandGrabbing); + } + this.wasOtherHandGrabbing = isOtherHandGrabbing; + } + + if (this.wasOtherHandGrabbing) return; + + const camera = this.data.camera.components.camera.camera; + if (!this.inVR && !this.isMobile) { + //mouse + const raycaster = this.el.components.raycaster.raycaster; + raycaster.setFromCamera(this.mousePos, camera); + this.origin = raycaster.ray.origin; + this.direction = raycaster.ray.direction; + } else if ((this.inVR || this.isMobile) && !this.hasPointingDevice) { + //gaze + camera.getWorldPosition(this.origin); + camera.getWorldDirection(this.direction); + } else { + //3d + this.data.controller.object3D.getWorldPosition(this.origin); + this.data.controller.object3D.getWorldQuaternion(this.controllerQuaternion); + this.direction + .set(0, 0, -1) + .applyQuaternion(this.controllerQuaternion) + .normalize(); + } + + this.el.setAttribute("raycaster", { origin: this.origin, direction: this.direction }); + + let intersection = null; + + if (!this.isGrabbing) { + const intersections = this.el.components.raycaster.intersections; + if (intersections.length > 0 && intersections[0].distance <= this.data.maxDistance) { + intersection = intersections[0]; + this.data.cursor.object3D.position.copy(intersection.point); + this.currentDistance = intersections[0].distance; + this.currentDistanceMod = 0; + } else { + this.currentDistance = this.data.maxDistance; + } + } + + if (this.isGrabbing || !intersection) { + const distance = Math.min( + Math.max(this.data.minDistance, this.currentDistance - this.currentDistanceMod), + this.data.maxDistance + ); + this.currentDistanceMod = this.currentDistance - distance; + this.direction.multiplyScalar(distance); + this.point.addVectors(this.origin, this.direction); + this.data.cursor.object3D.position.copy(this.point); + } + + if (intersection) { + if (this._isInteractableAllowed() && this._isClass("interactable", intersection.object.el)) { + this.currentTargetType = TARGET_TYPE_INTERACTABLE; + } else if (this._isClass("ui", intersection.object.el)) { + this.currentTargetType = TARGET_TYPE_UI; + } + } else { + this.currentTargetType = TARGET_TYPE_NONE; + } + + const isTarget = this._isTargetOfType(TARGET_TYPE_INTERACTABLE_OR_UI); + if ((this.isGrabbing || isTarget) && !this.wasIntersecting) { + this.wasIntersecting = true; + this.data.cursor.setAttribute("material", { color: this.data.cursorColorHovered }); + } else if (!this.isGrabbing && !isTarget && this.wasIntersecting) { + this.wasIntersecting = false; + this.data.cursor.setAttribute("material", { color: this.data.cursorColorUnhovered }); + } + + if (this.hasPointingDevice) { + this.el.setAttribute("line", { start: this.origin.clone(), end: this.data.cursor.object3D.position.clone() }); + } + }, + + _isClass: function(className, el) { + return ( + el.className === className || + (el.parentNode && el.parentNode != el.sceneEl && this._isClass(className, el.parentNode)) + ); + }, + + _isInteractableAllowed: function() { + return !(this.inVR && this.hasPointingDevice) || this.isMobile; + }, + + _isTargetOfType: function(mask) { + return (this.currentTargetType & mask) === this.currentTargetType; + }, + + _getController: function() { + //TODO: prefer initial hand set in data.hand + for (let i = this.data.trackedControls.length - 1; i >= 0; i--) { + const trackedControlsComponent = this.data.trackedControls[i].components["tracked-controls"]; + if (trackedControlsComponent && trackedControlsComponent.controller) { + return trackedControlsComponent.controller; + } + } + return null; + }, + + _startTeleport: function() { + this.data.controller.emit(this.data.teleportEvent, {}); + this.el.setAttribute("line", { visible: false }); + this.data.cursor.setAttribute("visible", false); + }, + + _endTeleport: function() { + this.data.controller.emit(this.data.teleportEndEvent, {}); + this.el.setAttribute("line", { visible: true }); + this.data.cursor.setAttribute("visible", true); + }, + + _handleMouseDown: function() { + if (this._isTargetOfType(TARGET_TYPE_INTERACTABLE)) { + const lookControls = this.data.camera.components["look-controls"]; + if (lookControls) lookControls.pause(); + this.data.cursor.emit(this.data.controllerEvent, {}); + } else if (this.inVR && this.hasPointingDevice) { + this._startTeleport(); + } + }, + + _handleMouseMove: function(e) { + this.mousePos.set(e.clientX / window.innerWidth * 2 - 1, -(e.clientY / window.innerHeight) * 2 + 1); + }, + + _handleMouseUp: function() { + const lookControls = this.data.camera.components["look-controls"]; + if (lookControls) lookControls.play(); + this.data.cursor.emit(this.data.controllerEndEvent, {}); + if (this.inVR && this.hasPointingDevice) { + this._endTeleport(); + } + }, + + _handleWheel: function(e) { + if (this.isGrabbing) { + switch (e.deltaMode) { + case e.DOM_DELTA_PIXEL: + this.currentDistanceMod += e.deltaY / 500; + break; + case e.DOM_DELTA_LINE: + this.currentDistanceMod += e.deltaY / 10; + break; + case e.DOM_DELTA_PAGE: + this.currentDistanceMod += e.deltaY / 2; + break; + } + } + }, + + _handleEnterVR: function() { + if (AFRAME.utils.device.checkHeadsetConnected()) { + this.inVR = true; + } + }, + + _handleExitVR: function() { + this.inVR = false; + }, + + _handleRaycasterIntersection: function(e) { + this.data.cursor.emit("raycaster-intersection", e.detail); + }, + + _handleRaycasterIntersectionCleared: function(e) { + this.data.cursor.emit("raycaster-intersection-cleared", e.detail); + }, + + _handleControllerEvent: function(e) { + switch (this.currentTargetType) { + case TARGET_TYPE_INTERACTABLE: + if (!this._isInteractableAllowed()) { + break; + } + case TARGET_TYPE_UI: + this.data.cursor.emit(this.data.controllerEvent, e.detail); + break; + default: + this._startTeleport(); + break; + } + }, + + _handleControllerEndEvent: function(e) { + if (this.isGrabbing || this._isTargetOfType(TARGET_TYPE_UI)) { + this.data.cursor.emit(this.data.controllerEndEvent, e.detail); + } else { + this._endTeleport(); + } + }, + + _handleModelLoaded: function() { + this.otherHand = this.data.playerRig.querySelector(this.data.otherHand); + } +}); diff --git a/src/components/event-repeater.js b/src/components/event-repeater.js index 64e287206..eed848d26 100644 --- a/src/components/event-repeater.js +++ b/src/components/event-repeater.js @@ -24,6 +24,6 @@ AFRAME.registerComponent("event-repeater", { }, _handleEvent: function(event, e) { - this.el.emit(event, e.details); + this.el.emit(event, e.detail ? e.detail : {}); } }); diff --git a/src/components/super-cursor.js b/src/components/super-cursor.js deleted file mode 100644 index ee70e9606..000000000 --- a/src/components/super-cursor.js +++ /dev/null @@ -1,168 +0,0 @@ -AFRAME.registerComponent("super-cursor", { - dependencies: ["raycaster"], - schema: { - cursor: { type: "selector" }, - camera: { type: "selector" }, - maxDistance: { default: 3 }, - minDistance: { default: 0.5 }, - cursorColorHovered: { default: "#FF0000" }, - cursorColorUnhovered: { efault: "#FFFFFF" } - }, - - init: function() { - this.isGrabbing = false; - this.isInteractable = false; - this.wasIntersecting = false; - this.currentDistance = this.data.maxDistance; - this.currentDistanceMod = 0; - this.enabled = true; - this.origin = new THREE.Vector3(); - this.direction = new THREE.Vector3(); - this.point = new THREE.Vector3(); - this.mousePos = new THREE.Vector2(); - - this.data.cursor.setAttribute("material", { color: this.data.cursorColorUnhovered }); - - this.mouseDownListener = this._handleMouseDown.bind(this); - this.mouseMoveListener = this._handleMouseMove.bind(this); - this.mouseUpListener = this._handleMouseUp.bind(this); - this.wheelListener = this._handleWheel.bind(this); - this.enterVRListener = this._handleEnterVR.bind(this); - this.exitVRListener = this._handleExitVR.bind(this); - }, - - play: function() { - document.addEventListener("mousedown", this.mouseDownListener); - document.addEventListener("mousemove", this.mouseMoveListener); - document.addEventListener("mouseup", this.mouseUpListener); - document.addEventListener("wheel", this.wheelListener); - window.addEventListener("enter-vr", this.enterVRListener); - window.addEventListener("exit-vr", this.exitVRListener); - - this._enable(); - }, - - pause: function() { - document.removeEventListener("mousedown", this.mouseDownListener); - document.removeEventListener("mousemove", this.mouseMoveListener); - document.removeEventListener("mouseup", this.mouseUpListener); - document.removeEventListener("wheel", this.wheelListener); - window.removeEventListener("enter-vr", this.enterVRListener); - window.removeEventListener("exit-vr", this.exitVRListener); - - this._disable(); - }, - - tick: function() { - if (!this.enabled) { - return; - } - - this.isGrabbing = this.data.cursor.components["super-hands"].state.has("grab-start"); - - const camera = this.data.camera.components.camera.camera; - const raycaster = this.el.components.raycaster.raycaster; - raycaster.setFromCamera(this.mousePos, camera); - this.origin = raycaster.ray.origin; - this.direction = raycaster.ray.direction; - this.el.setAttribute("raycaster", { origin: this.origin, direction: this.direction }); - - let intersection = null; - - if (!this.isGrabbing) { - const intersections = this.el.components.raycaster.intersections; - if (intersections.length > 0 && intersections[0].distance <= this.data.maxDistance) { - intersection = intersections[0]; - this.data.cursor.object3D.position.copy(intersection.point); - this.currentDistance = intersections[0].distance; - this.currentDistanceMod = 0; - } else { - this.currentDistance = this.data.maxDistance; - } - } - - if (this.isGrabbing || !intersection) { - const distance = Math.min( - Math.max(this.data.minDistance, this.currentDistance - this.currentDistanceMod), - this.data.maxDistance - ); - this.currentDistanceMod = this.currentDistance - distance; - this.direction.multiplyScalar(distance); - this.point.addVectors(this.origin, this.direction); - this.data.cursor.object3D.position.copy(this.point); - } - - this.isInteractable = intersection && this._isInteractable(intersection.object.el); - - if ((this.isGrabbing || this.isInteractable) && !this.wasIntersecting) { - this.wasIntersecting = true; - this.data.cursor.setAttribute("material", { color: this.data.cursorColorHovered }); - } else if (!this.isGrabbing && !this.isInteractable && this.wasIntersecting) { - this.wasIntersecting = false; - this.data.cursor.setAttribute("material", { color: this.data.cursorColorUnhovered }); - } - }, - - _isInteractable: function(el) { - return ( - el.className === "interactable" || - (el.parentNode && el.parentNode != el.sceneEl && this._isInteractable(el.parentNode)) - ); - }, - - _handleMouseDown: function() { - if (this.isInteractable) { - const lookControls = this.data.camera.components["look-controls"]; - if (lookControls) lookControls.pause(); - } - this.data.cursor.emit("action_grab", {}); - }, - - _handleMouseMove: function(e) { - this.mousePos.set(e.clientX / window.innerWidth * 2 - 1, -(e.clientY / window.innerHeight) * 2 + 1); - }, - - _handleMouseUp: function() { - const lookControls = this.data.camera.components["look-controls"]; - if (lookControls) lookControls.play(); - this.data.cursor.emit("action_release", {}); - }, - - _handleWheel: function(e) { - if (this.isGrabbing) { - switch (e.deltaMode) { - case e.DOM_DELTA_PIXEL: - this.currentDistanceMod += e.deltaY / 500; - break; - case e.DOM_DELTA_LINE: - this.currentDistanceMod += e.deltaY / 10; - break; - case e.DOM_DELTA_PAGE: - this.currentDistanceMod += e.deltaY / 2; - break; - } - } - }, - - _handleEnterVR: function() { - if (AFRAME.utils.device.checkHeadsetConnected() || AFRAME.utils.device.isMobile()) { - this._disable(); - } - }, - - _handleExitVR: function() { - this._enable(); - }, - - _enable: function() { - this.enabled = true; - this.data.cursor.setAttribute("visible", true); - this.el.setAttribute("raycaster", { enabled: true }); - }, - - _disable: function() { - this.enabled = false; - this.data.cursor.setAttribute("visible", false); - this.el.setAttribute("raycaster", { enabled: false }); - } -}); diff --git a/src/components/super-spawner.js b/src/components/super-spawner.js index bb6762a20..b67f60651 100644 --- a/src/components/super-spawner.js +++ b/src/components/super-spawner.js @@ -36,7 +36,6 @@ AFRAME.registerComponent("super-spawner", { const componentinInitializedListener = this._handleComponentInitialzed.bind(this, entity); const bodyLoadedListener = this._handleBodyLoaded.bind(this, entity); - this.entities.set(entity, { hand: hand, componentInitialized: false, @@ -68,8 +67,10 @@ AFRAME.registerComponent("super-spawner", { _emitEvents: function(entity) { const data = this.entities.get(entity); if (data.componentInitialized && data.bodyLoaded) { - data.hand.emit("action_grab", { targetEntity: entity }); - entity.emit("grab-start", { hand: data.hand }); + data.hand.emit("action_primary_down", { targetEntity: entity }); + const eventData = { bubbles: true, cancelable: true, detail: { hand: data.hand, target: entity } }; + const event = new CustomEvent("grab-start", eventData); + entity.dispatchEvent(event); entity.removeEventListener("componentinitialized", data.componentinInitializedListener); entity.removeEventListener("body-loaded", data.bodyLoadedListener); diff --git a/src/hub.html b/src/hub.html index 0f6df33ec..b69dec687 100644 --- a/src/hub.html +++ b/src/hub.html @@ -22,8 +22,6 @@ physics mute-mic="eventSrc: a-scene; toggleEvents: action_mute" personal-space-bubble="debug: false;" - - app-mode-input-mappings="modes: default, hud; actionSets: default, hud;" > <a-assets> @@ -112,16 +110,17 @@ body="type: dynamic; shape: none; mass: 5;" grabbable stretchable="useWorldPosition: true;" + hoverable ></a-entity> </template> <a-mixin id="super-hands" - super-hands="colliderEvent: collisions; colliderEventProperty: els; + super-hands=" + colliderEvent: collisions; colliderEventProperty: els; colliderEndEvent: collisions; colliderEndEventProperty: clearedEls; - grabStartButtons: action_grab; grabEndButtons: action_release; - stretchStartButtons: action_grab; stretchEndButtons: action_release; - dragDropStartButtons: action_grab; dragDropEndButtons: action_release; - " + grabStartButtons: action_primary_down; grabEndButtons: action_primary_up; + stretchStartButtons: action_primary_down; stretchEndButtons: action_primary_up; + dragDropStartButtons: action_primary_down; dragDropEndButtons: action_primary_up;" collision-filter="collisionForces: false" physics-collider ></a-mixin> @@ -137,22 +136,34 @@ super-spawner="template: #interactable-template;" position="2.9 1.2 0" body="mass: 0; type: static; shape: box;" + hoverable ></a-entity> <a-entity - id="super-cursor" - super-cursor="cursor: #3d-cursor; camera: #player-camera;" - raycaster="objects: .collidable, .interactable; far: 10;" - > - <a-sphere - id="3d-cursor" - radius="0.02" - static-body="shape: sphere;" - mixin="super-hands" - segments-height="9" - segments-width="9" - ></a-sphere> - </a-entity> + cursor-controller=" + cursor: #cursor; + camera: #player-camera; + controller: #player-right-controller; + playerRig: #player-rig; + otherHand: #right-super-hand;" + raycaster="objects: .collidable, .interactable, .ui; far: 3;" + line="visible: false; color: white; opacity: 0.2;" + ></a-entity> + + <a-sphere + id="cursor" + radius="0.02" + static-body="shape: sphere;" + collision-filter="collisionForces: false" + super-hands=" + colliderEvent: raycaster-intersection; colliderEventProperty: els; + colliderEndEvent: raycaster-intersection-cleared; colliderEndEventProperty: clearedEls; + grabStartButtons: action_primary_down; grabEndButtons: action_primary_up; + stretchStartButtons: action_primary_down; stretchEndButtons: action_primary_up; + dragDropStartButtons: action_primary_down; dragDropEndButtons: action_primary_up;" + segments-height="9" + segments-width="9" + ></a-sphere> <!-- Player Rig --> <a-entity @@ -162,13 +173,11 @@ wasd-to-analog2d character-controller="pivot: #player-camera" ik-root - app-mode-toggle-playing__character-controller="mode: hud; invert: true;" - app-mode-toggle-playing__wasd-to-analog2d="mode: hud; invert: true;" player-info > - <a-entity id="player-hud" + class="ui" hud-controller="head: #player-camera;" vr-mode-toggle-visibility vr-mode-toggle-playing__hud-controller @@ -199,7 +208,6 @@ teleportOrigin: #player-camera; button: action_teleport_; collisionEntities: [nav-mesh]" - app-mode-toggle-playing__teleport-controls="mode: hud; invert: true;" haptic-feedback ></a-entity> @@ -214,13 +222,6 @@ button: action_teleport_; collisionEntities: [nav-mesh]" haptic-feedback - raycaster="objects:.hud; showLine: true; far: 2;" - cursor="fuse: false; downEvents: action_ui_select_down; upEvents: action_ui_select_up;" - - app-mode-toggle-playing__teleport-controls="mode: hud; invert: true;" - app-mode-toggle-playing__raycaster="mode: hud;" - app-mode-toggle-playing__cursor="mode: hud;" - app-mode-toggle-attribute__line="mode: hud; property: visible;" ></a-entity> <a-entity gltf-model-plus="inflate: true;" class="model"> @@ -248,7 +249,8 @@ <template data-selector=".LeftHand"> <a-entity bone-visibility> <a-entity - event-repeater="events: action_grab, action_release; eventSource: #player-left-controller" + id="left-super-hand" + event-repeater="events: action_primary_down, action_primary_up; eventSource: #player-left-controller" static-body="shape: sphere; sphereRadius: 0.02" mixin="super-hands" position="0 0.05 0" @@ -259,7 +261,8 @@ <template data-selector=".RightHand"> <a-entity bone-visibility> <a-entity - event-repeater="events: action_grab, action_release; eventSource: #player-right-controller" + id="right-super-hand" + event-repeater="events: action_primary_down, action_primary_up; eventSource: #player-right-controller" static-body="shape: sphere; sphereRadius: 0.02" mixin="super-hands" position="0 -0.05 0" diff --git a/src/hub.js b/src/hub.js index 9dc3247e3..5074e8e3d 100644 --- a/src/hub.js +++ b/src/hub.js @@ -76,9 +76,10 @@ import "super-hands"; import "./components/super-networked-interactable"; import "./components/networked-counter"; import "./components/super-spawner"; -import "./components/super-cursor"; import "./components/event-repeater"; +import "./components/cursor-controller"; + import "./components/nav-mesh-helper"; import registerNetworkSchemas from "./network-schemas"; diff --git a/src/input-mappings.js b/src/input-mappings.js index 9296fd71f..09160b0ec 100644 --- a/src/input-mappings.js +++ b/src/input-mappings.js @@ -40,18 +40,18 @@ const config = { "trackpad.pressedmove": { left: "move" }, trackpad_dpad4_pressed_west_down: { right: "snap_rotate_left" }, trackpad_dpad4_pressed_east_down: { right: "snap_rotate_right" }, - trackpad_dpad4_pressed_center_down: { right: "action_teleport_down" }, - trackpad_dpad4_pressed_north_down: { right: "action_teleport_down" }, - trackpad_dpad4_pressed_south_down: { right: "action_teleport_down" }, - trackpadup: { right: "action_teleport_up" }, + trackpad_dpad4_pressed_center_down: { right: "action_primary_down" }, + trackpad_dpad4_pressed_north_down: { right: "action_primary_down" }, + trackpad_dpad4_pressed_south_down: { right: "action_primary_down" }, + trackpadup: { right: "action_primary_up" }, menudown: "thumb_down", menuup: "thumb_up", - gripdown: ["action_grab", "middle_ring_pinky_down", "index_down"], - gripup: ["action_release", "middle_ring_pinky_up", "index_up"], + gripdown: ["action_primary_down", "middle_ring_pinky_down", "index_down"], + gripup: ["action_primary_up", "middle_ring_pinky_up", "index_up"], trackpadtouchstart: "thumb_down", trackpadtouchend: "thumb_up", - triggerdown: ["action_grab", "index_down"], - triggerup: ["action_release", "index_up"] + triggerdown: ["action_primary_down", "index_down"], + triggerup: ["action_primary_up", "index_up"] }, "oculus-touch-controls": { joystick_dpad4_west: { @@ -60,8 +60,8 @@ const config = { joystick_dpad4_east: { right: "snap_rotate_right" }, - gripdown: ["action_grab", "middle_ring_pinky_down"], - gripup: ["action_release", "middle_ring_pinky_up"], + gripdown: ["action_primary_down", "middle_ring_pinky_down"], + gripup: ["action_primary_up", "middle_ring_pinky_up"], abuttontouchstart: "thumb_down", abuttontouchend: "thumb_up", bbuttontouchstart: "thumb_down", @@ -74,27 +74,27 @@ const config = { surfacetouchend: "thumb_up", thumbsticktouchstart: "thumb_down", thumbsticktouchend: "thumb_up", - triggerdown: "index_down", - triggerup: "index_up", + triggerdown: ["action_primary_down", "index_down"], + triggerup: ["action_primary_up", "index_up"], "axismove.reverseY": { left: "move" }, - abuttondown: "action_teleport_down", - abuttonup: "action_teleport_up" + abuttondown: "action_primary_down", + abuttonup: "action_primary_up" }, "daydream-controls": { trackpad_dpad4_pressed_west_down: "snap_rotate_left", trackpad_dpad4_pressed_east_down: "snap_rotate_right", - trackpad_dpad4_pressed_center_down: "action_teleport_down", - trackpad_dpad4_pressed_north_down: "action_teleport_down", - trackpad_dpad4_pressed_south_down: "action_teleport_down", - trackpadup: "action_teleport_up" + trackpad_dpad4_pressed_center_down: ["action_primary_down"], + trackpad_dpad4_pressed_north_down: ["action_primary_down"], + trackpad_dpad4_pressed_south_down: ["action_primary_down"], + trackpadup: ["action_primary_up"] }, "gearvr-controls": { trackpad_dpad4_pressed_west_down: "snap_rotate_left", trackpad_dpad4_pressed_east_down: "snap_rotate_right", - trackpad_dpad4_pressed_center_down: "action_teleport_down", - trackpad_dpad4_pressed_north_down: "action_teleport_down", - trackpad_dpad4_pressed_south_down: "action_teleport_down", - trackpadup: "action_teleport_up" + trackpad_dpad4_pressed_center_down: ["action_primary_down"], + trackpad_dpad4_pressed_north_down: ["action_primary_down"], + trackpad_dpad4_pressed_south_down: ["action_primary_down"], + trackpadup: ["action_primary_up"] }, keyboard: { m_press: "action_mute", -- GitLab