android: Add motion sensor

This commit is contained in:
Narr the Reg 2023-02-13 14:08:06 -06:00 committed by bunnei
parent 92fb7cc4e4
commit f1bb2f3685
4 changed files with 92 additions and 21 deletions

View File

@ -16,6 +16,10 @@ import android.graphics.BitmapFactory;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
@ -38,20 +42,19 @@ import java.util.Set;
* Draws the interactive input overlay on top of the * Draws the interactive input overlay on top of the
* {@link SurfaceView} that is rendering emulation. * {@link SurfaceView} that is rendering emulation.
*/ */
public final class InputOverlay extends SurfaceView implements OnTouchListener { public final class InputOverlay extends SurfaceView implements OnTouchListener, SensorEventListener {
private final Set<InputOverlayDrawableButton> overlayButtons = new HashSet<>(); private final Set<InputOverlayDrawableButton> overlayButtons = new HashSet<>();
private final Set<InputOverlayDrawableDpad> overlayDpads = new HashSet<>(); private final Set<InputOverlayDrawableDpad> overlayDpads = new HashSet<>();
private final Set<InputOverlayDrawableJoystick> overlayJoysticks = new HashSet<>(); private final Set<InputOverlayDrawableJoystick> overlayJoysticks = new HashSet<>();
private boolean mIsInEditMode = false; private boolean mIsInEditMode = false;
private InputOverlayDrawableButton mButtonBeingConfigured;
private InputOverlayDrawableDpad mDpadBeingConfigured;
private InputOverlayDrawableJoystick mJoystickBeingConfigured;
private SharedPreferences mPreferences; private SharedPreferences mPreferences;
// Stores the ID of the pointer that interacted with the 3DS touchscreen. private float[] gyro = new float[3];
private int mTouchscreenPointerId = -1; private float[] accel = new float[3];
private long motionTimestamp;
/** /**
* Constructor * Constructor
@ -67,12 +70,12 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
defaultOverlay(); defaultOverlay();
} }
// Reset 3ds touchscreen pointer ID
mTouchscreenPointerId = -1;
// Load the controls. // Load the controls.
refreshControls(); refreshControls();
// Set the on motion sensor listener.
setMotionSensorListener(context);
// Set the on touch listener. // Set the on touch listener.
setOnTouchListener(this); setOnTouchListener(this);
@ -83,6 +86,20 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
requestFocus(); requestFocus();
} }
private void setMotionSensorListener(Context context) {
SensorManager sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
Sensor gyro_sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
Sensor accel_sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (gyro_sensor != null) {
sensorManager.registerListener(this, gyro_sensor, SensorManager.SENSOR_DELAY_GAME);
}
if (accel_sensor != null) {
sensorManager.registerListener(this, accel_sensor, SensorManager.SENSOR_DELAY_GAME);
}
}
/** /**
* Resizes a {@link Bitmap} by a given scale factor * Resizes a {@link Bitmap} by a given scale factor
* *
@ -427,6 +444,36 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
return true; return true;
} }
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
accel[0] = -event.values[1] / SensorManager.GRAVITY_EARTH;
accel[1] = event.values[0] / SensorManager.GRAVITY_EARTH;
accel[2] = -event.values[2] / SensorManager.GRAVITY_EARTH;
}
if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
// Investigate why sensor value is off by 12x
gyro[0] = event.values[1] / 12.0f;
gyro[1] = -event.values[0] / 12.0f;
gyro[2] = event.values[2] / 12.0f;
}
// Only update state on accelerometer data
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) {
return;
}
long delta_timestamp = (event.timestamp - motionTimestamp) / 1000;
motionTimestamp = event.timestamp;
NativeLibrary.onGamePadMotionEvent(NativeLibrary.Player1Device, delta_timestamp, gyro[0], gyro[1], gyro[2], accel[0], accel[1], accel[2]);
NativeLibrary.onGamePadMotionEvent(NativeLibrary.ConsoleDevice, delta_timestamp, gyro[0], gyro[1], gyro[2], accel[0], accel[1], accel[2]);
}
@Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
private void addOverlayControls(String orientation) { private void addOverlayControls(String orientation) {
if (mPreferences.getBoolean("buttonToggle0", true)) { if (mPreferences.getBoolean("buttonToggle0", true)) {
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.button_a, overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.button_a,

View File

@ -11,12 +11,12 @@ void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
} }
void EmuWindow_Android::OnTouchPressed(int id, float x, float y) { void EmuWindow_Android::OnTouchPressed(int id, float x, float y) {
const auto [touch_x,touch_y]=MapToTouchScreen(x,y); const auto [touch_x, touch_y] = MapToTouchScreen(x, y);
input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, id); input_subsystem->GetTouchScreen()->TouchPressed(touch_x, touch_y, id);
} }
void EmuWindow_Android::OnTouchMoved(int id, float x, float y) { void EmuWindow_Android::OnTouchMoved(int id, float x, float y) {
const auto [touch_x,touch_y]=MapToTouchScreen(x,y); const auto [touch_x, touch_y] = MapToTouchScreen(x, y);
input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, id); input_subsystem->GetTouchScreen()->TouchMoved(touch_x, touch_y, id);
} }
@ -29,21 +29,19 @@ void EmuWindow_Android::OnGamepadButtonEvent(int player_index, int button_id, bo
} }
void EmuWindow_Android::OnGamepadJoystickEvent(int player_index, int stick_id, float x, float y) { void EmuWindow_Android::OnGamepadJoystickEvent(int player_index, int stick_id, float x, float y) {
input_subsystem->GetVirtualGamepad()->SetStickPosition( input_subsystem->GetVirtualGamepad()->SetStickPosition(player_index, stick_id, x, y);
player_index, stick_id, x, y);
} }
void EmuWindow_Android::OnGamepadMotionEvent(int player_index, u64 delta_timestamp, float gyro_x, float gyro_y, void EmuWindow_Android::OnGamepadMotionEvent(int player_index, u64 delta_timestamp, float gyro_x,
float gyro_z, float accel_x, float accel_y, float gyro_y, float gyro_z, float accel_x,
float accel_z) { float accel_y, float accel_z) {
// TODO: input_subsystem->GetVirtualGamepad()->SetMotionState(player_index, delta_timestamp, gyro_x,
// input_subsystem->GetVirtualGamepad()->SetMotionState(player_index, delta_timestamp, gyro_x, gyro_y, gyro_y, gyro_z, accel_x, accel_y, accel_z);
// gyro_z, accel_x, accel_y, accel_z);
} }
EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem_, EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem_,
ANativeWindow* surface_) ANativeWindow* surface_)
: input_subsystem{input_subsystem_} { : input_subsystem{input_subsystem_} {
LOG_INFO(Frontend, "initializing"); LOG_INFO(Frontend, "initializing");
if (!surface_) { if (!surface_) {

View File

@ -39,6 +39,22 @@ void VirtualGamepad::SetStickPosition(std::size_t player_index, VirtualStick axi
SetStickPosition(player_index, static_cast<int>(axis_id), x_value, y_value); SetStickPosition(player_index, static_cast<int>(axis_id), x_value, y_value);
} }
void VirtualGamepad::SetMotionState(std::size_t player_index, u64 delta_timestamp, float gyro_x,
float gyro_y, float gyro_z, float accel_x, float accel_y,
float accel_z) {
const auto identifier = GetIdentifier(player_index);
const BasicMotion motion_data{
.gyro_x = gyro_x,
.gyro_y = gyro_y,
.gyro_z = gyro_z,
.accel_x = accel_x,
.accel_y = accel_y,
.accel_z = accel_z,
.delta_timestamp = delta_timestamp,
};
SetMotion(identifier, 0, motion_data);
}
void VirtualGamepad::ResetControllers() { void VirtualGamepad::ResetControllers() {
for (std::size_t i = 0; i < PlayerIndexCount; i++) { for (std::size_t i = 0; i < PlayerIndexCount; i++) {
SetStickPosition(i, VirtualStick::Left, 0.0f, 0.0f); SetStickPosition(i, VirtualStick::Left, 0.0f, 0.0f);

View File

@ -52,7 +52,7 @@ public:
void SetButtonState(std::size_t player_index, VirtualButton button_id, bool value); void SetButtonState(std::size_t player_index, VirtualButton button_id, bool value);
/** /**
* Sets the status of all buttons bound with the key to released * Sets the status of a stick to a specific player index
* @param player_index the player number that will take this action * @param player_index the player number that will take this action
* @param axis_id the id of the axis to move * @param axis_id the id of the axis to move
* @param x_value the position of the stick in the x axis * @param x_value the position of the stick in the x axis
@ -62,6 +62,16 @@ public:
void SetStickPosition(std::size_t player_index, VirtualStick axis_id, float x_value, void SetStickPosition(std::size_t player_index, VirtualStick axis_id, float x_value,
float y_value); float y_value);
/**
* Sets the status of the motion sensor to a specific player index
* @param player_index the player number that will take this action
* @param delta_timestamp time passed since last reading
* @param gyro_x,gyro_y,gyro_z the gyro sensor readings
* @param accel_x,accel_y,accel_z the acelerometer reading
*/
void SetMotionState(std::size_t player_index, u64 delta_timestamp, float gyro_x, float gyro_y,
float gyro_z, float accel_x, float accel_y, float accel_z);
/// Restores all inputs into the neutral position /// Restores all inputs into the neutral position
void ResetControllers(); void ResetControllers();