android: Enable automated portrait controls

This commit is contained in:
Abandoned Cart 2023-06-11 19:37:55 -04:00
parent de9100ea81
commit 0ef93541b4
2 changed files with 40 additions and 81 deletions

View file

@ -10,6 +10,7 @@ import android.content.DialogInterface
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.content.res.Resources import android.content.res.Resources
import android.graphics.Color import android.graphics.Color
import android.os.Bundle import android.os.Bundle
@ -192,6 +193,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
} }
} }
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
if (!binding.surfaceInputOverlay.isInEditMode()) refreshInputOverlay()
}
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
if (!DirectoryInitialization.areDirectoriesReady) { if (!DirectoryInitialization.areDirectoriesReady) {

View file

@ -7,7 +7,6 @@ import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.res.Configuration
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.Point import android.graphics.Point
@ -77,25 +76,6 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
requestFocus() requestFocus()
} }
@SuppressLint("DrawAllocation")
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
val width = MeasureSpec.getSize(widthMeasureSpec)
val height = MeasureSpec.getSize(heightMeasureSpec)
if (height > width) {
val aspectRatio = with (context.getSystemService(Context.WINDOW_SERVICE) as WindowManager) {
val metrics = maximumWindowMetrics.bounds
Rational(metrics.height(), metrics.width()).toFloat()
}
val newWidth: Int = width
val newHeight: Int = (width / aspectRatio).roundToInt()
setMeasuredDimension(newWidth, newHeight)
invalidate()
} else {
setMeasuredDimension(width, height)
}
}
override fun draw(canvas: Canvas) { override fun draw(canvas: Canvas) {
super.draw(canvas) super.draw(canvas)
for (button in overlayButtons) { for (button in overlayButtons) {
@ -256,10 +236,6 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
val fingerPositionX = event.getX(pointerIndex).toInt() val fingerPositionX = event.getX(pointerIndex).toInt()
val fingerPositionY = event.getY(pointerIndex).toInt() val fingerPositionY = event.getY(pointerIndex).toInt()
// TODO: Provide support for portrait layout
//val orientation =
// if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) "-Portrait" else ""
for (button in overlayButtons) { for (button in overlayButtons) {
// Determine the button state to apply based on the MotionEvent action flag. // Determine the button state to apply based on the MotionEvent action flag.
when (event.action and MotionEvent.ACTION_MASK) { when (event.action and MotionEvent.ACTION_MASK) {
@ -288,8 +264,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
saveControlPosition( saveControlPosition(
buttonBeingConfigured!!.buttonId, buttonBeingConfigured!!.buttonId,
buttonBeingConfigured!!.bounds.centerX(), buttonBeingConfigured!!.bounds.centerX(),
buttonBeingConfigured!!.bounds.centerY(), buttonBeingConfigured!!.bounds.centerY()
""
) )
buttonBeingConfigured = null buttonBeingConfigured = null
} }
@ -321,8 +296,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
saveControlPosition( saveControlPosition(
dpadBeingConfigured!!.upId, dpadBeingConfigured!!.upId,
dpadBeingConfigured!!.bounds.centerX(), dpadBeingConfigured!!.bounds.centerX(),
dpadBeingConfigured!!.bounds.centerY(), dpadBeingConfigured!!.bounds.centerY()
""
) )
dpadBeingConfigured = null dpadBeingConfigured = null
} }
@ -352,8 +326,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
saveControlPosition( saveControlPosition(
joystickBeingConfigured!!.buttonId, joystickBeingConfigured!!.buttonId,
joystickBeingConfigured!!.bounds.centerX(), joystickBeingConfigured!!.bounds.centerX(),
joystickBeingConfigured!!.bounds.centerY(), joystickBeingConfigured!!.bounds.centerY()
""
) )
joystickBeingConfigured = null joystickBeingConfigured = null
} }
@ -363,7 +336,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
return true return true
} }
private fun addOverlayControls(orientation: String) { private fun addOverlayControls() {
val windowSize = getSafeScreenSize(context) val windowSize = getSafeScreenSize(context)
if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_0, true)) { if (preferences.getBoolean(Settings.PREF_BUTTON_TOGGLE_0, true)) {
overlayButtons.add( overlayButtons.add(
@ -372,8 +345,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
windowSize, windowSize,
R.drawable.facebutton_a, R.drawable.facebutton_a,
R.drawable.facebutton_a_depressed, R.drawable.facebutton_a_depressed,
ButtonType.BUTTON_A, ButtonType.BUTTON_A
orientation
) )
) )
} }
@ -384,8 +356,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
windowSize, windowSize,
R.drawable.facebutton_b, R.drawable.facebutton_b,
R.drawable.facebutton_b_depressed, R.drawable.facebutton_b_depressed,
ButtonType.BUTTON_B, ButtonType.BUTTON_B
orientation
) )
) )
} }
@ -396,8 +367,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
windowSize, windowSize,
R.drawable.facebutton_x, R.drawable.facebutton_x,
R.drawable.facebutton_x_depressed, R.drawable.facebutton_x_depressed,
ButtonType.BUTTON_X, ButtonType.BUTTON_X
orientation
) )
) )
} }
@ -408,8 +378,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
windowSize, windowSize,
R.drawable.facebutton_y, R.drawable.facebutton_y,
R.drawable.facebutton_y_depressed, R.drawable.facebutton_y_depressed,
ButtonType.BUTTON_Y, ButtonType.BUTTON_Y
orientation
) )
) )
} }
@ -420,8 +389,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
windowSize, windowSize,
R.drawable.l_shoulder, R.drawable.l_shoulder,
R.drawable.l_shoulder_depressed, R.drawable.l_shoulder_depressed,
ButtonType.TRIGGER_L, ButtonType.TRIGGER_L
orientation
) )
) )
} }
@ -432,8 +400,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
windowSize, windowSize,
R.drawable.r_shoulder, R.drawable.r_shoulder,
R.drawable.r_shoulder_depressed, R.drawable.r_shoulder_depressed,
ButtonType.TRIGGER_R, ButtonType.TRIGGER_R
orientation
) )
) )
} }
@ -444,8 +411,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
windowSize, windowSize,
R.drawable.zl_trigger, R.drawable.zl_trigger,
R.drawable.zl_trigger_depressed, R.drawable.zl_trigger_depressed,
ButtonType.TRIGGER_ZL, ButtonType.TRIGGER_ZL
orientation
) )
) )
} }
@ -456,8 +422,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
windowSize, windowSize,
R.drawable.zr_trigger, R.drawable.zr_trigger,
R.drawable.zr_trigger_depressed, R.drawable.zr_trigger_depressed,
ButtonType.TRIGGER_ZR, ButtonType.TRIGGER_ZR
orientation
) )
) )
} }
@ -468,8 +433,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
windowSize, windowSize,
R.drawable.facebutton_plus, R.drawable.facebutton_plus,
R.drawable.facebutton_plus_depressed, R.drawable.facebutton_plus_depressed,
ButtonType.BUTTON_PLUS, ButtonType.BUTTON_PLUS
orientation
) )
) )
} }
@ -480,8 +444,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
windowSize, windowSize,
R.drawable.facebutton_minus, R.drawable.facebutton_minus,
R.drawable.facebutton_minus_depressed, R.drawable.facebutton_minus_depressed,
ButtonType.BUTTON_MINUS, ButtonType.BUTTON_MINUS
orientation
) )
) )
} }
@ -492,8 +455,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
windowSize, windowSize,
R.drawable.dpad_standard, R.drawable.dpad_standard,
R.drawable.dpad_standard_cardinal_depressed, R.drawable.dpad_standard_cardinal_depressed,
R.drawable.dpad_standard_diagonal_depressed, R.drawable.dpad_standard_diagonal_depressed
orientation
) )
) )
} }
@ -506,8 +468,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
R.drawable.joystick, R.drawable.joystick,
R.drawable.joystick_depressed, R.drawable.joystick_depressed,
StickType.STICK_L, StickType.STICK_L,
ButtonType.STICK_L, ButtonType.STICK_L
orientation
) )
) )
} }
@ -520,8 +481,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
R.drawable.joystick, R.drawable.joystick,
R.drawable.joystick_depressed, R.drawable.joystick_depressed,
StickType.STICK_R, StickType.STICK_R,
ButtonType.STICK_R, ButtonType.STICK_R
orientation
) )
) )
} }
@ -532,8 +492,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
windowSize, windowSize,
R.drawable.facebutton_home, R.drawable.facebutton_home,
R.drawable.facebutton_home_depressed, R.drawable.facebutton_home_depressed,
ButtonType.BUTTON_HOME, ButtonType.BUTTON_HOME
orientation
) )
) )
} }
@ -544,8 +503,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
windowSize, windowSize,
R.drawable.facebutton_screenshot, R.drawable.facebutton_screenshot,
R.drawable.facebutton_screenshot_depressed, R.drawable.facebutton_screenshot_depressed,
ButtonType.BUTTON_CAPTURE, ButtonType.BUTTON_CAPTURE
orientation
) )
) )
} }
@ -556,23 +514,21 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
overlayButtons.clear() overlayButtons.clear()
overlayDpads.clear() overlayDpads.clear()
overlayJoysticks.clear() overlayJoysticks.clear()
val orientation =
if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) "-Portrait" else ""
// Add all the enabled overlay items back to the HashSet. // Add all the enabled overlay items back to the HashSet.
if (EmulationMenuSettings.showOverlay) { if (EmulationMenuSettings.showOverlay) {
addOverlayControls(orientation) addOverlayControls()
} }
invalidate() invalidate()
} }
private fun saveControlPosition(sharedPrefsId: Int, x: Int, y: Int, orientation: String) { private fun saveControlPosition(sharedPrefsId: Int, x: Int, y: Int) {
val windowSize = getSafeScreenSize(context) val windowSize = getSafeScreenSize(context)
val min = windowSize.first val min = windowSize.first
val max = windowSize.second val max = windowSize.second
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit() PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext).edit()
.putFloat("$sharedPrefsId$orientation-X", (x - min.x).toFloat() / max.x) .putFloat("$sharedPrefsId-X", (x - min.x).toFloat() / max.x)
.putFloat("$sharedPrefsId$orientation-Y", (y - min.y).toFloat() / max.y) .putFloat("$sharedPrefsId-Y", (y - min.y).toFloat() / max.y)
.apply() .apply()
} }
@ -791,9 +747,9 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
val insets = context.windowManager.currentWindowMetrics.windowInsets.displayCutout val insets = context.windowManager.currentWindowMetrics.windowInsets.displayCutout
if (insets != null) { if (insets != null) {
if (insets.boundingRectTop.bottom != 0 && insets.boundingRectTop.bottom > maxY / 2) if (insets.boundingRectTop.bottom != 0 && insets.boundingRectTop.bottom > maxY / 2)
insets.boundingRectTop.bottom.toFloat() else maxY maxY = insets.boundingRectTop.bottom.toFloat()
if (insets.boundingRectRight.left != 0 && insets.boundingRectRight.left > maxX / 2) if (insets.boundingRectRight.left != 0 && insets.boundingRectRight.left > maxX / 2)
insets.boundingRectRight.left.toFloat() else maxX maxX = insets.boundingRectRight.left.toFloat()
minX = insets.boundingRectLeft.right - insets.boundingRectLeft.left minX = insets.boundingRectLeft.right - insets.boundingRectLeft.left
minY = insets.boundingRectBottom.top - insets.boundingRectBottom.bottom minY = insets.boundingRectBottom.top - insets.boundingRectBottom.bottom
@ -862,8 +818,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
windowSize: Pair<Point, Point>, windowSize: Pair<Point, Point>,
defaultResId: Int, defaultResId: Int,
pressedResId: Int, pressedResId: Int,
buttonId: Int, buttonId: Int
orientation: String
): InputOverlayDrawableButton { ): InputOverlayDrawableButton {
// Resources handle for fetching the initial Drawable resource. // Resources handle for fetching the initial Drawable resource.
val res = context.resources val res = context.resources
@ -900,8 +855,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
// The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay. // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.
// These were set in the input overlay configuration menu. // These were set in the input overlay configuration menu.
val xKey = "$buttonId$orientation-X" val xKey = "$buttonId-X"
val yKey = "$buttonId$orientation-Y" val yKey = "$buttonId-Y"
val drawableXPercent = sPrefs.getFloat(xKey, 0f) val drawableXPercent = sPrefs.getFloat(xKey, 0f)
val drawableYPercent = sPrefs.getFloat(yKey, 0f) val drawableYPercent = sPrefs.getFloat(yKey, 0f)
val drawableX = (drawableXPercent * max.x + min.x).toInt() val drawableX = (drawableXPercent * max.x + min.x).toInt()
@ -943,8 +898,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
windowSize: Pair<Point, Point>, windowSize: Pair<Point, Point>,
defaultResId: Int, defaultResId: Int,
pressedOneDirectionResId: Int, pressedOneDirectionResId: Int,
pressedTwoDirectionsResId: Int, pressedTwoDirectionsResId: Int
orientation: String
): InputOverlayDrawableDpad { ): InputOverlayDrawableDpad {
// Resources handle for fetching the initial Drawable resource. // Resources handle for fetching the initial Drawable resource.
val res = context.resources val res = context.resources
@ -981,8 +935,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
// The X and Y coordinates of the InputOverlayDrawableDpad on the InputOverlay. // The X and Y coordinates of the InputOverlayDrawableDpad on the InputOverlay.
// These were set in the input overlay configuration menu. // These were set in the input overlay configuration menu.
val drawableXPercent = sPrefs.getFloat("${ButtonType.DPAD_UP}$orientation-X", 0f) val drawableXPercent = sPrefs.getFloat("${ButtonType.DPAD_UP}-X", 0f)
val drawableYPercent = sPrefs.getFloat("${ButtonType.DPAD_UP}$orientation-Y", 0f) val drawableYPercent = sPrefs.getFloat("${ButtonType.DPAD_UP}-Y", 0f)
val drawableX = (drawableXPercent * max.x + min.x).toInt() val drawableX = (drawableXPercent * max.x + min.x).toInt()
val drawableY = (drawableYPercent * max.y + min.y).toInt() val drawableY = (drawableYPercent * max.y + min.y).toInt()
val width = overlayDrawable.width val width = overlayDrawable.width
@ -1023,8 +977,7 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
defaultResInner: Int, defaultResInner: Int,
pressedResInner: Int, pressedResInner: Int,
joystick: Int, joystick: Int,
button: Int, button: Int
orientation: String
): InputOverlayDrawableJoystick { ): InputOverlayDrawableJoystick {
// Resources handle for fetching the initial Drawable resource. // Resources handle for fetching the initial Drawable resource.
val res = context.resources val res = context.resources
@ -1048,8 +1001,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
// The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay. // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay.
// These were set in the input overlay configuration menu. // These were set in the input overlay configuration menu.
val drawableXPercent = sPrefs.getFloat("$button$orientation-X", 0f) val drawableXPercent = sPrefs.getFloat("$button-X", 0f)
val drawableYPercent = sPrefs.getFloat("$button$orientation-Y", 0f) val drawableYPercent = sPrefs.getFloat("$button-Y", 0f)
val drawableX = (drawableXPercent * max.x + min.x).toInt() val drawableX = (drawableXPercent * max.x + min.x).toInt()
val drawableY = (drawableYPercent * max.y + min.y).toInt() val drawableY = (drawableYPercent * max.y + min.y).toInt()
val outerScale = 1.66f val outerScale = 1.66f