From 216a7ceea89f02b0790d8adb925fdeb546dc7ba7 Mon Sep 17 00:00:00 2001 From: Mahdi Hijazi Date: Tue, 9 May 2017 13:54:15 +0200 Subject: [PATCH] Android: Add pressed state to the on-screen controllers Now the buttons will be shown in different color to indicate a press event --- .../dolphinemu/overlay/InputOverlay.java | 180 ++++++++++++------ .../overlay/InputOverlayDrawableButton.java | 64 ++++++- .../overlay/InputOverlayDrawableDpad.java | 130 +++++++++++-- .../gcwii_dpad_pressed_one_direction.png | Bin 0 -> 15695 bytes .../gcwii_dpad_pressed_two_directions.png | Bin 0 -> 20649 bytes 5 files changed, 291 insertions(+), 83 deletions(-) create mode 100644 Source/Android/app/src/main/res/drawable-xxxhdpi/gcwii_dpad_pressed_one_direction.png create mode 100644 Source/Android/app/src/main/res/drawable-xxxhdpi/gcwii_dpad_pressed_two_directions.png 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 7f4421b101..780b441012 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 @@ -137,7 +137,9 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener // 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); NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(), ButtonState.PRESSED); + invalidate(); } break; case MotionEvent.ACTION_UP: @@ -147,6 +149,9 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener { NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, button.getId(), ButtonState.RELEASED); } + + button.setPressedState(false); + invalidate(); break; } } @@ -162,22 +167,33 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener // If a pointer enters the bounds of a button, press that button. if (dpad.getBounds().contains((int)event.getX(pointerIndex), (int)event.getY(pointerIndex))) { - if (dpad.getBounds().top + (dpad.getIntrinsicHeight() / 3) > (int)event.getY(pointerIndex)) + boolean up = false; + boolean down = false; + boolean left = false; + boolean right = false; + if (dpad.getBounds().top + (dpad.getHeight() / 3) > (int)event.getY(pointerIndex)) { NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(0), ButtonState.PRESSED); + up = true; } - if (dpad.getBounds().bottom - (dpad.getIntrinsicHeight() / 3) < (int)event.getY(pointerIndex)) + if (dpad.getBounds().bottom - (dpad.getHeight() / 3) < (int)event.getY(pointerIndex)) { NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(1), ButtonState.PRESSED); + down = true; } - if (dpad.getBounds().left + (dpad.getIntrinsicWidth() / 3) > (int)event.getX(pointerIndex)) + if (dpad.getBounds().left + (dpad.getWidth() / 3) > (int)event.getX(pointerIndex)) { NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(2), ButtonState.PRESSED); + left = true; } - if (dpad.getBounds().right - (dpad.getIntrinsicWidth() / 3) < (int)event.getX(pointerIndex)) + if (dpad.getBounds().right - (dpad.getWidth() / 3) < (int)event.getX(pointerIndex)) { NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(3), ButtonState.PRESSED); + right = true; } + + setDpadState(dpad, up, down, left, right); + invalidate(); } break; case MotionEvent.ACTION_UP: @@ -190,6 +206,8 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(i), ButtonState.RELEASED); } } + dpad.setState(InputOverlayDrawableDpad.STATE_DEFAULT); + invalidate(); break; } } @@ -323,43 +341,74 @@ 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 addGameCubeOverlayControls() { if (mPreferences.getBoolean("buttonToggleGc0", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_a, ButtonType.BUTTON_A)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_a, R.drawable.gcpad_a_pressed, ButtonType.BUTTON_A)); } if (mPreferences.getBoolean("buttonToggleGc1", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_b, ButtonType.BUTTON_B)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_b, R.drawable.gcpad_b_pressed, ButtonType.BUTTON_B)); } if (mPreferences.getBoolean("buttonToggleGc2", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_x, ButtonType.BUTTON_X)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_x, R.drawable.gcpad_x_pressed, ButtonType.BUTTON_X)); } if (mPreferences.getBoolean("buttonToggleGc3", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_y, ButtonType.BUTTON_Y)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_y, R.drawable.gcpad_y_pressed, ButtonType.BUTTON_Y)); } if (mPreferences.getBoolean("buttonToggleGc4", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_z, ButtonType.BUTTON_Z)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_z, R.drawable.gcpad_z_pressed, ButtonType.BUTTON_Z)); } if (mPreferences.getBoolean("buttonToggleGc5", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_start, ButtonType.BUTTON_START)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_start, R.drawable.gcpad_start_pressed, ButtonType.BUTTON_START)); } if (mPreferences.getBoolean("buttonToggleGc6", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_l, ButtonType.TRIGGER_L)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_l, R.drawable.gcpad_l_pressed, ButtonType.TRIGGER_L)); } if (mPreferences.getBoolean("buttonToggleGc7", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_r, ButtonType.TRIGGER_R)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.gcpad_r, R.drawable.gcpad_r_pressed, ButtonType.TRIGGER_R)); } if (mPreferences.getBoolean("buttonToggleGc8", true)) { overlayDpads.add(initializeOverlayDpad(getContext(), R.drawable.gcwii_dpad, + R.drawable.gcwii_dpad_pressed_one_direction, R.drawable.gcwii_dpad_pressed_two_directions, ButtonType.BUTTON_UP, ButtonType.BUTTON_DOWN, ButtonType.BUTTON_LEFT, ButtonType.BUTTON_RIGHT)); } @@ -381,43 +430,45 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener { if (mPreferences.getBoolean("buttonToggleWii0", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_a, ButtonType.WIIMOTE_BUTTON_A)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_a, R.drawable.wiimote_a_pressed, ButtonType.WIIMOTE_BUTTON_A)); } if (mPreferences.getBoolean("buttonToggleWii1", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_b, ButtonType.WIIMOTE_BUTTON_B)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_b, R.drawable.wiimote_b_pressed, ButtonType.WIIMOTE_BUTTON_B)); } if (mPreferences.getBoolean("buttonToggleWii2", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_one, ButtonType.WIIMOTE_BUTTON_1)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_one, R.drawable.wiimote_one_pressed, ButtonType.WIIMOTE_BUTTON_1)); } if (mPreferences.getBoolean("buttonToggleWii3", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_two, ButtonType.WIIMOTE_BUTTON_2)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_two, R.drawable.wiimote_two_pressed, ButtonType.WIIMOTE_BUTTON_2)); } if (mPreferences.getBoolean("buttonToggleWii4", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_plus, ButtonType.WIIMOTE_BUTTON_PLUS)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_plus, R.drawable.wiimote_plus_pressed, ButtonType.WIIMOTE_BUTTON_PLUS)); } if (mPreferences.getBoolean("buttonToggleWii5", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_minus, ButtonType.WIIMOTE_BUTTON_MINUS)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_minus, R.drawable.wiimote_minus_pressed, ButtonType.WIIMOTE_BUTTON_MINUS)); } if (mPreferences.getBoolean("buttonToggleWii6", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_home, ButtonType.WIIMOTE_BUTTON_HOME)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_home, R.drawable.wiimote_home_pressed, ButtonType.WIIMOTE_BUTTON_HOME)); } if (mPreferences.getBoolean("buttonToggleWii7", true)) { if (mPreferences.getInt("wiiController", 3) == 2) { overlayDpads.add(initializeOverlayDpad(getContext(), R.drawable.gcwii_dpad, + R.drawable.gcwii_dpad_pressed_one_direction, R.drawable.gcwii_dpad_pressed_two_directions, ButtonType.WIIMOTE_RIGHT, ButtonType.WIIMOTE_LEFT, ButtonType.WIIMOTE_UP, ButtonType.WIIMOTE_DOWN)); } else { overlayDpads.add(initializeOverlayDpad(getContext(), R.drawable.gcwii_dpad, + R.drawable.gcwii_dpad_pressed_one_direction, R.drawable.gcwii_dpad_pressed_two_directions, ButtonType.WIIMOTE_UP, ButtonType.WIIMOTE_DOWN, ButtonType.WIIMOTE_LEFT, ButtonType.WIIMOTE_RIGHT)); } @@ -428,11 +479,11 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener { if (mPreferences.getBoolean("buttonToggleWii8", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.nunchuk_c, ButtonType.NUNCHUK_BUTTON_C)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.nunchuk_c, R.drawable.nunchuk_c_pressed, ButtonType.NUNCHUK_BUTTON_C)); } if (mPreferences.getBoolean("buttonToggleWii9", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.nunchuk_z, ButtonType.NUNCHUK_BUTTON_Z)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.nunchuk_z, R.drawable.nunchuk_z_pressed, ButtonType.NUNCHUK_BUTTON_Z)); } if (mPreferences.getBoolean("buttonToggleWii10", true)) { @@ -446,51 +497,52 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener { if (mPreferences.getBoolean("buttonToggleClassic0", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_a, ButtonType.CLASSIC_BUTTON_A)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_a, R.drawable.classic_a_pressed, ButtonType.CLASSIC_BUTTON_A)); } if (mPreferences.getBoolean("buttonToggleClassic1", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_b, ButtonType.CLASSIC_BUTTON_B)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_b, R.drawable.classic_b_pressed, ButtonType.CLASSIC_BUTTON_B)); } if (mPreferences.getBoolean("buttonToggleClassic2", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_x, ButtonType.CLASSIC_BUTTON_X)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_x, R.drawable.classic_x_pressed, ButtonType.CLASSIC_BUTTON_X)); } if (mPreferences.getBoolean("buttonToggleClassic3", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_y, ButtonType.CLASSIC_BUTTON_Y)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_y, R.drawable.classic_y_pressed, ButtonType.CLASSIC_BUTTON_Y)); } if (mPreferences.getBoolean("buttonToggleClassic4", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_plus, ButtonType.CLASSIC_BUTTON_PLUS)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_plus, R.drawable.wiimote_plus_pressed, ButtonType.CLASSIC_BUTTON_PLUS)); } if (mPreferences.getBoolean("buttonToggleClassic5", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_minus, ButtonType.CLASSIC_BUTTON_MINUS)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_minus, R.drawable.wiimote_minus_pressed, ButtonType.CLASSIC_BUTTON_MINUS)); } if (mPreferences.getBoolean("buttonToggleClassic6", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_home, ButtonType.CLASSIC_BUTTON_HOME)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.wiimote_home, R.drawable.wiimote_home_pressed, ButtonType.CLASSIC_BUTTON_HOME)); } if (mPreferences.getBoolean("buttonToggleClassic7", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_l, ButtonType.CLASSIC_TRIGGER_L)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_l, R.drawable.classic_l_pressed, ButtonType.CLASSIC_TRIGGER_L)); } if (mPreferences.getBoolean("buttonToggleClassic8", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_r, ButtonType.CLASSIC_TRIGGER_R)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_r, R.drawable.classic_r_pressed, ButtonType.CLASSIC_TRIGGER_R)); } if (mPreferences.getBoolean("buttonToggleClassic9", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_zl, ButtonType.CLASSIC_BUTTON_ZL)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_zl, R.drawable.classic_zl_pressed, ButtonType.CLASSIC_BUTTON_ZL)); } if (mPreferences.getBoolean("buttonToggleClassic10", true)) { - overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_zr, ButtonType.CLASSIC_BUTTON_ZR)); + overlayButtons.add(initializeOverlayButton(getContext(), R.drawable.classic_zr, R.drawable.classic_zr_pressed, ButtonType.CLASSIC_BUTTON_ZR)); } if (mPreferences.getBoolean("buttonToggleClassic11", true)) { overlayDpads.add(initializeOverlayDpad(getContext(), R.drawable.gcwii_dpad, + R.drawable.gcwii_dpad_pressed_one_direction, R.drawable.gcwii_dpad_pressed_two_directions, ButtonType.CLASSIC_DPAD_UP, ButtonType.CLASSIC_DPAD_DOWN, ButtonType.CLASSIC_DPAD_LEFT, ButtonType.CLASSIC_DPAD_RIGHT)); } @@ -569,14 +621,15 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener * InputOverlayDrawableButton. Simply add it to the HashSet of overlay items and wait * for Android to call the onDraw method. * - * @param context The current {@link Context}. - * @param resId The resource ID of the {@link Drawable} to get the {@link Bitmap} of. - * @param buttonId Identifier for determining what type of button the initialized InputOverlayDrawableButton represents. + * @param context The current {@link Context}. + * @param defaultResId The resource ID of the {@link Drawable} to get the {@link Bitmap} of (Default State). + * @param pressedResId The resource ID of the {@link Drawable} to get the {@link Bitmap} of (Pressed State). + * @param buttonId Identifier for determining what type of button the initialized InputOverlayDrawableButton represents. * * @return An {@link InputOverlayDrawableButton} with the correct drawing bounds set. * */ - private static InputOverlayDrawableButton initializeOverlayButton(Context context, int resId, int buttonId) + private static InputOverlayDrawableButton initializeOverlayButton(Context context, int defaultResId, int pressedResId, int buttonId) { // Resources handle for fetching the initial Drawable resource. final Resources res = context.getResources(); @@ -633,23 +686,21 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener scale /= 100; // Initialize the InputOverlayDrawableButton. - final Bitmap bitmap = resizeBitmap(context, BitmapFactory.decodeResource(res, resId), scale); - final InputOverlayDrawableButton overlayDrawable = new InputOverlayDrawableButton(res, bitmap, buttonId); + final Bitmap defaultStateBitmap = resizeBitmap(context, BitmapFactory.decodeResource(res, defaultResId), scale); + final Bitmap pressedStateBitmap = resizeBitmap(context, BitmapFactory.decodeResource(res, pressedResId), scale); + final InputOverlayDrawableButton overlayDrawable = new InputOverlayDrawableButton(res, defaultStateBitmap, pressedStateBitmap, buttonId); // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay. // These were set in the input overlay configuration menu. int drawableX = (int) sPrefs.getFloat(buttonId + "-X", 0f); int drawableY = (int) sPrefs.getFloat(buttonId + "-Y", 0f); - // Intrinsic width and height of the InputOverlayDrawableButton. - // For any who may not know, intrinsic width/height - // are the original unmodified width and height of the image. - int intrinWidth = overlayDrawable.getIntrinsicWidth(); - int intrinHeight = overlayDrawable.getIntrinsicHeight(); + int width = overlayDrawable.getWidth(); + int height = overlayDrawable.getHeight(); // Now set the bounds for the InputOverlayDrawableButton. // This will dictate where on the screen (and the what the size) the InputOverlayDrawableButton will be. - overlayDrawable.setBounds(drawableX, drawableY, drawableX + intrinWidth, drawableY + intrinHeight); + overlayDrawable.setBounds(drawableX, drawableY, drawableX + width, drawableY + height); // Need to set the image's position overlayDrawable.setPosition(drawableX, drawableY); @@ -660,18 +711,25 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener /** * Initializes an {@link InputOverlayDrawableDpad} * - * @param context The current {@link Context}. - * @param resId The resource ID of the {@link Drawable} to get the {@link Bitmap} of. - * @param buttonUp Identifier for the up button. - * @param buttonDown Identifier for the down button. - * @param buttonLeft Identifier for the left button. - * @param buttonRight Identifier for the right button. + * @param context The current {@link Context}. + * @param defaultResId The {@link Bitmap} resource ID of the default sate. + * @param pressedOneDirectionResId The {@link Bitmap} resource ID of the pressed sate in one direction. + * @param pressedTwoDirectionsResId The {@link Bitmap} resource ID of the pressed sate in two directions. + * @param buttonUp Identifier for the up button. + * @param buttonDown Identifier for the down button. + * @param buttonLeft Identifier for the left button. + * @param buttonRight Identifier for the right button. * * @return the initialized {@link InputOverlayDrawableDpad} */ - private static InputOverlayDrawableDpad initializeOverlayDpad(Context context, int resId, - int buttonUp, int buttonDown, - int buttonLeft, int buttonRight) + private static InputOverlayDrawableDpad initializeOverlayDpad(Context context, + int defaultResId, + int pressedOneDirectionResId, + int pressedTwoDirectionsResId, + int buttonUp, + int buttonDown, + int buttonLeft, + int buttonRight) { // Resources handle for fetching the initial Drawable resource. final Resources res = context.getResources(); @@ -699,8 +757,11 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener scale /= 100; // Initialize the InputOverlayDrawableDpad. - final Bitmap bitmap = resizeBitmap(context, BitmapFactory.decodeResource(res, resId), scale); - final InputOverlayDrawableDpad overlayDrawable = new InputOverlayDrawableDpad(res, bitmap, + final Bitmap defaultStateBitmap = resizeBitmap(context, BitmapFactory.decodeResource(res, defaultResId), scale); + final Bitmap pressedOneDirectionStateBitmap = resizeBitmap(context, BitmapFactory.decodeResource(res, pressedOneDirectionResId), scale); + final Bitmap pressedTwoDirectionsStateBitmap = resizeBitmap(context, BitmapFactory.decodeResource(res, pressedTwoDirectionsResId), scale); + final InputOverlayDrawableDpad overlayDrawable = new InputOverlayDrawableDpad(res, defaultStateBitmap, + pressedOneDirectionStateBitmap, pressedTwoDirectionsStateBitmap, buttonUp, buttonDown, buttonLeft, buttonRight); // The X and Y coordinates of the InputOverlayDrawableDpad on the InputOverlay. @@ -708,15 +769,12 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener int drawableX = (int) sPrefs.getFloat(buttonUp + "-X", 0f); int drawableY = (int) sPrefs.getFloat(buttonUp + "-Y", 0f); - // Intrinsic width and height of the InputOverlayDrawableDpad. - // For any who may not know, intrinsic width/height - // are the original unmodified width and height of the image. - int intrinWidth = overlayDrawable.getIntrinsicWidth(); - int intrinHeight = overlayDrawable.getIntrinsicHeight(); + int width = overlayDrawable.getWidth(); + int height = overlayDrawable.getHeight(); // Now set the bounds for the InputOverlayDrawableDpad. // This will dictate where on the screen (and the what the size) the InputOverlayDrawableDpad will be. - overlayDrawable.setBounds(drawableX, drawableY, drawableX + intrinWidth, drawableY + intrinHeight); + overlayDrawable.setBounds(drawableX, drawableY, drawableX + width, drawableY + height); // Need to set the image's position overlayDrawable.setPosition(drawableX, drawableY); 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 7d692c36ba..4d557b5f28 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 @@ -8,33 +8,43 @@ package org.dolphinemu.dolphinemu.overlay; import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.view.MotionEvent; -import android.view.View; /** * Custom {@link BitmapDrawable} that is capable * of storing it's own ID. */ -public final class InputOverlayDrawableButton extends BitmapDrawable +public final class InputOverlayDrawableButton { // The ID identifying what type of button this Drawable represents. private int mButtonType; private int mPreviousTouchX, mPreviousTouchY; private int mControlPositionX, mControlPositionY; + private int mWidth; + private int mHeight; + private BitmapDrawable mDefaultStateBitmap; + private BitmapDrawable mPressedStateBitmap; + private boolean mPressedState = false; /** * Constructor - * - * @param res {@link Resources} instance. - * @param bitmap {@link Bitmap} to use with this Drawable. - * @param buttonType Identifier for this type of button. + * + * @param res {@link Resources} instance. + * @param defaultStateBitmap {@link Bitmap} to use with the default state Drawable. + * @param pressedStateBitmap {@link Bitmap} to use with the pressed state Drawable. + * @param buttonType Identifier for this type of button. */ - public InputOverlayDrawableButton(Resources res, Bitmap bitmap, int buttonType) + public InputOverlayDrawableButton(Resources res, Bitmap defaultStateBitmap, Bitmap pressedStateBitmap, int buttonType) { - super(res, bitmap); + mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap); + mPressedStateBitmap = new BitmapDrawable(res, pressedStateBitmap); mButtonType = buttonType; + + mWidth = mDefaultStateBitmap.getIntrinsicWidth(); + mHeight = mDefaultStateBitmap.getIntrinsicHeight(); } /** @@ -61,7 +71,7 @@ public final class InputOverlayDrawableButton extends BitmapDrawable case MotionEvent.ACTION_MOVE: mControlPositionX += fingerPositionX - mPreviousTouchX; mControlPositionY += fingerPositionY - mPreviousTouchY; - setBounds(new Rect(mControlPositionX, mControlPositionY, getBitmap().getWidth() + mControlPositionX, getBitmap().getHeight() + mControlPositionY)); + setBounds(mControlPositionX, mControlPositionY, getWidth() + mControlPositionX, getHeight() + mControlPositionY); mPreviousTouchX = fingerPositionX; mPreviousTouchY = fingerPositionY; break; @@ -75,4 +85,40 @@ public final class InputOverlayDrawableButton extends BitmapDrawable mControlPositionX = x; mControlPositionY = y; } + + public void draw(Canvas canvas) + { + getCurrentStateBitmapDrawable().draw(canvas); + } + + private BitmapDrawable getCurrentStateBitmapDrawable() + { + return mPressedState ? mPressedStateBitmap : mDefaultStateBitmap; + } + + public void setBounds(int left, int top, int right, int bottom) + { + mDefaultStateBitmap.setBounds(left, top, right, bottom); + mPressedStateBitmap.setBounds(left, top, right, bottom); + } + + public Rect getBounds() + { + return mDefaultStateBitmap.getBounds(); + } + + public int getWidth() + { + return mWidth; + } + + public int getHeight() + { + return mHeight; + } + + public void setPressedState(boolean isPressed) + { + mPressedState = isPressed; + } } 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 56ee4b2e18..cd76ce8e87 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 @@ -8,43 +8,123 @@ package org.dolphinemu.dolphinemu.overlay; import android.content.res.Resources; import android.graphics.Bitmap; +import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.view.MotionEvent; -import android.view.View; /** * Custom {@link BitmapDrawable} that is capable * of storing it's own ID. */ -public final class InputOverlayDrawableDpad extends BitmapDrawable +public final class InputOverlayDrawableDpad { // The ID identifying what type of button this Drawable represents. private int[] mButtonType = new int[4]; private int mPreviousTouchX, mPreviousTouchY; private int mControlPositionX, mControlPositionY; + private int mWidth; + private int mHeight; + private BitmapDrawable mDefaultStateBitmap; + private BitmapDrawable mPressedOneDirectionStateBitmap; + private BitmapDrawable mPressedTwoDirectionsStateBitmap; + private int mPressState = STATE_DEFAULT; + + 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; /** * Constructor * - * @param res {@link Resources} instance. - * @param bitmap {@link Bitmap} to use with this Drawable. - * @param buttonUp Identifier for the up button. - * @param buttonDown Identifier for the down button. - * @param buttonLeft Identifier for the left button. - * @param buttonRight Identifier for the right button. + * @param res {@link Resources} instance. + * @param defaultStateBitmap {@link Bitmap} of the default state. + * @param pressedOneDirectionStateBitmap {@link Bitmap} of the pressed state in one direction. + * @param pressedTwoDirectionsStateBitmap {@link Bitmap} of the pressed state in two direction. + * @param buttonUp Identifier for the up button. + * @param buttonDown Identifier for the down button. + * @param buttonLeft Identifier for the left button. + * @param buttonRight Identifier for the right button. */ - public InputOverlayDrawableDpad(Resources res, Bitmap bitmap, - int buttonUp, int buttonDown, - int buttonLeft, int buttonRight) + public InputOverlayDrawableDpad(Resources res, + Bitmap defaultStateBitmap, + Bitmap pressedOneDirectionStateBitmap, + Bitmap pressedTwoDirectionsStateBitmap, + int buttonUp, int buttonDown, + int buttonLeft, int buttonRight) { - super(res, bitmap); + mDefaultStateBitmap = new BitmapDrawable(res, defaultStateBitmap); + mPressedOneDirectionStateBitmap = new BitmapDrawable(res, pressedOneDirectionStateBitmap); + mPressedTwoDirectionsStateBitmap = new BitmapDrawable(res, pressedTwoDirectionsStateBitmap); + + mWidth = mDefaultStateBitmap.getIntrinsicWidth(); + mHeight = mDefaultStateBitmap.getIntrinsicHeight(); + mButtonType[0] = buttonUp; mButtonType[1] = buttonDown; mButtonType[2] = buttonLeft; mButtonType[3] = buttonRight; } + 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; + } + } + /** * Gets one of the InputOverlayDrawableDpad's button IDs. * @@ -69,7 +149,7 @@ public final class InputOverlayDrawableDpad extends BitmapDrawable case MotionEvent.ACTION_MOVE: mControlPositionX += fingerPositionX - mPreviousTouchX; mControlPositionY += fingerPositionY - mPreviousTouchY; - setBounds(new Rect(mControlPositionX, mControlPositionY, getBitmap().getWidth() + mControlPositionX, getBitmap().getHeight() + mControlPositionY)); + setBounds(mControlPositionX, mControlPositionY, getWidth() + mControlPositionX, getHeight() + mControlPositionY); mPreviousTouchX = fingerPositionX; mPreviousTouchY = fingerPositionY; break; @@ -83,4 +163,28 @@ public final class InputOverlayDrawableDpad extends BitmapDrawable mControlPositionX = x; mControlPositionY = y; } + + public void setBounds(int left, int top, int right, int bottom) + { + mDefaultStateBitmap.setBounds(left, top, right, bottom); + mPressedOneDirectionStateBitmap.setBounds(left, top, right, bottom); + mPressedTwoDirectionsStateBitmap.setBounds(left, top, right, bottom); + } + + public Rect getBounds() + { + return mDefaultStateBitmap.getBounds(); + } + + public int getWidth() { + return mWidth; + } + + public int getHeight() { + return mHeight; + } + + public void setState(int pressState) { + mPressState = pressState; + } } diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/gcwii_dpad_pressed_one_direction.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/gcwii_dpad_pressed_one_direction.png new file mode 100644 index 0000000000000000000000000000000000000000..4f0219b3a45876e8bea6b11a41c310c0b818952a GIT binary patch literal 15695 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 GWkdjb37Zjvf>F(~1 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 daQ&$;#?-^r)*(mC+*e*wxNr{Mqq literal 0 HcmV?d00001