mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-22 16:41:50 +01:00
Implement OSC customizable stick activation radius
This commit is contained in:
parent
d86b2ec3e9
commit
563c72afa9
@ -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)
|
||||
}
|
||||
|
@ -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) {}
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
@ -162,6 +162,15 @@
|
||||
app:layout_constraintStart_toStartOf="@id/scale_slider"
|
||||
app:layout_constraintTop_toBottomOf="@id/scale_slider" />
|
||||
|
||||
<include
|
||||
android:id="@+id/activation_slider"
|
||||
layout="@layout/osc_slider"
|
||||
android:layout_width="160dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
app:layout_constraintStart_toStartOf="@id/scale_slider"
|
||||
app:layout_constraintTop_toBottomOf="@id/opacity_slider" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/sliders_barrier"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -2,6 +2,7 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/all"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
@ -168,6 +168,7 @@
|
||||
<string name="select_all">Select All</string>
|
||||
<string name="osc_scale">Scale</string>
|
||||
<string name="osc_opacity">Opacity</string>
|
||||
<string name="osc_activation_radius">Activation Radius</string>
|
||||
<string name="button_color">Button color</string>
|
||||
<string name="toggle_grid">Toggle grid</string>
|
||||
<string name="setup_guide">Setup Guide</string>
|
||||
@ -177,7 +178,7 @@
|
||||
<string name="cancel">Cancel</string>
|
||||
<string name="osc_recenter_sticks">Recenter Sticks On Touch</string>
|
||||
<string name="osc_use_stick_regions">Use Stick Regions</string>
|
||||
<string name="osc_use_stick_regions_desc">When enabled, the stick activaation radius is extended to the corresponding half of the screen.</string>
|
||||
<string name="osc_use_stick_regions_desc">Extend the activation area of the sticks to rectangles covering the corresponding half of the screen</string>
|
||||
<string name="controller">Controller</string>
|
||||
<string name="config_controller">Configure Controller</string>
|
||||
<string name="controller_type">Controller Type</string>
|
||||
|
Loading…
Reference in New Issue
Block a user