Browse Source

EditorControls: Fully migrate to Pointer Events. (#27745)

Michael Herzog 1 year ago
parent
commit
a984c6f4c8
1 changed files with 109 additions and 44 deletions
  1. 109 44
      editor/js/EditorControls.js

+ 109 - 44
editor/js/EditorControls.js

@@ -31,6 +31,9 @@ class EditorControls extends THREE.EventDispatcher {
 		var spherical = new THREE.Spherical();
 		var spherical = new THREE.Spherical();
 		var sphere = new THREE.Sphere();
 		var sphere = new THREE.Sphere();
 
 
+		var pointers = [];
+		var pointerPositions = {};
+
 		// events
 		// events
 
 
 		var changeEvent = { type: 'change' };
 		var changeEvent = { type: 'change' };
@@ -122,19 +125,28 @@ class EditorControls extends THREE.EventDispatcher {
 
 
 			if ( scope.enabled === false ) return;
 			if ( scope.enabled === false ) return;
 
 
-			switch ( event.pointerType ) {
+			if ( pointers.length === 0 ) {
 
 
-				case 'mouse':
-				case 'pen':
-					onMouseDown( event );
-					break;
+				domElement.setPointerCapture( event.pointerId );
 
 
-				// TODO touch
+				domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
+				domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );
 
 
 			}
 			}
 
 
-			domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
-			domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );
+			//
+
+			addPointer( event );
+
+			if ( event.pointerType === 'touch' ) {
+
+				onTouchStart( event );
+
+			} else {
+
+				onMouseDown( event );
+
+			}
 
 
 		}
 		}
 
 
@@ -142,14 +154,13 @@ class EditorControls extends THREE.EventDispatcher {
 
 
 			if ( scope.enabled === false ) return;
 			if ( scope.enabled === false ) return;
 
 
-			switch ( event.pointerType ) {
+			if ( event.pointerType === 'touch' ) {
 
 
-				case 'mouse':
-				case 'pen':
-					onMouseMove( event );
-					break;
+				onTouchMove( event );
 
 
-				// TODO touch
+			} else {
+
+				onMouseMove( event );
 
 
 			}
 			}
 
 
@@ -157,19 +168,30 @@ class EditorControls extends THREE.EventDispatcher {
 
 
 		function onPointerUp( event ) {
 		function onPointerUp( event ) {
 
 
-			switch ( event.pointerType ) {
+			removePointer( event );
+
+			switch ( pointers.length ) {
+
+				case 0:
+
+					domElement.releasePointerCapture( event.pointerId );
+
+					domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
+					domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
 
 
-				case 'mouse':
-				case 'pen':
-					onMouseUp();
 					break;
 					break;
 
 
-				// TODO touch
+				case 1:
 
 
-			}
+					var pointerId = pointers[ 0 ];
+					var position = pointerPositions[ pointerId ];
 
 
-			domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
-			domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
+					// minimal placeholder event - allows state correction on pointer-up
+					onTouchStart( { pointerId: pointerId, pageX: position.x, pageY: position.y } );
+
+					break;
+
+			}
 
 
 		}
 		}
 
 
@@ -251,9 +273,6 @@ class EditorControls extends THREE.EventDispatcher {
 
 
 			domElement.removeEventListener( 'pointerdown', onPointerDown );
 			domElement.removeEventListener( 'pointerdown', onPointerDown );
 
 
-			domElement.removeEventListener( 'touchstart', touchStart );
-			domElement.removeEventListener( 'touchmove', touchMove );
-
 		};
 		};
 
 
 		domElement.addEventListener( 'contextmenu', contextmenu );
 		domElement.addEventListener( 'contextmenu', contextmenu );
@@ -269,20 +288,23 @@ class EditorControls extends THREE.EventDispatcher {
 
 
 		var prevDistance = null;
 		var prevDistance = null;
 
 
-		function touchStart( event ) {
+		function onTouchStart( event ) {
 
 
-			if ( scope.enabled === false ) return;
+			trackPointer( event );
 
 
-			switch ( event.touches.length ) {
+			switch ( pointers.length ) {
 
 
 				case 1:
 				case 1:
-					touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
-					touches[ 1 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
+					touches[ 0 ].set( event.pageX, event.pageY, 0 ).divideScalar( window.devicePixelRatio );
+					touches[ 1 ].set( event.pageX, event.pageY, 0 ).divideScalar( window.devicePixelRatio );
 					break;
 					break;
 
 
 				case 2:
 				case 2:
-					touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
-					touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
+
+					var position = getSecondPointerPosition( event );
+
+					touches[ 0 ].set( event.pageX, event.pageY, 0 ).divideScalar( window.devicePixelRatio );
+					touches[ 1 ].set( position.x, position.y, 0 ).divideScalar( window.devicePixelRatio );
 					prevDistance = touches[ 0 ].distanceTo( touches[ 1 ] );
 					prevDistance = touches[ 0 ].distanceTo( touches[ 1 ] );
 					break;
 					break;
 
 
@@ -294,12 +316,9 @@ class EditorControls extends THREE.EventDispatcher {
 		}
 		}
 
 
 
 
-		function touchMove( event ) {
+		function onTouchMove( event ) {
 
 
-			if ( scope.enabled === false ) return;
-
-			event.preventDefault();
-			event.stopPropagation();
+			trackPointer( event );
 
 
 			function getClosest( touch, touches ) {
 			function getClosest( touch, touches ) {
 
 
@@ -315,17 +334,20 @@ class EditorControls extends THREE.EventDispatcher {
 
 
 			}
 			}
 
 
-			switch ( event.touches.length ) {
+			switch ( pointers.length ) {
 
 
 				case 1:
 				case 1:
-					touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
-					touches[ 1 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
+					touches[ 0 ].set( event.pageX, event.pageY, 0 ).divideScalar( window.devicePixelRatio );
+					touches[ 1 ].set( event.pageX, event.pageY, 0 ).divideScalar( window.devicePixelRatio );
 					scope.rotate( touches[ 0 ].sub( getClosest( touches[ 0 ], prevTouches ) ).multiplyScalar( - 1 ) );
 					scope.rotate( touches[ 0 ].sub( getClosest( touches[ 0 ], prevTouches ) ).multiplyScalar( - 1 ) );
 					break;
 					break;
 
 
 				case 2:
 				case 2:
-					touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
-					touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
+
+					var position = getSecondPointerPosition( event );
+
+					touches[ 0 ].set( event.pageX, event.pageY, 0 ).divideScalar( window.devicePixelRatio );
+					touches[ 1 ].set( position.x, position.y, 0 ).divideScalar( window.devicePixelRatio );
 					var distance = touches[ 0 ].distanceTo( touches[ 1 ] );
 					var distance = touches[ 0 ].distanceTo( touches[ 1 ] );
 					scope.zoom( delta.set( 0, 0, prevDistance - distance ) );
 					scope.zoom( delta.set( 0, 0, prevDistance - distance ) );
 					prevDistance = distance;
 					prevDistance = distance;
@@ -347,8 +369,51 @@ class EditorControls extends THREE.EventDispatcher {
 
 
 		}
 		}
 
 
-		domElement.addEventListener( 'touchstart', touchStart, { passive: false } );
-		domElement.addEventListener( 'touchmove', touchMove, { passive: false } );
+		function addPointer( event ) {
+
+			pointers.push( event.pointerId );
+
+		}
+
+		function removePointer( event ) {
+
+			delete pointerPositions[ event.pointerId ];
+
+			for ( var i = 0; i < pointers.length; i ++ ) {
+
+				if ( pointers[ i ] == event.pointerId ) {
+
+					pointers.splice( i, 1 );
+					return;
+
+				}
+
+			}
+
+		}
+
+		function trackPointer( event ) {
+
+			var position = pointerPositions[ event.pointerId ];
+
+			if ( position === undefined ) {
+
+				position = new THREE.Vector2();
+				pointerPositions[ event.pointerId ] = position;
+
+			}
+
+			position.set( event.pageX, event.pageY );
+
+		}
+
+		function getSecondPointerPosition( event ) {
+
+			var pointerId = ( event.pointerId === pointers[ 0 ] ) ? pointers[ 1 ] : pointers[ 0 ];
+
+			return pointerPositions[ pointerId ];
+
+		}
 
 
 	}
 	}