Merge 7eb0bb2170120e42bfd12984375109e466a0b08a into 6262ddafa63f8e82e92ab3e88f25a4dcc8f10335

This commit is contained in:
Kleidis 2025-03-09 15:34:51 +01:00 committed by GitHub
commit c07c20ce8a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 369 additions and 43 deletions

View File

@ -15,7 +15,15 @@ enum class BooleanSetting(
ALLOW_PLUGIN_LOADER("allow_plugin_loader", Settings.SECTION_SYSTEM, true), ALLOW_PLUGIN_LOADER("allow_plugin_loader", Settings.SECTION_SYSTEM, true),
SWAP_SCREEN("swap_screen", Settings.SECTION_LAYOUT, false), SWAP_SCREEN("swap_screen", Settings.SECTION_LAYOUT, false),
INSTANT_DEBUG_LOG("instant_debug_log", Settings.SECTION_DEBUG, false), INSTANT_DEBUG_LOG("instant_debug_log", Settings.SECTION_DEBUG, false),
CUSTOM_LAYOUT("custom_layout",Settings.SECTION_LAYOUT,false); CUSTOM_LAYOUT("custom_layout",Settings.SECTION_LAYOUT,false),
SHOW_FPS("show_fps", Settings.SECTION_LAYOUT, true),
SHOW_FRAMETIME("show_frame_time", Settings.SECTION_LAYOUT, false),
SHOW_SPEED("show_speed", Settings.SECTION_LAYOUT, false),
SHOW_APP_RAM_USAGE("show_app_ram_usage", Settings.SECTION_LAYOUT, false),
SHOW_SYSTEM_RAM_USAGE("show_system_ram_usage", Settings.SECTION_LAYOUT, false),
SHOW_BAT_TEMPERATURE("show_bat_temperature", Settings.SECTION_LAYOUT, false),
OVERLAY_BACKGROUND("overlay_background", Settings.SECTION_LAYOUT, false);
override var boolean: Boolean = defaultValue override var boolean: Boolean = defaultValue
@ -35,7 +43,7 @@ enum class BooleanSetting(
companion object { companion object {
private val NOT_RUNTIME_EDITABLE = listOf( private val NOT_RUNTIME_EDITABLE = listOf(
PLUGIN_LOADER, PLUGIN_LOADER,
ALLOW_PLUGIN_LOADER, ALLOW_PLUGIN_LOADER,
ASYNC_SHADERS ASYNC_SHADERS
) )

View File

@ -64,7 +64,8 @@ enum class IntSetting(
DELAY_RENDER_THREAD_US("delay_game_render_thread_us", Settings.SECTION_RENDERER, 0), DELAY_RENDER_THREAD_US("delay_game_render_thread_us", Settings.SECTION_RENDERER, 0),
USE_ARTIC_BASE_CONTROLLER("use_artic_base_controller", Settings.SECTION_CONTROLS, 0), USE_ARTIC_BASE_CONTROLLER("use_artic_base_controller", Settings.SECTION_CONTROLS, 0),
ORIENTATION_OPTION("screen_orientation", Settings.SECTION_LAYOUT, 2), ORIENTATION_OPTION("screen_orientation", Settings.SECTION_LAYOUT, 2),
DISABLE_RIGHT_EYE_RENDER("disable_right_eye_render", Settings.SECTION_RENDERER, 0); DISABLE_RIGHT_EYE_RENDER("disable_right_eye_render", Settings.SECTION_RENDERER, 0),
PERF_OVERLAY_POSITION("perf_overlay_position", Settings.SECTION_LAYOUT, 0);
override var int: Int = defaultValue override var int: Int = defaultValue
override val valueAsString: String override val valueAsString: String

View File

@ -111,6 +111,7 @@ class Settings {
const val SECTION_THEME = "Theme" const val SECTION_THEME = "Theme"
const val SECTION_CUSTOM_LANDSCAPE = "Custom Landscape Layout" const val SECTION_CUSTOM_LANDSCAPE = "Custom Landscape Layout"
const val SECTION_CUSTOM_PORTRAIT = "Custom Portrait Layout" const val SECTION_CUSTOM_PORTRAIT = "Custom Portrait Layout"
const val SECTION_STATS_OVERLAY = "Stats Overlay"
const val KEY_BUTTON_A = "button_a" const val KEY_BUTTON_A = "button_a"
const val KEY_BUTTON_B = "button_b" const val KEY_BUTTON_B = "button_b"

View File

@ -46,6 +46,7 @@ import org.citra.citra_emu.utils.BirthdayMonth
import org.citra.citra_emu.utils.Log import org.citra.citra_emu.utils.Log
import org.citra.citra_emu.utils.SystemSaveGame import org.citra.citra_emu.utils.SystemSaveGame
import org.citra.citra_emu.utils.ThemeUtil import org.citra.citra_emu.utils.ThemeUtil
import org.citra.citra_emu.utils.EmulationMenuSettings
class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) { class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) {
private var menuTag: String? = null private var menuTag: String? = null
@ -101,6 +102,7 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
Settings.SECTION_THEME -> addThemeSettings(sl) Settings.SECTION_THEME -> addThemeSettings(sl)
Settings.SECTION_CUSTOM_LANDSCAPE -> addCustomLandscapeSettings(sl) Settings.SECTION_CUSTOM_LANDSCAPE -> addCustomLandscapeSettings(sl)
Settings.SECTION_CUSTOM_PORTRAIT -> addCustomPortraitSettings(sl) Settings.SECTION_CUSTOM_PORTRAIT -> addCustomPortraitSettings(sl)
Settings.SECTION_STATS_OVERLAY -> addStatsOverlaySettings(sl)
else -> { else -> {
fragmentView.showToastMessage("Unimplemented menu", false) fragmentView.showToastMessage("Unimplemented menu", false)
return return
@ -985,6 +987,14 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
FloatSetting.LARGE_SCREEN_PROPORTION.defaultValue FloatSetting.LARGE_SCREEN_PROPORTION.defaultValue
) )
) )
add(
SubmenuSetting(
R.string.stats_overlay_options,
R.string.stats_overlay_options_description,
R.drawable.ic_frames,
Settings.SECTION_STATS_OVERLAY
)
)
add( add(
SubmenuSetting( SubmenuSetting(
R.string.emulation_landscape_custom_layout, R.string.emulation_landscape_custom_layout,
@ -1004,6 +1014,116 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView)
} }
} }
private fun addStatsOverlaySettings(sl: ArrayList<SettingsItem>) {
settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.stats_overlay_options))
sl.apply {
add(HeaderSetting(R.string.stats_overlay_customization))
add(
SwitchSetting(
object : AbstractBooleanSetting {
override val key = "EmulationMenuSettings_showPerfStatsOvelray"
override val section = Settings.SECTION_LAYOUT
override val defaultValue = false
override var boolean: Boolean
get() = EmulationMenuSettings.showStatsOvelray
set(value) { EmulationMenuSettings.showStatsOvelray = value }
override val isRuntimeEditable = true
override val valueAsString: String get() = boolean.toString()
},
R.string.enable_stats_overlay_,
0,
"EmulationMenuSettings_showPerfStatsOvelray",
false
)
)
add(
SwitchSetting(
BooleanSetting.OVERLAY_BACKGROUND,
R.string.overlay_background,
R.string.overlay_background_description,
"overlay_background",
false
)
)
add(
SingleChoiceSetting(
IntSetting.PERF_OVERLAY_POSITION,
R.string.overlay_position,
R.string.overlay_position_description,
R.array.statsPosition,
R.array.statsPositionValues,
)
)
add(HeaderSetting(R.string.stats_overlay_items))
add(
SwitchSetting(
BooleanSetting.SHOW_FPS,
R.string.show_fps,
R.string.show_fps_description,
"show_fps",
true
)
)
add(
SwitchSetting(
BooleanSetting.SHOW_FRAMETIME,
R.string.show_frametime,
R.string.show_frametime_description,
"show_frame_time",
true
)
)
add(
SwitchSetting(
BooleanSetting.SHOW_SPEED,
R.string.show_speed,
R.string.show_speed_description,
"show_speed",
false
)
)
add(
SwitchSetting(
BooleanSetting.SHOW_APP_RAM_USAGE,
R.string.show_app_ram_usage,
R.string.show_app_ram_usage_description,
"show_app_ram_usage",
false
)
)
add(
SwitchSetting(
BooleanSetting.SHOW_SYSTEM_RAM_USAGE,
R.string.show_system_ram_usage,
R.string.show_system_ram_usage_description,
"show_system_ram_usage",
false
)
)
add(
SwitchSetting(
BooleanSetting.SHOW_BAT_TEMPERATURE,
R.string.show_bat_temperature,
R.string.show_bat_temperature_description,
"show_bat_temperature",
false
)
)
}
}
private fun addCustomLandscapeSettings(sl: ArrayList<SettingsItem>) { private fun addCustomLandscapeSettings(sl: ArrayList<SettingsItem>) {
settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.emulation_landscape_custom_layout)) settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.emulation_landscape_custom_layout))
sl.apply { sl.apply {

View File

@ -5,10 +5,14 @@
package org.citra.citra_emu.fragments package org.citra.citra_emu.fragments
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.app.ActivityManager
import android.content.Context import android.content.Context
import android.content.DialogInterface import android.content.DialogInterface
import android.content.Intent
import android.content.IntentFilter
import android.content.SharedPreferences import android.content.SharedPreferences
import android.net.Uri import android.net.Uri
import android.os.BatteryManager
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
@ -16,6 +20,7 @@ import android.os.SystemClock
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.view.Choreographer import android.view.Choreographer
import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MotionEvent import android.view.MotionEvent
import android.view.Surface import android.view.Surface
@ -26,6 +31,7 @@ import android.widget.PopupMenu
import android.widget.TextView import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.activity.OnBackPressedCallback import androidx.activity.OnBackPressedCallback
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.Insets import androidx.core.graphics.Insets
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
@ -71,6 +77,8 @@ import org.citra.citra_emu.utils.EmulationLifecycleUtil
import org.citra.citra_emu.utils.Log import org.citra.citra_emu.utils.Log
import org.citra.citra_emu.utils.ViewUtils import org.citra.citra_emu.utils.ViewUtils
import org.citra.citra_emu.viewmodel.EmulationViewModel import org.citra.citra_emu.viewmodel.EmulationViewModel
import org.citra.citra_emu.features.settings.model.BooleanSetting
import java.io.File
class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.FrameCallback { class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.FrameCallback {
private val preferences: SharedPreferences private val preferences: SharedPreferences
@ -174,8 +182,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
binding.surfaceInputOverlay.setIsInEditMode(false) binding.surfaceInputOverlay.setIsInEditMode(false)
} }
// Show/hide the "Show FPS" overlay
updateShowFpsOverlay() // Show/hide the "Stats" overlay
updateshowStatsOvelray()
val position = IntSetting.PERF_OVERLAY_POSITION.int
updateStatsPosition(position)
binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED) binding.drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
binding.drawerLayout.addDrawerListener(object : DrawerListener { binding.drawerLayout.addDrawerListener(object : DrawerListener {
@ -447,6 +459,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
Choreographer.getInstance().postFrameCallback(this) Choreographer.getInstance().postFrameCallback(this)
if (NativeLibrary.isRunning()) { if (NativeLibrary.isRunning()) {
NativeLibrary.unPauseEmulation() NativeLibrary.unPauseEmulation()
// If the overlay is enabled, we need to update the position if changed
val position = IntSetting.PERF_OVERLAY_POSITION.int
updateStatsPosition(position)
return return
} }
@ -624,7 +639,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
popupMenu.menu.apply { popupMenu.menu.apply {
findItem(R.id.menu_show_overlay).isChecked = EmulationMenuSettings.showOverlay findItem(R.id.menu_show_overlay).isChecked = EmulationMenuSettings.showOverlay
findItem(R.id.menu_show_fps).isChecked = EmulationMenuSettings.showFps findItem(R.id.menu_show_stats_overlay).isChecked =
EmulationMenuSettings.showStatsOvelray
findItem(R.id.menu_haptic_feedback).isChecked = EmulationMenuSettings.hapticFeedback findItem(R.id.menu_haptic_feedback).isChecked = EmulationMenuSettings.hapticFeedback
findItem(R.id.menu_emulation_joystick_rel_center).isChecked = findItem(R.id.menu_emulation_joystick_rel_center).isChecked =
EmulationMenuSettings.joystickRelCenter EmulationMenuSettings.joystickRelCenter
@ -640,15 +656,15 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
true true
} }
R.id.menu_show_fps -> { R.id.menu_show_stats_overlay -> {
EmulationMenuSettings.showFps = !EmulationMenuSettings.showFps EmulationMenuSettings.showStatsOvelray = !EmulationMenuSettings.showStatsOvelray
updateShowFpsOverlay() updateshowStatsOvelray()
true true
} }
R.id.menu_haptic_feedback -> { R.id.menu_haptic_feedback -> {
EmulationMenuSettings.hapticFeedback = !EmulationMenuSettings.hapticFeedback EmulationMenuSettings.hapticFeedback = !EmulationMenuSettings.hapticFeedback
updateShowFpsOverlay() updateshowStatsOvelray()
true true
} }
@ -1128,34 +1144,141 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
binding.surfaceInputOverlay.resetButtonPlacement() binding.surfaceInputOverlay.resetButtonPlacement()
} }
fun updateShowFpsOverlay() { fun updateshowStatsOvelray() {
if (EmulationMenuSettings.showFps) { if (EmulationMenuSettings.showStatsOvelray) {
val SYSTEM_FPS = 0 val SYSTEM_FPS = 0
val FPS = 1 val FPS = 1
val FRAMETIME = 2 val FRAMETIME = 2
val SPEED = 3 val SPEED = 3
perfStatsUpdater = Runnable { perfStatsUpdater = Runnable {
val sb = StringBuilder()
val perfStats = NativeLibrary.getPerfStats() val perfStats = NativeLibrary.getPerfStats()
val ramUsage =
File("/proc/self/statm").readLines()[0].split(' ')[1].toLong() * 4096 / 1000000
val ramUsageText = "RAM USAGE: " + ramUsage + " MB"
if (perfStats[FPS] > 0) { if (perfStats[FPS] > 0) {
binding.showFpsText.text = String.format( if (BooleanSetting.SHOW_FPS.boolean) {
"FPS: %d Speed: %d%% FT: %.2fms", sb.append(String.format("FPS: %d", (perfStats[FPS] + 0.5).toInt()))
(perfStats[FPS] + 0.5).toInt(), }
(perfStats[SPEED] * 100.0 + 0.5).toInt(),
(perfStats[FRAMETIME] * 1000.0f).toFloat() if (BooleanSetting.SHOW_FRAMETIME.boolean) {
) if (sb.isNotEmpty()) sb.append(" | ")
sb.append(
String.format(
"FT: %.1fms",
(perfStats[FRAMETIME] * 1000.0f).toFloat()
)
)
}
if (BooleanSetting.SHOW_SPEED.boolean) {
if (sb.isNotEmpty()) sb.append(" | ")
sb.append(
String.format(
"Speed: %d%%",
(perfStats[SPEED] * 100.0 + 0.5).toInt()
)
)
}
if (BooleanSetting.SHOW_APP_RAM_USAGE.boolean) {
if (sb.isNotEmpty()) sb.append(" | ")
val appRamUsage =
File("/proc/self/statm").readLines()[0].split(' ')[1].toLong() * 4096 / 1000000
sb.append("Process RAM: $appRamUsage MB")
}
if (BooleanSetting.SHOW_SYSTEM_RAM_USAGE.boolean) {
if (sb.isNotEmpty()) sb.append(" | ")
context?.let { ctx ->
val activityManager =
ctx.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val memInfo = ActivityManager.MemoryInfo()
activityManager.getMemoryInfo(memInfo)
val usedRamMB = (memInfo.totalMem - memInfo.availMem) / 1048576L
sb.append("RAM: $usedRamMB MB")
}
}
if (BooleanSetting.SHOW_BAT_TEMPERATURE.boolean) {
if (sb.isNotEmpty()) sb.append(" | ")
val batteryTemp = getBatteryTemperature()
val tempF = celsiusToFahrenheit(batteryTemp)
sb.append(String.format("%.1f°C/%.1f°F", batteryTemp, tempF))
}
if (BooleanSetting.OVERLAY_BACKGROUND.boolean) {
binding.showStatsOverlayText.setBackgroundResource(R.color.citra_transparent_black)
} else {
binding.showStatsOverlayText.setBackgroundResource(0)
}
binding.showStatsOverlayText.text = sb.toString()
} }
perfStatsUpdateHandler.postDelayed(perfStatsUpdater!!, 3000) perfStatsUpdateHandler.postDelayed(perfStatsUpdater!!, 3000)
} }
perfStatsUpdateHandler.post(perfStatsUpdater!!) perfStatsUpdateHandler.post(perfStatsUpdater!!)
binding.showFpsText.visibility = View.VISIBLE binding.showStatsOverlayText.visibility = View.VISIBLE
} else { } else {
if (perfStatsUpdater != null) { if (perfStatsUpdater != null) {
perfStatsUpdateHandler.removeCallbacks(perfStatsUpdater!!) perfStatsUpdateHandler.removeCallbacks(perfStatsUpdater!!)
} }
binding.showFpsText.visibility = View.GONE binding.showStatsOverlayText.visibility = View.GONE
} }
} }
private fun updateStatsPosition(position: Int) {
val params = binding.showStatsOverlayText.layoutParams as CoordinatorLayout.LayoutParams
when (position) {
0 -> {
params.gravity = (Gravity.TOP or Gravity.START)
params.setMargins(resources.getDimensionPixelSize(R.dimen.spacing_large), 0, 0, 0)
}
1 -> {
params.gravity = (Gravity.TOP or Gravity.CENTER_HORIZONTAL)
}
2 -> {
params.gravity = (Gravity.TOP or Gravity.END)
params.setMargins(0, 0, resources.getDimensionPixelSize(R.dimen.spacing_large), 0)
}
3 -> {
params.gravity = (Gravity.BOTTOM or Gravity.START)
params.setMargins(resources.getDimensionPixelSize(R.dimen.spacing_large), 0, 0, 0)
}
4 -> {
params.gravity = (Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL)
}
5 -> {
params.gravity = (Gravity.BOTTOM or Gravity.END)
params.setMargins(0, 0, resources.getDimensionPixelSize(R.dimen.spacing_large), 0)
}
}
binding.showStatsOverlayText.layoutParams = params
}
private fun getBatteryTemperature(): Float {
try {
val batteryIntent = requireContext().registerReceiver(null, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
// Temperature in tenths of a degree Celsius
val temperature = batteryIntent?.getIntExtra(BatteryManager.EXTRA_TEMPERATURE, 0) ?: 0
// Convert to degrees Celsius
return temperature / 10.0f
} catch (e: Exception) {
return 0.0f
}
}
private fun celsiusToFahrenheit(celsius: Float): Float {
return (celsius * 9 / 5) + 32
}
override fun surfaceCreated(holder: SurfaceHolder) { override fun surfaceCreated(holder: SurfaceHolder) {
// We purposely don't do anything here. // We purposely don't do anything here.
// All work is done in surfaceChanged, which we are guaranteed to get even for surface creation. // All work is done in surfaceChanged, which we are guaranteed to get even for surface creation.
@ -1190,23 +1313,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram
v.setPadding(left, cutInsets.top, right, 0) v.setPadding(left, cutInsets.top, right, 0)
// Ensure FPS text doesn't get cut off by rounded display corners
val sidePadding = resources.getDimensionPixelSize(R.dimen.spacing_large)
if (cutInsets.left == 0) {
binding.showFpsText.setPadding(
sidePadding,
cutInsets.top,
cutInsets.right,
cutInsets.bottom
)
} else {
binding.showFpsText.setPadding(
cutInsets.left,
cutInsets.top,
cutInsets.right,
cutInsets.bottom
)
}
windowInsets windowInsets
} }
} }

View File

@ -27,11 +27,11 @@ object EmulationMenuSettings {
.apply() .apply()
} }
var showFps: Boolean var showStatsOvelray: Boolean
get() = preferences.getBoolean("EmulationMenuSettings_ShowFps", false) get() = preferences.getBoolean("EmulationMenuSettings_showStatsOvelray", false)
set(value) { set(value) {
preferences.edit() preferences.edit()
.putBoolean("EmulationMenuSettings_ShowFps", value) .putBoolean("EmulationMenuSettings_showStatsOvelray", value)
.apply() .apply()
} }
var hapticFeedback: Boolean var hapticFeedback: Boolean

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#00000000"
android:strokeColor="#FF000000"
android:strokeWidth="1"
android:pathData="M4,4 L4,20 L20,20" />
<path
android:fillColor="#00000000"
android:strokeColor="#FF000000"
android:strokeWidth="2"
android:pathData="M4,16 L8,12 L12,14 L16,8 L20,10" />
<path
android:fillColor="#FF000000"
android:pathData="M4,16 C3.45,16 3,15.55 3,15 C3,14.45 3.45,14 4,14 C4.55,14 5,14.45 5,15 C5,15.55 4.55,16 4,16" />
<path
android:fillColor="#FF000000"
android:pathData="M8,12 C7.45,12 7,11.55 7,11 C7,10.45 7.45,10 8,10 C8.55,10 9,10.45 9,11 C9,11.55 8.55,12 8,12" />
<path
android:fillColor="#FF000000"
android:pathData="M12,14 C11.45,14 11,13.55 11,13 C11,12.45 11.45,12 12,12 C12.55,12 13,12.45 13,13 C13,13.55 12.55,14 12,14" />
<path
android:fillColor="#FF000000"
android:pathData="M16,8 C15.45,8 15,7.55 15,7 C15,6.45 15.45,6 16,6 C16.55,6 17,6.45 17,7 C17,7.55 16.55,8 16,8" />
<path
android:fillColor="#FF000000"
android:pathData="M20,10 C19.45,10 19,9.55 19,9 C19,8.45 19.45,8 20,8 C20.55,8 21,8.45 21,9 C21,9.55 20.55,10 20,10" />
</vector>

View File

@ -117,7 +117,7 @@
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>
<TextView <TextView
android:id="@+id/show_fps_text" android:id="@+id/show_stats_overlay_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="left" android:layout_gravity="left"

View File

@ -7,8 +7,8 @@
android:checkable="true" /> android:checkable="true" />
<item <item
android:id="@+id/menu_show_fps" android:id="@+id/menu_show_stats_overlay"
android:title="@string/emulation_show_fps" android:title="@string/show_stats_overlay"
android:checkable="true" /> android:checkable="true" />
<item <item

View File

@ -227,6 +227,7 @@
<color name="citra_surfaceTint_gray">#B7B7B7</color> <color name="citra_surfaceTint_gray">#B7B7B7</color>
<!-- Common Colors Across All Themes --> <!-- Common Colors Across All Themes -->
<color name="citra_transparent_black">#80000000</color>
<color name="citra_outlineVariant">#C6C5D0</color> <color name="citra_outlineVariant">#C6C5D0</color>
<color name="citra_error">#FFB4AB</color> <color name="citra_error">#FFB4AB</color>
<color name="citra_errorContainer">#93000A</color> <color name="citra_errorContainer">#93000A</color>

View File

@ -113,6 +113,23 @@
<item>11</item> <item>11</item>
</integer-array> </integer-array>
<string-array name="statsPosition">
<item>@string/overlay_position_top_left</item>
<item>@string/overlay_position_center_top</item>
<item>@string/overlay_position_top_right</item>
<item>@string/overlay_position_bottom_left</item>
<item>@string/overlay_position_center_bottom</item>
<item>@string/overlay_position_bottom_right</item>
</string-array>
<integer-array name="statsPositionValues">
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
<item>4</item>
<item>5</item>
</integer-array>
<string-array name="n3dsButtons"> <string-array name="n3dsButtons">
<item>@string/button_a</item> <item>@string/button_a</item>
<item>@string/button_b</item> <item>@string/button_b</item>

View File

@ -222,6 +222,7 @@
<color name="citra_surfaceTint_gray">#9E9E9E</color> <color name="citra_surfaceTint_gray">#9E9E9E</color>
<!-- Common Colors Across All Themes --> <!-- Common Colors Across All Themes -->
<color name="citra_transparent_black">#80000000</color>
<color name="citra_outlineVariant">#C6C5D0</color> <color name="citra_outlineVariant">#C6C5D0</color>
<color name="citra_error">#BA1A1A</color> <color name="citra_error">#BA1A1A</color>
<color name="citra_errorContainer">#FFDAD6</color> <color name="citra_errorContainer">#FFDAD6</color>

View File

@ -478,6 +478,36 @@
<string name="play">Play</string> <string name="play">Play</string>
<string name="shortcut">Shortcut</string> <string name="shortcut">Shortcut</string>
<!-- Stats Overlay settings -->
<string name="show_stats_overlay">ShoW Performance Stats Overlay</string>
<string name="stats_overlay_customization">Customization</string>
<string name="stats_overlay_items">Visibility</string>
<string name="stats_overlay_options">Performance Stats Overlay</string>
<string name="enable_stats_overlay_">Enable Performance Stats Overlay</string>
<string name="stats_overlay_options_description">Configure what information is shown in the performance stats overlay</string>
<string name="show_fps">Show FPS</string>
<string name="show_fps_description">Display current frames per second</string>
<string name="show_frametime">Show Frametime</string>
<string name="show_frametime_description">Display current frametime</string>
<string name="show_speed">Show Speed</string>
<string name="show_speed_description">Display current emulation speed percentage</string>
<string name="show_app_ram_usage">Show App Memory Usage</string>
<string name="show_app_ram_usage_description">Display the amount of RAM getting used by the emulator</string>
<string name="show_system_ram_usage">Show System Memory Usage</string>
<string name="show_system_ram_usage_description">Display the amount of RAM getting used by the system</string>
<string name="show_bat_temperature">Show Battery Temperature</string>
<string name="show_bat_temperature_description">Display current Battery temperature in Celsius and Fahrenheit</string>
<string name="overlay_position">Overlay Position</string>
<string name="overlay_position_description">Choose where the performance stats overlay is displayed on the screen</string>
<string name="overlay_position_top_left">Top Left</string>
<string name="overlay_position_top_right">Top Right</string>
<string name="overlay_position_bottom_left">Bottom Left</string>
<string name="overlay_position_bottom_right">Bottom Right</string>
<string name="overlay_position_center_top">Center Top</string>
<string name="overlay_position_center_bottom">Center Bottom</string>
<string name="overlay_background">Overlay Background</string>
<string name="overlay_background_description">Adds a background behind the overlay for easier reading</string>
<!-- Cheats --> <!-- Cheats -->
<string name="cheats">Cheats</string> <string name="cheats">Cheats</string>
<string name="cheats_add">Add Cheat</string> <string name="cheats_add">Add Cheat</string>

View File

@ -191,6 +191,15 @@ filter_mode =
# 6: Custom Layout # 6: Custom Layout
layout_option = layout_option =
# Position of the performance overlay
# 0: Top Left
# 1: Center Top
# 2: Top Right
# 3: Bottom Left
# 4: Center Bottom
# 5: Bottom Right
perf_overlay_position =
# Screen placement when using Custom layout option # Screen placement when using Custom layout option
# 0x, 0y is the top left corner of the render window. # 0x, 0y is the top left corner of the render window.
custom_top_x = custom_top_x =