diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java index dc888d74d4..25b84a811a 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/EmulationFragment.java @@ -102,14 +102,6 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C surfaceView.getHolder().addCallback(this); mInputOverlay = contents.findViewById(R.id.surface_input_overlay); - if (mInputOverlay != null) - { - // If the input overlay was previously disabled, then don't show it. - if (!mPreferences.getBoolean("showInputOverlay", true)) - { - mInputOverlay.setVisibility(View.GONE); - } - } Button doneButton = contents.findViewById(R.id.done_control_config); if (doneButton != null) @@ -199,18 +191,14 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C // If the overlay is currently set to INVISIBLE if (!mPreferences.getBoolean("showInputOverlay", false)) { - // Set it to VISIBLE - mInputOverlay.setVisibility(View.VISIBLE); editor.putBoolean("showInputOverlay", true); } else { - // Set it to INVISIBLE - mInputOverlay.setVisibility(View.GONE); editor.putBoolean("showInputOverlay", false); } - - editor.apply(); + editor.commit(); + mInputOverlay.refreshControls(); } public void refreshInputOverlay() diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlay.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlay.java index de29e00ed5..e7ad7dbae7 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlay.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlay.java @@ -43,6 +43,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener private final Set overlayButtons = new HashSet<>(); private final Set overlayDpads = new HashSet<>(); private final Set overlayJoysticks = new HashSet<>(); + private InputOverlayPointer overlayPointer; private boolean mIsInEditMode = false; private InputOverlayDrawableButton mButtonBeingConfigured; @@ -128,6 +129,8 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener } int pointerIndex = event.getActionIndex(); + // Tracks if any button/joystick is pressed down + boolean pressed = false; for (InputOverlayDrawableButton button : overlayButtons) { @@ -142,6 +145,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener { button.setPressedState(true); button.setTrackId(event.getPointerId(pointerIndex)); + pressed = true; NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(), ButtonState.PRESSED); } @@ -154,6 +158,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener button.setPressedState(false); NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(), ButtonState.RELEASED); + button.setTrackId(-1); } break; } @@ -166,35 +171,40 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_POINTER_DOWN: - case MotionEvent.ACTION_MOVE: - // Up, Down, Left, Right - boolean[] pressed = {false, false, false, false}; // If a pointer enters the bounds of a button, press that button. if (dpad.getBounds() .contains((int) event.getX(pointerIndex), (int) event.getY(pointerIndex))) { + dpad.setTrackId(event.getPointerId(pointerIndex)); + pressed = true; + } + case MotionEvent.ACTION_MOVE: + if (dpad.getTrackId() == event.getPointerId(pointerIndex)) + { + // Up, Down, Left, Right + boolean[] dpadPressed = {false, false, false, false}; + if (dpad.getBounds().top + (dpad.getHeight() / 3) > (int) event.getY(pointerIndex)) - pressed[0] = true; + dpadPressed[0] = true; if (dpad.getBounds().bottom - (dpad.getHeight() / 3) < (int) event.getY(pointerIndex)) - pressed[1] = true; + dpadPressed[1] = true; if (dpad.getBounds().left + (dpad.getWidth() / 3) > (int) event.getX(pointerIndex)) - pressed[2] = true; + dpadPressed[2] = true; if (dpad.getBounds().right - (dpad.getWidth() / 3) < (int) event.getX(pointerIndex)) - pressed[3] = true; + dpadPressed[3] = true; // Release the buttons first, then press - for (int i = 0; i < pressed.length; i++) - if (!pressed[i]) + for (int i = 0; i < dpadPressed.length; i++) + if (!dpadPressed[i]) NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(i), ButtonState.RELEASED); // Press buttons - for (int i = 0; i < pressed.length; i++) - if (pressed[i]) + for (int i = 0; i < dpadPressed.length; i++) + if (dpadPressed[i]) NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(i), ButtonState.PRESSED); - setDpadState(dpad, pressed[0], pressed[1], pressed[2], pressed[3]); - dpad.setTrackId(event.getPointerId(pointerIndex)); + setDpadState(dpad, dpadPressed[0], dpadPressed[1], dpadPressed[2], dpadPressed[3]); } break; case MotionEvent.ACTION_UP: @@ -208,6 +218,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(i), ButtonState.RELEASED); } + dpad.setTrackId(-1); } break; } @@ -215,7 +226,11 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener for (InputOverlayDrawableJoystick joystick : overlayJoysticks) { - joystick.TrackEvent(event); + if (joystick.TrackEvent(event)) + { + if (joystick.getTrackId() != -1) + pressed = true; + } int[] axisIDs = joystick.getAxisIDs(); float[] axises = joystick.getAxisValues(); @@ -225,6 +240,18 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener } } + // No button/joystick pressed, safe to move pointer + if (!pressed && overlayPointer != null) + { + overlayPointer.onTouch(event); + float[] axises = overlayPointer.getAxisValues(); + + NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, ButtonType.WIIMOTE_IR + 2, + axises[0]); + NativeLibrary.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, ButtonType.WIIMOTE_IR + 4, + axises[1]); + } + invalidate(); return true; @@ -617,24 +644,30 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT ? "-Portrait" : ""; - // Add all the enabled overlay items back to the HashSet. - if (EmulationActivity.isGameCubeGame() || mPreferences.getInt("wiiController", 3) == 0) + if (mPreferences.getBoolean("showInputOverlay", true)) { - addGameCubeOverlayControls(orientation); - } - else if (mPreferences.getInt("wiiController", 3) == 4) - { - addClassicOverlayControls(orientation); - } - else - { - addWiimoteOverlayControls(orientation); - if (mPreferences.getInt("wiiController", 3) == 3) + // Add all the enabled overlay items back to the HashSet. + if (EmulationActivity.isGameCubeGame() || mPreferences.getInt("wiiController", 3) == 0) { - addNunchukOverlayControls(orientation); + addGameCubeOverlayControls(orientation); + } + else if (mPreferences.getInt("wiiController", 3) == 4) + { + addClassicOverlayControls(orientation); + } + else + { + addWiimoteOverlayControls(orientation); + if (mPreferences.getInt("wiiController", 3) == 3) + { + addNunchukOverlayControls(orientation); + } } } + if (!EmulationActivity.isGameCubeGame()) + overlayPointer = new InputOverlayPointer(this.getContext()); + invalidate(); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableButton.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableButton.java index 96b4aeca0a..266cd273c4 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableButton.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableButton.java @@ -41,6 +41,7 @@ public final class InputOverlayDrawableButton public InputOverlayDrawableButton(Resources res, Bitmap defaultStateBitmap, Bitmap pressedStateBitmap, int buttonType) { + mTrackId = -1; mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap); mPressedStateBitmap = new BitmapDrawable(res, pressedStateBitmap); mButtonType = buttonType; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableDpad.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableDpad.java index fd60f1fc98..5aa8c4846d 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableDpad.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableDpad.java @@ -60,6 +60,7 @@ public final class InputOverlayDrawableDpad int buttonUp, int buttonDown, int buttonLeft, int buttonRight) { + mTrackId = -1; mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap); mPressedOneDirectionStateBitmap = new BitmapDrawable(res, pressedOneDirectionStateBitmap); mPressedTwoDirectionsStateBitmap = new BitmapDrawable(res, pressedTwoDirectionsStateBitmap); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableJoystick.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableJoystick.java index a54d01c7cf..55f6347096 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableJoystick.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayDrawableJoystick.java @@ -94,10 +94,11 @@ public final class InputOverlayDrawableJoystick mBoundsBoxBitmap.draw(canvas); } - public void TrackEvent(MotionEvent event) + public boolean TrackEvent(MotionEvent event) { boolean reCenter = mPreferences.getBoolean("joystickRelCenter", true); int pointerIndex = event.getActionIndex(); + boolean pressed = false; switch (event.getAction() & MotionEvent.ACTION_MASK) { @@ -105,7 +106,7 @@ public final class InputOverlayDrawableJoystick case MotionEvent.ACTION_POINTER_DOWN: if (getBounds().contains((int) event.getX(pointerIndex), (int) event.getY(pointerIndex))) { - mPressedState = true; + mPressedState = pressed = true; mOuterBitmap.setAlpha(0); mBoundsBoxBitmap.setAlpha(255); if (reCenter) @@ -121,6 +122,7 @@ public final class InputOverlayDrawableJoystick case MotionEvent.ACTION_POINTER_UP: if (trackId == event.getPointerId(pointerIndex)) { + pressed = true; mPressedState = false; axises[0] = axises[1] = 0.0f; mOuterBitmap.setAlpha(255); @@ -136,7 +138,7 @@ public final class InputOverlayDrawableJoystick } if (trackId == -1) - return; + return pressed; for (int i = 0; i < event.getPointerCount(); i++) { @@ -158,6 +160,7 @@ public final class InputOverlayDrawableJoystick SetInnerBounds(); } } + return pressed; } public boolean onConfigureTouch(MotionEvent event) @@ -274,4 +277,9 @@ public final class InputOverlayDrawableJoystick { return mHeight; } + + public int getTrackId() + { + return trackId; + } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayPointer.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayPointer.java new file mode 100644 index 0000000000..1191d2dc7a --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/overlay/InputOverlayPointer.java @@ -0,0 +1,60 @@ +package org.dolphinemu.dolphinemu.overlay; + +import android.app.Activity; +import android.content.Context; +import android.util.DisplayMetrics; +import android.view.Display; +import android.view.MotionEvent; + +public class InputOverlayPointer +{ + private final float[] axes = {0f, 0f}; + private float maxHeight; + private float maxWidth; + private int trackId = -1; + + public InputOverlayPointer(Context context) + { + Display display = ((Activity) context).getWindowManager().getDefaultDisplay(); + DisplayMetrics outMetrics = new DisplayMetrics(); + display.getMetrics(outMetrics); + maxWidth = outMetrics.widthPixels / 2; + maxHeight = outMetrics.heightPixels / 2; + } + + public boolean onTouch(MotionEvent event) + { + int pointerIndex = event.getActionIndex(); + + switch (event.getAction() & MotionEvent.ACTION_MASK) + { + case MotionEvent.ACTION_DOWN: + case MotionEvent.ACTION_POINTER_DOWN: + trackId = event.getPointerId(pointerIndex); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_POINTER_UP: + if (trackId == event.getPointerId(pointerIndex)) + trackId = -1; + break; + } + + if (trackId == -1) + return false; + + int x = (int) event.getX(event.findPointerIndex(trackId)); + int y = (int) event.getY(event.findPointerIndex(trackId)); + axes[0] = (y - maxHeight) / maxHeight; + axes[1] = (x - maxWidth) / maxWidth; + + return false; + } + + public float[] getAxisValues() + { + float[] ir = {0f, 0f}; + ir[0] = axes[0]; + ir[1] = axes[1]; + return axes; + } +} diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.h b/Source/Core/InputCommon/ControllerInterface/Android/Android.h index deb23539ce..59919982ef 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.h +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.h @@ -30,6 +30,7 @@ private: { public: std::string GetName() const; + bool IsDetectable() override { return false; } Axis(int padID, ButtonManager::ButtonType index, float neg = 1.0f) : _padID(padID), _index(index), _neg(neg) {