|
3 | 3 | * This module provides a set of utilities for working with gamepads in web applications. |
4 | 4 | */ |
5 | 5 |
|
| 6 | +const { |
| 7 | + GamepadVisualizer, |
| 8 | + getControllerImagePath, |
| 9 | + getControllerVisualConfig, |
| 10 | +} = require('./gamepad-visualizer'); |
| 11 | + |
| 12 | +const FIREFOX_SWITCH_GAMEPAD_FIXED_VERSION = 155; |
| 13 | +const FIREFOX_SWITCH_GAMEPAD_ISSUE_URL = 'https://bugzilla.mozilla.org/show_bug.cgi?id=1704419'; |
| 14 | + |
6 | 15 | /** |
7 | 16 | * Controller identity metadata used by browser ID lookups. |
8 | 17 | * @typedef {Object} GamepadIdentityMapping |
@@ -372,6 +381,40 @@ class GamepadHelper { |
372 | 381 | return null; |
373 | 382 | } |
374 | 383 |
|
| 384 | + /** |
| 385 | + * Get the image path for a full controller visual. |
| 386 | + * @param {string} controllerType - The type of controller (XBOX, PLAYSTATION, SWITCH) |
| 387 | + * @param {string} [basePath='/assets/img/gamepads/'] - The base path for the images |
| 388 | + * @param {string} [colorScheme='White'] - The image color ('Black' or 'White') |
| 389 | + * @returns {string|null} Encoded controller image path, or null when unavailable |
| 390 | + */ |
| 391 | + getControllerImagePath( |
| 392 | + controllerType, |
| 393 | + basePath = '/assets/img/gamepads/', |
| 394 | + colorScheme = 'White', |
| 395 | + ) { |
| 396 | + return getControllerImagePath(controllerType, basePath, colorScheme); |
| 397 | + } |
| 398 | + |
| 399 | + /** |
| 400 | + * Get a copy of the visual definition for a controller type. |
| 401 | + * @param {string} controllerType - The type of controller (XBOX, PLAYSTATION, SWITCH) |
| 402 | + * @returns {Object|null} Controller visual definition, or null when unavailable |
| 403 | + */ |
| 404 | + getControllerVisualConfig(controllerType) { |
| 405 | + return getControllerVisualConfig(controllerType); |
| 406 | + } |
| 407 | + |
| 408 | + /** |
| 409 | + * Create a reusable visualizer in a caller-provided DOM container. |
| 410 | + * @param {Element} container - DOM element that will contain the visual |
| 411 | + * @param {Object} [options] - Visualizer options |
| 412 | + * @returns {GamepadVisualizer} Controller visualizer |
| 413 | + */ |
| 414 | + createVisualizer(container, options = {}) { |
| 415 | + return new GamepadVisualizer(this, container, options); |
| 416 | + } |
| 417 | + |
375 | 418 | /** |
376 | 419 | * Check if the Gamepad API is supported in the current browser |
377 | 420 | * @returns {boolean} True if supported, false otherwise |
@@ -449,6 +492,55 @@ class GamepadHelper { |
449 | 492 | return this.getGamepadInfo(gamepadId).type; |
450 | 493 | } |
451 | 494 |
|
| 495 | + /** |
| 496 | + * Extract the major Firefox version from a user-agent string. |
| 497 | + * @param {string|null} userAgent - Browser user-agent string |
| 498 | + * @returns {number|null} Firefox major version, or null for other browsers |
| 499 | + */ |
| 500 | + getFirefoxMajorVersion(userAgent) { |
| 501 | + if (typeof userAgent !== 'string') { |
| 502 | + return null; |
| 503 | + } |
| 504 | + |
| 505 | + const match = /\bFirefox\/(\d+)/.exec(userAgent); |
| 506 | + return match ? Number.parseInt(match[1], 10) : null; |
| 507 | + } |
| 508 | + |
| 509 | + /** |
| 510 | + * Get known browser/controller compatibility issues for a gamepad. |
| 511 | + * @param {Gamepad|null} gamepad - Gamepad to inspect |
| 512 | + * @param {Object} [options] - Detection options |
| 513 | + * @param {string} [options.userAgent=navigator.userAgent] - Browser user-agent string |
| 514 | + * @returns {Object[]} Structured compatibility issues |
| 515 | + */ |
| 516 | + getCompatibilityIssues(gamepad, options = {}) { |
| 517 | + if (!gamepad) { |
| 518 | + return []; |
| 519 | + } |
| 520 | + |
| 521 | + const userAgent = options.userAgent ?? globalThis.navigator?.userAgent ?? ''; |
| 522 | + const firefoxVersion = this.getFirefoxMajorVersion(userAgent); |
| 523 | + const controllerInfo = this.getGamepadInfo(gamepad.id); |
| 524 | + if ( |
| 525 | + firefoxVersion === null |
| 526 | + || firefoxVersion >= FIREFOX_SWITCH_GAMEPAD_FIXED_VERSION |
| 527 | + || controllerInfo.type !== this.CONTROLLER_TYPES.SWITCH |
| 528 | + ) { |
| 529 | + return []; |
| 530 | + } |
| 531 | + |
| 532 | + return [{ |
| 533 | + code: 'firefox-switch-gamepad-mapping', |
| 534 | + severity: 'warning', |
| 535 | + browser: 'firefox', |
| 536 | + browserVersion: firefoxVersion, |
| 537 | + controllerType: controllerInfo.type, |
| 538 | + fixedVersion: FIREFOX_SWITCH_GAMEPAD_FIXED_VERSION, |
| 539 | + issueUrl: FIREFOX_SWITCH_GAMEPAD_ISSUE_URL, |
| 540 | + message: `Firefox versions before ${FIREFOX_SWITCH_GAMEPAD_FIXED_VERSION} can report incorrect buttons and axes for Nintendo Switch controllers.`, |
| 541 | + }]; |
| 542 | + } |
| 543 | + |
452 | 544 | /** |
453 | 545 | * Get button name for given controller type and button index |
454 | 546 | * @param {string} controllerType - The type of controller (XBOX, PLAYSTATION, SWITCH, STANDARD) |
@@ -590,5 +682,7 @@ if (globalThis.window) { |
590 | 682 | globalThis.GamepadHelper = GamepadHelper; |
591 | 683 | } |
592 | 684 |
|
| 685 | +GamepadHelper.GamepadVisualizer = GamepadVisualizer; |
| 686 | + |
593 | 687 | // Export the GamepadHelper class |
594 | 688 | module.exports = GamepadHelper; |
0 commit comments