mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-28 00:35:34 +00:00
Android: Add on-screen dpad support
This commit is contained in:
parent
c24a22e30f
commit
bd99b318e5
@ -37,10 +37,12 @@ import java.util.Set;
|
|||||||
public final class InputOverlay extends SurfaceView implements OnTouchListener
|
public final class InputOverlay extends SurfaceView implements OnTouchListener
|
||||||
{
|
{
|
||||||
private final Set<InputOverlayDrawableButton> overlayButtons = new HashSet<>();
|
private final Set<InputOverlayDrawableButton> overlayButtons = new HashSet<>();
|
||||||
|
private final Set<InputOverlayDrawableDpad> overlayDpads = new HashSet<>();
|
||||||
private final Set<InputOverlayDrawableJoystick> overlayJoysticks = new HashSet<>();
|
private final Set<InputOverlayDrawableJoystick> overlayJoysticks = new HashSet<>();
|
||||||
|
|
||||||
private boolean mIsInEditMode = false;
|
private boolean mIsInEditMode = false;
|
||||||
private InputOverlayDrawableButton mButtonBeingConfigured;
|
private InputOverlayDrawableButton mButtonBeingConfigured;
|
||||||
|
private InputOverlayDrawableDpad mDpadBeingConfigured;
|
||||||
private InputOverlayDrawableJoystick mJoystickBeingConfigured;
|
private InputOverlayDrawableJoystick mJoystickBeingConfigured;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,6 +86,9 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
|
|||||||
overlayButtons.add(initializeOverlayButton(context, R.drawable.gcpad_start, ButtonType.BUTTON_START));
|
overlayButtons.add(initializeOverlayButton(context, R.drawable.gcpad_start, ButtonType.BUTTON_START));
|
||||||
overlayButtons.add(initializeOverlayButton(context, R.drawable.gcpad_l, ButtonType.TRIGGER_L));
|
overlayButtons.add(initializeOverlayButton(context, R.drawable.gcpad_l, ButtonType.TRIGGER_L));
|
||||||
overlayButtons.add(initializeOverlayButton(context, R.drawable.gcpad_r, ButtonType.TRIGGER_R));
|
overlayButtons.add(initializeOverlayButton(context, R.drawable.gcpad_r, ButtonType.TRIGGER_R));
|
||||||
|
overlayDpads.add(initializeOverlayDpad(context, R.drawable.gcpad_dpad,
|
||||||
|
ButtonType.BUTTON_UP, ButtonType.BUTTON_DOWN,
|
||||||
|
ButtonType.BUTTON_LEFT, ButtonType.BUTTON_RIGHT));
|
||||||
overlayJoysticks.add(initializeOverlayJoystick(context,
|
overlayJoysticks.add(initializeOverlayJoystick(context,
|
||||||
R.drawable.gcpad_joystick_range, R.drawable.gcpad_joystick,
|
R.drawable.gcpad_joystick_range, R.drawable.gcpad_joystick,
|
||||||
ButtonType.STICK_MAIN));
|
ButtonType.STICK_MAIN));
|
||||||
@ -108,6 +113,11 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
|
|||||||
button.draw(canvas);
|
button.draw(canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (InputOverlayDrawableDpad dpad : overlayDpads)
|
||||||
|
{
|
||||||
|
dpad.draw(canvas);
|
||||||
|
}
|
||||||
|
|
||||||
for (InputOverlayDrawableJoystick joystick: overlayJoysticks)
|
for (InputOverlayDrawableJoystick joystick: overlayJoysticks)
|
||||||
{
|
{
|
||||||
joystick.draw(canvas);
|
joystick.draw(canvas);
|
||||||
@ -149,6 +159,48 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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:
|
||||||
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
// 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))
|
||||||
|
{
|
||||||
|
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(0), ButtonState.PRESSED);
|
||||||
|
}
|
||||||
|
if (dpad.getBounds().bottom - (dpad.getIntrinsicHeight() / 3) < (int)event.getY(pointerIndex))
|
||||||
|
{
|
||||||
|
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(1), ButtonState.PRESSED);
|
||||||
|
}
|
||||||
|
if (dpad.getBounds().left + (dpad.getIntrinsicWidth() / 3) > (int)event.getX(pointerIndex))
|
||||||
|
{
|
||||||
|
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(2), ButtonState.PRESSED);
|
||||||
|
}
|
||||||
|
if (dpad.getBounds().right - (dpad.getIntrinsicWidth() / 3) < (int)event.getX(pointerIndex))
|
||||||
|
{
|
||||||
|
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(3), ButtonState.PRESSED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
case MotionEvent.ACTION_POINTER_UP:
|
||||||
|
// If a pointer ends, release the buttons.
|
||||||
|
if (dpad.getBounds().contains((int)event.getX(pointerIndex), (int)event.getY(pointerIndex)))
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, dpad.getId(i), ButtonState.RELEASED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (InputOverlayDrawableJoystick joystick : overlayJoysticks)
|
for (InputOverlayDrawableJoystick joystick : overlayJoysticks)
|
||||||
{
|
{
|
||||||
@ -209,6 +261,40 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 no button is being moved now, remember the currently touched button to move.
|
||||||
|
if (mButtonBeingConfigured == null && dpad.getBounds().contains(fingerPositionX, fingerPositionY))
|
||||||
|
{
|
||||||
|
mDpadBeingConfigured = dpad;
|
||||||
|
mDpadBeingConfigured.onConfigureTouch(v, event);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
if (mDpadBeingConfigured != null)
|
||||||
|
{
|
||||||
|
mDpadBeingConfigured.onConfigureTouch(v, event);
|
||||||
|
invalidate();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
case MotionEvent.ACTION_POINTER_UP:
|
||||||
|
if (mDpadBeingConfigured == dpad)
|
||||||
|
{
|
||||||
|
//Persist button position by saving new place.
|
||||||
|
saveControlPosition(mDpadBeingConfigured.getId(0), mDpadBeingConfigured.getBounds().left, mDpadBeingConfigured.getBounds().top);
|
||||||
|
mDpadBeingConfigured = null;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (InputOverlayDrawableJoystick joystick : overlayJoysticks)
|
for (InputOverlayDrawableJoystick joystick : overlayJoysticks)
|
||||||
{
|
{
|
||||||
@ -341,6 +427,57 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
|
|||||||
return overlayDrawable;
|
return overlayDrawable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* @return the initialized {@link InputOverlayDrawableDpad}
|
||||||
|
*/
|
||||||
|
private static InputOverlayDrawableDpad initializeOverlayDpad(Context context, int resId,
|
||||||
|
int buttonUp, int buttonDown,
|
||||||
|
int buttonLeft, int buttonRight)
|
||||||
|
{
|
||||||
|
// Resources handle for fetching the initial Drawable resource.
|
||||||
|
final Resources res = context.getResources();
|
||||||
|
|
||||||
|
// SharedPreference to retrieve the X and Y coordinates for the InputOverlayDrawableDpad.
|
||||||
|
final SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
|
||||||
|
// Initialize the InputOverlayDrawableDpad.
|
||||||
|
float overlaySize = sPrefs.getInt("controls_size", 20);
|
||||||
|
overlaySize += 30;
|
||||||
|
overlaySize /= 50;
|
||||||
|
final Bitmap bitmap = resizeBitmap(context, BitmapFactory.decodeResource(res, resId), 0.30f * overlaySize);
|
||||||
|
final InputOverlayDrawableDpad overlayDrawable = new InputOverlayDrawableDpad(res, bitmap,
|
||||||
|
buttonUp, buttonDown, buttonLeft, buttonRight);
|
||||||
|
|
||||||
|
// The X and Y coordinates of the InputOverlayDrawableDpad on the InputOverlay.
|
||||||
|
// These were set in the input overlay configuration menu.
|
||||||
|
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();
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// Need to set the image's position
|
||||||
|
overlayDrawable.setPosition(drawableX, drawableY);
|
||||||
|
|
||||||
|
return overlayDrawable;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes an {@link InputOverlayDrawableJoystick}
|
* Initializes an {@link InputOverlayDrawableJoystick}
|
||||||
*
|
*
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2016 Dolphin Emulator Project
|
||||||
|
* Licensed under GPLv2+
|
||||||
|
* Refer to the license.txt file included.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.dolphinemu.dolphinemu.overlay;
|
||||||
|
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
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
|
||||||
|
{
|
||||||
|
// The ID identifying what type of button this Drawable represents.
|
||||||
|
private int[] mButtonType = new int[4];
|
||||||
|
private int mPreviousTouchX, mPreviousTouchY;
|
||||||
|
private int mControlPositionX, mControlPositionY;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
public InputOverlayDrawableDpad(Resources res, Bitmap bitmap,
|
||||||
|
int buttonUp, int buttonDown,
|
||||||
|
int buttonLeft, int buttonRight)
|
||||||
|
{
|
||||||
|
super(res, bitmap);
|
||||||
|
mButtonType[0] = buttonUp;
|
||||||
|
mButtonType[1] = buttonDown;
|
||||||
|
mButtonType[2] = buttonLeft;
|
||||||
|
mButtonType[3] = buttonRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets one of the InputOverlayDrawableDpad's button IDs.
|
||||||
|
*
|
||||||
|
* @return the requested InputOverlayDrawableDpad's button ID.
|
||||||
|
*/
|
||||||
|
public int getId(int direction)
|
||||||
|
{
|
||||||
|
return mButtonType[direction];
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean onConfigureTouch(View v, MotionEvent event)
|
||||||
|
{
|
||||||
|
int pointerIndex = event.getActionIndex();
|
||||||
|
int fingerPositionX = (int)event.getX(pointerIndex);
|
||||||
|
int fingerPositionY = (int)event.getY(pointerIndex);
|
||||||
|
switch (event.getAction())
|
||||||
|
{
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
mPreviousTouchX = fingerPositionX;
|
||||||
|
mPreviousTouchY = fingerPositionY;
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
mControlPositionX += fingerPositionX - mPreviousTouchX;
|
||||||
|
mControlPositionY += fingerPositionY - mPreviousTouchY;
|
||||||
|
setBounds(new Rect(mControlPositionX, mControlPositionY, getBitmap().getWidth() + mControlPositionX, getBitmap().getHeight() + mControlPositionY));
|
||||||
|
mPreviousTouchX = fingerPositionX;
|
||||||
|
mPreviousTouchY = fingerPositionY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPosition(int x, int y)
|
||||||
|
{
|
||||||
|
mControlPositionX = x;
|
||||||
|
mControlPositionY = y;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user