import { Vector3, Controls, Euler } from 'three'; 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; this.canJump = false; this.velocity = new Vector3(); this.direction = new Vector3(); this.rotationY = 0; this.vertex = new Vector3(); this.rvelo = 0; this.engine = engine; this.click = false; 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; switch (event.code) { case 'Space': if (this.canJump === true) this.velocity.y += 350; this.canJump = false; break; } }; const onKeyUp = (event) => { this.kb[event.code] = false; }; document.addEventListener('keydown', onKeyDown); document.addEventListener('keyup', onKeyUp); this.dom.addEventListener('click', () => { this.isLocked && this.clicked && this.clicked(); }); this.dom.addEventListener('mousedown', () => { this.isLocked && this.onpointer && this.onpointer('start'); }); this.dom.addEventListener('mousemove', () => { this.isLocked && this.onpointer && this.onpointer('drag'); }); this.dom.addEventListener('mouseup', () => { 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 } get moveBackward(){ return this.kb['ArrowDown'] || this.kb['KeyS'] || this.engine.xrController1?.gamepad?.axes[3] > 0.5 || false } get moveLeft(){ return this.kb['ArrowLeft'] || this.kb['KeyA'] || this.engine.xrController1?.gamepad?.axes[2] < -0.5 || false } get moveRight(){ return this.kb['ArrowRight'] || this.kb['KeyD'] || this.engine.xrController1?.gamepad?.axes[2] > 0.5 || false } get rotateLeft(){ return this.moveLeft; } get rotateRight(){ return this.moveRight; } get moveUp(){ return this.kb['KeyR'] || false } get moveDown(){ return this.kb['KeyF'] || false } get cameraLeft(){ return this.kb['KeyQ'] || false } get cameraRight(){ return this.kb['KeyE'] || false } get moving(){ return this.moveForward || this.moveBackward; } get rotating(){ return this.rotateLeft || this.rotateRight; } get motion(){ return this.moving || this.rotating; } get running(){ return this.moving && this.kb.ShiftLeft; } get input() { return [ this.moveLeft * 1 + this.moveRight * -1, this.moveForward * 1 + this.moveBackward * -1 ] } async lock(unadjustedMovement = false){ await this.dom.requestPointerLock( { unadjustedMovement } ); } unlock(){ this.dom.ownerDocument.exitPointerLock(); } } 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' ); }