mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-01 03:15:10 +01:00
Implement fixed aspect ratio surface
Adds a setting to letterbox the surface with black bars to 16:9 or 21:9 aspect ratio to avoid stretching out the rendered image
This commit is contained in:
parent
6cf9bc5729
commit
0ceecbba4f
@ -12,6 +12,7 @@ import android.content.res.AssetManager
|
|||||||
import android.graphics.PointF
|
import android.graphics.PointF
|
||||||
import android.os.*
|
import android.os.*
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import android.util.Rational
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
@ -221,9 +222,6 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
|||||||
returnFromEmulation()
|
returnFromEmulation()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This makes the window fullscreen, sets up the performance statistics and finally calls [executeApplication] for executing the application
|
|
||||||
*/
|
|
||||||
@SuppressLint("SetTextI18n", "ClickableViewAccessibility")
|
@SuppressLint("SetTextI18n", "ClickableViewAccessibility")
|
||||||
override fun onCreate(savedInstanceState : Bundle?) {
|
override fun onCreate(savedInstanceState : Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@ -237,6 +235,14 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
|||||||
|
|
||||||
binding.gameView.holder.addCallback(this)
|
binding.gameView.holder.addCallback(this)
|
||||||
|
|
||||||
|
binding.gameView.setAspectRatio(
|
||||||
|
when (settings.aspectRatio) {
|
||||||
|
0 -> Rational(16, 9)
|
||||||
|
1 -> Rational(21, 9)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
if (settings.perfStats) {
|
if (settings.perfStats) {
|
||||||
binding.perfStats.apply {
|
binding.perfStats.apply {
|
||||||
postDelayed(object : Runnable {
|
postDelayed(object : Runnable {
|
||||||
|
@ -38,5 +38,7 @@ class Settings @Inject constructor(@ApplicationContext private val context : Con
|
|||||||
|
|
||||||
var maxRefreshRate by sharedPreferences(context, false)
|
var maxRefreshRate by sharedPreferences(context, false)
|
||||||
|
|
||||||
|
var aspectRatio by sharedPreferences(context, 0)
|
||||||
|
|
||||||
var systemLanguage by sharedPreferences(context, 1)
|
var systemLanguage by sharedPreferences(context, 1)
|
||||||
}
|
}
|
||||||
|
39
app/src/main/java/emu/skyline/views/FixedRatioSurfaceView.kt
Normal file
39
app/src/main/java/emu/skyline/views/FixedRatioSurfaceView.kt
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package emu.skyline.views
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.util.Rational
|
||||||
|
import android.view.SurfaceView
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
class FixedRatioSurfaceView @JvmOverloads constructor(context : Context, attrs : AttributeSet? = null, defStyleAttr : Int = 0) : SurfaceView(context, attrs, defStyleAttr) {
|
||||||
|
private var aspectRatio : Float = 0f // (width / height), 0f is a special value for stretch
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the desired aspect ratio for this view
|
||||||
|
* @param ratio the ratio to force the view to, or null to stretch to fit
|
||||||
|
*/
|
||||||
|
fun setAspectRatio(ratio : Rational?) {
|
||||||
|
aspectRatio = ratio?.toFloat() ?: 0f
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMeasure(widthMeasureSpec : Int, heightMeasureSpec : Int) {
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
|
||||||
|
val width = MeasureSpec.getSize(widthMeasureSpec)
|
||||||
|
val height = MeasureSpec.getSize(heightMeasureSpec)
|
||||||
|
if (aspectRatio != 0f) {
|
||||||
|
val newWidth : Int
|
||||||
|
val newHeight : Int
|
||||||
|
if (height * aspectRatio < width) {
|
||||||
|
newWidth = (height * aspectRatio).roundToInt()
|
||||||
|
newHeight = height
|
||||||
|
} else {
|
||||||
|
newWidth = width
|
||||||
|
newHeight = (width / aspectRatio).roundToInt()
|
||||||
|
}
|
||||||
|
setMeasuredDimension(newWidth, newHeight)
|
||||||
|
} else {
|
||||||
|
setMeasuredDimension(width, height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,39 +1,39 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:keepScreenOn="true"
|
||||||
|
android:background="@android:color/black"
|
||||||
|
tools:context=".EmulationActivity">
|
||||||
|
|
||||||
|
<emu.skyline.views.FixedRatioSurfaceView
|
||||||
|
android:id="@+id/game_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:keepScreenOn="true"
|
android:layout_gravity="center" />
|
||||||
tools:background="@android:color/black"
|
|
||||||
tools:context=".EmulationActivity">
|
|
||||||
|
|
||||||
<SurfaceView
|
|
||||||
android:id="@+id/game_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:visibility="invisible" />
|
|
||||||
|
|
||||||
<emu.skyline.input.onscreen.OnScreenControllerView
|
<emu.skyline.input.onscreen.OnScreenControllerView
|
||||||
android:id="@+id/on_screen_controller_view"
|
android:id="@+id/on_screen_controller_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent" />
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/perf_stats"
|
android:id="@+id/perf_stats"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="5dp"
|
||||||
android:layout_marginTop="5dp"
|
android:layout_marginTop="5dp"
|
||||||
android:textColor="#9fffff00" />
|
android:textColor="#9fffff00" />
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/on_screen_controller_toggle"
|
android:id="@+id/on_screen_controller_toggle"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_gravity="bottom|end"
|
android:layout_gravity="bottom|end"
|
||||||
android:background="?attr/selectableItemBackgroundBorderless"
|
android:background="?attr/selectableItemBackgroundBorderless"
|
||||||
android:src="@drawable/ic_show"
|
android:src="@drawable/ic_show"
|
||||||
app:tint="#40FFFFFF"
|
app:tint="#40FFFFFF"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
@ -74,4 +74,9 @@
|
|||||||
<item>7</item>
|
<item>7</item>
|
||||||
<item>11</item>
|
<item>11</item>
|
||||||
</integer-array>
|
</integer-array>
|
||||||
|
<string-array name="aspect_ratios">
|
||||||
|
<item>16:9 (Switch, Recommended)</item>
|
||||||
|
<item>21:9 (Ultrawide Mods)</item>
|
||||||
|
<item>Device Aspect Ratio (Stretch to fit)</item>
|
||||||
|
</string-array>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
<string name="max_refresh_rate">Use Maximum Display Refresh Rate</string>
|
<string name="max_refresh_rate">Use Maximum Display Refresh Rate</string>
|
||||||
<string name="max_refresh_rate_enabled">Sets the display refresh rate as high as possible (Will break most games)</string>
|
<string name="max_refresh_rate_enabled">Sets the display refresh rate as high as possible (Will break most games)</string>
|
||||||
<string name="max_refresh_rate_disabled">Sets the display refresh rate to 60Hz</string>
|
<string name="max_refresh_rate_disabled">Sets the display refresh rate to 60Hz</string>
|
||||||
|
<string name="aspect_ratio">Aspect Ratio</string>
|
||||||
<!-- Input -->
|
<!-- Input -->
|
||||||
<string name="input">Input</string>
|
<string name="input">Input</string>
|
||||||
<string name="osc">On-Screen Controls</string>
|
<string name="osc">On-Screen Controls</string>
|
||||||
|
@ -103,6 +103,12 @@
|
|||||||
android:summaryOn="@string/max_refresh_rate_enabled"
|
android:summaryOn="@string/max_refresh_rate_enabled"
|
||||||
app:key="max_refresh_rate"
|
app:key="max_refresh_rate"
|
||||||
app:title="@string/max_refresh_rate" />
|
app:title="@string/max_refresh_rate" />
|
||||||
|
<emu.skyline.preference.IntegerListPreference
|
||||||
|
android:defaultValue="0"
|
||||||
|
android:entries="@array/aspect_ratios"
|
||||||
|
app:key="aspect_ratio"
|
||||||
|
app:title="@string/aspect_ratio"
|
||||||
|
app:useSimpleSummaryProvider="true" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="category_input"
|
android:key="category_input"
|
||||||
|
Loading…
Reference in New Issue
Block a user