Feat[V 2.Gamepad]: Merge #4179

* Feat: gamepad remapping, with custom deazone

* Fix[gamepad]: wrong starting pointer offset

* cleanup[gamepad]: Remove useless variables

* Fix[gamepad]: Reduce jitter

Turns out the argument was a bit off when there are cpu constraints

* Chore: bump up remapper library version

* Build: bump up library version
This commit is contained in:
Boulay Mathias 2023-05-21 12:50:06 +02:00 committed by GitHub
parent 7916166795
commit 809f5cd6e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 277 additions and 192 deletions

View File

@ -157,6 +157,7 @@ dependencies {
implementation 'com.github.PojavLauncherTeam:portrait-sdp:ed33e89cbc'
implementation 'com.github.PojavLauncherTeam:portrait-ssp:6c02fd739b'
implementation 'com.github.Mathias-Boulay:ExtendedView:1.0.0'
implementation 'com.github.Mathias-Boulay:android_gamepad_remapper:71397676b5'
// implementation 'com.intuit.sdp:sdp-android:1.0.5'

View File

@ -39,12 +39,32 @@ import net.kdt.pojavlaunch.utils.MathUtils;
import org.lwjgl.glfw.CallbackBridge;
import fr.spse.gamepad_remapper.RemapperManager;
import fr.spse.gamepad_remapper.RemapperView;
/**
* Class dealing with showing minecraft surface and taking inputs to dispatch them to minecraft
*/
public class MinecraftGLSurface extends View implements GrabListener{
public class MinecraftGLSurface extends View implements GrabListener {
/* Gamepad object for gamepad inputs, instantiated on need */
private Gamepad mGamepad = null;
/* The RemapperView.Builder object allows you to set which buttons to remap */
private final RemapperManager mInputManager = new RemapperManager(getContext(), new RemapperView.Builder(null)
.remapA(true)
.remapB(true)
.remapX(true)
.remapY(true)
.remapDpad(true)
.remapLeftJoystick(true)
.remapRightJoystick(true)
.remapStart(true)
.remapSelect(true)
.remapLeftShoulder(true)
.remapRightShoulder(true)
.remapLeftTrigger(true)
.remapRightTrigger(true));
/* Resolution scaler option, allow downsizing a window */
private final float mScaleFactor = LauncherPreferences.PREF_SCALE_FACTOR/100f;
/* Sensitivity, adjusted according to screen size */
@ -385,7 +405,7 @@ public class MinecraftGLSurface extends View implements GrabListener{
mGamepad = new Gamepad(this, event.getDevice());
}
mGamepad.update(event);
mInputManager.handleMotionEventInput(getContext(), event, mGamepad);
return true;
}
@ -479,7 +499,7 @@ public class MinecraftGLSurface extends View implements GrabListener{
mGamepad = new Gamepad(this, event.getDevice());
}
mGamepad.update(event);
mInputManager.handleKeyEventInput(getContext(), event, mGamepad);
return true;
}

View File

@ -1,6 +1,15 @@
package net.kdt.pojavlaunch.customcontrols.gamepad;
import static android.view.MotionEvent.AXIS_HAT_X;
import static android.view.MotionEvent.AXIS_HAT_Y;
import static android.view.MotionEvent.AXIS_LTRIGGER;
import static android.view.MotionEvent.AXIS_RTRIGGER;
import static android.view.MotionEvent.AXIS_RZ;
import static android.view.MotionEvent.AXIS_X;
import static android.view.MotionEvent.AXIS_Y;
import static android.view.MotionEvent.AXIS_Z;
import android.content.Context;
import android.view.Choreographer;
import android.view.InputDevice;
@ -38,19 +47,18 @@ import static net.kdt.pojavlaunch.utils.MCOptionUtils.getMcScale;
import static org.lwjgl.glfw.CallbackBridge.sendKeyPress;
import static org.lwjgl.glfw.CallbackBridge.sendMouseButton;
public class Gamepad implements GrabListener {
import fr.spse.gamepad_remapper.GamepadHandler;
public class Gamepad implements GrabListener, GamepadHandler {
/* Resolution scaler option, allow downsizing a window */
private final float mScaleFactor = LauncherPreferences.DEFAULT_PREF.getInt("resolutionRatio",100)/100f;
/* Mouse positions, scaled by the scaleFactor */
private float mMouse_x, mMouse_y;
/* Sensitivity, adjusted according to screen size */
private final double mSensitivityFactor = (1.4 * (1080f/ currentDisplayMetrics.heightPixels));
private final ImageView mPointerImageView;
private final GamepadDpad mGamepadDpad = new GamepadDpad();
private final GamepadJoystick mLeftJoystick;
private int mCurrentJoystickDirection = DIRECTION_NONE;
@ -70,9 +78,7 @@ public class Gamepad implements GrabListener {
// The negation is to force trigger the onGrabState
private boolean isGrabbing = !CallbackBridge.isGrabbing();
//private final boolean mModifierDigitalTriggers;
private final boolean mModifierAnalogTriggers;
private boolean mModifierSwappedAxis = true; //Triggers and right stick axis are swapped.
/* Choreographer with time to compute delta on ticking */
private final Choreographer mScreenChoreographer;
@ -97,25 +103,9 @@ public class Gamepad implements GrabListener {
/* Add the listener for the cross hair */
MCOptionUtils.addMCOptionListener(mGuiScaleListener);
Toast.makeText(contextView.getContext(),"GAMEPAD CREATED", Toast.LENGTH_LONG).show();
for(InputDevice.MotionRange range : inputDevice.getMotionRanges()){
if(range.getAxis() == MotionEvent.AXIS_RTRIGGER
|| range.getAxis() == MotionEvent.AXIS_LTRIGGER
|| range.getAxis() == MotionEvent.AXIS_GAS
|| range.getAxis() == MotionEvent.AXIS_BRAKE){
mModifierSwappedAxis = false;
break;
}
}
mLeftJoystick = new GamepadJoystick(AXIS_X, AXIS_Y, inputDevice);
mRightJoystick = new GamepadJoystick(AXIS_Z, AXIS_RZ, inputDevice);
mLeftJoystick = new GamepadJoystick(MotionEvent.AXIS_X, MotionEvent.AXIS_Y, inputDevice);
if(!mModifierSwappedAxis)
mRightJoystick = new GamepadJoystick(MotionEvent.AXIS_Z, MotionEvent.AXIS_RZ, inputDevice);
else
mRightJoystick = new GamepadJoystick(MotionEvent.AXIS_RX, MotionEvent.AXIS_RY, inputDevice);
//mModifierDigitalTriggers = inputDevice.hasKeys(KeyEvent.KEYCODE_BUTTON_R2)[0];
mModifierAnalogTriggers = supportAnalogTriggers(inputDevice);
Context ctx = contextView.getContext();
mPointerImageView = new ImageView(contextView.getContext());
@ -125,28 +115,20 @@ public class Gamepad implements GrabListener {
int size = (int) ((22 * getMcScale()) / mScaleFactor);
mPointerImageView.setLayoutParams(new FrameLayout.LayoutParams(size, size));
mMouse_x = CallbackBridge.windowWidth/2f;
mMouse_y = CallbackBridge.windowHeight/2f;
CallbackBridge.sendCursorPos(mMouse_x, mMouse_y);
placePointerView(CallbackBridge.physicalWidth/2, CallbackBridge.physicalHeight/2);
CallbackBridge.sendCursorPos(CallbackBridge.windowWidth/2f, CallbackBridge.windowHeight/2f);
((ViewGroup)contextView.getParent()).addView(mPointerImageView);
placePointerView(CallbackBridge.physicalWidth/2, CallbackBridge.physicalHeight/2);
CallbackBridge.addGrabListener(this);
}
public void update(KeyEvent event){
sendButton(event);
}
public void update(MotionEvent event){
updateDirectionalJoystick(event);
updateMouseJoystick(event);
updateAnalogTriggers(event);
int[] dpadEvent = mGamepadDpad.convertEvent(event);
sendButton(dpadEvent[0], dpadEvent[1]);
public void updateJoysticks(){
updateDirectionalJoystick();
updateMouseJoystick();
}
public void notifyGUISizeChange(int newSize){
@ -156,86 +138,6 @@ public class Gamepad implements GrabListener {
}
public void sendButton(KeyEvent event){
sendButton(event.getKeyCode(), event.getAction());
}
public void sendButton(int keycode, int action){
boolean isDown = action == KeyEvent.ACTION_DOWN;
switch (keycode){
case KeyEvent.KEYCODE_BUTTON_A:
getCurrentMap().BUTTON_A.update(isDown);
break;
case KeyEvent.KEYCODE_BUTTON_B:
getCurrentMap().BUTTON_B.update(isDown);
break;
case KeyEvent.KEYCODE_BUTTON_X:
getCurrentMap().BUTTON_X.update(isDown);
break;
case KeyEvent.KEYCODE_BUTTON_Y:
getCurrentMap().BUTTON_Y.update(isDown);
break;
//Shoulders
case KeyEvent.KEYCODE_BUTTON_L1:
getCurrentMap().SHOULDER_LEFT.update(isDown);
break;
case KeyEvent.KEYCODE_BUTTON_R1:
getCurrentMap().SHOULDER_RIGHT.update(isDown);
break;
//Triggers
case KeyEvent.KEYCODE_BUTTON_L2:
if(mModifierAnalogTriggers) break;
getCurrentMap().TRIGGER_LEFT.update(isDown);
break;
case KeyEvent.KEYCODE_BUTTON_R2:
if(mModifierAnalogTriggers) break;
getCurrentMap().TRIGGER_RIGHT.update(isDown);
break;
//L3 || R3
case KeyEvent.KEYCODE_BUTTON_THUMBL:
getCurrentMap().THUMBSTICK_LEFT.update(isDown);
break;
case KeyEvent.KEYCODE_BUTTON_THUMBR:
getCurrentMap().THUMBSTICK_RIGHT.update(isDown);
break;
//DPAD
case KeyEvent.KEYCODE_DPAD_UP:
getCurrentMap().DPAD_UP.update(isDown);
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
getCurrentMap().DPAD_DOWN.update(isDown);
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
getCurrentMap().DPAD_LEFT.update(isDown);
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
getCurrentMap().DPAD_RIGHT.update(isDown);
break;
case KeyEvent.KEYCODE_DPAD_CENTER:
getCurrentMap().DPAD_RIGHT.update(false);
getCurrentMap().DPAD_LEFT.update(false);
getCurrentMap().DPAD_UP.update(false);
getCurrentMap().DPAD_DOWN.update(false);
break;
//Start/select
case KeyEvent.KEYCODE_BUTTON_START:
getCurrentMap().BUTTON_START.update(isDown);
break;
case KeyEvent.KEYCODE_BUTTON_SELECT:
getCurrentMap().BUTTON_SELECT.update(isDown);
break;
default:
sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_SPACE, CallbackBridge.getCurrentMods(), isDown);
break;
}
}
public static void sendInput(int[] keycodes, boolean isDown){
for(int keycode : keycodes){
@ -281,6 +183,7 @@ public class Gamepad implements GrabListener {
*/
private void tick(long frameTimeNanos){
//update mouse position
long newFrameTime = System.nanoTime();
if(mLastHorizontalValue != 0 || mLastVerticalValue != 0){
GamepadJoystick currentJoystick = isGrabbing ? mLeftJoystick : mRightJoystick;
@ -291,7 +194,8 @@ public class Gamepad implements GrabListener {
// Compute delta since last tick time
float deltaX = (float) (Math.cos(mMouseAngle) * acceleration * mMouseSensitivity);
float deltaY = (float) (Math.sin(mMouseAngle) * acceleration * mMouseSensitivity);
float deltaTimeScale = ((frameTimeNanos - mLastFrameTime) / 16666666f); // Scale of 1 = 60Hz
newFrameTime = System.nanoTime(); // More accurate delta
float deltaTimeScale = ((newFrameTime - mLastFrameTime) / 16666666f); // Scale of 1 = 60Hz
deltaX *= deltaTimeScale;
deltaY *= deltaTimeScale;
@ -304,27 +208,24 @@ public class Gamepad implements GrabListener {
placePointerView((int) (CallbackBridge.mouseX / mScaleFactor), (int) (CallbackBridge.mouseY/ mScaleFactor));
}
mMouse_x = CallbackBridge.mouseX;
mMouse_y = CallbackBridge.mouseY;
//Send the mouse to the game
CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY);
}
// Update last nano time
mLastFrameTime = frameTimeNanos;
mLastFrameTime = newFrameTime;
}
private void updateMouseJoystick(MotionEvent event){
private void updateMouseJoystick(){
GamepadJoystick currentJoystick = isGrabbing ? mRightJoystick : mLeftJoystick;
float horizontalValue = currentJoystick.getHorizontalAxis(event);
float verticalValue = currentJoystick.getVerticalAxis(event);
float horizontalValue = currentJoystick.getHorizontalAxis();
float verticalValue = currentJoystick.getVerticalAxis();
if(horizontalValue != mLastHorizontalValue || verticalValue != mLastVerticalValue){
mLastHorizontalValue = horizontalValue;
mLastVerticalValue = verticalValue;
mMouseMagnitude = currentJoystick.getMagnitude(event);
mMouseAngle = currentJoystick.getAngleRadian(event);
mMouseMagnitude = currentJoystick.getMagnitude();
mMouseAngle = currentJoystick.getAngleRadian();
tick(System.nanoTime());
return;
@ -332,16 +233,16 @@ public class Gamepad implements GrabListener {
mLastHorizontalValue = horizontalValue;
mLastVerticalValue = verticalValue;
mMouseMagnitude = currentJoystick.getMagnitude(event);
mMouseAngle = currentJoystick.getAngleRadian(event);
mMouseMagnitude = currentJoystick.getMagnitude();
mMouseAngle = currentJoystick.getAngleRadian();
}
private void updateDirectionalJoystick(MotionEvent event){
private void updateDirectionalJoystick(){
GamepadJoystick currentJoystick = isGrabbing ? mLeftJoystick : mRightJoystick;
int lastJoystickDirection = mCurrentJoystickDirection;
mCurrentJoystickDirection = currentJoystick.getHeightDirection(event);
mCurrentJoystickDirection = currentJoystick.getHeightDirection();
if(mCurrentJoystickDirection == lastJoystickDirection) return;
@ -349,37 +250,6 @@ public class Gamepad implements GrabListener {
sendDirectionalKeycode(mCurrentJoystickDirection, true, getCurrentMap());
}
private void updateAnalogTriggers(MotionEvent event){
if(mModifierAnalogTriggers){
getCurrentMap().TRIGGER_LEFT.update(
(event.getAxisValue(MotionEvent.AXIS_LTRIGGER) > 0.5)
|| (event.getAxisValue(MotionEvent.AXIS_BRAKE) > 0.5)
|| (mModifierSwappedAxis &&(event.getAxisValue(MotionEvent.AXIS_Z) > 0.5)) );
getCurrentMap().TRIGGER_RIGHT.update(
(event.getAxisValue( MotionEvent.AXIS_RTRIGGER) > 0.5)
|| (event.getAxisValue(MotionEvent.AXIS_GAS) > 0.5)
|| (mModifierSwappedAxis && event.getAxisValue(MotionEvent.AXIS_RZ) > 0.5) );
}
}
/**
* Detect if a gamepad supports analog triggers
* @param inputDevice The input device with all the MotionRange
* @return Whether the gamepad supports analog triggers
*/
private boolean supportAnalogTriggers(InputDevice inputDevice){
for(InputDevice.MotionRange motionRange : inputDevice.getMotionRanges()){
int axis = motionRange.getAxis();
if( axis == MotionEvent.AXIS_BRAKE || axis == MotionEvent.AXIS_GAS ||
axis == MotionEvent.AXIS_LTRIGGER || axis == MotionEvent.AXIS_RTRIGGER ||
(mModifierSwappedAxis && axis == MotionEvent.AXIS_Z) ||
(mModifierSwappedAxis && axis == MotionEvent.AXIS_RZ)){
return true;
}
}
return false;
}
private GamepadMap getCurrentMap(){
return mCurrentMap;
@ -418,6 +288,7 @@ public class Gamepad implements GrabListener {
}
}
/** Place the pointer on the screen, offsetting the image size */
private void placePointerView(int x, int y){
mPointerImageView.setX(x - mPointerImageView.getWidth()/2f);
mPointerImageView.setY(y - mPointerImageView.getHeight()/2f);
@ -442,12 +313,123 @@ public class Gamepad implements GrabListener {
mCurrentMap = mMenuMap;
sendDirectionalKeycode(mCurrentJoystickDirection, false, mGameMap); // removing what we were doing
mMouse_x = CallbackBridge.windowWidth/2f;
mMouse_y = CallbackBridge.windowHeight/2f;
CallbackBridge.sendCursorPos(mMouse_x, mMouse_y);
CallbackBridge.sendCursorPos(CallbackBridge.windowWidth/2f, CallbackBridge.windowHeight/2f);
placePointerView(CallbackBridge.physicalWidth/2, CallbackBridge.physicalHeight/2);
mPointerImageView.setVisibility(View.VISIBLE);
// Sensitivity in menu is MC and HARDWARE resolution dependent
mMouseSensitivity = 19 * mScaleFactor / mSensitivityFactor;
}
@Override
public void handleGamepadInput(int keycode, float value) {
boolean isKeyEventDown = value == 1f;
switch (keycode){
case KeyEvent.KEYCODE_BUTTON_A:
getCurrentMap().BUTTON_A.update(isKeyEventDown);
break;
case KeyEvent.KEYCODE_BUTTON_B:
getCurrentMap().BUTTON_B.update(isKeyEventDown);
break;
case KeyEvent.KEYCODE_BUTTON_X:
getCurrentMap().BUTTON_X.update(isKeyEventDown);
break;
case KeyEvent.KEYCODE_BUTTON_Y:
getCurrentMap().BUTTON_Y.update(isKeyEventDown);
break;
//Shoulders
case KeyEvent.KEYCODE_BUTTON_L1:
getCurrentMap().SHOULDER_LEFT.update(isKeyEventDown);
break;
case KeyEvent.KEYCODE_BUTTON_R1:
getCurrentMap().SHOULDER_RIGHT.update(isKeyEventDown);
break;
//Triggers
case KeyEvent.KEYCODE_BUTTON_L2:
getCurrentMap().TRIGGER_LEFT.update(isKeyEventDown);
break;
case KeyEvent.KEYCODE_BUTTON_R2:
getCurrentMap().TRIGGER_RIGHT.update(isKeyEventDown);
break;
//L3 || R3
case KeyEvent.KEYCODE_BUTTON_THUMBL:
getCurrentMap().THUMBSTICK_LEFT.update(isKeyEventDown);
break;
case KeyEvent.KEYCODE_BUTTON_THUMBR:
getCurrentMap().THUMBSTICK_RIGHT.update(isKeyEventDown);
break;
//DPAD
case KeyEvent.KEYCODE_DPAD_UP:
getCurrentMap().DPAD_UP.update(isKeyEventDown);
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
getCurrentMap().DPAD_DOWN.update(isKeyEventDown);
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
getCurrentMap().DPAD_LEFT.update(isKeyEventDown);
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
getCurrentMap().DPAD_RIGHT.update(isKeyEventDown);
break;
case KeyEvent.KEYCODE_DPAD_CENTER:
getCurrentMap().DPAD_RIGHT.update(false);
getCurrentMap().DPAD_LEFT.update(false);
getCurrentMap().DPAD_UP.update(false);
getCurrentMap().DPAD_DOWN.update(false);
break;
//Start/select
case KeyEvent.KEYCODE_BUTTON_START:
getCurrentMap().BUTTON_START.update(isKeyEventDown);
break;
case KeyEvent.KEYCODE_BUTTON_SELECT:
getCurrentMap().BUTTON_SELECT.update(isKeyEventDown);
break;
/* Now, it is time for motionEvents */
case AXIS_HAT_X:
getCurrentMap().DPAD_RIGHT.update(value > 0.85);
getCurrentMap().DPAD_LEFT.update(value < -0.85);
break;
case AXIS_HAT_Y:
getCurrentMap().DPAD_DOWN.update(value > 0.85);
getCurrentMap().DPAD_UP.update(value < -0.85);
break;
// Left joystick
case AXIS_X:
mLeftJoystick.setXAxisValue(value);
updateJoysticks();
break;
case AXIS_Y:
mLeftJoystick.setYAxisValue(value);
updateJoysticks();
break;
// Right joystick
case AXIS_Z:
mRightJoystick.setXAxisValue(value);
updateJoysticks();
break;
case AXIS_RZ:
mRightJoystick.setYAxisValue(value);
updateJoysticks();
break;
// Triggers
case AXIS_RTRIGGER:
getCurrentMap().TRIGGER_RIGHT.update(value > 0.5);
break;
case AXIS_LTRIGGER:
getCurrentMap().TRIGGER_LEFT.update(value > 0.5);
break;
default:
sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_SPACE, CallbackBridge.getCurrentMods(), isKeyEventDown);
break;
}
}
}

View File

@ -1,5 +1,8 @@
package net.kdt.pojavlaunch.customcontrols.gamepad;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_DEADZONE_SCALE;
import android.util.Log;
import android.view.InputDevice;
import android.view.MotionEvent;
@ -21,42 +24,46 @@ public class GamepadJoystick {
public static final int DIRECTION_SOUTH_EAST = 7;
private final InputDevice mInputDevice;
private final int mVerticalAxis;
private final int mHorizontalAxis;
private final int mVerticalAxis;
private float mVerticalAxisValue = 0;
private float mHorizontalAxisValue = 0;
public GamepadJoystick(int horizontalAxis, int verticalAxis, InputDevice device){
this.mVerticalAxis = verticalAxis;
this.mHorizontalAxis = horizontalAxis;
mHorizontalAxis = horizontalAxis;
mVerticalAxis = verticalAxis;
this.mInputDevice = device;
}
public double getAngleRadian(MotionEvent event){
public double getAngleRadian(){
//From -PI to PI
return -Math.atan2(getVerticalAxis(event), getHorizontalAxis(event));
// TODO misuse of the deadzone here !
return -Math.atan2(getVerticalAxis(), getHorizontalAxis());
}
public double getAngleDegree(MotionEvent event){
public double getAngleDegree(){
//From 0 to 360 degrees
double result = Math.toDegrees(getAngleRadian(event));
double result = Math.toDegrees(getAngleRadian());
if(result < 0) result += 360;
return result;
}
public double getMagnitude(MotionEvent event){
float x = Math.abs(event.getAxisValue(mHorizontalAxis));
float y = Math.abs(event.getAxisValue(mVerticalAxis));
public double getMagnitude(){
float x = Math.abs(mHorizontalAxisValue);
float y = Math.abs(mVerticalAxisValue);
return MathUtils.dist(0,0, x, y);
}
public float getVerticalAxis(MotionEvent event){
return applyDeadzone(event, mVerticalAxis);
public float getVerticalAxis(){
return applyDeadzone(mVerticalAxisValue);
}
public float getHorizontalAxis(MotionEvent event){
return applyDeadzone(event, mHorizontalAxis);
public float getHorizontalAxis(){
return applyDeadzone(mHorizontalAxisValue);
}
public static boolean isJoystickEvent(MotionEvent event){
@ -65,9 +72,9 @@ public class GamepadJoystick {
}
public int getHeightDirection(MotionEvent event){
if(getMagnitude(event) <= getDeadzone()) return DIRECTION_NONE;
return ((int) ((getAngleDegree(event)+22.5)/45)) % 8;
public int getHeightDirection(){
if(getMagnitude() <= getDeadzone()) return DIRECTION_NONE;
return ((int) ((getAngleDegree()+22.5)/45)) % 8;
}
/**
@ -77,20 +84,31 @@ public class GamepadJoystick {
*/
public float getDeadzone() {
try{
return Math.max(mInputDevice.getMotionRange(mHorizontalAxis).getFlat() * 1.9f, 0.2f);
return mInputDevice.getMotionRange(mHorizontalAxis).getFlat() * PREF_DEADZONE_SCALE;
}catch (Exception e){
Log.e(GamepadJoystick.class.toString(), "Dynamic Deadzone is not supported ");
return 0.2f;
}
}
private float applyDeadzone(MotionEvent event, int axis){
private float applyDeadzone(float value){
//This piece of code also modifies the value
//to make it seem like there was no deadzone in the first place
double magnitude = getMagnitude(event);
double magnitude = getMagnitude();
float deadzone = getDeadzone();
if (magnitude < deadzone) return 0;
return (float) ( (event.getAxisValue(axis) / magnitude) * ((magnitude - deadzone) / (1 - deadzone)) );
return (float) ( (value / magnitude) * ((magnitude - deadzone) / (1 - deadzone)) );
}
/* Setters */
public void setXAxisValue(float value){
this.mHorizontalAxisValue = value;
}
public void setYAxisValue(float value){
this.mVerticalAxisValue = value;
}
}

View File

@ -0,0 +1,34 @@
package net.kdt.pojavlaunch.prefs;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.preference.Preference;
import net.kdt.pojavlaunch.R;
import fr.spse.gamepad_remapper.Remapper;
public class GamepadRemapPreference extends Preference {
public GamepadRemapPreference(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public GamepadRemapPreference(@NonNull Context context) {
super(context);
init();
}
private void init(){
setOnPreferenceClickListener(preference -> {
Remapper.wipePreferences(getContext());
Toast.makeText(getContext(), R.string.preference_controller_map_wiped, Toast.LENGTH_SHORT).show();
return true;
});
}
}

View File

@ -57,6 +57,7 @@ public class LauncherPreferences {
public static boolean PREF_BUTTON_ALL_CAPS = true;
public static boolean PREF_DUMP_SHADERS = false;
public static float PREF_DEADZONE_SCALE = 1f;
public static void loadPreferences(Context ctx) {
@ -96,6 +97,7 @@ public class LauncherPreferences {
PREF_FORCE_VSYNC = DEFAULT_PREF.getBoolean("force_vsync", false);
PREF_BUTTON_ALL_CAPS = DEFAULT_PREF.getBoolean("buttonAllCaps", true);
PREF_DUMP_SHADERS = DEFAULT_PREF.getBoolean("dump_shaders", false);
PREF_DEADZONE_SCALE = DEFAULT_PREF.getInt("gamepad_deadzone_scale", 100)/100f;
String argLwjglLibname = "-Dorg.lwjgl.opengl.libname=";
for (String arg : JREUtils.parseJavaArguments(PREF_CUSTOM_JAVA_ARGS)) {

View File

@ -23,6 +23,7 @@ public class LauncherPreferenceControlFragment extends LauncherPreferenceFragmen
int gyroSampleRate = LauncherPreferences.PREF_GYRO_SAMPLE_RATE;
float mouseSpeed = LauncherPreferences.PREF_MOUSESPEED;
float gyroSpeed = LauncherPreferences.PREF_GYRO_SENSITIVITY;
float joystickDeadzone = LauncherPreferences.PREF_DEADZONE_SCALE;
//Triggers a write for some reason which resets the value
addPreferencesFromResource(R.xml.pref_control);
@ -47,6 +48,11 @@ public class LauncherPreferenceControlFragment extends LauncherPreferenceFragmen
seek6.setValue((int)(mouseSpeed *100f));
seek6.setSuffix(" %");
CustomSeekBarPreference deadzoneSeek = findPreference("gamepad_deadzone_scale");
deadzoneSeek.setRange(50, 200);
deadzoneSeek.setValue((int) joystickDeadzone * 100);
deadzoneSeek.setSuffix(" %");
Context context = getContext();
if(context != null) {
mGyroAvailable = ((SensorManager)context.getSystemService(Context.SENSOR_SERVICE)).getDefaultSensor(Sensor.TYPE_GYROSCOPE) != null;

View File

@ -364,4 +364,10 @@
<string name="global_save_and_exit">Save and exit</string>
<string name="global_yes">Yes</string>
<string name="global_no">No</string>
<string name="preference_controller_map_wiped">The controller config has been wiped</string>
<string name="preference_category_controller_settings">Controller settings</string>
<string name="preference_wipe_controller_title">Reset controller mapping</string>
<string name="preference_wipe_controller_description">Allow you to remap the controller buttons</string>
<string name="preference_deadzone_scale_title">Joystick deadzone scale</string>
<string name="preference_deadzone_scale_description">Increase it if the joystick drifts</string>
</resources>

View File

@ -123,6 +123,22 @@
</PreferenceCategory>
<PreferenceCategory
android:title="@string/preference_category_controller_settings"
>
<net.kdt.pojavlaunch.prefs.GamepadRemapPreference
android:title="@string/preference_wipe_controller_title"
android:summary="@string/preference_wipe_controller_description"
/>
<net.kdt.pojavlaunch.prefs.CustomSeekBarPreference
android:key="gamepad_deadzone_scale"
android:title="@string/preference_deadzone_scale_title"
android:summary="@string/preference_deadzone_scale_description"
app2:showSeekBarValue="true"
app2:seekBarIncrement="5"
/>
</PreferenceCategory>