@antha/input 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,11 @@
1
+ export * from './bindings/antha-active-bindings-debug.element.js';
2
+ export * from './bindings/antha-binding-assignments-debug.element.js';
3
+ export * from './bindings/antha-input-bindings.mod.js';
4
+ export * from './bindings/antha-menu-nav.mod.js';
5
+ export * from './bindings/player-bindings.js';
6
+ export * from './elements/antha-keyboard.element.js';
7
+ export * from './raw-inputs/antha-raw-input-debug.element.js';
8
+ export * from './raw-inputs/antha-read-raw-input.mod.js';
9
+ export * from './raw-inputs/raw-input.js';
10
+ export * from 'gamepad-type';
11
+ export * from 'input-device-handler';
package/dist/index.js ADDED
@@ -0,0 +1,11 @@
1
+ export * from './bindings/antha-active-bindings-debug.element.js';
2
+ export * from './bindings/antha-binding-assignments-debug.element.js';
3
+ export * from './bindings/antha-input-bindings.mod.js';
4
+ export * from './bindings/antha-menu-nav.mod.js';
5
+ export * from './bindings/player-bindings.js';
6
+ export * from './elements/antha-keyboard.element.js';
7
+ export * from './raw-inputs/antha-raw-input-debug.element.js';
8
+ export * from './raw-inputs/antha-read-raw-input.mod.js';
9
+ export * from './raw-inputs/raw-input.js';
10
+ export * from 'gamepad-type';
11
+ export * from 'input-device-handler';
@@ -0,0 +1,9 @@
1
+ import { type AnthaReadRawInputModState } from './antha-read-raw-input.mod.js';
2
+ /**
3
+ * An element for debugging raw inputs that displays all current inputs.
4
+ *
5
+ * @category Internal
6
+ */
7
+ export declare const AnthaRawInputDebug: import("element-vir").DeclarativeElementDefinition<"antha-raw-input-debug", {
8
+ rawInputs: Readonly<AnthaReadRawInputModState["rawInputs"]>;
9
+ }, {}, {}, "antha-raw-input-debug-", "antha-raw-input-debug-", readonly [], readonly []>;
@@ -0,0 +1,43 @@
1
+ import { css, defineElement, html } from 'element-vir';
2
+ /**
3
+ * An element for debugging raw inputs that displays all current inputs.
4
+ *
5
+ * @category Internal
6
+ */
7
+ export const AnthaRawInputDebug = defineElement()({
8
+ tagName: 'antha-raw-input-debug',
9
+ styles: css `
10
+ :host {
11
+ display: flex;
12
+ gap: 16px;
13
+ flex-wrap: wrap;
14
+ }
15
+
16
+ .device {
17
+ min-width: 500px;
18
+ }
19
+
20
+ .no-inputs {
21
+ opacity: 0.3;
22
+ font-weight: bold;
23
+ }
24
+ `,
25
+ render({ inputs }) {
26
+ return Object.entries(inputs.rawInputs).map(([deviceKey, values,]) => {
27
+ const hasNoValues = Object.keys(values).length === 0;
28
+ const valuesTemplate = hasNoValues
29
+ ? html `
30
+ <p class="no-inputs">No inputs</p>
31
+ `
32
+ : html `
33
+ <pre>${JSON.stringify(values, null, 4)}</pre>
34
+ `;
35
+ return html `
36
+ <section class="device">
37
+ <b>${deviceKey}</b>
38
+ ${valuesTemplate}
39
+ </section>
40
+ `;
41
+ });
42
+ },
43
+ });
@@ -0,0 +1,89 @@
1
+ import { type PartialWithUndefined, type SelectFrom, type SetRequired } from '@augment-vir/common';
2
+ import { type GamepadBrandMap, type GamepadLayout, type GamepadModelMap } from 'gamepad-type';
3
+ import { InputDeviceHandler, type InputDeviceHandlerOptions, type InputDeviceKey } from 'input-device-handler';
4
+ import { type RawInput, type RawInputs, type SimpleInputDevicesMap } from './raw-input.js';
5
+ /**
6
+ * Options for {@link createAnthaReadRawInputMod}.
7
+ *
8
+ * @category Internal
9
+ */
10
+ export type AnthaReadRawInputModOptions = PartialWithUndefined<{
11
+ /**
12
+ * A device handler to insert into the game state. If not provided, the mod will create a device
13
+ * handler on its own.
14
+ */
15
+ deviceHandler: AnthaReadRawInputModState['deviceHandler'];
16
+ /**
17
+ * Used only when constructing an internal deviceHandler, which only happens if `deviceHandler`
18
+ * is not provided in these options.
19
+ */
20
+ deviceHandlerOptions: Omit<InputDeviceHandlerOptions, 'startLoopImmediately'>;
21
+ debugRawInputs: AnthaReadRawInputModState['debugRawInputs'];
22
+ }>;
23
+ /**
24
+ * All state used by and set by `createAnthaReadRawInputMod`.
25
+ *
26
+ * @category Internal
27
+ */
28
+ export type AnthaReadRawInputModState = {
29
+ deviceHandler: Pick<InputDeviceHandler, 'readAllDevices'>;
30
+ rawInputs: RawInputs;
31
+ currentInputDevices: SimpleInputDevicesMap;
32
+ /**
33
+ * If no model map is provided, the built-in defaults from
34
+ * [gamepad-type](https://www.npmjs.com/package/gamepad-type) are used. If a model map is
35
+ * provided, make sure to also include the default model map (`defaultGamepadModelMap` from
36
+ * gamepad-type) if you want it (as it will not be automatically appended to your provided
37
+ * map).
38
+ */
39
+ gamepadModelMap: GamepadModelMap;
40
+ /**
41
+ * If no gamepad layouts are provided, the built-in defaults from
42
+ * [gamepad-type](https://www.npmjs.com/package/gamepad-type) are used. If layouts are provided,
43
+ * make sure to also include the default layouts (`defaultGamepadLayouts` from gamepad-type) if
44
+ * you want them (as they will not be automatically appended to your provided layouts).
45
+ */
46
+ gamepadLayouts: GamepadLayout[];
47
+ /**
48
+ * If no brand map is provided, the built-in defaults from
49
+ * [gamepad-type](https://www.npmjs.com/package/gamepad-type) are used. If a brand map is
50
+ * provided, make sure to also include the default brand map (`defaultGamepadBrandMap` from
51
+ * gamepad-type) if you want it (as it will not be automatically appended to your provided
52
+ * map).
53
+ */
54
+ gamepadBrandMap: GamepadBrandMap;
55
+ /** If set to true, raw inputs are printed on the screen. */
56
+ debugRawInputs: boolean;
57
+ };
58
+ /**
59
+ * A pre-built mod that reads all current devices and device inputs and sets both on the state.
60
+ *
61
+ * @category Pre-Built Mods
62
+ */
63
+ export declare function createAnthaReadRawInputMod(options?: Readonly<AnthaReadRawInputModOptions>): import("@antha/engine").AnthaMod<NoInfer<AnthaReadRawInputModState>>;
64
+ /**
65
+ * The mod returned by {@link createAnthaReadRawInputMod}.
66
+ *
67
+ * @category Internal
68
+ */
69
+ export type AnthaReadRawInputMod = ReturnType<typeof createAnthaReadRawInputMod>;
70
+ /**
71
+ * Reads raw inputs from a `InputDeviceHandler`. This is the core internals of
72
+ * {@link createAnthaReadRawInputMod}.
73
+ *
74
+ * @category Internal
75
+ */
76
+ export declare function readRawInputs(state: SetRequired<SelectFrom<Partial<AnthaReadRawInputModState>, {
77
+ rawInputs: true;
78
+ deviceHandler: true;
79
+ gamepadLayouts: true;
80
+ gamepadBrandMap: true;
81
+ gamepadModelMap: true;
82
+ }>, 'deviceHandler'>, { msSinceLastExecute, }: Readonly<{
83
+ msSinceLastExecute: number;
84
+ }>): {
85
+ rawInputs: Partial<Record<InputDeviceKey, {
86
+ [x: string]: RawInput;
87
+ }>>;
88
+ currentDevices: Partial<Record<InputDeviceKey, import("./raw-input.js").SimpleInputDevice>>;
89
+ };
@@ -0,0 +1,113 @@
1
+ import { defineAnthaMod } from '@antha/engine';
2
+ import { mapObject, } from '@augment-vir/common';
3
+ import { html } from 'element-vir';
4
+ import { defaultGamepadLayouts, defaultGamepadModelMap, findMatchingGamepadLayout, findMatchingGamepadModel, } from 'gamepad-type';
5
+ import { InputDeviceHandler, isGamepadDeviceKey, } from 'input-device-handler';
6
+ import { AnthaRawInputDebug } from './antha-raw-input-debug.element.js';
7
+ import { calculateInputDirection, mapToSimpleDevicesMap, } from './raw-input.js';
8
+ /**
9
+ * A pre-built mod that reads all current devices and device inputs and sets both on the state.
10
+ *
11
+ * @category Pre-Built Mods
12
+ */
13
+ export function createAnthaReadRawInputMod(options = {}) {
14
+ return defineAnthaMod({
15
+ modName: 'antha-read-raw-input',
16
+ initState: {
17
+ debugRawInputs: !!options.debugRawInputs,
18
+ },
19
+ execute({ state, msSinceLastExecute }) {
20
+ if (!state.deviceHandler) {
21
+ state.deviceHandler =
22
+ options.deviceHandler ||
23
+ new InputDeviceHandler({
24
+ ...options.deviceHandlerOptions,
25
+ startLoopImmediately: false,
26
+ });
27
+ }
28
+ const { currentDevices, rawInputs } = readRawInputs(state, {
29
+ msSinceLastExecute,
30
+ });
31
+ state.rawInputs = rawInputs;
32
+ state.currentInputDevices = currentDevices;
33
+ if (state.debugRawInputs) {
34
+ return html `
35
+ <${AnthaRawInputDebug.assign({
36
+ rawInputs: state.rawInputs,
37
+ })}></${AnthaRawInputDebug}>
38
+ `;
39
+ }
40
+ else {
41
+ return undefined;
42
+ }
43
+ },
44
+ });
45
+ }
46
+ /**
47
+ * Reads raw inputs from a `InputDeviceHandler`. This is the core internals of
48
+ * {@link createAnthaReadRawInputMod}.
49
+ *
50
+ * @category Internal
51
+ */
52
+ export function readRawInputs(state, { msSinceLastExecute, }) {
53
+ const currentDevices = state.deviceHandler.readAllDevices();
54
+ const rawInputs = mapObject(currentDevices, (deviceKey, device) => {
55
+ const deviceInputs = {};
56
+ Object.values(device.currentInputs).forEach((currentInput) => {
57
+ const direction = calculateInputDirection(currentInput.inputValue);
58
+ const previousRawInput = state.rawInputs?.[deviceKey]?.[currentInput.inputName];
59
+ const duration = previousRawInput?.direction === direction
60
+ ? {
61
+ milliseconds: Math.round(previousRawInput.duration.milliseconds + msSinceLastExecute),
62
+ }
63
+ : {
64
+ milliseconds: 0,
65
+ };
66
+ const layout = isGamepadDeviceKey(deviceKey)
67
+ ? findMatchingGamepadLayout({
68
+ layouts: state.gamepadLayouts || defaultGamepadLayouts,
69
+ gamepad: {
70
+ deviceName: device.deviceName,
71
+ },
72
+ gamepadModelMap: state.gamepadModelMap || defaultGamepadModelMap,
73
+ })
74
+ : undefined;
75
+ const model = isGamepadDeviceKey(deviceKey)
76
+ ? findMatchingGamepadModel({
77
+ gamepad: {
78
+ deviceName: device.deviceName,
79
+ },
80
+ gamepadBrandMap: state.gamepadBrandMap,
81
+ gamepadModelMap: state.gamepadModelMap,
82
+ })
83
+ : undefined;
84
+ const mappedInputName = layout?.inputMappings[currentInput.inputName];
85
+ const rawInput = {
86
+ mapped: {
87
+ deviceName: model?.gamepadModel || device.deviceName,
88
+ gamepadBrand: model?.gamepadBrand,
89
+ inputName: mappedInputName || currentInput.inputName,
90
+ },
91
+ deviceKey,
92
+ deviceName: device.deviceName,
93
+ deviceType: device.deviceType,
94
+ direction,
95
+ duration,
96
+ inputName: currentInput.inputName,
97
+ inputValue: currentInput.inputValue,
98
+ };
99
+ if (mappedInputName) {
100
+ deviceInputs[mappedInputName] = rawInput;
101
+ }
102
+ deviceInputs[currentInput.inputName] = rawInput;
103
+ });
104
+ return {
105
+ key: deviceKey,
106
+ value: deviceInputs,
107
+ };
108
+ });
109
+ return {
110
+ rawInputs,
111
+ currentDevices: mapToSimpleDevicesMap(currentDevices),
112
+ };
113
+ }
@@ -0,0 +1,81 @@
1
+ import { type SelectFrom } from '@augment-vir/common';
2
+ import { type Duration, type DurationUnit } from 'date-vir';
3
+ import { type AllDevices, type InputDevice, type InputDeviceKey, type InputValueWrapper } from 'input-device-handler';
4
+ /**
5
+ * All possible directions of an input value.
6
+ *
7
+ * @category Internal
8
+ */
9
+ export declare enum InputDirection {
10
+ /** Right at 0. */
11
+ Flat = "flat",
12
+ Negative = "negative",
13
+ Positive = "positive"
14
+ }
15
+ /**
16
+ * Calculate the {@link InputDirection} value of an input value.
17
+ *
18
+ * @category Internal
19
+ */
20
+ export declare function calculateInputDirection(inputValue: number): InputDirection;
21
+ /**
22
+ * An individual raw input. Used in `createAnthaReadRawInputMod` and {@link RawInputs}.
23
+ *
24
+ * @category Internal
25
+ */
26
+ export type RawInput = Omit<InputValueWrapper<InputDeviceKey, any>, 'details'> & {
27
+ mapped: SelectFrom<InputValueWrapper<InputDeviceKey, any>, {
28
+ /**
29
+ * `deviceName` is mapped by `gamepadModelMap`. If no mapping exists, this will always
30
+ * be set to the original `deviceName`.
31
+ */
32
+ deviceName: true;
33
+ /**
34
+ * `deviceKey` is mapped by `gamepadLayouts`. If no mapping exists, this will always be
35
+ * set to the original `inputName`.
36
+ */
37
+ inputName: true;
38
+ }> & {
39
+ /** This will only be populated for gamepad devices. */
40
+ gamepadBrand: undefined | string;
41
+ };
42
+ /** The raw input's direction. */
43
+ direction: InputDirection;
44
+ /** How long this input has been held down in the current direction. */
45
+ duration: Duration<DurationUnit.Milliseconds>;
46
+ };
47
+ /**
48
+ * All raw inputs for all devices. Used in `createAnthaReadRawInputMod` and
49
+ * `AnthaReadRawInputModState`.
50
+ *
51
+ * @category Internal
52
+ */
53
+ export type RawInputs = Partial<Record<InputDeviceKey, {
54
+ [InputName in string]: RawInput;
55
+ }>>;
56
+ /**
57
+ * An input device object. A simpler version of `InputDevice` from the [`input-device-handler`
58
+ * package](https://www.npmjs.com/package/input-device-handler). Used in
59
+ * `createAnthaReadRawInputMod` and {@link SimpleInputDevicesMap}.
60
+ *
61
+ * @category Internal
62
+ */
63
+ export type SimpleInputDevice = Pick<InputDevice, 'deviceKey' | 'deviceName' | 'deviceType'>;
64
+ /**
65
+ * A collection of all current simple input devices. Used in `createAnthaReadRawInputMod` and
66
+ * `AnthaReadRawInputModState`.
67
+ *
68
+ * @category Internal
69
+ */
70
+ export type SimpleInputDevicesMap = Partial<Record<InputDeviceKey, SimpleInputDevice>>;
71
+ /**
72
+ * Maps `AllDevices` to {@link SimpleInputDevicesMap}.
73
+ *
74
+ * @category Internal
75
+ */
76
+ export declare function mapToSimpleDevicesMap(currentDevices: SelectFrom<AllDevices, {
77
+ [Key in InputDeviceKey]?: {
78
+ deviceName: true;
79
+ deviceType: true;
80
+ };
81
+ }>): SimpleInputDevicesMap;
@@ -0,0 +1,43 @@
1
+ import { mapObjectValues } from '@augment-vir/common';
2
+ /**
3
+ * All possible directions of an input value.
4
+ *
5
+ * @category Internal
6
+ */
7
+ export var InputDirection;
8
+ (function (InputDirection) {
9
+ /** Right at 0. */
10
+ InputDirection["Flat"] = "flat";
11
+ InputDirection["Negative"] = "negative";
12
+ InputDirection["Positive"] = "positive";
13
+ })(InputDirection || (InputDirection = {}));
14
+ /**
15
+ * Calculate the {@link InputDirection} value of an input value.
16
+ *
17
+ * @category Internal
18
+ */
19
+ export function calculateInputDirection(inputValue) {
20
+ if (inputValue === 0) {
21
+ return InputDirection.Flat;
22
+ }
23
+ else if (inputValue < 0) {
24
+ return InputDirection.Negative;
25
+ }
26
+ else {
27
+ return InputDirection.Positive;
28
+ }
29
+ }
30
+ /**
31
+ * Maps `AllDevices` to {@link SimpleInputDevicesMap}.
32
+ *
33
+ * @category Internal
34
+ */
35
+ export function mapToSimpleDevicesMap(currentDevices) {
36
+ return mapObjectValues(currentDevices, (deviceKey, device) => {
37
+ return {
38
+ deviceKey,
39
+ deviceName: device.deviceName,
40
+ deviceType: device.deviceType,
41
+ };
42
+ });
43
+ }
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@antha/input",
3
+ "version": "0.0.1",
4
+ "description": "An Antha mod for handling inputs.",
5
+ "keywords": [
6
+ "vir",
7
+ "antha",
8
+ "input"
9
+ ],
10
+ "homepage": "https://github.com/electrovir/antha",
11
+ "bugs": {
12
+ "url": "https://github.com/electrovir/antha/issues"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/electrovir/antha.git"
17
+ },
18
+ "license": "(MIT OR CC0-1.0)",
19
+ "author": {
20
+ "name": "electrovir",
21
+ "url": "https://github.com/electrovir"
22
+ },
23
+ "sideEffects": false,
24
+ "type": "module",
25
+ "main": "dist/index.js",
26
+ "module": "dist/index.js",
27
+ "types": "dist/index.d.ts",
28
+ "scripts": {
29
+ "compile": "virmator compile",
30
+ "docs": "virmator docs",
31
+ "test": "virmator test web",
32
+ "test:coverage": "npm test coverage",
33
+ "test:docs": "virmator docs check"
34
+ },
35
+ "dependencies": {
36
+ "@augment-vir/assert": "^31.73.1",
37
+ "@augment-vir/common": "^31.73.1",
38
+ "date-vir": "^8.5.0",
39
+ "device-navigation": "^4.7.2",
40
+ "gamepad-type": "^2.0.2",
41
+ "input-device-handler": "^9.0.3",
42
+ "object-shape-tester": "^6.14.0",
43
+ "type-fest": "^5.7.0",
44
+ "vira": "^31.24.1"
45
+ },
46
+ "devDependencies": {
47
+ "@augment-vir/test": "^31.73.1",
48
+ "@web/dev-server-esbuild": "^1.0.5",
49
+ "@web/test-runner": "^0.20.2",
50
+ "@web/test-runner-playwright": "^0.11.1",
51
+ "element-vir": "^26.17.0",
52
+ "istanbul-smart-text-reporter": "^1.1.5"
53
+ },
54
+ "peerDependencies": {
55
+ "@antha/engine": "*",
56
+ "element-vir": ">=26"
57
+ },
58
+ "engines": {
59
+ "node": ">=22"
60
+ },
61
+ "publishConfig": {
62
+ "access": "public"
63
+ }
64
+ }