mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-04 23:35:12 +01:00
Add comments
This commit is contained in:
parent
7526a985fb
commit
f479aeb4ac
@ -96,7 +96,7 @@ class AppDialog : BottomSheetDialogFragment() {
|
||||
|
||||
game_pin.setOnClickListener {
|
||||
val info = ShortcutInfo.Builder(context, item.title)
|
||||
info.setShortLabel(item.meta.name)
|
||||
info.setShortLabel(item.title)
|
||||
info.setActivity(ComponentName(requireContext(), EmulationActivity::class.java))
|
||||
info.setIcon(Icon.createWithAdaptiveBitmap(item.icon ?: missingIcon))
|
||||
|
||||
|
@ -164,7 +164,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
||||
}
|
||||
|
||||
/**
|
||||
* This executes the specified ROM, [preferenceFd] is assumed to be valid beforehand
|
||||
* This executes the specified ROM
|
||||
*
|
||||
* @param rom The URI of the ROM to execute
|
||||
*/
|
||||
@ -186,7 +186,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
||||
}
|
||||
|
||||
/**
|
||||
* This makes the window fullscreen then sets up [preferenceFd], sets up the performance statistics and finally calls [executeApplication] for executing the application
|
||||
* This makes the window fullscreen, sets up the performance statistics and finally calls [executeApplication] for executing the application
|
||||
*/
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onCreate(savedInstanceState : Bundle?) {
|
||||
@ -415,7 +415,7 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo
|
||||
else -> error("Invalid button id")
|
||||
}
|
||||
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, since drawing starts from top left
|
||||
}
|
||||
|
||||
@SuppressLint("WrongConstant")
|
||||
|
@ -31,9 +31,8 @@ import emu.skyline.adapter.GenericAdapter
|
||||
import emu.skyline.adapter.HeaderViewItem
|
||||
import emu.skyline.adapter.LayoutType
|
||||
import emu.skyline.data.AppItem
|
||||
import emu.skyline.data.BaseElement
|
||||
import emu.skyline.data.BaseHeader
|
||||
import emu.skyline.data.ElementType
|
||||
import emu.skyline.data.DataItem
|
||||
import emu.skyline.data.HeaderItem
|
||||
import emu.skyline.loader.LoaderResult
|
||||
import emu.skyline.loader.RomFile
|
||||
import emu.skyline.loader.RomFormat
|
||||
@ -71,7 +70,7 @@ class MainActivity : AppCompatActivity() {
|
||||
/**
|
||||
* This adds all files in [directory] with [extension] as an entry in [adapter] using [RomFile] to load metadata
|
||||
*/
|
||||
private fun addEntries(extension : String, romFormat : RomFormat, directory : DocumentFile, romElements : ArrayList<BaseElement>, found : Boolean = false) : Boolean {
|
||||
private fun addEntries(extension : String, romFormat : RomFormat, directory : DocumentFile, romElements : ArrayList<DataItem>, found : Boolean = false) : Boolean {
|
||||
var foundCurrent = found
|
||||
|
||||
directory.listFiles().forEach { file ->
|
||||
@ -83,7 +82,7 @@ class MainActivity : AppCompatActivity() {
|
||||
val finalFoundCurrent = foundCurrent
|
||||
runOnUiThread {
|
||||
if (!finalFoundCurrent) {
|
||||
romElements.add(BaseHeader(romFormat.name))
|
||||
romElements.add(HeaderItem(romFormat.name))
|
||||
adapter.addItem(HeaderViewItem(romFormat.name))
|
||||
}
|
||||
|
||||
@ -111,8 +110,8 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
if (loadFromFile) {
|
||||
try {
|
||||
loadSerializedList<BaseElement>(romsFile).forEach {
|
||||
if (it.elementType == ElementType.Header && it is BaseHeader)
|
||||
loadSerializedList<DataItem>(romsFile).forEach {
|
||||
if (it is HeaderItem)
|
||||
adapter.addItem(HeaderViewItem(it.title))
|
||||
else if (it is AppItem)
|
||||
adapter.addItem(it.toViewItem())
|
||||
@ -136,7 +135,7 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
val searchLocation = DocumentFile.fromTreeUri(this, Uri.parse(settings.searchLocation))!!
|
||||
|
||||
val romElements = ArrayList<BaseElement>()
|
||||
val romElements = ArrayList<DataItem>()
|
||||
addEntries("nro", RomFormat.NRO, searchLocation, romElements)
|
||||
addEntries("nso", RomFormat.NSO, searchLocation, romElements)
|
||||
addEntries("nca", RomFormat.NCA, searchLocation, romElements)
|
||||
@ -144,7 +143,7 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
runOnUiThread {
|
||||
if (romElements.isEmpty()) {
|
||||
romElements.add(BaseHeader(getString(R.string.no_rom)))
|
||||
romElements.add(HeaderItem(getString(R.string.no_rom)))
|
||||
adapter.addItem(HeaderViewItem(getString(R.string.no_rom)))
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,12 @@ package emu.skyline
|
||||
import android.app.Application
|
||||
import emu.skyline.input.InputManager
|
||||
|
||||
/**
|
||||
* Custom application class to initialize [InputManager]
|
||||
*/
|
||||
class SkylineApplication : Application() {
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
InputManager.init(applicationContext)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -69,5 +69,5 @@ class AppViewItem(var layoutType : LayoutType, private val item : AppItem, priva
|
||||
builder.show()
|
||||
}
|
||||
|
||||
override fun toString() = item.key()
|
||||
override fun key() = item.key()
|
||||
}
|
||||
|
@ -13,6 +13,9 @@ import info.debatty.java.stringsimilarity.Cosine
|
||||
import info.debatty.java.stringsimilarity.JaroWinkler
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Can handle any view types with [GenericViewHolderBinder] implemented, [GenericViewHolderBinder] are differentiated by the return value of [GenericViewHolderBinder.getLayoutFactory]
|
||||
*/
|
||||
class GenericAdapter : RecyclerView.Adapter<GenericViewHolder>(), Filterable {
|
||||
var currentSearchTerm = ""
|
||||
|
||||
@ -70,7 +73,7 @@ class GenericAdapter : RecyclerView.Adapter<GenericViewHolder>(), Filterable {
|
||||
* This sorts the items in [allItems] in relation to how similar they are to [currentSearchTerm]
|
||||
*/
|
||||
fun extractSorted() = allItems.mapNotNull { item ->
|
||||
item.toString().toLowerCase(Locale.getDefault()).let {
|
||||
item.key().toLowerCase(Locale.getDefault()).let {
|
||||
val similarity = (jw.similarity(currentSearchTerm, it)) + cos.similarity(currentSearchTerm, it) / 2
|
||||
if (similarity != 0.0) ScoredItem(similarity, item) else null
|
||||
}
|
||||
|
@ -22,4 +22,9 @@ abstract class GenericViewHolderBinder {
|
||||
abstract fun getLayoutFactory() : GenericLayoutFactory
|
||||
|
||||
abstract fun bind(holder : GenericViewHolder, position : Int)
|
||||
|
||||
/**
|
||||
* Used for filtering
|
||||
*/
|
||||
open fun key() : String = ""
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import emu.skyline.loader.LoaderResult
|
||||
/**
|
||||
* This class is a wrapper around [AppEntry], it is used for passing around game metadata
|
||||
*/
|
||||
class AppItem(val meta : AppEntry) : BaseItem() {
|
||||
class AppItem(private val meta : AppEntry) : DataItem {
|
||||
/**
|
||||
* The icon of the application
|
||||
*/
|
||||
@ -56,5 +56,5 @@ class AppItem(val meta : AppEntry) : BaseItem() {
|
||||
/**
|
||||
* The name and author is used as the key
|
||||
*/
|
||||
override fun key() = meta.name + if (meta.author != null) " ${meta.author}" else ""
|
||||
fun key() = meta.name + if (meta.author != null) " ${meta.author}" else ""
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
/*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
* Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
||||
*/
|
||||
|
||||
package emu.skyline.data
|
||||
|
||||
/**
|
||||
* This is an abstract class that all adapter item classes inherit from
|
||||
*/
|
||||
abstract class BaseItem : BaseElement(ElementType.Item) {
|
||||
/**
|
||||
* This function returns a string used for searching
|
||||
*/
|
||||
open fun key() : String = ""
|
||||
}
|
@ -5,4 +5,6 @@
|
||||
|
||||
package emu.skyline.data
|
||||
|
||||
class BaseHeader(val title : String) : BaseElement(ElementType.Header)
|
||||
import java.io.Serializable
|
||||
|
||||
interface DataItem : Serializable
|
@ -5,11 +5,4 @@
|
||||
|
||||
package emu.skyline.data
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
enum class ElementType {
|
||||
Header,
|
||||
Item
|
||||
}
|
||||
|
||||
abstract class BaseElement(val elementType : ElementType) : Serializable
|
||||
class HeaderItem(val title : String) : DataItem
|
@ -38,7 +38,7 @@ class ControllerActivity : AppCompatActivity() {
|
||||
private val adapter = GenericAdapter()
|
||||
|
||||
/**
|
||||
* This is a map between a button and it's corresponding [ControllerItem] in [adapter]
|
||||
* This is a map between a button and it's corresponding [ControllerViewItem] in [adapter]
|
||||
*/
|
||||
val buttonMap = mutableMapOf<ButtonId, ControllerViewItem>()
|
||||
|
||||
|
@ -10,7 +10,7 @@ import android.view.MotionEvent
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* This an abstract class for all host events that is inherited by all other event classes
|
||||
* This a sealed class for all host events that is inherited by all other event classes
|
||||
*
|
||||
* @param descriptor The device descriptor of the device this event originates from
|
||||
*/
|
||||
|
@ -11,9 +11,11 @@ import android.graphics.Paint
|
||||
import android.graphics.Rect
|
||||
import androidx.core.content.ContextCompat
|
||||
import emu.skyline.input.ButtonId
|
||||
import kotlin.math.absoluteValue
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* Converts relative values, such as coordinates and boundaries, to their absolute counterparts, also handles layout modifications like scaling and custom positioning
|
||||
*/
|
||||
abstract class OnScreenButton(
|
||||
onScreenControllerView : OnScreenControllerView,
|
||||
val buttonId : ButtonId,
|
||||
@ -47,7 +49,11 @@ abstract class OnScreenButton(
|
||||
var height = 0
|
||||
|
||||
protected val adjustedHeight get() = width / CONFIGURED_ASPECT_RATIO
|
||||
protected val heightDiff get() = (height - adjustedHeight).absoluteValue
|
||||
|
||||
/**
|
||||
* Buttons should be at bottom when device have large height than [adjustedHeight]
|
||||
*/
|
||||
protected val heightDiff get() = (height - adjustedHeight).coerceAtLeast(0f)
|
||||
|
||||
protected val itemWidth get() = width * relativeWidth
|
||||
private val itemHeight get() = adjustedHeight * relativeHeight
|
||||
@ -58,37 +64,23 @@ abstract class OnScreenButton(
|
||||
private val left get() = currentX - itemWidth / 2f
|
||||
private val top get() = currentY - itemHeight / 2f
|
||||
|
||||
protected val currentBounds
|
||||
get() = Rect(
|
||||
left.roundToInt(),
|
||||
top.roundToInt(),
|
||||
(left + itemWidth).roundToInt(),
|
||||
(top + itemHeight).roundToInt()
|
||||
)
|
||||
protected val currentBounds get() = Rect(left.roundToInt(), top.roundToInt(), (left + itemWidth).roundToInt(), (top + itemHeight).roundToInt())
|
||||
|
||||
/**
|
||||
* Keeps track of finger when there are multiple touches
|
||||
*/
|
||||
var touchPointerId = -1
|
||||
|
||||
var isEditing = false
|
||||
private set
|
||||
|
||||
protected open fun renderCenteredText(
|
||||
canvas : Canvas,
|
||||
text : String,
|
||||
size : Float,
|
||||
x : Float,
|
||||
y : Float
|
||||
) {
|
||||
protected open fun renderCenteredText(canvas : Canvas, text : String, size : Float, x : Float, y : Float) {
|
||||
buttonSymbolPaint.apply {
|
||||
textSize = size
|
||||
textAlign = Paint.Align.LEFT
|
||||
getTextBounds(text, 0, text.length, textBoundsRect)
|
||||
}
|
||||
canvas.drawText(
|
||||
text,
|
||||
x - textBoundsRect.width() / 2f - textBoundsRect.left,
|
||||
y + textBoundsRect.height() / 2f - textBoundsRect.bottom,
|
||||
buttonSymbolPaint
|
||||
)
|
||||
canvas.drawText(text, x - textBoundsRect.width() / 2f - textBoundsRect.left, y + textBoundsRect.height() / 2f - textBoundsRect.bottom, buttonSymbolPaint)
|
||||
}
|
||||
|
||||
open fun render(canvas : Canvas) {
|
||||
|
@ -16,6 +16,9 @@ interface ControllerConfiguration {
|
||||
var relativeY : Float
|
||||
}
|
||||
|
||||
/**
|
||||
* Dummy implementation so layout editor is able to render [OnScreenControllerView] when [android.view.View.isInEditMode] is true
|
||||
*/
|
||||
class ControllerConfigurationDummy(defaultRelativeX : Float, defaultRelativeY : Float) : ControllerConfiguration {
|
||||
override var enabled = true
|
||||
override var globalScale = 1f
|
||||
|
@ -25,12 +25,10 @@ import kotlin.math.roundToLong
|
||||
typealias OnButtonStateChangedListener = (buttonId : ButtonId, state : ButtonState) -> Unit
|
||||
typealias OnStickStateChangedListener = (buttonId : ButtonId, position : PointF) -> Unit
|
||||
|
||||
class OnScreenControllerView @JvmOverloads constructor(
|
||||
context : Context,
|
||||
attrs : AttributeSet? = null,
|
||||
defStyleAttr : Int = 0,
|
||||
defStyleRes : Int = 0
|
||||
) : View(context, attrs, defStyleAttr, defStyleRes) {
|
||||
/**
|
||||
* 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) {
|
||||
private val controls = Controls(this)
|
||||
private var onButtonStateChangedListener : OnButtonStateChangedListener? = null
|
||||
private var onStickStateChangedListener : OnStickStateChangedListener? = null
|
||||
@ -226,4 +224,4 @@ class OnScreenControllerView @JvmOverloads constructor(
|
||||
controls.allButtons.first { it.buttonId == buttonId }.config.enabled = enabled
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,10 +34,13 @@ open class CircularButton(
|
||||
) {
|
||||
val radius get() = itemWidth / 2f
|
||||
|
||||
/**
|
||||
* Checks if [x] and [y] are within circle
|
||||
*/
|
||||
override fun isTouched(x : Float, y : Float) : Boolean = PointF(currentX, currentY).minus(PointF(x, y)).length() <= radius
|
||||
|
||||
override fun onFingerDown(x : Float, y : Float) {
|
||||
drawable.alpha = (255 * 0.5f).roundToInt()
|
||||
drawable.alpha = 125
|
||||
}
|
||||
|
||||
override fun onFingerUp(x : Float, y : Float) {
|
||||
@ -81,19 +84,21 @@ class JoystickButton(
|
||||
override fun onFingerDown(x : Float, y : Float) {
|
||||
val relativeX = x / width
|
||||
val relativeY = (y - heightDiff) / adjustedHeight
|
||||
if (!recenterSticks) {
|
||||
if (recenterSticks) {
|
||||
this.relativeX = relativeX
|
||||
this.relativeY = relativeY
|
||||
}
|
||||
innerButton.relativeX = relativeX
|
||||
innerButton.relativeY = relativeY
|
||||
|
||||
// If first and second tap occur within 500 mills, then trigger stick press
|
||||
val currentTime = SystemClock.elapsedRealtime()
|
||||
initialTapPosition = PointF(x, y)
|
||||
val firstTapDiff = fingerUpTime - fingerDownTime
|
||||
val secondTapDiff = currentTime - fingerUpTime
|
||||
if (firstTapDiff in 0..500 && secondTapDiff in 0..500) {
|
||||
shortDoubleTapped = true
|
||||
// Indicate stick being pressed with lower alpha value
|
||||
drawable.alpha = 50
|
||||
}
|
||||
fingerDownTime = currentTime
|
||||
@ -115,6 +120,7 @@ class JoystickButton(
|
||||
val outerToInner = finger.minus(position)
|
||||
val distance = outerToInner.length()
|
||||
if (distance > radius) {
|
||||
// Limit distance to radius
|
||||
finger = position.add(outerToInner.multiply(1f / distance * radius))
|
||||
}
|
||||
|
||||
@ -168,7 +174,7 @@ open class RectangularButton(
|
||||
override fun isTouched(x : Float, y : Float) = currentBounds.contains(x.roundToInt(), y.roundToInt())
|
||||
|
||||
override fun onFingerDown(x : Float, y : Float) {
|
||||
drawable.alpha = (255 * 0.5f).roundToInt()
|
||||
drawable.alpha = 125
|
||||
}
|
||||
|
||||
override fun onFingerUp(x : Float, y : Float) {
|
||||
|
@ -80,6 +80,7 @@ class AppEntry(var name : String, var author : String?, var icon : Bitmap?, var
|
||||
output.writeInt(loaderResult.value)
|
||||
output.writeBoolean(icon != null)
|
||||
icon?.let {
|
||||
@Suppress("DEPRECATION")
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
|
||||
it.compress(Bitmap.CompressFormat.WEBP_LOSSY, 100, output)
|
||||
else
|
||||
|
@ -24,7 +24,7 @@ class Settings(context : Context) {
|
||||
|
||||
var onScreenControl by sharedPreferences(context, false)
|
||||
|
||||
var onScreenControlRecenterSticks by sharedPreferences(context, false)
|
||||
var onScreenControlRecenterSticks by sharedPreferences(context, true)
|
||||
|
||||
var logCompact by sharedPreferences(context, false)
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/button_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -39,7 +40,7 @@
|
||||
android:contentDescription="@string/buttons"
|
||||
android:outlineProvider="bounds"
|
||||
android:src="@drawable/ic_button"
|
||||
android:tint="?android:attr/textColorPrimary" />
|
||||
app:tint="?android:attr/textColorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/button_text"
|
||||
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/stick_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -51,7 +52,7 @@
|
||||
android:contentDescription="@string/buttons"
|
||||
android:outlineProvider="bounds"
|
||||
android:src="@drawable/ic_button"
|
||||
android:tint="?android:attr/textColorPrimary" />
|
||||
app:tint="?android:attr/textColorPrimary" />
|
||||
|
||||
|
||||
<RelativeLayout
|
||||
@ -72,7 +73,7 @@
|
||||
android:contentDescription="@string/buttons"
|
||||
android:outlineProvider="bounds"
|
||||
android:src="@drawable/ic_stick"
|
||||
android:tint="?android:attr/textColorPrimary" />
|
||||
app:tint="?android:attr/textColorPrimary" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/stick_name"
|
||||
|
Loading…
Reference in New Issue
Block a user