mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2025-10-05 15:52:45 +02:00
[android] input over(lay)haul 2: Individual scaling of buttons (#2562)
### (Needs testing) This PR makes it possible to adjust the scale of each touch input overlay button independently from the global scale This individual value always goes on top of the global scale. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2562 Co-authored-by: nyx <contact@innix.space> Co-committed-by: nyx <contact@innix.space>
This commit is contained in:
@@ -924,6 +924,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
IntSetting.OVERLAY_OPACITY.reset()
|
||||
binding.surfaceInputOverlay.post {
|
||||
binding.surfaceInputOverlay.resetLayoutVisibilityAndPlacement()
|
||||
binding.surfaceInputOverlay.resetIndividualControlScale()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1546,6 +1547,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||
.setNeutralButton(R.string.slider_default) { _: DialogInterface?, _: Int ->
|
||||
setControlScale(50)
|
||||
setControlOpacity(100)
|
||||
binding.surfaceInputOverlay.resetIndividualControlScale()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.overlay
|
||||
|
||||
@@ -13,6 +13,8 @@ import android.graphics.Rect
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.graphics.drawable.VectorDrawable
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.AttributeSet
|
||||
import android.view.HapticFeedbackConstants
|
||||
import android.view.MotionEvent
|
||||
@@ -52,6 +54,12 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
private var dpadBeingConfigured: InputOverlayDrawableDpad? = null
|
||||
private var joystickBeingConfigured: InputOverlayDrawableJoystick? = null
|
||||
|
||||
private var scaleDialog: OverlayScaleDialog? = null
|
||||
private var touchStartX = 0f
|
||||
private var touchStartY = 0f
|
||||
private var hasMoved = false
|
||||
private val moveThreshold = 20f
|
||||
|
||||
private lateinit var windowInsets: WindowInsets
|
||||
|
||||
var layout = OverlayLayout.Landscape
|
||||
@@ -254,23 +262,44 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
) {
|
||||
buttonBeingConfigured = button
|
||||
buttonBeingConfigured!!.onConfigureTouch(event)
|
||||
touchStartX = event.getX(pointerIndex)
|
||||
touchStartY = event.getY(pointerIndex)
|
||||
hasMoved = false
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_MOVE -> if (buttonBeingConfigured != null) {
|
||||
buttonBeingConfigured!!.onConfigureTouch(event)
|
||||
invalidate()
|
||||
return true
|
||||
val moveDistance = kotlin.math.sqrt(
|
||||
(event.getX(pointerIndex) - touchStartX).let { it * it } +
|
||||
(event.getY(pointerIndex) - touchStartY).let { it * it }
|
||||
)
|
||||
|
||||
if (moveDistance > moveThreshold) {
|
||||
hasMoved = true
|
||||
buttonBeingConfigured!!.onConfigureTouch(event)
|
||||
invalidate()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_UP,
|
||||
MotionEvent.ACTION_POINTER_UP -> if (buttonBeingConfigured === button) {
|
||||
// Persist button position by saving new place.
|
||||
saveControlPosition(
|
||||
buttonBeingConfigured!!.overlayControlData.id,
|
||||
buttonBeingConfigured!!.bounds.centerX(),
|
||||
buttonBeingConfigured!!.bounds.centerY(),
|
||||
layout
|
||||
)
|
||||
if (!hasMoved) {
|
||||
showScaleDialog(
|
||||
buttonBeingConfigured,
|
||||
null,
|
||||
null,
|
||||
fingerPositionX,
|
||||
fingerPositionY
|
||||
)
|
||||
} else {
|
||||
saveControlPosition(
|
||||
buttonBeingConfigured!!.overlayControlData.id,
|
||||
buttonBeingConfigured!!.bounds.centerX(),
|
||||
buttonBeingConfigured!!.bounds.centerY(),
|
||||
individuaScale = buttonBeingConfigured!!.overlayControlData.individualScale,
|
||||
layout
|
||||
)
|
||||
}
|
||||
buttonBeingConfigured = null
|
||||
}
|
||||
}
|
||||
@@ -287,23 +316,46 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
) {
|
||||
dpadBeingConfigured = dpad
|
||||
dpadBeingConfigured!!.onConfigureTouch(event)
|
||||
touchStartX = event.getX(pointerIndex)
|
||||
touchStartY = event.getY(pointerIndex)
|
||||
hasMoved = false
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_MOVE -> if (dpadBeingConfigured != null) {
|
||||
dpadBeingConfigured!!.onConfigureTouch(event)
|
||||
invalidate()
|
||||
return true
|
||||
val moveDistance = kotlin.math.sqrt(
|
||||
(event.getX(pointerIndex) - touchStartX).let { it * it } +
|
||||
(event.getY(pointerIndex) - touchStartY).let { it * it }
|
||||
)
|
||||
|
||||
if (moveDistance > moveThreshold) {
|
||||
hasMoved = true
|
||||
dpadBeingConfigured!!.onConfigureTouch(event)
|
||||
invalidate()
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_UP,
|
||||
MotionEvent.ACTION_POINTER_UP -> if (dpadBeingConfigured === dpad) {
|
||||
// Persist button position by saving new place.
|
||||
saveControlPosition(
|
||||
OverlayControl.COMBINED_DPAD.id,
|
||||
dpadBeingConfigured!!.bounds.centerX(),
|
||||
dpadBeingConfigured!!.bounds.centerY(),
|
||||
layout
|
||||
)
|
||||
if (!hasMoved) {
|
||||
// This was a click, show scale dialog for dpad
|
||||
showScaleDialog(
|
||||
null,
|
||||
dpadBeingConfigured,
|
||||
null,
|
||||
fingerPositionX,
|
||||
fingerPositionY
|
||||
)
|
||||
} else {
|
||||
// This was a move, save position
|
||||
saveControlPosition(
|
||||
OverlayControl.COMBINED_DPAD.id,
|
||||
dpadBeingConfigured!!.bounds.centerX(),
|
||||
dpadBeingConfigured!!.bounds.centerY(),
|
||||
individuaScale = dpadBeingConfigured!!.individualScale,
|
||||
layout
|
||||
)
|
||||
}
|
||||
dpadBeingConfigured = null
|
||||
}
|
||||
}
|
||||
@@ -317,21 +369,43 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
) {
|
||||
joystickBeingConfigured = joystick
|
||||
joystickBeingConfigured!!.onConfigureTouch(event)
|
||||
touchStartX = event.getX(pointerIndex)
|
||||
touchStartY = event.getY(pointerIndex)
|
||||
hasMoved = false
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_MOVE -> if (joystickBeingConfigured != null) {
|
||||
joystickBeingConfigured!!.onConfigureTouch(event)
|
||||
invalidate()
|
||||
val moveDistance = kotlin.math.sqrt(
|
||||
(event.getX(pointerIndex) - touchStartX).let { it * it } +
|
||||
(event.getY(pointerIndex) - touchStartY).let { it * it }
|
||||
)
|
||||
|
||||
if (moveDistance > moveThreshold) {
|
||||
hasMoved = true
|
||||
joystickBeingConfigured!!.onConfigureTouch(event)
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_UP,
|
||||
MotionEvent.ACTION_POINTER_UP -> if (joystickBeingConfigured != null) {
|
||||
saveControlPosition(
|
||||
joystickBeingConfigured!!.prefId,
|
||||
joystickBeingConfigured!!.bounds.centerX(),
|
||||
joystickBeingConfigured!!.bounds.centerY(),
|
||||
layout
|
||||
)
|
||||
if (!hasMoved) {
|
||||
showScaleDialog(
|
||||
null,
|
||||
null,
|
||||
joystickBeingConfigured,
|
||||
fingerPositionX,
|
||||
fingerPositionY
|
||||
)
|
||||
} else {
|
||||
saveControlPosition(
|
||||
joystickBeingConfigured!!.prefId,
|
||||
joystickBeingConfigured!!.bounds.centerX(),
|
||||
joystickBeingConfigured!!.bounds.centerY(),
|
||||
individuaScale = joystickBeingConfigured!!.individualScale,
|
||||
layout
|
||||
)
|
||||
}
|
||||
joystickBeingConfigured = null
|
||||
}
|
||||
}
|
||||
@@ -607,25 +681,117 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
invalidate()
|
||||
}
|
||||
|
||||
private fun saveControlPosition(id: String, x: Int, y: Int, layout: OverlayLayout) {
|
||||
private fun saveControlPosition(
|
||||
id: String,
|
||||
x: Int,
|
||||
y: Int,
|
||||
individuaScale: Float,
|
||||
layout: OverlayLayout
|
||||
) {
|
||||
val windowSize = getSafeScreenSize(context, Pair(measuredWidth, measuredHeight))
|
||||
val min = windowSize.first
|
||||
val max = windowSize.second
|
||||
val overlayControlData = NativeConfig.getOverlayControlData()
|
||||
val data = overlayControlData.firstOrNull { it.id == id }
|
||||
val newPosition = Pair((x - min.x).toDouble() / max.x, (y - min.y).toDouble() / max.y)
|
||||
|
||||
when (layout) {
|
||||
OverlayLayout.Landscape -> data?.landscapePosition = newPosition
|
||||
OverlayLayout.Portrait -> data?.portraitPosition = newPosition
|
||||
OverlayLayout.Foldable -> data?.foldablePosition = newPosition
|
||||
|
||||
}
|
||||
|
||||
data?.individualScale = individuaScale
|
||||
|
||||
NativeConfig.setOverlayControlData(overlayControlData)
|
||||
}
|
||||
|
||||
fun setIsInEditMode(editMode: Boolean) {
|
||||
inEditMode = editMode
|
||||
if (!editMode) {
|
||||
scaleDialog?.dismiss()
|
||||
scaleDialog = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun showScaleDialog(
|
||||
button: InputOverlayDrawableButton?,
|
||||
dpad: InputOverlayDrawableDpad?,
|
||||
joystick: InputOverlayDrawableJoystick?,
|
||||
x: Int, y: Int
|
||||
) {
|
||||
val overlayControlData = NativeConfig.getOverlayControlData()
|
||||
// prevent dialog from being spam opened
|
||||
scaleDialog?.dismiss()
|
||||
|
||||
|
||||
when {
|
||||
button != null -> {
|
||||
val buttonData =
|
||||
overlayControlData.firstOrNull { it.id == button.overlayControlData.id }
|
||||
if (buttonData != null) {
|
||||
scaleDialog =
|
||||
OverlayScaleDialog(context, button.overlayControlData) { newScale ->
|
||||
saveControlPosition(
|
||||
button.overlayControlData.id,
|
||||
button.bounds.centerX(),
|
||||
button.bounds.centerY(),
|
||||
individuaScale = newScale,
|
||||
layout
|
||||
)
|
||||
refreshControls()
|
||||
}
|
||||
|
||||
scaleDialog?.showDialog(x,y, button.bounds.width(), button.bounds.height())
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
dpad != null -> {
|
||||
val dpadData =
|
||||
overlayControlData.firstOrNull { it.id == OverlayControl.COMBINED_DPAD.id }
|
||||
if (dpadData != null) {
|
||||
scaleDialog = OverlayScaleDialog(context, dpadData) { newScale ->
|
||||
saveControlPosition(
|
||||
OverlayControl.COMBINED_DPAD.id,
|
||||
dpad.bounds.centerX(),
|
||||
dpad.bounds.centerY(),
|
||||
newScale,
|
||||
layout
|
||||
)
|
||||
|
||||
refreshControls()
|
||||
}
|
||||
|
||||
scaleDialog?.showDialog(x,y, dpad.bounds.width(), dpad.bounds.height())
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
joystick != null -> {
|
||||
val joystickData = overlayControlData.firstOrNull { it.id == joystick.prefId }
|
||||
if (joystickData != null) {
|
||||
scaleDialog = OverlayScaleDialog(context, joystickData) { newScale ->
|
||||
saveControlPosition(
|
||||
joystick.prefId,
|
||||
joystick.bounds.centerX(),
|
||||
joystick.bounds.centerY(),
|
||||
individuaScale = newScale,
|
||||
layout
|
||||
)
|
||||
|
||||
refreshControls()
|
||||
}
|
||||
|
||||
scaleDialog?.showDialog(x,y, joystick.bounds.width(), joystick.bounds.height())
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Applies and saves all default values for the overlay
|
||||
*/
|
||||
@@ -664,12 +830,24 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
val overlayControlData = NativeConfig.getOverlayControlData()
|
||||
overlayControlData.forEach {
|
||||
it.enabled = OverlayControl.from(it.id)?.defaultVisibility == true
|
||||
it.individualScale = OverlayControl.from(it.id)?.defaultIndividualScaleResource!!
|
||||
}
|
||||
NativeConfig.setOverlayControlData(overlayControlData)
|
||||
|
||||
refreshControls()
|
||||
}
|
||||
|
||||
fun resetIndividualControlScale() {
|
||||
val overlayControlData = NativeConfig.getOverlayControlData()
|
||||
overlayControlData.forEach { data ->
|
||||
val defaultControlData = OverlayControl.from(data.id) ?: return@forEach
|
||||
data.individualScale = defaultControlData.defaultIndividualScaleResource
|
||||
}
|
||||
NativeConfig.setOverlayControlData(overlayControlData)
|
||||
NativeConfig.saveGlobalConfig()
|
||||
refreshControls()
|
||||
}
|
||||
|
||||
private fun defaultOverlayPositionByLayout(layout: OverlayLayout) {
|
||||
val overlayControlData = NativeConfig.getOverlayControlData()
|
||||
for (data in overlayControlData) {
|
||||
@@ -860,6 +1038,9 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
scale *= (IntSetting.OVERLAY_SCALE.getInt() + 50).toFloat()
|
||||
scale /= 100f
|
||||
|
||||
// Apply individual scale
|
||||
scale *= overlayControlData.individualScale
|
||||
|
||||
// Initialize the InputOverlayDrawableButton.
|
||||
val defaultStateBitmap = getBitmap(context, defaultResId, scale)
|
||||
val pressedStateBitmap = getBitmap(context, pressedResId, scale)
|
||||
@@ -922,11 +1103,20 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
// Resources handle for fetching the initial Drawable resource.
|
||||
val res = context.resources
|
||||
|
||||
// Get the dpad control data for individual scale
|
||||
val overlayControlData = NativeConfig.getOverlayControlData()
|
||||
val dpadData = overlayControlData.firstOrNull { it.id == OverlayControl.COMBINED_DPAD.id }
|
||||
|
||||
// Decide scale based on button ID and user preference
|
||||
var scale = 0.25f
|
||||
scale *= (IntSetting.OVERLAY_SCALE.getInt() + 50).toFloat()
|
||||
scale /= 100f
|
||||
|
||||
// Apply individual scale
|
||||
if (dpadData != null) {
|
||||
scale *= dpadData.individualScale
|
||||
}
|
||||
|
||||
// Initialize the InputOverlayDrawableDpad.
|
||||
val defaultStateBitmap =
|
||||
getBitmap(context, defaultResId, scale)
|
||||
@@ -1000,6 +1190,9 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||
scale *= (IntSetting.OVERLAY_SCALE.getInt() + 50).toFloat()
|
||||
scale /= 100f
|
||||
|
||||
// Apply individual scale
|
||||
scale *= overlayControlData.individualScale
|
||||
|
||||
// Initialize the InputOverlayDrawableJoystick.
|
||||
val bitmapOuter = getBitmap(context, resOuter, scale)
|
||||
val bitmapInnerDefault = getBitmap(context, defaultResInner, 1.0f)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.overlay
|
||||
|
||||
@@ -42,6 +42,8 @@ class InputOverlayDrawableDpad(
|
||||
val width: Int
|
||||
val height: Int
|
||||
|
||||
var individualScale: Float = 1.0f
|
||||
|
||||
private val defaultStateBitmap: BitmapDrawable
|
||||
private val pressedOneDirectionStateBitmap: BitmapDrawable
|
||||
private val pressedTwoDirectionsStateBitmap: BitmapDrawable
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.overlay
|
||||
|
||||
@@ -51,6 +51,8 @@ class InputOverlayDrawableJoystick(
|
||||
val width: Int
|
||||
val height: Int
|
||||
|
||||
var individualScale: Float = 1.0f
|
||||
|
||||
private var opacity: Int = 0
|
||||
|
||||
private var virtBounds: Rect
|
||||
|
@@ -0,0 +1,124 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.overlay
|
||||
|
||||
import android.app.Dialog
|
||||
import android.content.Context
|
||||
import android.view.Gravity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.WindowManager
|
||||
import android.widget.TextView
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.slider.Slider
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.overlay.model.OverlayControlData
|
||||
|
||||
class OverlayScaleDialog(
|
||||
context: Context,
|
||||
private val overlayControlData: OverlayControlData,
|
||||
private val onScaleChanged: (Float) -> Unit
|
||||
) : Dialog(context) {
|
||||
|
||||
private var currentScale = overlayControlData.individualScale
|
||||
private val originalScale = overlayControlData.individualScale
|
||||
private lateinit var scaleValueText: TextView
|
||||
private lateinit var scaleSlider: Slider
|
||||
|
||||
init {
|
||||
setupDialog()
|
||||
}
|
||||
|
||||
private fun setupDialog() {
|
||||
val view = LayoutInflater.from(context).inflate(R.layout.dialog_overlay_scale, null)
|
||||
setContentView(view)
|
||||
|
||||
window?.setBackgroundDrawable(null)
|
||||
|
||||
window?.apply {
|
||||
attributes = attributes.apply {
|
||||
flags = flags and WindowManager.LayoutParams.FLAG_DIM_BEHIND.inv()
|
||||
flags = flags or WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
|
||||
}
|
||||
}
|
||||
|
||||
scaleValueText = view.findViewById(R.id.scaleValueText)
|
||||
scaleSlider = view.findViewById(R.id.scaleSlider)
|
||||
val resetButton = view.findViewById<MaterialButton>(R.id.resetButton)
|
||||
val confirmButton = view.findViewById<MaterialButton>(R.id.confirmButton)
|
||||
val cancelButton = view.findViewById<MaterialButton>(R.id.cancelButton)
|
||||
|
||||
scaleValueText.text = String.format("%.1fx", currentScale)
|
||||
scaleSlider.value = currentScale
|
||||
|
||||
scaleSlider.addOnChangeListener { _, value, input ->
|
||||
if (input) {
|
||||
currentScale = value
|
||||
scaleValueText.text = String.format("%.1fx", currentScale)
|
||||
}
|
||||
}
|
||||
|
||||
scaleSlider.addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
|
||||
override fun onStartTrackingTouch(slider: Slider) {
|
||||
// pass
|
||||
}
|
||||
|
||||
override fun onStopTrackingTouch(slider: Slider) {
|
||||
onScaleChanged(currentScale)
|
||||
}
|
||||
})
|
||||
|
||||
resetButton.setOnClickListener {
|
||||
currentScale = 1.0f
|
||||
scaleSlider.value = 1.0f
|
||||
scaleValueText.text = String.format("%.1fx", currentScale)
|
||||
onScaleChanged(currentScale)
|
||||
}
|
||||
|
||||
confirmButton.setOnClickListener {
|
||||
overlayControlData.individualScale = currentScale
|
||||
//slider value is already saved on touch dispatch but just to be sure
|
||||
onScaleChanged(currentScale)
|
||||
dismiss()
|
||||
}
|
||||
|
||||
// both cancel button and back gesture should revert the scale change
|
||||
cancelButton.setOnClickListener {
|
||||
onScaleChanged(originalScale)
|
||||
dismiss()
|
||||
}
|
||||
|
||||
setOnCancelListener {
|
||||
onScaleChanged(originalScale)
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
fun showDialog(anchorX: Int, anchorY: Int, anchorHeight: Int, anchorWidth: Int) {
|
||||
show()
|
||||
|
||||
show()
|
||||
|
||||
// TODO: this calculation is a bit rough, improve it later on
|
||||
window?.let { window ->
|
||||
val layoutParams = window.attributes
|
||||
layoutParams.gravity = Gravity.TOP or Gravity.START
|
||||
|
||||
val density = context.resources.displayMetrics.density
|
||||
val dialogWidthPx = (320 * density).toInt()
|
||||
val dialogHeightPx = (400 * density).toInt() // set your estimated dialog height
|
||||
|
||||
val screenHeight = context.resources.displayMetrics.heightPixels
|
||||
|
||||
|
||||
layoutParams.x = anchorX + anchorWidth / 2 - dialogWidthPx / 2
|
||||
layoutParams.y = anchorY + anchorHeight / 2 - dialogHeightPx / 2
|
||||
layoutParams.width = dialogWidthPx
|
||||
|
||||
|
||||
window.attributes = layoutParams
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.overlay.model
|
||||
|
||||
@@ -12,126 +12,144 @@ enum class OverlayControl(
|
||||
val defaultVisibility: Boolean,
|
||||
@IntegerRes val defaultLandscapePositionResources: Pair<Int, Int>,
|
||||
@IntegerRes val defaultPortraitPositionResources: Pair<Int, Int>,
|
||||
@IntegerRes val defaultFoldablePositionResources: Pair<Int, Int>
|
||||
@IntegerRes val defaultFoldablePositionResources: Pair<Int, Int>,
|
||||
val defaultIndividualScaleResource: Float,
|
||||
) {
|
||||
BUTTON_A(
|
||||
"button_a",
|
||||
true,
|
||||
Pair(R.integer.BUTTON_A_X, R.integer.BUTTON_A_Y),
|
||||
Pair(R.integer.BUTTON_A_X_PORTRAIT, R.integer.BUTTON_A_Y_PORTRAIT),
|
||||
Pair(R.integer.BUTTON_A_X_FOLDABLE, R.integer.BUTTON_A_Y_FOLDABLE)
|
||||
Pair(R.integer.BUTTON_A_X_FOLDABLE, R.integer.BUTTON_A_Y_FOLDABLE),
|
||||
1.0f
|
||||
),
|
||||
BUTTON_B(
|
||||
"button_b",
|
||||
true,
|
||||
Pair(R.integer.BUTTON_B_X, R.integer.BUTTON_B_Y),
|
||||
Pair(R.integer.BUTTON_B_X_PORTRAIT, R.integer.BUTTON_B_Y_PORTRAIT),
|
||||
Pair(R.integer.BUTTON_B_X_FOLDABLE, R.integer.BUTTON_B_Y_FOLDABLE)
|
||||
Pair(R.integer.BUTTON_B_X_FOLDABLE, R.integer.BUTTON_B_Y_FOLDABLE),
|
||||
1.0f
|
||||
),
|
||||
BUTTON_X(
|
||||
"button_x",
|
||||
true,
|
||||
Pair(R.integer.BUTTON_X_X, R.integer.BUTTON_X_Y),
|
||||
Pair(R.integer.BUTTON_X_X_PORTRAIT, R.integer.BUTTON_X_Y_PORTRAIT),
|
||||
Pair(R.integer.BUTTON_X_X_FOLDABLE, R.integer.BUTTON_X_Y_FOLDABLE)
|
||||
Pair(R.integer.BUTTON_X_X_FOLDABLE, R.integer.BUTTON_X_Y_FOLDABLE),
|
||||
1.0f
|
||||
),
|
||||
BUTTON_Y(
|
||||
"button_y",
|
||||
true,
|
||||
Pair(R.integer.BUTTON_Y_X, R.integer.BUTTON_Y_Y),
|
||||
Pair(R.integer.BUTTON_Y_X_PORTRAIT, R.integer.BUTTON_Y_Y_PORTRAIT),
|
||||
Pair(R.integer.BUTTON_Y_X_FOLDABLE, R.integer.BUTTON_Y_Y_FOLDABLE)
|
||||
Pair(R.integer.BUTTON_Y_X_FOLDABLE, R.integer.BUTTON_Y_Y_FOLDABLE),
|
||||
1.0f
|
||||
),
|
||||
BUTTON_PLUS(
|
||||
"button_plus",
|
||||
true,
|
||||
Pair(R.integer.BUTTON_PLUS_X, R.integer.BUTTON_PLUS_Y),
|
||||
Pair(R.integer.BUTTON_PLUS_X_PORTRAIT, R.integer.BUTTON_PLUS_Y_PORTRAIT),
|
||||
Pair(R.integer.BUTTON_PLUS_X_FOLDABLE, R.integer.BUTTON_PLUS_Y_FOLDABLE)
|
||||
Pair(R.integer.BUTTON_PLUS_X_FOLDABLE, R.integer.BUTTON_PLUS_Y_FOLDABLE),
|
||||
1.0f
|
||||
),
|
||||
BUTTON_MINUS(
|
||||
"button_minus",
|
||||
true,
|
||||
Pair(R.integer.BUTTON_MINUS_X, R.integer.BUTTON_MINUS_Y),
|
||||
Pair(R.integer.BUTTON_MINUS_X_PORTRAIT, R.integer.BUTTON_MINUS_Y_PORTRAIT),
|
||||
Pair(R.integer.BUTTON_MINUS_X_FOLDABLE, R.integer.BUTTON_MINUS_Y_FOLDABLE)
|
||||
Pair(R.integer.BUTTON_MINUS_X_FOLDABLE, R.integer.BUTTON_MINUS_Y_FOLDABLE),
|
||||
1.0f
|
||||
),
|
||||
BUTTON_HOME(
|
||||
"button_home",
|
||||
false,
|
||||
Pair(R.integer.BUTTON_HOME_X, R.integer.BUTTON_HOME_Y),
|
||||
Pair(R.integer.BUTTON_HOME_X_PORTRAIT, R.integer.BUTTON_HOME_Y_PORTRAIT),
|
||||
Pair(R.integer.BUTTON_HOME_X_FOLDABLE, R.integer.BUTTON_HOME_Y_FOLDABLE)
|
||||
Pair(R.integer.BUTTON_HOME_X_FOLDABLE, R.integer.BUTTON_HOME_Y_FOLDABLE),
|
||||
1.0f
|
||||
),
|
||||
BUTTON_CAPTURE(
|
||||
"button_capture",
|
||||
false,
|
||||
Pair(R.integer.BUTTON_CAPTURE_X, R.integer.BUTTON_CAPTURE_Y),
|
||||
Pair(R.integer.BUTTON_CAPTURE_X_PORTRAIT, R.integer.BUTTON_CAPTURE_Y_PORTRAIT),
|
||||
Pair(R.integer.BUTTON_CAPTURE_X_FOLDABLE, R.integer.BUTTON_CAPTURE_Y_FOLDABLE)
|
||||
Pair(R.integer.BUTTON_CAPTURE_X_FOLDABLE, R.integer.BUTTON_CAPTURE_Y_FOLDABLE),
|
||||
1.0f
|
||||
),
|
||||
BUTTON_L(
|
||||
"button_l",
|
||||
true,
|
||||
Pair(R.integer.BUTTON_L_X, R.integer.BUTTON_L_Y),
|
||||
Pair(R.integer.BUTTON_L_X_PORTRAIT, R.integer.BUTTON_L_Y_PORTRAIT),
|
||||
Pair(R.integer.BUTTON_L_X_FOLDABLE, R.integer.BUTTON_L_Y_FOLDABLE)
|
||||
Pair(R.integer.BUTTON_L_X_FOLDABLE, R.integer.BUTTON_L_Y_FOLDABLE),
|
||||
1.0f
|
||||
),
|
||||
BUTTON_R(
|
||||
"button_r",
|
||||
true,
|
||||
Pair(R.integer.BUTTON_R_X, R.integer.BUTTON_R_Y),
|
||||
Pair(R.integer.BUTTON_R_X_PORTRAIT, R.integer.BUTTON_R_Y_PORTRAIT),
|
||||
Pair(R.integer.BUTTON_R_X_FOLDABLE, R.integer.BUTTON_R_Y_FOLDABLE)
|
||||
Pair(R.integer.BUTTON_R_X_FOLDABLE, R.integer.BUTTON_R_Y_FOLDABLE),
|
||||
1.0f
|
||||
),
|
||||
BUTTON_ZL(
|
||||
"button_zl",
|
||||
true,
|
||||
Pair(R.integer.BUTTON_ZL_X, R.integer.BUTTON_ZL_Y),
|
||||
Pair(R.integer.BUTTON_ZL_X_PORTRAIT, R.integer.BUTTON_ZL_Y_PORTRAIT),
|
||||
Pair(R.integer.BUTTON_ZL_X_FOLDABLE, R.integer.BUTTON_ZL_Y_FOLDABLE)
|
||||
Pair(R.integer.BUTTON_ZL_X_FOLDABLE, R.integer.BUTTON_ZL_Y_FOLDABLE),
|
||||
1.0f
|
||||
),
|
||||
BUTTON_ZR(
|
||||
"button_zr",
|
||||
true,
|
||||
Pair(R.integer.BUTTON_ZR_X, R.integer.BUTTON_ZR_Y),
|
||||
Pair(R.integer.BUTTON_ZR_X_PORTRAIT, R.integer.BUTTON_ZR_Y_PORTRAIT),
|
||||
Pair(R.integer.BUTTON_ZR_X_FOLDABLE, R.integer.BUTTON_ZR_Y_FOLDABLE)
|
||||
Pair(R.integer.BUTTON_ZR_X_FOLDABLE, R.integer.BUTTON_ZR_Y_FOLDABLE),
|
||||
1.0f
|
||||
),
|
||||
BUTTON_STICK_L(
|
||||
"button_stick_l",
|
||||
true,
|
||||
Pair(R.integer.BUTTON_STICK_L_X, R.integer.BUTTON_STICK_L_Y),
|
||||
Pair(R.integer.BUTTON_STICK_L_X_PORTRAIT, R.integer.BUTTON_STICK_L_Y_PORTRAIT),
|
||||
Pair(R.integer.BUTTON_STICK_L_X_FOLDABLE, R.integer.BUTTON_STICK_L_Y_FOLDABLE)
|
||||
Pair(R.integer.BUTTON_STICK_L_X_FOLDABLE, R.integer.BUTTON_STICK_L_Y_FOLDABLE),
|
||||
1.0f
|
||||
),
|
||||
BUTTON_STICK_R(
|
||||
"button_stick_r",
|
||||
true,
|
||||
Pair(R.integer.BUTTON_STICK_R_X, R.integer.BUTTON_STICK_R_Y),
|
||||
Pair(R.integer.BUTTON_STICK_R_X_PORTRAIT, R.integer.BUTTON_STICK_R_Y_PORTRAIT),
|
||||
Pair(R.integer.BUTTON_STICK_R_X_FOLDABLE, R.integer.BUTTON_STICK_R_Y_FOLDABLE)
|
||||
Pair(R.integer.BUTTON_STICK_R_X_FOLDABLE, R.integer.BUTTON_STICK_R_Y_FOLDABLE),
|
||||
1.0f
|
||||
),
|
||||
STICK_L(
|
||||
"stick_l",
|
||||
true,
|
||||
Pair(R.integer.STICK_L_X, R.integer.STICK_L_Y),
|
||||
Pair(R.integer.STICK_L_X_PORTRAIT, R.integer.STICK_L_Y_PORTRAIT),
|
||||
Pair(R.integer.STICK_L_X_FOLDABLE, R.integer.STICK_L_Y_FOLDABLE)
|
||||
Pair(R.integer.STICK_L_X_FOLDABLE, R.integer.STICK_L_Y_FOLDABLE),
|
||||
1.0f
|
||||
),
|
||||
STICK_R(
|
||||
"stick_r",
|
||||
true,
|
||||
Pair(R.integer.STICK_R_X, R.integer.STICK_R_Y),
|
||||
Pair(R.integer.STICK_R_X_PORTRAIT, R.integer.STICK_R_Y_PORTRAIT),
|
||||
Pair(R.integer.STICK_R_X_FOLDABLE, R.integer.STICK_R_Y_FOLDABLE)
|
||||
Pair(R.integer.STICK_R_X_FOLDABLE, R.integer.STICK_R_Y_FOLDABLE),
|
||||
1.0f
|
||||
),
|
||||
COMBINED_DPAD(
|
||||
"combined_dpad",
|
||||
true,
|
||||
Pair(R.integer.COMBINED_DPAD_X, R.integer.COMBINED_DPAD_Y),
|
||||
Pair(R.integer.COMBINED_DPAD_X_PORTRAIT, R.integer.COMBINED_DPAD_Y_PORTRAIT),
|
||||
Pair(R.integer.COMBINED_DPAD_X_FOLDABLE, R.integer.COMBINED_DPAD_Y_FOLDABLE)
|
||||
Pair(R.integer.COMBINED_DPAD_X_FOLDABLE, R.integer.COMBINED_DPAD_Y_FOLDABLE),
|
||||
1.0f
|
||||
);
|
||||
|
||||
fun getDefaultPositionForLayout(layout: OverlayLayout): Pair<Double, Double> {
|
||||
@@ -173,7 +191,8 @@ enum class OverlayControl(
|
||||
defaultVisibility,
|
||||
getDefaultPositionForLayout(OverlayLayout.Landscape),
|
||||
getDefaultPositionForLayout(OverlayLayout.Portrait),
|
||||
getDefaultPositionForLayout(OverlayLayout.Foldable)
|
||||
getDefaultPositionForLayout(OverlayLayout.Foldable),
|
||||
defaultIndividualScaleResource
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.overlay.model
|
||||
|
||||
@@ -8,7 +8,8 @@ data class OverlayControlData(
|
||||
var enabled: Boolean,
|
||||
var landscapePosition: Pair<Double, Double>,
|
||||
var portraitPosition: Pair<Double, Double>,
|
||||
var foldablePosition: Pair<Double, Double>
|
||||
var foldablePosition: Pair<Double, Double>,
|
||||
var individualScale: Float
|
||||
) {
|
||||
fun positionFromLayout(layout: OverlayLayout): Pair<Double, Double> =
|
||||
when (layout) {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package org.yuzu.yuzu_emu.utils
|
||||
|
||||
@@ -170,7 +170,8 @@ object DirectoryInitialization {
|
||||
buttonEnabled,
|
||||
Pair(landscapeXPosition, landscapeYPosition),
|
||||
Pair(portraitXPosition, portraitYPosition),
|
||||
Pair(foldableXPosition, foldableYPosition)
|
||||
Pair(foldableXPosition, foldableYPosition),
|
||||
OverlayControl.map[buttonId]?.defaultIndividualScaleResource ?: 1.0f
|
||||
)
|
||||
overlayControlDataMap[buttonId] = controlData
|
||||
setOverlayData = true
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <common/logging/log.h>
|
||||
#include <input_common/main.h>
|
||||
@@ -103,6 +103,7 @@ void AndroidConfig::ReadOverlayValues() {
|
||||
ReadDoubleSetting(std::string("foldable\\x_position"));
|
||||
control_data.foldable_position.second =
|
||||
ReadDoubleSetting(std::string("foldable\\y_position"));
|
||||
control_data.individual_scale = static_cast<float>(ReadDoubleSetting(std::string("individual_scale")));
|
||||
AndroidSettings::values.overlay_control_data.push_back(control_data);
|
||||
}
|
||||
EndArray();
|
||||
@@ -255,6 +256,7 @@ void AndroidConfig::SaveOverlayValues() {
|
||||
control_data.foldable_position.first);
|
||||
WriteDoubleSetting(std::string("foldable\\y_position"),
|
||||
control_data.foldable_position.second);
|
||||
WriteDoubleSetting(std::string("individual_scale"), static_cast<double>(control_data.individual_scale));
|
||||
}
|
||||
EndArray();
|
||||
|
||||
|
@@ -24,6 +24,7 @@ namespace AndroidSettings {
|
||||
std::pair<double, double> landscape_position;
|
||||
std::pair<double, double> portrait_position;
|
||||
std::pair<double, double> foldable_position;
|
||||
float individual_scale;
|
||||
};
|
||||
|
||||
struct Values {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -369,7 +369,9 @@ jobjectArray Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getOverlayControlData(JN
|
||||
env->NewObject(Common::Android::GetOverlayControlDataClass(),
|
||||
Common::Android::GetOverlayControlDataConstructor(),
|
||||
Common::Android::ToJString(env, control_data.id), control_data.enabled,
|
||||
jlandscapePosition, jportraitPosition, jfoldablePosition);
|
||||
jlandscapePosition, jportraitPosition, jfoldablePosition,
|
||||
control_data.individual_scale);
|
||||
|
||||
env->SetObjectArrayElement(joverlayControlDataArray, i, jcontrolData);
|
||||
}
|
||||
return joverlayControlDataArray;
|
||||
@@ -418,9 +420,12 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setOverlayControlData(
|
||||
env,
|
||||
env->GetObjectField(jfoldablePosition, Common::Android::GetPairSecondField())));
|
||||
|
||||
float individual_scale = static_cast<float>(env->GetFloatField(
|
||||
joverlayControlData, Common::Android::GetOverlayControlDataIndividualScaleField()));
|
||||
|
||||
AndroidSettings::values.overlay_control_data.push_back(AndroidSettings::OverlayControlData{
|
||||
Common::Android::GetJString(env, jidString), enabled, landscape_position,
|
||||
portrait_position, foldable_position});
|
||||
portrait_position, foldable_position, individual_scale});
|
||||
}
|
||||
}
|
||||
|
||||
|
74
src/android/app/src/main/res/layout/dialog_overlay_scale.xml
Normal file
74
src/android/app/src/main/res/layout/dialog_overlay_scale.xml
Normal file
@@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="320dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="8dp"
|
||||
app:cardBackgroundColor="#CC222222">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="12dp">
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/scaleValueText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="1.0x"
|
||||
android:textAppearance="?attr/textAppearanceBody1"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<com.google.android.material.slider.Slider
|
||||
android:id="@+id/scaleSlider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:valueFrom="0.5"
|
||||
android:valueTo="4.0"
|
||||
android:stepSize="0.1"
|
||||
android:value="1.0"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:trackColorActive="@color/eden_border_gradient_start"
|
||||
app:trackColorInactive="@color/eden_border_gradient_end"
|
||||
app:tickColor="@color/eden_border_gradient_start"/>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/resetButton"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/reset"
|
||||
android:layout_marginEnd="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/cancelButton"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@android:string/cancel"
|
||||
android:layout_marginEnd="4dp" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/confirmButton"
|
||||
style="@style/Widget.Material3.Button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:backgroundTint="@color/eden_button_secondary_bg"
|
||||
android:textColor="@color/eden_border_gradient_end"
|
||||
android:text="@string/confirm" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.google.android.material.card.MaterialCardView>
|
@@ -855,6 +855,7 @@
|
||||
<string name="touchscreen">Touchscreen</string>
|
||||
<string name="lock_drawer">Lock drawer</string>
|
||||
<string name="unlock_drawer">Unlock drawer</string>
|
||||
<string name="reset">Reset</string>
|
||||
|
||||
<string name="load_settings">Loading settings…</string>
|
||||
|
||||
|
@@ -1,7 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <jni.h>
|
||||
@@ -49,6 +46,7 @@ static jclass s_overlay_control_data_class;
|
||||
static jmethodID s_overlay_control_data_constructor;
|
||||
static jfieldID s_overlay_control_data_id_field;
|
||||
static jfieldID s_overlay_control_data_enabled_field;
|
||||
static jfieldID s_overlay_control_data_individual_scale_field;
|
||||
static jfieldID s_overlay_control_data_landscape_position_field;
|
||||
static jfieldID s_overlay_control_data_portrait_position_field;
|
||||
static jfieldID s_overlay_control_data_foldable_position_field;
|
||||
@@ -244,6 +242,10 @@ namespace Common::Android {
|
||||
return s_overlay_control_data_enabled_field;
|
||||
}
|
||||
|
||||
jfieldID GetOverlayControlDataIndividualScaleField() {
|
||||
return s_overlay_control_data_individual_scale_field;
|
||||
}
|
||||
|
||||
jfieldID GetOverlayControlDataLandscapePositionField() {
|
||||
return s_overlay_control_data_landscape_position_field;
|
||||
}
|
||||
@@ -494,7 +496,7 @@ namespace Common::Android {
|
||||
reinterpret_cast<jclass>(env->NewGlobalRef(overlay_control_data_class));
|
||||
s_overlay_control_data_constructor =
|
||||
env->GetMethodID(overlay_control_data_class, "<init>",
|
||||
"(Ljava/lang/String;ZLkotlin/Pair;Lkotlin/Pair;Lkotlin/Pair;)V");
|
||||
"(Ljava/lang/String;ZLkotlin/Pair;Lkotlin/Pair;Lkotlin/Pair;F)V");
|
||||
s_overlay_control_data_id_field =
|
||||
env->GetFieldID(overlay_control_data_class, "id", "Ljava/lang/String;");
|
||||
s_overlay_control_data_enabled_field =
|
||||
@@ -505,6 +507,8 @@ namespace Common::Android {
|
||||
env->GetFieldID(overlay_control_data_class, "portraitPosition", "Lkotlin/Pair;");
|
||||
s_overlay_control_data_foldable_position_field =
|
||||
env->GetFieldID(overlay_control_data_class, "foldablePosition", "Lkotlin/Pair;");
|
||||
s_overlay_control_data_individual_scale_field =
|
||||
env->GetFieldID(overlay_control_data_class, "individualScale", "F");
|
||||
env->DeleteLocalRef(overlay_control_data_class);
|
||||
|
||||
const jclass patch_class = env->FindClass("org/yuzu/yuzu_emu/model/Patch");
|
||||
|
@@ -1,7 +1,4 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
@@ -67,6 +64,7 @@ jclass GetOverlayControlDataClass();
|
||||
jmethodID GetOverlayControlDataConstructor();
|
||||
jfieldID GetOverlayControlDataIdField();
|
||||
jfieldID GetOverlayControlDataEnabledField();
|
||||
jfieldID GetOverlayControlDataIndividualScaleField();
|
||||
jfieldID GetOverlayControlDataLandscapePositionField();
|
||||
jfieldID GetOverlayControlDataPortraitPositionField();
|
||||
jfieldID GetOverlayControlDataFoldablePositionField();
|
||||
|
Reference in New Issue
Block a user