Dodaj niestandardowe mapowania urządzeń kontrolera

Biblioteka kontrolerów gier przechowuje wewnętrzną bazę danych urządzeń kontrolerów, która służy do konfigurowania przycisków, układu osi ruchu, mapowania dla rozpoznanych kontrolerów oraz domyślnego mapowania dla nierozpoznanych kontrolerów. Baza danych obejmuje wiele popularnych kontrolerów, ale może nie obejmować wszystkich urządzeń związanych z konkretną grą. Biblioteka kontrolerów gier umożliwia dostosowywanie za pomocą funkcji, które:

  • Pobierz bieżącą bazę danych mapowania.
  • Dodaj wpisy do istniejącej bazy danych.
  • Zastąp istniejące wpisy bazy danych.
  • Zastąp całą bieżącą bazę danych nową.

Identyfikowanie urządzenia

Urządzenia będące kontrolerami są identyfikowane na podstawie wartości productId i vendorId. Każde rozpoznane urządzenie kontrolera ma w bazie danych co najmniej 1 wpis z pasującymi ustawieniami productId i vendorId. Struktura mapowania kontrolera zawiera pola, które określają minimalny i maksymalny zakres interfejsu API Androida dla danego wpisu. W bazie danych może być wiele wpisów z tymi samymi wartościami productId i vendorId, o ile mają one unikalne minimalne i maksymalne zakresy interfejsu API.

Odczytywanie bieżących danych ponownego mapowania

Aby pobrać bieżące dane mapowania, użyj funkcji Paddleboat_getControllerRemapTableData.

int32_t Paddleboat_getControllerRemapTableData(
   const int32_t destRemapTableEntryCount,
   Paddleboat_Controller_Mapping_Data* mappingData)

Paddleboat_getControllerRemapTableData zwraca łączną liczbę wpisów ponownego mapowania obecnych w wewnętrznej bazie danych.

Parametr Opis
destRemapTableEntryCount Rozmiar tablicy elementów Paddleboat_Controller_Mapping_Data przekazywanych w parametrze mappingData.
mappingData Wskaźnik do tablicy elementów Paddleboat_Controller_Mapping_Data.

Jeśli wartość destRemapTableEntryCount jest mniejsza niż łączna liczba wpisów ponownego mapowania, do wartości mappingData zostanie skopiowana tylko liczba wpisów określona w zasadzie destRemapTableEntryCount.

Dodawanie i zastępowanie danych mapowania

Aby dodać ponownie wpisy lub zastąpić bieżącą bazę danych remapuj, użyj funkcji Paddleboat_addControllerRemapData.

void Paddleboat_addControllerRemapData(
   const Paddleboat_Remap_Addition_Mode addMode,
   const int32_t remapTableEntryCount,
   const Paddleboat_Controller_Mapping_Data* mappingData)
Parametr Opis
addMode Reguły dodawania używane w operacji. Prawidłowe wartości to PADDLEBOAT_REMAP_ADD_MODE_DEFAULT lub PADDLEBOAT_REMAP_ADD_MODE_REPLACE_ALL
remapTableEntryCount Rozmiar tablicy elementów Paddleboat_Controller_Mapping_Data przekazywanych w parametrze mappingData.
mappingData Wskaźnik do tablicy elementów Paddleboat_Controller_Mapping_Data.

Tryby dodawania

Jeśli w polu addMode określono PADDLEBOAT_REMAP_ADD_MODE_REPLACE_ALL, istniejąca baza danych zostanie usunięta i zastąpiona zawartością nowej tablicy.

Jeśli w elemencie addMode określono PADDLEBOAT_REMAP_ADD_MODE_DEFAULT, do każdego elementu w tablicy przekazywanej w funkcji mappingData stosowane są te kryteria:

  • Jeśli Paddleboat_getControllerRemapTableData jest unikalny (czyli vendorId i productId jeszcze nie istnieją albo istnieją, ale mają niepokrywające się zakresy minApi lub maxApi), wpis jest dodawany do wewnętrznej bazy danych.
  • Jeśli Paddleboat_getControllerRemapTableData nie jest unikalny (istnieje vendorId i productId, a pokrywające się elementy minApi lub maxApi się pokrywają), zastępuje istniejący wpis w wewnętrznej bazie danych.

Struktura Paddleboat_Controller_Mapping_Data jest:

typedef struct Paddleboat_Controller_Mapping_Data {
    int16_t minimumEffectiveApiLevel; /** Min. API level for this entry */
    int16_t maximumEffectiveApiLevel; /** Max. API level, 0 = no max */
    int32_t vendorId; /** VendorID of the controller device for this entry */
    int32_t productId; /** ProductID of the controller device for this entry */
    int32_t flags; /** Flag bits, will be ORed with
                     * Paddleboat_Controller_Info.controllerFlags */

    /** AMOTION_EVENT_AXIS value for the corresponding Paddleboat control axis,
     *  or PADDLEBOAT_AXIS_IGNORED if unsupported. */
    uint16_t axisMapping[PADDLEBOAT_MAPPING_AXIS_COUNT];
    /** Button to set on positive or negative axis value,
     *  PADDLEBOAT_AXIS_BUTTON_IGNORED if none. */
    uint8_t axisPositiveButtonMapping[PADDLEBOAT_MAPPING_AXIS_COUNT];
    uint8_t axisNegativeButtonMapping[PADDLEBOAT_MAPPING_AXIS_COUNT];
    /** AKEYCODE_ value corresponding with the corresponding Paddleboat button.
     *  PADDLEBOAT_BUTTON_IGNORED if unsupported. */
    uint16_t buttonMapping[PADDLEBOAT_BUTTON_COUNT];
} Paddleboat_Controller_Mapping_Data;

Przykład mapowania

Poniżej widać pole Paddleboat_Controller_Mapping_Data z opisem kontrolera Google Stadia:

#define PADDLEBOAT_AXIS_BUTTON_DPAD_UP 0
#define PADDLEBOAT_AXIS_BUTTON_DPAD_LEFT 1
#define PADDLEBOAT_AXIS_BUTTON_DPAD_DOWN 2
#define PADDLEBOAT_AXIS_BUTTON_DPAD_RIGHT 3
#define PADDLEBOAT_AXIS_BUTTON_L2 9
#define PADDLEBOAT_AXIS_BUTTON_R2 12

static const Paddleboat_Controller_Mapping_Data stadia_controller_map[] = {
    16, 0, 0x18d1, 0x9400, PADDLEBOAT_CONTROLLER_LAYOUT_STANDARD,
    {
        /* LX */ AMOTION_EVENT_AXIS_X,
        /* LY */ AMOTION_EVENT_AXIS_Y,
        /* RX */ AMOTION_EVENT_AXIS_Z,
        /* RY */ AMOTION_EVENT_AXIS_RZ,
        /* L1 */ PADDLEBOAT_AXIS_IGNORED,
        /* L2 */ AMOTION_EVENT_AXIS_BRAKE,
        /* R1 */ PADDLEBOAT_AXIS_IGNORED,
        /* R2 */ AMOTION_EVENT_AXIS_GAS,
        /* HX */ AMOTION_EVENT_AXIS_HAT_X,
        /* HY */ AMOTION_EVENT_AXIS_HAT_Y,
    },
    {
        /* LX */ PADDLEBOAT_AXIS_BUTTON_IGNORED,
        /* LY */ PADDLEBOAT_AXIS_BUTTON_IGNORED,
        /* RX */ PADDLEBOAT_AXIS_BUTTON_IGNORED,
        /* RY */ PADDLEBOAT_AXIS_BUTTON_IGNORED,
        /* L1 */ PADDLEBOAT_AXIS_BUTTON_IGNORED,
        /* L2 */ PADDLEBOAT_AXIS_BUTTON_L2,
        /* R1 */ PADDLEBOAT_AXIS_BUTTON_IGNORED,
        /* R2 */ PADDLEBOAT_AXIS_BUTTON_R2,
        /* HX */ PADDLEBOAT_AXIS_BUTTON_DPAD_RIGHT,
        /* HY */ PADDLEBOAT_AXIS_BUTTON_DPAD_DOWN,
    },
    {
        /* LX */ PADDLEBOAT_AXIS_BUTTON_IGNORED,
        /* LY */ PADDLEBOAT_AXIS_BUTTON_IGNORED,
        /* RX */ PADDLEBOAT_AXIS_BUTTON_IGNORED,
        /* RY */ PADDLEBOAT_AXIS_BUTTON_IGNORED,
        /* L1 */ PADDLEBOAT_AXIS_BUTTON_IGNORED,
        /* L2 */ PADDLEBOAT_AXIS_BUTTON_IGNORED,
        /* R1 */ PADDLEBOAT_AXIS_BUTTON_IGNORED,
        /* R2 */ PADDLEBOAT_AXIS_BUTTON_IGNORED,
        /* HX */ PADDLEBOAT_AXIS_BUTTON_DPAD_LEFT,
        /* HY */ PADDLEBOAT_AXIS_BUTTON_DPAD_UP,
    },
    {
        /* UP     */ AKEYCODE_DPAD_UP,
        /* LEFT   */ AKEYCODE_DPAD_LEFT,
        /* DOWN   */ AKEYCODE_DPAD_DOWN,
        /* RIGHT  */ AKEYCODE_DPAD_RIGHT,
        /* A      */ AKEYCODE_BUTTON_A,
        /* B      */ AKEYCODE_BUTTON_B,
        /* X      */ AKEYCODE_BUTTON_X,
        /* Y      */ AKEYCODE_BUTTON_Y,
        /* L1     */ AKEYCODE_BUTTON_L1,
        /* L2     */ AKEYCODE_BUTTON_L2,
        /* L3     */ AKEYCODE_BUTTON_THUMBL,
        /* R1     */ AKEYCODE_BUTTON_R1,
        /* R2     */ AKEYCODE_BUTTON_R2,
        /* R3     */ AKEYCODE_BUTTON_THUMBR,
        /* SELECT */ AKEYCODE_BUTTON_SELECT,
        /* START  */ AKEYCODE_BUTTON_START,
        /* SYSTEM */ AKEYCODE_BUTTON_MODE,
        /* TOUCHP */ PADDLEBOAT_BUTTON_IGNORED,
        /* AUX1   */ PADDLEBOAT_BUTTON_IGNORED,
        /* AUX2   */ PADDLEBOAT_BUTTON_IGNORED,
        /* AUX3   */ PADDLEBOAT_BUTTON_IGNORED,
        /* AUX4   */ PADDLEBOAT_BUTTON_IGNORED
    }
};