From e49f9b10a856da67c0f9efada2cdee102e600c01 Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Sun, 17 Jan 2016 13:42:22 -0500 Subject: [PATCH 1/6] Implement Java-based Config file read/save --- .../model/settings/BooleanSetting.java | 28 +++ .../model/settings/FloatSetting.java | 28 +++ .../dolphinemu/model/settings/IntSetting.java | 28 +++ .../dolphinemu/model/settings/Setting.java | 26 +++ .../model/settings/SettingSection.java | 35 ++++ .../model/settings/StringSetting.java | 28 +++ .../dolphinemu/utils/SettingsFile.java | 193 ++++++++++++++++++ 7 files changed, 366 insertions(+) create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/BooleanSetting.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/FloatSetting.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/IntSetting.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/Setting.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/SettingSection.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/StringSetting.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/BooleanSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/BooleanSetting.java new file mode 100644 index 0000000000..e282e6f038 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/BooleanSetting.java @@ -0,0 +1,28 @@ +package org.dolphinemu.dolphinemu.model.settings; + +public final class BooleanSetting extends Setting +{ + private boolean mValue; + + public BooleanSetting(String key, SettingSection section, boolean value) + { + super(key, section); + mValue = value; + } + + public boolean getValue() + { + return mValue; + } + + public void setValue(boolean value) + { + mValue = value; + } + + @Override + public String getValueAsString() + { + return mValue ? "True" : "False"; + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/FloatSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/FloatSetting.java new file mode 100644 index 0000000000..82c273a991 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/FloatSetting.java @@ -0,0 +1,28 @@ +package org.dolphinemu.dolphinemu.model.settings; + +public final class FloatSetting extends Setting +{ + private float mValue; + + public FloatSetting(String key, SettingSection section, float value) + { + super(key, section); + mValue = value; + } + + public float getValue() + { + return mValue; + } + + public void setValue(float value) + { + mValue = value; + } + + @Override + public String getValueAsString() + { + return Float.toString(mValue); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/IntSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/IntSetting.java new file mode 100644 index 0000000000..b47ce6ecf3 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/IntSetting.java @@ -0,0 +1,28 @@ +package org.dolphinemu.dolphinemu.model.settings; + +public final class IntSetting extends Setting +{ + private int mValue; + + public IntSetting(String key, SettingSection section, int value) + { + super(key, section); + mValue = value; + } + + public int getValue() + { + return mValue; + } + + public void setValue(int value) + { + mValue = value; + } + + @Override + public String getValueAsString() + { + return Integer.toString(mValue); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/Setting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/Setting.java new file mode 100644 index 0000000000..7ebc5633d8 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/Setting.java @@ -0,0 +1,26 @@ +package org.dolphinemu.dolphinemu.model.settings; + +public abstract class Setting +{ + private String mKey; + + private SettingSection mSection; + + public Setting(String key, SettingSection section) + { + mKey = key; + mSection = section; + } + + public String getKey() + { + return mKey; + } + + public SettingSection getSection() + { + return mSection; + } + + public abstract String getValueAsString(); +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/SettingSection.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/SettingSection.java new file mode 100644 index 0000000000..7ab9626e65 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/SettingSection.java @@ -0,0 +1,35 @@ +package org.dolphinemu.dolphinemu.model.settings; + +import java.util.HashMap; + +public class SettingSection +{ + private String mName; + + private HashMap mSettings = new HashMap<>(); + + public SettingSection(String name) + { + mName = name; + } + + public String getName() + { + return mName; + } + + public void putSetting(String key, Setting setting) + { + mSettings.put(key, setting); + } + + public Setting getSetting(String key) + { + return mSettings.get(key); + } + + public HashMap getSettings() + { + return mSettings; + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/StringSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/StringSetting.java new file mode 100644 index 0000000000..5c381dda3a --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/StringSetting.java @@ -0,0 +1,28 @@ +package org.dolphinemu.dolphinemu.model.settings; + +public final class StringSetting extends Setting +{ + private String mValue; + + public StringSetting(String key, SettingSection section, String value) + { + super(key, section); + mValue = value; + } + + public String getValue() + { + return mValue; + } + + public void setValue(String value) + { + mValue = value; + } + + @Override + public String getValueAsString() + { + return mValue; + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java new file mode 100644 index 0000000000..c200c3dea3 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java @@ -0,0 +1,193 @@ +package org.dolphinemu.dolphinemu.utils; + +import android.os.Environment; +import android.support.annotation.NonNull; + +import org.dolphinemu.dolphinemu.model.settings.BooleanSetting; +import org.dolphinemu.dolphinemu.model.settings.FloatSetting; +import org.dolphinemu.dolphinemu.model.settings.IntSetting; +import org.dolphinemu.dolphinemu.model.settings.Setting; +import org.dolphinemu.dolphinemu.model.settings.SettingSection; +import org.dolphinemu.dolphinemu.model.settings.StringSetting; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.Set; + +public final class SettingsFile +{ + private SettingsFile() + { + } + + public static HashMap readFile(String fileName) + { + HashMap sections = new HashMap<>(); + + File ini = getSettingsFile(fileName); + + BufferedReader reader = null; + + try + { + reader = new BufferedReader(new FileReader(ini)); + + SettingSection current = null; + for (String line; (line = reader.readLine()) != null; ) + { + if (line.startsWith("[") && line.endsWith("]")) + { + current = sectionFromLine(line); + sections.put(current.getName(), current); + } + else if ((current != null) && line.contains("=")) + { + Setting setting = settingFromLine(current, line); + current.putSetting(setting.getKey(), setting); + } + } + } + catch (FileNotFoundException e) + { + Log.error("[SettingsFile] File not found: " + fileName + ".ini: " + e.getMessage()); + } + catch (IOException e) + { + Log.error("[SettingsFile] Error reading from: " + fileName + ".ini: " + e.getMessage()); + } finally + { + if (reader != null) + { + try + { + reader.close(); + } + catch (IOException e) + { + Log.error("[SettingsFile] Error closing: " + fileName + ".ini: " + e.getMessage()); + } + } + } + + return sections; + } + + @NonNull + private static File getSettingsFile(String fileName) + { + String storagePath = Environment.getExternalStorageDirectory().getAbsolutePath(); + return new File(storagePath + "/dolphin-emu/Config/" + fileName + ".ini"); + } + + public static void saveFile(String fileName, HashMap sections) + { + File ini = getSettingsFile(fileName); + + PrintWriter writer = null; + try + { + writer = new PrintWriter(ini, "UTF-8"); + + Set keySet = sections.keySet(); + + for (String key : keySet) + { + SettingSection section = sections.get(key); + writeSection(writer, section); + } + } + catch (FileNotFoundException e) + { + Log.error("[SettingsFile] File not found: " + fileName + ".ini: " + e.getMessage()); + } + catch (UnsupportedEncodingException e) + { + Log.error("[SettingsFile] Bad encoding; please file a bug report: " + fileName + ".ini: " + e.getMessage()); + } finally + { + if (writer != null) + { + writer.close(); + } + } + } + + private static SettingSection sectionFromLine(String line) + { + String sectionName = line.substring(1, line.length() - 1); + return new SettingSection(sectionName); + } + + private static Setting settingFromLine(SettingSection current, String line) + { + String[] splitLine = line.split("="); + + String key = splitLine[0].trim(); + String value = splitLine[1].trim(); + + try + { + int valueAsInt = Integer.valueOf(value); + + return new IntSetting(key, current, valueAsInt); + } + catch (NumberFormatException ex) + { + } + + try + { + float valueAsFloat = Float.valueOf(value); + + return new FloatSetting(key, current, valueAsFloat); + } + catch (NumberFormatException ex) + { + } + + switch (value) + { + case "True": + return new BooleanSetting(key, current, true); + case "False": + return new BooleanSetting(key, current, false); + default: + return new StringSetting(key, current, value); + } + } + + private static void writeSection(PrintWriter writer, SettingSection section) + { + // Write the section header. + String header = sectionAsString(section); + writer.println(header); + + // Write this section's values. + HashMap settings = section.getSettings(); + Set keySet = settings.keySet(); + + for (String key : keySet) + { + Setting setting = settings.get(key); + String settingString = settingAsString(setting); + + writer.println(settingString); + } + } + + private static String sectionAsString(SettingSection section) + { + return "[" + section.getName() + "]"; + } + + private static String settingAsString(Setting setting) + { + return setting.getKey() + " = " + setting.getValueAsString(); + } +} From ce8a3d9bfb140a39dcc5a8bc2f37107e17973ce8 Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Mon, 18 Jan 2016 18:27:04 -0500 Subject: [PATCH 2/6] Implement basic framework for new Settings UI --- .../Android/app/src/main/AndroidManifest.xml | 4 +- .../activities/SettingsActivity.java | 48 -- .../fragments/SettingsFragment.java | 155 ------ .../model/settings/view/CheckBoxSetting.java | 31 ++ .../model/settings/view/HeaderSetting.java | 18 + .../model/settings/view/SettingsItem.java | 48 ++ .../settings/view/SingleChoiceSetting.java | 45 ++ .../model/settings/view/SliderSetting.java | 61 +++ .../model/settings/view/SubmenuSetting.java | 25 + .../dolphinemu/services/AssetCopyService.java | 5 - .../services/SettingsSaveService.java | 28 - .../dolphinemu/ui/DividerItemDecoration.java | 157 ++++++ .../dolphinemu/ui/main/MainActivity.java | 5 +- .../dolphinemu/ui/main/TvMainActivity.java | 5 +- .../ui/settings/SettingsActivity.java | 106 ++++ .../settings/SettingsActivityPresenter.java | 88 ++++ .../ui/settings/SettingsActivityView.java | 18 + .../ui/settings/SettingsAdapter.java | 121 +++++ .../ui/settings/SettingsFragment.java | 118 +++++ .../settings/SettingsFragmentPresenter.java | 102 ++++ .../ui/settings/SettingsFragmentView.java | 16 + .../viewholder/CheckboxSettingViewHolder.java | 57 ++ .../settings/viewholder/HeaderViewHolder.java | 37 ++ .../viewholder/SettingViewHolder.java | 34 ++ .../viewholder/SingleChoiceViewHolder.java | 48 ++ .../settings/viewholder/SliderViewHolder.java | 50 ++ .../viewholder/SubmenuViewHolder.java | 48 ++ .../dolphinemu/utils/SettingsFile.java | 217 +++++--- .../dolphinemu/utils/UserPreferences.java | 495 ------------------ .../src/main/res/layout/activity_settings.xml | 23 +- .../src/main/res/layout/fragment_settings.xml | 11 + .../src/main/res/layout/list_item_setting.xml | 39 ++ .../res/layout/list_item_setting_checkbox.xml | 49 ++ .../res/layout/list_item_settings_header.xml | 18 + .../app/src/main/res/values/dimens.xml | 7 + .../app/src/main/res/values/styles.xml | 2 +- 36 files changed, 1508 insertions(+), 831 deletions(-) delete mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/SettingsActivity.java delete mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/SettingsFragment.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/CheckBoxSetting.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/HeaderSetting.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SettingsItem.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SingleChoiceSetting.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SliderSetting.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SubmenuSetting.java delete mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/SettingsSaveService.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/DividerItemDecoration.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivity.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivityPresenter.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivityView.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragment.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/CheckboxSettingViewHolder.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/HeaderViewHolder.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SettingViewHolder.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SingleChoiceViewHolder.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SliderViewHolder.java create mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SubmenuViewHolder.java delete mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java create mode 100644 Source/Android/app/src/main/res/layout/fragment_settings.xml create mode 100644 Source/Android/app/src/main/res/layout/list_item_setting.xml create mode 100644 Source/Android/app/src/main/res/layout/list_item_setting_checkbox.xml create mode 100644 Source/Android/app/src/main/res/layout/list_item_settings_header.xml diff --git a/Source/Android/app/src/main/AndroidManifest.xml b/Source/Android/app/src/main/AndroidManifest.xml index a6a7ecc888..be41d3f55b 100644 --- a/Source/Android/app/src/main/AndroidManifest.xml +++ b/Source/Android/app/src/main/AndroidManifest.xml @@ -56,7 +56,7 @@ android:label="@string/add_directory_title"/> @@ -71,8 +71,6 @@ - - shader_names = new ArrayList(); - List shader_values = new ArrayList(); - - // Disabled option - shader_names.add("Disabled"); - shader_values.add(""); - - // TODO Since shaders are included with the APK, we know what they are at build-time. We should - // TODO be able to run this logic somehow at build-time and not rely on the device doing it. - - File shaders_folder = new File(Environment.getExternalStorageDirectory() + File.separator + "dolphin-emu" + File.separator + "Shaders"); - if (shaders_folder.exists()) - { - File[] shaders = shaders_folder.listFiles(); - for (File file : shaders) - { - if (file.isFile()) - { - String filename = file.getName(); - if (filename.endsWith(".glsl")) - { - // Strip the extension and put it in to the list - shader_names.add(filename.substring(0, filename.lastIndexOf('.'))); - shader_values.add(filename.substring(0, filename.lastIndexOf('.'))); - } - } - } - } - - final ListPreference shader_preference = (ListPreference) findPreference("postProcessingShader"); - shader_preference.setEntries(shader_names.toArray(new CharSequence[shader_names.size()])); - shader_preference.setEntryValues(shader_values.toArray(new CharSequence[shader_values.size()])); - - // - // Disable all options if Software Rendering is used. - // - // Note that the numeric value in 'getPreference()' - // denotes the placement on the UI. So if more elements are - // added to the video settings, these may need to change. - // - mPreferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); - - if (mVideoBackendPreference.getValue().equals("Software Renderer")) - { - findPreference("enhancements").setEnabled(false); - findPreference("hacks").setEnabled(false); - findPreference("showFPS").setEnabled(false); - } - else if (mVideoBackendPreference.getValue().equals("OGL")) - { - findPreference("enhancements").setEnabled(true); - findPreference("hacks").setEnabled(true); - findPreference("showFPS").setEnabled(true); - - // Check if we support stereo - // If we support desktop GL then we must support at least OpenGL 3.2 - // If we only support OpenGLES then we need both OpenGLES 3.1 and AEP - if ((mEglHelper.supportsOpenGL() && mEglHelper.GetVersion() >= 320) || - (mEglHelper.supportsGLES3() && mEglHelper.GetVersion() >= 310 && mEglHelper.SupportsExtension("GL_ANDROID_extension_pack_es31a"))) - findPreference("StereoscopyScreen").setEnabled(true); - else - findPreference("StereoscopyScreen").setEnabled(false); - } - - // Also set a listener, so that if someone changes the video backend, it will disable - // the video settings, upon the user choosing "Software Rendering". - mPreferences.registerOnSharedPreferenceChangeListener(this); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences preferences, String key) - { - if (key.equals("gpuPref")) - { - if (preferences.getString(key, "Software Renderer").equals("Software Renderer")) - { - findPreference("enhancements").setEnabled(false); - findPreference("hacks").setEnabled(false); - findPreference("showFPS").setEnabled(false); - } - else if (preferences.getString(key, "Software Renderer").equals("OGL")) - { - findPreference("enhancements").setEnabled(true); - findPreference("hacks").setEnabled(true); - findPreference("showFPS").setEnabled(true); - } - } - } -} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/CheckBoxSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/CheckBoxSetting.java new file mode 100644 index 0000000000..17860e7c22 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/CheckBoxSetting.java @@ -0,0 +1,31 @@ +package org.dolphinemu.dolphinemu.model.settings.view; + + +import org.dolphinemu.dolphinemu.model.settings.BooleanSetting; +import org.dolphinemu.dolphinemu.model.settings.Setting; + +public class CheckBoxSetting extends SettingsItem +{ + public CheckBoxSetting(String key, Setting setting, int titleId, int descriptionId) + { + super(key, setting, titleId, descriptionId); + } + + public boolean isChecked() + { + BooleanSetting setting = (BooleanSetting) getSetting(); + return setting.getValue(); + } + + public void setChecked(boolean checked) + { + BooleanSetting setting = (BooleanSetting) getSetting(); + setting.setValue(checked); + } + + @Override + public int getType() + { + return TYPE_CHECKBOX; + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/HeaderSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/HeaderSetting.java new file mode 100644 index 0000000000..fec739157f --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/HeaderSetting.java @@ -0,0 +1,18 @@ +package org.dolphinemu.dolphinemu.model.settings.view; + + +import org.dolphinemu.dolphinemu.model.settings.Setting; + +public class HeaderSetting extends SettingsItem +{ + public HeaderSetting(String key, Setting setting, int titleId, int descriptionId) + { + super(key, setting, titleId, descriptionId); + } + + @Override + public int getType() + { + return SettingsItem.TYPE_HEADER; + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SettingsItem.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SettingsItem.java new file mode 100644 index 0000000000..d17c3e4318 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SettingsItem.java @@ -0,0 +1,48 @@ +package org.dolphinemu.dolphinemu.model.settings.view; + +import org.dolphinemu.dolphinemu.model.settings.Setting; + +public abstract class SettingsItem +{ + public static final int TYPE_HEADER = 0; + public static final int TYPE_CHECKBOX = 1; + public static final int TYPE_SINGLE_CHOICE = 2; + public static final int TYPE_SLIDER = 3; + public static final int TYPE_SUBMENU = 4; + + private String mKey; + private Setting mSetting; + + private int mTitleId; + private int mDescriptionId; + + public SettingsItem(String key, Setting setting, int titleId, int descriptionId) + { + mKey = key; + mSetting = setting; + mTitleId = titleId; + mDescriptionId = descriptionId; + } + + public String getKey() + { + return mKey; + } + + public Setting getSetting() + { + return mSetting; + } + + public int getNameId() + { + return mTitleId; + } + + public int getDescriptionId() + { + return mDescriptionId; + } + + public abstract int getType(); +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SingleChoiceSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SingleChoiceSetting.java new file mode 100644 index 0000000000..ef54c6a206 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SingleChoiceSetting.java @@ -0,0 +1,45 @@ +package org.dolphinemu.dolphinemu.model.settings.view; + +import org.dolphinemu.dolphinemu.model.settings.IntSetting; +import org.dolphinemu.dolphinemu.model.settings.Setting; + +public class SingleChoiceSetting extends SettingsItem +{ + private int mChoicesId; + private int mValuesId; + + public SingleChoiceSetting(String key, Setting setting, int titleId, int descriptionId, int choicesId, int valuesId) + { + super(key, setting, titleId, descriptionId); + mChoicesId = choicesId; + mValuesId = valuesId; + } + + public int getChoicesId() + { + return mChoicesId; + } + + public int getValuesId() + { + return mValuesId; + } + + public int getSelectedValue() + { + IntSetting setting = (IntSetting) getSetting(); + return setting.getValue(); + } + + public void setSelectedValue(int selection) + { + IntSetting setting = (IntSetting) getSetting(); + setting.setValue(selection); + } + + @Override + public int getType() + { + return TYPE_SINGLE_CHOICE; + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SliderSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SliderSetting.java new file mode 100644 index 0000000000..4194753f52 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SliderSetting.java @@ -0,0 +1,61 @@ +package org.dolphinemu.dolphinemu.model.settings.view; + +import org.dolphinemu.dolphinemu.model.settings.FloatSetting; +import org.dolphinemu.dolphinemu.model.settings.IntSetting; +import org.dolphinemu.dolphinemu.model.settings.Setting; +import org.dolphinemu.dolphinemu.utils.Log; + +public class SliderSetting extends SettingsItem +{ + private int mMax; + + public SliderSetting(String key, Setting setting, int titleId, int descriptionId, int max) + { + super(key, setting, titleId, descriptionId); + mMax = max; + } + + public int getMax() + { + return mMax; + } + + public int getSelectedValue() + { + Setting setting = getSetting(); + + if (setting instanceof IntSetting) + { + IntSetting intSetting = (IntSetting) setting; + return intSetting.getValue(); + } + else if (setting instanceof FloatSetting) + { + FloatSetting floatSetting = (FloatSetting) setting; + return Math.round(floatSetting.getValue()); + } + else + { + Log.error("[SliderSetting] Error casting setting type."); + return -1; + } + } + + public void setSelectedValue(int selection) + { + IntSetting setting = (IntSetting) getSetting(); + setting.setValue(selection); + } + + public void setSelectedValue(float selection) + { + FloatSetting setting = (FloatSetting) getSetting(); + setting.setValue(selection); + } + + @Override + public int getType() + { + return TYPE_SLIDER; + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SubmenuSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SubmenuSetting.java new file mode 100644 index 0000000000..63a73caf0a --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SubmenuSetting.java @@ -0,0 +1,25 @@ +package org.dolphinemu.dolphinemu.model.settings.view; + +import org.dolphinemu.dolphinemu.model.settings.Setting; + +public class SubmenuSetting extends SettingsItem +{ + private String mMenuKey; + + public SubmenuSetting(String key, Setting setting, int titleId, int descriptionId, String menuKey) + { + super(key, setting, titleId, descriptionId); + mMenuKey = menuKey; + } + + public String getMenuKey() + { + return mMenuKey; + } + + @Override + public int getType() + { + return TYPE_SUBMENU; + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/AssetCopyService.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/AssetCopyService.java index 6004c88c5e..a93e9c501b 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/AssetCopyService.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/AssetCopyService.java @@ -13,7 +13,6 @@ import android.preference.PreferenceManager; import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.utils.Log; -import org.dolphinemu.dolphinemu.utils.UserPreferences; import java.io.File; import java.io.FileOutputStream; @@ -61,10 +60,6 @@ public final class AssetCopyService extends IntentService copyAsset("GCPadNew.ini", ConfigDir + File.separator + "GCPadNew.ini"); copyAsset("WiimoteNew.ini", ConfigDir + File.separator + "WiimoteNew.ini"); - // Load the configuration keys set in the Dolphin ini and gfx ini files - // into the application's shared preferences. - UserPreferences.LoadIniToPrefs(this); - // Record the fact that we've done this before, so we don't do it on every launch. SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor editor = preferences.edit(); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/SettingsSaveService.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/SettingsSaveService.java deleted file mode 100644 index 5be3f4d27c..0000000000 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/services/SettingsSaveService.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.dolphinemu.dolphinemu.services; - -import android.app.IntentService; -import android.content.Intent; - -import org.dolphinemu.dolphinemu.utils.Log; -import org.dolphinemu.dolphinemu.utils.UserPreferences; - -/** - * IntentServices, unlike regular services, inherently run on a background thread. - * This IntentService saves all the options the user set in the Java-based UI into - * INI files the native code can read. - */ -public final class SettingsSaveService extends IntentService -{ - public SettingsSaveService() - { - super("SettingsSaveService"); - } - - @Override - protected void onHandleIntent(Intent intent) - { - Log.verbose("[SettingsSaveService] Saving settings to INI files..."); - UserPreferences.SavePrefsToIni(this); - Log.verbose("[SettingsSaveService] Save successful."); - } -} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/DividerItemDecoration.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/DividerItemDecoration.java new file mode 100644 index 0000000000..96b569e060 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/DividerItemDecoration.java @@ -0,0 +1,157 @@ +package org.dolphinemu.dolphinemu.ui; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.util.AttributeSet; +import android.view.View; + +/** + * Implementation from: + * https://gist.github.com/lapastillaroja/858caf1a82791b6c1a36 + */ +public class DividerItemDecoration extends RecyclerView.ItemDecoration +{ + + private Drawable mDivider; + private boolean mShowFirstDivider = false; + private boolean mShowLastDivider = false; + + + public DividerItemDecoration(Context context, AttributeSet attrs) + { + final TypedArray a = context + .obtainStyledAttributes(attrs, new int[]{android.R.attr.listDivider}); + mDivider = a.getDrawable(0); + a.recycle(); + } + + public DividerItemDecoration(Context context, AttributeSet attrs, boolean showFirstDivider, + boolean showLastDivider) + { + this(context, attrs); + mShowFirstDivider = showFirstDivider; + mShowLastDivider = showLastDivider; + } + + public DividerItemDecoration(Drawable divider) + { + mDivider = divider; + } + + public DividerItemDecoration(Drawable divider, boolean showFirstDivider, + boolean showLastDivider) + { + this(divider); + mShowFirstDivider = showFirstDivider; + mShowLastDivider = showLastDivider; + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, + RecyclerView.State state) + { + super.getItemOffsets(outRect, view, parent, state); + if (mDivider == null) + { + return; + } + if (parent.getChildPosition(view) < 1) + { + return; + } + + if (getOrientation(parent) == LinearLayoutManager.VERTICAL) + { + outRect.top = mDivider.getIntrinsicHeight(); + } + else + { + outRect.left = mDivider.getIntrinsicWidth(); + } + } + + @Override + public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) + { + if (mDivider == null) + { + super.onDrawOver(c, parent, state); + return; + } + + // Initialization needed to avoid compiler warning + int left = 0, right = 0, top = 0, bottom = 0, size; + int orientation = getOrientation(parent); + int childCount = parent.getChildCount(); + + if (orientation == LinearLayoutManager.VERTICAL) + { + size = mDivider.getIntrinsicHeight(); + left = parent.getPaddingLeft(); + right = parent.getWidth() - parent.getPaddingRight(); + } + else + { //horizontal + size = mDivider.getIntrinsicWidth(); + top = parent.getPaddingTop(); + bottom = parent.getHeight() - parent.getPaddingBottom(); + } + + for (int i = mShowFirstDivider ? 0 : 1; i < childCount; i++) + { + View child = parent.getChildAt(i); + RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); + + if (orientation == LinearLayoutManager.VERTICAL) + { + top = child.getTop() - params.topMargin; + bottom = top + size; + } + else + { //horizontal + left = child.getLeft() - params.leftMargin; + right = left + size; + } + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(c); + } + + // show last divider + if (mShowLastDivider && childCount > 0) + { + View child = parent.getChildAt(childCount - 1); + RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); + if (orientation == LinearLayoutManager.VERTICAL) + { + top = child.getBottom() + params.bottomMargin; + bottom = top + size; + } + else + { // horizontal + left = child.getRight() + params.rightMargin; + right = left + size; + } + mDivider.setBounds(left, top, right, bottom); + mDivider.draw(c); + } + } + + private int getOrientation(RecyclerView parent) + { + if (parent.getLayoutManager() instanceof LinearLayoutManager) + { + LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager(); + return layoutManager.getOrientation(); + } + else + { + throw new IllegalStateException( + "DividerItemDecoration can only be used with a LinearLayoutManager."); + } + } +} \ No newline at end of file diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java index e112899201..5a7ed0ab34 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java @@ -16,10 +16,11 @@ import android.view.View; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.activities.AddDirectoryActivity; -import org.dolphinemu.dolphinemu.activities.SettingsActivity; import org.dolphinemu.dolphinemu.adapters.PlatformPagerAdapter; import org.dolphinemu.dolphinemu.model.GameProvider; import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesView; +import org.dolphinemu.dolphinemu.ui.settings.SettingsActivity; +import org.dolphinemu.dolphinemu.utils.SettingsFile; import org.dolphinemu.dolphinemu.utils.StartupHandler; /** @@ -117,7 +118,7 @@ public final class MainActivity extends AppCompatActivity implements MainView @Override public void launchSettingsActivity() { - SettingsActivity.launch(this); + SettingsActivity.launch(this, SettingsFile.FILE_NAME_DOLPHIN); } @Override diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java index 38ab2eb4b4..51b2239118 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/TvMainActivity.java @@ -20,11 +20,12 @@ import android.support.v17.leanback.widget.RowPresenter; import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.activities.AddDirectoryActivity; import org.dolphinemu.dolphinemu.activities.EmulationActivity; -import org.dolphinemu.dolphinemu.activities.SettingsActivity; import org.dolphinemu.dolphinemu.adapters.GameRowPresenter; import org.dolphinemu.dolphinemu.adapters.SettingsRowPresenter; import org.dolphinemu.dolphinemu.model.Game; import org.dolphinemu.dolphinemu.model.TvSettingsItem; +import org.dolphinemu.dolphinemu.ui.settings.SettingsActivity; +import org.dolphinemu.dolphinemu.utils.SettingsFile; import org.dolphinemu.dolphinemu.utils.StartupHandler; import org.dolphinemu.dolphinemu.viewholders.TvGameViewHolder; @@ -114,7 +115,7 @@ public final class TvMainActivity extends Activity implements MainView @Override public void launchSettingsActivity() { - SettingsActivity.launch(this); + SettingsActivity.launch(this, SettingsFile.FILE_NAME_DOLPHIN); } @Override diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivity.java new file mode 100644 index 0000000000..7cd744aff2 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivity.java @@ -0,0 +1,106 @@ +package org.dolphinemu.dolphinemu.ui.settings; + + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.FragmentTransaction; +import android.support.v7.app.AppCompatActivity; +import android.widget.Toast; + +import org.dolphinemu.dolphinemu.BuildConfig; +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.model.settings.SettingSection; + +import java.util.HashMap; + +public final class SettingsActivity extends AppCompatActivity implements SettingsActivityView +{ + private SettingsActivityPresenter mPresenter = new SettingsActivityPresenter(this); + + + @Override + protected void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_settings); + + Intent launcher = getIntent(); + String filename = launcher.getStringExtra(ARGUMENT_FILE_NAME); + + mPresenter.onCreate(savedInstanceState, filename); + } + + /** + * If this is called, the user has left the settings screen (potentially through the + * home button) and will expect their changes to be persisted. So we kick off an + * IntentService which will do so on a background thread. + */ + @Override + protected void onStop() + { + super.onStop(); + + mPresenter.onStop(isFinishing()); + } + + @Override + public void showSettingsFragment(String menuTag, boolean addToStack) + { + FragmentTransaction transaction = getSupportFragmentManager().beginTransaction() + .replace(R.id.frame_content, SettingsFragment.newInstance(menuTag), SettingsFragment.FRAGMENT_TAG); + + if (addToStack) + { + transaction.addToBackStack(null); + } + + transaction.commit(); + } + + @Override + public HashMap getSettings() + { + return mPresenter.getSettings(); + } + + @Override + public void setSettings(HashMap settings) + { + mPresenter.setSettings(settings); + } + + @Override + public void onSettingsFileLoaded(HashMap settings) + { + SettingsFragmentView fragment = getFragment(); + + if (fragment != null) + { + fragment.onSettingsFileLoaded(settings); + } + } + + @Override + public void showToastMessage(String message) + { + Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); + } + + private SettingsFragment getFragment() + { + return (SettingsFragment) getSupportFragmentManager().findFragmentByTag(SettingsFragment.FRAGMENT_TAG); + } + + public static final String ARGUMENT_FILE_NAME = BuildConfig.APPLICATION_ID + ".file_name"; + + public static void launch(Context context, String menuTag) + { + Intent settings = new Intent(context, SettingsActivity.class); + + settings.putExtra(ARGUMENT_FILE_NAME, menuTag); + + context.startActivity(settings); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivityPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivityPresenter.java new file mode 100644 index 0000000000..662145e57f --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivityPresenter.java @@ -0,0 +1,88 @@ +package org.dolphinemu.dolphinemu.ui.settings; + + +import android.os.Bundle; + +import org.dolphinemu.dolphinemu.model.settings.SettingSection; +import org.dolphinemu.dolphinemu.utils.Log; +import org.dolphinemu.dolphinemu.utils.SettingsFile; + +import java.util.HashMap; + +import rx.android.schedulers.AndroidSchedulers; +import rx.functions.Action1; +import rx.schedulers.Schedulers; + +public class SettingsActivityPresenter +{ + private SettingsActivityView mView; + + private String mFileName; + private HashMap mSettingsBySection; + + public SettingsActivityPresenter(SettingsActivityView view) + { + mView = view; + } + + public void onCreate(Bundle savedInstanceState, String filename) + { + mFileName = filename; + + if (savedInstanceState == null) + { + SettingsFile.readFile(mFileName) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(new Action1>() + { + @Override + public void call(HashMap settingsBySection) + { + mSettingsBySection = settingsBySection; + mView.onSettingsFileLoaded(settingsBySection); + } + }); + + mView.showSettingsFragment(mFileName, false); + } + } + + public void setSettings(HashMap settings) + { + mSettingsBySection = settings; + } + + public HashMap getSettings() + { + return mSettingsBySection; + } + + public void onStop(boolean finishing) + { + if (mSettingsBySection != null && finishing) + { + Log.debug("[SettingsActivity] Settings activity stopping. Saving settings to INI..."); + SettingsFile.saveFile(mFileName, mSettingsBySection) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe( + new Action1() + { + @Override + public void call(Boolean aBoolean) + { + mView.showToastMessage("Saved successfully to " + mFileName + ".ini"); + } + }, + new Action1() + { + @Override + public void call(Throwable throwable) + { + mView.showToastMessage("Error saving " + mFileName + ".ini: " + throwable.getMessage()); + } + }); + } + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivityView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivityView.java new file mode 100644 index 0000000000..4299335684 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivityView.java @@ -0,0 +1,18 @@ +package org.dolphinemu.dolphinemu.ui.settings; + +import org.dolphinemu.dolphinemu.model.settings.SettingSection; + +import java.util.HashMap; + +public interface SettingsActivityView +{ + void showSettingsFragment(String menuTag, boolean addToStack); + + HashMap getSettings(); + + void setSettings(HashMap settings); + + void onSettingsFileLoaded(HashMap settings); + + void showToastMessage(String message); +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java new file mode 100644 index 0000000000..8d8272d2f7 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java @@ -0,0 +1,121 @@ +package org.dolphinemu.dolphinemu.ui.settings; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Toast; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; +import org.dolphinemu.dolphinemu.model.settings.view.SingleChoiceSetting; +import org.dolphinemu.dolphinemu.model.settings.view.SliderSetting; +import org.dolphinemu.dolphinemu.model.settings.view.SubmenuSetting; +import org.dolphinemu.dolphinemu.ui.settings.viewholder.CheckBoxSettingViewHolder; +import org.dolphinemu.dolphinemu.ui.settings.viewholder.HeaderViewHolder; +import org.dolphinemu.dolphinemu.ui.settings.viewholder.SettingViewHolder; +import org.dolphinemu.dolphinemu.ui.settings.viewholder.SingleChoiceViewHolder; +import org.dolphinemu.dolphinemu.ui.settings.viewholder.SliderViewHolder; +import org.dolphinemu.dolphinemu.ui.settings.viewholder.SubmenuViewHolder; +import org.dolphinemu.dolphinemu.utils.Log; + +import java.util.ArrayList; + +public class SettingsAdapter extends RecyclerView.Adapter +{ + private SettingsFragmentView mView; + private Context mContext; + private ArrayList mSettings; + + public SettingsAdapter(SettingsFragmentView view, Context context) + { + mView = view; + mContext = context; + } + + @Override + public SettingViewHolder onCreateViewHolder(ViewGroup parent, int viewType) + { + View view; + LayoutInflater inflater = LayoutInflater.from(parent.getContext()); + + switch (viewType) + { + case SettingsItem.TYPE_HEADER: + view = inflater.inflate(R.layout.list_item_settings_header, parent, false); + return new HeaderViewHolder(view, this); + + case SettingsItem.TYPE_CHECKBOX: + view = inflater.inflate(R.layout.list_item_setting_checkbox, parent, false); + return new CheckBoxSettingViewHolder(view, this); + + case SettingsItem.TYPE_SINGLE_CHOICE: + view = inflater.inflate(R.layout.list_item_setting, parent, false); + return new SingleChoiceViewHolder(view, this); + + case SettingsItem.TYPE_SLIDER: + view = inflater.inflate(R.layout.list_item_setting, parent, false); + return new SliderViewHolder(view, this); + + case SettingsItem.TYPE_SUBMENU: + view = inflater.inflate(R.layout.list_item_setting, parent, false); + return new SubmenuViewHolder(view, this); + + default: + Log.error("[SettingsAdapter] Invalid view type: " + viewType); + return null; + } + } + + @Override + public void onBindViewHolder(SettingViewHolder holder, int position) + { + holder.bind(getItem(position)); + } + + private SettingsItem getItem(int position) + { + return mSettings.get(position); + } + + @Override + public int getItemCount() + { + if (mSettings != null) + { + return mSettings.size(); + } + else + { + return 0; + } + } + + @Override + public int getItemViewType(int position) + { + return getItem(position).getType(); + } + + public void setSettings(ArrayList settings) + { + mSettings = settings; + notifyDataSetChanged(); + } + + public void onSingleChoiceClick(SingleChoiceSetting item) + { + Toast.makeText(mContext, "Single choice item clicked", Toast.LENGTH_SHORT).show(); + } + + public void onSliderClick(SliderSetting item) + { + Toast.makeText(mContext, "Slider item clicked", Toast.LENGTH_SHORT).show(); + } + + public void onSubmenuClick(SubmenuSetting item) + { + Toast.makeText(mContext, "Submenu item clicked", Toast.LENGTH_SHORT).show(); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragment.java new file mode 100644 index 0000000000..3d4817f3fc --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragment.java @@ -0,0 +1,118 @@ +package org.dolphinemu.dolphinemu.ui.settings; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v4.app.Fragment; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import org.dolphinemu.dolphinemu.BuildConfig; +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.model.settings.SettingSection; +import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; +import org.dolphinemu.dolphinemu.ui.DividerItemDecoration; + +import java.util.ArrayList; +import java.util.HashMap; + +public final class SettingsFragment extends Fragment implements SettingsFragmentView +{ + private SettingsFragmentPresenter mPresenter = new SettingsFragmentPresenter(this); + private SettingsActivityView mView; + + private SettingsAdapter mAdapter; + + @Override + public void onAttach(Context context) + { + super.onAttach(context); + + mView = (SettingsActivityView) context; + mPresenter.onAttach(); + } + + @Override + public void onCreate(Bundle savedInstanceState) + { + super.onCreate(savedInstanceState); + + setRetainInstance(true); + String menuTag = getArguments().getString(ARGUMENT_MENU_TAG); + + mAdapter = new SettingsAdapter(this, getActivity()); + + mPresenter.onCreate(menuTag); + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) + { + return inflater.inflate(R.layout.fragment_settings, container, false); + } + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) + { + LinearLayoutManager manager = new LinearLayoutManager(getActivity()); + + RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.list_settings); + + recyclerView.setAdapter(mAdapter); + recyclerView.setLayoutManager(manager); + recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), null)); + + SettingsActivityView activity = (SettingsActivityView) getActivity(); + HashMap settings = activity.getSettings(); + + mPresenter.onViewCreated(settings); + } + + @Override + public void onDetach() + { + super.onDetach(); + mView = null; + } + + @Override + public void onSettingsFileLoaded(HashMap settings) + { + mPresenter.setSettings(settings); + } + + @Override + public void passOptionsToActivity(HashMap settings) + { + if (mView != null) + { + mView.setSettings(settings); + } + } + + @Override + public void showSettingsList(ArrayList settingsList) + { + mAdapter.setSettings(settingsList); + } + + public static final String FRAGMENT_TAG = BuildConfig.APPLICATION_ID + ".fragment.settings"; + + public static final String ARGUMENT_MENU_TAG = FRAGMENT_TAG + ".menu_tag"; + + public static Fragment newInstance(String menuTag) + { + SettingsFragment fragment = new SettingsFragment(); + + Bundle arguments = new Bundle(); + arguments.putString(ARGUMENT_MENU_TAG, menuTag); + + fragment.setArguments(arguments); + return fragment; + } + +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java new file mode 100644 index 0000000000..d0bc5a36f9 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java @@ -0,0 +1,102 @@ +package org.dolphinemu.dolphinemu.ui.settings; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.model.settings.Setting; +import org.dolphinemu.dolphinemu.model.settings.SettingSection; +import org.dolphinemu.dolphinemu.model.settings.view.CheckBoxSetting; +import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; +import org.dolphinemu.dolphinemu.model.settings.view.SingleChoiceSetting; +import org.dolphinemu.dolphinemu.model.settings.view.SliderSetting; +import org.dolphinemu.dolphinemu.utils.SettingsFile; + +import java.util.ArrayList; +import java.util.HashMap; + +public class SettingsFragmentPresenter +{ + private SettingsFragmentView mView; + + private String mMenuTag; + + private HashMap mSettings; + private ArrayList mSettingsList; + + public SettingsFragmentPresenter(SettingsFragmentView view) + { + mView = view; + } + + public void onCreate(String menuTag) + { + mMenuTag = menuTag; + } + + public void onViewCreated(HashMap settings) + { + setSettings(settings); + } + + /** + * If the screen is rotated, the Activity will forget the settings map. This fragment + * won't, though; so rather than have the Activity reload from disk, have the fragment pass + * the settings map back to the Activity. + */ + public void onAttach() + { + if (mSettings != null) + { + mView.passOptionsToActivity(mSettings); + } + } + + public void setSettings(HashMap settings) + { + if (mSettingsList == null) + { + if (settings != null) + { + mSettings = settings; + } + + if (mSettings != null) + { + loadSettingsList(); + } + } + else + { + mView.showSettingsList(mSettingsList); + } + } + + private void loadSettingsList() + { + ArrayList sl = new ArrayList<>(); + + switch (mMenuTag) + { + case SettingsFile.FILE_NAME_DOLPHIN: + addCoreSettings(sl); + + break; + } + + mSettingsList = sl; + mView.showSettingsList(mSettingsList); + } + + private void addCoreSettings(ArrayList sl) + { + Setting cpuCore = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_CPU_CORE); + sl.add(new SingleChoiceSetting(cpuCore.getKey(), cpuCore, R.string.cpu_core, 0, R.array.string_emu_cores, R.array.int_emu_cores)); + + Setting dualCore = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_DUAL_CORE); + sl.add(new CheckBoxSetting(dualCore.getKey(), dualCore, R.string.dual_core, R.string.dual_core_descrip)); + + Setting overclockEnable = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_OVERCLOCK_ENABLE); + sl.add(new CheckBoxSetting(overclockEnable.getKey(), overclockEnable, R.string.overclock_enable, R.string.overclock_enable_description)); + + Setting overclock = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_OVERCLOCK_PERCENT); + sl.add(new SliderSetting(overclock.getKey(), overclock, R.string.overclock_title, 0, 400)); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java new file mode 100644 index 0000000000..5f0f366ef7 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java @@ -0,0 +1,16 @@ +package org.dolphinemu.dolphinemu.ui.settings; + +import org.dolphinemu.dolphinemu.model.settings.SettingSection; +import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; + +import java.util.ArrayList; +import java.util.HashMap; + +public interface SettingsFragmentView +{ + void onSettingsFileLoaded(HashMap settings); + + void passOptionsToActivity(HashMap settings); + + void showSettingsList(ArrayList settingsList); +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/CheckboxSettingViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/CheckboxSettingViewHolder.java new file mode 100644 index 0000000000..0059446bdc --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/CheckboxSettingViewHolder.java @@ -0,0 +1,57 @@ +package org.dolphinemu.dolphinemu.ui.settings.viewholder; + + +import android.view.View; +import android.widget.CheckBox; +import android.widget.TextView; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.model.settings.view.CheckBoxSetting; +import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; +import org.dolphinemu.dolphinemu.ui.settings.SettingsAdapter; + +public class CheckBoxSettingViewHolder extends SettingViewHolder +{ + private CheckBoxSetting mItem; + + private TextView mTextSettingName; + private TextView mTextSettingDescription; + + private CheckBox mCheckbox; + + public CheckBoxSettingViewHolder(View itemView, SettingsAdapter adapter) + { + super(itemView, adapter); + } + + @Override + protected void findViews(View root) + { + mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name); + mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description); + mCheckbox = (CheckBox) root.findViewById(R.id.checkbox); + } + + @Override + public void bind(SettingsItem item) + { + mItem = (CheckBoxSetting) item; + + mTextSettingName.setText(item.getNameId()); + + if (item.getDescriptionId() > 0) + { + mTextSettingDescription.setText(item.getDescriptionId()); + } + + mCheckbox.setChecked(mItem.isChecked()); + } + + @Override + public void onClick(View clicked) + { + mCheckbox.toggle(); + mItem.setChecked(mCheckbox.isChecked()); + getAdapter().notifyItemChanged(getAdapterPosition()); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/HeaderViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/HeaderViewHolder.java new file mode 100644 index 0000000000..9f0ba58196 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/HeaderViewHolder.java @@ -0,0 +1,37 @@ +package org.dolphinemu.dolphinemu.ui.settings.viewholder; + +import android.view.View; +import android.widget.TextView; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; +import org.dolphinemu.dolphinemu.ui.settings.SettingsAdapter; + +public class HeaderViewHolder extends SettingViewHolder +{ + private TextView mHeaderName; + + public HeaderViewHolder(View itemView, SettingsAdapter adapter) + { + super(itemView, adapter); + itemView.setOnClickListener(null); + } + + @Override + protected void findViews(View root) + { + mHeaderName = (TextView) root.findViewById(R.id.text_header_name); + } + + @Override + public void bind(SettingsItem item) + { + mHeaderName.setText(item.getNameId()); + } + + @Override + public void onClick(View clicked) + { + // no-op + } +} \ No newline at end of file diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SettingViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SettingViewHolder.java new file mode 100644 index 0000000000..ffa7d59d81 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SettingViewHolder.java @@ -0,0 +1,34 @@ +package org.dolphinemu.dolphinemu.ui.settings.viewholder; + +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; +import org.dolphinemu.dolphinemu.ui.settings.SettingsAdapter; + +public abstract class SettingViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener +{ + private SettingsAdapter mAdapter; + + public SettingViewHolder(View itemView, SettingsAdapter adapter) + { + super(itemView); + + mAdapter = adapter; + + itemView.setOnClickListener(this); + + findViews(itemView); + } + + protected SettingsAdapter getAdapter() + { + return mAdapter; + } + + protected abstract void findViews(View root); + + public abstract void bind(SettingsItem item); + + public abstract void onClick(View clicked); +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SingleChoiceViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SingleChoiceViewHolder.java new file mode 100644 index 0000000000..a9230d2ee4 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SingleChoiceViewHolder.java @@ -0,0 +1,48 @@ +package org.dolphinemu.dolphinemu.ui.settings.viewholder; + +import android.view.View; +import android.widget.TextView; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; +import org.dolphinemu.dolphinemu.model.settings.view.SingleChoiceSetting; +import org.dolphinemu.dolphinemu.ui.settings.SettingsAdapter; + +public class SingleChoiceViewHolder extends SettingViewHolder +{ + private SingleChoiceSetting mItem; + + private TextView mTextSettingName; + private TextView mTextSettingDescription; + + public SingleChoiceViewHolder(View itemView, SettingsAdapter adapter) + { + super(itemView, adapter); + } + + @Override + protected void findViews(View root) + { + mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name); + mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description); + } + + @Override + public void bind(SettingsItem item) + { + mItem = (SingleChoiceSetting) item; + + mTextSettingName.setText(item.getNameId()); + + if (item.getDescriptionId() > 0) + { + mTextSettingDescription.setText(item.getDescriptionId()); + } + } + + @Override + public void onClick(View clicked) + { + getAdapter().onSingleChoiceClick(mItem); + } +} diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SliderViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SliderViewHolder.java new file mode 100644 index 0000000000..c15ddfaff6 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SliderViewHolder.java @@ -0,0 +1,50 @@ +package org.dolphinemu.dolphinemu.ui.settings.viewholder; + + +import android.view.View; +import android.widget.TextView; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; +import org.dolphinemu.dolphinemu.model.settings.view.SliderSetting; +import org.dolphinemu.dolphinemu.ui.settings.SettingsAdapter; + +public class SliderViewHolder extends SettingViewHolder +{ + private SliderSetting mItem; + + private TextView mTextSettingName; + private TextView mTextSettingDescription; + + public SliderViewHolder(View itemView, SettingsAdapter adapter) + { + super(itemView, adapter); + } + + @Override + protected void findViews(View root) + { + mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name); + mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description); + } + + @Override + public void bind(SettingsItem item) + { + mItem = (SliderSetting) item; + + mTextSettingName.setText(item.getNameId()); + + if (item.getDescriptionId() > 0) + { + mTextSettingDescription.setText(item.getDescriptionId()); + } + } + + @Override + public void onClick(View clicked) + { + getAdapter().onSliderClick(mItem); + } +} + diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SubmenuViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SubmenuViewHolder.java new file mode 100644 index 0000000000..b90f1459a2 --- /dev/null +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SubmenuViewHolder.java @@ -0,0 +1,48 @@ +package org.dolphinemu.dolphinemu.ui.settings.viewholder; + +import android.view.View; +import android.widget.TextView; + +import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; +import org.dolphinemu.dolphinemu.model.settings.view.SubmenuSetting; +import org.dolphinemu.dolphinemu.ui.settings.SettingsAdapter; + +public class SubmenuViewHolder extends SettingViewHolder +{ + private SubmenuSetting mItem; + + private TextView mTextSettingName; + private TextView mTextSettingDescription; + + public SubmenuViewHolder(View itemView, SettingsAdapter adapter) + { + super(itemView, adapter); + } + + @Override + protected void findViews(View root) + { + mTextSettingName = (TextView) root.findViewById(R.id.text_setting_name); + mTextSettingDescription = (TextView) root.findViewById(R.id.text_setting_description); + } + + @Override + public void bind(SettingsItem item) + { + mItem = (SubmenuSetting) item; + + mTextSettingName.setText(item.getNameId()); + + if (item.getDescriptionId() > 0) + { + mTextSettingDescription.setText(item.getDescriptionId()); + } + } + + @Override + public void onClick(View clicked) + { + getAdapter().onSubmenuClick(mItem); + } +} \ No newline at end of file diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java index c200c3dea3..15ce0a7e36 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java @@ -20,62 +20,166 @@ import java.io.UnsupportedEncodingException; import java.util.HashMap; import java.util.Set; +import rx.Observable; +import rx.Subscriber; + public final class SettingsFile { + public static final String FILE_NAME_DOLPHIN = "Dolphin"; + public static final String FILE_NAME_GFX = "GFX"; + public static final String FILE_NAME_GCPAD = "GCPadNew"; + public static final String FILE_NAME_WIIMOTE = "WiimoteNew"; + + public static final String SECTION_CORE = "Core"; + + public static final String SECTION_GFX_SETTINGS = "Settings"; + public static final String SECTION_GFX_ENHANCEMENTS = "Enhancements"; + public static final String SECTION_GFX_HACKS = "Hacks"; + + + public static final String KEY_CPU_CORE= "CPUCore"; + public static final String KEY_DUAL_CORE= "CPUThread"; + public static final String KEY_OVERCLOCK_ENABLE= "OverclockEnable"; + public static final String KEY_OVERCLOCK_PERCENT= "Overclock"; + public static final String KEY_VIDEO_BACKEND= "GFXBackend"; + + public static final String KEY_SHOW_FPS= "ShowFPS"; + public static final String KEY_INTERNAL_RES= "EFBScale"; + public static final String KEY_FSAA= "MSAA"; + public static final String KEY_ANISOTROPY= "MaxAnisotropy"; + public static final String KEY_POST_SHADER= "PostProcessingShader"; + public static final String KEY_SCALED_EFB= "EFBScaledCopy"; + public static final String KEY_PER_PIXEL= "EnablePixelLighting"; + public static final String KEY_FORCE_FILTERING= "ForceFiltering"; + public static final String KEY_DISABLE_FOG= "DisableFog"; + + public static final String KEY_STEREO_MODE= "StereoMode"; + public static final String KEY_STEREO_DEPTH= "StereoDepth"; + public static final String KEY_STEREO_CONV= "StereoConvergencePercentage"; + public static final String KEY_STEREO_SWAP= "StereoSwapEyes"; + + public static final String KEY_SKIP_EFB= "EFBAccessEnable"; + public static final String KEY_IGNORE_FORMAT= "EFBEmulateFormatChanges"; + public static final String KEY_EFB_COPY= "EFBCopyEnable"; + public static final String KEY_EFB_TEXTURE= "EFBToTextureEnable"; + public static final String KEY_EFB_CACHE= "EFBCopyCacheEnable"; + public static final String KEY_TEXCACHE_ACCURACY= "SafeTextureCacheColorSamples"; + public static final String KEY_XFB= "UseXFB"; + public static final String KEY_XFB_REAL= "UseRealXFB"; + public static final String KEY_FAST_DEPTH= "FastDepthCalc"; + public static final String KEY_ASPECT_RATIO= "AspectRatio"; + private SettingsFile() { } - public static HashMap readFile(String fileName) + public static Observable> readFile(final String fileName) { - HashMap sections = new HashMap<>(); - - File ini = getSettingsFile(fileName); - - BufferedReader reader = null; - - try + return Observable.create(new Observable.OnSubscribe>() { - reader = new BufferedReader(new FileReader(ini)); - - SettingSection current = null; - for (String line; (line = reader.readLine()) != null; ) - { - if (line.startsWith("[") && line.endsWith("]")) - { - current = sectionFromLine(line); - sections.put(current.getName(), current); - } - else if ((current != null) && line.contains("=")) - { - Setting setting = settingFromLine(current, line); - current.putSetting(setting.getKey(), setting); - } - } - } - catch (FileNotFoundException e) - { - Log.error("[SettingsFile] File not found: " + fileName + ".ini: " + e.getMessage()); - } - catch (IOException e) - { - Log.error("[SettingsFile] Error reading from: " + fileName + ".ini: " + e.getMessage()); - } finally - { - if (reader != null) + @Override + public void call(Subscriber> subscriber) { + + HashMap sections = new HashMap<>(); + + File ini = getSettingsFile(fileName); + + BufferedReader reader = null; + try { - reader.close(); + reader = new BufferedReader(new FileReader(ini)); + + SettingSection current = null; + for (String line; (line = reader.readLine()) != null; ) + { + if (line.startsWith("[") && line.endsWith("]")) + { + current = sectionFromLine(line); + sections.put(current.getName(), current); + } + else if ((current != null) && line.contains("=")) + { + Setting setting = settingFromLine(current, line); + current.putSetting(setting.getKey(), setting); + } + } + } + catch (FileNotFoundException e) + { + Log.error("[SettingsFile] File not found: " + fileName + ".ini: " + e.getMessage()); + subscriber.onError(e); } catch (IOException e) { - Log.error("[SettingsFile] Error closing: " + fileName + ".ini: " + e.getMessage()); + Log.error("[SettingsFile] Error reading from: " + fileName + ".ini: " + e.getMessage()); + subscriber.onError(e); + } finally + { + if (reader != null) + { + try + { + reader.close(); + } + catch (IOException e) + { + Log.error("[SettingsFile] Error closing: " + fileName + ".ini: " + e.getMessage()); + subscriber.onError(e); + } + } } - } - } - return sections; + subscriber.onNext(sections); + subscriber.onCompleted(); + } + }); + } + + public static Observable saveFile(final String fileName, final HashMap sections) + { + return Observable.create(new Observable.OnSubscribe() + { + @Override + public void call(Subscriber subscriber) + { + File ini = getSettingsFile(fileName); + + PrintWriter writer = null; + try + { + writer = new PrintWriter(ini, "UTF-8"); + + Set keySet = sections.keySet(); + + for (String key : keySet) + { + SettingSection section = sections.get(key); + writeSection(writer, section); + } + } + catch (FileNotFoundException e) + { + Log.error("[SettingsFile] File not found: " + fileName + ".ini: " + e.getMessage()); + subscriber.onError(e); + } + catch (UnsupportedEncodingException e) + { + Log.error("[SettingsFile] Bad encoding; please file a bug report: " + fileName + ".ini: " + e.getMessage()); + subscriber.onError(e); + } finally + { + if (writer != null) + { + writer.close(); + } + } + + subscriber.onNext(true); + subscriber.onCompleted(); + } + }); } @NonNull @@ -85,39 +189,6 @@ public final class SettingsFile return new File(storagePath + "/dolphin-emu/Config/" + fileName + ".ini"); } - public static void saveFile(String fileName, HashMap sections) - { - File ini = getSettingsFile(fileName); - - PrintWriter writer = null; - try - { - writer = new PrintWriter(ini, "UTF-8"); - - Set keySet = sections.keySet(); - - for (String key : keySet) - { - SettingSection section = sections.get(key); - writeSection(writer, section); - } - } - catch (FileNotFoundException e) - { - Log.error("[SettingsFile] File not found: " + fileName + ".ini: " + e.getMessage()); - } - catch (UnsupportedEncodingException e) - { - Log.error("[SettingsFile] Bad encoding; please file a bug report: " + fileName + ".ini: " + e.getMessage()); - } finally - { - if (writer != null) - { - writer.close(); - } - } - } - private static SettingSection sectionFromLine(String line) { String sectionName = line.substring(1, line.length() - 1); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java deleted file mode 100644 index a5d8883b95..0000000000 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/UserPreferences.java +++ /dev/null @@ -1,495 +0,0 @@ -/** - * Copyright 2013 Dolphin Emulator Project - * Licensed under GPLv2+ - * Refer to the license.txt file included. - */ - -package org.dolphinemu.dolphinemu.utils; - -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Build; -import android.preference.PreferenceManager; - -import org.dolphinemu.dolphinemu.NativeLibrary; - -/** - * A class that retrieves all of the set user preferences in Android, in a safe way. - *

- * If any preferences are added to this emulator, an accessor for that preference - * should be added here. This way lengthy calls to getters from SharedPreferences - * aren't made necessary. - */ -public final class UserPreferences -{ - private UserPreferences() - { - // Disallows instantiation. - } - - /** - * Loads the settings stored in the Dolphin ini config files to the shared preferences of this front-end. - * - * @param ctx The context used to retrieve the SharedPreferences instance. - */ - public static void LoadIniToPrefs(Context ctx) - { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx); - - // Get an editor. - SharedPreferences.Editor editor = prefs.edit(); - - // Add the settings. - if (Build.CPU_ABI.contains("arm64")) - editor.putString("cpuCorePref", getConfig("Dolphin.ini", "Core", "CPUCore", "4")); - else - editor.putString("cpuCorePref", getConfig("Dolphin.ini", "Core", "CPUCore", "3")); - - editor.putBoolean("dualCorePref", getConfig("Dolphin.ini", "Core", "CPUThread", "True").equals("True")); - editor.putBoolean("OverclockEnable", getConfig("Dolphin.ini", "Core", "OverclockEnable", "False").equals("True")); - editor.putString("Overclock", getConfig("Dolphin.ini", "Core", "Overclock", "100")); - - // Load analog ranges from GCPadNew.ini and WiimoteNew.ini - editor.putString("mainRadius0", getConfig("GCPadNew.ini", "GCPad1", "Main Stick/Radius", "100,000000")); - editor.putString("cStickRadius0", getConfig("GCPadNew.ini", "GCPad1", "C-Stick/Radius", "100,000000")); - editor.putString("inputThres0", getConfig("GCPadNew.ini", "GCPad1", "Triggers/Threshold", "90,000000")); - editor.putString("mainRadius1", getConfig("GCPadNew.ini", "GCPad2", "Main Stick/Radius", "100,000000")); - editor.putString("cStickRadius1", getConfig("GCPadNew.ini", "GCPad2", "C-Stick/Radius", "100,000000")); - editor.putString("inputThres1", getConfig("GCPadNew.ini", "GCPad2", "Triggers/Threshold", "90,000000")); - editor.putString("mainRadius2", getConfig("GCPadNew.ini", "GCPad3", "Main Stick/Radius", "100,000000")); - editor.putString("cStickRadius2", getConfig("GCPadNew.ini", "GCPad3", "C-Stick/Radius", "100,000000")); - editor.putString("inputThres2", getConfig("GCPadNew.ini", "GCPad3", "Triggers/Threshold", "90,000000")); - editor.putString("mainRadius3", getConfig("GCPadNew.ini", "GCPad4", "Main Stick/Radius", "100,000000")); - editor.putString("cStickRadius3", getConfig("GCPadNew.ini", "GCPad4", "C-Stick/Radius", "100,000000")); - editor.putString("inputThres3", getConfig("GCPadNew.ini", "GCPad4", "Triggers/Threshold", "90,000000")); - - editor.putString("tiltRange4", getConfig("WiimoteNew.ini", "Wiimote1", "Tilt/Modifier/Range", "50,00000")); - editor.putString("tiltRange5", getConfig("WiimoteNew.ini", "Wiimote2", "Tilt/Modifier/Range", "50,00000")); - editor.putString("tiltRange6", getConfig("WiimoteNew.ini", "Wiimote3", "Tilt/Modifier/Range", "50,00000")); - editor.putString("tiltRange7", getConfig("WiimoteNew.ini", "Wiimote4", "Tilt/Modifier/Range", "50,00000")); - - editor.putString("nunchukRadius4", getConfig("WiimoteNew.ini", "Wiimote1", "Nunchuk/Stick/Radius", "100,000000")); - editor.putString("nunchukRange4", getConfig("WiimoteNew.ini", "Wiimote1", "Nunchuk/Tilt/Modifier/Range", "50,00000")); - editor.putString("nunchukRadius5", getConfig("WiimoteNew.ini", "Wiimote2", "Nunchuk/Stick/Radius", "100,000000")); - editor.putString("nunchukRange5", getConfig("WiimoteNew.ini", "Wiimote2", "Nunchuk/Tilt/Modifier/Range", "50,00000")); - editor.putString("nunchukRadius6", getConfig("WiimoteNew.ini", "Wiimote3", "Nunchuk/Stick/Radius", "100,000000")); - editor.putString("nunchukRange6", getConfig("WiimoteNew.ini", "Wiimote3", "Nunchuk/Tilt/Modifier/Range", "50,00000")); - editor.putString("nunchukRadius7", getConfig("WiimoteNew.ini", "Wiimote4", "Nunchuk/Stick/Radius", "100,000000")); - editor.putString("nunchukRange7", getConfig("WiimoteNew.ini", "Wiimote4", "Nunchuk/Tilt/Modifier/Range", "50,00000")); - - editor.putString("classicLRadius4", getConfig("WiimoteNew.ini", "Wiimote1", "Classic/Left Stick/Radius", "100,000000")); - editor.putString("classicRRadius4", getConfig("WiimoteNew.ini", "Wiimote1", "Classic/Right Stick/Radius", "100,000000")); - editor.putString("classicThres4", getConfig("WiimoteNew.ini", "Wiimote1", "Classic/Triggers/Threshold", "90,000000")); - editor.putString("classicLRadius5", getConfig("WiimoteNew.ini", "Wiimote2", "Classic/Left Stick/Radius", "100,000000")); - editor.putString("classicRRadius5", getConfig("WiimoteNew.ini", "Wiimote2", "Classic/Right Stick/Radius", "100,000000")); - editor.putString("classicThres5", getConfig("WiimoteNew.ini", "Wiimote2", "Classic/Triggers/Threshold", "90,000000")); - editor.putString("classicLRadius6", getConfig("WiimoteNew.ini", "Wiimote3", "Classic/Left Stick/Radius", "100,000000")); - editor.putString("classicRRadius6", getConfig("WiimoteNew.ini", "Wiimote3", "Classic/Right Stick/Radius", "100,000000")); - editor.putString("classicThres6", getConfig("WiimoteNew.ini", "Wiimote3", "Classic/Triggers/Threshold", "90,000000")); - editor.putString("classicLRadius7", getConfig("WiimoteNew.ini", "Wiimote4", "Classic/Left Stick/Radius", "100,000000")); - editor.putString("classicRRadius7", getConfig("WiimoteNew.ini", "Wiimote4", "Classic/Right Stick/Radius", "100,000000")); - editor.putString("classicThres7", getConfig("WiimoteNew.ini", "Wiimote4", "Classic/Triggers/Threshold", "90,000000")); - - editor.putString("guitarRadius4", getConfig("WiimoteNew.ini", "Wiimote1", "Guitar/Stick/Radius", "100,000000")); - editor.putString("guitarRadius5", getConfig("WiimoteNew.ini", "Wiimote2", "Guitar/Stick/Radius", "100,000000")); - editor.putString("guitarRadius6", getConfig("WiimoteNew.ini", "Wiimote3", "Guitar/Stick/Radius", "100,000000")); - editor.putString("guitarRadius7", getConfig("WiimoteNew.ini", "Wiimote4", "Guitar/Stick/Radius", "100,000000")); - - editor.putString("drumsRadius4", getConfig("WiimoteNew.ini", "Wiimote1", "Drums/Stick/Radius", "100,000000")); - editor.putString("drumsRadius5", getConfig("WiimoteNew.ini", "Wiimote2", "Drums/Stick/Radius", "100,000000")); - editor.putString("drumsRadius6", getConfig("WiimoteNew.ini", "Wiimote3", "Drums/Stick/Radius", "100,000000")); - editor.putString("drumsRadius7", getConfig("WiimoteNew.ini", "Wiimote4", "Drums/Stick/Radius", "100,000000")); - - editor.putString("turntableRadius4", getConfig("WiimoteNew.ini", "Wiimote1", "Turntable/Stick/Radius", "100,000000")); - editor.putString("turntableRadius5", getConfig("WiimoteNew.ini", "Wiimote2", "Turntable/Stick/Radius", "100,000000")); - editor.putString("turntableRadius6", getConfig("WiimoteNew.ini", "Wiimote3", "Turntable/Stick/Radius", "100,000000")); - editor.putString("turntableRadius7", getConfig("WiimoteNew.ini", "Wiimote4", "Turntable/Stick/Radius", "100,000000")); - - // Load Wiimote Extension settings from WiimoteNew.ini - editor.putString("wiimoteExtension4", getConfig("WiimoteNew.ini", "Wiimote1", "Extension", "None")); - editor.putString("wiimoteExtension5", getConfig("WiimoteNew.ini", "Wiimote2", "Extension", "None")); - editor.putString("wiimoteExtension6", getConfig("WiimoteNew.ini", "Wiimote3", "Extension", "None")); - editor.putString("wiimoteExtension7", getConfig("WiimoteNew.ini", "Wiimote4", "Extension", "None")); - - editor.putString("gpuPref", getConfig("Dolphin.ini", "Core", "GFXBackend", "OGL")); - editor.putBoolean("showFPS", getConfig("GFX.ini", "Settings", "ShowFPS", "False").equals("True")); - editor.putBoolean("drawOnscreenControls", getConfig("Dolphin.ini", "Android", "ScreenControls", "True").equals("True")); - - editor.putString("internalResolution", getConfig("GFX.ini", "Settings", "EFBScale", "2")); - editor.putString("FSAA", getConfig("GFX.ini", "Settings", "MSAA", "0")); - editor.putString("anisotropicFiltering", getConfig("GFX.ini", "Enhancements", "MaxAnisotropy", "0")); - editor.putString("postProcessingShader", getConfig("GFX.ini", "Enhancements", "PostProcessingShader", "")); - editor.putBoolean("scaledEFBCopy", getConfig("GFX.ini", "Hacks", "EFBScaledCopy", "True").equals("True")); - editor.putBoolean("perPixelLighting", getConfig("GFX.ini", "Settings", "EnablePixelLighting", "False").equals("True")); - editor.putBoolean("forceTextureFiltering", getConfig("GFX.ini", "Enhancements", "ForceFiltering", "False").equals("True")); - editor.putBoolean("disableFog", getConfig("GFX.ini", "Settings", "DisableFog", "False").equals("True")); - editor.putBoolean("skipEFBAccess", getConfig("GFX.ini", "Hacks", "EFBAccessEnable", "False").equals("True")); - editor.putBoolean("ignoreFormatChanges", getConfig("GFX.ini", "Hacks", "EFBEmulateFormatChanges", "False").equals("True")); - editor.putString("stereoscopyMode", getConfig("GFX.ini", "Stereoscopy", "StereoMode", "0")); - editor.putBoolean("stereoSwapEyes", getConfig("GFX.ini", "Stereoscopy", "StereoSwapEyes", "False").equals("True")); - editor.putString("stereoDepth", getConfig("GFX.ini", "Stereoscopy", "StereoDepth", "20")); - editor.putString("stereoConvergencePercentage", getConfig("GFX.ini", "Stereoscopy", "StereoConvergencePercentage", "100")); - editor.putBoolean("enableController1", getConfig("Dolphin.ini", "Core", "SIDevice0", "6") == "6"); - editor.putBoolean("enableController2", getConfig("Dolphin.ini", "Core", "SIDevice1", "0") == "6"); - editor.putBoolean("enableController3", getConfig("Dolphin.ini", "Core", "SIDevice2", "0") == "6"); - editor.putBoolean("enableController4", getConfig("Dolphin.ini", "Core", "SIDevice3", "0") == "6"); - - String efbCopyOn = getConfig("GFX.ini", "Hacks", "EFBCopyEnable", "True"); - String efbToTexture = getConfig("GFX.ini", "Hacks", "EFBToTextureEnable", "True"); - String efbCopyCache = getConfig("GFX.ini", "Hacks", "EFBCopyCacheEnable", "False"); - - if (efbCopyOn.equals("False")) - { - editor.putString("efbCopyMethod", "Off"); - } - else if (efbCopyOn.equals("True") && efbToTexture.equals("True")) - { - editor.putString("efbCopyMethod", "Texture"); - } - else if(efbCopyOn.equals("True") && efbToTexture.equals("False") && efbCopyCache.equals("False")) - { - editor.putString("efbCopyMethod", "RAM (uncached)"); - } - else if(efbCopyOn.equals("True") && efbToTexture.equals("False") && efbCopyCache.equals("True")) - { - editor.putString("efbCopyMethod", "RAM (cached)"); - } - - editor.putString("textureCacheAccuracy", getConfig("GFX.ini", "Settings", "SafeTextureCacheColorSamples", "128")); - - String usingXFB = getConfig("GFX.ini", "Settings", "UseXFB", "False"); - String usingRealXFB = getConfig("GFX.ini", "Settings", "UseRealXFB", "False"); - - if (usingXFB.equals("False")) - { - editor.putString("externalFrameBuffer", "Disabled"); - } - else if (usingXFB.equals("True") && usingRealXFB.equals("False")) - { - editor.putString("externalFrameBuffer", "Virtual"); - } - else if (usingXFB.equals("True") && usingRealXFB.equals("True")) - { - editor.putString("externalFrameBuffer", "Real"); - } - - editor.putBoolean("fastDepthCalculation", getConfig("GFX.ini", "Settings", "FastDepthCalc", "True").equals("True")); - editor.putString("aspectRatio", getConfig("GFX.ini", "Settings", "AspectRatio", "0")); - - // Apply the changes. - editor.apply(); - } - - // Small utility method that shortens calls to NativeLibrary.GetConfig. - private static String getConfig(String ini, String section, String key, String defaultValue) - { - return NativeLibrary.GetConfig(ini, section, key, defaultValue); - } - - /** - * Writes the preferences set in the front-end to the Dolphin ini files. - * - * @param ctx The context used to retrieve the user settings. - * */ - public static void SavePrefsToIni(Context ctx) - { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ctx); - - // Whether or not the user is using dual core. - boolean isUsingDualCore = prefs.getBoolean("dualCorePref", true); - - // Current CPU core being used. Falls back to interpreter upon error. - String currentEmuCore = prefs.getString("cpuCorePref", "0"); - - boolean overclockEnabled = prefs.getBoolean("OverclockEnable", false); - String overclockSetting = prefs.getString("Overclock", "100"); - - // Current GC analog range setup. Falls back to default upon error. - String currentMainRadius0 = prefs.getString("mainRadius0", "100,000000"); - String currentCStickRadius0 = prefs.getString("cStickRadius0", "100,000000"); - String currentInputThres0 = prefs.getString("inputThres0", "90,000000"); - String currentMainRadius1 = prefs.getString("mainRadius1", "100,000000"); - String currentCStickRadius1 = prefs.getString("cStickRadius1", "100,000000"); - String currentInputThres1 = prefs.getString("inputThres1", "90,000000"); - String currentMainRadius2 = prefs.getString("mainRadius2", "100,000000"); - String currentCStickRadius2 = prefs.getString("cStickRadius2", "100,000000"); - String currentInputThres2 = prefs.getString("inputThres2", "90,000000"); - String currentMainRadius3 = prefs.getString("mainRadius3", "100,000000"); - String currentCStickRadius3 = prefs.getString("cStickRadius3", "100,000000"); - String currentInputThres3 = prefs.getString("inputThres3", "90,000000"); - - // Current Wii analog range setup. Falls back to default on error. - String currentTiltRange4 = prefs.getString("tiltRange4", "50,000000"); - String currentTiltRange5 = prefs.getString("tiltRange5", "50,000000"); - String currentTiltRange6 = prefs.getString("tiltRange6", "50,000000"); - String currentTiltRange7 = prefs.getString("tiltRange7", "50,000000"); - - // Current Nunchuk analog range setup. Falls back to default upon error. - String currentNunchukRadius4 = prefs.getString("nunchukRadius4", "100,000000"); - String currentNunchukRange4 = prefs.getString("nunchukRange4", "50,000000"); - String currentNunchukRadius5 = prefs.getString("nunchukRadius5", "100,000000"); - String currentNunchukRange5 = prefs.getString("nunchukRange5", "50,000000"); - String currentNunchukRadius6 = prefs.getString("nunchukRadius6", "100,000000"); - String currentNunchukRange6 = prefs.getString("nunchukRange6", "50,000000"); - String currentNunchukRadius7 = prefs.getString("nunchukRadius7", "100,000000"); - String currentNunchukRange7 = prefs.getString("nunchukRange7", "50,000000"); - - // Current Classic analog range setup. Falls back to 100,000000 upon error. - String currentClassicLRadius4 = prefs.getString("classicLRadius4", "100,000000"); - String currentClassicRRadius4 = prefs.getString("classicRRadius4", "100,000000"); - String currentClassicThres4 = prefs.getString("classicThres4", "90,000000"); - String currentClassicLRadius5 = prefs.getString("classicLRadius5", "100,000000"); - String currentClassicRRadius5 = prefs.getString("classicRRadius5", "100,000000"); - String currentClassicThres5 = prefs.getString("classicThres5", "90,000000"); - String currentClassicLRadius6 = prefs.getString("classicLRadius6", "100,000000"); - String currentClassicRRadius6 = prefs.getString("classicRRadius6", "100,000000"); - String currentClassicThres6 = prefs.getString("classicThres6", "90,000000"); - String currentClassicLRadius7 = prefs.getString("classicLRadius7", "100,000000"); - String currentClassicRRadius7 = prefs.getString("classicRRadius7", "100,000000"); - String currentClassicThres7 = prefs.getString("classicThres7", "90,000000"); - - // Current Guitar analog range setup. Falls back to default upon error. - String currentGuitarRadius4 = prefs.getString("guitarRadius4", "100,000000"); - String currentGuitarRadius5 = prefs.getString("guitarRadius5", "100,000000"); - String currentGuitarRadius6 = prefs.getString("guitarRadius6", "100,000000"); - String currentGuitarRadius7 = prefs.getString("guitarRadius7", "100,000000"); - - // Current Drums modifier Radius setup. Falls back to default upon error. - String currentDrumsRadius4 = prefs.getString("drumsRadius4", "100,000000"); - String currentDrumsRadius5 = prefs.getString("drumsRadius5", "100,000000"); - String currentDrumsRadius6 = prefs.getString("drumsRadius6", "100,000000"); - String currentDrumsRadius7 = prefs.getString("drumsRadius7", "100,000000"); - - // Current Turntable analog range setup. Falls back to default upon error. - String currentTurntableRadius4 = prefs.getString("turntableRadius4", "100,000000"); - String currentTurntableRadius5 = prefs.getString("turntableRadius5", "100,000000"); - String currentTurntableRadius6 = prefs.getString("turntableRadius6", "100,000000"); - String currentTurntableRadius7 = prefs.getString("turntableRadius7", "100,000000"); - - // Current wiimote extension setup. Falls back to no extension upon error. - String currentWiimoteExtension4 = prefs.getString("wiimoteExtension4", "None"); - String currentWiimoteExtension5 = prefs.getString("wiimoteExtension5", "None"); - String currentWiimoteExtension6 = prefs.getString("wiimoteExtension6", "None"); - String currentWiimoteExtension7 = prefs.getString("wiimoteExtension7", "None"); - - // Current video backend being used. Falls back to software rendering upon error. - String currentVideoBackend = prefs.getString("gpuPref", "Software Rendering"); - - // Whether or not FPS will be displayed on-screen. - boolean showingFPS = prefs.getBoolean("showFPS", false); - - // Whether or not to draw on-screen controls. - boolean drawingOnscreenControls = prefs.getBoolean("drawOnscreenControls", true); - - // Whether or not to ignore all EFB access requests from the CPU. - boolean skipEFBAccess = prefs.getBoolean("skipEFBAccess", false); - - // Whether or not to ignore changes to the EFB format. - boolean ignoreFormatChanges = prefs.getBoolean("ignoreFormatChanges", false); - - // EFB copy method to use. - String efbCopyMethod = prefs.getString("efbCopyMethod", "Texture"); - - // Texture cache accuracy. Falls back to "Fast" up error. - String textureCacheAccuracy = prefs.getString("textureCacheAccuracy", "128"); - - // External frame buffer emulation. Falls back to disabled upon error. - String externalFrameBuffer = prefs.getString("externalFrameBuffer", "Disabled"); - - // Whether or not to use fast depth calculation. - boolean useFastDepthCalc = prefs.getBoolean("fastDepthCalculation", true); - - // Aspect ratio selection - String aspectRatio = prefs.getString("aspectRatio", "0"); - - // Internal resolution. Falls back to 1x Native upon error. - String internalResolution = prefs.getString("internalResolution", "2"); - - // FSAA Level. Falls back to 1x upon error. - String FSAALevel = prefs.getString("FSAA", "0"); - - // Anisotropic Filtering Level. Falls back to 1x upon error. - String anisotropicFiltLevel = prefs.getString("anisotropicFiltering", "0"); - - // Post processing shader setting - String postProcessing = prefs.getString("postProcessingShader", ""); - - // Whether or not Scaled EFB copies are used. - boolean usingScaledEFBCopy = prefs.getBoolean("scaledEFBCopy", true); - - // Whether or not per-pixel lighting is used. - boolean usingPerPixelLighting = prefs.getBoolean("perPixelLighting", false); - - // Whether or not texture filtering is being forced. - boolean isForcingTextureFiltering = prefs.getBoolean("forceTextureFiltering", false); - - // Whether or not fog is disabled. - boolean fogIsDisabled = prefs.getBoolean("disableFog", false); - - // Stereoscopy setting - String stereoscopyMode = prefs.getString("stereoscopyMode", "0"); - - // Stereoscopy swap eyes - boolean stereoscopyEyeSwap = prefs.getBoolean("stereoSwapEyes", false); - - // Stereoscopy separation - String stereoscopySeparation = prefs.getString("stereoDepth", "20"); - - // Stereoscopy convergence - String stereoConvergencePercentage = prefs.getString("stereoConvergencePercentage", "100"); - - // Controllers - // Controller 1 never gets disconnected due to touch screen - //boolean enableController1 = prefs.getBoolean("enableController1", true); - boolean enableController2 = prefs.getBoolean("enableController2", false); - boolean enableController3 = prefs.getBoolean("enableController3", false); - boolean enableController4 = prefs.getBoolean("enableController4", false); - - // CPU related Settings - NativeLibrary.SetConfig("Dolphin.ini", "Core", "CPUCore", currentEmuCore); - NativeLibrary.SetConfig("Dolphin.ini", "Core", "CPUThread", isUsingDualCore ? "True" : "False"); - - NativeLibrary.SetConfig("Dolphin.ini", "Core", "OverclockEnable", overclockEnabled ? "True" : "False"); - NativeLibrary.SetConfig("Dolphin.ini", "Core", "Overclock", overclockSetting); - - // GameCube analog ranges Setup - NativeLibrary.SetConfig("GCPadNew.ini", "GCPad1", "Main Stick/Radius", currentMainRadius0); - NativeLibrary.SetConfig("GCPadNew.ini", "GCPad1", "C-Stick/Radius", currentCStickRadius0); - NativeLibrary.SetConfig("GCPadNew.ini", "GCPad1", "Triggers/Threshold", currentInputThres0); - NativeLibrary.SetConfig("GCPadNew.ini", "GCPad2", "Main Stick/Radius", currentMainRadius1); - NativeLibrary.SetConfig("GCPadNew.ini", "GCPad2", "C-Stick/Radius", currentCStickRadius1); - NativeLibrary.SetConfig("GCPadNew.ini", "GCPad2", "Triggers/Threshold", currentInputThres1); - NativeLibrary.SetConfig("GCPadNew.ini", "GCPad3", "Main Stick/Radius", currentMainRadius2); - NativeLibrary.SetConfig("GCPadNew.ini", "GCPad3", "C-Stick/Radius", currentCStickRadius2); - NativeLibrary.SetConfig("GCPadNew.ini", "GCPad3", "Triggers/Threshold", currentInputThres2); - NativeLibrary.SetConfig("GCPadNew.ini", "GCPad4", "Main Stick/Radius", currentMainRadius3); - NativeLibrary.SetConfig("GCPadNew.ini", "GCPad4", "C-Stick/Radius", currentCStickRadius3); - NativeLibrary.SetConfig("GCPadNew.ini", "GCPad4", "Triggers/Threshold", currentInputThres3); - - // Wiimote analog ranges Setup - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote1", "Tilt/Modifier/Range", currentTiltRange4); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote2", "Tilt/Modifier/Range", currentTiltRange5); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote3", "Tilt/Modifier/Range", currentTiltRange6); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote4", "Tilt/Modifier/Range", currentTiltRange7); - - // Nunchuk analog ranges Setup - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote1", "Nunchuk/Stick/Radius", currentNunchukRadius4); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote1", "Nunchuk/Stick/Radius", currentNunchukRange4); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote2", "Nunchuk/Stick/Radius", currentNunchukRadius5); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote2", "Nunchuk/Stick/Radius", currentNunchukRange5); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote3", "Nunchuk/Stick/Radius", currentNunchukRadius6); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote3", "Nunchuk/Stick/Radius", currentNunchukRange6); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote4", "Nunchuk/Stick/Radius", currentNunchukRadius7); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote4", "Nunchuk/Stick/Radius", currentNunchukRange7); - - // Classic analog ranges Setup - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote1", "Classic/Left Stick/Radius", currentClassicLRadius4); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote1", "Classic/Right Stick/Radius", currentClassicRRadius4); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote1", "Classic/Triggers/Threshold", currentClassicThres4); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote2", "Classic/Left Stick/Radius", currentClassicLRadius5); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote2", "Classic/Right Stick/Radius", currentClassicRRadius5); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote2", "Classic/Triggers/Threshold", currentClassicThres5); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote3", "Classic/Left Stick/Radius", currentClassicLRadius6); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote3", "Classic/Right Stick/Radius", currentClassicRRadius6); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote3", "Classic/Triggers/Threshold", currentClassicThres6); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote4", "Classic/Left Stick/Radius", currentClassicLRadius7); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote4", "Classic/Right Stick/Radius", currentClassicRRadius7); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote4", "Classic/Triggers/Threshold", currentClassicThres7); - - // Guitar analog ranges Setup - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote1", "Guitar/Stick/Radius", currentGuitarRadius4); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote2", "Guitar/Stick/Radius", currentGuitarRadius5); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote3", "Guitar/Stick/Radius", currentGuitarRadius6); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote4", "Guitar/Stick/Radius", currentGuitarRadius7); - - // Drums analog ranges Setup - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote1", "Drums/Stick/Radius", currentDrumsRadius4); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote2", "Drums/Stick/Radius", currentDrumsRadius5); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote3", "Drums/Stick/Radius", currentDrumsRadius6); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote4", "Drums/Stick/Radius", currentDrumsRadius7); - - // Turntable analog ranges Setup - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote1", "Turntable/Stick/Radius", currentTurntableRadius4); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote2", "Turntable/Stick/Radius", currentTurntableRadius5); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote3", "Turntable/Stick/Radius", currentTurntableRadius6); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote4", "Turntable/Stick/Radius", currentTurntableRadius7); - - // Wiimote Extension Settings - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote1", "Extension", currentWiimoteExtension4); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote2", "Extension", currentWiimoteExtension5); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote3", "Extension", currentWiimoteExtension6); - NativeLibrary.SetConfig("WiimoteNew.ini", "Wiimote4", "Extension", currentWiimoteExtension7); - - // General Video Settings - NativeLibrary.SetConfig("Dolphin.ini", "Core", "GFXBackend", currentVideoBackend); - NativeLibrary.SetConfig("GFX.ini", "Settings", "ShowFPS", showingFPS ? "True" : "False"); - NativeLibrary.SetConfig("Dolphin.ini", "Android", "ScreenControls", drawingOnscreenControls ? "True" : "False"); - - // Video Hack Settings - NativeLibrary.SetConfig("GFX.ini", "Hacks", "EFBAccessEnable", skipEFBAccess ? "False" : "True"); - NativeLibrary.SetConfig("GFX.ini", "Hacks", "EFBEmulateFormatChanges", ignoreFormatChanges ? "True" : "False"); - NativeLibrary.SetConfig("GFX.ini", "Settings", "AspectRatio", aspectRatio); - - // Set EFB Copy Method - if (efbCopyMethod.equals("Off")) - { - NativeLibrary.SetConfig("GFX.ini", "Hacks", "EFBCopyEnable", "False"); - } - else if (efbCopyMethod.equals("Texture")) - { - NativeLibrary.SetConfig("GFX.ini", "Hacks", "EFBCopyEnable", "True"); - NativeLibrary.SetConfig("GFX.ini", "Hacks", "EFBToTextureEnable", "True"); - } - else if (efbCopyMethod.equals("RAM (uncached)")) - { - NativeLibrary.SetConfig("GFX.ini", "Hacks", "EFBCopyEnable", "True"); - NativeLibrary.SetConfig("GFX.ini", "Hacks", "EFBToTextureEnable", "False"); - NativeLibrary.SetConfig("GFX.ini", "Hacks", "EFBCopyCacheEnable", "False"); - } - else if (efbCopyMethod.equals("RAM (cached)")) - { - NativeLibrary.SetConfig("GFX.ini", "Hacks", "EFBCopyEnable", "True"); - NativeLibrary.SetConfig("GFX.ini", "Hacks", "EFBToTextureEnable", "False"); - NativeLibrary.SetConfig("GFX.ini", "Hacks", "EFBCopyCacheEnable", "True"); - } - - // Set texture cache accuracy - NativeLibrary.SetConfig("GFX.ini", "Settings", "SafeTextureCacheColorSamples", textureCacheAccuracy); - - // Set external frame buffer. - if (externalFrameBuffer.equals("Disabled")) - { - NativeLibrary.SetConfig("GFX.ini", "Settings", "UseXFB", "False"); - } - else if (externalFrameBuffer.equals("Virtual")) - { - NativeLibrary.SetConfig("GFX.ini", "Settings", "UseXFB", "True"); - NativeLibrary.SetConfig("GFX.ini", "Settings", "UseRealXFB", "False"); - } - else if (externalFrameBuffer.equals("Real")) - { - NativeLibrary.SetConfig("GFX.ini", "Settings", "UseXFB", "True"); - NativeLibrary.SetConfig("GFX.ini", "Settings", "UseRealXFB", "True"); - } - - NativeLibrary.SetConfig("GFX.ini", "Settings", "FastDepthCalc", useFastDepthCalc ? "True" : "False"); - - //-- Enhancement Settings --// - NativeLibrary.SetConfig("GFX.ini", "Settings", "EFBScale", internalResolution); - NativeLibrary.SetConfig("GFX.ini", "Settings", "MSAA", FSAALevel); - NativeLibrary.SetConfig("GFX.ini", "Enhancements", "MaxAnisotropy", anisotropicFiltLevel); - NativeLibrary.SetConfig("GFX.ini", "Enhancements", "PostProcessingShader", postProcessing); - NativeLibrary.SetConfig("GFX.ini", "Hacks", "EFBScaledCopy", usingScaledEFBCopy ? "True" : "False"); - NativeLibrary.SetConfig("GFX.ini", "Settings", "EnablePixelLighting", usingPerPixelLighting ? "True" : "False"); - NativeLibrary.SetConfig("GFX.ini", "Enhancements", "ForceFiltering", isForcingTextureFiltering ? "True" : "False"); - NativeLibrary.SetConfig("GFX.ini", "Settings", "DisableFog", fogIsDisabled ? "True" : "False"); - NativeLibrary.SetConfig("GFX.ini", "Stereoscopy", "StereoMode", stereoscopyMode); - NativeLibrary.SetConfig("GFX.ini", "Stereoscopy", "StereoSwapEyes", stereoscopyEyeSwap ? "True" : "False"); - NativeLibrary.SetConfig("GFX.ini", "Stereoscopy", "StereoDepth", stereoscopySeparation); - NativeLibrary.SetConfig("GFX.ini", "Stereoscopy", "StereoConvergence", stereoConvergencePercentage); - NativeLibrary.SetConfig("Dolphin.ini", "Core", "SIDevice0", "6"); - NativeLibrary.SetConfig("Dolphin.ini", "Core", "SIDevice1", enableController2 ? "6" : "0"); - NativeLibrary.SetConfig("Dolphin.ini", "Core", "SIDevice2", enableController3 ? "6" : "0"); - NativeLibrary.SetConfig("Dolphin.ini", "Core", "SIDevice3", enableController4 ? "6" : "0"); - } -} diff --git a/Source/Android/app/src/main/res/layout/activity_settings.xml b/Source/Android/app/src/main/res/layout/activity_settings.xml index d72e5a0142..492fbf04ec 100644 --- a/Source/Android/app/src/main/res/layout/activity_settings.xml +++ b/Source/Android/app/src/main/res/layout/activity_settings.xml @@ -1,20 +1,5 @@ - - - - - - - \ No newline at end of file + diff --git a/Source/Android/app/src/main/res/layout/fragment_settings.xml b/Source/Android/app/src/main/res/layout/fragment_settings.xml new file mode 100644 index 0000000000..3823d50d12 --- /dev/null +++ b/Source/Android/app/src/main/res/layout/fragment_settings.xml @@ -0,0 +1,11 @@ + + + + + + \ No newline at end of file diff --git a/Source/Android/app/src/main/res/layout/list_item_setting.xml b/Source/Android/app/src/main/res/layout/list_item_setting.xml new file mode 100644 index 0000000000..d150d53265 --- /dev/null +++ b/Source/Android/app/src/main/res/layout/list_item_setting.xml @@ -0,0 +1,39 @@ + + + + + + + + \ No newline at end of file diff --git a/Source/Android/app/src/main/res/layout/list_item_setting_checkbox.xml b/Source/Android/app/src/main/res/layout/list_item_setting_checkbox.xml new file mode 100644 index 0000000000..265c51bb61 --- /dev/null +++ b/Source/Android/app/src/main/res/layout/list_item_setting_checkbox.xml @@ -0,0 +1,49 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Source/Android/app/src/main/res/layout/list_item_settings_header.xml b/Source/Android/app/src/main/res/layout/list_item_settings_header.xml new file mode 100644 index 0000000000..3c72913c93 --- /dev/null +++ b/Source/Android/app/src/main/res/layout/list_item_settings_header.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/Source/Android/app/src/main/res/values/dimens.xml b/Source/Android/app/src/main/res/values/dimens.xml index 986b230792..ba98e10607 100644 --- a/Source/Android/app/src/main/res/values/dimens.xml +++ b/Source/Android/app/src/main/res/values/dimens.xml @@ -9,4 +9,11 @@ 16dp 128dp + + 2dp + 4dp + 8dp + 12dp + 16dp + 32dp diff --git a/Source/Android/app/src/main/res/values/styles.xml b/Source/Android/app/src/main/res/values/styles.xml index dba853f492..d5db92e1e3 100644 --- a/Source/Android/app/src/main/res/values/styles.xml +++ b/Source/Android/app/src/main/res/values/styles.xml @@ -17,7 +17,7 @@ - From c8e4008b83b96ea69b40cff98497d8f85830df62 Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Tue, 19 Jan 2016 23:03:44 -0500 Subject: [PATCH 3/6] Implement Seekbar dialog and SingleChoice dialog --- .../app/src/arm_64/res/values/arrays.xml | 4 +- .../model/settings/view/SliderSetting.java | 20 ++- .../ui/settings/SettingsAdapter.java | 156 +++++++++++++++++- .../ui/settings/SettingsFragment.java | 5 + .../settings/SettingsFragmentPresenter.java | 2 +- .../ui/settings/SettingsFragmentView.java | 4 + .../dolphinemu/utils/SliderPreference.java | 128 -------------- .../src/main/res/layout/dialog_seekbar.xml | 37 +++++ .../app/src/main/res/layout/slider_layout.xml | 23 --- .../app/src/main/res/values/arrays.xml | 4 +- .../app/src/main/res/values/strings.xml | 2 + 11 files changed, 225 insertions(+), 160 deletions(-) delete mode 100644 Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SliderPreference.java create mode 100644 Source/Android/app/src/main/res/layout/dialog_seekbar.xml delete mode 100644 Source/Android/app/src/main/res/layout/slider_layout.xml diff --git a/Source/Android/app/src/arm_64/res/values/arrays.xml b/Source/Android/app/src/arm_64/res/values/arrays.xml index 8f2ed0edff..fb98aa63da 100644 --- a/Source/Android/app/src/arm_64/res/values/arrays.xml +++ b/Source/Android/app/src/arm_64/res/values/arrays.xml @@ -9,10 +9,10 @@ @string/cached_interpreter @string/jit_arm64_recompiler - + 0 5 4 - + \ No newline at end of file diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SliderSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SliderSetting.java index 4194753f52..685ba5aa69 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SliderSetting.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SliderSetting.java @@ -4,15 +4,19 @@ import org.dolphinemu.dolphinemu.model.settings.FloatSetting; import org.dolphinemu.dolphinemu.model.settings.IntSetting; import org.dolphinemu.dolphinemu.model.settings.Setting; import org.dolphinemu.dolphinemu.utils.Log; +import org.dolphinemu.dolphinemu.utils.SettingsFile; public class SliderSetting extends SettingsItem { private int mMax; - public SliderSetting(String key, Setting setting, int titleId, int descriptionId, int max) + private String mUnits; + + public SliderSetting(String key, Setting setting, int titleId, int descriptionId, int max, String units) { super(key, setting, titleId, descriptionId); mMax = max; + mUnits = units; } public int getMax() @@ -32,7 +36,14 @@ public class SliderSetting extends SettingsItem else if (setting instanceof FloatSetting) { FloatSetting floatSetting = (FloatSetting) setting; - return Math.round(floatSetting.getValue()); + if (floatSetting.getKey().equals(SettingsFile.KEY_OVERCLOCK_PERCENT)) + { + return Math.round(floatSetting.getValue() * 100); + } + else + { + return Math.round(floatSetting.getValue()); + } } else { @@ -53,6 +64,11 @@ public class SliderSetting extends SettingsItem setting.setValue(selection); } + public String getUnits() + { + return mUnits; + } + @Override public int getType() { diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java index 8d8272d2f7..f386fc94df 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java @@ -1,13 +1,18 @@ package org.dolphinemu.dolphinemu.ui.settings; import android.content.Context; +import android.content.DialogInterface; +import android.support.v7.app.AlertDialog; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.SeekBar; +import android.widget.TextView; import android.widget.Toast; import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.model.settings.FloatSetting; import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; import org.dolphinemu.dolphinemu.model.settings.view.SingleChoiceSetting; import org.dolphinemu.dolphinemu.model.settings.view.SliderSetting; @@ -19,15 +24,23 @@ import org.dolphinemu.dolphinemu.ui.settings.viewholder.SingleChoiceViewHolder; import org.dolphinemu.dolphinemu.ui.settings.viewholder.SliderViewHolder; import org.dolphinemu.dolphinemu.ui.settings.viewholder.SubmenuViewHolder; import org.dolphinemu.dolphinemu.utils.Log; +import org.dolphinemu.dolphinemu.utils.SettingsFile; import java.util.ArrayList; public class SettingsAdapter extends RecyclerView.Adapter + implements DialogInterface.OnClickListener, SeekBar.OnSeekBarChangeListener { private SettingsFragmentView mView; private Context mContext; private ArrayList mSettings; + private SettingsItem mClickedItem; + private int mSeekbarProgress; + + private AlertDialog mDialog; + private TextView mTextSliderValue; + public SettingsAdapter(SettingsFragmentView view, Context context) { mView = view; @@ -106,16 +119,155 @@ public class SettingsAdapter extends RecyclerView.Adapter public void onSingleChoiceClick(SingleChoiceSetting item) { - Toast.makeText(mContext, "Single choice item clicked", Toast.LENGTH_SHORT).show(); + mClickedItem = item; + + int value = getSelectionForSingleChoiceValue(item); + + AlertDialog.Builder builder = new AlertDialog.Builder(mView.getActivity()); + + builder.setTitle(item.getNameId()); + builder.setSingleChoiceItems(item.getChoicesId(), value, this); + + mDialog = builder.show(); } public void onSliderClick(SliderSetting item) { - Toast.makeText(mContext, "Slider item clicked", Toast.LENGTH_SHORT).show(); + mClickedItem = item; + mSeekbarProgress = item.getSelectedValue(); + AlertDialog.Builder builder = new AlertDialog.Builder(mView.getActivity()); + + LayoutInflater inflater = LayoutInflater.from(mView.getActivity()); + View view = inflater.inflate(R.layout.dialog_seekbar, null); + + builder.setTitle(item.getNameId()); + builder.setView(view); + builder.setPositiveButton(R.string.dialog_seekbar_pos, this); + builder.setNegativeButton(R.string.dialog_seekbar_neg, this); + mDialog = builder.show(); + + mTextSliderValue = (TextView) view.findViewById(R.id.text_value); + mTextSliderValue.setText(String.valueOf(mSeekbarProgress)); + + TextView units = (TextView) view.findViewById(R.id.text_units); + units.setText(item.getUnits()); + + SeekBar seekbar = (SeekBar) view.findViewById(R.id.seekbar); + + seekbar.setMax(item.getMax()); + seekbar.setProgress(mSeekbarProgress); + + seekbar.setOnSeekBarChangeListener(this); } public void onSubmenuClick(SubmenuSetting item) { Toast.makeText(mContext, "Submenu item clicked", Toast.LENGTH_SHORT).show(); } + + @Override + public void onClick(DialogInterface dialog, int which) + { + if (mClickedItem instanceof SingleChoiceSetting) + { + SingleChoiceSetting scSetting = (SingleChoiceSetting) mClickedItem; + + int value = getValueForSingleChoiceSelection(scSetting, which); + + scSetting.setSelectedValue(value); + closeDialog(); + } + else if (mClickedItem instanceof SliderSetting) + { + SliderSetting sliderSetting = (SliderSetting) mClickedItem; + if (sliderSetting.getSetting() instanceof FloatSetting) + { + float value; + + if (sliderSetting.getKey().equals(SettingsFile.KEY_OVERCLOCK_PERCENT)) + { + value = mSeekbarProgress / 100.0f; + } + else + { + value = (float) mSeekbarProgress; + } + + sliderSetting.setSelectedValue(value); + } + else + { + sliderSetting.setSelectedValue(mSeekbarProgress); + } + } + + mClickedItem = null; + mSeekbarProgress = -1; + } + + public void closeDialog() + { + if (mDialog != null) + { + mDialog.dismiss(); + mDialog = null; + } + } + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) + { + mSeekbarProgress = progress; + mTextSliderValue.setText(String.valueOf(mSeekbarProgress)); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) + { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) + { + } + + private int getValueForSingleChoiceSelection(SingleChoiceSetting item, int which) + { + int valuesId = item.getValuesId(); + + if (valuesId > 0) + { + int[] valuesArray = mContext.getResources().getIntArray(valuesId); + return valuesArray[which]; + } + else + { + return which; + } + } + + private int getSelectionForSingleChoiceValue(SingleChoiceSetting item) + { + int value = item.getSelectedValue(); + int valuesId = item.getValuesId(); + + if (valuesId > 0) + { + int[] valuesArray = mContext.getResources().getIntArray(valuesId); + for (int index = 0; index < valuesArray.length; index++) + { + int current = valuesArray[index]; + if (current == value) + { + return index; + } + } + } + else + { + return value; + } + + return -1; + } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragment.java index 3d4817f3fc..a612233789 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragment.java @@ -77,6 +77,11 @@ public final class SettingsFragment extends Fragment implements SettingsFragment { super.onDetach(); mView = null; + + if (mAdapter != null) + { + mAdapter.closeDialog(); + } } @Override diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java index d0bc5a36f9..b53d7517f9 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java @@ -97,6 +97,6 @@ public class SettingsFragmentPresenter sl.add(new CheckBoxSetting(overclockEnable.getKey(), overclockEnable, R.string.overclock_enable, R.string.overclock_enable_description)); Setting overclock = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_OVERCLOCK_PERCENT); - sl.add(new SliderSetting(overclock.getKey(), overclock, R.string.overclock_title, 0, 400)); + sl.add(new SliderSetting(overclock.getKey(), overclock, R.string.overclock_title, 0, 400, "%")); } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java index 5f0f366ef7..cef3d73dff 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java @@ -1,5 +1,7 @@ package org.dolphinemu.dolphinemu.ui.settings; +import android.app.Activity; + import org.dolphinemu.dolphinemu.model.settings.SettingSection; import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; @@ -13,4 +15,6 @@ public interface SettingsFragmentView void passOptionsToActivity(HashMap settings); void showSettingsList(ArrayList settingsList); + + Activity getActivity(); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SliderPreference.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SliderPreference.java deleted file mode 100644 index da896cf590..0000000000 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SliderPreference.java +++ /dev/null @@ -1,128 +0,0 @@ -package org.dolphinemu.dolphinemu.utils; - -import android.app.AlertDialog; -import android.content.Context; -import android.os.Bundle; -import android.preference.DialogPreference; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.Button; -import android.widget.LinearLayout; -import android.widget.SeekBar; -import android.widget.TextView; -import android.widget.Toast; - -import org.dolphinemu.dolphinemu.R; - -public class SliderPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener, View.OnClickListener -{ - private static final String androidns = "http://schemas.android.com/apk/res/android"; - - // SeekBar - private int m_max, m_value; - private String m_key; - private SeekBar m_seekbar; - - // TextView - private TextView m_textview; - - public SliderPreference(Context context, AttributeSet attrs) - { - super(context, attrs); - - // Seekbar values - m_value = attrs.getAttributeIntValue(androidns, "defaultValue", 0); - m_max = attrs.getAttributeIntValue(androidns, "max", 100); - m_key = attrs.getAttributeValue(androidns, "key"); - } - - @Override - protected View onCreateDialogView() - { - LayoutInflater inflater = LayoutInflater.from(getContext()); - LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.slider_layout, null, false); - - m_seekbar = (SeekBar) layout.findViewById(R.id.sliderSeekBar); - m_textview = (TextView) layout.findViewById(R.id.sliderTextView); - - if (shouldPersist()) - { - if (m_key != null && m_key.equals("Overclock")) - { - Toast.makeText(getContext(), getContext().getString(R.string.overclock_warning), - Toast.LENGTH_LONG).show(); - - float valueAsFloat = Float.valueOf(getPersistedString(Integer.toString(m_value))); - float valueAsPercent = valueAsFloat * 100; - - m_value = Math.round(valueAsPercent); - } - else - { - m_value = Integer.valueOf(getPersistedString(Integer.toString(m_value))); - } - } - - m_seekbar.setMax(m_max); - m_seekbar.setProgress(m_value); - setProgressText(m_value); - m_seekbar.setOnSeekBarChangeListener(this); - - return layout; - } - - // SeekBar overrides - @Override - public void onProgressChanged(SeekBar seek, int value, boolean fromTouch) - { - m_value = value; - setProgressText(value); - } - - @Override - public void onStartTrackingTouch(SeekBar seek) - { - } - - @Override - public void onStopTrackingTouch(SeekBar seek) - { - } - - void setProgressText(int value) - { - m_textview.setText(String.valueOf(value)); - } - - @Override - public void showDialog(Bundle state) - { - super.showDialog(state); - - Button positiveButton = ((AlertDialog) getDialog()).getButton(AlertDialog.BUTTON_POSITIVE); - positiveButton.setOnClickListener(this); - } - - @Override - public void onClick(View v) - { - if (shouldPersist()) - { - String valueToSave; - if (m_key != null && m_key.equals("Overclock")) - { - float valueAsFloat = m_value / 100.0f; - valueToSave = Float.toString(valueAsFloat); - } - else - { - valueToSave = Integer.toString(m_seekbar.getProgress()); - } - - persistString(valueToSave); - callChangeListener(m_seekbar.getProgress()); - } - ((AlertDialog) getDialog()).dismiss(); - } -} diff --git a/Source/Android/app/src/main/res/layout/dialog_seekbar.xml b/Source/Android/app/src/main/res/layout/dialog_seekbar.xml new file mode 100644 index 0000000000..4d81af8d81 --- /dev/null +++ b/Source/Android/app/src/main/res/layout/dialog_seekbar.xml @@ -0,0 +1,37 @@ + + + + + + + + + + \ No newline at end of file diff --git a/Source/Android/app/src/main/res/layout/slider_layout.xml b/Source/Android/app/src/main/res/layout/slider_layout.xml deleted file mode 100644 index a667ff6489..0000000000 --- a/Source/Android/app/src/main/res/layout/slider_layout.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/Source/Android/app/src/main/res/values/arrays.xml b/Source/Android/app/src/main/res/values/arrays.xml index cf812c87e9..5017b8e3ec 100644 --- a/Source/Android/app/src/main/res/values/arrays.xml +++ b/Source/Android/app/src/main/res/values/arrays.xml @@ -9,11 +9,11 @@ @string/jit64_recompiler @string/jitil_recompiler - + 0 1 2 - + diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml index 7819de79cc..e4fae28f1f 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -334,6 +334,8 @@ Extension Bindings Video Settings Emulation Activity + OK + Cancel Toggle Touch Controls From d90dce6d127239aaa8efad21026223baa017634d Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Thu, 21 Jan 2016 17:36:48 -0500 Subject: [PATCH 4/6] Implement video settings + support for missing files / settings --- .../Android/app/src/main/AndroidManifest.xml | 2 +- .../model/settings/BooleanSetting.java | 2 +- .../model/settings/FloatSetting.java | 2 +- .../dolphinemu/model/settings/IntSetting.java | 2 +- .../dolphinemu/model/settings/Setting.java | 7 +- .../model/settings/StringSetting.java | 2 +- .../model/settings/view/CheckBoxSetting.java | 35 +- .../model/settings/view/HeaderSetting.java | 2 +- .../model/settings/view/SettingsItem.java | 15 +- .../settings/view/SingleChoiceSetting.java | 44 +- .../model/settings/view/SliderSetting.java | 57 +- .../model/settings/view/SubmenuSetting.java | 2 +- .../dolphinemu/ui/main/MainActivity.java | 5 +- .../dolphinemu/ui/main/MainPresenter.java | 9 +- .../dolphinemu/ui/main/MainView.java | 2 +- .../dolphinemu/ui/main/TvMainActivity.java | 12 +- .../settings/SettingsActivityPresenter.java | 27 +- .../ui/settings/SettingsAdapter.java | 36 +- .../ui/settings/SettingsFragment.java | 31 +- .../settings/SettingsFragmentPresenter.java | 226 +- .../ui/settings/SettingsFragmentView.java | 9 +- .../viewholder/CheckboxSettingViewHolder.java | 4 +- .../dolphinemu/utils/SettingsFile.java | 66 +- .../main/res/drawable-hdpi/ic_settings.png | Bin 561 -> 0 bytes .../res/drawable-hdpi/ic_settings_core.png | Bin 0 -> 259 bytes .../drawable-hdpi/ic_settings_graphics.png | Bin 0 -> 304 bytes .../main/res/drawable-xhdpi/ic_settings.png | Bin 737 -> 0 bytes .../res/drawable-xhdpi/ic_settings_core.png | Bin 0 -> 225 bytes .../drawable-xhdpi/ic_settings_graphics.png | Bin 0 -> 360 bytes .../main/res/drawable-xxhdpi/ic_settings.png | Bin 974 -> 0 bytes .../res/drawable-xxhdpi/ic_settings_core.png | Bin 0 -> 333 bytes .../drawable-xxhdpi/ic_settings_graphics.png | Bin 0 -> 570 bytes .../main/res/drawable-xxxhdpi/ic_settings.png | Bin 1273 -> 0 bytes .../res/drawable-xxxhdpi/ic_settings_core.png | Bin 0 -> 432 bytes .../drawable-xxxhdpi/ic_settings_graphics.png | Bin 0 -> 759 bytes .../main/res/drawable/ic_settings_core_tv.png | Bin 0 -> 432 bytes .../res/drawable/ic_settings_graphics_tv.png | Bin 0 -> 759 bytes .../src/main/res/drawable/ic_settings_tv.png | Bin 2248 -> 0 bytes .../app/src/main/res/menu/menu_game_grid.xml | 11 +- .../app/src/main/res/values/arrays.xml | 94 +- .../app/src/main/res/values/strings.xml | 3 +- .../app/src/main/res/xml/preferences.xml | 4834 ----------------- 42 files changed, 514 insertions(+), 5027 deletions(-) delete mode 100644 Source/Android/app/src/main/res/drawable-hdpi/ic_settings.png create mode 100644 Source/Android/app/src/main/res/drawable-hdpi/ic_settings_core.png create mode 100644 Source/Android/app/src/main/res/drawable-hdpi/ic_settings_graphics.png delete mode 100644 Source/Android/app/src/main/res/drawable-xhdpi/ic_settings.png create mode 100644 Source/Android/app/src/main/res/drawable-xhdpi/ic_settings_core.png create mode 100644 Source/Android/app/src/main/res/drawable-xhdpi/ic_settings_graphics.png delete mode 100644 Source/Android/app/src/main/res/drawable-xxhdpi/ic_settings.png create mode 100644 Source/Android/app/src/main/res/drawable-xxhdpi/ic_settings_core.png create mode 100644 Source/Android/app/src/main/res/drawable-xxhdpi/ic_settings_graphics.png delete mode 100644 Source/Android/app/src/main/res/drawable-xxxhdpi/ic_settings.png create mode 100644 Source/Android/app/src/main/res/drawable-xxxhdpi/ic_settings_core.png create mode 100644 Source/Android/app/src/main/res/drawable-xxxhdpi/ic_settings_graphics.png create mode 100644 Source/Android/app/src/main/res/drawable/ic_settings_core_tv.png create mode 100644 Source/Android/app/src/main/res/drawable/ic_settings_graphics_tv.png delete mode 100644 Source/Android/app/src/main/res/drawable/ic_settings_tv.png delete mode 100644 Source/Android/app/src/main/res/xml/preferences.xml diff --git a/Source/Android/app/src/main/AndroidManifest.xml b/Source/Android/app/src/main/AndroidManifest.xml index be41d3f55b..57a0e62abd 100644 --- a/Source/Android/app/src/main/AndroidManifest.xml +++ b/Source/Android/app/src/main/AndroidManifest.xml @@ -58,7 +58,7 @@ + android:label="@string/grid_menu_core_settings"/> >() - { - @Override - public void call(HashMap settingsBySection) - { - mSettingsBySection = settingsBySection; - mView.onSettingsFileLoaded(settingsBySection); - } - }); + { + @Override + public void call(HashMap settingsBySection) + { + mSettingsBySection = settingsBySection; + mView.onSettingsFileLoaded(settingsBySection); + } + }, + new Action1() + { + @Override + public void call(Throwable throwable) + { + Log.error("[SettingsActivityPresenter] Error reading file " + filename + ".ini: "+ throwable.getMessage()); + mView.onSettingsFileLoaded(null); + } + }); mView.showSettingsFragment(mFileName, false); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java index f386fc94df..bbb9a2ad1a 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java @@ -9,10 +9,12 @@ import android.view.View; import android.view.ViewGroup; import android.widget.SeekBar; import android.widget.TextView; -import android.widget.Toast; import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.model.settings.BooleanSetting; import org.dolphinemu.dolphinemu.model.settings.FloatSetting; +import org.dolphinemu.dolphinemu.model.settings.IntSetting; +import org.dolphinemu.dolphinemu.model.settings.view.CheckBoxSetting; import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; import org.dolphinemu.dolphinemu.model.settings.view.SingleChoiceSetting; import org.dolphinemu.dolphinemu.model.settings.view.SliderSetting; @@ -117,6 +119,17 @@ public class SettingsAdapter extends RecyclerView.Adapter notifyDataSetChanged(); } + public void onBooleanClick(CheckBoxSetting item, int position, boolean checked) + { + BooleanSetting setting = item.setChecked(checked); + notifyItemChanged(position); + + if (setting != null) + { + mView.addSetting(setting); + } + } + public void onSingleChoiceClick(SingleChoiceSetting item) { mClickedItem = item; @@ -162,7 +175,7 @@ public class SettingsAdapter extends RecyclerView.Adapter public void onSubmenuClick(SubmenuSetting item) { - Toast.makeText(mContext, "Submenu item clicked", Toast.LENGTH_SHORT).show(); + mView.loadSubMenu(item.getMenuKey()); } @Override @@ -174,7 +187,12 @@ public class SettingsAdapter extends RecyclerView.Adapter int value = getValueForSingleChoiceSelection(scSetting, which); - scSetting.setSelectedValue(value); + IntSetting setting = scSetting.setSelectedValue(value); + if (setting != null) + { + mView.addSetting(setting); + } + closeDialog(); } else if (mClickedItem instanceof SliderSetting) @@ -193,11 +211,19 @@ public class SettingsAdapter extends RecyclerView.Adapter value = (float) mSeekbarProgress; } - sliderSetting.setSelectedValue(value); + FloatSetting setting = sliderSetting.setSelectedValue(value); + if (setting != null) + { + mView.addSetting(setting); + } } else { - sliderSetting.setSelectedValue(mSeekbarProgress); + IntSetting setting = sliderSetting.setSelectedValue(mSeekbarProgress); + if (setting != null) + { + mView.addSetting(setting); + } } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragment.java index a612233789..50ef668b90 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragment.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragment.java @@ -12,6 +12,7 @@ import android.view.ViewGroup; import org.dolphinemu.dolphinemu.BuildConfig; import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.model.settings.Setting; import org.dolphinemu.dolphinemu.model.settings.SettingSection; import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; import org.dolphinemu.dolphinemu.ui.DividerItemDecoration; @@ -22,7 +23,7 @@ import java.util.HashMap; public final class SettingsFragment extends Fragment implements SettingsFragmentView { private SettingsFragmentPresenter mPresenter = new SettingsFragmentPresenter(this); - private SettingsActivityView mView; + private SettingsActivityView mActivity; private SettingsAdapter mAdapter; @@ -31,7 +32,7 @@ public final class SettingsFragment extends Fragment implements SettingsFragment { super.onAttach(context); - mView = (SettingsActivityView) context; + mActivity = (SettingsActivityView) context; mPresenter.onAttach(); } @@ -76,7 +77,7 @@ public final class SettingsFragment extends Fragment implements SettingsFragment public void onDetach() { super.onDetach(); - mView = null; + mActivity = null; if (mAdapter != null) { @@ -91,11 +92,11 @@ public final class SettingsFragment extends Fragment implements SettingsFragment } @Override - public void passOptionsToActivity(HashMap settings) + public void passSettingsToActivity(HashMap settings) { - if (mView != null) + if (mActivity != null) { - mView.setSettings(settings); + mActivity.setSettings(settings); } } @@ -105,6 +106,24 @@ public final class SettingsFragment extends Fragment implements SettingsFragment mAdapter.setSettings(settingsList); } + @Override + public void loadSubMenu(String menuKey) + { + mActivity.showSettingsFragment(menuKey, true); + } + + @Override + public void showToastMessage(String message) + { + mActivity.showToastMessage(message); + } + + @Override + public void addSetting(Setting setting) + { + mPresenter.addSetting(setting); + } + public static final String FRAGMENT_TAG = BuildConfig.APPLICATION_ID + ".fragment.settings"; public static final String ARGUMENT_MENU_TAG = FRAGMENT_TAG + ".menu_tag"; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java index b53d7517f9..22bb24a38f 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java @@ -1,12 +1,17 @@ package org.dolphinemu.dolphinemu.ui.settings; import org.dolphinemu.dolphinemu.R; +import org.dolphinemu.dolphinemu.model.settings.BooleanSetting; +import org.dolphinemu.dolphinemu.model.settings.IntSetting; import org.dolphinemu.dolphinemu.model.settings.Setting; import org.dolphinemu.dolphinemu.model.settings.SettingSection; import org.dolphinemu.dolphinemu.model.settings.view.CheckBoxSetting; +import org.dolphinemu.dolphinemu.model.settings.view.HeaderSetting; import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; import org.dolphinemu.dolphinemu.model.settings.view.SingleChoiceSetting; import org.dolphinemu.dolphinemu.model.settings.view.SliderSetting; +import org.dolphinemu.dolphinemu.model.settings.view.SubmenuSetting; +import org.dolphinemu.dolphinemu.utils.EGLHelper; import org.dolphinemu.dolphinemu.utils.SettingsFile; import java.util.ArrayList; @@ -45,23 +50,22 @@ public class SettingsFragmentPresenter { if (mSettings != null) { - mView.passOptionsToActivity(mSettings); + mView.passSettingsToActivity(mSettings); } } + public void addSetting(Setting setting) + { + mSettings.get(setting.getSection()).putSetting(setting.getKey(), setting); + } + public void setSettings(HashMap settings) { if (mSettingsList == null) { - if (settings != null) - { - mSettings = settings; - } + mSettings = settings; - if (mSettings != null) - { - loadSettingsList(); - } + loadSettingsList(); } else { @@ -77,8 +81,23 @@ public class SettingsFragmentPresenter { case SettingsFile.FILE_NAME_DOLPHIN: addCoreSettings(sl); - break; + + case SettingsFile.FILE_NAME_GFX: + addGraphicsSettings(sl); + break; + + case SettingsFile.SECTION_GFX_ENHANCEMENTS: + addEnhanceSettings(sl); + break; + + case SettingsFile.SECTION_GFX_HACKS: + addHackSettings(sl); + break; + + default: + mView.showToastMessage("Unimplemented menu."); + return; } mSettingsList = sl; @@ -87,16 +106,187 @@ public class SettingsFragmentPresenter private void addCoreSettings(ArrayList sl) { - Setting cpuCore = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_CPU_CORE); - sl.add(new SingleChoiceSetting(cpuCore.getKey(), cpuCore, R.string.cpu_core, 0, R.array.string_emu_cores, R.array.int_emu_cores)); + Setting cpuCore = null; + Setting dualCore = null; + Setting overclockEnable = null; + Setting overclock = null; - Setting dualCore = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_DUAL_CORE); - sl.add(new CheckBoxSetting(dualCore.getKey(), dualCore, R.string.dual_core, R.string.dual_core_descrip)); + if (mSettings != null) + { + cpuCore = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_CPU_CORE); + dualCore = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_DUAL_CORE); + overclockEnable = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_OVERCLOCK_ENABLE); + overclock = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_OVERCLOCK_PERCENT); + } + else + { + mSettings = new HashMap<>(); + mSettings.put(SettingsFile.SECTION_CORE, new SettingSection(SettingsFile.SECTION_CORE)); - Setting overclockEnable = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_OVERCLOCK_ENABLE); - sl.add(new CheckBoxSetting(overclockEnable.getKey(), overclockEnable, R.string.overclock_enable, R.string.overclock_enable_description)); + mView.passSettingsToActivity(mSettings); + } - Setting overclock = mSettings.get(SettingsFile.SECTION_CORE).getSetting(SettingsFile.KEY_OVERCLOCK_PERCENT); - sl.add(new SliderSetting(overclock.getKey(), overclock, R.string.overclock_title, 0, 400, "%")); + // TODO Set default value for cpuCore based on arch. + sl.add(new SingleChoiceSetting(SettingsFile.KEY_CPU_CORE, SettingsFile.SECTION_CORE, R.string.cpu_core, 0, R.array.string_emu_cores, R.array.int_emu_cores, 4, cpuCore)); + sl.add(new CheckBoxSetting(SettingsFile.KEY_DUAL_CORE, SettingsFile.SECTION_CORE, R.string.dual_core, R.string.dual_core_descrip, true, dualCore)); + sl.add(new CheckBoxSetting(SettingsFile.KEY_OVERCLOCK_ENABLE, SettingsFile.SECTION_CORE, R.string.overclock_enable, R.string.overclock_enable_description, false, overclockEnable)); + sl.add(new SliderSetting(SettingsFile.KEY_OVERCLOCK_PERCENT, SettingsFile.SECTION_CORE, R.string.overclock_title, 0, 400, "%", 100, overclock)); + + } + + private void addGraphicsSettings(ArrayList sl) + { + Setting showFps = null; + + if (mSettings != null) + { + showFps = mSettings.get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_SHOW_FPS); + } + else + { + mSettings = new HashMap<>(); + + mSettings.put(SettingsFile.SECTION_GFX_SETTINGS, new SettingSection(SettingsFile.SECTION_GFX_SETTINGS)); + mSettings.put(SettingsFile.SECTION_GFX_ENHANCEMENTS, new SettingSection(SettingsFile.SECTION_GFX_ENHANCEMENTS)); + mSettings.put(SettingsFile.SECTION_GFX_HACKS, new SettingSection(SettingsFile.SECTION_GFX_HACKS)); + + mView.passSettingsToActivity(mSettings); + } + + sl.add(new CheckBoxSetting(SettingsFile.KEY_SHOW_FPS, SettingsFile.SECTION_GFX_SETTINGS, R.string.show_fps, 0, true, showFps)); + + sl.add(new SubmenuSetting(null, null, R.string.enhancements, 0, SettingsFile.SECTION_GFX_ENHANCEMENTS)); + sl.add(new SubmenuSetting(null, null, R.string.hacks, 0, SettingsFile.SECTION_GFX_HACKS)); + } + + private void addEnhanceSettings(ArrayList sl) + { + Setting resolution = mSettings.get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_INTERNAL_RES); + Setting fsaa = mSettings.get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_FSAA); + Setting anisotropic = mSettings.get(SettingsFile.SECTION_GFX_ENHANCEMENTS).getSetting(SettingsFile.KEY_ANISOTROPY); + Setting efbScaledCopy = mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_SCALED_EFB); + Setting perPixel = mSettings.get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_PER_PIXEL); + Setting forceFilter = mSettings.get(SettingsFile.SECTION_GFX_ENHANCEMENTS).getSetting(SettingsFile.KEY_FORCE_FILTERING); + Setting disableFog = mSettings.get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_DISABLE_FOG); + + sl.add(new SingleChoiceSetting(SettingsFile.KEY_INTERNAL_RES, SettingsFile.SECTION_GFX_SETTINGS, R.string.internal_resolution, R.string.internal_resolution_descrip, R.array.internalResolutionEntries, R.array.internalResolutionValues, 0, resolution)); + sl.add(new SingleChoiceSetting(SettingsFile.KEY_FSAA, SettingsFile.SECTION_GFX_SETTINGS, R.string.FSAA, R.string.FSAA_descrip, R.array.FSAAEntries, R.array.FSAAValues, 0, fsaa)); + sl.add(new SingleChoiceSetting(SettingsFile.KEY_ANISOTROPY, SettingsFile.SECTION_GFX_ENHANCEMENTS, R.string.anisotropic_filtering, R.string.anisotropic_filtering_descrip, R.array.anisotropicFilteringEntries, R.array.anisotropicFilteringValues, 0, anisotropic)); + + // TODO +// Setting shader = mSettings.get(SettingsFile.SECTION_GFX_ENHANCEMENTS).getSetting(SettingsFile.KEY_POST_SHADER) +// sl.add(new SingleChoiceSetting(.getKey(), , R.string., R.string._descrip, R.array., R.array.)); + + sl.add(new CheckBoxSetting(SettingsFile.KEY_SCALED_EFB, SettingsFile.SECTION_GFX_HACKS, R.string.scaled_efb_copy, R.string.scaled_efb_copy_descrip, true, efbScaledCopy)); + sl.add(new CheckBoxSetting(SettingsFile.KEY_PER_PIXEL, SettingsFile.SECTION_GFX_SETTINGS, R.string.per_pixel_lighting, R.string.per_pixel_lighting_descrip, false, perPixel)); + sl.add(new CheckBoxSetting(SettingsFile.KEY_FORCE_FILTERING, SettingsFile.SECTION_GFX_ENHANCEMENTS, R.string.force_texture_filtering, R.string.force_texture_filtering_descrip, false, forceFilter)); + sl.add(new CheckBoxSetting(SettingsFile.KEY_DISABLE_FOG, SettingsFile.SECTION_GFX_SETTINGS, R.string.disable_fog, R.string.disable_fog_descrip, false, disableFog)); + + /* + Check if we support stereo + If we support desktop GL then we must support at least OpenGL 3.2 + If we only support OpenGLES then we need both OpenGLES 3.1 and AEP + */ + EGLHelper helper = new EGLHelper(EGLHelper.EGL_OPENGL_ES2_BIT); + + if ((helper.supportsOpenGL() && helper.GetVersion() >= 320) || + (helper.supportsGLES3() && helper.GetVersion() >= 310 && helper.SupportsExtension("GL_ANDROID_extension_pack_es31a"))) + { + sl.add(new SubmenuSetting(null, null, R.string.stereoscopy, 0, SettingsFile.SECTION_STEREOSCOPY)); + } + } + + private void addHackSettings(ArrayList sl) + { + int efbCopyMethodValue = getEfbCopyMethodValue(); + int xfbValue = getXfbValue(); + + Setting skipEFB = mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_SKIP_EFB); + Setting ignoreFormat = mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_IGNORE_FORMAT); + IntSetting efbCopyMethod = new IntSetting(SettingsFile.KEY_EFB_COPY_METHOD, null, efbCopyMethodValue); + Setting texCacheAccuracy = mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_TEXCACHE_ACCURACY); + IntSetting xfb = new IntSetting(SettingsFile.KEY_XFB, SettingsFile.SECTION_GFX_HACKS, xfbValue); + Setting fastDepth = mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_FAST_DEPTH); + Setting aspectRatio = mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_ASPECT_RATIO); + + sl.add(new HeaderSetting(null, null, R.string.embedded_frame_buffer, 0)); + sl.add(new CheckBoxSetting(SettingsFile.KEY_SKIP_EFB, SettingsFile.SECTION_GFX_HACKS, R.string.skip_efb_access, R.string.skip_efb_access_descrip, false, skipEFB)); + sl.add(new CheckBoxSetting(SettingsFile.KEY_IGNORE_FORMAT, SettingsFile.SECTION_GFX_HACKS, R.string.ignore_format_changes, R.string.ignore_format_changes_descrip, false, ignoreFormat)); + sl.add(new SingleChoiceSetting(SettingsFile.KEY_EFB_COPY_METHOD, SettingsFile.SECTION_GFX_HACKS, R.string.efb_copy_method, R.string.efb_copy_method_descrip, R.array.efbCopyMethodEntries, R.array.efbCopyMethodValues, 1, efbCopyMethod)); + + sl.add(new HeaderSetting(null, null, R.string.texture_cache, 0)); + sl.add(new SingleChoiceSetting(SettingsFile.KEY_TEXCACHE_ACCURACY, SettingsFile.SECTION_GFX_HACKS, R.string.texture_cache_accuracy, R.string.texture_cache_accuracy_descrip, R.array.textureCacheAccuracyEntries, R.array.textureCacheAccuracyValues, 128, texCacheAccuracy)); + + sl.add(new HeaderSetting(null, null, R.string.external_frame_buffer, 0)); + sl.add(new SingleChoiceSetting(SettingsFile.KEY_XFB, SettingsFile.SECTION_GFX_HACKS, R.string.external_frame_buffer, R.string.external_frame_buffer_descrip, R.array.externalFrameBufferEntries, R.array.externalFrameBufferValues, 0, xfb)); + + sl.add(new HeaderSetting(null, null, R.string.other, 0)); + sl.add(new CheckBoxSetting(SettingsFile.KEY_FAST_DEPTH, SettingsFile.SECTION_GFX_HACKS, R.string.fast_depth_calculation, R.string.fast_depth_calculation_descrip, true, fastDepth)); + sl.add(new SingleChoiceSetting(SettingsFile.KEY_ASPECT_RATIO, SettingsFile.SECTION_GFX_HACKS, R.string.aspect_ratio, R.string.aspect_ratio_descrip, R.array.aspectRatioEntries, R.array.aspectRatioValues, 0, aspectRatio)); + } + + private int getEfbCopyMethodValue() + { + int efbCopyMethodValue; + try + { + boolean efbCopyOn = ((BooleanSetting) mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_EFB_COPY)).getValue(); + boolean efbCopyTexture = ((BooleanSetting) mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_EFB_TEXTURE)).getValue(); + boolean efbCopyCache = ((BooleanSetting) mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_EFB_CACHE)).getValue(); + + + if (!efbCopyOn) + { + efbCopyMethodValue = 0; + } + else if (efbCopyTexture) + { + efbCopyMethodValue = 1; + } + else if (!efbCopyCache) + { + efbCopyMethodValue = 2; + } + else + { + efbCopyMethodValue = 3; + } + } + catch (NullPointerException ex) + { + efbCopyMethodValue = 1; + } + + return efbCopyMethodValue; + } + + private int getXfbValue() + { + int xfbValue; + + try + { + boolean usingXFB = ((BooleanSetting) mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_XFB)).getValue(); + boolean usingRealXFB = ((BooleanSetting) mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_XFB_REAL)).getValue(); + + if (!usingXFB) + { + xfbValue = 0; + } + else if (!usingRealXFB) + { + xfbValue = 1; + } + else + { + xfbValue = 2; + } + } + catch (NullPointerException ex) + { + xfbValue = 0; + } + + return xfbValue; } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java index cef3d73dff..f5a035eed3 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java @@ -2,6 +2,7 @@ package org.dolphinemu.dolphinemu.ui.settings; import android.app.Activity; +import org.dolphinemu.dolphinemu.model.settings.Setting; import org.dolphinemu.dolphinemu.model.settings.SettingSection; import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; @@ -12,9 +13,15 @@ public interface SettingsFragmentView { void onSettingsFileLoaded(HashMap settings); - void passOptionsToActivity(HashMap settings); + void passSettingsToActivity(HashMap settings); void showSettingsList(ArrayList settingsList); Activity getActivity(); + + void loadSubMenu(String menuKey); + + void showToastMessage(String message); + + void addSetting(Setting setting); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/CheckboxSettingViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/CheckboxSettingViewHolder.java index 0059446bdc..05985cc671 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/CheckboxSettingViewHolder.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/CheckboxSettingViewHolder.java @@ -51,7 +51,7 @@ public class CheckBoxSettingViewHolder extends SettingViewHolder public void onClick(View clicked) { mCheckbox.toggle(); - mItem.setChecked(mCheckbox.isChecked()); - getAdapter().notifyItemChanged(getAdapterPosition()); + + getAdapter().onBooleanClick(mItem, getAdapterPosition(), mCheckbox.isChecked()); } } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java index 15ce0a7e36..5bfa678098 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java @@ -36,39 +36,43 @@ public final class SettingsFile public static final String SECTION_GFX_ENHANCEMENTS = "Enhancements"; public static final String SECTION_GFX_HACKS = "Hacks"; + public static final String SECTION_STEREOSCOPY = "Stereoscopy"; - public static final String KEY_CPU_CORE= "CPUCore"; - public static final String KEY_DUAL_CORE= "CPUThread"; - public static final String KEY_OVERCLOCK_ENABLE= "OverclockEnable"; - public static final String KEY_OVERCLOCK_PERCENT= "Overclock"; - public static final String KEY_VIDEO_BACKEND= "GFXBackend"; + public static final String KEY_CPU_CORE = "CPUCore"; + public static final String KEY_DUAL_CORE = "CPUThread"; + public static final String KEY_OVERCLOCK_ENABLE = "OverclockEnable"; + public static final String KEY_OVERCLOCK_PERCENT = "Overclock"; + public static final String KEY_VIDEO_BACKEND = "GFXBackend"; - public static final String KEY_SHOW_FPS= "ShowFPS"; - public static final String KEY_INTERNAL_RES= "EFBScale"; - public static final String KEY_FSAA= "MSAA"; - public static final String KEY_ANISOTROPY= "MaxAnisotropy"; - public static final String KEY_POST_SHADER= "PostProcessingShader"; - public static final String KEY_SCALED_EFB= "EFBScaledCopy"; - public static final String KEY_PER_PIXEL= "EnablePixelLighting"; - public static final String KEY_FORCE_FILTERING= "ForceFiltering"; - public static final String KEY_DISABLE_FOG= "DisableFog"; + public static final String KEY_SHOW_FPS = "ShowFPS"; + public static final String KEY_INTERNAL_RES = "EFBScale"; + public static final String KEY_FSAA = "MSAA"; + public static final String KEY_ANISOTROPY = "MaxAnisotropy"; + public static final String KEY_POST_SHADER = "PostProcessingShader"; + public static final String KEY_SCALED_EFB = "EFBScaledCopy"; + public static final String KEY_PER_PIXEL = "EnablePixelLighting"; + public static final String KEY_FORCE_FILTERING = "ForceFiltering"; + public static final String KEY_DISABLE_FOG = "DisableFog"; - public static final String KEY_STEREO_MODE= "StereoMode"; - public static final String KEY_STEREO_DEPTH= "StereoDepth"; - public static final String KEY_STEREO_CONV= "StereoConvergencePercentage"; - public static final String KEY_STEREO_SWAP= "StereoSwapEyes"; + public static final String KEY_STEREO_MODE = "StereoMode"; + public static final String KEY_STEREO_DEPTH = "StereoDepth"; + public static final String KEY_STEREO_CONV = "StereoConvergencePercentage"; + public static final String KEY_STEREO_SWAP = "StereoSwapEyes"; - public static final String KEY_SKIP_EFB= "EFBAccessEnable"; - public static final String KEY_IGNORE_FORMAT= "EFBEmulateFormatChanges"; - public static final String KEY_EFB_COPY= "EFBCopyEnable"; - public static final String KEY_EFB_TEXTURE= "EFBToTextureEnable"; - public static final String KEY_EFB_CACHE= "EFBCopyCacheEnable"; - public static final String KEY_TEXCACHE_ACCURACY= "SafeTextureCacheColorSamples"; - public static final String KEY_XFB= "UseXFB"; - public static final String KEY_XFB_REAL= "UseRealXFB"; + public static final String KEY_SKIP_EFB = "EFBAccessEnable"; + public static final String KEY_IGNORE_FORMAT = "EFBEmulateFormatChanges"; + public static final String KEY_EFB_COPY = "EFBCopyEnable"; + public static final String KEY_EFB_TEXTURE = "EFBToTextureEnable"; + public static final String KEY_EFB_CACHE = "EFBCopyCacheEnable"; + public static final String KEY_TEXCACHE_ACCURACY = "SafeTextureCacheColorSamples"; + public static final String KEY_XFB = "UseXFB"; + public static final String KEY_XFB_REAL = "UseRealXFB"; public static final String KEY_FAST_DEPTH= "FastDepthCalc"; public static final String KEY_ASPECT_RATIO= "AspectRatio"; + // Internal only, not actually found in settings file. + public static final String KEY_EFB_COPY_METHOD = "EFBCopyMethod"; + private SettingsFile() { } @@ -206,7 +210,7 @@ public final class SettingsFile { int valueAsInt = Integer.valueOf(value); - return new IntSetting(key, current, valueAsInt); + return new IntSetting(key, current.getName(), valueAsInt); } catch (NumberFormatException ex) { @@ -216,7 +220,7 @@ public final class SettingsFile { float valueAsFloat = Float.valueOf(value); - return new FloatSetting(key, current, valueAsFloat); + return new FloatSetting(key, current.getName(), valueAsFloat); } catch (NumberFormatException ex) { @@ -225,11 +229,11 @@ public final class SettingsFile switch (value) { case "True": - return new BooleanSetting(key, current, true); + return new BooleanSetting(key, current.getName(), true); case "False": - return new BooleanSetting(key, current, false); + return new BooleanSetting(key, current.getName(), false); default: - return new StringSetting(key, current, value); + return new StringSetting(key, current.getName(), value); } } diff --git a/Source/Android/app/src/main/res/drawable-hdpi/ic_settings.png b/Source/Android/app/src/main/res/drawable-hdpi/ic_settings.png deleted file mode 100644 index f9a8915fd2dc378d35756de89784556e6fdc7db9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 561 zcmV-10?z%3P)004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00002VoOIv0RM-N%)bBt010qN zS#tmY3ljhU3ljkVnw%H_00F5aMxdglhe=rd5VQ00000NkvXXu0mjf7RTZX diff --git a/Source/Android/app/src/main/res/drawable-hdpi/ic_settings_core.png b/Source/Android/app/src/main/res/drawable-hdpi/ic_settings_core.png new file mode 100644 index 0000000000000000000000000000000000000000..27985eba15b08194314e7698c1bd4ac1bdec47b8 GIT binary patch literal 259 zcmV+e0sQ`nP)22eM`bRR!lfzA3bfrKBV$Yts9*~VVrKVpmp1-b)V+|RBWR1Ik7{OApcZ6Yfr<1dc(kani5EoG7=O<>XkC2MZhg(3ZUUqreE1~g;9H1 z3(zsz`0>VowvIHyp6Cdhpf+&GckyK4Az$xhpSeow-wy>!`T4M{zZ=9YvU004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00002VoOIv0RM-N%)bBt010qN zS#tmY3ljhU3ljkVnw%H_00LP_L_t(o!{wOIYZFlr$0xNhfhN^PB<61QP-zeTfPz1; z^dQxPr5C}!K?FUt)`L*6MGt!LRCWH-_|9`s9Bn=AF69nLToD#$tcrfQw2R&clt z?Jgx4ZbNGd=9r>Nk%`tk!#!$fQe%ms7H)zf-3#A zMO5-qBbW&=`pPULBuH?KIZ6TOX)nQf>OKZ}23)5jMZpJM=bUy-$F1*`C+11Wn3duS zr)+tUWkubb0Yn*T$_n}!2mKPQp9db3S=GHD%zLo++2fzdg0N{AjaUgr4W#46csp93 zY#W-S)GbMsl%GbQj`#LfL70Bfkj>C_|EMvq1{1{Pkz@?rB`bmXuj#Dh2rdWEd*6rEAeH9$d4v}Fsr#JEN<>Dyikq>Z;<_H98*skj_azRJuqN|GdF z+*UVdr(D#wXf?8O{ala1@rWAEHe z8?~_0z4vCfm-XgC-*S!p%uw;&4u@%mxX!!QbuAuLt}jp_&*|2D9}E0Yoo{i6!4~c; zPjQ$Gx;pBkXlbM&Y{Ql7^)|E}^@E-hthJ&2H&@^&AFVI6{?+Mc?5_S-(Q|^oR4iHa T4YrnW00000NkvXXu0mjftyfGA diff --git a/Source/Android/app/src/main/res/drawable-xhdpi/ic_settings_core.png b/Source/Android/app/src/main/res/drawable-xhdpi/ic_settings_core.png new file mode 100644 index 0000000000000000000000000000000000000000..c6fae135879c2dfde3b5b1124773377b9039ba80 GIT binary patch literal 225 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUt6`n4RAr-gY-aO6cU?9-?(5|F>@0GFsD+JJu(h!A1d8~Bg~<2<5k%q|H=5m* zH}G|nY(Daqgjr8SJeTn(KmiK;w?GSw!Cs25BbX-7pd}DrxD)fWQ%R@<#$r!RbOiPm z2^@3;Y%2;-fC3bt00k&O0SZtce~m!ss=xwNKou-q6WD;p!~NUfWP?B)iQ$``E9j-H z;hPq?N1_boioStjozRrPb0lhDmC`o@CB-^f_rq5OUPYn_whw)4P|q-+%CaB6Dxiu) z7hJ#@bUv7}`9%r5i$qKx1RA5l@Ye!aBcY3GKjaqpG!nYJ+7Gz}0x53l?DJ>t9|VrB z4|k^)2}I)X0mnA^!fPKfO_En=A~uog;f1G^6rcbFjB^83q&%Aoj)~&{0000004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00002VoOIv0RM-N%)bBt010qN zS#tmY3ljhU3ljkVnw%H_00TxzL_t(&-tC%ONK`=>$5(Te(xUPj>1rX0iHP)INJ2!= zTM#5k6k=FdP*Km(1#(xT2(ya>f=~*Y5ZxXNwTLdHDUw7NO4BY@W?GhsznTShOU=po%aP#Ll~WFDwd3RGtvs9g$l z-#pN;6zG#_paiTU+AL7MCD019KwB+=wwMKSS^^!OYM@Y>7@(RQpEnWg;I$=C52Zx- z^j*$5-cwJAK2V8U`T-?Gx}O))gKE5Dqq|=e+j;1IQ=|(tk9Qu@L!2R-1g@hSSBWEs zYQA_p?I%hP=$K#eZv+zld%1Lg(img9<2y^$fv#a9E~x^o#Z;_T0Se=>F`!OnSp)6C zWbCv8iebIoCpK|2kKD!t@dt+IHUmA+1x)JE88RZzL%Ib5Q| z7$&G>f6kpmOK0P-oJ-}tSx8)5H%Lu0)^dy0UZ#?IhBE20)_qm2+-b{He{kn-L4GOIhB(- zlPAJu?@+=?5ia{~GIW6orFqt+1XLl-^#$rcb}B6^v_s+hSUHE|{_3Hx&?0Url*Jb8 zQk-yZE2uORZv~Xk8%5*LAVCV}qM}M4c`~3_Mm4Net6<<#l)lbneD!qI-ovG5VMiz@ z*$bvZbHhDGjBLnG1z_?!sKtegS~>$T`6uLaXdxesZi5Cq9kstzw#z6`smfNm%NWih zLRAvu8e>4KR7=NYBREa!wJen%(~dLB5}o3DRFHQ9iD8|ciwI~gZ#}vXQb{JUT+zm9 zB$_O$`0Q0OB6a=H@3ZXmKwAn1sN=u;J|NH{a=5=@R*RMEjv`K;PnFo>|+FdXY wbVLet&^%B&&lwlAXQT#yMhOB1fo3YuFU0)zMLKxvdjJ3c07*qoM6N<$f_WFC82|tP diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/ic_settings_core.png b/Source/Android/app/src/main/res/drawable-xxhdpi/ic_settings_core.png new file mode 100644 index 0000000000000000000000000000000000000000..4c5f2493a54a7de1d79b668a5d5b3391a16ffb48 GIT binary patch literal 333 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@Zgyv2U=;CmaSW-r_4c+eSF?dYTVnV( zzPFM~<1Wi*eARL)H18FduD4|4eV6-<`RbEwRva|YJhMjOHY1}#0|OHWh(itB#!Kt zsJ;ZW5NPX9##v|UJ#WYV;%SId4VcRqu#_b#D%btEg}$(P;kw)d&B1eium9}5wMxhT z(k0(pNBb9jYQA&q`YIno^FAd8h`R-jA7WI37{^$$sfIDMgvs~OysRU@U}Ere^>bP0 Hl+XkKAS-p1 literal 0 HcmV?d00001 diff --git a/Source/Android/app/src/main/res/drawable-xxhdpi/ic_settings_graphics.png b/Source/Android/app/src/main/res/drawable-xxhdpi/ic_settings_graphics.png new file mode 100644 index 0000000000000000000000000000000000000000..7b7e2f7a1a130ef1371fb294263d488cbce09673 GIT binary patch literal 570 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@Zgyv2U}E%iaSW-r_4c-{_hAPK_77cB zfdz%1Qwz#OWbWQ|E#WEQ6WibLfL*}8!TH&)@5~+Ew>!2e^!Yt{5)#klDmVXusQ2s% zyH79OEAyZI-{aQZ@^77I*{u`^WcB11U|>;TVB~OMU=nC}@~Du>Z}R2EpF-vf7iP^_ zx~Rd-vOnbCtFFxwte<2KN`|@5IVlm~@b2nL&jrhx9dai-*s?e7^I_T<1=5XV5IWOi z@uT`MKFj$GUh9-Mipx7pF16e?U%=si>FG#`+vmBSpHyAoQG8cA-8R+Vn(fy_Q3u|0 zHp|!T$UAWJ{Eg}HWedd5&DwEn(q1 zuisj{|76#es%L8^-O5;yXFp5wLg}%uenHo2I}X3%iTRbv*!8>T%z`Jbhi)aGGM_4S zi|@<1o746@lX;$&@>cYz{O!=U?!m0T9?E3MyqH&fJW|DY^I5IG8LJ$g&tkvzC}+Y= z#)A813)+61x?!R!e~Zba$~Yr9004R> z004l5008;`004mK004C`008P>0026e000+ooVrmw00002VoOIv0RM-N%)bBt010qN zS#tmY3ljhU3ljkVnw%H_00ePKL_t(|+U=WNY*a-QfV*4TDlG(JXqQ@kO2Zo@2nYd6 zi4|ffAvBn%sYmMXSn{@=n&0Rl9}+vQra+)HeOE9l}RN{3_gD22G809d@{`JO}0@K|FwwY*vL@| zpU}0Ho5Oyuu>~mPzK7WXPEtXXD*nJ$?(rH?Dmcl2r^79>132ho`Zt0SKTY*E0P`7Q z1#}8 zB;n&U8)$Epr)1dQDR=6W>`BK02AJnEPE8+AqieY$`V}$Udeg zah&@t3tK>P5wc@wwyyXnQ>!z&+=badSi+Miqq65ty zgZ^hes?h6zkLuuB5pJ2MN-BVfp534iIl?j`tQI!h`^gN{=cjw~_j4|`-~S~Z{#`fk z56JVli|Kv^r9Ry+0oA$*@U9r(Z8rhR!~hG@{VL)FS1*I!5!N`Jz0F!FXvx3Litt8v j2oM5<03kpK5Y+PsBjmQgU@Z4^aSW-r_4bZq-XQ}4)_}4t z?T(`9xvNtSMrvJgZg`-QDtvv~rBd+|rpC3(e^V9CbZ^k@F<&~Rx2Ic;fkAR@8pwV#f?)<*Abvv)!IrTVv_i^vDA)kdLAMAV z-t(-!IlW*l(D<3v#k4`+GW(^W+82fy-uJ5d847%P3i=odym>x|GAdkg%J}k^8E!Iz z0Lz1Wum1j8d|w_R*3iSyzi(sKm#+vRh7^_!0-J?E9)^Gi-x;Jgzv)3T>45xJcIFr% z<~d3XKAntl$_!hSW2d#8&7Yqs&ZzKuqG`Tu)m82VvhPcMuKekrm8;Sq-(vaW`o&Fl zKX1p?{_3tQl@`9`8T`CdN<48@Wfc3J*!TY|c3eHV6J{fjhKCV^sgS>q(LOZta`v&U QCqb$_UHx3vIVCg!02_LcyZ`_I literal 0 HcmV?d00001 diff --git a/Source/Android/app/src/main/res/drawable-xxxhdpi/ic_settings_graphics.png b/Source/Android/app/src/main/res/drawable-xxxhdpi/ic_settings_graphics.png new file mode 100644 index 0000000000000000000000000000000000000000..d7b1ac95ce6fce4239ff35ffbec5f4e1f2837a20 GIT binary patch literal 759 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>VA|*D;uunK>+Rixe!`A2$3G@{ zIOP3cskk)5gyo|s&#PdQl@C)YS|1rRMDm%w3|`UMXfp4sMoX23K0}qF*95-*o!pAK z<+tbFoICer-T#yCt#1FV&-ib>t6sO-Ja-gekXJ1h?)#i~YU?@Ge%)E~zuSC} zOSrXKWNyZxs9*nh@{2O+=6ybp-C#fIxn$qc^*ww+*Q)0yfBrm+J&xIgw{Q7;UHju} zzE&PeTfL_8fv&^tMVkJq``@oEo%JyF%vYNaLJ!I|r(T}Idvbrp=C6wmJiC34`8`9M zd9>NhNjX*-`_9^Y;8MukEb8U+tTCKnZNuz*EB-xfN#F1@@)={k=d>7b*l*@J&>KDZ^vT|6{};tcvO5_%fYjR^3>UU%$X|Fp z@sjPz-3$-JzCF&qzGV6`hF{7Gu~l{9?WaEQs?W~-ne@j;BIHkMdU)iX+tZK#cmLvZ zL4J*GpZ?)h1uH8>`0wn>{r|(zw9b>C0hpXv7#KL9i7G_h{CV@IV;8O;1iQi0)z4*} HQ$iB}GI>8r literal 0 HcmV?d00001 diff --git a/Source/Android/app/src/main/res/drawable/ic_settings_core_tv.png b/Source/Android/app/src/main/res/drawable/ic_settings_core_tv.png new file mode 100644 index 0000000000000000000000000000000000000000..9c8fde1b4343098d22b297dee26d8fe7da149b40 GIT binary patch literal 432 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>U@Z4^aSW-r_4bZq-XQ}4)_}4t z?T(`9xvNtSMrvJgZg`-QDtvv~rBd+|rpC3(e^V9CbZ^k@F<&~Rx2Ic;fkAR@8pwV#f?)<*Abvv)!IrTVv_i^vDA)kdLAMAV z-t(-!IlW*l(D<3v#k4`+GW(^W+82fy-uJ5d847%P3i=odym>x|GAdkg%J}k^8E!Iz z0Lz1Wum1j8d|w_R*3iSyzi(sKm#+vRh7^_!0-J?E9)^Gi-x;Jgzv)3T>45xJcIFr% z<~d3XKAntl$_!hSW2d#8&7Yqs&ZzKuqG`Tu)m82VvhPcMuKekrm8;Sq-(vaW`o&Fl zKX1p?{_3tQl@`9`8T`CdN<48@Wfc3J*!TY|c3eHV6J{fjhKCV^sgS>q(LOZta`v&U QCqb$_UHx3vIVCg!02_LcyZ`_I literal 0 HcmV?d00001 diff --git a/Source/Android/app/src/main/res/drawable/ic_settings_graphics_tv.png b/Source/Android/app/src/main/res/drawable/ic_settings_graphics_tv.png new file mode 100644 index 0000000000000000000000000000000000000000..d7b1ac95ce6fce4239ff35ffbec5f4e1f2837a20 GIT binary patch literal 759 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>VA|*D;uunK>+Rixe!`A2$3G@{ zIOP3cskk)5gyo|s&#PdQl@C)YS|1rRMDm%w3|`UMXfp4sMoX23K0}qF*95-*o!pAK z<+tbFoICer-T#yCt#1FV&-ib>t6sO-Ja-gekXJ1h?)#i~YU?@Ge%)E~zuSC} zOSrXKWNyZxs9*nh@{2O+=6ybp-C#fIxn$qc^*ww+*Q)0yfBrm+J&xIgw{Q7;UHju} zzE&PeTfL_8fv&^tMVkJq``@oEo%JyF%vYNaLJ!I|r(T}Idvbrp=C6wmJiC34`8`9M zd9>NhNjX*-`_9^Y;8MukEb8U+tTCKnZNuz*EB-xfN#F1@@)={k=d>7b*l*@J&>KDZ^vT|6{};tcvO5_%fYjR^3>UU%$X|Fp z@sjPz-3$-JzCF&qzGV6`hF{7Gu~l{9?WaEQs?W~-ne@j;BIHkMdU)iX+tZK#cmLvZ zL4J*GpZ?)h1uH8>`0wn>{r|(zw9b>C0hpXv7#KL9i7G_h{CV@IV;8O;1iQi0)z4*} HQ$iB}GI>8r literal 0 HcmV?d00001 diff --git a/Source/Android/app/src/main/res/drawable/ic_settings_tv.png b/Source/Android/app/src/main/res/drawable/ic_settings_tv.png deleted file mode 100644 index 9e242e7748071f029d35d43492b9619b7c2104fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2248 zcmV;(2sihMP)G0000P&NklrVMn5aWc@&Elg(y z3`{nIA$HIXAwDd_4PnHE&7mF62P7zh>=$K|=Yfehm9a`KR0b!iN~&|MKWjFAAky9*ockpQ|Y#fFC^fbPn$;ROkxyKUI;mITnoz2IVMG`<~Ph-n-59^p%Az5o9qA7a}xuJuE29#ihy*=5%mRj>`rH%_ z;98~D%h6y;IYiIe7#)oOe+*R6UtZ_Ss9tvyYiS~t?NJCY1szq)XHX9> zJU^uopBgCX;l(JMVk*&bm+t_Xe1xt>)-b-?HJ^8gf_ErDeYP8Ukp^^C)6Z{!c?4C# zTn3_;!T*SgdS;;*z#Pg6YN5{nL-~|+)U%7I*-ahks3X^3fHFY5;48ow+5yqQ4SoXr z1pp9xd<2+==<);C0j{71(d7hLZUa1w=x(vg0D06Sx@+VrcLCNQF16lOfUnVsxKxsf zZUVfE=-J<01el5F-H&Vsi19JK6Q{_w8(;~ki6?Ca7(o-Mi3ElA0&Jvj;tg8?CXqzw zm~10J2Ky0us>n1SU=BjxPfQ2M;S56GrwlP0UWqe2{ zQSpq)0N2ohe{F1L27^&4HiVgMp$-4qxYk^N)%aG+k^pxf4C4vT;oDks0S@3(6N|}4 z1zZllq#2(Mn+xzh{=7+ki1U_P@n^re0FU5Df?`z2mC%A8zc3ddi}!Hv6ys0^Hi1uY zubctq0w`jvCUX3oka>&_OsXZ@dVn0x zV^Rl?`aGmJm9v<$1m$4MFy|~&e4i7}=L5`WBiBiQVYFjLIU}NQQa+2-n6Me;XxlO2 zdHP4^aW!*D5Y`N50cH_aocp8pz@`<1)4^b80fy2^ILlE{3$TuGDo_r0fN)-lUVz<% zQ+8Q>MauT*1*jsN;>+sMm>)(jz)1`DQ`*~9!ufaf0yGd#k<$R92tCjpjY&RM4V4DdLem~@UDl;sVg4wE|gnV$fI z*=+w@m4z+EyiE*p9bhaq*w9P?%Hpmefel9)<1)Z3ny_W7)c`xOz*j0kE zw1==M$y4?ZXbk6FY-?cx%EE4@72EcZXEVU9oW_MuD75hE|6g4A4-;(#D5VWoYRE$w z+;EQLN-M?Y0}NmTZq*q4Ur@wx++VdH)5pdJ63$u}23@oS=@lLM?`K2sS*9x-C%F^Z|o=UEPNk*HXP zG8rJ7(+GVh%|Ec|#|VA1ZCr{dN9fs$vJqe+Nkrc+GQmy&#Rf#*UPjppa5asjCK?!S zFM#54QWKBa{u-+jh~6Eizuf?e>4@Il<>B1CtkuD{g38qwt+WV#KY_zt4W9jNqX;-HV%jPem+G;M%rVU(W$ zil+hb8n&&a;gqQIcdUb)@4AIsO7DiV12T_Y*^LH?>4XEz?j8U=HO3^#ICe zfJ_detDfh%q1&emyNH6FT!s2<<9Lw+xT3HpNuZ zwh-$j*B`Z1s6a!hx0gmx1x1mDq7UI~_#Lc1Ka=gl6%K152C_4fC?+CV3 zq5LoU0k&YvCJCUkmDsXE0_bcWw#=0PI=d5FCQAUF6=2KN5{9-f(;K!0Ns5X8>UDA-4$WO2nnFOOjDo5JxCIKXXOae#%nFNpkvi}1j W#h1@&<)CH&0000 + \ No newline at end of file diff --git a/Source/Android/app/src/main/res/values/arrays.xml b/Source/Android/app/src/main/res/values/arrays.xml index 5017b8e3ec..d8320239bd 100644 --- a/Source/Android/app/src/main/res/values/arrays.xml +++ b/Source/Android/app/src/main/res/values/arrays.xml @@ -20,66 +20,38 @@ @string/interpreter @string/jit_arm_recompiler - + 0 3 - + @string/interpreter @string/jit_arm64_recompiler - + 0 4 - + @string/interpreter - + 0 - + @string/interpreter @string/cached_interpreter - + 0 5 - - - - - @string/software_renderer - @string/opengl_es3 - - - Software Renderer - OGL - - - - - @string/software_renderer - @string/opengl - - - Software Renderer - OGL - - - - - @string/software_renderer - - - Software Renderer - + @@ -119,37 +91,11 @@ @string/texture_cache_accuracy_medium @string/texture_cache_accuracy_high - + 128 512 0 - - - - - 100 - 90 - 80 - 70 - 60 - 50 - 40 - 30 - 20 - 10 - - - 100,000000 - 90,000000 - 80,000000 - 70,000000 - 60,000000 - 50,000000 - 40,000000 - 30,000000 - 20,000000 - 10,000000 - + @@ -174,7 +120,7 @@ 5x Native (3200x2640) 6x Native (3840x3168) for 4K - + 2 3 4 @@ -183,7 +129,7 @@ 7 8 9 - + @@ -191,11 +137,11 @@ 2x 4x - + 0 1 2 - + @@ -205,13 +151,13 @@ 8x 16x - + 0 1 2 3 4 - + @@ -220,12 +166,12 @@ Top-and-Bottom Anaglyph - + 0 1 2 3 - + @@ -234,12 +180,12 @@ Force 4:3 Stretch To Window - + 0 1 2 3 - + Europe diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml index e4fae28f1f..ba3982396f 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -320,7 +320,8 @@ - Settings + Settings + Video Settings Refresh Library diff --git a/Source/Android/app/src/main/res/xml/preferences.xml b/Source/Android/app/src/main/res/xml/preferences.xml deleted file mode 100644 index 3a5bc32422..0000000000 --- a/Source/Android/app/src/main/res/xml/preferences.xml +++ /dev/null @@ -1,4834 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From cee84d8e90e8a4b047d72cac0dcddf22cbad3707 Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Thu, 21 Jan 2016 22:39:36 -0500 Subject: [PATCH 5/6] Cleanup and documentation --- .../dolphinemu/model/settings/Setting.java | 23 ++++++++ .../model/settings/SettingSection.java | 23 +++++++- .../model/settings/view/CheckBoxSetting.java | 2 +- .../model/settings/view/HeaderSetting.java | 2 +- .../model/settings/view/SettingsItem.java | 53 +++++++++++++++++-- .../settings/view/SingleChoiceSetting.java | 2 +- .../model/settings/view/SliderSetting.java | 2 +- .../model/settings/view/SubmenuSetting.java | 2 +- .../dolphinemu/ui/DividerItemDecoration.java | 2 +- .../settings/SettingsActivityPresenter.java | 2 +- .../ui/settings/SettingsActivityView.java | 33 ++++++++++++ .../ui/settings/SettingsAdapter.java | 2 +- .../settings/SettingsFragmentPresenter.java | 2 +- .../ui/settings/SettingsFragmentView.java | 42 +++++++++++++++ ...er.java => CheckBoxSettingViewHolder.java} | 2 +- .../settings/viewholder/HeaderViewHolder.java | 2 +- .../viewholder/SettingViewHolder.java | 17 ++++++ .../viewholder/SingleChoiceViewHolder.java | 2 +- .../settings/viewholder/SliderViewHolder.java | 2 +- .../viewholder/SubmenuViewHolder.java | 2 +- .../dolphinemu/utils/SettingsFile.java | 34 ++++++++++++ 21 files changed, 234 insertions(+), 19 deletions(-) rename Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/{CheckboxSettingViewHolder.java => CheckBoxSettingViewHolder.java} (95%) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/Setting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/Setting.java index 2af471e694..8ede2bbe07 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/Setting.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/Setting.java @@ -1,25 +1,48 @@ package org.dolphinemu.dolphinemu.model.settings; +/** + * Abstraction for a setting item as read from / written to Dolphin's configuration ini files. + * These files generally consist of a key/value pair, though the type of value is ambiguous and + * must be inferred at read-time. The type of value determines which child of this class is used + * to represent the Setting. + */ public abstract class Setting { private String mKey; private String mSection; + /** + * Base constructor. + * + * @param key Everything to the left of the = in a line from the ini file. + * @param section The corresponding recent section header; e.g. [Core] or [Enhancements] without the brackets. + */ public Setting(String key, String section) { mKey = key; mSection = section; } + /** + * + * @return The identifier used to write this setting to the ini file. + */ public String getKey() { return mKey; } + /** + * + * @return The name of the header under which this Setting should be written in the ini file. + */ public String getSection() { return mSection; } + /** + * @return A representation of this Setting's backing value converted to a String (e.g. for serialization). + */ public abstract String getValueAsString(); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/SettingSection.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/SettingSection.java index 7ab9626e65..9f082f6e9d 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/SettingSection.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/SettingSection.java @@ -2,12 +2,21 @@ package org.dolphinemu.dolphinemu.model.settings; import java.util.HashMap; -public class SettingSection +/** + * A semantically-related group of Settings objects. These Settings are + * internally stored as a Hashmap. + */ +public final class SettingSection { private String mName; private HashMap mSettings = new HashMap<>(); + /** + * Create a new SettingSection with no Settings in it. + * + * @param name The header of this section; e.g. [Core] or [Enhancements] without the brackets. + */ public SettingSection(String name) { mName = name; @@ -18,11 +27,23 @@ public class SettingSection return mName; } + /** + * Convenience method; inserts a value directly into the backing Hashmap. + * + * @param key The key where the Setting will be inserted. + * @param setting The Setting to be inserted. + */ public void putSetting(String key, Setting setting) { mSettings.put(key, setting); } + /** + * Convenience method; gets a value directly from the backing Hashmap. + * + * @param key Used to retrieve the Setting. + * @return A Setting object (you should probably cast this before using) + */ public Setting getSetting(String key) { return mSettings.get(key); diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/CheckBoxSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/CheckBoxSetting.java index 510dfdf1af..adc19f8c30 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/CheckBoxSetting.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/CheckBoxSetting.java @@ -4,7 +4,7 @@ package org.dolphinemu.dolphinemu.model.settings.view; import org.dolphinemu.dolphinemu.model.settings.BooleanSetting; import org.dolphinemu.dolphinemu.model.settings.Setting; -public class CheckBoxSetting extends SettingsItem +public final class CheckBoxSetting extends SettingsItem { private boolean mDefaultValue; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/HeaderSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/HeaderSetting.java index 9ddfae3983..2d5744c555 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/HeaderSetting.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/HeaderSetting.java @@ -3,7 +3,7 @@ package org.dolphinemu.dolphinemu.model.settings.view; import org.dolphinemu.dolphinemu.model.settings.Setting; -public class HeaderSetting extends SettingsItem +public final class HeaderSetting extends SettingsItem { public HeaderSetting(String key, Setting setting, int titleId, int descriptionId) { diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SettingsItem.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SettingsItem.java index 1de3663555..4ec62717b7 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SettingsItem.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SettingsItem.java @@ -2,6 +2,13 @@ package org.dolphinemu.dolphinemu.model.settings.view; import org.dolphinemu.dolphinemu.model.settings.Setting; +/** + * ViewModel abstraction for an Item in the RecyclerView powering SettingsFragments. + * Each one corresponds to a {@link Setting} object, so this class's subclasses + * should vaguely correspond to those subclasses. There are a few with multiple analogues + * and a few with none (Headers, for example, do not correspond to anything in the ini + * file.) + */ public abstract class SettingsItem { public static final int TYPE_HEADER = 0; @@ -15,41 +22,73 @@ public abstract class SettingsItem private Setting mSetting; - private int mTitleId; + private int mNameId; private int mDescriptionId; - public SettingsItem(String key, String section, Setting setting, int titleId, int descriptionId) + /** + * Base constructor. Takes a key / section name in case the third parameter, the Setting, + * is null; in which case, one can be constructed and saved using the key / section. + * + * @param key Identifier for the Setting represented by this Item. + * @param section Section to which the Setting belongs. + * @param setting A possibly-null backing Setting, to be modified on UI events. + * @param nameId Resource ID for a text string to be displayed as this setting's name. + * @param descriptionId Resource ID for a text string to be displayed as this setting's description. + */ + public SettingsItem(String key, String section, Setting setting, int nameId, int descriptionId) { mKey = key; mSection = section; mSetting = setting; - mTitleId = titleId; + mNameId = nameId; mDescriptionId = descriptionId; } + /** + * + * @return The identifier for the backing Setting. + */ public String getKey() { return mKey; } + /** + * + * @return The header under which the backing Setting belongs. + */ public String getSection() { return mSection; } + /** + * + * @return The backing Setting, possibly null. + */ public Setting getSetting() { return mSetting; } + /** + * Replace the backing setting with a new one. Generally used in cases where + * the backing setting is null. + * + * @param setting A non-null Setting. + */ public void setSetting(Setting setting) { mSetting = setting; } + /** + * + * @return A resource ID for a text string representing this Setting's name. + */ public int getNameId() { - return mTitleId; + return mNameId; } public int getDescriptionId() @@ -57,5 +96,11 @@ public abstract class SettingsItem return mDescriptionId; } + /** + * Used by {@link org.dolphinemu.dolphinemu.ui.settings.SettingsAdapter}'s onCreateViewHolder() + * method to determine which type of ViewHolder should be created. + * + * @return An integer (ideally, one of the constants defined in this file) + */ public abstract int getType(); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SingleChoiceSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SingleChoiceSetting.java index 12b7ae4882..07880587c2 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SingleChoiceSetting.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SingleChoiceSetting.java @@ -4,7 +4,7 @@ package org.dolphinemu.dolphinemu.model.settings.view; import org.dolphinemu.dolphinemu.model.settings.IntSetting; import org.dolphinemu.dolphinemu.model.settings.Setting; -public class SingleChoiceSetting extends SettingsItem +public final class SingleChoiceSetting extends SettingsItem { private int mDefaultValue; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SliderSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SliderSetting.java index 062f5f3cdc..0dbb39b521 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SliderSetting.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SliderSetting.java @@ -6,7 +6,7 @@ import org.dolphinemu.dolphinemu.model.settings.Setting; import org.dolphinemu.dolphinemu.utils.Log; import org.dolphinemu.dolphinemu.utils.SettingsFile; -public class SliderSetting extends SettingsItem +public final class SliderSetting extends SettingsItem { private int mMax; private int mDefaultValue; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SubmenuSetting.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SubmenuSetting.java index 1e15555cda..32db709b37 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SubmenuSetting.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/settings/view/SubmenuSetting.java @@ -2,7 +2,7 @@ package org.dolphinemu.dolphinemu.model.settings.view; import org.dolphinemu.dolphinemu.model.settings.Setting; -public class SubmenuSetting extends SettingsItem +public final class SubmenuSetting extends SettingsItem { private String mMenuKey; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/DividerItemDecoration.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/DividerItemDecoration.java index 96b569e060..fcd0befdc2 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/DividerItemDecoration.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/DividerItemDecoration.java @@ -14,7 +14,7 @@ import android.view.View; * Implementation from: * https://gist.github.com/lapastillaroja/858caf1a82791b6c1a36 */ -public class DividerItemDecoration extends RecyclerView.ItemDecoration +public final class DividerItemDecoration extends RecyclerView.ItemDecoration { private Drawable mDivider; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivityPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivityPresenter.java index 07f58024b8..aac7e8e2ed 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivityPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivityPresenter.java @@ -13,7 +13,7 @@ import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action1; import rx.schedulers.Schedulers; -public class SettingsActivityPresenter +public final class SettingsActivityPresenter { private SettingsActivityView mView; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivityView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivityView.java index 4299335684..2409ed1221 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivityView.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsActivityView.java @@ -4,15 +4,48 @@ import org.dolphinemu.dolphinemu.model.settings.SettingSection; import java.util.HashMap; +/** + * Abstraction for the Activity that manages SettingsFragments. + */ public interface SettingsActivityView { + /** + * Show a new SettingsFragment. + * + * @param menuTag Identifier for the settings group that should be displayed. + * @param addToStack Whether or not this fragment should replace a previous one. + */ void showSettingsFragment(String menuTag, boolean addToStack); + /** + * Called by a contained Fragment to get access to the Setting Hashmap + * loaded from disk, so that each Fragment doesn't need to perform its own + * read operation. + * + * @return A possibly null Hashmap of Settings. + */ HashMap getSettings(); + /** + * Used to provide the Activity with a Settings Hashmap if a Fragment already + * has one; for example, if a rotation occurs, the Fragment will not be killed, + * but the Activity will, so the Activity needs to have its Hashmap resupplied. + * + * @param settings The Fragment's Settings hashmap. + */ void setSettings(HashMap settings); + /** + * Called when an asynchronous load operation completes. + * + * @param settings The (possibly null) result of the load operation. + */ void onSettingsFileLoaded(HashMap settings); + /** + * Display a popup text message on screen. + * + * @param message The contents of the onscreen message. + */ void showToastMessage(String message); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java index bbb9a2ad1a..ca754bb882 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java @@ -30,7 +30,7 @@ import org.dolphinemu.dolphinemu.utils.SettingsFile; import java.util.ArrayList; -public class SettingsAdapter extends RecyclerView.Adapter +public final class SettingsAdapter extends RecyclerView.Adapter implements DialogInterface.OnClickListener, SeekBar.OnSeekBarChangeListener { private SettingsFragmentView mView; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java index 22bb24a38f..6cb03472c0 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentPresenter.java @@ -17,7 +17,7 @@ import org.dolphinemu.dolphinemu.utils.SettingsFile; import java.util.ArrayList; import java.util.HashMap; -public class SettingsFragmentPresenter +public final class SettingsFragmentPresenter { private SettingsFragmentView mView; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java index f5a035eed3..0c0546d490 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java @@ -9,19 +9,61 @@ import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; import java.util.ArrayList; import java.util.HashMap; +/** + * Abstraction for a screen showing a list of settings. Instances of + * this type of view will each display a layer of the setting hierarchy. + */ public interface SettingsFragmentView { + /** + * Called by the containing Activity to notify the Fragment that an + * asynchronous load operation completed. + * + * @param settings The potentially-null result of the load operation. + */ void onSettingsFileLoaded(HashMap settings); + /** + * Pass a settings Hashmap to the containing activity, so that it can + * share the Hashmap with other SettingsFragments; useful so that rotations + * do not require an additional load operation. + * + * @param settings A Hashmap containing all the settings + */ void passSettingsToActivity(HashMap settings); + /** + * Pass an ArrayList to the View so that it can be displayed on screen. + * + * @param settingsList The result of converting the Hashmap to an ArrayList + */ void showSettingsList(ArrayList settingsList); + /** + * @return The Fragment's containing activity. + */ Activity getActivity(); + /** + * Tell the Fragment to tell the containing Activity to show a new + * Fragment containing a submenu of settings. + * + * @param menuKey Identifier for the settings group that should be shown. + */ void loadSubMenu(String menuKey); + /** + * Tell the Fragment to tell the containing activity to display a toast message. + * + * @param message Text to be shown in the Toast + */ void showToastMessage(String message); + /** + * Have the fragment add a setting to the Hashmap. Useful if the setting + * was missing from the .ini file, but included in the UI. + * + * @param setting The (possibly missing) new setting. + */ void addSetting(Setting setting); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/CheckboxSettingViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/CheckBoxSettingViewHolder.java similarity index 95% rename from Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/CheckboxSettingViewHolder.java rename to Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/CheckBoxSettingViewHolder.java index 05985cc671..c65fde1d66 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/CheckboxSettingViewHolder.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/CheckBoxSettingViewHolder.java @@ -10,7 +10,7 @@ import org.dolphinemu.dolphinemu.model.settings.view.CheckBoxSetting; import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; import org.dolphinemu.dolphinemu.ui.settings.SettingsAdapter; -public class CheckBoxSettingViewHolder extends SettingViewHolder +public final class CheckBoxSettingViewHolder extends SettingViewHolder { private CheckBoxSetting mItem; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/HeaderViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/HeaderViewHolder.java index 9f0ba58196..6e3b53d4b3 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/HeaderViewHolder.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/HeaderViewHolder.java @@ -7,7 +7,7 @@ import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; import org.dolphinemu.dolphinemu.ui.settings.SettingsAdapter; -public class HeaderViewHolder extends SettingViewHolder +public final class HeaderViewHolder extends SettingViewHolder { private TextView mHeaderName; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SettingViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SettingViewHolder.java index ffa7d59d81..f57e9fc82c 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SettingViewHolder.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SettingViewHolder.java @@ -26,9 +26,26 @@ public abstract class SettingViewHolder extends RecyclerView.ViewHolder implemen return mAdapter; } + /** + * Gets handles to all this ViewHolder's child views using their XML-defined identifiers. + * + * @param root The newly inflated top-level view. + */ protected abstract void findViews(View root); + /** + * Called by the adapter to set this ViewHolder's child views to display the list item + * it must now represent. + * + * @param item The list item that should be represented by this ViewHolder. + */ public abstract void bind(SettingsItem item); + /** + * Called when this ViewHolder's view is clicked on. Implementations should usually pass + * this event up to the adapter. + * + * @param clicked The view that was clicked on. + */ public abstract void onClick(View clicked); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SingleChoiceViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SingleChoiceViewHolder.java index a9230d2ee4..add1b76637 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SingleChoiceViewHolder.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SingleChoiceViewHolder.java @@ -8,7 +8,7 @@ import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; import org.dolphinemu.dolphinemu.model.settings.view.SingleChoiceSetting; import org.dolphinemu.dolphinemu.ui.settings.SettingsAdapter; -public class SingleChoiceViewHolder extends SettingViewHolder +public final class SingleChoiceViewHolder extends SettingViewHolder { private SingleChoiceSetting mItem; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SliderViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SliderViewHolder.java index c15ddfaff6..9615c720fb 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SliderViewHolder.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SliderViewHolder.java @@ -9,7 +9,7 @@ import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; import org.dolphinemu.dolphinemu.model.settings.view.SliderSetting; import org.dolphinemu.dolphinemu.ui.settings.SettingsAdapter; -public class SliderViewHolder extends SettingViewHolder +public final class SliderViewHolder extends SettingViewHolder { private SliderSetting mItem; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SubmenuViewHolder.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SubmenuViewHolder.java index b90f1459a2..4a8243cec7 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SubmenuViewHolder.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/viewholder/SubmenuViewHolder.java @@ -8,7 +8,7 @@ import org.dolphinemu.dolphinemu.model.settings.view.SettingsItem; import org.dolphinemu.dolphinemu.model.settings.view.SubmenuSetting; import org.dolphinemu.dolphinemu.ui.settings.SettingsAdapter; -public class SubmenuViewHolder extends SettingViewHolder +public final class SubmenuViewHolder extends SettingViewHolder { private SubmenuSetting mItem; diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java index 5bfa678098..7f9eb74742 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java @@ -23,6 +23,9 @@ import java.util.Set; import rx.Observable; import rx.Subscriber; +/** + * Contains static methods for interacting with .ini files in which settings are stored. + */ public final class SettingsFile { public static final String FILE_NAME_DOLPHIN = "Dolphin"; @@ -77,6 +80,14 @@ public final class SettingsFile { } + /** + * Reads a given .ini file from disk and returns it as an Rx Observable. If successful, + * this Observable emits a Hashmap of SettingSections, themselves effectively a Hashmap of + * key/value settings. If unsuccessful, the observer notifies the subscriber of why it failed. + * + * @param fileName The name of the settings file without a path or extension. + * @return An Observable that emits a Hashmap of the file's contents, then completes. + */ public static Observable> readFile(final String fileName) { return Observable.create(new Observable.OnSubscribe>() @@ -141,6 +152,15 @@ public final class SettingsFile }); } + /** + * Saves a Settings Hashmap to a given .ini file on disk, returning the operation + * as an Rx Observable. If successful, this Observable emits an event to notify subscribers; + * if unsuccessful, the observer notifies the subscriber of why it failed. + * + * @param fileName The target filename without a path or extension. + * @param sections The hashmap containing the Settings we want to serialize. + * @return An Observable representing the operation. + */ public static Observable saveFile(final String fileName, final HashMap sections) { return Observable.create(new Observable.OnSubscribe() @@ -199,6 +219,14 @@ public final class SettingsFile return new SettingSection(sectionName); } + /** + * For a line of text, determines what type of data is being represented, and returns + * a Setting object containing this data. + * + * @param current The section currently being parsed by the consuming method. + * @param line The line of text being parsed. + * @return A typed Setting containing the key/value contained in the line. + */ private static Setting settingFromLine(SettingSection current, String line) { String[] splitLine = line.split("="); @@ -237,6 +265,12 @@ public final class SettingsFile } } + /** + * Writes the contents of a Section hashmap to disk. + * + * @param writer A PrintWriter pointed at a file on disk. + * @param section A section containing settings to be written to the file. + */ private static void writeSection(PrintWriter writer, SettingSection section) { // Write the section header. From 2190496ce8d3e522f1510af9712bcb0d0b8f40f1 Mon Sep 17 00:00:00 2001 From: sigmabeta Date: Sat, 23 Jan 2016 11:51:24 -0500 Subject: [PATCH 6/6] Fix special case for XFB & update EFB to match desktop --- .../ui/settings/SettingsAdapter.java | 43 ++++++++++++++-- .../ui/settings/SettingsFragment.java | 5 +- .../settings/SettingsFragmentPresenter.java | 49 +++---------------- .../ui/settings/SettingsFragmentView.java | 7 ++- .../dolphinemu/utils/SettingsFile.java | 2 +- .../app/src/main/res/values/arrays.xml | 24 ++------- .../app/src/main/res/values/strings.xml | 7 +-- 7 files changed, 59 insertions(+), 78 deletions(-) diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java index ca754bb882..c83c578f06 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsAdapter.java @@ -126,7 +126,7 @@ public final class SettingsAdapter extends RecyclerView.Adapter sl) { - int efbCopyMethodValue = getEfbCopyMethodValue(); int xfbValue = getXfbValue(); Setting skipEFB = mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_SKIP_EFB); Setting ignoreFormat = mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_IGNORE_FORMAT); - IntSetting efbCopyMethod = new IntSetting(SettingsFile.KEY_EFB_COPY_METHOD, null, efbCopyMethodValue); + Setting efbToTexture = mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_EFB_TEXTURE); Setting texCacheAccuracy = mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_TEXCACHE_ACCURACY); IntSetting xfb = new IntSetting(SettingsFile.KEY_XFB, SettingsFile.SECTION_GFX_HACKS, xfbValue); Setting fastDepth = mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_FAST_DEPTH); @@ -212,62 +211,27 @@ public final class SettingsFragmentPresenter sl.add(new HeaderSetting(null, null, R.string.embedded_frame_buffer, 0)); sl.add(new CheckBoxSetting(SettingsFile.KEY_SKIP_EFB, SettingsFile.SECTION_GFX_HACKS, R.string.skip_efb_access, R.string.skip_efb_access_descrip, false, skipEFB)); sl.add(new CheckBoxSetting(SettingsFile.KEY_IGNORE_FORMAT, SettingsFile.SECTION_GFX_HACKS, R.string.ignore_format_changes, R.string.ignore_format_changes_descrip, false, ignoreFormat)); - sl.add(new SingleChoiceSetting(SettingsFile.KEY_EFB_COPY_METHOD, SettingsFile.SECTION_GFX_HACKS, R.string.efb_copy_method, R.string.efb_copy_method_descrip, R.array.efbCopyMethodEntries, R.array.efbCopyMethodValues, 1, efbCopyMethod)); + sl.add(new CheckBoxSetting(SettingsFile.KEY_EFB_TEXTURE, SettingsFile.SECTION_GFX_HACKS, R.string.efb_copy_method, R.string.efb_copy_method_descrip, true, efbToTexture)); sl.add(new HeaderSetting(null, null, R.string.texture_cache, 0)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_TEXCACHE_ACCURACY, SettingsFile.SECTION_GFX_HACKS, R.string.texture_cache_accuracy, R.string.texture_cache_accuracy_descrip, R.array.textureCacheAccuracyEntries, R.array.textureCacheAccuracyValues, 128, texCacheAccuracy)); sl.add(new HeaderSetting(null, null, R.string.external_frame_buffer, 0)); - sl.add(new SingleChoiceSetting(SettingsFile.KEY_XFB, SettingsFile.SECTION_GFX_HACKS, R.string.external_frame_buffer, R.string.external_frame_buffer_descrip, R.array.externalFrameBufferEntries, R.array.externalFrameBufferValues, 0, xfb)); + sl.add(new SingleChoiceSetting(SettingsFile.KEY_XFB_METHOD, SettingsFile.SECTION_GFX_HACKS, R.string.external_frame_buffer, R.string.external_frame_buffer_descrip, R.array.externalFrameBufferEntries, R.array.externalFrameBufferValues, 0, xfb)); sl.add(new HeaderSetting(null, null, R.string.other, 0)); sl.add(new CheckBoxSetting(SettingsFile.KEY_FAST_DEPTH, SettingsFile.SECTION_GFX_HACKS, R.string.fast_depth_calculation, R.string.fast_depth_calculation_descrip, true, fastDepth)); sl.add(new SingleChoiceSetting(SettingsFile.KEY_ASPECT_RATIO, SettingsFile.SECTION_GFX_HACKS, R.string.aspect_ratio, R.string.aspect_ratio_descrip, R.array.aspectRatioEntries, R.array.aspectRatioValues, 0, aspectRatio)); } - private int getEfbCopyMethodValue() - { - int efbCopyMethodValue; - try - { - boolean efbCopyOn = ((BooleanSetting) mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_EFB_COPY)).getValue(); - boolean efbCopyTexture = ((BooleanSetting) mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_EFB_TEXTURE)).getValue(); - boolean efbCopyCache = ((BooleanSetting) mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_EFB_CACHE)).getValue(); - - - if (!efbCopyOn) - { - efbCopyMethodValue = 0; - } - else if (efbCopyTexture) - { - efbCopyMethodValue = 1; - } - else if (!efbCopyCache) - { - efbCopyMethodValue = 2; - } - else - { - efbCopyMethodValue = 3; - } - } - catch (NullPointerException ex) - { - efbCopyMethodValue = 1; - } - - return efbCopyMethodValue; - } - private int getXfbValue() { int xfbValue; try { - boolean usingXFB = ((BooleanSetting) mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_XFB)).getValue(); - boolean usingRealXFB = ((BooleanSetting) mSettings.get(SettingsFile.SECTION_GFX_HACKS).getSetting(SettingsFile.KEY_XFB_REAL)).getValue(); + boolean usingXFB = ((BooleanSetting) mSettings.get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_XFB)).getValue(); + boolean usingRealXFB = ((BooleanSetting) mSettings.get(SettingsFile.SECTION_GFX_SETTINGS).getSetting(SettingsFile.KEY_XFB_REAL)).getValue(); if (!usingXFB) { @@ -290,3 +254,4 @@ public final class SettingsFragmentPresenter return xfbValue; } } + diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java index 0c0546d490..c437863c94 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/settings/SettingsFragmentView.java @@ -60,10 +60,9 @@ public interface SettingsFragmentView void showToastMessage(String message); /** - * Have the fragment add a setting to the Hashmap. Useful if the setting - * was missing from the .ini file, but included in the UI. + * Have the fragment add a setting to the Hashmap. * - * @param setting The (possibly missing) new setting. + * @param setting The (possibly previously missing) new setting. */ - void addSetting(Setting setting); + void putSetting(Setting setting); } diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java index 7f9eb74742..865e3371ae 100644 --- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java +++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/SettingsFile.java @@ -74,7 +74,7 @@ public final class SettingsFile public static final String KEY_ASPECT_RATIO= "AspectRatio"; // Internal only, not actually found in settings file. - public static final String KEY_EFB_COPY_METHOD = "EFBCopyMethod"; + public static final String KEY_XFB_METHOD = "XFBMethod"; private SettingsFile() { diff --git a/Source/Android/app/src/main/res/values/arrays.xml b/Source/Android/app/src/main/res/values/arrays.xml index d8320239bd..c7299780c6 100644 --- a/Source/Android/app/src/main/res/values/arrays.xml +++ b/Source/Android/app/src/main/res/values/arrays.xml @@ -71,20 +71,6 @@ Turntable - - - @string/disabled - @string/efb_copy_texture - @string/efb_copy_ram_uncached - @string/efb_copy_ram_cached - - - Off - Texture - RAM (cached) - RAM (uncached) - - @string/texture_cache_accuracy_low @@ -103,11 +89,11 @@ @string/external_frame_buffer_virtual @string/external_frame_buffer_real - - Disabled - Virtual - Real - + + 0 + 1 + 2 + diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml index ba3982396f..cf98d53bb9 100644 --- a/Source/Android/app/src/main/res/values/strings.xml +++ b/Source/Android/app/src/main/res/values/strings.xml @@ -286,11 +286,8 @@ Ignore any requests from the CPU to read/write to the EFB. Ignore Format Changes Ignore any changes to the EFB format. - EFB Copy Method - Determines how EFB copies will be emulated. - Texture - RAM (uncached) - RAM (cached) + Store EFB Copies to Texture Only + Stores EFB Copies exclusively on the GPU, bypassing system memory. Causes graphical defects in a small number of games. If unsure, leave this checked. Texture Cache Texture Cache Accuracy The safer the selection, the less likely the emulator will be missing any texture updates from RAM.