@matematrolii/sketchbook
Version:
3D matematrolii playground built on three.js and cannon.js
251 lines (221 loc) • 7.33 kB
text/typescript
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);
}
}
}