@flare-engine/input 0.3.0 → 0.4.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/README.md +3 -1
- package/dist/index.d.mts +37 -10
- package/dist/index.d.mts.map +1 -1
- package/dist/index.d.ts +37 -10
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +101 -39
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +102 -39
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# @flare-engine/input
|
|
2
2
|
|
|
3
|
-
Pointer / touch / gesture / virtual-control / gamepad / keyboard input. `InputManager` polls per frame; `Pointer` exposes primary touch with `isDown` / `justPressed` / `delta
|
|
3
|
+
Pointer / touch / gesture / virtual-control / gamepad / keyboard input. `InputManager` polls per frame; `Pointer` exposes the primary touch (the finger that started the current gesture) with `isDown` / `justPressed` / `delta` — other simultaneous touches reach only `touches[]`, never `pointer`, and when the primary lifts it does not transfer to a remaining finger: `pointer` stays unset until every touch is up and a fresh press starts a new primary; `GestureDetector` emits tap / swipe / pinch / long-press; data-only `VirtualJoystick` + `VirtualButton` state (RN components live in `@flare-engine/react`); `GamepadSource` + `RemapTable` cover gamepad polling and persistent rebinds; `createKeyboard` provides buffered `isDown` / `wasPressed` / `wasReleased` edges per `KeyboardEvent.code` with blur-clears-held semantics.
|
|
4
|
+
|
|
5
|
+
Per-frame edge flags come in two deliberate shapes: per-thing boolean fields (`Pointer.justPressed/justReleased`, `VirtualButtonState.justPressed/justReleased`, `GamepadButtonState.justPressed/justReleased`) for state you already hold a reference to, and keyed query functions (`KeyboardState.wasPressed/wasReleased(code)`, `wasButtonPressed/wasButtonReleased(state, button)`) for state addressed by an id.
|
|
4
6
|
|
|
5
7
|
## Install
|
|
6
8
|
|
package/dist/index.d.mts
CHANGED
|
@@ -41,9 +41,9 @@ interface GamepadButtonState {
|
|
|
41
41
|
pressed: boolean;
|
|
42
42
|
value: number;
|
|
43
43
|
/** True for exactly one frame after a press. */
|
|
44
|
-
|
|
44
|
+
justPressed: boolean;
|
|
45
45
|
/** True for exactly one frame after a release. */
|
|
46
|
-
|
|
46
|
+
justReleased: boolean;
|
|
47
47
|
}
|
|
48
48
|
interface GamepadState {
|
|
49
49
|
connected: boolean;
|
|
@@ -68,7 +68,7 @@ interface GamepadSnapshot {
|
|
|
68
68
|
declare function createGamepadState(index?: number, buttonCount?: number, axisCount?: number): GamepadState;
|
|
69
69
|
/**
|
|
70
70
|
* Apply a fresh snapshot to an existing `GamepadState` in place. Derived
|
|
71
|
-
* `
|
|
71
|
+
* `justPressed` / `justReleased` flags are recomputed from the
|
|
72
72
|
* previous `pressed` value.
|
|
73
73
|
*
|
|
74
74
|
* `deadZone` in [0, 1). Values at or below are treated as 0.
|
|
@@ -91,6 +91,11 @@ declare function getAxis(state: GamepadState, axis: number): number;
|
|
|
91
91
|
* - `createWebGamepadSource()` wraps the W3C `navigator.getGamepads` API.
|
|
92
92
|
* - Native implementations (e.g., `react-native-gamepad`) inject their own
|
|
93
93
|
* via the `GamepadSource` interface — the package itself ships no native deps.
|
|
94
|
+
*
|
|
95
|
+
* **Freshness contract:** each call returns fresh objects. An implementation
|
|
96
|
+
* must not reuse or mutate a snapshot (or its `buttons`/`axes` arrays) that a
|
|
97
|
+
* previous `poll()` call returned. A caller may therefore retain a returned
|
|
98
|
+
* snapshot across frames without it changing out from under them.
|
|
94
99
|
*/
|
|
95
100
|
interface GamepadSource {
|
|
96
101
|
poll(): (GamepadSnapshot | null)[];
|
|
@@ -159,7 +164,8 @@ declare class GestureDetector {
|
|
|
159
164
|
private swipeMinDistance;
|
|
160
165
|
private swipeMaxDuration;
|
|
161
166
|
private _startPos;
|
|
162
|
-
|
|
167
|
+
/** Elapsed time (seconds) since `pointerDown` for the in-progress press. */
|
|
168
|
+
private _elapsed;
|
|
163
169
|
private _isTracking;
|
|
164
170
|
private _longPressFired;
|
|
165
171
|
private _pinchStartDistance;
|
|
@@ -167,8 +173,18 @@ declare class GestureDetector {
|
|
|
167
173
|
constructor(config?: GestureConfig);
|
|
168
174
|
/** Feed a pointer-down event. */
|
|
169
175
|
pointerDown(x: number, y: number): void;
|
|
170
|
-
/**
|
|
171
|
-
|
|
176
|
+
/**
|
|
177
|
+
* Feed a pointer-up event.
|
|
178
|
+
*
|
|
179
|
+
* `elapsedSinceDown` is optional: pass it when the host tracks its own
|
|
180
|
+
* timestamps (e.g. event-driven, no per-frame `update()` calls); omit it
|
|
181
|
+
* to use the elapsed time already accumulated via `update(dt, ...)`. Either
|
|
182
|
+
* way there is one clock per press — passing it here re-syncs the same
|
|
183
|
+
* accumulator `update()` advances, rather than racing it. If a long press
|
|
184
|
+
* already fired for this press, tap/swipe are suppressed so one press
|
|
185
|
+
* yields exactly one gesture.
|
|
186
|
+
*/
|
|
187
|
+
pointerUp(x: number, y: number, elapsedSinceDown?: number): void;
|
|
172
188
|
/**
|
|
173
189
|
* Update gesture tracking. Call each frame with dt.
|
|
174
190
|
* @param dt Delta time in seconds.
|
|
@@ -225,8 +241,6 @@ interface KeyboardState {
|
|
|
225
241
|
}
|
|
226
242
|
/** Create a fresh keyboard state. */
|
|
227
243
|
declare function createKeyboard(): KeyboardState;
|
|
228
|
-
/** Free-function parity with `resetPointerFrame`. Delegates to `kb.reset()`. */
|
|
229
|
-
declare function resetKeyboardFrame(kb: KeyboardState): void;
|
|
230
244
|
/**
|
|
231
245
|
* Web turnkey adapter: registers `keydown`, `keyup`, and `blur` listeners on
|
|
232
246
|
* `target`. `blur` calls `kb.clear()` (stuck-key guard). Returns a detach fn.
|
|
@@ -336,13 +350,26 @@ declare function loadRemap(store: RemapStore, key: string): Promise<RemapTable |
|
|
|
336
350
|
* Feed events from the platform (RN touch/gesture handlers) via the on* methods.
|
|
337
351
|
*/
|
|
338
352
|
declare class InputManager {
|
|
339
|
-
/**
|
|
353
|
+
/**
|
|
354
|
+
* Primary pointer — the touch that started the current gesture (first
|
|
355
|
+
* `onPointerDown` while no touch was active), or the mouse.
|
|
356
|
+
*
|
|
357
|
+
* Once assigned, the primary id stays fixed to that touch until it lifts;
|
|
358
|
+
* it does NOT transfer to a remaining finger. While a second finger is
|
|
359
|
+
* down, its events reach only `touches` — `pointer` neither moves nor
|
|
360
|
+
* releases because of it. When the primary lifts, `pointer.isDown` goes
|
|
361
|
+
* false even if other fingers remain down, and a new primary is assigned
|
|
362
|
+
* only once every touch has lifted and a fresh `onPointerDown` arrives.
|
|
363
|
+
* This keeps `pointer` a single continuous stream with no mid-gesture
|
|
364
|
+
* teleport; read `touches` for anything beyond one finger.
|
|
365
|
+
*/
|
|
340
366
|
readonly pointer: Pointer;
|
|
341
367
|
/** Buffered keyboard state. Feed via `attachKeyboardListeners` (web) or `keyboard.keyDown`/`keyUp` (mobile/RN). */
|
|
342
368
|
readonly keyboard: KeyboardState;
|
|
343
369
|
/** All active touch points. */
|
|
344
370
|
readonly touches: TouchPoint[];
|
|
345
371
|
private _touchMap;
|
|
372
|
+
private _primaryTouchId;
|
|
346
373
|
private _gamepads;
|
|
347
374
|
private _gamepadDeadZone;
|
|
348
375
|
private _gamepadRemaps;
|
|
@@ -420,5 +447,5 @@ declare function updateJoystick(state: VirtualJoystickState, centerX: number, ce
|
|
|
420
447
|
/** Reset joystick state when touch is released. */
|
|
421
448
|
declare function releaseJoystick(state: VirtualJoystickState): void;
|
|
422
449
|
//#endregion
|
|
423
|
-
export { type AxisMap, GamepadAxis, type GamepadAxisId, GamepadButton, type GamepadButtonId, type GamepadButtonState, type GamepadSnapshot, type GamepadSource, type GamepadState, type GestureConfig, GestureDetector, InputManager, type KeyBindings, type KeyboardEventLike, type KeyboardEventTargetLike, type KeyboardState, type PinchEvent, type Pointer, type RemapStore, type RemapTable, type SwipeDirection, type SwipeEvent, type TouchPoint, type VirtualButtonState, type VirtualJoystickConfig, type VirtualJoystickState, applyRemap, attachKeyboardListeners, createButtonState, createGamepadState, createIdentityRemap, createJoystickState, createKeyboard, createPointer, createWebGamepadSource, getAxis, isActionDown, isButtonDown, loadRemap, pointerDown, pointerMove, pointerUp, pressButton, releaseButton, releaseJoystick, resetButtonFrame, resetGamepadFrame,
|
|
450
|
+
export { type AxisMap, GamepadAxis, type GamepadAxisId, GamepadButton, type GamepadButtonId, type GamepadButtonState, type GamepadSnapshot, type GamepadSource, type GamepadState, type GestureConfig, GestureDetector, InputManager, type KeyBindings, type KeyboardEventLike, type KeyboardEventTargetLike, type KeyboardState, type PinchEvent, type Pointer, type RemapStore, type RemapTable, type SwipeDirection, type SwipeEvent, type TouchPoint, type VirtualButtonState, type VirtualJoystickConfig, type VirtualJoystickState, applyRemap, attachKeyboardListeners, createButtonState, createGamepadState, createIdentityRemap, createJoystickState, createKeyboard, createPointer, createWebGamepadSource, getAxis, isActionDown, isButtonDown, loadRemap, pointerDown, pointerMove, pointerUp, pressButton, releaseButton, releaseJoystick, resetButtonFrame, resetGamepadFrame, resetPointerFrame, saveRemap, updateGamepadFromSnapshot, updateJoystick, wasActionPressed, wasActionReleased, wasButtonPressed, wasButtonReleased };
|
|
424
451
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/gamepad.ts","../src/gamepad-source.ts","../src/gestures.ts","../src/keyboard.ts","../src/pointer.ts","../src/remap.ts","../src/input-manager.ts","../src/virtual-button.ts","../src/virtual-joystick.ts"],"mappings":";;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/gamepad.ts","../src/gamepad-source.ts","../src/gestures.ts","../src/keyboard.ts","../src/pointer.ts","../src/remap.ts","../src/input-manager.ts","../src/virtual-button.ts","../src/virtual-joystick.ts"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -41,9 +41,9 @@ interface GamepadButtonState {
|
|
|
41
41
|
pressed: boolean;
|
|
42
42
|
value: number;
|
|
43
43
|
/** True for exactly one frame after a press. */
|
|
44
|
-
|
|
44
|
+
justPressed: boolean;
|
|
45
45
|
/** True for exactly one frame after a release. */
|
|
46
|
-
|
|
46
|
+
justReleased: boolean;
|
|
47
47
|
}
|
|
48
48
|
interface GamepadState {
|
|
49
49
|
connected: boolean;
|
|
@@ -68,7 +68,7 @@ interface GamepadSnapshot {
|
|
|
68
68
|
declare function createGamepadState(index?: number, buttonCount?: number, axisCount?: number): GamepadState;
|
|
69
69
|
/**
|
|
70
70
|
* Apply a fresh snapshot to an existing `GamepadState` in place. Derived
|
|
71
|
-
* `
|
|
71
|
+
* `justPressed` / `justReleased` flags are recomputed from the
|
|
72
72
|
* previous `pressed` value.
|
|
73
73
|
*
|
|
74
74
|
* `deadZone` in [0, 1). Values at or below are treated as 0.
|
|
@@ -91,6 +91,11 @@ declare function getAxis(state: GamepadState, axis: number): number;
|
|
|
91
91
|
* - `createWebGamepadSource()` wraps the W3C `navigator.getGamepads` API.
|
|
92
92
|
* - Native implementations (e.g., `react-native-gamepad`) inject their own
|
|
93
93
|
* via the `GamepadSource` interface — the package itself ships no native deps.
|
|
94
|
+
*
|
|
95
|
+
* **Freshness contract:** each call returns fresh objects. An implementation
|
|
96
|
+
* must not reuse or mutate a snapshot (or its `buttons`/`axes` arrays) that a
|
|
97
|
+
* previous `poll()` call returned. A caller may therefore retain a returned
|
|
98
|
+
* snapshot across frames without it changing out from under them.
|
|
94
99
|
*/
|
|
95
100
|
interface GamepadSource {
|
|
96
101
|
poll(): (GamepadSnapshot | null)[];
|
|
@@ -159,7 +164,8 @@ declare class GestureDetector {
|
|
|
159
164
|
private swipeMinDistance;
|
|
160
165
|
private swipeMaxDuration;
|
|
161
166
|
private _startPos;
|
|
162
|
-
|
|
167
|
+
/** Elapsed time (seconds) since `pointerDown` for the in-progress press. */
|
|
168
|
+
private _elapsed;
|
|
163
169
|
private _isTracking;
|
|
164
170
|
private _longPressFired;
|
|
165
171
|
private _pinchStartDistance;
|
|
@@ -167,8 +173,18 @@ declare class GestureDetector {
|
|
|
167
173
|
constructor(config?: GestureConfig);
|
|
168
174
|
/** Feed a pointer-down event. */
|
|
169
175
|
pointerDown(x: number, y: number): void;
|
|
170
|
-
/**
|
|
171
|
-
|
|
176
|
+
/**
|
|
177
|
+
* Feed a pointer-up event.
|
|
178
|
+
*
|
|
179
|
+
* `elapsedSinceDown` is optional: pass it when the host tracks its own
|
|
180
|
+
* timestamps (e.g. event-driven, no per-frame `update()` calls); omit it
|
|
181
|
+
* to use the elapsed time already accumulated via `update(dt, ...)`. Either
|
|
182
|
+
* way there is one clock per press — passing it here re-syncs the same
|
|
183
|
+
* accumulator `update()` advances, rather than racing it. If a long press
|
|
184
|
+
* already fired for this press, tap/swipe are suppressed so one press
|
|
185
|
+
* yields exactly one gesture.
|
|
186
|
+
*/
|
|
187
|
+
pointerUp(x: number, y: number, elapsedSinceDown?: number): void;
|
|
172
188
|
/**
|
|
173
189
|
* Update gesture tracking. Call each frame with dt.
|
|
174
190
|
* @param dt Delta time in seconds.
|
|
@@ -225,8 +241,6 @@ interface KeyboardState {
|
|
|
225
241
|
}
|
|
226
242
|
/** Create a fresh keyboard state. */
|
|
227
243
|
declare function createKeyboard(): KeyboardState;
|
|
228
|
-
/** Free-function parity with `resetPointerFrame`. Delegates to `kb.reset()`. */
|
|
229
|
-
declare function resetKeyboardFrame(kb: KeyboardState): void;
|
|
230
244
|
/**
|
|
231
245
|
* Web turnkey adapter: registers `keydown`, `keyup`, and `blur` listeners on
|
|
232
246
|
* `target`. `blur` calls `kb.clear()` (stuck-key guard). Returns a detach fn.
|
|
@@ -336,13 +350,26 @@ declare function loadRemap(store: RemapStore, key: string): Promise<RemapTable |
|
|
|
336
350
|
* Feed events from the platform (RN touch/gesture handlers) via the on* methods.
|
|
337
351
|
*/
|
|
338
352
|
declare class InputManager {
|
|
339
|
-
/**
|
|
353
|
+
/**
|
|
354
|
+
* Primary pointer — the touch that started the current gesture (first
|
|
355
|
+
* `onPointerDown` while no touch was active), or the mouse.
|
|
356
|
+
*
|
|
357
|
+
* Once assigned, the primary id stays fixed to that touch until it lifts;
|
|
358
|
+
* it does NOT transfer to a remaining finger. While a second finger is
|
|
359
|
+
* down, its events reach only `touches` — `pointer` neither moves nor
|
|
360
|
+
* releases because of it. When the primary lifts, `pointer.isDown` goes
|
|
361
|
+
* false even if other fingers remain down, and a new primary is assigned
|
|
362
|
+
* only once every touch has lifted and a fresh `onPointerDown` arrives.
|
|
363
|
+
* This keeps `pointer` a single continuous stream with no mid-gesture
|
|
364
|
+
* teleport; read `touches` for anything beyond one finger.
|
|
365
|
+
*/
|
|
340
366
|
readonly pointer: Pointer;
|
|
341
367
|
/** Buffered keyboard state. Feed via `attachKeyboardListeners` (web) or `keyboard.keyDown`/`keyUp` (mobile/RN). */
|
|
342
368
|
readonly keyboard: KeyboardState;
|
|
343
369
|
/** All active touch points. */
|
|
344
370
|
readonly touches: TouchPoint[];
|
|
345
371
|
private _touchMap;
|
|
372
|
+
private _primaryTouchId;
|
|
346
373
|
private _gamepads;
|
|
347
374
|
private _gamepadDeadZone;
|
|
348
375
|
private _gamepadRemaps;
|
|
@@ -420,5 +447,5 @@ declare function updateJoystick(state: VirtualJoystickState, centerX: number, ce
|
|
|
420
447
|
/** Reset joystick state when touch is released. */
|
|
421
448
|
declare function releaseJoystick(state: VirtualJoystickState): void;
|
|
422
449
|
//#endregion
|
|
423
|
-
export { type AxisMap, GamepadAxis, type GamepadAxisId, GamepadButton, type GamepadButtonId, type GamepadButtonState, type GamepadSnapshot, type GamepadSource, type GamepadState, type GestureConfig, GestureDetector, InputManager, type KeyBindings, type KeyboardEventLike, type KeyboardEventTargetLike, type KeyboardState, type PinchEvent, type Pointer, type RemapStore, type RemapTable, type SwipeDirection, type SwipeEvent, type TouchPoint, type VirtualButtonState, type VirtualJoystickConfig, type VirtualJoystickState, applyRemap, attachKeyboardListeners, createButtonState, createGamepadState, createIdentityRemap, createJoystickState, createKeyboard, createPointer, createWebGamepadSource, getAxis, isActionDown, isButtonDown, loadRemap, pointerDown, pointerMove, pointerUp, pressButton, releaseButton, releaseJoystick, resetButtonFrame, resetGamepadFrame,
|
|
450
|
+
export { type AxisMap, GamepadAxis, type GamepadAxisId, GamepadButton, type GamepadButtonId, type GamepadButtonState, type GamepadSnapshot, type GamepadSource, type GamepadState, type GestureConfig, GestureDetector, InputManager, type KeyBindings, type KeyboardEventLike, type KeyboardEventTargetLike, type KeyboardState, type PinchEvent, type Pointer, type RemapStore, type RemapTable, type SwipeDirection, type SwipeEvent, type TouchPoint, type VirtualButtonState, type VirtualJoystickConfig, type VirtualJoystickState, applyRemap, attachKeyboardListeners, createButtonState, createGamepadState, createIdentityRemap, createJoystickState, createKeyboard, createPointer, createWebGamepadSource, getAxis, isActionDown, isButtonDown, loadRemap, pointerDown, pointerMove, pointerUp, pressButton, releaseButton, releaseJoystick, resetButtonFrame, resetGamepadFrame, resetPointerFrame, saveRemap, updateGamepadFromSnapshot, updateJoystick, wasActionPressed, wasActionReleased, wasButtonPressed, wasButtonReleased };
|
|
424
451
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/gamepad.ts","../src/gamepad-source.ts","../src/gestures.ts","../src/keyboard.ts","../src/pointer.ts","../src/remap.ts","../src/input-manager.ts","../src/virtual-button.ts","../src/virtual-joystick.ts"],"mappings":";;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/gamepad.ts","../src/gamepad-source.ts","../src/gestures.ts","../src/keyboard.ts","../src/pointer.ts","../src/remap.ts","../src/input-manager.ts","../src/virtual-button.ts","../src/virtual-joystick.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,16 @@ let _flare_engine_events = require("@flare-engine/events");
|
|
|
8
8
|
* default. Callers can translate raw indices via `remap.ts` before feeding
|
|
9
9
|
* snapshots into `updateGamepadFromSnapshot`.
|
|
10
10
|
*/
|
|
11
|
+
/**
|
|
12
|
+
* Dev-flag access for the dead-zone guard, which runs per axis per frame. Read
|
|
13
|
+
* as a `globalThis` property rather than a bare `__DEV__` identifier for the
|
|
14
|
+
* reason measured in PERF-10 (~0.46 ns vs ~270 ns on JSC).
|
|
15
|
+
*/
|
|
16
|
+
const G$1 = globalThis;
|
|
17
|
+
/** Warn at most once per process; a bad dead zone repeats every frame. */
|
|
18
|
+
let _warnedDeadZone = false;
|
|
19
|
+
/** Largest dead zone that still leaves the rescale well-defined. */
|
|
20
|
+
const MAX_DEAD_ZONE = .99;
|
|
11
21
|
/** W3C Standard Gamepad button indices. */
|
|
12
22
|
const GamepadButton = {
|
|
13
23
|
A: 0,
|
|
@@ -40,8 +50,8 @@ function createGamepadState(index = 0, buttonCount = 17, axisCount = 4) {
|
|
|
40
50
|
for (let i = 0; i < buttonCount; i++) buttons[i] = {
|
|
41
51
|
pressed: false,
|
|
42
52
|
value: 0,
|
|
43
|
-
|
|
44
|
-
|
|
53
|
+
justPressed: false,
|
|
54
|
+
justReleased: false
|
|
45
55
|
};
|
|
46
56
|
return {
|
|
47
57
|
connected: false,
|
|
@@ -53,13 +63,21 @@ function createGamepadState(index = 0, buttonCount = 17, axisCount = 4) {
|
|
|
53
63
|
};
|
|
54
64
|
}
|
|
55
65
|
function applyDeadZone(value, deadZone) {
|
|
66
|
+
let dz = deadZone;
|
|
67
|
+
if (!(dz >= 0 && dz < 1)) {
|
|
68
|
+
if (G$1.__DEV__ && !_warnedDeadZone) {
|
|
69
|
+
_warnedDeadZone = true;
|
|
70
|
+
console.warn(`[flare-engine/input] deadZone=${deadZone} is outside [0, 1); clamping. Values at or above 1 would suppress the axis entirely.`);
|
|
71
|
+
}
|
|
72
|
+
dz = dz >= 1 ? MAX_DEAD_ZONE : 0;
|
|
73
|
+
}
|
|
56
74
|
const abs = Math.abs(value);
|
|
57
|
-
if (abs
|
|
58
|
-
return (value < 0 ? -1 : 1) * ((abs -
|
|
75
|
+
if (!(abs > dz)) return 0;
|
|
76
|
+
return (value < 0 ? -1 : 1) * ((abs - dz) / (1 - dz));
|
|
59
77
|
}
|
|
60
78
|
/**
|
|
61
79
|
* Apply a fresh snapshot to an existing `GamepadState` in place. Derived
|
|
62
|
-
* `
|
|
80
|
+
* `justPressed` / `justReleased` flags are recomputed from the
|
|
63
81
|
* previous `pressed` value.
|
|
64
82
|
*
|
|
65
83
|
* `deadZone` in [0, 1). Values at or below are treated as 0.
|
|
@@ -73,8 +91,8 @@ function updateGamepadFromSnapshot(state, snapshot, deadZone = 0) {
|
|
|
73
91
|
for (let i = 0; i < state.buttons.length; i++) {
|
|
74
92
|
const b = state.buttons[i];
|
|
75
93
|
if (!b) continue;
|
|
76
|
-
b.
|
|
77
|
-
b.
|
|
94
|
+
b.justPressed = false;
|
|
95
|
+
b.justReleased = b.pressed;
|
|
78
96
|
b.pressed = false;
|
|
79
97
|
b.value = 0;
|
|
80
98
|
}
|
|
@@ -93,17 +111,17 @@ function updateGamepadFromSnapshot(state, snapshot, deadZone = 0) {
|
|
|
93
111
|
const prev = state.buttons[i];
|
|
94
112
|
const src = srcButtons[i];
|
|
95
113
|
if (!prev || !src) continue;
|
|
96
|
-
const
|
|
114
|
+
const wasDown = prev.pressed;
|
|
97
115
|
prev.pressed = src.pressed;
|
|
98
116
|
prev.value = src.value;
|
|
99
|
-
prev.
|
|
100
|
-
prev.
|
|
117
|
+
prev.justPressed = src.pressed && !wasDown;
|
|
118
|
+
prev.justReleased = !src.pressed && wasDown;
|
|
101
119
|
}
|
|
102
120
|
for (let i = bLen; i < state.buttons.length; i++) {
|
|
103
121
|
const b = state.buttons[i];
|
|
104
122
|
if (!b) continue;
|
|
105
|
-
b.
|
|
106
|
-
b.
|
|
123
|
+
b.justPressed = false;
|
|
124
|
+
b.justReleased = b.pressed;
|
|
107
125
|
b.pressed = false;
|
|
108
126
|
b.value = 0;
|
|
109
127
|
}
|
|
@@ -119,8 +137,8 @@ function clearFrameFlags(state) {
|
|
|
119
137
|
for (let i = 0; i < state.buttons.length; i++) {
|
|
120
138
|
const b = state.buttons[i];
|
|
121
139
|
if (!b) continue;
|
|
122
|
-
b.
|
|
123
|
-
b.
|
|
140
|
+
b.justPressed = false;
|
|
141
|
+
b.justReleased = false;
|
|
124
142
|
}
|
|
125
143
|
}
|
|
126
144
|
function anyButtonDown(state) {
|
|
@@ -131,10 +149,10 @@ function isButtonDown(state, button) {
|
|
|
131
149
|
return state.buttons[button]?.pressed ?? false;
|
|
132
150
|
}
|
|
133
151
|
function wasButtonPressed(state, button) {
|
|
134
|
-
return state.buttons[button]?.
|
|
152
|
+
return state.buttons[button]?.justPressed ?? false;
|
|
135
153
|
}
|
|
136
154
|
function wasButtonReleased(state, button) {
|
|
137
|
-
return state.buttons[button]?.
|
|
155
|
+
return state.buttons[button]?.justReleased ?? false;
|
|
138
156
|
}
|
|
139
157
|
function getAxis(state, axis) {
|
|
140
158
|
return state.axes[axis] ?? 0;
|
|
@@ -206,7 +224,8 @@ var GestureDetector = class {
|
|
|
206
224
|
x: 0,
|
|
207
225
|
y: 0
|
|
208
226
|
};
|
|
209
|
-
|
|
227
|
+
/** Elapsed time (seconds) since `pointerDown` for the in-progress press. */
|
|
228
|
+
_elapsed = 0;
|
|
210
229
|
_isTracking = false;
|
|
211
230
|
_longPressFired = false;
|
|
212
231
|
_pinchStartDistance = 0;
|
|
@@ -224,18 +243,30 @@ var GestureDetector = class {
|
|
|
224
243
|
x,
|
|
225
244
|
y
|
|
226
245
|
};
|
|
227
|
-
this.
|
|
246
|
+
this._elapsed = 0;
|
|
228
247
|
this._isTracking = true;
|
|
229
248
|
this._longPressFired = false;
|
|
230
249
|
}
|
|
231
|
-
/**
|
|
250
|
+
/**
|
|
251
|
+
* Feed a pointer-up event.
|
|
252
|
+
*
|
|
253
|
+
* `elapsedSinceDown` is optional: pass it when the host tracks its own
|
|
254
|
+
* timestamps (e.g. event-driven, no per-frame `update()` calls); omit it
|
|
255
|
+
* to use the elapsed time already accumulated via `update(dt, ...)`. Either
|
|
256
|
+
* way there is one clock per press — passing it here re-syncs the same
|
|
257
|
+
* accumulator `update()` advances, rather than racing it. If a long press
|
|
258
|
+
* already fired for this press, tap/swipe are suppressed so one press
|
|
259
|
+
* yields exactly one gesture.
|
|
260
|
+
*/
|
|
232
261
|
pointerUp(x, y, elapsedSinceDown) {
|
|
233
262
|
if (!this._isTracking) return;
|
|
234
263
|
this._isTracking = false;
|
|
264
|
+
if (elapsedSinceDown !== void 0) this._elapsed = elapsedSinceDown;
|
|
265
|
+
if (this._longPressFired) return;
|
|
235
266
|
const dx = x - this._startPos.x;
|
|
236
267
|
const dy = y - this._startPos.y;
|
|
237
268
|
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
238
|
-
const duration =
|
|
269
|
+
const duration = this._elapsed;
|
|
239
270
|
if (dist >= this.swipeMinDistance && duration <= this.swipeMaxDuration) {
|
|
240
271
|
const absDx = Math.abs(dx);
|
|
241
272
|
const absDy = Math.abs(dy);
|
|
@@ -265,8 +296,8 @@ var GestureDetector = class {
|
|
|
265
296
|
*/
|
|
266
297
|
update(dt, currentX, currentY) {
|
|
267
298
|
if (!this._isTracking) return;
|
|
268
|
-
this.
|
|
269
|
-
if (!this._longPressFired && this.
|
|
299
|
+
this._elapsed += dt;
|
|
300
|
+
if (!this._longPressFired && this._elapsed >= this.longPressMinDuration) {
|
|
270
301
|
const dx = currentX - this._startPos.x;
|
|
271
302
|
const dy = currentY - this._startPos.y;
|
|
272
303
|
if (Math.sqrt(dx * dx + dy * dy) <= this.tapMaxDistance) {
|
|
@@ -383,10 +414,6 @@ function createKeyboard() {
|
|
|
383
414
|
}
|
|
384
415
|
};
|
|
385
416
|
}
|
|
386
|
-
/** Free-function parity with `resetPointerFrame`. Delegates to `kb.reset()`. */
|
|
387
|
-
function resetKeyboardFrame(kb) {
|
|
388
|
-
kb.reset();
|
|
389
|
-
}
|
|
390
417
|
/**
|
|
391
418
|
* Web turnkey adapter: registers `keydown`, `keyup`, and `blur` listeners on
|
|
392
419
|
* `target`. `blur` calls `kb.clear()` (stuck-key guard). Returns a detach fn.
|
|
@@ -581,20 +608,33 @@ function isRemapTable(value) {
|
|
|
581
608
|
* Feed events from the platform (RN touch/gesture handlers) via the on* methods.
|
|
582
609
|
*/
|
|
583
610
|
var InputManager = class {
|
|
584
|
-
/**
|
|
611
|
+
/**
|
|
612
|
+
* Primary pointer — the touch that started the current gesture (first
|
|
613
|
+
* `onPointerDown` while no touch was active), or the mouse.
|
|
614
|
+
*
|
|
615
|
+
* Once assigned, the primary id stays fixed to that touch until it lifts;
|
|
616
|
+
* it does NOT transfer to a remaining finger. While a second finger is
|
|
617
|
+
* down, its events reach only `touches` — `pointer` neither moves nor
|
|
618
|
+
* releases because of it. When the primary lifts, `pointer.isDown` goes
|
|
619
|
+
* false even if other fingers remain down, and a new primary is assigned
|
|
620
|
+
* only once every touch has lifted and a fresh `onPointerDown` arrives.
|
|
621
|
+
* This keeps `pointer` a single continuous stream with no mid-gesture
|
|
622
|
+
* teleport; read `touches` for anything beyond one finger.
|
|
623
|
+
*/
|
|
585
624
|
pointer = createPointer();
|
|
586
625
|
/** Buffered keyboard state. Feed via `attachKeyboardListeners` (web) or `keyboard.keyDown`/`keyUp` (mobile/RN). */
|
|
587
626
|
keyboard = createKeyboard();
|
|
588
627
|
/** All active touch points. */
|
|
589
628
|
touches = [];
|
|
590
629
|
_touchMap = /* @__PURE__ */ new Map();
|
|
630
|
+
_primaryTouchId = null;
|
|
591
631
|
_gamepads = [];
|
|
592
632
|
_gamepadDeadZone = .15;
|
|
593
633
|
_gamepadRemaps = /* @__PURE__ */ new Map();
|
|
594
634
|
/** Call once per frame to reset per-frame flags. */
|
|
595
635
|
update() {
|
|
596
636
|
resetPointerFrame(this.pointer);
|
|
597
|
-
|
|
637
|
+
this.keyboard.reset();
|
|
598
638
|
for (let i = 0; i < this._gamepads.length; i++) {
|
|
599
639
|
const pad = this._gamepads[i];
|
|
600
640
|
if (pad) resetGamepadFrame(pad);
|
|
@@ -602,17 +642,21 @@ var InputManager = class {
|
|
|
602
642
|
}
|
|
603
643
|
/** Feed a touch/pointer begin event. */
|
|
604
644
|
onPointerDown(id, x, y) {
|
|
605
|
-
|
|
645
|
+
if (this._touchMap.size === 0) this._primaryTouchId = id;
|
|
646
|
+
if (id === this._primaryTouchId) pointerDown(this.pointer, x, y);
|
|
606
647
|
this._addOrUpdateTouch(id, x, y, true);
|
|
607
648
|
}
|
|
608
649
|
/** Feed a touch/pointer move event. */
|
|
609
650
|
onPointerMove(id, x, y) {
|
|
610
|
-
pointerMove(this.pointer, x, y);
|
|
651
|
+
if (id === this._primaryTouchId) pointerMove(this.pointer, x, y);
|
|
611
652
|
this._addOrUpdateTouch(id, x, y, true);
|
|
612
653
|
}
|
|
613
654
|
/** Feed a touch/pointer end event. */
|
|
614
655
|
onPointerUp(id, x, y) {
|
|
615
|
-
|
|
656
|
+
if (id === this._primaryTouchId) {
|
|
657
|
+
pointerUp(this.pointer, x, y);
|
|
658
|
+
this._primaryTouchId = null;
|
|
659
|
+
}
|
|
616
660
|
this._removeTouch(id);
|
|
617
661
|
}
|
|
618
662
|
/** Access the gamepad state at `index`. Allocates on first access. */
|
|
@@ -671,6 +715,16 @@ var InputManager = class {
|
|
|
671
715
|
};
|
|
672
716
|
//#endregion
|
|
673
717
|
//#region src/virtual-joystick.ts
|
|
718
|
+
/**
|
|
719
|
+
* Dev-flag access for the config guard in `updateJoystick`, which runs once per
|
|
720
|
+
* frame while a stick is held. Read as a `globalThis` property, not as a bare
|
|
721
|
+
* `__DEV__` identifier: on JSC an unresolvable global costs ~270 ns per
|
|
722
|
+
* evaluation where a property miss is inline-cached at ~0.46 ns. Same reasoning
|
|
723
|
+
* as `@flare-engine/core`'s `Pool` — see PERF-10.
|
|
724
|
+
*/
|
|
725
|
+
const G = globalThis;
|
|
726
|
+
/** Warn at most once per process; a bad config repeats every frame. */
|
|
727
|
+
let _warnedConfig = false;
|
|
674
728
|
const DEFAULT_DEAD_ZONE = 10;
|
|
675
729
|
const DEFAULT_MAX_RADIUS = 50;
|
|
676
730
|
/** Create a default joystick state. */
|
|
@@ -699,27 +753,36 @@ function createJoystickState() {
|
|
|
699
753
|
* @param config Joystick configuration.
|
|
700
754
|
*/
|
|
701
755
|
function updateJoystick(state, centerX, centerY, touchX, touchY, config) {
|
|
702
|
-
|
|
703
|
-
|
|
756
|
+
let deadZone = config?.deadZone ?? DEFAULT_DEAD_ZONE;
|
|
757
|
+
let maxRadius = config?.maxRadius ?? DEFAULT_MAX_RADIUS;
|
|
758
|
+
if (!(deadZone >= 0 && maxRadius > deadZone)) {
|
|
759
|
+
if (G.__DEV__ && !_warnedConfig) {
|
|
760
|
+
_warnedConfig = true;
|
|
761
|
+
console.warn(`[flare-engine/input] updateJoystick: invalid config (deadZone=${deadZone}, maxRadius=${maxRadius}); expected 0 <= deadZone < maxRadius. Falling back to defaults for this call.`);
|
|
762
|
+
}
|
|
763
|
+
if (!(deadZone >= 0)) deadZone = DEFAULT_DEAD_ZONE;
|
|
764
|
+
if (!(maxRadius > deadZone)) maxRadius = deadZone + DEFAULT_MAX_RADIUS;
|
|
765
|
+
}
|
|
704
766
|
const dx = touchX - centerX;
|
|
705
767
|
const dy = touchY - centerY;
|
|
706
768
|
const dist = Math.sqrt(dx * dx + dy * dy);
|
|
707
769
|
state.active = true;
|
|
708
|
-
if (dist
|
|
770
|
+
if (!(dist >= deadZone)) {
|
|
709
771
|
state.direction.x = 0;
|
|
710
772
|
state.direction.y = 0;
|
|
711
773
|
state.magnitude = 0;
|
|
712
|
-
|
|
713
|
-
state.offset.
|
|
774
|
+
const centred = dist === 0 || !Number.isFinite(dist);
|
|
775
|
+
state.offset.x = centred ? 0 : dx;
|
|
776
|
+
state.offset.y = centred ? 0 : dy;
|
|
714
777
|
return;
|
|
715
778
|
}
|
|
716
779
|
const clampedDist = Math.min(dist, maxRadius);
|
|
717
780
|
const normalizedDist = (clampedDist - deadZone) / (maxRadius - deadZone);
|
|
718
|
-
const invDist = 1 / dist;
|
|
781
|
+
const invDist = dist > 0 ? 1 / dist : 0;
|
|
719
782
|
state.direction.x = dx * invDist;
|
|
720
783
|
state.direction.y = dy * invDist;
|
|
721
784
|
state.magnitude = Math.min(normalizedDist, 1);
|
|
722
|
-
const scale = clampedDist / dist;
|
|
785
|
+
const scale = dist > 0 ? clampedDist / dist : 0;
|
|
723
786
|
state.offset.x = dx * scale;
|
|
724
787
|
state.offset.y = dy * scale;
|
|
725
788
|
}
|
|
@@ -758,7 +821,6 @@ exports.releaseButton = releaseButton;
|
|
|
758
821
|
exports.releaseJoystick = releaseJoystick;
|
|
759
822
|
exports.resetButtonFrame = resetButtonFrame;
|
|
760
823
|
exports.resetGamepadFrame = resetGamepadFrame;
|
|
761
|
-
exports.resetKeyboardFrame = resetKeyboardFrame;
|
|
762
824
|
exports.resetPointerFrame = resetPointerFrame;
|
|
763
825
|
exports.saveRemap = saveRemap;
|
|
764
826
|
exports.updateGamepadFromSnapshot = updateGamepadFromSnapshot;
|