diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 96af607bb..be35c71fe 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -43,9 +43,9 @@ android:value="com.github.stenzek.duckstation.MainActivity" /> dialog.dismiss())) + .setNegativeButton(R.string.controller_mapping_activity_cancel, ((dialog, which) -> dialog.dismiss())) .create() .show(); } @@ -140,7 +141,7 @@ public class ControllerMappingActivity extends AppCompatActivity { return; } - Toast.makeText(ControllerMappingActivity.this, String.format(ControllerMappingActivity.this.getString(R.string.controller_mapping_activity_input_profile_saved), name), + Toast.makeText(ControllerSettingsActivity.this, String.format(ControllerSettingsActivity.this.getString(R.string.controller_mapping_activity_input_profile_saved), name), Toast.LENGTH_LONG).show(); }); builder.setNegativeButton(R.string.controller_mapping_activity_cancel, (dialog, which) -> dialog.dismiss()); @@ -159,57 +160,150 @@ public class ControllerMappingActivity extends AppCompatActivity { pref.updateValue(); } - public static class ControllerPortFragment extends PreferenceFragmentCompat { - private ControllerMappingActivity activity; - private int controllerIndex; + public static class SettingsFragment extends PreferenceFragmentCompat { + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + setPreferencesFromResource(R.xml.controllers_preferences, rootKey); + } + } - public ControllerPortFragment(ControllerMappingActivity activity, int controllerIndex) { + public static class ControllerPortFragment extends PreferenceFragmentCompat { + private ControllerSettingsActivity activity; + private int controllerIndex; + private PreferenceCategory mButtonsCategory; + private PreferenceCategory mAxisCategory; + private PreferenceCategory mSettingsCategory; + + public ControllerPortFragment(ControllerSettingsActivity activity, int controllerIndex) { this.activity = activity; this.controllerIndex = controllerIndex; } @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + final PreferenceScreen ps = getPreferenceManager().createPreferenceScreen(getContext()); + setPreferenceScreen(ps); + createPreferences(); + } + + private SwitchPreferenceCompat createTogglePreference(String key, int title, int summary, boolean defaultValue) { + final SwitchPreferenceCompat pref = new SwitchPreferenceCompat(getContext()); + pref.setKey(key); + pref.setTitle(title); + pref.setSummary(summary); + pref.setIconSpaceReserved(false); + pref.setDefaultValue(defaultValue); + return pref; + } + + private void createPreferences() { + final PreferenceScreen ps = getPreferenceScreen(); final SharedPreferences sp = getPreferenceManager().getSharedPreferences(); final String defaultControllerType = controllerIndex == 0 ? "DigitalController" : "None"; - final String controllerType = sp.getString(String.format("Controller%d/Type", controllerIndex), defaultControllerType); + final String controllerTypeKey = String.format("Controller%d/Type", controllerIndex); + final String controllerType = sp.getString(controllerTypeKey, defaultControllerType); + final String[] controllerButtons = AndroidHostInterface.getControllerButtonNames(controllerType); + final String[] axisButtons = AndroidHostInterface.getControllerAxisNames(controllerType); + final int vibrationMotors = AndroidHostInterface.getControllerVibrationMotorCount(controllerType); + + final ListPreference typePreference = new ListPreference(getContext()); + typePreference.setEntries(R.array.settings_controller_type_entries); + typePreference.setEntryValues(R.array.settings_controller_type_values); + typePreference.setKey(controllerTypeKey); + typePreference.setTitle(R.string.settings_controller_type); + typePreference.setSummaryProvider(ListPreference.SimpleSummaryProvider.getInstance()); + typePreference.setIconSpaceReserved(false); + typePreference.setOnPreferenceChangeListener((pref, value) -> { + removePreferences(); + createPreferences(value.toString()); + return true; + }); + ps.addPreference(typePreference); + + mButtonsCategory = new PreferenceCategory(getContext()); + mButtonsCategory.setTitle(getContext().getString(R.string.controller_settings_category_button_bindings)); + mButtonsCategory.setIconSpaceReserved(false); + ps.addPreference(mButtonsCategory); + + mAxisCategory = new PreferenceCategory(getContext()); + mAxisCategory.setTitle(getContext().getString(R.string.controller_settings_category_axis_bindings)); + mAxisCategory.setIconSpaceReserved(false); + ps.addPreference(mAxisCategory); + + mSettingsCategory = new PreferenceCategory(getContext()); + mSettingsCategory.setTitle(getContext().getString(R.string.controller_settings_category_settings)); + mSettingsCategory.setIconSpaceReserved(false); + ps.addPreference(mSettingsCategory); + + createPreferences(controllerType); + } + + private void createPreferences(String controllerType) { + final PreferenceScreen ps = getPreferenceScreen(); + final SharedPreferences sp = getPreferenceManager().getSharedPreferences(); final String[] controllerButtons = AndroidHostInterface.getControllerButtonNames(controllerType); final String[] axisButtons = AndroidHostInterface.getControllerAxisNames(controllerType); final int vibrationMotors = AndroidHostInterface.getControllerVibrationMotorCount(controllerType); - final PreferenceScreen ps = getPreferenceManager().createPreferenceScreen(getContext()); if (controllerButtons != null) { for (String buttonName : controllerButtons) { final ControllerBindingPreference cbp = new ControllerBindingPreference(getContext(), null); cbp.initButton(controllerIndex, buttonName); - ps.addPreference(cbp); + mButtonsCategory.addPreference(cbp); activity.mPreferences.add(cbp); } } + if (axisButtons != null) { for (String axisName : axisButtons) { final ControllerBindingPreference cbp = new ControllerBindingPreference(getContext(), null); cbp.initAxis(controllerIndex, axisName); - ps.addPreference(cbp); + mAxisCategory.addPreference(cbp); activity.mPreferences.add(cbp); } } + if (vibrationMotors > 0) { final ControllerBindingPreference cbp = new ControllerBindingPreference(getContext(), null); cbp.initVibration(controllerIndex); - ps.addPreference(cbp); + mSettingsCategory.addPreference(cbp); activity.mPreferences.add(cbp); } - setPreferenceScreen(ps); + if (controllerType.equals("AnalogController")) { + mSettingsCategory.addPreference( + createTogglePreference(String.format("Controller%d/ForceAnalogOnReset", controllerIndex), + R.string.settings_use_analog_sticks_for_dpad, R.string.settings_summary_enable_analog_mode_on_reset, true)); + + mSettingsCategory.addPreference( + createTogglePreference(String.format("Controller%d/AnalogDPadInDigitalMode", controllerIndex), + R.string.settings_enable_analog_mode_on_reset, R.string.settings_summary_use_analog_sticks_for_dpad, true)); + } + } + + private void removePreferences() { + for (int i = 0; i < mButtonsCategory.getPreferenceCount(); i++) { + activity.mPreferences.remove(mButtonsCategory.getPreference(i)); + } + mButtonsCategory.removeAll(); + + for (int i = 0; i < mAxisCategory.getPreferenceCount(); i++) { + activity.mPreferences.remove(mAxisCategory.getPreference(i)); + } + mAxisCategory.removeAll(); + + for (int i = 0; i < mSettingsCategory.getPreferenceCount(); i++) { + activity.mPreferences.remove(mSettingsCategory.getPreference(i)); + } + mSettingsCategory.removeAll(); } } public static class HotkeyFragment extends PreferenceFragmentCompat { - private ControllerMappingActivity activity; + private ControllerSettingsActivity activity; private HotkeyInfo[] mHotkeyInfo; - public HotkeyFragment(ControllerMappingActivity activity) { + public HotkeyFragment(ControllerSettingsActivity activity) { this.activity = activity; this.mHotkeyInfo = AndroidHostInterface.getInstance().getHotkeyInfoList(); } @@ -231,56 +325,65 @@ public class ControllerMappingActivity extends AppCompatActivity { } public static class SettingsCollectionFragment extends Fragment { - private ControllerMappingActivity activity; + private ControllerSettingsActivity activity; private SettingsCollectionAdapter adapter; private ViewPager2 viewPager; + private String[] controllerPortNames; - public SettingsCollectionFragment(ControllerMappingActivity activity) { + public SettingsCollectionFragment(ControllerSettingsActivity activity) { this.activity = activity; + + controllerPortNames = new String[] { "Port 1", "Port 2" }; } @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_controller_mapping, container, false); + return inflater.inflate(R.layout.fragment_controller_settings, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - adapter = new SettingsCollectionAdapter(activity, this); + adapter = new SettingsCollectionAdapter(activity, this, controllerPortNames.length); viewPager = view.findViewById(R.id.view_pager); viewPager.setAdapter(adapter); TabLayout tabLayout = view.findViewById(R.id.tab_layout); new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> { - if (position == NUM_CONTROLLER_PORTS) - tab.setText("Hotkeys"); + if (position == 0) + tab.setText(R.string.controller_settings_tab_settings); + else if (position <= controllerPortNames.length) + tab.setText(controllerPortNames[position - 1]); else - tab.setText(String.format("Port %d", position + 1)); + tab.setText(R.string.controller_settings_tab_hotkeys); }).attach(); } } public static class SettingsCollectionAdapter extends FragmentStateAdapter { - private ControllerMappingActivity activity; + private ControllerSettingsActivity activity; + private int controllerPorts; - public SettingsCollectionAdapter(@NonNull ControllerMappingActivity activity, @NonNull Fragment fragment) { + public SettingsCollectionAdapter(@NonNull ControllerSettingsActivity activity, @NonNull Fragment fragment, int controllerPorts) { super(fragment); this.activity = activity; + this.controllerPorts = controllerPorts; } @NonNull @Override public Fragment createFragment(int position) { - if (position != NUM_CONTROLLER_PORTS) - return new ControllerPortFragment(activity, position + 1); + if (position == 0) + return new SettingsFragment(); + else if (position <= controllerPorts) + return new ControllerPortFragment(activity, position); else return new HotkeyFragment(activity); } @Override public int getItemCount() { - return NUM_CONTROLLER_PORTS + 1; + return NUM_CONTROLLER_PORTS + 2; } } } \ No newline at end of file diff --git a/android/app/src/main/java/com/github/stenzek/duckstation/GamePropertiesActivity.java b/android/app/src/main/java/com/github/stenzek/duckstation/GamePropertiesActivity.java index 86165abca..cd0847d2f 100644 --- a/android/app/src/main/java/com/github/stenzek/duckstation/GamePropertiesActivity.java +++ b/android/app/src/main/java/com/github/stenzek/duckstation/GamePropertiesActivity.java @@ -1,16 +1,11 @@ package com.github.stenzek.duckstation; -import android.content.SharedPreferences; import android.os.Bundle; -import android.util.Property; import android.view.LayoutInflater; -import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.widget.EditText; import android.widget.ListAdapter; -import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -20,7 +15,6 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; import androidx.fragment.app.ListFragment; import androidx.preference.PreferenceFragmentCompat; -import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import androidx.viewpager2.adapter.FragmentStateAdapter; import androidx.viewpager2.widget.ViewPager2; @@ -28,8 +22,6 @@ import androidx.viewpager2.widget.ViewPager2; import com.google.android.material.tabs.TabLayout; import com.google.android.material.tabs.TabLayoutMediator; -import java.util.ArrayList; - public class GamePropertiesActivity extends AppCompatActivity { PropertyListAdapter mPropertiesListAdapter; GameListEntry mGameListEntry; @@ -183,7 +175,7 @@ public class GamePropertiesActivity extends AppCompatActivity { @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_controller_mapping, container, false); + return inflater.inflate(R.layout.fragment_controller_settings, container, false); } @Override diff --git a/android/app/src/main/java/com/github/stenzek/duckstation/MainActivity.java b/android/app/src/main/java/com/github/stenzek/duckstation/MainActivity.java index 9db6d5e48..7f87cb476 100644 --- a/android/app/src/main/java/com/github/stenzek/duckstation/MainActivity.java +++ b/android/app/src/main/java/com/github/stenzek/duckstation/MainActivity.java @@ -26,8 +26,6 @@ import androidx.appcompat.app.AppCompatDelegate; import androidx.appcompat.widget.Toolbar; import androidx.core.app.ActivityCompat; import androidx.core.content.ContextCompat; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentFactory; import androidx.preference.PreferenceManager; import java.io.ByteArrayOutputStream; @@ -237,8 +235,8 @@ public class MainActivity extends AppCompatActivity { Intent intent = new Intent(this, SettingsActivity.class); startActivityForResult(intent, REQUEST_SETTINGS); return true; - } else if (id == R.id.action_controller_mapping) { - Intent intent = new Intent(this, ControllerMappingActivity.class); + } else if (id == R.id.action_controller_settings) { + Intent intent = new Intent(this, ControllerSettingsActivity.class); startActivity(intent); return true; } else if (id == R.id.action_switch_view) { diff --git a/android/app/src/main/java/com/github/stenzek/duckstation/SettingsActivity.java b/android/app/src/main/java/com/github/stenzek/duckstation/SettingsActivity.java index df106181f..16d879a7f 100644 --- a/android/app/src/main/java/com/github/stenzek/duckstation/SettingsActivity.java +++ b/android/app/src/main/java/com/github/stenzek/duckstation/SettingsActivity.java @@ -107,13 +107,10 @@ public class SettingsActivity extends AppCompatActivity { case 3: // Enhancements return new SettingsFragment(R.xml.enhancements_preferences); - case 4: // Controllers - return new SettingsFragment(R.xml.controllers_preferences); - - case 5: // Achievements + case 4: // Achievements return new AchievementSettingsFragment(); - case 6: // Advanced + case 5: // Advanced return new SettingsFragment(R.xml.advanced_preferences); default: @@ -123,7 +120,7 @@ public class SettingsActivity extends AppCompatActivity { @Override public int getItemCount() { - return 7; + return 6; } } } \ No newline at end of file diff --git a/android/app/src/main/res/layout/fragment_controller_mapping.xml b/android/app/src/main/res/layout/fragment_controller_settings.xml similarity index 91% rename from android/app/src/main/res/layout/fragment_controller_mapping.xml rename to android/app/src/main/res/layout/fragment_controller_settings.xml index d60ed84ea..a47a49de4 100644 --- a/android/app/src/main/res/layout/fragment_controller_mapping.xml +++ b/android/app/src/main/res/layout/fragment_controller_settings.xml @@ -10,7 +10,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" app:tabTextAppearance="@style/TabTextAppearance" - app:tabMode="fixed" /> + app:tabMinWidth="150dp" + app:tabMode="scrollable" /> + android:orderInCategory="102" + android:title="@string/action_controller_mapping" + app:showAsAction="ifRoom" /> diff --git a/android/app/src/main/res/values-es/arrays.xml b/android/app/src/main/res/values-es/arrays.xml index bdf4c4e08..a5724e92e 100644 --- a/android/app/src/main/res/values-es/arrays.xml +++ b/android/app/src/main/res/values-es/arrays.xml @@ -69,8 +69,11 @@ xBR (Sin unión de bordes) + None Control Digital (Mando) Control Analógico (DualShock) + Analog Joystick + NeGcon Sin tarjeta de memoria @@ -139,7 +142,6 @@ Pantalla Audio Mejoras - Controles Achievements Avanzado diff --git a/android/app/src/main/res/values-it/arrays.xml b/android/app/src/main/res/values-it/arrays.xml index a0fb37e2d..abaadd120 100644 --- a/android/app/src/main/res/values-it/arrays.xml +++ b/android/app/src/main/res/values-it/arrays.xml @@ -69,8 +69,11 @@ xBR (No Blending Bordi) + None Controller Digitale (Gamepad) Controller Analogico (DualShock) + Analog Joystick + NeGcon No Memory Card @@ -139,7 +142,6 @@ Display Audio Miglioramenti - Controller Achievements Avanzate diff --git a/android/app/src/main/res/values-nl/arrays.xml b/android/app/src/main/res/values-nl/arrays.xml index bfb95f2a7..0d36a1d14 100644 --- a/android/app/src/main/res/values-nl/arrays.xml +++ b/android/app/src/main/res/values-nl/arrays.xml @@ -69,8 +69,11 @@ xBR (Geen Edge Blending) + None Digitale Controller (Gamepad) Analoge Controller (DualShock) + Analog Joystick + NeGcon Geen Geheugenkaart @@ -139,7 +142,6 @@ Weergave Audio Verbeteringen - Controllers Achievements Geavanceerd diff --git a/android/app/src/main/res/values-pt-rBR/arrays.xml b/android/app/src/main/res/values-pt-rBR/arrays.xml index ba286ee0d..6a43906b7 100644 --- a/android/app/src/main/res/values-pt-rBR/arrays.xml +++ b/android/app/src/main/res/values-pt-rBR/arrays.xml @@ -69,8 +69,11 @@ xBR (Sem ajustes laterais) + None Controle Digital (Gamepad) Controle Analógico (DualShock) + Analog Joystick + NeGcon Sem Cartão de Memória @@ -139,7 +142,6 @@ Vídeo Áudio Melhorias - Controles Achievements Avançado diff --git a/android/app/src/main/res/values-ru/arrays.xml b/android/app/src/main/res/values-ru/arrays.xml index 7b3d17d11..768d9e6e0 100644 --- a/android/app/src/main/res/values-ru/arrays.xml +++ b/android/app/src/main/res/values-ru/arrays.xml @@ -69,8 +69,11 @@ xBR (без сглаживания краёв) + None Цифровой Аналоговый (DualShock) + Analog Joystick + NeGcon Без карты памяти @@ -145,7 +148,6 @@ Экран Звук Улучшения - Контроллеры Достижения Расширенные diff --git a/android/app/src/main/res/values/arrays.xml b/android/app/src/main/res/values/arrays.xml index 450aa5559..5e40dc8aa 100644 --- a/android/app/src/main/res/values/arrays.xml +++ b/android/app/src/main/res/values/arrays.xml @@ -138,12 +138,18 @@ xBRBinAlpha + None Digital Controller (Gamepad) Analog Controller (DualShock) + Analog Joystick + NeGcon + None DigitalController AnalogController + AnalogJoystick + NeGcon No Memory Card @@ -265,7 +271,6 @@ Display Audio Enhancements - Controllers Achievements Advanced diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index cc92a4237..3f92b2e5f 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -1,7 +1,7 @@ DuckStation Settings - Controller Mapping + Controller Settings Settings Console Region Enable TTY Output @@ -167,7 +167,7 @@ ]]> Cancel Clear - Controller Mapping + Controller Settings No profiles found. Select Input Profile Failed to load profile \'%s\' @@ -267,4 +267,11 @@ Confirm Logout After logging out, no more achievements will be unlocked until you log back in again. Achievements already unlocked will not be lost. Device for Vibration + Settings + Hotkeys + Button Bindings + Axis Bindings + Settings + Touchscreen Controller + Memory Cards diff --git a/android/app/src/main/res/xml/controllers_preferences.xml b/android/app/src/main/res/xml/controllers_preferences.xml index 77953e447..c25f063f0 100644 --- a/android/app/src/main/res/xml/controllers_preferences.xml +++ b/android/app/src/main/res/xml/controllers_preferences.xml @@ -14,88 +14,64 @@ ~ limitations under the License. --> - + - - - - - - - - - + + + + + + + - - - - - - + + + +