Skip to content
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.
You can’t perform that action at this time.