diff --git a/app/src/main/java/emu/skyline/input/onscreen/OnScreenConfiguration.kt b/app/src/main/java/emu/skyline/input/onscreen/OnScreenConfiguration.kt
index 0309f7b7..7b0b42ab 100644
--- a/app/src/main/java/emu/skyline/input/onscreen/OnScreenConfiguration.kt
+++ b/app/src/main/java/emu/skyline/input/onscreen/OnScreenConfiguration.kt
@@ -26,6 +26,10 @@ interface OnScreenConfiguration {
const val MaxScale = 2.5f
const val DefaultScale = 1f
+ const val MinActivationRadius = 1.0f
+ const val DefaultActivationRadius = 1.0f
+ const val MaxActivationRadius = 8.0f
+
val DefaultTextColor = SwitchColors.BLACK.color
val DefaultBackgroundColor = SwitchColors.WHITE.color
}
@@ -51,6 +55,11 @@ interface OnScreenConfiguration {
var scale : Float
var relativeX : Float
var relativeY : Float
+
+ /**
+ * A modifier applied to the radius of the stick, applied when determining when the stick has been touched
+ */
+ var activationRadius : Float
}
class OnScreenConfigurationImpl(private val context : Context, private val buttonId : ButtonId, defaultRelativeX : Float, defaultRelativeY : Float, defaultEnabled : Boolean) : OnScreenConfiguration {
@@ -66,4 +75,6 @@ class OnScreenConfigurationImpl(private val context : Context, private val butto
override var scale by config(OnScreenConfiguration.DefaultScale)
override var relativeX by config(defaultRelativeX)
override var relativeY by config(defaultRelativeY)
+
+ override var activationRadius by config(OnScreenConfiguration.DefaultActivationRadius)
}
diff --git a/app/src/main/java/emu/skyline/input/onscreen/OnScreenControllerView.kt b/app/src/main/java/emu/skyline/input/onscreen/OnScreenControllerView.kt
index e818abea..8f66a489 100644
--- a/app/src/main/java/emu/skyline/input/onscreen/OnScreenControllerView.kt
+++ b/app/src/main/java/emu/skyline/input/onscreen/OnScreenControllerView.kt
@@ -355,6 +355,16 @@ class OnScreenControllerView @JvmOverloads constructor(context : Context, attrs
invalidate()
}
+ fun setStickActivationRadius(@IntRange(from = 0, to = 100) radius : Int) {
+ fun toRadiusRange(value : Int) : Float = (value / 100f) * (OnScreenConfiguration.MaxActivationRadius - OnScreenConfiguration.MinActivationRadius) + OnScreenConfiguration.MinActivationRadius
+
+ (editInfo.editButton as? JoystickButton)?.let { joystick ->
+ joystick.config.activationRadius = toRadiusRange(radius)
+ joystick.loadActivationRadius()
+ }
+ invalidate()
+ }
+
fun moveButtonUp() {
editInfo.editButton.moveUp()
invalidate()
@@ -462,6 +472,7 @@ class OnScreenControllerView @JvmOverloads constructor(context : Context, attrs
override var relativeX = 0f
override var relativeY = 0f
+ override var activationRadius = 0f
}
override fun startMove(x : Float, y : Float) {}
diff --git a/app/src/main/java/emu/skyline/input/onscreen/OnScreenEditActivity.kt b/app/src/main/java/emu/skyline/input/onscreen/OnScreenEditActivity.kt
index e0a27f45..b79e12ce 100644
--- a/app/src/main/java/emu/skyline/input/onscreen/OnScreenEditActivity.kt
+++ b/app/src/main/java/emu/skyline/input/onscreen/OnScreenEditActivity.kt
@@ -120,6 +120,9 @@ class OnScreenEditActivity : AppCompatActivity() {
populateSlider(binding.opacitySlider, getString(R.string.osc_opacity)) {
binding.onScreenControllerView.setButtonOpacity(it)
}
+ populateSlider(binding.activationSlider, getString(R.string.osc_activation_radius)) {
+ binding.onScreenControllerView.setStickActivationRadius(it)
+ }
binding.enabledCheckbox.setOnClickListener { _ ->
binding.onScreenControllerView.setButtonEnabled(binding.enabledCheckbox.isChecked)
@@ -190,6 +193,8 @@ class OnScreenEditActivity : AppCompatActivity() {
if (fromUser)
valueListener?.invoke(value.roundToInt())
}
+ // Update the value label with the initial value to avoid it being blank
+ slider.valueLabel.text = "${value.roundToInt()}%"
}
}
@@ -197,13 +202,23 @@ class OnScreenEditActivity : AppCompatActivity() {
* Updates the control panel UI elements to reflect the currently selected button
*/
private fun updateActiveButtonDisplayInfo(button : ConfigurableButton) {
+ fun Float.toSliderRange(min : Float, max : Float) : Float = ((this - min) / (max - min) * 100f).coerceIn(0f, 100f)
+ fun Int.toSliderRange(min : Int, max : Int) : Float = ((this - min) / (max - min).toFloat() * 100f).coerceIn(0f, 100f)
+
binding.enabledCheckbox.checkedState = button.config.groupEnabled
- binding.toggleModeCheckbox.isEnabled = button.supportsToggleMode()
- binding.toggleModeCheckbox.checkedState = button.config.groupToggleMode
currentButtonName = button.buttonId.short ?: ""
binding.currentButton.text = getString(R.string.osc_current_button, currentButtonName)
- binding.scaleSlider.slider.value = (button.config.scale - OnScreenConfiguration.MinScale) / (OnScreenConfiguration.MaxScale - OnScreenConfiguration.MinScale) * 100f
- binding.opacitySlider.slider.value = (button.config.alpha - OnScreenConfiguration.MinAlpha) / (OnScreenConfiguration.MaxAlpha - OnScreenConfiguration.MinAlpha).toFloat() * 100f
+ binding.scaleSlider.slider.value = button.config.scale.toSliderRange(OnScreenConfiguration.MinScale, OnScreenConfiguration.MaxScale)
+ binding.opacitySlider.slider.value = button.config.alpha.toSliderRange(OnScreenConfiguration.MinAlpha, OnScreenConfiguration.MaxAlpha)
+ if (button is JoystickButton) {
+ binding.toggleModeCheckbox.isGone = true
+ binding.activationSlider.all.isGone = false
+ binding.activationSlider.slider.value = button.config.activationRadius.toSliderRange(OnScreenConfiguration.MinActivationRadius, OnScreenConfiguration.MaxActivationRadius)
+ } else {
+ binding.toggleModeCheckbox.isGone = false
+ binding.toggleModeCheckbox.checkedState = button.config.groupToggleMode
+ binding.activationSlider.all.isGone = true
+ }
}
@SuppressLint("ClickableViewAccessibility")
diff --git a/app/src/main/java/emu/skyline/input/onscreen/OnScreenItemDefinitions.kt b/app/src/main/java/emu/skyline/input/onscreen/OnScreenItemDefinitions.kt
index e8c41e85..4683f2c0 100644
--- a/app/src/main/java/emu/skyline/input/onscreen/OnScreenItemDefinitions.kt
+++ b/app/src/main/java/emu/skyline/input/onscreen/OnScreenItemDefinitions.kt
@@ -6,6 +6,7 @@
package emu.skyline.input.onscreen
import android.graphics.Canvas
+import android.graphics.Color
import android.graphics.Paint
import android.graphics.PointF
import android.graphics.Rect
@@ -67,22 +68,45 @@ open class JoystickButton(
private val innerButton = CircularButton(onScreenControllerView, buttonId, config.relativeX, config.relativeY, defaultRelativeRadiusToX * 0.75f, R.drawable.ic_stick)
open var recenterSticks = false
+ set(value) {
+ field = value
+ radiusModifier = getRadiusModifier()
+ }
+
+ private var radiusModifier = getRadiusModifier()
+ private fun getRadiusModifier() = if (recenterSticks) config.activationRadius else OnScreenConfiguration.DefaultActivationRadius
+
+ fun loadActivationRadius() {
+ radiusModifier = getRadiusModifier()
+ }
+
private var initialTapPosition = PointF()
private var fingerDownTime = 0L
private var fingerUpTime = 0L
var shortDoubleTapped = false
private set
+ override fun isTouched(x : Float, y : Float) = (PointF(currentX, currentY) - (PointF(x, y))).length() <= radius * radiusModifier
+
override fun supportsToggleMode() : Boolean = false
override fun renderCenteredText(canvas : Canvas, text : String, size : Float, x : Float, y : Float, alpha : Int) = Unit
+ private val activationRadiusPaint = Paint().apply {
+ color = onScreenControllerView.context.obtainStyledAttributes(intArrayOf(R.attr.colorPrimary)).use { it.getColor(0, Color.RED) }
+ alpha = 64
+ }
+
override fun render(canvas : Canvas) {
super.render(canvas)
innerButton.width = width
innerButton.height = height
innerButton.render(canvas)
+
+ if (editInfo.isEditing && editInfo.editButton == this) {
+ canvas.drawCircle(currentX, currentY, radius * config.activationRadius, activationRadiusPaint)
+ }
}
override fun onFingerDown(x : Float, y : Float) : Boolean {
@@ -156,6 +180,7 @@ open class JoystickButton(
override fun resetConfig() {
super.resetConfig()
+ config.activationRadius = OnScreenConfiguration.DefaultActivationRadius
innerButton.relativeX = relativeX
innerButton.relativeY = relativeY
diff --git a/app/src/main/res/layout/on_screen_edit_activity.xml b/app/src/main/res/layout/on_screen_edit_activity.xml
index 0b858ca2..dc8dc17d 100644
--- a/app/src/main/res/layout/on_screen_edit_activity.xml
+++ b/app/src/main/res/layout/on_screen_edit_activity.xml
@@ -162,6 +162,15 @@
app:layout_constraintStart_toStartOf="@id/scale_slider"
app:layout_constraintTop_toBottomOf="@id/scale_slider" />
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d5f6b97d..f60a4615 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -168,6 +168,7 @@
Select All
Scale
Opacity
+ Activation Radius
Button color
Toggle grid
Setup Guide
@@ -177,7 +178,7 @@
Cancel
Recenter Sticks On Touch
Use Stick Regions
- When enabled, the stick activaation radius is extended to the corresponding half of the screen.
+ Extend the activation area of the sticks to rectangles covering the corresponding half of the screen
Controller
Configure Controller
Controller Type