mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-26 17:04:14 +01:00
Add joystick press and general clean up
This commit is contained in:
parent
3057e4b29a
commit
e023dbbf0a
@ -411,9 +411,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onButtonStateChanged(buttonId : ButtonId, state : ButtonState) {
|
private fun onButtonStateChanged(buttonId : ButtonId, state : ButtonState) = setButtonState(0, buttonId.value(), state.state)
|
||||||
setButtonState(0, buttonId.value(), state.state)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun onStickStateChanged(buttonId : ButtonId, position : PointF) {
|
private fun onStickStateChanged(buttonId : ButtonId, position : PointF) {
|
||||||
val stickId = when (buttonId) {
|
val stickId = when (buttonId) {
|
||||||
@ -423,7 +421,6 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
|||||||
|
|
||||||
else -> error("Invalid button id")
|
else -> error("Invalid button id")
|
||||||
}
|
}
|
||||||
Log.i("blaa", "$position")
|
|
||||||
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
|
setAxisValue(0, stickId.yAxis.ordinal, (-position.y * Short.MAX_VALUE).toInt()) // Y is inverted
|
||||||
}
|
}
|
||||||
|
@ -49,9 +49,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
/**
|
/**
|
||||||
* The adapter used for adding elements to [app_list]
|
* The adapter used for adding elements to [app_list]
|
||||||
*/
|
*/
|
||||||
private val adapter by lazy {
|
private lateinit var adapter : AppAdapter
|
||||||
AppAdapter(layoutType = layoutType, onClick = ::selectStartGame, onLongClick = ::selectShowGameDialog)
|
|
||||||
}
|
|
||||||
|
|
||||||
private var reloading = AtomicBoolean()
|
private var reloading = AtomicBoolean()
|
||||||
|
|
||||||
@ -223,6 +221,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val metrics = resources.displayMetrics
|
val metrics = resources.displayMetrics
|
||||||
val gridSpan = ceil((metrics.widthPixels / metrics.density) / itemWidth).toInt()
|
val gridSpan = ceil((metrics.widthPixels / metrics.density) / itemWidth).toInt()
|
||||||
|
|
||||||
|
adapter = AppAdapter(layoutType = layoutType, onClick = ::selectStartGame, onLongClick = ::selectShowGameDialog)
|
||||||
app_list.adapter = adapter
|
app_list.adapter = adapter
|
||||||
app_list.layoutManager = when (adapter.layoutType) {
|
app_list.layoutManager = when (adapter.layoutType) {
|
||||||
LayoutType.List -> LinearLayoutManager(this).also { app_list.addItemDecoration(DividerItemDecoration(this, RecyclerView.VERTICAL)) }
|
LayoutType.List -> LinearLayoutManager(this).also { app_list.addItemDecoration(DividerItemDecoration(this, RecyclerView.VERTICAL)) }
|
||||||
|
@ -15,12 +15,13 @@ import android.view.ViewGroup
|
|||||||
import android.view.Window
|
import android.view.Window
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.RelativeLayout
|
import android.widget.RelativeLayout
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.graphics.drawable.toBitmap
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import emu.skyline.R
|
import emu.skyline.R
|
||||||
import emu.skyline.data.AppItem
|
import emu.skyline.data.AppItem
|
||||||
|
import kotlinx.android.extensions.LayoutContainer
|
||||||
|
import kotlinx.android.synthetic.main.app_item_grid_compact.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This enumerates the type of layouts the menu can be in
|
* This enumerates the type of layouts the menu can be in
|
||||||
@ -47,23 +48,9 @@ internal class AppAdapter(val layoutType : LayoutType, private val onClick : Int
|
|||||||
super.addHeader(BaseHeader(string))
|
super.addHeader(BaseHeader(string))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private class ItemViewHolder(override val containerView : View) : RecyclerView.ViewHolder(containerView), LayoutContainer
|
||||||
* The ViewHolder used by items is used to hold the views associated with an item
|
|
||||||
*
|
|
||||||
* @param parent The parent view that contains all the others
|
|
||||||
* @param icon The ImageView associated with the icon
|
|
||||||
* @param title The TextView associated with the title
|
|
||||||
* @param subtitle The TextView associated with the subtitle
|
|
||||||
*/
|
|
||||||
private class ItemViewHolder(val parent : View, var icon : ImageView, var title : TextView, var subtitle : TextView, var card : View? = null) : RecyclerView.ViewHolder(parent)
|
|
||||||
|
|
||||||
/**
|
private class HeaderViewHolder(override val containerView : View) : RecyclerView.ViewHolder(containerView), LayoutContainer
|
||||||
* The ViewHolder used by headers is used to hold the views associated with an headers
|
|
||||||
*
|
|
||||||
* @param parent The parent view that contains all the others
|
|
||||||
* @param header The TextView associated with the header
|
|
||||||
*/
|
|
||||||
private class HeaderViewHolder(val parent : View, var header : TextView? = null) : RecyclerView.ViewHolder(parent)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function creates the view-holder of type [viewType] with the layout parent as [parent]
|
* This function creates the view-holder of type [viewType] with the layout parent as [parent]
|
||||||
@ -79,20 +66,9 @@ internal class AppAdapter(val layoutType : LayoutType, private val onClick : Int
|
|||||||
}
|
}
|
||||||
|
|
||||||
return when (ElementType.values()[viewType]) {
|
return when (ElementType.values()[viewType]) {
|
||||||
ElementType.Item -> {
|
ElementType.Item -> ItemViewHolder(view)
|
||||||
ItemViewHolder(view, view.findViewById(R.id.icon), view.findViewById(R.id.text_title), view.findViewById(R.id.text_subtitle)).apply {
|
|
||||||
if (layoutType == LayoutType.Grid || layoutType == LayoutType.GridCompact) {
|
|
||||||
card = view.findViewById(R.id.app_item_grid)
|
|
||||||
title.isSelected = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ElementType.Header -> {
|
ElementType.Header -> HeaderViewHolder(view)
|
||||||
HeaderViewHolder(view).apply {
|
|
||||||
header = view.findViewById(R.id.text_title)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,8 +79,8 @@ internal class AppAdapter(val layoutType : LayoutType, private val onClick : Int
|
|||||||
val item = getItem(position)
|
val item = getItem(position)
|
||||||
|
|
||||||
if (item is AppItem && holder is ItemViewHolder) {
|
if (item is AppItem && holder is ItemViewHolder) {
|
||||||
holder.title.text = item.title
|
holder.text_title.text = item.title
|
||||||
holder.subtitle.text = item.subTitle ?: item.loaderResultString(holder.subtitle.context)
|
holder.text_subtitle.text = item.subTitle ?: item.loaderResultString(holder.text_subtitle.context)
|
||||||
|
|
||||||
holder.icon.setImageBitmap(item.icon ?: missingIcon)
|
holder.icon.setImageBitmap(item.icon ?: missingIcon)
|
||||||
|
|
||||||
@ -114,13 +90,13 @@ internal class AppAdapter(val layoutType : LayoutType, private val onClick : Int
|
|||||||
|
|
||||||
when (layoutType) {
|
when (layoutType) {
|
||||||
LayoutType.List -> holder.itemView
|
LayoutType.List -> holder.itemView
|
||||||
LayoutType.Grid, LayoutType.GridCompact -> holder.card!!
|
LayoutType.Grid, LayoutType.GridCompact -> holder.card_app_item_grid
|
||||||
}.apply {
|
}.apply {
|
||||||
setOnClickListener { onClick.invoke(item) }
|
setOnClickListener { onClick.invoke(item) }
|
||||||
setOnLongClickListener { true.also { onLongClick.invoke(item) } }
|
setOnLongClickListener { true.also { onLongClick.invoke(item) } }
|
||||||
}
|
}
|
||||||
} else if (item is BaseHeader && holder is HeaderViewHolder) {
|
} else if (item is BaseHeader && holder is HeaderViewHolder) {
|
||||||
holder.header!!.text = item.title
|
holder.text_title.text = item.title
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,11 +9,13 @@ import android.content.Context
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import emu.skyline.R
|
import emu.skyline.R
|
||||||
import emu.skyline.data.BaseItem
|
import emu.skyline.data.BaseItem
|
||||||
import emu.skyline.input.*
|
import emu.skyline.input.*
|
||||||
|
import kotlinx.android.extensions.LayoutContainer
|
||||||
|
import kotlinx.android.synthetic.main.controller_item.*
|
||||||
|
import kotlinx.android.synthetic.main.section_item.text_title
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is a class that holds everything relevant to a single item in the controller configuration list
|
* This is a class that holds everything relevant to a single item in the controller configuration list
|
||||||
@ -22,14 +24,8 @@ import emu.skyline.input.*
|
|||||||
* @param subContent The secondary line of text to show data more specific data about the item
|
* @param subContent The secondary line of text to show data more specific data about the item
|
||||||
*/
|
*/
|
||||||
abstract class ControllerItem(var content : String, var subContent : String) : BaseItem() {
|
abstract class ControllerItem(var content : String, var subContent : String) : BaseItem() {
|
||||||
/**
|
lateinit var adapter : ControllerAdapter
|
||||||
* The underlying adapter this item is contained within
|
|
||||||
*/
|
|
||||||
var adapter : ControllerAdapter? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The position of this item in the adapter
|
|
||||||
*/
|
|
||||||
var position : Int? = null
|
var position : Int? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,7 +38,7 @@ abstract class ControllerItem(var content : String, var subContent : String) : B
|
|||||||
if (subContent != null)
|
if (subContent != null)
|
||||||
this.subContent = subContent
|
this.subContent = subContent
|
||||||
|
|
||||||
position?.let { adapter?.notifyItemChanged(it) }
|
position?.let { adapter.notifyItemChanged(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -149,71 +145,45 @@ class ControllerStickItem(val context : ControllerActivity, val stick : StickId)
|
|||||||
override fun update() = update(null, getSummary(context, stick))
|
override fun update() = update(null, getSummary(context, stick))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ControllerCheckBox()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This adapter is used to create a list which handles having a simple view
|
* This adapter is used to create a list which handles having a simple view
|
||||||
*/
|
*/
|
||||||
class ControllerAdapter(private val onItemClickCallback : (item : ControllerItem) -> Unit) : HeaderAdapter<ControllerItem?, BaseHeader, RecyclerView.ViewHolder>() {
|
class ControllerAdapter(private val onItemClickCallback : (item : ControllerItem) -> Unit) : HeaderAdapter<ControllerItem?, BaseHeader, RecyclerView.ViewHolder>() {
|
||||||
/**
|
|
||||||
* This adds a header to the view with the contents of [string]
|
|
||||||
*/
|
|
||||||
fun addHeader(string : String) {
|
fun addHeader(string : String) {
|
||||||
super.addHeader(BaseHeader(string))
|
super.addHeader(BaseHeader(string))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This functions sets [ControllerItem.adapter] and delegates the call to [HeaderAdapter.addItem]
|
|
||||||
*/
|
|
||||||
fun addItem(item : ControllerItem) {
|
fun addItem(item : ControllerItem) {
|
||||||
item.adapter = this
|
item.adapter = this
|
||||||
super.addItem(item)
|
super.addItem(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private class ItemViewHolder(override val containerView : View) : RecyclerView.ViewHolder(containerView), LayoutContainer
|
||||||
* The ViewHolder used by items is used to hold the views associated with an item
|
|
||||||
*
|
|
||||||
* @param parent The parent view that contains all the others
|
|
||||||
* @param title The TextView associated with the title
|
|
||||||
* @param subtitle The TextView associated with the subtitle
|
|
||||||
* @param item The View containing the two other views
|
|
||||||
*/
|
|
||||||
class ItemViewHolder(val parent : View, var title : TextView, var subtitle : TextView, var item : View) : RecyclerView.ViewHolder(parent)
|
|
||||||
|
|
||||||
/**
|
private class HeaderViewHolder(override val containerView : View) : RecyclerView.ViewHolder(containerView), LayoutContainer
|
||||||
* The ViewHolder used by headers is used to hold the views associated with an headers
|
|
||||||
*
|
|
||||||
* @param parent The parent view that contains all the others
|
|
||||||
* @param header The TextView associated with the header
|
|
||||||
*/
|
|
||||||
private class HeaderViewHolder(val parent : View, var header : TextView? = null) : RecyclerView.ViewHolder(parent)
|
|
||||||
|
|
||||||
/**
|
override fun onCreateViewHolder(parent : ViewGroup, viewType : Int) : RecyclerView.ViewHolder = LayoutInflater.from(parent.context).let { layoutInflater ->
|
||||||
* This function creates the view-holder of type [viewType] with the layout parent as [parent]
|
when (ElementType.values()[viewType]) {
|
||||||
*/
|
ElementType.Header -> HeaderViewHolder(layoutInflater.inflate(R.layout.section_item, parent, false))
|
||||||
override fun onCreateViewHolder(parent : ViewGroup, viewType : Int) = when (ElementType.values()[viewType]) {
|
|
||||||
ElementType.Header -> LayoutInflater.from(parent.context).inflate(R.layout.section_item, parent, false).let { view ->
|
|
||||||
HeaderViewHolder(view).apply { header = view.findViewById(R.id.text_title) }
|
|
||||||
}
|
|
||||||
|
|
||||||
ElementType.Item -> LayoutInflater.from(parent.context).inflate(R.layout.controller_item, parent, false).let { view ->
|
ElementType.Item -> ItemViewHolder(layoutInflater.inflate(R.layout.controller_item, parent, false))
|
||||||
ItemViewHolder(view, view.findViewById(R.id.text_title), view.findViewById(R.id.text_subtitle), view.findViewById(R.id.controller_item))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This function binds the item at [position] to the supplied [holder]
|
|
||||||
*/
|
|
||||||
override fun onBindViewHolder(holder : RecyclerView.ViewHolder, position : Int) {
|
override fun onBindViewHolder(holder : RecyclerView.ViewHolder, position : Int) {
|
||||||
val item = getItem(position)
|
val item = getItem(position)
|
||||||
|
|
||||||
if (item is ControllerItem && holder is ItemViewHolder) {
|
if (item is ControllerItem && holder is ItemViewHolder) {
|
||||||
item.position = position
|
item.position = position
|
||||||
|
|
||||||
holder.title.text = item.content
|
holder.text_title.text = item.content
|
||||||
holder.subtitle.text = item.subContent
|
holder.text_subtitle.text = item.subContent
|
||||||
|
|
||||||
holder.parent.setOnClickListener { onItemClickCallback.invoke(item) }
|
holder.itemView.setOnClickListener { onItemClickCallback.invoke(item) }
|
||||||
} else if (item is BaseHeader && holder is HeaderViewHolder) {
|
} else if (item is BaseHeader && holder is HeaderViewHolder) {
|
||||||
holder.header?.text = item.title
|
holder.text_title.text = item.title
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,11 +11,12 @@ import android.content.Context
|
|||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.TextView
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import emu.skyline.R
|
import emu.skyline.R
|
||||||
import emu.skyline.data.BaseItem
|
import emu.skyline.data.BaseItem
|
||||||
|
import kotlinx.android.extensions.LayoutContainer
|
||||||
|
import kotlinx.android.synthetic.main.log_item.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is used to hold all data about a log entry
|
* This class is used to hold all data about a log entry
|
||||||
@ -55,22 +56,9 @@ internal class LogAdapter internal constructor(val context : Context, val compac
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private class ItemViewHolder(override val containerView : View) : RecyclerView.ViewHolder(containerView), LayoutContainer
|
||||||
* The ViewHolder used by items is used to hold the views associated with an item
|
|
||||||
*
|
|
||||||
* @param parent The parent view that contains all the others
|
|
||||||
* @param title The TextView associated with the title
|
|
||||||
* @param subtitle The TextView associated with the subtitle
|
|
||||||
*/
|
|
||||||
private class ItemViewHolder(val parent : View, var title : TextView, var subtitle : TextView? = null) : RecyclerView.ViewHolder(parent)
|
|
||||||
|
|
||||||
/**
|
private class HeaderViewHolder(override val containerView : View) : RecyclerView.ViewHolder(containerView), LayoutContainer
|
||||||
* The ViewHolder used by headers is used to hold the views associated with an headers
|
|
||||||
*
|
|
||||||
* @param parent The parent view that contains all the others
|
|
||||||
* @param header The TextView associated with the header
|
|
||||||
*/
|
|
||||||
private class HeaderViewHolder(val parent : View, var header : TextView) : RecyclerView.ViewHolder(parent)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function creates the view-holder of type [viewType] with the layout parent as [parent]
|
* This function creates the view-holder of type [viewType] with the layout parent as [parent]
|
||||||
@ -87,14 +75,14 @@ internal class LogAdapter internal constructor(val context : Context, val compac
|
|||||||
return when (ElementType.values()[viewType]) {
|
return when (ElementType.values()[viewType]) {
|
||||||
ElementType.Item -> {
|
ElementType.Item -> {
|
||||||
if (compact) {
|
if (compact) {
|
||||||
ItemViewHolder(view, view.findViewById(R.id.text_title))
|
ItemViewHolder(view)
|
||||||
} else {
|
} else {
|
||||||
ItemViewHolder(view, view.findViewById(R.id.text_title), view.findViewById(R.id.text_subtitle))
|
ItemViewHolder(view)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ElementType.Header -> {
|
ElementType.Header -> {
|
||||||
HeaderViewHolder(view, view.findViewById(R.id.text_title))
|
HeaderViewHolder(view)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -106,15 +94,15 @@ internal class LogAdapter internal constructor(val context : Context, val compac
|
|||||||
val item = getItem(position)
|
val item = getItem(position)
|
||||||
|
|
||||||
if (item is LogItem && holder is ItemViewHolder) {
|
if (item is LogItem && holder is ItemViewHolder) {
|
||||||
holder.title.text = item.message
|
holder.text_title.text = item.message
|
||||||
holder.subtitle?.text = item.level
|
holder.text_subtitle?.text = item.level
|
||||||
|
|
||||||
holder.parent.setOnClickListener {
|
holder.itemView.setOnClickListener {
|
||||||
clipboard.setPrimaryClip(ClipData.newPlainText("Log Message", item.message + " (" + item.level + ")"))
|
clipboard.setPrimaryClip(ClipData.newPlainText("Log Message", item.message + " (" + item.level + ")"))
|
||||||
Toast.makeText(holder.itemView.context, "Copied to clipboard", Toast.LENGTH_LONG).show()
|
Toast.makeText(holder.itemView.context, "Copied to clipboard", Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
} else if (item is BaseHeader && holder is HeaderViewHolder) {
|
} else if (item is BaseHeader && holder is HeaderViewHolder) {
|
||||||
holder.header.text = item.title
|
holder.text_title.text = item.title
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ class ControllerActivity : AppCompatActivity() {
|
|||||||
/**
|
/**
|
||||||
* The index of the controller this activity manages
|
* The index of the controller this activity manages
|
||||||
*/
|
*/
|
||||||
var id : Int = -1
|
val id by lazy { intent.getIntExtra("index", 0) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The adapter used by [controller_list] to hold all the items
|
* The adapter used by [controller_list] to hold all the items
|
||||||
@ -55,6 +55,8 @@ class ControllerActivity : AppCompatActivity() {
|
|||||||
if (controller.type == ControllerType.None)
|
if (controller.type == ControllerType.None)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var wroteTitle = false
|
var wroteTitle = false
|
||||||
|
|
||||||
for (item in GeneralType.values()) {
|
for (item in GeneralType.values()) {
|
||||||
@ -128,8 +130,6 @@ class ControllerActivity : AppCompatActivity() {
|
|||||||
override fun onCreate(state : Bundle?) {
|
override fun onCreate(state : Bundle?) {
|
||||||
super.onCreate(state)
|
super.onCreate(state)
|
||||||
|
|
||||||
id = intent.getIntExtra("index", 0)
|
|
||||||
|
|
||||||
if (id < 0 || id > 7)
|
if (id < 0 || id > 7)
|
||||||
throw IllegalArgumentException()
|
throw IllegalArgumentException()
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ class ControllerActivity : AppCompatActivity() {
|
|||||||
is ControllerTypeItem -> {
|
is ControllerTypeItem -> {
|
||||||
val controller = InputManager.controllers[id]!!
|
val controller = InputManager.controllers[id]!!
|
||||||
|
|
||||||
val types = ControllerType.values().filter { !it.firstController || id == 0 }
|
val types = ControllerType.values().apply { if (id != 0) filter { !it.firstController } }
|
||||||
val typeNames = types.map { getString(it.stringRes) }.toTypedArray()
|
val typeNames = types.map { getString(it.stringRes) }.toTypedArray()
|
||||||
|
|
||||||
MaterialAlertDialogBuilder(this)
|
MaterialAlertDialogBuilder(this)
|
||||||
|
@ -87,7 +87,7 @@ class OnScreenControllerView @JvmOverloads constructor(
|
|||||||
val outerToInner = joystick.outerToInner()
|
val outerToInner = joystick.outerToInner()
|
||||||
val outerToInnerLength = outerToInner.length()
|
val outerToInnerLength = outerToInner.length()
|
||||||
val direction = outerToInner.normalize()
|
val direction = outerToInner.normalize()
|
||||||
val duration = (150f * outerToInnerLength / radius).roundToLong()
|
val duration = (50f * outerToInnerLength / radius).roundToLong()
|
||||||
joystickAnimators[joystick] = ValueAnimator.ofFloat(outerToInnerLength, 0f).apply {
|
joystickAnimators[joystick] = ValueAnimator.ofFloat(outerToInnerLength, 0f).apply {
|
||||||
addUpdateListener { animation ->
|
addUpdateListener { animation ->
|
||||||
val value = animation.animatedValue as Float
|
val value = animation.animatedValue as Float
|
||||||
@ -106,6 +106,8 @@ class OnScreenControllerView @JvmOverloads constructor(
|
|||||||
|
|
||||||
override fun onAnimationEnd(animation : Animator?) {
|
override fun onAnimationEnd(animation : Animator?) {
|
||||||
super.onAnimationEnd(animation)
|
super.onAnimationEnd(animation)
|
||||||
|
if (joystick.shortDoubleTapped)
|
||||||
|
onButtonStateChangedListener?.invoke(joystick.buttonId, ButtonState.Released)
|
||||||
joystick.onFingerUp(event.x, event.y)
|
joystick.onFingerUp(event.x, event.y)
|
||||||
invalidate()
|
invalidate()
|
||||||
}
|
}
|
||||||
@ -123,6 +125,8 @@ class OnScreenControllerView @JvmOverloads constructor(
|
|||||||
joystickAnimators[joystick] = null
|
joystickAnimators[joystick] = null
|
||||||
joystick.touchPointerId = pointerId
|
joystick.touchPointerId = pointerId
|
||||||
joystick.onFingerDown(x, y)
|
joystick.onFingerDown(x, y)
|
||||||
|
if (joystick.shortDoubleTapped)
|
||||||
|
onButtonStateChangedListener?.invoke(joystick.buttonId, ButtonState.Pressed)
|
||||||
performClick()
|
performClick()
|
||||||
handled = true
|
handled = true
|
||||||
}
|
}
|
||||||
@ -139,7 +143,7 @@ class OnScreenControllerView @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handled.also { if (it) invalidate() }
|
handled.also { if (it) invalidate() else super.onTouchEvent(event) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private val editingTouchHandler = OnTouchListener { _, event ->
|
private val editingTouchHandler = OnTouchListener { _, event ->
|
||||||
@ -169,7 +173,7 @@ class OnScreenControllerView @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}.also { handled -> if (handled) invalidate() }
|
}.also { handled -> if (handled) invalidate() else super.onTouchEvent(event) }
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -7,6 +7,7 @@ package emu.skyline.input.onscreen
|
|||||||
|
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.PointF
|
import android.graphics.PointF
|
||||||
|
import android.os.SystemClock
|
||||||
import androidx.core.graphics.minus
|
import androidx.core.graphics.minus
|
||||||
import emu.skyline.R
|
import emu.skyline.R
|
||||||
import emu.skyline.input.ButtonId
|
import emu.skyline.input.ButtonId
|
||||||
@ -59,6 +60,11 @@ 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)
|
||||||
|
|
||||||
|
private var fingerDownTime = 0L
|
||||||
|
private var fingerUpTime = 0L
|
||||||
|
var shortDoubleTapped = false
|
||||||
|
private set
|
||||||
|
|
||||||
override fun renderCenteredText(canvas : Canvas, text : String, size : Float, x : Float, y : Float) = Unit
|
override fun renderCenteredText(canvas : Canvas, text : String, size : Float, x : Float, y : Float) = Unit
|
||||||
|
|
||||||
override fun render(canvas : Canvas) {
|
override fun render(canvas : Canvas) {
|
||||||
@ -74,12 +80,23 @@ class JoystickButton(
|
|||||||
relativeY = (y - heightDiff) / adjustedHeight
|
relativeY = (y - heightDiff) / adjustedHeight
|
||||||
innerButton.relativeX = relativeX
|
innerButton.relativeX = relativeX
|
||||||
innerButton.relativeY = relativeY
|
innerButton.relativeY = relativeY
|
||||||
|
|
||||||
|
val currentTime = SystemClock.elapsedRealtime()
|
||||||
|
val firstTapDiff = fingerUpTime - fingerDownTime
|
||||||
|
val secondTapDiff = currentTime - fingerUpTime
|
||||||
|
if (firstTapDiff in 0..500 && secondTapDiff in 0..500) {
|
||||||
|
shortDoubleTapped = true
|
||||||
|
}
|
||||||
|
fingerDownTime = currentTime
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onFingerUp(x : Float, y : Float) {
|
override fun onFingerUp(x : Float, y : Float) {
|
||||||
loadConfigValues()
|
loadConfigValues()
|
||||||
innerButton.relativeX = relativeX
|
innerButton.relativeX = relativeX
|
||||||
innerButton.relativeY = relativeY
|
innerButton.relativeY = relativeY
|
||||||
|
|
||||||
|
fingerUpTime = SystemClock.elapsedRealtime()
|
||||||
|
shortDoubleTapped = false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onFingerMoved(x : Float, y : Float) : PointF {
|
fun onFingerMoved(x : Float, y : Float) : PointF {
|
||||||
@ -91,6 +108,11 @@ class JoystickButton(
|
|||||||
finger = position.add(outerToInner.multiply(1f / distance * radius))
|
finger = position.add(outerToInner.multiply(1f / distance * radius))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (distance > radius * 0.075f) {
|
||||||
|
fingerDownTime = 0
|
||||||
|
fingerUpTime = 0
|
||||||
|
}
|
||||||
|
|
||||||
innerButton.relativeX = finger.x / width
|
innerButton.relativeX = finger.x / width
|
||||||
innerButton.relativeY = (finger.y - heightDiff) / adjustedHeight
|
innerButton.relativeY = (finger.y - heightDiff) / adjustedHeight
|
||||||
return finger.minus(position).multiply(1f / radius)
|
return finger.minus(position).multiply(1f / radius)
|
||||||
@ -100,6 +122,7 @@ class JoystickButton(
|
|||||||
|
|
||||||
override fun edit(x : Float, y : Float) {
|
override fun edit(x : Float, y : Float) {
|
||||||
super.edit(x, y)
|
super.edit(x, y)
|
||||||
|
|
||||||
innerButton.relativeX = relativeX
|
innerButton.relativeX = relativeX
|
||||||
innerButton.relativeY = relativeY
|
innerButton.relativeY = relativeY
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:id="@+id/app_item_grid"
|
android:id="@+id/card_app_item_grid"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<androidx.cardview.widget.CardView
|
<androidx.cardview.widget.CardView
|
||||||
android:id="@+id/app_item_grid"
|
android:id="@+id/card_app_item_grid"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
|
Loading…
Reference in New Issue
Block a user