Feat: In game quick settings

This commit is contained in:
Mathias-Boulay 2024-11-19 00:05:36 +01:00
parent 3777261f1f
commit d6534d5367
6 changed files with 450 additions and 95 deletions

View File

@ -1,6 +1,7 @@
package net.kdt.pojavlaunch;
import static net.kdt.pojavlaunch.Tools.currentDisplayMetrics;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_ENABLE_GYRO;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_SUSTAINED_PERFORMANCE;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_USE_ALTERNATE_SURFACE;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_VIRTUAL_MOUSE_START;
@ -55,6 +56,7 @@ import net.kdt.pojavlaunch.customcontrols.mouse.GyroControl;
import net.kdt.pojavlaunch.customcontrols.mouse.Touchpad;
import net.kdt.pojavlaunch.lifecycle.ContextExecutor;
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
import net.kdt.pojavlaunch.prefs.QuickSettingSideDialog;
import net.kdt.pojavlaunch.services.GameService;
import net.kdt.pojavlaunch.utils.JREUtils;
import net.kdt.pojavlaunch.utils.MCOptionUtils;
@ -91,6 +93,8 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
public AdapterView.OnItemClickListener ingameControlsEditorListener;
private GameService.LocalBinder mServiceBinder;
private QuickSettingSideDialog mQuickSettingSideDialog;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@ -103,7 +107,8 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
initLayout(R.layout.activity_basemain);
CallbackBridge.addGrabListener(touchpad);
CallbackBridge.addGrabListener(minecraftGLView);
if(LauncherPreferences.PREF_ENABLE_GYRO) mGyroControl = new GyroControl(this);
mGyroControl = new GyroControl(this);
// Enabling this on TextureView results in a broken white result
if(PREF_USE_ALTERNATE_SURFACE) getWindow().setBackgroundDrawable(null);
@ -185,9 +190,8 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
case 0: dialogForceClose(MainActivity.this); break;
case 1: openLogOutput(); break;
case 2: dialogSendCustomKey(); break;
case 3: adjustMouseSpeedLive(); break;
case 4: adjustGyroSensitivityLive(); break;
case 5: openCustomControls(); break;
case 3: mQuickSettingSideDialog.appear(true); break;
case 4: openCustomControls(); break;
}
drawerLayout.closeDrawers();
};
@ -208,6 +212,23 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
Tools.showErrorRemote(e);
}
});
mQuickSettingSideDialog = new QuickSettingSideDialog(this, mControlLayout) {
@Override
public void onResolutionChanged() {
//TODO: reflect the change in event positions sent down to the game
minecraftGLView.refreshSize();
}
@Override
public void onGyroStateChanged() {
if (PREF_ENABLE_GYRO) {
mGyroControl.enable();
} else {
mGyroControl.disable();
}
}
};
} catch (Throwable e) {
Tools.showError(this, e, true);
}
@ -260,16 +281,17 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
@Override
public void onResume() {
super.onResume();
if(mGyroControl != null) mGyroControl.enable();
if(PREF_ENABLE_GYRO) mGyroControl.enable();
CallbackBridge.nativeSetWindowAttrib(LwjglGlfwKeycode.GLFW_HOVERED, 1);
}
@Override
protected void onPause() {
if(mGyroControl != null) mGyroControl.disable();
mGyroControl.disable();
if (CallbackBridge.isGrabbing()){
sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_ESCAPE);
}
mQuickSettingSideDialog.cancel();
CallbackBridge.nativeSetWindowAttrib(LwjglGlfwKeycode.GLFW_HOVERED, 0);
super.onPause();
}
@ -423,83 +445,6 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
if(touchCharInput != null) touchCharInput.switchKeyboardState();
}
int tmpMouseSpeed;
public void adjustMouseSpeedLive() {
AlertDialog.Builder b = new AlertDialog.Builder(this);
b.setTitle(R.string.mcl_setting_title_mousespeed);
View v = LayoutInflater.from(this).inflate(R.layout.dialog_live_mouse_speed_editor,null);
final SeekBar sb = v.findViewById(R.id.mouseSpeed);
final TextView tv = v.findViewById(R.id.mouseSpeedTV);
sb.setMax(275);
tmpMouseSpeed = (int) ((LauncherPreferences.PREF_MOUSESPEED*100));
sb.setProgress(tmpMouseSpeed-25);
tv.setText(getString(R.string.percent_format, tmpMouseSpeed));
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
tmpMouseSpeed = i+25;
tv.setText(getString(R.string.percent_format, tmpMouseSpeed));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
});
b.setView(v);
b.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
LauncherPreferences.PREF_MOUSESPEED = ((float)tmpMouseSpeed)/100f;
LauncherPreferences.DEFAULT_PREF.edit().putInt("mousespeed",tmpMouseSpeed).apply();
dialogInterface.dismiss();
System.gc();
});
b.setNegativeButton(android.R.string.cancel, (dialogInterface, i) -> {
dialogInterface.dismiss();
System.gc();
});
b.show();
}
int tmpGyroSensitivity;
public void adjustGyroSensitivityLive() {
if(!LauncherPreferences.PREF_ENABLE_GYRO) {
Toast.makeText(this, R.string.toast_turn_on_gyro, Toast.LENGTH_LONG).show();
return;
}
AlertDialog.Builder b = new AlertDialog.Builder(this);
b.setTitle(R.string.preference_gyro_sensitivity_title);
View v = LayoutInflater.from(this).inflate(R.layout.dialog_live_mouse_speed_editor,null);
final SeekBar sb = v.findViewById(R.id.mouseSpeed);
final TextView tv = v.findViewById(R.id.mouseSpeedTV);
sb.setMax(275);
tmpGyroSensitivity = (int) ((LauncherPreferences.PREF_GYRO_SENSITIVITY*100));
sb.setProgress(tmpGyroSensitivity -25);
tv.setText(getString(R.string.percent_format, tmpGyroSensitivity));
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
tmpGyroSensitivity = i+25;
tv.setText(getString(R.string.percent_format, tmpGyroSensitivity));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {}
});
b.setView(v);
b.setPositiveButton(android.R.string.ok, (dialogInterface, i) -> {
LauncherPreferences.PREF_GYRO_SENSITIVITY = ((float) tmpGyroSensitivity)/100f;
LauncherPreferences.DEFAULT_PREF.edit().putInt("gyroSensitivity", tmpGyroSensitivity).apply();
dialogInterface.dismiss();
System.gc();
});
b.setNegativeButton(android.R.string.cancel, (dialogInterface, i) -> {
dialogInterface.dismiss();
System.gc();
});
b.show();
}
private static void setUri(Context context, String input, Intent intent) {
if(input.startsWith("file:")) {
int truncLength = 5;

View File

@ -87,6 +87,11 @@ public class GyroControl implements SensorEventListener, GrabListener {
SensorManager.getRotationMatrixFromVector(mCurrentRotation, sensorEvent.values);
float xLocalFactor = xFactor;
float yLocalFactor = yFactor;
if(LauncherPreferences.PREF_GYRO_INVERT_X) xLocalFactor *= -1;
if(LauncherPreferences.PREF_GYRO_INVERT_Y) yLocalFactor *= -1;
if(mFirstPass){ // Setup initial position
mFirstPass = false;
return;
@ -101,20 +106,20 @@ public class GyroControl implements SensorEventListener, GrabListener {
float absY = Math.abs(mStoredY);
if(absX + absY > MULTI_AXIS_LOW_PASS_THRESHOLD) {
CallbackBridge.mouseX -= ((mSwapXY ? mStoredY : mStoredX) * xFactor);
CallbackBridge.mouseY += ((mSwapXY ? mStoredX : mStoredY) * yFactor);
CallbackBridge.mouseX -= ((mSwapXY ? mStoredY : mStoredX) * xLocalFactor);
CallbackBridge.mouseY += ((mSwapXY ? mStoredX : mStoredY) * yLocalFactor);
mStoredX = 0;
mStoredY = 0;
updatePosition = true;
} else {
if(Math.abs(mStoredX) > SINGLE_AXIS_LOW_PASS_THRESHOLD){
CallbackBridge.mouseX -= ((mSwapXY ? mStoredY : mStoredX) * xFactor);
CallbackBridge.mouseX -= ((mSwapXY ? mStoredY : mStoredX) * xLocalFactor);
mStoredX = 0;
updatePosition = true;
}
if(Math.abs(mStoredY) > SINGLE_AXIS_LOW_PASS_THRESHOLD) {
CallbackBridge.mouseY += ((mSwapXY ? mStoredX : mStoredY) * yFactor);
CallbackBridge.mouseY += ((mSwapXY ? mStoredX : mStoredY) * yLocalFactor);
mStoredY = 0;
updatePosition = true;
}
@ -151,9 +156,6 @@ public class GyroControl implements SensorEventListener, GrabListener {
yFactor = -1;
break;
}
if(LauncherPreferences.PREF_GYRO_INVERT_X) xFactor *= -1;
if(LauncherPreferences.PREF_GYRO_INVERT_Y) yFactor *= -1;
}
@Override
@ -242,9 +244,6 @@ public class GyroControl implements SensorEventListener, GrabListener {
}
break;
}
if(LauncherPreferences.PREF_GYRO_INVERT_X) xFactor *= -1;
if(LauncherPreferences.PREF_GYRO_INVERT_Y) yFactor *= -1;
}
}
}

View File

@ -0,0 +1,220 @@
package net.kdt.pojavlaunch.prefs;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_DISABLE_GESTURES;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_ENABLE_GYRO;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_GYRO_INVERT_X;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_GYRO_INVERT_Y;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_GYRO_SENSITIVITY;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_LONGPRESS_TRIGGER;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_MOUSESPEED;
import static net.kdt.pojavlaunch.prefs.LauncherPreferences.PREF_SCALE_FACTOR;
import android.annotation.SuppressLint;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Switch;
import android.widget.TextView;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.kdt.CustomSeekbar;
import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.utils.SimpleSeekBarListener;
/**
* Side dialog for quick settings that you can change in game
* The implementation has to take action on some preference changes
*/
public abstract class QuickSettingSideDialog extends com.kdt.SideDialogView<ConstraintLayout> {
@SuppressLint("UseSwitchCompatOrMaterialCode")
private Switch mGyroSwitch, mGyroXSwitch, mGyroYSwitch, mGestureSwitch;
private CustomSeekbar mGyroSensitivityBar, mMouseSpeedBar, mGestureDelayBar, mResolutionBar;
private TextView mGyroSensitivityText, mGyroSensitivityDisplayText, mMouseSpeedText, mGestureDelayText, mGestureDelayDisplayText, mResolutionText;
private boolean mOriginalGyroEnabled, mOriginalGyroXEnabled, mOriginalGyroYEnabled, mOriginalGestureDisabled;
private float mOriginalGyroSensitivity, mOriginalMouseSpeed;
private int mOriginalGestureDelay, mOriginalResolution;
public QuickSettingSideDialog(Context context, ViewGroup parent) {
super(context, parent, R.layout.dialog_quick_setting);
setTitle(R.string.quick_setting_title);
bindLayout();
setupCancelButton();
}
@Override
public boolean appear(boolean fromRight) {
boolean hasChanged = super.appear(fromRight);
if (hasChanged) setupListeners();
return hasChanged;
}
@Override
public void disappear() {
super.disappear();
removeListeners();
}
private void bindLayout() {
// Bind layout elements
mGyroSwitch = mDialogContent.findViewById(R.id.checkboxGyro);
mGyroXSwitch = mDialogContent.findViewById(R.id.checkboxGyroX);
mGyroYSwitch = mDialogContent.findViewById(R.id.checkboxGyroY);
mGestureSwitch = mDialogContent.findViewById(R.id.checkboxGesture);
mGyroSensitivityBar = mDialogContent.findViewById(R.id.editGyro_seekbar);
mMouseSpeedBar = mDialogContent.findViewById(R.id.editMouseSpeed_seekbar);
mGestureDelayBar = mDialogContent.findViewById(R.id.editGestureDelay_seekbar);
mResolutionBar = mDialogContent.findViewById(R.id.editResolution_seekbar);
mGyroSensitivityText = mDialogContent.findViewById(R.id.editGyro_textView_percent);
mGyroSensitivityDisplayText = mDialogContent.findViewById(R.id.editGyro_textView);
mMouseSpeedText = mDialogContent.findViewById(R.id.editMouseSpeed_textView_percent);
mGestureDelayText = mDialogContent.findViewById(R.id.editGestureDelay_textView_percent);
mGestureDelayDisplayText = mDialogContent.findViewById(R.id.editGestureDelay_textView);
mResolutionText = mDialogContent.findViewById(R.id.editResolution_textView_percent);
}
private void setupListeners() {
mOriginalGyroEnabled = PREF_ENABLE_GYRO;
mOriginalGyroXEnabled = PREF_GYRO_INVERT_X;
mOriginalGyroYEnabled = PREF_GYRO_INVERT_Y;
mOriginalGestureDisabled = PREF_DISABLE_GESTURES;
mOriginalGyroSensitivity = PREF_GYRO_SENSITIVITY;
mOriginalMouseSpeed = PREF_MOUSESPEED;
mOriginalGestureDelay = PREF_LONGPRESS_TRIGGER;
mOriginalResolution = PREF_SCALE_FACTOR;
mGyroSwitch.setChecked(mOriginalGyroEnabled);
mGyroXSwitch.setChecked(mOriginalGyroXEnabled);
mGyroYSwitch.setChecked(mOriginalGyroYEnabled);
mGestureSwitch.setChecked(mOriginalGestureDisabled);
mGyroSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
PREF_ENABLE_GYRO = isChecked;
onGyroStateChanged();
updateGyroVisibility(isChecked);
LauncherPreferences.DEFAULT_PREF.edit().putBoolean("enableGyro", isChecked).apply();
});
mGyroXSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
PREF_GYRO_INVERT_X = isChecked;
LauncherPreferences.DEFAULT_PREF.edit().putBoolean("gyroInvertX", isChecked).apply();
});
mGyroYSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
PREF_GYRO_INVERT_Y = isChecked;
LauncherPreferences.DEFAULT_PREF.edit().putBoolean("gyroInvertY", isChecked).apply();
});
mGestureSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
PREF_DISABLE_GESTURES = isChecked;
updateGestureVisibility(isChecked);
LauncherPreferences.DEFAULT_PREF.edit().putBoolean("disableGestures", isChecked).apply();
});
mGyroSensitivityBar.setRange(25, 300);
mGyroSensitivityBar.setIncrement(5);
mGyroSensitivityBar.setOnSeekBarChangeListener((SimpleSeekBarListener) (seekBar, progress, fromUser) -> {
PREF_GYRO_SENSITIVITY = progress / 100f;
LauncherPreferences.DEFAULT_PREF.edit().putInt("gyroSensitivity", progress).apply();
mGyroSensitivityText.setText(progress + "%");
});
mGyroSensitivityBar.setProgress((int) (mOriginalGyroSensitivity * 100f));
mMouseSpeedBar.setRange(25, 300);
mMouseSpeedBar.setIncrement(5);
mMouseSpeedBar.setOnSeekBarChangeListener((SimpleSeekBarListener) (seekBar, progress, fromUser) -> {
PREF_MOUSESPEED = progress / 100f;
LauncherPreferences.DEFAULT_PREF.edit().putInt("mousespeed", progress).apply();
mMouseSpeedText.setText(progress + "%");
});
mMouseSpeedBar.setProgress((int) (mOriginalMouseSpeed * 100f));
mGestureDelayBar.setRange(100, 1000);
mGestureDelayBar.setIncrement(10);
mGestureDelayBar.setOnSeekBarChangeListener((SimpleSeekBarListener) (seekBar, progress, fromUser) -> {
PREF_LONGPRESS_TRIGGER = progress;
LauncherPreferences.DEFAULT_PREF.edit().putInt("timeLongPressTrigger", progress).apply();
mGestureDelayText.setText(progress + "ms");
});
mGestureDelayBar.setProgress(mOriginalGestureDelay);
mResolutionBar.setRange(25, 100);
mResolutionBar.setIncrement(5);
mResolutionBar.setOnSeekBarChangeListener((SimpleSeekBarListener) (seekBar, progress, fromUser) -> {
onResolutionChanged();
PREF_SCALE_FACTOR = progress;
LauncherPreferences.DEFAULT_PREF.edit().putInt("resolutionRatio", progress).apply();
mResolutionText.setText(progress + "%");
});
mResolutionBar.setProgress(mOriginalResolution);
updateGyroVisibility(mOriginalGyroEnabled);
updateGestureVisibility(mOriginalGestureDisabled);
}
private void updateGyroVisibility(boolean isEnabled) {
int visibility = isEnabled ? View.VISIBLE : View.GONE;
mGyroXSwitch.setVisibility(visibility);
mGyroYSwitch.setVisibility(visibility);
mGyroSensitivityBar.setVisibility(visibility);
mGyroSensitivityText.setVisibility(visibility);
mGyroSensitivityDisplayText.setVisibility(visibility);
}
private void updateGestureVisibility(boolean isDisabled) {
int visibility = isDisabled ? View.GONE : View.VISIBLE;
mGestureDelayBar.setVisibility(visibility);
mGestureDelayText.setVisibility(visibility);
mGestureDelayDisplayText.setVisibility(visibility);
}
private void removeListeners() {
mGyroSwitch.setOnCheckedChangeListener(null);
mGyroXSwitch.setOnCheckedChangeListener(null);
mGyroYSwitch.setOnCheckedChangeListener(null);
mGestureSwitch.setOnCheckedChangeListener(null);
mGyroSensitivityBar.setOnSeekBarChangeListener(null);
mMouseSpeedBar.setOnSeekBarChangeListener(null);
mGestureDelayBar.setOnSeekBarChangeListener(null);
mResolutionBar.setOnSeekBarChangeListener(null);
}
private void setupCancelButton() {
setStartButtonListener(android.R.string.cancel, v -> cancel());
setEndButtonListener(android.R.string.ok, v -> disappear());
}
/** Resets all settings to their original values */
public void cancel() {
PREF_ENABLE_GYRO = mOriginalGyroEnabled;
PREF_GYRO_INVERT_X = mOriginalGyroXEnabled;
PREF_GYRO_INVERT_Y = mOriginalGyroYEnabled;
PREF_DISABLE_GESTURES = mOriginalGestureDisabled;
PREF_GYRO_SENSITIVITY = mOriginalGyroSensitivity;
PREF_MOUSESPEED = mOriginalMouseSpeed;
PREF_LONGPRESS_TRIGGER = mOriginalGestureDelay;
PREF_SCALE_FACTOR = mOriginalResolution;
onGyroStateChanged();
onResolutionChanged();
disappear();
}
/** Called when the resolution is changed. Use {@link LauncherPreferences#PREF_SCALE_FACTOR} */
public abstract void onResolutionChanged();
/** Called when the gyro state is changed. Use {@link LauncherPreferences#PREF_ENABLE_GYRO} */
public abstract void onGyroStateChanged();
}

View File

@ -0,0 +1,191 @@
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/edit_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="@dimen/padding_moderate"
android:paddingVertical="@dimen/padding_moderate"
app:layout_optimizationLevel="standard|dimensions|chains">
<!-- Resolution settings -->
<TextView
android:id="@+id/editResolution_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/_5sdp"
android:gravity="center"
android:paddingEnd="5dp"
android:text="@string/mcl_setting_title_resolution_scaler"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.kdt.CustomSeekbar
android:id="@+id/editResolution_seekbar"
android:layout_width="0dp"
android:layout_height="@dimen/_36sdp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.538"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editResolution_textView" />
<TextView
android:id="@+id/editResolution_textView_percent"
android:layout_width="50dp"
android:layout_height="0dp"
android:gravity="center"
tools:text="50%"
app:layout_constraintBottom_toBottomOf="@id/editResolution_textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/editResolution_textView" />
<!-- Gyroscope settings -->
<Switch
android:id="@+id/checkboxGyro"
android:layout_width="match_parent"
android:layout_height="@dimen/_36sdp"
android:text="@string/preference_enable_gyro_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/editResolution_seekbar"
tools:ignore="UseSwitchCompatOrMaterialXml" />
<Switch
android:id="@+id/checkboxGyroX"
android:layout_width="match_parent"
android:layout_height="@dimen/_36sdp"
android:text="@string/preference_gyro_invert_x_axis"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/checkboxGyro"
tools:ignore="UseSwitchCompatOrMaterialXml" />
<Switch
android:id="@+id/checkboxGyroY"
android:layout_width="match_parent"
android:layout_height="@dimen/_36sdp"
android:text="@string/preference_gyro_invert_y_axis"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/checkboxGyroX"
tools:ignore="UseSwitchCompatOrMaterialXml" />
<!-- Gyroscope sensitivity -->
<TextView
android:id="@+id/editGyro_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/_5sdp"
android:gravity="center"
android:paddingEnd="5dp"
android:text="@string/preference_gyro_sensitivity_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/checkboxGyroY" />
<com.kdt.CustomSeekbar
android:id="@+id/editGyro_seekbar"
android:layout_width="0dp"
android:layout_height="@dimen/_36sdp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.538"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editGyro_textView" />
<TextView
android:id="@+id/editGyro_textView_percent"
android:layout_width="50dp"
android:layout_height="0dp"
android:gravity="center"
tools:text="100%"
app:layout_constraintBottom_toBottomOf="@id/editGyro_textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/editGyro_textView" />
<!-- Mouse settings -->
<TextView
android:id="@+id/editMouseSpeed_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/_5sdp"
android:gravity="center"
android:paddingEnd="5dp"
android:text="@string/mcl_setting_title_mousespeed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/editGyro_seekbar" />
<com.kdt.CustomSeekbar
android:id="@+id/editMouseSpeed_seekbar"
android:layout_width="0dp"
android:layout_height="@dimen/_36sdp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.538"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editMouseSpeed_textView" />
<TextView
android:id="@+id/editMouseSpeed_textView_percent"
android:layout_width="50dp"
android:layout_height="0dp"
android:gravity="center"
tools:text="100%"
app:layout_constraintBottom_toBottomOf="@id/editMouseSpeed_textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/editMouseSpeed_textView" />
<!-- Gesture toggle -->
<Switch
android:id="@+id/checkboxGesture"
android:layout_width="match_parent"
android:layout_height="@dimen/_36sdp"
android:text="@string/mcl_disable_gestures"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/editMouseSpeed_seekbar"
tools:ignore="UseSwitchCompatOrMaterialXml" />
<!-- gesture settings -->
<TextView
android:id="@+id/editGestureDelay_textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/_5sdp"
android:gravity="center"
android:paddingEnd="5dp"
android:text="@string/mcl_setting_title_longpresstrigger"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/checkboxGesture" />
<com.kdt.CustomSeekbar
android:id="@+id/editGestureDelay_seekbar"
android:layout_width="0dp"
android:layout_height="@dimen/_36sdp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.538"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/editGestureDelay_textView" />
<TextView
android:id="@+id/editGestureDelay_textView_percent"
android:layout_width="50dp"
android:layout_height="0dp"
android:gravity="center"
tools:text="270ms"
app:layout_constraintBottom_toBottomOf="@id/editGestureDelay_textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@id/editGestureDelay_textView" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -30,8 +30,7 @@
<item>@string/control_forceclose</item>
<item>@string/control_viewout</item>
<item>@string/control_customkey</item>
<item>@string/mcl_setting_title_mousespeed</item>
<item>@string/preference_gyro_sensitivity_title</item>
<item>@string/quick_setting_title</item>
<item>@string/mcl_option_customcontrol</item>
</string-array>

View File

@ -418,4 +418,5 @@
<string name="discord_invite" translatable="false">https://discord.gg/pojavlauncher-724163890803638273</string>
<string name="local_login_bad_username_title">Unsuitable username</string>
<string name="local_login_bad_username_text">The username must be between 316 characters long, and must only contain latin letters, arabic numerals and underscores.</string>
<string name="quick_setting_title">Quick settings</string>
</resources>