Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .idea/[NanoForge] Engine.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { type Context } from "../../../context";
import { type IInputLibrary } from "../interfaces";
import { Library } from "../library";

export abstract class BaseInputLibrary extends Library implements IInputLibrary {}
export abstract class BaseInputLibrary extends Library implements IInputLibrary {
public abstract __run(_context: Context): Promise<void>;
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { type IExposedLibrary } from "../bases/exposed.library.type";
import { type IRunnerLibrary } from "../bases/runner.library.type";

export interface IInputLibrary extends IExposedLibrary {}
export interface IInputLibrary extends IExposedLibrary, IRunnerLibrary {}
156 changes: 155 additions & 1 deletion packages/input/src/input-handler.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,41 @@
import { InputEnum } from "./input.enum";
import {
BUTTONS_MASKS,
type DragState,
MOUSE_BUTTON_MAP,
type MouseState,
type WheelState,
} from "./mouse.types";

export class InputHandler {
public inputs: Record<string, boolean> = {};
public mouse: MouseState = {
x: 0,
y: 0,
prevX: 0,
prevY: 0,
deltaX: 0,
deltaY: 0,
focus: false,
};
public wheel: WheelState = {
deltaX: 0,
deltaY: 0,
deltaZ: 0,
};
public drag: DragState = {
active: false,
startX: 0,
startY: 0,
x: 0,
y: 0,
deltaX: 0,
deltaY: 0,
};

constructor() {
this.resetInputs();

window.addEventListener("keydown", (e: KeyboardEvent) => {
this.inputs[e.code] = true;
});
Expand All @@ -12,12 +44,134 @@ export class InputHandler {
this.inputs[e.code] = false;
});

window.addEventListener("mousedown", (e: MouseEvent) => {
const button = MOUSE_BUTTON_MAP[e.button];
if (button === undefined) return;

this.inputs[button] = true;
this.updatePointer(e);

this.drag.active = true;
this.drag.button = button;
this.drag.startX = e.clientX;
this.drag.startY = e.clientY;
this.drag.x = e.clientX;
this.drag.y = e.clientY;
this.drag.deltaX = 0;
this.drag.deltaY = 0;
});

window.addEventListener("mouseup", (e: MouseEvent) => {
const button = MOUSE_BUTTON_MAP[e.button];
if (button !== undefined) this.inputs[button] = false;

this.updatePointer(e);

if (this.drag.button === button) {
this.drag.active = false;
this.drag.button = undefined;
this.drag.x = 0;
this.drag.y = 0;
this.drag.deltaX = 0;
this.drag.deltaY = 0;
}
});

window.addEventListener("mousemove", (e: MouseEvent) => {
this.updatePointer(e);
this.updateInputsMouseButtons(e.buttons);

if (this.drag.active) {
this.drag.x = e.clientX;
this.drag.y = e.clientY;
this.drag.deltaX = e.clientX - this.drag.startX;
this.drag.deltaY = e.clientY - this.drag.startY;
}
});

window.addEventListener("wheel", (e: WheelEvent) => {
this.wheel.deltaX += e.deltaX;
this.wheel.deltaY += e.deltaY;
this.wheel.deltaZ += e.deltaZ;
});

window.addEventListener("mouseenter", () => {
this.mouse.focus = true;
});

window.addEventListener("mouseleave", () => {
this.mouse.focus = false;
});

window.addEventListener("blur", () => {
this.resetInputs();
});

document.addEventListener("visibilitychange", () => {
if (document.hidden) this.resetInputs();
});

for (const key in InputEnum) {
this.inputs[key] = false;
}
}

getKeyStatus(key: InputEnum): boolean {
public getKeyStatus(key: InputEnum): boolean {
return this.inputs[key] || false;
}

public getMousePosition() {
return { x: this.mouse.x, y: this.mouse.y };
}

public isDragging(button?: InputEnum): boolean {
if (!button) return this.drag.active;
return this.drag.active && this.drag.button === button;
}

public resetPerFrame(): void {
this.mouse.deltaX = 0;
this.mouse.deltaY = 0;
this.wheel.deltaX = 0;
this.wheel.deltaY = 0;
this.wheel.deltaZ = 0;
}

private updatePointer(e: MouseEvent): void {
this.mouse.prevX = this.mouse.x;
this.mouse.prevY = this.mouse.y;
this.mouse.x = e.clientX;
this.mouse.y = e.clientY;
this.mouse.deltaX = this.mouse.x - this.mouse.prevX;
this.mouse.deltaY = this.mouse.y - this.mouse.prevY;
}

private updateInputsMouseButtons(buttons: number): void {
for (const [mask, input] of BUTTONS_MASKS) {
this.inputs[input] = (buttons & mask) !== 0;
}
}

private resetInputs(): void {
for (const key of Object.values(InputEnum)) {
this.inputs[key] = false;
}

this.drag.active = false;
this.drag.button = undefined;
this.drag.startX = 0;
this.drag.startY = 0;
this.drag.x = 0;
this.drag.y = 0;
this.drag.deltaX = 0;
this.drag.deltaY = 0;

this.wheel.deltaX = 0;
this.wheel.deltaY = 0;
this.wheel.deltaZ = 0;

this.mouse.deltaX = 0;
this.mouse.deltaY = 0;
this.mouse.focus = false;
}
}
5 changes: 5 additions & 0 deletions packages/input/src/input.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,4 +141,9 @@ export enum InputEnum {
BrowserBack = "BrowserBack",
LaunchApp1 = "LaunchApp1",
LaunchMail = "LaunchMail",
MouseLeft = "MouseLeft",
MouseMiddle = "MouseMiddle",
MouseRight = "MouseRight",
Back = "BackButton",
Forward = "Forward",
}
37 changes: 36 additions & 1 deletion packages/input/src/input.library.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { BaseInputLibrary } from "@nanoforge-dev/common";
import { BaseInputLibrary, GRAPHICS_LIBRARY } from "@nanoforge-dev/common";

import { InputHandler } from "./input-handler";
import { type InputEnum } from "./input.enum";
import { type DragState, type MouseState, type WheelState } from "./mouse.types";

export class InputLibrary extends BaseInputLibrary {
private _inputHandler?: InputHandler;

constructor() {
super({ runAfter: [GRAPHICS_LIBRARY] });
}

get __name(): string {
return "InputLibrary";
}
Expand All @@ -14,6 +19,11 @@ export class InputLibrary extends BaseInputLibrary {
this._inputHandler = new InputHandler();
}

public override async __run() {
if (!this._inputHandler) this.throwNotInitializedError();
this._inputHandler.resetPerFrame();
}

public isKeyPressed(key: InputEnum): boolean | undefined {
if (!this._inputHandler) this.throwNotInitializedError();
return this._inputHandler.getKeyStatus(key);
Expand All @@ -28,4 +38,29 @@ export class InputLibrary extends BaseInputLibrary {
}
return res;
}

public getMousePosition(): { x: number; y: number } {
if (!this._inputHandler) this.throwNotInitializedError();
return this._inputHandler.getMousePosition();
}

public getMouseState(): MouseState {
if (!this._inputHandler) this.throwNotInitializedError();
return this._inputHandler.mouse;
}

public isDragging(button?: InputEnum): boolean {
if (!this._inputHandler) this.throwNotInitializedError();
return this._inputHandler.isDragging(button);
}

public getDragState(): DragState {
if (!this._inputHandler) this.throwNotInitializedError();
return this._inputHandler.drag;
}

public getWheelState(): WheelState {
if (!this._inputHandler) this.throwNotInitializedError();
return this._inputHandler.wheel;
}
}
40 changes: 40 additions & 0 deletions packages/input/src/mouse.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { InputEnum } from "./input.enum";

export type MouseState = {
x: number;
y: number;
prevX: number;
prevY: number;
deltaX: number;
deltaY: number;
focus: boolean;
};

export type DragState = {
active: boolean;
button?: InputEnum | undefined;
startX: number;
startY: number;
x: number;
y: number;
deltaX: number;
deltaY: number;
};

export type WheelState = { deltaX: number; deltaY: number; deltaZ: number };

export const MOUSE_BUTTON_MAP: Partial<Record<number, InputEnum>> = {
0: InputEnum.MouseLeft,
1: InputEnum.MouseMiddle,
2: InputEnum.MouseRight,
3: InputEnum.Back,
4: InputEnum.Forward,
};

export const BUTTONS_MASKS = new Map<number, InputEnum>([
[1, InputEnum.MouseLeft],
[2, InputEnum.MouseRight],
[4, InputEnum.MouseMiddle],
[8, InputEnum.Back],
[16, InputEnum.Forward],
]);
Loading
Loading