like2d 1.0.0 → 2.0.0
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.
- package/LICENSE +22 -0
- package/README.md +67 -43
- package/dist/adapters/callback/index.d.ts +43 -0
- package/dist/adapters/callback/index.d.ts.map +1 -0
- package/dist/adapters/callback/index.js +80 -0
- package/dist/adapters/scene/index.d.ts +42 -0
- package/dist/adapters/scene/index.d.ts.map +1 -0
- package/dist/adapters/scene/index.js +112 -0
- package/dist/adapters/scene/scene.d.ts +18 -0
- package/dist/adapters/scene/scene.d.ts.map +1 -0
- package/dist/adapters/scene/startup-scene.d.ts +17 -0
- package/dist/adapters/scene/startup-scene.d.ts.map +1 -0
- package/dist/adapters/scene/startup-scene.js +41 -0
- package/dist/core/audio.d.ts +61 -0
- package/dist/core/audio.d.ts.map +1 -0
- package/dist/core/audio.js +226 -0
- package/dist/core/canvas-config.d.ts +22 -0
- package/dist/core/canvas-config.d.ts.map +1 -0
- package/dist/core/canvas-config.js +14 -0
- package/dist/core/canvas-manager.d.ts +26 -0
- package/dist/core/canvas-manager.d.ts.map +1 -0
- package/dist/core/canvas-manager.js +197 -0
- package/dist/core/events.d.ts +52 -0
- package/dist/core/events.d.ts.map +1 -0
- package/dist/core/gamepad-button-map.d.ts.map +1 -0
- package/dist/core/gamepad-buttons.d.ts +23 -0
- package/dist/core/gamepad-buttons.d.ts.map +1 -0
- package/dist/core/gamepad-buttons.js +36 -0
- package/dist/core/gamepad-db.d.ts.map +1 -0
- package/dist/{gamepad-mapping.d.ts → core/gamepad-mapping.d.ts} +3 -15
- package/dist/core/gamepad-mapping.d.ts.map +1 -0
- package/dist/core/gamepad-mapping.js +223 -0
- package/dist/{gamepad.d.ts → core/gamepad.d.ts} +22 -17
- package/dist/core/gamepad.d.ts.map +1 -0
- package/dist/{gamepad.js → core/gamepad.js} +91 -70
- package/dist/{graphics.d.ts → core/graphics.d.ts} +2 -8
- package/dist/core/graphics.d.ts.map +1 -0
- package/dist/{graphics.js → core/graphics.js} +4 -41
- package/dist/core/input-state.d.ts.map +1 -0
- package/dist/{input.d.ts → core/input.d.ts} +11 -14
- package/dist/core/input.d.ts.map +1 -0
- package/dist/{input.js → core/input.js} +31 -41
- package/dist/core/keyboard.d.ts +15 -0
- package/dist/core/keyboard.d.ts.map +1 -0
- package/dist/core/keyboard.js +70 -0
- package/dist/core/mouse.d.ts +29 -0
- package/dist/core/mouse.d.ts.map +1 -0
- package/dist/core/mouse.js +130 -0
- package/dist/{rect.d.ts → core/rect.d.ts} +1 -2
- package/dist/core/rect.d.ts.map +1 -0
- package/dist/{rect.js → core/rect.js} +24 -28
- package/dist/{timer.d.ts → core/timer.d.ts} +0 -1
- package/dist/core/timer.d.ts.map +1 -0
- package/dist/{timer.js → core/timer.js} +0 -1
- package/dist/{vector2.d.ts → core/vector2.d.ts} +4 -10
- package/dist/core/vector2.d.ts.map +1 -0
- package/dist/{vector2.js → core/vector2.js} +40 -40
- package/dist/engine.d.ts +42 -0
- package/dist/engine.d.ts.map +1 -0
- package/dist/engine.js +154 -0
- package/dist/index.d.ts +38 -44
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -250
- package/package.json +8 -23
- package/dist/audio.d.ts +0 -52
- package/dist/audio.d.ts.map +0 -1
- package/dist/audio.js +0 -250
- package/dist/events.d.ts +0 -36
- package/dist/events.d.ts.map +0 -1
- package/dist/gamepad-button-map.d.ts.map +0 -1
- package/dist/gamepad-db.d.ts.map +0 -1
- package/dist/gamepad-mapping.d.ts.map +0 -1
- package/dist/gamepad-mapping.js +0 -191
- package/dist/gamepad.d.ts.map +0 -1
- package/dist/graphics.d.ts.map +0 -1
- package/dist/input-state.d.ts.map +0 -1
- package/dist/input.d.ts.map +0 -1
- package/dist/keyboard.d.ts +0 -9
- package/dist/keyboard.d.ts.map +0 -1
- package/dist/keyboard.js +0 -33
- package/dist/mouse.d.ts +0 -20
- package/dist/mouse.d.ts.map +0 -1
- package/dist/mouse.js +0 -84
- package/dist/rect.d.ts.map +0 -1
- package/dist/scene.d.ts +0 -10
- package/dist/scene.d.ts.map +0 -1
- package/dist/timer.d.ts.map +0 -1
- package/dist/vector2.d.ts.map +0 -1
- /package/dist/{scene.js → adapters/scene/scene.js} +0 -0
- /package/dist/{events.js → core/events.js} +0 -0
- /package/dist/{gamepad-button-map.d.ts → core/gamepad-button-map.d.ts} +0 -0
- /package/dist/{gamepad-button-map.js → core/gamepad-button-map.js} +0 -0
- /package/dist/{gamepad-db.d.ts → core/gamepad-db.d.ts} +0 -0
- /package/dist/{gamepad-db.js → core/gamepad-db.js} +0 -0
- /package/dist/{input-state.d.ts → core/input-state.d.ts} +0 -0
- /package/dist/{input-state.js → core/input-state.js} +0 -0
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/** The audio module performs a few things:
|
|
2
|
+
*
|
|
3
|
+
* ## Make audio resources behave as if synchronous
|
|
4
|
+
* Functions like playback and seeking are deferred until the sound is loaded.
|
|
5
|
+
*
|
|
6
|
+
* ## Track and give global control to all audio objects
|
|
7
|
+
* Start, stop, or set global volume for every currently playing sound.
|
|
8
|
+
*
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Handle to a loaded audio resource.
|
|
12
|
+
* Use `play()`, `stop()`, `pause()`, `resume()` for playback control.
|
|
13
|
+
* Access the underlying HTMLAudioElement via `source.audio` for looping,
|
|
14
|
+
* pitch, etc. Note: Use `source.setVolume()` instead of setting
|
|
15
|
+
* `source.audio.volume` directly to ensure global volume scaling works correctly.
|
|
16
|
+
*/
|
|
17
|
+
export class Source {
|
|
18
|
+
constructor(path, audioRef, options = {}) {
|
|
19
|
+
Object.defineProperty(this, "path", {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
configurable: true,
|
|
22
|
+
writable: true,
|
|
23
|
+
value: void 0
|
|
24
|
+
});
|
|
25
|
+
/** Underlying HTMLAudioElement. Modify directly for looping, pitch, etc. Use methods for playback control. Avoid setting volume directly. */
|
|
26
|
+
Object.defineProperty(this, "audio", {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
configurable: true,
|
|
29
|
+
writable: true,
|
|
30
|
+
value: void 0
|
|
31
|
+
});
|
|
32
|
+
Object.defineProperty(this, "options", {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
configurable: true,
|
|
35
|
+
writable: true,
|
|
36
|
+
value: void 0
|
|
37
|
+
});
|
|
38
|
+
/** Resolves when the audio is loaded and ready to play. */
|
|
39
|
+
Object.defineProperty(this, "ready", {
|
|
40
|
+
enumerable: true,
|
|
41
|
+
configurable: true,
|
|
42
|
+
writable: true,
|
|
43
|
+
value: void 0
|
|
44
|
+
});
|
|
45
|
+
Object.defineProperty(this, "loadState", {
|
|
46
|
+
enumerable: true,
|
|
47
|
+
configurable: true,
|
|
48
|
+
writable: true,
|
|
49
|
+
value: { loaded: false, pendingPlay: false, pendingSeek: 0 }
|
|
50
|
+
});
|
|
51
|
+
Object.defineProperty(this, "audioRef", {
|
|
52
|
+
enumerable: true,
|
|
53
|
+
configurable: true,
|
|
54
|
+
writable: true,
|
|
55
|
+
value: void 0
|
|
56
|
+
});
|
|
57
|
+
this.path = path;
|
|
58
|
+
this.audioRef = audioRef;
|
|
59
|
+
this.audio = document.createElement('audio');
|
|
60
|
+
this.audio.src = path;
|
|
61
|
+
this.options = {
|
|
62
|
+
volume: Math.max(0, Math.min(1, options.volume ?? 1))
|
|
63
|
+
};
|
|
64
|
+
this.audio.volume = this.options.volume * audioRef.getVolume();
|
|
65
|
+
this.ready = new Promise((resolve, reject) => {
|
|
66
|
+
this.audio.oncanplaythrough = () => {
|
|
67
|
+
if (this.loadState.loaded)
|
|
68
|
+
return;
|
|
69
|
+
const { pendingPlay, pendingSeek } = this.loadState;
|
|
70
|
+
this.loadState = { loaded: true };
|
|
71
|
+
this.audio.currentTime = pendingSeek;
|
|
72
|
+
if (pendingPlay) {
|
|
73
|
+
this.audio.play()?.catch(() => {
|
|
74
|
+
// Play failed (autoplay policy) - reset so user can retry
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
resolve();
|
|
78
|
+
};
|
|
79
|
+
this.audio.onerror = () => reject(new Error(`Failed to load audio: ${path}`));
|
|
80
|
+
// Handle audio that is already loaded (cached) when we attach the listener
|
|
81
|
+
if (this.audio.readyState >= 3) {
|
|
82
|
+
this.loadState = { loaded: true };
|
|
83
|
+
resolve();
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
isReady() {
|
|
88
|
+
return this.loadState.loaded;
|
|
89
|
+
}
|
|
90
|
+
play() {
|
|
91
|
+
if (this.loadState.loaded) {
|
|
92
|
+
this.audio.play()?.catch(() => {
|
|
93
|
+
// Play failed (autoplay policy) - ignore
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
this.loadState.pendingPlay = true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
stop() {
|
|
101
|
+
if (this.loadState.loaded) {
|
|
102
|
+
this.audio.pause();
|
|
103
|
+
this.audio.currentTime = 0;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
this.loadState.pendingPlay = false;
|
|
107
|
+
this.loadState.pendingSeek = 0;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
pause() {
|
|
111
|
+
if (this.loadState.loaded) {
|
|
112
|
+
this.audio.pause();
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
this.loadState.pendingPlay = false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
resume() {
|
|
119
|
+
if (this.loadState.loaded) {
|
|
120
|
+
if (this.audio.paused) {
|
|
121
|
+
this.audio.play()?.catch(() => {
|
|
122
|
+
// Play failed (autoplay policy, etc.) - ignore
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
this.loadState.pendingPlay = true;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
seek(position) {
|
|
131
|
+
if (this.loadState.loaded) {
|
|
132
|
+
this.audio.currentTime = position;
|
|
133
|
+
}
|
|
134
|
+
else {
|
|
135
|
+
this.loadState.pendingSeek = position;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
tell() {
|
|
139
|
+
if (this.loadState.loaded)
|
|
140
|
+
return this.audio.currentTime;
|
|
141
|
+
return this.loadState.pendingSeek;
|
|
142
|
+
}
|
|
143
|
+
isPlaying() {
|
|
144
|
+
if (this.loadState.loaded)
|
|
145
|
+
return !this.audio.paused && !this.audio.ended;
|
|
146
|
+
return this.loadState.pendingPlay;
|
|
147
|
+
}
|
|
148
|
+
isPaused() {
|
|
149
|
+
if (this.loadState.loaded)
|
|
150
|
+
return this.audio.paused;
|
|
151
|
+
return !this.loadState.pendingPlay;
|
|
152
|
+
}
|
|
153
|
+
isStopped() {
|
|
154
|
+
if (this.loadState.loaded)
|
|
155
|
+
return this.audio.paused && this.audio.currentTime === 0;
|
|
156
|
+
return !this.loadState.pendingPlay && this.loadState.pendingSeek === 0;
|
|
157
|
+
}
|
|
158
|
+
/** Set volume (0-1). Applies global volume scaling. Prefer this over `source.audio.volume`. */
|
|
159
|
+
setVolume(volume) {
|
|
160
|
+
this.options.volume = Math.max(0, Math.min(1, volume));
|
|
161
|
+
this.audio.volume = this.options.volume * this.audioRef.getVolume();
|
|
162
|
+
}
|
|
163
|
+
getVolume() {
|
|
164
|
+
return this.options.volume;
|
|
165
|
+
}
|
|
166
|
+
getDuration() {
|
|
167
|
+
if (this.loadState.loaded)
|
|
168
|
+
return this.audio.duration;
|
|
169
|
+
return 0;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
export class Audio {
|
|
173
|
+
constructor() {
|
|
174
|
+
Object.defineProperty(this, "sources", {
|
|
175
|
+
enumerable: true,
|
|
176
|
+
configurable: true,
|
|
177
|
+
writable: true,
|
|
178
|
+
value: []
|
|
179
|
+
});
|
|
180
|
+
Object.defineProperty(this, "globalVolume", {
|
|
181
|
+
enumerable: true,
|
|
182
|
+
configurable: true,
|
|
183
|
+
writable: true,
|
|
184
|
+
value: 1
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
newSource(path, options) {
|
|
188
|
+
const source = new Source(path, this, options);
|
|
189
|
+
this.sources.push(new WeakRef(source));
|
|
190
|
+
return source;
|
|
191
|
+
}
|
|
192
|
+
/** Get all audio sources -- note that sources are tracked
|
|
193
|
+
* using weak references, and storing this list can cause
|
|
194
|
+
* a memory leak.
|
|
195
|
+
*/
|
|
196
|
+
getAllSources() {
|
|
197
|
+
const active = [];
|
|
198
|
+
for (const sourceRef of this.sources) {
|
|
199
|
+
const source = sourceRef.deref();
|
|
200
|
+
if (source)
|
|
201
|
+
active.push(source);
|
|
202
|
+
}
|
|
203
|
+
return active;
|
|
204
|
+
}
|
|
205
|
+
stopAll() {
|
|
206
|
+
this.getAllSources().forEach(s => s.stop());
|
|
207
|
+
}
|
|
208
|
+
pauseAll() {
|
|
209
|
+
this.getAllSources().forEach(s => s.pause());
|
|
210
|
+
}
|
|
211
|
+
resumeAll() {
|
|
212
|
+
this.getAllSources().forEach(s => s.resume());
|
|
213
|
+
}
|
|
214
|
+
setVolume(volume) {
|
|
215
|
+
this.globalVolume = Math.max(0, Math.min(1, volume));
|
|
216
|
+
this.getAllSources().forEach(s => {
|
|
217
|
+
s.audio.volume = s.options.volume * this.globalVolume;
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
getVolume() {
|
|
221
|
+
return this.globalVolume;
|
|
222
|
+
}
|
|
223
|
+
clone(source) {
|
|
224
|
+
return this.newSource(source.path, { ...source.options });
|
|
225
|
+
}
|
|
226
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Vector2 } from './vector2';
|
|
2
|
+
export type CanvasMode = 'fixed' | 'native';
|
|
3
|
+
export type CanvasConfig = {
|
|
4
|
+
mode: 'fixed';
|
|
5
|
+
size: Vector2;
|
|
6
|
+
pixelArt?: boolean;
|
|
7
|
+
} | {
|
|
8
|
+
mode: 'native';
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Calculate the scale and offset for rendering fixed-size content to a target canvas.
|
|
12
|
+
* This is useful when you want to render in "native" mode but maintain a fixed game resolution.
|
|
13
|
+
*
|
|
14
|
+
* @param canvasSize - The actual canvas size in pixels
|
|
15
|
+
* @param gameSize - The desired game resolution (fixed size)
|
|
16
|
+
* @returns Object containing the scale factor and offset for centering
|
|
17
|
+
*/
|
|
18
|
+
export declare function calcFixedScale(canvasSize: Vector2, gameSize: Vector2): {
|
|
19
|
+
scale: number;
|
|
20
|
+
offset: Vector2;
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=canvas-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-config.d.ts","sourceRoot":"","sources":["../../src/core/canvas-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5C,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GACpD;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEvB;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAKzG"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calculate the scale and offset for rendering fixed-size content to a target canvas.
|
|
3
|
+
* This is useful when you want to render in "native" mode but maintain a fixed game resolution.
|
|
4
|
+
*
|
|
5
|
+
* @param canvasSize - The actual canvas size in pixels
|
|
6
|
+
* @param gameSize - The desired game resolution (fixed size)
|
|
7
|
+
* @returns Object containing the scale factor and offset for centering
|
|
8
|
+
*/
|
|
9
|
+
export function calcFixedScale(canvasSize, gameSize) {
|
|
10
|
+
const scale = Math.min(canvasSize[0] / gameSize[0], canvasSize[1] / gameSize[1]);
|
|
11
|
+
const scaledGame = [gameSize[0] * scale, gameSize[1] * scale];
|
|
12
|
+
const offset = [(canvasSize[0] - scaledGame[0]) * 0.5, (canvasSize[1] - scaledGame[1]) * 0.5];
|
|
13
|
+
return { scale, offset };
|
|
14
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { CanvasConfig } from './canvas-config';
|
|
2
|
+
import { type Vector2 } from './vector2';
|
|
3
|
+
export declare class CanvasManager {
|
|
4
|
+
private canvas;
|
|
5
|
+
private container;
|
|
6
|
+
private ctx;
|
|
7
|
+
private config;
|
|
8
|
+
private resizeObserver;
|
|
9
|
+
private pixelArtCanvas;
|
|
10
|
+
private pixelArtCtx;
|
|
11
|
+
private onWindowResize;
|
|
12
|
+
private onFullscreenChange;
|
|
13
|
+
onResize: ((size: Vector2, pixelSize: Vector2, fullscreen: boolean) => void) | null;
|
|
14
|
+
constructor(canvas: HTMLCanvasElement, container: HTMLElement, ctx: CanvasRenderingContext2D, config?: CanvasConfig);
|
|
15
|
+
private listenForPixelRatioChanges;
|
|
16
|
+
setConfig(config: CanvasConfig): void;
|
|
17
|
+
getConfig(): CanvasConfig;
|
|
18
|
+
private applyConfig;
|
|
19
|
+
private applyFixedMode;
|
|
20
|
+
private applyNativeMode;
|
|
21
|
+
dispose(): void;
|
|
22
|
+
present(): void;
|
|
23
|
+
getDisplayCanvas(): HTMLCanvasElement;
|
|
24
|
+
transformMousePosition(cssX: number, cssY: number): Vector2;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=canvas-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas-manager.d.ts","sourceRoot":"","sources":["../../src/core/canvas-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AAmB/C,qBAAa,aAAa;IAWtB,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,GAAG;IACX,OAAO,CAAC,MAAM;IAbhB,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,cAAc,CAAkC;IACxD,OAAO,CAAC,WAAW,CAAyC;IAE5D,OAAO,CAAC,cAAc,CAA4B;IAClD,OAAO,CAAC,kBAAkB,CAA4B;IAE/C,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;gBAGxF,MAAM,EAAE,iBAAiB,EACzB,SAAS,EAAE,WAAW,EACtB,GAAG,EAAE,wBAAwB,EAC7B,MAAM,GAAE,YAAiC;IAYnD,OAAO,CAAC,0BAA0B;IAQlC,SAAS,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;IAKrC,SAAS,IAAI,YAAY;IAIzB,OAAO,CAAC,WAAW;IA+BnB,OAAO,CAAC,cAAc;IAiCtB,OAAO,CAAC,eAAe;IAkBvB,OAAO,IAAI,IAAI;IASf,OAAO,IAAI,IAAI;IAaf,gBAAgB,IAAI,iBAAiB;IAIrC,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;CAiB5D"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { Vec2 } from './vector2';
|
|
2
|
+
function setCanvasSize(canvas, size) {
|
|
3
|
+
canvas.width = size[0];
|
|
4
|
+
canvas.height = size[1];
|
|
5
|
+
}
|
|
6
|
+
function setCanvasDisplaySize(canvas, size) {
|
|
7
|
+
canvas.style.width = `${size[0]}px`;
|
|
8
|
+
canvas.style.height = `${size[1]}px`;
|
|
9
|
+
}
|
|
10
|
+
function centerElement(el) {
|
|
11
|
+
el.style.position = 'absolute';
|
|
12
|
+
el.style.left = '50%';
|
|
13
|
+
el.style.top = '50%';
|
|
14
|
+
el.style.transform = 'translate(-50%, -50%)';
|
|
15
|
+
}
|
|
16
|
+
export class CanvasManager {
|
|
17
|
+
constructor(canvas, container, ctx, config = { mode: 'native' }) {
|
|
18
|
+
Object.defineProperty(this, "canvas", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
configurable: true,
|
|
21
|
+
writable: true,
|
|
22
|
+
value: canvas
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(this, "container", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
configurable: true,
|
|
27
|
+
writable: true,
|
|
28
|
+
value: container
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(this, "ctx", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true,
|
|
33
|
+
writable: true,
|
|
34
|
+
value: ctx
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(this, "config", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
configurable: true,
|
|
39
|
+
writable: true,
|
|
40
|
+
value: config
|
|
41
|
+
});
|
|
42
|
+
Object.defineProperty(this, "resizeObserver", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
configurable: true,
|
|
45
|
+
writable: true,
|
|
46
|
+
value: null
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(this, "pixelArtCanvas", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
configurable: true,
|
|
51
|
+
writable: true,
|
|
52
|
+
value: null
|
|
53
|
+
});
|
|
54
|
+
Object.defineProperty(this, "pixelArtCtx", {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
configurable: true,
|
|
57
|
+
writable: true,
|
|
58
|
+
value: null
|
|
59
|
+
});
|
|
60
|
+
Object.defineProperty(this, "onWindowResize", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
configurable: true,
|
|
63
|
+
writable: true,
|
|
64
|
+
value: () => this.applyConfig()
|
|
65
|
+
});
|
|
66
|
+
Object.defineProperty(this, "onFullscreenChange", {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
configurable: true,
|
|
69
|
+
writable: true,
|
|
70
|
+
value: () => this.applyConfig()
|
|
71
|
+
});
|
|
72
|
+
Object.defineProperty(this, "onResize", {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
configurable: true,
|
|
75
|
+
writable: true,
|
|
76
|
+
value: null
|
|
77
|
+
});
|
|
78
|
+
this.resizeObserver = new ResizeObserver(() => this.applyConfig());
|
|
79
|
+
this.resizeObserver.observe(this.container);
|
|
80
|
+
window.addEventListener('resize', this.onWindowResize);
|
|
81
|
+
document.addEventListener('fullscreenchange', this.onFullscreenChange);
|
|
82
|
+
this.listenForPixelRatioChanges();
|
|
83
|
+
this.applyConfig();
|
|
84
|
+
}
|
|
85
|
+
listenForPixelRatioChanges() {
|
|
86
|
+
const media = window.matchMedia(`(resolution: ${window.devicePixelRatio}dppx)`);
|
|
87
|
+
media.addEventListener('change', () => {
|
|
88
|
+
this.applyConfig();
|
|
89
|
+
this.listenForPixelRatioChanges();
|
|
90
|
+
}, { once: true });
|
|
91
|
+
}
|
|
92
|
+
setConfig(config) {
|
|
93
|
+
this.config = config;
|
|
94
|
+
this.applyConfig();
|
|
95
|
+
}
|
|
96
|
+
getConfig() {
|
|
97
|
+
return { ...this.config };
|
|
98
|
+
}
|
|
99
|
+
applyConfig() {
|
|
100
|
+
const containerSize = document.fullscreenElement
|
|
101
|
+
? [document.fullscreenElement.clientWidth, document.fullscreenElement.clientHeight]
|
|
102
|
+
: [this.container.clientWidth, this.container.clientHeight];
|
|
103
|
+
// Always clean up pixel art canvas first
|
|
104
|
+
if (this.pixelArtCanvas) {
|
|
105
|
+
this.pixelArtCanvas.remove();
|
|
106
|
+
this.pixelArtCanvas = null;
|
|
107
|
+
this.pixelArtCtx = null;
|
|
108
|
+
}
|
|
109
|
+
switch (this.config.mode) {
|
|
110
|
+
case 'fixed':
|
|
111
|
+
this.applyFixedMode(containerSize);
|
|
112
|
+
break;
|
|
113
|
+
case 'native':
|
|
114
|
+
this.applyNativeMode(containerSize);
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
const displayCanvas = this.pixelArtCanvas ?? this.canvas;
|
|
118
|
+
const isFullscreen = !!document.fullscreenElement;
|
|
119
|
+
this.onResize?.(containerSize, [displayCanvas.width, displayCanvas.height], isFullscreen);
|
|
120
|
+
}
|
|
121
|
+
applyFixedMode(csize) {
|
|
122
|
+
const { size: gameSize, pixelArt } = this.config;
|
|
123
|
+
const pixelRatio = window.devicePixelRatio || 1;
|
|
124
|
+
const scale = Math.min(csize[0] / gameSize[0], csize[1] / gameSize[1]);
|
|
125
|
+
if (pixelArt) {
|
|
126
|
+
const physicalScale = scale * pixelRatio;
|
|
127
|
+
const intScale = Math.max(1, Math.floor(physicalScale));
|
|
128
|
+
this.pixelArtCanvas = document.createElement('canvas');
|
|
129
|
+
this.pixelArtCtx = this.pixelArtCanvas.getContext('2d');
|
|
130
|
+
setCanvasSize(this.pixelArtCanvas, Vec2.mul(gameSize, intScale));
|
|
131
|
+
setCanvasSize(this.canvas, gameSize);
|
|
132
|
+
this.canvas.style.display = 'none';
|
|
133
|
+
const pac = this.pixelArtCanvas;
|
|
134
|
+
setCanvasDisplaySize(pac, Vec2.mul(gameSize, scale));
|
|
135
|
+
pac.style.maxWidth = '100%';
|
|
136
|
+
pac.style.maxHeight = '100%';
|
|
137
|
+
pac.style.imageRendering = 'auto';
|
|
138
|
+
centerElement(pac);
|
|
139
|
+
this.container.appendChild(pac);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
setCanvasSize(this.canvas, gameSize);
|
|
143
|
+
this.canvas.style.display = 'block';
|
|
144
|
+
setCanvasDisplaySize(this.canvas, Vec2.mul(gameSize, scale));
|
|
145
|
+
this.canvas.style.imageRendering = pixelArt ? 'pixelated' : 'auto';
|
|
146
|
+
this.ctx.imageSmoothingEnabled = !pixelArt;
|
|
147
|
+
centerElement(this.canvas);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
applyNativeMode(csize) {
|
|
151
|
+
const pixelRatio = window.devicePixelRatio || 1;
|
|
152
|
+
const canvasSize = Vec2.mul(csize, pixelRatio);
|
|
153
|
+
setCanvasSize(this.canvas, Vec2.floor(canvasSize));
|
|
154
|
+
setCanvasDisplaySize(this.canvas, csize);
|
|
155
|
+
this.canvas.style.position = 'absolute';
|
|
156
|
+
this.canvas.style.left = '0';
|
|
157
|
+
this.canvas.style.top = '0';
|
|
158
|
+
this.canvas.style.transform = 'none';
|
|
159
|
+
this.canvas.style.margin = '0';
|
|
160
|
+
this.canvas.style.display = 'block';
|
|
161
|
+
this.canvas.style.imageRendering = 'auto';
|
|
162
|
+
this.ctx.setTransform(1, 0, 0, 1, 0, 0);
|
|
163
|
+
}
|
|
164
|
+
dispose() {
|
|
165
|
+
this.resizeObserver?.disconnect();
|
|
166
|
+
window.removeEventListener('resize', this.onWindowResize);
|
|
167
|
+
document.removeEventListener('fullscreenchange', this.onFullscreenChange);
|
|
168
|
+
this.pixelArtCanvas?.remove();
|
|
169
|
+
this.pixelArtCanvas = null;
|
|
170
|
+
this.pixelArtCtx = null;
|
|
171
|
+
}
|
|
172
|
+
present() {
|
|
173
|
+
if (!this.pixelArtCtx || !this.pixelArtCanvas) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
this.pixelArtCtx.imageSmoothingEnabled = false;
|
|
177
|
+
this.pixelArtCtx.drawImage(this.canvas, 0, 0, this.canvas.width, this.canvas.height, 0, 0, this.pixelArtCanvas.width, this.pixelArtCanvas.height);
|
|
178
|
+
}
|
|
179
|
+
getDisplayCanvas() {
|
|
180
|
+
return this.pixelArtCanvas ?? this.canvas;
|
|
181
|
+
}
|
|
182
|
+
transformMousePosition(cssX, cssY) {
|
|
183
|
+
const displayCanvas = this.getDisplayCanvas();
|
|
184
|
+
const rect = displayCanvas.getBoundingClientRect();
|
|
185
|
+
const relative = [cssX - rect.left, cssY - rect.top];
|
|
186
|
+
switch (this.config.mode) {
|
|
187
|
+
case 'fixed': {
|
|
188
|
+
const scale = [displayCanvas.width / rect.width, displayCanvas.height / rect.height];
|
|
189
|
+
return Vec2.mul(relative, scale);
|
|
190
|
+
}
|
|
191
|
+
case 'native':
|
|
192
|
+
default: {
|
|
193
|
+
return Vec2.mul(relative, window.devicePixelRatio || 1);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Vector2 } from './vector2';
|
|
2
|
+
export type Like2DEvent = {
|
|
3
|
+
type: 'load';
|
|
4
|
+
args: [];
|
|
5
|
+
timestamp: number;
|
|
6
|
+
} | {
|
|
7
|
+
type: 'update';
|
|
8
|
+
args: [dt: number];
|
|
9
|
+
timestamp: number;
|
|
10
|
+
} | {
|
|
11
|
+
type: 'draw';
|
|
12
|
+
args: [canvas: HTMLCanvasElement];
|
|
13
|
+
timestamp: number;
|
|
14
|
+
} | {
|
|
15
|
+
type: 'resize';
|
|
16
|
+
args: [size: Vector2, pixelSize: Vector2, fullscreen: boolean];
|
|
17
|
+
timestamp: number;
|
|
18
|
+
} | {
|
|
19
|
+
type: 'keypressed';
|
|
20
|
+
args: [scancode: string, keycode: string];
|
|
21
|
+
timestamp: number;
|
|
22
|
+
} | {
|
|
23
|
+
type: 'keyreleased';
|
|
24
|
+
args: [scancode: string, keycode: string];
|
|
25
|
+
timestamp: number;
|
|
26
|
+
} | {
|
|
27
|
+
type: 'mousepressed';
|
|
28
|
+
args: [x: number, y: number, button: number];
|
|
29
|
+
timestamp: number;
|
|
30
|
+
} | {
|
|
31
|
+
type: 'mousereleased';
|
|
32
|
+
args: [x: number, y: number, button: number];
|
|
33
|
+
timestamp: number;
|
|
34
|
+
} | {
|
|
35
|
+
type: 'gamepadpressed';
|
|
36
|
+
args: [gamepadIndex: number, buttonIndex: number, buttonName: string];
|
|
37
|
+
timestamp: number;
|
|
38
|
+
} | {
|
|
39
|
+
type: 'gamepadreleased';
|
|
40
|
+
args: [gamepadIndex: number, buttonIndex: number, buttonName: string];
|
|
41
|
+
timestamp: number;
|
|
42
|
+
} | {
|
|
43
|
+
type: 'actionpressed';
|
|
44
|
+
args: [action: string];
|
|
45
|
+
timestamp: number;
|
|
46
|
+
} | {
|
|
47
|
+
type: 'actionreleased';
|
|
48
|
+
args: [action: string];
|
|
49
|
+
timestamp: number;
|
|
50
|
+
};
|
|
51
|
+
export type EventType = Like2DEvent['type'];
|
|
52
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/core/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACtE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACrG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACpF;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACrF;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACzF;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC1F;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACpH;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,IAAI,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACrH;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,gBAAgB,CAAC;IAAC,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1E,MAAM,MAAM,SAAS,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gamepad-button-map.d.ts","sourceRoot":"","sources":["../../src/core/gamepad-button-map.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAiCrD,CAAC;AAGF,eAAO,MAAM,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAiBvD,CAAC;AAEF,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAErE"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare namespace GP {
|
|
2
|
+
const Bottom = 0;
|
|
3
|
+
const Right = 1;
|
|
4
|
+
const Left = 2;
|
|
5
|
+
const Top = 3;
|
|
6
|
+
const LB = 4;
|
|
7
|
+
const RB = 5;
|
|
8
|
+
const LT = 6;
|
|
9
|
+
const RT = 7;
|
|
10
|
+
const Back = 8;
|
|
11
|
+
const Start = 9;
|
|
12
|
+
const Guide = 10;
|
|
13
|
+
const LS = 11;
|
|
14
|
+
const RS = 12;
|
|
15
|
+
const DUp = 13;
|
|
16
|
+
const DDown = 14;
|
|
17
|
+
const DLeft = 15;
|
|
18
|
+
const DRight = 16;
|
|
19
|
+
}
|
|
20
|
+
export declare const GP_NAMES: Record<number, string>;
|
|
21
|
+
export declare const GP_NAME_MAP: Record<string, number>;
|
|
22
|
+
export declare function getGPName(buttonIndex: number): string;
|
|
23
|
+
//# sourceMappingURL=gamepad-buttons.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gamepad-buttons.d.ts","sourceRoot":"","sources":["../../src/core/gamepad-buttons.ts"],"names":[],"mappings":"AAGA,yBAAiB,EAAE,CAAC;IAEX,MAAM,MAAM,IAAI,CAAC;IACjB,MAAM,KAAK,IAAI,CAAC;IAChB,MAAM,IAAI,IAAI,CAAC;IACf,MAAM,GAAG,IAAI,CAAC;IAGd,MAAM,EAAE,IAAI,CAAC;IACb,MAAM,EAAE,IAAI,CAAC;IACb,MAAM,EAAE,IAAI,CAAC;IACb,MAAM,EAAE,IAAI,CAAC;IAGb,MAAM,IAAI,IAAI,CAAC;IACf,MAAM,KAAK,IAAI,CAAC;IAChB,MAAM,KAAK,KAAK,CAAC;IAGjB,MAAM,EAAE,KAAK,CAAC;IACd,MAAM,EAAE,KAAK,CAAC;IAGd,MAAM,GAAG,KAAK,CAAC;IACf,MAAM,KAAK,KAAK,CAAC;IACjB,MAAM,KAAK,KAAK,CAAC;IACjB,MAAM,MAAM,KAAK,CAAC;CAC1B;AAMD,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAE3C,CAAC;AAGF,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAkC,CAAC;AAElF,wBAAgB,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAErD"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Gamepad button constants
|
|
2
|
+
// Use these constants instead of magic numbers
|
|
3
|
+
export var GP;
|
|
4
|
+
(function (GP) {
|
|
5
|
+
// Face buttons (physical positions)
|
|
6
|
+
GP.Bottom = 0; // A on Xbox, X on PlayStation, B on Nintendo
|
|
7
|
+
GP.Right = 1; // B on Xbox, O on PlayStation, A on Nintendo
|
|
8
|
+
GP.Left = 2; // X on Xbox, □ on PlayStation, Y on Nintendo
|
|
9
|
+
GP.Top = 3; // Y on Xbox, △ on PlayStation, X on Nintendo
|
|
10
|
+
// Bumpers and triggers
|
|
11
|
+
GP.LB = 4; // Left bumper (L1)
|
|
12
|
+
GP.RB = 5; // Right bumper (R1)
|
|
13
|
+
GP.LT = 6; // Left trigger (L2)
|
|
14
|
+
GP.RT = 7; // Right trigger (R2)
|
|
15
|
+
// Menu buttons
|
|
16
|
+
GP.Back = 8; // Select/Back/Minus
|
|
17
|
+
GP.Start = 9; // Start/Plus
|
|
18
|
+
GP.Guide = 10; // Home/Guide button
|
|
19
|
+
// Stick presses
|
|
20
|
+
GP.LS = 11; // Left stick press (L3)
|
|
21
|
+
GP.RS = 12; // Right stick press (R3)
|
|
22
|
+
// D-Pad
|
|
23
|
+
GP.DUp = 13;
|
|
24
|
+
GP.DDown = 14;
|
|
25
|
+
GP.DLeft = 15;
|
|
26
|
+
GP.DRight = 16;
|
|
27
|
+
})(GP || (GP = {}));
|
|
28
|
+
// Build reverse mappings programmatically
|
|
29
|
+
const GP_ENTRIES = Object.entries(GP);
|
|
30
|
+
// Map button index to name (for debugging/display)
|
|
31
|
+
export const GP_NAMES = Object.fromEntries(GP_ENTRIES.map(([name, index]) => [index, name]));
|
|
32
|
+
// Map name to button index (for action system parsing)
|
|
33
|
+
export const GP_NAME_MAP = Object.fromEntries(GP_ENTRIES);
|
|
34
|
+
export function getGPName(buttonIndex) {
|
|
35
|
+
return GP_NAMES[buttonIndex] ?? `Button${buttonIndex}`;
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gamepad-db.d.ts","sourceRoot":"","sources":["../../src/core/gamepad-db.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IAEjB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE7B,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAE1B,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAGD,eAAO,MAAM,WAAW,qQASd,CAAC;AAEX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAGrD,eAAO,MAAM,QAAQ,iDAGX,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;AAEhD,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAwC;IACxD,OAAO,CAAC,kBAAkB,CAAwC;IAClE,OAAO,CAAC,MAAM,CAAS;IAEvB,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IA0B7B,OAAO,CAAC,uBAAuB;IAU/B;;OAEG;IACH,QAAQ,IAAI,OAAO;IAInB;;OAEG;IACH,eAAe,IAAI,MAAM;IAIzB;;OAEG;IACH,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAIvD,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS;IAKzF;;OAEG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIpC;;OAEG;IACH,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,EAAE;IAa5D;;OAEG;IACH,OAAO,CAAC,SAAS;CAiFlB;AAGD,eAAO,MAAM,eAAe,iBAAwB,CAAC"}
|
|
@@ -1,30 +1,18 @@
|
|
|
1
1
|
export interface ButtonMapping {
|
|
2
2
|
toStandard: Map<number, number>;
|
|
3
|
-
fromStandard: Map<number, number>;
|
|
4
3
|
controllerName: string;
|
|
5
4
|
hasMapping: boolean;
|
|
5
|
+
vendor: number | null;
|
|
6
|
+
product: number | null;
|
|
6
7
|
}
|
|
7
8
|
export declare class GamepadMapping {
|
|
8
|
-
private mappings;
|
|
9
9
|
private dbLoaded;
|
|
10
10
|
loadDatabase(): Promise<void>;
|
|
11
|
-
/**
|
|
12
|
-
* Load database from raw text content
|
|
13
|
-
*/
|
|
14
11
|
loadDatabaseFromText(content: string): void;
|
|
15
12
|
/**
|
|
16
|
-
* Get
|
|
13
|
+
* Get button mapping for a specific gamepad
|
|
17
14
|
*/
|
|
18
15
|
getMapping(gamepad: Gamepad): ButtonMapping;
|
|
19
|
-
/**
|
|
20
|
-
* Clear all cached mappings
|
|
21
|
-
*/
|
|
22
|
-
clear(): void;
|
|
23
|
-
/**
|
|
24
|
-
* Create a new button mapping for a gamepad
|
|
25
|
-
*/
|
|
26
|
-
private createMapping;
|
|
27
|
-
private findDatabaseMapping;
|
|
28
16
|
private extractVendorProduct;
|
|
29
17
|
}
|
|
30
18
|
export declare const gamepadMapping: GamepadMapping;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gamepad-mapping.d.ts","sourceRoot":"","sources":["../../src/core/gamepad-mapping.ts"],"names":[],"mappings":"AA+HA,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAS;IAEnB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IA+BnC,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAK3C;;OAEG;IACH,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa;IAsC3C,OAAO,CAAC,oBAAoB;CAuB7B;AAUD,eAAO,MAAM,cAAc,gBAAuB,CAAC"}
|