14 changed files with 491 additions and 69 deletions
-
244src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlay.kt
-
6src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableDpad.kt
-
6src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/InputOverlayDrawableJoystick.kt
-
124src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/OverlayScaleDialog.kt
-
61src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControl.kt
-
7src/android/app/src/main/java/org/yuzu/yuzu_emu/overlay/model/OverlayControlData.kt
-
7src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt
-
6src/android/app/src/main/jni/android_config.cpp
-
1src/android/app/src/main/jni/android_settings.h
-
13src/android/app/src/main/jni/native_config.cpp
-
74src/android/app/src/main/res/layout/dialog_overlay_scale.xml
-
1src/android/app/src/main/res/values/strings.xml
-
9src/common/android/id_cache.cpp
-
1src/common/android/id_cache.h
@ -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 |
|||
} |
|||
|
|||
} |
|||
|
|||
} |
|||
@ -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> |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue