OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 package org.chromium.content.browser.input; |
| 6 |
| 7 import android.view.KeyEvent; |
| 8 import android.view.MotionEvent; |
| 9 |
| 10 import org.chromium.base.JNINamespace; |
| 11 import org.chromium.content.browser.input.gamepad_mapping.CanonicalAxisIndex; |
| 12 import org.chromium.content.browser.input.gamepad_mapping.CanonicalButtonIndex; |
| 13 |
| 14 import java.util.Arrays; |
| 15 |
| 16 /** |
| 17 * Device specific input data converter for Gamepad API. |
| 18 * Implemented per device by subclasses. |
| 19 */ |
| 20 @JNINamespace("content") |
| 21 abstract class GamepadDataMapper { |
| 22 protected static final String PS3_SIXAXIS_DEVICE_NAME = "Sony PLAYSTATION(R)
3 Controller"; |
| 23 protected static final String STANDARD_GAMEPAD_NAME = "(STANDARD_GAMEPAD)"; |
| 24 protected static final String STANDARD_MAPPING = "standard"; |
| 25 |
| 26 protected final WebGamepadData mData; |
| 27 |
| 28 public abstract WebGamepadData map(float[] axes, boolean[] buttons); |
| 29 |
| 30 // Factory method. |
| 31 public static GamepadDataMapper createDataMapper(String deviceName) { |
| 32 if (deviceName.equals(PS3_SIXAXIS_DEVICE_NAME)) |
| 33 return new PS3SixAxisGamepadDataMapper(); |
| 34 |
| 35 return new GenericGamepadDataMapper(deviceName); |
| 36 } |
| 37 |
| 38 protected GamepadDataMapper(String deviceName) { |
| 39 mData = new WebGamepadData(); |
| 40 mData.id = deviceName + " " + STANDARD_GAMEPAD_NAME; |
| 41 mData.mapping = STANDARD_MAPPING; |
| 42 mData.axes = new float[CanonicalAxisIndex.NUM_CANONICAL_AXES]; |
| 43 mData.buttons = new float[CanonicalButtonIndex.NUM_CANONICAL_BUTTONS]; |
| 44 } |
| 45 |
| 46 protected void clearAxesAndButtons() { |
| 47 Arrays.fill(mData.axes, 0); |
| 48 Arrays.fill(mData.buttons, 0); |
| 49 } |
| 50 |
| 51 // Most of the time we jut use 1 for pressed and 0 for not pressed. |
| 52 // Note that however some devices can represent some buttons of the standard
gamepad |
| 53 // with analog values so we still want to store the button values as floats. |
| 54 // For example the Samsung EI-GP20 maps dpad to AXIS_HAT_X and AXIS_HAT_Y. |
| 55 protected float buttonValue(boolean pressed) { return pressed ? 1.0f : 0.0f;
} |
| 56 |
| 57 protected void mapCommonXYAxes(float[] axes) { |
| 58 mData.axes[CanonicalAxisIndex.AXIS_LEFT_STICK_X] = axes[MotionEvent.AXIS
_X]; |
| 59 mData.axes[CanonicalAxisIndex.AXIS_LEFT_STICK_Y] = axes[MotionEvent.AXIS
_Y]; |
| 60 } |
| 61 |
| 62 protected void mapCommonTriggerAxes(float[] axes) { |
| 63 mData.buttons[CanonicalButtonIndex.BUTTON_LEFT_SHOULDER] = axes[MotionEv
ent.AXIS_LTRIGGER]; |
| 64 mData.buttons[CanonicalButtonIndex.BUTTON_RIGHT_SHOULDER] = axes[MotionE
vent.AXIS_RTRIGGER]; |
| 65 } |
| 66 |
| 67 protected void mapCommonTriggerButtons(boolean[] buttons) { |
| 68 boolean l1 = buttons[KeyEvent.KEYCODE_BUTTON_L1]; |
| 69 boolean r1 = buttons[KeyEvent.KEYCODE_BUTTON_R1]; |
| 70 mData.buttons[CanonicalButtonIndex.BUTTON_LEFT_TRIGGER] = buttonValue(l1
); |
| 71 mData.buttons[CanonicalButtonIndex.BUTTON_RIGHT_TRIGGER] = buttonValue(r
1); |
| 72 } |
| 73 |
| 74 protected void mapCommonThumbstickButtons(boolean[] buttons) { |
| 75 boolean thumbL = buttons[KeyEvent.KEYCODE_BUTTON_THUMBL]; |
| 76 boolean thumbR = buttons[KeyEvent.KEYCODE_BUTTON_THUMBR]; |
| 77 mData.buttons[CanonicalButtonIndex.BUTTON_LEFT_THUMBSTICK] = buttonValue
(thumbL); |
| 78 mData.buttons[CanonicalButtonIndex.BUTTON_RIGHT_THUMBSTICK] = buttonValu
e(thumbR); |
| 79 } |
| 80 |
| 81 protected void mapCommonStartSelectButtons(boolean[] buttons) { |
| 82 boolean select = buttons[KeyEvent.KEYCODE_BUTTON_SELECT]; |
| 83 boolean start = buttons[KeyEvent.KEYCODE_BUTTON_START]; |
| 84 mData.buttons[CanonicalButtonIndex.BUTTON_BACK_SELECT] = buttonValue(sel
ect); |
| 85 mData.buttons[CanonicalButtonIndex.BUTTON_START] = buttonValue(start); |
| 86 } |
| 87 |
| 88 protected void mapCommonDpadButtons(boolean[] buttons) { |
| 89 boolean dpadDown = buttons[KeyEvent.KEYCODE_DPAD_DOWN]; |
| 90 boolean dpadUp = buttons[KeyEvent.KEYCODE_DPAD_UP]; |
| 91 boolean dpadLeft = buttons[KeyEvent.KEYCODE_DPAD_LEFT]; |
| 92 boolean dpadRight = buttons[KeyEvent.KEYCODE_DPAD_RIGHT]; |
| 93 mData.buttons[CanonicalButtonIndex.BUTTON_DPAD_DOWN] = buttonValue(dpadD
own); |
| 94 mData.buttons[CanonicalButtonIndex.BUTTON_DPAD_UP] = buttonValue(dpadUp)
; |
| 95 mData.buttons[CanonicalButtonIndex.BUTTON_DPAD_LEFT] = buttonValue(dpadL
eft); |
| 96 mData.buttons[CanonicalButtonIndex.BUTTON_DPAD_RIGHT] = buttonValue(dpad
Right); |
| 97 } |
| 98 |
| 99 protected void mapCommonXYABButtons(boolean[] buttons) { |
| 100 boolean bA = buttons[KeyEvent.KEYCODE_BUTTON_A]; |
| 101 boolean bB = buttons[KeyEvent.KEYCODE_BUTTON_B]; |
| 102 boolean bX = buttons[KeyEvent.KEYCODE_BUTTON_X]; |
| 103 boolean bY = buttons[KeyEvent.KEYCODE_BUTTON_Y]; |
| 104 mData.buttons[CanonicalButtonIndex.BUTTON_PRIMARY] = buttonValue(bA); |
| 105 mData.buttons[CanonicalButtonIndex.BUTTON_SECONDARY] = buttonValue(bB); |
| 106 mData.buttons[CanonicalButtonIndex.BUTTON_TERTIARY] = buttonValue(bX); |
| 107 mData.buttons[CanonicalButtonIndex.BUTTON_QUATERNARY] = buttonValue(bY); |
| 108 } |
| 109 } |
| 110 |
| 111 // This is a last resort if we find a device that we don't know about. |
| 112 // The Android API is general enough that this can be better than nothing |
| 113 // but we should not really rely on this. |
| 114 class GenericGamepadDataMapper extends GamepadDataMapper { |
| 115 private final String mDeviceName; |
| 116 |
| 117 GenericGamepadDataMapper(String deviceName) { |
| 118 super(deviceName); |
| 119 mDeviceName = deviceName; |
| 120 } |
| 121 |
| 122 // Find something for right stick x and y. |
| 123 private void mapRightSticks(float[] axes) { |
| 124 int position = CanonicalAxisIndex.AXIS_RIGHT_STICK_X; |
| 125 // position + 1 is AXIS_RIGHT_STICK_Y. |
| 126 assert mData.axes.length > position + 1; |
| 127 float x = axes[MotionEvent.AXIS_RX]; |
| 128 float y = axes[MotionEvent.AXIS_RY]; |
| 129 if (x != 0 || y != 0) { |
| 130 mData.axes[position++] = x; |
| 131 mData.axes[position] = y; |
| 132 return; |
| 133 } |
| 134 x = axes[MotionEvent.AXIS_Z]; |
| 135 y = axes[MotionEvent.AXIS_RZ]; |
| 136 if (x != 0 || y != 0) { |
| 137 mData.axes[position++] = x; |
| 138 mData.axes[position] = y; |
| 139 return; |
| 140 } |
| 141 x = axes[MotionEvent.AXIS_HAT_X]; |
| 142 y = axes[MotionEvent.AXIS_HAT_Y]; |
| 143 if (x != 0 || y != 0) { |
| 144 mData.axes[position++] = x; |
| 145 mData.axes[position] = y; |
| 146 } |
| 147 } |
| 148 |
| 149 public WebGamepadData map(float[] axes, boolean[] buttons) { |
| 150 clearAxesAndButtons(); |
| 151 |
| 152 mapCommonXYAxes(axes); |
| 153 mapRightSticks(axes); |
| 154 mapCommonTriggerAxes(axes); |
| 155 mapCommonXYABButtons(buttons); |
| 156 mapCommonTriggerButtons(buttons); |
| 157 mapCommonThumbstickButtons(buttons); |
| 158 mapCommonStartSelectButtons(buttons); |
| 159 mapCommonDpadButtons(buttons); |
| 160 |
| 161 // TODO(b.kelemen): meta is missing. |
| 162 |
| 163 return mData; |
| 164 } |
| 165 } |
| 166 |
| 167 class PS3SixAxisGamepadDataMapper extends GamepadDataMapper { |
| 168 PS3SixAxisGamepadDataMapper() { |
| 169 super(PS3_SIXAXIS_DEVICE_NAME); |
| 170 } |
| 171 |
| 172 public WebGamepadData map(float[] axes, boolean[] buttons) { |
| 173 clearAxesAndButtons(); |
| 174 |
| 175 mapCommonXYAxes(axes); |
| 176 |
| 177 mData.axes[CanonicalAxisIndex.AXIS_RIGHT_STICK_X] = axes[MotionEvent.AXI
S_Z]; |
| 178 mData.axes[CanonicalAxisIndex.AXIS_RIGHT_STICK_Y] = axes[MotionEvent.AXI
S_RZ]; |
| 179 |
| 180 mapCommonTriggerAxes(axes); |
| 181 |
| 182 boolean bA = buttons[KeyEvent.KEYCODE_BUTTON_A]; |
| 183 boolean bB = buttons[KeyEvent.KEYCODE_BUTTON_B]; |
| 184 boolean bX = buttons[KeyEvent.KEYCODE_BUTTON_X]; |
| 185 boolean bY = buttons[KeyEvent.KEYCODE_BUTTON_Y]; |
| 186 mData.buttons[CanonicalButtonIndex.BUTTON_PRIMARY] = buttonValue(bX); |
| 187 mData.buttons[CanonicalButtonIndex.BUTTON_SECONDARY] = buttonValue(bY); |
| 188 mData.buttons[CanonicalButtonIndex.BUTTON_TERTIARY] = buttonValue(bA); |
| 189 mData.buttons[CanonicalButtonIndex.BUTTON_QUATERNARY] = buttonValue(bB); |
| 190 |
| 191 mapCommonTriggerButtons(buttons); |
| 192 mapCommonThumbstickButtons(buttons); |
| 193 mapCommonStartSelectButtons(buttons); |
| 194 mapCommonDpadButtons(buttons); |
| 195 |
| 196 // TODO(b.kelemen): PS button is missing. Looks like it is swallowed by
Android |
| 197 // but probably there is a way to configure otherwise and in this case w
e should |
| 198 // handle it. |
| 199 |
| 200 return mData; |
| 201 } |
| 202 } |
| 203 |
| 204 // TODO(b.kelemen): add more implementations. It would be nice to support at lea
st those that are |
| 205 // supported on Linux. |
OLD | NEW |