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 @@ -