新增自訂控制器裝置對應關係

遊戲控制器程式庫會維護控制器裝置的內部資料庫,用於設定按鈕、動態軸版面配置、可辨識的控制器對應,以及為無法辨識的控制器預設對應。資料庫包含許多熱門的控制器,但可能不會包含與特定遊戲相關的所有裝置。遊戲控制器程式庫支援具有下列功能的自訂功能:

  • 擷取目前的對應資料庫。
  • 將條目新增至現有資料庫。
  • 取代現有的資料庫條目。
  • 使用新的資料庫取代目前的資料庫。

標識裝置

控制器裝置會以 productIdvendorId 值標識。每個已辨識的控制器裝置在資料庫中至少含有一個與 productIdvendorId 相符的條目。控制器對應結構中包含可針對該條目指定合格 Android API 上下限值範圍的欄位。只要在 API 範圍中設有不重複上限值和下限值,資料庫中就可能存在多個具有相同 productIdvendorId 的條目。

讀取目前的重新對應資料

使用 Paddleboat_getControllerRemapTableData 函式擷取目前的重新對應資料。

int32_t Paddleboat_getControllerRemapTableData(
   const int32_t destRemapTableEntryCount,
   Paddleboat_Controller_Mapping_Data* mappingData)

Paddleboat_getControllerRemapTableData 會傳回內部資料庫中的重新對應條目總數。

參數 說明
destRemapTableEntryCount 透過 mappingData 參數傳送的 Paddleboat_Controller_Mapping_Data 元素陣列大小。
mappingData 指向 Paddleboat_Controller_Mapping_Data 元素陣列的指標。

如果 destRemapTableEntryCount 小於重新對應條目總數,則只有 destRemapTableEntryCount 指定的條目數量會複製到 mappingData

新增或取代對應資料

使用 Paddleboat_addControllerRemapData 函式新增對應條目,或是取代目前的重新對應資料庫。

void Paddleboat_addControllerRemapData(
   const Paddleboat_Remap_Addition_Mode addMode,
   const int32_t remapTableEntryCount,
   const Paddleboat_Controller_Mapping_Data* mappingData)
參數 說明
addMode 用於該作業的額外規則。 有效值為 PADDLEBOAT_REMAP_ADD_MODE_DEFAULTPADDLEBOAT_REMAP_ADD_MODE_REPLACE_ALL
remapTableEntryCount 透過 mappingData 參數傳送的 Paddleboat_Controller_Mapping_Data 元素陣列大小。
mappingData 指向 Paddleboat_Controller_Mapping_Data 元素陣列的指標。

新增模式

如果在 addMode 中指定 PADDLEBOAT_REMAP_ADD_MODE_REPLACE_ALL,則現有資料庫會遭到刪除,並替換成新陣列的內容。

如果在 addMode 中指定 PADDLEBOAT_REMAP_ADD_MODE_DEFAULT,則下列條件會套用至 mappingData 中傳送的陣列中的每個元素:

  • 如果 Paddleboat_getControllerRemapTableData 不重複 (也就是 vendorIdproductId 尚不存在,或存在但有非重疊 minApimaxApi 範圍),則系統會將該條目新增至內部資料庫。
  • 如果 Paddleboat_getControllerRemapTableData 重複 (vendorIdproductId 已存在且有 minApimaxApi 重疊),則系統會取代內部資料庫的現有條目。

Paddleboat_Controller_Mapping_Data 結構如下:

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;

對應範例

下方說明了用來描述 Google Stadia 控制器Paddleboat_Controller_Mapping_Data

#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
    }
};