From 467301bc4e0e52ce3de03a4e3860cb6c2a3f568c Mon Sep 17 00:00:00 2001 From: Gamer64ytb <76565986+Gamer64ytb@users.noreply.github.com> Date: Tue, 9 Apr 2024 09:31:24 +0200 Subject: [PATCH] Android: Implement touch controls opacity option. --- .../citra_emu/fragments/EmulationFragment.kt | 44 +++++++++++++++++++ .../citra/citra_emu/overlay/InputOverlay.kt | 14 ++++-- .../overlay/InputOverlayDrawableButton.kt | 11 ++++- .../overlay/InputOverlayDrawableDpad.kt | 15 ++++++- .../overlay/InputOverlayDrawableJoystick.kt | 14 ++++-- .../main/res/menu/menu_overlay_options.xml | 4 ++ .../app/src/main/res/values-es/strings.xml | 1 + .../app/src/main/res/values/strings.xml | 1 + 8 files changed, 95 insertions(+), 9 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/citra/citra_emu/fragments/EmulationFragment.kt index eeff4ff1b..344043793 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/fragments/EmulationFragment.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/fragments/EmulationFragment.kt @@ -617,6 +617,11 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram true } + R.id.menu_emulation_adjust_opacity -> { + showAdjustOpacityDialog() + true + } + R.id.menu_emulation_joystick_rel_center -> { EmulationMenuSettings.joystickRelCenter = !EmulationMenuSettings.joystickRelCenter @@ -793,6 +798,37 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram .show() } + private fun showAdjustOpacityDialog() { + val sliderBinding = DialogSliderBinding.inflate(layoutInflater) + + sliderBinding.apply { + slider.valueTo = 100f + slider.value = preferences.getInt("controlOpacity", 100).toFloat() + slider.addOnChangeListener( + Slider.OnChangeListener { slider: Slider, progress: Float, _: Boolean -> + textValue.text = (progress.toInt()).toString() + setControlOpacity(slider.value.toInt()) + }) + textValue.text = (sliderBinding.slider.value.toInt()).toString() + textUnits.text = "%" + } + val previousProgress = sliderBinding.slider.value.toInt() + + MaterialAlertDialogBuilder(requireContext()) + .setTitle(R.string.emulation_control_opacity) + .setView(sliderBinding.root) + .setNegativeButton(android.R.string.cancel) { _: DialogInterface?, _: Int -> + setControlOpacity(previousProgress) + } + .setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int -> + setControlOpacity(sliderBinding.slider.value.toInt()) + } + .setNeutralButton(R.string.slider_default) { _: DialogInterface?, _: Int -> + setControlOpacity(100) + } + .show() + } + private fun setControlScale(scale: Int) { preferences.edit() .putInt("controlScale", scale) @@ -800,6 +836,13 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram binding.surfaceInputOverlay.refreshControls() } + private fun setControlOpacity(opacity: Int) { + preferences.edit() + .putInt("controlOpacity", opacity) + .apply() + binding.surfaceInputOverlay.refreshControls() + } + private fun showResetOverlayDialog() { MaterialAlertDialogBuilder(requireContext()) .setTitle(getString(R.string.emulation_touch_overlay_reset)) @@ -813,6 +856,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback, Choreographer.Fram private fun resetInputOverlay() { preferences.edit() .putInt("controlScale", 50) + .putInt("controlOpacity", 100) .apply() val editor = preferences.edit() diff --git a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt index deb718c7e..a5ac5ad6a 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlay.kt @@ -890,12 +890,14 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex } scale *= (preferences.getInt("controlScale", 50) + 50).toFloat() scale /= 100f + + val opacity: Int = preferences.getInt("controlOpacity", 100) * 255 / 100 // Initialize the InputOverlayDrawableButton. val defaultStateBitmap = getBitmap(context, defaultResId, scale) val pressedStateBitmap = getBitmap(context, pressedResId, scale) val overlayDrawable = - InputOverlayDrawableButton(res, defaultStateBitmap, pressedStateBitmap, buttonId) + InputOverlayDrawableButton(res, defaultStateBitmap, pressedStateBitmap, buttonId, opacity) // The X and Y coordinates of the InputOverlayDrawableButton on the InputOverlay. // These were set in the input overlay configuration menu. @@ -947,6 +949,8 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex scale *= (preferences.getInt("controlScale", 50) + 50).toFloat() scale /= 100f + val opacity: Int = preferences.getInt("controlOpacity", 100) * 255 / 100 + // Initialize the InputOverlayDrawableDpad. val defaultStateBitmap = getBitmap(context, defaultResId, scale) val pressedOneDirectionStateBitmap = getBitmap(context, pressedOneDirectionResId, scale) @@ -959,7 +963,8 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex buttonUp, buttonDown, buttonLeft, - buttonRight + buttonRight, + opacity ) // The X and Y coordinates of the InputOverlayDrawableDpad on the InputOverlay. @@ -1004,6 +1009,8 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex scale *= (preferences.getInt("controlScale", 50) + 50).toFloat() scale /= 100f + val opacity: Int = preferences.getInt("controlOpacity", 100) * 255 / 100 + // Initialize the InputOverlayDrawableJoystick. val bitmapOuter = getBitmap(context, resOuter, scale) val bitmapInnerDefault = getBitmap(context, defaultResInner, scale) @@ -1040,7 +1047,8 @@ class InputOverlay(context: Context?, attrs: AttributeSet?) : SurfaceView(contex bitmapInnerPressed, outerRect, innerRect, - joystick + joystick, + opacity ) // Need to set the image's position diff --git a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlayDrawableButton.kt b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlayDrawableButton.kt index 5f83fa776..87bcf194b 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlayDrawableButton.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlayDrawableButton.kt @@ -25,7 +25,8 @@ class InputOverlayDrawableButton( res: Resources, defaultStateBitmap: Bitmap, pressedStateBitmap: Bitmap, - val id: Int + val id: Int, + val opacity: Int ) { var trackId: Int private var previousTouchX = 0 @@ -34,6 +35,7 @@ class InputOverlayDrawableButton( private var controlPositionY = 0 val width: Int val height: Int + private val opacityId: Int private val defaultStateBitmap: BitmapDrawable private val pressedStateBitmap: BitmapDrawable private var pressedState = false @@ -41,6 +43,7 @@ class InputOverlayDrawableButton( init { this.defaultStateBitmap = BitmapDrawable(res, defaultStateBitmap) this.pressedStateBitmap = BitmapDrawable(res, pressedStateBitmap) + this.opacityId = this.opacity trackId = -1 width = this.defaultStateBitmap.intrinsicWidth height = this.defaultStateBitmap.intrinsicHeight @@ -111,7 +114,11 @@ class InputOverlayDrawableButton( controlPositionY = y } - fun draw(canvas: Canvas) = currentStateBitmapDrawable.draw(canvas) + fun draw(canvas: Canvas) { + val bitmapDrawable: BitmapDrawable = currentStateBitmapDrawable + bitmapDrawable.alpha = opacityId + bitmapDrawable.draw(canvas) + } private val currentStateBitmapDrawable: BitmapDrawable get() = if (pressedState) pressedStateBitmap else defaultStateBitmap diff --git a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlayDrawableDpad.kt b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlayDrawableDpad.kt index f7a5a3fe5..80c5f7346 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlayDrawableDpad.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlayDrawableDpad.kt @@ -24,6 +24,7 @@ import org.citra.citra_emu.NativeLibrary * @param downId Identifier for the down button. * @param leftId Identifier for the left button. * @param rightId Identifier for the right button. + * @param opacity 0-255 alpha value */ class InputOverlayDrawableDpad( res: Resources, @@ -33,7 +34,8 @@ class InputOverlayDrawableDpad( val upId: Int, val downId: Int, val leftId: Int, - val rightId: Int + val rightId: Int, + val opacity: Int ) { var trackId: Int private var previousTouchX = 0 @@ -42,6 +44,7 @@ class InputOverlayDrawableDpad( private var controlPositionY = 0 val width: Int val height: Int + private val opacityId: Int private val defaultStateBitmap: BitmapDrawable private val pressedOneDirectionStateBitmap: BitmapDrawable private val pressedTwoDirectionsStateBitmap: BitmapDrawable @@ -54,6 +57,7 @@ class InputOverlayDrawableDpad( this.defaultStateBitmap = BitmapDrawable(res, defaultStateBitmap) this.pressedOneDirectionStateBitmap = BitmapDrawable(res, pressedOneDirectionStateBitmap) this.pressedTwoDirectionsStateBitmap = BitmapDrawable(res, pressedTwoDirectionsStateBitmap) + this.opacityId = this.opacity width = this.defaultStateBitmap.intrinsicWidth height = this.defaultStateBitmap.intrinsicHeight trackId = -1 @@ -125,6 +129,7 @@ class InputOverlayDrawableDpad( // Pressed up if (upButtonState && !leftButtonState && !rightButtonState) { + pressedOneDirectionStateBitmap.alpha = opacityId pressedOneDirectionStateBitmap.draw(canvas) return } @@ -133,6 +138,7 @@ class InputOverlayDrawableDpad( if (downButtonState && !leftButtonState && !rightButtonState) { canvas.save() canvas.rotate(180f, px.toFloat(), py.toFloat()) + pressedOneDirectionStateBitmap.alpha = opacityId pressedOneDirectionStateBitmap.draw(canvas) canvas.restore() return @@ -142,6 +148,7 @@ class InputOverlayDrawableDpad( if (leftButtonState && !upButtonState && !downButtonState) { canvas.save() canvas.rotate(270f, px.toFloat(), py.toFloat()) + pressedOneDirectionStateBitmap.alpha = opacityId pressedOneDirectionStateBitmap.draw(canvas) canvas.restore() return @@ -151,6 +158,7 @@ class InputOverlayDrawableDpad( if (rightButtonState && !upButtonState && !downButtonState) { canvas.save() canvas.rotate(90f, px.toFloat(), py.toFloat()) + pressedOneDirectionStateBitmap.alpha = opacityId pressedOneDirectionStateBitmap.draw(canvas) canvas.restore() return @@ -158,6 +166,7 @@ class InputOverlayDrawableDpad( // Pressed up left if (upButtonState && leftButtonState && !rightButtonState) { + pressedTwoDirectionsStateBitmap.alpha = opacityId pressedTwoDirectionsStateBitmap.draw(canvas) return } @@ -166,6 +175,7 @@ class InputOverlayDrawableDpad( if (upButtonState && !leftButtonState && rightButtonState) { canvas.save() canvas.rotate(90f, px.toFloat(), py.toFloat()) + pressedTwoDirectionsStateBitmap.alpha = opacityId pressedTwoDirectionsStateBitmap.draw(canvas) canvas.restore() return @@ -175,6 +185,7 @@ class InputOverlayDrawableDpad( if (downButtonState && leftButtonState && !rightButtonState) { canvas.save() canvas.rotate(270f, px.toFloat(), py.toFloat()) + pressedTwoDirectionsStateBitmap.alpha = opacityId pressedTwoDirectionsStateBitmap.draw(canvas) canvas.restore() return @@ -184,12 +195,14 @@ class InputOverlayDrawableDpad( if (downButtonState && !leftButtonState && rightButtonState) { canvas.save() canvas.rotate(180f, px.toFloat(), py.toFloat()) + pressedTwoDirectionsStateBitmap.alpha = opacityId pressedTwoDirectionsStateBitmap.draw(canvas) canvas.restore() return } // Not pressed + defaultStateBitmap.alpha = opacityId defaultStateBitmap.draw(canvas) } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlayDrawableJoystick.kt b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlayDrawableJoystick.kt index f521077a4..f9b4c01c1 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlayDrawableJoystick.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/overlay/InputOverlayDrawableJoystick.kt @@ -28,6 +28,7 @@ import kotlin.math.sqrt * @param rectOuter [Rect] which represents the outer joystick bounds. * @param rectInner [Rect] which represents the inner joystick bounds. * @param joystickId Identifier for which joystick this is. + * @param opacity 0-255 alpha value */ class InputOverlayDrawableJoystick( res: Resources, @@ -36,7 +37,8 @@ class InputOverlayDrawableJoystick( bitmapInnerPressed: Bitmap, rectOuter: Rect, rectInner: Rect, - val joystickId: Int + val joystickId: Int, + val opacity: Int ) { var trackId = -1 var xAxis = 0f @@ -47,6 +49,7 @@ class InputOverlayDrawableJoystick( private var previousTouchY = 0 val width: Int val height: Int + private val opacityId: Int private var virtBounds: Rect private var origBounds: Rect private val outerBitmap: BitmapDrawable @@ -69,6 +72,7 @@ class InputOverlayDrawableJoystick( width = bitmapOuter.width height = bitmapOuter.height bounds = rectOuter + opacityId = opacity defaultStateInnerBitmap.bounds = rectInner pressedStateInnerBitmap.bounds = rectInner virtBounds = bounds @@ -76,10 +80,14 @@ class InputOverlayDrawableJoystick( boundsBoxBitmap.alpha = 0 boundsBoxBitmap.bounds = virtBounds setInnerBounds() + defaultStateInnerBitmap.alpha = opacity + pressedStateInnerBitmap.alpha = opacity + outerBitmap.alpha = opacity } fun draw(canvas: Canvas?) { outerBitmap.draw(canvas!!) + currentStateBitmapDrawable.alpha = opacityId currentStateBitmapDrawable.draw(canvas) boundsBoxBitmap.draw(canvas) } @@ -100,7 +108,7 @@ class InputOverlayDrawableJoystick( } pressedState = true outerBitmap.alpha = 0 - boundsBoxBitmap.alpha = 255 + boundsBoxBitmap.alpha = opacityId if (EmulationMenuSettings.joystickRelCenter) { virtBounds.offset( xPosition - virtBounds.centerX(), @@ -117,7 +125,7 @@ class InputOverlayDrawableJoystick( pressedState = false xAxis = 0.0f yAxis = 0.0f - outerBitmap.alpha = 255 + outerBitmap.alpha = opacityId boundsBoxBitmap.alpha = 0 virtBounds = Rect(origBounds.left, origBounds.top, origBounds.right, origBounds.bottom) bounds = Rect(origBounds.left, origBounds.top, origBounds.right, origBounds.bottom) 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 18b315c88..f79c3148b 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 @@ -23,6 +23,10 @@ android:id="@+id/menu_emulation_adjust_scale" android:title="@string/emulation_control_scale" /> + + Hecho Activar Controles Ajustar Escala + Ajustar Opacidad Posición central relativa del stick Deslizamiento de la Cruceta Abrir Configuración diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 781e78da1..66ea2f7e2 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -329,6 +329,7 @@ Done Toggle Controls Adjust Scale + Adjust Opacity Relative Stick Center D-Pad Sliding Open Settings