Permalink
Browse files

Merge pull request #415 from BonzaiThePenguin/master

Drag and drop editing for the touchscreen controls
  • Loading branch information...
littleguy77 committed Feb 26, 2015
2 parents 9cfded0 + 443a05c commit 4d06db689bd6c6fb7e0dfa2520299b4cf806a249
@@ -32,6 +32,7 @@
import paulscode.android.mupen64plusae.util.Utility;
import android.content.res.Resources;
import android.graphics.Point;
+import android.graphics.Rect;
import android.util.FloatMath;
import android.util.Log;
import android.util.SparseArray;
@@ -83,6 +84,9 @@
/** Y-coordinates of the buttons, in percent. */
private final ArrayList<Integer> buttonY;
+ /** names of the buttons. */
+ private final ArrayList<String> buttonNames;
+
/** Analog background image (fixed). */
protected Image analogBackImage;
@@ -177,6 +181,7 @@ public TouchMap( Resources resources )
buttonMasks = new ArrayList<Image>();
buttonX = new ArrayList<Integer>();
buttonY = new ArrayList<Integer>();
+ buttonNames = new ArrayList<String>();
}
/**
@@ -188,6 +193,7 @@ public void clear()
buttonMasks.clear();
buttonX.clear();
buttonY.clear();
+ buttonNames.clear();
analogBackImage = null;
analogForeImage = null;
analogBackX = analogBackY = 0;
@@ -264,6 +270,24 @@ public int getButtonPress( int xLocation, int yLocation )
return UNMAPPED;
}
+ /**
+ * Gets the frame for the N64 button with a given asset name
+ *
+ * @param assetName The asset name for the button
+ *
+ * @return The frame for the N64 button with the given asset name
+ *
+ */
+ public Rect getButtonFrame( String assetName )
+ {
+ for( int i = 0; i < buttonNames.size(); i++ )
+ {
+ if ( buttonNames.get( i ).equals( assetName ) )
+ return new Rect( buttonMasks.get( i ).drawRect );
+ }
+ return new Rect(0, 0, 0, 0);
+ }
+
/**
* Gets the N64 button mapped to a given mask color.
*
@@ -325,6 +349,18 @@ public Point getAnalogDisplacement( int xLocation, int yLocation )
return new Point( dX, dY );
}
+ /**
+ * Gets the N64 analog stick's frame.
+ *
+ * @return The analog stick's frame.
+ */
+ public Rect getAnalogFrame()
+ {
+ if( analogBackImage != null )
+ return new Rect( analogBackImage.drawRect );
+ return new Rect(0, 0, 0, 0);
+ }
+
/**
* Gets the N64 analog stick displacement, constrained to an octagon.
*
@@ -506,6 +542,7 @@ protected void loadButton( Profile profile, String name )
// Position (percentages of the digitizer dimensions)
buttonX.add( x );
buttonY.add( y );
+ buttonNames.add( name );
// Load the displayed and mask images
buttonImages.add( new Image( mResources, skinFolder + "/" + name + ".png" ) );
@@ -37,13 +37,15 @@
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.ActionBar;
+import android.app.ActionBar.OnMenuVisibilityListener;
import android.app.Activity;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Point;
+import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.TextUtils;
@@ -57,6 +59,7 @@
import android.view.View.OnTouchListener;
import android.view.Window;
import android.view.WindowManager.LayoutParams;
+import android.view.SoundEffectConstants;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
@@ -97,6 +100,19 @@
private GameOverlay mOverlay;
private ImageView mSurface;
+ // Live drag and drop editing
+ private int initialX;
+ private int initialY;
+ private int dragIndex;
+ private boolean dragging;
+ private String dragAsset;
+ private int dragX;
+ private int dragY;
+ private Rect dragFrame;
+
+ // Don't enter immersive mode until the ActionBar menus are closed
+ private boolean actionBarMenuOpen = false;
+
@TargetApi( 11 )
@Override
protected void onCreate( Bundle savedInstanceState )
@@ -163,6 +179,18 @@ protected void onCreate( Bundle savedInstanceState )
ColorDrawable color = new ColorDrawable( Color.parseColor( "#303030" ) );
color.setAlpha( mUserPrefs.displayActionBarTransparency );
getActionBar().setBackgroundDrawable( color );
+
+ // onOptionsMenuClosed is not called due to a bug in Android:
+ // http://stackoverflow.com/questions/3688077/android-onoptionsmenuclosed-not-being-called-for-submenu
+ // so add a menu visibility listener instead
+ getActionBar().addOnMenuVisibilityListener( new OnMenuVisibilityListener()
+ {
+ @Override
+ public void onMenuVisibilityChanged( boolean isVisible )
+ {
+ actionBarMenuOpen = isVisible;
+ }
+ });
}
// Initialize the touchmap and overlay
@@ -206,7 +234,7 @@ protected void onResume()
public void onWindowFocusChanged( boolean hasFocus )
{
super.onWindowFocusChanged( hasFocus );
- if( hasFocus )
+ if( hasFocus && !actionBarMenuOpen )
hideSystemBars();
}
@@ -385,37 +413,125 @@ private void hideSystemBars()
@Override
public boolean onTouch( View v, MotionEvent event )
{
- if( ( event.getAction() & MotionEvent.ACTION_MASK ) != MotionEvent.ACTION_DOWN )
- return false;
-
int x = (int) event.getX();
int y = (int) event.getY();
- // Get the N64 index of the button that was pressed
- int index = mTouchscreenMap.getButtonPress( x, y );
- if( index != TouchMap.UNMAPPED )
+ if( ( event.getAction() & MotionEvent.ACTION_MASK ) == MotionEvent.ACTION_DOWN )
{
- String assetName = TouchMap.ASSET_NAMES.get( index );
- String title = READABLE_NAMES.get( index );
+ initialX = x;
+ initialY = y;
+ dragIndex = TouchMap.UNMAPPED;
+ dragging = false;
+ dragAsset = "";
- // D-pad buttons are not holdable
- if( DPAD.equals( assetName ) )
- index = -1;
+ if( AppData.IS_KITKAT && mUserPrefs.isImmersiveModeEnabled )
+ {
+ // ignore edge swipes.
+ // unfortunately KitKat lacks a way to do this on its own,
+ // so just ignore all touches along the edges.
+ // http://stackoverflow.com/questions/20530333/ignore-immersive-mode-swipe
+ View view = getWindow().getDecorView();
+ if ( y < 10 || y > view.getHeight() - 10 || x < 10 || x > view.getWidth() - 10 )
+ return false;
+ }
- popupDialog( assetName, title, index );
+ // Get the N64 index of the button that was pressed
+ int index = mTouchscreenMap.getButtonPress( x, y );
+ if( index != TouchMap.UNMAPPED )
+ {
+ dragIndex = index;
+ dragAsset = TouchMap.ASSET_NAMES.get( index );
+ dragFrame = mTouchscreenMap.getButtonFrame( dragAsset );
+ }
+ else
+ {
+ // See if analog was pressed
+ Point point = mTouchscreenMap.getAnalogDisplacement( x, y );
+ int dX = point.x;
+ int dY = point.y;
+ float displacement = FloatMath.sqrt( ( dX * dX ) + ( dY * dY ) );
+ if( mTouchscreenMap.isInCaptureRange( displacement ) )
+ {
+ dragAsset = ANALOG;
+ dragFrame = mTouchscreenMap.getAnalogFrame();
+ }
+ }
+
+ dragX = mProfile.getInt( dragAsset + TAG_X, INITIAL_ASSET_POS );
+ dragY = mProfile.getInt( dragAsset + TAG_Y, INITIAL_ASSET_POS );
+
+ return true;
}
- else
+ else if( ( event.getAction() & MotionEvent.ACTION_MASK ) == MotionEvent.ACTION_MOVE )
{
- // See if analog was pressed
- Point point = mTouchscreenMap.getAnalogDisplacement( x, y );
- int dX = point.x;
- int dY = point.y;
- float displacement = FloatMath.sqrt( ( dX * dX ) + ( dY * dY ) );
- if( mTouchscreenMap.isInCaptureRange( displacement ) )
- popupDialog( ANALOG, getString( R.string.controller_analog ), -1 );
+ if ( dragIndex != TouchMap.UNMAPPED || ANALOG.equals(dragAsset) )
+ {
+ if ( !dragging )
+ {
+ int dX = x - initialX;
+ int dY = y - initialY;
+ float displacement = FloatMath.sqrt( ( dX * dX ) + ( dY * dY ) );
+ if ( displacement >= 10 )
+ dragging = true;
+ }
+ if ( !dragging )
+ return false;
+
+ // drag this button or analog stick around
+
+ // calculate the X and Y percentage
+ View view = getWindow().getDecorView();
+ int newDragX = ( x - ( initialX - dragFrame.left ) ) * 100/( view.getWidth() - ( dragFrame.right - dragFrame.left ) );
+ int newDragY = ( y - ( initialY - dragFrame.top ) ) * 100/( view.getHeight() - ( dragFrame.bottom - dragFrame.top ) );
+
+ newDragX = Math.min( Math.max( newDragX, 0 ), 100 );
+ newDragY = Math.min( Math.max( newDragY, 0 ), 100 );
+
+ if ( newDragX != dragX || newDragY != dragY )
+ {
+ dragX = newDragX;
+ dragY = newDragY;
+ mProfile.put( dragAsset + TAG_X, String.valueOf( newDragX ) );
+ mProfile.put( dragAsset + TAG_Y, String.valueOf( newDragY ) );
+ refresh();
+ }
+ }
+ }
+ else if( ( event.getAction() & MotionEvent.ACTION_MASK ) == MotionEvent.ACTION_UP )
+ {
+ // if this touch was part of a drag/swipe gesture then don't tap the button
+ if ( dragging )
+ return false;
+
+ // show the editor for the tapped button
+ if ( ANALOG.equals( dragAsset ) )
+ {
+ // play the standard button sound effect
+ View view = getWindow().getDecorView();
+ view.playSoundEffect( SoundEffectConstants.CLICK );
+
+ popupDialog( dragAsset, getString( R.string.controller_analog ), -1 );
+ }
+ else if( dragIndex != TouchMap.UNMAPPED )
+ {
+ int index = dragIndex;
+ String title = READABLE_NAMES.get( dragIndex );
+
+ // D-pad buttons are not holdable
+ if( DPAD.equals( dragAsset ) )
+ index = -1;
+
+ // play the standard button sound effect
+ View view = getWindow().getDecorView();
+ view.playSoundEffect( SoundEffectConstants.CLICK );
+
+ popupDialog( dragAsset, title, index );
+ }
+
+ return true;
}
- return true;
+ return false;
}
@SuppressLint( "InflateParams" )

0 comments on commit 4d06db6

Please sign in to comment.