mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-28 07:45:37 +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
|
// Hide on screen controls when first controller is not set
|
||||||
binding.onScreenControllerView.apply {
|
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)
|
setOnButtonStateChangedListener(::onButtonStateChanged)
|
||||||
setOnStickStateChangedListener(::onStickStateChanged)
|
setOnStickStateChangedListener(::onStickStateChanged)
|
||||||
recenterSticks = settings.onScreenControlRecenterSticks
|
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 onButtonStateChanged(buttonId : ButtonId, state : ButtonState) = setButtonState(0, buttonId.value(), state.state)
|
||||||
|
|
||||||
private fun onStickStateChanged(buttonId : ButtonId, position : PointF) {
|
private fun onStickStateChanged(stickId : StickId, position : PointF) {
|
||||||
val stickId = when (buttonId) {
|
|
||||||
ButtonId.LeftStick -> StickId.Left
|
|
||||||
|
|
||||||
ButtonId.RightStick -> StickId.Right
|
|
||||||
|
|
||||||
else -> error("Invalid button ID")
|
|
||||||
}
|
|
||||||
setAxisValue(0, stickId.xAxis.ordinal, (position.x * Short.MAX_VALUE).toInt())
|
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
|
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 android.view.View.OnTouchListener
|
||||||
import emu.skyline.input.ButtonId
|
import emu.skyline.input.ButtonId
|
||||||
import emu.skyline.input.ButtonState
|
import emu.skyline.input.ButtonState
|
||||||
|
import emu.skyline.input.ControllerType
|
||||||
|
import emu.skyline.input.StickId
|
||||||
import emu.skyline.utils.add
|
import emu.skyline.utils.add
|
||||||
import emu.skyline.utils.multiply
|
import emu.skyline.utils.multiply
|
||||||
import emu.skyline.utils.normalize
|
import emu.skyline.utils.normalize
|
||||||
import kotlin.math.roundToLong
|
import kotlin.math.roundToLong
|
||||||
|
|
||||||
typealias OnButtonStateChangedListener = (buttonId : ButtonId, state : ButtonState) -> Unit
|
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
|
* 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) {
|
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 val controls = Controls(this)
|
||||||
private var onButtonStateChangedListener : OnButtonStateChangedListener? = null
|
private var onButtonStateChangedListener : OnButtonStateChangedListener? = null
|
||||||
private var onStickStateChangedListener : OnStickStateChangedListener? = null
|
private var onStickStateChangedListener : OnStickStateChangedListener? = null
|
||||||
private val joystickAnimators = mutableMapOf<JoystickButton, Animator?>()
|
private val joystickAnimators = mutableMapOf<JoystickButton, Animator?>()
|
||||||
|
var controllerType : ControllerType? = null
|
||||||
|
set(value) {
|
||||||
|
field = value
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
var recenterSticks = false
|
var recenterSticks = false
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
@ -42,11 +55,16 @@ class OnScreenControllerView @JvmOverloads constructor(context : Context, attrs
|
|||||||
override fun onDraw(canvas : Canvas) {
|
override fun onDraw(canvas : Canvas) {
|
||||||
super.onDraw(canvas)
|
super.onDraw(canvas)
|
||||||
|
|
||||||
controls.allButtons.forEach {
|
val allowedIds = controllerTypeMappings[controllerType]
|
||||||
if (it.config.enabled) {
|
controls.allButtons.forEach { button ->
|
||||||
it.width = width
|
if (button.config.enabled
|
||||||
it.height = height
|
&& allowedIds?.let { (buttonIds, stickIds) ->
|
||||||
it.render(canvas)
|
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 vector = direction.multiply(value)
|
||||||
val newPosition = position.add(vector)
|
val newPosition = position.add(vector)
|
||||||
joystick.onFingerMoved(newPosition.x, newPosition.y, false)
|
joystick.onFingerMoved(newPosition.x, newPosition.y, false)
|
||||||
onStickStateChangedListener?.invoke(joystick.buttonId, vector.multiply(1f / radius))
|
onStickStateChangedListener?.invoke(joystick.stickId, vector.multiply(1f / radius))
|
||||||
invalidate()
|
invalidate()
|
||||||
}
|
}
|
||||||
addListener(object : AnimatorListenerAdapter() {
|
addListener(object : AnimatorListenerAdapter() {
|
||||||
override fun onAnimationCancel(animation : Animator?) {
|
override fun onAnimationCancel(animation : Animator?) {
|
||||||
super.onAnimationCancel(animation)
|
super.onAnimationCancel(animation)
|
||||||
onAnimationEnd(animation)
|
onAnimationEnd(animation)
|
||||||
onStickStateChangedListener?.invoke(joystick.buttonId, PointF(0f, 0f))
|
onStickStateChangedListener?.invoke(joystick.stickId, PointF(0f, 0f))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAnimationEnd(animation : Animator?) {
|
override fun onAnimationEnd(animation : Animator?) {
|
||||||
@ -163,7 +181,7 @@ class OnScreenControllerView @JvmOverloads constructor(context : Context, attrs
|
|||||||
if (joystick.shortDoubleTapped)
|
if (joystick.shortDoubleTapped)
|
||||||
onButtonStateChangedListener?.invoke(joystick.buttonId, ButtonState.Pressed)
|
onButtonStateChangedListener?.invoke(joystick.buttonId, ButtonState.Pressed)
|
||||||
if (recenterSticks)
|
if (recenterSticks)
|
||||||
onStickStateChangedListener?.invoke(joystick.buttonId, joystick.outerToInnerRelative())
|
onStickStateChangedListener?.invoke(joystick.stickId, joystick.outerToInnerRelative())
|
||||||
performClick()
|
performClick()
|
||||||
handled = true
|
handled = true
|
||||||
}
|
}
|
||||||
@ -173,7 +191,7 @@ class OnScreenControllerView @JvmOverloads constructor(context : Context, attrs
|
|||||||
for (i in 0 until event.pointerCount) {
|
for (i in 0 until event.pointerCount) {
|
||||||
if (event.getPointerId(i) == joystick.touchPointerId) {
|
if (event.getPointerId(i) == joystick.touchPointerId) {
|
||||||
val centerToPoint = joystick.onFingerMoved(event.getX(i), event.getY(i))
|
val centerToPoint = joystick.onFingerMoved(event.getX(i), event.getY(i))
|
||||||
onStickStateChangedListener?.invoke(joystick.buttonId, centerToPoint)
|
onStickStateChangedListener?.invoke(joystick.stickId, centerToPoint)
|
||||||
handled = true
|
handled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,25 +12,27 @@ import androidx.core.graphics.minus
|
|||||||
import emu.skyline.R
|
import emu.skyline.R
|
||||||
import emu.skyline.input.ButtonId
|
import emu.skyline.input.ButtonId
|
||||||
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.add
|
||||||
import emu.skyline.utils.multiply
|
import emu.skyline.utils.multiply
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
open class CircularButton(
|
open class CircularButton(
|
||||||
onScreenControllerView : OnScreenControllerView,
|
onScreenControllerView : OnScreenControllerView,
|
||||||
buttonId : ButtonId,
|
buttonId : ButtonId,
|
||||||
defaultRelativeX : Float,
|
defaultRelativeX : Float,
|
||||||
defaultRelativeY : Float,
|
defaultRelativeY : Float,
|
||||||
defaultRelativeRadiusToX : Float,
|
defaultRelativeRadiusToX : Float,
|
||||||
drawableId : Int = R.drawable.ic_button
|
drawableId : Int = R.drawable.ic_button
|
||||||
) : OnScreenButton(
|
) : OnScreenButton(
|
||||||
onScreenControllerView,
|
onScreenControllerView,
|
||||||
buttonId,
|
buttonId,
|
||||||
defaultRelativeX,
|
defaultRelativeX,
|
||||||
defaultRelativeY,
|
defaultRelativeY,
|
||||||
defaultRelativeRadiusToX * 2f,
|
defaultRelativeRadiusToX * 2f,
|
||||||
defaultRelativeRadiusToX * CONFIGURED_ASPECT_RATIO * 2f,
|
defaultRelativeRadiusToX * CONFIGURED_ASPECT_RATIO * 2f,
|
||||||
drawableId
|
drawableId
|
||||||
) {
|
) {
|
||||||
val radius get() = itemWidth / 2f
|
val radius get() = itemWidth / 2f
|
||||||
|
|
||||||
@ -49,18 +51,18 @@ open class CircularButton(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class JoystickButton(
|
class JoystickButton(
|
||||||
onScreenControllerView : OnScreenControllerView,
|
onScreenControllerView : OnScreenControllerView,
|
||||||
buttonId : ButtonId,
|
val stickId : StickId,
|
||||||
defaultRelativeX : Float,
|
defaultRelativeX : Float,
|
||||||
defaultRelativeY : Float,
|
defaultRelativeY : Float,
|
||||||
defaultRelativeRadiusToX : Float
|
defaultRelativeRadiusToX : Float
|
||||||
) : CircularButton(
|
) : CircularButton(
|
||||||
onScreenControllerView,
|
onScreenControllerView,
|
||||||
buttonId,
|
stickId.button,
|
||||||
defaultRelativeX,
|
defaultRelativeX,
|
||||||
defaultRelativeY,
|
defaultRelativeY,
|
||||||
defaultRelativeRadiusToX,
|
defaultRelativeRadiusToX,
|
||||||
R.drawable.ic_button
|
R.drawable.ic_button
|
||||||
) {
|
) {
|
||||||
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)
|
||||||
|
|
||||||
@ -155,21 +157,21 @@ class JoystickButton(
|
|||||||
}
|
}
|
||||||
|
|
||||||
open class RectangularButton(
|
open class RectangularButton(
|
||||||
onScreenControllerView : OnScreenControllerView,
|
onScreenControllerView : OnScreenControllerView,
|
||||||
buttonId : ButtonId,
|
buttonId : ButtonId,
|
||||||
defaultRelativeX : Float,
|
defaultRelativeX : Float,
|
||||||
defaultRelativeY : Float,
|
defaultRelativeY : Float,
|
||||||
defaultRelativeWidth : Float,
|
defaultRelativeWidth : Float,
|
||||||
defaultRelativeHeight : Float,
|
defaultRelativeHeight : Float,
|
||||||
drawableId : Int = R.drawable.ic_rectangular_button
|
drawableId : Int = R.drawable.ic_rectangular_button
|
||||||
) : OnScreenButton(
|
) : OnScreenButton(
|
||||||
onScreenControllerView,
|
onScreenControllerView,
|
||||||
buttonId,
|
buttonId,
|
||||||
defaultRelativeX,
|
defaultRelativeX,
|
||||||
defaultRelativeY,
|
defaultRelativeY,
|
||||||
defaultRelativeWidth,
|
defaultRelativeWidth,
|
||||||
defaultRelativeHeight,
|
defaultRelativeHeight,
|
||||||
drawableId
|
drawableId
|
||||||
) {
|
) {
|
||||||
override fun isTouched(x : Float, y : Float) = currentBounds.contains(x.roundToInt(), y.roundToInt())
|
override fun isTouched(x : Float, y : Float) = currentBounds.contains(x.roundToInt(), y.roundToInt())
|
||||||
|
|
||||||
@ -183,26 +185,26 @@ open class RectangularButton(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TriggerButton(
|
class TriggerButton(
|
||||||
onScreenControllerView : OnScreenControllerView,
|
onScreenControllerView : OnScreenControllerView,
|
||||||
buttonId : ButtonId,
|
buttonId : ButtonId,
|
||||||
defaultRelativeX : Float,
|
defaultRelativeX : Float,
|
||||||
defaultRelativeY : Float,
|
defaultRelativeY : Float,
|
||||||
defaultRelativeWidth : Float,
|
defaultRelativeWidth : Float,
|
||||||
defaultRelativeHeight : Float
|
defaultRelativeHeight : Float
|
||||||
) : RectangularButton(
|
) : RectangularButton(
|
||||||
onScreenControllerView,
|
onScreenControllerView,
|
||||||
buttonId,
|
buttonId,
|
||||||
defaultRelativeX,
|
defaultRelativeX,
|
||||||
defaultRelativeY,
|
defaultRelativeY,
|
||||||
defaultRelativeWidth,
|
defaultRelativeWidth,
|
||||||
defaultRelativeHeight,
|
defaultRelativeHeight,
|
||||||
when (buttonId) {
|
when (buttonId) {
|
||||||
ZL -> R.drawable.ic_trigger_button_left
|
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) {
|
class Controls(onScreenControllerView : OnScreenControllerView) {
|
||||||
@ -229,14 +231,14 @@ class Controls(onScreenControllerView : OnScreenControllerView) {
|
|||||||
val buttonPairs = circularButtonPairs + triggerButtonPairs
|
val buttonPairs = circularButtonPairs + triggerButtonPairs
|
||||||
|
|
||||||
val circularButtons = circularButtonPairs.flatten() + listOf(
|
val circularButtons = circularButtonPairs.flatten() + listOf(
|
||||||
CircularButton(onScreenControllerView, Plus, 0.57f, 0.75f, 0.025f),
|
CircularButton(onScreenControllerView, Plus, 0.57f, 0.75f, 0.025f),
|
||||||
CircularButton(onScreenControllerView, Minus, 0.43f, 0.75f, 0.025f),
|
CircularButton(onScreenControllerView, Minus, 0.43f, 0.75f, 0.025f),
|
||||||
CircularButton(onScreenControllerView, Menu, 0.5f, 0.75f, 0.025f)
|
CircularButton(onScreenControllerView, Menu, 0.5f, 0.75f, 0.025f)
|
||||||
)
|
)
|
||||||
|
|
||||||
val joysticks = listOf(
|
val joysticks = listOf(
|
||||||
JoystickButton(onScreenControllerView, LeftStick, 0.1f, 0.8f, 0.05f),
|
JoystickButton(onScreenControllerView, Left, 0.1f, 0.8f, 0.05f),
|
||||||
JoystickButton(onScreenControllerView, RightStick, 0.75f, 0.6f, 0.05f)
|
JoystickButton(onScreenControllerView, Right, 0.75f, 0.6f, 0.05f)
|
||||||
)
|
)
|
||||||
|
|
||||||
val rectangularButtons = listOf(buttonL, buttonR)
|
val rectangularButtons = listOf(buttonL, buttonR)
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
tools:context=".MainActivity">
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
@ -20,7 +21,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fitsSystemWindows="true"
|
android:fitsSystemWindows="true"
|
||||||
app:layout_scrollFlags="enterAlwaysCollapsed">
|
app:layout_scrollFlags="scroll">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
Loading…
Reference in New Issue
Block a user