diff --git a/FCL/build.gradle b/FCL/build.gradle index 863ca6924..f2fe4e251 100644 --- a/FCL/build.gradle +++ b/FCL/build.gradle @@ -176,6 +176,7 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'com.google.android.material:material:1.11.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'com.github.Mathias-Boulay:android_gamepad_remapper:06184ddbce' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' diff --git a/FCL/src/main/java/com/tungsten/fcl/control/FCLInput.java b/FCL/src/main/java/com/tungsten/fcl/control/FCLInput.java index e58c017ef..58738ad2b 100644 --- a/FCL/src/main/java/com/tungsten/fcl/control/FCLInput.java +++ b/FCL/src/main/java/com/tungsten/fcl/control/FCLInput.java @@ -15,7 +15,11 @@ import java.util.HashMap; -public class FCLInput implements View.OnCapturedPointerListener { +import fr.spse.gamepad_remapper.GamepadHandler; +import fr.spse.gamepad_remapper.RemapperManager; +import fr.spse.gamepad_remapper.RemapperView; + +public class FCLInput implements View.OnCapturedPointerListener, GamepadHandler { public static final int MOUSE_LEFT = 1000; public static final int MOUSE_MIDDLE = 1001; @@ -35,6 +39,9 @@ public class FCLInput implements View.OnCapturedPointerListener { private Choreographer choreographer; private float lastXAxis; private float lastYAxis; + private RemapperManager remapperManager; + private boolean leftTriggerDown = false; + private boolean rightTriggerDown = false; public static final HashMap MOUSE_MAP = new HashMap() { @@ -68,6 +75,7 @@ public FCLInput(MenuCallback menu) { this.screenWidth = AndroidUtils.getScreenWidth(FCLApplication.getCurrentActivity()); this.screenHeight = AndroidUtils.getScreenHeight(FCLApplication.getCurrentActivity()); + resetMapper(); } public void setPointer(int x, int y, String id) { @@ -210,11 +218,7 @@ public boolean handleKeyEvent(KeyEvent event) { } } if (event.getDevice() != null && ((event.getSource() & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)) { - if (event.getRepeatCount() == 0) { - int converted = GamepadKeycodeMap.convert(event.getKeyCode()); - sendKeyEvent(converted, event.getAction() == KeyEvent.ACTION_DOWN); - } - return true; + return remapperManager.handleKeyEventInput(((GameMenu) menu).getActivity(),event,this); } if ((event.getFlags() & KeyEvent.FLAG_SOFT_KEYBOARD) == KeyEvent.FLAG_SOFT_KEYBOARD) { if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER) @@ -256,6 +260,7 @@ public void doFrame(long frameTimeNanos) { }; choreographer.postFrameCallback(frameCallback); } + remapperManager.handleMotionEventInput(((GameMenu) menu).getActivity(),event,this); if (event.getAction() == MotionEvent.ACTION_MOVE) { handleDPad(event); handleLeftJoyStick(event); @@ -340,5 +345,78 @@ private void handleRightJoyStick(MotionEvent event) { doTick(); } } +public void resetMapper() { + remapperManager = new RemapperManager(((GameMenu) menu).getActivity(), new RemapperView.Builder(null) + .remapA(true) + .remapB(true) + .remapX(true) + .remapY(true) + .remapLeftJoystick(true) + .remapRightJoystick(true) + .remapStart(true) + .remapSelect(true) + .remapLeftShoulder(true) + .remapRightShoulder(true) + .remapLeftTrigger(true) + .remapRightTrigger(true)); +} + /** + * Function handling all gamepad actions. + * + * @param code Either a keycode (Eg. KEYBODE_BUTTON_A), either an axis (Eg. AXIS_HAT_X) + * @param value For keycodes, 0 for released state, 1 for pressed state. + * For Axis, the value of the axis. Varies between 0/1 or -1/1 depending on the axis. + */ + @Override + public void handleGamepadInput(int code, float value) { + boolean isKeyDown = value == 1f; + switch (code) { + case KeyEvent.KEYCODE_BUTTON_A: + case KeyEvent.KEYCODE_BUTTON_B: + case KeyEvent.KEYCODE_BUTTON_X: + case KeyEvent.KEYCODE_BUTTON_Y: + //Shoulders + case KeyEvent.KEYCODE_BUTTON_L1: + case KeyEvent.KEYCODE_BUTTON_R1: + //Triggers + case KeyEvent.KEYCODE_BUTTON_L2: + case KeyEvent.KEYCODE_BUTTON_R2: + //L3 || R3 + case KeyEvent.KEYCODE_BUTTON_THUMBL: + case KeyEvent.KEYCODE_BUTTON_THUMBR: + //DPAD + case KeyEvent.KEYCODE_DPAD_UP: + case KeyEvent.KEYCODE_DPAD_DOWN: + case KeyEvent.KEYCODE_DPAD_LEFT: + case KeyEvent.KEYCODE_DPAD_RIGHT: + case KeyEvent.KEYCODE_DPAD_CENTER: + //Start/select + case KeyEvent.KEYCODE_BUTTON_START: + case KeyEvent.KEYCODE_BUTTON_SELECT: + sendKeyEvent(GamepadKeycodeMap.convert(code), isKeyDown); + break; + // Triggers + case MotionEvent.AXIS_LTRIGGER: + if (!leftTriggerDown && value > 0.5) { + leftTriggerDown = true; + sendKeyEvent(GamepadKeycodeMap.convert(KeyEvent.KEYCODE_BUTTON_L2), leftTriggerDown); + } else if (leftTriggerDown && value < 0.5) { + leftTriggerDown = false; + sendKeyEvent(GamepadKeycodeMap.convert(KeyEvent.KEYCODE_BUTTON_L2), leftTriggerDown); + } + break; + case MotionEvent.AXIS_RTRIGGER: + if (!rightTriggerDown && value > 0.5) { + rightTriggerDown = true; + sendKeyEvent(GamepadKeycodeMap.convert(KeyEvent.KEYCODE_BUTTON_R2), rightTriggerDown); + } else if (rightTriggerDown && value < 0.5) { + rightTriggerDown = false; + sendKeyEvent(GamepadKeycodeMap.convert(KeyEvent.KEYCODE_BUTTON_R2), rightTriggerDown); + } + break; + default: + break; + } + } } diff --git a/FCL/src/main/java/com/tungsten/fcl/control/GameMenu.java b/FCL/src/main/java/com/tungsten/fcl/control/GameMenu.java index 457031ce3..94bdf0620 100644 --- a/FCL/src/main/java/com/tungsten/fcl/control/GameMenu.java +++ b/FCL/src/main/java/com/tungsten/fcl/control/GameMenu.java @@ -74,6 +74,8 @@ import java.util.logging.Level; import java.util.stream.Collectors; +import fr.spse.gamepad_remapper.Remapper; + public class GameMenu implements MenuCallback, View.OnClickListener { private boolean simulated; @@ -108,6 +110,7 @@ public class GameMenu implements MenuCallback, View.OnClickListener { private FCLButton openMultiplayerMenu; private FCLButton manageQuickInput; private FCLButton sendKeycode; + private FCLButton gamepadResetMapper; private FCLButton forceExit; public FCLActivity getActivity() { @@ -347,6 +350,7 @@ private void initRightMenu() { openMultiplayerMenu = findViewById(R.id.open_multiplayer_menu); manageQuickInput = findViewById(R.id.open_quick_input); sendKeycode = findViewById(R.id.open_send_key); + gamepadResetMapper = findViewById(R.id.gamepad_reset_mapper); forceExit = findViewById(R.id.force_exit); FXUtils.bindBoolean(lockMenuSwitch, menuSetting.lockMenuViewProperty()); @@ -464,6 +468,7 @@ protected void invalidated() { openMultiplayerMenu.setOnClickListener(this); manageQuickInput.setOnClickListener(this); sendKeycode.setOnClickListener(this); + gamepadResetMapper.setOnClickListener(this); forceExit.setOnClickListener(this); } @@ -721,6 +726,10 @@ public void onClone(CustomControl view) { SelectKeycodeDialog dialog = new SelectKeycodeDialog(getActivity(), list, false, true, this); dialog.show(); } + if (v == gamepadResetMapper) { + Remapper.wipePreferences(getActivity()); + getInput().resetMapper(); + } if (v == forceExit) { FCLAlertDialog.Builder builder = new FCLAlertDialog.Builder(activity); builder.setAlertLevel(FCLAlertDialog.AlertLevel.ALERT); diff --git a/FCL/src/main/res/layout/menu_right.xml b/FCL/src/main/res/layout/menu_right.xml index d94833091..ab73a6bf8 100644 --- a/FCL/src/main/res/layout/menu_right.xml +++ b/FCL/src/main/res/layout/menu_right.xml @@ -471,6 +471,34 @@ android:layout_height="1dp" android:background="@android:color/darker_gray"/> + + + + + + + + 鼠标灵敏度 鼠标尺寸 手柄 + 重置映射 + 重置 调整死区 联机菜单 打开 diff --git a/FCL/src/main/res/values/strings.xml b/FCL/src/main/res/values/strings.xml index 8d9ff031e..7df1f5443 100644 --- a/FCL/src/main/res/values/strings.xml +++ b/FCL/src/main/res/values/strings.xml @@ -528,6 +528,8 @@ Mouse Sensitivity Mouse Size GamePad + ResetMapper + Reset DeadZone AimAssistZone Multiplayer Menu