From 1b285a128823d1d627be6286797f3bc7a8f6aa42 Mon Sep 17 00:00:00 2001 From: littleguy77 Date: Mon, 21 Jan 2013 01:18:45 -0500 Subject: [PATCH] front: Replaced InputMapPreference with InputMapActivity. Controller enabled/disabled is persisted as its own boolean now, rather than being serialized with the input map. This is much more logical and easier to maintain in the long run. Fewer buttons/axes are mapped by default now, to minimize conflicts out of the box. They are - analog stick <-> AXIS_X and AXIS_Y - d-pad <-> KEY_DPAD_* (no AXIS_HAT_*, conflicts w/ Nyko PlayPad) - start, R, L buttons to their virtually universal keycodes A TogglePreference was implemented. Basically a fancier version of a checkbox preference. Besides the slider/toggle widget, the main difference is that clicking on the list item in the preference menu does not do anything (checkbox preference it toggles the check state). This is so that you can handle the click in your own custom way, e.g. to launch an activity like InputMapActivity. To change widget state, you need to click on the widget itself. This imitates the "master on/ off switch" pattern used in the Android settings: http://developer.android.com/design/patterns/settings.html --- res/xml/preferences.xml | 56 ++- .../mupen64plusae/GameLifecycleHandler.java | 8 +- .../mupen64plusae/input/map/InputMap.java | 54 +-- .../persistent/InputMapPreference.java | 376 ------------------ .../persistent/PlayerMapPreference.java | 8 +- .../persistent/TogglePreference.java | 65 +++ .../mupen64plusae/persistent/UserPrefs.java | 62 +-- 7 files changed, 163 insertions(+), 466 deletions(-) delete mode 100644 src/paulscode/android/mupen64plusae/persistent/InputMapPreference.java create mode 100644 src/paulscode/android/mupen64plusae/persistent/TogglePreference.java diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml index c21c6063bc..5d760d60c3 100644 --- a/res/xml/preferences.xml +++ b/res/xml/preferences.xml @@ -143,12 +143,18 @@ android:title="@string/touchpadLayout_title" /> - + android:title="@string/inputMap1_title" > + + + + - - + + + + + - + + + + + + android:title="@string/inputMap4_title" > + + + + mPublisher; @@ -154,27 +151,6 @@ public int get( int inputCode ) return mMap.get( inputCode, UNMAPPED ); } - /** - * Checks if the map is enabled. - * - * @return True, if the map is enabled. - */ - public boolean isEnabled() - { - return mEnabled; - } - - /** - * Enables or disables the map. Note that this does not change the map data itself, but - * rather indicates whether client code should or should not use the map. - * - * @param value True to enable the map; false to disable. - */ - public void setEnabled( boolean value ) - { - mEnabled = value; - } - /** * Maps an input code to an N64/Mupen command. * @@ -271,7 +247,7 @@ public void unregisterListener( Listener listener ) public String serialize() { // Serialize the map data to a multi-delimited string - String result = mEnabled + "/"; + String result = ""; for( int i = 0; i < mMap.size(); i++ ) { // Putting the n64 command first makes the string a bit more human readable IMO @@ -289,28 +265,20 @@ public void deserialize( String s ) { // Reset the map mMap.clear(); - mEnabled = false; // Parse the new map data from the multi-delimited string if( s != null ) { - String[] groups = s.split( "/" ); - if( groups.length == 2 ) + // Read the input mappings + String[] pairs = s.split( "," ); + for( String pair : pairs ) { - // Read the enabled state - mEnabled = SafeMethods.toBoolean( groups[0], false ); - - // Read the input mappings - String[] pairs = groups[1].split( "," ); - for( String pair : pairs ) + String[] elements = pair.split( ":" ); + if( elements.length == 2 ) { - String[] elements = pair.split( ":" ); - if( elements.length == 2 ) - { - int value = SafeMethods.toInt( elements[0], UNMAPPED ); - int key = SafeMethods.toInt( elements[1], 0 ); - mapInput( key, value, false ); - } + int value = SafeMethods.toInt( elements[0], UNMAPPED ); + int key = SafeMethods.toInt( elements[1], 0 ); + mapInput( key, value, false ); } } } diff --git a/src/paulscode/android/mupen64plusae/persistent/InputMapPreference.java b/src/paulscode/android/mupen64plusae/persistent/InputMapPreference.java deleted file mode 100644 index f996462b60..0000000000 --- a/src/paulscode/android/mupen64plusae/persistent/InputMapPreference.java +++ /dev/null @@ -1,376 +0,0 @@ -/** - * Mupen64PlusAE, an N64 emulator for the Android platform - * - * Copyright (C) 2013 Paul Lamb - * - * This file is part of Mupen64PlusAE. - * - * Mupen64PlusAE is free software: you can redistribute it and/or modify it under the terms of the - * GNU General Public License as published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * Mupen64PlusAE is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with Mupen64PlusAE. If - * not, see . - * - * Authors: littleguy77 - */ -package paulscode.android.mupen64plusae.persistent; - -import java.util.List; - -import paulscode.android.mupen64plusae.R; -import paulscode.android.mupen64plusae.input.AbstractController; -import paulscode.android.mupen64plusae.input.map.InputMap; -import paulscode.android.mupen64plusae.input.provider.AbstractProvider; -import paulscode.android.mupen64plusae.input.provider.AxisProvider; -import paulscode.android.mupen64plusae.input.provider.KeyProvider; -import paulscode.android.mupen64plusae.input.provider.KeyProvider.ImeFormula; -import paulscode.android.mupen64plusae.input.provider.LazyProvider; -import paulscode.android.mupen64plusae.util.Prompt; -import paulscode.android.mupen64plusae.util.Prompt.OnInputCodeListener; -import android.annotation.TargetApi; -import android.app.AlertDialog.Builder; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnClickListener; -import android.content.res.TypedArray; -import android.graphics.PorterDuff; -import android.preference.DialogPreference; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.view.View; -import android.view.WindowManager; -import android.widget.Button; -import android.widget.CompoundButton; -import android.widget.TextView; - -public class InputMapPreference extends DialogPreference implements - AbstractProvider.OnInputListener, DialogInterface.OnClickListener, View.OnClickListener, - CompoundButton.OnCheckedChangeListener -{ - private static final float UNMAPPED_BUTTON_ALPHA = 0.2f; - private static final int UNMAPPED_BUTTON_FILTER = 0x66FFFFFF; - private static final int MIN_LAYOUT_WIDTH_DP = 480; - private static final int MIN_LAYOUT_HEIGHT_DP = 480; - private static final String INPUT_MAP1 = "inputMap1"; - - private final InputMap mMap; - private final LazyProvider mProvider; - private CompoundButton mToggleWidget; - private TextView mFeedbackText; - private final Button[] mN64Button; - private List mUnmappableKeyCodes; - private boolean mSpecialKeysVisible = false; - private boolean mDoReclick = false; - - public InputMapPreference( Context context, AttributeSet attrs ) - { - super( context, attrs ); - - mMap = new InputMap(); - mProvider = new LazyProvider(); - mProvider.registerListener( this ); - mN64Button = new Button[InputMap.NUM_MAPPABLES]; - setWidgetLayoutResource( R.layout.widget_toggle ); - - // Select the appropriate dialog layout according to device configuration. Although you can - // do this through the resource directory structure and layout aliases, we'll do it this way - // for now since it's easier to maintain in the short term while the design is in flux. - // TODO: Consider using resource directories to handle device variation, once design is set. - WindowManager manager = (WindowManager) getContext().getSystemService( - Context.WINDOW_SERVICE ); - DisplayMetrics metrics = new DisplayMetrics(); - manager.getDefaultDisplay().getMetrics( metrics ); - float scalefactor = (float) DisplayMetrics.DENSITY_DEFAULT / (float) metrics.densityDpi; - int widthDp = Math.round( metrics.widthPixels * scalefactor ); - int heightDp = Math.round( metrics.heightPixels * scalefactor ); - - // For short screens, hide the dialog title to yield more space - if( heightDp < MIN_LAYOUT_HEIGHT_DP ) - setDialogTitle( null ); - - // For narrow screens, use an alternate layout - if( widthDp < MIN_LAYOUT_WIDTH_DP ) - setDialogLayoutResource( R.layout.input_map_preference_port ); - else - setDialogLayoutResource( R.layout.input_map_preference ); - } - - @Override - protected Object onGetDefaultValue( TypedArray a, int index ) - { - return a.getString( index ); - } - - @Override - protected void onSetInitialValue( boolean restorePersistedValue, Object defaultValue ) - { - if( restorePersistedValue ) - { - // Restore persisted value - mMap.deserialize( getPersistedString( "" ) ); - } - else - { - // Set default state from the XML attribute - String value = (String) defaultValue; - persistString( value ); - mMap.deserialize( value ); - } - updateViews(); - } - - @Override - protected void onBindView( View view ) - { - // Set up the menu item seen in the preferences menu - super.onBindView( view ); - - // Restore the persisted map - mMap.deserialize( getPersistedString( "" ) ); - - // Get the toggle widget and set its state - mToggleWidget = (CompoundButton) view.findViewById( R.id.widgetToggle ); - mToggleWidget.setOnCheckedChangeListener( this ); - mToggleWidget.setChecked( mMap.isEnabled() ); - } - - @Override - protected void onBindDialogView( View view ) - { - // Set up the dialog view seen when the preference menu item is clicked - super.onBindDialogView( view ); - - // Hide some widgets that do not apply - UserPrefs prefs = new UserPrefs( getContext() ); - if( prefs.isTouchpadEnabled && getKey().equals( INPUT_MAP1 ) ) - { - // First player and Xperia PLAY touchpad is enabled, hide the a- and c-pads - view.findViewById( R.id.aPadDefault ).setVisibility( View.GONE ); - view.findViewById( R.id.cPadDefault ).setVisibility( View.GONE ); - } - else - { - // All other cases, hide the Xperia PLAY stuff - view.findViewById( R.id.aPadXperiaPlay ).setVisibility( View.GONE ); - view.findViewById( R.id.cPadXperiaPlay ).setVisibility( View.GONE ); - } - int specialKeyVisibility = mSpecialKeysVisible ? View.VISIBLE : View.GONE; - view.findViewById( R.id.include_all_special_keys ).setVisibility( specialKeyVisibility ); - - // Get the text view object - mFeedbackText = (TextView) view.findViewById( R.id.textFeedback ); - - // Create a button list to simplify highlighting and mapping - // @formatter:off - setupButton( view, R.id.buttonDR, AbstractController.DPD_R ); - setupButton( view, R.id.buttonDL, AbstractController.DPD_L ); - setupButton( view, R.id.buttonDD, AbstractController.DPD_D ); - setupButton( view, R.id.buttonDU, AbstractController.DPD_U ); - setupButton( view, R.id.buttonS, AbstractController.START ); - setupButton( view, R.id.buttonZ, AbstractController.BTN_Z ); - setupButton( view, R.id.buttonB, AbstractController.BTN_B ); - setupButton( view, R.id.buttonA, AbstractController.BTN_A ); - setupButton( view, R.id.buttonCR, AbstractController.CPD_R ); - setupButton( view, R.id.buttonCL, AbstractController.CPD_L ); - setupButton( view, R.id.buttonCD, AbstractController.CPD_D ); - setupButton( view, R.id.buttonCU, AbstractController.CPD_U ); - setupButton( view, R.id.buttonR, AbstractController.BTN_R ); - setupButton( view, R.id.buttonL, AbstractController.BTN_L ); - setupButton( view, R.id.buttonMempak, AbstractController.BTN_MEMPAK ); - setupButton( view, R.id.buttonRumble, AbstractController.BTN_RUMBLEPAK ); - setupButton( view, R.id.buttonAR, InputMap.AXIS_R ); - setupButton( view, R.id.buttonAL, InputMap.AXIS_L ); - setupButton( view, R.id.buttonAD, InputMap.AXIS_D ); - setupButton( view, R.id.buttonAU, InputMap.AXIS_U ); - setupButton( view, R.id.buttonIncrementSlot, InputMap.FUNC_INCREMENT_SLOT ); - setupButton( view, R.id.buttonSaveSlot, InputMap.FUNC_SAVE_SLOT ); - setupButton( view, R.id.buttonReset, InputMap.FUNC_RESET ); - setupButton( view, R.id.buttonLoadSlot, InputMap.FUNC_LOAD_SLOT ); - setupButton( view, R.id.buttonPause, InputMap.FUNC_PAUSE ); - setupButton( view, R.id.buttonStop, InputMap.FUNC_STOP ); - setupButton( view, R.id.buttonSpeedDown, InputMap.FUNC_SPEED_DOWN ); - setupButton( view, R.id.buttonSpeedUp, InputMap.FUNC_SPEED_UP ); - setupButton( view, R.id.buttonFastForward, InputMap.FUNC_FAST_FORWARD ); - // setupButton( view, R.id.buttonFrameAdvance, InputMap.FUNC_FRAME_ADVANCE ); - // setupButton( view, R.id.buttonGameshark, InputMap.FUNC_GAMESHARK ); - // @formatter:on - - // Setup analog axis listening, if applicable - if( AppData.IS_HONEYCOMB_MR1 ) - mProvider.addProvider( new AxisProvider( view ) ); - - // Refresh the dialog view - updateViews(); - } - - @Override - protected void onPrepareDialogBuilder( Builder builder ) - { - super.onPrepareDialogBuilder( builder ); - - // Setup key listening - mUnmappableKeyCodes = ( new UserPrefs( getContext() ) ).unmappableKeyCodes; - mProvider.addProvider( new KeyProvider( builder, ImeFormula.DEFAULT, mUnmappableKeyCodes ) ); - - // Add neutral button to toggle special function visibility - int resId = mSpecialKeysVisible - ? R.string.inputMapPreference_hideSpecial - : R.string.inputMapPreference_showSpecial; - builder.setNeutralButton( resId, new OnClickListener() - { - @Override - public void onClick( DialogInterface dialog, int which ) - { - mSpecialKeysVisible = !mSpecialKeysVisible; - mDoReclick = true; - } - } ); - } - - @Override - protected void onDialogClosed( boolean positiveResult ) - { - // Unregister parent providers, new ones added on next click - mProvider.removeAllProviders(); - - // Clicking Cancel or Ok returns us to the parent preference menu. We must return to a clean - // state so that the toggle doesn't persist unwanted changes. - - if( mDoReclick ) - { - // User pressed neutral button: keep dirty state by immediately reopening - mDoReclick = false; - onClick(); - } - else if( positiveResult ) - { - // User pressed Ok: clean the state by persisting map - persistString( mMap.serialize() ); - notifyChanged(); - } - else - { - // User pressed Cancel/Back: clean the state by restoring map - mMap.deserialize( getPersistedString( "" ) ); - } - } - - @Override - public void onClick( View view ) - { - // Handle button clicks in the mapping screen - Button button; - for( int i = 0; i < mN64Button.length; i++ ) - { - // Find the button that was pressed - if( view.equals( mN64Button[i] ) ) - { - // Popup a dialog to listen to input codes from user - final int index = i; - button = (Button) view; - String message = getContext().getString( R.string.inputMapPreference_popupMessage, - mMap.getMappedCodeInfo( index ) ); - String btnText = getContext().getString( R.string.inputMapPreference_popupUnmap ); - - Prompt.promptInputCode( getContext(), button.getText(), message, btnText, - mUnmappableKeyCodes, new OnInputCodeListener() - { - @Override - public void OnInputCode( int inputCode, int hardwareId ) - { - if( inputCode == 0 ) - mMap.unmapCommand( index ); - else - mMap.map( inputCode, index ); - updateViews(); - } - } ); - } - } - } - - @Override - public void onCheckedChanged( CompoundButton buttonView, boolean isChecked ) - { - // Handle the toggle button in the preferences menu - if( buttonView.equals( mToggleWidget ) ) - { - mMap.setEnabled( isChecked ); - persistString( mMap.serialize() ); - } - } - - @Override - public void onInput( int inputCode, float strength, int hardwareId ) - { - updateViews( inputCode, strength ); - } - - @Override - public void onInput( int[] inputCodes, float[] strengths, int hardwareId ) - { - // Nothing to do here, just implement the interface - } - - @TargetApi( 11 ) - private void updateViews( int inputCode, float strength ) - { - // Modify the button appearance to provide feedback to user - int selectedIndex = mMap.get( inputCode ); - for( int i = 0; i < mN64Button.length; i++ ) - { - // Highlight the currently active button - Button button = mN64Button[i]; - if( button != null ) - { - button.setPressed( i == selectedIndex - && strength > AbstractProvider.STRENGTH_THRESHOLD ); - - // Fade any buttons that aren't mapped - if( AppData.IS_HONEYCOMB ) - { - if( mMap.isMapped( i ) ) - button.setAlpha( 1 ); - else - button.setAlpha( UNMAPPED_BUTTON_ALPHA ); - } - else - { - // For older APIs try something similar (not quite the same) - if( mMap.isMapped( i ) ) - button.getBackground().clearColorFilter(); - else - button.getBackground().setColorFilter( UNMAPPED_BUTTON_FILTER, - PorterDuff.Mode.MULTIPLY ); - button.invalidate(); - } - } - } - - // Update the feedback text (not all layouts include this, so check null) - if( mFeedbackText != null ) - { - mFeedbackText.setText( strength > AbstractProvider.STRENGTH_THRESHOLD - ? AbstractProvider.getInputName( inputCode ) - : "" ); - } - } - - private void updateViews() - { - // Default update, don't highlight anything - updateViews( 0, 0 ); - } - - private void setupButton( View parentView, int resId, int index ) - { - mN64Button[index] = (Button) parentView.findViewById( resId ); - if( mN64Button[index] != null ) - mN64Button[index].setOnClickListener( this ); - } -} diff --git a/src/paulscode/android/mupen64plusae/persistent/PlayerMapPreference.java b/src/paulscode/android/mupen64plusae/persistent/PlayerMapPreference.java index 748dc262f3..920306612b 100644 --- a/src/paulscode/android/mupen64plusae/persistent/PlayerMapPreference.java +++ b/src/paulscode/android/mupen64plusae/persistent/PlayerMapPreference.java @@ -90,10 +90,10 @@ protected void onBindDialogView( View view ) mMap.deserialize( mValue ); // Initialize and refresh the widgets - buttonPlayer1 = setupButton( view, R.id.btnPlayer1, prefs.inputMap1.isEnabled() ); - buttonPlayer2 = setupButton( view, R.id.btnPlayer2, prefs.inputMap2.isEnabled() ); - buttonPlayer3 = setupButton( view, R.id.btnPlayer3, prefs.inputMap3.isEnabled() ); - buttonPlayer4 = setupButton( view, R.id.btnPlayer4, prefs.inputMap4.isEnabled() ); + buttonPlayer1 = setupButton( view, R.id.btnPlayer1, prefs.isInputEnabled1 ); + buttonPlayer2 = setupButton( view, R.id.btnPlayer2, prefs.isInputEnabled2 ); + buttonPlayer3 = setupButton( view, R.id.btnPlayer3, prefs.isInputEnabled3 ); + buttonPlayer4 = setupButton( view, R.id.btnPlayer4, prefs.isInputEnabled4 ); updateViews(); } diff --git a/src/paulscode/android/mupen64plusae/persistent/TogglePreference.java b/src/paulscode/android/mupen64plusae/persistent/TogglePreference.java new file mode 100644 index 0000000000..4f89bc2af0 --- /dev/null +++ b/src/paulscode/android/mupen64plusae/persistent/TogglePreference.java @@ -0,0 +1,65 @@ +package paulscode.android.mupen64plusae.persistent; + +import paulscode.android.mupen64plusae.R; +import android.content.Context; +import android.content.res.TypedArray; +import android.preference.Preference; +import android.util.AttributeSet; +import android.view.View; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; + +public class TogglePreference extends Preference implements OnCheckedChangeListener +{ + private boolean mValue; + + public TogglePreference( Context context, AttributeSet attrs ) + { + super( context, attrs ); + + // Add a toggle to the preference + setWidgetLayoutResource( R.layout.widget_toggle ); + } + + public void setValue( boolean value ) + { + mValue = value; + if( shouldPersist() ) + persistBoolean( mValue ); + } + + public boolean getValue() + { + return mValue; + } + + @Override + protected Object onGetDefaultValue( TypedArray a, int index ) + { + return a.getBoolean( index, false ); + } + + @Override + protected void onSetInitialValue( boolean restorePersistedValue, Object defaultValue ) + { + setValue( restorePersistedValue ? getPersistedBoolean( mValue ) : (Boolean) defaultValue ); + } + + @Override + protected void onBindView( View view ) + { + // Set up the menu item seen in the preferences menu + super.onBindView( view ); + + // Get the toggle widget, set its state, and define its callback + CompoundButton toggleWidget = (CompoundButton) view.findViewById( R.id.widgetToggle ); + toggleWidget.setChecked( mValue ); + toggleWidget.setOnCheckedChangeListener( this ); + } + + @Override + public void onCheckedChanged( CompoundButton buttonView, boolean isChecked ) + { + setValue( isChecked ); + } +} diff --git a/src/paulscode/android/mupen64plusae/persistent/UserPrefs.java b/src/paulscode/android/mupen64plusae/persistent/UserPrefs.java index a3ecd3afee..d0f3d05033 100644 --- a/src/paulscode/android/mupen64plusae/persistent/UserPrefs.java +++ b/src/paulscode/android/mupen64plusae/persistent/UserPrefs.java @@ -121,27 +121,39 @@ public class UserPrefs /** The filename of the selected touchscreen layout. */ public final String touchscreenLayout; - /** True if Xperia Play-specific features are enabled. */ + /** True if Xperia Play touchpad is enabled. */ public final boolean isTouchpadEnabled; /** The filename of the selected Xperia Play layout. */ public final String touchpadLayout; - /** The player map for multi-player gaming. */ - public final PlayerMap playerMap; + /** True if Player 1's controller is enabled. */ + public final boolean isInputEnabled1; + + /** True if Player 2's controller is enabled. */ + public final boolean isInputEnabled2; + + /** True if Player 3's controller is enabled. */ + public final boolean isInputEnabled3; - /** The button map for player 1. */ + /** True if Player 4's controller is enabled. */ + public final boolean isInputEnabled4; + + /** The button map for Player 1. */ public final InputMap inputMap1; - /** The button map for player 2. */ + /** The button map for Player 2. */ public final InputMap inputMap2; - /** The button map for player 3. */ + /** The button map for Player 3. */ public final InputMap inputMap3; - /** The button map for player 4. */ + /** The button map for Player 4. */ public final InputMap inputMap4; + /** The player map for multi-player gaming. */ + public final PlayerMap playerMap; + /** True if any type of AbstractController is enabled for Player 1. */ public final boolean isPlugged1; @@ -235,7 +247,7 @@ public class UserPrefs // ... add more as needed // Shared preferences default values - private static final String DEFAULT_MAP_STRING = ""; + private static final String DEFAULT_MAP_STRING = "0:22,1:21,2:20,3:19,4:108,12:103,13:102,16:-1,17:-2,18:-3,19:-4"; private static final boolean DEFAULT_SPECIAL_VISIBILITY = false; // ... add more as needed @@ -281,15 +293,19 @@ public UserPrefs( Context context ) isTouchpadEnabled = mPreferences.getBoolean( "touchpadEnabled", false ); touchpadLayout = appData.touchpadLayoutsDir + mPreferences.getString( "touchpadLayout", "" ); - // Controller prefs - playerMap = new PlayerMap( mPreferences.getString( "playerMap", "" ) ); - inputMap1 = new InputMap( mPreferences.getString( "inputMap1", "" ) ); - inputMap2 = new InputMap( mPreferences.getString( "inputMap2", "" ) ); - inputMap3 = new InputMap( mPreferences.getString( "inputMap3", "" ) ); - inputMap4 = new InputMap( mPreferences.getString( "inputMap4", "" ) ); - // Input prefs isOctagonalJoystick = mPreferences.getBoolean( "inputOctagonConstraints", true ); + isInputEnabled1 = mPreferences.getBoolean( "inputEnabled1", false ); + isInputEnabled2 = mPreferences.getBoolean( "inputEnabled2", false ); + isInputEnabled3 = mPreferences.getBoolean( "inputEnabled3", false ); + isInputEnabled4 = mPreferences.getBoolean( "inputEnabled4", false ); + + // Controller prefs + inputMap1 = new InputMap( getMapString( 1 ) ); + inputMap2 = new InputMap( getMapString( 2 ) ); + inputMap3 = new InputMap( getMapString( 3 ) ); + inputMap4 = new InputMap( getMapString( 4 ) ); + playerMap = new PlayerMap( mPreferences.getString( "playerMap", "" ) ); // Video prefs videoOrientation = getSafeInt( mPreferences, "videoOrientation", 0 ); @@ -353,17 +369,17 @@ else if( isFpsEnabled ) touchscreenLayout = folder; // Determine which players are "plugged in" - isPlugged1 = inputMap1.isEnabled() || isTouchscreenEnabled || isTouchpadEnabled; - isPlugged2 = inputMap2.isEnabled(); - isPlugged3 = inputMap3.isEnabled(); - isPlugged4 = inputMap4.isEnabled(); + isPlugged1 = isInputEnabled1 || isTouchscreenEnabled || isTouchpadEnabled; + isPlugged2 = isInputEnabled2; + isPlugged3 = isInputEnabled3; + isPlugged4 = isInputEnabled4; // Determine whether controller deconfliction is needed int numControllers = 0; - numControllers += inputMap1.isEnabled() ? 1 : 0; - numControllers += inputMap2.isEnabled() ? 1 : 0; - numControllers += inputMap3.isEnabled() ? 1 : 0; - numControllers += inputMap4.isEnabled() ? 1 : 0; + numControllers += isInputEnabled1 ? 1 : 0; + numControllers += isInputEnabled2 ? 1 : 0; + numControllers += isInputEnabled3 ? 1 : 0; + numControllers += isInputEnabled4 ? 1 : 0; boolean isControllerShared = mPreferences.getBoolean( "inputShareController", false ); playerMap.setEnabled( numControllers > 1 && !isControllerShared );