Feature: Gyroscope controls

This commit is contained in:
artdeell 2023-02-01 19:13:13 +03:00
parent c9e9466977
commit 27a3bb8121
7 changed files with 162 additions and 4 deletions

View file

@ -0,0 +1,59 @@
package net.kdt.pojavlaunch;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
import org.lwjgl.glfw.CallbackBridge;
public class GyroControl implements SensorEventListener, GrabListener {
private final SensorManager mSensorManager;
private final Sensor mSensor;
private boolean mShouldHandleEvents;
private float mLastX, mLastY;
public GyroControl(Context context) {
mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);
}
public void enable() {
if(mSensor == null) return;
mSensorManager.registerListener(this, mSensor, 1000 * LauncherPreferences.PREF_GYRO_SAMPLE_RATE);
mShouldHandleEvents = CallbackBridge.isGrabbing();
CallbackBridge.addGrabListener(this);
}
public void disable() {
if(mSensor == null) return;
mSensorManager.unregisterListener(this);
CallbackBridge.removeGrabListener(this);
}
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
if(mShouldHandleEvents && sensorEvent.sensor == mSensor) {
CallbackBridge.mouseX += (sensorEvent.values[0]-mLastX) * LauncherPreferences.PREF_GYRO_SENSITIVITY * 1000;
CallbackBridge.mouseY += (sensorEvent.values[1]-mLastY) * LauncherPreferences.PREF_GYRO_SENSITIVITY * 1000;
CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY);
mLastX = sensorEvent.values[0];
mLastY = sensorEvent.values[1];
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
@Override
public void onGrabState(boolean isGrabbing) {
mShouldHandleEvents = isGrabbing;
}
}

View file

@ -62,6 +62,7 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
private DrawerLayout drawerLayout; private DrawerLayout drawerLayout;
private ListView navDrawer; private ListView navDrawer;
private View mDrawerPullButton; private View mDrawerPullButton;
private GyroControl mGyroControl = null;
public static ControlLayout mControlLayout; public static ControlLayout mControlLayout;
@ -87,6 +88,7 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
initLayout(R.layout.activity_basemain); initLayout(R.layout.activity_basemain);
CallbackBridge.addGrabListener(touchpad); CallbackBridge.addGrabListener(touchpad);
CallbackBridge.addGrabListener(minecraftGLView); CallbackBridge.addGrabListener(minecraftGLView);
if(LauncherPreferences.PREF_ENALBE_GYRO) mGyroControl = new GyroControl(this);
// Enabling this on TextureView results in a broken white result // Enabling this on TextureView results in a broken white result
if(PREF_USE_ALTERNATE_SURFACE) getWindow().setBackgroundDrawable(null); if(PREF_USE_ALTERNATE_SURFACE) getWindow().setBackgroundDrawable(null);
@ -168,7 +170,8 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
case 2: minecraftGLView.togglepointerDebugging(); break; case 2: minecraftGLView.togglepointerDebugging(); break;
case 3: dialogSendCustomKey(); break; case 3: dialogSendCustomKey(); break;
case 4: adjustMouseSpeedLive(); break; case 4: adjustMouseSpeedLive(); break;
case 5: openCustomControls(); break; case 5: adjustGyroSensitivityLive(); break;
case 6: openCustomControls(); break;
} }
drawerLayout.closeDrawers(); drawerLayout.closeDrawers();
}; };
@ -240,6 +243,7 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
mIsResuming = true; mIsResuming = true;
if(mGyroControl != null) mGyroControl.enable();
final int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; final int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
final View decorView = getWindow().getDecorView(); final View decorView = getWindow().getDecorView();
decorView.setSystemUiVisibility(uiOptions); decorView.setSystemUiVisibility(uiOptions);
@ -248,6 +252,7 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
@Override @Override
protected void onPause() { protected void onPause() {
if(mGyroControl != null) mGyroControl.disable();
if (CallbackBridge.isGrabbing()){ if (CallbackBridge.isGrabbing()){
sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_ESCAPE); sendKeyPress(LwjglGlfwKeycode.GLFW_KEY_ESCAPE);
} }
@ -509,6 +514,46 @@ public class MainActivity extends BaseActivity implements ControlButtonMenuListe
b.show(); b.show();
} }
int tmpGyroSensitivity;
public void adjustGyroSensitivityLive() {
if(!LauncherPreferences.PREF_ENALBE_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(tmpGyroSensitivity +" %");
sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
tmpGyroSensitivity = i+25;
tv.setText(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).commit();
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) { private static void setUri(Context context, String input, Intent intent) {
if(input.startsWith("file:")) { if(input.startsWith("file:")) {
int truncLength = 5; int truncLength = 5;

View file

@ -51,6 +51,9 @@ public class LauncherPreferences {
public static boolean PREF_USE_ALTERNATE_SURFACE = true; public static boolean PREF_USE_ALTERNATE_SURFACE = true;
public static boolean PREF_JAVA_SANDBOX = true; public static boolean PREF_JAVA_SANDBOX = true;
public static int PREF_SCALE_FACTOR = 100; public static int PREF_SCALE_FACTOR = 100;
public static boolean PREF_ENALBE_GYRO = false;
public static float PREF_GYRO_SENSITIVITY = 100;
public static int PREF_GYRO_SAMPLE_RATE = 16;
public static void loadPreferences(Context ctx) { public static void loadPreferences(Context ctx) {
@ -85,6 +88,9 @@ public class LauncherPreferences {
PREF_USE_ALTERNATE_SURFACE = DEFAULT_PREF.getBoolean("alternate_surface", false); PREF_USE_ALTERNATE_SURFACE = DEFAULT_PREF.getBoolean("alternate_surface", false);
PREF_JAVA_SANDBOX = DEFAULT_PREF.getBoolean("java_sandbox", true); PREF_JAVA_SANDBOX = DEFAULT_PREF.getBoolean("java_sandbox", true);
PREF_SCALE_FACTOR = DEFAULT_PREF.getInt("resolutionRatio", 100); PREF_SCALE_FACTOR = DEFAULT_PREF.getInt("resolutionRatio", 100);
PREF_ENALBE_GYRO = DEFAULT_PREF.getBoolean("enableGyro", false);
PREF_GYRO_SENSITIVITY = ((float)DEFAULT_PREF.getInt("gyroSensitivity", 100))/100f;
PREF_GYRO_SAMPLE_RATE = DEFAULT_PREF.getInt("gyroSampleRate", 16);
/* /*
if (PREF_CUSTOM_JAVA_ARGS.isEmpty()) { if (PREF_CUSTOM_JAVA_ARGS.isEmpty()) {

View file

@ -1,21 +1,28 @@
package net.kdt.pojavlaunch.prefs.screens; package net.kdt.pojavlaunch.prefs.screens;
import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.os.Bundle; import android.os.Bundle;
import androidx.preference.SwitchPreference;
import net.kdt.pojavlaunch.R; import net.kdt.pojavlaunch.R;
import net.kdt.pojavlaunch.prefs.CustomSeekBarPreference; import net.kdt.pojavlaunch.prefs.CustomSeekBarPreference;
import net.kdt.pojavlaunch.prefs.LauncherPreferences; import net.kdt.pojavlaunch.prefs.LauncherPreferences;
public class LauncherPreferenceControlFragment extends LauncherPreferenceFragment { public class LauncherPreferenceControlFragment extends LauncherPreferenceFragment {
private boolean mGyroAvailable = false;
@Override @Override
public void onCreatePreferences(Bundle b, String str) { public void onCreatePreferences(Bundle b, String str) {
// Get values // Get values
int longPressTrigger = LauncherPreferences.PREF_LONGPRESS_TRIGGER; int longPressTrigger = LauncherPreferences.PREF_LONGPRESS_TRIGGER;
int prefButtonSize = (int) LauncherPreferences.PREF_BUTTONSIZE; int prefButtonSize = (int) LauncherPreferences.PREF_BUTTONSIZE;
int mouseScale = (int) LauncherPreferences.PREF_MOUSESCALE; int mouseScale = (int) LauncherPreferences.PREF_MOUSESCALE;
int gyroSampleRate = LauncherPreferences.PREF_GYRO_SAMPLE_RATE;
float mouseSpeed = LauncherPreferences.PREF_MOUSESPEED; float mouseSpeed = LauncherPreferences.PREF_MOUSESPEED;
float gyroSpeed = LauncherPreferences.PREF_GYRO_SENSITIVITY;
//Triggers a write for some reason which resets the value //Triggers a write for some reason which resets the value
addPreferencesFromResource(R.xml.pref_control); addPreferencesFromResource(R.xml.pref_control);
@ -40,7 +47,20 @@ public class LauncherPreferenceControlFragment extends LauncherPreferenceFragmen
seek6.setValue((int)(mouseSpeed *100f)); seek6.setValue((int)(mouseSpeed *100f));
seek6.setSuffix(" %"); seek6.setSuffix(" %");
Context context = getContext();
if(context != null) {
mGyroAvailable = ((SensorManager)context.getSystemService(Context.SENSOR_SERVICE)).getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR) != null;
}
SwitchPreference gyroSwitch = findPreference("enableGyro");
gyroSwitch.setVisible(mGyroAvailable);
CustomSeekBarPreference gyroSensitivitySeek = findPreference("gyroSensitivity");
gyroSensitivitySeek.setRange(25, 300);
gyroSensitivitySeek.setValue((int) (gyroSpeed*100f));
gyroSensitivitySeek.setSuffix(" %");
CustomSeekBarPreference gyroSampleRateSeek = findPreference("gyroSampleRate");
gyroSampleRateSeek.setRange(5, 50);
gyroSampleRateSeek.setValue(gyroSampleRate);
gyroSampleRateSeek.setSuffix(" ms");
computeVisibility(); computeVisibility();
} }
@ -53,6 +73,10 @@ public class LauncherPreferenceControlFragment extends LauncherPreferenceFragmen
private void computeVisibility(){ private void computeVisibility(){
CustomSeekBarPreference seek2 = findPreference("timeLongPressTrigger"); CustomSeekBarPreference seek2 = findPreference("timeLongPressTrigger");
seek2.setVisible(!LauncherPreferences.PREF_DISABLE_GESTURES); seek2.setVisible(!LauncherPreferences.PREF_DISABLE_GESTURES);
CustomSeekBarPreference gyroSensitivitySeek = findPreference("gyroSensitivity");
gyroSensitivitySeek.setVisible(mGyroAvailable && LauncherPreferences.PREF_ENALBE_GYRO);
CustomSeekBarPreference gyroSampleRateSeek = findPreference("gyroSampleRate");
gyroSampleRateSeek.setVisible(mGyroAvailable && LauncherPreferences.PREF_ENALBE_GYRO);
} }
} }

View file

@ -30,6 +30,7 @@
<item>@string/control_adebug</item> <item>@string/control_adebug</item>
<item>@string/control_customkey</item> <item>@string/control_customkey</item>
<item>@string/mcl_setting_title_mousespeed</item> <item>@string/mcl_setting_title_mousespeed</item>
<item>@string/preference_gyro_sensitivity_title</item>
<item>@string/mcl_option_customcontrol</item> <item>@string/mcl_option_customcontrol</item>
</string-array> </string-array>

View file

@ -331,4 +331,11 @@
<string name="xerr_child">Your account is a child account, and needs to be added into a Family in order to log in.</string> <string name="xerr_child">Your account is a child account, and needs to be added into a Family in order to log in.</string>
<string name="minecraft_not_owned">It seems like this account does not have a Minecraft profile. If you have Xbox Game Pass, please log in on https://minecraft.net/ and set it up.</string> <string name="minecraft_not_owned">It seems like this account does not have a Minecraft profile. If you have Xbox Game Pass, please log in on https://minecraft.net/ and set it up.</string>
<string name="xerr_not_available">Xbox Live is not available in your country</string> <string name="xerr_not_available">Xbox Live is not available in your country</string>
<string name="preference_enable_gyro_title">Enable gyroscope controls</string>
<string name="preference_enable_gyro_description">Enabling this will allow you to turn in game by turning your phone</string>
<string name="preference_gyro_sensitivity_title">Gyroscope controls sensitivity</string>
<string name="preference_gyro_sensitivity_description">Adjust the sensitivity of gyroscope controls</string>
<string name="toast_turn_on_gyro">Enable gyro controls first to use this!</string>
<string name="preference_gyro_sample_rate_title">Gyroscope sampling rate</string>
<string name="preference_gyro_sample_rate_description">If you have performance issues with the gyroscope controls, increase this</string>
</resources> </resources>

View file

@ -77,7 +77,23 @@
android:title="@string/preference_mouse_start_title" android:title="@string/preference_mouse_start_title"
android:summary="@string/preference_mouse_start_description" android:summary="@string/preference_mouse_start_description"
/> />
<SwitchPreference
android:key="enableGyro"
android:title="@string/preference_enable_gyro_title"
android:summary="@string/preference_enable_gyro_description"/>
<net.kdt.pojavlaunch.prefs.CustomSeekBarPreference
android:key="gyroSensitivity"
android:title="@string/preference_gyro_sensitivity_title"
android:summary="@string/preference_gyro_sensitivity_description"
app2:selectable="false"
app2:seekBarIncrement="5"
app2:showSeekBarValue="true"/>
<net.kdt.pojavlaunch.prefs.CustomSeekBarPreference
android:key="gyroSampleRate"
android:title="@string/preference_gyro_sample_rate_title"
android:summary="@string/preference_gyro_sample_rate_description"
app2:selectable="false"
app2:showSeekBarValue="true"/>
</PreferenceCategory> </PreferenceCategory>