mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	android: Clean up overlay controls and avoid triggering touch screen when a button is pressed (#6391)
This commit is contained in:
		
							parent
							
								
									bc5b065abe
								
							
						
					
					
						commit
						90bcf49db0
					
				
					 4 changed files with 386 additions and 352 deletions
				
			
		|  | @ -342,182 +342,93 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener { | |||
|         if (isInEditMode()) { | ||||
|             return onTouchWhileEditing(event); | ||||
|         } | ||||
| 
 | ||||
|         int pointerIndex = event.getActionIndex(); | ||||
| 
 | ||||
|         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 (int i = 0; i < event.getPointerCount(); i++) { | ||||
|                 if (mTouchscreenPointerId == event.getPointerId(i)) { | ||||
|                     NativeLibrary.onTouchMoved(event.getX(i), event.getY(i)); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         boolean shouldUpdateView = false; | ||||
|         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.updateStatus(event)) { | ||||
|                 continue; | ||||
|             } | ||||
|             NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(), button.getStatus()); | ||||
|             shouldUpdateView = 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.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; | ||||
|         } | ||||
| 
 | ||||
|         for (InputOverlayDrawableJoystick joystick : overlayJoysticks) { | ||||
|             joystick.TrackEvent(event); | ||||
|             int axisID = joystick.getId(); | ||||
|             float[] axises = joystick.getAxisValues(); | ||||
| 
 | ||||
|             if (!joystick.updateStatus(event)) { | ||||
|                 continue; | ||||
|             } | ||||
|             int axisID = joystick.getJoystickId(); | ||||
|             NativeLibrary | ||||
|                     .onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, axisID, axises[0], axises[1]); | ||||
|                     .onGamePadMoveEvent(NativeLibrary.TouchScreenDevice, axisID, joystick.getXAxis(), joystick.getYAxis()); | ||||
|             shouldUpdateView = true; | ||||
|         } | ||||
| 
 | ||||
|         invalidate(); | ||||
|         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++) { | ||||
|                 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) { | ||||
|             if (button.getTrackId() == trackId) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|         for (InputOverlayDrawableDpad dpad : overlayDpads) { | ||||
|             if (dpad.getTrackId() == trackId) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|         for (InputOverlayDrawableJoystick joystick : overlayJoysticks) { | ||||
|             if (joystick.getTrackId() == trackId) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     public boolean onTouchWhileEditing(MotionEvent event) { | ||||
|         int pointerIndex = event.getActionIndex(); | ||||
|         int fingerPositionX = (int) event.getX(pointerIndex); | ||||
|  | @ -587,7 +498,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener { | |||
|                 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; | ||||
|  | @ -615,7 +526,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener { | |||
|                 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; | ||||
|  | @ -627,29 +538,6 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener { | |||
|         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, | ||||
|  |  | |||
|  | @ -13,6 +13,8 @@ import android.graphics.Rect; | |||
| 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. | ||||
|  | @ -42,26 +44,45 @@ public final class InputOverlayDrawableButton { | |||
|         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; | ||||
| 
 | ||||
|     public int getTrackId() { | ||||
|         return mTrackId; | ||||
|     } | ||||
|         if (isActionDown) { | ||||
|             if (!getBounds().contains(xPosition, yPosition)) { | ||||
|                 return false; | ||||
|             } | ||||
|             mPressedState = true; | ||||
|             mTrackId = pointerId; | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|     public void setTrackId(int trackId) { | ||||
|         mTrackId = trackId; | ||||
|         if (isActionUp) { | ||||
|             if (mTrackId != pointerId) { | ||||
|                 return false; | ||||
|             } | ||||
|             mPressedState = false; | ||||
|             mTrackId = -1; | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     public boolean onConfigureTouch(MotionEvent event) { | ||||
|  | @ -104,6 +125,22 @@ public final class InputOverlayDrawableButton { | |||
|         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(); | ||||
|     } | ||||
|  |  | |||
|  | @ -13,23 +13,19 @@ import android.graphics.Rect; | |||
| 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. | ||||
|  */ | ||||
| public final class InputOverlayDrawableDpad { | ||||
|     public static final int STATE_DEFAULT = 0; | ||||
|     public static final int STATE_PRESSED_UP = 1; | ||||
|     public static final int STATE_PRESSED_DOWN = 2; | ||||
|     public static final int STATE_PRESSED_LEFT = 3; | ||||
|     public static final int STATE_PRESSED_RIGHT = 4; | ||||
|     public static final int STATE_PRESSED_UP_LEFT = 5; | ||||
|     public static final int STATE_PRESSED_UP_RIGHT = 6; | ||||
|     public static final int STATE_PRESSED_DOWN_LEFT = 7; | ||||
|     public static final int STATE_PRESSED_DOWN_RIGHT = 8; | ||||
|     public static final float VIRT_AXIS_DEADZONE = 0.5f; | ||||
|     // The ID identifying what type of button this Drawable represents. | ||||
|     private int[] mButtonType = new int[4]; | ||||
|     private int mUpButtonId; | ||||
|     private int mDownButtonId; | ||||
|     private int mLeftButtonId; | ||||
|     private int mRightButtonId; | ||||
|     private int mTrackId; | ||||
|     private int mPreviousTouchX, mPreviousTouchY; | ||||
|     private int mControlPositionX, mControlPositionY; | ||||
|  | @ -38,7 +34,10 @@ public final class InputOverlayDrawableDpad { | |||
|     private BitmapDrawable mDefaultStateBitmap; | ||||
|     private BitmapDrawable mPressedOneDirectionStateBitmap; | ||||
|     private BitmapDrawable mPressedTwoDirectionsStateBitmap; | ||||
|     private int mPressState = STATE_DEFAULT; | ||||
|     private boolean mUpButtonState; | ||||
|     private boolean mDownButtonState; | ||||
|     private boolean mLeftButtonState; | ||||
|     private boolean mRightButtonState; | ||||
| 
 | ||||
|     /** | ||||
|      * Constructor | ||||
|  | @ -65,73 +64,167 @@ public final class InputOverlayDrawableDpad { | |||
|         mWidth = mDefaultStateBitmap.getIntrinsicWidth(); | ||||
|         mHeight = mDefaultStateBitmap.getIntrinsicHeight(); | ||||
| 
 | ||||
|         mButtonType[0] = buttonUp; | ||||
|         mButtonType[1] = buttonDown; | ||||
|         mButtonType[2] = buttonLeft; | ||||
|         mButtonType[3] = buttonRight; | ||||
|         mUpButtonId = buttonUp; | ||||
|         mDownButtonId = buttonDown; | ||||
|         mLeftButtonId = buttonLeft; | ||||
|         mRightButtonId = buttonRight; | ||||
| 
 | ||||
|         mTrackId = -1; | ||||
|     } | ||||
| 
 | ||||
|     public boolean updateStatus(MotionEvent event, boolean dpadSlide) { | ||||
|         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; | ||||
|             } | ||||
|             mTrackId = pointerId; | ||||
|         } | ||||
| 
 | ||||
|         if (isActionUp) { | ||||
|             if (mTrackId != pointerId) { | ||||
|                 return false; | ||||
|             } | ||||
|             mTrackId = -1; | ||||
|             mUpButtonState = false; | ||||
|             mDownButtonState = false; | ||||
|             mLeftButtonState = false; | ||||
|             mRightButtonState = false; | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         if (mTrackId == -1) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         if (!dpadSlide && !isActionDown) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         for (int i = 0; i < event.getPointerCount(); i++) { | ||||
|             if (mTrackId != event.getPointerId(i)) { | ||||
|                 continue; | ||||
|             } | ||||
|             float touchX = event.getX(i); | ||||
|             float touchY = event.getY(i); | ||||
|             float maxY = getBounds().bottom; | ||||
|             float maxX = getBounds().right; | ||||
|             touchX -= getBounds().centerX(); | ||||
|             maxX -= getBounds().centerX(); | ||||
|             touchY -= getBounds().centerY(); | ||||
|             maxY -= getBounds().centerY(); | ||||
|             final float AxisX = touchX / maxX; | ||||
|             final float AxisY = touchY / maxY; | ||||
|             final boolean upState = mUpButtonState; | ||||
|             final boolean downState = mDownButtonState; | ||||
|             final boolean leftState = mLeftButtonState; | ||||
|             final boolean rightState = mRightButtonState; | ||||
| 
 | ||||
|             mUpButtonState = AxisY < -InputOverlayDrawableDpad.VIRT_AXIS_DEADZONE; | ||||
|             mDownButtonState = AxisY > InputOverlayDrawableDpad.VIRT_AXIS_DEADZONE; | ||||
|             mLeftButtonState = AxisX < -InputOverlayDrawableDpad.VIRT_AXIS_DEADZONE; | ||||
|             mRightButtonState = AxisX > InputOverlayDrawableDpad.VIRT_AXIS_DEADZONE; | ||||
|             return upState != mUpButtonState || downState != mDownButtonState || leftState != mLeftButtonState || rightState != mRightButtonState; | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     public void draw(Canvas canvas) { | ||||
|         int px = mControlPositionX + (getWidth() / 2); | ||||
|         int py = mControlPositionY + (getHeight() / 2); | ||||
|         switch (mPressState) { | ||||
|             case STATE_DEFAULT: | ||||
|                 mDefaultStateBitmap.draw(canvas); | ||||
|                 break; | ||||
|             case STATE_PRESSED_UP: | ||||
|                 mPressedOneDirectionStateBitmap.draw(canvas); | ||||
|                 break; | ||||
|             case STATE_PRESSED_RIGHT: | ||||
|                 canvas.save(); | ||||
|                 canvas.rotate(90, px, py); | ||||
|                 mPressedOneDirectionStateBitmap.draw(canvas); | ||||
|                 canvas.restore(); | ||||
|                 break; | ||||
|             case STATE_PRESSED_DOWN: | ||||
|                 canvas.save(); | ||||
|                 canvas.rotate(180, px, py); | ||||
|                 mPressedOneDirectionStateBitmap.draw(canvas); | ||||
|                 canvas.restore(); | ||||
|                 break; | ||||
|             case STATE_PRESSED_LEFT: | ||||
|                 canvas.save(); | ||||
|                 canvas.rotate(270, px, py); | ||||
|                 mPressedOneDirectionStateBitmap.draw(canvas); | ||||
|                 canvas.restore(); | ||||
|                 break; | ||||
|             case STATE_PRESSED_UP_LEFT: | ||||
|                 mPressedTwoDirectionsStateBitmap.draw(canvas); | ||||
|                 break; | ||||
|             case STATE_PRESSED_UP_RIGHT: | ||||
|                 canvas.save(); | ||||
|                 canvas.rotate(90, px, py); | ||||
|                 mPressedTwoDirectionsStateBitmap.draw(canvas); | ||||
|                 canvas.restore(); | ||||
|                 break; | ||||
|             case STATE_PRESSED_DOWN_RIGHT: | ||||
|                 canvas.save(); | ||||
|                 canvas.rotate(180, px, py); | ||||
|                 mPressedTwoDirectionsStateBitmap.draw(canvas); | ||||
|                 canvas.restore(); | ||||
|                 break; | ||||
|             case STATE_PRESSED_DOWN_LEFT: | ||||
|                 canvas.save(); | ||||
|                 canvas.rotate(270, px, py); | ||||
|                 mPressedTwoDirectionsStateBitmap.draw(canvas); | ||||
|                 canvas.restore(); | ||||
|                 break; | ||||
| 
 | ||||
|         // Pressed up | ||||
|         if (mUpButtonState && !mLeftButtonState && !mRightButtonState) { | ||||
|             mPressedOneDirectionStateBitmap.draw(canvas); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Pressed down | ||||
|         if (mDownButtonState && !mLeftButtonState && !mRightButtonState) { | ||||
|             canvas.save(); | ||||
|             canvas.rotate(180, px, py); | ||||
|             mPressedOneDirectionStateBitmap.draw(canvas); | ||||
|             canvas.restore(); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Pressed left | ||||
|         if (mLeftButtonState && !mUpButtonState && !mDownButtonState) { | ||||
|             canvas.save(); | ||||
|             canvas.rotate(270, px, py); | ||||
|             mPressedOneDirectionStateBitmap.draw(canvas); | ||||
|             canvas.restore(); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Pressed right | ||||
|         if (mRightButtonState && !mUpButtonState && !mDownButtonState) { | ||||
|             canvas.save(); | ||||
|             canvas.rotate(90, px, py); | ||||
|             mPressedOneDirectionStateBitmap.draw(canvas); | ||||
|             canvas.restore(); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Pressed up left | ||||
|         if (mUpButtonState && mLeftButtonState && !mRightButtonState) { | ||||
|             mPressedTwoDirectionsStateBitmap.draw(canvas); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Pressed up right | ||||
|         if (mUpButtonState && !mLeftButtonState && mRightButtonState) { | ||||
|             canvas.save(); | ||||
|             canvas.rotate(90, px, py); | ||||
|             mPressedTwoDirectionsStateBitmap.draw(canvas); | ||||
|             canvas.restore(); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Pressed down left | ||||
|         if (mDownButtonState && mLeftButtonState && !mRightButtonState) { | ||||
|             canvas.save(); | ||||
|             canvas.rotate(270, px, py); | ||||
|             mPressedTwoDirectionsStateBitmap.draw(canvas); | ||||
|             canvas.restore(); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Pressed down right | ||||
|         if (mDownButtonState && !mLeftButtonState && mRightButtonState) { | ||||
|             canvas.save(); | ||||
|             canvas.rotate(180, px, py); | ||||
|             mPressedTwoDirectionsStateBitmap.draw(canvas); | ||||
|             canvas.restore(); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         // Not pressed | ||||
|         mDefaultStateBitmap.draw(canvas); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets one of the InputOverlayDrawableDpad's button IDs. | ||||
|      * | ||||
|      * @return the requested InputOverlayDrawableDpad's button ID. | ||||
|      */ | ||||
|     public int getId(int direction) { | ||||
|         return mButtonType[direction]; | ||||
|     public int getUpId() { | ||||
|         return mUpButtonId; | ||||
|     } | ||||
| 
 | ||||
|     public int getDownId() { | ||||
|         return mDownButtonId; | ||||
|     } | ||||
| 
 | ||||
|     public int getLeftId() { | ||||
|         return mLeftButtonId; | ||||
|     } | ||||
| 
 | ||||
|     public int getRightId() { | ||||
|         return mRightButtonId; | ||||
|     } | ||||
| 
 | ||||
|     public int getTrackId() { | ||||
|  | @ -142,6 +235,22 @@ public final class InputOverlayDrawableDpad { | |||
|         mTrackId = trackId; | ||||
|     } | ||||
| 
 | ||||
|     public int getUpStatus() { | ||||
|         return mUpButtonState ? NativeLibrary.ButtonState.PRESSED : NativeLibrary.ButtonState.RELEASED; | ||||
|     } | ||||
| 
 | ||||
|     public int getDownStatus() { | ||||
|         return mDownButtonState ? NativeLibrary.ButtonState.PRESSED : NativeLibrary.ButtonState.RELEASED; | ||||
|     } | ||||
| 
 | ||||
|     public int getLeftStatus() { | ||||
|         return mLeftButtonState ? NativeLibrary.ButtonState.PRESSED : NativeLibrary.ButtonState.RELEASED; | ||||
|     } | ||||
| 
 | ||||
|     public int getRightStatus() { | ||||
|         return mRightButtonState ? NativeLibrary.ButtonState.PRESSED : NativeLibrary.ButtonState.RELEASED; | ||||
|     } | ||||
| 
 | ||||
|     public boolean onConfigureTouch(MotionEvent event) { | ||||
|         int pointerIndex = event.getActionIndex(); | ||||
|         int fingerPositionX = (int) event.getX(pointerIndex); | ||||
|  | @ -187,7 +296,4 @@ public final class InputOverlayDrawableDpad { | |||
|         return mHeight; | ||||
|     } | ||||
| 
 | ||||
|     public void setState(int pressState) { | ||||
|         mPressState = pressState; | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -21,10 +21,12 @@ import org.citra.citra_emu.utils.EmulationMenuSettings; | |||
|  * of storing it's own ID. | ||||
|  */ | ||||
| public final class InputOverlayDrawableJoystick { | ||||
|     private final int[] axisIDs = {0, 0, 0, 0}; | ||||
|     private final float[] axises = {0f, 0f}; | ||||
|     private int trackId = -1; | ||||
|     private int mJoystickType; | ||||
|     // The ID value what type of joystick this Drawable represents. | ||||
|     private int mJoystickId; | ||||
|     // The ID value what motion event is tracking | ||||
|     private int mTrackId = -1; | ||||
|     private float mXAxis; | ||||
|     private float mYAxis; | ||||
|     private int mControlPositionX, mControlPositionY; | ||||
|     private int mPreviousTouchX, mPreviousTouchY; | ||||
|     private int mWidth; | ||||
|  | @ -51,11 +53,7 @@ public final class InputOverlayDrawableJoystick { | |||
|     public InputOverlayDrawableJoystick(Resources res, Bitmap bitmapOuter, | ||||
|                                         Bitmap bitmapInnerDefault, Bitmap bitmapInnerPressed, | ||||
|                                         Rect rectOuter, Rect rectInner, int joystick) { | ||||
|         axisIDs[0] = joystick + 1; // Up | ||||
|         axisIDs[1] = joystick + 2; // Down | ||||
|         axisIDs[2] = joystick + 3; // Left | ||||
|         axisIDs[3] = joystick + 4; // Right | ||||
|         mJoystickType = joystick; | ||||
|         mJoystickId = joystick; | ||||
| 
 | ||||
|         mOuterBitmap = new BitmapDrawable(res, bitmapOuter); | ||||
|         mDefaultStateInnerBitmap = new BitmapDrawable(res, bitmapInnerDefault); | ||||
|  | @ -74,84 +72,87 @@ public final class InputOverlayDrawableJoystick { | |||
|         SetInnerBounds(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets this InputOverlayDrawableJoystick's button ID. | ||||
|      * | ||||
|      * @return this InputOverlayDrawableJoystick's button ID. | ||||
|      */ | ||||
|     public int getId() { | ||||
|         return mJoystickType; | ||||
|     } | ||||
| 
 | ||||
|     public void draw(Canvas canvas) { | ||||
|         mOuterBitmap.draw(canvas); | ||||
|         getCurrentStateBitmapDrawable().draw(canvas); | ||||
|         mBoundsBoxBitmap.draw(canvas); | ||||
|     } | ||||
| 
 | ||||
|     public void TrackEvent(MotionEvent event) { | ||||
|     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; | ||||
| 
 | ||||
|         switch (event.getAction() & MotionEvent.ACTION_MASK) { | ||||
|             case MotionEvent.ACTION_DOWN: | ||||
|             case MotionEvent.ACTION_POINTER_DOWN: | ||||
|                 if (getBounds().contains((int) event.getX(pointerIndex), (int) event.getY(pointerIndex))) { | ||||
|                     mPressedState = true; | ||||
|                     mOuterBitmap.setAlpha(0); | ||||
|                     mBoundsBoxBitmap.setAlpha(255); | ||||
|                     if (EmulationMenuSettings.getJoystickRelCenter()) { | ||||
|                         getVirtBounds().offset((int) event.getX(pointerIndex) - getVirtBounds().centerX(), | ||||
|                                 (int) event.getY(pointerIndex) - getVirtBounds().centerY()); | ||||
|                     } | ||||
|                     mBoundsBoxBitmap.setBounds(getVirtBounds()); | ||||
|                     trackId = event.getPointerId(pointerIndex); | ||||
|                 } | ||||
|                 break; | ||||
|             case MotionEvent.ACTION_UP: | ||||
|             case MotionEvent.ACTION_POINTER_UP: | ||||
|                 if (trackId == event.getPointerId(pointerIndex)) { | ||||
|                     mPressedState = false; | ||||
|                     axises[0] = axises[1] = 0.0f; | ||||
|                     mOuterBitmap.setAlpha(255); | ||||
|                     mBoundsBoxBitmap.setAlpha(0); | ||||
|                     setVirtBounds(new Rect(mOrigBounds.left, mOrigBounds.top, mOrigBounds.right, | ||||
|                             mOrigBounds.bottom)); | ||||
|                     setBounds(new Rect(mOrigBounds.left, mOrigBounds.top, mOrigBounds.right, | ||||
|                             mOrigBounds.bottom)); | ||||
|                     SetInnerBounds(); | ||||
|                     trackId = -1; | ||||
|                 } | ||||
|                 break; | ||||
|         if (isActionDown) { | ||||
|             if (!getBounds().contains(xPosition, yPosition)) { | ||||
|                 return false; | ||||
|             } | ||||
|             mPressedState = true; | ||||
|             mOuterBitmap.setAlpha(0); | ||||
|             mBoundsBoxBitmap.setAlpha(255); | ||||
|             if (EmulationMenuSettings.getJoystickRelCenter()) { | ||||
|                 getVirtBounds().offset(xPosition - getVirtBounds().centerX(), | ||||
|                         yPosition - getVirtBounds().centerY()); | ||||
|             } | ||||
|             mBoundsBoxBitmap.setBounds(getVirtBounds()); | ||||
|             mTrackId = pointerId; | ||||
|         } | ||||
| 
 | ||||
|         if (trackId == -1) | ||||
|             return; | ||||
|         if (isActionUp) { | ||||
|             if (mTrackId != pointerId) { | ||||
|                 return false; | ||||
|             } | ||||
|             mPressedState = false; | ||||
|             mXAxis = 0.0f; | ||||
|             mYAxis = 0.0f; | ||||
|             mOuterBitmap.setAlpha(255); | ||||
|             mBoundsBoxBitmap.setAlpha(0); | ||||
|             setVirtBounds(new Rect(mOrigBounds.left, mOrigBounds.top, mOrigBounds.right, | ||||
|                     mOrigBounds.bottom)); | ||||
|             setBounds(new Rect(mOrigBounds.left, mOrigBounds.top, mOrigBounds.right, | ||||
|                     mOrigBounds.bottom)); | ||||
|             SetInnerBounds(); | ||||
|             mTrackId = -1; | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         if (mTrackId == -1) | ||||
|             return false; | ||||
| 
 | ||||
|         for (int i = 0; i < event.getPointerCount(); i++) { | ||||
|             if (trackId == event.getPointerId(i)) { | ||||
|                 float touchX = event.getX(i); | ||||
|                 float touchY = event.getY(i); | ||||
|                 float maxY = getVirtBounds().bottom; | ||||
|                 float maxX = getVirtBounds().right; | ||||
|                 touchX -= getVirtBounds().centerX(); | ||||
|                 maxX -= getVirtBounds().centerX(); | ||||
|                 touchY -= getVirtBounds().centerY(); | ||||
|                 maxY -= getVirtBounds().centerY(); | ||||
|                 final float AxisX = touchX / maxX; | ||||
|                 final float AxisY = touchY / maxY; | ||||
| 
 | ||||
|                 // Clamp the circle pad input to a circle | ||||
|                 final float angle = (float) Math.atan2(AxisY, AxisX); | ||||
|                 float radius = (float) Math.sqrt(AxisX * AxisX + AxisY * AxisY); | ||||
|                 if(radius > 1.0f) | ||||
|                 { | ||||
|                     radius = 1.0f; | ||||
|                 } | ||||
|                 axises[0] = ((float)Math.cos(angle) * radius); | ||||
|                 axises[1] = ((float)Math.sin(angle) * radius); | ||||
|                 SetInnerBounds(); | ||||
|             if (mTrackId != event.getPointerId(i)) { | ||||
|                 continue; | ||||
|             } | ||||
|             float touchX = event.getX(i); | ||||
|             float touchY = event.getY(i); | ||||
|             float maxY = getVirtBounds().bottom; | ||||
|             float maxX = getVirtBounds().right; | ||||
|             touchX -= getVirtBounds().centerX(); | ||||
|             maxX -= getVirtBounds().centerX(); | ||||
|             touchY -= getVirtBounds().centerY(); | ||||
|             maxY -= getVirtBounds().centerY(); | ||||
|             final float AxisX = touchX / maxX; | ||||
|             final float AxisY = touchY / maxY; | ||||
|             final float oldXAxis = mXAxis; | ||||
|             final float oldYAxis = mYAxis; | ||||
| 
 | ||||
|             // Clamp the circle pad input to a circle | ||||
|             final float angle = (float) Math.atan2(AxisY, AxisX); | ||||
|             float radius = (float) Math.sqrt(AxisX * AxisX + AxisY * AxisY); | ||||
|             if (radius > 1.0f) { | ||||
|                 radius = 1.0f; | ||||
|             } | ||||
|             mXAxis = ((float) Math.cos(angle) * radius); | ||||
|             mYAxis = ((float) Math.sin(angle) * radius); | ||||
|             SetInnerBounds(); | ||||
|             return oldXAxis != mXAxis && oldYAxis != mYAxis; | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     public boolean onConfigureTouch(MotionEvent event) { | ||||
|  | @ -160,7 +161,7 @@ public final class InputOverlayDrawableJoystick { | |||
|         int fingerPositionY = (int) event.getY(pointerIndex); | ||||
| 
 | ||||
|         int scale = 1; | ||||
|         if (mJoystickType == ButtonType.STICK_C) { | ||||
|         if (mJoystickId == ButtonType.STICK_C) { | ||||
|             // C-stick is scaled down to be half the size of the circle pad | ||||
|             scale = 2; | ||||
|         } | ||||
|  | @ -192,23 +193,25 @@ public final class InputOverlayDrawableJoystick { | |||
|         return true; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     public float[] getAxisValues() { | ||||
|         return axises; | ||||
|     public int getJoystickId() { | ||||
|         return mJoystickId; | ||||
|     } | ||||
| 
 | ||||
|     public int[] getAxisIDs() { | ||||
|         return axisIDs; | ||||
|     public float getXAxis() { | ||||
|         return mXAxis; | ||||
|     } | ||||
| 
 | ||||
|     public float getYAxis() { | ||||
|         return mYAxis; | ||||
|     } | ||||
| 
 | ||||
|     public int getTrackId() { | ||||
|         return mTrackId; | ||||
|     } | ||||
| 
 | ||||
|     private void SetInnerBounds() { | ||||
|         int X = getVirtBounds().centerX() + (int) ((axises[0]) * (getVirtBounds().width() / 2)); | ||||
|         int Y = getVirtBounds().centerY() + (int) ((axises[1]) * (getVirtBounds().height() / 2)); | ||||
| 
 | ||||
|         if (mJoystickType == ButtonType.STICK_LEFT) { | ||||
|             X += 1; | ||||
|             Y += 1; | ||||
|         } | ||||
|         int X = getVirtBounds().centerX() + (int) ((mXAxis) * (getVirtBounds().width() / 2)); | ||||
|         int Y = getVirtBounds().centerY() + (int) ((mYAxis) * (getVirtBounds().height() / 2)); | ||||
| 
 | ||||
|         if (X > getVirtBounds().centerX() + (getVirtBounds().width() / 2)) | ||||
|             X = getVirtBounds().centerX() + (getVirtBounds().width() / 2); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue