187 lines
5.1 KiB
JavaScript
187 lines
5.1 KiB
JavaScript
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' );
|
|
} |