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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

r3rsD^e&r)Z*^I1 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 Z{9=r{Mqq literal 0 HcmV?d00001