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