summaryrefslogtreecommitdiff
path: root/Source/Android/src/org
diff options
context:
space:
mode:
authorRyan Houdek <Sonicadvance1@gmail.com>2013-11-14 15:17:51 -0600
committerRyan Houdek <Sonicadvance1@gmail.com>2013-11-14 15:18:33 -0600
commitfeedee5c23a0493ae4f25564844ede88079ac777 (patch)
treef5bef7db7c6dc44e460ff9432a761e155294b1ad /Source/Android/src/org
parent9d3d568ae452dcba91f821aa43a249ca12afeb49 (diff)
[Android-overlay] Support touch screen axises in native. Have a non-configurable main joystick on screen at this point.
Diffstat (limited to 'Source/Android/src/org')
-rw-r--r--Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java8
-rw-r--r--Source/Android/src/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlay.java154
-rw-r--r--Source/Android/src/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawableButton.java (renamed from Source/Android/src/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawable.java)8
-rw-r--r--Source/Android/src/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawableJoystick.java140
4 files changed, 264 insertions, 46 deletions
diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java
index 53db64b194..58b33d393d 100644
--- a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java
@@ -60,6 +60,14 @@ public final class NativeLibrary
public static native void onTouchEvent(int Button, int Action);
/**
+ * Handles touch events.
+ *
+ * @param Button Key code identifying which button was pressed.
+ * @param Action Mask for the action being performed.
+ */
+ public static native void onTouchAxisEvent(int Axis, float loc);
+
+ /**
* Handles button press events for a gamepad.
*
* @param Device The input descriptor of the gamepad.
diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlay.java b/Source/Android/src/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlay.java
index 651df513e9..c3b4e5c734 100644
--- a/Source/Android/src/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlay.java
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlay.java
@@ -6,36 +6,41 @@
package org.dolphinemu.dolphinemu.emulation.overlay;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.dolphinemu.dolphinemu.NativeLibrary;
-import org.dolphinemu.dolphinemu.NativeLibrary.ButtonState;
-import org.dolphinemu.dolphinemu.NativeLibrary.ButtonType;
-import org.dolphinemu.dolphinemu.R;
-
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
+import android.graphics.*;
import android.graphics.drawable.Drawable;
import android.preference.PreferenceManager;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.MotionEvent;
+import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
+import org.dolphinemu.dolphinemu.NativeLibrary;
+import org.dolphinemu.dolphinemu.NativeLibrary.ButtonState;
+import org.dolphinemu.dolphinemu.NativeLibrary.ButtonType;
+import org.dolphinemu.dolphinemu.R;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Semaphore;
/**
* Draws the interactive input overlay on top of the
* {@link NativeGLSurfaceView} that is rendering emulation.
*/
-public final class InputOverlay extends SurfaceView implements OnTouchListener
+public final class InputOverlay extends SurfaceView implements OnTouchListener, Runnable
{
- private final Set<InputOverlayDrawable> overlayItems = new HashSet<InputOverlayDrawable>();
+ private final Set<InputOverlayDrawableButton> overlayButtons = new HashSet<InputOverlayDrawableButton>();
+ private final Set<InputOverlayDrawableJoystick> overlayJoysticks = new HashSet<InputOverlayDrawableJoystick>();
+ Semaphore _sema;
+ SurfaceHolder surfaceHolder;
+ Thread thread = null;
/**
* Constructor
*
@@ -47,9 +52,13 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
super(context, attrs);
// Add all the overlay items to the HashSet.
- overlayItems.add(initializeOverlayDrawable(context, R.drawable.button_a, ButtonType.BUTTON_A));
- overlayItems.add(initializeOverlayDrawable(context, R.drawable.button_b, ButtonType.BUTTON_B));
- overlayItems.add(initializeOverlayDrawable(context, R.drawable.button_start, ButtonType.BUTTON_START));
+ overlayButtons.add(initializeOverlayButton(context, R.drawable.button_a, ButtonType.BUTTON_A));
+ overlayButtons.add(initializeOverlayButton(context, R.drawable.button_b, ButtonType.BUTTON_B));
+ overlayButtons.add(initializeOverlayButton(context, R.drawable.button_start, ButtonType.BUTTON_START));
+ overlayJoysticks.add(initializeOverlayJoystick(context,
+ R.drawable.joy_outer, R.drawable.joy_inner,
+ ButtonType.STICK_MAIN_UP, ButtonType.STICK_MAIN_DOWN,
+ ButtonType.STICK_MAIN_LEFT, ButtonType.STICK_MAIN_RIGHT));
// Set the on touch listener.
setOnTouchListener(this);
@@ -59,8 +68,42 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
// Request focus for the overlay so it has priority on presses.
requestFocus();
- }
+ _sema = new Semaphore(0);
+ surfaceHolder = getHolder();
+ surfaceHolder.setFormat(PixelFormat.TRANSPARENT);
+ thread = new Thread(this);
+ thread.start();
+ }
+ private boolean Draw()
+ {
+ if(surfaceHolder.getSurface().isValid()){
+ // Draw everything
+ Canvas canvas = surfaceHolder.lockCanvas();
+ canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
+ for (InputOverlayDrawableButton item : overlayButtons)
+ item.draw(canvas);
+ for (InputOverlayDrawableJoystick item : overlayJoysticks)
+ item.Draw(canvas);
+ surfaceHolder.unlockCanvasAndPost(canvas);
+ return true;
+ }
+ return false;
+ }
+ @Override
+ public void run() {
+ boolean didFirstPost = false;
+ while(!didFirstPost)
+ if (Draw())
+ didFirstPost = true;
+ while(true){
+ try
+ {
+ _sema.acquire();
+ Draw();
+ } catch (InterruptedException ex) {}
+ }
+ }
@Override
public boolean onTouch(View v, MotionEvent event)
{
@@ -69,7 +112,7 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
// The reason it won't work is that when moving an axis, you would get the event MotionEvent.ACTION_MOVE.
int buttonState = (event.getAction() == MotionEvent.ACTION_DOWN) ? ButtonState.PRESSED : ButtonState.RELEASED;
- for (InputOverlayDrawable item : overlayItems)
+ for (InputOverlayDrawableButton item : overlayButtons)
{
// Check if there was a touch within the bounds of a drawable.
if (item.getBounds().contains((int)event.getX(), (int)event.getY()))
@@ -93,24 +136,22 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
}
}
}
-
- return true;
- }
-
- @Override
- public void onDraw(Canvas canvas)
- {
- super.onDraw(canvas);
-
- // Draw all overlay items.
- for (InputOverlayDrawable item : overlayItems)
+ for (InputOverlayDrawableJoystick item : overlayJoysticks)
{
- item.draw(canvas);
+ item.TrackEvent(event);
+ int[] axisIDs = item.getAxisIDs();
+ float[] axises = item.getAxisValues();
+
+ for (int a = 0; a < 4; ++a)
+ NativeLibrary.onTouchAxisEvent(axisIDs[a], axises[a]);
}
+ _sema.release();
+
+ return true;
}
/**
- * Initializes an InputOverlayDrawable, given by resId, with all of the
+ * Initializes an InputOverlayDrawableButton, given by resId, with all of the
* parameters set for it to be properly shown on the InputOverlay.
* <p>
* This works due to the way the X and Y coordinates are stored within
@@ -130,48 +171,77 @@ public final class InputOverlay extends SurfaceView implements OnTouchListener
* </ul>
* <p>
* Technically no modifications should need to be performed on the returned
- * InputOverlayDrawable. Simply add it to the HashSet of overlay items and wait
+ * 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 InputOverlayDrawable represents.
+ * @param buttonId Identifier for determining what type of button the initialized InputOverlayDrawableButton represents.
*
- * @return An {@link InputOverlayDrawable} with the correct drawing bounds set.
+ * @return An {@link InputOverlayDrawableButton} with the correct drawing bounds set.
*
*/
- private static InputOverlayDrawable initializeOverlayDrawable(Context context, int resId, int buttonId)
+ private static InputOverlayDrawableButton initializeOverlayButton(Context context, int resId, int buttonId)
{
// Resources handle for fetching the initial Drawable resource.
final Resources res = context.getResources();
- // SharedPreference to retrieve the X and Y coordinates for the InputOverlayDrawable.
+ // SharedPreference to retrieve the X and Y coordinates for the InputOverlayDrawableButton.
final SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(context);
- // Initialize the InputOverlayDrawable.
+ // Initialize the InputOverlayDrawableButton.
final Bitmap bitmap = BitmapFactory.decodeResource(res, resId);
- final InputOverlayDrawable overlayDrawable = new InputOverlayDrawable(res, bitmap, buttonId);
+ final InputOverlayDrawableButton overlayDrawable = new InputOverlayDrawableButton(res, bitmap, buttonId);
// String ID of the Drawable. This is what is passed into SharedPreferences
// to check whether or not a value has been set.
final String drawableId = res.getResourceEntryName(resId);
- // The X and Y coordinates of the InputOverlayDrawable on the InputOverlay.
+ // 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(drawableId+"-X", 0f);
int drawableY = (int) sPrefs.getFloat(drawableId+"-Y", 0f);
- // Intrinsic width and height of the InputOverlayDrawable.
+ // 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();
- // Now set the bounds for the InputOverlayDrawable.
- // This will dictate where on the screen (and the what the size) the InputOverlayDrawable will be.
+ // 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);
return overlayDrawable;
}
+ private static InputOverlayDrawableJoystick initializeOverlayJoystick(Context context, int resOuter, int resInner, int axisUp, int axisDown, int axisLeft, int axisRight)
+ {
+ // Resources handle for fetching the initial Drawable resource.
+ final Resources res = context.getResources();
+
+ // SharedPreference to retrieve the X and Y coordinates for the InputOverlayDrawableButton.
+ final SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(context);
+
+ // Initialize the InputOverlayDrawableButton.
+ final Bitmap bitmapOuter = BitmapFactory.decodeResource(res, resOuter);
+ final Bitmap bitmapInner = BitmapFactory.decodeResource(res, resInner);
+
+ // Now set the bounds for the InputOverlayDrawableButton.
+ // This will dictate where on the screen (and the what the size) the InputOverlayDrawableButton will be.
+ int outerSize = bitmapOuter.getWidth() + 256;
+ int X = 0;
+ int Y = 0;
+ Rect outerRect = new Rect(X, Y, X + outerSize, Y + outerSize);
+ Rect innerRect = new Rect(0, 0, outerSize / 4, outerSize / 4);
+
+ final InputOverlayDrawableJoystick overlayDrawable
+ = new InputOverlayDrawableJoystick(res,
+ bitmapOuter, bitmapInner,
+ outerRect, innerRect,
+ axisUp, axisDown, axisLeft, axisRight);
+
+
+ return overlayDrawable;
+ }
}
diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawable.java b/Source/Android/src/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawableButton.java
index a4f445b5e3..12343b586f 100644
--- a/Source/Android/src/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawable.java
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawableButton.java
@@ -14,7 +14,7 @@ import android.graphics.drawable.BitmapDrawable;
* Custom {@link BitmapDrawable} that is capable
* of storing it's own ID.
*/
-public class InputOverlayDrawable extends BitmapDrawable
+public class InputOverlayDrawableButton extends BitmapDrawable
{
// The ID identifying what type of button this Drawable represents.
private int buttonType;
@@ -26,7 +26,7 @@ public class InputOverlayDrawable extends BitmapDrawable
* @param bitmap {@link Bitmap} to use with this Drawable.
* @param buttonType Identifier for this type of button.
*/
- public InputOverlayDrawable(Resources res, Bitmap bitmap, int buttonType)
+ public InputOverlayDrawableButton(Resources res, Bitmap bitmap, int buttonType)
{
super(res, bitmap);
@@ -34,9 +34,9 @@ public class InputOverlayDrawable extends BitmapDrawable
}
/**
- * Gets this InputOverlayDrawable's button ID.
+ * Gets this InputOverlayDrawableButton's button ID.
*
- * @return this InputOverlayDrawable's button ID.
+ * @return this InputOverlayDrawableButton's button ID.
*/
public int getId()
{
diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawableJoystick.java b/Source/Android/src/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawableJoystick.java
new file mode 100644
index 0000000000..0ceb5b9186
--- /dev/null
+++ b/Source/Android/src/org/dolphinemu/dolphinemu/emulation/overlay/InputOverlayDrawableJoystick.java
@@ -0,0 +1,140 @@
+/**
+ * Copyright 2013 Dolphin Emulator Project
+ * Licensed under GPLv2
+ * Refer to the license.txt file included.
+ */
+
+package org.dolphinemu.dolphinemu.emulation.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;
+
+/**
+ * Custom {@link android.graphics.drawable.BitmapDrawable} that is capable
+ * of storing it's own ID.
+ */
+public class InputOverlayDrawableJoystick extends BitmapDrawable
+{
+ // The ID identifying what type of button this Drawable represents.
+ private int axisIDs[] = {0, 0, 0, 0};
+ private float axises[] = {0f, 0f};
+ private int trackid = -1;
+ private BitmapDrawable ringInner;
+
+ /**
+ * Constructor
+ *
+ * @param res {@link android.content.res.Resources} instance.
+ * @param bitmapOuter {@link android.graphics.Bitmap} to use with this Drawable.
+ * @param axisUp Identifier for this type of axis.
+ * @param axisDown Identifier for this type of axis.
+ * @param axisLeft Identifier for this type of axis.
+ * @param axisRight Identifier for this type of axis.
+ */
+ public InputOverlayDrawableJoystick(Resources res,
+ Bitmap bitmapOuter, Bitmap bitmapInner,
+ Rect rectOuter, Rect rectInner,
+ int axisUp, int axisDown, int axisLeft, int axisRight)
+ {
+ super(res, bitmapOuter);
+ this.setBounds(rectOuter);
+
+ this.ringInner = new BitmapDrawable(res, bitmapInner);
+ this.ringInner.setBounds(rectInner);
+ SetInnerBounds();
+ this.axisIDs[0] = axisUp;
+ this.axisIDs[1] = axisDown;
+ this.axisIDs[2] = axisLeft;
+ this.axisIDs[3] = axisRight;
+ }
+ public void Draw(Canvas canvas)
+ {
+ this.draw(canvas);
+ ringInner.draw(canvas);
+ }
+ public void TrackEvent(MotionEvent event)
+ {
+ int pointerIndex = event.getActionIndex();
+ if (trackid == -1)
+ {
+ if (event.getAction() == MotionEvent.ACTION_DOWN)
+ if(getBounds().contains((int)event.getX(), (int)event.getY()))
+ trackid = event.getPointerId(pointerIndex);
+ }
+ else
+ {
+ if (event.getAction() == MotionEvent.ACTION_UP)
+ {
+ if (trackid == event.getPointerId(pointerIndex))
+ {
+ axises[0] = axises[1] = 0.0f;
+ SetInnerBounds();
+ trackid = -1;
+ }
+ }
+ }
+ if (trackid == -1)
+ return;
+ float touchX = event.getX();
+ float touchY = event.getY();
+ float maxY = this.getBounds().bottom;
+ float maxX = this.getBounds().right;
+ touchX -= this.getBounds().centerX();
+ maxX -= this.getBounds().centerX();
+ touchY -= this.getBounds().centerY();
+ maxY -= this.getBounds().centerY();
+ final float AxisX = touchX / maxX;
+ final float AxisY = touchY/maxY;
+
+ this.axises[0] = AxisY;
+ this.axises[1] = AxisX;
+
+ SetInnerBounds();
+ }
+ public float[] getAxisValues()
+ {
+ float[] joyaxises = new float[4];
+ if (axises[0] >= 0.0f)
+ {
+ joyaxises[0] = 0.0f;
+ joyaxises[1] = Math.min(axises[0], 1.0f);
+ }
+ else
+ {
+ joyaxises[0] = Math.min(Math.abs(axises[0]), 1.0f);
+ joyaxises[1] = 0.0f;
+ }
+ if (axises[1] >= 0.0)
+ {
+ joyaxises[2] = 0.0f;
+ joyaxises[3] = Math.min(axises[1], 1.0f);
+ }
+ else
+ {
+ joyaxises[2] = Math.min(Math.abs(axises[1]), 1.0f);
+ joyaxises[3] = 0.0f;
+ }
+ return joyaxises;
+ }
+ public int[] getAxisIDs()
+ {
+ return axisIDs;
+ }
+ private void SetInnerBounds()
+ {
+ float floatX = this.getBounds().centerX();
+ float floatY = this.getBounds().centerY();
+ floatY += axises[0] * (this.getBounds().height() / 2);
+ floatX += axises[1] * (this.getBounds().width() / 2);
+ int X = (int)(floatX);
+ int Y = (int)(floatY);
+ int width = this.ringInner.getBounds().width() / 2;
+ int height = this.ringInner.getBounds().height() / 2;
+ this.ringInner.setBounds(X - width, Y - height,
+ X + width, Y + height);
+ }
+}