mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-25 23:15:29 +03:00
Implement toggle mode for OSC buttons
When toggle mode is enabled, the button will toggle between the `Pressed` and `Released` state when it's pressed. Without toggle mode: ACTION_DOWN -> Pressed ACTION_UP -> Released ACTION_DOWN -> Pressed ACTION_UP -> Released With toggle mode: ACTION_DOWN -> Pressed ACTION_UP -> No event ACTION_DOWN -> No event ACTION_UP -> Released
This commit is contained in:
parent
78252fbcbd
commit
560fcd9442
@ -14,6 +14,12 @@ interface ConfigurableButton {
|
||||
val buttonId : ButtonId
|
||||
val config : OnScreenConfiguration
|
||||
|
||||
/**
|
||||
* Returns whether this button supports toggle mode
|
||||
* Usually true for buttons and false for sticks
|
||||
*/
|
||||
fun supportsToggleMode() : Boolean = true
|
||||
|
||||
/**
|
||||
* Starts a button move session
|
||||
* @param x The x coordinate of the initial touch
|
||||
|
@ -107,6 +107,7 @@ abstract class OnScreenButton(
|
||||
var partnerPointerId = -1
|
||||
|
||||
var isPressed = false
|
||||
var isToggled = false
|
||||
|
||||
var hapticFeedback = false
|
||||
|
||||
@ -167,12 +168,26 @@ abstract class OnScreenButton(
|
||||
|
||||
abstract fun isTouched(x : Float, y : Float) : Boolean
|
||||
|
||||
open fun onFingerDown(x : Float, y : Float) {
|
||||
isPressed = true
|
||||
/**
|
||||
* @return Whether button events should be sent to guest
|
||||
*/
|
||||
open fun onFingerDown(x : Float, y : Float) : Boolean {
|
||||
if (!config.toggleMode || !isToggled)
|
||||
isPressed = true
|
||||
|
||||
isToggled = !isToggled
|
||||
|
||||
return !config.toggleMode || isToggled
|
||||
}
|
||||
|
||||
open fun onFingerUp(x : Float, y : Float) {
|
||||
isPressed = false
|
||||
/**
|
||||
* @return Whether button events should be sent to guest
|
||||
*/
|
||||
open fun onFingerUp(x : Float, y : Float) : Boolean {
|
||||
if (!config.toggleMode || !isToggled)
|
||||
isPressed = false
|
||||
|
||||
return !isPressed
|
||||
}
|
||||
|
||||
fun loadConfigValues() {
|
||||
@ -264,6 +279,7 @@ abstract class OnScreenButton(
|
||||
|
||||
override fun resetConfig() {
|
||||
config.enabled = defaultEnabled
|
||||
config.toggleMode = OnScreenConfiguration.DefaultToggleMode
|
||||
config.alpha = OnScreenConfiguration.DefaultAlpha
|
||||
config.textColor = OnScreenConfiguration.DefaultTextColor
|
||||
config.backgroundColor = OnScreenConfiguration.DefaultBackgroundColor
|
||||
|
@ -16,6 +16,8 @@ interface OnScreenConfiguration {
|
||||
const val GroupEnabled = 1
|
||||
const val GroupIndeterminate = 2
|
||||
|
||||
const val DefaultToggleMode = false
|
||||
|
||||
const val MinAlpha = 0
|
||||
const val MaxAlpha = 255
|
||||
const val DefaultAlpha = 128
|
||||
@ -35,6 +37,13 @@ interface OnScreenConfiguration {
|
||||
*/
|
||||
val groupEnabled get() = if (enabled) GroupEnabled else GroupDisabled
|
||||
|
||||
var toggleMode : Boolean
|
||||
|
||||
/**
|
||||
* The toggle mode of group of buttons, returns an integer that can be used to set the state of a MaterialCheckBox
|
||||
*/
|
||||
val groupToggleMode get() = if (toggleMode) GroupEnabled else GroupDisabled
|
||||
|
||||
var alpha : Int
|
||||
var textColor : Int
|
||||
var backgroundColor : Int
|
||||
@ -48,6 +57,7 @@ class OnScreenConfigurationImpl(private val context : Context, private val butto
|
||||
private inline fun <reified T> config(default : T, prefix : String = "${buttonId.name}_") = sharedPreferences(context, default, prefix, "controller_config")
|
||||
|
||||
override var enabled by config(defaultEnabled)
|
||||
override var toggleMode by config(OnScreenConfiguration.DefaultToggleMode)
|
||||
|
||||
override var alpha by config(OnScreenConfiguration.DefaultAlpha)
|
||||
override var textColor by config(OnScreenConfiguration.DefaultTextColor)
|
||||
|
@ -122,13 +122,13 @@ class OnScreenControllerView @JvmOverloads constructor(context : Context, attrs
|
||||
MotionEvent.ACTION_POINTER_UP -> {
|
||||
if (pointerId == button.touchPointerId) {
|
||||
button.touchPointerId = -1
|
||||
button.onFingerUp(x, y)
|
||||
onButtonStateChangedListener?.invoke(button.buttonId, ButtonState.Released)
|
||||
if (button.onFingerUp(x, y))
|
||||
onButtonStateChangedListener?.invoke(button.buttonId, ButtonState.Released)
|
||||
handled = true
|
||||
} else if (pointerId == button.partnerPointerId) {
|
||||
button.partnerPointerId = -1
|
||||
button.onFingerUp(x, y)
|
||||
onButtonStateChangedListener?.invoke(button.buttonId, ButtonState.Released)
|
||||
if (button.onFingerUp(x, y))
|
||||
onButtonStateChangedListener?.invoke(button.buttonId, ButtonState.Released)
|
||||
handled = true
|
||||
}
|
||||
}
|
||||
@ -137,10 +137,10 @@ class OnScreenControllerView @JvmOverloads constructor(context : Context, attrs
|
||||
MotionEvent.ACTION_POINTER_DOWN -> {
|
||||
if (button.config.enabled && button.isTouched(x, y)) {
|
||||
button.touchPointerId = pointerId
|
||||
button.onFingerDown(x, y)
|
||||
if (button.onFingerDown(x, y))
|
||||
onButtonStateChangedListener?.invoke(button.buttonId, ButtonState.Pressed)
|
||||
if (hapticFeedback) vibrator.vibrate(effectClick)
|
||||
performClick()
|
||||
onButtonStateChangedListener?.invoke(button.buttonId, ButtonState.Pressed)
|
||||
handled = true
|
||||
}
|
||||
}
|
||||
@ -153,9 +153,9 @@ class OnScreenControllerView @JvmOverloads constructor(context : Context, attrs
|
||||
for (otherButton in buttonPair) {
|
||||
if (otherButton != button && otherButton.config.enabled && otherButton.isTouched(event.getX(fingerId), event.getY(fingerId))) {
|
||||
otherButton.partnerPointerId = fingerId
|
||||
otherButton.onFingerDown(x, y)
|
||||
if (otherButton.onFingerDown(x, y))
|
||||
onButtonStateChangedListener?.invoke(otherButton.buttonId, ButtonState.Pressed)
|
||||
performClick()
|
||||
onButtonStateChangedListener?.invoke(otherButton.buttonId, ButtonState.Pressed)
|
||||
handled = true
|
||||
}
|
||||
}
|
||||
@ -318,6 +318,11 @@ class OnScreenControllerView @JvmOverloads constructor(context : Context, attrs
|
||||
invalidate()
|
||||
}
|
||||
|
||||
fun setButtonToggleMode(toggleMode : Boolean) {
|
||||
editInfo.editButton.config.toggleMode = toggleMode
|
||||
invalidate()
|
||||
}
|
||||
|
||||
fun setButtonScale(@IntRange(from = 0, to = 100) scale : Int) {
|
||||
fun toScaleRange(value : Int) : Float = (value / 100f) * (OnScreenConfiguration.MaxScale - OnScreenConfiguration.MinScale) + OnScreenConfiguration.MinScale
|
||||
|
||||
@ -398,6 +403,21 @@ class OnScreenControllerView @JvmOverloads constructor(context : Context, attrs
|
||||
return OnScreenConfiguration.GroupIndeterminate
|
||||
}
|
||||
|
||||
override var toggleMode : Boolean
|
||||
get() = controls.allButtons.all { it.supportsToggleMode() == it.config.toggleMode }
|
||||
set(value) {
|
||||
controls.allButtons.forEach { if (it.supportsToggleMode()) it.config.toggleMode = value }
|
||||
}
|
||||
|
||||
override val groupToggleMode : Int
|
||||
get() {
|
||||
if (controls.allButtons.all { !it.supportsToggleMode() || it.config.toggleMode })
|
||||
return OnScreenConfiguration.GroupEnabled
|
||||
if (controls.allButtons.all { !it.supportsToggleMode() || !it.config.toggleMode })
|
||||
return OnScreenConfiguration.GroupDisabled
|
||||
return OnScreenConfiguration.GroupIndeterminate
|
||||
}
|
||||
|
||||
override var alpha : Int
|
||||
get() = controls.allButtons.sumOf { it.config.alpha } / controls.allButtons.size
|
||||
set(value) {
|
||||
|
@ -123,6 +123,9 @@ class OnScreenEditActivity : AppCompatActivity() {
|
||||
binding.enabledCheckbox.setOnClickListener { _ ->
|
||||
binding.onScreenControllerView.setButtonEnabled(binding.enabledCheckbox.isChecked)
|
||||
}
|
||||
binding.toggleModeCheckbox.setOnClickListener { _ ->
|
||||
binding.onScreenControllerView.setButtonToggleMode(binding.toggleModeCheckbox.isChecked)
|
||||
}
|
||||
|
||||
binding.moveUpButton.setOnClickListener { binding.onScreenControllerView.moveButtonUp() }
|
||||
binding.moveDownButton.setOnClickListener { binding.onScreenControllerView.moveButtonDown() }
|
||||
@ -194,6 +197,8 @@ class OnScreenEditActivity : AppCompatActivity() {
|
||||
*/
|
||||
private fun updateActiveButtonDisplayInfo(button : ConfigurableButton) {
|
||||
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
|
||||
|
@ -68,6 +68,8 @@ class JoystickButton(
|
||||
var shortDoubleTapped = false
|
||||
private set
|
||||
|
||||
override fun supportsToggleMode() : Boolean = false
|
||||
|
||||
override fun renderCenteredText(canvas : Canvas, text : String, size : Float, x : Float, y : Float, alpha : Int) = Unit
|
||||
|
||||
override fun render(canvas : Canvas) {
|
||||
@ -78,7 +80,7 @@ class JoystickButton(
|
||||
innerButton.render(canvas)
|
||||
}
|
||||
|
||||
override fun onFingerDown(x : Float, y : Float) {
|
||||
override fun onFingerDown(x : Float, y : Float) : Boolean {
|
||||
val relativeX = x / width
|
||||
val relativeY = (y - heightDiff) / adjustedHeight
|
||||
if (recenterSticks) {
|
||||
@ -99,9 +101,11 @@ class JoystickButton(
|
||||
isPressed = true
|
||||
}
|
||||
fingerDownTime = currentTime
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onFingerUp(x : Float, y : Float) {
|
||||
override fun onFingerUp(x : Float, y : Float) : Boolean {
|
||||
loadConfigValues()
|
||||
innerButton.relativeX = relativeX
|
||||
innerButton.relativeY = relativeY
|
||||
@ -109,6 +113,8 @@ class JoystickButton(
|
||||
fingerUpTime = SystemClock.elapsedRealtime()
|
||||
shortDoubleTapped = false
|
||||
isPressed = false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun onFingerMoved(x : Float, y : Float, manualMove : Boolean = true) : PointF {
|
||||
|
@ -137,7 +137,6 @@
|
||||
android:minHeight="0dp"
|
||||
android:paddingVertical="8dp"
|
||||
android:text="@string/osc_toggle_mode"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="@+id/enabled_checkbox"
|
||||
app:layout_constraintTop_toBottomOf="@id/enabled_checkbox"
|
||||
tools:ignore="TouchTargetSizeCheck" />
|
||||
|
Loading…
Reference in New Issue
Block a user