steamworks-ffi-node 0.6.9 → 0.7.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 +153 -107
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/internal/SteamInputManager.d.ts +496 -0
- package/dist/internal/SteamInputManager.d.ts.map +1 -0
- package/dist/internal/SteamInputManager.js +993 -0
- package/dist/internal/SteamInputManager.js.map +1 -0
- package/dist/internal/SteamLibraryLoader.d.ts +48 -0
- package/dist/internal/SteamLibraryLoader.d.ts.map +1 -1
- package/dist/internal/SteamLibraryLoader.js +61 -0
- package/dist/internal/SteamLibraryLoader.js.map +1 -1
- package/dist/steam.d.ts +59 -0
- package/dist/steam.d.ts.map +1 -1
- package/dist/steam.js +5 -0
- package/dist/steam.js.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/input.d.ts +252 -0
- package/dist/types/input.d.ts.map +1 -0
- package/dist/types/input.js +142 -0
- package/dist/types/input.js.map +1 -0
- package/docs/README.md +30 -2
- package/package.json +8 -2
- package/verify-sdk-setup.js +3 -3
|
@@ -0,0 +1,993 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SteamInputManager = void 0;
|
|
4
|
+
const types_1 = require("../types");
|
|
5
|
+
/**
|
|
6
|
+
* Controller type names for display
|
|
7
|
+
*/
|
|
8
|
+
const CONTROLLER_TYPE_NAMES = {
|
|
9
|
+
[types_1.SteamInputType.Unknown]: 'Unknown',
|
|
10
|
+
[types_1.SteamInputType.SteamController]: 'Steam Controller',
|
|
11
|
+
[types_1.SteamInputType.XBox360Controller]: 'Xbox 360 Controller',
|
|
12
|
+
[types_1.SteamInputType.XBoxOneController]: 'Xbox One Controller',
|
|
13
|
+
[types_1.SteamInputType.GenericGamepad]: 'Generic Gamepad',
|
|
14
|
+
[types_1.SteamInputType.PS4Controller]: 'PS4 Controller',
|
|
15
|
+
[types_1.SteamInputType.AppleMFiController]: 'Apple MFi Controller',
|
|
16
|
+
[types_1.SteamInputType.AndroidController]: 'Android Controller',
|
|
17
|
+
[types_1.SteamInputType.SwitchJoyConPair]: 'Switch Joy-Con Pair',
|
|
18
|
+
[types_1.SteamInputType.SwitchJoyConSingle]: 'Switch Joy-Con Single',
|
|
19
|
+
[types_1.SteamInputType.SwitchProController]: 'Switch Pro Controller',
|
|
20
|
+
[types_1.SteamInputType.MobileTouch]: 'Mobile Touch',
|
|
21
|
+
[types_1.SteamInputType.PS3Controller]: 'PS3 Controller',
|
|
22
|
+
[types_1.SteamInputType.PS5Controller]: 'PS5 Controller',
|
|
23
|
+
[types_1.SteamInputType.SteamDeckController]: 'Steam Deck',
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* SteamInputManager
|
|
27
|
+
*
|
|
28
|
+
* Manages Steam Input operations for unified controller support.
|
|
29
|
+
* Supports Xbox, PlayStation, Nintendo Switch, Steam Controller, and more.
|
|
30
|
+
*
|
|
31
|
+
* Features:
|
|
32
|
+
* - Controller detection and enumeration
|
|
33
|
+
* - Action set management
|
|
34
|
+
* - Digital and analog action handling
|
|
35
|
+
* - Motion data (gyro, accelerometer)
|
|
36
|
+
* - Haptic feedback and vibration
|
|
37
|
+
* - LED control
|
|
38
|
+
* - Button glyph display
|
|
39
|
+
* - Configuration UI
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* const inputManager = new SteamInputManager(libraryLoader, apiCore);
|
|
44
|
+
*
|
|
45
|
+
* // Initialize
|
|
46
|
+
* inputManager.init();
|
|
47
|
+
*
|
|
48
|
+
* // Update every frame
|
|
49
|
+
* inputManager.runFrame();
|
|
50
|
+
*
|
|
51
|
+
* // Get connected controllers
|
|
52
|
+
* const controllers = inputManager.getConnectedControllers();
|
|
53
|
+
*
|
|
54
|
+
* // Read actions
|
|
55
|
+
* const jumpHandle = inputManager.getDigitalActionHandle('Jump');
|
|
56
|
+
* const jumpData = inputManager.getDigitalActionData(controllerHandle, jumpHandle);
|
|
57
|
+
* if (jumpData.state) {
|
|
58
|
+
* console.log('Jump pressed!');
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
class SteamInputManager {
|
|
63
|
+
/**
|
|
64
|
+
* Creates a new SteamInputManager instance
|
|
65
|
+
*
|
|
66
|
+
* @param libraryLoader - The Steam library loader for FFI calls
|
|
67
|
+
*/
|
|
68
|
+
constructor(libraryLoader) {
|
|
69
|
+
/** Cached ISteamInput interface pointer */
|
|
70
|
+
this.steamInputInterface = null;
|
|
71
|
+
this.libraryLoader = libraryLoader;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Get the ISteamInput interface pointer
|
|
75
|
+
* @private
|
|
76
|
+
*/
|
|
77
|
+
getSteamInputInterface() {
|
|
78
|
+
if (!this.steamInputInterface) {
|
|
79
|
+
this.steamInputInterface = this.libraryLoader.SteamAPI_SteamInput_v006();
|
|
80
|
+
}
|
|
81
|
+
return this.steamInputInterface;
|
|
82
|
+
}
|
|
83
|
+
// ========================================
|
|
84
|
+
// Initialization
|
|
85
|
+
// ========================================
|
|
86
|
+
/**
|
|
87
|
+
* Initialize Steam Input
|
|
88
|
+
*
|
|
89
|
+
* Must be called before using any other Steam Input functions.
|
|
90
|
+
* Should be called after SteamAPI_Init().
|
|
91
|
+
*
|
|
92
|
+
* @param explicitlyCallRunFrame - If true, you must call runFrame() manually each frame.
|
|
93
|
+
* If false, Steam will automatically update input state.
|
|
94
|
+
* Default is true for explicit control.
|
|
95
|
+
* @returns True if initialization was successful
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```typescript
|
|
99
|
+
* if (inputManager.init()) {
|
|
100
|
+
* console.log('Steam Input initialized successfully');
|
|
101
|
+
* }
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
init(explicitlyCallRunFrame = true) {
|
|
105
|
+
const iface = this.getSteamInputInterface();
|
|
106
|
+
if (!iface) {
|
|
107
|
+
console.error('[SteamInput] Failed to get ISteamInput interface');
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
const result = this.libraryLoader.SteamAPI_ISteamInput_Init(iface, explicitlyCallRunFrame);
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
console.error('[SteamInput] Init error:', error);
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Shutdown Steam Input
|
|
121
|
+
*
|
|
122
|
+
* Should be called before SteamAPI_Shutdown().
|
|
123
|
+
*
|
|
124
|
+
* @returns True if shutdown was successful
|
|
125
|
+
*/
|
|
126
|
+
shutdown() {
|
|
127
|
+
const iface = this.getSteamInputInterface();
|
|
128
|
+
if (!iface)
|
|
129
|
+
return false;
|
|
130
|
+
try {
|
|
131
|
+
const result = this.libraryLoader.SteamAPI_ISteamInput_Shutdown(iface);
|
|
132
|
+
return result;
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
console.error('[SteamInput] Shutdown error:', error);
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Set the absolute path to the Input Action Manifest file
|
|
141
|
+
*
|
|
142
|
+
* Used for games that provide their own input_actions.vdf file.
|
|
143
|
+
* Must be called before init().
|
|
144
|
+
*
|
|
145
|
+
* @param manifestPath - Absolute path to input_actions.vdf
|
|
146
|
+
* @returns True if successful
|
|
147
|
+
*/
|
|
148
|
+
setInputActionManifestFilePath(manifestPath) {
|
|
149
|
+
const iface = this.getSteamInputInterface();
|
|
150
|
+
if (!iface)
|
|
151
|
+
return false;
|
|
152
|
+
try {
|
|
153
|
+
return this.libraryLoader.SteamAPI_ISteamInput_SetInputActionManifestFilePath(iface, manifestPath);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
console.error('[SteamInput] SetInputActionManifestFilePath error:', error);
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Update input state for all controllers
|
|
162
|
+
*
|
|
163
|
+
* Must be called every frame if init() was called with explicitlyCallRunFrame=true.
|
|
164
|
+
* Synchronizes controller state and processes input data.
|
|
165
|
+
*
|
|
166
|
+
* @param reservedValue - Reserved for future use, should be false
|
|
167
|
+
*
|
|
168
|
+
* @example
|
|
169
|
+
* ```typescript
|
|
170
|
+
* // In your game loop
|
|
171
|
+
* function gameLoop() {
|
|
172
|
+
* inputManager.runFrame();
|
|
173
|
+
* // Read input state
|
|
174
|
+
* // Update game logic
|
|
175
|
+
* requestAnimationFrame(gameLoop);
|
|
176
|
+
* }
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
runFrame(reservedValue = false) {
|
|
180
|
+
const iface = this.getSteamInputInterface();
|
|
181
|
+
if (!iface)
|
|
182
|
+
return;
|
|
183
|
+
try {
|
|
184
|
+
this.libraryLoader.SteamAPI_ISteamInput_RunFrame(iface, reservedValue);
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
console.error('[SteamInput] RunFrame error:', error);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
// ========================================
|
|
191
|
+
// Controller Enumeration
|
|
192
|
+
// ========================================
|
|
193
|
+
/**
|
|
194
|
+
* Get all currently connected controller handles
|
|
195
|
+
*
|
|
196
|
+
* Controller handles persist across disconnects/reconnects.
|
|
197
|
+
*
|
|
198
|
+
* @returns Array of controller handles (max 16 controllers)
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```typescript
|
|
202
|
+
* const controllers = inputManager.getConnectedControllers();
|
|
203
|
+
* console.log(`Found ${controllers.length} controller(s)`);
|
|
204
|
+
*
|
|
205
|
+
* controllers.forEach(handle => {
|
|
206
|
+
* const type = inputManager.getInputTypeForHandle(handle);
|
|
207
|
+
* console.log(`Controller: ${handle}, Type: ${type}`);
|
|
208
|
+
* });
|
|
209
|
+
* ```
|
|
210
|
+
*/
|
|
211
|
+
getConnectedControllers() {
|
|
212
|
+
const iface = this.getSteamInputInterface();
|
|
213
|
+
if (!iface)
|
|
214
|
+
return [];
|
|
215
|
+
try {
|
|
216
|
+
const handlesArray = new BigUint64Array(types_1.STEAM_INPUT.MAX_COUNT);
|
|
217
|
+
const handleBuffer = Buffer.from(handlesArray.buffer);
|
|
218
|
+
const count = this.libraryLoader.SteamAPI_ISteamInput_GetConnectedControllers(iface, handleBuffer);
|
|
219
|
+
const handles = [];
|
|
220
|
+
for (let i = 0; i < count; i++) {
|
|
221
|
+
handles.push(handlesArray[i]);
|
|
222
|
+
}
|
|
223
|
+
return handles;
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
console.error('[SteamInput] GetConnectedControllers error:', error);
|
|
227
|
+
return [];
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Get the input type for a specific controller
|
|
232
|
+
*
|
|
233
|
+
* @param inputHandle - Controller handle
|
|
234
|
+
* @returns Controller type enum value
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* ```typescript
|
|
238
|
+
* const type = inputManager.getInputTypeForHandle(handle);
|
|
239
|
+
* if (type === SteamInputType.PS5Controller) {
|
|
240
|
+
* console.log('DualSense detected!');
|
|
241
|
+
* }
|
|
242
|
+
* ```
|
|
243
|
+
*/
|
|
244
|
+
getInputTypeForHandle(inputHandle) {
|
|
245
|
+
const iface = this.getSteamInputInterface();
|
|
246
|
+
if (!iface)
|
|
247
|
+
return types_1.SteamInputType.Unknown;
|
|
248
|
+
try {
|
|
249
|
+
return this.libraryLoader.SteamAPI_ISteamInput_GetInputTypeForHandle(iface, inputHandle);
|
|
250
|
+
}
|
|
251
|
+
catch (error) {
|
|
252
|
+
console.error('[SteamInput] GetInputTypeForHandle error:', error);
|
|
253
|
+
return types_1.SteamInputType.Unknown;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Get comprehensive controller information
|
|
258
|
+
*
|
|
259
|
+
* Convenience method that combines multiple queries into one object.
|
|
260
|
+
*
|
|
261
|
+
* @param inputHandle - Controller handle
|
|
262
|
+
* @returns Controller information object
|
|
263
|
+
*/
|
|
264
|
+
getControllerInfo(inputHandle) {
|
|
265
|
+
const type = this.getInputTypeForHandle(inputHandle);
|
|
266
|
+
const gamepadIndex = this.getGamepadIndexForController(inputHandle);
|
|
267
|
+
return {
|
|
268
|
+
handle: inputHandle,
|
|
269
|
+
type,
|
|
270
|
+
typeName: CONTROLLER_TYPE_NAMES[type] || `Unknown (${type})`,
|
|
271
|
+
gamepadIndex,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Get the controller handle for a specific gamepad index
|
|
276
|
+
*
|
|
277
|
+
* Useful for mapping XInput indices to Steam Input handles.
|
|
278
|
+
*
|
|
279
|
+
* @param gamepadIndex - XInput gamepad index (0-3)
|
|
280
|
+
* @returns Controller handle, or 0n if not found
|
|
281
|
+
*/
|
|
282
|
+
getControllerForGamepadIndex(gamepadIndex) {
|
|
283
|
+
const iface = this.getSteamInputInterface();
|
|
284
|
+
if (!iface)
|
|
285
|
+
return BigInt(0);
|
|
286
|
+
try {
|
|
287
|
+
return this.libraryLoader.SteamAPI_ISteamInput_GetControllerForGamepadIndex(iface, gamepadIndex);
|
|
288
|
+
}
|
|
289
|
+
catch (error) {
|
|
290
|
+
console.error('[SteamInput] GetControllerForGamepadIndex error:', error);
|
|
291
|
+
return BigInt(0);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Get the gamepad index for a controller handle
|
|
296
|
+
*
|
|
297
|
+
* @param inputHandle - Controller handle
|
|
298
|
+
* @returns XInput gamepad index (0-3), or -1 if not emulating gamepad
|
|
299
|
+
*/
|
|
300
|
+
getGamepadIndexForController(inputHandle) {
|
|
301
|
+
const iface = this.getSteamInputInterface();
|
|
302
|
+
if (!iface)
|
|
303
|
+
return -1;
|
|
304
|
+
try {
|
|
305
|
+
return this.libraryLoader.SteamAPI_ISteamInput_GetGamepadIndexForController(iface, inputHandle);
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
console.error('[SteamInput] GetGamepadIndexForController error:', error);
|
|
309
|
+
return -1;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// ========================================
|
|
313
|
+
// Action Sets
|
|
314
|
+
// ========================================
|
|
315
|
+
/**
|
|
316
|
+
* Get the handle for an action set by name
|
|
317
|
+
*
|
|
318
|
+
* Action sets group related actions together (e.g., "MenuControls", "GameplayControls").
|
|
319
|
+
* Should be queried once at startup and cached.
|
|
320
|
+
*
|
|
321
|
+
* @param actionSetName - Name of the action set from input_actions.vdf
|
|
322
|
+
* @returns Action set handle
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* ```typescript
|
|
326
|
+
* const menuSet = inputManager.getActionSetHandle('MenuControls');
|
|
327
|
+
* const gameSet = inputManager.getActionSetHandle('GameplayControls');
|
|
328
|
+
* ```
|
|
329
|
+
*/
|
|
330
|
+
getActionSetHandle(actionSetName) {
|
|
331
|
+
const iface = this.getSteamInputInterface();
|
|
332
|
+
if (!iface)
|
|
333
|
+
return BigInt(0);
|
|
334
|
+
try {
|
|
335
|
+
return this.libraryLoader.SteamAPI_ISteamInput_GetActionSetHandle(iface, actionSetName);
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
console.error('[SteamInput] GetActionSetHandle error:', error);
|
|
339
|
+
return BigInt(0);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Activate an action set for a controller
|
|
344
|
+
*
|
|
345
|
+
* Only one action set can be active at a time (plus layers).
|
|
346
|
+
*
|
|
347
|
+
* @param inputHandle - Controller handle
|
|
348
|
+
* @param actionSetHandle - Action set handle to activate
|
|
349
|
+
*
|
|
350
|
+
* @example
|
|
351
|
+
* ```typescript
|
|
352
|
+
* const gameSet = inputManager.getActionSetHandle('GameplayControls');
|
|
353
|
+
* inputManager.activateActionSet(controllerHandle, gameSet);
|
|
354
|
+
* ```
|
|
355
|
+
*/
|
|
356
|
+
activateActionSet(inputHandle, actionSetHandle) {
|
|
357
|
+
const iface = this.getSteamInputInterface();
|
|
358
|
+
if (!iface)
|
|
359
|
+
return;
|
|
360
|
+
try {
|
|
361
|
+
this.libraryLoader.SteamAPI_ISteamInput_ActivateActionSet(iface, inputHandle, actionSetHandle);
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
console.error('[SteamInput] ActivateActionSet error:', error);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Get the currently active action set for a controller
|
|
369
|
+
*
|
|
370
|
+
* @param inputHandle - Controller handle
|
|
371
|
+
* @returns Currently active action set handle
|
|
372
|
+
*/
|
|
373
|
+
getCurrentActionSet(inputHandle) {
|
|
374
|
+
const iface = this.getSteamInputInterface();
|
|
375
|
+
if (!iface)
|
|
376
|
+
return BigInt(0);
|
|
377
|
+
try {
|
|
378
|
+
return this.libraryLoader.SteamAPI_ISteamInput_GetCurrentActionSet(iface, inputHandle);
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
console.error('[SteamInput] GetCurrentActionSet error:', error);
|
|
382
|
+
return BigInt(0);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
/**
|
|
386
|
+
* Activate an action set layer
|
|
387
|
+
*
|
|
388
|
+
* Layers add additional actions on top of the base action set.
|
|
389
|
+
* Up to 16 layers can be active simultaneously.
|
|
390
|
+
*
|
|
391
|
+
* @param inputHandle - Controller handle
|
|
392
|
+
* @param actionSetLayerHandle - Action set layer handle
|
|
393
|
+
*/
|
|
394
|
+
activateActionSetLayer(inputHandle, actionSetLayerHandle) {
|
|
395
|
+
const iface = this.getSteamInputInterface();
|
|
396
|
+
if (!iface)
|
|
397
|
+
return;
|
|
398
|
+
try {
|
|
399
|
+
this.libraryLoader.SteamAPI_ISteamInput_ActivateActionSetLayer(iface, inputHandle, actionSetLayerHandle);
|
|
400
|
+
}
|
|
401
|
+
catch (error) {
|
|
402
|
+
console.error('[SteamInput] ActivateActionSetLayer error:', error);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Deactivate an action set layer
|
|
407
|
+
*
|
|
408
|
+
* @param inputHandle - Controller handle
|
|
409
|
+
* @param actionSetLayerHandle - Action set layer handle
|
|
410
|
+
*/
|
|
411
|
+
deactivateActionSetLayer(inputHandle, actionSetLayerHandle) {
|
|
412
|
+
const iface = this.getSteamInputInterface();
|
|
413
|
+
if (!iface)
|
|
414
|
+
return;
|
|
415
|
+
try {
|
|
416
|
+
this.libraryLoader.SteamAPI_ISteamInput_DeactivateActionSetLayer(iface, inputHandle, actionSetLayerHandle);
|
|
417
|
+
}
|
|
418
|
+
catch (error) {
|
|
419
|
+
console.error('[SteamInput] DeactivateActionSetLayer error:', error);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Deactivate all action set layers
|
|
424
|
+
*
|
|
425
|
+
* @param inputHandle - Controller handle
|
|
426
|
+
*/
|
|
427
|
+
deactivateAllActionSetLayers(inputHandle) {
|
|
428
|
+
const iface = this.getSteamInputInterface();
|
|
429
|
+
if (!iface)
|
|
430
|
+
return;
|
|
431
|
+
try {
|
|
432
|
+
this.libraryLoader.SteamAPI_ISteamInput_DeactivateAllActionSetLayers(iface, inputHandle);
|
|
433
|
+
}
|
|
434
|
+
catch (error) {
|
|
435
|
+
console.error('[SteamInput] DeactivateAllActionSetLayers error:', error);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Get all currently active action set layers
|
|
440
|
+
*
|
|
441
|
+
* @param inputHandle - Controller handle
|
|
442
|
+
* @returns Array of active layer handles
|
|
443
|
+
*/
|
|
444
|
+
getActiveActionSetLayers(inputHandle) {
|
|
445
|
+
const iface = this.getSteamInputInterface();
|
|
446
|
+
if (!iface)
|
|
447
|
+
return [];
|
|
448
|
+
try {
|
|
449
|
+
const layersArray = new BigUint64Array(types_1.STEAM_INPUT.MAX_ACTIVE_LAYERS);
|
|
450
|
+
const layerBuffer = Buffer.from(layersArray.buffer);
|
|
451
|
+
const count = this.libraryLoader.SteamAPI_ISteamInput_GetActiveActionSetLayers(iface, inputHandle, layerBuffer);
|
|
452
|
+
const layers = [];
|
|
453
|
+
for (let i = 0; i < count; i++) {
|
|
454
|
+
layers.push(layersArray[i]);
|
|
455
|
+
}
|
|
456
|
+
return layers;
|
|
457
|
+
}
|
|
458
|
+
catch (error) {
|
|
459
|
+
console.error('[SteamInput] GetActiveActionSetLayers error:', error);
|
|
460
|
+
return [];
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
// ========================================
|
|
464
|
+
// Digital Actions (Buttons)
|
|
465
|
+
// ========================================
|
|
466
|
+
/**
|
|
467
|
+
* Get the handle for a digital action by name
|
|
468
|
+
*
|
|
469
|
+
* Digital actions represent button presses (on/off state).
|
|
470
|
+
* Should be queried once at startup and cached.
|
|
471
|
+
*
|
|
472
|
+
* @param actionName - Name of the digital action from input_actions.vdf
|
|
473
|
+
* @returns Digital action handle
|
|
474
|
+
*
|
|
475
|
+
* @example
|
|
476
|
+
* ```typescript
|
|
477
|
+
* const jumpHandle = inputManager.getDigitalActionHandle('Jump');
|
|
478
|
+
* const shootHandle = inputManager.getDigitalActionHandle('Shoot');
|
|
479
|
+
* ```
|
|
480
|
+
*/
|
|
481
|
+
getDigitalActionHandle(actionName) {
|
|
482
|
+
const iface = this.getSteamInputInterface();
|
|
483
|
+
if (!iface)
|
|
484
|
+
return BigInt(0);
|
|
485
|
+
try {
|
|
486
|
+
return this.libraryLoader.SteamAPI_ISteamInput_GetDigitalActionHandle(iface, actionName);
|
|
487
|
+
}
|
|
488
|
+
catch (error) {
|
|
489
|
+
console.error('[SteamInput] GetDigitalActionHandle error:', error);
|
|
490
|
+
return BigInt(0);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Get the current state of a digital action
|
|
495
|
+
*
|
|
496
|
+
* @param inputHandle - Controller handle
|
|
497
|
+
* @param digitalActionHandle - Digital action handle
|
|
498
|
+
* @returns Digital action data (state and active status)
|
|
499
|
+
*
|
|
500
|
+
* @example
|
|
501
|
+
* ```typescript
|
|
502
|
+
* const jumpData = inputManager.getDigitalActionData(controllerHandle, jumpHandle);
|
|
503
|
+
* if (jumpData.state && jumpData.active) {
|
|
504
|
+
* player.jump();
|
|
505
|
+
* }
|
|
506
|
+
* ```
|
|
507
|
+
*/
|
|
508
|
+
getDigitalActionData(inputHandle, digitalActionHandle) {
|
|
509
|
+
const iface = this.getSteamInputInterface();
|
|
510
|
+
if (!iface) {
|
|
511
|
+
return { state: false, active: false };
|
|
512
|
+
}
|
|
513
|
+
try {
|
|
514
|
+
// Allocate buffer for InputDigitalActionData_t struct (bool state + bool active)
|
|
515
|
+
const buffer = Buffer.alloc(2);
|
|
516
|
+
this.libraryLoader.SteamAPI_ISteamInput_GetDigitalActionData(iface, inputHandle, digitalActionHandle, buffer);
|
|
517
|
+
return {
|
|
518
|
+
state: buffer.readUInt8(0) !== 0,
|
|
519
|
+
active: buffer.readUInt8(1) !== 0,
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
catch (error) {
|
|
523
|
+
console.error('[SteamInput] GetDigitalActionData error:', error);
|
|
524
|
+
return { state: false, active: false };
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Get the localized string for a digital action name
|
|
529
|
+
*
|
|
530
|
+
* @param digitalActionHandle - Digital action handle
|
|
531
|
+
* @returns Localized action name, or empty string if not found
|
|
532
|
+
*/
|
|
533
|
+
getStringForDigitalActionName(digitalActionHandle) {
|
|
534
|
+
const iface = this.getSteamInputInterface();
|
|
535
|
+
if (!iface)
|
|
536
|
+
return '';
|
|
537
|
+
try {
|
|
538
|
+
return this.libraryLoader.SteamAPI_ISteamInput_GetStringForDigitalActionName(iface, digitalActionHandle) || '';
|
|
539
|
+
}
|
|
540
|
+
catch (error) {
|
|
541
|
+
console.error('[SteamInput] GetStringForDigitalActionName error:', error);
|
|
542
|
+
return '';
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
// ========================================
|
|
546
|
+
// Analog Actions (Sticks, Triggers)
|
|
547
|
+
// ========================================
|
|
548
|
+
/**
|
|
549
|
+
* Get the handle for an analog action by name
|
|
550
|
+
*
|
|
551
|
+
* Analog actions represent continuous inputs like joysticks and triggers.
|
|
552
|
+
* Should be queried once at startup and cached.
|
|
553
|
+
*
|
|
554
|
+
* @param actionName - Name of the analog action from input_actions.vdf
|
|
555
|
+
* @returns Analog action handle
|
|
556
|
+
*
|
|
557
|
+
* @example
|
|
558
|
+
* ```typescript
|
|
559
|
+
* const moveHandle = inputManager.getAnalogActionHandle('Move');
|
|
560
|
+
* const lookHandle = inputManager.getAnalogActionHandle('Look');
|
|
561
|
+
* ```
|
|
562
|
+
*/
|
|
563
|
+
getAnalogActionHandle(actionName) {
|
|
564
|
+
const iface = this.getSteamInputInterface();
|
|
565
|
+
if (!iface)
|
|
566
|
+
return BigInt(0);
|
|
567
|
+
try {
|
|
568
|
+
return this.libraryLoader.SteamAPI_ISteamInput_GetAnalogActionHandle(iface, actionName);
|
|
569
|
+
}
|
|
570
|
+
catch (error) {
|
|
571
|
+
console.error('[SteamInput] GetAnalogActionHandle error:', error);
|
|
572
|
+
return BigInt(0);
|
|
573
|
+
}
|
|
574
|
+
}
|
|
575
|
+
/**
|
|
576
|
+
* Get the current state of an analog action
|
|
577
|
+
*
|
|
578
|
+
* @param inputHandle - Controller handle
|
|
579
|
+
* @param analogActionHandle - Analog action handle
|
|
580
|
+
* @returns Analog action data (mode, x, y values, and active status)
|
|
581
|
+
*
|
|
582
|
+
* @example
|
|
583
|
+
* ```typescript
|
|
584
|
+
* const moveData = inputManager.getAnalogActionData(controllerHandle, moveHandle);
|
|
585
|
+
* if (moveData.active) {
|
|
586
|
+
* player.move(moveData.x, moveData.y);
|
|
587
|
+
* }
|
|
588
|
+
* ```
|
|
589
|
+
*/
|
|
590
|
+
getAnalogActionData(inputHandle, analogActionHandle) {
|
|
591
|
+
const iface = this.getSteamInputInterface();
|
|
592
|
+
if (!iface) {
|
|
593
|
+
return { mode: 0, x: 0, y: 0, active: false };
|
|
594
|
+
}
|
|
595
|
+
try {
|
|
596
|
+
// Allocate buffer for InputAnalogActionData_t struct
|
|
597
|
+
// EInputSourceMode (4 bytes), float x, float y, bool active
|
|
598
|
+
const buffer = Buffer.alloc(13);
|
|
599
|
+
this.libraryLoader.SteamAPI_ISteamInput_GetAnalogActionData(iface, inputHandle, analogActionHandle, buffer);
|
|
600
|
+
return {
|
|
601
|
+
mode: buffer.readInt32LE(0),
|
|
602
|
+
x: buffer.readFloatLE(4),
|
|
603
|
+
y: buffer.readFloatLE(8),
|
|
604
|
+
active: buffer.readUInt8(12) !== 0,
|
|
605
|
+
};
|
|
606
|
+
}
|
|
607
|
+
catch (error) {
|
|
608
|
+
console.error('[SteamInput] GetAnalogActionData error:', error);
|
|
609
|
+
return { mode: 0, x: 0, y: 0, active: false };
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Get the localized string for an analog action name
|
|
614
|
+
*
|
|
615
|
+
* @param analogActionHandle - Analog action handle
|
|
616
|
+
* @returns Localized action name, or empty string if not found
|
|
617
|
+
*/
|
|
618
|
+
getStringForAnalogActionName(analogActionHandle) {
|
|
619
|
+
const iface = this.getSteamInputInterface();
|
|
620
|
+
if (!iface)
|
|
621
|
+
return '';
|
|
622
|
+
try {
|
|
623
|
+
return this.libraryLoader.SteamAPI_ISteamInput_GetStringForAnalogActionName(iface, analogActionHandle) || '';
|
|
624
|
+
}
|
|
625
|
+
catch (error) {
|
|
626
|
+
console.error('[SteamInput] GetStringForAnalogActionName error:', error);
|
|
627
|
+
return '';
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Stop analog action momentum for trackball mode
|
|
632
|
+
*
|
|
633
|
+
* If an analog action is in trackball mode (mouse emulation),
|
|
634
|
+
* this stops the momentum/inertia.
|
|
635
|
+
*
|
|
636
|
+
* @param inputHandle - Controller handle
|
|
637
|
+
* @param analogActionHandle - Analog action handle
|
|
638
|
+
*/
|
|
639
|
+
stopAnalogActionMomentum(inputHandle, analogActionHandle) {
|
|
640
|
+
const iface = this.getSteamInputInterface();
|
|
641
|
+
if (!iface)
|
|
642
|
+
return;
|
|
643
|
+
try {
|
|
644
|
+
this.libraryLoader.SteamAPI_ISteamInput_StopAnalogActionMomentum(iface, inputHandle, analogActionHandle);
|
|
645
|
+
}
|
|
646
|
+
catch (error) {
|
|
647
|
+
console.error('[SteamInput] StopAnalogActionMomentum error:', error);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
// ========================================
|
|
651
|
+
// Motion Data
|
|
652
|
+
// ========================================
|
|
653
|
+
/**
|
|
654
|
+
* Get motion data from controller (gyroscope and accelerometer)
|
|
655
|
+
*
|
|
656
|
+
* Provides quaternion rotation, positional acceleration, and angular velocity.
|
|
657
|
+
*
|
|
658
|
+
* @param inputHandle - Controller handle
|
|
659
|
+
* @returns Motion data, or null if not supported
|
|
660
|
+
*
|
|
661
|
+
* @example
|
|
662
|
+
* ```typescript
|
|
663
|
+
* const motion = inputManager.getMotionData(controllerHandle);
|
|
664
|
+
* if (motion) {
|
|
665
|
+
* // Use gyro for aiming
|
|
666
|
+
* camera.rotateByGyro(motion.rotVelX, motion.rotVelY, motion.rotVelZ);
|
|
667
|
+
* }
|
|
668
|
+
* ```
|
|
669
|
+
*/
|
|
670
|
+
getMotionData(inputHandle) {
|
|
671
|
+
const iface = this.getSteamInputInterface();
|
|
672
|
+
if (!iface)
|
|
673
|
+
return null;
|
|
674
|
+
try {
|
|
675
|
+
// Allocate buffer for InputMotionData_t struct
|
|
676
|
+
// 4 floats (quat) + 3 floats (posAccel) + 3 floats (rotVel) = 10 floats = 40 bytes
|
|
677
|
+
const buffer = Buffer.alloc(40);
|
|
678
|
+
this.libraryLoader.SteamAPI_ISteamInput_GetMotionData(iface, inputHandle, buffer);
|
|
679
|
+
return {
|
|
680
|
+
rotQuatX: buffer.readFloatLE(0),
|
|
681
|
+
rotQuatY: buffer.readFloatLE(4),
|
|
682
|
+
rotQuatZ: buffer.readFloatLE(8),
|
|
683
|
+
rotQuatW: buffer.readFloatLE(12),
|
|
684
|
+
posAccelX: buffer.readFloatLE(16),
|
|
685
|
+
posAccelY: buffer.readFloatLE(20),
|
|
686
|
+
posAccelZ: buffer.readFloatLE(24),
|
|
687
|
+
rotVelX: buffer.readFloatLE(28),
|
|
688
|
+
rotVelY: buffer.readFloatLE(32),
|
|
689
|
+
rotVelZ: buffer.readFloatLE(36),
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
catch (error) {
|
|
693
|
+
console.error('[SteamInput] GetMotionData error:', error);
|
|
694
|
+
return null;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
// ========================================
|
|
698
|
+
// Haptics and Rumble
|
|
699
|
+
// ========================================
|
|
700
|
+
/**
|
|
701
|
+
* Trigger vibration/rumble on a controller
|
|
702
|
+
*
|
|
703
|
+
* @param inputHandle - Controller handle
|
|
704
|
+
* @param leftSpeed - Left motor speed (0-65535)
|
|
705
|
+
* @param rightSpeed - Right motor speed (0-65535)
|
|
706
|
+
*
|
|
707
|
+
* @example
|
|
708
|
+
* ```typescript
|
|
709
|
+
* // Light rumble
|
|
710
|
+
* inputManager.triggerVibration(handle, 10000, 10000);
|
|
711
|
+
*
|
|
712
|
+
* // Strong rumble
|
|
713
|
+
* inputManager.triggerVibration(handle, 65535, 65535);
|
|
714
|
+
*
|
|
715
|
+
* // Stop rumble
|
|
716
|
+
* inputManager.triggerVibration(handle, 0, 0);
|
|
717
|
+
* ```
|
|
718
|
+
*/
|
|
719
|
+
triggerVibration(inputHandle, leftSpeed, rightSpeed) {
|
|
720
|
+
const iface = this.getSteamInputInterface();
|
|
721
|
+
if (!iface)
|
|
722
|
+
return;
|
|
723
|
+
try {
|
|
724
|
+
this.libraryLoader.SteamAPI_ISteamInput_TriggerVibration(iface, inputHandle, leftSpeed, rightSpeed);
|
|
725
|
+
}
|
|
726
|
+
catch (error) {
|
|
727
|
+
console.error('[SteamInput] TriggerVibration error:', error);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
/**
|
|
731
|
+
* Trigger extended vibration with trigger motor support (Xbox controllers)
|
|
732
|
+
*
|
|
733
|
+
* @param inputHandle - Controller handle
|
|
734
|
+
* @param leftSpeed - Left motor speed (0-65535)
|
|
735
|
+
* @param rightSpeed - Right motor speed (0-65535)
|
|
736
|
+
* @param leftTriggerSpeed - Left trigger motor speed (0-65535)
|
|
737
|
+
* @param rightTriggerSpeed - Right trigger motor speed (0-65535)
|
|
738
|
+
*/
|
|
739
|
+
triggerVibrationExtended(inputHandle, leftSpeed, rightSpeed, leftTriggerSpeed, rightTriggerSpeed) {
|
|
740
|
+
const iface = this.getSteamInputInterface();
|
|
741
|
+
if (!iface)
|
|
742
|
+
return;
|
|
743
|
+
try {
|
|
744
|
+
this.libraryLoader.SteamAPI_ISteamInput_TriggerVibrationExtended(iface, inputHandle, leftSpeed, rightSpeed, leftTriggerSpeed, rightTriggerSpeed);
|
|
745
|
+
}
|
|
746
|
+
catch (error) {
|
|
747
|
+
console.error('[SteamInput] TriggerVibrationExtended error:', error);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
/**
|
|
751
|
+
* Trigger a simple haptic event (Steam Controller, Steam Deck)
|
|
752
|
+
*
|
|
753
|
+
* @param inputHandle - Controller handle
|
|
754
|
+
* @param hapticLocation - Left, right, or both
|
|
755
|
+
* @param intensity - Intensity (0-255)
|
|
756
|
+
* @param gainDB - Gain in decibels
|
|
757
|
+
* @param otherIntensity - Intensity for the other pad
|
|
758
|
+
* @param otherGainDB - Gain for the other pad
|
|
759
|
+
*/
|
|
760
|
+
triggerSimpleHapticEvent(inputHandle, hapticLocation, intensity, gainDB, otherIntensity, otherGainDB) {
|
|
761
|
+
const iface = this.getSteamInputInterface();
|
|
762
|
+
if (!iface)
|
|
763
|
+
return;
|
|
764
|
+
try {
|
|
765
|
+
this.libraryLoader.SteamAPI_ISteamInput_TriggerSimpleHapticEvent(iface, inputHandle, hapticLocation, intensity, gainDB, otherIntensity, otherGainDB);
|
|
766
|
+
}
|
|
767
|
+
catch (error) {
|
|
768
|
+
console.error('[SteamInput] TriggerSimpleHapticEvent error:', error);
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Set controller LED color (supported controllers only)
|
|
773
|
+
*
|
|
774
|
+
* @param inputHandle - Controller handle
|
|
775
|
+
* @param colorR - Red (0-255)
|
|
776
|
+
* @param colorG - Green (0-255)
|
|
777
|
+
* @param colorB - Blue (0-255)
|
|
778
|
+
* @param flags - LED flags (0 = set color, 1 = restore default)
|
|
779
|
+
*
|
|
780
|
+
* @example
|
|
781
|
+
* ```typescript
|
|
782
|
+
* // Set LED to red
|
|
783
|
+
* inputManager.setLEDColor(handle, 255, 0, 0, 0);
|
|
784
|
+
*
|
|
785
|
+
* // Set LED to blue
|
|
786
|
+
* inputManager.setLEDColor(handle, 0, 0, 255, 0);
|
|
787
|
+
*
|
|
788
|
+
* // Restore default LED color
|
|
789
|
+
* inputManager.setLEDColor(handle, 0, 0, 0, 1);
|
|
790
|
+
* ```
|
|
791
|
+
*/
|
|
792
|
+
setLEDColor(inputHandle, colorR, colorG, colorB, flags = 0) {
|
|
793
|
+
const iface = this.getSteamInputInterface();
|
|
794
|
+
if (!iface)
|
|
795
|
+
return;
|
|
796
|
+
try {
|
|
797
|
+
this.libraryLoader.SteamAPI_ISteamInput_SetLEDColor(iface, inputHandle, colorR, colorG, colorB, flags);
|
|
798
|
+
}
|
|
799
|
+
catch (error) {
|
|
800
|
+
console.error('[SteamInput] SetLEDColor error:', error);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* Trigger a legacy haptic pulse (Steam Controller)
|
|
805
|
+
*
|
|
806
|
+
* @param inputHandle - Controller handle
|
|
807
|
+
* @param targetPad - Left or right pad
|
|
808
|
+
* @param durationMicroSec - Duration in microseconds
|
|
809
|
+
*/
|
|
810
|
+
legacyTriggerHapticPulse(inputHandle, targetPad, durationMicroSec) {
|
|
811
|
+
const iface = this.getSteamInputInterface();
|
|
812
|
+
if (!iface)
|
|
813
|
+
return;
|
|
814
|
+
try {
|
|
815
|
+
this.libraryLoader.SteamAPI_ISteamInput_Legacy_TriggerHapticPulse(iface, inputHandle, targetPad, durationMicroSec);
|
|
816
|
+
}
|
|
817
|
+
catch (error) {
|
|
818
|
+
console.error('[SteamInput] Legacy_TriggerHapticPulse error:', error);
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
// ========================================
|
|
822
|
+
// Glyphs and Localization
|
|
823
|
+
// ========================================
|
|
824
|
+
/**
|
|
825
|
+
* Get the path to a PNG glyph for an action origin
|
|
826
|
+
*
|
|
827
|
+
* Useful for showing button prompts in your UI.
|
|
828
|
+
*
|
|
829
|
+
* @param origin - Action origin (button)
|
|
830
|
+
* @param size - Glyph size (small, medium, large)
|
|
831
|
+
* @param flags - Glyph style flags
|
|
832
|
+
* @returns Path to PNG file, or empty string if not available
|
|
833
|
+
*
|
|
834
|
+
* @example
|
|
835
|
+
* ```typescript
|
|
836
|
+
* const origins = inputManager.getDigitalActionOrigins(handle, actionSet, jumpHandle);
|
|
837
|
+
* if (origins.length > 0) {
|
|
838
|
+
* const glyphPath = inputManager.getGlyphPNGForActionOrigin(
|
|
839
|
+
* origins[0],
|
|
840
|
+
* SteamInputGlyphSize.Medium,
|
|
841
|
+
* SteamInputGlyphStyle.Dark
|
|
842
|
+
* );
|
|
843
|
+
* // Display glyph image in UI
|
|
844
|
+
* }
|
|
845
|
+
* ```
|
|
846
|
+
*/
|
|
847
|
+
getGlyphPNGForActionOrigin(origin, size, flags) {
|
|
848
|
+
const iface = this.getSteamInputInterface();
|
|
849
|
+
if (!iface)
|
|
850
|
+
return '';
|
|
851
|
+
try {
|
|
852
|
+
return this.libraryLoader.SteamAPI_ISteamInput_GetGlyphPNGForActionOrigin(iface, origin, size, flags) || '';
|
|
853
|
+
}
|
|
854
|
+
catch (error) {
|
|
855
|
+
console.error('[SteamInput] GetGlyphPNGForActionOrigin error:', error);
|
|
856
|
+
return '';
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
/**
|
|
860
|
+
* Get the path to an SVG glyph for an action origin
|
|
861
|
+
*
|
|
862
|
+
* @param origin - Action origin (button)
|
|
863
|
+
* @param flags - Glyph style flags
|
|
864
|
+
* @returns Path to SVG file, or empty string if not available
|
|
865
|
+
*/
|
|
866
|
+
getGlyphSVGForActionOrigin(origin, flags) {
|
|
867
|
+
const iface = this.getSteamInputInterface();
|
|
868
|
+
if (!iface)
|
|
869
|
+
return '';
|
|
870
|
+
try {
|
|
871
|
+
return this.libraryLoader.SteamAPI_ISteamInput_GetGlyphSVGForActionOrigin(iface, origin, flags) || '';
|
|
872
|
+
}
|
|
873
|
+
catch (error) {
|
|
874
|
+
console.error('[SteamInput] GetGlyphSVGForActionOrigin error:', error);
|
|
875
|
+
return '';
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
/**
|
|
879
|
+
* Get localized string for an action origin
|
|
880
|
+
*
|
|
881
|
+
* @param origin - Action origin (button)
|
|
882
|
+
* @returns Localized button name (e.g., "A Button", "Cross")
|
|
883
|
+
*/
|
|
884
|
+
getStringForActionOrigin(origin) {
|
|
885
|
+
const iface = this.getSteamInputInterface();
|
|
886
|
+
if (!iface)
|
|
887
|
+
return '';
|
|
888
|
+
try {
|
|
889
|
+
return this.libraryLoader.SteamAPI_ISteamInput_GetStringForActionOrigin(iface, origin) || '';
|
|
890
|
+
}
|
|
891
|
+
catch (error) {
|
|
892
|
+
console.error('[SteamInput] GetStringForActionOrigin error:', error);
|
|
893
|
+
return '';
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
// ========================================
|
|
897
|
+
// Utility
|
|
898
|
+
// ========================================
|
|
899
|
+
/**
|
|
900
|
+
* Open the Steam Input configuration UI
|
|
901
|
+
*
|
|
902
|
+
* Shows the binding panel where users can customize their controller configuration.
|
|
903
|
+
*
|
|
904
|
+
* @param inputHandle - Controller handle
|
|
905
|
+
* @returns True if successful
|
|
906
|
+
*
|
|
907
|
+
* @example
|
|
908
|
+
* ```typescript
|
|
909
|
+
* // In your settings menu
|
|
910
|
+
* if (userClicksConfigureController) {
|
|
911
|
+
* inputManager.showBindingPanel(controllerHandle);
|
|
912
|
+
* }
|
|
913
|
+
* ```
|
|
914
|
+
*/
|
|
915
|
+
showBindingPanel(inputHandle) {
|
|
916
|
+
const iface = this.getSteamInputInterface();
|
|
917
|
+
if (!iface)
|
|
918
|
+
return false;
|
|
919
|
+
try {
|
|
920
|
+
return this.libraryLoader.SteamAPI_ISteamInput_ShowBindingPanel(iface, inputHandle);
|
|
921
|
+
}
|
|
922
|
+
catch (error) {
|
|
923
|
+
console.error('[SteamInput] ShowBindingPanel error:', error);
|
|
924
|
+
return false;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* Get the binding revision for a device
|
|
929
|
+
*
|
|
930
|
+
* @param inputHandle - Controller handle
|
|
931
|
+
* @returns Device binding revision, or null if not available
|
|
932
|
+
*/
|
|
933
|
+
getDeviceBindingRevision(inputHandle) {
|
|
934
|
+
const iface = this.getSteamInputInterface();
|
|
935
|
+
if (!iface)
|
|
936
|
+
return null;
|
|
937
|
+
try {
|
|
938
|
+
const majorBuffer = Buffer.alloc(4);
|
|
939
|
+
const minorBuffer = Buffer.alloc(4);
|
|
940
|
+
const success = this.libraryLoader.SteamAPI_ISteamInput_GetDeviceBindingRevision(iface, inputHandle, majorBuffer, minorBuffer);
|
|
941
|
+
if (success) {
|
|
942
|
+
return {
|
|
943
|
+
major: majorBuffer.readInt32LE(0),
|
|
944
|
+
minor: minorBuffer.readInt32LE(0),
|
|
945
|
+
};
|
|
946
|
+
}
|
|
947
|
+
return null;
|
|
948
|
+
}
|
|
949
|
+
catch (error) {
|
|
950
|
+
console.error('[SteamInput] GetDeviceBindingRevision error:', error);
|
|
951
|
+
return null;
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Get the Remote Play session ID for a controller
|
|
956
|
+
*
|
|
957
|
+
* @param inputHandle - Controller handle
|
|
958
|
+
* @returns Session ID, or 0 if not in a Remote Play session
|
|
959
|
+
*/
|
|
960
|
+
getRemotePlaySessionID(inputHandle) {
|
|
961
|
+
const iface = this.getSteamInputInterface();
|
|
962
|
+
if (!iface)
|
|
963
|
+
return 0;
|
|
964
|
+
try {
|
|
965
|
+
return this.libraryLoader.SteamAPI_ISteamInput_GetRemotePlaySessionID(iface, inputHandle);
|
|
966
|
+
}
|
|
967
|
+
catch (error) {
|
|
968
|
+
console.error('[SteamInput] GetRemotePlaySessionID error:', error);
|
|
969
|
+
return 0;
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
/**
|
|
973
|
+
* Get the current session input configuration settings
|
|
974
|
+
*
|
|
975
|
+
* Returns a bitmask of ESteamInputConfigurationEnableType values.
|
|
976
|
+
*
|
|
977
|
+
* @returns Configuration settings bitmask
|
|
978
|
+
*/
|
|
979
|
+
getSessionInputConfigurationSettings() {
|
|
980
|
+
const iface = this.getSteamInputInterface();
|
|
981
|
+
if (!iface)
|
|
982
|
+
return 0;
|
|
983
|
+
try {
|
|
984
|
+
return this.libraryLoader.SteamAPI_ISteamInput_GetSessionInputConfigurationSettings(iface);
|
|
985
|
+
}
|
|
986
|
+
catch (error) {
|
|
987
|
+
console.error('[SteamInput] GetSessionInputConfigurationSettings error:', error);
|
|
988
|
+
return 0;
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
exports.SteamInputManager = SteamInputManager;
|
|
993
|
+
//# sourceMappingURL=SteamInputManager.js.map
|