From dc92f771c8c60789ff5f24cedc9d9640780915c0 Mon Sep 17 00:00:00 2001 From: joni <johnfshaughnessy@gmail.com> Date: Tue, 8 May 2018 14:35:49 -0700 Subject: [PATCH] Clean up touch events in cursor controller. --- src/components/cursor-controller.js | 146 +++++++++++++--------------- 1 file changed, 65 insertions(+), 81 deletions(-) diff --git a/src/components/cursor-controller.js b/src/components/cursor-controller.js index ddbc9e84c..7cc12441d 100644 --- a/src/components/cursor-controller.js +++ b/src/components/cursor-controller.js @@ -41,30 +41,24 @@ AFRAME.registerComponent("cursor-controller", { this.data.cursor.setAttribute("material", { color: this.data.cursorColorUnhovered }); - this._handleMouseDown = this._handleMouseDown.bind(this); - this._handleMouseMove = this._handleMouseMove.bind(this); - this._handleMouseUp = this._handleMouseUp.bind(this); - this._handleWheel = this._handleWheel.bind(this); - this._handleEnterVR = this._handleEnterVR.bind(this); - this._handleExitVR = this._handleExitVR.bind(this); - this._handlePrimaryDown = this._handlePrimaryDown.bind(this); - this._handlePrimaryUp = this._handlePrimaryUp.bind(this); - this._handleModelLoaded = this._handleModelLoaded.bind(this); - this._handleCursorLoaded = this._handleCursorLoaded.bind(this); - this._handleControllerConnected = this._handleControllerConnected.bind(this); - this._handleControllerDisconnected = this._handleControllerDisconnected.bind(this); - - this._handleTouchStart = this._handleTouchStart.bind(this); - this._updateRaycasterIntersections = this._updateRaycasterIntersections.bind(this); - this._handleTouchMove = this._handleTouchMove.bind(this); - this._handleTouchEnd = this._handleTouchEnd.bind(this); - - this.el.sceneEl.renderer.sortObjects = true; - this.data.cursor.addEventListener("loaded", this.cursorLoadedListener); - }, - - remove: function() { - this.data.cursor.removeEventListener("loaded", this._cursorLoadedListener); + [ + "_handleTouchStart", + "_handleTouchMove", + "_handleTouchEnd", + "_handleMouseDown", + "_handleMouseMove", + "_handleMouseUp", + "_handleWheel", + "_handleEnterVR", + "_handleExitVR", + "_handlePrimaryDown", + "_handlePrimaryUp", + "_handleModelLoaded", + "_handleControllerConnected", + "_handleControllerDisconnected" + ].map(fn => { + this[fn] = this[fn].bind(this); + }); }, update: function(oldData) { @@ -81,6 +75,7 @@ AFRAME.registerComponent("cursor-controller", { document.addEventListener("touchstart", this._handleTouchStart); document.addEventListener("touchmove", this._handleTouchMove); document.addEventListener("touchend", this._handleTouchEnd); + document.addEventListener("touchcancel", this._handleTouchEnd); document.addEventListener("mousedown", this._handleMouseDown); document.addEventListener("mousemove", this._handleMouseMove); document.addEventListener("mouseup", this._handleMouseUp); @@ -93,7 +88,6 @@ AFRAME.registerComponent("cursor-controller", { this.data.playerRig.addEventListener(this.data.primaryUp, this._handlePrimaryUp); this.data.playerRig.addEventListener(this.data.grabEvent, this._handlePrimaryDown); this.data.playerRig.addEventListener(this.data.releaseEvent, this._handlePrimaryUp); - this.data.playerRig.addEventListener("model-loaded", this._handleModelLoaded); this.el.sceneEl.addEventListener("controllerconnected", this._handleControllerConnected); @@ -104,6 +98,7 @@ AFRAME.registerComponent("cursor-controller", { document.removeEventListener("touchstart", this._handleTouchStart); document.removeEventListener("touchmove", this._handleTouchMove); document.removeEventListener("touchend", this._handleTouchEnd); + document.removeEventListener("touchcancel", this._handleTouchEnd); document.removeEventListener("mousedown", this._handleMouseDown); document.removeEventListener("mousemove", this._handleMouseMove); document.removeEventListener("mouseup", this._handleMouseUp); @@ -116,7 +111,6 @@ AFRAME.registerComponent("cursor-controller", { this.data.playerRig.removeEventListener(this.data.primaryUp, this._handlePrimaryUp); this.data.playerRig.removeEventListener(this.data.grabEvent, this._handlePrimaryDown); this.data.playerRig.removeEventListener(this.data.releaseEvent, this._handlePrimaryUp); - this.data.playerRig.removeEventListener("model-loaded", this._handleModelLoaded); this.el.sceneEl.removeEventListener("controllerconnected", this._handleControllerConnected); @@ -255,50 +249,39 @@ AFRAME.registerComponent("cursor-controller", { }, _handleTouchStart: function(e) { - if (!this.isMobile || this.hasPointingDevice) return; - - const touch = e.touches[0]; - if (touch.clientY / window.innerHeight >= 0.8) return true; - this.mousePos.set(touch.clientX / window.innerWidth * 2 - 1, -(touch.clientY / window.innerHeight) * 2 + 1); - this._updateRaycasterIntersections(); + if (!this.isMobile || this.hasPointingDevice || this.activeTouch) return; - // update cursor position - if (!this.isGrabbing) { - const intersections = this.el.components.raycaster.intersections; - if (intersections.length > 0 && intersections[0].distance <= this.data.maxDistance) { - const 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; + for (let i = e.touches.length - 1; i >= 0; i--) { + const touch = e.touches[i]; + if (touch.clientY / window.innerHeight < 0.8) { + this.activeTouch = touch; + break; } } + if (!this.activeTouch) return; - this._setLookControlsEnabled(false); - - // Set timeout because if I don't, the duck moves is picked up at the - // the wrong offset from the cursor: If the cursor started below and - // to the left, the duck lifts above and to the right by the same amount. - // I don't understand exactly why this is, since I am setting the - // cursor object's position manually in this function, but something else - // must happen before cursor-grab ends up doing the right thing. - // TODO : Figure this out. - window.setTimeout(() => { - this.data.cursor.emit("cursor-grab", {}); - }, 40); - - this.lastTouch = touch; - }, - - _updateRaycasterIntersections: function() { - const raycaster = this.el.components.raycaster.raycaster; + // Update the ray and cursor positions + const raycasterComp = this.el.components.raycaster; + const raycaster = raycasterComp.raycaster; const camera = this.data.camera.components.camera.camera; + const cursor = this.data.cursor; + this.mousePos.set( + this.activeTouch.clientX / window.innerWidth * 2 - 1, + -(this.activeTouch.clientY / window.innerHeight) * 2 + 1 + ); 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 }); - this.el.components.raycaster.checkIntersections(); + raycasterComp.data.origin = raycaster.ray.origin; + raycasterComp.data.direction = raycaster.ray.direction; + raycasterComp.checkIntersections(); + const intersections = raycasterComp.intersections; + if (intersections.length == 0 || intersections[0].distance >= this.data.maxDistance) { + this.activeTouch = null; + return; + } + cursor.object3D.position.copy(intersections[0].point); + // Cursor position must be synced to physics before constraint is created + cursor.components["static-body"].syncToPhysics(); + cursor.emit("cursor-grab", {}); }, _handleTouchMove: function(e) { @@ -306,26 +289,31 @@ AFRAME.registerComponent("cursor-controller", { for (let i = 0; i < e.touches.length; i++) { const touch = e.touches[i]; - if (touch.clientY / window.innerHeight >= 0.8) return true; - this.mousePos.set(touch.clientX / window.innerWidth * 2 - 1, -(touch.clientY / window.innerHeight) * 2 + 1); - this.lastTouch = touch; + if ( + (!this.activeTouch && touch.clientY / window.innerHeight < 0.8) || + touch.identifier === this.activeTouch.identifier + ) { + this.mousePos.set(touch.clientX / window.innerWidth * 2 - 1, -(touch.clientY / window.innerHeight) * 2 + 1); + return; + } } }, _handleTouchEnd: function(e) { - if (!this.isMobile || this.hasPointingDevice) return; - - for (let i = 0; i < e.changedTouches.length; i++) { - const touch = e.changedTouches[i]; - const thisTouchDidNotDriveMousePos = - Math.abs(touch.clientX - this.lastTouch.clientX) > 0.1 && - Math.abs(touch.clientY - this.lastTouch.clientY) > 0.1; - if (thisTouchDidNotDriveMousePos) { - return; + if (!this.isMobile || this.hasPointingDevice || !this.activeTouch) return; + + if (e.touches) { + for (let i = 0; i < e.touches.length; i++) { + const touch = e.touches[i]; + if (touch.identifier === this.activeTouch.identifier) { + // Touch is still active + return; + } } } - this._setLookControlsEnabled(true); + this.data.cursor.emit("cursor-release", {}); + this.activeTouch = null; }, _handleMouseDown: function() { @@ -408,10 +396,6 @@ AFRAME.registerComponent("cursor-controller", { this.physicalHand = this.data.playerRig.querySelector(this.data.physicalHandSelector); }, - _handleCursorLoaded: function() { - this.data.cursor.object3DMap.mesh.renderOrder = 1; - }, - _handleControllerConnected: function(e) { const data = { controller: e.target, -- GitLab