Skip to content

Commit

Permalink
android: Clean up overlay controls and avoid triggering touch screen …
Browse files Browse the repository at this point in the history
…when a button is pressed (#6391)
  • Loading branch information
german77 authored Apr 9, 2023
1 parent bc5b065 commit 90bcf49
Show file tree
Hide file tree
Showing 4 changed files with 382 additions and 348 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -342,180 +342,91 @@ public boolean onTouch(View v, MotionEvent event) {
if (isInEditMode()) {
return onTouchWhileEditing(event);
}
boolean shouldUpdateView = false;
for (InputOverlayDrawableButton button : overlayButtons) {
if (!button.updateStatus(event)) {
continue;
}
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(), button.getStatus());
shouldUpdateView = true;
}

int pointerIndex = event.getActionIndex();
for (InputOverlayDrawableDpad dpad : overlayDpads) {
if (!dpad.updateStatus(event, EmulationMenuSettings.getDpadSlideEnable())) {
continue;
}
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getUpId(), dpad.getUpStatus());
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getDownId(), dpad.getDownStatus());
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getLeftId(), dpad.getLeftStatus());
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getRightId(), dpad.getRightStatus());
shouldUpdateView = true;
}

if (mPreferences.getBoolean("isTouchEnabled", true)) {
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
if (NativeLibrary.onTouchEvent(event.getX(pointerIndex), event.getY(pointerIndex), true)) {
mTouchscreenPointerId = event.getPointerId(pointerIndex);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
if (mTouchscreenPointerId == event.getPointerId(pointerIndex)) {
// We don't really care where the touch has been released. We only care whether it has been
// released or not.
NativeLibrary.onTouchEvent(0, 0, false);
mTouchscreenPointerId = -1;
}
break;
for (InputOverlayDrawableJoystick joystick : overlayJoysticks) {
if (!joystick.updateStatus(event)) {
continue;
}
int axisID = joystick.getJoystickId();
NativeLibrary
.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, axisID, joystick.getXAxis(), joystick.getYAxis());
shouldUpdateView = true;
}

if (shouldUpdateView) {
invalidate();
}

if (!mPreferences.getBoolean("isTouchEnabled", true)) {
return true;
}

int pointerIndex = event.getActionIndex();
int xPosition = (int) event.getX(pointerIndex);
int yPosition = (int) event.getY(pointerIndex);
int pointerId = event.getPointerId(pointerIndex);
int motionEvent = event.getAction() & MotionEvent.ACTION_MASK;
boolean isActionDown = motionEvent == MotionEvent.ACTION_DOWN || motionEvent == MotionEvent.ACTION_POINTER_DOWN;
boolean isActionMove = motionEvent == MotionEvent.ACTION_MOVE;
boolean isActionUp = motionEvent == MotionEvent.ACTION_UP || motionEvent == MotionEvent.ACTION_POINTER_UP;

if (isActionDown && !isTouchInputConsumed(pointerId)) {
NativeLibrary.onTouchEvent(xPosition, yPosition, true);
}

if (isActionMove) {
for (int i = 0; i < event.getPointerCount(); i++) {
if (mTouchscreenPointerId == event.getPointerId(i)) {
NativeLibrary.onTouchMoved(event.getX(i), event.getY(i));
int fingerId = event.getPointerId(i);
if (isTouchInputConsumed(fingerId)) {
continue;
}
NativeLibrary.onTouchMoved(xPosition, yPosition);
}
}

if (isActionUp && !isTouchInputConsumed(pointerId)) {
NativeLibrary.onTouchEvent(0, 0, false);
}

return true;
}

private boolean isTouchInputConsumed(int trackId) {
for (InputOverlayDrawableButton button : overlayButtons) {
// Determine the button state to apply based on the MotionEvent action flag.
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
// If a pointer enters the bounds of a button, press that button.
if (button.getBounds()
.contains((int) event.getX(pointerIndex), (int) event.getY(pointerIndex))) {
button.setPressedState(true);
button.setTrackId(event.getPointerId(pointerIndex));
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(),
ButtonState.PRESSED);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
// If a pointer ends, release the button it was pressing.
if (button.getTrackId() == event.getPointerId(pointerIndex)) {
button.setPressedState(false);
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(),
ButtonState.RELEASED);
}
break;
if (button.getTrackId() == trackId) {
return true;
}
}

for (InputOverlayDrawableDpad dpad : overlayDpads) {
// Determine the button state to apply based on the MotionEvent action flag.
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
// 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));
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
// If a pointer ends, release the buttons.
if (dpad.getTrackId() == event.getPointerId(pointerIndex)) {
for (int i = 0; i < 4; i++) {
dpad.setState(InputOverlayDrawableDpad.STATE_DEFAULT);
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(i),
NativeLibrary.ButtonState.RELEASED);
}
dpad.setTrackId(-1);
}
break;
}

if (dpad.getTrackId() != -1) {
for (int i = 0; i < event.getPointerCount(); i++) {
if (dpad.getTrackId() == event.getPointerId(i)) {
float touchX = event.getX(i);
float touchY = event.getY(i);
float maxY = dpad.getBounds().bottom;
float maxX = dpad.getBounds().right;
touchX -= dpad.getBounds().centerX();
maxX -= dpad.getBounds().centerX();
touchY -= dpad.getBounds().centerY();
maxY -= dpad.getBounds().centerY();
final float AxisX = touchX / maxX;
final float AxisY = touchY / maxY;

boolean up = false;
boolean down = false;
boolean left = false;
boolean right = false;
if (EmulationMenuSettings.getDpadSlideEnable() ||
(event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN ||
(event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN) {
if (AxisY < -InputOverlayDrawableDpad.VIRT_AXIS_DEADZONE) {
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(0),
NativeLibrary.ButtonState.PRESSED);
up = true;
} else {
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(0),
NativeLibrary.ButtonState.RELEASED);
}
if (AxisY > InputOverlayDrawableDpad.VIRT_AXIS_DEADZONE) {
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(1),
NativeLibrary.ButtonState.PRESSED);
down = true;
} else {
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(1),
NativeLibrary.ButtonState.RELEASED);
}
if (AxisX < -InputOverlayDrawableDpad.VIRT_AXIS_DEADZONE) {
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(2),
NativeLibrary.ButtonState.PRESSED);
left = true;
} else {
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(2),
NativeLibrary.ButtonState.RELEASED);
}
if (AxisX > InputOverlayDrawableDpad.VIRT_AXIS_DEADZONE) {
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(3),
NativeLibrary.ButtonState.PRESSED);
right = true;
} else {
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(3),
NativeLibrary.ButtonState.RELEASED);
}

// Set state
if (up) {
if (left)
dpad.setState(InputOverlayDrawableDpad.STATE_PRESSED_UP_LEFT);
else if (right)
dpad.setState(InputOverlayDrawableDpad.STATE_PRESSED_UP_RIGHT);
else
dpad.setState(InputOverlayDrawableDpad.STATE_PRESSED_UP);
} else if (down) {
if (left)
dpad.setState(InputOverlayDrawableDpad.STATE_PRESSED_DOWN_LEFT);
else if (right)
dpad.setState(InputOverlayDrawableDpad.STATE_PRESSED_DOWN_RIGHT);
else
dpad.setState(InputOverlayDrawableDpad.STATE_PRESSED_DOWN);
} else if (left) {
dpad.setState(InputOverlayDrawableDpad.STATE_PRESSED_LEFT);
} else if (right) {
dpad.setState(InputOverlayDrawableDpad.STATE_PRESSED_RIGHT);
} else {
dpad.setState(InputOverlayDrawableDpad.STATE_DEFAULT);
}
}
}
}
if (dpad.getTrackId() == trackId) {
return true;
}
}

for (InputOverlayDrawableJoystick joystick : overlayJoysticks) {
joystick.TrackEvent(event);
int axisID = joystick.getId();
float[] axises = joystick.getAxisValues();

NativeLibrary
.onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, axisID, axises[0], axises[1]);
if (joystick.getTrackId() == trackId) {
return true;
}
}

invalidate();

return true;
return false;
}

public boolean onTouchWhileEditing(MotionEvent event) {
Expand Down Expand Up @@ -587,7 +498,7 @@ public boolean onTouchWhileEditing(MotionEvent event) {
case MotionEvent.ACTION_POINTER_UP:
if (mDpadBeingConfigured == dpad) {
// Persist button position by saving new place.
saveControlPosition(mDpadBeingConfigured.getId(0),
saveControlPosition(mDpadBeingConfigured.getUpId(),
mDpadBeingConfigured.getBounds().left, mDpadBeingConfigured.getBounds().top,
orientation);
mDpadBeingConfigured = null;
Expand Down Expand Up @@ -615,7 +526,7 @@ public boolean onTouchWhileEditing(MotionEvent event) {
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
if (mJoystickBeingConfigured != null) {
saveControlPosition(mJoystickBeingConfigured.getId(),
saveControlPosition(mJoystickBeingConfigured.getJoystickId(),
mJoystickBeingConfigured.getBounds().left,
mJoystickBeingConfigured.getBounds().top, orientation);
mJoystickBeingConfigured = null;
Expand All @@ -627,29 +538,6 @@ public boolean onTouchWhileEditing(MotionEvent event) {
return true;
}

private void setDpadState(InputOverlayDrawableDpad dpad, boolean up, boolean down, boolean left,
boolean right) {
if (up) {
if (left)
dpad.setState(InputOverlayDrawableDpad.STATE_PRESSED_UP_LEFT);
else if (right)
dpad.setState(InputOverlayDrawableDpad.STATE_PRESSED_UP_RIGHT);
else
dpad.setState(InputOverlayDrawableDpad.STATE_PRESSED_UP);
} else if (down) {
if (left)
dpad.setState(InputOverlayDrawableDpad.STATE_PRESSED_DOWN_LEFT);
else if (right)
dpad.setState(InputOverlayDrawableDpad.STATE_PRESSED_DOWN_RIGHT);
else
dpad.setState(InputOverlayDrawableDpad.STATE_PRESSED_DOWN);
} else if (left) {
dpad.setState(InputOverlayDrawableDpad.STATE_PRESSED_LEFT);
} else if (right) {
dpad.setState(InputOverlayDrawableDpad.STATE_PRESSED_RIGHT);
}
}

private void addOverlayControls(String orientation) {
if (mPreferences.getBoolean("buttonToggle0", true)) {
overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.button_a,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import android.graphics.drawable.BitmapDrawable;
import android.view.MotionEvent;

import org.citra.citra_emu.NativeLibrary;

/**
* Custom {@link BitmapDrawable} that is capable
* of storing it's own ID.
Expand Down Expand Up @@ -42,26 +44,45 @@ public InputOverlayDrawableButton(Resources res, Bitmap defaultStateBitmap,
mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap);
mPressedStateBitmap = new BitmapDrawable(res, pressedStateBitmap);
mButtonType = buttonType;
mTrackId = -1;

mWidth = mDefaultStateBitmap.getIntrinsicWidth();
mHeight = mDefaultStateBitmap.getIntrinsicHeight();
}

/**
* Gets this InputOverlayDrawableButton's button ID.
* Updates button status based on the motion event.
*
* @return this InputOverlayDrawableButton's button ID.
* @return true if value was changed
*/
public int getId() {
return mButtonType;
}
public boolean updateStatus(MotionEvent event) {
int pointerIndex = event.getActionIndex();
int xPosition = (int) event.getX(pointerIndex);
int yPosition = (int) event.getY(pointerIndex);
int pointerId = event.getPointerId(pointerIndex);
int motionEvent = event.getAction() & MotionEvent.ACTION_MASK;
boolean isActionDown = motionEvent == MotionEvent.ACTION_DOWN || motionEvent == MotionEvent.ACTION_POINTER_DOWN;
boolean isActionUp = motionEvent == MotionEvent.ACTION_UP || motionEvent == MotionEvent.ACTION_POINTER_UP;

if (isActionDown) {
if (!getBounds().contains(xPosition, yPosition)) {
return false;
}
mPressedState = true;
mTrackId = pointerId;
return true;
}

public int getTrackId() {
return mTrackId;
}
if (isActionUp) {
if (mTrackId != pointerId) {
return false;
}
mPressedState = false;
mTrackId = -1;
return true;
}

public void setTrackId(int trackId) {
mTrackId = trackId;
return false;
}

public boolean onConfigureTouch(MotionEvent event) {
Expand Down Expand Up @@ -104,6 +125,22 @@ public void setBounds(int left, int top, int right, int bottom) {
mPressedStateBitmap.setBounds(left, top, right, bottom);
}

public int getId() {
return mButtonType;
}

public int getTrackId() {
return mTrackId;
}

public void setTrackId(int trackId) {
mTrackId = trackId;
}

public int getStatus() {
return mPressedState ? NativeLibrary.ButtonState.PRESSED : NativeLibrary.ButtonState.RELEASED;
}

public Rect getBounds() {
return mDefaultStateBitmap.getBounds();
}
Expand Down
Loading

0 comments on commit 90bcf49

Please sign in to comment.