Android: Add touch to move pointer in overlay

This commit is contained in:
zackhow 2018-10-05 16:59:17 -04:00
parent 3627ef8a04
commit 47d6406fd4
7 changed files with 136 additions and 44 deletions

View File

@ -102,14 +102,6 @@ public final class EmulationFragment extends Fragment implements SurfaceHolder.C
surfaceView.getHolder().addCallback(this); surfaceView.getHolder().addCallback(this);
mInputOverlay = contents.findViewById(R.id.surface_input_overlay); 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); Button doneButton = contents.findViewById(R.id.done_control_config);
if (doneButton != null) 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 the overlay is currently set to INVISIBLE
if (!mPreferences.getBoolean("showInputOverlay", false)) if (!mPreferences.getBoolean("showInputOverlay", false))
{ {
// Set it to VISIBLE
mInputOverlay.setVisibility(View.VISIBLE);
editor.putBoolean("showInputOverlay", true); editor.putBoolean("showInputOverlay", true);
} }
else else
{ {
// Set it to INVISIBLE
mInputOverlay.setVisibility(View.GONE);
editor.putBoolean("showInputOverlay", false); editor.putBoolean("showInputOverlay", false);
} }
editor.commit();
editor.apply(); mInputOverlay.refreshControls();
} }
public void refreshInputOverlay() public void refreshInputOverlay()

View File

@ -43,6 +43,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
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 InputOverlayPointer overlayPointer;
private boolean mIsInEditMode = false; private boolean mIsInEditMode = false;
private InputOverlayDrawableButton mButtonBeingConfigured; private InputOverlayDrawableButton mButtonBeingConfigured;
@ -128,6 +129,8 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
} }
int pointerIndex = event.getActionIndex(); int pointerIndex = event.getActionIndex();
// Tracks if any button/joystick is pressed down
boolean pressed = false;
for (InputOverlayDrawableButton button : overlayButtons) for (InputOverlayDrawableButton button : overlayButtons)
{ {
@ -142,6 +145,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
{ {
button.setPressedState(true); button.setPressedState(true);
button.setTrackId(event.getPointerId(pointerIndex)); button.setTrackId(event.getPointerId(pointerIndex));
pressed = true;
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(), NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(),
ButtonState.PRESSED); ButtonState.PRESSED);
} }
@ -154,6 +158,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
button.setPressedState(false); button.setPressedState(false);
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(), NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(),
ButtonState.RELEASED); ButtonState.RELEASED);
button.setTrackId(-1);
} }
break; break;
} }
@ -166,35 +171,40 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
{ {
case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_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 a pointer enters the bounds of a button, press that button.
if (dpad.getBounds() if (dpad.getBounds()
.contains((int) event.getX(pointerIndex), (int) event.getY(pointerIndex))) .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)) 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)) 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)) 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)) if (dpad.getBounds().right - (dpad.getWidth() / 3) < (int) event.getX(pointerIndex))
pressed[3] = true; dpadPressed[3] = true;
// Release the buttons first, then press // Release the buttons first, then press
for (int i = 0; i < pressed.length; i++) for (int i = 0; i < dpadPressed.length; i++)
if (!pressed[i]) if (!dpadPressed[i])
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(i), NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(i),
ButtonState.RELEASED); ButtonState.RELEASED);
// Press buttons // Press buttons
for (int i = 0; i < pressed.length; i++) for (int i = 0; i < dpadPressed.length; i++)
if (pressed[i]) if (dpadPressed[i])
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(i), NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(i),
ButtonState.PRESSED); ButtonState.PRESSED);
setDpadState(dpad, pressed[0], pressed[1], pressed[2], pressed[3]); setDpadState(dpad, dpadPressed[0], dpadPressed[1], dpadPressed[2], dpadPressed[3]);
dpad.setTrackId(event.getPointerId(pointerIndex));
} }
break; break;
case MotionEvent.ACTION_UP: case MotionEvent.ACTION_UP:
@ -208,6 +218,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(i), NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(i),
ButtonState.RELEASED); ButtonState.RELEASED);
} }
dpad.setTrackId(-1);
} }
break; break;
} }
@ -215,7 +226,11 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
for (InputOverlayDrawableJoystick joystick : overlayJoysticks) for (InputOverlayDrawableJoystick joystick : overlayJoysticks)
{ {
joystick.TrackEvent(event); if (joystick.TrackEvent(event))
{
if (joystick.getTrackId() != -1)
pressed = true;
}
int[] axisIDs = joystick.getAxisIDs(); int[] axisIDs = joystick.getAxisIDs();
float[] axises = joystick.getAxisValues(); 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(); invalidate();
return true; return true;
@ -617,24 +644,30 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT ? getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT ?
"-Portrait" : ""; "-Portrait" : "";
// Add all the enabled overlay items back to the HashSet. if (mPreferences.getBoolean("showInputOverlay", true))
if (EmulationActivity.isGameCubeGame() || mPreferences.getInt("wiiController", 3) == 0)
{ {
addGameCubeOverlayControls(orientation); // Add all the enabled overlay items back to the HashSet.
} if (EmulationActivity.isGameCubeGame() || mPreferences.getInt("wiiController", 3) == 0)
else if (mPreferences.getInt("wiiController", 3) == 4)
{
addClassicOverlayControls(orientation);
}
else
{
addWiimoteOverlayControls(orientation);
if (mPreferences.getInt("wiiController", 3) == 3)
{ {
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(); invalidate();
} }

View File

@ -41,6 +41,7 @@ public final class InputOverlayDrawableButton
public InputOverlayDrawableButton(Resources res, Bitmap defaultStateBitmap, public InputOverlayDrawableButton(Resources res, Bitmap defaultStateBitmap,
Bitmap pressedStateBitmap, int buttonType) Bitmap pressedStateBitmap, int buttonType)
{ {
mTrackId = -1;
mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap); mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap);
mPressedStateBitmap = new BitmapDrawable(res, pressedStateBitmap); mPressedStateBitmap = new BitmapDrawable(res, pressedStateBitmap);
mButtonType = buttonType; mButtonType = buttonType;

View File

@ -60,6 +60,7 @@ public final class InputOverlayDrawableDpad
int buttonUp, int buttonDown, int buttonUp, int buttonDown,
int buttonLeft, int buttonRight) int buttonLeft, int buttonRight)
{ {
mTrackId = -1;
mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap); mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap);
mPressedOneDirectionStateBitmap = new BitmapDrawable(res, pressedOneDirectionStateBitmap); mPressedOneDirectionStateBitmap = new BitmapDrawable(res, pressedOneDirectionStateBitmap);
mPressedTwoDirectionsStateBitmap = new BitmapDrawable(res, pressedTwoDirectionsStateBitmap); mPressedTwoDirectionsStateBitmap = new BitmapDrawable(res, pressedTwoDirectionsStateBitmap);

View File

@ -94,10 +94,11 @@ public final class InputOverlayDrawableJoystick
mBoundsBoxBitmap.draw(canvas); mBoundsBoxBitmap.draw(canvas);
} }
public void TrackEvent(MotionEvent event) public boolean TrackEvent(MotionEvent event)
{ {
boolean reCenter = mPreferences.getBoolean("joystickRelCenter", true); boolean reCenter = mPreferences.getBoolean("joystickRelCenter", true);
int pointerIndex = event.getActionIndex(); int pointerIndex = event.getActionIndex();
boolean pressed = false;
switch (event.getAction() & MotionEvent.ACTION_MASK) switch (event.getAction() & MotionEvent.ACTION_MASK)
{ {
@ -105,7 +106,7 @@ public final class InputOverlayDrawableJoystick
case MotionEvent.ACTION_POINTER_DOWN: case MotionEvent.ACTION_POINTER_DOWN:
if (getBounds().contains((int) event.getX(pointerIndex), (int) event.getY(pointerIndex))) if (getBounds().contains((int) event.getX(pointerIndex), (int) event.getY(pointerIndex)))
{ {
mPressedState = true; mPressedState = pressed = true;
mOuterBitmap.setAlpha(0); mOuterBitmap.setAlpha(0);
mBoundsBoxBitmap.setAlpha(255); mBoundsBoxBitmap.setAlpha(255);
if (reCenter) if (reCenter)
@ -121,6 +122,7 @@ public final class InputOverlayDrawableJoystick
case MotionEvent.ACTION_POINTER_UP: case MotionEvent.ACTION_POINTER_UP:
if (trackId == event.getPointerId(pointerIndex)) if (trackId == event.getPointerId(pointerIndex))
{ {
pressed = true;
mPressedState = false; mPressedState = false;
axises[0] = axises[1] = 0.0f; axises[0] = axises[1] = 0.0f;
mOuterBitmap.setAlpha(255); mOuterBitmap.setAlpha(255);
@ -136,7 +138,7 @@ public final class InputOverlayDrawableJoystick
} }
if (trackId == -1) if (trackId == -1)
return; return pressed;
for (int i = 0; i < event.getPointerCount(); i++) for (int i = 0; i < event.getPointerCount(); i++)
{ {
@ -158,6 +160,7 @@ public final class InputOverlayDrawableJoystick
SetInnerBounds(); SetInnerBounds();
} }
} }
return pressed;
} }
public boolean onConfigureTouch(MotionEvent event) public boolean onConfigureTouch(MotionEvent event)
@ -274,4 +277,9 @@ public final class InputOverlayDrawableJoystick
{ {
return mHeight; return mHeight;
} }
public int getTrackId()
{
return trackId;
}
} }

View File

@ -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;
}
}

View File

@ -30,6 +30,7 @@ private:
{ {
public: public:
std::string GetName() const; std::string GetName() const;
bool IsDetectable() override { return false; }
Axis(int padID, ButtonManager::ButtonType index, float neg = 1.0f) Axis(int padID, ButtonManager::ButtonType index, float neg = 1.0f)
: _padID(padID), _index(index), _neg(neg) : _padID(padID), _index(index), _neg(neg)
{ {