mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-22 14:39:18 +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 MaxScale = 2.5f
|
||||||
const val DefaultScale = 1f
|
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 DefaultTextColor = SwitchColors.BLACK.color
|
||||||
val DefaultBackgroundColor = SwitchColors.WHITE.color
|
val DefaultBackgroundColor = SwitchColors.WHITE.color
|
||||||
}
|
}
|
||||||
@ -51,6 +55,11 @@ interface OnScreenConfiguration {
|
|||||||
var scale : Float
|
var scale : Float
|
||||||
var relativeX : Float
|
var relativeX : Float
|
||||||
var relativeY : 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 {
|
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 scale by config(OnScreenConfiguration.DefaultScale)
|
||||||
override var relativeX by config(defaultRelativeX)
|
override var relativeX by config(defaultRelativeX)
|
||||||
override var relativeY by config(defaultRelativeY)
|
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()
|
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() {
|
fun moveButtonUp() {
|
||||||
editInfo.editButton.moveUp()
|
editInfo.editButton.moveUp()
|
||||||
invalidate()
|
invalidate()
|
||||||
@ -462,6 +472,7 @@ class OnScreenControllerView @JvmOverloads constructor(context : Context, attrs
|
|||||||
|
|
||||||
override var relativeX = 0f
|
override var relativeX = 0f
|
||||||
override var relativeY = 0f
|
override var relativeY = 0f
|
||||||
|
override var activationRadius = 0f
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun startMove(x : Float, y : Float) {}
|
override fun startMove(x : Float, y : Float) {}
|
||||||
|
@ -120,6 +120,9 @@ class OnScreenEditActivity : AppCompatActivity() {
|
|||||||
populateSlider(binding.opacitySlider, getString(R.string.osc_opacity)) {
|
populateSlider(binding.opacitySlider, getString(R.string.osc_opacity)) {
|
||||||
binding.onScreenControllerView.setButtonOpacity(it)
|
binding.onScreenControllerView.setButtonOpacity(it)
|
||||||
}
|
}
|
||||||
|
populateSlider(binding.activationSlider, getString(R.string.osc_activation_radius)) {
|
||||||
|
binding.onScreenControllerView.setStickActivationRadius(it)
|
||||||
|
}
|
||||||
|
|
||||||
binding.enabledCheckbox.setOnClickListener { _ ->
|
binding.enabledCheckbox.setOnClickListener { _ ->
|
||||||
binding.onScreenControllerView.setButtonEnabled(binding.enabledCheckbox.isChecked)
|
binding.onScreenControllerView.setButtonEnabled(binding.enabledCheckbox.isChecked)
|
||||||
@ -190,6 +193,8 @@ class OnScreenEditActivity : AppCompatActivity() {
|
|||||||
if (fromUser)
|
if (fromUser)
|
||||||
valueListener?.invoke(value.roundToInt())
|
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
|
* Updates the control panel UI elements to reflect the currently selected button
|
||||||
*/
|
*/
|
||||||
private fun updateActiveButtonDisplayInfo(button : ConfigurableButton) {
|
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.enabledCheckbox.checkedState = button.config.groupEnabled
|
||||||
binding.toggleModeCheckbox.isEnabled = button.supportsToggleMode()
|
|
||||||
binding.toggleModeCheckbox.checkedState = button.config.groupToggleMode
|
|
||||||
currentButtonName = button.buttonId.short ?: ""
|
currentButtonName = button.buttonId.short ?: ""
|
||||||
binding.currentButton.text = getString(R.string.osc_current_button, currentButtonName)
|
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.scaleSlider.slider.value = button.config.scale.toSliderRange(OnScreenConfiguration.MinScale, OnScreenConfiguration.MaxScale)
|
||||||
binding.opacitySlider.slider.value = (button.config.alpha - OnScreenConfiguration.MinAlpha) / (OnScreenConfiguration.MaxAlpha - OnScreenConfiguration.MinAlpha).toFloat() * 100f
|
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")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
package emu.skyline.input.onscreen
|
package emu.skyline.input.onscreen
|
||||||
|
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Color
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
import android.graphics.PointF
|
import android.graphics.PointF
|
||||||
import android.graphics.Rect
|
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)
|
private val innerButton = CircularButton(onScreenControllerView, buttonId, config.relativeX, config.relativeY, defaultRelativeRadiusToX * 0.75f, R.drawable.ic_stick)
|
||||||
|
|
||||||
open var recenterSticks = false
|
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 initialTapPosition = PointF()
|
||||||
private var fingerDownTime = 0L
|
private var fingerDownTime = 0L
|
||||||
private var fingerUpTime = 0L
|
private var fingerUpTime = 0L
|
||||||
var shortDoubleTapped = false
|
var shortDoubleTapped = false
|
||||||
private set
|
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 supportsToggleMode() : Boolean = false
|
||||||
|
|
||||||
override fun renderCenteredText(canvas : Canvas, text : String, size : Float, x : Float, y : Float, alpha : Int) = Unit
|
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) {
|
override fun render(canvas : Canvas) {
|
||||||
super.render(canvas)
|
super.render(canvas)
|
||||||
|
|
||||||
innerButton.width = width
|
innerButton.width = width
|
||||||
innerButton.height = height
|
innerButton.height = height
|
||||||
innerButton.render(canvas)
|
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 {
|
override fun onFingerDown(x : Float, y : Float) : Boolean {
|
||||||
@ -156,6 +180,7 @@ open class JoystickButton(
|
|||||||
|
|
||||||
override fun resetConfig() {
|
override fun resetConfig() {
|
||||||
super.resetConfig()
|
super.resetConfig()
|
||||||
|
config.activationRadius = OnScreenConfiguration.DefaultActivationRadius
|
||||||
|
|
||||||
innerButton.relativeX = relativeX
|
innerButton.relativeX = relativeX
|
||||||
innerButton.relativeY = relativeY
|
innerButton.relativeY = relativeY
|
||||||
|
@ -162,6 +162,15 @@
|
|||||||
app:layout_constraintStart_toStartOf="@id/scale_slider"
|
app:layout_constraintStart_toStartOf="@id/scale_slider"
|
||||||
app:layout_constraintTop_toBottomOf="@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
|
<androidx.constraintlayout.widget.Barrier
|
||||||
android:id="@+id/sliders_barrier"
|
android:id="@+id/sliders_barrier"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/all"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
@ -168,6 +168,7 @@
|
|||||||
<string name="select_all">Select All</string>
|
<string name="select_all">Select All</string>
|
||||||
<string name="osc_scale">Scale</string>
|
<string name="osc_scale">Scale</string>
|
||||||
<string name="osc_opacity">Opacity</string>
|
<string name="osc_opacity">Opacity</string>
|
||||||
|
<string name="osc_activation_radius">Activation Radius</string>
|
||||||
<string name="button_color">Button color</string>
|
<string name="button_color">Button color</string>
|
||||||
<string name="toggle_grid">Toggle grid</string>
|
<string name="toggle_grid">Toggle grid</string>
|
||||||
<string name="setup_guide">Setup Guide</string>
|
<string name="setup_guide">Setup Guide</string>
|
||||||
@ -177,7 +178,7 @@
|
|||||||
<string name="cancel">Cancel</string>
|
<string name="cancel">Cancel</string>
|
||||||
<string name="osc_recenter_sticks">Recenter Sticks On Touch</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">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="controller">Controller</string>
|
||||||
<string name="config_controller">Configure Controller</string>
|
<string name="config_controller">Configure Controller</string>
|
||||||
<string name="controller_type">Controller Type</string>
|
<string name="controller_type">Controller Type</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user