UNPKG

@matematrolii/sketchbook

Version:

3D matematrolii playground built on three.js and cannon.js

251 lines (221 loc) 7.33 kB
import { World } from "../world/World"; import { IInputReceiver } from "../interfaces/IInputReceiver"; import { IUpdatable } from "../interfaces/IUpdatable"; import { EventType } from "../enums/EventType"; import { MATEMATROLII_EVENT } from "../enums/WorldType"; export class InputManager implements IUpdatable { public updateOrder: number = 3; public world: World; public domElement: any; public pointerLock: any; public isLocked: boolean; public inputReceiver: IInputReceiver; public boundOnMouseDown: (evt: any) => void; public boundOnMouseMove: (evt: any) => void; public boundOnMouseUp: (evt: any) => void; public boundOnMouseWheelMove: (evt: any) => void; public boundOnPointerlockChange: (evt: any) => void; public boundOnPointerlockError: (evt: any) => void; public boundOnKeyDown: (evt: any) => void; public boundOnKeyUp: (evt: any) => void; public boundMatematroliiPointerLock: (evt: any) => void; constructor(world: World, domElement: HTMLElement) { this.world = world; this.pointerLock = world.params.Pointer_Lock; this.domElement = domElement || document.body; this.isLocked = false; // Bindings for later event use // Mouse this.boundOnMouseDown = (evt) => this.onMouseDown(evt); this.boundOnMouseMove = (evt) => this.onMouseMove(evt); this.boundOnMouseUp = (evt) => this.onMouseUp(evt); this.boundOnMouseWheelMove = (evt) => this.onMouseWheelMove(evt); // Pointer lock this.boundOnPointerlockChange = (evt) => this.onPointerlockChange(evt); this.boundOnPointerlockError = (evt) => this.onPointerlockError(evt); this.boundMatematroliiPointerLock = (evt) => this.onMatematroliiPointerLock(evt); // Keys this.boundOnKeyDown = (evt) => this.onKeyDown(evt); this.boundOnKeyUp = (evt) => this.onKeyUp(evt); // Init event listeners // Mouse this.domElement.addEventListener("mousedown", this.boundOnMouseDown, false); document.addEventListener("wheel", this.boundOnMouseWheelMove, false); document.addEventListener( "pointerlockchange", this.boundOnPointerlockChange, false ); document.addEventListener( "pointerlockerror", this.boundOnPointerlockError, false ); document.addEventListener( MATEMATROLII_EVENT, this.boundMatematroliiPointerLock, false ); // Keys document.addEventListener("keydown", this.boundOnKeyDown, false); document.addEventListener("keyup", this.boundOnKeyUp, false); world.registerUpdatable(this); } public destroy(): void { this.world.unregisterUpdatable(this); this.domElement.removeEventListener("mousedown", this.boundOnMouseDown, false); document.removeEventListener("wheel", this.boundOnMouseWheelMove, false); document.removeEventListener( "pointerlockchange", this.boundOnPointerlockChange, false ); document.removeEventListener( "pointerlockerror", this.boundOnPointerlockError, false ); document.removeEventListener( MATEMATROLII_EVENT, this.boundMatematroliiPointerLock, false ); // Keys document.removeEventListener("keydown", this.boundOnKeyDown, false); document.removeEventListener("keyup", this.boundOnKeyUp, false); this.world = undefined; this.pointerLock = undefined; this.domElement = undefined; this.isLocked = undefined; this.boundOnMouseDown = undefined; this.boundOnMouseMove = undefined; this.boundOnMouseUp = undefined; this.boundOnMouseWheelMove = undefined; // Pointer lock this.boundOnPointerlockChange = undefined; this.boundOnPointerlockError = undefined; this.boundMatematroliiPointerLock = undefined; // Keys this.boundOnKeyDown = undefined; this.boundOnKeyUp = undefined; } public onMatematroliiPointerLock(event: CustomEvent): void { if (event.detail) { const type = event.detail?.type; if (type === EventType.START) { this.domElement.requestPointerLock(); this.world.render(this.world); } else if (type === EventType.PAUSE) { document.exitPointerLock(); this.world.stopRender(); } } } public update(timestep: number, unscaledTimeStep: number): void { if ( this.inputReceiver === undefined && this.world !== undefined && this.world.cameraOperator !== undefined ) { this.setInputReceiver(this.world.cameraOperator); } this.inputReceiver?.inputReceiverUpdate(unscaledTimeStep); } public setInputReceiver(receiver: IInputReceiver): void { this.inputReceiver = receiver; this.inputReceiver.inputReceiverInit(); } public setPointerLock(enabled: boolean): void { this.pointerLock = enabled; } public onPointerlockChange(event: MouseEvent): void { if (document.pointerLockElement === this.domElement) { this.domElement.addEventListener( "mousemove", this.boundOnMouseMove, false ); this.domElement.addEventListener("mouseup", this.boundOnMouseUp, false); this.isLocked = true; } else { this.domElement.removeEventListener( "mousemove", this.boundOnMouseMove, false ); this.domElement.removeEventListener( "mouseup", this.boundOnMouseUp, false ); this.isLocked = false; } } public onPointerlockError(event: MouseEvent): void { console.error("PointerLockControls: Unable to use Pointer Lock API"); } public onMouseDown(event: MouseEvent): void { if (this.pointerLock) { this.domElement.requestPointerLock(); } else { this.domElement.addEventListener( "mousemove", this.boundOnMouseMove, false ); this.domElement.addEventListener("mouseup", this.boundOnMouseUp, false); } if (this.inputReceiver !== undefined && this.pointerLock) { this.inputReceiver.handleMouseButton(event, "mouse" + event.button, true); } } public onMouseMove(event: MouseEvent): void { if (this.inputReceiver !== undefined) { this.inputReceiver.handleMouseMove( event, event.movementX, event.movementY ); } } public onMouseUp(event: MouseEvent): void { if (!this.pointerLock) { this.domElement.removeEventListener( "mousemove", this.boundOnMouseMove, false ); this.domElement.removeEventListener( "mouseup", this.boundOnMouseUp, false ); } if (this.inputReceiver !== undefined) { this.inputReceiver.handleMouseButton( event, "mouse" + event.button, false ); } } public onKeyDown(event: KeyboardEvent): void { if (this.inputReceiver !== undefined) { this.inputReceiver.handleKeyboardEvent(event, event.code, true); } } public onKeyUp(event: KeyboardEvent): void { if (event.code === "Escape") { document.exitPointerLock(); } if (this.inputReceiver !== undefined) { this.inputReceiver.handleKeyboardEvent(event, event.code, false); } } public onMouseWheelMove(event: WheelEvent): void { if (this.inputReceiver !== undefined) { this.inputReceiver.handleMouseWheel(event, event.deltaY); } } }