From ca4b07a2d7b67ee042ab886d8373faf88c2fd883 Mon Sep 17 00:00:00 2001 From: Charles Lombardo Date: Thu, 1 Jun 2023 17:30:27 -0400 Subject: [PATCH] android: Enable overlay scale/opacity dialog --- .../yuzu_emu/activities/EmulationActivity.kt | 49 ------------ .../features/settings/model/Settings.kt | 1 + .../yuzu_emu/fragments/EmulationFragment.kt | 75 ++++++++++++++++--- .../org/yuzu/yuzu_emu/overlay/InputOverlay.kt | 12 ++- .../overlay/InputOverlayDrawableButton.kt | 6 ++ .../overlay/InputOverlayDrawableDpad.kt | 7 ++ .../overlay/InputOverlayDrawableJoystick.kt | 22 +++++- .../main/res/layout/dialog_overlay_adjust.xml | 67 +++++++++++++++++ .../main/res/menu/menu_overlay_options.xml | 4 + .../app/src/main/res/values/strings.xml | 4 +- 10 files changed, 182 insertions(+), 65 deletions(-) create mode 100644 src/android/app/src/main/res/layout/dialog_overlay_adjust.xml diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt index 37caa1b83e..abeb019957 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt @@ -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" diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt index a904c2011f..23c31e13ab 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/Settings.kt @@ -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" diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt index ea44733c15..5f1a941909 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt @@ -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 -> diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt index bb20e5207e..693e709732 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt @@ -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 } } diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt index 99d7d9521a..4a93e0b148 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableButton.kt @@ -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 diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.kt index 625cad661e..43d664d218 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.kt @@ -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 diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt index 1960eaff08..f1d32192a9 100644 --- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt +++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt @@ -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 + } + } } diff --git a/src/android/app/src/main/res/layout/dialog_overlay_adjust.xml b/src/android/app/src/main/res/layout/dialog_overlay_adjust.xml new file mode 100644 index 0000000000..59bb983e19 --- /dev/null +++ b/src/android/app/src/main/res/layout/dialog_overlay_adjust.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + diff --git a/src/android/app/src/main/res/menu/menu_overlay_options.xml b/src/android/app/src/main/res/menu/menu_overlay_options.xml index 09e8b79709..4885b4f6fb 100644 --- a/src/android/app/src/main/res/menu/menu_overlay_options.xml +++ b/src/android/app/src/main/res/menu/menu_overlay_options.xml @@ -10,6 +10,10 @@ android:id="@+id/menu_edit_overlay" android:title="@string/emulation_touch_overlay_edit" /> + + diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index d3340fe991..5e44551ad0 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -204,7 +204,9 @@ Haptics Show Overlay Toggle All - Adjust Scale + Adjust Overlay + Scale + Opacity Reset Overlay Edit Overlay Pause Emulation