mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-27 15:05:31 +03:00
Filter on screen buttons by controller type
This commit is contained in:
parent
2ff06d5421
commit
ce60101989
@ -218,7 +218,10 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
||||
|
||||
// Hide on screen controls when first controller is not set
|
||||
binding.onScreenControllerView.apply {
|
||||
isGone = inputManager.controllers[0]!!.type == ControllerType.None || !settings.onScreenControl
|
||||
inputManager.controllers[0]!!.type.let {
|
||||
controllerType = it
|
||||
isGone = it == ControllerType.None || !settings.onScreenControl
|
||||
}
|
||||
setOnButtonStateChangedListener(::onButtonStateChanged)
|
||||
setOnStickStateChangedListener(::onStickStateChanged)
|
||||
recenterSticks = settings.onScreenControlRecenterSticks
|
||||
@ -414,14 +417,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
||||
|
||||
private fun onButtonStateChanged(buttonId : ButtonId, state : ButtonState) = setButtonState(0, buttonId.value(), state.state)
|
||||
|
||||
private fun onStickStateChanged(buttonId : ButtonId, position : PointF) {
|
||||
val stickId = when (buttonId) {
|
||||
ButtonId.LeftStick -> StickId.Left
|
||||
|
||||
ButtonId.RightStick -> StickId.Right
|
||||
|
||||
else -> error("Invalid button ID")
|
||||
}
|
||||
private fun onStickStateChanged(stickId : StickId, position : PointF) {
|
||||
setAxisValue(0, stickId.xAxis.ordinal, (position.x * Short.MAX_VALUE).toInt())
|
||||
setAxisValue(0, stickId.yAxis.ordinal, (-position.y * Short.MAX_VALUE).toInt()) // Y is inverted, since drawing starts from top left
|
||||
}
|
||||
|
@ -17,22 +17,35 @@ import android.view.View
|
||||
import android.view.View.OnTouchListener
|
||||
import emu.skyline.input.ButtonId
|
||||
import emu.skyline.input.ButtonState
|
||||
import emu.skyline.input.ControllerType
|
||||
import emu.skyline.input.StickId
|
||||
import emu.skyline.utils.add
|
||||
import emu.skyline.utils.multiply
|
||||
import emu.skyline.utils.normalize
|
||||
import kotlin.math.roundToLong
|
||||
|
||||
typealias OnButtonStateChangedListener = (buttonId : ButtonId, state : ButtonState) -> Unit
|
||||
typealias OnStickStateChangedListener = (buttonId : ButtonId, position : PointF) -> Unit
|
||||
typealias OnStickStateChangedListener = (stickId : StickId, position : PointF) -> Unit
|
||||
|
||||
/**
|
||||
* Renders On-Screen Controls as a single view, handles touch inputs and button toggling
|
||||
*/
|
||||
class OnScreenControllerView @JvmOverloads constructor(context : Context, attrs : AttributeSet? = null, defStyleAttr : Int = 0, defStyleRes : Int = 0) : View(context, attrs, defStyleAttr, defStyleRes) {
|
||||
companion object {
|
||||
private val controllerTypeMappings = mapOf(*ControllerType.values().map {
|
||||
it to (setOf(*it.buttons) to setOf(*it.sticks))
|
||||
}.toTypedArray())
|
||||
}
|
||||
|
||||
private val controls = Controls(this)
|
||||
private var onButtonStateChangedListener : OnButtonStateChangedListener? = null
|
||||
private var onStickStateChangedListener : OnStickStateChangedListener? = null
|
||||
private val joystickAnimators = mutableMapOf<JoystickButton, Animator?>()
|
||||
var controllerType : ControllerType? = null
|
||||
set(value) {
|
||||
field = value
|
||||
invalidate()
|
||||
}
|
||||
var recenterSticks = false
|
||||
set(value) {
|
||||
field = value
|
||||
@ -42,11 +55,16 @@ class OnScreenControllerView @JvmOverloads constructor(context : Context, attrs
|
||||
override fun onDraw(canvas : Canvas) {
|
||||
super.onDraw(canvas)
|
||||
|
||||
controls.allButtons.forEach {
|
||||
if (it.config.enabled) {
|
||||
it.width = width
|
||||
it.height = height
|
||||
it.render(canvas)
|
||||
val allowedIds = controllerTypeMappings[controllerType]
|
||||
controls.allButtons.forEach { button ->
|
||||
if (button.config.enabled
|
||||
&& allowedIds?.let { (buttonIds, stickIds) ->
|
||||
if (button is JoystickButton) stickIds.contains(button.stickId) else buttonIds.contains(button.buttonId)
|
||||
} != false
|
||||
) {
|
||||
button.width = width
|
||||
button.height = height
|
||||
button.render(canvas)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -128,14 +146,14 @@ class OnScreenControllerView @JvmOverloads constructor(context : Context, attrs
|
||||
val vector = direction.multiply(value)
|
||||
val newPosition = position.add(vector)
|
||||
joystick.onFingerMoved(newPosition.x, newPosition.y, false)
|
||||
onStickStateChangedListener?.invoke(joystick.buttonId, vector.multiply(1f / radius))
|
||||
onStickStateChangedListener?.invoke(joystick.stickId, vector.multiply(1f / radius))
|
||||
invalidate()
|
||||
}
|
||||
addListener(object : AnimatorListenerAdapter() {
|
||||
override fun onAnimationCancel(animation : Animator?) {
|
||||
super.onAnimationCancel(animation)
|
||||
onAnimationEnd(animation)
|
||||
onStickStateChangedListener?.invoke(joystick.buttonId, PointF(0f, 0f))
|
||||
onStickStateChangedListener?.invoke(joystick.stickId, PointF(0f, 0f))
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(animation : Animator?) {
|
||||
@ -163,7 +181,7 @@ class OnScreenControllerView @JvmOverloads constructor(context : Context, attrs
|
||||
if (joystick.shortDoubleTapped)
|
||||
onButtonStateChangedListener?.invoke(joystick.buttonId, ButtonState.Pressed)
|
||||
if (recenterSticks)
|
||||
onStickStateChangedListener?.invoke(joystick.buttonId, joystick.outerToInnerRelative())
|
||||
onStickStateChangedListener?.invoke(joystick.stickId, joystick.outerToInnerRelative())
|
||||
performClick()
|
||||
handled = true
|
||||
}
|
||||
@ -173,7 +191,7 @@ class OnScreenControllerView @JvmOverloads constructor(context : Context, attrs
|
||||
for (i in 0 until event.pointerCount) {
|
||||
if (event.getPointerId(i) == joystick.touchPointerId) {
|
||||
val centerToPoint = joystick.onFingerMoved(event.getX(i), event.getY(i))
|
||||
onStickStateChangedListener?.invoke(joystick.buttonId, centerToPoint)
|
||||
onStickStateChangedListener?.invoke(joystick.stickId, centerToPoint)
|
||||
handled = true
|
||||
}
|
||||
}
|
||||
|
@ -12,25 +12,27 @@ import androidx.core.graphics.minus
|
||||
import emu.skyline.R
|
||||
import emu.skyline.input.ButtonId
|
||||
import emu.skyline.input.ButtonId.*
|
||||
import emu.skyline.input.StickId
|
||||
import emu.skyline.input.StickId.*
|
||||
import emu.skyline.utils.add
|
||||
import emu.skyline.utils.multiply
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
open class CircularButton(
|
||||
onScreenControllerView : OnScreenControllerView,
|
||||
buttonId : ButtonId,
|
||||
defaultRelativeX : Float,
|
||||
defaultRelativeY : Float,
|
||||
defaultRelativeRadiusToX : Float,
|
||||
drawableId : Int = R.drawable.ic_button
|
||||
onScreenControllerView : OnScreenControllerView,
|
||||
buttonId : ButtonId,
|
||||
defaultRelativeX : Float,
|
||||
defaultRelativeY : Float,
|
||||
defaultRelativeRadiusToX : Float,
|
||||
drawableId : Int = R.drawable.ic_button
|
||||
) : OnScreenButton(
|
||||
onScreenControllerView,
|
||||
buttonId,
|
||||
defaultRelativeX,
|
||||
defaultRelativeY,
|
||||
defaultRelativeRadiusToX * 2f,
|
||||
defaultRelativeRadiusToX * CONFIGURED_ASPECT_RATIO * 2f,
|
||||
drawableId
|
||||
onScreenControllerView,
|
||||
buttonId,
|
||||
defaultRelativeX,
|
||||
defaultRelativeY,
|
||||
defaultRelativeRadiusToX * 2f,
|
||||
defaultRelativeRadiusToX * CONFIGURED_ASPECT_RATIO * 2f,
|
||||
drawableId
|
||||
) {
|
||||
val radius get() = itemWidth / 2f
|
||||
|
||||
@ -49,18 +51,18 @@ open class CircularButton(
|
||||
}
|
||||
|
||||
class JoystickButton(
|
||||
onScreenControllerView : OnScreenControllerView,
|
||||
buttonId : ButtonId,
|
||||
defaultRelativeX : Float,
|
||||
defaultRelativeY : Float,
|
||||
defaultRelativeRadiusToX : Float
|
||||
onScreenControllerView : OnScreenControllerView,
|
||||
val stickId : StickId,
|
||||
defaultRelativeX : Float,
|
||||
defaultRelativeY : Float,
|
||||
defaultRelativeRadiusToX : Float
|
||||
) : CircularButton(
|
||||
onScreenControllerView,
|
||||
buttonId,
|
||||
defaultRelativeX,
|
||||
defaultRelativeY,
|
||||
defaultRelativeRadiusToX,
|
||||
R.drawable.ic_button
|
||||
onScreenControllerView,
|
||||
stickId.button,
|
||||
defaultRelativeX,
|
||||
defaultRelativeY,
|
||||
defaultRelativeRadiusToX,
|
||||
R.drawable.ic_button
|
||||
) {
|
||||
private val innerButton = CircularButton(onScreenControllerView, buttonId, config.relativeX, config.relativeY, defaultRelativeRadiusToX * 0.75f, R.drawable.ic_stick)
|
||||
|
||||
@ -155,21 +157,21 @@ class JoystickButton(
|
||||
}
|
||||
|
||||
open class RectangularButton(
|
||||
onScreenControllerView : OnScreenControllerView,
|
||||
buttonId : ButtonId,
|
||||
defaultRelativeX : Float,
|
||||
defaultRelativeY : Float,
|
||||
defaultRelativeWidth : Float,
|
||||
defaultRelativeHeight : Float,
|
||||
drawableId : Int = R.drawable.ic_rectangular_button
|
||||
onScreenControllerView : OnScreenControllerView,
|
||||
buttonId : ButtonId,
|
||||
defaultRelativeX : Float,
|
||||
defaultRelativeY : Float,
|
||||
defaultRelativeWidth : Float,
|
||||
defaultRelativeHeight : Float,
|
||||
drawableId : Int = R.drawable.ic_rectangular_button
|
||||
) : OnScreenButton(
|
||||
onScreenControllerView,
|
||||
buttonId,
|
||||
defaultRelativeX,
|
||||
defaultRelativeY,
|
||||
defaultRelativeWidth,
|
||||
defaultRelativeHeight,
|
||||
drawableId
|
||||
onScreenControllerView,
|
||||
buttonId,
|
||||
defaultRelativeX,
|
||||
defaultRelativeY,
|
||||
defaultRelativeWidth,
|
||||
defaultRelativeHeight,
|
||||
drawableId
|
||||
) {
|
||||
override fun isTouched(x : Float, y : Float) = currentBounds.contains(x.roundToInt(), y.roundToInt())
|
||||
|
||||
@ -183,26 +185,26 @@ open class RectangularButton(
|
||||
}
|
||||
|
||||
class TriggerButton(
|
||||
onScreenControllerView : OnScreenControllerView,
|
||||
buttonId : ButtonId,
|
||||
defaultRelativeX : Float,
|
||||
defaultRelativeY : Float,
|
||||
defaultRelativeWidth : Float,
|
||||
defaultRelativeHeight : Float
|
||||
onScreenControllerView : OnScreenControllerView,
|
||||
buttonId : ButtonId,
|
||||
defaultRelativeX : Float,
|
||||
defaultRelativeY : Float,
|
||||
defaultRelativeWidth : Float,
|
||||
defaultRelativeHeight : Float
|
||||
) : RectangularButton(
|
||||
onScreenControllerView,
|
||||
buttonId,
|
||||
defaultRelativeX,
|
||||
defaultRelativeY,
|
||||
defaultRelativeWidth,
|
||||
defaultRelativeHeight,
|
||||
when (buttonId) {
|
||||
ZL -> R.drawable.ic_trigger_button_left
|
||||
onScreenControllerView,
|
||||
buttonId,
|
||||
defaultRelativeX,
|
||||
defaultRelativeY,
|
||||
defaultRelativeWidth,
|
||||
defaultRelativeHeight,
|
||||
when (buttonId) {
|
||||
ZL -> R.drawable.ic_trigger_button_left
|
||||
|
||||
ZR -> R.drawable.ic_trigger_button_right
|
||||
ZR -> R.drawable.ic_trigger_button_right
|
||||
|
||||
else -> error("Unsupported trigger button")
|
||||
}
|
||||
else -> error("Unsupported trigger button")
|
||||
}
|
||||
)
|
||||
|
||||
class Controls(onScreenControllerView : OnScreenControllerView) {
|
||||
@ -229,14 +231,14 @@ class Controls(onScreenControllerView : OnScreenControllerView) {
|
||||
val buttonPairs = circularButtonPairs + triggerButtonPairs
|
||||
|
||||
val circularButtons = circularButtonPairs.flatten() + listOf(
|
||||
CircularButton(onScreenControllerView, Plus, 0.57f, 0.75f, 0.025f),
|
||||
CircularButton(onScreenControllerView, Minus, 0.43f, 0.75f, 0.025f),
|
||||
CircularButton(onScreenControllerView, Menu, 0.5f, 0.75f, 0.025f)
|
||||
CircularButton(onScreenControllerView, Plus, 0.57f, 0.75f, 0.025f),
|
||||
CircularButton(onScreenControllerView, Minus, 0.43f, 0.75f, 0.025f),
|
||||
CircularButton(onScreenControllerView, Menu, 0.5f, 0.75f, 0.025f)
|
||||
)
|
||||
|
||||
val joysticks = listOf(
|
||||
JoystickButton(onScreenControllerView, LeftStick, 0.1f, 0.8f, 0.05f),
|
||||
JoystickButton(onScreenControllerView, RightStick, 0.75f, 0.6f, 0.05f)
|
||||
JoystickButton(onScreenControllerView, Left, 0.1f, 0.8f, 0.05f),
|
||||
JoystickButton(onScreenControllerView, Right, 0.75f, 0.6f, 0.05f)
|
||||
)
|
||||
|
||||
val rectangularButtons = listOf(buttonL, buttonR)
|
||||
|
@ -4,6 +4,7 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
@ -20,7 +21,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
app:layout_scrollFlags="enterAlwaysCollapsed">
|
||||
app:layout_scrollFlags="scroll">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
|
Loading…
Reference in New Issue
Block a user