mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-29 19:05:29 +03:00
Add Controller Setup Guide
A setup guide for controllers that goes through every available button/stick sequentially and opens up a corresponding dialog to map them.
This commit is contained in:
parent
e2cae74425
commit
5dea15632c
@ -35,6 +35,8 @@ class ControllerGeneralViewItem(private val controllerId : Int, val type : Gener
|
|||||||
}
|
}
|
||||||
|
|
||||||
GeneralType.RumbleDevice -> controller.rumbleDeviceName ?: context.getString(R.string.none)
|
GeneralType.RumbleDevice -> controller.rumbleDeviceName ?: context.getString(R.string.none)
|
||||||
|
|
||||||
|
GeneralType.SetupGuide -> context.getString(R.string.setup_guide_description)
|
||||||
}
|
}
|
||||||
super.bind(binding, position)
|
super.bind(binding, position)
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ enum class ControllerType(val stringRes : Int, val firstController : Boolean, va
|
|||||||
enum class GeneralType(val stringRes : Int, val compatibleControllers : Array<ControllerType>? = null) {
|
enum class GeneralType(val stringRes : Int, val compatibleControllers : Array<ControllerType>? = null) {
|
||||||
PartnerJoyCon(R.string.partner_joycon, arrayOf(ControllerType.JoyConLeft)),
|
PartnerJoyCon(R.string.partner_joycon, arrayOf(ControllerType.JoyConLeft)),
|
||||||
RumbleDevice(R.string.rumble_device),
|
RumbleDevice(R.string.rumble_device),
|
||||||
|
SetupGuide(R.string.setup_guide),
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -9,14 +9,15 @@ import android.content.Intent
|
|||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewTreeObserver
|
import android.view.ViewTreeObserver
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.appcompat.app.AppCompatDialogFragment
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.core.view.marginTop
|
import androidx.core.view.marginTop
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration
|
import androidx.recyclerview.widget.DividerItemDecoration
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import emu.skyline.R
|
import emu.skyline.R
|
||||||
@ -55,6 +56,10 @@ class ControllerActivity : AppCompatActivity() {
|
|||||||
*/
|
*/
|
||||||
val axisMap = mutableMapOf<AxisId, ControllerStickViewItem>()
|
val axisMap = mutableMapOf<AxisId, ControllerStickViewItem>()
|
||||||
|
|
||||||
|
val stickItems = mutableListOf<ControllerStickViewItem>()
|
||||||
|
|
||||||
|
val buttonItems = mutableListOf<ControllerButtonViewItem>()
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var settings : Settings
|
lateinit var settings : Settings
|
||||||
|
|
||||||
@ -108,17 +113,14 @@ class ControllerActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wroteTitle = false
|
if (controller.type.sticks.isNotEmpty())
|
||||||
|
items.add(ControllerHeaderItem(getString(R.string.sticks)))
|
||||||
|
|
||||||
for (stick in controller.type.sticks) {
|
for (stick in controller.type.sticks) {
|
||||||
if (!wroteTitle) {
|
|
||||||
items.add(ControllerHeaderItem(getString(R.string.sticks)))
|
|
||||||
wroteTitle = true
|
|
||||||
}
|
|
||||||
|
|
||||||
val stickItem = ControllerStickViewItem(id, stick, onControllerStickClick)
|
val stickItem = ControllerStickViewItem(id, stick, onControllerStickClick)
|
||||||
|
|
||||||
items.add(stickItem)
|
items.add(stickItem)
|
||||||
|
stickItems.add(stickItem)
|
||||||
buttonMap[stick.button] = stickItem
|
buttonMap[stick.button] = stickItem
|
||||||
axisMap[stick.xAxis] = stickItem
|
axisMap[stick.xAxis] = stickItem
|
||||||
axisMap[stick.yAxis] = stickItem
|
axisMap[stick.yAxis] = stickItem
|
||||||
@ -132,32 +134,26 @@ class ControllerActivity : AppCompatActivity() {
|
|||||||
val buttonArrays = arrayOf(dpadButtons, faceButtons, shoulderTriggerButtons, shoulderRailButtons)
|
val buttonArrays = arrayOf(dpadButtons, faceButtons, shoulderTriggerButtons, shoulderRailButtons)
|
||||||
|
|
||||||
for (buttonArray in buttonArrays) {
|
for (buttonArray in buttonArrays) {
|
||||||
wroteTitle = false
|
val filteredButtons = controller.type.buttons.filter { it in buttonArray.second }
|
||||||
|
|
||||||
for (button in controller.type.buttons.filter { it in buttonArray.second }) {
|
if (filteredButtons.isNotEmpty())
|
||||||
if (!wroteTitle) {
|
items.add(ControllerHeaderItem(getString(buttonArray.first)))
|
||||||
items.add(ControllerHeaderItem(getString(buttonArray.first)))
|
|
||||||
wroteTitle = true
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for (button in filteredButtons) {
|
||||||
val buttonItem = ControllerButtonViewItem(id, button, onControllerButtonClick)
|
val buttonItem = ControllerButtonViewItem(id, button, onControllerButtonClick)
|
||||||
|
|
||||||
items.add(buttonItem)
|
items.add(buttonItem)
|
||||||
|
buttonItems.add(buttonItem)
|
||||||
buttonMap[button] = buttonItem
|
buttonMap[button] = buttonItem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wroteTitle = false
|
items.add(ControllerHeaderItem(getString(R.string.misc_buttons))) // The menu button will always exist
|
||||||
|
|
||||||
for (button in controller.type.buttons.filterNot { item -> buttonArrays.any { item in it.second } }.plus(ButtonId.Menu)) {
|
for (button in controller.type.buttons.filterNot { item -> buttonArrays.any { item in it.second } }.plus(ButtonId.Menu)) {
|
||||||
if (!wroteTitle) {
|
|
||||||
items.add(ControllerHeaderItem(getString(R.string.misc_buttons)))
|
|
||||||
wroteTitle = true
|
|
||||||
}
|
|
||||||
|
|
||||||
val buttonItem = ControllerButtonViewItem(id, button, onControllerButtonClick)
|
val buttonItem = ControllerButtonViewItem(id, button, onControllerButtonClick)
|
||||||
|
|
||||||
items.add(buttonItem)
|
items.add(buttonItem)
|
||||||
|
buttonItems.add(buttonItem)
|
||||||
buttonMap[button] = buttonItem
|
buttonMap[button] = buttonItem
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@ -309,6 +305,18 @@ class ControllerActivity : AppCompatActivity() {
|
|||||||
GeneralType.RumbleDevice -> {
|
GeneralType.RumbleDevice -> {
|
||||||
RumbleDialog(item).show(supportFragmentManager, null)
|
RumbleDialog(item).show(supportFragmentManager, null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GeneralType.SetupGuide -> {
|
||||||
|
var dialogFragment : BottomSheetDialogFragment? = null
|
||||||
|
|
||||||
|
for (buttonItem in buttonItems.reversed())
|
||||||
|
dialogFragment = ButtonDialog(buttonItem, dialogFragment)
|
||||||
|
|
||||||
|
for (stickItem in stickItems.reversed())
|
||||||
|
dialogFragment = StickDialog(stickItem, dialogFragment)
|
||||||
|
|
||||||
|
dialogFragment?.show(supportFragmentManager, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Unit
|
Unit
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,8 @@ import android.os.Handler
|
|||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.animation.LinearInterpolator
|
import android.view.animation.LinearInterpolator
|
||||||
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
import androidx.fragment.app.commit
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import emu.skyline.R
|
import emu.skyline.R
|
||||||
@ -25,7 +27,7 @@ import kotlin.math.abs
|
|||||||
*
|
*
|
||||||
* @param item This is used to hold the [ControllerButtonViewItem] between instances
|
* @param item This is used to hold the [ControllerButtonViewItem] between instances
|
||||||
*/
|
*/
|
||||||
class ButtonDialog @JvmOverloads constructor(private val item : ControllerButtonViewItem? = null) : BottomSheetDialogFragment() {
|
class ButtonDialog @JvmOverloads constructor(private val item : ControllerButtonViewItem? = null, private val nextDialog : BottomSheetDialogFragment? = null) : BottomSheetDialogFragment() {
|
||||||
private var _binding : ButtonDialogBinding? = null
|
private var _binding : ButtonDialogBinding? = null
|
||||||
private val binding get() = _binding!!
|
private val binding get() = _binding!!
|
||||||
|
|
||||||
@ -42,8 +44,22 @@ class ButtonDialog @JvmOverloads constructor(private val item : ControllerButton
|
|||||||
override fun onStart() {
|
override fun onStart() {
|
||||||
super.onStart()
|
super.onStart()
|
||||||
|
|
||||||
val behavior = BottomSheetBehavior.from(requireView().parent as View)
|
val parentView = requireView().parent as View
|
||||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
if (parentView.layoutParams is CoordinatorLayout.LayoutParams) {
|
||||||
|
val behavior = BottomSheetBehavior.from(parentView)
|
||||||
|
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun gotoNextOrDismiss() {
|
||||||
|
if (nextDialog != null) {
|
||||||
|
parentFragmentManager.commit {
|
||||||
|
remove(this@ButtonDialog)
|
||||||
|
add(nextDialog, null)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view : View, savedInstanceState : Bundle?) {
|
override fun onViewCreated(view : View, savedInstanceState : Bundle?) {
|
||||||
@ -69,7 +85,7 @@ class ButtonDialog @JvmOverloads constructor(private val item : ControllerButton
|
|||||||
|
|
||||||
item.update()
|
item.update()
|
||||||
|
|
||||||
dismiss()
|
gotoNextOrDismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that layout animations are proper
|
// Ensure that layout animations are proper
|
||||||
@ -131,7 +147,7 @@ class ButtonDialog @JvmOverloads constructor(private val item : ControllerButton
|
|||||||
|
|
||||||
item.update()
|
item.update()
|
||||||
|
|
||||||
dismiss()
|
gotoNextOrDismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
@ -209,7 +225,7 @@ class ButtonDialog @JvmOverloads constructor(private val item : ControllerButton
|
|||||||
|
|
||||||
item.update()
|
item.update()
|
||||||
|
|
||||||
dismiss()
|
gotoNextOrDismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
axisHandler.postDelayed(axisRunnable!!, 1000)
|
axisHandler.postDelayed(axisRunnable!!, 1000)
|
||||||
|
@ -12,6 +12,8 @@ import android.os.Looper
|
|||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.*
|
import android.view.*
|
||||||
import android.view.animation.LinearInterpolator
|
import android.view.animation.LinearInterpolator
|
||||||
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
import androidx.fragment.app.commit
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||||
import emu.skyline.R
|
import emu.skyline.R
|
||||||
@ -29,7 +31,7 @@ import kotlin.math.max
|
|||||||
*
|
*
|
||||||
* @param item This is used to hold the [ControllerStickViewItem] between instances
|
* @param item This is used to hold the [ControllerStickViewItem] between instances
|
||||||
*/
|
*/
|
||||||
class StickDialog @JvmOverloads constructor(val item : ControllerStickViewItem? = null) : BottomSheetDialogFragment() {
|
class StickDialog @JvmOverloads constructor(val item : ControllerStickViewItem? = null, private val nextDialog : BottomSheetDialogFragment? = null) : BottomSheetDialogFragment() {
|
||||||
/**
|
/**
|
||||||
* This enumerates all of the stages this dialog can be in
|
* This enumerates all of the stages this dialog can be in
|
||||||
*/
|
*/
|
||||||
@ -82,6 +84,17 @@ class StickDialog @JvmOverloads constructor(val item : ControllerStickViewItem?
|
|||||||
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
behavior.state = BottomSheetBehavior.STATE_EXPANDED
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun gotoNextOrDismiss() {
|
||||||
|
if (nextDialog != null) {
|
||||||
|
parentFragmentManager.commit {
|
||||||
|
remove(this@StickDialog)
|
||||||
|
add(nextDialog, null)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function converts [dip] (Density Independent Pixels) to normal pixels
|
* This function converts [dip] (Density Independent Pixels) to normal pixels
|
||||||
*/
|
*/
|
||||||
@ -218,6 +231,8 @@ class StickDialog @JvmOverloads constructor(val item : ControllerStickViewItem?
|
|||||||
binding.stickNext.text = getString(if (ordinal + 1 == size) R.string.done else R.string.next)
|
binding.stickNext.text = getString(if (ordinal + 1 == size) R.string.done else R.string.next)
|
||||||
|
|
||||||
updateAnimation()
|
updateAnimation()
|
||||||
|
} else if (ordinal == size) {
|
||||||
|
gotoNextOrDismiss()
|
||||||
} else {
|
} else {
|
||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
@ -254,7 +269,7 @@ class StickDialog @JvmOverloads constructor(val item : ControllerStickViewItem?
|
|||||||
|
|
||||||
item.update()
|
item.update()
|
||||||
|
|
||||||
dismiss()
|
gotoNextOrDismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that layout animations are proper
|
// Ensure that layout animations are proper
|
||||||
|
@ -68,7 +68,8 @@
|
|||||||
android:max="100"
|
android:max="100"
|
||||||
android:progress="25"
|
android:progress="25"
|
||||||
android:secondaryProgressTintMode="screen"
|
android:secondaryProgressTintMode="screen"
|
||||||
android:visibility="gone" />
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:id="@+id/button_reset"
|
android:id="@+id/button_reset"
|
||||||
|
@ -161,4 +161,6 @@
|
|||||||
<!-- Misc -->
|
<!-- Misc -->
|
||||||
<!--suppress AndroidLintUnusedResources -->
|
<!--suppress AndroidLintUnusedResources -->
|
||||||
<string name="expand_button_title" tools:override="true">Expand</string>
|
<string name="expand_button_title" tools:override="true">Expand</string>
|
||||||
|
<string name="setup_guide">Setup Guide</string>
|
||||||
|
<string name="setup_guide_description">Sequentially map every stick and button</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user