Add comments

This commit is contained in:
Willi Ye 2020-10-05 12:04:57 +02:00 committed by ◱ PixelyIon
parent 7526a985fb
commit f479aeb4ac
21 changed files with 72 additions and 81 deletions

View File

@ -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))

View File

@ -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")

View File

@ -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)))
}

View File

@ -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)
}
}
}

View File

@ -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()
}

View File

@ -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
}

View File

@ -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 = ""
}

View File

@ -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 ""
}

View File

@ -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 = ""
}

View File

@ -5,4 +5,6 @@
package emu.skyline.data
class BaseHeader(val title : String) : BaseElement(ElementType.Header)
import java.io.Serializable
interface DataItem : Serializable

View File

@ -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

View File

@ -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>()

View File

@ -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
*/

View File

@ -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) {

View File

@ -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

View File

@ -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()
}
}
}

View File

@ -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) {

View File

@ -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

View File

@ -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)

View File

@ -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"

View File

@ -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"