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
|
||||
{
|
||||
private final Set<InputOverlayDrawableButton> overlayButtons = new HashSet<>();
|
||||
private final Set<InputOverlayDrawableDpad> overlayDpads = new HashSet<>();
|
||||
private final Set<InputOverlayDrawableJoystick> overlayJoysticks = new HashSet<>();
|
||||
|
||||
private boolean mIsInEditMode = false;
|
||||
private InputOverlayDrawableButton mButtonBeingConfigured;
|
||||
private InputOverlayDrawableDpad mDpadBeingConfigured;
|
||||
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_l, ButtonType.TRIGGER_L));
|
||||
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,
|
||||
R.drawable.gcpad_joystick_range, R.drawable.gcpad_joystick,
|
||||
ButtonType.STICK_MAIN));
|
||||
|
@ -108,6 +113,11 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
|
|||
button.draw(canvas);
|
||||
}
|
||||
|
||||
for (InputOverlayDrawableDpad dpad : overlayDpads)
|
||||
{
|
||||
dpad.draw(canvas);
|
||||
}
|
||||
|
||||
for (InputOverlayDrawableJoystick joystick: overlayJoysticks)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -341,6 +427,57 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
|
|||
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}
|
||||
*
|
||||
|
|
|
@ -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…
Reference in New Issue