rewrite pointerlock controls

This commit is contained in:
2026-02-27 13:22:41 +02:00
parent 6b94bde264
commit 0649d0708c
3 changed files with 86 additions and 24 deletions
+65 -9
View File
@@ -1,8 +1,12 @@
import { Vector3 } from 'three';
import { PointerLockControls } from 'three/examples/jsm/Addons.js';
import { Vector3, Controls, Euler } from 'three';
class PointerControls {
const _MOUSE_SENSITIVITY = 0.002;
const _euler = new Euler( 0, 0, 0, 'YXZ' );
class PointerControls extends Controls {
constructor(engine) {
super( engine.cameraWorld, engine.renderer.domElement );
this.kb = {};
this.dom = engine.renderer.domElement;
@@ -16,7 +20,14 @@ class PointerControls {
this.engine = engine;
this.click = false;
this.controls = new PointerLockControls(engine.camera, this.dom);
this.isLocked = false;
this.minPolarAngle = 0;
this.maxPolarAngle = Math.PI;
this.pointerSpeed = 1.0;
this._onMouseMove = onMouseMove.bind( this );
this._onPointerlockChange = onPointerlockChange.bind( this );
this._onPointerlockError = onPointerlockError.bind( this );
const onKeyDown = (event) => {
this.kb[event.code] = true;
@@ -36,24 +47,43 @@ class PointerControls {
document.addEventListener('keyup', onKeyUp);
this.dom.addEventListener('click', () => {
this.controls.isLocked && this.clicked && this.clicked();
this.isLocked && this.clicked && this.clicked();
});
this.dom.addEventListener('mousedown', () => {
this.controls.isLocked && this.onpointer && this.onpointer('start');
this.isLocked && this.onpointer && this.onpointer('start');
});
this.dom.addEventListener('mousemove', () => {
this.controls.isLocked && this.onpointer && this.onpointer('drag');
this.isLocked && this.onpointer && this.onpointer('drag');
});
this.dom.addEventListener('mouseup', () => {
this.controls.isLocked && this.onpointer && this.onpointer('end');
this.isLocked && this.onpointer && this.onpointer('end');
});
this.update = () => { };
this.connect(this.dom);
}
connect( element ) {
super.connect( element );
this.dom.ownerDocument.addEventListener( 'mousemove', this._onMouseMove );
this.dom.ownerDocument.addEventListener( 'pointerlockchange', this._onPointerlockChange );
this.dom.ownerDocument.addEventListener( 'pointerlockerror', this._onPointerlockError );
}
disconnect() {
this.dom.ownerDocument.removeEventListener( 'mousemove', this._onMouseMove );
this.dom.ownerDocument.removeEventListener( 'pointerlockchange', this._onPointerlockChange );
this.dom.ownerDocument.removeEventListener( 'pointerlockerror', this._onPointerlockError );
}
dispose() {
this.disconnect();
}
get moveForward(){
return this.kb['ArrowUp'] || this.kb['KeyW'] || this.engine.xrController1?.gamepad?.axes[3] < -0.5 || false
}
@@ -128,4 +158,30 @@ class PointerControls {
}
}
export { PointerControls };
export { PointerControls };
function onMouseMove( event ) {
if ( this.enabled === false || this.isLocked === false ) return;
const camera = this.object;
_euler.setFromQuaternion( camera.quaternion );
_euler.y -= event.movementX * _MOUSE_SENSITIVITY * this.pointerSpeed;
_euler.x -= -event.movementY * _MOUSE_SENSITIVITY * this.pointerSpeed;
_euler.x = Math.max( Math.PI / 2 - this.maxPolarAngle, Math.min( Math.PI / 2 - this.minPolarAngle, _euler.x ) );
camera.quaternion.setFromEuler( _euler )
this.dispatchEvent( { type: 'change' } );
}
function onPointerlockChange() {
if ( this.dom.ownerDocument.pointerLockElement === this.dom ) {
this.dispatchEvent( { type: 'lock' } );
this.isLocked = true;
} else {
this.dispatchEvent( { type: 'unlock' } );
this.isLocked = false;
}
//this.engine.cameraRig.rotation.y = this.isLocked ? 0 : Math.PI;
}
function onPointerlockError() {
console.error( 'Unable to use Pointer Lock API' );
}