mirror of
https://github.com/izzy2lost/PSX2.git
synced 2026-07-05 15:18:36 -07:00
lots of ui menu changes
This commit is contained in:
@@ -1211,6 +1211,12 @@ Java_com_izzy2lost_psx2_NativeApp_resume(JNIEnv *env, jclass clazz) {
|
||||
}).detach();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_izzy2lost_psx2_NativeApp_isPaused(JNIEnv *env, jclass clazz) {
|
||||
return VMManager::GetState() == VMState::Paused;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_izzy2lost_psx2_NativeApp_shutdown(JNIEnv *env, jclass clazz) {
|
||||
|
||||
@@ -114,6 +114,13 @@ public class GameSettingsDialogFragment extends DialogFragment {
|
||||
serialView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// Aspect Ratio Spinner
|
||||
Spinner spAspectRatio = view.findViewById(R.id.sp_aspect_ratio);
|
||||
ArrayAdapter<CharSequence> aspectAdapter = ArrayAdapter.createFromResource(ctx,
|
||||
R.array.aspect_ratio_entries, android.R.layout.simple_spinner_item);
|
||||
aspectAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spAspectRatio.setAdapter(aspectAdapter);
|
||||
|
||||
// Blending Accuracy Spinner
|
||||
Spinner spBlendingAccuracy = view.findViewById(R.id.sp_blending_accuracy);
|
||||
ArrayAdapter<CharSequence> blendingAdapter = ArrayAdapter.createFromResource(ctx,
|
||||
@@ -147,6 +154,7 @@ public class GameSettingsDialogFragment extends DialogFragment {
|
||||
android.content.SharedPreferences gp = ctx.getSharedPreferences("app_prefs", Context.MODE_PRIVATE);
|
||||
int gRenderer = gp.getInt("renderer", -1);
|
||||
float gScale = gp.getFloat("upscale_multiplier", 1.0f);
|
||||
int gAspect = gp.getInt("aspect_ratio", 1);
|
||||
int gBlend = gp.getInt("blending_accuracy", 1);
|
||||
boolean gWide = gp.getBoolean("widescreen_patches", true);
|
||||
boolean gNoInt = gp.getBoolean("no_interlacing_patches", true);
|
||||
@@ -157,6 +165,7 @@ public class GameSettingsDialogFragment extends DialogFragment {
|
||||
// Map to indices
|
||||
int defaultRendererIdx = (gRenderer == -1 ? 0 : (gRenderer == 14 ? 1 : (gRenderer == 12 ? 2 : 3)));
|
||||
int defaultScaleIdx = Math.max(0, Math.min(7, Math.round(gScale) - 1));
|
||||
spAspectRatio.setSelection(Math.max(0, Math.min(4, gAspect)));
|
||||
spRenderer.setSelection(defaultRendererIdx);
|
||||
spResolution.setSelection(defaultScaleIdx);
|
||||
spBlendingAccuracy.setSelection(Math.max(0, Math.min(5, gBlend)));
|
||||
@@ -206,6 +215,22 @@ public class GameSettingsDialogFragment extends DialogFragment {
|
||||
if (m.find()) {
|
||||
try { float mult = Float.parseFloat(m.group(1)); int sel = Math.max(0, Math.min(7, Math.round(mult - 1))); spResolution.setSelection(sel); } catch (Exception ignored) {}
|
||||
}
|
||||
m = java.util.regex.Pattern.compile("(?m)^AspectRatio=\\s*(.+)$").matcher(content);
|
||||
if (m.find()) {
|
||||
String av = m.group(1).trim();
|
||||
int idx = 1; // default Auto 4:3/3:2
|
||||
try {
|
||||
int num = Integer.parseInt(av);
|
||||
if (num >= 0 && num <= 4) idx = num;
|
||||
} catch (Exception e) {
|
||||
if ("Stretch".equalsIgnoreCase(av)) idx = 0;
|
||||
else if ("Auto".equalsIgnoreCase(av)) idx = 1;
|
||||
else if ("4:3".equalsIgnoreCase(av)) idx = 2;
|
||||
else if ("16:9".equalsIgnoreCase(av)) idx = 3;
|
||||
else if ("10:7".equalsIgnoreCase(av)) idx = 4;
|
||||
}
|
||||
spAspectRatio.setSelection(idx);
|
||||
}
|
||||
m = java.util.regex.Pattern.compile("(?m)^accurate_blending_unit=\\s*(.+)$").matcher(content);
|
||||
if (m.find()) {
|
||||
String bv = m.group(1).trim();
|
||||
@@ -255,6 +280,7 @@ public class GameSettingsDialogFragment extends DialogFragment {
|
||||
}
|
||||
} catch (Throwable ignored) {
|
||||
// Fallback to defaults if loading fails
|
||||
spAspectRatio.setSelection(1);
|
||||
spBlendingAccuracy.setSelection(1);
|
||||
// Mirror global default when error
|
||||
android.content.SharedPreferences prefs = ctx.getSharedPreferences("app_prefs", Context.MODE_PRIVATE);
|
||||
@@ -276,6 +302,7 @@ public class GameSettingsDialogFragment extends DialogFragment {
|
||||
.setView(view)
|
||||
.setNegativeButton("Cancel", (d, w) -> d.dismiss())
|
||||
.setPositiveButton("Save", (d, w) -> {
|
||||
final int aspectIdx = spAspectRatio.getSelectedItemPosition();
|
||||
final int blendLevel = spBlendingAccuracy.getSelectedItemPosition();
|
||||
final int rendererIdx = spRenderer.getSelectedItemPosition();
|
||||
final int resIdx = spResolution.getSelectedItemPosition();
|
||||
@@ -288,7 +315,7 @@ public class GameSettingsDialogFragment extends DialogFragment {
|
||||
|
||||
// Persist per-game INI explicitly (supports Auto as well)
|
||||
writeGameSettingsIni(ctx, gameSerial, gameCrc,
|
||||
blendLevel, rendererIdx, resIdx, wide, noInt,
|
||||
aspectIdx, blendLevel, rendererIdx, resIdx, wide, noInt,
|
||||
/*enablePatches*/ enablePatches, enableCheats);
|
||||
|
||||
// Live-apply per-game settings in one batch
|
||||
@@ -301,6 +328,7 @@ public class GameSettingsDialogFragment extends DialogFragment {
|
||||
else renderer = 13;
|
||||
|
||||
float scale = Math.max(1, Math.min(8, resIdx + 1));
|
||||
NativeApp.setAspectRatio(aspectIdx);
|
||||
NativeApp.setLoadTextures(loadTex);
|
||||
NativeApp.setAsyncTextureLoading(asyncTex);
|
||||
NativeApp.applyPerGameSettingsBatch(renderer, scale, blendLevel, wide, noInt, enablePatches, enableCheats);
|
||||
@@ -385,6 +413,7 @@ public class GameSettingsDialogFragment extends DialogFragment {
|
||||
private static void writeGameSettingsIni(Context ctx,
|
||||
String gameSerial,
|
||||
String gameCrc,
|
||||
int aspectRatioIdx,
|
||||
int blendingAccuracyIdx,
|
||||
int rendererIdx,
|
||||
int resolutionIdx,
|
||||
@@ -403,11 +432,13 @@ public class GameSettingsDialogFragment extends DialogFragment {
|
||||
String rendererName = (rendererIdx == 0) ? "Auto" : (rendererIdx == 1 ? "Vulkan" : (rendererIdx == 2 ? "OpenGL" : "Software"));
|
||||
float upscale = Math.max(1, Math.min(8, resolutionIdx + 1));
|
||||
int abl = Math.max(0, Math.min(5, blendingAccuracyIdx));
|
||||
int aspectRatio = Math.max(0, Math.min(4, aspectRatioIdx));
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("[EmuCore/GS]\n");
|
||||
sb.append("Renderer=").append(rendererName).append('\n');
|
||||
sb.append("upscale_multiplier=").append((int) upscale).append('\n');
|
||||
sb.append("AspectRatio=").append(aspectRatio).append('\n');
|
||||
sb.append("accurate_blending_unit=").append(abl).append('\n');
|
||||
sb.append('\n');
|
||||
sb.append("[EmuCore]\n");
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,69 +0,0 @@
|
||||
package com.izzy2lost.psx2;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class LettersAdapter extends RecyclerView.Adapter<LettersAdapter.VH> {
|
||||
public interface OnClick {
|
||||
void onClick(char letter);
|
||||
}
|
||||
|
||||
private final List<Character> letters;
|
||||
private final OnClick onClick;
|
||||
|
||||
public LettersAdapter(List<Character> letters, OnClick onClick) {
|
||||
this.letters = letters;
|
||||
this.onClick = onClick;
|
||||
setHasStableIds(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
// Ensure uniqueness across the infinite range by including position
|
||||
return position;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public VH onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_letter, parent, false);
|
||||
return new VH(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull VH holder, int position) {
|
||||
int n = letters != null ? letters.size() : 0;
|
||||
if (n == 0) return;
|
||||
int real = position % n;
|
||||
char ch = letters.get(real);
|
||||
holder.text.setText(String.valueOf(ch));
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
android.util.Log.d("LettersAdapter", "Letter clicked: " + ch + " at position " + position);
|
||||
if (onClick != null) {
|
||||
onClick.onClick(ch);
|
||||
} else {
|
||||
android.util.Log.d("LettersAdapter", "onClick is null!");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return (letters != null && !letters.isEmpty()) ? Integer.MAX_VALUE : 0;
|
||||
}
|
||||
|
||||
static class VH extends RecyclerView.ViewHolder {
|
||||
final TextView text;
|
||||
VH(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
text = itemView.findViewById(R.id.text_letter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,8 @@ import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Spinner;
|
||||
import android.view.ViewGroup;
|
||||
import android.content.res.ColorStateList;
|
||||
import android.graphics.Color;
|
||||
@@ -74,6 +76,7 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF
|
||||
private boolean joyRightPressed = false;
|
||||
private boolean controllerUiApplied = false;
|
||||
private AlertDialog mBiosPromptDialog = null;
|
||||
private boolean mControllerHintShowing = false;
|
||||
|
||||
private boolean isThread() {
|
||||
if (mEmulationThread != null) {
|
||||
@@ -223,6 +226,15 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF
|
||||
lp.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
|
||||
w.setAttributes(lp);
|
||||
}
|
||||
|
||||
// Common flags for legacy immersive (works as belt-and-suspenders on newer API too)
|
||||
final int legacyFlags = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
// Tell Window to lay out edge-to-edge and hide all system bars
|
||||
w.setDecorFitsSystemWindows(false);
|
||||
@@ -231,15 +243,22 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF
|
||||
controller.hide(WindowInsets.Type.systemBars());
|
||||
controller.setSystemBarsBehavior(WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE);
|
||||
}
|
||||
// Also apply legacy flags to decor; helps on 3-button nav devices
|
||||
View decor = w.getDecorView();
|
||||
decor.setSystemUiVisibility(legacyFlags);
|
||||
decor.setOnSystemUiVisibilityChangeListener(vis -> {
|
||||
if ((vis & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
|
||||
decor.setSystemUiVisibility(legacyFlags);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
View decor = w.getDecorView();
|
||||
int flags = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
|
||||
decor.setSystemUiVisibility(flags);
|
||||
decor.setSystemUiVisibility(legacyFlags);
|
||||
decor.setOnSystemUiVisibilityChangeListener(vis -> {
|
||||
if ((vis & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
|
||||
decor.setSystemUiVisibility(legacyFlags);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,7 +333,7 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF
|
||||
}
|
||||
|
||||
private static final String[] GAME_EXTS = new String[]{
|
||||
".iso", ".bin", ".img", ".mdf", ".nrg", ".chd"
|
||||
".iso", ".bin", ".img", ".mdf", ".nrg", ".chd", ".cso", ".zso", ".gz"
|
||||
};
|
||||
|
||||
private static boolean hasGameExt(String name) {
|
||||
@@ -483,11 +502,23 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF
|
||||
if (btn_settings != null) {
|
||||
btn_settings.setOnClickListener(v -> {
|
||||
try {
|
||||
// Refresh drawer settings before opening
|
||||
refreshDrawerSettings();
|
||||
DrawerLayout drawer = findViewById(R.id.drawer_layout);
|
||||
if (drawer != null) drawer.openDrawer(androidx.core.view.GravityCompat.START);
|
||||
} catch (Throwable ignored) {}
|
||||
});
|
||||
}
|
||||
|
||||
// Pause/Play button toggles emulation pause state
|
||||
MaterialButton btn_pause_play = findViewById(R.id.btn_pause_play);
|
||||
if (btn_pause_play != null) {
|
||||
btn_pause_play.setOnClickListener(v -> {
|
||||
try {
|
||||
togglePauseState();
|
||||
} catch (Throwable ignored) {}
|
||||
});
|
||||
}
|
||||
// Wire left drawer header controls (title/power/reboot/renderer)
|
||||
try {
|
||||
NavigationView nav = findViewById(R.id.nav_view);
|
||||
@@ -542,6 +573,18 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF
|
||||
} catch (Throwable ignored) {}
|
||||
});
|
||||
}
|
||||
View btnGames = header.findViewById(R.id.drawer_btn_games);
|
||||
if (btnGames != null) {
|
||||
btnGames.setOnClickListener(v -> {
|
||||
try {
|
||||
// Close drawer first
|
||||
DrawerLayout drawer = findViewById(R.id.drawer_layout);
|
||||
if (drawer != null) drawer.closeDrawer(androidx.core.view.GravityCompat.START);
|
||||
// Open games dialog
|
||||
openGamesDialog();
|
||||
} catch (Throwable ignored) {}
|
||||
});
|
||||
}
|
||||
if (btnGameState != null) {
|
||||
btnGameState.setOnClickListener(v -> {
|
||||
try {
|
||||
@@ -550,6 +593,9 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF
|
||||
} catch (Throwable ignored) {}
|
||||
});
|
||||
}
|
||||
|
||||
// Setup drawer settings controls to mirror quick actions
|
||||
setupDrawerSettings(header);
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
@@ -809,6 +855,11 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF
|
||||
|
||||
// Hide on-screen touch controls when a physical controller is connected
|
||||
setControlsVisible(!hasController);
|
||||
|
||||
// Show controller hint when no controller is connected (only once)
|
||||
if (!hasController) {
|
||||
showControllerHintIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
private int getCurrentRendererPref() {
|
||||
@@ -1333,7 +1384,7 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF
|
||||
SDLControllerManager.initialize();
|
||||
|
||||
// Load and apply saved settings
|
||||
SettingsDialogFragment.loadAndApplySettings(this);
|
||||
loadAndApplyStoredSettings();
|
||||
|
||||
mHIDDeviceManager = HIDDeviceManager.acquire(this);
|
||||
// Initialize HID device manager for USB and Bluetooth controllers
|
||||
@@ -1360,6 +1411,14 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF
|
||||
if(!isThread()) {
|
||||
mEmulationThread = new Thread(() -> NativeApp.runVMThread(m_szGamefile));
|
||||
mEmulationThread.start();
|
||||
// Show pause button when game starts (game is always running initially)
|
||||
runOnUiThread(() -> {
|
||||
MaterialButton btn_pause_play = findViewById(R.id.btn_pause_play);
|
||||
if (btn_pause_play != null) {
|
||||
btn_pause_play.setVisibility(View.VISIBLE);
|
||||
btn_pause_play.setIcon(ContextCompat.getDrawable(this, R.drawable.pause_circle_24px));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1395,6 +1454,7 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF
|
||||
} else {
|
||||
// No game loaded; just shutdown for safety
|
||||
NativeApp.shutdown();
|
||||
updatePausePlayButton();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1704,10 +1764,320 @@ public class MainActivity extends AppCompatActivity implements GamesCoverDialogF
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void setupDrawerSettings(View header) {
|
||||
if (header == null) return;
|
||||
|
||||
SharedPreferences prefs = getSharedPreferences("app_prefs", MODE_PRIVATE);
|
||||
|
||||
// Aspect Ratio spinner - setup like QuickActions
|
||||
Spinner spAspect = header.findViewById(R.id.drawer_sp_aspect_ratio);
|
||||
if (spAspect != null) {
|
||||
if (spAspect.getAdapter() == null) {
|
||||
ArrayAdapter<CharSequence> aspectAdapter = ArrayAdapter.createFromResource(this,
|
||||
R.array.aspect_ratio_entries, android.R.layout.simple_spinner_item);
|
||||
aspectAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spAspect.setAdapter(aspectAdapter);
|
||||
spAspect.setOnItemSelectedListener(new android.widget.AdapterView.OnItemSelectedListener() {
|
||||
@Override public void onItemSelected(android.widget.AdapterView<?> parent, View view, int position, long id) {
|
||||
prefs.edit().putInt("aspect_ratio", position).apply();
|
||||
try { NativeApp.setAspectRatio(position); } catch (Throwable ignored) {}
|
||||
}
|
||||
@Override public void onNothingSelected(android.widget.AdapterView<?> parent) {}
|
||||
});
|
||||
}
|
||||
ArrayAdapter<?> adapter = (ArrayAdapter<?>) spAspect.getAdapter();
|
||||
if (adapter != null) {
|
||||
int savedAspect = prefs.getInt("aspect_ratio", 1);
|
||||
if (savedAspect < 0 || savedAspect >= adapter.getCount()) savedAspect = 1;
|
||||
spAspect.setSelection(savedAspect);
|
||||
}
|
||||
}
|
||||
|
||||
// Resolution Scale spinner
|
||||
Spinner spScale = header.findViewById(R.id.drawer_sp_scale);
|
||||
if (spScale != null) {
|
||||
if (spScale.getAdapter() == null) {
|
||||
ArrayAdapter<CharSequence> scaleAdapter = ArrayAdapter.createFromResource(this,
|
||||
R.array.scale_entries, android.R.layout.simple_spinner_item);
|
||||
scaleAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spScale.setAdapter(scaleAdapter);
|
||||
spScale.setOnItemSelectedListener(new android.widget.AdapterView.OnItemSelectedListener() {
|
||||
@Override public void onItemSelected(android.widget.AdapterView<?> parent, View view, int position, long id) {
|
||||
float scale = Math.max(1, Math.min(8, position + 1));
|
||||
prefs.edit().putFloat("upscale_multiplier", scale).apply();
|
||||
try { NativeApp.renderUpscalemultiplier(scale); } catch (Throwable ignored) {}
|
||||
}
|
||||
@Override public void onNothingSelected(android.widget.AdapterView<?> parent) {}
|
||||
});
|
||||
}
|
||||
ArrayAdapter<?> adapter = (ArrayAdapter<?>) spScale.getAdapter();
|
||||
if (adapter != null) {
|
||||
float savedScale = prefs.getFloat("upscale_multiplier", 1.0f);
|
||||
int scaleIndex = Math.max(0, Math.min(adapter.getCount() - 1, Math.round(savedScale) - 1));
|
||||
spScale.setSelection(scaleIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Blending Accuracy spinner - setup like QuickActions
|
||||
Spinner spBlending = header.findViewById(R.id.drawer_sp_blending_accuracy);
|
||||
if (spBlending != null) {
|
||||
if (spBlending.getAdapter() == null) {
|
||||
ArrayAdapter<CharSequence> blendAdapter = ArrayAdapter.createFromResource(this,
|
||||
R.array.blending_accuracy_entries, android.R.layout.simple_spinner_item);
|
||||
blendAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
spBlending.setAdapter(blendAdapter);
|
||||
spBlending.setOnItemSelectedListener(new android.widget.AdapterView.OnItemSelectedListener() {
|
||||
@Override public void onItemSelected(android.widget.AdapterView<?> parent, View view, int position, long id) {
|
||||
prefs.edit().putInt("blending_accuracy", position).apply();
|
||||
try { NativeApp.setBlendingAccuracy(position); } catch (Throwable ignored) {}
|
||||
}
|
||||
@Override public void onNothingSelected(android.widget.AdapterView<?> parent) {}
|
||||
});
|
||||
}
|
||||
ArrayAdapter<?> adapter = (ArrayAdapter<?>) spBlending.getAdapter();
|
||||
if (adapter != null) {
|
||||
int savedBlend = prefs.getInt("blending_accuracy", 1);
|
||||
if (savedBlend < 0 || savedBlend >= adapter.getCount()) savedBlend = 1;
|
||||
spBlending.setSelection(savedBlend);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup switch listeners only once
|
||||
setupDrawerSwitchListeners(header, prefs);
|
||||
}
|
||||
|
||||
private void setupDrawerSwitchListeners(View header, SharedPreferences prefs) {
|
||||
// Widescreen Patches switch
|
||||
com.google.android.material.materialswitch.MaterialSwitch swWide = header.findViewById(R.id.drawer_sw_widescreen);
|
||||
if (swWide != null && swWide.getTag() == null) {
|
||||
swWide.setTag("setup"); // Mark as setup to avoid duplicate listeners
|
||||
swWide.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
prefs.edit().putBoolean("widescreen_patches", isChecked).apply();
|
||||
try { NativeApp.setWidescreenPatches(isChecked); } catch (Throwable ignored) {}
|
||||
});
|
||||
}
|
||||
|
||||
// No Interlacing switch
|
||||
com.google.android.material.materialswitch.MaterialSwitch swNoInt = header.findViewById(R.id.drawer_sw_no_interlacing);
|
||||
if (swNoInt != null && swNoInt.getTag() == null) {
|
||||
swNoInt.setTag("setup");
|
||||
swNoInt.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
prefs.edit().putBoolean("no_interlacing_patches", isChecked).apply();
|
||||
try { NativeApp.setNoInterlacingPatches(isChecked); } catch (Throwable ignored) {}
|
||||
});
|
||||
}
|
||||
|
||||
// Load Textures switch
|
||||
com.google.android.material.materialswitch.MaterialSwitch swLoadTex = header.findViewById(R.id.drawer_sw_load_textures);
|
||||
if (swLoadTex != null && swLoadTex.getTag() == null) {
|
||||
swLoadTex.setTag("setup");
|
||||
swLoadTex.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
prefs.edit().putBoolean("load_textures", isChecked).apply();
|
||||
try { NativeApp.setLoadTextures(isChecked); } catch (Throwable ignored) {}
|
||||
});
|
||||
}
|
||||
|
||||
// Async Textures switch
|
||||
com.google.android.material.materialswitch.MaterialSwitch swAsyncTex = header.findViewById(R.id.drawer_sw_async_textures);
|
||||
if (swAsyncTex != null && swAsyncTex.getTag() == null) {
|
||||
swAsyncTex.setTag("setup");
|
||||
swAsyncTex.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
prefs.edit().putBoolean("async_texture_loading", isChecked).apply();
|
||||
try { NativeApp.setAsyncTextureLoading(isChecked); } catch (Throwable ignored) {}
|
||||
});
|
||||
}
|
||||
|
||||
// Precache Textures switch
|
||||
com.google.android.material.materialswitch.MaterialSwitch swPrecache = header.findViewById(R.id.drawer_sw_precache_textures);
|
||||
if (swPrecache != null && swPrecache.getTag() == null) {
|
||||
swPrecache.setTag("setup");
|
||||
swPrecache.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
prefs.edit().putBoolean("precache_textures", isChecked).apply();
|
||||
try { NativeApp.setPrecacheTextureReplacements(isChecked); } catch (Throwable ignored) {}
|
||||
});
|
||||
}
|
||||
|
||||
// HUD Developer switch
|
||||
com.google.android.material.materialswitch.MaterialSwitch swDevHud = header.findViewById(R.id.drawer_sw_dev_hud);
|
||||
if (swDevHud != null && swDevHud.getTag() == null) {
|
||||
swDevHud.setTag("setup");
|
||||
swDevHud.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
prefs.edit().putBoolean("hud_visible", isChecked).apply();
|
||||
try { NativeApp.setHudVisible(isChecked); } catch (Throwable ignored) {}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshDrawerSettings() {
|
||||
try {
|
||||
NavigationView nav = findViewById(R.id.nav_view);
|
||||
if (nav != null && nav.getHeaderCount() > 0) {
|
||||
View header = nav.getHeaderView(0);
|
||||
if (header != null) {
|
||||
SharedPreferences prefs = getSharedPreferences("app_prefs", MODE_PRIVATE);
|
||||
|
||||
// Refresh switch states only (spinners are set up once in setupDrawerSettings)
|
||||
com.google.android.material.materialswitch.MaterialSwitch swWide = header.findViewById(R.id.drawer_sw_widescreen);
|
||||
if (swWide != null) {
|
||||
swWide.setChecked(prefs.getBoolean("widescreen_patches", true));
|
||||
}
|
||||
|
||||
com.google.android.material.materialswitch.MaterialSwitch swNoInt = header.findViewById(R.id.drawer_sw_no_interlacing);
|
||||
if (swNoInt != null) {
|
||||
swNoInt.setChecked(prefs.getBoolean("no_interlacing_patches", true));
|
||||
}
|
||||
|
||||
com.google.android.material.materialswitch.MaterialSwitch swLoadTex = header.findViewById(R.id.drawer_sw_load_textures);
|
||||
if (swLoadTex != null) {
|
||||
swLoadTex.setChecked(prefs.getBoolean("load_textures", false));
|
||||
}
|
||||
|
||||
com.google.android.material.materialswitch.MaterialSwitch swAsyncTex = header.findViewById(R.id.drawer_sw_async_textures);
|
||||
if (swAsyncTex != null) {
|
||||
swAsyncTex.setChecked(prefs.getBoolean("async_texture_loading", true));
|
||||
}
|
||||
|
||||
com.google.android.material.materialswitch.MaterialSwitch swPrecache = header.findViewById(R.id.drawer_sw_precache_textures);
|
||||
if (swPrecache != null) {
|
||||
swPrecache.setChecked(prefs.getBoolean("precache_textures", false));
|
||||
}
|
||||
|
||||
com.google.android.material.materialswitch.MaterialSwitch swDevHud = header.findViewById(R.id.drawer_sw_dev_hud);
|
||||
if (swDevHud != null) {
|
||||
swDevHud.setChecked(prefs.getBoolean("hud_visible", false));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
private void loadAndApplyStoredSettings() {
|
||||
try {
|
||||
SharedPreferences prefs = getSharedPreferences("app_prefs", MODE_PRIVATE);
|
||||
|
||||
// Apply aspect ratio setting
|
||||
int aspectRatio = prefs.getInt("aspect_ratio", 1);
|
||||
NativeApp.setAspectRatio(aspectRatio);
|
||||
|
||||
// Apply blending accuracy setting
|
||||
int blendingAccuracy = prefs.getInt("blending_accuracy", 1);
|
||||
NativeApp.setBlendingAccuracy(blendingAccuracy);
|
||||
|
||||
// Apply other settings
|
||||
boolean widescreenPatches = prefs.getBoolean("widescreen_patches", true);
|
||||
NativeApp.setWidescreenPatches(widescreenPatches);
|
||||
|
||||
boolean noInterlacing = prefs.getBoolean("no_interlacing_patches", true);
|
||||
NativeApp.setNoInterlacingPatches(noInterlacing);
|
||||
|
||||
boolean loadTextures = prefs.getBoolean("load_textures", false);
|
||||
NativeApp.setLoadTextures(loadTextures);
|
||||
|
||||
boolean asyncTextures = prefs.getBoolean("async_texture_loading", true);
|
||||
NativeApp.setAsyncTextureLoading(asyncTextures);
|
||||
|
||||
boolean precacheTextures = prefs.getBoolean("precache_textures", false);
|
||||
NativeApp.setPrecacheTextureReplacements(precacheTextures);
|
||||
|
||||
// Apply renderer setting
|
||||
int renderer = prefs.getInt("renderer", -1);
|
||||
NativeApp.renderGpu(renderer);
|
||||
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
private void showControllerHintIfNeeded() {
|
||||
// Prevent multiple dialogs from showing
|
||||
if (mControllerHintShowing) return;
|
||||
|
||||
SharedPreferences prefs = getSharedPreferences("app_prefs", MODE_PRIVATE);
|
||||
boolean hasShownHint = prefs.getBoolean("controller_hint_shown", false);
|
||||
|
||||
// Only show the hint once, and only if setup is complete
|
||||
if (!hasShownHint && prefs.getBoolean("first_run_done", false)) {
|
||||
mControllerHintShowing = true;
|
||||
// Small delay to avoid showing immediately on startup
|
||||
findViewById(android.R.id.content).postDelayed(() -> {
|
||||
if (!isFinishing() && !mSetupWizardActive && mControllerHintShowing) {
|
||||
showControllerHintDialog();
|
||||
}
|
||||
}, 2000); // 2 second delay
|
||||
}
|
||||
}
|
||||
|
||||
private void showControllerHintDialog() {
|
||||
// Double-check to prevent multiple dialogs
|
||||
if (!mControllerHintShowing) return;
|
||||
|
||||
View dialogView = getLayoutInflater().inflate(R.layout.dialog_controller_hint, null);
|
||||
|
||||
com.google.android.material.materialswitch.MaterialSwitch swDontShow = dialogView.findViewById(R.id.sw_dont_show_again);
|
||||
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this,
|
||||
com.google.android.material.R.style.ThemeOverlay_Material3_MaterialAlertDialog)
|
||||
.setCustomTitle(UiUtils.centeredDialogTitle(this, "Controller Tip"))
|
||||
.setView(dialogView)
|
||||
.setPositiveButton("Got it!", (dialog, which) -> {
|
||||
SharedPreferences prefs = getSharedPreferences("app_prefs", MODE_PRIVATE);
|
||||
if (swDontShow != null && swDontShow.isChecked()) {
|
||||
prefs.edit().putBoolean("controller_hint_shown", true).apply();
|
||||
}
|
||||
mControllerHintShowing = false;
|
||||
dialog.dismiss();
|
||||
})
|
||||
.setCancelable(true)
|
||||
.setOnDismissListener(dialog -> {
|
||||
mControllerHintShowing = false;
|
||||
});
|
||||
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
// Pause/Play toggle functionality
|
||||
public void togglePauseState() {
|
||||
try {
|
||||
boolean isPaused = NativeApp.isPaused();
|
||||
if (isPaused) {
|
||||
NativeApp.resume();
|
||||
} else {
|
||||
NativeApp.pause();
|
||||
}
|
||||
updatePausePlayButton();
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
private void updatePausePlayButton() {
|
||||
MaterialButton btn_pause_play = findViewById(R.id.btn_pause_play);
|
||||
if (btn_pause_play != null) {
|
||||
try {
|
||||
boolean isPaused = NativeApp.isPaused();
|
||||
boolean hasGame = hasSelectedGame() && isThread();
|
||||
|
||||
// Show button only when a game is running
|
||||
btn_pause_play.setVisibility(hasGame ? View.VISIBLE : View.GONE);
|
||||
|
||||
if (hasGame) {
|
||||
// Update icon to show the action it will perform
|
||||
if (isPaused) {
|
||||
// Game is paused, show pause icon (will pause more/stay paused)
|
||||
btn_pause_play.setIcon(ContextCompat.getDrawable(this, R.drawable.pause_circle_24px));
|
||||
} else {
|
||||
// Game is running, show play icon (will keep playing)
|
||||
btn_pause_play.setIcon(ContextCompat.getDrawable(this, R.drawable.play_circle_24px));
|
||||
}
|
||||
}
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
// Call this method when game starts/stops to update button visibility
|
||||
public void updateGameState() {
|
||||
updatePausePlayButton();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -159,6 +159,7 @@ public class NativeApp {
|
||||
|
||||
public static native void pause();
|
||||
public static native void resume();
|
||||
public static native boolean isPaused();
|
||||
public static native void shutdown();
|
||||
|
||||
public static native boolean saveStateToSlot(int slot);
|
||||
|
||||
@@ -10,6 +10,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.materialswitch.MaterialSwitch;
|
||||
import android.widget.Spinner;
|
||||
@@ -22,13 +23,14 @@ public class QuickActionsDialogFragment extends DialogFragment {
|
||||
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
||||
View view = getLayoutInflater().inflate(R.layout.dialog_quick_actions, null, false);
|
||||
|
||||
MaterialButton btnPower = view.findViewById(R.id.btn_quick_power);
|
||||
MaterialButton btnReboot = view.findViewById(R.id.btn_quick_reboot);
|
||||
FloatingActionButton btnPower = view.findViewById(R.id.btn_quick_power);
|
||||
FloatingActionButton btnReboot = view.findViewById(R.id.btn_quick_reboot);
|
||||
com.google.android.material.button.MaterialButtonToggleGroup tgRenderer = view.findViewById(R.id.qa_tg_renderer);
|
||||
View tbAt = view.findViewById(R.id.qa_tb_at);
|
||||
View tbVk = view.findViewById(R.id.qa_tb_vk);
|
||||
View tbGl = view.findViewById(R.id.qa_tb_gl);
|
||||
View tbSw = view.findViewById(R.id.qa_tb_sw);
|
||||
FloatingActionButton btnPausePlay = view.findViewById(R.id.btn_quick_pause_play);
|
||||
MaterialButton btnGames = view.findViewById(R.id.btn_quick_games);
|
||||
MaterialButton btnSaves = view.findViewById(R.id.btn_quick_saves);
|
||||
MaterialButton btnCancel = view.findViewById(R.id.btn_cancel);
|
||||
@@ -51,6 +53,26 @@ public class QuickActionsDialogFragment extends DialogFragment {
|
||||
.show());
|
||||
}
|
||||
|
||||
// Pause/Play toggle
|
||||
if (btnPausePlay != null) {
|
||||
try {
|
||||
boolean isPaused = NativeApp.isPaused();
|
||||
btnPausePlay.setImageResource(R.drawable.play_pause_24px);
|
||||
} catch (Throwable ignored) {}
|
||||
btnPausePlay.setOnClickListener(v -> {
|
||||
try {
|
||||
if (requireActivity() instanceof MainActivity) {
|
||||
((MainActivity) requireActivity()).togglePauseState();
|
||||
} else {
|
||||
boolean paused = NativeApp.isPaused();
|
||||
if (paused) NativeApp.resume(); else NativeApp.pause();
|
||||
}
|
||||
boolean isPausedNow = NativeApp.isPaused();
|
||||
btnPausePlay.setImageResource(R.drawable.play_pause_24px);
|
||||
} catch (Throwable ignored) {}
|
||||
});
|
||||
}
|
||||
|
||||
// Reboot game
|
||||
if (btnReboot != null) {
|
||||
btnReboot.setOnClickListener(v -> new MaterialAlertDialogBuilder(requireContext(),
|
||||
@@ -208,3 +230,5 @@ public class QuickActionsDialogFragment extends DialogFragment {
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -56,12 +56,16 @@ public class SetupWizardDialogFragment extends DialogFragment {
|
||||
int pad = (int)(24 * getResources().getDisplayMetrics().density);
|
||||
root.setPadding(pad, pad, pad, pad);
|
||||
root.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
// Use theme background
|
||||
root.setBackgroundColor(ContextCompat.getColor(requireContext(), R.color.md_theme_surface));
|
||||
|
||||
titleView = new TextView(requireContext());
|
||||
titleView.setText("Welcome! Let's set up PSX2");
|
||||
titleView.setTextSize(22f);
|
||||
titleView.setTextSize(26f);
|
||||
titleView.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
titleView.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
||||
titleView.setTextColor(ContextCompat.getColor(requireContext(), R.color.md_theme_tertiaryFixedDim));
|
||||
titleView.setTypeface(titleView.getTypeface(), android.graphics.Typeface.BOLD);
|
||||
root.addView(titleView);
|
||||
|
||||
// Subtitle removed; using inline hint near the Done button instead.
|
||||
@@ -144,7 +148,8 @@ public class SetupWizardDialogFragment extends DialogFragment {
|
||||
hintView.setTextSize(14f);
|
||||
hintView.setGravity(Gravity.CENTER_HORIZONTAL);
|
||||
hintView.setTextAlignment(View.TEXT_ALIGNMENT_CENTER);
|
||||
hintView.setAlpha(0.8f);
|
||||
hintView.setTextColor(ContextCompat.getColor(requireContext(), R.color.brand_primary));
|
||||
hintView.setAlpha(0.9f);
|
||||
LinearLayout.LayoutParams hintLp = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
|
||||
hintLp.topMargin = (int)(8 * getResources().getDisplayMetrics().density);
|
||||
hintView.setLayoutParams(hintLp);
|
||||
@@ -199,11 +204,37 @@ public class SetupWizardDialogFragment extends DialogFragment {
|
||||
btnGames.setIcon(step2 ? ContextCompat.getDrawable(requireContext(), R.drawable.check_circle_24px) : null);
|
||||
btnBios.setIcon(step3 ? ContextCompat.getDrawable(requireContext(), R.drawable.check_circle_24px) : null);
|
||||
|
||||
// Add theme accent to completed buttons
|
||||
int themeAccent = ContextCompat.getColor(requireContext(), R.color.md_theme_tertiary);
|
||||
int defaultColor = ContextCompat.getColor(requireContext(), R.color.md_theme_onSurface);
|
||||
|
||||
btnData.setIconTint(step1 ? android.content.res.ColorStateList.valueOf(themeAccent) : null);
|
||||
btnGames.setIconTint(step2 ? android.content.res.ColorStateList.valueOf(themeAccent) : null);
|
||||
btnBios.setIconTint(step3 ? android.content.res.ColorStateList.valueOf(themeAccent) : null);
|
||||
|
||||
btnGames.setEnabled(step1);
|
||||
btnBios.setEnabled(step1 && step2);
|
||||
boolean doneEnabled = (step1 && step2 && step3);
|
||||
btnDone.setEnabled(doneEnabled);
|
||||
if (hintView != null) hintView.setVisibility(doneEnabled ? View.GONE : View.VISIBLE);
|
||||
|
||||
// Style the Done button when ready
|
||||
if (doneEnabled) {
|
||||
btnDone.setBackgroundTintList(android.content.res.ColorStateList.valueOf(themeAccent));
|
||||
btnDone.setTextColor(ContextCompat.getColor(requireContext(), R.color.md_theme_onTertiary));
|
||||
if (hintView != null) {
|
||||
hintView.setText("🎉 Ready to go! Tap Done to start.");
|
||||
hintView.setTextColor(ContextCompat.getColor(requireContext(), R.color.md_theme_tertiaryFixedDim));
|
||||
}
|
||||
} else {
|
||||
btnDone.setBackgroundTintList(null);
|
||||
btnDone.setTextColor(defaultColor);
|
||||
if (hintView != null) {
|
||||
hintView.setText("Complete all steps to finish.");
|
||||
hintView.setTextColor(ContextCompat.getColor(requireContext(), R.color.brand_primary));
|
||||
}
|
||||
}
|
||||
|
||||
if (hintView != null) hintView.setVisibility(View.VISIBLE);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M360,640L440,640L440,320L360,320L360,640ZM520,640L600,640L600,320L520,320L520,640ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,800Q614,800 707,707Q800,614 800,480Q800,346 707,253Q614,160 480,160Q346,160 253,253Q160,346 160,480Q160,614 253,707Q346,800 480,800ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M380,660L660,480L380,300L380,660ZM480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,800Q614,800 707,707Q800,614 800,480Q800,346 707,253Q614,160 480,160Q346,160 253,253Q160,346 160,480Q160,614 253,707Q346,800 480,800ZM480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Q480,480 480,480Z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M200,648L200,312L440,480L200,648ZM520,640L520,320L600,320L600,640L520,640ZM680,640L680,320L760,320L760,640L680,640Z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- Selected/Checked state -->
|
||||
<item android:state_checked="true" android:color="@color/toggle_button_selected" />
|
||||
<!-- Default/Unselected state -->
|
||||
<item android:color="@color/toggle_button_unselected" />
|
||||
</selector>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- Selected/Checked state - neon purple text -->
|
||||
<item android:state_checked="true" android:color="@color/md_theme_tertiary" />
|
||||
<!-- Default/Unselected state - neon blue text -->
|
||||
<item android:color="@color/brand_primary" />
|
||||
</selector>
|
||||
@@ -39,6 +39,29 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:layout_margin="12dp"/>
|
||||
|
||||
<!-- Pause/Play button in top right corner -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_pause_play"
|
||||
style="@style/PSX2.ElevatedTransparentButton"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:insetLeft="0dp"
|
||||
android:insetRight="0dp"
|
||||
android:insetTop="0dp"
|
||||
android:insetBottom="0dp"
|
||||
android:gravity="center"
|
||||
android:text=""
|
||||
app:icon="@drawable/play_circle_24px"
|
||||
app:iconTint="@color/brand_primary"
|
||||
app:iconGravity="textStart"
|
||||
app:iconSize="24dp"
|
||||
app:iconPadding="0dp"
|
||||
app:rippleColor="#80cdcdcd"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_margin="12dp"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<!-- Visibility toggle removed -->
|
||||
|
||||
<!-- Top center menu row -->
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.drawerlayout.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/dlg_drawer_layout"
|
||||
@@ -63,16 +63,7 @@
|
||||
app:iconPadding="8dp"
|
||||
app:iconSize="24dp" />
|
||||
</LinearLayout>
|
||||
<!-- Letters row above covers -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_letters"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="24dp"
|
||||
android:layout_marginTop="0dp"
|
||||
android:paddingStart="24dp"
|
||||
android:paddingEnd="24dp"
|
||||
android:clipToPadding="false"
|
||||
android:overScrollMode="never"/>
|
||||
<!-- Letters row removed -->
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_covers"
|
||||
@@ -137,3 +128,4 @@
|
||||
app:headerLayout="@layout/drawer_header_settings" />
|
||||
|
||||
</androidx.drawerlayout.widget.DrawerLayout>
|
||||
|
||||
|
||||
@@ -39,6 +39,29 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:layout_margin="12dp"/>
|
||||
|
||||
<!-- Pause/Play button in top right corner -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_pause_play"
|
||||
style="@style/PSX2.ElevatedTransparentButton"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:insetLeft="0dp"
|
||||
android:insetRight="0dp"
|
||||
android:insetTop="0dp"
|
||||
android:insetBottom="0dp"
|
||||
android:gravity="center"
|
||||
android:text=""
|
||||
app:icon="@drawable/play_circle_24px"
|
||||
app:iconTint="@color/brand_primary"
|
||||
app:iconGravity="textStart"
|
||||
app:iconSize="24dp"
|
||||
app:iconPadding="0dp"
|
||||
app:rippleColor="#80cdcdcd"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:layout_margin="12dp"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<!-- Visibility toggle removed -->
|
||||
|
||||
<LinearLayout
|
||||
|
||||
@@ -63,16 +63,7 @@
|
||||
app:iconPadding="8dp"
|
||||
app:iconSize="24dp" />
|
||||
</LinearLayout>
|
||||
<!-- Letters row above covers -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_letters"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginTop="0dp"
|
||||
android:paddingStart="24dp"
|
||||
android:paddingEnd="24dp"
|
||||
android:clipToPadding="false"
|
||||
android:overScrollMode="never"/>
|
||||
<!-- Letters row removed -->
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_covers"
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:src="@drawable/stadia_controller_24px"
|
||||
android:tint="?attr/colorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Controller Quick Actions"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="When using a controller, press Select + Start together to open the Quick Actions menu for easy access to settings and features."
|
||||
android:textSize="14sp"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:lineSpacingExtra="2dp"
|
||||
android:textColor="?android:attr/textColorSecondary" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:background="?attr/colorSurfaceVariant"
|
||||
android:padding="12dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SELECT"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:textColor="?attr/colorOnPrimary"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="+"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="START"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:textColor="?attr/colorOnPrimary"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/sw_dont_show_again"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Don't show this tip again"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -15,11 +15,13 @@
|
||||
<!-- Game Title -->
|
||||
<TextView
|
||||
android:id="@+id/tv_game_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Game Title"
|
||||
android:textStyle="bold"
|
||||
android:textSize="18sp"
|
||||
android:textColor="@android:color/white"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<!-- Subtitle -->
|
||||
@@ -28,7 +30,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Per-Game Settings (Long-press from game list)"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#666666"
|
||||
android:textColor="@color/md_theme_tertiaryFixedDim"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<!-- Game Serial/CRC -->
|
||||
@@ -38,7 +40,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Serial: SLUS-12345 | CRC: 12345678"
|
||||
android:textSize="12sp"
|
||||
android:textColor="#888888"
|
||||
android:textColor="@color/md_theme_tertiaryFixedDim"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<TextView
|
||||
@@ -46,7 +48,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="These settings will override global settings for this game only."
|
||||
android:textSize="14sp"
|
||||
android:textColor="#666666"
|
||||
android:textColor="@color/md_theme_tertiaryFixedDim"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
|
||||
@@ -58,13 +60,29 @@
|
||||
android:text="Graphics"
|
||||
android:textStyle="bold"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/brand_primary"
|
||||
android:paddingBottom="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Aspect Ratio"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/brand_primary"
|
||||
android:paddingBottom="4dp"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/sp_aspect_ratio"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Blending Accuracy"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/brand_primary"
|
||||
android:paddingBottom="4dp"/>
|
||||
|
||||
<Spinner
|
||||
@@ -78,6 +96,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Renderer"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/brand_primary"
|
||||
android:paddingBottom="4dp"/>
|
||||
|
||||
<Spinner
|
||||
@@ -91,6 +110,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Resolution"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/brand_primary"
|
||||
android:paddingBottom="4dp"/>
|
||||
|
||||
<Spinner
|
||||
@@ -106,6 +126,7 @@
|
||||
android:text="Game Patches"
|
||||
android:textStyle="bold"
|
||||
android:textSize="16sp"
|
||||
android:textColor="@color/brand_primary"
|
||||
android:paddingBottom="8dp"/>
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
@@ -113,6 +134,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Widescreen Patches"
|
||||
android:textColor="@android:color/white"
|
||||
style="@style/Widget.Material3.CompoundButton.MaterialSwitch"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
@@ -121,6 +143,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="No Interlacing Patches"
|
||||
android:textColor="@android:color/white"
|
||||
style="@style/Widget.Material3.CompoundButton.MaterialSwitch"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
@@ -139,6 +162,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Enable Cheats"
|
||||
android:textColor="@android:color/white"
|
||||
style="@style/Widget.Material3.CompoundButton.MaterialSwitch"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
@@ -148,6 +172,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Texture Packs"
|
||||
android:textSize="14sp"
|
||||
android:textColor="@color/brand_primary"
|
||||
android:paddingBottom="4dp"/>
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
@@ -155,6 +180,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Load Texture Replacements"
|
||||
android:textColor="@android:color/white"
|
||||
style="@style/Widget.Material3.CompoundButton.MaterialSwitch"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
@@ -163,6 +189,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Async Texture Loading"
|
||||
android:textColor="@android:color/white"
|
||||
style="@style/Widget.Material3.CompoundButton.MaterialSwitch"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
@@ -13,40 +18,41 @@
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:textColor="?android:attr/textColorPrimary" />
|
||||
android:textColor="@color/brand_primary" />
|
||||
|
||||
<!-- Row 1: Power + Reboot -->
|
||||
<!-- Row 1: Pause/Play + Power + Reboot (icons only, centered) -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/btn_quick_pause_play"
|
||||
style="?attr/floatingActionButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="Pause/Play"
|
||||
app:srcCompat="@drawable/play_pause_24px"
|
||||
android:layout_marginEnd="12dp" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/btn_quick_power"
|
||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||
android:layout_width="0dp"
|
||||
style="?attr/floatingActionButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Power"
|
||||
android:textAllCaps="false"
|
||||
android:drawableStart="@drawable/ic_power"
|
||||
android:drawablePadding="8dp" />
|
||||
android:contentDescription="Power"
|
||||
app:srcCompat="@drawable/ic_power"
|
||||
android:layout_marginEnd="12dp" />
|
||||
|
||||
<View
|
||||
android:layout_width="8dp"
|
||||
android:layout_height="0dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/btn_quick_reboot"
|
||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||
android:layout_width="0dp"
|
||||
style="?attr/floatingActionButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Reboot"
|
||||
android:textAllCaps="false"
|
||||
android:drawableStart="@drawable/ic_reboot"
|
||||
android:drawablePadding="8dp" />
|
||||
android:contentDescription="Reboot"
|
||||
app:srcCompat="@drawable/ic_reboot" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Row 2: Renderer toggle buttons -->
|
||||
@@ -109,8 +115,10 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="GAMES"
|
||||
android:textColor="@android:color/white"
|
||||
android:textAllCaps="true"
|
||||
android:drawableStart="@drawable/stadia_controller_24px"
|
||||
android:drawableTint="@color/brand_primary"
|
||||
android:drawablePadding="8dp" />
|
||||
|
||||
<View
|
||||
@@ -124,8 +132,10 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="SAVES"
|
||||
android:textColor="@android:color/white"
|
||||
android:textAllCaps="true"
|
||||
android:drawableStart="@drawable/save_24px"
|
||||
android:drawableTint="@color/brand_primary"
|
||||
android:drawablePadding="8dp" />
|
||||
</LinearLayout>
|
||||
|
||||
@@ -135,6 +145,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Aspect Ratio"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/brand_primary"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<Spinner
|
||||
@@ -149,6 +160,7 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Blending Accuracy"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/brand_primary"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<Spinner
|
||||
@@ -225,4 +237,7 @@
|
||||
android:text="Cancel"
|
||||
android:textAllCaps="false" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user