forked from suyu/suyu
android: Add motion sensor
This commit is contained in:
parent
92fb7cc4e4
commit
f1bb2f3685
4 changed files with 92 additions and 21 deletions
|
@ -16,6 +16,10 @@ import android.graphics.BitmapFactory;
|
|||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
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.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
|
@ -38,20 +42,19 @@ import java.util.Set;
|
|||
* Draws the interactive input overlay on top of the
|
||||
* {@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<InputOverlayDrawableDpad> overlayDpads = new HashSet<>();
|
||||
private final Set<InputOverlayDrawableJoystick> overlayJoysticks = new HashSet<>();
|
||||
|
||||
private boolean mIsInEditMode = false;
|
||||
private InputOverlayDrawableButton mButtonBeingConfigured;
|
||||
private InputOverlayDrawableDpad mDpadBeingConfigured;
|
||||
private InputOverlayDrawableJoystick mJoystickBeingConfigured;
|
||||
|
||||
private SharedPreferences mPreferences;
|
||||
|
||||
// Stores the ID of the pointer that interacted with the 3DS touchscreen.
|
||||
private int mTouchscreenPointerId = -1;
|
||||
private float[] gyro = new float[3];
|
||||
private float[] accel = new float[3];
|
||||
|
||||
private long motionTimestamp;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
|
@ -67,12 +70,12 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
|
|||
defaultOverlay();
|
||||
}
|
||||
|
||||
// Reset 3ds touchscreen pointer ID
|
||||
mTouchscreenPointerId = -1;
|
||||
|
||||
// Load the controls.
|
||||
refreshControls();
|
||||
|
||||
// Set the on motion sensor listener.
|
||||
setMotionSensorListener(context);
|
||||
|
||||
// Set the on touch listener.
|
||||
setOnTouchListener(this);
|
||||
|
||||
|
@ -83,6 +86,20 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
|
|||
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
|
||||
*
|
||||
|
@ -427,6 +444,36 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener {
|
|||
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) {
|
||||
if (mPreferences.getBoolean("buttonToggle0", true)) {
|
||||
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.button_a,
|
||||
|
|
|
@ -11,12 +11,12 @@ void EmuWindow_Android::OnSurfaceChanged(ANativeWindow* surface) {
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
input_subsystem->GetVirtualGamepad()->SetStickPosition(
|
||||
player_index, stick_id, x, y);
|
||||
input_subsystem->GetVirtualGamepad()->SetStickPosition(player_index, stick_id, x, y);
|
||||
}
|
||||
|
||||
void EmuWindow_Android::OnGamepadMotionEvent(int player_index, u64 delta_timestamp, float gyro_x, float gyro_y,
|
||||
float gyro_z, float accel_x, float accel_y,
|
||||
float accel_z) {
|
||||
// TODO:
|
||||
// input_subsystem->GetVirtualGamepad()->SetMotionState(player_index, delta_timestamp, gyro_x, gyro_y,
|
||||
// gyro_z, accel_x, accel_y, accel_z);
|
||||
void EmuWindow_Android::OnGamepadMotionEvent(int player_index, u64 delta_timestamp, float gyro_x,
|
||||
float gyro_y, float gyro_z, float accel_x,
|
||||
float accel_y, float accel_z) {
|
||||
input_subsystem->GetVirtualGamepad()->SetMotionState(player_index, delta_timestamp, gyro_x,
|
||||
gyro_y, gyro_z, accel_x, accel_y, accel_z);
|
||||
}
|
||||
|
||||
EmuWindow_Android::EmuWindow_Android(InputCommon::InputSubsystem* input_subsystem_,
|
||||
ANativeWindow* surface_)
|
||||
: input_subsystem{input_subsystem_} {
|
||||
: input_subsystem{input_subsystem_} {
|
||||
LOG_INFO(Frontend, "initializing");
|
||||
|
||||
if (!surface_) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
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() {
|
||||
for (std::size_t i = 0; i < PlayerIndexCount; i++) {
|
||||
SetStickPosition(i, VirtualStick::Left, 0.0f, 0.0f);
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
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 axis_id the id of the axis to move
|
||||
* @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,
|
||||
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
|
||||
void ResetControllers();
|
||||
|
||||
|
|
Loading…
Reference in a new issue