添加自定义控制器设备映射

Game Controller 库负责维护控制器设备的内部数据库,它可用于配置按钮、动作轴布局、识别出的控制器的映射以及无法识别的控制器的默认映射。通过 数据库包含许多常用的控制器,但可能并未包含所有设备 与特定游戏相关Game Controller 库支持自定义,具有可实现以下目的的函数:

  • 检索当前映射数据库。
  • 向现有数据库添加条目。
  • 替换现有的数据库条目。
  • 将整个当前数据库替换为全新数据库。

识别设备

控制器设备由其 productIdvendorId 值进行标识。每个识别出的控制器设备在数据库中至少有一个条目具有 匹配“productId”和“vendorId”。控制器映射结构包含用于指定该条目符合条件的最小和最大 Android API 范围的字段。以下位置可能存在多个具有相同 productIdvendorId 的条目: 只要 API 范围不重复,就可以访问数据库。

读取当前的重新映射数据

您可以使用 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;

映射示例

以下代码显示了已填充的 Paddleboat_Controller_Mapping_Data,以描述 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
   
}
};