mirror of
https://git.suyu.dev/suyu/suyu
synced 2024-11-01 21:07:52 +00:00
android: Enable overlay scale/opacity dialog
This commit is contained in:
parent
1957b7e6cc
commit
ca4b07a2d7
10 changed files with 182 additions and 65 deletions
|
@ -252,39 +252,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
|||
View.SYSTEM_UI_FLAG_IMMERSIVE
|
||||
}
|
||||
|
||||
private fun editControlsPlacement() {
|
||||
if (emulationFragment!!.isConfiguringControls) {
|
||||
emulationFragment!!.stopConfiguringControls()
|
||||
} else {
|
||||
emulationFragment!!.startConfiguringControls()
|
||||
}
|
||||
}
|
||||
|
||||
private fun adjustScale() {
|
||||
val sliderBinding = DialogSliderBinding.inflate(layoutInflater)
|
||||
sliderBinding.slider.valueTo = 150F
|
||||
sliderBinding.slider.value =
|
||||
PreferenceManager.getDefaultSharedPreferences(applicationContext)
|
||||
.getInt(Settings.PREF_CONTROL_SCALE, 50).toFloat()
|
||||
sliderBinding.slider.addOnChangeListener(OnChangeListener { _, value, _ ->
|
||||
sliderBinding.textValue.text = value.toString()
|
||||
setControlScale(value.toInt())
|
||||
})
|
||||
sliderBinding.textValue.text = sliderBinding.slider.value.toString()
|
||||
sliderBinding.textUnits.text = "%"
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle(R.string.emulation_control_scale)
|
||||
.setView(sliderBinding.root)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int ->
|
||||
setControlScale(sliderBinding.slider.value.toInt())
|
||||
}
|
||||
.setNeutralButton(R.string.slider_default) { _: DialogInterface?, _: Int ->
|
||||
setControlScale(50)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun startMotionSensorListener() {
|
||||
val sensorManager = this.getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||
val gyroSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE)
|
||||
|
@ -302,22 +269,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
|||
sensorManager.unregisterListener(this, accelSensor)
|
||||
}
|
||||
|
||||
private fun setControlScale(scale: Int) {
|
||||
PreferenceManager.getDefaultSharedPreferences(applicationContext).edit()
|
||||
.putInt(Settings.PREF_CONTROL_SCALE, scale)
|
||||
.apply()
|
||||
emulationFragment!!.refreshInputOverlay()
|
||||
}
|
||||
|
||||
private fun resetOverlay() {
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle(getString(R.string.emulation_touch_overlay_reset))
|
||||
.setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int -> emulationFragment!!.resetInputOverlay() }
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
.show()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val EXTRA_SELECTED_GAME = "SelectedGame"
|
||||
|
||||
|
|
|
@ -111,6 +111,7 @@ class Settings {
|
|||
|
||||
const val PREF_OVERLAY_INIT = "OverlayInit"
|
||||
const val PREF_CONTROL_SCALE = "controlScale"
|
||||
const val PREF_CONTROL_OPACITY = "controlOpacity"
|
||||
const val PREF_TOUCH_ENABLED = "isTouchEnabled"
|
||||
const val PREF_BUTTON_TOGGLE_0 = "buttonToggle0"
|
||||
const val PREF_BUTTON_TOGGLE_1 = "buttonToggle1"
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
|
||||
package org.yuzu.yuzu_emu.fragments
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.AlertDialog
|
||||
import android.content.Context
|
||||
import android.content.DialogInterface
|
||||
import android.content.SharedPreferences
|
||||
import android.graphics.Color
|
||||
import android.os.Bundle
|
||||
|
@ -21,10 +23,12 @@ import androidx.core.view.WindowInsetsCompat
|
|||
import androidx.fragment.app.Fragment
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.slider.Slider
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.YuzuApplication
|
||||
import org.yuzu.yuzu_emu.activities.EmulationActivity
|
||||
import org.yuzu.yuzu_emu.databinding.DialogOverlayAdjustBinding
|
||||
import org.yuzu.yuzu_emu.databinding.FragmentEmulationBinding
|
||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsActivity
|
||||
|
@ -168,14 +172,14 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
super.onDetach()
|
||||
}
|
||||
|
||||
fun refreshInputOverlay() {
|
||||
private fun refreshInputOverlay() {
|
||||
binding.surfaceInputOverlay.refreshControls()
|
||||
}
|
||||
|
||||
fun resetInputOverlay() {
|
||||
// Reset button scale
|
||||
private fun resetInputOverlay() {
|
||||
preferences.edit()
|
||||
.putInt(Settings.PREF_CONTROL_SCALE, 50)
|
||||
.remove(Settings.PREF_CONTROL_SCALE)
|
||||
.remove(Settings.PREF_CONTROL_OPACITY)
|
||||
.apply()
|
||||
binding.surfaceInputOverlay.post { binding.surfaceInputOverlay.resetButtonPlacement() }
|
||||
}
|
||||
|
@ -251,6 +255,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
true
|
||||
}
|
||||
|
||||
R.id.menu_adjust_overlay -> {
|
||||
adjustOverlay()
|
||||
true
|
||||
}
|
||||
|
||||
R.id.menu_toggle_controls -> {
|
||||
val preferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||
|
@ -278,9 +287,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
// Override normal behaviour so the dialog doesn't close
|
||||
dialog.getButton(AlertDialog.BUTTON_NEUTRAL)
|
||||
.setOnClickListener {
|
||||
val isChecked = !optionsArray[0];
|
||||
val isChecked = !optionsArray[0]
|
||||
for (i in 0..14) {
|
||||
optionsArray[i] = isChecked;
|
||||
optionsArray[i] = isChecked
|
||||
dialog.listView.setItemChecked(i, isChecked)
|
||||
preferences.edit()
|
||||
.putBoolean("buttonToggle$i", isChecked)
|
||||
|
@ -328,18 +337,64 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
popup.show()
|
||||
}
|
||||
|
||||
fun startConfiguringControls() {
|
||||
private fun startConfiguringControls() {
|
||||
binding.doneControlConfig.visibility = View.VISIBLE
|
||||
binding.surfaceInputOverlay.setIsInEditMode(true)
|
||||
}
|
||||
|
||||
fun stopConfiguringControls() {
|
||||
private fun stopConfiguringControls() {
|
||||
binding.doneControlConfig.visibility = View.GONE
|
||||
binding.surfaceInputOverlay.setIsInEditMode(false)
|
||||
}
|
||||
|
||||
val isConfiguringControls: Boolean
|
||||
get() = binding.surfaceInputOverlay.isInEditMode
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun adjustOverlay() {
|
||||
val adjustBinding = DialogOverlayAdjustBinding.inflate(layoutInflater)
|
||||
adjustBinding.apply {
|
||||
inputScaleSlider.apply {
|
||||
valueTo = 150F
|
||||
value = preferences.getInt(Settings.PREF_CONTROL_SCALE, 50).toFloat()
|
||||
addOnChangeListener(Slider.OnChangeListener { _, value, _ ->
|
||||
inputScaleValue.text = "${value.toInt()}%"
|
||||
setControlScale(value.toInt())
|
||||
})
|
||||
}
|
||||
inputOpacitySlider.apply {
|
||||
valueTo = 100F
|
||||
value = preferences.getInt(Settings.PREF_CONTROL_OPACITY, 100).toFloat()
|
||||
addOnChangeListener(Slider.OnChangeListener { _, value, _ ->
|
||||
inputOpacityValue.text = "${value.toInt()}%"
|
||||
setControlOpacity(value.toInt())
|
||||
})
|
||||
}
|
||||
inputScaleValue.text = "${inputScaleSlider.value.toInt()}%"
|
||||
inputOpacityValue.text = "${inputOpacitySlider.value.toInt()}%"
|
||||
}
|
||||
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
.setTitle(R.string.emulation_control_adjust)
|
||||
.setView(adjustBinding.root)
|
||||
.setPositiveButton(android.R.string.ok, null)
|
||||
.setNeutralButton(R.string.slider_default) { _: DialogInterface?, _: Int ->
|
||||
setControlScale(50)
|
||||
setControlOpacity(100)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun setControlScale(scale: Int) {
|
||||
preferences.edit()
|
||||
.putInt(Settings.PREF_CONTROL_SCALE, scale)
|
||||
.apply()
|
||||
refreshInputOverlay()
|
||||
}
|
||||
|
||||
private fun setControlOpacity(opacity: Int) {
|
||||
preferences.edit()
|
||||
.putInt(Settings.PREF_CONTROL_OPACITY, opacity)
|
||||
.apply()
|
||||
refreshInputOverlay()
|
||||
}
|
||||
|
||||
private fun setInsets() {
|
||||
ViewCompat.setOnApplyWindowInsetsListener(binding.inGameMenu) { v: View, windowInsets: WindowInsetsCompat ->
|
||||
|
|
|
@ -49,9 +49,6 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
|
|||
private var dpadBeingConfigured: InputOverlayDrawableDpad? = null
|
||||
private var joystickBeingConfigured: InputOverlayDrawableJoystick? = null
|
||||
|
||||
private val preferences: SharedPreferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||
|
||||
private lateinit var windowInsets: WindowInsets
|
||||
|
||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
||||
|
@ -709,6 +706,9 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
|
|||
}
|
||||
|
||||
companion object {
|
||||
private val preferences: SharedPreferences =
|
||||
PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
|
||||
|
||||
/**
|
||||
* Resizes a [Bitmap] by a given scale factor
|
||||
*
|
||||
|
@ -899,6 +899,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
|
|||
drawableX - (width / 2),
|
||||
drawableY - (height / 2)
|
||||
)
|
||||
val savedOpacity = preferences.getInt(Settings.PREF_CONTROL_OPACITY, 100)
|
||||
overlayDrawable.setOpacity(savedOpacity * 255 / 100)
|
||||
return overlayDrawable
|
||||
}
|
||||
|
||||
|
@ -973,6 +975,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
|
|||
|
||||
// Need to set the image's position
|
||||
overlayDrawable.setPosition(drawableX - (width / 2), drawableY - (height / 2))
|
||||
val savedOpacity = preferences.getInt(Settings.PREF_CONTROL_OPACITY, 100)
|
||||
overlayDrawable.setOpacity(savedOpacity * 255 / 100)
|
||||
return overlayDrawable
|
||||
}
|
||||
|
||||
|
@ -1052,6 +1056,8 @@ class InputOverlay(context: Context, attrs: AttributeSet?) : SurfaceView(context
|
|||
|
||||
// Need to set the image's position
|
||||
overlayDrawable.setPosition(drawableX, drawableY)
|
||||
val savedOpacity = preferences.getInt(Settings.PREF_CONTROL_OPACITY, 100)
|
||||
overlayDrawable.setOpacity(savedOpacity * 255 / 100)
|
||||
return overlayDrawable
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,6 +114,7 @@ class InputOverlayDrawableButton(
|
|||
controlPositionX = fingerPositionX - (width / 2)
|
||||
controlPositionY = fingerPositionY - (height / 2)
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
controlPositionX += fingerPositionX - previousTouchX
|
||||
controlPositionY += fingerPositionY - previousTouchY
|
||||
|
@ -135,6 +136,11 @@ class InputOverlayDrawableButton(
|
|||
pressedStateBitmap.setBounds(left, top, right, bottom)
|
||||
}
|
||||
|
||||
fun setOpacity(value: Int) {
|
||||
defaultStateBitmap.alpha = value
|
||||
pressedStateBitmap.alpha = value
|
||||
}
|
||||
|
||||
val status: Int
|
||||
get() = if (pressedState) ButtonState.PRESSED else ButtonState.RELEASED
|
||||
val bounds: Rect
|
||||
|
|
|
@ -231,6 +231,7 @@ class InputOverlayDrawableDpad(
|
|||
previousTouchX = fingerPositionX
|
||||
previousTouchY = fingerPositionY
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
controlPositionX += fingerPositionX - previousTouchX
|
||||
controlPositionY += fingerPositionY - previousTouchY
|
||||
|
@ -258,6 +259,12 @@ class InputOverlayDrawableDpad(
|
|||
pressedTwoDirectionsStateBitmap.setBounds(left, top, right, bottom)
|
||||
}
|
||||
|
||||
fun setOpacity(value: Int) {
|
||||
defaultStateBitmap.alpha = value
|
||||
pressedOneDirectionStateBitmap.alpha = value
|
||||
pressedTwoDirectionsStateBitmap.alpha = value
|
||||
}
|
||||
|
||||
val bounds: Rect
|
||||
get() = defaultStateBitmap.bounds
|
||||
|
||||
|
|
|
@ -48,6 +48,8 @@ class InputOverlayDrawableJoystick(
|
|||
val width: Int
|
||||
val height: Int
|
||||
|
||||
private var opacity: Int = 0
|
||||
|
||||
private var virtBounds: Rect
|
||||
private var origBounds: Rect
|
||||
|
||||
|
@ -121,7 +123,7 @@ class InputOverlayDrawableJoystick(
|
|||
}
|
||||
pressedState = true
|
||||
outerBitmap.alpha = 0
|
||||
boundsBoxBitmap.alpha = 255
|
||||
boundsBoxBitmap.alpha = opacity
|
||||
if (EmulationMenuSettings.joystickRelCenter) {
|
||||
virtBounds.offset(
|
||||
xPosition - virtBounds.centerX(),
|
||||
|
@ -139,7 +141,7 @@ class InputOverlayDrawableJoystick(
|
|||
pressedState = false
|
||||
xAxis = 0.0f
|
||||
yAxis = 0.0f
|
||||
outerBitmap.alpha = 255
|
||||
outerBitmap.alpha = opacity
|
||||
boundsBoxBitmap.alpha = 0
|
||||
virtBounds = Rect(
|
||||
origBounds.left,
|
||||
|
@ -203,6 +205,7 @@ class InputOverlayDrawableJoystick(
|
|||
controlPositionX = fingerPositionX - (width / 2)
|
||||
controlPositionY = fingerPositionY - (height / 2)
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_MOVE -> {
|
||||
controlPositionX += fingerPositionX - previousTouchX
|
||||
controlPositionY += fingerPositionY - previousTouchY
|
||||
|
@ -261,4 +264,19 @@ class InputOverlayDrawableJoystick(
|
|||
controlPositionX = x
|
||||
controlPositionY = y
|
||||
}
|
||||
|
||||
fun setOpacity(value: Int) {
|
||||
opacity = value
|
||||
|
||||
defaultStateInnerBitmap.alpha = value
|
||||
pressedStateInnerBitmap.alpha = value
|
||||
|
||||
if (trackId == -1) {
|
||||
outerBitmap.alpha = value
|
||||
boundsBoxBitmap.alpha = 0
|
||||
} else {
|
||||
outerBitmap.alpha = 0
|
||||
boundsBoxBitmap.alpha = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/input_scale_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/emulation_control_scale"
|
||||
android:textAlignment="viewStart"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintStart_toStartOf="@+id/input_scale_slider"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/input_scale_slider"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/input_scale_name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/input_scale_value"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
app:layout_constraintBottom_toTopOf="@+id/input_scale_slider"
|
||||
app:layout_constraintEnd_toEndOf="@+id/input_scale_slider"
|
||||
tools:text="100%" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/input_opacity_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/emulation_control_opacity"
|
||||
android:textAlignment="viewStart"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintStart_toStartOf="@+id/input_opacity_slider"
|
||||
app:layout_constraintTop_toBottomOf="@+id/input_scale_slider" />
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/input_opacity_slider"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="24dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/input_opacity_name" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/input_opacity_value"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="end"
|
||||
app:layout_constraintBottom_toTopOf="@+id/input_opacity_slider"
|
||||
app:layout_constraintEnd_toEndOf="@+id/input_opacity_slider"
|
||||
tools:text="100%" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -10,6 +10,10 @@
|
|||
android:id="@+id/menu_edit_overlay"
|
||||
android:title="@string/emulation_touch_overlay_edit" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_adjust_overlay"
|
||||
android:title="@string/emulation_control_adjust" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_toggle_controls"
|
||||
android:title="@string/emulation_toggle_controls" />
|
||||
|
|
|
@ -204,7 +204,9 @@
|
|||
<string name="emulation_haptics">Haptics</string>
|
||||
<string name="emulation_show_overlay">Show Overlay</string>
|
||||
<string name="emulation_toggle_all">Toggle All</string>
|
||||
<string name="emulation_control_scale">Adjust Scale</string>
|
||||
<string name="emulation_control_adjust">Adjust Overlay</string>
|
||||
<string name="emulation_control_scale">Scale</string>
|
||||
<string name="emulation_control_opacity">Opacity</string>
|
||||
<string name="emulation_touch_overlay_reset">Reset Overlay</string>
|
||||
<string name="emulation_touch_overlay_edit">Edit Overlay</string>
|
||||
<string name="emulation_pause">Pause Emulation</string>
|
||||
|
|
Loading…
Reference in a new issue